8 "github.com/davecgh/go-spew/spew"
10 "github.com/bytom/bytom/consensus"
11 "github.com/bytom/bytom/protocol/bc"
12 "github.com/bytom/bytom/protocol/bc/types"
13 "github.com/bytom/bytom/testutil"
16 func stringToBigInt(s string, base int) *big.Int {
17 result, _ := new(big.Int).SetString(s, base)
21 func TestNewBlockNode(t *testing.T) {
23 blockHeader *types.BlockHeader
25 wantBlockNode *BlockNode
28 blockHeader: &types.BlockHeader{
32 parentNode: &BlockNode{},
33 wantBlockNode: &BlockNode{
34 Hash: testutil.MustDecodeHash("f1a5a6ddebad7285928a07ce1534104a8d1cd435fc80e90bb9f0034bbe5f8109"),
35 Seed: consensus.InitialSeed,
40 blockHeader: &types.BlockHeader{
44 parentNode: &BlockNode{},
45 wantBlockNode: &BlockNode{
46 Hash: testutil.MustDecodeHash("b14067726f09d74da89aeb97ca1b15a8b95760b47a0d71549b0aa5ab8c5e724f"),
47 Seed: consensus.InitialSeed,
53 blockHeader: &types.BlockHeader{
57 parentNode: &BlockNode{},
58 wantBlockNode: &BlockNode{
59 Hash: testutil.MustDecodeHash("b14067726f09d74da89aeb97ca1b15a8b95760b47a0d71549b0aa5ab8c5e724f"),
60 Seed: consensus.InitialSeed,
67 for i, c := range cases {
68 blockNode, err := NewBlockNode(c.blockHeader, c.parentNode)
73 if !reflect.DeepEqual(blockNode, c.wantBlockNode) {
74 t.Fatal("NewBlockNode test error, index:", i, "want:", spew.Sdump(c.wantBlockNode), "got:", spew.Sdump(blockNode))
79 func TestCalcPastMedianTime(t *testing.T) {
85 Timestamps: []uint64{1},
89 Timestamps: []uint64{1, 2},
93 Timestamps: []uint64{1, 3, 2},
97 Timestamps: []uint64{1, 3, 2, 3},
101 Timestamps: []uint64{1, 2, 3, 4, 5, 6, 7, 8, 11, 10, 9},
105 Timestamps: []uint64{1, 2, 3, 4, 5, 6, 7, 8, 11, 10, 9, 11, 11, 11, 14},
110 for idx, c := range cases {
111 var parentNode *BlockNode
112 for i := range c.Timestamps {
113 blockHeader := &types.BlockHeader{
115 Timestamp: c.Timestamps[i],
118 blockNode, err := NewBlockNode(blockHeader, parentNode)
122 parentNode = blockNode
125 medianTime := parentNode.CalcPastMedianTime()
126 if medianTime != c.MedianTime {
127 t.Fatalf("calc median timestamp failed, index: %d, expected: %d, have: %d", idx, c.MedianTime, medianTime)
132 func TestCalcNextSeed(t *testing.T) {
141 seed: consensus.InitialSeed,
145 Height: consensus.SeedPerRetarget - 1,
146 Seed: &bc.Hash{V1: 100},
148 seed: &bc.Hash{V1: 100},
152 Height: consensus.SeedPerRetarget,
153 Seed: &bc.Hash{V2: 200},
154 Hash: bc.Hash{V3: 300},
156 seed: &bc.Hash{V3: 300},
160 for i, c := range cases {
161 seed := c.node.CalcNextSeed()
162 if *seed != *c.seed {
163 t.Fatalf("calc next seed failed, index: %d, expected: %v, have: %v", i, c.seed, seed)
168 func TestSetMainChain(t *testing.T) {
169 blockIndex := NewBlockIndex()
170 var lastNode *BlockNode
171 for i := uint64(0); i < 4; i++ {
174 Hash: bc.Hash{V0: i},
177 blockIndex.AddNode(node)
182 blockIndex.SetMainChain(lastNode)
183 for lastNode.Parent != nil {
184 if !blockIndex.InMainchain(lastNode.Hash) {
185 t.Fatalf("block %d, hash %v is not in main chain", lastNode.Height, lastNode.Hash)
187 lastNode = lastNode.Parent
190 // fork and set main chain
191 forkHeight := uint64(1)
192 lastNode = blockIndex.nodeByHeight(forkHeight)
193 for i := uint64(1); i <= 3; i++ {
195 Height: lastNode.Height + 1,
196 Hash: bc.Hash{V1: uint64(i)},
199 blockIndex.AddNode(node)
204 blockIndex.SetMainChain(lastNode)
205 for lastNode.Parent != nil {
206 if !blockIndex.InMainchain(lastNode.Hash) {
207 t.Fatalf("after fork, block %d, hash %v is not in main chain", lastNode.Height, lastNode.Hash)
209 lastNode = lastNode.Parent
212 if bestNode != blockIndex.BestNode() {
213 t.Fatalf("check best node failed")
216 for tailNode.Parent != nil && tailNode.Height > forkHeight {
217 if blockIndex.InMainchain(tailNode.Hash) {
218 t.Fatalf("old chain block %d, hash %v still in main chain", tailNode.Height, tailNode.Hash)
220 tailNode = tailNode.Parent
224 // MockBlockIndex will mock a empty BlockIndex
225 func MockBlockIndex() *BlockIndex {
227 index: make(map[bc.Hash]*BlockNode),
228 mainChain: make([]*BlockNode, 0, 2),
232 func TestSetMainChainExtendCap(t *testing.T) {
233 blockIndex := MockBlockIndex()
234 var lastNode *BlockNode
246 wantCap: 500 + approxNodesPerDay,
252 wantCap: 500 + approxNodesPerDay,
258 wantCap: 2000 + approxNodesPerDay,
262 for num, c := range cases {
263 for i := c.start; i < c.stop; i++ {
266 Hash: bc.Hash{V0: i},
269 blockIndex.AddNode(node)
272 blockIndex.SetMainChain(lastNode)
273 if c.wantLen != len(blockIndex.mainChain) || c.wantCap != cap(blockIndex.mainChain) {
274 t.Fatalf("SetMainChain extended capacity error, index: %d, got len: %d, got cap: %d, want len: %d, want cap: %d", num, len(blockIndex.mainChain), cap(blockIndex.mainChain), c.wantLen, c.wantCap)
278 for i := 0; i < len(blockIndex.mainChain); i++ {
279 if blockIndex.mainChain[i] != blockIndex.index[blockIndex.mainChain[i].Hash] {
280 t.Fatal("SetMainChain extended capacity error, index:", i, "want:", spew.Sdump(blockIndex.mainChain[i]), "got:", spew.Sdump(blockIndex.index[blockIndex.mainChain[i].Hash]))