diff --git a/modAionImpl/src/org/aion/zero/impl/blockchain/AionBlockchainImpl.java b/modAionImpl/src/org/aion/zero/impl/blockchain/AionBlockchainImpl.java index 47946899b6..4feba4b991 100644 --- a/modAionImpl/src/org/aion/zero/impl/blockchain/AionBlockchainImpl.java +++ b/modAionImpl/src/org/aion/zero/impl/blockchain/AionBlockchainImpl.java @@ -1160,7 +1160,7 @@ BlockContext createNewMiningBlockInternal( // derive base block reward BigInteger baseBlockReward = this.chainConfiguration - .getRewardsCalculator() + .getRewardsCalculator(forkUtility.isUnityForkActive(block.getHeader().getNumber())) .calculateReward(block.getHeader().getNumber()); return new BlockContext(block, baseBlockReward, totalTransactionFee); } @@ -1783,7 +1783,7 @@ private Map addReward(Block block) { Map rewards = new HashMap<>(); BigInteger minerReward = this.chainConfiguration - .getRewardsCalculator() + .getRewardsCalculator(forkUtility.isUnityForkActive(block.getHeader().getNumber())) .calculateReward(block.getHeader().getNumber()); rewards.put(block.getCoinbase(), minerReward); @@ -2480,6 +2480,11 @@ public boolean isUnityForkEnabledAtNextBlock() { return forkUtility.isUnityForkActive(bestBlockNumber.get() + 1); } + @Override + public boolean isUnityForkActive(long block_number) { + return forkUtility.isUnityForkActive(block_number); + } + /** * A method for creating a new staking block template for the external staker. * diff --git a/modAionImpl/src/org/aion/zero/impl/blockchain/ChainConfiguration.java b/modAionImpl/src/org/aion/zero/impl/blockchain/ChainConfiguration.java index 85ef1dcde4..1d73d32a32 100644 --- a/modAionImpl/src/org/aion/zero/impl/blockchain/ChainConfiguration.java +++ b/modAionImpl/src/org/aion/zero/impl/blockchain/ChainConfiguration.java @@ -8,6 +8,7 @@ import java.util.Map; import org.aion.equihash.OptimizedEquiValidator; import org.aion.mcf.blockchain.BlockHeader.BlockSealType; +import org.aion.zero.impl.core.RewardsCalculatorAfterUnity; import org.aion.zero.impl.core.UnityBlockDiffCalculator; import org.aion.zero.impl.types.IBlockConstants; import org.aion.zero.impl.core.IDifficultyCalculator; @@ -52,6 +53,7 @@ public class ChainConfiguration { protected IDifficultyCalculator preUnityDifficultyCalculator; protected IDifficultyCalculator unityDifficultyCalculator; protected IRewardsCalculator rewardsCalculatorAdapter; + protected IRewardsCalculator rewardsCalculatorAfterUnity; protected OptimizedEquiValidator equiValidator; public ChainConfiguration(final Long monetaryUpdateBlkNum, final BigInteger initialSupply) { @@ -85,6 +87,8 @@ public ChainConfiguration( }; this.rewardsCalculatorAdapter = rewardsCalcInternal::calculateReward; + this.rewardsCalculatorAfterUnity = RewardsCalculatorAfterUnity::calculateReward; + unityDifficultyCalculator = unityCalc::calcDifficulty; } @@ -95,8 +99,8 @@ public IDifficultyCalculator getPreUnityDifficultyCalculator() { return preUnityDifficultyCalculator; } - public IRewardsCalculator getRewardsCalculator() { - return rewardsCalculatorAdapter; + public IRewardsCalculator getRewardsCalculator(boolean isAfterUnityFork) { + return isAfterUnityFork ? rewardsCalculatorAfterUnity : rewardsCalculatorAdapter; } private OptimizedEquiValidator getEquihashValidator() { diff --git a/modAionImpl/src/org/aion/zero/impl/blockchain/UnityChain.java b/modAionImpl/src/org/aion/zero/impl/blockchain/UnityChain.java index b70fe7e16d..fca8c75695 100644 --- a/modAionImpl/src/org/aion/zero/impl/blockchain/UnityChain.java +++ b/modAionImpl/src/org/aion/zero/impl/blockchain/UnityChain.java @@ -55,4 +55,6 @@ Block createStakingBlockTemplate( void loadBestMiningBlock(); boolean isUnityForkEnabledAtNextBlock(); + + boolean isUnityForkActive(long block_number); } diff --git a/modAionImpl/src/org/aion/zero/impl/core/RewardsCalculatorAfterUnity.java b/modAionImpl/src/org/aion/zero/impl/core/RewardsCalculatorAfterUnity.java new file mode 100644 index 0000000000..c1462d3d86 --- /dev/null +++ b/modAionImpl/src/org/aion/zero/impl/core/RewardsCalculatorAfterUnity.java @@ -0,0 +1,15 @@ +package org.aion.zero.impl.core; + +import java.math.BigInteger; + +/** + * The unity protocol block rewards is a fixed rewards equal to 4.5 AION. + */ +public class RewardsCalculatorAfterUnity { + + private static final BigInteger fixedBlockRewards = BigInteger.valueOf(4_500_000_000_000_000_000L); + + public static BigInteger calculateReward(long number) { + return fixedBlockRewards; + } +} diff --git a/modAionImpl/test/org/aion/zero/impl/blockchain/BlockchainIntegrationTest.java b/modAionImpl/test/org/aion/zero/impl/blockchain/BlockchainIntegrationTest.java index 8c7ecd6be5..5eca075cc8 100644 --- a/modAionImpl/test/org/aion/zero/impl/blockchain/BlockchainIntegrationTest.java +++ b/modAionImpl/test/org/aion/zero/impl/blockchain/BlockchainIntegrationTest.java @@ -353,7 +353,7 @@ public void testBlockContextCreation() { // check that the correct amount was calculated assertThat( configuration - .getRewardsCalculator() + .getRewardsCalculator(false) .calculateReward(context.block.getHeader().getNumber())) .isEqualTo(context.baseBlockReward); } diff --git a/modAionImpl/test/org/aion/zero/impl/blockchain/ChainConfigurationTest.java b/modAionImpl/test/org/aion/zero/impl/blockchain/ChainConfigurationTest.java index 34a48a1574..25aded04db 100644 --- a/modAionImpl/test/org/aion/zero/impl/blockchain/ChainConfigurationTest.java +++ b/modAionImpl/test/org/aion/zero/impl/blockchain/ChainConfigurationTest.java @@ -10,13 +10,9 @@ import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class ChainConfigurationTest { - private static final Logger log = LoggerFactory.getLogger(ChainConfigurationTest.class); - @Mock A0BlockHeader header; @Before @@ -95,11 +91,11 @@ public void testRampUpFunctionBoundaries() { // UPPER BOUND when(header.getNumber()).thenReturn(upperBound); BigInteger blockReward259200 = - config.getRewardsCalculator().calculateReward(header.getNumber()); + config.getRewardsCalculator(false).calculateReward(header.getNumber()); when(header.getNumber()).thenReturn(upperBound + 1); BigInteger blockReward259201 = - config.getRewardsCalculator().calculateReward(header.getNumber()); + config.getRewardsCalculator(false).calculateReward(header.getNumber()); // check that at the upper bound of our range (which is not included) blockReward is capped assertThat(blockReward259200).isEqualTo(new BigInteger("1497989283243258292")); @@ -109,17 +105,49 @@ public void testRampUpFunctionBoundaries() { // check that for an arbitrarily large block, the block reward is still the same when(header.getNumber()).thenReturn(upperBound + 100000); - BigInteger blockUpper = config.getRewardsCalculator().calculateReward(header.getNumber()); + BigInteger blockUpper = config.getRewardsCalculator(false).calculateReward(header.getNumber()); assertThat(blockUpper).isEqualTo(config.getConstants().getBlockReward()); // LOWER BOUNDS when(header.getNumber()).thenReturn(0l); - BigInteger blockReward0 = config.getRewardsCalculator().calculateReward(header.getNumber()); + BigInteger blockReward0 = config.getRewardsCalculator(false).calculateReward(header.getNumber()); assertThat(blockReward0).isEqualTo(new BigInteger("748994641621655092")); // first block (should have gas value of increment) when(header.getNumber()).thenReturn(1l); - BigInteger blockReward1 = config.getRewardsCalculator().calculateReward(header.getNumber()); + BigInteger blockReward1 = config.getRewardsCalculator(false).calculateReward(header.getNumber()); assertThat(blockReward1).isEqualTo(increment); } + + @Test + public void testCalculatorReturnsByFork() { + + long upperBound = 259200L; + ChainConfiguration config = new ChainConfiguration(); + BigInteger increment = + config.getConstants() + .getBlockReward() + .subtract(config.getConstants().getRampUpStartValue()) + .divide(BigInteger.valueOf(upperBound)) + .add(config.getConstants().getRampUpStartValue()); + + // UPPER BOUND + when(header.getNumber()).thenReturn(upperBound); + BigInteger blockReward259200 = + config.getRewardsCalculator(false).calculateReward(header.getNumber()); + + // check that at the upper bound of our range (which is not included) blockReward is capped + assertThat(blockReward259200).isEqualTo(new BigInteger("1497989283243258292")); + + BigInteger blockRewardAfterUnityFork = + config.getRewardsCalculator(true).calculateReward(header.getNumber()); + + assertThat(blockRewardAfterUnityFork).isEqualTo(new BigInteger("4500000000000000000")); + + BigInteger blockRewardAfterUnityForkPlusOne = + config.getRewardsCalculator(true).calculateReward(header.getNumber() + 1); + + assertThat(blockRewardAfterUnityForkPlusOne).isEqualTo(new BigInteger("4500000000000000000")); + + } } diff --git a/modApiServer/src/org/aion/api/server/pb/ApiAion0.java b/modApiServer/src/org/aion/api/server/pb/ApiAion0.java index 2fc657a944..ea4f6b82b5 100644 --- a/modApiServer/src/org/aion/api/server/pb/ApiAion0.java +++ b/modApiServer/src/org/aion/api/server/pb/ApiAion0.java @@ -1001,13 +1001,15 @@ public byte[] process(byte[] request, byte[] socketId) { BigInteger reward; try { + AionBlockchainImpl blockchainImpl = (AionBlockchainImpl) this.ac.getBlockchain(); + req = Message.req_getBlockReward.parseFrom(data); long num = req.getBlockNumber(); reward = - ((AionBlockchainImpl) ac.getBlockchain()) - .getChainConfiguration() - .getRewardsCalculator() - .calculateReward(num); + blockchainImpl + .getChainConfiguration() + .getRewardsCalculator(blockchainImpl.isUnityForkActive(num)) + .calculateReward(num); } catch (Exception e) { LOG.error("ApiAion0.process.getBlockReward exception: [{}]", e); return ApiUtil.toReturnHeader( diff --git a/modApiServer/src/org/aion/api/server/rpc/ApiWeb3Aion.java b/modApiServer/src/org/aion/api/server/rpc/ApiWeb3Aion.java index e7255986ae..2ff0657373 100644 --- a/modApiServer/src/org/aion/api/server/rpc/ApiWeb3Aion.java +++ b/modApiServer/src/org/aion/api/server/rpc/ApiWeb3Aion.java @@ -1951,11 +1951,13 @@ private JSONObject computeMetrics() { txnCount += b.getTransactionsList().size(); } + AionBlockchainImpl blockchainImpl = (AionBlockchainImpl) ac.getBlockchain(); + BigInteger lastBlkReward = - ((AionBlockchainImpl) ac.getBlockchain()) - .getChainConfiguration() - .getRewardsCalculator() - .calculateReward(b.getHeader().getNumber()); + blockchainImpl + .getChainConfiguration() + .getRewardsCalculator(blockchainImpl.isUnityForkActive(b.getHeader().getNumber())) + .calculateReward(b.getHeader().getNumber()); double blkTime = 0; double hashRate = 0; @@ -2265,10 +2267,12 @@ public RpcMsg ops_getBlock(Object _params) { Long bn = this.parseBnOrId(_bnOrHash); + AionBlockchainImpl blockchainImpl = (AionBlockchainImpl) this.ac.getBlockchain(); + // user passed a Long block number if (bn != null) { if (bn >= 0) { - block = this.ac.getBlockchain().getBlockByNumber(bn); + block = blockchainImpl.getBlockByNumber(bn); if (block == null) { return new RpcMsg(JSONObject.NULL); } @@ -2279,13 +2283,13 @@ public RpcMsg ops_getBlock(Object _params) { // see if the user passed in a hash if (block == null) { - block = this.ac.getBlockchain().getBlockByHash(ByteUtil.hexStringToBytes(_bnOrHash)); + block = blockchainImpl.getBlockByHash(ByteUtil.hexStringToBytes(_bnOrHash)); if (block == null) { return new RpcMsg(JSONObject.NULL); } } - Block mainBlock = this.ac.getBlockchain().getBlockByNumber(block.getNumber()); + Block mainBlock = blockchainImpl.getBlockByNumber(block.getNumber()); if (mainBlock == null) { return new RpcMsg(JSONObject.NULL); } @@ -2297,10 +2301,10 @@ public RpcMsg ops_getBlock(Object _params) { // ok so now we have a mainchain block BigInteger blkReward = - ((AionBlockchainImpl) ac.getBlockchain()) - .getChainConfiguration() - .getRewardsCalculator() - .calculateReward(block.getHeader().getNumber()); + blockchainImpl + .getChainConfiguration() + .getRewardsCalculator(blockchainImpl.isUnityForkActive(block.getHeader().getNumber())) + .calculateReward(block.getHeader().getNumber()); BigInteger totalDiff = this.ac.getAionHub().getTotalDifficultyForHash(block.getHash()); @@ -2992,10 +2996,12 @@ private Long parseBnOrId(String _bnOrId) { private RpcMsg rpcBlockDetailsFromBlock(Block block){ + AionBlockchainImpl blockchainImpl = (AionBlockchainImpl) ac.getBlockchain(); + BigInteger blkReward = - ((AionBlockchainImpl) ac.getBlockchain()) + blockchainImpl .getChainConfiguration() - .getRewardsCalculator() + .getRewardsCalculator(blockchainImpl.isUnityForkActive(block.getHeader().getNumber())) .calculateReward(block.getHeader().getNumber()); BigInteger totalDiff = this.ac.getAionHub().getTotalDifficultyForHash(block.getHash());