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