github.com/inklabsfoundation/inkchain@v0.17.1-0.20181025012015-c3cef8062f19/core/scc/lscc/lscc.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package lscc 18 19 import ( 20 "fmt" 21 "regexp" 22 23 "github.com/golang/protobuf/proto" 24 "github.com/inklabsfoundation/inkchain/common/cauthdsl" 25 "github.com/inklabsfoundation/inkchain/common/flogging" 26 "github.com/inklabsfoundation/inkchain/common/policies" 27 "github.com/inklabsfoundation/inkchain/core/chaincode/shim" 28 "github.com/inklabsfoundation/inkchain/core/common/ccprovider" 29 "github.com/inklabsfoundation/inkchain/core/common/sysccprovider" 30 "github.com/inklabsfoundation/inkchain/core/peer" 31 "github.com/inklabsfoundation/inkchain/core/policy" 32 "github.com/inklabsfoundation/inkchain/core/policyprovider" 33 "github.com/inklabsfoundation/inkchain/msp/mgmt" 34 mspmgmt "github.com/inklabsfoundation/inkchain/msp/mgmt" 35 "github.com/inklabsfoundation/inkchain/protos/common" 36 pb "github.com/inklabsfoundation/inkchain/protos/peer" 37 "github.com/inklabsfoundation/inkchain/protos/utils" 38 ) 39 40 //The life cycle system chaincode manages chaincodes deployed 41 //on this peer. It manages chaincodes via Invoke proposals. 42 // "Args":["deploy",<ChaincodeDeploymentSpec>] 43 // "Args":["upgrade",<ChaincodeDeploymentSpec>] 44 // "Args":["stop",<ChaincodeInvocationSpec>] 45 // "Args":["start",<ChaincodeInvocationSpec>] 46 47 var logger = flogging.MustGetLogger("lscc") 48 49 const ( 50 //CHAINCODETABLE prefix for chaincode tables 51 CHAINCODETABLE = "chaincodes" 52 53 //chaincode lifecyle commands 54 55 //INSTALL install command 56 INSTALL = "install" 57 58 //DEPLOY deploy command 59 DEPLOY = "deploy" 60 61 //UPGRADE upgrade chaincode 62 UPGRADE = "upgrade" 63 64 //GETCCINFO get chaincode 65 GETCCINFO = "getid" 66 67 //GETDEPSPEC get ChaincodeDeploymentSpec 68 GETDEPSPEC = "getdepspec" 69 70 //GETCCDATA get ChaincodeData 71 GETCCDATA = "getccdata" 72 73 //GETCHAINCODES gets the instantiated chaincodes on a channel 74 GETCHAINCODES = "getchaincodes" 75 76 //GETINSTALLEDCHAINCODES gets the installed chaincodes on a peer 77 GETINSTALLEDCHAINCODES = "getinstalledchaincodes" 78 79 allowedCharsChaincodeName = "[A-Za-z0-9_-]+" 80 allowedCharsVersion = "[A-Za-z0-9_.-]+" 81 82 ) 83 84 //---------- the LSCC ----------------- 85 86 // LifeCycleSysCC implements chaincode lifecycle and policies around it 87 type LifeCycleSysCC struct { 88 // sccprovider is the interface with which we call 89 // methods of the system chaincode package without 90 // import cycles 91 sccprovider sysccprovider.SystemChaincodeProvider 92 93 // policyChecker is the interface used to perform 94 // access control 95 policyChecker policy.PolicyChecker 96 } 97 98 //----------------errors--------------- 99 100 //AlreadyRegisteredErr Already registered error 101 type AlreadyRegisteredErr string 102 103 func (f AlreadyRegisteredErr) Error() string { 104 return fmt.Sprintf("%s already registered", string(f)) 105 } 106 107 //InvalidFunctionErr invalid function error 108 type InvalidFunctionErr string 109 110 func (f InvalidFunctionErr) Error() string { 111 return fmt.Sprintf("invalid function to lscc %s", string(f)) 112 } 113 114 //InvalidArgsLenErr invalid arguments length error 115 type InvalidArgsLenErr int 116 117 func (i InvalidArgsLenErr) Error() string { 118 return fmt.Sprintf("invalid number of argument to lscc %d", int(i)) 119 } 120 121 //InvalidArgsErr invalid arguments error 122 type InvalidArgsErr int 123 124 func (i InvalidArgsErr) Error() string { 125 return fmt.Sprintf("invalid argument (%d) to lscc", int(i)) 126 } 127 128 //TXExistsErr transaction exists error 129 type TXExistsErr string 130 131 func (t TXExistsErr) Error() string { 132 return fmt.Sprintf("transaction exists %s", string(t)) 133 } 134 135 //TXNotFoundErr transaction not found error 136 type TXNotFoundErr string 137 138 func (t TXNotFoundErr) Error() string { 139 return fmt.Sprintf("transaction not found %s", string(t)) 140 } 141 142 //InvalidDeploymentSpecErr invalide chaincode deployment spec error 143 type InvalidDeploymentSpecErr string 144 145 func (f InvalidDeploymentSpecErr) Error() string { 146 return fmt.Sprintf("invalid deployment spec : %s", string(f)) 147 } 148 149 //ExistsErr chaincode exists error 150 type ExistsErr string 151 152 func (t ExistsErr) Error() string { 153 return fmt.Sprintf("chaincode exists %s", string(t)) 154 } 155 156 //NotFoundErr chaincode not registered with LSCC error 157 type NotFoundErr string 158 159 func (t NotFoundErr) Error() string { 160 return fmt.Sprintf("could not find chaincode with name '%s'", string(t)) 161 } 162 163 //InvalidChainNameErr invalid chain name error 164 type InvalidChainNameErr string 165 166 func (f InvalidChainNameErr) Error() string { 167 return fmt.Sprintf("invalid chain name %s", string(f)) 168 } 169 170 //InvalidChaincodeNameErr invalid chaincode name error 171 type InvalidChaincodeNameErr string 172 173 func (f InvalidChaincodeNameErr) Error() string { 174 return fmt.Sprintf("invalid chaincode name '%s'. Names can only consist of alphanumerics, '_', and '-'", string(f)) 175 } 176 177 //EmptyChaincodeNameErr trying to upgrade to same version of Chaincode 178 type EmptyChaincodeNameErr string 179 180 func (f EmptyChaincodeNameErr) Error() string { 181 return fmt.Sprint("chaincode name not provided") 182 } 183 184 //InvalidVersionErr invalid version error 185 type InvalidVersionErr string 186 187 func (f InvalidVersionErr) Error() string { 188 return fmt.Sprintf("invalid chaincode version '%s'. Versions can only consist of alphanumerics, '_', '-', and '.'", string(f)) 189 } 190 191 //ChaincodeMismatchErr chaincode name from two places don't match 192 type ChaincodeMismatchErr string 193 194 func (f ChaincodeMismatchErr) Error() string { 195 return fmt.Sprintf("chaincode name mismatch %s", string(f)) 196 } 197 198 //EmptyVersionErr empty version error 199 type EmptyVersionErr string 200 201 func (f EmptyVersionErr) Error() string { 202 return fmt.Sprintf("version not provided for chaincode with name '%s'", string(f)) 203 } 204 205 //MarshallErr error marshaling/unmarshalling 206 type MarshallErr string 207 208 func (m MarshallErr) Error() string { 209 return fmt.Sprintf("error while marshalling %s", string(m)) 210 } 211 212 //IdenticalVersionErr trying to upgrade to same version of Chaincode 213 type IdenticalVersionErr string 214 215 func (f IdenticalVersionErr) Error() string { 216 return fmt.Sprintf("version already exists for chaincode with name '%s'", string(f)) 217 } 218 219 //InvalidCCOnFSError error due to mismatch between fingerprint on lscc and installed CC 220 type InvalidCCOnFSError string 221 222 func (f InvalidCCOnFSError) Error() string { 223 return fmt.Sprintf("chaincode fingerprint mismatch %s", string(f)) 224 } 225 226 //InstantiationPolicyViolatedErr when chaincode instantiation policy has been violated on instantiate or upgrade 227 type InstantiationPolicyViolatedErr string 228 229 func (f InstantiationPolicyViolatedErr) Error() string { 230 return fmt.Sprintf("chaincode instantiation policy violated(%s)", string(f)) 231 } 232 233 //InstantiationPolicyMissing when no existing instantiation policy is found when upgrading CC 234 type InstantiationPolicyMissing string 235 236 func (f InstantiationPolicyMissing) Error() string { 237 return "instantiation policy missing" 238 } 239 240 //-------------- helper functions ------------------ 241 //create the chaincode on the given chain 242 func (lscc *LifeCycleSysCC) createChaincode(stub shim.ChaincodeStubInterface, cd *ccprovider.ChaincodeData) error { 243 return lscc.putChaincodeData(stub, cd) 244 } 245 246 //upgrade the chaincode on the given chain 247 func (lscc *LifeCycleSysCC) upgradeChaincode(stub shim.ChaincodeStubInterface, cd *ccprovider.ChaincodeData) error { 248 return lscc.putChaincodeData(stub, cd) 249 } 250 251 //create the chaincode on the given chain 252 func (lscc *LifeCycleSysCC) putChaincodeData(stub shim.ChaincodeStubInterface, cd *ccprovider.ChaincodeData) error { 253 // check that escc and vscc are real system chaincodes 254 if !lscc.sccprovider.IsSysCC(string(cd.Escc)) { 255 return fmt.Errorf("%s is not a valid endorsement system chaincode", string(cd.Escc)) 256 } 257 if !lscc.sccprovider.IsSysCC(string(cd.Vscc)) { 258 return fmt.Errorf("%s is not a valid validation system chaincode", string(cd.Vscc)) 259 } 260 261 cdbytes, err := proto.Marshal(cd) 262 if err != nil { 263 return err 264 } 265 266 if cdbytes == nil { 267 return MarshallErr(cd.Name) 268 } 269 270 err = stub.PutState(cd.Name, cdbytes) 271 272 return err 273 } 274 275 //checks for existence of chaincode on the given channel 276 func (lscc *LifeCycleSysCC) getCCInstance(stub shim.ChaincodeStubInterface, ccname string) ([]byte, error) { 277 cdbytes, err := stub.GetState(ccname) 278 if err != nil { 279 return nil, TXNotFoundErr(err.Error()) 280 } 281 if cdbytes == nil { 282 return nil, NotFoundErr(ccname) 283 } 284 285 return cdbytes, nil 286 } 287 288 //gets the cd out of the bytes 289 func (lscc *LifeCycleSysCC) getChaincodeData(ccname string, cdbytes []byte) (*ccprovider.ChaincodeData, error) { 290 cd := &ccprovider.ChaincodeData{} 291 err := proto.Unmarshal(cdbytes, cd) 292 if err != nil { 293 return nil, MarshallErr(ccname) 294 } 295 296 //this should not happen but still a sanity check is not a bad thing 297 if cd.Name != ccname { 298 return nil, ChaincodeMismatchErr(fmt.Sprintf("%s!=%s", ccname, cd.Name)) 299 } 300 301 return cd, nil 302 } 303 304 //checks for existence of chaincode on the given chain 305 func (lscc *LifeCycleSysCC) getCCCode(ccname string, cdbytes []byte) (*ccprovider.ChaincodeData, *pb.ChaincodeDeploymentSpec, []byte, error) { 306 cd, err := lscc.getChaincodeData(ccname, cdbytes) 307 if err != nil { 308 return nil, nil, nil, err 309 } 310 311 ccpack, err := ccprovider.GetChaincodeFromFS(ccname, cd.Version) 312 if err != nil { 313 return nil, nil, nil, InvalidDeploymentSpecErr(err.Error()) 314 } 315 316 //this is the big test and the reason every launch should go through 317 //getChaincode call. We validate the chaincode entry against the 318 //the chaincode in FS 319 if err = ccpack.ValidateCC(cd); err != nil { 320 return nil, nil, nil, InvalidCCOnFSError(err.Error()) 321 } 322 323 //these are guaranteed to be non-nil because we got a valid ccpack 324 depspec := ccpack.GetDepSpec() 325 depspecbytes := ccpack.GetDepSpecBytes() 326 327 return cd, depspec, depspecbytes, nil 328 } 329 330 // getChaincodes returns all chaincodes instantiated on this LSCC's channel 331 func (lscc *LifeCycleSysCC) getChaincodes(stub shim.ChaincodeStubInterface) pb.Response { 332 // get all rows from LSCC 333 itr, err := stub.GetStateByRange("", "") 334 335 if err != nil { 336 return shim.Error(err.Error()) 337 } 338 defer itr.Close() 339 340 // array to store metadata for all chaincode entries from LSCC 341 var ccInfoArray []*pb.ChaincodeInfo 342 343 for itr.HasNext() { 344 response, err := itr.Next() 345 if err != nil { 346 return shim.Error(err.Error()) 347 } 348 349 ccdata := &ccprovider.ChaincodeData{} 350 if err = proto.Unmarshal(response.Value, ccdata); err != nil { 351 return shim.Error(err.Error()) 352 } 353 354 var path string 355 var input string 356 357 //if chaincode is not installed on the system we won't have 358 //data beyond name and version 359 ccpack, err := ccprovider.GetChaincodeFromFS(ccdata.Name, ccdata.Version) 360 if err == nil { 361 path = ccpack.GetDepSpec().GetChaincodeSpec().ChaincodeId.Path 362 input = ccpack.GetDepSpec().GetChaincodeSpec().Input.String() 363 } 364 365 ccInfo := &pb.ChaincodeInfo{Name: ccdata.Name, Version: ccdata.Version, Path: path, Input: input, Escc: ccdata.Escc, Vscc: ccdata.Vscc} 366 367 // add this specific chaincode's metadata to the array of all chaincodes 368 ccInfoArray = append(ccInfoArray, ccInfo) 369 } 370 // add array with info about all instantiated chaincodes to the query 371 // response proto 372 cqr := &pb.ChaincodeQueryResponse{Chaincodes: ccInfoArray} 373 374 cqrbytes, err := proto.Marshal(cqr) 375 if err != nil { 376 return shim.Error(err.Error()) 377 } 378 379 return shim.Success(cqrbytes) 380 } 381 382 // getInstalledChaincodes returns all chaincodes installed on the peer 383 func (lscc *LifeCycleSysCC) getInstalledChaincodes() pb.Response { 384 // get chaincode query response proto which contains information about all 385 // installed chaincodes 386 cqr, err := ccprovider.GetInstalledChaincodes() 387 if err != nil { 388 return shim.Error(err.Error()) 389 } 390 391 cqrbytes, err := proto.Marshal(cqr) 392 if err != nil { 393 return shim.Error(err.Error()) 394 } 395 396 return shim.Success(cqrbytes) 397 } 398 399 //do access control 400 func (lscc *LifeCycleSysCC) acl(stub shim.ChaincodeStubInterface, chainname string, cds *pb.ChaincodeDeploymentSpec) error { 401 return nil 402 } 403 404 //check validity of chain name 405 func (lscc *LifeCycleSysCC) isValidChainName(chainname string) bool { 406 //TODO we probably need more checks 407 if chainname == "" { 408 return false 409 } 410 return true 411 } 412 413 // isValidChaincodeName checks the validity of chaincode name. Chaincode names 414 // should never be blank and should only consist of alphanumerics, '_', and '-' 415 func (lscc *LifeCycleSysCC) isValidChaincodeName(chaincodeName string) error { 416 if chaincodeName == "" { 417 return EmptyChaincodeNameErr("") 418 } 419 420 if !isValidCCNameOrVersion(chaincodeName, allowedCharsChaincodeName) { 421 return InvalidChaincodeNameErr(chaincodeName) 422 } 423 424 return nil 425 } 426 427 // isValidChaincodeVersion checks the validity of chaincode version. Versions 428 // should never be blank and should only consist of alphanumerics, '_', '-', 429 // and '.' 430 func (lscc *LifeCycleSysCC) isValidChaincodeVersion(chaincodeName string, version string) error { 431 if version == "" { 432 return EmptyVersionErr(chaincodeName) 433 } 434 435 if !isValidCCNameOrVersion(version, allowedCharsVersion) { 436 return InvalidVersionErr(version) 437 } 438 439 return nil 440 } 441 442 func isValidCCNameOrVersion(ccNameOrVersion string, regExp string) bool { 443 re, _ := regexp.Compile(regExp) 444 445 matched := re.FindString(ccNameOrVersion) 446 if len(matched) != len(ccNameOrVersion) { 447 return false 448 } 449 450 return true 451 } 452 453 // executeInstall implements the "install" Invoke transaction 454 func (lscc *LifeCycleSysCC) executeInstall(stub shim.ChaincodeStubInterface, ccbytes []byte) error { 455 ccpack, err := ccprovider.GetCCPackage(ccbytes) 456 if err != nil { 457 return err 458 } 459 460 cds := ccpack.GetDepSpec() 461 462 if cds == nil { 463 return fmt.Errorf("nil deployment spec from from the CC package") 464 } 465 466 if err = lscc.isValidChaincodeName(cds.ChaincodeSpec.ChaincodeId.Name); err != nil { 467 return err 468 } 469 470 if err = lscc.isValidChaincodeVersion(cds.ChaincodeSpec.ChaincodeId.Name, cds.ChaincodeSpec.ChaincodeId.Version); err != nil { 471 return err 472 } 473 474 //everything checks out..lets write the package to the FS 475 if err = ccpack.PutChaincodeToFS(); err != nil { 476 return fmt.Errorf("Error installing chaincode code %s:%s(%s)", cds.ChaincodeSpec.ChaincodeId.Name, cds.ChaincodeSpec.ChaincodeId.Version, err) 477 } 478 479 return err 480 } 481 482 // getInstantiationPolicy retrieves the instantiation policy from a SignedCDSPackage 483 func (lscc *LifeCycleSysCC) getInstantiationPolicy(channel string, ccpack ccprovider.CCPackage) ([]byte, error) { 484 var ip []byte 485 var err error 486 // if ccpack is a SignedCDSPackage, return its IP, otherwise use a default IP 487 sccpack, isSccpack := ccpack.(*ccprovider.SignedCDSPackage) 488 if isSccpack { 489 ip = sccpack.GetInstantiationPolicy() 490 if ip == nil { 491 return nil, fmt.Errorf("Instantiation policy cannot be null for a SignedCCDeploymentSpec") 492 } 493 } else { 494 // the default instantiation policy allows any of the channel MSP admins 495 // to be able to instantiate 496 mspids := peer.GetMSPIDs(channel) 497 498 p := cauthdsl.SignedByAnyAdmin(mspids) 499 ip, err = utils.Marshal(p) 500 if err != nil { 501 return nil, fmt.Errorf("Error marshalling default instantiation policy") 502 } 503 504 } 505 return ip, nil 506 } 507 508 // checkInstantiationPolicy evaluates an instantiation policy against a signed proposal 509 func (lscc *LifeCycleSysCC) checkInstantiationPolicy(stub shim.ChaincodeStubInterface, chainName string, instantiationPolicy []byte) error { 510 // create a policy object from the policy bytes 511 mgr := mspmgmt.GetManagerForChain(chainName) 512 if mgr == nil { 513 return fmt.Errorf("Error checking chaincode instantiation policy: MSP manager for chain %s not found", chainName) 514 } 515 npp := cauthdsl.NewPolicyProvider(mgr) 516 instPol, _, err := npp.NewPolicy(instantiationPolicy) 517 if err != nil { 518 return err 519 } 520 // get the signed instantiation proposal 521 signedProp, err := stub.GetSignedProposal() 522 if err != nil { 523 return err 524 } 525 proposal, err := utils.GetProposal(signedProp.ProposalBytes) 526 if err != nil { 527 return err 528 } 529 // get the signature header of the proposal 530 header, err := utils.GetHeader(proposal.Header) 531 if err != nil { 532 return err 533 } 534 shdr, err := utils.GetSignatureHeader(header.SignatureHeader) 535 if err != nil { 536 return err 537 } 538 // construct signed data we can evaluate the instantiation policy against 539 sd := []*common.SignedData{&common.SignedData{ 540 Data: signedProp.ProposalBytes, 541 Identity: shdr.Creator, 542 Signature: signedProp.Signature, 543 }} 544 err = instPol.Evaluate(sd) 545 if err != nil { 546 return InstantiationPolicyViolatedErr(err.Error()) 547 } 548 return nil 549 } 550 551 // executeDeploy implements the "instantiate" Invoke transaction 552 func (lscc *LifeCycleSysCC) executeDeploy(stub shim.ChaincodeStubInterface, chainname string, depSpec []byte, policy []byte, escc []byte, vscc []byte) (*ccprovider.ChaincodeData, error) { 553 cds, err := utils.GetChaincodeDeploymentSpec(depSpec) 554 555 if err != nil { 556 return nil, err 557 } 558 559 if err = lscc.isValidChaincodeName(cds.ChaincodeSpec.ChaincodeId.Name); err != nil { 560 return nil, err 561 } 562 563 if err = lscc.isValidChaincodeVersion(cds.ChaincodeSpec.ChaincodeId.Name, cds.ChaincodeSpec.ChaincodeId.Version); err != nil { 564 return nil, err 565 } 566 567 if err = lscc.acl(stub, chainname, cds); err != nil { 568 return nil, err 569 } 570 571 //just test for existence of the chaincode in the LSCC 572 _, err = lscc.getCCInstance(stub, cds.ChaincodeSpec.ChaincodeId.Name) 573 if err == nil { 574 return nil, ExistsErr(cds.ChaincodeSpec.ChaincodeId.Name) 575 } 576 577 //get the chaincode from the FS 578 ccpack, err := ccprovider.GetChaincodeFromFS(cds.ChaincodeSpec.ChaincodeId.Name, cds.ChaincodeSpec.ChaincodeId.Version) 579 if err != nil { 580 return nil, fmt.Errorf("cannot get package for the chaincode to be instantiated (%s:%s)-%s", cds.ChaincodeSpec.ChaincodeId.Name, cds.ChaincodeSpec.ChaincodeId.Version, err) 581 } 582 583 //this is guarantees to be not nil 584 cd := ccpack.GetChaincodeData() 585 586 //retain chaincode specific data and fill channel specific ones 587 cd.Escc = string(escc) 588 cd.Vscc = string(vscc) 589 cd.Policy = policy 590 591 // retrieve and evaluate instantiation policy 592 cd.InstantiationPolicy, err = lscc.getInstantiationPolicy(chainname, ccpack) 593 if err != nil { 594 return nil, err 595 } 596 err = lscc.checkInstantiationPolicy(stub, chainname, cd.InstantiationPolicy) 597 if err != nil { 598 return nil, err 599 } 600 601 err = lscc.createChaincode(stub, cd) 602 603 return cd, err 604 } 605 606 // executeUpgrade implements the "upgrade" Invoke transaction. 607 func (lscc *LifeCycleSysCC) executeUpgrade(stub shim.ChaincodeStubInterface, chainName string, depSpec []byte, policy []byte, escc []byte, vscc []byte) (*ccprovider.ChaincodeData, error) { 608 cds, err := utils.GetChaincodeDeploymentSpec(depSpec) 609 if err != nil { 610 return nil, err 611 } 612 613 if err = lscc.acl(stub, chainName, cds); err != nil { 614 return nil, err 615 } 616 617 chaincodeName := cds.ChaincodeSpec.ChaincodeId.Name 618 if err = lscc.isValidChaincodeName(chaincodeName); err != nil { 619 return nil, err 620 } 621 622 if err = lscc.isValidChaincodeVersion(chaincodeName, cds.ChaincodeSpec.ChaincodeId.Version); err != nil { 623 return nil, err 624 } 625 626 // check for existence of chaincode instance only (it has to exist on the channel) 627 // we dont care about the old chaincode on the FS. In particular, user may even 628 // have deleted it 629 cdbytes, _ := lscc.getCCInstance(stub, chaincodeName) 630 if cdbytes == nil { 631 return nil, NotFoundErr(chainName) 632 } 633 634 //we need the cd to compare the version 635 cd, err := lscc.getChaincodeData(chaincodeName, cdbytes) 636 if err != nil { 637 return nil, err 638 } 639 640 //do not upgrade if same version 641 if cd.Version == cds.ChaincodeSpec.ChaincodeId.Version { 642 return nil, IdenticalVersionErr(cds.ChaincodeSpec.ChaincodeId.Name) 643 } 644 645 //do not upgrade if instantiation policy is violated 646 if cd.InstantiationPolicy == nil { 647 return nil, InstantiationPolicyMissing("") 648 } 649 err = lscc.checkInstantiationPolicy(stub, chainName, cd.InstantiationPolicy) 650 if err != nil { 651 return nil, err 652 } 653 654 ccpack, err := ccprovider.GetChaincodeFromFS(chaincodeName, cds.ChaincodeSpec.ChaincodeId.Version) 655 if err != nil { 656 return nil, fmt.Errorf("cannot get package for the chaincode to be upgraded (%s:%s)-%s", chaincodeName, cds.ChaincodeSpec.ChaincodeId.Version, err) 657 } 658 659 //get the new cd to upgrade to this is guaranteed to be not nil 660 cd = ccpack.GetChaincodeData() 661 662 //retain chaincode specific data and fill channel specific ones 663 cd.Escc = string(escc) 664 cd.Vscc = string(vscc) 665 cd.Policy = policy 666 667 // retrieve and evaluate new instantiation policy 668 cd.InstantiationPolicy, err = lscc.getInstantiationPolicy(chainName, ccpack) 669 if err != nil { 670 return nil, err 671 } 672 err = lscc.checkInstantiationPolicy(stub, chainName, cd.InstantiationPolicy) 673 if err != nil { 674 return nil, err 675 } 676 677 err = lscc.upgradeChaincode(stub, cd) 678 if err != nil { 679 return nil, err 680 } 681 682 return cd, nil 683 } 684 685 //-------------- the chaincode stub interface implementation ---------- 686 687 //Init only initializes the system chaincode provider 688 func (lscc *LifeCycleSysCC) Init(stub shim.ChaincodeStubInterface) pb.Response { 689 lscc.sccprovider = sysccprovider.GetSystemChaincodeProvider() 690 691 // Init policy checker for access control 692 lscc.policyChecker = policyprovider.GetPolicyChecker() 693 694 return shim.Success(nil) 695 } 696 697 // Invoke implements lifecycle functions "deploy", "start", "stop", "upgrade". 698 // Deploy's arguments - {[]byte("deploy"), []byte(<chainname>), <unmarshalled pb.ChaincodeDeploymentSpec>} 699 // 700 // Invoke also implements some query-like functions 701 // Get chaincode arguments - {[]byte("getid"), []byte(<chainname>), []byte(<chaincodename>)} 702 func (lscc *LifeCycleSysCC) Invoke(stub shim.ChaincodeStubInterface) pb.Response { 703 args := stub.GetArgs() 704 if len(args) < 1 { 705 return shim.Error(InvalidArgsLenErr(len(args)).Error()) 706 } 707 708 function := string(args[0]) 709 710 // Handle ACL: 711 // 1. get the signed proposal 712 sp, err := stub.GetSignedProposal() 713 if err != nil { 714 return shim.Error(fmt.Sprintf("Failed retrieving signed proposal on executing %s with error %s", function, err)) 715 } 716 717 switch function { 718 case INSTALL: 719 if len(args) < 2 { 720 return shim.Error(InvalidArgsLenErr(len(args)).Error()) 721 } 722 723 // 2. check local MSP Admins policy 724 if err = lscc.policyChecker.CheckPolicyNoChannel(mgmt.Admins, sp); err != nil { 725 return shim.Error(fmt.Sprintf("Authorization for INSTALL has been denied (error-%s)", err)) 726 } 727 728 depSpec := args[1] 729 730 err := lscc.executeInstall(stub, depSpec) 731 if err != nil { 732 return shim.Error(err.Error()) 733 } 734 return shim.Success([]byte("OK")) 735 case DEPLOY: 736 if len(args) < 3 || len(args) > 6 { 737 return shim.Error(InvalidArgsLenErr(len(args)).Error()) 738 } 739 740 // TODO: add access control check 741 // once the instantiation process will be completed. 742 743 //chain the chaincode shoud be associated with. It 744 //should be created with a register call 745 chainname := string(args[1]) 746 747 if !lscc.isValidChainName(chainname) { 748 return shim.Error(InvalidChainNameErr(chainname).Error()) 749 } 750 751 depSpec := args[2] 752 753 // optional arguments here (they can each be nil and may or may not be present) 754 // args[3] is a marshalled SignaturePolicyEnvelope representing the endorsement policy 755 // args[4] is the name of escc 756 // args[5] is the name of vscc 757 var policy []byte 758 if len(args) > 3 && len(args[3]) > 0 { 759 policy = args[3] 760 } else { 761 p := cauthdsl.SignedByAnyMember(peer.GetMSPIDs(chainname)) 762 policy, err = utils.Marshal(p) 763 if err != nil { 764 return shim.Error(err.Error()) 765 } 766 } 767 768 var escc []byte 769 if len(args) > 4 && args[4] != nil { 770 escc = args[4] 771 } else { 772 escc = []byte("escc") 773 } 774 775 var vscc []byte 776 if len(args) > 5 && args[5] != nil { 777 vscc = args[5] 778 } else { 779 vscc = []byte("vscc") 780 } 781 782 cd, err := lscc.executeDeploy(stub, chainname, depSpec, policy, escc, vscc) 783 if err != nil { 784 return shim.Error(err.Error()) 785 } 786 cdbytes, err := proto.Marshal(cd) 787 if err != nil { 788 return shim.Error(err.Error()) 789 } 790 return shim.Success(cdbytes) 791 case UPGRADE: 792 if len(args) < 3 || len(args) > 6 { 793 return shim.Error(InvalidArgsLenErr(len(args)).Error()) 794 } 795 796 chainname := string(args[1]) 797 if !lscc.isValidChainName(chainname) { 798 return shim.Error(InvalidChainNameErr(chainname).Error()) 799 } 800 801 // TODO: add access control check 802 // once the instantiation process will be completed. 803 804 depSpec := args[2] 805 806 // optional arguments here (they can each be nil and may or may not be present) 807 // args[3] is a marshalled SignaturePolicyEnvelope representing the endorsement policy 808 // args[4] is the name of escc 809 // args[5] is the name of vscc 810 var policy []byte 811 if len(args) > 3 && len(args[3]) > 0 { 812 policy = args[3] 813 } else { 814 p := cauthdsl.SignedByAnyMember(peer.GetMSPIDs(chainname)) 815 policy, err = utils.Marshal(p) 816 if err != nil { 817 return shim.Error(err.Error()) 818 } 819 } 820 821 var escc []byte 822 if len(args) > 4 && args[4] != nil { 823 escc = args[4] 824 } else { 825 escc = []byte("escc") 826 } 827 828 var vscc []byte 829 if len(args) > 5 && args[5] != nil { 830 vscc = args[5] 831 } else { 832 vscc = []byte("vscc") 833 } 834 835 cd, err := lscc.executeUpgrade(stub, chainname, depSpec, policy, escc, vscc) 836 if err != nil { 837 return shim.Error(err.Error()) 838 } 839 cdbytes, err := proto.Marshal(cd) 840 if err != nil { 841 return shim.Error(err.Error()) 842 } 843 return shim.Success(cdbytes) 844 case GETCCINFO, GETDEPSPEC, GETCCDATA: 845 if len(args) != 3 { 846 return shim.Error(InvalidArgsLenErr(len(args)).Error()) 847 } 848 849 chain := string(args[1]) 850 ccname := string(args[2]) 851 852 // 2. check local Channel Readers policy 853 // Notice that this information are already available on the ledger 854 // therefore we enforce here that the caller is reader of the channel. 855 if err = lscc.policyChecker.CheckPolicy(chain, policies.ChannelApplicationReaders, sp); err != nil { 856 return shim.Error(fmt.Sprintf("Authorization for %s on channel %s has been denied with error %s", function, args[1], err)) 857 } 858 859 cdbytes, err := lscc.getCCInstance(stub, ccname) 860 if err != nil { 861 logger.Errorf("error getting chaincode %s on channel: %s(err:%s)", ccname, chain, err) 862 return shim.Error(err.Error()) 863 } 864 865 switch function { 866 case GETCCINFO: 867 cd, err := lscc.getChaincodeData(ccname, cdbytes) 868 if err != nil { 869 return shim.Error(err.Error()) 870 } 871 return shim.Success([]byte(cd.Name)) 872 case GETCCDATA: 873 return shim.Success(cdbytes) 874 default: 875 _, _, depspecbytes, err := lscc.getCCCode(ccname, cdbytes) 876 if err != nil { 877 return shim.Error(err.Error()) 878 } 879 return shim.Success(depspecbytes) 880 } 881 case GETCHAINCODES: 882 if len(args) != 1 { 883 return shim.Error(InvalidArgsLenErr(len(args)).Error()) 884 } 885 886 // 2. check local MSP Admins policy 887 if err = lscc.policyChecker.CheckPolicyNoChannel(mgmt.Members, sp); err != nil { 888 return shim.Error(fmt.Sprintf("Authorization for GETCHAINCODES on channel %s has been denied with error %s", args[0], err)) 889 } 890 891 return lscc.getChaincodes(stub) 892 case GETINSTALLEDCHAINCODES: 893 if len(args) != 1 { 894 return shim.Error(InvalidArgsLenErr(len(args)).Error()) 895 } 896 897 // 2. check local MSP Admins policy 898 if err = lscc.policyChecker.CheckPolicyNoChannel(mgmt.Members, sp); err != nil { 899 return shim.Error(fmt.Sprintf("Authorization for GETINSTALLEDCHAINCODES on channel %s has been denied with error %s", args[0], err)) 900 } 901 902 return lscc.getInstalledChaincodes() 903 } 904 905 return shim.Error(InvalidFunctionErr(function).Error()) 906 } 907 908