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