美文网首页
Fabric2.0.0 区块交易校验流程解析

Fabric2.0.0 区块交易校验流程解析

作者: liurenhao | 来源:发表于2023-02-28 10:05 被阅读0次

    gossip/privdata/coordinator.goStoreBlock方法中分别对区块交易和读写集进行了校验,关键代码如下:

    // 此方法对区块信息和交易签名等进行了校验
    err := c.Validator.Validate(block)
    ......
    ......
    // 此方法中对读写集进行了校验
    err = c.CommitLegacy(blockAndPvtData, &ledger.CommitOptions{})
    

    区块和交易校验

    先看区块和交易的校验,在core/committer/txvalidator/v20/validator.go中的Validate(block *common.Block)方法:

    func (v *TxValidator) Validate(block *common.Block) error {
        var err error
        var errPos int
    
        startValidation := time.Now() // timer to log Validate block duration
        logger.Debugf("[%s] START Block Validation for block [%d]", v.ChannelID, block.Header.Number)
    
        // Initialize trans as valid here, then set invalidation reason code upon invalidation below
        txsfltr := ledgerUtil.NewTxValidationFlags(len(block.Data.Data))
        // array of txids
        txidArray := make([]string, len(block.Data.Data))
    
        results := make(chan *blockValidationResult)
        go func() {
            for tIdx, d := range block.Data.Data {
                // ensure that we don't have too many concurrent validation workers
                v.Semaphore.Acquire(context.Background())
    
                go func(index int, data []byte) {
                    defer v.Semaphore.Release()
    
                    v.validateTx(&blockValidationRequest{
                        d:     data,
                        block: block,
                        tIdx:  index,
                    }, results)
                }(tIdx, d)
            }
        }()
    

    读写集校验

    core/ledger/kvledger/kv_ledger.goCommitLegacy方法中

    // 此处进行读写集校验
    txstatsInfo, updateBatchBytes, err := l.txtmgmt.ValidateAndPrepare(pvtdataAndBlock, true)
    

    上述方法实现在core/ledger/kvledger/txmgmt/txmgr/lockbasedtxmgr/lockbased_txmgr.go

    batch, txstatsInfo, err := txmgr.validator.ValidateAndPrepareBatch(blockAndPvtdata, doMVCCValidation)
    

    实现在core/ledger/kvledger/txmgmt/validator/valimpl/default_impl.go

    func (impl *DefaultImpl) ValidateAndPrepareBatch(blockAndPvtdata *ledger.BlockAndPvtData,
        doMVCCValidation bool) (*privacyenabledstate.UpdateBatch, []*txmgr.TxStatInfo, error) {
           // 此处进行第一次读写集校验   levelDB为空校验
        if internalBlock, txsStatInfo, err = preprocessProtoBlock(
            impl.txmgr,
            impl.db.ValidateKeyValue,
            block,
            doMVCCValidation,
            impl.customTxProcessors,
        ); err != nil {
            return nil, nil, err
        }
            // 此处进行读写集校验,包括了“双花”校验等
        if pubAndHashUpdates, err = impl.internalValidator.ValidateAndPrepareBatch(internalBlock, doMVCCValidation); err != nil {
            return nil, nil, err
        }
            // 此处是隐私数据读写集校验
        logger.Debug("validating rwset...")
        if pvtUpdates, err = validateAndPreparePvtBatch(
            internalBlock,
            impl.db,
            pubAndHashUpdates,
            blockAndPvtdata.PvtData,
            impl.customTxProcessors,
        ); err != nil {
            return nil, nil, err
        }
    
    }
    

    跟到core/ledger/kvledger/txmgmt/validator/statebasedval/state_based_validator.go中的validateEndorserTX方法

    func (v *Validator) validateEndorserTX(
        txRWSet *rwsetutil.TxRwSet,
        doMVCCValidation bool,
        updates *internal.PubAndHashUpdates) (peer.TxValidationCode, error) {
    
        var validationCode = peer.TxValidationCode_VALID
        var err error
        // 此处进行MVCC校验  
        if doMVCCValidation {
            validationCode, err = v.validateTx(txRWSet, updates)
        }
        return validationCode, err
    }
    

    MVCC Check是在读取账本中的键值对时进行的一种检查机制。在Hyperledger Fabric中,账本的每个版本都有一个对应的版本号,称为“交易编号”(transaction ID)。在读取账本中的某个键值对时,Peer节点首先获取当前账本中该键的最新版本号,并将该版本号与请求读取该键的事务的版本号进行比较,如果两个版本号相同,则表示读取操作是有效的。如果事务的版本号小于最新版本号,则Peer节点会拒绝读取请求,因为该事务读取的版本已经过期,不再是当前有效的版本。

    func (v *Validator) validateTx(txRWSet *rwsetutil.TxRwSet, updates *internal.PubAndHashUpdates) (peer.TxValidationCode, error) {
        // Uncomment the following only for local debugging. Don't want to print data in the logs in production
        //logger.Debugf("validateTx - validating txRWSet: %s", spew.Sdump(txRWSet))
        for _, nsRWSet := range txRWSet.NsRwSets {
            ns := nsRWSet.NameSpace
            // Validate public reads
            if valid, err := v.validateReadSet(ns, nsRWSet.KvRwSet.Reads, updates.PubUpdates); !valid || err != nil {
                if err != nil {
                    return peer.TxValidationCode(-1), err
                }
                return peer.TxValidationCode_MVCC_READ_CONFLICT, nil
            }
            // Validate range queries for phantom items
            if valid, err := v.validateRangeQueries(ns, nsRWSet.KvRwSet.RangeQueriesInfo, updates.PubUpdates); !valid || err != nil {
                if err != nil {
                    return peer.TxValidationCode(-1), err
                }
                return peer.TxValidationCode_PHANTOM_READ_CONFLICT, nil
            }
            // Validate hashes for private reads
            if valid, err := v.validateNsHashedReadSets(ns, nsRWSet.CollHashedRwSets, updates.HashUpdates); !valid || err != nil {
                if err != nil {
                    return peer.TxValidationCode(-1), err
                }
                return peer.TxValidationCode_MVCC_READ_CONFLICT, nil
            }
        }
        return peer.TxValidationCode_VALID, nil
    }
    

    相关文章

      网友评论

          本文标题:Fabric2.0.0 区块交易校验流程解析

          本文链接:https://www.haomeiwen.com/subject/sqnqldtx.html