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 }