Skip to content

Commit 2a12ea5

Browse files
ale-linuxMatthias Neugschwandtner
authored andcommitted
[FAB-9747] check capabilities for cc metadata put/get
Make sure that a chaincode can invoke the new metadata-related getters and setters only if the channel operates in 1.2 mode. Change-Id: I15e77cd88a6e7ef0e802b02743a7e3cbdcc30ee3 Signed-off-by: Alessandro Sorniotti <ale.linux@sopit.net> Signed-off-by: Matthias Neugschwandtner <eug@zurich.ibm.com>
1 parent ba89a79 commit 2a12ea5

File tree

10 files changed

+177
-18
lines changed

10 files changed

+177
-18
lines changed

core/chaincode/chaincode_suite_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,8 @@ type queryResponseBuilder interface {
135135
type registry interface {
136136
chaincode.Registry
137137
}
138+
139+
//go:generate counterfeiter -o fake/application_config_retriever.go --fake-name ApplicationConfigRetriever . applicationConfigRetriever
140+
type applicationConfigRetriever interface {
141+
chaincode.ApplicationConfigRetriever
142+
}

core/chaincode/chaincode_support.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ type ChaincodeSupport struct {
5353
Launcher Launcher
5454
SystemCCProvider sysccprovider.SystemChaincodeProvider
5555
Lifecycle Lifecycle
56+
appConfig ApplicationConfigRetriever
5657
}
5758

5859
// NewChaincodeSupport creates a new ChaincodeSupport instance.
@@ -68,6 +69,7 @@ func NewChaincodeSupport(
6869
processor Processor,
6970
SystemCCProvider sysccprovider.SystemChaincodeProvider,
7071
platformRegistry *platforms.Registry,
72+
appConfig ApplicationConfigRetriever,
7173
) *ChaincodeSupport {
7274
cs := &ChaincodeSupport{
7375
UserRunsCC: userRunsCC,
@@ -77,6 +79,7 @@ func NewChaincodeSupport(
7779
ACLProvider: aclProvider,
7880
SystemCCProvider: SystemCCProvider,
7981
Lifecycle: lifecycle,
82+
appConfig: appConfig,
8083
}
8184

8285
// Keep TestQueries working
@@ -178,6 +181,7 @@ func (cs *ChaincodeSupport) HandleChaincodeStream(stream ccintf.ChaincodeStream)
178181
QueryResponseBuilder: &QueryResponseGenerator{MaxResultLimit: 100},
179182
UUIDGenerator: UUIDGeneratorFunc(util.GenerateUUID),
180183
LedgerGetter: peer.Default,
184+
AppConfig: cs.appConfig,
181185
}
182186

183187
return handler.ProcessStream(stream)

core/chaincode/chaincode_support_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ func initMockPeer(chainIDs ...string) (*ChaincodeSupport, error) {
192192
),
193193
sccp,
194194
pr,
195+
peer.DefaultSupport,
195196
)
196197
ipRegistry.ChaincodeSupport = chaincodeSupport
197198

core/chaincode/exectransaction_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ func initPeer(chainIDs ...string) (net.Listener, *ChaincodeSupport, func(), erro
137137
),
138138
sccp,
139139
pr,
140+
peer.DefaultSupport,
140141
)
141142
ipRegistry.ChaincodeSupport = chaincodeSupport
142143
pb.RegisterChaincodeSupportServer(grpcServer, chaincodeSupport)

core/chaincode/fake/application_config_retriever.go

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

core/chaincode/handler.go

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ type Handler struct {
141141
LedgerGetter LedgerGetter
142142
// UUIDGenerator is used to generate UUIDs
143143
UUIDGenerator UUIDGenerator
144+
// AppConfig is used to retrieve the application config for a channel
145+
AppConfig ApplicationConfigRetriever
144146

145147
// state holds the current handler state. It will be created, established, or
146148
// ready.
@@ -151,8 +153,6 @@ type Handler struct {
151153
// the peer.
152154
ccInstance *sysccprovider.ChaincodeInstance
153155

154-
appConfig ApplicationConfigRetriever
155-
156156
// serialLock is used to serialize sends across the grpc chat stream.
157157
serialLock sync.Mutex
158158
// chatStream is the bidirectional grpc stream used to communicate with the
@@ -544,6 +544,29 @@ func (h *Handler) registerTxid(msg *pb.ChaincodeMessage) bool {
544544
return false
545545
}
546546

547+
func (h *Handler) checkMetadataCap(msg *pb.ChaincodeMessage) error {
548+
ac, there := h.AppConfig.GetApplicationConfig(msg.ChannelId)
549+
var err error
550+
if !there {
551+
err = errors.Errorf("[%s]Failed to get application config for invoked chaincode. Sending %s",
552+
shorttxid(msg.Txid),
553+
pb.ChaincodeMessage_ERROR,
554+
)
555+
chaincodeLogger.Errorf(err.Error())
556+
return err
557+
}
558+
559+
if !ac.Capabilities().KeyLevelEndorsement() {
560+
err = errors.Errorf("[%s]Request to invoke metadata function not supported. Sending %s",
561+
shorttxid(msg.Txid),
562+
pb.ChaincodeMessage_ERROR,
563+
)
564+
chaincodeLogger.Errorf(err.Error())
565+
return err
566+
}
567+
return nil
568+
}
569+
547570
// Handles query to ledger to get state
548571
func (h *Handler) HandleGetState(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) {
549572
key := string(msg.Payload)
@@ -575,8 +598,13 @@ func (h *Handler) HandleGetState(msg *pb.ChaincodeMessage, txContext *Transactio
575598

576599
// Handles query to ledger to get state metadata
577600
func (h *Handler) HandleGetStateMetadata(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) {
601+
err := h.checkMetadataCap(msg)
602+
if err != nil {
603+
return nil, errors.Wrap(err, "metadata not supported")
604+
}
605+
578606
getStateMetadata := &pb.GetStateMetadata{}
579-
err := proto.Unmarshal(msg.Payload, getStateMetadata)
607+
err = proto.Unmarshal(msg.Payload, getStateMetadata)
580608
if err != nil {
581609
return nil, errors.Wrap(err, "unmarshal failed")
582610
}
@@ -827,8 +855,13 @@ func (h *Handler) HandlePutState(msg *pb.ChaincodeMessage, txContext *Transactio
827855
}
828856

829857
func (h *Handler) HandlePutStateMetadata(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) {
858+
err := h.checkMetadataCap(msg)
859+
if err != nil {
860+
return nil, errors.Wrap(err, "metadata not supported")
861+
}
862+
830863
putStateMetadata := &pb.PutStateMetadata{}
831-
err := proto.Unmarshal(msg.Payload, putStateMetadata)
864+
err = proto.Unmarshal(msg.Payload, putStateMetadata)
832865
if err != nil {
833866
return nil, errors.Wrap(err, "unmarshal failed")
834867
}
@@ -1023,7 +1056,7 @@ func (h *Handler) Close() { h.TXContexts.Close() }
10231056

10241057
// GetApplicationConfig implements the method of the same name in the handlerSupport interface
10251058
func (h *Handler) GetApplicationConfig(chainID string) (channelconfig.Application, bool) {
1026-
return h.appConfig.GetApplicationConfig(chainID)
1059+
return h.AppConfig.GetApplicationConfig(chainID)
10271060
}
10281061

10291062
type State int

core/chaincode/handler_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"time"
1212

1313
"github.com/golang/protobuf/proto"
14+
"github.com/hyperledger/fabric/common/mocks/config"
1415
"github.com/hyperledger/fabric/common/util"
1516
"github.com/hyperledger/fabric/core/aclmgmt/resources"
1617
"github.com/hyperledger/fabric/core/chaincode"
@@ -40,6 +41,7 @@ var _ = Describe("Handler", func() {
4041
fakeInvoker *mock.Invoker
4142
fakeLedgerGetter *mock.LedgerGetter
4243
fakeHandlerRegistry *fake.Registry
44+
fakeApplicationConfigRetriever *fake.ApplicationConfigRetriever
4345

4446
responseNotifier chan *pb.ChaincodeMessage
4547
txContext *chaincode.TransactionContext
@@ -76,6 +78,12 @@ var _ = Describe("Handler", func() {
7678
fakeContextRegistry.GetReturns(txContext)
7779
fakeContextRegistry.CreateReturns(txContext, nil)
7880

81+
fakeApplicationConfigRetriever = &fake.ApplicationConfigRetriever{}
82+
applicationCapability := &config.MockApplication{
83+
CapabilitiesRv: &config.MockApplicationCapabilities{KeyLevelEndorsementRv: true},
84+
}
85+
fakeApplicationConfigRetriever.GetApplicationConfigReturns(applicationCapability, true)
86+
7987
handler = &chaincode.Handler{
8088
ACLProvider: fakeACLProvider,
8189
ActiveTransactions: fakeTransactionRegistry,
@@ -91,6 +99,7 @@ var _ = Describe("Handler", func() {
9199
UUIDGenerator: chaincode.UUIDGeneratorFunc(func() string {
92100
return "generated-query-id"
93101
}),
102+
AppConfig: fakeApplicationConfigRetriever,
94103
}
95104
chaincode.SetHandlerChatStream(handler, fakeChatStream)
96105
chaincode.SetHandlerChaincodeID(handler, &pb.ChaincodeID{Name: "test-handler-name"})

core/chaincode/shim/shim_test.go

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -959,7 +959,7 @@ func TestSetKeyEP(t *testing.T) {
959959
go func() {
960960
respSet := &mockpeer.MockResponseSet{
961961
DoneFunc: errorFunc,
962-
ErrorFunc: errorFunc,
962+
ErrorFunc: nil,
963963
Responses: []*mockpeer.MockResponse{
964964
{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_REGISTER}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_REGISTERED}},
965965
},
@@ -973,24 +973,25 @@ func TestSetKeyEP(t *testing.T) {
973973
//wait for init
974974
processDone(t, done, false)
975975

976-
channelId := "testchannel"
976+
channelID := "testchannel"
977977

978-
peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_READY, Txid: "1", ChannelId: channelId})
978+
peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_READY, Txid: "1", ChannelId: channelID})
979979

980980
ci := &pb.ChaincodeInput{Args: [][]byte{[]byte("init"), []byte("A"), []byte("100"), []byte("B"), []byte("200")}, Decorations: nil}
981981
payload := utils.MarshalOrPanic(ci)
982982
respSet := &mockpeer.MockResponseSet{
983983
DoneFunc: errorFunc,
984984
ErrorFunc: errorFunc,
985985
Responses: []*mockpeer.MockResponse{
986-
{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Txid: "2"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "2", ChannelId: channelId}},
987-
{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Txid: "2"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "2", ChannelId: channelId}},
988-
{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "2", ChannelId: channelId}, nil}},
986+
{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Txid: "2"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "2", ChannelId: channelID}},
987+
{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Txid: "2"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "2", ChannelId: channelID}},
988+
{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "2", ChannelId: channelID}, nil},
989+
},
989990
}
990991
peerSide.SetResponses(respSet)
991992

992993
//use the payload computed from prev init
993-
peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INIT, Payload: payload, Txid: "2", ChannelId: channelId})
994+
peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INIT, Payload: payload, Txid: "2", ChannelId: channelID})
994995

995996
processDone(t, done, false)
996997

@@ -999,15 +1000,16 @@ func TestSetKeyEP(t *testing.T) {
9991000
DoneFunc: errorFunc,
10001001
ErrorFunc: errorFunc,
10011002
Responses: []*mockpeer.MockResponse{
1002-
{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE_METADATA, Txid: "4", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: nil, Txid: "4", ChannelId: channelId}},
1003-
{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "4", ChannelId: channelId}, nil}},
1003+
{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE_METADATA, Txid: "4", ChannelId: channelID}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: nil, Txid: "4", ChannelId: channelID}},
1004+
{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "4", ChannelId: channelID}, nil},
1005+
},
10041006
}
10051007
peerSide.SetResponses(respSet)
10061008

10071009
ci = &pb.ChaincodeInput{Args: [][]byte{[]byte("putep"), []byte("A"), []byte("epA")}, Decorations: nil}
10081010
payload = utils.MarshalOrPanic(ci)
10091011

1010-
peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "4", ChannelId: channelId})
1012+
peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "4", ChannelId: channelID})
10111013

10121014
//wait for done
10131015
processDone(t, done, false)
@@ -1017,15 +1019,16 @@ func TestSetKeyEP(t *testing.T) {
10171019
DoneFunc: errorFunc,
10181020
ErrorFunc: errorFunc,
10191021
Responses: []*mockpeer.MockResponse{
1020-
{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE_METADATA, Txid: "5", ChannelId: channelId}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: []byte("epA"), Txid: "5", ChannelId: channelId}},
1021-
{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "5", ChannelId: channelId}, nil}},
1022+
{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE_METADATA, Txid: "5", ChannelId: channelID}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: []byte("epA"), Txid: "5", ChannelId: channelID}},
1023+
{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "5", ChannelId: channelID}, nil},
1024+
},
10221025
}
10231026
peerSide.SetResponses(respSet)
10241027

10251028
ci = &pb.ChaincodeInput{Args: [][]byte{[]byte("getep"), []byte("A")}, Decorations: nil}
10261029
payload = utils.MarshalOrPanic(ci)
10271030

1028-
peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "5", ChannelId: channelId})
1031+
peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "5", ChannelId: channelID})
10291032

10301033
//wait for done
10311034
processDone(t, done, false)

core/scc/cscc/configure_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ func TestConfigerInvokeJoinChainCorrectParams(t *testing.T) {
233233
),
234234
mp,
235235
platforms.NewRegistry(&golang.Platform{}),
236+
peer.DefaultSupport,
236237
)
237238

238239
// Init the policy checker

peer/node/start.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,7 @@ func registerChaincodeSupport(grpcServer *comm.GRPCServer, ccEndpoint string, ca
604604
}),
605605
sccp,
606606
pr,
607+
peer.DefaultSupport,
607608
)
608609
ipRegistry.ChaincodeSupport = chaincodeSupport
609610
ccp := chaincode.NewProvider(chaincodeSupport)

0 commit comments

Comments
 (0)