Skip to content

Commit fc95c06

Browse files
committed
[FAB-3329] set chaincode version in ProposalResponse
When endorser endorse proposal, set ChaincodeID field of ChaincodeAction with the ChaincodeID which was used to execute chaincode, especially the chaincode version. This CR add ChaincodeID to escc args and set it when endorsing proposal. Another CR will implement checking chaincode version of transaction matches latest chaincode version in commiiter side. Change-Id: I62d7a5d34e12ff9d3131aa52d1af428bb8d58f2e Signed-off-by: jiangyaoguo <[email protected]>
1 parent 62aec85 commit fc95c06

15 files changed

+165
-73
lines changed

common/ledger/testutil/test_helper.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/hyperledger/fabric/common/util"
2626
lutils "github.com/hyperledger/fabric/core/ledger/util"
2727
"github.com/hyperledger/fabric/protos/common"
28+
pb "github.com/hyperledger/fabric/protos/peer"
2829
ptestutils "github.com/hyperledger/fabric/protos/testutils"
2930
"github.com/hyperledger/fabric/protos/utils"
3031

@@ -75,15 +76,18 @@ func (bg *BlockGenerator) NextTestBlocks(numBlocks int) []*common.Block {
7576

7677
// ConstructTransaction constructs a transaction for testing
7778
func ConstructTransaction(_ *testing.T, simulationResults []byte, sign bool) (*common.Envelope, string, error) {
78-
ccName := "foo"
79+
ccid := &pb.ChaincodeID{
80+
Name: "foo",
81+
Version: "v1",
82+
}
7983
//response := &pb.Response{Status: 200}
8084
var txID string
8185
var txEnv *common.Envelope
8286
var err error
8387
if sign {
84-
txEnv, txID, err = ptestutils.ConstructSingedTxEnvWithDefaultSigner(util.GetTestChainID(), ccName, nil, simulationResults, nil, nil)
88+
txEnv, txID, err = ptestutils.ConstructSingedTxEnvWithDefaultSigner(util.GetTestChainID(), ccid, nil, simulationResults, nil, nil)
8589
} else {
86-
txEnv, txID, err = ptestutils.ConstructUnsingedTxEnv(util.GetTestChainID(), ccName, nil, simulationResults, nil, nil)
90+
txEnv, txID, err = ptestutils.ConstructUnsingedTxEnv(util.GetTestChainID(), ccid, nil, simulationResults, nil, nil)
8791
}
8892
return txEnv, txID, err
8993
}

core/chaincode/exectransaction_test.go

+15-7
Original file line numberDiff line numberDiff line change
@@ -171,28 +171,36 @@ func endTxSimulationCDS(chainID string, _ string, txsim ledger.TxSimulator, payl
171171
if err != nil {
172172
return err
173173
}
174+
175+
// get lscc ChaincodeID
176+
lsccid := &pb.ChaincodeID{
177+
Name: "lscc",
178+
Version: util.GetSysCCVersion(),
179+
}
180+
174181
// get a proposal - we need it to get a transaction
175182
prop, _, err := putils.CreateDeployProposalFromCDS(chainID, cds, ss, nil, nil, nil)
176183
if err != nil {
177184
return err
178185
}
179186

180-
return endTxSimulation(chainID, txsim, payload, commit, prop, blockNumber)
187+
return endTxSimulation(chainID, lsccid, txsim, payload, commit, prop, blockNumber)
181188
}
182189

183-
func endTxSimulationCIS(chainID string, _ string, txsim ledger.TxSimulator, payload []byte, commit bool, cis *pb.ChaincodeInvocationSpec, blockNumber uint64) error {
190+
func endTxSimulationCIS(chainID string, ccid *pb.ChaincodeID, _ string, txsim ledger.TxSimulator, payload []byte, commit bool, cis *pb.ChaincodeInvocationSpec, blockNumber uint64) error {
184191
// get serialized version of the signer
185192
ss, err := signer.Serialize()
186193
if err != nil {
187194
return err
188195
}
196+
189197
// get a proposal - we need it to get a transaction
190198
prop, _, err := putils.CreateProposalFromCIS(common.HeaderType_ENDORSER_TRANSACTION, chainID, cis, ss)
191199
if err != nil {
192200
return err
193201
}
194202

195-
return endTxSimulation(chainID, txsim, payload, commit, prop, blockNumber)
203+
return endTxSimulation(chainID, ccid, txsim, payload, commit, prop, blockNumber)
196204
}
197205

198206
//getting a crash from ledger.Commit when doing concurrent invokes
@@ -205,7 +213,7 @@ func endTxSimulationCIS(chainID string, _ string, txsim ledger.TxSimulator, payl
205213
//concurrently (100 concurrent invokes followed by 100 concurrent queries)
206214
var _commitLock_ sync.Mutex
207215

208-
func endTxSimulation(chainID string, txsim ledger.TxSimulator, _ []byte, commit bool, prop *pb.Proposal, blockNumber uint64) error {
216+
func endTxSimulation(chainID string, ccid *pb.ChaincodeID, txsim ledger.TxSimulator, _ []byte, commit bool, prop *pb.Proposal, blockNumber uint64) error {
209217
txsim.Done()
210218
if lgr := peer.GetLedger(chainID); lgr != nil {
211219
if commit {
@@ -218,7 +226,7 @@ func endTxSimulation(chainID string, txsim ledger.TxSimulator, _ []byte, commit
218226
}
219227

220228
// assemble a (signed) proposal response message
221-
resp, err := putils.CreateProposalResponse(prop.Header, prop.Payload, &pb.Response{Status: 200}, txSimulationResults, nil, nil, signer)
229+
resp, err := putils.CreateProposalResponse(prop.Header, prop.Payload, &pb.Response{Status: 200}, txSimulationResults, nil, ccid, nil, signer)
222230
if err != nil {
223231
return err
224232
}
@@ -355,10 +363,10 @@ func invokeWithVersion(ctx context.Context, chainID string, version string, spec
355363
//no error, lets try commit
356364
if err == nil {
357365
//capture returned error from commit
358-
err = endTxSimulationCIS(chainID, uuid, txsim, []byte("invoke"), true, cdInvocationSpec, blockNumber)
366+
err = endTxSimulationCIS(chainID, spec.ChaincodeId, uuid, txsim, []byte("invoke"), true, cdInvocationSpec, blockNumber)
359367
} else {
360368
//there was an error, just close simulation and return that
361-
endTxSimulationCIS(chainID, uuid, txsim, []byte("invoke"), false, cdInvocationSpec, blockNumber)
369+
endTxSimulationCIS(chainID, spec.ChaincodeId, uuid, txsim, []byte("invoke"), false, cdInvocationSpec, blockNumber)
362370
}
363371
}()
364372

core/common/validation/fullflow_test.go

+11-7
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,17 @@ import (
3535
func getProposal() (*peer.Proposal, error) {
3636
cis := &peer.ChaincodeInvocationSpec{
3737
ChaincodeSpec: &peer.ChaincodeSpec{
38-
ChaincodeId: &peer.ChaincodeID{Name: "foo"},
38+
ChaincodeId: getChaincodeID(),
3939
Type: peer.ChaincodeSpec_GOLANG}}
4040

4141
proposal, _, err := utils.CreateProposalFromCIS(common.HeaderType_ENDORSER_TRANSACTION, util.GetTestChainID(), cis, signerSerialized)
4242
return proposal, err
4343
}
4444

45+
func getChaincodeID() *peer.ChaincodeID {
46+
return &peer.ChaincodeID{Name: "foo", Version: "v1"}
47+
}
48+
4549
func TestGoodPath(t *testing.T) {
4650
// get a toy proposal
4751
prop, err := getProposal()
@@ -68,7 +72,7 @@ func TestGoodPath(t *testing.T) {
6872
simRes := []byte("simulation_result")
6973

7074
// endorse it to get a proposal response
71-
presp, err := utils.CreateProposalResponse(prop.Header, prop.Payload, response, simRes, nil, nil, signer)
75+
presp, err := utils.CreateProposalResponse(prop.Header, prop.Payload, response, simRes, nil, getChaincodeID(), nil, signer)
7276
if err != nil {
7377
t.Fatalf("CreateProposalResponse failed, err %s", err)
7478
return
@@ -202,7 +206,7 @@ func TestBadTx(t *testing.T) {
202206
simRes := []byte("simulation_result")
203207

204208
// endorse it to get a proposal response
205-
presp, err := utils.CreateProposalResponse(prop.Header, prop.Payload, response, simRes, nil, nil, signer)
209+
presp, err := utils.CreateProposalResponse(prop.Header, prop.Payload, response, simRes, nil, getChaincodeID(), nil, signer)
206210
if err != nil {
207211
t.Fatalf("CreateProposalResponse failed, err %s", err)
208212
return
@@ -255,7 +259,7 @@ func Test2EndorsersAgree(t *testing.T) {
255259
simRes1 := []byte("simulation_result")
256260

257261
// endorse it to get a proposal response
258-
presp1, err := utils.CreateProposalResponse(prop.Header, prop.Payload, response1, simRes1, nil, nil, signer)
262+
presp1, err := utils.CreateProposalResponse(prop.Header, prop.Payload, response1, simRes1, nil, getChaincodeID(), nil, signer)
259263
if err != nil {
260264
t.Fatalf("CreateProposalResponse failed, err %s", err)
261265
return
@@ -265,7 +269,7 @@ func Test2EndorsersAgree(t *testing.T) {
265269
simRes2 := []byte("simulation_result")
266270

267271
// endorse it to get a proposal response
268-
presp2, err := utils.CreateProposalResponse(prop.Header, prop.Payload, response2, simRes2, nil, nil, signer)
272+
presp2, err := utils.CreateProposalResponse(prop.Header, prop.Payload, response2, simRes2, nil, getChaincodeID(), nil, signer)
269273
if err != nil {
270274
t.Fatalf("CreateProposalResponse failed, err %s", err)
271275
return
@@ -298,7 +302,7 @@ func Test2EndorsersDisagree(t *testing.T) {
298302
simRes1 := []byte("simulation_result1")
299303

300304
// endorse it to get a proposal response
301-
presp1, err := utils.CreateProposalResponse(prop.Header, prop.Payload, response1, simRes1, nil, nil, signer)
305+
presp1, err := utils.CreateProposalResponse(prop.Header, prop.Payload, response1, simRes1, nil, getChaincodeID(), nil, signer)
302306
if err != nil {
303307
t.Fatalf("CreateProposalResponse failed, err %s", err)
304308
return
@@ -308,7 +312,7 @@ func Test2EndorsersDisagree(t *testing.T) {
308312
simRes2 := []byte("simulation_result2")
309313

310314
// endorse it to get a proposal response
311-
presp2, err := utils.CreateProposalResponse(prop.Header, prop.Payload, response2, simRes2, nil, nil, signer)
315+
presp2, err := utils.CreateProposalResponse(prop.Header, prop.Payload, response2, simRes2, nil, getChaincodeID(), nil, signer)
312316
if err != nil {
313317
t.Fatalf("CreateProposalResponse failed, err %s", err)
314318
return

core/endorser/endorser.go

+26-10
Original file line numberDiff line numberDiff line change
@@ -210,18 +210,19 @@ func (e *Endorser) getCDSFromLSCC(ctx context.Context, chainID string, txid stri
210210
func (e *Endorser) endorseProposal(ctx context.Context, chainID string, txid string, signedProp *pb.SignedProposal, proposal *pb.Proposal, response *pb.Response, simRes []byte, event *pb.ChaincodeEvent, visibility []byte, ccid *pb.ChaincodeID, txsim ledger.TxSimulator, cd *ccprovider.ChaincodeData) (*pb.ProposalResponse, error) {
211211
endorserLogger.Debugf("endorseProposal starts for chainID %s, ccid %s", chainID, ccid)
212212

213+
isSysCC := cd == nil
213214
// 1) extract the name of the escc that is requested to endorse this chaincode
214215
var escc string
215216
//ie, not "lscc" or system chaincodes
216-
if cd != nil {
217+
if isSysCC {
218+
// FIXME: getCDSFromLSCC seems to fail for lscc - not sure this is expected?
219+
// TODO: who should endorse a call to LSCC?
220+
escc = "escc"
221+
} else {
217222
escc = cd.Escc
218223
if escc == "" { // this should never happen, LSCC always fills this field
219224
panic("No ESCC specified in ChaincodeData")
220225
}
221-
} else {
222-
// FIXME: getCDSFromLSCC seems to fail for lscc - not sure this is expected?
223-
// TODO: who should endorse a call to LSCC?
224-
escc = "escc"
225226
}
226227

227228
endorserLogger.Debugf("endorseProposal info: escc for cid %s is %s", ccid, escc)
@@ -241,16 +242,31 @@ func (e *Endorser) endorseProposal(ctx context.Context, chainID string, txid str
241242
return nil, fmt.Errorf("failed to marshal response bytes - %s", err)
242243
}
243244

245+
// set version of executing chaincode
246+
if isSysCC {
247+
// if we want to allow mixed fabric levels we should
248+
// set syscc version to ""
249+
ccid.Version = util.GetSysCCVersion()
250+
} else {
251+
ccid.Version = cd.Version
252+
}
253+
254+
ccidBytes, err := putils.Marshal(ccid)
255+
if err != nil {
256+
return nil, fmt.Errorf("failed to marshal ChaincodeID - %s", err)
257+
}
258+
244259
// 3) call the ESCC we've identified
245260
// arguments:
246261
// args[0] - function name (not used now)
247262
// args[1] - serialized Header object
248263
// args[2] - serialized ChaincodeProposalPayload object
249-
// args[3] - result of executing chaincode
250-
// args[4] - binary blob of simulation results
251-
// args[5] - serialized events
252-
// args[6] - payloadVisibility
253-
args := [][]byte{[]byte(""), proposal.Header, proposal.Payload, resBytes, simRes, eventBytes, visibility}
264+
// args[3] - ChaincodeID of executing chaincode
265+
// args[4] - result of executing chaincode
266+
// args[5] - binary blob of simulation results
267+
// args[6] - serialized events
268+
// args[7] - payloadVisibility
269+
args := [][]byte{[]byte(""), proposal.Header, proposal.Payload, ccidBytes, resBytes, simRes, eventBytes, visibility}
254270
version := util.GetSysCCVersion()
255271
ecccis := &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_GOLANG, ChaincodeId: &pb.ChaincodeID{Name: escc}, Input: &pb.ChaincodeInput{Args: args}}}
256272
res, _, err := e.callChaincode(ctx, chainID, version, txid, signedProp, proposal, ecccis, &pb.ChaincodeID{Name: escc}, txsim)

core/ledger/kvledger/example/app.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,12 @@ func (app *App) QueryBalances(accounts []string) ([]int, error) {
115115
}
116116

117117
func constructTransaction(simulationResults []byte) *common.Envelope {
118+
ccid := &pb.ChaincodeID{
119+
Name: "foo",
120+
Version: "v1",
121+
}
118122
response := &pb.Response{Status: 200}
119-
txEnv, _, _ := ptestutils.ConstructSingedTxEnvWithDefaultSigner(util.GetTestChainID(), "foo", response, simulationResults, nil, nil)
123+
txEnv, _, _ := ptestutils.ConstructSingedTxEnvWithDefaultSigner(util.GetTestChainID(), ccid, response, simulationResults, nil, nil)
120124
return txEnv
121125
}
122126

core/scc/escc/endorser_onevalidsignature.go

+27-15
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,12 @@ func (e *EndorserOneValidSignature) Init(stub shim.ChaincodeStubInterface) pb.Re
5252
// args[0] - function name (not used now)
5353
// args[1] - serialized Header object
5454
// args[2] - serialized ChaincodeProposalPayload object
55-
// args[3] - result of executing chaincode
56-
// args[4] - binary blob of simulation results
57-
// args[5] - serialized events
58-
// args[6] - payloadVisibility
55+
// args[3] - ChaincodeID of executing chaincode
56+
// args[4] - result of executing chaincode
57+
// args[5] - binary blob of simulation results
58+
// args[6] - serialized events
59+
// args[7] - payloadVisibility
60+
5961
//
6062
// NOTE: this chaincode is meant to sign another chaincode's simulation
6163
// results. It should not manipulate state as any state change will be
@@ -64,9 +66,9 @@ func (e *EndorserOneValidSignature) Init(stub shim.ChaincodeStubInterface) pb.Re
6466
// definition can't be a state change of our own.
6567
func (e *EndorserOneValidSignature) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
6668
args := stub.GetArgs()
67-
if len(args) < 5 {
69+
if len(args) < 6 {
6870
return shim.Error(fmt.Sprintf("Incorrect number of arguments (expected a minimum of 5, provided %d)", len(args)))
69-
} else if len(args) > 7 {
71+
} else if len(args) > 8 {
7072
return shim.Error(fmt.Sprintf("Incorrect number of arguments (expected a maximum of 7, provided %d)", len(args)))
7173
}
7274

@@ -88,13 +90,23 @@ func (e *EndorserOneValidSignature) Invoke(stub shim.ChaincodeStubInterface) pb.
8890

8991
payl = args[2]
9092

93+
// handle ChaincodeID
94+
if args[3] == nil {
95+
return shim.Error("ChaincodeID is null")
96+
}
97+
98+
ccid, err := putils.UnmarshalChaincodeID(args[3])
99+
if err != nil {
100+
return shim.Error(err.Error())
101+
}
102+
91103
// handle executing chaincode result
92104
// Status code < 500 can be endorsed
93-
if args[3] == nil {
105+
if args[4] == nil {
94106
return shim.Error("Response of chaincode executing is null")
95107
}
96108

97-
response, err := putils.GetResponse(args[3])
109+
response, err := putils.GetResponse(args[4])
98110
if err != nil {
99111
return shim.Error(fmt.Sprintf("Failed to get Response of executing chaincode: %s", err.Error()))
100112
}
@@ -105,18 +117,18 @@ func (e *EndorserOneValidSignature) Invoke(stub shim.ChaincodeStubInterface) pb.
105117

106118
// handle simulation results
107119
var results []byte
108-
if args[4] == nil {
120+
if args[5] == nil {
109121
return shim.Error("simulation results are null")
110122
}
111123

112-
results = args[4]
124+
results = args[5]
113125

114126
// Handle serialized events if they have been provided
115127
// they might be nil in case there's no events but there
116128
// is a visibility field specified as the next arg
117129
events := []byte("")
118-
if len(args) > 5 && args[5] != nil {
119-
events = args[5]
130+
if len(args) > 6 && args[6] != nil {
131+
events = args[6]
120132
}
121133

122134
// Handle payload visibility (it's an optional argument)
@@ -128,8 +140,8 @@ func (e *EndorserOneValidSignature) Invoke(stub shim.ChaincodeStubInterface) pb.
128140
// mechanisms that shall be encoded in this field (and handled
129141
// appropriately by the peer)
130142
var visibility []byte
131-
if len(args) > 6 {
132-
visibility = args[6]
143+
if len(args) > 7 {
144+
visibility = args[7]
133145
}
134146

135147
// obtain the default signing identity for this peer; it will be used to sign this proposal response
@@ -144,7 +156,7 @@ func (e *EndorserOneValidSignature) Invoke(stub shim.ChaincodeStubInterface) pb.
144156
}
145157

146158
// obtain a proposal response
147-
presp, err := utils.CreateProposalResponse(hdr, payl, response, results, events, visibility, signingEndorser)
159+
presp, err := utils.CreateProposalResponse(hdr, payl, response, results, events, ccid, visibility, signingEndorser)
148160
if err != nil {
149161
return shim.Error(err.Error())
150162
}

0 commit comments

Comments
 (0)