Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use any peer to evaluate system chaincode transactions #3447

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions integration/gateway/gateway_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/hyperledger/fabric-protos-go/gateway"
"github.com/hyperledger/fabric-protos-go/orderer"
"github.com/hyperledger/fabric-protos-go/peer"
"github.com/hyperledger/fabric-protos-go/peer/lifecycle"
"github.com/hyperledger/fabric/integration/nwo"
"github.com/hyperledger/fabric/protoutil"
. "github.com/onsi/ginkgo"
Expand Down Expand Up @@ -262,6 +263,25 @@ var _ = Describe("GatewayService", func() {
Expect(response.Result.Payload).To(Equal(expectedResponse.Result.Payload))
Expect(proto.Equal(response, expectedResponse)).To(BeTrue(), "Expected\n\t%#v\nto proto.Equal\n\t%#v", response, expectedResponse)
})

It("should responsd with system chaincode result", func() {
proposedTransaction, transactionID := NewProposedTransaction(signingIdentity, "testchannel", "qscc", "GetChainInfo", nil, []byte("testchannel"))

request := &gateway.EvaluateRequest{
TransactionId: transactionID,
ChannelId: "testchannel",
ProposedTransaction: proposedTransaction,
}

response, err := gatewayClient.Evaluate(ctx, request)
Expect(err).NotTo(HaveOccurred())

status := common.Status(response.GetResult().GetStatus())
Expect(status).To(Equal(common.Status_SUCCESS))

blockchainInfo := new(common.BlockchainInfo)
Expect(proto.Unmarshal(response.GetResult().GetPayload(), blockchainInfo)).NotTo(HaveOccurred())
})
})

Describe("Submit", func() {
Expand All @@ -275,6 +295,29 @@ var _ = Describe("GatewayService", func() {
Expect(result.Payload).To(Equal(expectedResult.Payload))
Expect(proto.Equal(result, expectedResult)).To(BeTrue(), "Expected\n\t%#v\nto proto.Equal\n\t%#v", result, expectedResult)
})

It("should endorse a system chaincode transaction", func() {
arg, err := proto.Marshal(&lifecycle.QueryInstalledChaincodesArgs{})
Expect(err).NotTo(HaveOccurred())
adminSigner := network.PeerUserSigner(org1Peer0, "Admin")
proposedTransaction, transactionID := NewProposedTransaction(adminSigner, "testchannel", "_lifecycle", "QueryInstalledChaincodes", nil, arg)

request := &gateway.EndorseRequest{
TransactionId: transactionID,
ChannelId: "testchannel",
ProposedTransaction: proposedTransaction,
EndorsingOrganizations: []string{adminSigner.MSPID}, // Only use peers for our admin ID org
}

response, err := gatewayClient.Endorse(ctx, request)
Expect(err).NotTo(HaveOccurred())

chaincodeAction, err := protoutil.GetActionFromEnvelopeMsg(response.GetPreparedTransaction())
Expect(err).NotTo(HaveOccurred())

queryResult := new(lifecycle.QueryInstalledChaincodesResult)
Expect(proto.Unmarshal(chaincodeAction.GetResponse().GetPayload(), queryResult)).NotTo(HaveOccurred())
})
})

Describe("CommitStatus", func() {
Expand Down
1 change: 1 addition & 0 deletions internal/peer/node/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,7 @@ func serve(args []string) error {
aclProvider,
coreConfig.LocalMSPID,
coreConfig.GatewayOptions,
builtinSCCs,
)
gatewayprotos.RegisterGatewayServer(peerServer.Server(), gatewayServer)
} else {
Expand Down
3 changes: 2 additions & 1 deletion internal/pkg/gateway/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1837,6 +1837,7 @@ func TestNilArgs(t *testing.T) {
"msp1",
&comm.SecureOptions{},
config.GetOptions(viper.New()),
nil,
)
ctx := context.Background()

Expand Down Expand Up @@ -1979,7 +1980,7 @@ func prepareTest(t *testing.T, tt *testDef) *preparedTest {
Endpoint: "localhost:7051",
}

server := newServer(localEndorser, disc, mockFinder, mockPolicy, mockLedgerProvider, member, "msp1", &comm.SecureOptions{}, options)
server := newServer(localEndorser, disc, mockFinder, mockPolicy, mockLedgerProvider, member, "msp1", &comm.SecureOptions{}, options, nil)

dialer := &mocks.Dialer{}
dialer.Returns(nil, nil)
Expand Down
26 changes: 24 additions & 2 deletions internal/pkg/gateway/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/hyperledger/fabric/common/flogging"
"github.com/hyperledger/fabric/common/ledger"
"github.com/hyperledger/fabric/core/peer"
"github.com/hyperledger/fabric/core/scc"
gdiscovery "github.com/hyperledger/fabric/gossip/discovery"
"github.com/hyperledger/fabric/internal/pkg/comm"
"github.com/hyperledger/fabric/internal/pkg/gateway/commit"
Expand Down Expand Up @@ -52,7 +53,16 @@ type LedgerProvider interface {
}

// CreateServer creates an embedded instance of the Gateway.
func CreateServer(localEndorser peerproto.EndorserServer, discovery Discovery, peerInstance *peer.Peer, secureOptions *comm.SecureOptions, policy ACLChecker, localMSPID string, options config.Options) *Server {
func CreateServer(
localEndorser peerproto.EndorserServer,
discovery Discovery,
peerInstance *peer.Peer,
secureOptions *comm.SecureOptions,
policy ACLChecker,
localMSPID string,
options config.Options,
systemChaincodes scc.BuiltinSCCs,
) *Server {
adapter := &peerAdapter{
Peer: peerInstance,
}
Expand All @@ -70,14 +80,25 @@ func CreateServer(localEndorser peerproto.EndorserServer, discovery Discovery, p
localMSPID,
secureOptions,
options,
systemChaincodes,
)

peerInstance.AddConfigCallbacks(server.registry.configUpdate)

return server
}

func newServer(localEndorser peerproto.EndorserClient, discovery Discovery, finder CommitFinder, policy ACLChecker, ledgerProvider LedgerProvider, localInfo gdiscovery.NetworkMember, localMSPID string, secureOptions *comm.SecureOptions, options config.Options) *Server {
func newServer(localEndorser peerproto.EndorserClient,
discovery Discovery,
finder CommitFinder,
policy ACLChecker,
ledgerProvider LedgerProvider,
localInfo gdiscovery.NetworkMember,
localMSPID string,
secureOptions *comm.SecureOptions,
options config.Options,
systemChaincodes scc.BuiltinSCCs,
) *Server {
return &Server{
registry: &registry{
localEndorser: &endorser{client: localEndorser, endpointConfig: &endpointConfig{pkiid: localInfo.PKIid, address: localInfo.Endpoint, mspid: localMSPID}},
Expand All @@ -86,6 +107,7 @@ func newServer(localEndorser peerproto.EndorserClient, discovery Discovery, find
endpointFactory: &endpointFactory{timeout: options.DialTimeout, clientCert: secureOptions.Certificate, clientKey: secureOptions.Key},
remoteEndorsers: map[string]*endorser{},
channelInitialized: map[string]bool{},
systemChaincodes: systemChaincodes,
},
commitFinder: finder,
policy: policy,
Expand Down
32 changes: 22 additions & 10 deletions internal/pkg/gateway/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ import (
"github.com/hyperledger/fabric-protos-go/peer"
"github.com/hyperledger/fabric/common/channelconfig"
"github.com/hyperledger/fabric/common/flogging"
"github.com/hyperledger/fabric/core/scc"
gossipapi "github.com/hyperledger/fabric/gossip/api"
gossipcommon "github.com/hyperledger/fabric/gossip/common"
gossipdiscovery "github.com/hyperledger/fabric/gossip/discovery"
"github.com/pkg/errors"
)

type Discovery interface {
Expand All @@ -42,6 +44,7 @@ type registry struct {
channelInitialized map[string]bool
configLock sync.RWMutex
channelOrderers sync.Map // channel (string) -> orderer addresses (endpointConfig)
systemChaincodes scc.BuiltinSCCs
}

type endorserState struct {
Expand All @@ -55,7 +58,7 @@ func (reg *registry) endorsementPlan(channel string, interest *peer.ChaincodeInt
descriptor, err := reg.discovery.PeersForEndorsement(gossipcommon.ChannelID(channel), interest)
if err != nil {
logger.Errorw("PeersForEndorsement failed.", "error", err, "channel", channel, "ChaincodeInterest", proto.MarshalTextString(interest))
return nil, fmt.Errorf("no combination of peers can be derived which satisfy the endorsement policy: %s", err)
return nil, errors.Wrap(err, "no combination of peers can be derived which satisfy the endorsement policy")
}

// There are two parts to an endorsement plan:
Expand Down Expand Up @@ -186,17 +189,16 @@ func (reg *registry) endorsersByOrg(channel string, chaincode string) map[string
if endorser == nil {
continue
}
for _, installedChaincode := range member.Properties.GetChaincodes() {
// only consider the peers that have our chaincode installed
if installedChaincode.GetName() == chaincode {
endorsersByOrg[endorser.mspid] = append(endorsersByOrg[endorser.mspid], &endorserState{endorser: endorser, height: member.Properties.GetLedgerHeight()})
}
}
for _, es := range endorsersByOrg {
// sort by decreasing height in each org
sort.Slice(es, sorter(es, reg.localEndorser.address))
if reg.hasChaincode(member, chaincode) {
endorsersByOrg[endorser.mspid] = append(endorsersByOrg[endorser.mspid], &endorserState{endorser: endorser, height: member.Properties.GetLedgerHeight()})
}
}

// sort by decreasing height in each org
for _, es := range endorsersByOrg {
sort.Slice(es, sorter(es, reg.localEndorser.address))
}

return endorsersByOrg
}

Expand Down Expand Up @@ -465,3 +467,13 @@ func (reg *registry) closeStaleOrdererConnections(channel string, channelOrderer
}
}
}

func (reg *registry) hasChaincode(member gossipdiscovery.NetworkMember, chaincodeName string) bool {
for _, installedChaincode := range member.Properties.GetChaincodes() {
if installedChaincode.GetName() == chaincodeName {
return true
}
}

return reg.systemChaincodes.IsSysCC(chaincodeName)
}