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 }
相关文章推荐
- OKhttp的用法
- 新手之服务端创建服务以及客户端的实现
- android获取手机分辨率
- Android电话拨号器案例
- JSP使用include指令出现“Duplicate local variable basePath”错误提示
- 自动旋转的太极图
- Java中出现No enclosing instance of type XXX is accessible问题
- [李景山php]每天laravel[013]-laravel 中级任务翻译---添加任务
- 如何得到JavaVM,JNIEnv接口
- hadoop第二周作业
- CMS新闻DEMO
- 分针网—每日分享:Axios全攻略
- MyEclipse8.6破解方法
- iOS学习笔记-020.UIPageControl分页控件
- js检测关闭页面或浏览器
- java DateUtil 工具类 总结
- python学习13--pickle
- Web.xml配置详解
- Kubernetes 1.5安装 小提示
- 捕获异常,手动让Spring事务回滚