9 "github.com/davecgh/go-spew/spew"
11 "github.com/bytom/consensus"
12 "github.com/bytom/consensus/difficulty"
13 "github.com/bytom/protocol/bc"
14 "github.com/bytom/protocol/bc/types"
15 "github.com/bytom/testutil"
18 func stringToBigInt(s string, base int) *big.Int {
19 result, _ := new(big.Int).SetString(s, base)
23 func TestNewBlockNode(t *testing.T) {
25 blockHeader *types.BlockHeader
27 wantBlockNode *BlockNode
30 blockHeader: &types.BlockHeader{
35 parentNode: &BlockNode{
38 wantBlockNode: &BlockNode{
40 Hash: testutil.MustDecodeHash("f1a5a6ddebad7285928a07ce1534104a8d1cd435fc80e90bb9f0034bbe5f8109"),
41 Seed: consensus.InitialSeed,
42 WorkSum: new(big.Int).SetInt64(0),
49 blockHeader: &types.BlockHeader{
54 parentNode: &BlockNode{
55 WorkSum: new(big.Int).SetInt64(100),
57 wantBlockNode: &BlockNode{
59 Hash: testutil.MustDecodeHash("b14067726f09d74da89aeb97ca1b15a8b95760b47a0d71549b0aa5ab8c5e724f"),
60 Seed: consensus.InitialSeed,
62 WorkSum: stringToBigInt("193956598387464313942329958138505708296934647681139973265423088790474254103", 10),
64 WorkSum: new(big.Int).SetInt64(100),
69 blockHeader: &types.BlockHeader{
74 parentNode: &BlockNode{
75 WorkSum: new(big.Int).SetInt64(math.MaxInt64),
77 wantBlockNode: &BlockNode{
79 Hash: testutil.MustDecodeHash("b14067726f09d74da89aeb97ca1b15a8b95760b47a0d71549b0aa5ab8c5e724f"),
80 Seed: consensus.InitialSeed,
82 WorkSum: stringToBigInt("193956598387464313942329958138505708296934647681139973274646460827329029810", 10),
84 WorkSum: new(big.Int).SetInt64(math.MaxInt64),
90 for i, c := range cases {
91 blockNode, err := NewBlockNode(c.blockHeader, c.parentNode)
96 if !reflect.DeepEqual(blockNode, c.wantBlockNode) {
97 t.Fatal("NewBlockNode test error, index:", i, "want:", spew.Sdump(c.wantBlockNode), "got:", spew.Sdump(blockNode))
102 func TestCalcPastMedianTime(t *testing.T) {
108 Timestamps: []uint64{1},
112 Timestamps: []uint64{1, 2},
116 Timestamps: []uint64{1, 3, 2},
120 Timestamps: []uint64{1, 3, 2, 3},
124 Timestamps: []uint64{1, 2, 3, 4, 5, 6, 7, 8, 11, 10, 9},
128 Timestamps: []uint64{1, 2, 3, 4, 5, 6, 7, 8, 11, 10, 9, 11, 11, 11, 14},
133 for idx, c := range cases {
134 var parentNode *BlockNode
135 for i := range c.Timestamps {
136 blockHeader := &types.BlockHeader{
138 Timestamp: c.Timestamps[i],
141 blockNode, err := NewBlockNode(blockHeader, parentNode)
145 parentNode = blockNode
148 medianTime := parentNode.CalcPastMedianTime()
149 if medianTime != c.MedianTime {
150 t.Fatalf("calc median timestamp failed, index: %d, expected: %d, have: %d", idx, c.MedianTime, medianTime)
155 func TestCalcNextBits(t *testing.T) {
156 targetTimeSpan := uint64(consensus.BlocksPerRetarget * consensus.TargetSecondsPerBlock)
158 parentNode *BlockNode
159 currentNode *BlockNode
163 currentNode: &BlockNode{
170 currentNode: &BlockNode{
171 Height: consensus.BlocksPerRetarget - 1,
177 parentNode: &BlockNode{
181 currentNode: &BlockNode{
182 Height: consensus.BlocksPerRetarget,
183 Bits: difficulty.BigToCompact(big.NewInt(1000)),
184 Timestamp: targetTimeSpan,
186 bits: difficulty.BigToCompact(big.NewInt(1000)),
189 parentNode: &BlockNode{
193 currentNode: &BlockNode{
194 Height: consensus.BlocksPerRetarget,
195 Bits: difficulty.BigToCompact(big.NewInt(1000)),
196 Timestamp: targetTimeSpan * 2,
198 bits: difficulty.BigToCompact(big.NewInt(2000)),
202 for i, c := range cases {
203 c.currentNode.Parent = c.parentNode
204 bits := c.currentNode.CalcNextBits()
206 t.Fatalf("calc next bit failed, index: %d, expected: %d, have: %d", i, c.bits, bits)
211 func TestCalcNextSeed(t *testing.T) {
220 seed: consensus.InitialSeed,
224 Height: consensus.SeedPerRetarget - 1,
225 Seed: &bc.Hash{V1: 100},
227 seed: &bc.Hash{V1: 100},
231 Height: consensus.SeedPerRetarget,
232 Seed: &bc.Hash{V2: 200},
233 Hash: bc.Hash{V3: 300},
235 seed: &bc.Hash{V3: 300},
239 for i, c := range cases {
240 seed := c.node.CalcNextSeed()
241 if *seed != *c.seed {
242 t.Fatalf("calc next seed failed, index: %d, expected: %v, have: %v", i, c.seed, seed)
247 func TestSetMainChain(t *testing.T) {
248 blockIndex := NewBlockIndex()
249 var lastNode *BlockNode
250 for i := uint64(0); i < 4; i++ {
253 Hash: bc.Hash{V0: i},
256 blockIndex.AddNode(node)
261 blockIndex.SetMainChain(lastNode)
262 for lastNode.Parent != nil {
263 if !blockIndex.InMainchain(lastNode.Hash) {
264 t.Fatalf("block %d, hash %v is not in main chain", lastNode.Height, lastNode.Hash)
266 lastNode = lastNode.Parent
269 // fork and set main chain
270 forkHeight := uint64(1)
271 lastNode = blockIndex.nodeByHeight(forkHeight)
272 for i := uint64(1); i <= 3; i++ {
274 Height: lastNode.Height + 1,
275 Hash: bc.Hash{V1: uint64(i)},
278 blockIndex.AddNode(node)
283 blockIndex.SetMainChain(lastNode)
284 for lastNode.Parent != nil {
285 if !blockIndex.InMainchain(lastNode.Hash) {
286 t.Fatalf("after fork, block %d, hash %v is not in main chain", lastNode.Height, lastNode.Hash)
288 lastNode = lastNode.Parent
291 if bestNode != blockIndex.BestNode() {
292 t.Fatalf("check best node failed")
295 for tailNode.Parent != nil && tailNode.Height > forkHeight {
296 if blockIndex.InMainchain(tailNode.Hash) {
297 t.Fatalf("old chain block %d, hash %v still in main chain", tailNode.Height, tailNode.Hash)
299 tailNode = tailNode.Parent
303 // MockBlockIndex will mock a empty BlockIndex
304 func MockBlockIndex() *BlockIndex {
306 index: make(map[bc.Hash]*BlockNode),
307 mainChain: make([]*BlockNode, 0, 2),
311 func TestSetMainChainExtendCap(t *testing.T) {
312 blockIndex := MockBlockIndex()
313 var lastNode *BlockNode
325 wantCap: 500 + approxNodesPerDay,
331 wantCap: 500 + approxNodesPerDay,
337 wantCap: 2000 + approxNodesPerDay,
341 for num, c := range cases {
342 for i := c.start; i < c.stop; i++ {
345 Hash: bc.Hash{V0: i},
348 blockIndex.AddNode(node)
351 blockIndex.SetMainChain(lastNode)
352 if c.wantLen != len(blockIndex.mainChain) || c.wantCap != cap(blockIndex.mainChain) {
353 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)
357 for i := 0; i < len(blockIndex.mainChain); i++ {
358 if blockIndex.mainChain[i] != blockIndex.index[blockIndex.mainChain[i].Hash] {
359 t.Fatal("SetMainChain extended capacity error, index:", i, "want:", spew.Sdump(blockIndex.mainChain[i]), "got:", spew.Sdump(blockIndex.index[blockIndex.mainChain[i].Hash]))