Skip to content

Commit 461ad48

Browse files
committed
Implement GetTxTimestamp() for chaincode stub
This change sets the transaction timestamp in the proposal's ChannelHeader and then implements stub.GetTxTimestamp() to retrieve that timestamp. https://jira.hyperledger.org/browse/FAB-2701 Change-Id: I95ed9004294a80d1e277dae67970a9735d9cb71b Signed-off-by: Will Lahti <[email protected]>
1 parent c4e7104 commit 461ad48

File tree

5 files changed

+44
-9
lines changed

5 files changed

+44
-9
lines changed

core/chaincode/shim/chaincode.go

+13-4
Original file line numberDiff line numberDiff line change
@@ -558,11 +558,20 @@ func (stub *ChaincodeStub) GetArgsSlice() ([]byte, error) {
558558
return res, nil
559559
}
560560

561-
// GetTxTimestamp returns transaction created timestamp, which is currently
562-
// taken from the peer receiving the transaction. Note that this timestamp
563-
// may not be the same with the other peers' time.
561+
// GetTxTimestamp returns the timestamp when the transaction was created. This
562+
// is taken from the transaction ChannelHeader, so it will be the same across
563+
// all endorsers.
564564
func (stub *ChaincodeStub) GetTxTimestamp() (*timestamp.Timestamp, error) {
565-
return nil, nil
565+
hdr, err := utils.GetHeader(stub.proposal.Header)
566+
if err != nil {
567+
return nil, err
568+
}
569+
chdr, err := utils.UnmarshalChannelHeader(hdr.ChannelHeader)
570+
if err != nil {
571+
return nil, err
572+
}
573+
574+
return chdr.GetTimestamp(), nil
566575
}
567576

568577
// ------------- ChaincodeEvent API ----------------------

core/chaincode/shim/interfaces.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,9 @@ type ChaincodeStubInterface interface {
118118
// GetArgsSlice returns the arguments to the stub call as a byte array
119119
GetArgsSlice() ([]byte, error)
120120

121-
// GetTxTimestamp returns transaction created timestamp, which is currently
122-
// taken from the peer receiving the transaction. Note that this timestamp
123-
// may not be the same with the other peers' time.
121+
// GetTxTimestamp returns the timestamp when the transaction was created. This
122+
// is taken from the transaction ChannelHeader, so it will be the same across
123+
// all endorsers.
124124
GetTxTimestamp() (*timestamp.Timestamp, error)
125125

126126
// SetEvent saves the event to be sent when a transaction is made part of a block

core/chaincode/shim/mockstub.go

+12-2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"strings"
2626

2727
"github.com/golang/protobuf/ptypes/timestamp"
28+
"github.com/hyperledger/fabric/common/util"
2829
pb "github.com/hyperledger/fabric/protos/peer"
2930
"github.com/op/go-logging"
3031
)
@@ -57,6 +58,8 @@ type MockStub struct {
5758
// stores a transaction uuid while being Invoked / Deployed
5859
// TODO if a chaincode uses recursion this may need to be a stack of TxIDs or possibly a reference counting map
5960
TxID string
61+
62+
TxTimestamp *timestamp.Timestamp
6063
}
6164

6265
func (stub *MockStub) GetTxID() string {
@@ -92,6 +95,7 @@ func (stub *MockStub) GetFunctionAndParameters() (function string, params []stri
9295
// MockStub doesn't support concurrent transactions at present.
9396
func (stub *MockStub) MockTransactionStart(txid string) {
9497
stub.TxID = txid
98+
stub.setTxTimestamp(util.CreateUtcTimestamp())
9599
}
96100

97101
// End a mocked transaction, clearing the UUID.
@@ -270,9 +274,15 @@ func (stub *MockStub) GetArgsSlice() ([]byte, error) {
270274
return nil, nil
271275
}
272276

273-
// Not implemented
277+
func (stub *MockStub) setTxTimestamp(time *timestamp.Timestamp) {
278+
stub.TxTimestamp = time
279+
}
280+
274281
func (stub *MockStub) GetTxTimestamp() (*timestamp.Timestamp, error) {
275-
return nil, nil
282+
if stub.TxTimestamp == nil {
283+
return nil, errors.New("TxTimestamp not set.")
284+
}
285+
return stub.TxTimestamp, nil
276286
}
277287

278288
// Not implemented

core/chaincode/shim/mockstub_test.go

+12
Original file line numberDiff line numberDiff line change
@@ -219,3 +219,15 @@ func TestGetStateByPartialCompositeKeyCollision(t *testing.T) {
219219
t.FailNow()
220220
}
221221
}
222+
223+
func TestGetTxTimestamp(t *testing.T) {
224+
stub := NewMockStub("GetTxTimestamp", nil)
225+
stub.MockTransactionStart("init")
226+
227+
timestamp, err := stub.GetTxTimestamp()
228+
if timestamp == nil || err != nil {
229+
t.FailNow()
230+
}
231+
232+
stub.MockTransactionEnd("init")
233+
}

protos/utils/proputils.go

+4
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/golang/protobuf/proto"
2828
"github.com/hyperledger/fabric/bccsp"
2929
"github.com/hyperledger/fabric/bccsp/factory"
30+
"github.com/hyperledger/fabric/common/util"
3031
"github.com/hyperledger/fabric/core/chaincode/platforms"
3132
"github.com/hyperledger/fabric/core/crypto/primitives"
3233
"github.com/hyperledger/fabric/protos/common"
@@ -361,9 +362,12 @@ func CreateChaincodeProposalWithTxIDNonceAndTransient(txid string, typ common.He
361362
// get a more appropriate mechanism to handle it in.
362363
var epoch uint64 = 0
363364

365+
timestamp := util.CreateUtcTimestamp()
366+
364367
hdr := &common.Header{ChannelHeader: MarshalOrPanic(&common.ChannelHeader{
365368
Type: int32(typ),
366369
TxId: txid,
370+
Timestamp: timestamp,
367371
ChannelId: chainID,
368372
Extension: ccHdrExtBytes,
369373
Epoch: epoch}),

0 commit comments

Comments
 (0)