diff --git a/consensus/ubqhash/consensus.go b/consensus/ubqhash/consensus.go index 8c3eac4532..73e68f9c22 100644 --- a/consensus/ubqhash/consensus.go +++ b/consensus/ubqhash/consensus.go @@ -703,62 +703,71 @@ func (ubqhash *Ubqhash) SealHash(header *types.Header) (hash common.Hash) { return hash } +// Calculates the base block reward as per the ubiq monetary policy +func CalcBaseBlockReward(height *big.Int) *big.Int { + reward := new(big.Int).Set(blockReward) + + if height.Cmp(big.NewInt(358363)) > 0 { + reward = big.NewInt(7e+18) + } + if height.Cmp(big.NewInt(716727)) > 0 { + reward = big.NewInt(6e+18) + } + if height.Cmp(big.NewInt(1075090)) > 0 { + reward = big.NewInt(5e+18) + } + if height.Cmp(big.NewInt(1433454)) > 0 { + reward = big.NewInt(4e+18) + } + if height.Cmp(big.NewInt(1791818)) > 0 { + reward = big.NewInt(3e+18) + } + if height.Cmp(big.NewInt(2150181)) > 0 { + reward = big.NewInt(2e+18) + } + if height.Cmp(big.NewInt(2508545)) > 0 { + reward = big.NewInt(1e+18) + } + return reward +} + +func CalcUncleBlockReward(config *params.ChainConfig, blockHeight *big.Int, uncleHeight *big.Int, blockReward *big.Int) *big.Int { + reward := new(big.Int) + // calculate reward based on depth + reward.Add(uncleHeight, big2) + reward.Sub(reward, blockHeight) + reward.Mul(reward, blockReward) + reward.Div(reward, big2) + + // negative uncle reward fix. (activates along-side EIP158) + if config.IsEIP158(blockHeight) && reward.Cmp(big.NewInt(0)) < 0 { + reward = big.NewInt(0) + } + return reward +} + // AccumulateRewards credits the coinbase of the given block with the mining // reward. The total reward consists of the static block reward and rewards for // included uncles. The coinbase of each uncle block is also rewarded. func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header, uncles []*types.Header) { - reward := new(big.Int).Set(blockReward) + // block reward (miner) + reward := CalcBaseBlockReward(header.Number) - if header.Number.Cmp(big.NewInt(358363)) > 0 { - reward = big.NewInt(7e+18) - } - if header.Number.Cmp(big.NewInt(716727)) > 0 { - reward = big.NewInt(6e+18) - } - if header.Number.Cmp(big.NewInt(1075090)) > 0 { - reward = big.NewInt(5e+18) - } - if header.Number.Cmp(big.NewInt(1433454)) > 0 { - reward = big.NewInt(4e+18) - } - if header.Number.Cmp(big.NewInt(1791818)) > 0 { - reward = big.NewInt(3e+18) - } - if header.Number.Cmp(big.NewInt(2150181)) > 0 { - reward = big.NewInt(2e+18) - } - if header.Number.Cmp(big.NewInt(2508545)) > 0 { - reward = big.NewInt(1e+18) - } - - // Uncle reward step down fix. + // Uncle reward step down fix. (activates along-side byzantium) ufixReward := new(big.Int).Set(blockReward) if config.IsByzantium(header.Number) { ufixReward = reward } - r := new(big.Int) for _, uncle := range uncles { - r.Add(uncle.Number, big2) - r.Sub(r, header.Number) - r.Mul(r, ufixReward) - r.Div(r, big2) - - if header.Number.Cmp(big.NewInt(10)) < 0 { - state.AddBalance(uncle.Coinbase, r) - r.Div(ufixReward, big32) - if r.Cmp(big.NewInt(0)) < 0 { - r = big.NewInt(0) - } - } else { - if r.Cmp(big.NewInt(0)) < 0 { - r = big.NewInt(0) - } - state.AddBalance(uncle.Coinbase, r) - r.Div(ufixReward, big32) - } - - reward.Add(reward, r) + // uncle block miner reward (depth === 1 ? baseBlockReward * 0.5 : 0) + uncleReward := CalcUncleBlockReward(config, header.Number, uncle.Number, ufixReward) + // update uncle miner balance + state.AddBalance(uncle.Coinbase, uncleReward) + // include uncle bonus reward (baseBlockReward/32) + uncleReward.Div(ufixReward, big32) + reward.Add(reward, uncleReward) } + // update block miner balance state.AddBalance(header.Coinbase, reward) } diff --git a/consensus/ubqhash/consensus_test.go b/consensus/ubqhash/consensus_test.go index 5b3953c2f9..04646c5959 100644 --- a/consensus/ubqhash/consensus_test.go +++ b/consensus/ubqhash/consensus_test.go @@ -102,3 +102,117 @@ func TestCalcDifficulty(t *testing.T) { } } } + +func TestCalcBaseBlockReward(t *testing.T) { + reward := CalcBaseBlockReward(big.NewInt(1)) + if reward.Cmp(big.NewInt(8e+18)) != 0 { + t.Error("TestCalcBaseBlockReward 8 (start)", "failed. Expected", big.NewInt(8e+18), "and calculated", reward) + } + reward = CalcBaseBlockReward(big.NewInt(358363)) + if reward.Cmp(big.NewInt(8e+18)) != 0 { + t.Error("TestCalcBaseBlockReward 8 (end)", "failed. Expected", big.NewInt(8e+18), "and calculated", reward) + } + + reward = CalcBaseBlockReward(big.NewInt(358364)) + if reward.Cmp(big.NewInt(7e+18)) != 0 { + t.Error("TestCalcBaseBlockReward 7 (start)", "failed. Expected", big.NewInt(7e+18), "and calculated", reward) + } + reward = CalcBaseBlockReward(big.NewInt(716727)) + if reward.Cmp(big.NewInt(7e+18)) != 0 { + t.Error("TestCalcBaseBlockReward 7 (end)", "failed. Expected", big.NewInt(7e+18), "and calculated", reward) + } + + reward = CalcBaseBlockReward(big.NewInt(716728)) + if reward.Cmp(big.NewInt(6e+18)) != 0 { + t.Error("TestCalcBaseBlockReward 6 (start)", "failed. Expected", big.NewInt(6e+18), "and calculated", reward) + } + reward = CalcBaseBlockReward(big.NewInt(1075090)) + if reward.Cmp(big.NewInt(6e+18)) != 0 { + t.Error("TestCalcBaseBlockReward 6 (end)", "failed. Expected", big.NewInt(6e+18), "and calculated", reward) + } + + reward = CalcBaseBlockReward(big.NewInt(1075091)) + if reward.Cmp(big.NewInt(5e+18)) != 0 { + t.Error("TestCalcBaseBlockReward 5 (start)", "failed. Expected", big.NewInt(5e+18), "and calculated", reward) + } + reward = CalcBaseBlockReward(big.NewInt(1433454)) + if reward.Cmp(big.NewInt(5e+18)) != 0 { + t.Error("TestCalcBaseBlockReward 5 (end)", "failed. Expected", big.NewInt(5e+18), "and calculated", reward) + } + + reward = CalcBaseBlockReward(big.NewInt(1433455)) + if reward.Cmp(big.NewInt(4e+18)) != 0 { + t.Error("TestCalcBaseBlockReward 4 (start)", "failed. Expected", big.NewInt(4e+18), "and calculated", reward) + } + reward = CalcBaseBlockReward(big.NewInt(1791818)) + if reward.Cmp(big.NewInt(4e+18)) != 0 { + t.Error("TestCalcBaseBlockReward 4 (end)", "failed. Expected", big.NewInt(4e+18), "and calculated", reward) + } + + reward = CalcBaseBlockReward(big.NewInt(1791819)) + if reward.Cmp(big.NewInt(3e+18)) != 0 { + t.Error("TestCalcBaseBlockReward 3 (start)", "failed. Expected", big.NewInt(3e+18), "and calculated", reward) + } + reward = CalcBaseBlockReward(big.NewInt(2150181)) + if reward.Cmp(big.NewInt(3e+18)) != 0 { + t.Error("TestCalcBaseBlockReward 3 (end)", "failed. Expected", big.NewInt(3e+18), "and calculated", reward) + } + + reward = CalcBaseBlockReward(big.NewInt(2150182)) + if reward.Cmp(big.NewInt(2e+18)) != 0 { + t.Error("TestCalcBaseBlockReward 2 (start)", "failed. Expected", big.NewInt(2e+18), "and calculated", reward) + } + reward = CalcBaseBlockReward(big.NewInt(2508545)) + if reward.Cmp(big.NewInt(2e+18)) != 0 { + t.Error("TestCalcBaseBlockReward 2 (end)", "failed. Expected", big.NewInt(2e+18), "and calculated", reward) + } + + reward = CalcBaseBlockReward(big.NewInt(2508546)) + if reward.Cmp(big.NewInt(1e+18)) != 0 { + t.Error("TestCalcBaseBlockReward 1 (start)", "failed. Expected", big.NewInt(1e+18), "and calculated", reward) + } +} + +func TestCalcUncleBlockReward(t *testing.T) { + config := ¶ms.ChainConfig{HomesteadBlock: big.NewInt(0), EIP158Block: big.NewInt(10)} + reward := big.NewInt(8e+18) + // depth 1 + u := CalcUncleBlockReward(config, big.NewInt(5), big.NewInt(4), reward) + if u.Cmp(big.NewInt(4e+18)) != 0 { + t.Error("TestCalcUncleBlockReward 8", "failed. Expected", big.NewInt(4e+18), "and calculated", u) + } + + // depth 2 + u = CalcUncleBlockReward(config, big.NewInt(8), big.NewInt(6), reward) + if u.Cmp(big.NewInt(0)) != 0 { + t.Error("TestCalcUncleBlockReward 8", "failed. Expected", big.NewInt(0), "and calculated", u) + } + + // depth 3 (before negative fix) + u = CalcUncleBlockReward(config, big.NewInt(8), big.NewInt(5), reward) + if u.Cmp(big.NewInt(-4e+18)) != 0 { + t.Error("TestCalcUncleBlockReward 8", "failed. Expected", big.NewInt(-4e+18), "and calculated", u) + } + + // depth 3 (after negative fix) + u = CalcUncleBlockReward(config, big.NewInt(10), big.NewInt(7), reward) + if u.Cmp(big.NewInt(0)) != 0 { + t.Error("TestCalcUncleBlockReward 8", "failed. Expected", big.NewInt(0), "and calculated", u) + } + + reward = big.NewInt(7e+18) + expected := big.NewInt(35e+17) + // depth 1 (after stepdown) + u = CalcUncleBlockReward(config, big.NewInt(8), big.NewInt(7), reward) + if u.Cmp(expected) != 0 { + t.Error("TestCalcUncleBlockReward 7", "failed. Expected", expected, "and calculated", u) + } + + reward = big.NewInt(5e+18) + expected = big.NewInt(25e+17) + // depth 1 (after stepdown) + u = CalcUncleBlockReward(config, big.NewInt(8), big.NewInt(7), reward) + if u.Cmp(expected) != 0 { + t.Error("TestCalcUncleBlockReward 5", "failed. Expected", expected, "and calculated", u) + } +}