Skip to content

Commit 269379a

Browse files
author
Srinivasan Muralidharan
committed
FAB-1318 - complete upgrade from endorser side
https://jira.hyperledger.org/browse/FAB-1318 This completes the work begun with https://gerrit.hyperledger.org/r/#/c/2973 https://gerrit.hyperledger.org/r/#/c/2945/. The command peer chaincode upgrade -n mycc -p <upgrade chaincode path> -c '{"Args":[<args to upgrade chaincode>]}' will upgrade exisisting chaincode "mycc" if one exists. There is still work left on the committer side to comb block for transactions colliding with an upgrade. Upgrade will override those colliding transactions for that <chain, chaincode>. This will be in a future CR when ledger and committer support for this work is available. A chaincode is uniquely identified by (chain name, chaincode name). When upgrading a chaincode, many versions of the chaincode may be running (typically 2, the "current" and the "upgrade" but one can imagine multiple upgrades of the same chaincode in progress. Even if only one will succeed...). When upgrading, LCCC bumps up the version number for that chaincode. This version is used to dissambiguate different versions of the chaincode in a chain, just as chain id dissambiguated the chaincode among different chains. Chaincode framework will panic if version is not specified or not found. Change-Id: Ie0e11cf4ed1263f91c8399021ea65a3e877e08ba Signed-off-by: Srinivasan Muralidharan <[email protected]>
1 parent 784d260 commit 269379a

17 files changed

+610
-209
lines changed

core/chaincode/chaincode_support.go

+16-15
Original file line numberDiff line numberDiff line change
@@ -88,32 +88,34 @@ type CCContext struct {
8888
Proposal *pb.Proposal
8989

9090
//this is not set but computed (note that this is not exported. use GetCanonicalName)
91-
canName string
91+
canonicalName string
9292
}
9393

9494
//NewCCContext just construct a new struct with whatever args
9595
func NewCCContext(cid, name, version, txid string, syscc bool, prop *pb.Proposal) *CCContext {
96-
var canName string
97-
if version != "" {
98-
canName = name + ":" + version + "/" + cid
99-
} else {
100-
canName = name + "/" + cid
96+
//version CANNOT be empty. The chaincode namespace has to use version and chain name.
97+
//All system chaincodes share the same version given by utils.GetSysCCVersion. Note
98+
//that neither Chain Name or Version are stored in a chaincodes state on the ledger
99+
if version == "" {
100+
panic(fmt.Sprintf("---empty version---(chain=%s,chaincode=%s,version=%s,txid=%s,syscc=%t,proposal=%p", cid, name, version, txid, syscc, prop))
101101
}
102102

103+
canName := name + ":" + version + "/" + cid
104+
103105
cccid := &CCContext{cid, name, version, txid, syscc, prop, canName}
104106

105-
chaincodeLogger.Infof("NewCCCC (chain=%s,chaincode=%s,version=%s,txid=%s,syscc=%t,proposal=%p,canname=%s", cid, name, version, txid, syscc, prop, cccid.canName)
107+
chaincodeLogger.Infof("NewCCCC (chain=%s,chaincode=%s,version=%s,txid=%s,syscc=%t,proposal=%p,canname=%s", cid, name, version, txid, syscc, prop, cccid.canonicalName)
106108

107109
return cccid
108110
}
109111

110112
//GetCanonicalName returns the canonical name associated with the proposal context
111113
func (cccid *CCContext) GetCanonicalName() string {
112-
if cccid.canName == "" {
114+
if cccid.canonicalName == "" {
113115
panic(fmt.Sprintf("cccid not constructed using NewCCContext(chain=%s,chaincode=%s,version=%s,txid=%s,syscc=%t)", cccid.ChainID, cccid.Name, cccid.Version, cccid.TxID, cccid.Syscc))
114116
}
115117

116-
return cccid.canName
118+
return cccid.canonicalName
117119
}
118120

119121
//
@@ -425,7 +427,7 @@ func (chaincodeSupport *ChaincodeSupport) launchAndWaitForRegister(ctxt context.
425427

426428
vmtype, _ := chaincodeSupport.getVMType(cds)
427429

428-
sir := container.StartImageReq{CCID: ccintf.CCID{ChaincodeSpec: cds.ChaincodeSpec, NetworkID: chaincodeSupport.peerNetworkID, PeerID: chaincodeSupport.peerID, ChainID: cccid.ChainID}, Reader: targz, Args: args, Env: env}
430+
sir := container.StartImageReq{CCID: ccintf.CCID{ChaincodeSpec: cds.ChaincodeSpec, NetworkID: chaincodeSupport.peerNetworkID, PeerID: chaincodeSupport.peerID, ChainID: cccid.ChainID, Version: cccid.Version}, Reader: targz, Args: args, Env: env}
429431

430432
ipcCtxt := context.WithValue(ctxt, ccintf.GetCCHandlerKey(), chaincodeSupport)
431433

@@ -468,7 +470,7 @@ func (chaincodeSupport *ChaincodeSupport) Stop(context context.Context, cccid *C
468470
}
469471

470472
//stop the chaincode
471-
sir := container.StopImageReq{CCID: ccintf.CCID{ChaincodeSpec: cds.ChaincodeSpec, NetworkID: chaincodeSupport.peerNetworkID, PeerID: chaincodeSupport.peerID, ChainID: cccid.ChainID}, Timeout: 0}
473+
sir := container.StopImageReq{CCID: ccintf.CCID{ChaincodeSpec: cds.ChaincodeSpec, NetworkID: chaincodeSupport.peerNetworkID, PeerID: chaincodeSupport.peerID, ChainID: cccid.ChainID, Version: cccid.Version}, Timeout: 0}
472474

473475
vmtype, _ := chaincodeSupport.getVMType(cds)
474476

@@ -548,9 +550,6 @@ func (chaincodeSupport *ChaincodeSupport) Launch(context context.Context, cccid
548550
chaincodeLogger.Error("You are attempting to perform an action other than Deploy on Chaincode that is not ready and you are in developer mode. Did you forget to Deploy your chaincode?")
549551
}
550552

551-
//PDMP - panic if not using simulator path
552-
_ = getTxSimulator(context)
553-
554553
var depPayload []byte
555554

556555
//hopefully we are restarting from existing image and the deployed transaction exists
@@ -563,11 +562,13 @@ func (chaincodeSupport *ChaincodeSupport) Launch(context context.Context, cccid
563562
}
564563

565564
cds = &pb.ChaincodeDeploymentSpec{}
565+
566566
//Get lang from original deployment
567567
err = proto.Unmarshal(depPayload, cds)
568568
if err != nil {
569569
return cID, cMsg, fmt.Errorf("failed to unmarshal deployment transactions for %s - %s", canName, err)
570570
}
571+
571572
cLang = cds.ChaincodeSpec.Type
572573
}
573574

@@ -636,7 +637,7 @@ func (chaincodeSupport *ChaincodeSupport) Deploy(context context.Context, cccid
636637
}
637638

638639
var targz io.Reader = bytes.NewBuffer(cds.CodePackage)
639-
cir := &container.CreateImageReq{CCID: ccintf.CCID{ChaincodeSpec: cds.ChaincodeSpec, NetworkID: chaincodeSupport.peerNetworkID, PeerID: chaincodeSupport.peerID, ChainID: cccid.ChainID}, Args: args, Reader: targz, Env: envs}
640+
cir := &container.CreateImageReq{CCID: ccintf.CCID{ChaincodeSpec: cds.ChaincodeSpec, NetworkID: chaincodeSupport.peerNetworkID, PeerID: chaincodeSupport.peerID, ChainID: cccid.ChainID, Version: cccid.Version}, Args: args, Reader: targz, Env: envs}
640641

641642
vmtype, _ := chaincodeSupport.getVMType(cds)
642643

core/chaincode/chaincodeexec.go

+21-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import (
2121

2222
"fmt"
2323

24+
"github.com/golang/protobuf/proto"
25+
"github.com/hyperledger/fabric/core/util"
2426
pb "github.com/hyperledger/fabric/protos/peer"
2527
)
2628

@@ -36,11 +38,29 @@ func createCIS(ccname string, args [][]byte) (*pb.ChaincodeInvocationSpec, error
3638

3739
// GetCDSFromLCCC gets chaincode deployment spec from LCCC
3840
func GetCDSFromLCCC(ctxt context.Context, txid string, prop *pb.Proposal, chainID string, chaincodeID string) ([]byte, error) {
39-
cccid := NewCCContext(chainID, "lccc", "", txid, true, prop)
41+
version := util.GetSysCCVersion()
42+
cccid := NewCCContext(chainID, "lccc", version, txid, true, prop)
4043
payload, _, err := ExecuteChaincode(ctxt, cccid, [][]byte{[]byte("getdepspec"), []byte(chainID), []byte(chaincodeID)})
4144
return payload, err
4245
}
4346

47+
// GetChaincodeDataFromLCCC gets chaincode data from LCCC given name
48+
func GetChaincodeDataFromLCCC(ctxt context.Context, txid string, prop *pb.Proposal, chainID string, chaincodeID string) (*ChaincodeData, error) {
49+
version := util.GetSysCCVersion()
50+
cccid := NewCCContext(chainID, "lccc", version, txid, true, prop)
51+
payload, _, err := ExecuteChaincode(ctxt, cccid, [][]byte{[]byte("getccdata"), []byte(chainID), []byte(chaincodeID)})
52+
if err == nil {
53+
cd := &ChaincodeData{}
54+
err = proto.Unmarshal(payload, cd)
55+
if err != nil {
56+
return nil, err
57+
}
58+
return cd, nil
59+
}
60+
61+
return nil, err
62+
}
63+
4464
// ExecuteChaincode executes a given chaincode given chaincode name and arguments
4565
func ExecuteChaincode(ctxt context.Context, cccid *CCContext, args [][]byte) ([]byte, *pb.ChaincodeEvent, error) {
4666
var spec *pb.ChaincodeInvocationSpec

core/chaincode/chaincodetest.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,7 @@ chaincode:
392392
# system chaincodes whitelist. To add system chaincode "myscc" to the
393393
# whitelist, add "myscc: enable" to the list
394394
system:
395+
cscc: enable
395396
lccc: enable
396397
escc: enable
397398
vscc: enable

core/chaincode/exectransaction_test.go

+33-25
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ func initPeer(chainIDs ...string) (net.Listener, error) {
9191
RegisterSysCCs()
9292

9393
for _, id := range chainIDs {
94+
deDeploySysCCs(id)
9495
if err = peer.MockCreateChain(id); err != nil {
9596
closeListenerAndSleep(lis)
9697
return nil, err
@@ -106,7 +107,7 @@ func initPeer(chainIDs ...string) (net.Listener, error) {
106107
func finitPeer(lis net.Listener, chainIDs ...string) {
107108
if lis != nil {
108109
for _, c := range chainIDs {
109-
deRegisterSysCCs(c)
110+
deDeploySysCCs(c)
110111
if lgr := peer.GetLedger(c); lgr != nil {
111112
lgr.Close()
112113
}
@@ -263,7 +264,8 @@ func deploy2(ctx context.Context, cccid *CCContext, chaincodeDeploymentSpec *pb.
263264
}
264265
}()
265266

266-
lcccid := NewCCContext(cccid.ChainID, cis.ChaincodeSpec.ChaincodeID.Name, "", uuid, true, nil)
267+
sysCCVers := util.GetSysCCVersion()
268+
lcccid := NewCCContext(cccid.ChainID, cis.ChaincodeSpec.ChaincodeID.Name, sysCCVers, uuid, true, nil)
267269

268270
//write to lccc
269271
if _, _, err = Execute(ctx, lcccid, cis); err != nil {
@@ -279,6 +281,11 @@ func deploy2(ctx context.Context, cccid *CCContext, chaincodeDeploymentSpec *pb.
279281

280282
// Invoke a chaincode.
281283
func invoke(ctx context.Context, chainID string, spec *pb.ChaincodeSpec) (ccevt *pb.ChaincodeEvent, uuid string, retval []byte, err error) {
284+
return invokeWithVersion(ctx, chainID, "0", spec)
285+
}
286+
287+
// Invoke a chaincode with version (needed for upgrade)
288+
func invokeWithVersion(ctx context.Context, chainID string, version string, spec *pb.ChaincodeSpec) (ccevt *pb.ChaincodeEvent, uuid string, retval []byte, err error) {
282289
chaincodeInvocationSpec := &pb.ChaincodeInvocationSpec{ChaincodeSpec: spec}
283290

284291
// Now create the Transactions message and send to Peer.
@@ -301,7 +308,7 @@ func invoke(ctx context.Context, chainID string, spec *pb.ChaincodeSpec) (ccevt
301308
}
302309
}()
303310

304-
cccid := NewCCContext(chainID, chaincodeInvocationSpec.ChaincodeSpec.ChaincodeID.Name, "", uuid, false, nil)
311+
cccid := NewCCContext(chainID, chaincodeInvocationSpec.ChaincodeSpec.ChaincodeID.Name, version, uuid, false, nil)
305312
retval, ccevt, err = Execute(ctx, cccid, chaincodeInvocationSpec)
306313
if err != nil {
307314
return nil, uuid, nil, fmt.Errorf("Error invoking chaincode: %s ", err)
@@ -332,7 +339,7 @@ func executeDeployTransaction(t *testing.T, chainID string, name string, url str
332339
args := util.ToChaincodeArgs(f, "a", "100", "b", "200")
333340
spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: &pb.ChaincodeID{Name: name, Path: url}, CtorMsg: &pb.ChaincodeInput{Args: args}}
334341

335-
cccid := NewCCContext(chainID, name, "", "", false, nil)
342+
cccid := NewCCContext(chainID, name, "0", "", false, nil)
336343

337344
_, err = deploy(ctxt, cccid, spec)
338345

@@ -359,7 +366,7 @@ func chaincodeQueryChaincode(chainID string, user string) error {
359366

360367
spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID1, CtorMsg: &pb.ChaincodeInput{Args: args}, SecureContext: user}
361368

362-
cccid1 := NewCCContext(chainID, "example02", "", "", false, nil)
369+
cccid1 := NewCCContext(chainID, "example02", "0", "", false, nil)
363370

364371
_, err := deploy(ctxt, cccid1, spec1)
365372

@@ -380,7 +387,7 @@ func chaincodeQueryChaincode(chainID string, user string) error {
380387

381388
spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID2, CtorMsg: &pb.ChaincodeInput{Args: args}, SecureContext: user}
382389

383-
cccid2 := NewCCContext(chainID, "example05", "", "", false, nil)
390+
cccid2 := NewCCContext(chainID, "example05", "0", "", false, nil)
384391

385392
_, err = deploy(ctxt, cccid2, spec2)
386393
chaincodeID2 := spec2.ChaincodeID.Name
@@ -479,32 +486,33 @@ func checkFinalState(cccid *CCContext) error {
479486

480487
defer txsim.Done()
481488

482-
canName := cccid.GetCanonicalName()
489+
cName := cccid.GetCanonicalName()
490+
483491
// Invoke ledger to get state
484492
var Aval, Bval int
485-
resbytes, resErr := txsim.GetState(canName, "a")
493+
resbytes, resErr := txsim.GetState(cccid.Name, "a")
486494
if resErr != nil {
487-
return fmt.Errorf("Error retrieving state from ledger for <%s>: %s", canName, resErr)
495+
return fmt.Errorf("Error retrieving state from ledger for <%s>: %s", cName, resErr)
488496
}
489497
fmt.Printf("Got string: %s\n", string(resbytes))
490498
Aval, resErr = strconv.Atoi(string(resbytes))
491499
if resErr != nil {
492-
return fmt.Errorf("Error retrieving state from ledger for <%s>: %s", canName, resErr)
500+
return fmt.Errorf("Error retrieving state from ledger for <%s>: %s", cName, resErr)
493501
}
494502
if Aval != 90 {
495-
return fmt.Errorf("Incorrect result. Aval is wrong for <%s>", canName)
503+
return fmt.Errorf("Incorrect result. Aval is wrong for <%s>", cName)
496504
}
497505

498-
resbytes, resErr = txsim.GetState(canName, "b")
506+
resbytes, resErr = txsim.GetState(cccid.Name, "b")
499507
if resErr != nil {
500-
return fmt.Errorf("Error retrieving state from ledger for <%s>: %s", canName, resErr)
508+
return fmt.Errorf("Error retrieving state from ledger for <%s>: %s", cName, resErr)
501509
}
502510
Bval, resErr = strconv.Atoi(string(resbytes))
503511
if resErr != nil {
504-
return fmt.Errorf("Error retrieving state from ledger for <%s>: %s", canName, resErr)
512+
return fmt.Errorf("Error retrieving state from ledger for <%s>: %s", cName, resErr)
505513
}
506514
if Bval != 210 {
507-
return fmt.Errorf("Incorrect result. Bval is wrong for <%s>", canName)
515+
return fmt.Errorf("Incorrect result. Bval is wrong for <%s>", cName)
508516
}
509517

510518
// Success
@@ -576,7 +584,7 @@ func TestExecuteInvokeTransaction(t *testing.T) {
576584

577585
var ctxt = context.Background()
578586

579-
cccid := NewCCContext(chainID, "example02", "", "", false, nil)
587+
cccid := NewCCContext(chainID, "example02", "0", "", false, nil)
580588
url := "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02"
581589
chaincodeID := &pb.ChaincodeID{Name: "example02", Path: url}
582590

@@ -642,7 +650,7 @@ func TestExecuteInvokeInvalidTransaction(t *testing.T) {
642650
url := "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02"
643651
chaincodeID := &pb.ChaincodeID{Name: "example02", Path: url}
644652

645-
cccid := NewCCContext(chainID, "example02", "", "", false, nil)
653+
cccid := NewCCContext(chainID, "example02", "0", "", false, nil)
646654

647655
//FAIL, FAIL!
648656
args := []string{"x", "-1"}
@@ -699,7 +707,7 @@ func chaincodeInvokeChaincode(t *testing.T, chainID string, user string) (err er
699707

700708
spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID1, CtorMsg: &pb.ChaincodeInput{Args: args}, SecureContext: user}
701709

702-
cccid1 := NewCCContext(chainID, "example02", "", "", false, nil)
710+
cccid1 := NewCCContext(chainID, "example02", "0", "", false, nil)
703711

704712
_, err = deploy(ctxt, cccid1, spec1)
705713
chaincodeID1 := spec1.ChaincodeID.Name
@@ -723,7 +731,7 @@ func chaincodeInvokeChaincode(t *testing.T, chainID string, user string) (err er
723731

724732
spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID2, CtorMsg: &pb.ChaincodeInput{Args: args}, SecureContext: user}
725733

726-
cccid2 := NewCCContext(chainID, "example04", "", "", false, nil)
734+
cccid2 := NewCCContext(chainID, "example04", "0", "", false, nil)
727735

728736
_, err = deploy(ctxt, cccid2, spec2)
729737
chaincodeID2 := spec2.ChaincodeID.Name
@@ -798,7 +806,7 @@ func TestChaincodeInvokeChaincodeErrorCase(t *testing.T) {
798806

799807
spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID1, CtorMsg: &pb.ChaincodeInput{Args: args}}
800808

801-
cccid1 := NewCCContext(chainID, "example02", "", "", false, nil)
809+
cccid1 := NewCCContext(chainID, "example02", "0", "", false, nil)
802810

803811
_, err = deploy(ctxt, cccid1, spec1)
804812
chaincodeID1 := spec1.ChaincodeID.Name
@@ -820,7 +828,7 @@ func TestChaincodeInvokeChaincodeErrorCase(t *testing.T) {
820828

821829
spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID2, CtorMsg: &pb.ChaincodeInput{Args: args}}
822830

823-
cccid2 := NewCCContext(chainID, "pthru", "", "", false, nil)
831+
cccid2 := NewCCContext(chainID, "pthru", "0", "", false, nil)
824832

825833
_, err = deploy(ctxt, cccid2, spec2)
826834
chaincodeID2 := spec2.ChaincodeID.Name
@@ -887,7 +895,7 @@ func TestRangeQuery(t *testing.T) {
887895

888896
spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Args: args}}
889897

890-
cccid := NewCCContext(chainID, "tmap", "", "", false, nil)
898+
cccid := NewCCContext(chainID, "tmap", "0", "", false, nil)
891899

892900
_, err = deploy(ctxt, cccid, spec)
893901
chaincodeID := spec.ChaincodeID.Name
@@ -933,7 +941,7 @@ func TestGetEvent(t *testing.T) {
933941
f := "init"
934942
spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Args: util.ToChaincodeArgs(f)}}
935943

936-
cccid := NewCCContext(chainID, "esender", "", "", false, nil)
944+
cccid := NewCCContext(chainID, "esender", "0", "", false, nil)
937945

938946
_, err = deploy(ctxt, cccid, spec)
939947
chaincodeID := spec.ChaincodeID.Name
@@ -1002,7 +1010,7 @@ func TestChaincodeQueryChaincodeUsingInvoke(t *testing.T) {
10021010

10031011
spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID1, CtorMsg: &pb.ChaincodeInput{Args: args}}
10041012

1005-
cccid1 := NewCCContext(chainID, "example02", "", "", false, nil)
1013+
cccid1 := NewCCContext(chainID, "example02", "0", "", false, nil)
10061014

10071015
_, err = deploy(ctxt, cccid1, spec1)
10081016
chaincodeID1 := spec1.ChaincodeID.Name
@@ -1024,7 +1032,7 @@ func TestChaincodeQueryChaincodeUsingInvoke(t *testing.T) {
10241032

10251033
spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID2, CtorMsg: &pb.ChaincodeInput{Args: args}}
10261034

1027-
cccid2 := NewCCContext(chainID, "example05", "", "", false, nil)
1035+
cccid2 := NewCCContext(chainID, "example05", "0", "", false, nil)
10281036

10291037
_, err = deploy(ctxt, cccid2, spec2)
10301038
chaincodeID2 := spec2.ChaincodeID.Name

0 commit comments

Comments
 (0)