github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/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/osdi23p228/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  }