OSDN Git Service

Hulk did something
[bytom/vapor.git] / consensus / difficulty / difficulty_test.go
diff --git a/consensus/difficulty/difficulty_test.go b/consensus/difficulty/difficulty_test.go
new file mode 100644 (file)
index 0000000..205e485
--- /dev/null
@@ -0,0 +1,888 @@
+package difficulty
+
+import (
+       "math/big"
+       "reflect"
+       "strconv"
+       "testing"
+
+       "github.com/vapor/consensus"
+       "github.com/vapor/protocol/bc"
+       "github.com/vapor/protocol/bc/types"
+)
+
+// A lower difficulty Int actually reflects a more difficult mining progress.
+func TestCalcNextRequiredDifficulty(t *testing.T) {
+       targetTimeSpan := uint64(consensus.BlocksPerRetarget * consensus.TargetSecondsPerBlock)
+       cases := []struct {
+               lastBH    *types.BlockHeader
+               compareBH *types.BlockHeader
+               want      uint64
+       }{
+               {
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget,
+                               Timestamp: targetTimeSpan,
+                               Bits:      BigToCompact(big.NewInt(1000)),
+                       },
+                       &types.BlockHeader{
+                               Height:    0,
+                               Timestamp: 0,
+                       },
+                       BigToCompact(big.NewInt(1000)),
+               },
+               {
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget,
+                               Timestamp: targetTimeSpan * 2,
+                               Bits:      BigToCompact(big.NewInt(1000)),
+                       },
+                       &types.BlockHeader{
+                               Height:    0,
+                               Timestamp: 0,
+                       },
+                       BigToCompact(big.NewInt(2000)),
+               },
+               {
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget - 1,
+                               Timestamp: targetTimeSpan*2 - consensus.TargetSecondsPerBlock,
+                               Bits:      BigToCompact(big.NewInt(1000)),
+                       },
+                       &types.BlockHeader{
+                               Height:    0,
+                               Timestamp: 0,
+                       },
+                       BigToCompact(big.NewInt(1000)),
+               },
+               {
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget,
+                               Timestamp: targetTimeSpan / 2,
+                               Bits:      BigToCompact(big.NewInt(1000)),
+                       },
+                       &types.BlockHeader{
+                               Height:    0,
+                               Timestamp: 0,
+                       },
+                       BigToCompact(big.NewInt(500)),
+               },
+               {
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget * 2,
+                               Timestamp: targetTimeSpan + targetTimeSpan*2,
+                               Bits:      BigToCompact(big.NewInt(1000)),
+                       },
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget,
+                               Timestamp: targetTimeSpan,
+                       },
+                       BigToCompact(big.NewInt(2000)),
+               },
+               {
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget * 2,
+                               Timestamp: targetTimeSpan + targetTimeSpan/2,
+                               Bits:      BigToCompact(big.NewInt(1000)),
+                       },
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget,
+                               Timestamp: targetTimeSpan,
+                       },
+                       BigToCompact(big.NewInt(500)),
+               },
+               {
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget*2 - 1,
+                               Timestamp: targetTimeSpan + targetTimeSpan*2 - consensus.TargetSecondsPerBlock,
+                               Bits:      BigToCompact(big.NewInt(1000)),
+                       },
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget,
+                               Timestamp: targetTimeSpan,
+                       },
+                       BigToCompact(big.NewInt(1000)),
+               },
+               {
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget*2 - 1,
+                               Timestamp: targetTimeSpan + targetTimeSpan/2 - consensus.TargetSecondsPerBlock,
+                               Bits:      BigToCompact(big.NewInt(1000)),
+                       },
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget,
+                               Timestamp: targetTimeSpan,
+                       },
+                       BigToCompact(big.NewInt(1000)),
+               },
+               // lastBH.Height: 0, lastBH.Timestamp - compareBH.Timestamp: 0, lastBH.Bits: 0
+               {
+                       &types.BlockHeader{
+                               Height:    0,
+                               Timestamp: 0,
+                               Bits:      0,
+                       },
+                       &types.BlockHeader{
+                               Height:    0,
+                               Timestamp: 0,
+                       },
+                       0,
+               },
+               // lastBH.Height: 0, lastBH.Timestamp - compareBH.Timestamp: 0, lastBH.Bits: 18446744073709551615
+               {
+                       &types.BlockHeader{
+                               Height:    0,
+                               Timestamp: 0,
+                               Bits:      18446744073709551615,
+                       },
+                       &types.BlockHeader{
+                               Height:    0,
+                               Timestamp: 0,
+                       },
+                       18446744073709551615,
+               },
+               // lastBH.Height: 0, lastBH.Timestamp - compareBH.Timestamp: 0, lastBH.Bits: bigInt(1000)
+               {
+                       &types.BlockHeader{
+                               Height:    0,
+                               Timestamp: 0,
+                               Bits:      BigToCompact(big.NewInt(1000)),
+                       },
+                       &types.BlockHeader{
+                               Height:    0,
+                               Timestamp: 0,
+                       },
+                       BigToCompact(big.NewInt(1000)),
+               },
+               // lastBH.Height: consensus.BlocksPerRetarget, lastBH.Timestamp - compareBH.Timestamp: 0, lastBH.Bits: bigInt(1000)
+               {
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget,
+                               Timestamp: targetTimeSpan,
+                               Bits:      BigToCompact(big.NewInt(1000)),
+                       },
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget - 1,
+                               Timestamp: targetTimeSpan,
+                       },
+                       0,
+               },
+               // lastBH.Height: consensus.BlocksPerRetarget, lastBH.Timestamp - compareBH.Timestamp: -9223372036854775808, lastBH.Bits: bigInt(1000)
+               {
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget,
+                               Timestamp: targetTimeSpan,
+                               Bits:      BigToCompact(big.NewInt(1000)),
+                       },
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget - 1,
+                               Timestamp: targetTimeSpan + 9223372036854775808,
+                       },
+                       540431955291560988,
+               },
+               // lastBH.Height: consensus.BlocksPerRetarget, lastBH.Timestamp - compareBH.Timestamp: 9223372036854775807, lastBH.Bits: bigInt(1000)
+               {
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget,
+                               Timestamp: targetTimeSpan + 9223372036854775807,
+                               Bits:      BigToCompact(big.NewInt(1000)),
+                       },
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget - 1,
+                               Timestamp: targetTimeSpan,
+                       },
+                       504403158272597019,
+               },
+               // lastBH.Height: consensus.BlocksPerRetarget, lastBH.Timestamp - compareBH.Timestamp: 18446744073709551615, lastBH.Bits: bigInt(1000)
+               {
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget,
+                               Timestamp: 18446744073709551615,
+                               Bits:      BigToCompact(big.NewInt(1000)),
+                       },
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget - 1,
+                               Timestamp: 0,
+                       },
+                       108086391056957440,
+               },
+               // lastBH.Height: consensus.BlocksPerRetarget, lastBH.Timestamp - compareBH.Timestamp: 302400, lastBH.Bits: bigInt(1000)
+               {
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget,
+                               Timestamp: targetTimeSpan * 2,
+                               Bits:      BigToCompact(big.NewInt(1000)),
+                       },
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget - 1,
+                               Timestamp: targetTimeSpan,
+                       },
+                       BigToCompact(big.NewInt(1000)),
+               },
+               // lastBH.Height: consensus.BlocksPerRetarget, lastBH.Timestamp - compareBH.Timestamp: 604800, lastBH.Bits: bigInt(1000)
+               {
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget,
+                               Timestamp: targetTimeSpan * 3,
+                               Bits:      BigToCompact(big.NewInt(1000)),
+                       },
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget - 1,
+                               Timestamp: targetTimeSpan,
+                       },
+                       144115188076367872,
+               },
+               // lastBH.Height: consensus.BlocksPerRetarget, lastBH.Timestamp - compareBH.Timestamp: 151200, lastBH.Bits: bigInt(1000)
+               {
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget,
+                               Timestamp: targetTimeSpan + 9223372036854775807,
+                               Bits:      BigToCompact(big.NewInt(1000)),
+                       },
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget - 1,
+                               Timestamp: targetTimeSpan,
+                       },
+                       504403158272597019,
+               },
+               // lastBH.Height: consensus.BlocksPerRetarget, lastBH.Timestamp - compareBH.Timestamp: 302400, lastBH.Bits: 0
+               {
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget,
+                               Timestamp: targetTimeSpan * 2,
+                               Bits:      0,
+                       },
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget - 1,
+                               Timestamp: targetTimeSpan,
+                       },
+                       0,
+               },
+               // lastBH.Height: consensus.BlocksPerRetarget, lastBH.Timestamp - compareBH.Timestamp: 302400, lastBH.Bits: 18446744073709551615
+               {
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget,
+                               Timestamp: targetTimeSpan * 2,
+                               Bits:      18446744073709551615,
+                       },
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget - 1,
+                               Timestamp: targetTimeSpan,
+                       },
+                       252201579141136384,
+               },
+               // lastBH.Height: consensus.BlocksPerRetarget + 1, lastBH.Timestamp - compareBH.Timestamp: 302400, lastBH.Bits: bigInt(1000)
+               {
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget + 1,
+                               Timestamp: targetTimeSpan * 2,
+                               Bits:      BigToCompact(big.NewInt(1000)),
+                       },
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget,
+                               Timestamp: targetTimeSpan,
+                       },
+                       BigToCompact(big.NewInt(1000)),
+               },
+               // lastBH.Height: consensus.BlocksPerRetarget - 1, lastBH.Timestamp - compareBH.Timestamp: 302400, lastBH.Bits: bigInt(1000)
+               {
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget - 1,
+                               Timestamp: targetTimeSpan * 2,
+                               Bits:      BigToCompact(big.NewInt(1000)),
+                       },
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget - 2,
+                               Timestamp: targetTimeSpan,
+                       },
+                       BigToCompact(big.NewInt(1000)),
+               },
+               // lastBH.Height: consensus.BlocksPerRetarget * 2, lastBH.Timestamp - compareBH.Timestamp: 302400, lastBH.Bits: bigInt(1000)
+               {
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget * 2,
+                               Timestamp: targetTimeSpan * 2,
+                               Bits:      BigToCompact(big.NewInt(1000)),
+                       },
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget*2 - 1,
+                               Timestamp: targetTimeSpan,
+                       },
+                       BigToCompact(big.NewInt(1000)),
+               },
+               // lastBH.Height: consensus.BlocksPerRetarget / 2, lastBH.Timestamp - compareBH.Timestamp: 302400, lastBH.Bits: bigInt(1000)
+               {
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget / 2,
+                               Timestamp: targetTimeSpan * 2,
+                               Bits:      BigToCompact(big.NewInt(1000)),
+                       },
+                       &types.BlockHeader{
+                               Height:    consensus.BlocksPerRetarget/2 - 1,
+                               Timestamp: targetTimeSpan,
+                       },
+                       BigToCompact(big.NewInt(1000)),
+               },
+       }
+
+       for i, c := range cases {
+               if got := CalcNextRequiredDifficulty(c.lastBH, c.compareBH); got != c.want {
+                       t.Errorf("Compile(%d) = %d want %d\n", i, got, c.want)
+                       return
+               }
+       }
+}
+
+func TestHashToBig(t *testing.T) {
+       cases := []struct {
+               in  [32]byte
+               out [32]byte
+       }{
+               {
+                       in: [32]byte{
+                               0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+                               0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+                               0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+                               0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+                       },
+                       out: [32]byte{
+                               0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+                               0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+                               0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+                               0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+                       },
+               },
+               {
+                       in: [32]byte{
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                               0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+                       },
+                       out: [32]byte{
+                               0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+                               0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       },
+               },
+               {
+                       in: [32]byte{
+                               0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+                               0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+                               0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+                               0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+                       },
+                       out: [32]byte{
+                               0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
+                               0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
+                               0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8,
+                               0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0,
+                       },
+               },
+       }
+
+       for i, c := range cases {
+               bhash := bc.NewHash(c.in)
+               result := HashToBig(&bhash).Bytes()
+
+               var resArr [32]byte
+               copy(resArr[:], result)
+
+               if !reflect.DeepEqual(resArr, c.out) {
+                       t.Errorf("TestHashToBig test #%d failed:\n\tgot\t%x\n\twant\t%x\n", i, resArr, c.out)
+                       return
+               }
+       }
+}
+
+func TestCompactToBig(t *testing.T) {
+       cases := []struct {
+               in  string
+               out *big.Int
+       }{
+               {
+                       in: `00000000` + //Exponent
+                               `0` + //Sign
+                               `0000000000000000000000000000000000000000000000000000000`, //Mantissa
+                       out: big.NewInt(0),
+               },
+               {
+                       in: `00000000` + //Exponent
+                               `1` + //Sign
+                               `0000000000000000000000000000000000000000000000000000000`, //Mantissa
+                       out: big.NewInt(0),
+               },
+               {
+                       in: `00000001` + //Exponent
+                               `0` + //Sign
+                               `0000000000000000000000000000000000000010000000000000000`, //Mantissa
+                       out: big.NewInt(1),
+               },
+               {
+                       in: `00000001` + //Exponent
+                               `1` + //Sign
+                               `0000000000000000000000000000000000000010000000000000000`, //Mantissa
+                       out: big.NewInt(-1),
+               },
+               {
+                       in: `00000011` + //Exponent
+                               `0` + //Sign
+                               `0000000000000000000000000000000000000010000000000000000`, //Mantissa
+                       out: big.NewInt(65536),
+               },
+               {
+                       in: `00000011` + //Exponent
+                               `1` + //Sign
+                               `0000000000000000000000000000000000000010000000000000000`, //Mantissa
+                       out: big.NewInt(-65536),
+               },
+               {
+                       in: `00000100` + //Exponent
+                               `0` + //Sign
+                               `0000000000000000000000000000000000000010000000000000000`, //Mantissa
+                       out: big.NewInt(16777216),
+               },
+               {
+                       in: `00000100` + //Exponent
+                               `1` + //Sign
+                               `0000000000000000000000000000000000000010000000000000000`, //Mantissa
+                       out: big.NewInt(-16777216),
+               },
+               {
+                       //btm PowMin test
+                       // PowMinBits = 2161727821138738707, i.e 0x1e000000000dbe13, as defined
+                       // in /consensus/general.go
+                       in: `00011110` + //Exponent
+                               `0` + //Sign
+                               `0000000000000000000000000000000000011011011111000010011`, //Mantissa
+                       out: big.NewInt(0).Lsh(big.NewInt(0x0dbe13), 27*8), //2161727821138738707
+               },
+       }
+
+       for i, c := range cases {
+               compact, _ := strconv.ParseUint(c.in, 2, 64)
+               r := CompactToBig(compact)
+               if r.Cmp(c.out) != 0 {
+                       t.Error("TestCompactToBig test #", i, "failed: got", r, "want", c.out)
+                       return
+               }
+       }
+}
+
+func TestBigToCompact(t *testing.T) {
+       // basic tests
+       tests := []struct {
+               in  int64
+               out uint64
+       }{
+               {0, 0x0000000000000000},
+               {-0, 0x0000000000000000},
+               {1, 0x0100000000010000},
+               {-1, 0x0180000000010000},
+               {65536, 0x0300000000010000},
+               {-65536, 0x0380000000010000},
+               {16777216, 0x0400000000010000},
+               {-16777216, 0x0480000000010000},
+       }
+
+       for x, test := range tests {
+               n := big.NewInt(test.in)
+               r := BigToCompact(n)
+               if r != test.out {
+                       t.Errorf("TestBigToCompact test #%d failed: got 0x%016x want 0x%016x\n",
+                               x, r, test.out)
+                       return
+               }
+       }
+
+       // btm PowMin test
+       // PowMinBits = 2161727821138738707, i.e 0x1e000000000dbe13, as defined
+       // in /consensus/general.go
+       n := big.NewInt(0).Lsh(big.NewInt(0x0dbe13), 27*8)
+       out := uint64(0x1e000000000dbe13)
+       r := BigToCompact(n)
+       if r != out {
+               t.Errorf("TestBigToCompact test #%d failed: got 0x%016x want 0x%016x\n",
+                       len(tests), r, out)
+               return
+       }
+}
+
+func TestCalcWorkWithIntStr(t *testing.T) {
+       cases := []struct {
+               strBits string
+               want    *big.Int
+       }{
+               // Exponent: 0, Sign: 0, Mantissa: 0
+               {
+                       `00000000` + //Exponent
+                               `0` + //Sign
+                               `0000000000000000000000000000000000000000000000000000000`, //Mantissa
+                       big.NewInt(0),
+               },
+               // Exponent: 0, Sign: 0, Mantissa: 1 (difficultyNum = 0 and difficultyNum.Sign() = 0)
+               {
+                       `00000000` +
+                               `0` +
+                               `0000000000000000000000000000000000000000000000000000001`,
+                       big.NewInt(0),
+               },
+               // Exponent: 0, Sign: 0, Mantissa: 65536 (difficultyNum = 0 and difficultyNum.Sign() = 0)
+               {
+                       `00000000` +
+                               `0` +
+                               `0000000000000000000000000000000000000010000000000000000`,
+                       big.NewInt(0),
+               },
+               // Exponent: 0, Sign: 0, Mantissa: 16777216 (difficultyNum = 1 and difficultyNum.Sign() = 1)
+               {
+                       `00000000` +
+                               `0` +
+                               `0000000000000000000000000000001000000000000000000000000`,
+                       new(big.Int).Div(oneLsh256, big.NewInt(2)),
+               },
+               // Exponent: 0, Sign: 0, Mantissa: 0x007fffffffffffff
+               {
+                       `00000000` +
+                               `0` +
+                               `1111111111111111111111111111111111111111111111111111111`,
+                       big.NewInt(0).Lsh(big.NewInt(0x020000), 208),
+               },
+               // Exponent: 0, Sign: 1, Mantissa: 0
+               {
+                       `00000000` +
+                               `1` +
+                               `0000000000000000000000000000000000000000000000000000000`,
+                       big.NewInt(0),
+               },
+               // Exponent: 0, Sign: 1, Mantissa: 1 (difficultyNum = 0 and difficultyNum.Sign() = 0)
+               {
+                       `00000000` +
+                               `1` +
+                               `0000000000000000000000000000000000000000000000000000001`,
+                       big.NewInt(0),
+               },
+               // Exponent: 0, Sign: 1, Mantissa: 65536 (difficultyNum = 0 and difficultyNum.Sign() = 0)
+               {
+                       `00000000` +
+                               `1` +
+                               `0000000000000000000000000000000000000010000000000000000`,
+                       big.NewInt(0),
+               },
+               // Exponent: 0, Sign: 0, Mantissa: 16777216 (difficultyNum = -1 and difficultyNum.Sign() = -1)
+               {
+                       `00000000` +
+                               `1` +
+                               `0000000000000000000000000000001000000000000000000000000`,
+                       big.NewInt(0),
+               },
+               // Exponent: 0, Sign: 1, Mantissa: 0x007fffffffffffff
+               {
+                       `00000000` +
+                               `1` +
+                               `1111111111111111111111111111111111111111111111111111111`,
+                       big.NewInt(0),
+               },
+               // Exponent: 3, Sign: 0, Mantissa: 0
+               {
+                       `00000011` +
+                               `0` +
+                               `0000000000000000000000000000000000000000000000000000000`,
+                       big.NewInt(0),
+               },
+               // Exponent: 3, Sign: 0, Mantissa: 1 (difficultyNum = 1 and difficultyNum.Sign() = 1)
+               {
+                       `00000011` +
+                               `0` +
+                               `0000000000000000000000000000000000000000000000000000001`,
+                       new(big.Int).Div(oneLsh256, big.NewInt(2)),
+               },
+               // Exponent: 3, Sign: 0, Mantissa: 65536 (difficultyNum = 65536 and difficultyNum.Sign() = 1)
+               {
+                       `00000011` +
+                               `0` +
+                               `0000000000000000000000000000000000000010000000000000000`,
+                       new(big.Int).Div(oneLsh256, big.NewInt(65537)),
+               },
+               // Exponent: 0, Sign: 0, Mantissa: 16777216 (difficultyNum = 16777216 and difficultyNum.Sign() = 1)
+               {
+                       `00000011` +
+                               `0` +
+                               `0000000000000000000000000000001000000000000000000000000`,
+                       new(big.Int).Div(oneLsh256, big.NewInt(16777217)),
+               },
+               // Exponent: 3, Sign: 0, Mantissa: 0x007fffffffffffff
+               {
+                       `00000011` +
+                               `0` +
+                               `1111111111111111111111111111111111111111111111111111111`,
+                       new(big.Int).Div(oneLsh256, big.NewInt(36028797018963968)),
+               },
+               // Exponent: 3, Sign: 1, Mantissa: 0
+               {
+                       `00000011` +
+                               `1` +
+                               `0000000000000000000000000000000000000000000000000000000`,
+                       big.NewInt(0),
+               },
+               //Exponent: 3, Sign: 1, Mantissa: 1 (difficultyNum = -1 and difficultyNum.Sign() = -1)
+               {
+                       `00000011` +
+                               `1` +
+                               `0000000000000000000000000000000000000000000000000000001`,
+                       big.NewInt(0),
+               },
+               // Exponent: 3, Sign: 1, Mantissa: 65536 (difficultyNum = -65536 and difficultyNum.Sign() = -1)
+               {
+                       `00000011` +
+                               `1` +
+                               `0000000000000000000000000000000000000010000000000000000`,
+                       big.NewInt(0),
+               },
+               // Exponent: 3, Sign: 1, Mantissa: 16777216 (difficultyNum = -16777216 and difficultyNum.Sign() = -1)
+               {
+                       `00000011` +
+                               `1` +
+                               `0000000000000000000000000000001000000000000000000000000`,
+                       big.NewInt(0),
+               },
+               // Exponent: 3, Sign: 1, Mantissa: 0x007fffffffffffff
+               {
+                       `00000011` +
+                               `1` +
+                               `1111111111111111111111111111111111111111111111111111111`,
+                       big.NewInt(0),
+               },
+               // Exponent: 7, Sign: 0, Mantissa: 0
+               {
+                       `00000111` +
+                               `0` +
+                               `0000000000000000000000000000000000000000000000000000000`,
+                       big.NewInt(0),
+               },
+               //Exponent: 7, Sign: 1, Mantissa: 1 (difficultyNum = 4294967296 and difficultyNum.Sign() = 1)
+               {
+                       `00000111` +
+                               `0` +
+                               `0000000000000000000000000000000000000000000000000000001`,
+                       new(big.Int).Div(oneLsh256, big.NewInt(4294967297)),
+               },
+               // Exponent: 7, Sign: 0, Mantissa: 65536 (difficultyNum = 4294967296 and difficultyNum.Sign() = 1)
+               {
+                       `00000111` +
+                               `0` +
+                               `0000000000000000000000000000000000000010000000000000000`,
+                       new(big.Int).Div(oneLsh256, big.NewInt(281474976710657)),
+               },
+               // Exponent: 7, Sign: 0, Mantissa: 16777216 (difficultyNum = 72057594037927936 and difficultyNum.Sign() = 1)
+               {
+                       `00000111` +
+                               `0` +
+                               `0000000000000000000000000000001000000000000000000000000`,
+                       new(big.Int).Div(oneLsh256, big.NewInt(72057594037927937)),
+               },
+               // Exponent: 7, Sign: 0, Mantissa: 0x007fffffffffffff
+               {
+                       `00000111` +
+                               `0` +
+                               `1111111111111111111111111111111111111111111111111111111`,
+                       new(big.Int).Div(oneLsh256, new(big.Int).Add(big.NewInt(0).Lsh(big.NewInt(36028797018963967), 32), bigOne)),
+               },
+               // Exponent: 7, Sign: 1, Mantissa: 0
+               {
+                       `00000111` +
+                               `1` +
+                               `0000000000000000000000000000000000000000000000000000000`,
+                       big.NewInt(0),
+               },
+               // Exponent: 7, Sign: 1, Mantissa: 1 (difficultyNum = -4294967296 and difficultyNum.Sign() = -1)
+               {
+                       `00000111` +
+                               `1` +
+                               `0000000000000000000000000000000000000000000000000000001`,
+                       big.NewInt(0),
+               },
+               // Exponent: 7, Sign: 1, Mantissa: 65536 (difficultyNum = -72057594037927936 and difficultyNum.Sign() = -1)
+               {
+                       `00000111` +
+                               `1` +
+                               `0000000000000000000000000000000000000010000000000000000`,
+                       big.NewInt(0),
+               },
+               // Exponent: 7, Sign: 1, Mantissa: 16777216 (difficultyNum = -154742504910672530067423232 and difficultyNum.Sign() = -1)
+               {
+                       `00000111` +
+                               `1` +
+                               `0000000000000000000000000000001000000000000000000000000`,
+                       big.NewInt(0),
+               },
+               // Exponent: 7, Sign: 1, Mantissa: 0x007fffffffffffff
+               {
+                       `00000111` +
+                               `1` +
+                               `1111111111111111111111111111111111111111111111111111111`,
+                       big.NewInt(0),
+               },
+               // Exponent: 255, Sign: 0, Mantissa: 1 (difficultyNum.Sign() = 1)
+               {
+                       `11111111` +
+                               `0` +
+                               `0000000000000000000000000000000000000000000000000000001`,
+                       big.NewInt(0),
+               },
+               // Exponent: 255, Sign: 0, Mantissa: 65536 (difficultyNum.Sign() = 1)
+               {
+                       `11111111` +
+                               `0` +
+                               `0000000000000000000000000000000000000010000000000000000`,
+                       big.NewInt(0),
+               },
+               // Exponent: 255, Sign: 0, Mantissa: 16777216 (difficultyNum.Sign() = 1)
+               {
+                       `11111111` +
+                               `0` +
+                               `0000000000000000000000000000001000000000000000000000000`,
+                       big.NewInt(0),
+               },
+               // Exponent: 255, Sign: 0, Mantissa: 0x007fffffffffffff
+               {
+                       `11111111` +
+                               `0` +
+                               `1111111111111111111111111111111111111111111111111111111`,
+                       big.NewInt(0),
+               },
+               // Exponent: 255, Sign: 1, Mantissa: 1
+               {
+                       `11111111` +
+                               `1` +
+                               `0000000000000000000000000000000000000000000000000000001`,
+                       big.NewInt(0),
+               },
+               // Exponent: 255, Sign: 1, Mantissa: 65536
+               {
+                       `11111111` +
+                               `1` +
+                               `0000000000000000000000000000000000000010000000000000000`,
+                       big.NewInt(0),
+               },
+               // Exponent: 255, Sign: 1, Mantissa: 16777216
+               {
+                       `11111111` +
+                               `1` +
+                               `0000000000000000000000000000001000000000000000000000000`,
+                       big.NewInt(0),
+               },
+               // Exponent: 255, Sign: 1, Mantissa: 0x007fffffffffffff
+               {
+                       `11111111` +
+                               `1` +
+                               `1111111111111111111111111111111111111111111111111111111`,
+                       big.NewInt(0),
+               },
+       }
+
+       for i, c := range cases {
+               bits, err := strconv.ParseUint(c.strBits, 2, 64)
+               if err != nil {
+                       t.Errorf("convert string into uint error: %s\n", err)
+                       return
+               }
+
+               if got := CalcWork(bits); got.Cmp(c.want) != 0 {
+                       t.Errorf("CalcWork(%d) = %s, want %s\n", i, got, c.want)
+                       return
+               }
+       }
+}
+
+func TestCalcWork(t *testing.T) {
+       testCases := []struct {
+               bits uint64
+               want *big.Int
+       }{
+               {
+                       0,
+                       big.NewInt(0),
+               },
+               {
+                       1,
+                       big.NewInt(0),
+               },
+               {
+                       65535,
+                       big.NewInt(0),
+               },
+               {
+                       16777215,
+                       big.NewInt(0),
+               },
+               {
+                       16777216,
+                       new(big.Int).Div(oneLsh256, big.NewInt(2)),
+               },
+               {
+                       4294967295,
+                       new(big.Int).Div(oneLsh256, big.NewInt(256)),
+               },
+               {
+                       36028797018963967,
+                       new(big.Int).Div(oneLsh256, big.NewInt(2147483648)),
+               },
+               {
+                       36028797018963968,
+                       big.NewInt(0),
+               },
+               {
+                       216172782113783808,
+                       big.NewInt(0),
+               },
+               {
+                       216172782113783809,
+                       new(big.Int).Div(oneLsh256, big.NewInt(2)),
+               },
+               {
+                       216172782130561024,
+                       new(big.Int).Div(oneLsh256, big.NewInt(16777217)),
+               },
+               {
+                       252201579132747775,
+                       new(big.Int).Div(oneLsh256, big.NewInt(36028797018963968)),
+               },
+               {
+                       252201579132747776,
+                       big.NewInt(0),
+               },
+               {
+                       288230376151711744,
+                       big.NewInt(0),
+               },
+               {
+                       288230376151711745,
+                       new(big.Int).Div(oneLsh256, big.NewInt(257)),
+               },
+               {
+                       540431955284459519,
+                       new(big.Int).Div(oneLsh256, new(big.Int).Add(big.NewInt(0).Lsh(big.NewInt(36028797018963967), 32), bigOne)),
+               },
+               {
+                       540431955284459520,
+                       big.NewInt(0),
+               },
+               {
+                       9223372036854775807,
+                       big.NewInt(0),
+               },
+               {
+                       18446744073709551615,
+                       big.NewInt(0),
+               },
+       }
+
+       for i, c := range testCases {
+               if got := CalcWork(c.bits); got.Cmp(c.want) != 0 {
+                       t.Errorf("test case with uint64 for CalcWork(%d) = %s, want %s\n", i, got, c.want)
+                       return
+               }
+       }
+}