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 } } }