您的位置:首页 > 其它

Hyperledger Fabric创世纪块源码解析

2017-01-17 13:20 441 查看




1.serve函数中创世纪块开始,调用MakeGenesis函数

makeGenesisError := genesis.MakeGenesis()
if makeGenesisError != nil {
return makeGenesisError
}


2.MakeGenesis创建创世纪块并且添加到区块链上

func MakeGenesis() error {
once.Do(func() {
ledger, err := ledger.GetLedger()
if err != nil {
makeGenesisError = err
return
}

if ledger.GetBlockchainSize() == 0 {
genesisLogger.Info("Creating genesis block.")
if makeGenesisError = ledger.BeginTxBatch(0); makeGenesisError == nil {
makeGenesisError = ledger.CommitTxBatch(0, nil, nil, nil)
}
}
})
return makeGenesisError
}


3.GetLedger给一个引用到一个“单列模式”账本

func GetLedger() (*Ledger, error) {
once.Do(func() {
ledger, ledgerError = GetNewLedger()
})
return ledger, ledgerError
}


3.1. GetNewLedger 给一个引用到新的账本

func GetNewLedger() (*Ledger, error) {
blockchain, err := newBlockchain()
if err != nil {
return nil, err
}

state := state.NewState()
return &Ledger{blockchain, state, nil}, nil
}


a.从newBlockchain开始,是创建一个新的区块链,整个过程包括获取数据库句柄,从数据库中取东西,获取区块的哈希值等等。

b.从NewState开始,构建一个状态树的逻辑结构,以便于以这个逻辑结构后面存储东西

4.GetBlockchainSize返回区块链上的块的数量

func (ledger *Ledger) GetBlockchainSize() uint64 {
return ledger.blockchain.getSize()
}


5.当当前的transaction-batch需要提交时获取调用。如果交易详细和状态改变(在这交易批执行期间可能会发生)被提交到永久存储时,这个函数返回成功,在这个过程中涉及到写块,将块写到数据库,发送事件等机制

func (ledger *Ledger) CommitTxBatch(id interface{}, transactions []*protos.Transaction, transactionResults []*protos.TransactionResult, metadata []byte) error {
err := ledger.checkValidIDCommitORRollback(id)
if err != nil {
return err
}

stateHash, err := ledger.state.GetHash()
if err != nil {
ledger.resetForNextTxGroup(false)
ledger.blockchain.blockPersistenceStatus(false)
return err
}

writeBatch := gorocksdb.NewWriteBatch()
defer writeBatch.Destroy()
block := protos.NewBlock(transactions, metadata)

ccEvents := []*protos.ChaincodeEvent{}

if transactionResults != nil {
ccEvents = make([]*protos.ChaincodeEvent, len(transactionResults))
for i := 0; i < len(transactionResults); i++ {
if transactionResults[i].ChaincodeEvent != nil {
ccEvents[i] = transactionResults[i].ChaincodeEvent
} else {
ccEvents[i] = &protos.ChaincodeEvent{}
}
}
}
// 直接在NonHashData存储chaincode事件。这可能会在新共识中改变,我们可以将其移动到交易
block.NonHashData = &protos.NonHashData{ChaincodeEvents: ccEvents}
newBlockNumber, err := ledger.blockchain.addPersistenceChangesForNewBlock(context.TODO(), block, stateHash, writeBatch)
if err != nil {
ledger.resetForNextTxGroup(false)
ledger.blockchain.blockPersistenceStatus(false)
return err
}
ledger.state.AddChangesForPersistence(newBlockNumber, writeBatch)
opt := gorocksdb.NewDefaultWriteOptions()
defer opt.Destroy()
dbErr := db.GetDBHandle().DB.Write(opt, writeBatch)
if dbErr != nil {
ledger.resetForNextTxGroup(false)
ledger.blockchain.blockPersistenceStatus(false)
return dbErr
}

ledger.resetForNextTxGroup(true)
ledger.blockchain.blockPersistenceStatus(true)

sendProducerBlockEvent(block)

//send chaincode events from transaction results
// 从交易结果发送链上代码事件
sendChaincodeEvents(transactionResults)

if len(transactionResults) != 0 {
ledgerLogger.Debug("There were some erroneous transactions. We need to send a 'TX rejected' message here.")
}
return nil
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  中创