Fabric 1.0原始碼分析(7)configtx(配置交易) #configtxgen(生成通道配置)
# Fabric 1.0原始碼筆記 之 configtx(配置交易) #configtxgen(生成通道配置)
## 1、configtxgen概述
configtxgen,用於生成通道配置,具體有如下三種用法:
* 生成Orderer服務啟動的初始區塊(即系統通道的創世區塊檔案)
* configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block
* 生成新建應用通道的配置交易(即用於建立應用通道的配置交易檔案)
* configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel
* 生成錨節點配置更新檔案
* configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP
configtxgen程式碼分佈在common/configtx/tool目錄,目錄結構如下:
* localconfig/config.go,configtx.yaml配置檔案相關的結構體及方法。
## 2、configtx.yaml配置檔案示例
```bash
Profiles:
TwoOrgsOrdererGenesis: #Orderer系統通道配置
Orderer:
<<: *OrdererDefaults #引用OrdererDefaults併合併到當前
Organizations: #屬於Orderer通道的組織
- *OrdererOrg
Consortiums: #Orderer所服務的聯盟列表
SampleConsortium:
Organizations:
- *Org1
- *Org2
TwoOrgsChannel: #應用通道配置
Consortium: SampleConsortium #應用通道關聯的聯盟
Application:
<<: *ApplicationDefaults #引用ApplicationDefaults併合併到當前
Organizations: #初始加入應用通道的組織
- *Org1
- *Org2
Organizations:
- &OrdererOrg
Name: OrdererOrg
ID: OrdererMSP # MSP ID
MSPDir: crypto-config/ordererOrganizations/example.com/msp #MSP相關檔案本地路徑
- &Org1
Name: Org1MSP
ID: Org1MSP
MSPDir: crypto-config/peerOrganizations/org1.example.com/msp
AnchorPeers: #錨節點地址,用於跨組織的Gossip通訊
- Host: peer0.org1.example.com
Port: 7051
- &Org2
Name: Org2MSP
ID: Org2MSP
MSPDir: crypto-config/peerOrganizations/org2.example.com/msp
AnchorPeers: #錨節點地址,用於跨組織的Gossip通訊
- Host: peer0.org2.example.com
Port: 7051
Orderer: &OrdererDefaults
OrdererType: solo # Orderer共識外掛型別,分solo或kafka
Addresses:
- orderer.example.com:7050 #服務地址
BatchTimeout: 2s #建立批量交易的最大超時,一批交易構成一個塊
BatchSize: #寫入區塊內的交易個數
MaxMessageCount: 10 #一批訊息的最大個數
AbsoluteMaxBytes: 98 MB #一批交易的最大位元組數,任何時候均不能超過
PreferredMaxBytes: 512 KB #批量交易的建議位元組數
Kafka:
Brokers: #Kafka埠
- 127.0.0.1:9092
Organizations: #參與維護Orderer的組織,預設空
Application: &ApplicationDefaults
Organizations: #加入到通道的組織資訊,此處為不包括任何組織
```
配置檔案解讀:
* 每個Profile表示某種場景下的通道配置模板,包括Orderer系統通道模板和應用通道模板,其中TwoOrgsOrdererGenesis為系統通道模板,TwoOrgsChannel為應用通道模板。
* Orderer系統通道模板,包括Orderer和Consortiums,其中Orderer指定系統通道配置,Consortiums為Orderer服務的聯盟列表。
* 應用通道,包括Application和Consortium,其中Application為應用通道的配置,Consortium為應用通道所關聯的聯盟名稱。
附:[YAML 語言教程](http://www.ruanyifeng.com/blog/2016/07/yaml.html?f=tt)
-表示陣列,&表示錨點,*表示引用,<<表示合併到當前資料。
## 3、configtx.yaml配置檔案相關的結構體及方法
### 3.1、configtx.yaml配置檔案相關的結構體定義
```go
type TopLevel struct {
Profiles map[string]*Profile //通道配置
Organizations []*Organization //組織
Application *Application //應用通道配置
Orderer *Orderer //系統通道配置
}
type Profile struct { //通道配置:系統通道配置或應用通道配置
Consortium string //應用通道配置中通道所關聯的聯盟名稱
Application *Application //應用通道配置
Orderer *Orderer //系統通道配置
Consortiums map[string]*Consortium //系統通道配置中Orderer服務的聯盟列表
}
type Consortium struct { //聯盟,即組織列表
Organizations []*Organization //組織
}
type Application struct { //應用通道配置,即初始加入通道的組織
Organizations []*Organization
}
type Organization struct { //組織
Name string //組織名稱
ID string //組織MSP ID
MSPDir string //組織MSP檔案所在路徑
AdminPrincipal string //管理員身份規則
AnchorPeers []*AnchorPeer //錨節點列表
}
type AnchorPeer struct { //錨節點,即主機和埠
Host string
Port int
}
type Orderer struct { //系統通道配置
OrdererType string //共識外掛型別
Addresses []string //Orderer服務地址
BatchTimeout time.Duration //批處理超時
BatchSize BatchSize //批處理大小
Kafka Kafka //Kafka
Organizations []*Organization //參與維護Orderer的組織,預設空
MaxChannels uint64 //Orderer最大通道數
}
type BatchSize struct { //批處理大小
MaxMessageCount uint32 //最大交易數量
AbsoluteMaxBytes uint32 //最大位元組數
PreferredMaxBytes uint32 //建議位元組數
}
type Kafka struct {
Brokers []string //Kafka Broker
}
//程式碼在common/configtx/tool/localconfig/config.go
```
### 3.2、configtx.yaml配置檔案相關的方法
```go
//獲取指定profile的Profile結構
func Load(profile string) *Profile
//將Profile校驗並補充完整
func (p *Profile) completeInitialization(configDir string)
func translatePaths(configDir string, org *Organization)
//程式碼在common/configtx/tool/localconfig/config.go
```
## 4、Generator介面及實現
Generator介面定義:
```go
type Generator interface {
bootstrap.Helper
ChannelTemplate() configtx.Template //獲取用於初始化通道的模板
GenesisBlockForChannel(channelID string) *cb.Block //用於outputBlock
}
//程式碼在common/configtx/tool/provisional/provisional.go
```
Generator介面實現,即bootstrapper。
```go
type bootstrapper struct {
channelGroups []*cb.ConfigGroup
ordererGroups []*cb.ConfigGroup
applicationGroups []*cb.ConfigGroup
consortiumsGroups []*cb.ConfigGroup
}
func New(conf *genesisconfig.Profile) Generator
func (bs *bootstrapper) ChannelTemplate() configtx.Template
func (bs *bootstrapper) GenesisBlock() *cb.Block
func (bs *bootstrapper) GenesisBlockForChannel(channelID string) *cb.Block
//程式碼在common/configtx/tool/provisional/provisional.go
```
func New(conf *genesisconfig.Profile) Generator程式碼如下:
```go
func New(conf *genesisconfig.Profile) Generator {
bs := &bootstrapper{
channelGroups: []*cb.ConfigGroup{
config.DefaultHashingAlgorithm(), //預設雜湊函式
config.DefaultBlockDataHashingStructure(), //預設塊資料雜湊結構
//預設通道策略,包括讀策略、寫策略和管理策略
//ReadersPolicyKey = "Readers",ImplicitMetaPolicy_ANY,任意
policies.TemplateImplicitMetaAnyPolicy([]string{}, configvaluesmsp.ReadersPolicyKey),
//WritersPolicyKey = "Writers",ImplicitMetaPolicy_ANY,任意
policies.TemplateImplicitMetaAnyPolicy([]string{}, configvaluesmsp.WritersPolicyKey),
//AdminsPolicyKey = "Admins",ImplicitMetaPolicy_MAJORITY,大多數
policies.TemplateImplicitMetaMajorityPolicy([]string{}, configvaluesmsp.AdminsPolicyKey),
},
}
if conf.Orderer != nil { //系統通道配置
oa := config.TemplateOrdererAddresses(conf.Orderer.Addresses) //設定Orderer地址
oa.Values[config.OrdererAddressesKey].ModPolicy = OrdererAdminsPolicy //OrdererAdminsPolicy = "/Channel/Orderer/Admins"
bs.ordererGroups = []*cb.ConfigGroup{
oa,
config.TemplateConsensusType(conf.Orderer.OrdererType), //設定共識外掛型別
config.TemplateBatchSize(&ab.BatchSize{ //設定批處理大小
MaxMessageCount: conf.Orderer.BatchSize.MaxMessageCount,
AbsoluteMaxBytes: conf.Orderer.BatchSize.AbsoluteMaxBytes,
PreferredMaxBytes: conf.Orderer.BatchSize.PreferredMaxBytes,
}),
config.TemplateBatchTimeout(conf.Orderer.BatchTimeout.String()), //設定批處理超時
config.TemplateChannelRestrictions(conf.Orderer.MaxChannels), //設定最大通道數
//初始化Orderer讀、寫、管理策略
policies.TemplateImplicitMetaPolicyWithSubPolicy([]string{config.OrdererGroupKey}, BlockValidationPolicyKey, configvaluesmsp.WritersPolicyKey, cb.ImplicitMetaPolicy_ANY),
policies.TemplateImplicitMetaAnyPolicy([]string{config.OrdererGroupKey}, configvaluesmsp.ReadersPolicyKey),
policies.TemplateImplicitMetaAnyPolicy([]string{config.OrdererGroupKey}, configvaluesmsp.WritersPolicyKey),
policies.TemplateImplicitMetaMajorityPolicy([]string{config.OrdererGroupKey}, configvaluesmsp.AdminsPolicyKey),
}
for _, org := range conf.Orderer.Organizations {
mspConfig, err := msp.GetVerifyingMspConfig(org.MSPDir, org.ID)
bs.ordererGroups = append(bs.ordererGroups,
configvaluesmsp.TemplateGroupMSPWithAdminRolePrincipal([]string{config.OrdererGroupKey, org.Name},
mspConfig, org.AdminPrincipal == genesisconfig.AdminRoleAdminPrincipal,
),
)
}
switch conf.Orderer.OrdererType {
case ConsensusTypeSolo:
case ConsensusTypeKafka:
bs.ordererGroups = append(bs.ordererGroups, config.TemplateKafkaBrokers(conf.Orderer.Kafka.Brokers)) //設定Kafka
default:
}
}
if conf.Application != nil { //應用通道配置
bs.applicationGroups = []*cb.ConfigGroup{
policies.TemplateImplicitMetaAnyPolicy([]string{config.ApplicationGroupKey}, configvaluesmsp.ReadersPolicyKey),
policies.TemplateImplicitMetaAnyPolicy([]string{config.ApplicationGroupKey}, configvaluesmsp.WritersPolicyKey),
policies.TemplateImplicitMetaMajorityPolicy([]string{config.ApplicationGroupKey}, configvaluesmsp.AdminsPolicyKey),
}
for _, org := range conf.Application.Organizations {
mspConfig, err := msp.GetVerifyingMspConfig(org.MSPDir, org.ID)
bs.applicationGroups = append(bs.applicationGroups,
configvaluesmsp.TemplateGroupMSPWithAdminRolePrincipal([]string{config.ApplicationGroupKey, org.Name},
mspConfig, org.AdminPrincipal == genesisconfig.AdminRoleAdminPrincipal,
),
)
var anchorProtos []*pb.AnchorPeer
for _, anchorPeer := range org.AnchorPeers {
anchorProtos = append(anchorProtos, &pb.AnchorPeer{
Host: anchorPeer.Host,
Port: int32(anchorPeer.Port),
})
}
bs.applicationGroups = append(bs.applicationGroups, config.TemplateAnchorPeers(org.Name, anchorProtos))
}
}
if conf.Consortiums != nil { //聯盟相關
tcg := config.TemplateConsortiumsGroup()
tcg.Groups[config.ConsortiumsGroupKey].ModPolicy = OrdererAdminsPolicy
tcg.Groups[config.ConsortiumsGroupKey].Policies[configvaluesmsp.AdminsPolicyKey] = &cb.ConfigPolicy{
Policy: &cb.Policy{
Type: int32(cb.Policy_SIGNATURE),
Value: utils.MarshalOrPanic(cauthdsl.AcceptAllPolicy),
},
ModPolicy: OrdererAdminsPolicy,
}
bs.consortiumsGroups = append(bs.consortiumsGroups, tcg)
for consortiumName, consortium := range conf.Consortiums {
cg := config.TemplateConsortiumChannelCreationPolicy(consortiumName, policies.ImplicitMetaPolicyWithSubPolicy(
configvaluesmsp.AdminsPolicyKey,
cb.ImplicitMetaPolicy_ANY,
).Policy)
cg.Groups[config.ConsortiumsGroupKey].Groups[consortiumName].ModPolicy = OrdererAdminsPolicy
cg.Groups[config.ConsortiumsGroupKey].Groups[consortiumName].Values[config.ChannelCreationPolicyKey].ModPolicy = OrdererAdminsPolicy
bs.consortiumsGroups = append(bs.consortiumsGroups, cg)
for _, org := range consortium.Organizations {
mspConfig, err := msp.GetVerifyingMspConfig(org.MSPDir, org.ID)
bs.consortiumsGroups = append(bs.consortiumsGroups,
configvaluesmsp.TemplateGroupMSPWithAdminRolePrincipal(
[]string{config.ConsortiumsGroupKey, consortiumName, org.Name},
mspConfig, org.AdminPrincipal == genesisconfig.AdminRoleAdminPrincipal,
),
)
}
}
}
return bs
}
//程式碼在common/configtx/tool/provisional/provisional.go
```
func (bs *bootstrapper) GenesisBlockForChannel(channelID string) *cb.Block程式碼如下:
```go
func (bs *bootstrapper) GenesisBlockForChannel(channelID string) *cb.Block {
block, err := genesis.NewFactoryImpl(
configtx.NewModPolicySettingTemplate(
configvaluesmsp.AdminsPolicyKey,
configtx.NewCompositeTemplate(
configtx.NewSimpleTemplate(bs.consortiumsGroups...),
bs.ChannelTemplate(),
),
),
).Block(channelID)
return block
}
//程式碼在common/configtx/tool/provisional/provisional.go
```
## 5、configtxgen命令
### 5.1、main函式
```go
func main() {
var outputBlock, outputChannelCreateTx, profile, channelID, inspectBlock, inspectChannelCreateTx, outputAnchorPeersUpdate, asOrg string
//-outputBlock,初始區塊寫入指定檔案
flag.StringVar(&outputBlock, "outputBlock", "", "The path to write the genesis block to (if set)")
//-channelID,指定通道名稱
flag.StringVar(&channelID, "channelID", provisional.TestChainID, "The channel ID to use in the configtx")
//-outputCreateChannelTx,將通道建立交易寫入指定檔案
flag.StringVar(&outputChannelCreateTx, "outputCreateChannelTx", "", "The path to write a channel creation configtx to (if set)")
//-profile,指定profile
flag.StringVar(&profile, "profile", genesisconfig.SampleInsecureProfile, "The profile from configtx.yaml to use for generation.")
//-inspectBlock,列印指定區塊的配置資訊
flag.StringVar(&inspectBlock, "inspectBlock", "", "Prints the configuration contained in the block at the specified path")
//-inspectChannelCreateTx,列印通道建立交易檔案中的配置更新資訊
flag.StringVar(&inspectChannelCreateTx, "inspectChannelCreateTx", "", "Prints the configuration contained in the transaction at the specified path")
//-outputAnchorPeersUpdate,生成錨節點配置更新檔案,需同時指定-asOrg
flag.StringVar(&outputAnchorPeersUpdate, "outputAnchorPeersUpdate", "", "Creates an config update to update an anchor peer (works only with the default channel creation, and only for the first update)")
//-asOrg,以指定身份執行更新配置交易,如更新錨節點配置資訊
flag.StringVar(&asOrg, "asOrg", "", "Performs the config generation as a particular organization (by name), only including values in the write set that org (likely) has privilege to set")
flag.Parse()
factory.InitFactories(nil)
config := genesisconfig.Load(profile) //讀取指定配置
if outputBlock != "" { //生成Orderer服務啟動的初始區塊
err := doOutputBlock(config, channelID, outputBlock)
}
if outputChannelCreateTx != "" { //生成新建應用通道的配置交易
err := doOutputChannelCreateTx(config, channelID, outputChannelCreateTx)
}
if outputAnchorPeersUpdate != "" { //生成錨節點配置更新檔案
err := doOutputAnchorPeersUpdate(config, channelID, outputAnchorPeersUpdate, asOrg)
}
}
//程式碼在common/configtx/tool/configtxgen/main.go
```
### 5.2、doOutputBlock(生成Orderer服務啟動的初始區塊,即系統通道的初始區塊檔案)
```go
func doOutputBlock(config *genesisconfig.Profile, channelID string, outputBlock string) error {
pgen := provisional.New(config) //構建Generator例項
genesisBlock := pgen.GenesisBlockForChannel(channelID) //生成創世區塊
err := ioutil.WriteFile(outputBlock, utils.MarshalOrPanic(genesisBlock), 0644) //創世區塊寫入檔案
return nil
}
//程式碼在common/configtx/tool/configtxgen/main.go
```
genesis更詳細內容,參考:[Fabric 1.0原始碼筆記 之 configtx(配置交易) #genesis(系統通道創世區塊)](genesis.md)
### 5.3、doOutputChannelCreateTx(生成新建應用通道的配置交易)
```go
func doOutputChannelCreateTx(conf *genesisconfig.Profile, channelID string, outputChannelCreateTx string) error {
var orgNames []string
for _, org := range conf.Application.Organizations {
orgNames = append(orgNames, org.Name)
}
configtx, err := configtx.MakeChainCreationTransaction(channelID, conf.Consortium, nil, orgNames...)
err = ioutil.WriteFile(outputChannelCreateTx, utils.MarshalOrPanic(configtx), 0644)
return nil
}
//程式碼在common/configtx/tool/configtxgen/main.go
```
### 5.4、doOutputAnchorPeersUpdate(生成錨節點配置更新檔案)
```go
func doOutputAnchorPeersUpdate(conf *genesisconfig.Profile, channelID string, outputAnchorPeersUpdate string, asOrg string) error {
var org *genesisconfig.Organization
for _, iorg := range conf.Application.Organizations {
if iorg.Name == asOrg {
org = iorg
}
}
anchorPeers := make([]*pb.AnchorPeer, len(org.AnchorPeers))
for i, anchorPeer := range org.AnchorPeers {
anchorPeers[i] = &pb.AnchorPeer{
Host: anchorPeer.Host,
Port: int32(anchorPeer.Port),
}
}
configGroup := config.TemplateAnchorPeers(org.Name, anchorPeers)
configGroup.Groups[config.ApplicationGroupKey].Groups[org.Name].Values[config.AnchorPeersKey].ModPolicy = mspconfig.AdminsPolicyKey
configUpdate := &cb.ConfigUpdate{
ChannelId: channelID,
WriteSet: configGroup,
ReadSet: cb.NewConfigGroup(),
}
configUpdate.ReadSet.Groups[config.ApplicationGroupKey] = cb.NewConfigGroup()
configUpdate.ReadSet.Groups[config.ApplicationGroupKey].Version = 1
configUpdate.ReadSet.Groups[config.ApplicationGroupKey].ModPolicy = mspconfig.AdminsPolicyKey
configUpdate.ReadSet.Groups[config.ApplicationGroupKey].Groups[org.Name] = cb.NewConfigGroup()
configUpdate.ReadSet.Groups[config.ApplicationGroupKey].Groups[org.Name].Values[config.MSPKey] = &cb.ConfigValue{}
configUpdate.ReadSet.Groups[config.ApplicationGroupKey].Groups[org.Name].Policies[mspconfig.ReadersPolicyKey] = &cb.ConfigPolicy{}
configUpdate.ReadSet.Groups[config.ApplicationGroupKey].Groups[org.Name].Policies[mspconfig.WritersPolicyKey] = &cb.ConfigPolicy{}
configUpdate.ReadSet.Groups[config.ApplicationGroupKey].Groups[org.Name].Policies[mspconfig.AdminsPolicyKey] = &cb.ConfigPolicy{}
configUpdate.WriteSet.Groups[config.ApplicationGroupKey].Version = 1
configUpdate.WriteSet.Groups[config.ApplicationGroupKey].ModPolicy = mspconfig.AdminsPolicyKey
configUpdate.WriteSet.Groups[config.ApplicationGroupKey].Groups[org.Name].Version = 1
configUpdate.WriteSet.Groups[config.ApplicationGroupKey].Groups[org.Name].ModPolicy = mspconfig.AdminsPolicyKey
configUpdate.WriteSet.Groups[config.ApplicationGroupKey].Groups[org.Name].Values[config.MSPKey] = &cb.ConfigValue{}
configUpdate.WriteSet.Groups[config.ApplicationGroupKey].Groups[org.Name].Policies[mspconfig.ReadersPolicyKey] = &cb.ConfigPolicy{}
configUpdate.WriteSet.Groups[config.ApplicationGroupKey].Groups[org.Name].Policies[mspconfig.WritersPolicyKey] = &cb.ConfigPolicy{}
configUpdate.WriteSet.Groups[config.ApplicationGroupKey].Groups[org.Name].Policies[mspconfig.AdminsPolicyKey] = &cb.ConfigPolicy{}
configUpdateEnvelope := &cb.ConfigUpdateEnvelope{
ConfigUpdate: utils.MarshalOrPanic(configUpdate),
}
update := &cb.Envelope{
Payload: utils.MarshalOrPanic(&cb.Payload{
Header: &cb.Header{
ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{
ChannelId: channelID,
Type: int32(cb.HeaderType_CONFIG_UPDATE),
}),
},
Data: utils.MarshalOrPanic(configUpdateEnvelope),
}),
}
err := ioutil.WriteFile(outputAnchorPeersUpdate, utils.MarshalOrPanic(update), 0644)
return nil
}
//程式碼在common/configtx/tool/configtxgen/main.go
```
網址:http://www.qukuailianxueyuan.io/
欲領取造幣技術與全套虛擬機器資料
區塊鏈技術交流QQ群:756146052 備註:CSDN
尹成學院微信:備註:CSDN
網址:http://www.qukuailianxueyuan.io/
欲領取造幣技術與全套虛擬機器資料
區塊鏈技術交流QQ群:756146052 備註:CSDN
尹成學院微信:備註:CSDN
相關文章
- Fabric 1.0原始碼分析(6)configtx(配置交易) #ChannelConfig(通道配置)原始碼
- Fabric 1.0原始碼分析(8)configtx(配置交易) #genesis(系統通道創世區塊)原始碼
- Fabric 1.0原始碼分析(9)configtx(配置交易)體系介紹原始碼
- Fabric 1.0原始碼分析(27) Orderer #configupdate(處理通道配置更新)原始碼
- Fabric 1.0原始碼分析(43) Tx(Transaction 交易)原始碼
- Fabric 1.0原始碼分析(42)scc(系統鏈碼) #cscc(通道相關)原始碼
- Fabric 1.0原始碼分析(25) Orderer原始碼
- Fabric 1.0原始碼分析(31) Peer原始碼
- Fabric 1.0原始碼分析(28) Orderer #localconfig(Orderer配置檔案定義)原始碼
- Fabric 1.0原始碼分析(40) Proposal(提案)原始碼
- Fabric 1.0原始碼分析(3)Chaincode(鏈碼)原始碼AI
- Fabric 1.0原始碼分析(18) Ledger(賬本)原始碼
- Fabric 1.0原始碼分析(47)Fabric 1.0.4 go程式碼量統計原始碼Go
- Fabric 1.0原始碼分析(42)scc(系統鏈碼)原始碼
- Fabric 1.0原始碼分析(13)events(事件服務)原始碼事件
- Fabric 1.0原始碼分析(26)Orderer #ledger(Orderer Ledger)原始碼
- Fabric 1.0原始碼分析(39) policy(背書策略)原始碼
- Fabric 1.0原始碼分析(12)cryptogen(生成組織關係和身份證書)原始碼
- Fabric 1.0原始碼分析(15)gossip(流言演算法)原始碼Go演算法
- Fabric 1.0原始碼分析(23)LevelDB(KV資料庫)原始碼資料庫
- Fabric 1.0原始碼分析(44)Tx #RWSet(讀寫集)原始碼
- Fabric 1.0原始碼分析(14) flogging(Fabric日誌系統)原始碼
- Fabric 1.0原始碼分析(10)consenter(共識外掛)原始碼
- Fabric 1.0原始碼分析(29) Orderer #multichain(多鏈支援包)原始碼AI
- Fabric 1.0原始碼分析(35)Peer #EndorserServer(Endorser服務端)原始碼Server服務端
- Fabric 1.0原始碼分析(36) Peer #EndorserClient(Endorser客戶端)原始碼client客戶端
- Fabric 1.0原始碼分析(41)putils(protos/utils工具包)原始碼
- Fabric 1.0原始碼分析(45)gRPC(Fabric中註冊的gRPC Service)原始碼RPC
- Fabric 1.0原始碼分析(5)Chaincode(鏈碼)體系總結原始碼AI
- Fabric 1.0原始碼分析(2) blockfile(區塊檔案儲存)原始碼BloC
- Fabric 1.0原始碼分析(19) Ledger #statedb(狀態資料庫)原始碼資料庫
- Fabric 1.0原始碼分析(21)Ledger #historydb(歷史資料庫)原始碼資料庫
- Fabric 1.0原始碼分析(22)Ledger #blkstorage(block檔案儲存)原始碼BloC
- Fabric 1.0原始碼分析(32) Peer #peer node start命令實現原始碼
- Fabric 1.0原始碼分析(20) Ledger #idStore(ledgerID資料庫)原始碼資料庫
- Fabric 1.0原始碼分析(30) Orderer #BroadcastServer(Broadcast服務端)原始碼ASTServer服務端
- Fabric 1.0原始碼分析(37) Peer #DeliverClient(Deliver客戶端)原始碼client客戶端
- Fabric 1.0原始碼分析(38) Peer #BroadcastClient(Broadcast客戶端)原始碼ASTclient客戶端