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