您的位置:首页 > 其它

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

 

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: