Skip to content

Commit

Permalink
[FAB-8391] Change Transaction ID to Header
Browse files Browse the repository at this point in the history
This change adjust the transactor to leverage a Transaction Header
and creates a TransactionID type. With the transaction header,
we can limit the need for placing proposal creation functions
into interfaces.

Change-Id: I9b4f33b1523fb7d960464a674a76553b46bb5aa9
Signed-off-by: Troy Ronda <troy@troyronda.com>
  • Loading branch information
troyronda committed Feb 23, 2018
1 parent f0853f3 commit 58e97f4
Show file tree
Hide file tree
Showing 33 changed files with 373 additions and 265 deletions.
11 changes: 9 additions & 2 deletions pkg/client/channel/chclient_test.go
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/hyperledger/fabric-sdk-go/pkg/fab/channel"
fcmocks "github.com/hyperledger/fabric-sdk-go/pkg/fab/mocks"
"github.com/hyperledger/fabric-sdk-go/pkg/fab/peer"
"github.com/hyperledger/fabric-sdk-go/pkg/fab/txn"
pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer"
"github.com/pkg/errors"
)
Expand Down Expand Up @@ -640,9 +641,15 @@ func createAndSendTestTransactionProposal(sender fab.ProposalSender, chrequest *
Args: chrequest.Args,
TransientMap: chrequest.TransientMap,
}
tpreq, err := sender.CreateChaincodeInvokeProposal(request)

txh, err := sender.CreateTransactionHeader()
if err != nil {
return nil, fab.EmptyTransactionID, errors.WithMessage(err, "creation of transaction header failed")
}

tpreq, err := txn.CreateChaincodeInvokeProposal(txh, request)
if err != nil {
return nil, fab.TransactionID{}, errors.WithMessage(err, "creation of transaction proposal failed")
return nil, fab.EmptyTransactionID, errors.WithMessage(err, "creation of transaction proposal failed")
}

tpr, err := sender.SendTransactionProposal(tpreq, targets)
Expand Down
8 changes: 5 additions & 3 deletions pkg/client/channel/txnhandler.go
Expand Up @@ -249,19 +249,21 @@ func createAndSendTransaction(sender fab.Sender, proposal *fab.TransactionPropos
return transactionResponse, nil
}

func createAndSendTransactionProposal(sender fab.ProposalSender, chrequest *Request, targets []fab.ProposalProcessor) ([]*fab.TransactionProposalResponse, *fab.TransactionProposal, error) {
func createAndSendTransactionProposal(transactor fab.Transactor, chrequest *Request, targets []fab.ProposalProcessor) ([]*fab.TransactionProposalResponse, *fab.TransactionProposal, error) {
request := fab.ChaincodeInvokeRequest{
ChaincodeID: chrequest.ChaincodeID,
Fcn: chrequest.Fcn,
Args: chrequest.Args,
TransientMap: chrequest.TransientMap,
}

proposal, err := sender.CreateChaincodeInvokeProposal(request)
txh, err := transactor.CreateTransactionHeader()

proposal, err := txn.CreateChaincodeInvokeProposal(txh, request)
if err != nil {
return nil, nil, errors.WithMessage(err, "creating transaction proposal failed")
}

transactionProposalResponses, err := sender.SendTransactionProposal(proposal, targets)
transactionProposalResponses, err := transactor.SendTransactionProposal(proposal, targets)
return transactionProposalResponses, proposal, err
}
25 changes: 5 additions & 20 deletions pkg/client/common/mocks/mocktransactor.go
Expand Up @@ -20,29 +20,14 @@ type MockTransactor struct {
Orderers []fab.Orderer
}

// CreateTransactionID creates a Transaction ID based on the current context.
func (t *MockTransactor) CreateTransactionID() (fab.TransactionID, error) {
txid, err := txn.NewID(t.Ctx)
// CreateTransactionHeader creates a Transaction Header based on the current context.
func (t *MockTransactor) CreateTransactionHeader() (fab.TransactionHeader, error) {
txh, err := txn.NewHeader(t.Ctx, t.ChannelID)
if err != nil {
return fab.TransactionID{}, errors.WithMessage(err, "new transaction ID failed")
return nil, errors.WithMessage(err, "new transaction ID failed")
}

return txid, nil
}

// CreateChaincodeInvokeProposal creates a Transaction Proposal based on the current context and channel config.
func (t *MockTransactor) CreateChaincodeInvokeProposal(request fab.ChaincodeInvokeRequest) (*fab.TransactionProposal, error) {
txid, err := t.CreateTransactionID()
if err != nil {
return nil, errors.WithMessage(err, "create transaction ID failed")
}

tp, err := txn.CreateChaincodeInvokeProposal(txid, t.ChannelID, request)
if err != nil {
return nil, errors.WithMessage(err, "new transaction proposal failed")
}

return tp, nil
return txh, nil
}

// SendTransactionProposal sends a TransactionProposal to the target peers.
Expand Down
2 changes: 1 addition & 1 deletion pkg/client/resmgmt/resmgmt.go
Expand Up @@ -470,7 +470,7 @@ func (rc *Client) sendCCProposal(ccProposalType channel.ChaincodeProposalType, c
IdentityContext: rc.identity,
}

txid, err := txn.NewID(&deployCtx)
txid, err := txn.NewHeader(&deployCtx, channelID)
if err != nil {
return errors.WithMessage(err, "create transaction ID failed")
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/context/api/fab/channel.go
Expand Up @@ -50,7 +50,7 @@ type Channel interface {
QueryInfo() (*common.BlockchainInfo, error)
QueryBlock(blockNumber int) (*common.Block, error)
QueryBlockByHash(blockHash []byte) (*common.Block, error)
QueryTransaction(transactionID string) (*pb.ProcessedTransaction, error)
QueryTransaction(transactionID TransactionID) (*pb.ProcessedTransaction, error)
QueryInstantiatedChaincodes() (*pb.ChaincodeQueryResponse, error)
QueryByChaincode(request ChaincodeInvokeRequest) ([][]byte, error)
QueryBySystemChaincode(request ChaincodeInvokeRequest) ([][]byte, error)
Expand All @@ -62,7 +62,7 @@ type ChannelLedger interface {
QueryInfo(targets []ProposalProcessor) ([]*common.BlockchainInfo, error)
QueryBlock(blockNumber int, targets []ProposalProcessor) ([]*common.Block, error)
QueryBlockByHash(blockHash []byte, targets []ProposalProcessor) ([]*common.Block, error)
QueryTransaction(transactionID string, targets []ProposalProcessor) ([]*pb.ProcessedTransaction, error)
QueryTransaction(transactionID TransactionID, targets []ProposalProcessor) ([]*pb.ProcessedTransaction, error)
QueryInstantiatedChaincodes(targets []ProposalProcessor) ([]*pb.ChaincodeQueryResponse, error)
QueryConfigBlock(targets []ProposalProcessor, minResponses int) (*common.ConfigEnvelope, error) // TODO: generalize minResponses
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/context/api/fab/event.go
Expand Up @@ -22,7 +22,7 @@ type EventHub interface {
Disconnect() error
RegisterChaincodeEvent(ccid string, eventname string, callback func(*ChaincodeEvent)) *ChainCodeCBE
UnregisterChaincodeEvent(cbe *ChainCodeCBE)
RegisterTxEvent(txnID TransactionID, callback func(string, pb.TxValidationCode, error))
RegisterTxEvent(txnID TransactionID, callback func(TransactionID, pb.TxValidationCode, error))
UnregisterTxEvent(txnID TransactionID)
RegisterBlockEvent(callback func(*common.Block))
UnregisterBlockEvent(callback func(*common.Block))
Expand Down
34 changes: 20 additions & 14 deletions pkg/context/api/fab/proposer.go
Expand Up @@ -6,33 +6,39 @@ SPDX-License-Identifier: Apache-2.0

package fab

import pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer"
import (
pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer"
)

// ProposalProcessor simulates transaction proposal, so that a client can submit the result for ordering.
type ProposalProcessor interface {
ProcessTransactionProposal(ProcessProposalRequest) (*TransactionProposalResponse, error)
}

// ProposalSender provides the ability for a transaction proposal to be created and sent.
//
// TODO: CreateChaincodeInvokeProposal should be refactored as it is mostly a factory method.
type ProposalSender interface {
CreateTransactionID() (TransactionID, error)
CreateChaincodeInvokeProposal(ChaincodeInvokeRequest) (*TransactionProposal, error)
CreateTransactionHeader() (TransactionHeader, error)
SendTransactionProposal(*TransactionProposal, []ProposalProcessor) ([]*TransactionProposalResponse, error)
}

// TransactionID contains the ID of a Fabric Transaction Proposal
// TODO: change to interface?
type TransactionID struct {
ID string
Creator []byte
Nonce []byte
// TransactionID provides the identifier of a Fabric transaction proposal.
type TransactionID string

// EmptyTransactionID represents a non-existing transaction (usually due to error).
const EmptyTransactionID = TransactionID("")

// SystemChannel is the Fabric channel for managaing resources.
const SystemChannel = ""

// TransactionHeader provides a handle to transaction metadata.
type TransactionHeader interface {
TransactionID() TransactionID
Creator() []byte
Nonce() []byte
ChannelID() string
}

// ChaincodeInvokeRequest contains the parameters for sending a transaction proposal.
//
// Deprecated: this struct has been replaced by ChaincodeInvokeProposal.
type ChaincodeInvokeRequest struct {
Targets []ProposalProcessor // Deprecated: this parameter is ignored in the new codes and will be removed shortly.
ChaincodeID string
Expand All @@ -43,7 +49,7 @@ type ChaincodeInvokeRequest struct {

// TransactionProposal contains a marashalled transaction proposal.
type TransactionProposal struct {
TxnID TransactionID // TODO: remove?
TxnID TransactionID
*pb.Proposal
}

Expand Down
18 changes: 6 additions & 12 deletions pkg/fab/channel/block.go
Expand Up @@ -20,34 +20,28 @@ import (
// block retrieves the block at the given position
func (c *Channel) block(pos *ab.SeekPosition) (*common.Block, error) {

creator, err := c.clientContext.Identity()
if err != nil {
return nil, errors.WithMessage(err, "serializing identity failed")
}

txnID, err := txn.NewID(c.clientContext)
th, err := txn.NewHeader(c.clientContext, c.name)
if err != nil {
return nil, errors.Wrap(err, "generating TX ID failed")
}

channelHeaderOpts := txn.ChannelHeaderOpts{
ChannelID: c.name,
TxnID: txnID,
TxnHeader: th,
TLSCertHash: ccomm.TLSCertHash(c.clientContext.Config()),
}
seekInfoHeader, err := txn.CreateChannelHeader(common.HeaderType_DELIVER_SEEK_INFO, channelHeaderOpts)
if err != nil {
return nil, errors.Wrap(err, "NewChannelHeader failed")
return nil, errors.Wrap(err, "CreateChannelHeader failed")
}

seekInfoHeaderBytes, err := proto.Marshal(seekInfoHeader)
if err != nil {
return nil, errors.Wrap(err, "marshal seek info failed")
}

signatureHeader := &common.SignatureHeader{
Creator: creator,
Nonce: txnID.Nonce,
signatureHeader, err := txn.CreateSignatureHeader(th)
if err != nil {
return nil, errors.Wrap(err, "CreateSignatureHeader failed")
}

signatureHeaderBytes, err := proto.Marshal(signatureHeader)
Expand Down
38 changes: 19 additions & 19 deletions pkg/fab/channel/channel.go
Expand Up @@ -381,7 +381,7 @@ func (c *Channel) QueryBlock(blockNumber int) (*common.Block, error) {
// This query will be made to the primary peer.
// Returns the ProcessedTransaction information containing the transaction.
// TODO: add optional target
func (c *Channel) QueryTransaction(transactionID string) (*pb.ProcessedTransaction, error) {
func (c *Channel) QueryTransaction(transactionID fab.TransactionID) (*pb.ProcessedTransaction, error) {
l, err := NewLedger(c.clientContext, c.name)
if err != nil {
return nil, errors.WithMessage(err, "ledger client creation failed")
Expand Down Expand Up @@ -456,19 +456,19 @@ func (c *Channel) SendInstantiateProposal(chaincodeName string,
collConfig []*common.CollectionConfig, targets []fab.ProposalProcessor) ([]*fab.TransactionProposalResponse, fab.TransactionID, error) {

if chaincodeName == "" {
return nil, fab.TransactionID{}, errors.New("chaincodeName is required")
return nil, fab.EmptyTransactionID, errors.New("chaincodeName is required")
}
if chaincodePath == "" {
return nil, fab.TransactionID{}, errors.New("chaincodePath is required")
return nil, fab.EmptyTransactionID, errors.New("chaincodePath is required")
}
if chaincodeVersion == "" {
return nil, fab.TransactionID{}, errors.New("chaincodeVersion is required")
return nil, fab.EmptyTransactionID, errors.New("chaincodeVersion is required")
}
if chaincodePolicy == nil {
return nil, fab.TransactionID{}, errors.New("chaincodePolicy is required")
return nil, fab.EmptyTransactionID, errors.New("chaincodePolicy is required")
}
if len(targets) == 0 {
return nil, fab.TransactionID{}, errors.New("missing peer objects for chaincode proposal")
return nil, fab.EmptyTransactionID, errors.New("missing peer objects for chaincode proposal")
}

cp := ChaincodeDeployRequest{
Expand All @@ -480,14 +480,14 @@ func (c *Channel) SendInstantiateProposal(chaincodeName string,
CollConfig: collConfig,
}

txid, err := txn.NewID(c.clientContext)
txh, err := txn.NewHeader(c.clientContext, c.name)
if err != nil {
return nil, fab.TransactionID{}, errors.WithMessage(err, "create transaction ID failed")
return nil, fab.EmptyTransactionID, errors.WithMessage(err, "create transaction ID failed")
}

tp, err := CreateChaincodeDeployProposal(txid, InstantiateChaincode, c.name, cp)
tp, err := CreateChaincodeDeployProposal(txh, InstantiateChaincode, c.name, cp)
if err != nil {
return nil, fab.TransactionID{}, errors.WithMessage(err, "creation of chaincode proposal failed")
return nil, fab.EmptyTransactionID, errors.WithMessage(err, "creation of chaincode proposal failed")
}

tpr, err := txn.SendProposal(c.clientContext, tp, targets)
Expand All @@ -500,19 +500,19 @@ func (c *Channel) SendUpgradeProposal(chaincodeName string,
chaincodePolicy *common.SignaturePolicyEnvelope, targets []fab.ProposalProcessor) ([]*fab.TransactionProposalResponse, fab.TransactionID, error) {

if chaincodeName == "" {
return nil, fab.TransactionID{}, errors.New("chaincodeName is required")
return nil, fab.EmptyTransactionID, errors.New("chaincodeName is required")
}
if chaincodePath == "" {
return nil, fab.TransactionID{}, errors.New("chaincodePath is required")
return nil, fab.EmptyTransactionID, errors.New("chaincodePath is required")
}
if chaincodeVersion == "" {
return nil, fab.TransactionID{}, errors.New("chaincodeVersion is required")
return nil, fab.EmptyTransactionID, errors.New("chaincodeVersion is required")
}
if chaincodePolicy == nil {
return nil, fab.TransactionID{}, errors.New("chaincodePolicy is required")
return nil, fab.EmptyTransactionID, errors.New("chaincodePolicy is required")
}
if len(targets) == 0 {
return nil, fab.TransactionID{}, errors.New("missing peer objects for chaincode proposal")
return nil, fab.EmptyTransactionID, errors.New("missing peer objects for chaincode proposal")
}

cp := ChaincodeDeployRequest{
Expand All @@ -523,14 +523,14 @@ func (c *Channel) SendUpgradeProposal(chaincodeName string,
Policy: chaincodePolicy,
}

txid, err := txn.NewID(c.clientContext)
txh, err := txn.NewHeader(c.clientContext, c.name)
if err != nil {
return nil, fab.TransactionID{}, errors.WithMessage(err, "create transaction ID failed")
return nil, fab.EmptyTransactionID, errors.WithMessage(err, "create transaction ID failed")
}

tp, err := CreateChaincodeDeployProposal(txid, UpgradeChaincode, c.name, cp)
tp, err := CreateChaincodeDeployProposal(txh, UpgradeChaincode, c.name, cp)
if err != nil {
return nil, fab.TransactionID{}, errors.WithMessage(err, "creation of chaincode proposal failed")
return nil, fab.EmptyTransactionID, errors.WithMessage(err, "creation of chaincode proposal failed")
}

tpr, err := txn.SendProposal(c.clientContext, tp, targets)
Expand Down
8 changes: 4 additions & 4 deletions pkg/fab/channel/ledger.go
Expand Up @@ -157,7 +157,7 @@ func createCommonBlock(tpr *fab.TransactionProposalResponse) (*common.Block, err
// QueryTransaction queries the ledger for Transaction by number.
// This query will be made to specified targets.
// Returns the ProcessedTransaction information containing the transaction.
func (c *Ledger) QueryTransaction(transactionID string, targets []fab.ProposalProcessor) ([]*pb.ProcessedTransaction, error) {
func (c *Ledger) QueryTransaction(transactionID fab.TransactionID, targets []fab.ProposalProcessor) ([]*pb.ProcessedTransaction, error) {

// prepare arguments to call qscc GetTransactionByID function
var args [][]byte
Expand Down Expand Up @@ -289,13 +289,13 @@ func collectProposalResponses(tprs []*fab.TransactionProposalResponse) [][]byte
return responses
}

func queryChaincode(ctx context.Context, channel string, request fab.ChaincodeInvokeRequest, targets []fab.ProposalProcessor) ([]*fab.TransactionProposalResponse, error) {
txid, err := txn.NewID(ctx)
func queryChaincode(ctx context.Context, channelID string, request fab.ChaincodeInvokeRequest, targets []fab.ProposalProcessor) ([]*fab.TransactionProposalResponse, error) {
txh, err := txn.NewHeader(ctx, channelID)
if err != nil {
return nil, errors.WithMessage(err, "creation of transaction ID failed")
}

tp, err := txn.CreateChaincodeInvokeProposal(txid, channel, request)
tp, err := txn.CreateChaincodeInvokeProposal(txh, request)
if err != nil {
return nil, errors.WithMessage(err, "NewProposal failed")
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/fab/channel/proposal.go
Expand Up @@ -37,7 +37,7 @@ type ChaincodeDeployRequest struct {
}

// CreateChaincodeDeployProposal creates an instantiate or upgrade chaincode proposal.
func CreateChaincodeDeployProposal(txid fab.TransactionID, deploy ChaincodeProposalType, channelID string, chaincode ChaincodeDeployRequest) (*fab.TransactionProposal, error) {
func CreateChaincodeDeployProposal(txh *txn.TransactionHeader, deploy ChaincodeProposalType, channelID string, chaincode ChaincodeDeployRequest) (*fab.TransactionProposal, error) {

// Generate arguments for deploy (channel, marshaled CCDS, marshaled chaincode policy, marshaled collection policy)
args := [][]byte{}
Expand Down Expand Up @@ -87,5 +87,5 @@ func CreateChaincodeDeployProposal(txid fab.TransactionID, deploy ChaincodePropo
Args: args,
}

return txn.CreateChaincodeInvokeProposal(txid, channelID, cir)
return txn.CreateChaincodeInvokeProposal(txh, cir)
}

0 comments on commit 58e97f4

Please sign in to comment.