github.com/lzy4123/fabric@v2.1.1+incompatible/common/ledger/blockledger/util.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package blockledger 8 9 import ( 10 "github.com/golang/protobuf/proto" 11 cb "github.com/hyperledger/fabric-protos-go/common" 12 ab "github.com/hyperledger/fabric-protos-go/orderer" 13 "github.com/hyperledger/fabric/protoutil" 14 ) 15 16 var closedChan chan struct{} 17 18 func init() { 19 closedChan = make(chan struct{}) 20 close(closedChan) 21 } 22 23 // NotFoundErrorIterator simply always returns an error of cb.Status_NOT_FOUND, 24 // and is generally useful for implementations of the Reader interface 25 type NotFoundErrorIterator struct{} 26 27 // Next returns nil, cb.Status_NOT_FOUND 28 func (nfei *NotFoundErrorIterator) Next() (*cb.Block, cb.Status) { 29 return nil, cb.Status_NOT_FOUND 30 } 31 32 // ReadyChan returns a closed channel 33 func (nfei *NotFoundErrorIterator) ReadyChan() <-chan struct{} { 34 return closedChan 35 } 36 37 // Close does nothing 38 func (nfei *NotFoundErrorIterator) Close() {} 39 40 // CreateNextBlock provides a utility way to construct the next block from 41 // contents and metadata for a given ledger 42 // XXX This will need to be modified to accept marshaled envelopes 43 // to accommodate non-deterministic marshaling 44 func CreateNextBlock(rl Reader, messages []*cb.Envelope) *cb.Block { 45 var nextBlockNumber uint64 46 var previousBlockHash []byte 47 var err error 48 49 if rl.Height() > 0 { 50 it, _ := rl.Iterator(&ab.SeekPosition{ 51 Type: &ab.SeekPosition_Newest{ 52 Newest: &ab.SeekNewest{}, 53 }, 54 }) 55 block, status := it.Next() 56 if status != cb.Status_SUCCESS { 57 panic("Error seeking to newest block for chain with non-zero height") 58 } 59 nextBlockNumber = block.Header.Number + 1 60 previousBlockHash = protoutil.BlockHeaderHash(block.Header) 61 } 62 63 data := &cb.BlockData{ 64 Data: make([][]byte, len(messages)), 65 } 66 67 for i, msg := range messages { 68 data.Data[i], err = proto.Marshal(msg) 69 if err != nil { 70 panic(err) 71 } 72 } 73 74 block := protoutil.NewBlock(nextBlockNumber, previousBlockHash) 75 block.Header.DataHash = protoutil.BlockDataHash(data) 76 block.Data = data 77 78 return block 79 } 80 81 // GetBlock is a utility method for retrieving a single block 82 func GetBlock(rl Reader, index uint64) *cb.Block { 83 iterator, _ := rl.Iterator(&ab.SeekPosition{ 84 Type: &ab.SeekPosition_Specified{ 85 Specified: &ab.SeekSpecified{Number: index}, 86 }, 87 }) 88 if iterator == nil { 89 return nil 90 } 91 defer iterator.Close() 92 block, status := iterator.Next() 93 if status != cb.Status_SUCCESS { 94 return nil 95 } 96 return block 97 }