github.com/koko1123/flow-go-1@v0.29.6/consensus/hotstuff/forks/test/block_builder.go (about)

     1  package test
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/koko1123/flow-go-1/consensus/hotstuff/forks"
     7  	"github.com/koko1123/flow-go-1/consensus/hotstuff/model"
     8  	"github.com/koko1123/flow-go-1/model/flow"
     9  )
    10  
    11  // BlockView specifies the data to create a block
    12  type BlockView struct {
    13  	View uint64 // the view of the block to be created
    14  
    15  	// the version of the block for that view.  useful for creating a different block of the same view with a different version
    16  	BlockVersion int
    17  
    18  	QCView uint64 // the view for the QC to be built on top of
    19  
    20  	// the version of the QC for that view.
    21  	QCVersion int
    22  }
    23  
    24  func (bv *BlockView) QCIndex() string {
    25  	return fmt.Sprintf("%v-%v", bv.QCView, bv.QCVersion)
    26  }
    27  
    28  func (bv *BlockView) BlockIndex() string {
    29  	return fmt.Sprintf("%v-%v", bv.View, bv.BlockVersion)
    30  }
    31  
    32  type BlockBuilder struct {
    33  	blockViews []*BlockView
    34  }
    35  
    36  func NewBlockBuilder() *BlockBuilder {
    37  	return &BlockBuilder{
    38  		blockViews: make([]*BlockView, 0),
    39  	}
    40  }
    41  
    42  func (f *BlockBuilder) Add(qcView uint64, blockView uint64) {
    43  	f.blockViews = append(f.blockViews, &BlockView{
    44  		View:   blockView,
    45  		QCView: qcView,
    46  	})
    47  }
    48  
    49  // [3,4] denotes a block of view 4, with a qc of view 3.
    50  // [3,4'] denotes a block of view 4, with a qc of view 3, but has a different BlockID than [3,4],
    51  // [3,4'] can be created by AddVersioned(3, 4, 0, 1)
    52  // [3',4] can be created by AddVersioned(3, 4, 1, 0)
    53  func (f *BlockBuilder) AddVersioned(qcView uint64, blockView uint64, qcversion int, blockversion int) {
    54  	f.blockViews = append(f.blockViews, &BlockView{
    55  		View:         blockView,
    56  		QCView:       qcView,
    57  		BlockVersion: blockversion,
    58  		QCVersion:    qcversion,
    59  	})
    60  }
    61  
    62  func (f *BlockBuilder) Blocks() ([]*model.Block, error) {
    63  	blocks := make([]*model.Block, 0, len(f.blockViews))
    64  
    65  	genesisBQ := makeGenesis()
    66  	genesisBV := &BlockView{
    67  		View:   genesisBQ.Block.View,
    68  		QCView: genesisBQ.QC.View,
    69  	}
    70  
    71  	qcs := make(map[string]*flow.QuorumCertificate)
    72  	qcs[genesisBV.QCIndex()] = genesisBQ.QC
    73  
    74  	for _, bv := range f.blockViews {
    75  		qc, ok := qcs[bv.QCIndex()]
    76  		if !ok {
    77  			return nil, fmt.Errorf("test fail: no qc found for qc index: %v", bv.QCIndex())
    78  		}
    79  		payloadHash := makePayloadHash(bv.View, qc, bv.BlockVersion)
    80  		block := &model.Block{
    81  			View:        bv.View,
    82  			QC:          qc,
    83  			PayloadHash: payloadHash,
    84  		}
    85  		block.BlockID = makeBlockID(block)
    86  
    87  		blocks = append(blocks, block)
    88  
    89  		// generate QC for the new block
    90  		qcs[bv.BlockIndex()] = &flow.QuorumCertificate{
    91  			View:          block.View,
    92  			BlockID:       block.BlockID,
    93  			SignerIndices: nil,
    94  			SigData:       nil,
    95  		}
    96  	}
    97  
    98  	return blocks, nil
    99  }
   100  
   101  func makePayloadHash(view uint64, qc *flow.QuorumCertificate, blockVersion int) flow.Identifier {
   102  	return flow.MakeID(struct {
   103  		View         uint64
   104  		QC           *flow.QuorumCertificate
   105  		BlockVersion uint64
   106  	}{
   107  		View:         view,
   108  		QC:           qc,
   109  		BlockVersion: uint64(blockVersion),
   110  	})
   111  }
   112  
   113  func makeBlockID(block *model.Block) flow.Identifier {
   114  	return flow.MakeID(struct {
   115  		View        uint64
   116  		QC          *flow.QuorumCertificate
   117  		PayloadHash flow.Identifier
   118  	}{
   119  		View:        block.View,
   120  		QC:          block.QC,
   121  		PayloadHash: block.PayloadHash,
   122  	})
   123  }
   124  
   125  func makeGenesis() *forks.BlockQC {
   126  	genesis := &model.Block{
   127  		View: 1,
   128  	}
   129  	genesis.BlockID = makeBlockID(genesis)
   130  
   131  	genesisQC := &flow.QuorumCertificate{
   132  		View:    1,
   133  		BlockID: genesis.BlockID,
   134  	}
   135  	genesisBQ := &forks.BlockQC{
   136  		Block: genesis,
   137  		QC:    genesisQC,
   138  	}
   139  	return genesisBQ
   140  }