Fabric 1.0原始碼分析(3)Chaincode(鏈碼)
# Fabric 1.0原始碼筆記 之 Chaincode(鏈碼) #ChaincodeSupport(鏈碼支援服務端)
## 1、ChaincodeSupport概述
ChaincodeSupport相關程式碼分佈在protos/peer/chaincode_shim.pb.go和core/chaincode目錄。
* protos/peer/chaincode_shim.pb.go,ChaincodeSupportServer介面定義。
* core/chaincode目錄:
* chaincode_support.go,ChaincodeSupportServer介面實現,即ChaincodeSupport結構體及方法,以及ChaincodeSupport服務端Register處理流程。
* handler.go,HandleMessage介面定義及實現。
## 2、ChaincodeSupportServer介面定義
### 2.1、ChaincodeSupportServer介面定義
```go
type ChaincodeSupportServer interface {
Register(ChaincodeSupport_RegisterServer) error
}
//程式碼在protos/peer/chaincode_shim.pb.go
```
### 2.2、gRPC相關實現
```go
var _ChaincodeSupport_serviceDesc = grpc.ServiceDesc{
ServiceName: "protos.ChaincodeSupport",
HandlerType: (*ChaincodeSupportServer)(nil),
Methods: []grpc.MethodDesc{},
Streams: []grpc.StreamDesc{
{
StreamName: "Register",
Handler: _ChaincodeSupport_Register_Handler,
ServerStreams: true,
ClientStreams: true,
},
},
Metadata: "peer/chaincode_shim.proto",
}
func RegisterChaincodeSupportServer(s *grpc.Server, srv ChaincodeSupportServer) {
s.RegisterService(&_ChaincodeSupport_serviceDesc, srv)
}
func _ChaincodeSupport_Register_Handler(srv interface{}, stream grpc.ServerStream) error {
return srv.(ChaincodeSupportServer).Register(&chaincodeSupportRegisterServer{stream})
}
//程式碼在protos/peer/chaincode_shim.pb.go
```
## 3、ChaincodeSupportServer介面實現
### 3.1、ChaincodeSupport結構體定義
```go
type ChaincodeSupport struct {
runningChaincodes *runningChaincodes
peerAddress string
ccStartupTimeout time.Duration
peerNetworkID string
peerID string
peerTLSCertFile string
peerTLSKeyFile string
peerTLSSvrHostOrd string
keepalive time.Duration
chaincodeLogLevel string
shimLogLevel string
logFormat string
executetimeout time.Duration
userRunsCC bool
peerTLS bool
}
//全域性變數定義
var theChaincodeSupport *ChaincodeSupport
//獲取theChaincodeSupport
func GetChain() *ChaincodeSupport
//構造ChaincodeSupport並賦值給theChaincodeSupport
func NewChaincodeSupport(getCCEndpoint func() (*pb.PeerEndpoint, error), userrunsCC bool, ccstartuptimeout time.Duration) *ChaincodeSupport
//程式碼在core/chaincode/chaincode_support.go
```
### 3.2、ChaincodeSupport結構體方法
```go
//呼叫chaincodeSupport.HandleChaincodeStream(stream.Context(), stream)
func (chaincodeSupport *ChaincodeSupport) Register(stream pb.ChaincodeSupport_RegisterServer) error
func getTxSimulator(context context.Context) ledger.TxSimulator
func getHistoryQueryExecutor(context context.Context) ledger.HistoryQueryExecutor
func GetChain() *ChaincodeSupport
func (chaincodeSupport *ChaincodeSupport) preLaunchSetup(chaincode string) chan bool
func (chaincodeSupport *ChaincodeSupport) chaincodeHasBeenLaunched(chaincode string) (*chaincodeRTEnv, bool)
func (chaincodeSupport *ChaincodeSupport) launchStarted(chaincode string) bool
func NewChaincodeSupport(getCCEndpoint func() (*pb.PeerEndpoint, error), userrunsCC bool, ccstartuptimeout time.Duration) *ChaincodeSupport
func getLogLevelFromViper(module string) string
func (d *DuplicateChaincodeHandlerError) Error() string
func newDuplicateChaincodeHandlerError(chaincodeHandler *Handler) error
func (chaincodeSupport *ChaincodeSupport) registerHandler(chaincodehandler *Handler) error
func (chaincodeSupport *ChaincodeSupport) deregisterHandler(chaincodehandler *Handler) error
func (chaincodeSupport *ChaincodeSupport) sendReady(context context.Context, cccid *ccprovider.CCContext, timeout time.Duration) error
func (chaincodeSupport *ChaincodeSupport) getArgsAndEnv(cccid *ccprovider.CCContext, cLang pb.ChaincodeSpec_Type) (args []string, envs []string, err error)
func (chaincodeSupport *ChaincodeSupport) launchAndWaitForRegister(ctxt context.Context, cccid *ccprovider.CCContext, cds *pb.ChaincodeDeploymentSpec, cLang pb.ChaincodeSpec_Type, builder api.BuildSpecFactory) error
func (chaincodeSupport *ChaincodeSupport) Stop(context context.Context, cccid *ccprovider.CCContext, cds *pb.ChaincodeDeploymentSpec) error
func (chaincodeSupport *ChaincodeSupport) Launch(context context.Context, cccid *ccprovider.CCContext, spec interface{}) (*pb.ChaincodeID, *pb.ChaincodeInput, error)
func (chaincodeSupport *ChaincodeSupport) getVMType(cds *pb.ChaincodeDeploymentSpec) (string, error)
//呼叫HandleChaincodeStream(chaincodeSupport, ctxt, stream)
func (chaincodeSupport *ChaincodeSupport) HandleChaincodeStream(ctxt context.Context, stream ccintf.ChaincodeStream) error
func createCCMessage(typ pb.ChaincodeMessage_Type, txid string, cMsg *pb.ChaincodeInput) (*pb.ChaincodeMessage, error)
func (chaincodeSupport *ChaincodeSupport) Execute(ctxt context.Context, cccid *ccprovider.CCContext, msg *pb.ChaincodeMessage, timeout time.Duration) (*pb.ChaincodeMessage, error)
func IsDevMode() bool
//程式碼在core/chaincode/chaincode_support.go
```
### 3.3、ChaincodeSupport服務端Register處理流程
即接收和處理ChaincodeMessage。
#### 3.3.1、構造Handler
```go
//構造Handler
handler := newChaincodeSupportHandler(chaincodeSupport, stream)
return handler.processStream() //下文展開介紹
//程式碼在core/chaincode/handler.go
```
handler := newChaincodeSupportHandler(chaincodeSupport, stream)程式碼如下:
此處使用了狀態機包,github.com/looplab/fsm。
```go
func newChaincodeSupportHandler(chaincodeSupport *ChaincodeSupport, peerChatStream ccintf.ChaincodeStream) *Handler {
v := &Handler{
ChatStream: peerChatStream,
}
v.chaincodeSupport = chaincodeSupport
v.nextState = make(chan *nextStateInfo)
v.FSM = fsm.NewFSM(
createdstate,
fsm.Events{ //有限狀態機
{Name: pb.ChaincodeMessage_REGISTER.String(), Src: []string{createdstate}, Dst: establishedstate},
{Name: pb.ChaincodeMessage_READY.String(), Src: []string{establishedstate}, Dst: readystate},
{Name: pb.ChaincodeMessage_PUT_STATE.String(), Src: []string{readystate}, Dst: readystate},
{Name: pb.ChaincodeMessage_DEL_STATE.String(), Src: []string{readystate}, Dst: readystate},
{Name: pb.ChaincodeMessage_INVOKE_CHAINCODE.String(), Src: []string{readystate}, Dst: readystate},
{Name: pb.ChaincodeMessage_COMPLETED.String(), Src: []string{readystate}, Dst: readystate},
{Name: pb.ChaincodeMessage_GET_STATE.String(), Src: []string{readystate}, Dst: readystate},
{Name: pb.ChaincodeMessage_GET_STATE_BY_RANGE.String(), Src: []string{readystate}, Dst: readystate},
{Name: pb.ChaincodeMessage_GET_QUERY_RESULT.String(), Src: []string{readystate}, Dst: readystate},
{Name: pb.ChaincodeMessage_GET_HISTORY_FOR_KEY.String(), Src: []string{readystate}, Dst: readystate},
{Name: pb.ChaincodeMessage_QUERY_STATE_NEXT.String(), Src: []string{readystate}, Dst: readystate},
{Name: pb.ChaincodeMessage_QUERY_STATE_CLOSE.String(), Src: []string{readystate}, Dst: readystate},
{Name: pb.ChaincodeMessage_ERROR.String(), Src: []string{readystate}, Dst: readystate},
{Name: pb.ChaincodeMessage_RESPONSE.String(), Src: []string{readystate}, Dst: readystate},
{Name: pb.ChaincodeMessage_INIT.String(), Src: []string{readystate}, Dst: readystate},
{Name: pb.ChaincodeMessage_TRANSACTION.String(), Src: []string{readystate}, Dst: readystate},
},
fsm.Callbacks{
"before_" + pb.ChaincodeMessage_REGISTER.String(): func(e *fsm.Event) { v.beforeRegisterEvent(e, v.FSM.Current()) },
"before_" + pb.ChaincodeMessage_COMPLETED.String(): func(e *fsm.Event) { v.beforeCompletedEvent(e, v.FSM.Current()) },
"after_" + pb.ChaincodeMessage_GET_STATE.String(): func(e *fsm.Event) { v.afterGetState(e, v.FSM.Current()) },
"after_" + pb.ChaincodeMessage_GET_STATE_BY_RANGE.String(): func(e *fsm.Event) { v.afterGetStateByRange(e, v.FSM.Current()) },
"after_" + pb.ChaincodeMessage_GET_QUERY_RESULT.String(): func(e *fsm.Event) { v.afterGetQueryResult(e, v.FSM.Current()) },
"after_" + pb.ChaincodeMessage_GET_HISTORY_FOR_KEY.String(): func(e *fsm.Event) { v.afterGetHistoryForKey(e, v.FSM.Current()) },
"after_" + pb.ChaincodeMessage_QUERY_STATE_NEXT.String(): func(e *fsm.Event) { v.afterQueryStateNext(e, v.FSM.Current()) },
"after_" + pb.ChaincodeMessage_QUERY_STATE_CLOSE.String(): func(e *fsm.Event) { v.afterQueryStateClose(e, v.FSM.Current()) },
"after_" + pb.ChaincodeMessage_PUT_STATE.String(): func(e *fsm.Event) { v.enterBusyState(e, v.FSM.Current()) },
"after_" + pb.ChaincodeMessage_DEL_STATE.String(): func(e *fsm.Event) { v.enterBusyState(e, v.FSM.Current()) },
"after_" + pb.ChaincodeMessage_INVOKE_CHAINCODE.String(): func(e *fsm.Event) { v.enterBusyState(e, v.FSM.Current()) },
"enter_" + establishedstate: func(e *fsm.Event) { v.enterEstablishedState(e, v.FSM.Current()) },
"enter_" + readystate: func(e *fsm.Event) { v.enterReadyState(e, v.FSM.Current()) },
"enter_" + endstate: func(e *fsm.Event) { v.enterEndState(e, v.FSM.Current()) },
},
)
v.policyChecker = policy.NewPolicyChecker(
peer.NewChannelPolicyManagerGetter(),
mgmt.GetLocalMSP(),
mgmt.NewLocalMSPPrincipalGetter(),
)
return v
}
//程式碼在core/chaincode/handler.go
```
#### 3.3.2、處理流
```go
return handler.processStream() //處理流
//程式碼在core/chaincode/handler.go
```
return handler.processStream()程式碼如下:
```go
func (handler *Handler) processStream() error {
defer handler.deregister()
msgAvail := make(chan *pb.ChaincodeMessage) //可用的ChaincodeMessage
var nsInfo *nextStateInfo
var in *pb.ChaincodeMessage
var err error
recv := true //收到ChaincodeMessage,即in = <-msgAvail
errc := make(chan error, 1)
for {
in = nil
err = nil
nsInfo = nil
if recv {
recv = false
go func() { //routine用於接收ChaincodeMessage
var in2 *pb.ChaincodeMessage
in2, err = handler.ChatStream.Recv()
msgAvail <- in2 //收到ChaincodeMessage
}()
}
select {
case sendErr := <-errc:
if sendErr != nil { //收到錯誤
return sendErr
}
continue //收到nil
case in = <-msgAvail: //收到ChaincodeMessage
if err == io.EOF { //io結束
chaincodeLogger.Debugf("Received EOF, ending chaincode support stream, %s", err)
return err
} else if err != nil { //收到錯誤
chaincodeLogger.Errorf("Error handling chaincode support stream: %s", err)
return err
} else if in == nil { //收到空
err = fmt.Errorf("Received nil message, ending chaincode support stream")
chaincodeLogger.Debug("Received nil message, ending chaincode support stream")
return err
}
chaincodeLogger.Debugf("[%s]Received message %s from shim", shorttxid(in.Txid), in.Type.String())
if in.Type.String() == pb.ChaincodeMessage_ERROR.String() { //收到錯誤
chaincodeLogger.Errorf("Got error: %s", string(in.Payload))
}
//繼續接收下一條
recv = true
if in.Type == pb.ChaincodeMessage_KEEPALIVE { //收到KEEPALIVE訊息
chaincodeLogger.Debug("Received KEEPALIVE Response")
continue
}
case nsInfo = <-handler.nextState: //下一個狀態
in = nsInfo.msg
if in == nil { //下一個狀態訊息為nil,結束流
err = fmt.Errorf("Next state nil message, ending chaincode support stream")
chaincodeLogger.Debug("Next state nil message, ending chaincode support stream")
return err
}
chaincodeLogger.Debugf("[%s]Move state message %s", shorttxid(in.Txid), in.Type.String())
case <-handler.waitForKeepaliveTimer():
if handler.chaincodeSupport.keepalive <= 0 {
chaincodeLogger.Errorf("Invalid select: keepalive not on (keepalive=%d)", handler.chaincodeSupport.keepalive)
continue
}
handler.serialSendAsync(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_KEEPALIVE}, nil)
continue
}
err = handler.HandleMessage(in) //處理訊息
if err != nil {
chaincodeLogger.Errorf("[%s]Error handling message, ending stream: %s", shorttxid(in.Txid), err)
return fmt.Errorf("Error handling message, ending stream: %s", err)
}
if nsInfo != nil && nsInfo.sendToCC {
chaincodeLogger.Debugf("[%s]sending state message %s", shorttxid(in.Txid), in.Type.String())
if nsInfo.sendSync {
if in.Type.String() != pb.ChaincodeMessage_READY.String() {
panic(fmt.Sprintf("[%s]Sync send can only be for READY state %s\n", shorttxid(in.Txid), in.Type.String()))
}
if err = handler.serialSend(in); err != nil {
return fmt.Errorf("[%s]Error sending ready message, ending stream: %s", shorttxid(in.Txid), err)
}
} else {
handler.serialSendAsync(in, errc)
}
}
}
}
//程式碼在core/chaincode/handler.go
```
err = handler.HandleMessage(in)程式碼如下:
```go
func (handler *Handler) HandleMessage(msg *pb.ChaincodeMessage) error {
eventErr := handler.FSM.Event(msg.Type.String(), msg) //發起事件
filteredErr := filterError(eventErr)
return filteredErr
}
//程式碼在core/chaincode/handler.go
```
補充ChaincodeMessage結構體:
```go
type ChaincodeMessage struct {
Type ChaincodeMessage_Type
Timestamp *google_protobuf1.Timestamp
Payload []byte
Txid string
Proposal *SignedProposal
ChaincodeEvent *ChaincodeEvent
}
type ChaincodeMessage_Type int32
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
)
//程式碼在protos/peer/chaincode_shim.pb.go
```
## 4、HandleMessage介面定義及實現
### 4.1、HandleMessage介面定義
```go
type MessageHandler interface {
//處理ChaincodeMessage
HandleMessage(msg *pb.ChaincodeMessage) error
//傳送ChaincodeMessage
SendMessage(msg *pb.ChaincodeMessage) error
}
//程式碼在core/chaincode/handler.go
```
### 4.2、HandleMessage介面實現
HandleMessage介面實現,即結構體Handler,定義如下:
```go
type Handler struct {
sync.RWMutex
serialLock sync.Mutex
ChatStream ccintf.ChaincodeStream
FSM *fsm.FSM
ChaincodeID *pb.ChaincodeID
ccInstance *sysccprovider.ChaincodeInstance
chaincodeSupport *ChaincodeSupport
registered bool
readyNotify chan bool
txCtxs map[string]*transactionContext
txidMap map[string]bool
nextState chan *nextStateInfo
policyChecker policy.PolicyChecker
}
//程式碼在core/chaincode/handler.go
```
涉及方法如下:
```go
func shorttxid(txid string) string
func (handler *Handler) decomposeRegisteredName(cid *pb.ChaincodeID)
func getChaincodeInstance(ccName string) *sysccprovider.ChaincodeInstance
func (handler *Handler) getCCRootName() string
func (handler *Handler) serialSend(msg *pb.ChaincodeMessage) error
func (handler *Handler) serialSendAsync(msg *pb.ChaincodeMessage, errc chan error)
func (handler *Handler) createTxContext(ctxt context.Context, chainID string, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal) (*transactionContext, error)
func (handler *Handler) getTxContext(txid string) *transactionContext
func (handler *Handler) deleteTxContext(txid string)
func (handler *Handler) putQueryIterator(txContext *transactionContext, txid string,
func (handler *Handler) getQueryIterator(txContext *transactionContext, txid string) commonledger.ResultsIterator
func (handler *Handler) deleteQueryIterator(txContext *transactionContext, txid string)
func (handler *Handler) checkACL(signedProp *pb.SignedProposal, proposal *pb.Proposal, ccIns *sysccprovider.ChaincodeInstance) error
func (handler *Handler) deregister() error
func (handler *Handler) triggerNextState(msg *pb.ChaincodeMessage, send bool)
func (handler *Handler) triggerNextStateSync(msg *pb.ChaincodeMessage)
func (handler *Handler) waitForKeepaliveTimer() <-chan time.Time
func (handler *Handler) processStream() error
func HandleChaincodeStream(chaincodeSupport *ChaincodeSupport, ctxt context.Context, stream ccintf.ChaincodeStream) error
//構造Handler
func newChaincodeSupportHandler(chaincodeSupport *ChaincodeSupport, peerChatStream ccintf.ChaincodeStream) *Handler
func (handler *Handler) createTXIDEntry(txid string) bool
func (handler *Handler) deleteTXIDEntry(txid string)
func (handler *Handler) notifyDuringStartup(val bool)
func (handler *Handler) beforeRegisterEvent(e *fsm.Event, state string)
func (handler *Handler) notify(msg *pb.ChaincodeMessage)
func (handler *Handler) beforeCompletedEvent(e *fsm.Event, state string)
func (handler *Handler) afterGetState(e *fsm.Event, state string)
func (handler *Handler) isValidTxSim(txid string, fmtStr string, args ...interface{}) (*transactionContext, *pb.ChaincodeMessage)
func (handler *Handler) handleGetState(msg *pb.ChaincodeMessage)
func (handler *Handler) afterGetStateByRange(e *fsm.Event, state string)
func (handler *Handler) handleGetStateByRange(msg *pb.ChaincodeMessage)
func getQueryResponse(handler *Handler, txContext *transactionContext, iter commonledger.ResultsIterator,
func (handler *Handler) afterQueryStateNext(e *fsm.Event, state string)
func (handler *Handler) handleQueryStateNext(msg *pb.ChaincodeMessage)
func (handler *Handler) afterQueryStateClose(e *fsm.Event, state string)
func (handler *Handler) handleQueryStateClose(msg *pb.ChaincodeMessage)
func (handler *Handler) afterGetQueryResult(e *fsm.Event, state string)
func (handler *Handler) handleGetQueryResult(msg *pb.ChaincodeMessage)
func (handler *Handler) afterGetHistoryForKey(e *fsm.Event, state string)
func (handler *Handler) handleGetHistoryForKey(msg *pb.ChaincodeMessage)
func (handler *Handler) enterBusyState(e *fsm.Event, state string)
func (handler *Handler) enterEstablishedState(e *fsm.Event, state string)
func (handler *Handler) enterReadyState(e *fsm.Event, state string)
func (handler *Handler) enterEndState(e *fsm.Event, state string)
func (handler *Handler) setChaincodeProposal(signedProp *pb.SignedProposal, prop *pb.Proposal, msg *pb.ChaincodeMessage) error
func (handler *Handler) ready(ctxt context.Context, chainID string, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal) (chan *pb.ChaincodeMessage, error)
//處理訊息
func (handler *Handler) HandleMessage(msg *pb.ChaincodeMessage) error
func filterError(errFromFSMEvent error) error
func (handler *Handler) sendExecuteMessage(ctxt context.Context, chainID string, msg *pb.ChaincodeMessage, signedProp *pb.SignedProposal, prop *pb.Proposal) (chan *pb.ChaincodeMessage, error)
func (handler *Handler) isRunning() bool
//程式碼在core/chaincode/handler.go
```
網址:http://www.qukuailianxueyuan.io/
欲領取造幣技術與全套虛擬機器資料
區塊鏈技術交流QQ群:756146052 備註:CSDN
尹成學院微信:備註:CSDN
網址:http://www.qukuailianxueyuan.io/
欲領取造幣技術與全套虛擬機器資料
區塊鏈技術交流QQ群:756146052 備註:CSDN
尹成學院微信:備註:CSDN
網址:http://www.qukuailianxueyuan.io/
欲領取造幣技術與全套虛擬機器資料
區塊鏈技術交流QQ群:756146052 備註:CSDN
尹成學院微信:備註:CSDN
網址:http://www.qukuailianxueyuan.io/
欲領取造幣技術與全套虛擬機器資料
區塊鏈技術交流QQ群:756146052 備註:CSDN
尹成學院微信:備註:CSDN
網址:http://www.qukuailianxueyuan.io/
欲領取造幣技術與全套虛擬機器資料
區塊鏈技術交流QQ群:756146052 備註:CSDN
尹成學院微信:備註:CSDN
相關文章
- Fabric 1.0原始碼分析(5)Chaincode(鏈碼)體系總結原始碼AI
- Fabric 1.0原始碼分析(4)Chaincode(鏈碼)#platforms(鏈碼語言平臺)原始碼AIPlatform
- Fabric 1.0原始碼分析(34) Peer #peer chaincode命令及子命令實現原始碼AI
- Fabric 1.0原始碼分析(42)scc(系統鏈碼)原始碼
- Fabric 1.0原始碼分析(25) Orderer原始碼
- Fabric 1.0原始碼分析(31) Peer原始碼
- Fabric 1.0原始碼分析(29) Orderer #multichain(多鏈支援包)原始碼AI
- Fabric 1.0原始碼分析(40) Proposal(提案)原始碼
- Fabric 1.0原始碼分析(42)scc(系統鏈碼) #cscc(通道相關)原始碼
- Fabric 1.0原始碼分析(47)Fabric 1.0.4 go程式碼量統計原始碼Go
- Fabric 1.0原始碼分析(18) Ledger(賬本)原始碼
- Fabric 1.0原始碼分析(43) Tx(Transaction 交易)原始碼
- Fabric 1.0原始碼分析(14) flogging(Fabric日誌系統)原始碼
- Fabric 1.0原始碼分析(13)events(事件服務)原始碼事件
- Fabric 1.0原始碼分析(26)Orderer #ledger(Orderer Ledger)原始碼
- Fabric 1.0原始碼分析(39) policy(背書策略)原始碼
- Fabric 1.0原始碼分析(45)gRPC(Fabric中註冊的gRPC Service)原始碼RPC
- Fabric 1.0原始碼分析(10)consenter(共識外掛)原始碼
- Fabric 1.0原始碼分析(15)gossip(流言演算法)原始碼Go演算法
- Fabric 1.0原始碼分析(23)LevelDB(KV資料庫)原始碼資料庫
- Fabric 1.0原始碼分析(44)Tx #RWSet(讀寫集)原始碼
- Fabric 1.0原始碼分析(1)BCCSP(區塊鏈加密服務提供者)原始碼區塊鏈加密
- 區塊鏈教程Fabric1.0原始碼分析policy(背書策略)-兄弟連區塊鏈區塊鏈原始碼
- Fabric 1.0原始碼分析(6)configtx(配置交易) #ChannelConfig(通道配置)原始碼
- Fabric 1.0原始碼分析(20) Ledger #idStore(ledgerID資料庫)原始碼資料庫
- Fabric 1.0原始碼分析(30) Orderer #BroadcastServer(Broadcast服務端)原始碼ASTServer服務端
- Fabric 1.0原始碼分析(35)Peer #EndorserServer(Endorser服務端)原始碼Server服務端
- Fabric 1.0原始碼分析(36) Peer #EndorserClient(Endorser客戶端)原始碼client客戶端
- Fabric 1.0原始碼分析(37) Peer #DeliverClient(Deliver客戶端)原始碼client客戶端
- Fabric 1.0原始碼分析(38) Peer #BroadcastClient(Broadcast客戶端)原始碼ASTclient客戶端
- Fabric 1.0原始碼分析(41)putils(protos/utils工具包)原始碼
- Fabric 1.0原始碼分析(2) blockfile(區塊檔案儲存)原始碼BloC
- Fabric 1.0原始碼分析(7)configtx(配置交易) #configtxgen(生成通道配置)原始碼
- Fabric 1.0原始碼分析(9)configtx(配置交易)體系介紹原始碼
- Fabric 1.0原始碼分析(19) Ledger #statedb(狀態資料庫)原始碼資料庫
- Fabric 1.0原始碼分析(21)Ledger #historydb(歷史資料庫)原始碼資料庫
- Fabric 1.0原始碼分析(22)Ledger #blkstorage(block檔案儲存)原始碼BloC
- Fabric 1.0原始碼分析(27) Orderer #configupdate(處理通道配置更新)原始碼