Fabric 1.0原始碼分析(26)Orderer #ledger(Orderer Ledger)

尹成發表於2018-05-20
# Fabric 1.0原始碼筆記 之 Orderer #ledger(Orderer Ledger)

## 1、Orderer Ledger概述

Orderer Ledger程式碼分佈在orderer/ledger目錄下,目錄結構如下:

* orderer/ledger目錄:
    * ledger.go,Factory、Iterator、Reader、Writer、ReadWriter等介面定義。
    * util.go,Orderer Ledger工具函式,及NotFoundErrorIterator結構體定義。
    * file目錄,file型別ledger實現。
    * json目錄,json型別ledger實現。
    * ram目錄,記憶體型別ledger實現。
    
## 2、介面定義

Factory介面定義:

```go
type Factory interface {
    //按chainID獲取已存在的ledger,如不存在則建立
    GetOrCreate(chainID string) (ReadWriter, error)
    //獲取ChainID列表
    ChainIDs() []string
    //關閉並釋放所有資源
    Close()
}
//程式碼在orderer/ledger/ledger.go
```

ReadWriter介面定義:

```go
type Reader interface {
    //按起始塊號獲取迭代器
    Iterator(startType *ab.SeekPosition) (Iterator, uint64)
    //獲取ledger高度(即塊數)
    Height() uint64
}

type Writer interface {
    //ledger向追加新塊
    Append(block *cb.Block) error
}

type ReadWriter interface {
    Reader //嵌入Reader
    Writer //嵌入Writer
}

type Iterator interface {
    //獲取下一個可用的塊
    Next() (*cb.Block, cb.Status)
    //獲取可用的通道
    ReadyChan() <-chan struct{}
}
//程式碼在orderer/ledger/ledger.go
```

## 3、file型別ledger實現

### 3.1、fileLedgerFactory結構體及方法(實現Factory介面)

```go
type fileLedgerFactory struct {
    blkstorageProvider blkstorage.BlockStoreProvider //blkstorage
    ledgers map[string]ledger.ReadWriter //多鏈
    mutex sync.Mutex
}

//從ledgers中查詢,如找到則返回,否則建立Ledger(即blkstorage)並構造fileLedger
func (flf *fileLedgerFactory) GetOrCreate(chainID string) (ledger.ReadWriter, error)
//獲取已存在的Ledger列表,調取flf.blkstorageProvider.List()
func (flf *fileLedgerFactory) ChainIDs() []string
//關閉並釋放資源flf.blkstorageProvider.Close()
func (flf *fileLedgerFactory) Close()
//構造fileLedgerFactory
func New(directory string) ledger.Factory
//程式碼在orderer/ledger/file/factory.go
```

blkstorage更詳細內容,可參考:[Fabric 1.0原始碼筆記 之 Ledger #blkstorage(block檔案儲存)](../ledger/blkstorage.md)

### 3.2、fileLedger結構體及方法(實現ReadWriter介面)

```go
type fileLedger struct {
    blockStore blkstorage.BlockStore //blkstorage
    signal chan struct{}
}

//按起始塊號獲取迭代器
func (fl *fileLedger) Iterator(startPosition *ab.SeekPosition) (ledger.Iterator, uint64)
//獲取ledger高度(即塊數)
func (fl *fileLedger) Height() uint64
//ledger向追加新塊
func (fl *fileLedger) Append(block *cb.Block) error
//程式碼在orderer/ledger/file/impl.go
```

### 3.3、fileLedgerIterator結構體及方法(實現Iterator介面)

```go
type fileLedgerIterator struct {
    ledger *fileLedger
    blockNumber uint64 //當前已迭代的塊號
}
//獲取下一個可用的塊,如果沒有可用的塊則阻止
func (i *fileLedgerIterator) Next() (*cb.Block, cb.Status)
//獲取可用的通道,如果塊不可用返回signal,否則返回closedChan
func (i *fileLedgerIterator) ReadyChan() <-chan struct{}
//程式碼在orderer/ledger/file/impl.go
```

## 4、Orderer Ledger工具函式

```go
//建立塊
func CreateNextBlock(rl Reader, messages []*cb.Envelope) *cb.Block
func GetBlock(rl Reader, index uint64) *cb.Block
//地址在orderer/ledger/util.go
```

func CreateNextBlock(rl Reader, messages []*cb.Envelope) *cb.Block程式碼如下:

```go
func CreateNextBlock(rl Reader, messages []*cb.Envelope) *cb.Block {
    var nextBlockNumber uint64
    var previousBlockHash []byte

    if rl.Height() > 0 {
        it, _ := rl.Iterator(&ab.SeekPosition{
            Type: &ab.SeekPosition_Newest{
                &ab.SeekNewest{},
            },
        })
        <-it.ReadyChan()
        block, status := it.Next() //獲取前一個最新的塊
        nextBlockNumber = block.Header.Number + 1
        previousBlockHash = block.Header.Hash() //前一個最新的塊的雜湊
    }

    data := &cb.BlockData{
        Data: make([][]byte, len(messages)),
    }

    var err error
    for i, msg := range messages {
        data.Data[i], err = proto.Marshal(msg) //逐一填充資料
    }

    block := cb.NewBlock(nextBlockNumber, previousBlockHash)
    block.Header.DataHash = data.Hash()
    block.Data = data

    return block
}
//地址在orderer/ledger/util.go
```






網址:http://www.qukuailianxueyuan.io/



欲領取造幣技術與全套虛擬機器資料

區塊鏈技術交流QQ群:756146052  備註:CSDN

尹成學院微信:備註:CSDN




網址:http://www.qukuailianxueyuan.io/



欲領取造幣技術與全套虛擬機器資料

區塊鏈技術交流QQ群:756146052  備註:CSDN

尹成學院微信:備註:CSDN

相關文章