github.com/aergoio/aergo@v1.3.1/consensus/impl/dpos/lib_test.go (about) 1 package dpos 2 3 import ( 4 "fmt" 5 "testing" 6 7 "github.com/aergoio/aergo/internal/enc" 8 "github.com/aergoio/aergo/types" 9 "github.com/libp2p/go-libp2p-core/crypto" 10 "github.com/stretchr/testify/assert" 11 ) 12 13 type testChain struct { 14 chain []*types.Block 15 status *Status 16 bestNo types.BlockNo 17 18 bpid string 19 lpb map[string]types.BlockNo 20 bpKey []crypto.PrivKey 21 bpClusterSize uint16 22 } 23 24 type testCluster struct { 25 size uint16 26 } 27 28 func (c *testCluster) Size() uint16 { 29 return c.size 30 } 31 32 func (c *testCluster) Update(ids []string) error { 33 return nil 34 } 35 36 func newTestChain(clusterSize uint16) (*testChain, error) { 37 bpKey := make([]crypto.PrivKey, int(clusterSize)) 38 for i := 0; i < int(clusterSize); i++ { 39 var err error 40 bpKey[i], _, err = crypto.GenerateKeyPair(crypto.Secp256k1, 256) 41 if err != nil { 42 return nil, err 43 } 44 } 45 46 b, err := bpKey[0].GetPublic().Bytes() 47 if err != nil { 48 return nil, err 49 } 50 51 tc := &testChain{ 52 chain: make([]*types.Block, 0), 53 status: NewStatus(&testCluster{size: clusterSize}, nil, nil, 0), 54 bpid: enc.ToString(b), 55 lpb: make(map[string]types.BlockNo), 56 bpKey: bpKey, 57 bpClusterSize: clusterSize, 58 } 59 tc.setGenesis(types.NewBlock(nil, nil, nil, nil, nil, 0)) 60 61 // Prevent DB access 62 tc.status.done = true 63 64 return tc, nil 65 } 66 67 func (tc *testChain) setGenesis(block *types.Block) { 68 if block.BlockNo() != 0 { 69 panic("invalid genesis block: non-zero block no") 70 } 71 tc.status.libState.genesisInfo = &blockInfo{BlockHash: block.ID(), BlockNo: 0} 72 tc.status.bestBlock = block 73 tc.chain = append(tc.chain, block) 74 } 75 76 func (tc *testChain) addBlock(i types.BlockNo) error { 77 pk := tc.getBpKey(i % types.BlockNo(tc.bpClusterSize)) 78 b, err := pk.Bytes() 79 if err != nil { 80 return err 81 } 82 spk := enc.ToString(b) 83 84 prevBlock := tc.chain[len(tc.chain)-1] 85 block := types.NewBlock(prevBlock, nil, nil, nil, nil, 0) 86 87 confirmNo := func(no types.BlockNo) (confirms types.BlockNo) { 88 lpb := types.BlockNo(0) 89 if v, exist := tc.lpb[spk]; exist { 90 lpb = v 91 } 92 confirms = no - lpb 93 94 return 95 } 96 block.SetConfirms(confirmNo(block.BlockNo())) 97 98 if err = block.Sign(pk); err != nil { 99 return err 100 } 101 102 tc.lpb[spk] = block.BlockNo() 103 104 tc.chain = append(tc.chain, block) 105 tc.bestNo = types.BlockNo(len(tc.chain) - 1) 106 tc.status.Update(block) 107 108 return nil 109 } 110 111 func (tc *testChain) getBpKey(i types.BlockNo) crypto.PrivKey { 112 return tc.bpKey[i%types.BlockNo(tc.bpClusterSize)] 113 } 114 115 func TestTestChain(t *testing.T) { 116 const ( 117 clusterSize = 3 118 maxBlockNo = types.BlockNo(clusterSize) * 20 119 ) 120 121 a := assert.New(t) 122 tc, err := newTestChain(clusterSize) 123 a.Nil(err) 124 125 for i := types.BlockNo(1); i <= maxBlockNo; i++ { 126 a.Nil(tc.addBlock(i)) 127 fmt.Println("LIB:", tc.status.libState.Lib.BlockNo) 128 } 129 130 a.Equal(tc.bestNo, maxBlockNo) 131 a.Equal(tc.status.libState.Lib.BlockNo, maxBlockNo-clusterSize-1) 132 } 133 134 func TestNumLimitGC(t *testing.T) { 135 const ( 136 clusterSize = 23 137 consensusCount = clusterSize*2/3 + 1 138 ) 139 140 a := assert.New(t) 141 142 ls := newLibStatus(consensusCount) 143 144 for i := 1; i <= clusterSize*3; i++ { 145 ls.confirms.PushBack( 146 &confirmInfo{ 147 blockInfo: &blockInfo{BlockNo: types.BlockNo(i)}, 148 }) 149 } 150 151 ls.gc() 152 a.True(ls.confirms.Len() <= ls.gcNumLimit()) 153 } 154 155 func TestLibGC(t *testing.T) { 156 const ( 157 clusterSize = 23 158 consensusCount = clusterSize*2/3 + 1 159 libNo = 3 160 ) 161 162 a := assert.New(t) 163 164 ls := newLibStatus(consensusCount) 165 ls.Lib = &blockInfo{BlockNo: libNo} 166 167 for i := 1; i <= clusterSize*3; i++ { 168 ls.confirms.PushBack( 169 &confirmInfo{ 170 blockInfo: &blockInfo{BlockNo: types.BlockNo(i)}, 171 }) 172 } 173 174 ls.gc() 175 a.True(cInfo(ls.confirms.Front()).blockInfo.BlockNo > libNo) 176 }