From c1bed51dcfd75892c1ff0c9862bce860182fb75d Mon Sep 17 00:00:00 2001 From: egonspace Date: Thu, 16 May 2024 18:18:08 +0900 Subject: [PATCH] fix: move halving logic to BriocheConfig --- core/blockchain_test.go | 26 ---- params/config.go | 43 +++++- params/config_test.go | 315 ++++++++++++++++++++++++++++++++++++++++ wemix/admin.go | 39 +---- wemix/admin_test.go | 308 --------------------------------------- 5 files changed, 359 insertions(+), 372 deletions(-) delete mode 100644 wemix/admin_test.go diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 03b70d26c803..cda30f0f5860 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -164,7 +164,6 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error { blockchain.reportBlock(block, receipts, err) return err } - err = blockchain.validator.ValidateState(block, statedb, receipts, usedGas, fees) if err != nil { blockchain.reportBlock(block, receipts, err) @@ -3771,28 +3770,3 @@ func TestSetCanonical(t *testing.T) { chain.SetCanonical(canon[DefaultCacheConfig.TriesInMemory-1]) verify(canon[DefaultCacheConfig.TriesInMemory-1]) } - -func TestRewardValidation(t *testing.T) { - // Configure and generate a sample block chain - var ( - db = rawdb.NewMemoryDatabase() - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - funds = big.NewInt(1000000000) - deleteAddr = common.Address{1} - gspec = &Genesis{ - Config: ¶ms.ChainConfig{ChainID: big.NewInt(1), EIP150Block: big.NewInt(0), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)}, - Alloc: GenesisAlloc{address: {Balance: funds}, deleteAddr: {Balance: new(big.Int)}}, - } - genesis = gspec.MustCommit(db) - ) - - blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) - defer blockchain.Stop() - - blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 1, nil) - - if _, err := blockchain.InsertChain(blocks); err != nil { - t.Fatal(err) - } -} diff --git a/params/config.go b/params/config.go index 2a384d10ce3a..2e7c12fd9754 100644 --- a/params/config.go +++ b/params/config.go @@ -165,6 +165,9 @@ var ( BlockReward: big.NewInt(1e18), FirstHalvingBlock: big.NewInt(53_557_371), HalvingPeriod: big.NewInt(63_115_200), + NoRewardHereafter: big.NewInt(1_000_000_000), // TODO fix last reward block + HalvingTimes: 16, + HalvingRate: 50, }, } @@ -186,12 +189,15 @@ var ( LondonBlock: big.NewInt(0), PangyoBlock: big.NewInt(10_000_000), ApplepieBlock: big.NewInt(26_240_268), - BriocheBlock: big.NewInt(60_537_845), // 24-06-17 02:00:00 (UTC) expected + BriocheBlock: big.NewInt(60_537_845), // TODO fix hardfork date Ethash: new(EthashConfig), Brioche: &BriocheConfig{ BlockReward: big.NewInt(1e18), FirstHalvingBlock: big.NewInt(60_537_845), HalvingPeriod: big.NewInt(63_115_200), + NoRewardHereafter: big.NewInt(1_000_000_000), // TODO fix last reward block + HalvingTimes: 16, + HalvingRate: 50, }, } @@ -433,6 +439,41 @@ type BriocheConfig struct { HalvingRate uint32 `json:"halvingRate,omitempty"` // 0<=HalvingRate<=100; 0 - no reward on halving; 100 - no halving } +func (bc *BriocheConfig) GetBriocheBlockReward(defaultReward *big.Int, num *big.Int) *big.Int { + blockReward := big.NewInt(0).Set(defaultReward) // default brioche block reward + if bc != nil { + if bc.BlockReward != nil { + blockReward = big.NewInt(0).Set(bc.BlockReward) + } + if bc.NoRewardHereafter != nil && + bc.NoRewardHereafter.Cmp(num) <= 0 { + blockReward = big.NewInt(0) + } else if bc.FirstHalvingBlock != nil && + bc.HalvingPeriod != nil && + bc.HalvingTimes > 0 && + num.Cmp(bc.FirstHalvingBlock) >= 0 { + blockReward = bc.halveRewards(blockReward, num) + } + } + return blockReward +} + +func (bc *BriocheConfig) halveRewards(baseReward *big.Int, num *big.Int) *big.Int { + result := big.NewInt(0).Set(baseReward) + past := big.NewInt(0).Set(num) + past.Sub(past, bc.FirstHalvingBlock) + halvingTimes := bc.HalvingTimes + for ; halvingTimes > 0; halvingTimes-- { + result = result.Mul(result, big.NewInt(int64(bc.HalvingRate))) + result = result.Div(result, big.NewInt(100)) + if past.Cmp(bc.HalvingPeriod) < 0 { + break + } + past = past.Sub(past, bc.HalvingPeriod) + } + return result +} + // String implements the stringer interface, returning the consensus engine details. func (c *EthashConfig) String() string { return "ethash" diff --git a/params/config_test.go b/params/config_test.go index 3c8ebaf4a511..9e528f3cf0b1 100644 --- a/params/config_test.go +++ b/params/config_test.go @@ -96,3 +96,318 @@ func TestCheckCompatible(t *testing.T) { } } } + +func TestHalveRewards(t *testing.T) { + testcases := []struct { + reward *big.Int + period *big.Int + past *big.Int + times uint64 + rate uint32 + expected *big.Int + }{ + // sample test + {big.NewInt(1e18), big.NewInt(100), big.NewInt(0), 4, 50, big.NewInt(5e17)}, + {big.NewInt(1e18), big.NewInt(100), big.NewInt(99), 4, 50, big.NewInt(5e17)}, + {big.NewInt(1e18), big.NewInt(100), big.NewInt(100), 4, 50, big.NewInt(25e16)}, + {big.NewInt(1e18), big.NewInt(100), big.NewInt(101), 4, 50, big.NewInt(25e16)}, + + // times test + {big.NewInt(1e18), big.NewInt(100), big.NewInt(0), 0, 50, big.NewInt(1e18)}, + {big.NewInt(1e18), big.NewInt(100), big.NewInt(100), 0, 50, big.NewInt(1e18)}, + {big.NewInt(1e18), big.NewInt(100), big.NewInt(100), 1, 50, big.NewInt(5e17)}, + {big.NewInt(1e18), big.NewInt(100), big.NewInt(100), 2, 50, big.NewInt(25e16)}, + {big.NewInt(1e18), big.NewInt(100), big.NewInt(100), 3, 50, big.NewInt(25e16)}, + + // rate test + {big.NewInt(1e18), big.NewInt(100), big.NewInt(100), 2, 10, big.NewInt(1e16)}, + {big.NewInt(1e18), big.NewInt(100), big.NewInt(200), 3, 10, big.NewInt(1e15)}, + {big.NewInt(1e18), big.NewInt(100), big.NewInt(100), 2, 20, big.NewInt(4e16)}, + {big.NewInt(1e18), big.NewInt(100), big.NewInt(100), 2, 30, big.NewInt(9e16)}, + {big.NewInt(1e18), big.NewInt(100), big.NewInt(100), 2, 90, big.NewInt(81e16)}, + + // brioche halving test + {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(0), 16, 50, big.NewInt(5e17)}, + {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 - 1), 16, 50, big.NewInt(5e17)}, + {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200), 16, 50, big.NewInt(25e16)}, + {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200*2 - 1), 16, 50, big.NewInt(25e16)}, + {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 2), 16, 50, big.NewInt(125e15)}, + {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 3), 16, 50, big.NewInt(625e14)}, + {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 4), 16, 50, big.NewInt(3125e13)}, + {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 5), 16, 50, big.NewInt(15625e12)}, + {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 6), 16, 50, big.NewInt(78125e11)}, + {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 7), 16, 50, big.NewInt(390625e10)}, + {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 8), 16, 50, big.NewInt(1953125e9)}, + {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 9), 16, 50, big.NewInt(9765625e8)}, + {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 10), 16, 50, big.NewInt(48828125e7)}, + {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 11), 16, 50, big.NewInt(244140625e6)}, + {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 12), 16, 50, big.NewInt(1220703125e5)}, + {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 13), 16, 50, big.NewInt(6103515625e4)}, + {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 14), 16, 50, big.NewInt(30517578125e3)}, + {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 15), 16, 50, big.NewInt(152587890625e2)}, + {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 15), 17, 50, big.NewInt(152587890625e2)}, + } + + for _, tc := range testcases { + brioche := &BriocheConfig{ + BlockReward: tc.reward, + FirstHalvingBlock: big.NewInt(0), + HalvingPeriod: tc.period, + HalvingTimes: tc.times, + HalvingRate: tc.rate, + } + halved := brioche.halveRewards(tc.reward, tc.period) + if tc.expected.Cmp(halved) != 0 { + t.Errorf("halveRewards mismatched (expected=%v, actual=%v)", tc.expected, halved) + } + } +} + +func TestGetBriocheBlockReward(t *testing.T) { + defaultBlockReward := big.NewInt(1234e14) + testcases := []struct { + briocheConfig *BriocheConfig + blockNum *big.Int + expected *big.Int + }{ + // nil case + { + briocheConfig: nil, + blockNum: big.NewInt(100), + expected: defaultBlockReward, + }, + + // normal case + { + briocheConfig: &BriocheConfig{ + BlockReward: big.NewInt(1e18), + FirstHalvingBlock: big.NewInt(100), + HalvingPeriod: big.NewInt(100), + NoRewardHereafter: big.NewInt(101), + HalvingTimes: 10, + HalvingRate: 50, + }, + blockNum: big.NewInt(100), + expected: big.NewInt(5e17), + }, + { + briocheConfig: &BriocheConfig{ + BlockReward: big.NewInt(1e18), + FirstHalvingBlock: big.NewInt(100), + HalvingPeriod: big.NewInt(100), + NoRewardHereafter: big.NewInt(201), + HalvingTimes: 10, + HalvingRate: 50, + }, + blockNum: big.NewInt(200), + expected: big.NewInt(25e16), + }, + + // base block reward variations + { + briocheConfig: &BriocheConfig{ + BlockReward: big.NewInt(7e18), + FirstHalvingBlock: big.NewInt(100), + HalvingPeriod: big.NewInt(100), + NoRewardHereafter: big.NewInt(101), + HalvingTimes: 10, + HalvingRate: 50, + }, + blockNum: big.NewInt(100), + expected: big.NewInt(35e17), + }, + { + briocheConfig: &BriocheConfig{ + BlockReward: big.NewInt(3), + FirstHalvingBlock: big.NewInt(100), + HalvingPeriod: big.NewInt(100), + NoRewardHereafter: big.NewInt(101), + HalvingTimes: 10, + HalvingRate: 50, + }, + blockNum: big.NewInt(100), + expected: big.NewInt(1), + }, + { + briocheConfig: &BriocheConfig{ + BlockReward: big.NewInt(1), + FirstHalvingBlock: big.NewInt(100), + HalvingPeriod: big.NewInt(100), + NoRewardHereafter: big.NewInt(101), + HalvingTimes: 10, + HalvingRate: 50, + }, + blockNum: big.NewInt(100), + expected: big.NewInt(0), + }, + { + briocheConfig: &BriocheConfig{ + BlockReward: nil, // it will use the default block reward + FirstHalvingBlock: big.NewInt(100), + HalvingPeriod: big.NewInt(100), + NoRewardHereafter: big.NewInt(101), + HalvingTimes: 10, + HalvingRate: 50, + }, + blockNum: big.NewInt(100), + expected: big.NewInt(5e17), + }, + + // no halving + { + briocheConfig: &BriocheConfig{ + BlockReward: nil, // it will use the default block reward + FirstHalvingBlock: nil, + HalvingPeriod: big.NewInt(100), + NoRewardHereafter: big.NewInt(101), + HalvingTimes: 10, + HalvingRate: 50, + }, + blockNum: big.NewInt(100), + expected: big.NewInt(1e18), + }, + { + briocheConfig: &BriocheConfig{ + BlockReward: big.NewInt(10), + FirstHalvingBlock: big.NewInt(100), + HalvingPeriod: nil, + NoRewardHereafter: big.NewInt(101), + HalvingTimes: 10, + HalvingRate: 50, + }, + blockNum: big.NewInt(100), + expected: big.NewInt(10), + }, + { + briocheConfig: &BriocheConfig{ + BlockReward: big.NewInt(10), + FirstHalvingBlock: big.NewInt(100), + HalvingPeriod: big.NewInt(100), + NoRewardHereafter: big.NewInt(101), + HalvingTimes: 0, + HalvingRate: 50, + }, + blockNum: big.NewInt(100), + expected: big.NewInt(10), + }, + { + briocheConfig: &BriocheConfig{ + BlockReward: big.NewInt(10), + FirstHalvingBlock: big.NewInt(100), + HalvingPeriod: big.NewInt(100), + NoRewardHereafter: big.NewInt(200), + HalvingTimes: 10, + HalvingRate: 50, + }, + blockNum: big.NewInt(99), // not yet halving time + expected: big.NewInt(10), + }, + { + briocheConfig: &BriocheConfig{ + BlockReward: big.NewInt(10), + FirstHalvingBlock: big.NewInt(100), + HalvingPeriod: big.NewInt(100), + NoRewardHereafter: big.NewInt(200), + HalvingTimes: 10, + HalvingRate: 100, // no halving rate + }, + blockNum: big.NewInt(100), + expected: big.NewInt(10), + }, + + // no reward case + { + briocheConfig: &BriocheConfig{ + BlockReward: big.NewInt(10), + FirstHalvingBlock: big.NewInt(100), + HalvingPeriod: big.NewInt(100), + NoRewardHereafter: big.NewInt(200), + HalvingTimes: 10, + HalvingRate: 0, // no reward + }, + blockNum: big.NewInt(100), + expected: big.NewInt(0), + }, + { + briocheConfig: &BriocheConfig{ + BlockReward: big.NewInt(10), + FirstHalvingBlock: big.NewInt(100), + HalvingPeriod: big.NewInt(100), + NoRewardHereafter: big.NewInt(200), + HalvingTimes: 10, + HalvingRate: 50, + }, + blockNum: big.NewInt(199), + expected: big.NewInt(5), + }, + { + briocheConfig: &BriocheConfig{ + BlockReward: big.NewInt(10), + FirstHalvingBlock: big.NewInt(100), + HalvingPeriod: big.NewInt(100), + NoRewardHereafter: big.NewInt(200), + HalvingTimes: 10, + HalvingRate: 50, + }, + blockNum: big.NewInt(200), + expected: big.NewInt(0), + }, + + // halving rate variations + { + briocheConfig: &BriocheConfig{ + BlockReward: big.NewInt(1e18), + FirstHalvingBlock: big.NewInt(100), + HalvingPeriod: big.NewInt(100), + NoRewardHereafter: big.NewInt(1000), + HalvingTimes: 10, + HalvingRate: 10, + }, + blockNum: big.NewInt(100), + expected: big.NewInt(1e17), + }, + { + briocheConfig: &BriocheConfig{ + BlockReward: big.NewInt(1e18), + FirstHalvingBlock: big.NewInt(100), + HalvingPeriod: big.NewInt(100), + NoRewardHereafter: big.NewInt(1000), + HalvingTimes: 10, + HalvingRate: 10, + }, + blockNum: big.NewInt(200), + expected: big.NewInt(1e16), + }, + { + briocheConfig: &BriocheConfig{ + BlockReward: big.NewInt(1e18), + FirstHalvingBlock: big.NewInt(100), + HalvingPeriod: big.NewInt(100), + NoRewardHereafter: big.NewInt(1000), + HalvingTimes: 10, + HalvingRate: 1, + }, + blockNum: big.NewInt(300), + expected: big.NewInt(1e12), + }, + { + briocheConfig: &BriocheConfig{ + BlockReward: big.NewInt(1e18), + FirstHalvingBlock: big.NewInt(100), + HalvingPeriod: big.NewInt(100), + NoRewardHereafter: big.NewInt(1000), + HalvingTimes: 10, + HalvingRate: 99, + }, + blockNum: big.NewInt(300), + expected: big.NewInt(970299e12), + }, + } + + for _, tc := range testcases { + actual := tc.briocheConfig.GetBriocheBlockReward(defaultBlockReward, tc.blockNum) + if tc.expected.Cmp(actual) != 0 { + t.Errorf("getBriocheReward mismatched (expected=%v, actual=%v)", tc.expected, actual) + } + } +} diff --git a/wemix/admin.go b/wemix/admin.go index a763eb1cad19..65fbb4e3920a 100644 --- a/wemix/admin.go +++ b/wemix/admin.go @@ -127,7 +127,7 @@ var ( etcdClusterName = "Wemix" big0 = big.NewInt(0) nilAddress = common.Address{} - defaultBriocheBlockReward = int64(1e18) + defaultBriocheBlockReward = big.NewInt(1e18) admin *wemixAdmin ErrAlreadyRunning = errors.New("already running") @@ -1182,7 +1182,7 @@ func (ma *wemixAdmin) calculateRewards(config *params.ChainConfig, num, fees *bi var blockReward *big.Int if config.IsBrioche(num) { - blockReward = getBriocheBlockReward(config.Brioche, num) + blockReward = config.Brioche.GetBriocheBlockReward(defaultBriocheBlockReward, num) } else { // if the wemix chain is not on brioche hard fork, use the `rewardAmount` from gov contract blockReward = big.NewInt(0).Set(rp.rewardAmount) @@ -1210,45 +1210,10 @@ func (ma *wemixAdmin) calculateRewards(config *params.ChainConfig, num, fees *bi return } -func getBriocheBlockReward(brioche *params.BriocheConfig, num *big.Int) *big.Int { - blockReward := big.NewInt(defaultBriocheBlockReward) // default brioche block reward - if brioche != nil { - if brioche.BlockReward != nil { - blockReward = big.NewInt(0).Set(brioche.BlockReward) - } - if brioche.NoRewardHereafter != nil && - brioche.NoRewardHereafter.Cmp(num) <= 0 { - blockReward = big.NewInt(0) - } else if brioche.FirstHalvingBlock != nil && - brioche.HalvingPeriod != nil && - brioche.HalvingTimes > 0 && - num.Cmp(brioche.FirstHalvingBlock) >= 0 { - past := big.NewInt(0).Set(num) - past.Sub(past, brioche.FirstHalvingBlock) - blockReward = halveRewards(blockReward, brioche.HalvingPeriod, past, brioche.HalvingTimes, brioche.HalvingRate) - } - } - return blockReward -} - func calculateRewards(config *params.ChainConfig, num, fees *big.Int, addBalance func(common.Address, *big.Int)) (*common.Address, []byte, error) { return admin.calculateRewards(config, num, fees, addBalance) } -func halveRewards(baseReward *big.Int, halvePeriod *big.Int, pastBlocks *big.Int, halvingTimes uint64, halvingRate uint32) *big.Int { - result := big.NewInt(0).Set(baseReward) - past := big.NewInt(0).Set(pastBlocks) - for ; halvingTimes > 0; halvingTimes-- { - result = result.Mul(result, big.NewInt(int64(halvingRate))) - result = result.Div(result, big.NewInt(100)) - if past.Cmp(halvePeriod) < 0 { - break - } - past = past.Sub(past, halvePeriod) - } - return result -} - func verifyRewards(num *big.Int, rewards string) error { return nil //return admin.verifyRewards(num, rewards) diff --git a/wemix/admin_test.go b/wemix/admin_test.go deleted file mode 100644 index dcca75724a9a..000000000000 --- a/wemix/admin_test.go +++ /dev/null @@ -1,308 +0,0 @@ -package wemix - -import ( - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/params" -) - -func TestHalveRewards(t *testing.T) { - testcases := []struct { - reward *big.Int - period *big.Int - past *big.Int - times uint64 - rate uint32 - expected *big.Int - }{ - // sample test - {big.NewInt(1e18), big.NewInt(100), big.NewInt(0), 4, 50, big.NewInt(5e17)}, - {big.NewInt(1e18), big.NewInt(100), big.NewInt(99), 4, 50, big.NewInt(5e17)}, - {big.NewInt(1e18), big.NewInt(100), big.NewInt(100), 4, 50, big.NewInt(25e16)}, - {big.NewInt(1e18), big.NewInt(100), big.NewInt(101), 4, 50, big.NewInt(25e16)}, - - // times test - {big.NewInt(1e18), big.NewInt(100), big.NewInt(0), 0, 50, big.NewInt(1e18)}, - {big.NewInt(1e18), big.NewInt(100), big.NewInt(100), 0, 50, big.NewInt(1e18)}, - {big.NewInt(1e18), big.NewInt(100), big.NewInt(100), 1, 50, big.NewInt(5e17)}, - {big.NewInt(1e18), big.NewInt(100), big.NewInt(100), 2, 50, big.NewInt(25e16)}, - {big.NewInt(1e18), big.NewInt(100), big.NewInt(100), 3, 50, big.NewInt(25e16)}, - - // rate test - {big.NewInt(1e18), big.NewInt(100), big.NewInt(100), 2, 10, big.NewInt(1e16)}, - {big.NewInt(1e18), big.NewInt(100), big.NewInt(200), 3, 10, big.NewInt(1e15)}, - {big.NewInt(1e18), big.NewInt(100), big.NewInt(100), 2, 20, big.NewInt(4e16)}, - {big.NewInt(1e18), big.NewInt(100), big.NewInt(100), 2, 30, big.NewInt(9e16)}, - {big.NewInt(1e18), big.NewInt(100), big.NewInt(100), 2, 90, big.NewInt(81e16)}, - - // brioche halving test - {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(0), 16, 50, big.NewInt(5e17)}, - {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 - 1), 16, 50, big.NewInt(5e17)}, - {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200), 16, 50, big.NewInt(25e16)}, - {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200*2 - 1), 16, 50, big.NewInt(25e16)}, - {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 2), 16, 50, big.NewInt(125e15)}, - {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 3), 16, 50, big.NewInt(625e14)}, - {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 4), 16, 50, big.NewInt(3125e13)}, - {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 5), 16, 50, big.NewInt(15625e12)}, - {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 6), 16, 50, big.NewInt(78125e11)}, - {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 7), 16, 50, big.NewInt(390625e10)}, - {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 8), 16, 50, big.NewInt(1953125e9)}, - {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 9), 16, 50, big.NewInt(9765625e8)}, - {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 10), 16, 50, big.NewInt(48828125e7)}, - {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 11), 16, 50, big.NewInt(244140625e6)}, - {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 12), 16, 50, big.NewInt(1220703125e5)}, - {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 13), 16, 50, big.NewInt(6103515625e4)}, - {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 14), 16, 50, big.NewInt(30517578125e3)}, - {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 15), 16, 50, big.NewInt(152587890625e2)}, - {big.NewInt(1e18), big.NewInt(63115200), big.NewInt(63115200 * 15), 17, 50, big.NewInt(152587890625e2)}, - } - - for _, tc := range testcases { - halved := halveRewards(tc.reward, tc.period, tc.past, tc.times, tc.rate) - if tc.expected.Cmp(halved) != 0 { - t.Errorf("halveRewards mismatched (expected=%v, actual=%v)", tc.expected, halved) - } - } -} - -func TestGetBriocheBlockReward(t *testing.T) { - testcases := []struct { - briocheConfig *params.BriocheConfig - blockNum *big.Int - expected *big.Int - }{ - // normal case - { - briocheConfig: ¶ms.BriocheConfig{ - BlockReward: big.NewInt(1e18), - FirstHalvingBlock: big.NewInt(100), - HalvingPeriod: big.NewInt(100), - NoRewardHereafter: big.NewInt(101), - HalvingTimes: 10, - HalvingRate: 50, - }, - blockNum: big.NewInt(100), - expected: big.NewInt(5e17), - }, - { - briocheConfig: ¶ms.BriocheConfig{ - BlockReward: big.NewInt(1e18), - FirstHalvingBlock: big.NewInt(100), - HalvingPeriod: big.NewInt(100), - NoRewardHereafter: big.NewInt(201), - HalvingTimes: 10, - HalvingRate: 50, - }, - blockNum: big.NewInt(200), - expected: big.NewInt(25e16), - }, - - // base block reward variations - { - briocheConfig: ¶ms.BriocheConfig{ - BlockReward: big.NewInt(7e18), - FirstHalvingBlock: big.NewInt(100), - HalvingPeriod: big.NewInt(100), - NoRewardHereafter: big.NewInt(101), - HalvingTimes: 10, - HalvingRate: 50, - }, - blockNum: big.NewInt(100), - expected: big.NewInt(35e17), - }, - { - briocheConfig: ¶ms.BriocheConfig{ - BlockReward: big.NewInt(3), - FirstHalvingBlock: big.NewInt(100), - HalvingPeriod: big.NewInt(100), - NoRewardHereafter: big.NewInt(101), - HalvingTimes: 10, - HalvingRate: 50, - }, - blockNum: big.NewInt(100), - expected: big.NewInt(1), - }, - { - briocheConfig: ¶ms.BriocheConfig{ - BlockReward: big.NewInt(1), - FirstHalvingBlock: big.NewInt(100), - HalvingPeriod: big.NewInt(100), - NoRewardHereafter: big.NewInt(101), - HalvingTimes: 10, - HalvingRate: 50, - }, - blockNum: big.NewInt(100), - expected: big.NewInt(0), - }, - { - briocheConfig: ¶ms.BriocheConfig{ - BlockReward: nil, // it will use the default block reward - FirstHalvingBlock: big.NewInt(100), - HalvingPeriod: big.NewInt(100), - NoRewardHereafter: big.NewInt(101), - HalvingTimes: 10, - HalvingRate: 50, - }, - blockNum: big.NewInt(100), - expected: big.NewInt(5e17), - }, - - // no halving - { - briocheConfig: ¶ms.BriocheConfig{ - BlockReward: nil, // it will use the default block reward - FirstHalvingBlock: nil, - HalvingPeriod: big.NewInt(100), - NoRewardHereafter: big.NewInt(101), - HalvingTimes: 10, - HalvingRate: 50, - }, - blockNum: big.NewInt(100), - expected: big.NewInt(1e18), - }, - { - briocheConfig: ¶ms.BriocheConfig{ - BlockReward: big.NewInt(10), - FirstHalvingBlock: big.NewInt(100), - HalvingPeriod: nil, - NoRewardHereafter: big.NewInt(101), - HalvingTimes: 10, - HalvingRate: 50, - }, - blockNum: big.NewInt(100), - expected: big.NewInt(10), - }, - { - briocheConfig: ¶ms.BriocheConfig{ - BlockReward: big.NewInt(10), - FirstHalvingBlock: big.NewInt(100), - HalvingPeriod: big.NewInt(100), - NoRewardHereafter: big.NewInt(101), - HalvingTimes: 0, - HalvingRate: 50, - }, - blockNum: big.NewInt(100), - expected: big.NewInt(10), - }, - { - briocheConfig: ¶ms.BriocheConfig{ - BlockReward: big.NewInt(10), - FirstHalvingBlock: big.NewInt(100), - HalvingPeriod: big.NewInt(100), - NoRewardHereafter: big.NewInt(200), - HalvingTimes: 10, - HalvingRate: 50, - }, - blockNum: big.NewInt(99), // not yet halving time - expected: big.NewInt(10), - }, - { - briocheConfig: ¶ms.BriocheConfig{ - BlockReward: big.NewInt(10), - FirstHalvingBlock: big.NewInt(100), - HalvingPeriod: big.NewInt(100), - NoRewardHereafter: big.NewInt(200), - HalvingTimes: 10, - HalvingRate: 100, // no halving rate - }, - blockNum: big.NewInt(100), - expected: big.NewInt(10), - }, - - // no reward case - { - briocheConfig: ¶ms.BriocheConfig{ - BlockReward: big.NewInt(10), - FirstHalvingBlock: big.NewInt(100), - HalvingPeriod: big.NewInt(100), - NoRewardHereafter: big.NewInt(200), - HalvingTimes: 10, - HalvingRate: 0, // no reward - }, - blockNum: big.NewInt(100), - expected: big.NewInt(0), - }, - { - briocheConfig: ¶ms.BriocheConfig{ - BlockReward: big.NewInt(10), - FirstHalvingBlock: big.NewInt(100), - HalvingPeriod: big.NewInt(100), - NoRewardHereafter: big.NewInt(200), - HalvingTimes: 10, - HalvingRate: 50, - }, - blockNum: big.NewInt(199), - expected: big.NewInt(5), - }, - { - briocheConfig: ¶ms.BriocheConfig{ - BlockReward: big.NewInt(10), - FirstHalvingBlock: big.NewInt(100), - HalvingPeriod: big.NewInt(100), - NoRewardHereafter: big.NewInt(200), - HalvingTimes: 10, - HalvingRate: 50, - }, - blockNum: big.NewInt(200), - expected: big.NewInt(0), - }, - - // halving rate variations - { - briocheConfig: ¶ms.BriocheConfig{ - BlockReward: big.NewInt(1e18), - FirstHalvingBlock: big.NewInt(100), - HalvingPeriod: big.NewInt(100), - NoRewardHereafter: big.NewInt(1000), - HalvingTimes: 10, - HalvingRate: 10, - }, - blockNum: big.NewInt(100), - expected: big.NewInt(1e17), - }, - { - briocheConfig: ¶ms.BriocheConfig{ - BlockReward: big.NewInt(1e18), - FirstHalvingBlock: big.NewInt(100), - HalvingPeriod: big.NewInt(100), - NoRewardHereafter: big.NewInt(1000), - HalvingTimes: 10, - HalvingRate: 10, - }, - blockNum: big.NewInt(200), - expected: big.NewInt(1e16), - }, - { - briocheConfig: ¶ms.BriocheConfig{ - BlockReward: big.NewInt(1e18), - FirstHalvingBlock: big.NewInt(100), - HalvingPeriod: big.NewInt(100), - NoRewardHereafter: big.NewInt(1000), - HalvingTimes: 10, - HalvingRate: 1, - }, - blockNum: big.NewInt(300), - expected: big.NewInt(1e12), - }, - { - briocheConfig: ¶ms.BriocheConfig{ - BlockReward: big.NewInt(1e18), - FirstHalvingBlock: big.NewInt(100), - HalvingPeriod: big.NewInt(100), - NoRewardHereafter: big.NewInt(1000), - HalvingTimes: 10, - HalvingRate: 99, - }, - blockNum: big.NewInt(300), - expected: big.NewInt(970299e12), - }, - } - - for _, tc := range testcases { - actual := getBriocheBlockReward(tc.briocheConfig, tc.blockNum) - if tc.expected.Cmp(actual) != 0 { - t.Errorf("getBriocheReward mismatched (expected=%v, actual=%v)", tc.expected, actual) - } - } -}