Skip to content

Commit

Permalink
Implement GetTxTimestamp() for chaincode stub
Browse files Browse the repository at this point in the history
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 <wtlahti@us.ibm.com>
  • Loading branch information
wlahti committed Mar 29, 2017
1 parent c4e7104 commit 461ad48
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 9 deletions.
17 changes: 13 additions & 4 deletions core/chaincode/shim/chaincode.go
Original file line number Diff line number Diff line change
Expand Up @@ -558,11 +558,20 @@ func (stub *ChaincodeStub) GetArgsSlice() ([]byte, error) {
return res, nil
}

// GetTxTimestamp returns transaction created timestamp, which is currently
// taken from the peer receiving the transaction. Note that this timestamp
// may not be the same with the other peers' time.
// GetTxTimestamp returns the timestamp when the transaction was created. This
// is taken from the transaction ChannelHeader, so it will be the same across
// all endorsers.
func (stub *ChaincodeStub) GetTxTimestamp() (*timestamp.Timestamp, error) {
return nil, nil
hdr, err := utils.GetHeader(stub.proposal.Header)
if err != nil {
return nil, err
}
chdr, err := utils.UnmarshalChannelHeader(hdr.ChannelHeader)
if err != nil {
return nil, err
}

return chdr.GetTimestamp(), nil
}

// ------------- ChaincodeEvent API ----------------------
Expand Down
6 changes: 3 additions & 3 deletions core/chaincode/shim/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,9 @@ type ChaincodeStubInterface interface {
// GetArgsSlice returns the arguments to the stub call as a byte array
GetArgsSlice() ([]byte, error)

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

// SetEvent saves the event to be sent when a transaction is made part of a block
Expand Down
14 changes: 12 additions & 2 deletions core/chaincode/shim/mockstub.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"strings"

"github.com/golang/protobuf/ptypes/timestamp"
"github.com/hyperledger/fabric/common/util"
pb "github.com/hyperledger/fabric/protos/peer"
"github.com/op/go-logging"
)
Expand Down Expand Up @@ -57,6 +58,8 @@ type MockStub struct {
// stores a transaction uuid while being Invoked / Deployed
// TODO if a chaincode uses recursion this may need to be a stack of TxIDs or possibly a reference counting map
TxID string

TxTimestamp *timestamp.Timestamp
}

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

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

// Not implemented
func (stub *MockStub) setTxTimestamp(time *timestamp.Timestamp) {
stub.TxTimestamp = time
}

func (stub *MockStub) GetTxTimestamp() (*timestamp.Timestamp, error) {
return nil, nil
if stub.TxTimestamp == nil {
return nil, errors.New("TxTimestamp not set.")
}
return stub.TxTimestamp, nil
}

// Not implemented
Expand Down
12 changes: 12 additions & 0 deletions core/chaincode/shim/mockstub_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,3 +219,15 @@ func TestGetStateByPartialCompositeKeyCollision(t *testing.T) {
t.FailNow()
}
}

func TestGetTxTimestamp(t *testing.T) {
stub := NewMockStub("GetTxTimestamp", nil)
stub.MockTransactionStart("init")

timestamp, err := stub.GetTxTimestamp()
if timestamp == nil || err != nil {
t.FailNow()
}

stub.MockTransactionEnd("init")
}
4 changes: 4 additions & 0 deletions protos/utils/proputils.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/bccsp"
"github.com/hyperledger/fabric/bccsp/factory"
"github.com/hyperledger/fabric/common/util"
"github.com/hyperledger/fabric/core/chaincode/platforms"
"github.com/hyperledger/fabric/core/crypto/primitives"
"github.com/hyperledger/fabric/protos/common"
Expand Down Expand Up @@ -361,9 +362,12 @@ func CreateChaincodeProposalWithTxIDNonceAndTransient(txid string, typ common.He
// get a more appropriate mechanism to handle it in.
var epoch uint64 = 0

timestamp := util.CreateUtcTimestamp()

hdr := &common.Header{ChannelHeader: MarshalOrPanic(&common.ChannelHeader{
Type: int32(typ),
TxId: txid,
Timestamp: timestamp,
ChannelId: chainID,
Extension: ccHdrExtBytes,
Epoch: epoch}),
Expand Down

0 comments on commit 461ad48

Please sign in to comment.