Skip to content

Commit

Permalink
[FAB-5133] Split txn proposal APIs into their own pkg
Browse files Browse the repository at this point in the history
Change-Id: I303708523f07909aaf0b95b35b9789171350e324
Signed-off-by: Troy Ronda <troy@troyronda.com>
  • Loading branch information
troyronda committed Jun 30, 2017
1 parent d81817d commit f7b2f4f
Show file tree
Hide file tree
Showing 19 changed files with 224 additions and 143 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ integration-tests: integration-test
mock-gen:
go get -u github.com/golang/mock/gomock
go get -u github.com/golang/mock/mockgen
mockgen -source=pkg/fabric-client/peer/peer.go -destination=pkg/fabric-client/peer/mocks/mockpeer.gen.go
mockgen -build_flags '$(LDFLAGS)' github.com/hyperledger/fabric-sdk-go/api/txnapi TxnProposalProcessor | sed "s/github.com\/hyperledger\/fabric-sdk-go\/vendor\///g" > api/txnapi/mocks/mocktxnapi.gen.go
mockgen -build_flags '$(LDFLAGS)' github.com/hyperledger/fabric-sdk-go/api Config | sed "s/github.com\/hyperledger\/fabric-sdk-go\/vendor\///g" > api/mocks/mockconfig.gen.go

clean:
Expand Down
38 changes: 10 additions & 28 deletions api/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ SPDX-License-Identifier: Apache-2.0
package api

import (
"github.com/hyperledger/fabric-sdk-go/api/txnapi"
"github.com/hyperledger/fabric/msp"
"github.com/hyperledger/fabric/protos/common"
pb "github.com/hyperledger/fabric/protos/peer"
Expand Down Expand Up @@ -50,14 +51,16 @@ type Channel interface {
QueryTransaction(transactionID string) (*pb.ProcessedTransaction, error)
QueryInstantiatedChaincodes() (*pb.ChaincodeQueryResponse, error)
QueryByChaincode(chaincodeName string, args []string, targets []Peer) ([][]byte, error)
CreateTransactionProposal(chaincodeName string, channelID string, args []string, sign bool, transientData map[string][]byte) (*TransactionProposal, error)
SendTransactionProposal(proposal *TransactionProposal, retry int, targets []Peer) ([]*TransactionProposalResponse, error)
CreateTransaction(resps []*TransactionProposalResponse) (*Transaction, error)
SendTransaction(tx *Transaction) ([]*TransactionResponse, error)
SendInstantiateProposal(chaincodeName string, channelID string, args []string, chaincodePath string, chaincodeVersion string, targets []Peer) ([]*TransactionProposalResponse, string, error)
SendInstantiateProposal(chaincodeName string, channelID string, args []string, chaincodePath string, chaincodeVersion string, targets []Peer) ([]*txnapi.TransactionProposalResponse, string, error)
OrganizationUnits() ([]string, error)
QueryExtensionInterface() ChannelExtension
LoadConfigUpdateEnvelope(data []byte) error

// Transaction Proposal
CreateTransactionProposal(chaincodeName string, channelID string, args []string, sign bool, transientData map[string][]byte) (*txnapi.TransactionProposal, error)
SendTransactionProposal(proposal *txnapi.TransactionProposal, retry int, targets []Peer) ([]*txnapi.TransactionProposalResponse, error)
CreateTransaction(resps []*txnapi.TransactionProposalResponse) (*Transaction, error)
SendTransaction(tx *Transaction) ([]*TransactionResponse, error)
}

// The ChannelExtension interface allows extensions of the SDK to add functionality to Channel overloads.
Expand All @@ -68,7 +71,7 @@ type ChannelExtension interface {
BroadcastEnvelope(envelope *SignedEnvelope) ([]*TransactionResponse, error)

// TODO: This should go somewhere else - see TransactionProposal.GetBytes(). - deprecated
ProposalBytes(tp *TransactionProposal) ([]byte, error)
ProposalBytes(tp *txnapi.TransactionProposal) ([]byte, error)
}

// OrgAnchorPeer contains information about an anchor peer on this channel
Expand All @@ -84,27 +87,6 @@ type GenesisBlockRequest struct {
Nonce []byte
}

// The TransactionProposal object to be send to the endorsers
type TransactionProposal struct {
TransactionID string

SignedProposal *pb.SignedProposal
Proposal *pb.Proposal
}

// TransactionProposalResponse ...
/**
* The TransactionProposalResponse result object returned from endorsers.
*/
type TransactionProposalResponse struct {
Endorser string
Err error
Status int32

Proposal *TransactionProposal
ProposalResponse *pb.ProposalResponse
}

// JoinChannelRequest allows a set of peers to transact on a channel on the network
type JoinChannelRequest struct {
Targets []Peer
Expand All @@ -115,7 +97,7 @@ type JoinChannelRequest struct {

// The Transaction object created from an endorsed proposal
type Transaction struct {
Proposal *TransactionProposal
Proposal *txnapi.TransactionProposal
Transaction *pb.Transaction
}

Expand Down
3 changes: 2 additions & 1 deletion api/fabricclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ SPDX-License-Identifier: Apache-2.0
package api

import (
"github.com/hyperledger/fabric-sdk-go/api/txnapi"
"github.com/hyperledger/fabric/bccsp"
"github.com/hyperledger/fabric/protos/common"
pb "github.com/hyperledger/fabric/protos/peer"
Expand Down Expand Up @@ -42,7 +43,7 @@ type FabricClient interface {
GetCryptoSuite() bccsp.BCCSP
SaveUserToStateStore(user User, skipPersistence bool) error
LoadUserFromStateStore(name string) (User, error)
InstallChaincode(chaincodeName string, chaincodePath string, chaincodeVersion string, chaincodePackage []byte, targets []Peer) ([]*TransactionProposalResponse, string, error)
InstallChaincode(chaincodeName string, chaincodePath string, chaincodeVersion string, chaincodePackage []byte, targets []Peer) ([]*txnapi.TransactionProposalResponse, string, error)
QueryChannels(peer Peer) (*pb.ChannelQueryResponse, error)
QueryInstalledChaincodes(peer Peer) (*pb.ChaincodeQueryResponse, error)
GetIdentity() ([]byte, error)
Expand Down
14 changes: 11 additions & 3 deletions api/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ package api

import (
"encoding/pem"

"github.com/hyperledger/fabric-sdk-go/api/txnapi"
)

// The Peer class represents a peer in the target blockchain network to which
Expand All @@ -24,16 +26,22 @@ import (
// It should be noted that Peer event streams function at the Peer level and not at the
// channel and chaincode levels.
type Peer interface {
txnapi.TxnProposalProcessor

// Events (need verb)
ConnectEventSource()
IsEventListened(event string, channel Channel) (bool, error)
AddListener(eventType string, eventTypeData interface{}, eventCallback interface{}) (string, error)
RemoveListener(eventListenerRef string) (bool, error)

// ECert Client (need verb)
EnrollmentCertificate() *pem.Block
SetEnrollmentCertificate(pem *pem.Block)

// Peer Properties
Name() string
SetName(name string)
Roles() []string
SetRoles(roles []string)
EnrollmentCertificate() *pem.Block
SetEnrollmentCertificate(pem *pem.Block)
URL() string
SendProposal(proposal *TransactionProposal) (*TransactionProposalResponse, error)
}
45 changes: 45 additions & 0 deletions api/txnapi/mocks/mocktxnapi.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 42 additions & 0 deletions api/txnapi/txnproposer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

// Package txnapi allows SDK users to plugin their own implementations of transaction processing.
package txnapi

import (
pb "github.com/hyperledger/fabric/protos/peer"
)

// TxnProposalProcessor simulates transaction proposal, so that a client can submit the result for ordering.
type TxnProposalProcessor interface {
ProcessTransactionProposal(proposal TransactionProposal) (TransactionProposalResult, error)
}

// TransactionProposal requests simulation of a proposed transaction from transaction processors.
type TransactionProposal struct {
TransactionID string

SignedProposal *pb.SignedProposal
Proposal *pb.Proposal
}

// TransactionProposalResponse encapsulates both the result of transaction proposal processing and errors.
type TransactionProposalResponse struct {
TransactionProposalResult
Err error // TODO: consider refactoring
}

// TransactionProposalResult respresents the result of transaction proposal processing.
type TransactionProposalResult struct {
Endorser string
Status int32

Proposal TransactionProposal
ProposalResponse *pb.ProposalResponse
}

// TODO: TransactionProposalResponse and TransactionProposalResult may need better names.
8 changes: 6 additions & 2 deletions api/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,15 @@ type User interface {
GetName() string
GetRoles() []string
SetRoles([]string)
SetMspID(mspID string)
GetMspID() string

// ECerts
GetEnrollmentCertificate() []byte
SetEnrollmentCertificate(cert []byte)
SetPrivateKey(privateKey bccsp.Key)
GetPrivateKey() bccsp.Key
SetMspID(mspID string)
GetMspID() string

// TCerts
GenerateTcerts(count int, attributes []string)
}
53 changes: 25 additions & 28 deletions pkg/fabric-client/channel/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (

"github.com/golang/protobuf/proto"
api "github.com/hyperledger/fabric-sdk-go/api"
"github.com/hyperledger/fabric-sdk-go/api/txnapi"
"github.com/hyperledger/fabric/bccsp"

"github.com/hyperledger/fabric/msp"
Expand Down Expand Up @@ -97,7 +98,7 @@ func (c *channel) ClientContext() api.FabricClient {
}

// ProposalBytes returns the serialized transaction.
func (c *channel) ProposalBytes(tp *api.TransactionProposal) ([]byte, error) {
func (c *channel) ProposalBytes(tp *txnapi.TransactionProposal) ([]byte, error) {
return proto.Marshal(tp.SignedProposal)
}

Expand Down Expand Up @@ -459,7 +460,7 @@ func (c *channel) JoinChannel(request *api.JoinChannelRequest) error {
if err != nil {
return fmt.Errorf("Error signing proposal: %v", err)
}
transactionProposal := &api.TransactionProposal{
transactionProposal := &txnapi.TransactionProposal{
TransactionID: txID,
SignedProposal: signedProposal,
Proposal: proposal,
Expand Down Expand Up @@ -944,13 +945,13 @@ func (c *channel) QueryByChaincode(chaincodeName string, args []string, targets
* ECert to sign.
*/
func (c *channel) CreateTransactionProposal(chaincodeName string, channelID string,
args []string, sign bool, transientData map[string][]byte) (*api.TransactionProposal, error) {
args []string, sign bool, transientData map[string][]byte) (*txnapi.TransactionProposal, error) {
return CreateTransactionProposal(chaincodeName, channelID, args, sign, transientData, c.clientContext)
}

//CreateTransactionProposal ...
func CreateTransactionProposal(chaincodeName string, channelID string,
args []string, sign bool, transientData map[string][]byte, clientContext api.FabricClient) (*api.TransactionProposal, error) {
args []string, sign bool, transientData map[string][]byte, clientContext api.FabricClient) (*txnapi.TransactionProposal, error) {

argsArray := make([][]byte, len(args))
for i, arg := range args {
Expand Down Expand Up @@ -987,7 +988,7 @@ func CreateTransactionProposal(chaincodeName string, channelID string,
return nil, err
}
signedProposal := &pb.SignedProposal{ProposalBytes: proposalBytes, Signature: signature}
return &api.TransactionProposal{
return &txnapi.TransactionProposal{
TransactionID: txID,
SignedProposal: signedProposal,
Proposal: proposal,
Expand All @@ -997,7 +998,7 @@ func CreateTransactionProposal(chaincodeName string, channelID string,

// SendTransactionProposal ...
// Send the created proposal to peer for endorsement.
func (c *channel) SendTransactionProposal(proposal *api.TransactionProposal, retry int, targets []api.Peer) ([]*api.TransactionProposalResponse, error) {
func (c *channel) SendTransactionProposal(proposal *txnapi.TransactionProposal, retry int, targets []api.Peer) ([]*txnapi.TransactionProposalResponse, error) {
if proposal == nil || proposal.SignedProposal == nil {
return nil, fmt.Errorf("signedProposal is nil")
}
Expand All @@ -1014,40 +1015,36 @@ func (c *channel) SendTransactionProposal(proposal *api.TransactionProposal, ret
}

//SendTransactionProposal ...
func SendTransactionProposal(proposal *api.TransactionProposal, retry int, targetPeers []api.Peer) ([]*api.TransactionProposalResponse, error) {
func SendTransactionProposal(proposal *txnapi.TransactionProposal, retry int, targets []api.Peer) ([]*txnapi.TransactionProposalResponse, error) {

if proposal == nil || proposal.SignedProposal == nil {
return nil, fmt.Errorf("signedProposal is nil")
}

if len(targetPeers) < 1 {
if len(targets) < 1 {
return nil, fmt.Errorf("Missing peer objects for sending transaction proposal")
}

var responseMtx sync.Mutex
var transactionProposalResponses []*api.TransactionProposalResponse
var transactionProposalResponses []*txnapi.TransactionProposalResponse
var wg sync.WaitGroup

for _, p := range targetPeers {
for _, p := range targets {
wg.Add(1)
go func(peer api.Peer) {
go func(processor txnapi.TxnProposalProcessor) {
defer wg.Done()
var err error
var proposalResponse *api.TransactionProposalResponse
logger.Debugf("Send ProposalRequest to peer :%s", peer.URL())
if proposalResponse, err = peer.SendProposal(proposal); err != nil {
logger.Debugf("Receive Error Response :%v", proposalResponse)
proposalResponse = &api.TransactionProposalResponse{
Endorser: peer.URL(),
Err: fmt.Errorf("Error calling endorser '%s': %s", peer.URL(), err),
Proposal: proposal,
}
} else {
logger.Debugf("Receive Proposal ChaincodeActionResponse :%v\n", proposalResponse)

r, err := processor.ProcessTransactionProposal(*proposal)
if err != nil {
logger.Debugf("Received error response from txn proposal processing: %v", err)
// Error is handled downstream.
}

tpr := txnapi.TransactionProposalResponse{
TransactionProposalResult: r, Err: err}

responseMtx.Lock()
transactionProposalResponses = append(transactionProposalResponses, proposalResponse)
transactionProposalResponses = append(transactionProposalResponses, &tpr)
responseMtx.Unlock()
}(p)
}
Expand All @@ -1059,12 +1056,12 @@ func SendTransactionProposal(proposal *api.TransactionProposal, retry int, targe
/**
* Create a transaction with proposal response, following the endorsement policy.
*/
func (c *channel) CreateTransaction(resps []*api.TransactionProposalResponse) (*api.Transaction, error) {
func (c *channel) CreateTransaction(resps []*txnapi.TransactionProposalResponse) (*api.Transaction, error) {
if len(resps) == 0 {
return nil, fmt.Errorf("At least one proposal response is necessary")
}

proposal := resps[0].Proposal
proposal := &resps[0].Proposal

// the original header
hdr, err := protos_utils.GetHeader(proposal.Proposal.Header)
Expand Down Expand Up @@ -1206,7 +1203,7 @@ func (c *channel) SendTransaction(tx *api.Transaction) ([]*api.TransactionRespon
* @param {[]string} chaincodeVersion: required - string of the version of the chaincode
*/
func (c *channel) SendInstantiateProposal(chaincodeName string, channelID string,
args []string, chaincodePath string, chaincodeVersion string, targets []api.Peer) ([]*api.TransactionProposalResponse, string, error) {
args []string, chaincodePath string, chaincodeVersion string, targets []api.Peer) ([]*txnapi.TransactionProposalResponse, string, error) {

if chaincodeName == "" {
return nil, "", fmt.Errorf("Missing 'chaincodeName' parameter")
Expand Down Expand Up @@ -1258,7 +1255,7 @@ func (c *channel) SendInstantiateProposal(chaincodeName string, channelID string
return nil, "", err
}

transactionProposalResponse, err := c.SendTransactionProposal(&api.TransactionProposal{
transactionProposalResponse, err := c.SendTransactionProposal(&txnapi.TransactionProposal{
SignedProposal: signedProposal,
Proposal: proposal,
TransactionID: txID,
Expand Down
Loading

0 comments on commit f7b2f4f

Please sign in to comment.