Skip to content

Commit

Permalink
[FAB-8054] Split transactor from Channel
Browse files Browse the repository at this point in the history
This change splits the transactor into its own type and interface.

Change-Id: I07409a4ef58ae9e39fa38850738cb0a53000e6e0
Signed-off-by: Troy Ronda <troy@troyronda.com>
  • Loading branch information
troyronda committed Feb 16, 2018
1 parent 89112b8 commit ff9b6bf
Show file tree
Hide file tree
Showing 50 changed files with 1,077 additions and 853 deletions.
5 changes: 1 addition & 4 deletions api/apifabclient/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ import (
* primary orderer to retrieve the configuration settings for this channel.
*/
type Channel interface {
Sender
ProposalSender

Name() string
ChannelConfig() (*common.ConfigEnvelope, error)

Expand Down Expand Up @@ -56,7 +53,7 @@ type Channel interface {
QueryInstantiatedChaincodes() (*pb.ChaincodeQueryResponse, error)
QueryByChaincode(ChaincodeInvokeRequest) ([][]byte, error)
QueryBySystemChaincode(request ChaincodeInvokeRequest) ([][]byte, error)
QueryConfigBlock(peers []Peer, minResponses int) (*common.ConfigEnvelope, error)
QueryConfigBlock(targets []ProposalProcessor, minResponses int) (*common.ConfigEnvelope, error)
}

// ChannelLedger provides access to the underlying ledger for a channel.
Expand Down
9 changes: 8 additions & 1 deletion api/apifabclient/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ type ChannelProvider interface {
type ChannelService interface {
Config() (ChannelConfig, error)
Ledger() (ChannelLedger, error)
Channel() (Channel, error)
Channel() (Channel, error) // TODO remove
Transactor() (Transactor, error)
EventHub() (EventHub, error) // TODO support new event delivery
}

// Transactor supplies methods for sending transaction proposals and transactions.
type Transactor interface {
Sender
ProposalSender
}
4 changes: 2 additions & 2 deletions api/apifabclient/mocks/mockfabclient.gen.go

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

24 changes: 15 additions & 9 deletions api/apifabclient/proposer.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@ import (

// ProposalProcessor simulates transaction proposal, so that a client can submit the result for ordering.
type ProposalProcessor interface {
ProcessTransactionProposal(proposal TransactionProposal) (TransactionProposalResponse, error)
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 {
SendTransactionProposal(ChaincodeInvokeRequest, []ProposalProcessor) ([]*TransactionProposalResponse, TransactionID, error)
CreateChaincodeInvokeProposal(ChaincodeInvokeRequest) (*TransactionProposal, error)
SendTransactionProposal(*TransactionProposal, []ProposalProcessor) ([]*TransactionProposalResponse, error)
}

// TransactionID contains the ID of a Fabric Transaction Proposal
Expand All @@ -27,27 +30,30 @@ type TransactionID struct {
}

// ChaincodeInvokeRequest contains the parameters for sending a transaction proposal.
//
// Deprecated: this struct has been replaced by ChaincodeInvokeProposal.
type ChaincodeInvokeRequest struct {
Targets []ProposalProcessor // TODO: remove
Targets []ProposalProcessor // Deprecated: this parameter is ignored in the new codes and will be removed shortly.
ChaincodeID string
TransientMap map[string][]byte
Fcn string
Args [][]byte
}

// TransactionProposal requests simulation of a proposed transaction from transaction processors.
// TransactionProposal contains a marashalled transaction proposal.
type TransactionProposal struct {
TxnID TransactionID
TxnID TransactionID // TODO: remove?
*pb.Proposal
}

// ProcessProposalRequest requests simulation of a proposed transaction from transaction processors.
type ProcessProposalRequest struct {
SignedProposal *pb.SignedProposal
Proposal *pb.Proposal
}

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

Proposal TransactionProposal
ProposalResponse *pb.ProposalResponse
*pb.ProposalResponse
}
10 changes: 9 additions & 1 deletion api/apifabclient/sender.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,17 @@ import (
pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer"
)

// TransactionRequest holds endorsed Transaction Proposals.
type TransactionRequest struct {
Proposal *TransactionProposal
ProposalResponses []*TransactionProposalResponse
}

// Sender provides the ability for a transaction to be created and sent.
//
// TODO: CreateTransaction should be refactored as it is actually a factory method.
type Sender interface {
CreateTransaction(resps []*TransactionProposalResponse) (*Transaction, error)
CreateTransaction(request TransactionRequest) (*Transaction, error)
SendTransaction(tx *Transaction) (*TransactionResponse, error)
}

Expand Down
1 change: 1 addition & 0 deletions api/apitxn/chclient/chclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type Response struct {
Payload []byte
TransactionID apifabclient.TransactionID
TxValidationCode pb.TxValidationCode
Proposal *apifabclient.TransactionProposal
Responses []*apifabclient.TransactionProposalResponse
}

Expand Down
3 changes: 2 additions & 1 deletion api/apitxn/chclient/txnhandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ type Handler interface {
//ClientContext contains context parameters for handler execution
type ClientContext struct {
CryptoSuite apicryptosuite.CryptoSuite
Channel apifabclient.Channel
Discovery apifabclient.DiscoveryService
Selection apifabclient.SelectionService
Channel apifabclient.Channel // TODO: this should be removed when we have MSP split out.
Transactor apifabclient.Transactor
EventHub apifabclient.EventHub
}

Expand Down
89 changes: 89 additions & 0 deletions pkg/fabric-client/channel/ccdeploy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package channel

import (
"github.com/golang/protobuf/proto"
"github.com/pkg/errors"

"github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/common"
pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer"
protos_utils "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/utils"

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

// ChaincodeProposalType reflects transitions in the chaincode lifecycle
type ChaincodeProposalType int

// Define chaincode proposal types
const (
InstantiateChaincode ChaincodeProposalType = iota
UpgradeChaincode
)

// ChaincodeDeployRequest holds parameters for creating an instantiate or upgrade chaincode proposal.
type ChaincodeDeployRequest struct {
Name string
Path string
Version string
Args [][]byte
Policy *common.SignaturePolicyEnvelope
CollConfig []*common.CollectionConfig
}

// CreateChaincodeDeployProposal creates an instantiate or upgrade chaincode proposal.
func CreateChaincodeDeployProposal(ctx fab.IdentityContext, deploy ChaincodeProposalType, channelID string, chaincode ChaincodeDeployRequest) (*fab.TransactionProposal, error) {

ccds := &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{
Type: pb.ChaincodeSpec_GOLANG, ChaincodeId: &pb.ChaincodeID{Name: chaincode.Name, Path: chaincode.Path, Version: chaincode.Version},
Input: &pb.ChaincodeInput{Args: chaincode.Args}}}

creator, err := ctx.Identity()
if err != nil {
return nil, errors.Wrap(err, "getting user context's identity failed")
}
chaincodePolicyBytes, err := protos_utils.Marshal(chaincode.Policy)
if err != nil {
return nil, err
}
var collConfigBytes []byte
if chaincode.CollConfig != nil {
var err error
collConfigBytes, err = proto.Marshal(&common.CollectionConfigPackage{Config: chaincode.CollConfig})
if err != nil {
return nil, err
}
}

var proposal *pb.Proposal
var txID string

switch deploy {

case InstantiateChaincode:
proposal, txID, err = protos_utils.CreateDeployProposalFromCDS(channelID, ccds, creator, chaincodePolicyBytes, []byte("escc"), []byte("vscc"), collConfigBytes)
if err != nil {
return nil, errors.Wrap(err, "create instantiate chaincode proposal failed")
}
case UpgradeChaincode:
proposal, txID, err = protos_utils.CreateUpgradeProposalFromCDS(channelID, ccds, creator, chaincodePolicyBytes, []byte("escc"), []byte("vscc"))
if err != nil {
return nil, errors.Wrap(err, "create upgrade chaincode proposal failed")
}
default:
return nil, errors.Errorf("chaincode proposal type %d not supported", deploy)
}

txnID := fab.TransactionID{ID: txID} // Nonce is missing
tp := fab.TransactionProposal{
Proposal: proposal,
TxnID: txnID,
}

return &tp, err
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ package channel

import (
"net"
"strings"
"testing"

"google.golang.org/grpc"
Expand All @@ -22,19 +21,6 @@ import (
"github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/mocks"
)

func TestAddPeerDuplicateCheck(t *testing.T) {
channel, _ := setupTestChannel()

peer := mocks.MockPeer{MockName: "Peer1", MockURL: "http://peer1.com", MockRoles: []string{}, MockCert: nil}
channel.AddPeer(&peer)

err := channel.AddPeer(&peer)

if err == nil || !strings.Contains(err.Error(), "http://peer1.com already exists") {
t.Fatal("Duplicate Peer check is not working as expected")
}
}

func TestSendInstantiateProposal(t *testing.T) {
//Setup channel
user := mocks.NewMockUserWithMSPID("test", "1234")
Expand All @@ -45,15 +31,14 @@ func TestSendInstantiateProposal(t *testing.T) {
defer mockCtrl.Finish()
proc := mock_fab.NewMockProposalProcessor(mockCtrl)

tp := fab.TransactionProposal{SignedProposal: &pb.SignedProposal{}}
tpr := fab.TransactionProposalResponse{Endorser: "example.com", Status: 99, Proposal: tp, ProposalResponse: nil}
tpr := fab.TransactionProposalResponse{Endorser: "example.com", Status: 99}

proc.EXPECT().ProcessTransactionProposal(gomock.Any()).Return(tpr, nil)
proc.EXPECT().ProcessTransactionProposal(gomock.Any()).Return(tpr, nil)
proc.EXPECT().ProcessTransactionProposal(gomock.Any()).Return(&tpr, nil)
proc.EXPECT().ProcessTransactionProposal(gomock.Any()).Return(&tpr, nil)
targets := []fab.ProposalProcessor{proc}

//Add a Peer
peer := mocks.MockPeer{MockName: "Peer1", MockURL: "http://peer1.com", MockRoles: []string{}, MockCert: nil}
peer := mocks.MockPeer{MockName: "Peer1", MockURL: "http://peer1.com", MockRoles: []string{}}
channel.AddPeer(&peer)

tresponse, txnid, err := channel.SendInstantiateProposal("", nil, "",
Expand Down Expand Up @@ -121,10 +106,9 @@ func TestSendUpgradeProposal(t *testing.T) {
defer mockCtrl.Finish()
proc := mock_fab.NewMockProposalProcessor(mockCtrl)

tp := fab.TransactionProposal{SignedProposal: &pb.SignedProposal{}}
tpr := fab.TransactionProposalResponse{Endorser: "example.com", Status: 99, Proposal: tp, ProposalResponse: nil}
tpr := fab.TransactionProposalResponse{Endorser: "example.com", Status: 99, ProposalResponse: nil}

proc.EXPECT().ProcessTransactionProposal(gomock.Any()).Return(tpr, nil)
proc.EXPECT().ProcessTransactionProposal(gomock.Any()).Return(&tpr, nil)
targets := []fab.ProposalProcessor{proc}

//Add a Peer
Expand Down
Loading

0 comments on commit ff9b6bf

Please sign in to comment.