Skip to content

Commit

Permalink
FAB-11037 Remove InvocationSpec from chaincode pkg
Browse files Browse the repository at this point in the history
This CR finally completes removing the legacy data "ChaincodeSpec"
structures from the non-shim related pieces of the chaincode package.
To maintain compatibility with the existing chaincode images, the
ChaincodeSpec still exists in the handler path, and to maintain
compatibility with the legacy lifecycle, a single deployment spec
acceing execute method is available.  Both of these should be removed in
time.

Change-Id: I5659695a55e0947a1ccec23721192a4c88177b38
Signed-off-by: Jason Yellick <jyellick@us.ibm.com>
  • Loading branch information
Jason Yellick committed Jul 16, 2018
1 parent 354c924 commit 1fe243f
Show file tree
Hide file tree
Showing 14 changed files with 144 additions and 140 deletions.
10 changes: 5 additions & 5 deletions core/chaincode/ccproviderimpl.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ func NewProvider(cs *ChaincodeSupport) *CCProviderImpl {
}

// Execute executes the chaincode given context and spec (invocation or deploy)
func (c *CCProviderImpl) Execute(txParams *ccprovider.TransactionParams, cccid *ccprovider.CCContext, spec *pb.ChaincodeInvocationSpec) (*pb.Response, *pb.ChaincodeEvent, error) {
return c.cs.Execute(txParams, cccid, spec)
func (c *CCProviderImpl) Execute(txParams *ccprovider.TransactionParams, cccid *ccprovider.CCContext, input *pb.ChaincodeInput) (*pb.Response, *pb.ChaincodeEvent, error) {
return c.cs.Execute(txParams, cccid, input)
}

// ExecuteInit executes the chaincode given context and spec (invocation or deploy)
func (c *CCProviderImpl) ExecuteInit(txParams *ccprovider.TransactionParams, cccid *ccprovider.CCContext, spec *pb.ChaincodeDeploymentSpec) (*pb.Response, *pb.ChaincodeEvent, error) {
return c.cs.ExecuteInit(txParams, cccid, spec)
// ExecuteLegacyInit executes a chaincode which is not in the LSCC table
func (c *CCProviderImpl) ExecuteLegacyInit(txParams *ccprovider.TransactionParams, cccid *ccprovider.CCContext, spec *pb.ChaincodeDeploymentSpec) (*pb.Response, *pb.ChaincodeEvent, error) {
return c.cs.ExecuteLegacyInit(txParams, cccid, spec)
}

// Stop stops the chaincode given context and spec
Expand Down
114 changes: 59 additions & 55 deletions core/chaincode/chaincode_support.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,10 @@ func (cs *ChaincodeSupport) LaunchInit(ccci *ccprovider.ChaincodeContainerInfo)
// Launch starts executing chaincode if it is not already running. This method
// blocks until the peer side handler gets into ready state or encounters a fatal
// error. If the chaincode is already running, it simply returns.
func (cs *ChaincodeSupport) Launch(chainID, chaincodeName, chaincodeVersion string) error {
func (cs *ChaincodeSupport) Launch(chainID, chaincodeName, chaincodeVersion string) (*Handler, error) {
cname := chaincodeName + ":" + chaincodeVersion
if cs.HandlerRegistry.Handler(cname) != nil {
return nil
if h := cs.HandlerRegistry.Handler(cname); h != nil {
return h, nil
}

ccci, err := cs.Lifecycle.ChaincodeContainerInfo(chainID, chaincodeName)
Expand All @@ -137,10 +137,19 @@ func (cs *ChaincodeSupport) Launch(chainID, chaincodeName, chaincodeVersion stri
)
}

return errors.Wrapf(err, "[channel %s] failed to get chaincode container info for %s", chainID, cname)
return nil, errors.Wrapf(err, "[channel %s] failed to get chaincode container info for %s", chainID, cname)
}

return cs.Launcher.Launch(ccci)
if err := cs.Launcher.Launch(ccci); err != nil {
return nil, errors.Wrapf(err, "[channel %s] could not launch chaincode %s", chainID, cname)
}

h := cs.HandlerRegistry.Handler(cname)
if h == nil {
return nil, errors.Wrapf(err, "[channel %s] claimed to start chaincode container for %s but could not find handler", chainID, cname)
}

return h, nil
}

// Stop stops a chaincode if running.
Expand Down Expand Up @@ -194,15 +203,32 @@ func createCCMessage(messageType pb.ChaincodeMessage_Type, cid string, txid stri
return ccmsg, nil
}

// Execute init invokes chaincode and returns the original response.
func (cs *ChaincodeSupport) ExecuteInit(txParams *ccprovider.TransactionParams, cccid *ccprovider.CCContext, spec *pb.ChaincodeDeploymentSpec) (*pb.Response, *pb.ChaincodeEvent, error) {
resp, err := cs.InvokeInit(txParams, cccid, spec)
// ExecuteLegacyInit is a temporary method which should be removed once the old style lifecycle
// is entirely deprecated. Ideally one release after the introduction of the new lifecycle.
// It does not attempt to start the chaincode based on the information from lifecycle, but instead
// accepts the container information directly in the form of a ChaincodeDeploymentSpec.
func (cs *ChaincodeSupport) ExecuteLegacyInit(txParams *ccprovider.TransactionParams, cccid *ccprovider.CCContext, spec *pb.ChaincodeDeploymentSpec) (*pb.Response, *pb.ChaincodeEvent, error) {
ccci := ccprovider.DeploymentSpecToChaincodeContainerInfo(spec)
ccci.Version = cccid.Version

err := cs.LaunchInit(ccci)
if err != nil {
return nil, nil, err
}

cname := ccci.Name + ":" + ccci.Version
h := cs.HandlerRegistry.Handler(cname)
if h == nil {
return nil, nil, errors.Wrapf(err, "[channel %s] claimed to start chaincode container for %s but could not find handler", txParams.ChannelID, cname)
}

resp, err := cs.execute(pb.ChaincodeMessage_INIT, txParams, cccid, spec.GetChaincodeSpec().Input, h)
return processChaincodeExecutionResult(txParams.TxID, cccid.Name, resp, err)
}

// Execute invokes chaincode and returns the original response.
func (cs *ChaincodeSupport) Execute(txParams *ccprovider.TransactionParams, cccid *ccprovider.CCContext, spec *pb.ChaincodeInvocationSpec) (*pb.Response, *pb.ChaincodeEvent, error) {
resp, err := cs.Invoke(txParams, cccid, spec)
func (cs *ChaincodeSupport) Execute(txParams *ccprovider.TransactionParams, cccid *ccprovider.CCContext, input *pb.ChaincodeInput) (*pb.Response, *pb.ChaincodeEvent, error) {
resp, err := cs.Invoke(txParams, cccid, input)
return processChaincodeExecutionResult(txParams.TxID, cccid.Name, resp, err)
}

Expand Down Expand Up @@ -236,69 +262,47 @@ func processChaincodeExecutionResult(txid, ccName string, resp *pb.ChaincodeMess
}
}

func (cs *ChaincodeSupport) InvokeInit(txParams *ccprovider.TransactionParams, cccid *ccprovider.CCContext, spec *pb.ChaincodeDeploymentSpec) (*pb.ChaincodeMessage, error) {
cctyp := pb.ChaincodeMessage_INIT

ccci := ccprovider.DeploymentSpecToChaincodeContainerInfo(spec)
ccci.Version = cccid.Version

err := cs.LaunchInit(ccci)
func (cs *ChaincodeSupport) InvokeInit(txParams *ccprovider.TransactionParams, cccid *ccprovider.CCContext, input *pb.ChaincodeInput) (*pb.ChaincodeMessage, error) {
h, err := cs.Launch(txParams.ChannelID, cccid.Name, cccid.Version)
if err != nil {
return nil, err
}

chaincodeSpec := spec.GetChaincodeSpec()
if chaincodeSpec == nil {
return nil, errors.New("chaincode spec is nil")
}

input := chaincodeSpec.Input
input.Decorations = txParams.ProposalDecorations
ccMsg, err := createCCMessage(cctyp, txParams.ChannelID, txParams.TxID, input)
if err != nil {
return nil, errors.WithMessage(err, "failed to create chaincode message")
}

return cs.execute(txParams, cccid, ccMsg)
return cs.execute(pb.ChaincodeMessage_INIT, txParams, cccid, input, h)
}

// Invoke will invoke chaincode and return the message containing the response.
// The chaincode will be launched if it is not already running.
func (cs *ChaincodeSupport) Invoke(txParams *ccprovider.TransactionParams, cccid *ccprovider.CCContext, spec *pb.ChaincodeInvocationSpec) (*pb.ChaincodeMessage, error) {
cctyp := pb.ChaincodeMessage_TRANSACTION

chaincodeSpec := spec.GetChaincodeSpec()
if chaincodeSpec == nil {
return nil, errors.New("chaincode spec is nil")
}

err := cs.Launch(txParams.ChannelID, chaincodeSpec.Name(), cccid.Version)
func (cs *ChaincodeSupport) Invoke(txParams *ccprovider.TransactionParams, cccid *ccprovider.CCContext, input *pb.ChaincodeInput) (*pb.ChaincodeMessage, error) {
h, err := cs.Launch(txParams.ChannelID, cccid.Name, cccid.Version)
if err != nil {
return nil, err
}

input := chaincodeSpec.Input
// TODO add Init exactly once semantics here once new lifecycle
// is available. Enforced if the target channel is using the new lifecycle
//
// First, the function name of the chaincode to invoke should be checked. If it is
// "init", then consider this invocation to be of type pb.ChaincodeMessage_INIT,
// otherwise consider it to be of type pb.ChaincodeMessage_TRANSACTION,
//
// Secondly, A check should be made whether the chaincode has been
// inited, then, if true, only allow cctyp pb.ChaincodeMessage_TRANSACTION,
// otherwise, only allow cctype pb.ChaincodeMessage_INIT,
cctype := pb.ChaincodeMessage_TRANSACTION

return cs.execute(cctype, txParams, cccid, input, h)
}

// execute executes a transaction and waits for it to complete until a timeout value.
func (cs *ChaincodeSupport) execute(cctyp pb.ChaincodeMessage_Type, txParams *ccprovider.TransactionParams, cccid *ccprovider.CCContext, input *pb.ChaincodeInput, h *Handler) (*pb.ChaincodeMessage, error) {
input.Decorations = txParams.ProposalDecorations
ccMsg, err := createCCMessage(cctyp, txParams.ChannelID, txParams.TxID, input)
if err != nil {
return nil, errors.WithMessage(err, "failed to create chaincode message")
}

return cs.execute(txParams, cccid, ccMsg)
}

// execute executes a transaction and waits for it to complete until a timeout value.
func (cs *ChaincodeSupport) execute(txParams *ccprovider.TransactionParams, cccid *ccprovider.CCContext, msg *pb.ChaincodeMessage) (*pb.ChaincodeMessage, error) {
cname := cccid.GetCanonicalName()
chaincodeLogger.Debugf("canonical name: %s", cname)

handler := cs.HandlerRegistry.Handler(cname)
if handler == nil {
chaincodeLogger.Debugf("chaincode is not running: %s", cname)
return nil, errors.Errorf("unable to invoke chaincode %s", cname)
}

ccresp, err := handler.Execute(txParams, cccid, msg, cs.ExecuteTimeout)
ccresp, err := h.Execute(txParams, cccid, ccMsg, cs.ExecuteTimeout)
if err != nil {
return nil, errors.WithMessage(err, fmt.Sprintf("error sending"))
}
Expand Down
4 changes: 2 additions & 2 deletions core/chaincode/chaincode_support_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ func endTx(t *testing.T, txParams *ccprovider.TransactionParams, txsim ledger.Tx
func execCC(t *testing.T, txParams *ccprovider.TransactionParams, ccSide *mockpeer.MockCCComm, cccid *ccprovider.CCContext, waitForERROR bool, expectExecErr bool, done chan error, cis *pb.ChaincodeInvocationSpec, respSet *mockpeer.MockResponseSet, chaincodeSupport *ChaincodeSupport) error {
ccSide.SetResponses(respSet)

resp, _, err := chaincodeSupport.Execute(txParams, cccid, cis)
resp, _, err := chaincodeSupport.Execute(txParams, cccid, cis.ChaincodeSpec.Input)
if err == nil && resp.Status != shim.OK {
err = errors.New(resp.Message)
}
Expand Down Expand Up @@ -411,7 +411,7 @@ func deployCC(t *testing.T, txParams *ccprovider.TransactionParams, cccid *ccpro
}

//write to lscc
if _, _, err := chaincodeSupport.Execute(txParams, lsccid, lsccSpec); err != nil {
if _, _, err := chaincodeSupport.Execute(txParams, lsccid, lsccSpec.ChaincodeSpec.Input); err != nil {
t.Fatalf("Error deploying chaincode %v (err: %s)", cccid, err)
}
}
Expand Down
6 changes: 3 additions & 3 deletions core/chaincode/exectransaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -455,12 +455,12 @@ func deploy2(chainID string, cccid *ccprovider.CCContext, chaincodeDeploymentSpe
}

//write to lscc
if _, _, err = chaincodeSupport.Execute(txParams, lsccid, cis); err != nil {
if _, _, err = chaincodeSupport.Execute(txParams, lsccid, cis.ChaincodeSpec.Input); err != nil {
return nil, fmt.Errorf("Error deploying chaincode (1): %s", err)
}

var resp *pb.Response
if resp, _, err = chaincodeSupport.ExecuteInit(txParams, cccid, chaincodeDeploymentSpec); err != nil {
if resp, _, err = chaincodeSupport.ExecuteLegacyInit(txParams, cccid, chaincodeDeploymentSpec); err != nil {
return nil, fmt.Errorf("Error deploying chaincode(2): %s", err)
}

Expand Down Expand Up @@ -513,7 +513,7 @@ func invokeWithVersion(chainID string, version string, spec *pb.ChaincodeSpec, b
Proposal: prop,
}

resp, ccevt, err = chaincodeSupport.Execute(txParams, cccid, cdInvocationSpec)
resp, ccevt, err = chaincodeSupport.Execute(txParams, cccid, cdInvocationSpec.ChaincodeSpec.Input)
if err != nil {
return nil, uuid, nil, fmt.Errorf("Error invoking chaincode: %s", err)
}
Expand Down
5 changes: 2 additions & 3 deletions core/chaincode/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ type Registry interface {

// An Invoker invokes chaincode.
type Invoker interface {
Invoke(txParams *ccprovider.TransactionParams, cccid *ccprovider.CCContext, spec *pb.ChaincodeInvocationSpec) (*pb.ChaincodeMessage, error)
Invoke(txParams *ccprovider.TransactionParams, cccid *ccprovider.CCContext, spec *pb.ChaincodeInput) (*pb.ChaincodeMessage, error)
}

// SystemCCProvider provides system chaincode metadata.
Expand Down Expand Up @@ -881,10 +881,9 @@ func (h *Handler) HandleInvokeChaincode(msg *pb.ChaincodeMessage, txContext *Tra
Name: targetInstance.ChaincodeName,
Version: version,
}
cciSpec := &pb.ChaincodeInvocationSpec{ChaincodeSpec: chaincodeSpec}

// Execute the chaincode... this CANNOT be an init at least for now
responseMessage, err := h.Invoker.Invoke(txParams, cccid, cciSpec)
responseMessage, err := h.Invoker.Invoke(txParams, cccid, chaincodeSpec.Input)
if err != nil {
return nil, errors.Wrap(err, "execute failed")
}
Expand Down
2 changes: 1 addition & 1 deletion core/chaincode/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1503,7 +1503,7 @@ var _ = Describe("Handler", func() {
})

It("marks the new transaction simulator as done after execute", func() {
fakeInvoker.InvokeStub = func(*ccprovider.TransactionParams, *ccprovider.CCContext, *pb.ChaincodeInvocationSpec) (*pb.ChaincodeMessage, error) {
fakeInvoker.InvokeStub = func(*ccprovider.TransactionParams, *ccprovider.CCContext, *pb.ChaincodeInput) (*pb.ChaincodeMessage, error) {
Expect(newTxSimulator.DoneCallCount()).To(Equal(0))
return responseMessage, nil
}
Expand Down
10 changes: 5 additions & 5 deletions core/chaincode/mock/invoker.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions core/common/ccprovider/ccprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -490,10 +490,11 @@ type TransactionParams struct {
// chaincode package without importing it; more methods
// should be added below if necessary
type ChaincodeProvider interface {
// Execute executes the chaincode given context and spec (invocation or deploy)
Execute(txParams *TransactionParams, cccid *CCContext, spec *pb.ChaincodeInvocationSpec) (*pb.Response, *pb.ChaincodeEvent, error)
// ExecuteInit is a special case for executing chaincode deployment specs, needed for old lifecycle
ExecuteInit(txParams *TransactionParams, cccid *CCContext, spec *pb.ChaincodeDeploymentSpec) (*pb.Response, *pb.ChaincodeEvent, error)
// Execute executes a standard chaincode invocation for a chaincode and an input
Execute(txParams *TransactionParams, cccid *CCContext, input *pb.ChaincodeInput) (*pb.Response, *pb.ChaincodeEvent, error)
// ExecuteLegacyInit is a special case for executing chaincode deployment specs,
// which are not already in the LSCC, needed for old lifecycle
ExecuteLegacyInit(txParams *TransactionParams, cccid *CCContext, spec *pb.ChaincodeDeploymentSpec) (*pb.Response, *pb.ChaincodeEvent, error)
// Stop stops the chaincode give
Stop(ccci *ChaincodeContainerInfo) error
}
Expand Down
Loading

0 comments on commit 1fe243f

Please sign in to comment.