hyperledger fabric 笔记(三)-----peer源码
2018-10-31 14:58
1086 查看
Committer的机制
commiter负责在接受交易结果前再次检查合法性,接受合法交易对账本的修改,并写入区块链结构
committer.go
[code]type Committer interface { // CommitWithPvtData block and private data into the ledger // 将区块和私有数据写入账本 CommitWithPvtData(blockAndPvtData *ledger.BlockAndPvtData) error // GetPvtDataAndBlockByNum retrieves block with private data with given // sequence number 使用给定的私有数据检索块 GetPvtDataAndBlockByNum(seqNum uint64) (*ledger.BlockAndPvtData, error) // GetPvtDataByNum returns a slice of the private data from the ledger // for given block and based on the filter which indicates a map of // collections and namespaces of private data to retrieve // 从给定区块中返回私有数据切片,并根据过滤器指示要检索的私有数据的集合和名称空间的映射 GetPvtDataByNum(blockNum uint64, filter ledger.PvtNsCollFilter) ([]*ledger.TxPvtData, error) // Get recent block sequence number // 获取最近的区块序列号 LedgerHeight() (uint64, error) // Gets blocks with sequence numbers provided in the slice // 根据参数提供的序列号获取区块 GetBlocks(blockSeqs []uint64) []*common.Block // Closes committing service // 关闭提交服务 Close() }
committer_impl.go
[code]// LedgerCommitter is the implementation of Committer interface // it keeps the reference to the ledger to commit blocks and retrieve // chain information // LedgerCommitter 是commiter接口的实现,它保持对账本的引用来提交区块和检索链信息 type LedgerCommitter struct { ledger.PeerLedger eventer ConfigBlockEventer } // ConfigBlockEventer callback function proto type to define action // upon arrival on new configuaration update block // ConfigBlockEventer 回调函数原型在到达新配置更新块时定义动作 type ConfigBlockEventer func(block *common.Block) error // NewLedgerCommitter is a factory function to create an instance of the committer // which passes incoming blocks via validation and commits them into the ledger. // NewLedgerCommitter 是一个工厂函数,用于创建提交者的一个实例,他通过验证传入传入块,并将它们提交到分类账中 func NewLedgerCommitter(ledger ledger.PeerLedger) *LedgerCommitter { return NewLedgerCommitterReactive(ledger, func(_ *common.Block) error { return nil }) } // NewLedgerCommitterReactive is a factory function to create an instance of the committer // same as way as NewLedgerCommitter, while also provides an option to specify callback to // be called upon new configuration block arrival and commit event // NewLedgerCommitterReactive 是一个工厂函数,用于创建与NewLedgerCommitter相同的提交者实例,同时还提供一个选项来指定在新的配置块到达和提交事件时调用的回调 func NewLedgerCommitterReactive(ledger ledger.PeerLedger, eventer ConfigBlockEventer) *LedgerCommitter { return &LedgerCommitter{PeerLedger: ledger, eventer: eventer} } // preCommit takes care to validate the block and update based on its // content // preCommit负责验证块并根据其内容进行更新 func (lc *LedgerCommitter) preCommit(block *common.Block) error { // Updating CSCC with new configuration block if utils.IsConfigBlock(block) { logger.Debug("Received configuration update, calling CSCC ConfigUpdate") if err := lc.eventer(block); err != nil { return errors.WithMessage(err, "could not update CSCC with new configuration update") } } return nil } // CommitWithPvtData commits blocks atomically with private data // CommitWithPvtData以私有数据自动提交块 func (lc *LedgerCommitter) CommitWithPvtData(blockAndPvtData *ledger.BlockAndPvtData) error { // Do validation and whatever needed before // committing new block if err := lc.preCommit(blockAndPvtData.Block); err != nil { return err } // Committing new block if err := lc.PeerLedger.CommitWithPvtData(blockAndPvtData); err != nil { return err } // post commit actions, such as event publishing lc.postCommit(blockAndPvtData.Block) return nil } // GetPvtDataAndBlockByNum retrieves private data and block for given sequence number // GetPvtDataAndBlockByNum通过给定的私有数据检索块序列号 func (lc *LedgerCommitter) GetPvtDataAndBlockByNum(seqNum uint64) (*ledger.BlockAndPvtData, error) { return lc.PeerLedger.GetPvtDataAndBlockByNum(seqNum, nil) } // postCommit publish event or handle other tasks once block committed to the ledger // postCommit 一旦提交到分类账本,则通过postcommit发布事件或处理其他任务 func (lc *LedgerCommitter) postCommit(block *common.Block) { // create/send block events *after* the block has been committed bevent, fbevent, channelID, err := producer.CreateBlockEvents(block) if err != nil { logger.Errorf("Channel [%s] Error processing block events for block number [%d]: %+v", channelID, block.Header.Number, err) } else { if err := producer.Send(bevent); err != nil { logger.Errorf("Channel [%s] Error sending block event for block number [%d]: %+v", channelID, block.Header.Number, err) } if err := producer.Send(fbevent); err != nil { logger.Errorf("Channel [%s] Error sending filtered block event for block number [%d]: %+v", channelID, block.Header.Number, err) } } } // LedgerHeight returns recently committed block sequence number // LedgerHeight返回最近提交的块顺序号 func (lc *LedgerCommitter) LedgerHeight() (uint64, error) { var info *common.BlockchainInfo var err error if info, err = lc.GetBlockchainInfo(); err != nil { logger.Errorf("Cannot get blockchain info, %s", info) return uint64(0), err } return info.Height, nil } // GetBlocks used to retrieve blocks with sequence numbers provided in the slice // GetBlocks 用于检索切片中提供的序号的块 func (lc *LedgerCommitter) GetBlocks(blockSeqs []uint64) []*common.Block { var blocks []*common.Block for _, seqNum := range blockSeqs { if blck, err := lc.GetBlockByNumber(seqNum); err != nil { logger.Errorf("Not able to acquire block num %d, from the ledger skipping...", seqNum) continue } else { logger.Debug("Appending next block with seqNum = ", seqNum, " to the resulting set") blocks = append(blocks, blck) } } return blocks }
validator.go
[code]// Support provides all of the needed to evaluate the VSCC // 提供了评估VSCC所需的所有支持 type Support interface { // Acquire implements semaphore-like acquire semantics // Acquire 实现信号量的获取语义 Acquire(ctx context.Context, n int64) error // Release implements semaphore-like release semantics // Release 实现了信号量释放语义 Release(n int64) // Ledger returns the ledger associated with this validator // Ledger返回与此验证程序相关联的账本 Ledger() ledger.PeerLedger // MSPManager returns the MSP manager for this channel // MSPManager 返回此channel的MSP管理器 MSPManager() msp.MSPManager // Apply attempts to apply a configtx to become the new config // Apply尝试使用configtx成为新的配置 Apply(configtx *common.ConfigEnvelope) error // GetMSPIDs returns the IDs for the application MSPs // that have been defined in the channel // GetMSPIDs返回已在channel中定义的应用程序MSP的ID GetMSPIDs(cid string) []string // Capabilities defines the capabilities for the application portion of this channel // Capabilities 定义此channel的应用程序部分的功能 Capabilities() channelconfig.ApplicationCapabilities // ChaincodeByName returns the definition (and whether they exist) // for a chaincode in a specific channel // ChaincodeByName 返回指定channel的chaincode定义,并判断是否存在 ChaincodeByName(chainname, ccname string) (resourcesconfig.ChaincodeDefinition, bool) } //Validator interface which defines API to validate block transactions // and return the bit array mask indicating invalid transactions which // didn't pass validation. // Validator 定义API以验证块事务并返回位数组掩码,指示未通过验证的无效事务 type Validator interface { Validate(block *common.Block) error } // private interface to decouple tx validator // and vscc execution, in order to increase // testability of txValidator // vsccValidator 用来解耦tx validator和vscc execution,以提高txValidator的可测性 type vsccValidator interface { VSCCValidateTx(payload *common.Payload, envBytes []byte, env *common.Envelope) (error, peer.TxValidationCode) } // vsccValidator implementation which used to call // vscc chaincode and validate block transactions // vsccValidatorImpl vsccValidator的实现,用于调用vscc chaincode并验证块事务 type vsccValidatorImpl struct { support Support ccprovider ccprovider.ChaincodeProvider sccprovider sysccprovider.SystemChaincodeProvider } // implementation of Validator interface, keeps // reference to the ledger to enable tx simulation // and execution of vscc // txValidator Validator的实现,继续参考账本以启用tx模拟和执行vscc type txValidator struct { support Support vscc vsccValidator } // NewTxValidator creates new transactions validator // NewTxValidator 创建新的事务验证器 func NewTxValidator(support Support) Validator { // Encapsulates interface implementation return &txValidator{support, &vsccValidatorImpl{ support: support, ccprovider: ccprovider.GetChaincodeProvider(), sccprovider: sysccprovider.GetSystemChaincodeProvider()}} } // Validate performs the validation of a block. The validation // of each transaction in the block is performed in parallel. // The approach is as follows: the committer thread starts the // tx validation function in a goroutine (using a semaphore to cap // the number of concurrent validating goroutines). The committer // thread then reads results of validation (in orderer of completion // of the goroutines) from the results channel. The goroutines // perform the validation of the txs in the block and enqueue the // validation result in the results channel. A few note-worthy facts: // 1) to keep the approach simple, the committer thread enqueues // all transactions in the block and then moves on to reading the // results. // 2) for parallel validation to work, it is important that the // validation function does not change the state of the system. // Otherwise the order in which validation is perform matters // and we have to resort to sequential validation (or some locking). // This is currently true, because the only function that affects // state is when a config transaction is received, but they are // guaranteed to be alone in the block. If/when this assumption // is violated, this code must be changed. /* Validate执行块的验证,并执行块中每个是事务的验证方法如下:提交程序线程在goroutine中启动tx验证函数, (使用信号量来限制并发验证goroutine的数量)。该thread然后从结果channel中读取验证结果(在完成goroutine的订购者中)。 goroutine执行块中txs的验证并将结果排入结果channel中 1)为了保持验证方法简单,提交者线程将块中的所有事务排入队列,然后继续读取结果 2)为了使并行验证正常工作,重要的是验证功能不会改变系统的状态。此处验证执行的顺序很重要,我们不得不求助于顺序验证(或者一些锁定) 。目前就是这样做的,因为影响状态的函数是收到交易并验证交易,但这必须保证交易独立在区块中,如果这个条件改变了,代码也要改变。 */ func (v *txValidator) Validate(block *common.Block) error // generateCCKey generates a unique identifier for chaincode in specific channel // generateCCKey 为特定channel中的chaincode生成唯一标识符 func (v *txValidator) generateCCKey(ccName, chainID string) string { return fmt.Sprintf("%s/%s", ccName, chainID) } // invalidTXsForUpgradeCC invalid all txs that should be invalided because of chaincode upgrade txs // invalidTXsForUpgradeCC 无效所有由于chaincode升级txs而应该被废止的txs func (v *txValidator) invalidTXsForUpgradeCC(txsChaincodeNames map[int]*sysccprovider.ChaincodeInstance, txsUpgradedChaincodes map[int]*sysccprovider.ChaincodeInstance, txsfltr ledgerUtil.TxValidationFlags) ledgerUtil.TxValidationFlags // GetInfoForValidate gets the ChaincodeInstance(with latest version) of tx, vscc and policy from lscc // GetInfoForValidate 从lscc获取tx、vscc和policy的chaincode实例(最新版本) func (v *vsccValidatorImpl) GetInfoForValidate(txid, chID, ccID string) (*sysccprovider.ChaincodeInstance, *sysccprovider.ChaincodeInstance, []byte, error) // txWritesToNamespace returns true if the supplied NsRwSet // performs a ledger write // txWritesToNamespace 确认提供NsRwSet执行账本写入 func (v *vsccValidatorImpl) txWritesToNamespace(ns *rwsetutil.NsRwSet) bool
阅读更多
相关文章推荐
- Hyperledger fabric0.6 peer启动过程源码分析
- Hyperledger Fabric处理Peer与Peer之间通信的源码解析
- HyperLedger Fabric:自顶向下的方法--第1篇 编译fabric源码及手工搭建单个Peer节点网络
- Hyperledger fabric 源码分析之 peer 服务启动过程
- Hyperledger Fabric的PBFT源码分析(一)
- hyperledger fabric0.6简析之peer start
- Hyperledger Fabric V1.0 学习笔记(一) Centos 7中的环境搭建
- Hyperledger Fabric源码解析
- Hyperledger Fabric笔记--kafka共识的多orderer集群部署
- Hyperledger Fabric 1.0 从零开始(四)——Fabric源码及镜像文件处理
- Hyperledger/fabric(v0.7) create and join peer to a new channel
- Hyperledger fabric 学习笔记: go语言 与 JSON
- (二) Hyperledger Fabric 启动你的第一个网络
- Hyperledger Fabric Client SDK for Go 下载与配置
- hyperledger fabric0.6 简析start
- Hyperledger Fabric V1.0学习之一---在mac上配置hyperledger fabric
- hyperledger fabric 1.0.5 分布式部署 (五)
- 在window下搭建即时即用的hyperledger fabric 的环境
- HyperLedger Fabric协议规范
- Hyperledger Fabric 1.0 实战开发系列 第二课 Fabric环境搭建