Skip to content

Commit

Permalink
[FAB-5201] Refactor SendTransactionProposal
Browse files Browse the repository at this point in the history
- SendTransactionProposal and QueryByChaincode take struct parameters
- SendTransactionProposal creates and sends in one step
- TransactionID struct used (and returned)

Change-Id: I41bc22d207c0b15d0ad449edf3f28bbba489965e
Signed-off-by: Troy Ronda <troy@troyronda.com>
  • Loading branch information
troyronda committed Jul 7, 2017
1 parent ab834b8 commit 6265e33
Show file tree
Hide file tree
Showing 35 changed files with 764 additions and 459 deletions.
28 changes: 5 additions & 23 deletions api/apifabclient/channel.go
Expand Up @@ -30,14 +30,8 @@ type Channel interface {
Name() string
Initialize(data []byte) error
IsInitialized() bool
IsSecurityEnabled() bool
QueryExtensionInterface() ChannelExtension
LoadConfigUpdateEnvelope(data []byte) error
SendInstantiateProposal(chaincodeName string, args []string, chaincodePath string, chaincodeVersion string, targets []txn.ProposalProcessor) ([]*txn.TransactionProposalResponse, string, error)

// TCerts
TCertBatchSize() int
SetTCertBatchSize(batchSize int)
SendInstantiateProposal(chaincodeName string, args []string, chaincodePath string, chaincodeVersion string, targets []txn.ProposalProcessor) ([]*txn.TransactionProposalResponse, txn.TransactionID, error)

// Network
// TODO: Use PeerEndorser
Expand Down Expand Up @@ -66,18 +60,8 @@ type Channel interface {
QueryBlockByHash(blockHash []byte) (*common.Block, error)
QueryTransaction(transactionID string) (*pb.ProcessedTransaction, error)
QueryInstantiatedChaincodes() (*pb.ChaincodeQueryResponse, error)
QueryByChaincode(chaincodeName string, args []string, targets []txn.ProposalProcessor) ([][]byte, error)
}

// The ChannelExtension interface allows extensions of the SDK to add functionality to Channel overloads.
type ChannelExtension interface {
ClientContext() FabricClient

SignPayload(payload []byte) (*SignedEnvelope, error)
BroadcastEnvelope(envelope *SignedEnvelope) ([]*txn.TransactionResponse, error)

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

// OrgAnchorPeer contains information about an anchor peer on this channel
Expand All @@ -89,14 +73,12 @@ type OrgAnchorPeer struct {

// GenesisBlockRequest ...
type GenesisBlockRequest struct {
TxID string
Nonce []byte
TxnID txn.TransactionID
}

// JoinChannelRequest allows a set of peers to transact on a channel on the network
type JoinChannelRequest struct {
Targets []Peer
GenesisBlock *common.Block
TxID string
Nonce []byte
TxnID txn.TransactionID
}
5 changes: 3 additions & 2 deletions api/apifabclient/event.go
Expand Up @@ -7,6 +7,7 @@ SPDX-License-Identifier: Apache-2.0
package apifabclient

import (
"github.com/hyperledger/fabric-sdk-go/api/apitxn"
common "github.com/hyperledger/fabric/protos/common"
ehpb "github.com/hyperledger/fabric/protos/peer"
pb "github.com/hyperledger/fabric/protos/peer"
Expand All @@ -20,8 +21,8 @@ type EventHub interface {
Disconnect()
RegisterChaincodeEvent(ccid string, eventname string, callback func(*ChaincodeEvent)) *ChainCodeCBE
UnregisterChaincodeEvent(cbe *ChainCodeCBE)
RegisterTxEvent(txID string, callback func(string, pb.TxValidationCode, error))
UnregisterTxEvent(txID string)
RegisterTxEvent(txnID apitxn.TransactionID, callback func(string, pb.TxValidationCode, error))
UnregisterTxEvent(txnID apitxn.TransactionID)
RegisterBlockEvent(callback func(*common.Block))
UnregisterBlockEvent(callback func(*common.Block))
}
Expand Down
1 change: 1 addition & 0 deletions api/apifabclient/fabricclient.go
Expand Up @@ -51,6 +51,7 @@ type FabricClient interface {
GetUserContext() User
SetUserContext(user User)
GetConfig() config.Config // TODO: refactor to a fab client config interface
NewTxnID() (txn.TransactionID, error)
}

// CreateChannelRequest requests channel creation on the network
Expand Down
23 changes: 22 additions & 1 deletion api/apitxn/proposer.go
Expand Up @@ -16,9 +16,30 @@ type ProposalProcessor interface {
ProcessTransactionProposal(proposal TransactionProposal) (TransactionProposalResult, error)
}

// ProposalSender provides the ability for a transaction proposal to be created and sent.
type ProposalSender interface {
SendTransactionProposal(ChaincodeInvokeRequest) ([]*TransactionProposalResponse, TransactionID, error)
}

// TransactionID contains the ID of a Fabric Transaction Proposal
type TransactionID struct {
ID string
Nonce []byte
}

// ChaincodeInvokeRequest contains the parameters for sending a transaction proposal.
type ChaincodeInvokeRequest struct {
Targets []ProposalProcessor
ChaincodeID string
TxnID TransactionID // TODO: does it make sense to include the TxnID in the request?
TransientMap map[string][]byte
Fcn string
Args []string
}

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

SignedProposal *pb.SignedProposal
Proposal *pb.Proposal
Expand Down
6 changes: 0 additions & 6 deletions api/apitxn/sender.go
Expand Up @@ -17,12 +17,6 @@ type Sender interface {
SendTransaction(tx *Transaction) ([]*TransactionResponse, error)
}

// ProposalSender provides the ability for a transaction proposal to be created and sent.
type ProposalSender interface {
CreateTransactionProposal(chaincodeName string, args []string, sign bool, transientData map[string][]byte) (*TransactionProposal, error)
SendTransactionProposal(proposal *TransactionProposal, retry int, targets []ProposalProcessor) ([]*TransactionProposalResponse, error)
}

// The Transaction object created from an endorsed proposal.
type Transaction struct {
Proposal *TransactionProposal
Expand Down
8 changes: 4 additions & 4 deletions pkg/fabric-client/channel/block.go
Expand Up @@ -34,11 +34,11 @@ func (c *Channel) GenesisBlock(request *fab.GenesisBlockRequest) (*common.Block,
return nil, fmt.Errorf("GenesisBlock - error: Missing orderer assigned to this channel for the GenesisBlock request")
}
// verify that we have transaction id
if request.TxID == "" {
if request.TxnID.ID == "" {
return nil, fmt.Errorf("GenesisBlock - error: Missing txId input parameter with the required transaction identifier")
}
// verify that we have the nonce
if request.Nonce == nil {
if request.TxnID.Nonce == nil {
return nil, fmt.Errorf("GenesisBlock - error: Missing nonce input parameter with the required single use number")
}

Expand All @@ -57,11 +57,11 @@ func (c *Channel) GenesisBlock(request *fab.GenesisBlockRequest) (*common.Block,
Behavior: ab.SeekInfo_BLOCK_UNTIL_READY,
}
protos_utils.MakeChannelHeader(common.HeaderType_DELIVER_SEEK_INFO, 1, c.Name(), 0)
seekInfoHeader, err := BuildChannelHeader(common.HeaderType_DELIVER_SEEK_INFO, c.Name(), request.TxID, 0, "", time.Now())
seekInfoHeader, err := BuildChannelHeader(common.HeaderType_DELIVER_SEEK_INFO, c.Name(), request.TxnID.ID, 0, "", time.Now())
if err != nil {
return nil, fmt.Errorf("Error building channel header: %v", err)
}
seekHeader, err := fc.BuildHeader(creator, seekInfoHeader, request.Nonce)
seekHeader, err := fc.BuildHeader(creator, seekInfoHeader, request.TxnID.Nonce)
if err != nil {
return nil, fmt.Errorf("Error building header: %v", err)
}
Expand Down
16 changes: 8 additions & 8 deletions pkg/fabric-client/channel/block_test.go
Expand Up @@ -10,7 +10,7 @@ import (
"testing"

fab "github.com/hyperledger/fabric-sdk-go/api/apifabclient"
fc "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/internal"
"github.com/hyperledger/fabric-sdk-go/api/apitxn"
"github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/mocks"
"github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/peer"
)
Expand All @@ -22,12 +22,13 @@ func TestGenesisBlock(t *testing.T) {
peers = append(peers, peer)
orderer := mocks.NewMockOrderer("", nil)
orderer.(mocks.MockOrderer).EnqueueForSendDeliver(mocks.NewSimpleMockError())
nonce, _ := fc.GenerateRandomNonce()
txID, _ := fc.ComputeTxID(nonce, []byte("testID"))
txid, _ := channel.ClientContext().NewTxnID()
badtxid := apitxn.TransactionID{
ID: txid.ID,
}

genesisBlockReq := &fab.GenesisBlockRequest{
TxID: txID,
Nonce: nonce,
TxnID: txid,
}

channel.AddOrderer(orderer)
Expand Down Expand Up @@ -65,7 +66,7 @@ func TestGenesisBlock(t *testing.T) {
}

genesisBlockReq = &fab.GenesisBlockRequest{
TxID: txID,
TxnID: badtxid,
}
_, err = channel.GenesisBlock(genesisBlockReq)

Expand All @@ -76,8 +77,7 @@ func TestGenesisBlock(t *testing.T) {
channel.RemoveOrderer(orderer)

genesisBlockReq = &fab.GenesisBlockRequest{
TxID: txID,
Nonce: nonce,
TxnID: txid,
}

_, err = channel.GenesisBlock(genesisBlockReq)
Expand Down
49 changes: 19 additions & 30 deletions pkg/fabric-client/channel/channel.go
Expand Up @@ -10,6 +10,8 @@ import (
"fmt"

fab "github.com/hyperledger/fabric-sdk-go/api/apifabclient"
"github.com/hyperledger/fabric-sdk-go/api/apitxn"
"github.com/hyperledger/fabric/bccsp"
"github.com/hyperledger/fabric/msp"
"github.com/op/go-logging"
)
Expand All @@ -22,14 +24,21 @@ type Channel struct {
name string // aka channel ID
securityEnabled bool // Security enabled flag
peers map[string]fab.Peer
// TODO proposalProcessors map[string]txn.ProposalProcessor
tcertBatchSize int // The number of tcerts to get in each batch
orderers map[string]fab.Orderer
clientContext fab.FabricClient
primaryPeer fab.Peer
mspManager msp.MSPManager
anchorPeers []*fab.OrgAnchorPeer
initialized bool
orderers map[string]fab.Orderer
clientContext ClientContext
primaryPeer fab.Peer
mspManager msp.MSPManager
anchorPeers []*fab.OrgAnchorPeer
initialized bool
}

// ClientContext ...
type ClientContext interface {
GetUserContext() fab.User
GetIdentity() ([]byte, error)
GetCryptoSuite() bccsp.BCCSP
NewTxnID() (apitxn.TransactionID, error)
// TODO: ClientContext.IsSecurityEnabled()
}

// NewChannel represents a channel in a Fabric network.
Expand All @@ -46,19 +55,14 @@ func NewChannel(name string, client fab.FabricClient) (*Channel, error) {
p := make(map[string]fab.Peer)
o := make(map[string]fab.Orderer)
c := Channel{name: name, securityEnabled: client.GetConfig().IsSecurityEnabled(), peers: p,
tcertBatchSize: client.GetConfig().TcertBatchSize(), orderers: o, clientContext: client, mspManager: msp.NewMSPManager()}
orderers: o, clientContext: client, mspManager: msp.NewMSPManager()}
logger.Infof("Constructed channel instance: %v", c)

return &c, nil
}

// QueryExtensionInterface ... TODO.
func (c *Channel) QueryExtensionInterface() fab.ChannelExtension {
return c
}

// ClientContext returns the Client that was passed in to NewChannel
func (c *Channel) ClientContext() fab.FabricClient {
func (c *Channel) ClientContext() ClientContext {
return c.clientContext
}

Expand All @@ -67,21 +71,6 @@ func (c *Channel) Name() string {
return c.name
}

// IsSecurityEnabled determine if security is enabled.
func (c *Channel) IsSecurityEnabled() bool {
return c.securityEnabled
}

// TCertBatchSize gets the tcert batch size.
func (c *Channel) TCertBatchSize() int {
return c.tcertBatchSize
}

// SetTCertBatchSize sets the tcert batch size.
func (c *Channel) SetTCertBatchSize(batchSize int) {
c.tcertBatchSize = batchSize
}

// AddPeer adds a peer endpoint to channel.
// It returns error if the peer with that url already exists.
func (c *Channel) AddPeer(peer fab.Peer) error {
Expand Down
3 changes: 2 additions & 1 deletion pkg/fabric-client/channel/channel_test.go
Expand Up @@ -298,11 +298,12 @@ func setupTestChannel() (*Channel, error) {
user := mocks.NewMockUser("test")
cryptoSuite := &mocks.MockCryptoSuite{}
client.SaveUserToStateStore(user, true)
client.SetUserContext(user)
client.SetCryptoSuite(cryptoSuite)
return NewChannel("testChannel", client)
}

func setupMassiveTestChannel(numberOfPeers int, numberOfOrderers int) (fab.Channel, error) {
func setupMassiveTestChannel(numberOfPeers int, numberOfOrderers int) (*Channel, error) {
channel, error := setupTestChannel()
if error != nil {
return channel, error
Expand Down
18 changes: 0 additions & 18 deletions pkg/fabric-client/channel/config_test.go
Expand Up @@ -22,20 +22,6 @@ func TestChannelConfigs(t *testing.T) {

channel, _ := NewChannel("testChannel", client)

if client.GetConfig().IsSecurityEnabled() != channel.IsSecurityEnabled() {
t.Fatal("Is Security Enabled flag is incorrect in channel")
}

if client.GetConfig().TcertBatchSize() != channel.TCertBatchSize() {
t.Fatal("Tcert batch size is incorrect")
}

channel.SetTCertBatchSize(22)

if channel.TCertBatchSize() != 22 {
t.Fatal("TCert batch size update on channel is not working")
}

if channel.IsReadonly() {
//TODO: Rightnow it is returning false always, need to revisit test once actual implementation is provided
t.Fatal("Is Readonly test failed")
Expand All @@ -46,10 +32,6 @@ func TestChannelConfigs(t *testing.T) {
t.Fatal("UpdateChannel test failed")
}

if channel.QueryExtensionInterface().ClientContext() != client {
t.Fatal("Client context not matching with client")
}

channel.SetMSPManager(nil)

}
Expand Down

0 comments on commit 6265e33

Please sign in to comment.