Skip to content

Commit a2a2973

Browse files
committed
[FAB-12963] Prover Service: check token capability
- Add CapabilityChecker interface and implementation - ProcessCommand checks if FabToken capability is enabled and returns error response if not enabled Change-Id: I74d4b4222507c169b44d7aee87f58c7a8623f905 Signed-off-by: Wenjian Qiao <wenjianq@gmail.com>
1 parent 225a683 commit a2a2973

File tree

5 files changed

+207
-32
lines changed

5 files changed

+207
-32
lines changed

peer/node/start.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,9 @@ func registerProverService(peerServer *comm.GRPCServer, aclProvider aclmgmt.ACLP
884884
}
885885

886886
prover := &server.Prover{
887+
CapabilityChecker: &server.TokenCapabilityChecker{
888+
PeerOps: peer.Default,
889+
},
887890
Marshaler: responseMarshaler,
888891
PolicyChecker: policyChecker,
889892
TMSManager: &server.Manager{

token/server/capability_checker.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
Copyright IBM Corp. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
package server
7+
8+
import (
9+
"github.com/hyperledger/fabric/core/peer"
10+
"github.com/pkg/errors"
11+
)
12+
13+
//go:generate counterfeiter -o mock/capability_checker.go -fake-name CapabilityChecker . CapabilityChecker
14+
15+
// CapabilityChecker is used to check whether or not a channel supports token functions.
16+
type CapabilityChecker interface {
17+
FabToken(channelId string) (bool, error)
18+
}
19+
20+
// TokenCapabilityChecker implements CapabilityChecker interface
21+
type TokenCapabilityChecker struct {
22+
PeerOps peer.Operations
23+
}
24+
25+
func (c *TokenCapabilityChecker) FabToken(channelId string) (bool, error) {
26+
ac, ok := c.PeerOps.GetChannelConfig(channelId).ApplicationConfig()
27+
if !ok {
28+
return false, errors.Errorf("no application config found for channel %s", channelId)
29+
}
30+
return ac.Capabilities().FabToken(), nil
31+
}

token/server/mock/capability_checker.go

Lines changed: 103 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

token/server/prover.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@ type Marshaler interface {
3030

3131
// A Provider is responslble for processing token commands.
3232
type Prover struct {
33-
Marshaler Marshaler
34-
PolicyChecker PolicyChecker
35-
TMSManager TMSManager
33+
CapabilityChecker CapabilityChecker
34+
Marshaler Marshaler
35+
PolicyChecker PolicyChecker
36+
TMSManager TMSManager
3637
}
3738

3839
// NewProver creates a Prover
@@ -62,6 +63,16 @@ func (s *Prover) ProcessCommand(ctx context.Context, sc *token.SignedCommand) (*
6263
return s.MarshalErrorResponse(sc.Command, err)
6364
}
6465

66+
// check if FabToken capability is enabled
67+
channelId := command.Header.ChannelId
68+
enabled, err := s.CapabilityChecker.FabToken(channelId)
69+
if err != nil {
70+
return s.MarshalErrorResponse(sc.Command, err)
71+
}
72+
if !enabled {
73+
return s.MarshalErrorResponse(sc.Command, errors.Errorf("FabToken capability not enabled for channel %s", channelId))
74+
}
75+
6576
err = s.PolicyChecker.Check(sc, command)
6677
if err != nil {
6778
return s.MarshalErrorResponse(sc.Command, err)

token/server/prover_test.go

Lines changed: 56 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,12 @@ func clock() time.Time {
3232

3333
var _ = Describe("Prover", func() {
3434
var (
35-
fakePolicyChecker *mock.PolicyChecker
36-
fakeMarshaler *mock.Marshaler
37-
fakeIssuer *mock.Issuer
38-
fakeTransactor *mock.Transactor
39-
fakeTMSManager *mock.TMSManager
35+
fakeCapabilityChecker *mock.CapabilityChecker
36+
fakePolicyChecker *mock.PolicyChecker
37+
fakeMarshaler *mock.Marshaler
38+
fakeIssuer *mock.Issuer
39+
fakeTransactor *mock.Transactor
40+
fakeTMSManager *mock.TMSManager
4041

4142
prover *server.Prover
4243

@@ -59,6 +60,8 @@ var _ = Describe("Prover", func() {
5960
)
6061

6162
BeforeEach(func() {
63+
fakeCapabilityChecker = &mock.CapabilityChecker{}
64+
fakeCapabilityChecker.FabTokenReturns(true, nil)
6265
fakePolicyChecker = &mock.PolicyChecker{}
6366

6467
tokenTransaction = &token.TokenTransaction{
@@ -138,9 +141,10 @@ var _ = Describe("Prover", func() {
138141
fakeMarshaler.MarshalCommandResponseReturns(marshaledResponse, nil)
139142

140143
prover = &server.Prover{
141-
PolicyChecker: fakePolicyChecker,
142-
Marshaler: fakeMarshaler,
143-
TMSManager: fakeTMSManager,
144+
CapabilityChecker: fakeCapabilityChecker,
145+
PolicyChecker: fakePolicyChecker,
146+
Marshaler: fakeMarshaler,
147+
TMSManager: fakeTMSManager,
144148
}
145149

146150
importRequest = &token.ImportRequest{
@@ -342,6 +346,25 @@ var _ = Describe("Prover", func() {
342346
}))
343347
})
344348
})
349+
350+
Context("when fabtoken capability is not enabled", func() {
351+
BeforeEach(func() {
352+
fakeCapabilityChecker.FabTokenReturns(false, nil)
353+
})
354+
355+
It("returns a response with error", func() {
356+
resp, err := prover.ProcessCommand(context.Background(), signedCommand)
357+
Expect(err).NotTo(HaveOccurred())
358+
Expect(resp).To(Equal(marshaledResponse))
359+
360+
Expect(fakeMarshaler.MarshalCommandResponseCallCount()).To(Equal(1))
361+
cmd, payload := fakeMarshaler.MarshalCommandResponseArgsForCall(0)
362+
Expect(cmd).To(Equal(ProtoMarshal(command)))
363+
Expect(payload).To(Equal(&token.CommandResponse_Err{
364+
Err: &token.Error{Message: "FabToken capability not enabled for channel channel-id"},
365+
}))
366+
})
367+
})
345368
})
346369

347370
Describe("ProcessCommand_RequestImport", func() {
@@ -624,9 +647,10 @@ var _ = Describe("Prover", func() {
624647

625648
BeforeEach(func() {
626649
prover = &server.Prover{
627-
PolicyChecker: fakePolicyChecker,
628-
Marshaler: fakeMarshaler,
629-
TMSManager: manager,
650+
CapabilityChecker: fakeCapabilityChecker,
651+
PolicyChecker: fakePolicyChecker,
652+
Marshaler: fakeMarshaler,
653+
TMSManager: manager,
630654
}
631655
importRequest = &token.ImportRequest{
632656
Credential: []byte("credential"),
@@ -726,11 +750,7 @@ var _ = Describe("Prover", func() {
726750
fakeSignerIdentity.SignReturns([]byte("response_signature"), nil)
727751
marshaler, _ = server.NewResponseMarshaler(fakeSignerIdentity)
728752

729-
prover = &server.Prover{
730-
PolicyChecker: fakePolicyChecker,
731-
Marshaler: marshaler,
732-
TMSManager: manager,
733-
}
753+
prover.Marshaler = marshaler
734754

735755
// start grpc server for prover
736756
listener, err := net.Listen("tcp", "127.0.0.1:")
@@ -846,6 +866,8 @@ var _ = Describe("ProverListUnspentTokens", func() {
846866
fakeIterator := &mock2.ResultsIterator{}
847867
fakePolicyChecker := &mock.PolicyChecker{}
848868
fakeSigner := &mock.SignerIdentity{}
869+
fakeCapabilityChecker := &mock.CapabilityChecker{}
870+
fakeCapabilityChecker.FabTokenReturns(true, nil)
849871

850872
fakeLedgerReader := &mock2.LedgerReader{}
851873
fakeLedgerManager := &mock2.LedgerManager{}
@@ -855,9 +877,10 @@ var _ = Describe("ProverListUnspentTokens", func() {
855877
marshaler = &server.ResponseMarshaler{Signer: fakeSigner, Creator: []byte("Alice"), Time: clock}
856878

857879
prover = &server.Prover{
858-
Marshaler: marshaler,
859-
PolicyChecker: fakePolicyChecker,
860-
TMSManager: manager,
880+
CapabilityChecker: fakeCapabilityChecker,
881+
Marshaler: marshaler,
882+
PolicyChecker: fakePolicyChecker,
883+
TMSManager: manager,
861884
}
862885

863886
fakeLedgerReader.GetStateRangeScanIteratorReturns(fakeIterator, nil)
@@ -964,13 +987,14 @@ var _ = Describe("ProverListUnspentTokens", func() {
964987

965988
var _ = Describe("Prover Transfer using TMS", func() {
966989
var (
967-
prover *server.Prover
968-
marshaler *server.ResponseMarshaler
969-
expectedResponse *token.CommandResponse_TokenTransaction
970-
command *token.Command
971-
signedCommand *token.SignedCommand
972-
marshaledCommand []byte
973-
transferRequest *token.TransferRequest
990+
fakeCapabilityChecker *mock.CapabilityChecker
991+
prover *server.Prover
992+
marshaler *server.ResponseMarshaler
993+
expectedResponse *token.CommandResponse_TokenTransaction
994+
command *token.Command
995+
signedCommand *token.SignedCommand
996+
marshaledCommand []byte
997+
transferRequest *token.TransferRequest
974998
)
975999
It("initializes variables and expected responses", func() {
9761000

@@ -1036,6 +1060,8 @@ var _ = Describe("Prover Transfer using TMS", func() {
10361060
inTokens[1], err = proto.Marshal(&token.PlainOutput{Owner: []byte("Alice"), Type: "XYZ", Quantity: 200})
10371061
Expect(err).NotTo(HaveOccurred())
10381062

1063+
fakeCapabilityChecker = &mock.CapabilityChecker{}
1064+
fakeCapabilityChecker.FabTokenReturns(true, nil)
10391065
fakePolicyChecker := &mock.PolicyChecker{}
10401066
fakeSigner := &mock.SignerIdentity{}
10411067
fakeLedgerReader := &mock2.LedgerReader{}
@@ -1045,9 +1071,10 @@ var _ = Describe("Prover Transfer using TMS", func() {
10451071
marshaler = &server.ResponseMarshaler{Signer: fakeSigner, Creator: []byte("creator"), Time: clock}
10461072

10471073
prover = &server.Prover{
1048-
Marshaler: marshaler,
1049-
PolicyChecker: fakePolicyChecker,
1050-
TMSManager: manager,
1074+
CapabilityChecker: fakeCapabilityChecker,
1075+
Marshaler: marshaler,
1076+
PolicyChecker: fakePolicyChecker,
1077+
TMSManager: manager,
10511078
}
10521079

10531080
fakeSigner.SignReturns([]byte("it is a signature"), nil)

0 commit comments

Comments
 (0)