fabric 2.0, chaincode execution


First of all, it is executed via endorser ProcessProposal service. The endorser will then try to invoke the chaincode, inccluding:

  • Start the CC container if need
  • Set up the stream handler registration
  • Pass MSG with Transaction
  • Handle the response from CC, until Completed indication received
  • Notify endorser the job done. 30s timeout by default

endorser ProcessProposal

endorser will try to invoke chaincode by calling callChaincode(), which will then invoke chaincode for execution.

github.com/hyperledger/fabric/core/chaincode.(*ChaincodeSupport).Invoke at chaincode_support.go:197
github.com/hyperledger/fabric/core/chaincode.(*ChaincodeSupport).Execute at chaincode_support.go:155
github.com/hyperledger/fabric/core/endorser.(*SupportImpl).Execute at support.go:126
github.com/hyperledger/fabric/core/endorser.(*Endorser).callChaincode at endorser.go:119
github.com/hyperledger/fabric/core/endorser.(*Endorser).SimulateProposal at endorser.go:187
github.com/hyperledger/fabric/core/endorser.(*Endorser).ProcessProposalSuccessfullyOrError at endorser.go:397
github.com/hyperledger/fabric/core/endorser.(*Endorser).ProcessProposal at endorser.go:340
github.com/hyperledger/fabric/core/handlers/auth/filter.(*expirationCheckFilter).ProcessProposal at expiration.go:61
github.com/hyperledger/fabric/core/handlers/auth/filter.(*filter).ProcessProposal at filter.go:32
github.com/hyperledger/fabric/vendor/github.com/hyperledger/fabric-protos-go/peer._Endorser_ProcessProposal_Handler.func1 at peer.pb.go:107
github.com/hyperledger/fabric/internal/peer/node.unaryGrpcLimiter.func1 at grpc_limiters.go:51
github.com/hyperledger/fabric/vendor/github.com/grpc-ecosystem/go-grpc-middleware.ChainUnaryServer.func1.1.1 at chain.go:25
github.com/hyperledger/fabric/common/grpclogging.UnaryServerInterceptor.func1 at server.go:92
github.com/hyperledger/fabric/vendor/github.com/grpc-ecosystem/go-grpc-middleware.ChainUnaryServer.func1.1.1 at chain.go:25
github.com/hyperledger/fabric/common/grpcmetrics.UnaryServerInterceptor.func1 at interceptor.go:31
github.com/hyperledger/fabric/vendor/github.com/grpc-ecosystem/go-grpc-middleware.ChainUnaryServer.func1.1.1 at chain.go:25
github.com/hyperledger/fabric/vendor/github.com/grpc-ecosystem/go-grpc-middleware.ChainUnaryServer.func1 at chain.go:34
github.com/hyperledger/fabric/vendor/github.com/hyperledger/fabric-protos-go/peer._Endorser_ProcessProposal_Handler at peer.pb.go:109
github.com/hyperledger/fabric/vendor/google.golang.org/grpc.(*Server).processUnaryRPC at server.go:995
github.com/hyperledger/fabric/vendor/google.golang.org/grpc.(*Server).handleStream at server.go:1275
github.com/hyperledger/fabric/vendor/google.golang.org/grpc.(*Server).serveStreams.func1.1 at server.go:710
runtime.goexit at asm_amd64.s:1357
 - Async stack trace
github.com/hyperledger/fabric/vendor/google.golang.org/grpc.(*Server).serveStreams.func1 at server.go:708

Launch CC

Look into chaincode.Invoke, we can see it will launch the chaincode if it is not running.

// 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, chaincodeName string, input *pb.ChaincodeInput) (*pb.ChaincodeMessage, error) {
	ccid, cctype, err := cs.CheckInvocation(txParams, chaincodeName, input)
	if err != nil {
		return nil, errors.WithMessage(err, "invalid invocation")
	}

	h, err := cs.Launch(ccid)
	if err != nil {
		return nil, err
	}

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

Check the launching, it will try CC server model, or start client model.


func (r *RuntimeLauncher) Launch(ccid string, streamHandler extcc.StreamHandler) error {
	var startFailCh chan error
	var timeoutCh <-chan time.Time

	startTime := time.Now()
	launchState, alreadyStarted := r.Registry.Launching(ccid)
	if !alreadyStarted {
		startFailCh = make(chan error, 1)
		timeoutCh = time.NewTimer(r.StartupTimeout).C

		go func() {
			// go through the build process to obtain connecion information
			ccservinfo, err := r.Runtime.Build(ccid)
			if err != nil {
				startFailCh <- errors.WithMessage(err, "error building chaincode")
				return
			}

			// chaincode server model indicated... proceed to connect to CC
			if ccservinfo != nil {
				if err = r.ConnectionHandler.Stream(ccid, ccservinfo, streamHandler); err != nil {
					startFailCh <- errors.WithMessagef(err, "connection to %s failed", ccid)
					return
				}

				launchState.Notify(errors.Errorf("connection to %s terminated", ccid))
				return
			}

			// default peer-as-server model... compute connection information for CC callback
			// and proceed to launch chaincode
			ccinfo, err := r.ChaincodeClientInfo(ccid)
			if err != nil {
				startFailCh <- errors.WithMessage(err, "could not get connection info")
				return
			}
			if ccinfo == nil {
				startFailCh <- errors.New("could not get connection info")
				return
			}
			if err = r.Runtime.Start(ccid, ccinfo); err != nil {
				startFailCh <- errors.WithMessage(err, "error starting container")
				return
			}
			exitCode, err := r.Runtime.Wait(ccid)
			if err != nil {
				launchState.Notify(errors.Wrap(err, "failed to wait on container exit"))
			}
			launchState.Notify(errors.Errorf("container exited with %d", exitCode))
		}()
	}

	var err error
	select {
	case <-launchState.Done():
		err = errors.WithMessage(launchState.Err(), "chaincode registration failed")
	case err = <-startFailCh:
		launchState.Notify(err)
		r.Metrics.LaunchFailures.With("chaincode", ccid).Add(1)
	case <-timeoutCh:
		err = errors.Errorf("timeout expired while starting chaincode %s for transaction", ccid)
		launchState.Notify(err)
		r.Metrics.LaunchTimeouts.With("chaincode", ccid).Add(1)
	}

	success := true
	if err != nil && !alreadyStarted {
		success = false
		chaincodeLogger.Debugf("stopping due to error while launching: %+v", err)
		defer r.Registry.Deregister(ccid)
	}

	r.Metrics.LaunchDuration.With(
		"chaincode", ccid,
		"success", strconv.FormatBool(success),
	).Observe(time.Since(startTime).Seconds())

	chaincodeLogger.Debug("launch complete")
	return err
}

When CC is launched, it will be started with argument ‘chaincode -peer.address 1.2.3.4:7052’, which indicates CC in Container should set up a gRPC connection to endorser immediately.

CC register

Therefore, peer side will get the gRPC from chaincode container. In this case, the handler is newly created, so its state is ‘Created’, and the first message is ChaincodeMessage_REGISTER. It will eventaully call HandleRegister() to register the CC. As a result, Message ChaincodeMessage_REGISTERED and ChaincodeMessage_READY wil be sent back to CC.

//ChaincodeSupport Handler state:
const (
	Created State = iota
	Established
	Ready
)
// Message Types
const (
	ChaincodeMessage_UNDEFINED             ChaincodeMessage_Type = 0
	ChaincodeMessage_REGISTER              ChaincodeMessage_Type = 1
	ChaincodeMessage_REGISTERED            ChaincodeMessage_Type = 2
	ChaincodeMessage_INIT                  ChaincodeMessage_Type = 3
	ChaincodeMessage_READY                 ChaincodeMessage_Type = 4
	ChaincodeMessage_TRANSACTION           ChaincodeMessage_Type = 5
	ChaincodeMessage_COMPLETED             ChaincodeMessage_Type = 6
	ChaincodeMessage_ERROR                 ChaincodeMessage_Type = 7
	ChaincodeMessage_GET_STATE             ChaincodeMessage_Type = 8
	ChaincodeMessage_PUT_STATE             ChaincodeMessage_Type = 9
	ChaincodeMessage_DEL_STATE             ChaincodeMessage_Type = 10
	ChaincodeMessage_INVOKE_CHAINCODE      ChaincodeMessage_Type = 11
	ChaincodeMessage_RESPONSE              ChaincodeMessage_Type = 13
	ChaincodeMessage_GET_STATE_BY_RANGE    ChaincodeMessage_Type = 14
	ChaincodeMessage_GET_QUERY_RESULT      ChaincodeMessage_Type = 15
	ChaincodeMessage_QUERY_STATE_NEXT      ChaincodeMessage_Type = 16
	ChaincodeMessage_QUERY_STATE_CLOSE     ChaincodeMessage_Type = 17
	ChaincodeMessage_KEEPALIVE             ChaincodeMessage_Type = 18
	ChaincodeMessage_GET_HISTORY_FOR_KEY   ChaincodeMessage_Type = 19
	ChaincodeMessage_GET_STATE_METADATA    ChaincodeMessage_Type = 20
	ChaincodeMessage_PUT_STATE_METADATA    ChaincodeMessage_Type = 21
	ChaincodeMessage_GET_PRIVATE_DATA_HASH ChaincodeMessage_Type = 22
)
github.com/hyperledger/fabric/core/chaincode.(*Handler).HandleRegister at handler.go:486
github.com/hyperledger/fabric/core/chaincode.(*Handler).handleMessageCreatedState at handler.go:167
github.com/hyperledger/fabric/core/chaincode.(*Handler).handleMessage at handler.go:156
github.com/hyperledger/fabric/core/chaincode.(*Handler).ProcessStream at handler.go:403
github.com/hyperledger/fabric/core/chaincode.(*ChaincodeSupport).HandleChaincodeStream at chaincode_support.go:125
github.com/hyperledger/fabric/core/chaincode.(*ChaincodeSupport).Register at chaincode_support.go:130
github.com/hyperledger/fabric/vendor/github.com/hyperledger/fabric-protos-go/peer._ChaincodeSupport_Register_Handler at chaincode_shim.pb.go:1169
github.com/hyperledger/fabric/vendor/google.golang.org/grpc.(*Server).processStreamingRPC at server.go:1199
github.com/hyperledger/fabric/vendor/google.golang.org/grpc.(*Server).handleStream at server.go:1279
github.com/hyperledger/fabric/vendor/google.golang.org/grpc.(*Server).serveStreams.func1.1 at server.go:710
runtime.goexit at asm_amd64.s:1357
 - Async stack trace
github.com/hyperledger/fabric/vendor/google.golang.org/grpc.(*Server).serveStreams.func1 at server.go:708

Chaincode invocation

When CC is ready, ChaincodeMessage_TRANSACTION will be sent to CC container side.

CC as client:

Client endorser CC Handler Invoke CC Start CC with peer.address gRPC establishment, Register HandleRegister Registered Ready Transaction Put_State Response Put_State Response Completed Notify, tctx.ResponseNotifier Response Client endorser CC Handler
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值