OSDN Git Service

blockindex unit tests
authorlbqds <lbqds@outlook.com>
Thu, 19 Apr 2018 07:29:12 +0000 (15:29 +0800)
committerlbqds <lbqds@outlook.com>
Thu, 19 Apr 2018 08:32:18 +0000 (16:32 +0800)
protocol/orphan_manage.go
protocol/state/blockindex.go
protocol/state/blockindex_test.go [new file with mode: 0644]
protocol/validation/block_test.go

index 20067e1..0399ffd 100644 (file)
@@ -49,7 +49,7 @@ func (o *OrphanManage) Add(block *types.Block) {
        log.WithFields(log.Fields{"hash": blockHash.String(), "height": block.Height}).Info("add block to orphan")
 }
 
-// Delete will delelte the block from OrphanManage
+// Delete will delete the block from OrphanManage
 func (o *OrphanManage) Delete(hash *bc.Hash) {
        o.mtx.Lock()
        defer o.mtx.Unlock()
index 9278f13..0135280 100644 (file)
@@ -93,7 +93,7 @@ func (node *BlockNode) CalcPastMedianTime() uint64 {
        return timestamps[len(timestamps)/2]
 }
 
-// CalcNextBits calculate the seed for next block
+// CalcNextBits calculate the bits for next block
 func (node *BlockNode) CalcNextBits() uint64 {
        if node.Height%consensus.BlocksPerRetarget != 0 || node.Height == 0 {
                return node.Bits
@@ -108,6 +108,9 @@ func (node *BlockNode) CalcNextBits() uint64 {
 
 // CalcNextSeed calculate the seed for next block
 func (node *BlockNode) CalcNextSeed() *bc.Hash {
+       if node.Height == 0 {
+               return consensus.InitialSeed
+       }
        if node.Height%consensus.SeedPerRetarget == 0 {
                return &node.Hash
        }
diff --git a/protocol/state/blockindex_test.go b/protocol/state/blockindex_test.go
new file mode 100644 (file)
index 0000000..945468e
--- /dev/null
@@ -0,0 +1,212 @@
+package state
+
+import (
+       "math/big"
+       "testing"
+
+       "github.com/bytom/consensus"
+       "github.com/bytom/consensus/difficulty"
+       "github.com/bytom/protocol/bc"
+       "github.com/bytom/protocol/bc/types"
+)
+
+func TestCalcPastMedianTime(t *testing.T) {
+       cases := []struct {
+               Timestamps []uint64
+               MedianTime uint64
+       }{
+               {
+                       Timestamps: []uint64{1},
+                       MedianTime: 1,
+               },
+               {
+                       Timestamps: []uint64{1, 2},
+                       MedianTime: 2,
+               },
+               {
+                       Timestamps: []uint64{1, 3, 2},
+                       MedianTime: 2,
+               },
+               {
+                       Timestamps: []uint64{1, 3, 2, 3},
+                       MedianTime: 3,
+               },
+               {
+                       Timestamps: []uint64{1, 2, 3, 4, 5, 6, 7, 8, 11, 10, 9},
+                       MedianTime: 6,
+               },
+               {
+                       Timestamps: []uint64{1, 2, 3, 4, 5, 6, 7, 8, 11, 10, 9, 11, 11, 11, 14},
+                       MedianTime: 10,
+               },
+       }
+
+       for idx, c := range cases {
+               var parentNode *BlockNode
+               for i, _ := range c.Timestamps {
+                       blockHeader := &types.BlockHeader{
+                               Height:    uint64(i),
+                               Timestamp: c.Timestamps[i],
+                       }
+
+                       blockNode, err := NewBlockNode(blockHeader, parentNode)
+                       if err != nil {
+                               t.Fatal(err)
+                       }
+                       parentNode = blockNode
+               }
+
+               medianTime := parentNode.CalcPastMedianTime()
+               if medianTime != c.MedianTime {
+                       t.Fatalf("calc median timestamp failed, index: %d, expected: %d, have: %d", idx, c.MedianTime, medianTime)
+               }
+       }
+}
+
+func TestCalcNextBits(t *testing.T) {
+       targetTimeSpan := uint64(consensus.BlocksPerRetarget * consensus.TargetSecondsPerBlock)
+       cases := []struct {
+               parentNode  *BlockNode
+               currentNode *BlockNode
+               bits        uint64
+       }{
+               {
+                       currentNode: &BlockNode{
+                               Height: 0,
+                               Bits:   1000,
+                       },
+                       bits: 1000,
+               },
+               {
+                       currentNode: &BlockNode{
+                               Height: consensus.BlocksPerRetarget - 1,
+                               Bits:   1000,
+                       },
+                       bits: 1000,
+               },
+               {
+                       parentNode: &BlockNode{
+                               Height:    0,
+                               Timestamp: 0,
+                       },
+                       currentNode: &BlockNode{
+                               Height:    consensus.BlocksPerRetarget,
+                               Bits:      difficulty.BigToCompact(big.NewInt(1000)),
+                               Timestamp: targetTimeSpan,
+                       },
+                       bits: difficulty.BigToCompact(big.NewInt(1000)),
+               },
+               {
+                       parentNode: &BlockNode{
+                               Height:    0,
+                               Timestamp: 0,
+                       },
+                       currentNode: &BlockNode{
+                               Height:    consensus.BlocksPerRetarget,
+                               Bits:      difficulty.BigToCompact(big.NewInt(1000)),
+                               Timestamp: targetTimeSpan * 2,
+                       },
+                       bits: difficulty.BigToCompact(big.NewInt(2000)),
+               },
+       }
+
+       for i, c := range cases {
+               c.currentNode.Parent = c.parentNode
+               bits := c.currentNode.CalcNextBits()
+               if bits != c.bits {
+                       t.Fatalf("calc next bit failed, index: %d, expected: %d, have: %d", i, c.bits, bits)
+               }
+       }
+}
+
+func TestCalcNextSeed(t *testing.T) {
+       cases := []struct {
+               node *BlockNode
+               seed *bc.Hash
+       }{
+               {
+                       node: &BlockNode{
+                               Height: 0,
+                       },
+                       seed: consensus.InitialSeed,
+               },
+               {
+                       node: &BlockNode{
+                               Height: consensus.SeedPerRetarget - 1,
+                               Seed:   &bc.Hash{V1: 100},
+                       },
+                       seed: &bc.Hash{V1: 100},
+               },
+               {
+                       node: &BlockNode{
+                               Height: consensus.SeedPerRetarget,
+                               Seed:   &bc.Hash{V2: 200},
+                               Hash:   bc.Hash{V3: 300},
+                       },
+                       seed: &bc.Hash{V3: 300},
+               },
+       }
+
+       for i, c := range cases {
+               seed := c.node.CalcNextSeed()
+               if *seed != *c.seed {
+                       t.Fatalf("calc next seed failed, index: %d, expected: %v, have: %v", i, c.seed, seed)
+               }
+       }
+}
+
+func TestSetMainChain(t *testing.T) {
+       blockIndex := NewBlockIndex()
+       var lastNode *BlockNode
+       for i := uint64(0); i < 4; i++ {
+               node := &BlockNode{
+                       Height: i,
+                       Hash:   bc.Hash{V0: i},
+                       Parent: lastNode,
+               }
+               blockIndex.AddNode(node)
+               lastNode = node
+       }
+
+       tailNode := lastNode
+       blockIndex.SetMainChain(lastNode)
+       for lastNode.Parent != nil {
+               if !blockIndex.InMainchain(lastNode.Hash) {
+                       t.Fatalf("block %d, hash %v is not in main chain", lastNode.Height, lastNode.Hash)
+               }
+               lastNode = lastNode.Parent
+       }
+
+       // fork and set main chain
+       forkHeight := uint64(1)
+       lastNode = blockIndex.nodeByHeight(forkHeight)
+       for i := uint64(1); i <= 3; i++ {
+               node := &BlockNode{
+                       Height: lastNode.Height + 1,
+                       Hash:   bc.Hash{V1: uint64(i)},
+                       Parent: lastNode,
+               }
+               blockIndex.AddNode(node)
+               lastNode = node
+       }
+
+       bestNode := lastNode
+       blockIndex.SetMainChain(lastNode)
+       for lastNode.Parent != nil {
+               if !blockIndex.InMainchain(lastNode.Hash) {
+                       t.Fatalf("after fork, block %d, hash %v is not in main chain", lastNode.Height, lastNode.Hash)
+               }
+               lastNode = lastNode.Parent
+       }
+
+       if bestNode != blockIndex.BestNode() {
+               t.Fatalf("check best node failed")
+       }
+
+       for tailNode.Parent != nil && tailNode.Height > forkHeight {
+               if blockIndex.InMainchain(tailNode.Hash) {
+                       t.Fatalf("old chain block %d, hash %v still in main chain", tailNode.Height, tailNode.Hash)
+               }
+               tailNode = tailNode.Parent
+       }
+}
index 5e2ad35..fede7b0 100644 (file)
@@ -95,6 +95,7 @@ func TestValidateBlockHeader(t *testing.T) {
        // real matrix calculate cost.
        tensority.AIHash.AddCache(&bc.Hash{V0: 0}, &bc.Hash{}, testutil.MaxHash)
        tensority.AIHash.AddCache(&bc.Hash{V0: 1}, &bc.Hash{}, testutil.MinHash)
+       tensority.AIHash.AddCache(&bc.Hash{V0: 1}, consensus.InitialSeed, testutil.MinHash)
 
        cases := []struct {
                block  *bc.Block