How to write fabric chaincode and How it work

code version: fabric 2.0.1

shim package is located in vendor/github.com/hyperledger/fabric-chaincode-go. It is a little old, we can get newer code in hyperledger/fabric-chaincode-go repo, which include CID package that we usually use to check permission in chaincode.

write chaincode

Take golang chaincode as example, The way to write fabric chaincode is almost as same as normal golang code. The key diffence is that syscall is prohibitive in chaincode, the storage of chaincode is actully located in peer, and put state and get data or so are implemented via grpc with peer. Also, grpc with peer is the only connection.

neccesary steps:
step1: implement chaincode interface
/ Chaincode interface must be implemented by all chaincodes. The fabric runs
// the transactions by calling these functions as specified.
type Chaincode interface {
	// Init is called during Instantiate transaction after the chaincode container
	// has been established for the first time, allowing the chaincode to
	// initialize its internal data
	Init(stub ChaincodeStubInterface) pb.Response

	// Invoke is called to update or query the ledger in a proposal transaction.
	// Updated state variables are not committed to the ledger until the
	// transaction is committed.
	Invoke(stub ChaincodeStubInterface) pb.Response
}
step2: use shim package to comnicate with peer via grpc for data storage
func main() {
	err := shim.Start(&SimpleChaincode{})
	if err != nil {
		startErrChan <- err
	}
}
example
// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct{}

func (t *SimpleChaincode) Init(stub ChaincodeStubInterface) pb.Response {}

func (t *SimpleChaincode) Invoke(stub ChaincodeStubInterface) pb.Response {}

func main() {
	err := shim.Start(&SimpleChaincode{})
	if err != nil {
		startErrChan <- err
	}
}
end

If you are intersted in the internal work mechanisms of chaincode, you should continue.

All chaincode message are handled by handler, which located in shim package above.

handler

// Handler handler implementation for shim side of chaincode.
type Handler struct {
	// serialLock is used to prevent concurrent calls to Send on the
	// PeerChaincodeStream. This is required by gRPC.
	serialLock sync.Mutex
	// chatStream is the client used to access the chaincode support server on
	// the peer.
	chatStream PeerChaincodeStream

	// cc is the chaincode associated with this handler.
	cc Chaincode
	// state holds the current state of this handler.
	state state

	// Multiple queries (and one transaction) with different txids can be executing in parallel for this chaincode
	// responseChannels is the channel on which responses are communicated by the shim to the chaincodeStub.
	// need lock to protect chaincode from attempting
	// concurrent requests to the peer
	responseChannelsMutex sync.Mutex
	responseChannels      map[string]chan pb.ChaincodeMessage
}

chatStream used to send and recv through stream.

cc is chaincode, we can invoke Init() and Invoke() in our chaincode through it.

responseChannels is the channel which waits for the response from peer to arrive on, it will be handled by handler.handleResponse(). The result of response maybe response or error. the former means success, and will follow resp payload for chaincode stub.get operatrion.

state is used to register stream. There are three state: “created”, “established” and “ready”.

When new handler, state is “created”. Regardless of chaincode act as a client or server, state will turn to “established” when receive registered message from peer after chatWithPeer() send register message in order to register stream, then turn to “ready” after receive ready message from peer.

Peer and chaincode can communicate normally until state is “ready”. message type will be introduced below.

we will discuss in another blobs with respect to state and handler register.

PeerChaincodeStream

PeerChaincodeStream has two implements: as client and as server. We often use client pattern. the server pattern is newly added in v2.0.

// PeerChaincodeStream is the common stream interface for Peer - chaincode communication.
// Both chaincode-as-server and chaincode-as-client patterns need to support this
type PeerChaincodeStream interface {
	Send(*pb.ChaincodeMessage) error
	Recv() (*pb.ChaincodeMessage, error)
}

message

the usage of message REGISTER/REGISTERED/READY is introduced above, you can review it if forgot.

When chaincode receive message INIT, handler will init chaincode though handler.cc.Init(). If success, response message COMPLETED.

When chaincode receive message TRANSACTION, handler will invoke chaincode invoke() thouhr handler.cc.Invoke(). If success, response message COMPLETED.

Other message is used by stub.GetState(), stub.PutState() and so on.

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
)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值