From f61e6b268f3190d675dc9e6ca1754f1ebbb787fa Mon Sep 17 00:00:00 2001 From: Angelo De Caro Date: Sat, 18 Feb 2017 16:12:58 +0100 Subject: [PATCH] Passing SignedProposal the chaincode execution This change-set passes the SignedProposal to the chaincode execution engine for two reasons: 1. being able to apply ACL on CC2CC 2. passing signed proposal to chaincode, if needed. Change-Id: I994ee261e942b2714e2506a4ea417bd4004a5963 Signed-off-by: Angelo De Caro --- core/chaincode/ccproviderimpl.go | 8 +++--- core/chaincode/chaincode_support.go | 6 ++--- core/chaincode/chaincodeexec.go | 8 +++--- core/chaincode/concurrency_test.go | 2 +- core/chaincode/exectransaction_test.go | 30 +++++++++++----------- core/chaincode/handler.go | 34 +++++++++++++++---------- core/chaincode/multichains_test.go | 2 +- core/chaincode/systemchaincode_test.go | 2 +- core/chaincode/upgrade_test.go | 8 +++--- core/committer/txvalidator/validator.go | 4 +-- core/common/ccprovider/ccprovider.go | 13 +++++++--- core/endorser/endorser.go | 28 ++++++++++---------- core/endorser/endorser_test.go | 10 ++++---- core/mocks/ccprovider/ccprovider.go | 4 +-- core/scc/sysccapi.go | 4 +-- 15 files changed, 88 insertions(+), 75 deletions(-) diff --git a/core/chaincode/ccproviderimpl.go b/core/chaincode/ccproviderimpl.go index 824242c051f..96461191baa 100644 --- a/core/chaincode/ccproviderimpl.go +++ b/core/chaincode/ccproviderimpl.go @@ -67,13 +67,13 @@ func (c *ccProviderImpl) GetContext(ledger ledger.PeerLedger) (context.Context, // GetCCContext returns an interface that encapsulates a // chaincode context; the interface is required to avoid // referencing the chaincode package from the interface definition -func (c *ccProviderImpl) GetCCContext(cid, name, version, txid string, syscc bool, prop *pb.Proposal) interface{} { - ctx := ccprovider.NewCCContext(cid, name, version, txid, syscc, prop) +func (c *ccProviderImpl) GetCCContext(cid, name, version, txid string, syscc bool, signedProp *pb.SignedProposal, prop *pb.Proposal) interface{} { + ctx := ccprovider.NewCCContext(cid, name, version, txid, syscc, signedProp, prop) return &ccProviderContextImpl{ctx: ctx} } // GetCCValidationInfoFromLCCC returns the VSCC and the policy listed in LCCC for the supplied chaincode -func (c *ccProviderImpl) GetCCValidationInfoFromLCCC(ctxt context.Context, txid string, prop *pb.Proposal, chainID string, chaincodeID string) (string, []byte, error) { +func (c *ccProviderImpl) GetCCValidationInfoFromLCCC(ctxt context.Context, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal, chainID string, chaincodeID string) (string, []byte, error) { // LCCC does not have any notion about its own // endorsing policy - we should never call this // function with lccc as the chaincodeID @@ -81,7 +81,7 @@ func (c *ccProviderImpl) GetCCValidationInfoFromLCCC(ctxt context.Context, txid panic("GetCCValidationInfoFromLCCC invoke for LCCC") } - data, err := GetChaincodeDataFromLCCC(ctxt, txid, prop, chainID, chaincodeID) + data, err := GetChaincodeDataFromLCCC(ctxt, txid, signedProp, prop, chainID, chaincodeID) if err != nil { return "", nil, err } diff --git a/core/chaincode/chaincode_support.go b/core/chaincode/chaincode_support.go index 7e60956bdc9..98c73ee10f3 100644 --- a/core/chaincode/chaincode_support.go +++ b/core/chaincode/chaincode_support.go @@ -291,7 +291,7 @@ func (chaincodeSupport *ChaincodeSupport) sendReady(context context.Context, ccc var notfy chan *pb.ChaincodeMessage var err error - if notfy, err = chrte.handler.ready(context, cccid.ChainID, cccid.TxID, cccid.Proposal); err != nil { + if notfy, err = chrte.handler.ready(context, cccid.ChainID, cccid.TxID, cccid.SignedProposal, cccid.Proposal); err != nil { return fmt.Errorf("Error sending %s: %s", pb.ChaincodeMessage_INIT, err) } if notfy != nil { @@ -533,7 +533,7 @@ func (chaincodeSupport *ChaincodeSupport) Launch(context context.Context, cccid var depPayload []byte //hopefully we are restarting from existing image and the deployed transaction exists - depPayload, err = GetCDSFromLCCC(context, cccid.TxID, cccid.Proposal, cccid.ChainID, cID.Name) + depPayload, err = GetCDSFromLCCC(context, cccid.TxID, cccid.SignedProposal, cccid.Proposal, cccid.ChainID, cID.Name) if err != nil { return cID, cMsg, fmt.Errorf("Could not get deployment transaction from LCCC for %s - %s", canName, err) } @@ -642,7 +642,7 @@ func (chaincodeSupport *ChaincodeSupport) Execute(ctxt context.Context, cccid *c var notfy chan *pb.ChaincodeMessage var err error - if notfy, err = chrte.handler.sendExecuteMessage(ctxt, cccid.ChainID, msg, cccid.Proposal); err != nil { + if notfy, err = chrte.handler.sendExecuteMessage(ctxt, cccid.ChainID, msg, cccid.SignedProposal, cccid.Proposal); err != nil { return nil, fmt.Errorf("Error sending %s: %s", msg.Type.String(), err) } var ccresp *pb.ChaincodeMessage diff --git a/core/chaincode/chaincodeexec.go b/core/chaincode/chaincodeexec.go index 499fa94f210..73824b7cc77 100644 --- a/core/chaincode/chaincodeexec.go +++ b/core/chaincode/chaincodeexec.go @@ -39,9 +39,9 @@ func createCIS(ccname string, args [][]byte) (*pb.ChaincodeInvocationSpec, error } // GetCDSFromLCCC gets chaincode deployment spec from LCCC -func GetCDSFromLCCC(ctxt context.Context, txid string, prop *pb.Proposal, chainID string, chaincodeID string) ([]byte, error) { +func GetCDSFromLCCC(ctxt context.Context, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal, chainID string, chaincodeID string) ([]byte, error) { version := util.GetSysCCVersion() - cccid := ccprovider.NewCCContext(chainID, "lccc", version, txid, true, prop) + cccid := ccprovider.NewCCContext(chainID, "lccc", version, txid, true, signedProp, prop) res, _, err := ExecuteChaincode(ctxt, cccid, [][]byte{[]byte("getdepspec"), []byte(chainID), []byte(chaincodeID)}) if err != nil { return nil, fmt.Errorf("Execute getdepspec(%s, %s) of LCCC error: %s", chainID, chaincodeID, err) @@ -54,9 +54,9 @@ func GetCDSFromLCCC(ctxt context.Context, txid string, prop *pb.Proposal, chainI } // GetChaincodeDataFromLCCC gets chaincode data from LCCC given name -func GetChaincodeDataFromLCCC(ctxt context.Context, txid string, prop *pb.Proposal, chainID string, chaincodeID string) (*ccprovider.ChaincodeData, error) { +func GetChaincodeDataFromLCCC(ctxt context.Context, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal, chainID string, chaincodeID string) (*ccprovider.ChaincodeData, error) { version := util.GetSysCCVersion() - cccid := ccprovider.NewCCContext(chainID, "lccc", version, txid, true, prop) + cccid := ccprovider.NewCCContext(chainID, "lccc", version, txid, true, signedProp, prop) res, _, err := ExecuteChaincode(ctxt, cccid, [][]byte{[]byte("getccdata"), []byte(chainID), []byte(chaincodeID)}) if err == nil { if res.Status != shim.OK { diff --git a/core/chaincode/concurrency_test.go b/core/chaincode/concurrency_test.go index 0e5bd009a0d..e0a91e83999 100644 --- a/core/chaincode/concurrency_test.go +++ b/core/chaincode/concurrency_test.go @@ -54,7 +54,7 @@ func TestExecuteConcurrentInvokes(t *testing.T) { spec := &pb.ChaincodeSpec{Type: 1, ChaincodeId: chaincodeID, Input: &pb.ChaincodeInput{Args: args}} - cccid := ccprovider.NewCCContext(chainID, "nkpi", "0", "", false, nil) + cccid := ccprovider.NewCCContext(chainID, "nkpi", "0", "", false, nil, nil) defer theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) diff --git a/core/chaincode/exectransaction_test.go b/core/chaincode/exectransaction_test.go index 22a312e693f..7971f60f79a 100644 --- a/core/chaincode/exectransaction_test.go +++ b/core/chaincode/exectransaction_test.go @@ -288,7 +288,7 @@ func deploy2(ctx context.Context, cccid *ccprovider.CCContext, chaincodeDeployme ccprovider.PutChaincodeIntoFS(chaincodeDeploymentSpec) sysCCVers := util.GetSysCCVersion() - lcccid := ccprovider.NewCCContext(cccid.ChainID, cis.ChaincodeSpec.ChaincodeId.Name, sysCCVers, uuid, true, nil) + lcccid := ccprovider.NewCCContext(cccid.ChainID, cis.ChaincodeSpec.ChaincodeId.Name, sysCCVers, uuid, true, nil, nil) //write to lccc if _, _, err = ExecuteWithErrorFilter(ctx, lcccid, cis); err != nil { @@ -331,7 +331,7 @@ func invokeWithVersion(ctx context.Context, chainID string, version string, spec } }() - cccid := ccprovider.NewCCContext(chainID, chaincodeInvocationSpec.ChaincodeSpec.ChaincodeId.Name, version, uuid, false, nil) + cccid := ccprovider.NewCCContext(chainID, chaincodeInvocationSpec.ChaincodeSpec.ChaincodeId.Name, version, uuid, false, nil, nil) retval, ccevt, err = ExecuteWithErrorFilter(ctx, cccid, chaincodeInvocationSpec) if err != nil { return nil, uuid, nil, fmt.Errorf("Error invoking chaincode: %s", err) @@ -362,7 +362,7 @@ func executeDeployTransaction(t *testing.T, chainID string, name string, url str args := util.ToChaincodeArgs(f, "a", "100", "b", "200") spec := &pb.ChaincodeSpec{Type: 1, ChaincodeId: &pb.ChaincodeID{Name: name, Path: url, Version: "0"}, Input: &pb.ChaincodeInput{Args: args}} - cccid := ccprovider.NewCCContext(chainID, name, "0", "", false, nil) + cccid := ccprovider.NewCCContext(chainID, name, "0", "", false, nil, nil) _, err = deploy(ctxt, cccid, spec, 0) @@ -389,7 +389,7 @@ func chaincodeQueryChaincode(chainID string, user string) error { spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID1, Input: &pb.ChaincodeInput{Args: args}} - cccid1 := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil) + cccid1 := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil, nil) var nextBlockNumber uint64 @@ -413,7 +413,7 @@ func chaincodeQueryChaincode(chainID string, user string) error { spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID2, Input: &pb.ChaincodeInput{Args: args}} - cccid2 := ccprovider.NewCCContext(chainID, "example05", "0", "", false, nil) + cccid2 := ccprovider.NewCCContext(chainID, "example05", "0", "", false, nil, nil) _, err = deploy(ctxt, cccid2, spec2, nextBlockNumber) nextBlockNumber++ @@ -618,7 +618,7 @@ func TestExecuteInvokeTransaction(t *testing.T) { var ctxt = context.Background() - cccid := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil) + cccid := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil, nil) url := "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02" chaincodeID := &pb.ChaincodeID{Name: "example02", Path: url, Version: "0"} @@ -652,7 +652,7 @@ func TestExecuteInvokeInvalidTransaction(t *testing.T) { url := "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02" chaincodeID := &pb.ChaincodeID{Name: "example02", Path: url, Version: "0"} - cccid := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil) + cccid := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil, nil) //FAIL, FAIL! args := []string{"x", "-1"} @@ -709,7 +709,7 @@ func chaincodeInvokeChaincode(t *testing.T, chainID string, user string) (err er spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID1, Input: &pb.ChaincodeInput{Args: args}} - cccid1 := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil) + cccid1 := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil, nil) var nextBlockNumber uint64 @@ -736,7 +736,7 @@ func chaincodeInvokeChaincode(t *testing.T, chainID string, user string) (err er spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID2, Input: &pb.ChaincodeInput{Args: args}} - cccid2 := ccprovider.NewCCContext(chainID, "example04", "0", "", false, nil) + cccid2 := ccprovider.NewCCContext(chainID, "example04", "0", "", false, nil, nil) _, err = deploy(ctxt, cccid2, spec2, nextBlockNumber) nextBlockNumber++ @@ -812,7 +812,7 @@ func TestChaincodeInvokeChaincodeErrorCase(t *testing.T) { spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID1, Input: &pb.ChaincodeInput{Args: args}} - cccid1 := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil) + cccid1 := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil, nil) var nextBlockNumber uint64 @@ -837,7 +837,7 @@ func TestChaincodeInvokeChaincodeErrorCase(t *testing.T) { spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID2, Input: &pb.ChaincodeInput{Args: args}} - cccid2 := ccprovider.NewCCContext(chainID, "pthru", "0", "", false, nil) + cccid2 := ccprovider.NewCCContext(chainID, "pthru", "0", "", false, nil, nil) _, err = deploy(ctxt, cccid2, spec2, nextBlockNumber) nextBlockNumber++ @@ -903,7 +903,7 @@ func TestQueries(t *testing.T) { spec := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} - cccid := ccprovider.NewCCContext(chainID, "tmap", "0", "", false, nil) + cccid := ccprovider.NewCCContext(chainID, "tmap", "0", "", false, nil, nil) var nextBlockNumber uint64 _, err = deploy(ctxt, cccid, spec, nextBlockNumber) @@ -1003,7 +1003,7 @@ func TestGetEvent(t *testing.T) { f := "init" spec := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: util.ToChaincodeArgs(f)}} - cccid := ccprovider.NewCCContext(chainID, "esender", "0", "", false, nil) + cccid := ccprovider.NewCCContext(chainID, "esender", "0", "", false, nil, nil) var nextBlockNumber uint64 _, err = deploy(ctxt, cccid, spec, nextBlockNumber) nextBlockNumber++ @@ -1073,7 +1073,7 @@ func TestChaincodeQueryChaincodeUsingInvoke(t *testing.T) { spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID1, Input: &pb.ChaincodeInput{Args: args}} - cccid1 := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil) + cccid1 := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil, nil) var nextBlockNumber uint64 _, err = deploy(ctxt, cccid1, spec1, nextBlockNumber) nextBlockNumber++ @@ -1096,7 +1096,7 @@ func TestChaincodeQueryChaincodeUsingInvoke(t *testing.T) { spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID2, Input: &pb.ChaincodeInput{Args: args}} - cccid2 := ccprovider.NewCCContext(chainID, "example05", "0", "", false, nil) + cccid2 := ccprovider.NewCCContext(chainID, "example05", "0", "", false, nil, nil) _, err = deploy(ctxt, cccid2, spec2, nextBlockNumber) nextBlockNumber++ diff --git a/core/chaincode/handler.go b/core/chaincode/handler.go index 343141c5cff..977a0fe1568 100644 --- a/core/chaincode/handler.go +++ b/core/chaincode/handler.go @@ -54,6 +54,7 @@ type MessageHandler interface { type transactionContext struct { chainID string + signedProp *pb.SignedProposal proposal *pb.Proposal responseNotifier chan *pb.ChaincodeMessage @@ -181,7 +182,7 @@ func (handler *Handler) serialSendAsync(msg *pb.ChaincodeMessage, errc chan erro }() } -func (handler *Handler) createTxContext(ctxt context.Context, chainID string, txid string, prop *pb.Proposal) (*transactionContext, error) { +func (handler *Handler) createTxContext(ctxt context.Context, chainID string, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal) (*transactionContext, error) { if handler.txCtxs == nil { return nil, fmt.Errorf("cannot create notifier for txid:%s", txid) } @@ -190,7 +191,7 @@ func (handler *Handler) createTxContext(ctxt context.Context, chainID string, tx if handler.txCtxs[txid] != nil { return nil, fmt.Errorf("txid:%s exists", txid) } - txctx := &transactionContext{chainID: chainID, proposal: prop, responseNotifier: make(chan *pb.ChaincodeMessage, 1), + txctx := &transactionContext{chainID: chainID, signedProp: signedProp, proposal: prop, responseNotifier: make(chan *pb.ChaincodeMessage, 1), queryIteratorMap: make(map[string]commonledger.ResultsIterator)} handler.txCtxs[txid] = txctx txctx.txsimulator = getTxSimulator(ctxt) @@ -233,7 +234,7 @@ func (handler *Handler) deleteQueryIterator(txContext *transactionContext, txid } // Check if the transactor is allow to call this chaincode on this channel -func (handler *Handler) checkACL(proposal *pb.Proposal, calledCC *ccParts) *pb.ChaincodeMessage { +func (handler *Handler) checkACL(signedProp *pb.SignedProposal, proposal *pb.Proposal, calledCC *ccParts) *pb.ChaincodeMessage { // TODO: Decide what to pass in to verify that this transactor can access this // channel (chID) and chaincode (ccID). Very likely we need the signedProposal // which contains the sig and creator cert @@ -1249,7 +1250,7 @@ func (handler *Handler) enterBusyState(e *fsm.Event, state string) { shorttxid(msg.Txid), calledCcParts.name, calledCcParts.suffix) } - triggerNextStateMsg = handler.checkACL(txContext.proposal, calledCcParts) + triggerNextStateMsg = handler.checkACL(txContext.signedProp, txContext.proposal, calledCcParts) if triggerNextStateMsg != nil { return } @@ -1286,7 +1287,7 @@ func (handler *Handler) enterBusyState(e *fsm.Event, state string) { //Call LCCC to get the called chaincode artifacts var cd *ccprovider.ChaincodeData - cd, err = GetChaincodeDataFromLCCC(ctxt, msg.Txid, txContext.proposal, calledCcParts.suffix, calledCcParts.name) + cd, err = GetChaincodeDataFromLCCC(ctxt, msg.Txid, txContext.signedProp, txContext.proposal, calledCcParts.suffix, calledCcParts.name) if err != nil { payload := []byte(err.Error()) chaincodeLogger.Debugf("[%s]Failed to get chaincoed data (%s) for invoked chaincode. Sending %s", @@ -1294,7 +1295,7 @@ func (handler *Handler) enterBusyState(e *fsm.Event, state string) { triggerNextStateMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid} return } - cccid := ccprovider.NewCCContext(calledCcParts.suffix, calledCcParts.name, cd.Version, msg.Txid, false, txContext.proposal) + cccid := ccprovider.NewCCContext(calledCcParts.suffix, calledCcParts.name, cd.Version, msg.Txid, false, txContext.signedProp, txContext.proposal) // Launch the new chaincode if not already running if chaincodeLogger.IsEnabledFor(logging.DEBUG) { @@ -1373,19 +1374,24 @@ func (handler *Handler) enterEndState(e *fsm.Event, state string) { e.Cancel(fmt.Errorf("Entered end state")) } -func (handler *Handler) setChaincodeProposal(prop *pb.Proposal, msg *pb.ChaincodeMessage) error { +func (handler *Handler) setChaincodeProposal(signedProp *pb.SignedProposal, prop *pb.Proposal, msg *pb.ChaincodeMessage) error { chaincodeLogger.Debug("Setting chaincode proposal context...") if prop != nil { chaincodeLogger.Debug("Proposal different from nil. Creating chaincode proposal context...") + // Check that also signedProp is different from nil + if signedProp == nil { + return fmt.Errorf("Failed getting proposal context. Signed proposal is nil.") + } + msg.Proposal = prop } return nil } //move to ready -func (handler *Handler) ready(ctxt context.Context, chainID string, txid string, prop *pb.Proposal) (chan *pb.ChaincodeMessage, error) { - txctx, funcErr := handler.createTxContext(ctxt, chainID, txid, prop) +func (handler *Handler) ready(ctxt context.Context, chainID string, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal) (chan *pb.ChaincodeMessage, error) { + txctx, funcErr := handler.createTxContext(ctxt, chainID, txid, signedProp, prop) if funcErr != nil { return nil, funcErr } @@ -1393,7 +1399,8 @@ func (handler *Handler) ready(ctxt context.Context, chainID string, txid string, chaincodeLogger.Debug("sending READY") ccMsg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_READY, Txid: txid} - if err := handler.setChaincodeProposal(prop, ccMsg); err != nil { + //if security is disabled the context elements will just be nil + if err := handler.setChaincodeProposal(signedProp, prop, ccMsg); err != nil { return nil, err } @@ -1448,8 +1455,8 @@ func filterError(errFromFSMEvent error) error { return nil } -func (handler *Handler) sendExecuteMessage(ctxt context.Context, chainID string, msg *pb.ChaincodeMessage, prop *pb.Proposal) (chan *pb.ChaincodeMessage, error) { - txctx, err := handler.createTxContext(ctxt, chainID, msg.Txid, prop) +func (handler *Handler) sendExecuteMessage(ctxt context.Context, chainID string, msg *pb.ChaincodeMessage, signedProp *pb.SignedProposal, prop *pb.Proposal) (chan *pb.ChaincodeMessage, error) { + txctx, err := handler.createTxContext(ctxt, chainID, msg.Txid, signedProp, prop) if err != nil { return nil, err } @@ -1457,7 +1464,8 @@ func (handler *Handler) sendExecuteMessage(ctxt context.Context, chainID string, chaincodeLogger.Debugf("[%s]Inside sendExecuteMessage. Message %s", shorttxid(msg.Txid), msg.Type.String()) } - if err = handler.setChaincodeProposal(prop, msg); err != nil { + //if security is disabled the context elements will just be nil + if err = handler.setChaincodeProposal(signedProp, prop, msg); err != nil { return nil, err } diff --git a/core/chaincode/multichains_test.go b/core/chaincode/multichains_test.go index 37198e73907..289760f41a2 100644 --- a/core/chaincode/multichains_test.go +++ b/core/chaincode/multichains_test.go @@ -42,7 +42,7 @@ func TestExecuteInvokeOnManyChains(t *testing.T) { args := []string{"a", "b", "10"} for _, c := range chains { - cccid := ccprovider.NewCCContext(c, "example02", "0", "", false, nil) + cccid := ccprovider.NewCCContext(c, "example02", "0", "", false, nil, nil) err = invokeExample02Transaction(ctxt, cccid, chaincodeID, args, false) if err != nil { t.Fail() diff --git a/core/chaincode/systemchaincode_test.go b/core/chaincode/systemchaincode_test.go index 007e76fea0d..c1648721435 100644 --- a/core/chaincode/systemchaincode_test.go +++ b/core/chaincode/systemchaincode_test.go @@ -108,7 +108,7 @@ func deploySampleSysCC(t *testing.T, ctxt context.Context, chainID string) error _, _, _, err := invokeWithVersion(ctxt, chainID, sysCCVers, spec, nextBlockNumber) nextBlockNumber++ - cccid := ccprovider.NewCCContext(chainID, "sample_syscc", sysCCVers, "", true, nil) + cccid := ccprovider.NewCCContext(chainID, "sample_syscc", sysCCVers, "", true, nil, nil) cdsforStop := &pb.ChaincodeDeploymentSpec{ExecEnv: 1, ChaincodeSpec: spec} if err != nil { theChaincodeSupport.Stop(ctxt, cccid, cdsforStop) diff --git a/core/chaincode/upgrade_test.go b/core/chaincode/upgrade_test.go index 8a8c1910286..469e58cd4ab 100644 --- a/core/chaincode/upgrade_test.go +++ b/core/chaincode/upgrade_test.go @@ -81,7 +81,7 @@ func upgrade2(ctx context.Context, cccid *ccprovider.CCContext, }() sysCCVers := util.GetSysCCVersion() - lcccid := ccprovider.NewCCContext(cccid.ChainID, cis.ChaincodeSpec.ChaincodeId.Name, sysCCVers, uuid, true, nil) + lcccid := ccprovider.NewCCContext(cccid.ChainID, cis.ChaincodeSpec.ChaincodeId.Name, sysCCVers, uuid, true, nil, nil) var versionBytes []byte //write to lccc @@ -98,7 +98,7 @@ func upgrade2(ctx context.Context, cccid *ccprovider.CCContext, return nil, fmt.Errorf("Expected new version from LCCC but got same %s(%s)", newVersion, cccid.Version) } - newcccid = ccprovider.NewCCContext(cccid.ChainID, chaincodeDeploymentSpec.ChaincodeSpec.ChaincodeId.Name, newVersion, uuid, false, nil) + newcccid = ccprovider.NewCCContext(cccid.ChainID, chaincodeDeploymentSpec.ChaincodeSpec.ChaincodeId.Name, newVersion, uuid, false, nil, nil) if _, _, err = ExecuteWithErrorFilter(ctx, newcccid, chaincodeDeploymentSpec); err != nil { return nil, fmt.Errorf("Error deploying chaincode for upgrade: %s", err) @@ -137,7 +137,7 @@ func TestUpgradeCC(t *testing.T) { spec := &pb.ChaincodeSpec{Type: 1, ChaincodeId: chaincodeID, Input: &pb.ChaincodeInput{Args: args}} - cccid := ccprovider.NewCCContext(chainID, ccName, "0", "", false, nil) + cccid := ccprovider.NewCCContext(chainID, ccName, "0", "", false, nil, nil) var nextBlockNumber uint64 _, err = deploy(ctxt, cccid, spec, nextBlockNumber) @@ -227,7 +227,7 @@ func TestInvalUpgradeCC(t *testing.T) { f := "init" args := util.ToChaincodeArgs(f, "a", "100", "b", "200") - cccid := ccprovider.NewCCContext(chainID, ccName, "0", "", false, nil) + cccid := ccprovider.NewCCContext(chainID, ccName, "0", "", false, nil, nil) //Note ccName hasn't changed... chaincodeID := &pb.ChaincodeID{Name: ccName, Path: url, Version: "1"} diff --git a/core/committer/txvalidator/validator.go b/core/committer/txvalidator/validator.go index 64412d303a2..7247f76fbde 100644 --- a/core/committer/txvalidator/validator.go +++ b/core/committer/txvalidator/validator.go @@ -220,7 +220,7 @@ func (v *vsccValidatorImpl) VSCCValidateTx(payload *common.Payload, envBytes []b } // obtain name of the VSCC and the policy from LCCC - vscc, policy, err := v.ccprovider.GetCCValidationInfoFromLCCC(ctxt, txid, nil, chainID, hdrExt.ChaincodeId.Name) + vscc, policy, err := v.ccprovider.GetCCValidationInfoFromLCCC(ctxt, txid, nil, nil, chainID, hdrExt.ChaincodeId.Name) if err != nil { logger.Errorf("Unable to get chaincode data from LCCC for txid %s, due to %s", txid, err) return err @@ -236,7 +236,7 @@ func (v *vsccValidatorImpl) VSCCValidateTx(payload *common.Payload, envBytes []b // Get chaincode version version := coreUtil.GetSysCCVersion() - cccid := v.ccprovider.GetCCContext(chainID, vscc, version, vscctxid, true, nil) + cccid := v.ccprovider.GetCCContext(chainID, vscc, version, vscctxid, true, nil, nil) // invoke VSCC logger.Info("Invoking VSCC txid", txid, "chaindID", chainID) diff --git a/core/common/ccprovider/ccprovider.go b/core/common/ccprovider/ccprovider.go index eafc3c90f3d..2a25ed62a0b 100644 --- a/core/common/ccprovider/ccprovider.go +++ b/core/common/ccprovider/ccprovider.go @@ -124,6 +124,11 @@ type CCContext struct { //Syscc is this a system chaincode Syscc bool + //SignedProposal for this invoke (if any) + //this is kept here for access control and in case we need to pass something + //from this to the chaincode + SignedProposal *pb.SignedProposal + //Proposal for this invoke (if any) //this is kept here just in case we need to pass something //from this to the chaincode @@ -134,7 +139,7 @@ type CCContext struct { } //NewCCContext just construct a new struct with whatever args -func NewCCContext(cid, name, version, txid string, syscc bool, prop *pb.Proposal) *CCContext { +func NewCCContext(cid, name, version, txid string, syscc bool, signedProp *pb.SignedProposal, prop *pb.Proposal) *CCContext { //version CANNOT be empty. The chaincode namespace has to use version and chain name. //All system chaincodes share the same version given by utils.GetSysCCVersion. Note //that neither Chain Name or Version are stored in a chaincodes state on the ledger @@ -144,7 +149,7 @@ func NewCCContext(cid, name, version, txid string, syscc bool, prop *pb.Proposal canName := name + ":" + version - cccid := &CCContext{cid, name, version, txid, syscc, prop, canName} + cccid := &CCContext{cid, name, version, txid, syscc, signedProp, prop, canName} ccproviderLogger.Infof("NewCCCC (chain=%s,chaincode=%s,version=%s,txid=%s,syscc=%t,proposal=%p,canname=%s", cid, name, version, txid, syscc, prop, cccid.canonicalName) @@ -189,9 +194,9 @@ type ChaincodeProvider interface { // GetContext returns a ledger context GetContext(ledger ledger.PeerLedger) (context.Context, error) // GetCCContext returns an opaque chaincode context - GetCCContext(cid, name, version, txid string, syscc bool, prop *pb.Proposal) interface{} + GetCCContext(cid, name, version, txid string, syscc bool, signedProp *pb.SignedProposal, prop *pb.Proposal) interface{} // GetCCValidationInfoFromLCCC returns the VSCC and the policy listed by LCCC for the supplied chaincode - GetCCValidationInfoFromLCCC(ctxt context.Context, txid string, prop *pb.Proposal, chainID string, chaincodeID string) (string, []byte, error) + GetCCValidationInfoFromLCCC(ctxt context.Context, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal, chainID string, chaincodeID string) (string, []byte, error) // ExecuteChaincode executes the chaincode given context and args ExecuteChaincode(ctxt context.Context, cccid interface{}, args [][]byte) (*pb.Response, *pb.ChaincodeEvent, error) // Execute executes the chaincode given context and spec (invocation or deploy) diff --git a/core/endorser/endorser.go b/core/endorser/endorser.go index 6da9f9f31f9..df7c03ea1d1 100644 --- a/core/endorser/endorser.go +++ b/core/endorser/endorser.go @@ -55,7 +55,7 @@ func NewEndorserServer() pb.EndorserServer { } //TODO - what would Endorser's ACL be ? -func (*Endorser) checkACL(prop *pb.Proposal) error { +func (*Endorser) checkACL(signedProp *pb.SignedProposal, prop *pb.Proposal) error { return nil } @@ -81,7 +81,7 @@ func (*Endorser) getHistoryQueryExecutor(ledgername string) (ledger.HistoryQuery } //call specified chaincode (system or user) -func (e *Endorser) callChaincode(ctxt context.Context, chainID string, version string, txid string, prop *pb.Proposal, cis *pb.ChaincodeInvocationSpec, cid *pb.ChaincodeID, txsim ledger.TxSimulator) (*pb.Response, *pb.ChaincodeEvent, error) { +func (e *Endorser) callChaincode(ctxt context.Context, chainID string, version string, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal, cis *pb.ChaincodeInvocationSpec, cid *pb.ChaincodeID, txsim ledger.TxSimulator) (*pb.Response, *pb.ChaincodeEvent, error) { var err error var res *pb.Response var ccevent *pb.ChaincodeEvent @@ -93,7 +93,7 @@ func (e *Endorser) callChaincode(ctxt context.Context, chainID string, version s //is this a system chaincode scc := syscc.IsSysCC(cid.Name) - cccid := ccprovider.NewCCContext(chainID, cid.Name, version, txid, scc, prop) + cccid := ccprovider.NewCCContext(chainID, cid.Name, version, txid, scc, signedProp, prop) res, ccevent, err = chaincode.ExecuteChaincode(ctxt, cccid, cis.ChaincodeSpec.Input.Args) @@ -125,7 +125,7 @@ func (e *Endorser) callChaincode(ctxt context.Context, chainID string, version s return nil, nil, fmt.Errorf("attempting to deploy a system chaincode %s/%s", cds.ChaincodeSpec.ChaincodeId.Name, chainID) } - cccid = ccprovider.NewCCContext(chainID, cds.ChaincodeSpec.ChaincodeId.Name, cds.ChaincodeSpec.ChaincodeId.Version, txid, false, prop) + cccid = ccprovider.NewCCContext(chainID, cds.ChaincodeSpec.ChaincodeId.Name, cds.ChaincodeSpec.ChaincodeId.Version, txid, false, signedProp, prop) _, _, err = chaincode.Execute(ctxt, cccid, cds) if err != nil { @@ -138,7 +138,7 @@ func (e *Endorser) callChaincode(ctxt context.Context, chainID string, version s } //simulate the proposal by calling the chaincode -func (e *Endorser) simulateProposal(ctx context.Context, chainID string, txid string, prop *pb.Proposal, cid *pb.ChaincodeID, txsim ledger.TxSimulator) (*ccprovider.ChaincodeData, *pb.Response, []byte, *pb.ChaincodeEvent, error) { +func (e *Endorser) simulateProposal(ctx context.Context, chainID string, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal, cid *pb.ChaincodeID, txsim ledger.TxSimulator) (*ccprovider.ChaincodeData, *pb.Response, []byte, *pb.ChaincodeEvent, error) { //we do expect the payload to be a ChaincodeInvocationSpec //if we are supporting other payloads in future, this be glaringly point //as something that should change @@ -147,7 +147,7 @@ func (e *Endorser) simulateProposal(ctx context.Context, chainID string, txid st return nil, nil, nil, nil, err } //---1. check ACL - if err = e.checkACL(prop); err != nil { + if err = e.checkACL(signedProp, prop); err != nil { return nil, nil, nil, nil, err } @@ -161,7 +161,7 @@ func (e *Endorser) simulateProposal(ctx context.Context, chainID string, txid st //default it to a system CC version := util.GetSysCCVersion() if !syscc.IsSysCC(cid.Name) { - cd, err = e.getCDSFromLCCC(ctx, chainID, txid, prop, cid.Name, txsim) + cd, err = e.getCDSFromLCCC(ctx, chainID, txid, signedProp, prop, cid.Name, txsim) if err != nil { return nil, nil, nil, nil, fmt.Errorf("failed to obtain cds for %s - %s", cid.Name, err) } @@ -172,7 +172,7 @@ func (e *Endorser) simulateProposal(ctx context.Context, chainID string, txid st var simResult []byte var res *pb.Response var ccevent *pb.ChaincodeEvent - res, ccevent, err = e.callChaincode(ctx, chainID, version, txid, prop, cis, cid, txsim) + res, ccevent, err = e.callChaincode(ctx, chainID, version, txid, signedProp, prop, cis, cid, txsim) if err != nil { return nil, nil, nil, nil, err } @@ -186,17 +186,17 @@ func (e *Endorser) simulateProposal(ctx context.Context, chainID string, txid st return cd, res, simResult, ccevent, nil } -func (e *Endorser) getCDSFromLCCC(ctx context.Context, chainID string, txid string, prop *pb.Proposal, chaincodeID string, txsim ledger.TxSimulator) (*ccprovider.ChaincodeData, error) { +func (e *Endorser) getCDSFromLCCC(ctx context.Context, chainID string, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal, chaincodeID string, txsim ledger.TxSimulator) (*ccprovider.ChaincodeData, error) { ctxt := ctx if txsim != nil { ctxt = context.WithValue(ctx, chaincode.TXSimulatorKey, txsim) } - return chaincode.GetChaincodeDataFromLCCC(ctxt, txid, prop, chainID, chaincodeID) + return chaincode.GetChaincodeDataFromLCCC(ctxt, txid, signedProp, prop, chainID, chaincodeID) } //endorse the proposal by calling the ESCC -func (e *Endorser) endorseProposal(ctx context.Context, chainID string, txid string, proposal *pb.Proposal, response *pb.Response, simRes []byte, event *pb.ChaincodeEvent, visibility []byte, ccid *pb.ChaincodeID, txsim ledger.TxSimulator, cd *ccprovider.ChaincodeData) (*pb.ProposalResponse, error) { +func (e *Endorser) endorseProposal(ctx context.Context, chainID string, txid string, signedProp *pb.SignedProposal, proposal *pb.Proposal, response *pb.Response, simRes []byte, event *pb.ChaincodeEvent, visibility []byte, ccid *pb.ChaincodeID, txsim ledger.TxSimulator, cd *ccprovider.ChaincodeData) (*pb.ProposalResponse, error) { endorserLogger.Infof("endorseProposal starts for chainID %s, ccid %s", chainID, ccid) // 1) extract the name of the escc that is requested to endorse this chaincode @@ -242,7 +242,7 @@ func (e *Endorser) endorseProposal(ctx context.Context, chainID string, txid str args := [][]byte{[]byte(""), proposal.Header, proposal.Payload, resBytes, simRes, eventBytes, visibility} version := util.GetSysCCVersion() ecccis := &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_GOLANG, ChaincodeId: &pb.ChaincodeID{Name: escc}, Input: &pb.ChaincodeInput{Args: args}}} - res, _, err := e.callChaincode(ctx, chainID, version, txid, proposal, ecccis, &pb.ChaincodeID{Name: escc}, txsim) + res, _, err := e.callChaincode(ctx, chainID, version, txid, signedProp, proposal, ecccis, &pb.ChaincodeID{Name: escc}, txsim) if err != nil { return nil, err } @@ -335,7 +335,7 @@ func (e *Endorser) ProcessProposal(ctx context.Context, signedProp *pb.SignedPro // to validate the supplied action before endorsing it //1 -- simulate - cd, res, simulationResult, ccevent, err := e.simulateProposal(ctx, chainID, txid, prop, hdrExt.ChaincodeId, txsim) + cd, res, simulationResult, ccevent, err := e.simulateProposal(ctx, chainID, txid, signedProp, prop, hdrExt.ChaincodeId, txsim) if err != nil { return &pb.ProposalResponse{Response: &pb.Response{Status: 500, Message: err.Error()}}, err } @@ -348,7 +348,7 @@ func (e *Endorser) ProcessProposal(ctx context.Context, signedProp *pb.SignedPro if ischainless { pResp = &pb.ProposalResponse{Response: res} } else { - pResp, err = e.endorseProposal(ctx, chainID, txid, prop, res, simulationResult, ccevent, hdrExt.PayloadVisibility, hdrExt.ChaincodeId, txsim, cd) + pResp, err = e.endorseProposal(ctx, chainID, txid, signedProp, prop, res, simulationResult, ccevent, hdrExt.PayloadVisibility, hdrExt.ChaincodeId, txsim, cd) if err != nil { return &pb.ProposalResponse{Response: &pb.Response{Status: 500, Message: err.Error()}}, err } diff --git a/core/endorser/endorser_test.go b/core/endorser/endorser_test.go index 823255d1b3b..f9b974fa37e 100644 --- a/core/endorser/endorser_test.go +++ b/core/endorser/endorser_test.go @@ -278,7 +278,7 @@ func TestDeploy(t *testing.T) { spec := &pb.ChaincodeSpec{Type: 1, ChaincodeId: &pb.ChaincodeID{Name: "ex01", Path: "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example01", Version: "0"}, Input: &pb.ChaincodeInput{Args: [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}}} defer deleteChaincodeOnDisk("ex01.0") - cccid := ccprovider.NewCCContext(chainID, "ex01", "0", "", false, nil) + cccid := ccprovider.NewCCContext(chainID, "ex01", "0", "", false, nil, nil) _, _, err := deploy(endorserServer, chainID, spec, nil) if err != nil { @@ -299,7 +299,7 @@ func TestRedeploy(t *testing.T) { defer deleteChaincodeOnDisk("ex02.0") - cccid := ccprovider.NewCCContext(chainID, "ex02", "0", "", false, nil) + cccid := ccprovider.NewCCContext(chainID, "ex02", "0", "", false, nil, nil) _, _, err := deploy(endorserServer, chainID, spec, nil) if err != nil { @@ -338,7 +338,7 @@ func TestDeployAndInvoke(t *testing.T) { argsDeploy := util.ToChaincodeArgs(f, "a", "100", "b", "200") spec := &pb.ChaincodeSpec{Type: 1, ChaincodeId: chaincodeID, Input: &pb.ChaincodeInput{Args: argsDeploy}} - cccid := ccprovider.NewCCContext(chainID, "ex01", "0", "", false, nil) + cccid := ccprovider.NewCCContext(chainID, "ex01", "0", "", false, nil, nil) resp, prop, err := deploy(endorserServer, chainID, spec, nil) chaincodeID1 := spec.ChaincodeId.Name @@ -391,8 +391,8 @@ func TestDeployAndUpgrade(t *testing.T) { argsDeploy := util.ToChaincodeArgs(f, "a", "100", "b", "200") spec := &pb.ChaincodeSpec{Type: 1, ChaincodeId: chaincodeID1, Input: &pb.ChaincodeInput{Args: argsDeploy}} - cccid1 := ccprovider.NewCCContext(chainID, "upgradeex01", "0", "", false, nil) - cccid2 := ccprovider.NewCCContext(chainID, "upgradeex01", "1", "", false, nil) + cccid1 := ccprovider.NewCCContext(chainID, "upgradeex01", "0", "", false, nil, nil) + cccid2 := ccprovider.NewCCContext(chainID, "upgradeex01", "1", "", false, nil, nil) resp, prop, err := deploy(endorserServer, chainID, spec, nil) diff --git a/core/mocks/ccprovider/ccprovider.go b/core/mocks/ccprovider/ccprovider.go index 241fc26af7a..32fbc8d60dc 100644 --- a/core/mocks/ccprovider/ccprovider.go +++ b/core/mocks/ccprovider/ccprovider.go @@ -47,12 +47,12 @@ func (c *mockCcProviderImpl) GetContext(ledger ledger.PeerLedger) (context.Conte } // GetCCContext does nothing -func (c *mockCcProviderImpl) GetCCContext(cid, name, version, txid string, syscc bool, prop *peer.Proposal) interface{} { +func (c *mockCcProviderImpl) GetCCContext(cid, name, version, txid string, syscc bool, signedProp *peer.SignedProposal, prop *peer.Proposal) interface{} { return &mockCcProviderContextImpl{} } // GetCCValidationInfoFromLCCC does nothing -func (c *mockCcProviderImpl) GetCCValidationInfoFromLCCC(ctxt context.Context, txid string, prop *peer.Proposal, chainID string, chaincodeID string) (string, []byte, error) { +func (c *mockCcProviderImpl) GetCCValidationInfoFromLCCC(ctxt context.Context, txid string, signedProp *peer.SignedProposal, prop *peer.Proposal, chainID string, chaincodeID string) (string, []byte, error) { return "vscc", nil, nil } diff --git a/core/scc/sysccapi.go b/core/scc/sysccapi.go index 685712e0189..3ad32e6f770 100644 --- a/core/scc/sysccapi.go +++ b/core/scc/sysccapi.go @@ -118,7 +118,7 @@ func deploySysCC(chainID string, syscc *SystemChaincode) error { version := util.GetSysCCVersion() - cccid := ccprov.GetCCContext(chainID, chaincodeDeploymentSpec.ChaincodeSpec.ChaincodeId.Name, version, txid, true, nil) + cccid := ccprov.GetCCContext(chainID, chaincodeDeploymentSpec.ChaincodeSpec.ChaincodeId.Name, version, txid, true, nil, nil) _, _, err = ccprov.ExecuteWithErrorFilter(ctxt, cccid, chaincodeDeploymentSpec) @@ -145,7 +145,7 @@ func DeDeploySysCC(chainID string, syscc *SystemChaincode) error { version := util.GetSysCCVersion() - cccid := ccprov.GetCCContext(chainID, syscc.Name, version, "", true, nil) + cccid := ccprov.GetCCContext(chainID, syscc.Name, version, "", true, nil, nil) err = ccprov.Stop(ctx, cccid, chaincodeDeploymentSpec)