Hyperledger Fabric创世纪块源码解析

Hyperledger Fabric创世纪块源码解析_第1张图片
Hyperledger Fabric创世纪块源码解析_第2张图片

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
}

你可能感兴趣的:(Hyperledger,Fabric,区块链技术)