use of org.aion.zero.impl.vm.TestResourceProvider in project aion by aionnetwork.
the class SignatureSchemeSwapForkTest method testSigatureSchemeSwapFork.
@Test
public void testSigatureSchemeSwapFork() throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException {
// setup Unity fork and AVM
long unityForkBlock = 2;
long signatureSwapForkBlockHeight = unityForkBlock + 3;
setupAVM(unityForkBlock);
TestResourceProvider resourceProvider = TestResourceProvider.initializeAndCreateNewProvider(AvmPathManager.getPathOfProjectRootDirectory());
// setup an identical blockchains
StandaloneBlockchain blockchain = setupIdenticalBlockchain(unityForkBlock, signatureSwapForkBlockHeight);
// create block with staker registry
Block blockWithRegistry = BlockchainTestUtils.generateNextMiningBlockWithStakerRegistry(blockchain, blockchain.getGenesis(), resourceProvider, stakingRegistryOwner);
// import block on firstChain
Pair<ImportResult, AionBlockSummary> result = blockchain.tryToConnectAndFetchSummary(blockWithRegistry);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
assertThat(result.getRight().getReceipts().get(0).isSuccessful()).isTrue();
assertThat(result.getRight().getReceipts().get(0).getLogInfoList()).isNotEmpty();
assertThat(result.getRight().getReceipts().get(0).getEnergyUsed()).isEqualTo(1_225_655L);
// set the staking contract address in the staking genesis
AionTransaction deploy = blockWithRegistry.getTransactionsList().get(0);
AionAddress contract = TxUtil.calculateContractAddress(deploy.getSenderAddress().toByteArray(), deploy.getNonceBI());
blockchain.getGenesis().setStakingContractAddress(contract);
// create Unity block with stakers
Block block2Unity = BlockchainTestUtils.generateNextMiningBlockWithStakers(blockchain, blockchain.getBestBlock(), resourceProvider, stakers, MIN_SELF_STAKE);
// import block2Unity on blockchain
result = blockchain.tryToConnectAndFetchSummary(block2Unity);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
verifyReceipts(result.getRight().getReceipts(), 3, true);
// create staking block
Block block3Staking = BlockchainTestUtils.generateNextStakingBlock(blockchain, blockchain.getBestBlock(), Collections.emptyList(), stakers.get(0));
assertThat(block3Staking).isNotNull();
// import block3Staking on blockchain
result = blockchain.tryToConnectAndFetchSummary(block3Staking);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
// create next mining block
Block block4Mining = BlockchainTestUtils.generateNextMiningBlock(blockchain, blockchain.getBestBlock(), Collections.emptyList());
// import block4Mining on blockchain
result = blockchain.tryToConnectAndFetchSummary(block4Mining);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
// create the first signatureSchemeSwap block
Block block5SignatureSchemeSwapStaking = BlockchainTestUtils.generateNextStakingBlock(blockchain, blockchain.getBestBlock(), Collections.emptyList(), stakers.get(0));
assertThat(block5SignatureSchemeSwapStaking).isNotNull();
// import block5SignatureSchemeSwapStaking on blockchain
result = blockchain.tryToConnectAndFetchSummary(block5SignatureSchemeSwapStaking);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
// create next mining block
Block block6Mining = BlockchainTestUtils.generateNextMiningBlock(blockchain, blockchain.getBestBlock(), Collections.emptyList());
// import block6Mining on blockchain
result = blockchain.tryToConnectAndFetchSummary(block6Mining);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
// create next staking block
Block block7Staking = BlockchainTestUtils.generateNextStakingBlock(blockchain, blockchain.getBestBlock(), Collections.emptyList(), stakers.get(0));
// import block7Staking on blockchain
result = blockchain.tryToConnectAndFetchSummary(block7Staking);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
}
use of org.aion.zero.impl.vm.TestResourceProvider in project aion by aionnetwork.
the class SignatureSchemeSwapForkTest method testSigatureSchemeSwapForkBlockRewards.
@Test
public void testSigatureSchemeSwapForkBlockRewards() throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException {
// setup Unity fork and AVM
long unityForkBlock = 2;
long signatureSwapForkBlockHeight = unityForkBlock + 3;
setupAVM(unityForkBlock);
TestResourceProvider resourceProvider = TestResourceProvider.initializeAndCreateNewProvider(AvmPathManager.getPathOfProjectRootDirectory());
// setup an identical blockchains
StandaloneBlockchain blockchain = setupIdenticalBlockchain(unityForkBlock, signatureSwapForkBlockHeight);
// create block with staker registry
Block blockWithRegistry = BlockchainTestUtils.generateNextMiningBlockWithStakerRegistry(blockchain, blockchain.getGenesis(), resourceProvider, stakingRegistryOwner);
// import block on firstChain
Pair<ImportResult, AionBlockSummary> result = blockchain.tryToConnectAndFetchSummary(blockWithRegistry);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
assertThat(result.getRight().getReceipts().get(0).isSuccessful()).isTrue();
assertThat(result.getRight().getReceipts().get(0).getLogInfoList()).isNotEmpty();
assertThat(result.getRight().getReceipts().get(0).getEnergyUsed()).isEqualTo(1_225_655L);
// set the staking contract address in the staking genesis
AionTransaction deploy = blockWithRegistry.getTransactionsList().get(0);
AionAddress contract = TxUtil.calculateContractAddress(deploy.getSenderAddress().toByteArray(), deploy.getNonceBI());
blockchain.getGenesis().setStakingContractAddress(contract);
// create Unity block with stakers
Block block2Unity = BlockchainTestUtils.generateNextMiningBlockWithStakers(blockchain, blockchain.getBestBlock(), resourceProvider, stakers, MIN_SELF_STAKE);
// import block2Unity on blockchain
result = blockchain.tryToConnectAndFetchSummary(block2Unity);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
verifyReceipts(result.getRight().getReceipts(), 3, true);
// create staking block
Block block3Staking = BlockchainTestUtils.generateNextStakingBlock(blockchain, blockchain.getBestBlock(), Collections.emptyList(), stakers.get(0));
assertThat(block3Staking).isNotNull();
// import block3Staking on blockchain
result = blockchain.tryToConnectAndFetchSummary(block3Staking);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
// create next mining block
Block block4Mining = BlockchainTestUtils.generateNextMiningBlock(blockchain, blockchain.getBestBlock(), Collections.emptyList());
// import block4Mining on blockchain
result = blockchain.tryToConnectAndFetchSummary(block4Mining);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
// create the first signatureSchemeSwap block
Block block5SignatureSchemeSwapStaking = BlockchainTestUtils.generateNextStakingBlock(blockchain, blockchain.getBestBlock(), Collections.emptyList(), stakers.get(0));
assertThat(block5SignatureSchemeSwapStaking).isNotNull();
// Check the balance of the blockProducer
AionAddress blockProducer = block5SignatureSchemeSwapStaking.getCoinbase();
BigInteger balance = blockchain.getRepository().getBalance(blockProducer);
// import block5SignatureSchemeSwapStaking on blockchain
result = blockchain.tryToConnectAndFetchSummary(block5SignatureSchemeSwapStaking);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
// Check the block producer receive the correct balance (4.5 AION)
BigInteger newBalance = blockchain.getRepository().getBalance(blockProducer);
assertThat(newBalance).isEqualTo(balance.add(IRewardsCalculator.fixedRewardsAfterUnity));
// create next mining block
Block block6Mining = BlockchainTestUtils.generateNextMiningBlock(blockchain, blockchain.getBestBlock(), Collections.emptyList(), block5SignatureSchemeSwapStaking.getTimestamp() + 1);
// Check the balance of the blockProducer
blockProducer = block6Mining.getCoinbase();
balance = blockchain.getRepository().getBalance(blockProducer);
// import block6Mining on blockchain
result = blockchain.tryToConnectAndFetchSummary(block6Mining);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
// Check the block producer receive the correct balance by the rewards adjustment calculator
newBalance = blockchain.getRepository().getBalance(blockProducer);
long timeSpan = block6Mining.getTimestamp() - block5SignatureSchemeSwapStaking.getTimestamp();
assertThat(newBalance).isEqualTo(balance.add(TimeVaryingRewardsCalculator.calculateReward(timeSpan)));
// create next staking block
Block block7Staking = BlockchainTestUtils.generateNextStakingBlock(blockchain, blockchain.getBestBlock(), Collections.emptyList(), stakers.get(1));
// Check the balance of the blockProducer
assert block7Staking != null;
blockProducer = block7Staking.getCoinbase();
balance = blockchain.getRepository().getBalance(blockProducer);
// import block7Staking on blockchain
result = blockchain.tryToConnectAndFetchSummary(block7Staking);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
// Check the block producer receive the correct balance (4.5 AION)
newBalance = blockchain.getRepository().getBalance(blockProducer);
assertThat(newBalance).isEqualTo(balance.add(IRewardsCalculator.fixedRewardsAfterUnity));
// create next mining block
Block block8Mining = BlockchainTestUtils.generateNextMiningBlock(blockchain, blockchain.getBestBlock(), Collections.emptyList(), block7Staking.getTimestamp() + 71);
// Check the balance of the blockProducer
blockProducer = block8Mining.getCoinbase();
balance = blockchain.getRepository().getBalance(blockProducer);
// import block6Mining on blockchain
result = blockchain.tryToConnectAndFetchSummary(block8Mining);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
// Check the block producer receive the correct balance by the rewards adjustment calculator
newBalance = blockchain.getRepository().getBalance(blockProducer);
timeSpan = block8Mining.getTimestamp() - block7Staking.getTimestamp();
assertThat(newBalance).isEqualTo(balance.add(TimeVaryingRewardsCalculator.calculateReward(timeSpan)));
}
use of org.aion.zero.impl.vm.TestResourceProvider in project aion by aionnetwork.
the class BlockchainForkingTest method testReBranchOnUnityBlockchain.
/**
* The test builds two blockchains causing several re-branching on top of the unity block, the first staking block and the next mining block.
*/
@Test
public void testReBranchOnUnityBlockchain() throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException {
// setup accounts
List<ECKey> accounts = generateAccounts(10);
ECKey stakingRegistryOwner = accounts.get(0);
List<ECKey> stakersOnChain1 = List.of(accounts.get(1), accounts.get(2), accounts.get(3));
List<ECKey> stakersOnChain2 = List.of(accounts.get(4), accounts.get(5), accounts.get(6));
List<ECKey> stakersOnBothChains = List.of(accounts.get(7), accounts.get(8), accounts.get(9));
// setup Unity fork and AVM
long unityForkBlock = 2;
// clear setting from @Before
AvmTestConfig.clearConfigurations();
TransactionTypeRule.allowAVMContractTransaction();
TestResourceProvider resourceProvider = TestResourceProvider.initializeAndCreateNewProvider(AvmPathManager.getPathOfProjectRootDirectory());
// enable both AVMs without overlap
AvmTestConfig.supportBothAvmVersions(0, unityForkBlock, 0);
// setup two identical blockchains
StandaloneBlockchain.Builder builder = new StandaloneBlockchain.Builder();
StandaloneBlockchain firstChain = builder.withValidatorConfiguration("simple").withDefaultAccounts(accounts).withAvmEnabled().build().bc;
StandaloneBlockchain secondChain = builder.withValidatorConfiguration("simple").withDefaultAccounts(accounts).withAvmEnabled().build().bc;
firstChain.forkUtility.enableUnityFork(unityForkBlock);
secondChain.forkUtility.enableUnityFork(unityForkBlock);
assertThat(secondChain).isNotEqualTo(firstChain);
assertThat(secondChain.genesis).isEqualTo(firstChain.genesis);
/* Setup the first block in the chain with the staker registry deployment.
* After this both chains will have:
* (gen)->(staker-registry)
*/
// create block with staker registry
Block blockWithRegistry = BlockchainTestUtils.generateNextMiningBlockWithStakerRegistry(firstChain, firstChain.getGenesis(), resourceProvider, stakingRegistryOwner);
// import block on firstChain
Pair<ImportResult, AionBlockSummary> result = firstChain.tryToConnectAndFetchSummary(blockWithRegistry);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
assertThat(result.getRight().getReceipts().get(0).isSuccessful()).isTrue();
assertThat(result.getRight().getReceipts().get(0).getLogInfoList()).isNotEmpty();
assertThat(result.getRight().getReceipts().get(0).getEnergyUsed()).isEqualTo(1_225_655L);
// import block on secondChain
result = secondChain.tryToConnectAndFetchSummary(blockWithRegistry);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
assertThat(result.getRight().getReceipts().get(0).isSuccessful()).isTrue();
assertThat(result.getRight().getReceipts().get(0).getLogInfoList()).isNotEmpty();
assertThat(result.getRight().getReceipts().get(0).getEnergyUsed()).isEqualTo(1_225_655L);
// ensure both chains have the same root
assertThat(secondChain.getRepository().getRoot()).isEqualTo(firstChain.getRepository().getRoot());
// set the staking contract address in the staking genesis
AionTransaction deploy = blockWithRegistry.getTransactionsList().get(0);
AionAddress contract = TxUtil.calculateContractAddress(deploy.getSenderAddress().toByteArray(), deploy.getNonceBI());
firstChain.getGenesis().setStakingContractAddress(contract);
secondChain.getGenesis().setStakingContractAddress(contract);
/* Import blocks such that a re-branching occurs on the Unity fork block.
* The firstChain imports blocks 2 and 3 without re-org for state comparison:
* (gen)->(staker-registry)->(block2Unity)->(block3Staking)
* The secondChain imports blocks 1, 2 and 3, in the order of their indices, causing a re-org:
* (gen)->(staker-registry)->(block1Unity)
* ->(block2Unity)->(block3Staking)
*/
// setup firstChain
// create Unity block with stakersOnChain1
Block block2Unity = BlockchainTestUtils.generateNextMiningBlockWithStakers(firstChain, firstChain.getBestBlock(), resourceProvider, stakersOnChain1, MIN_SELF_STAKE);
// import block2Unity on firstChain (main chain)
result = firstChain.tryToConnectAndFetchSummary(block2Unity);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
verifyReceipts(result.getRight().getReceipts(), 3, true);
// create staking block with stakersOnBothChains
Block block3Staking = BlockchainTestUtils.generateNextStakingBlockWithStakers(firstChain, block2Unity, resourceProvider, stakersOnBothChains, MIN_SELF_STAKE, stakersOnChain1.get(0));
assertThat(block3Staking).isNotNull();
// import block3Staking on firstChain (main chain)
result = firstChain.tryToConnectAndFetchSummary(block3Staking);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
verifyReceipts(result.getRight().getReceipts(), 3, true);
// setup secondChain
// create Unity block with stakersOnChain2
Block block1Unity = BlockchainTestUtils.generateNextMiningBlockWithStakers(secondChain, secondChain.getBestBlock(), resourceProvider, stakersOnChain2, MIN_SELF_STAKE);
// import block1Unity on secondChain (main chain)
result = secondChain.tryToConnectAndFetchSummary(block1Unity);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
verifyReceipts(result.getRight().getReceipts(), 3, true);
// create staking block with stakersOnBothChains as setup block for next section -- not connecting
// NOTE: this block can be created only on top of the main chain and therefore must be built here
Block block4Staking = BlockchainTestUtils.generateNextStakingBlockWithStakers(secondChain, block1Unity, resourceProvider, stakersOnBothChains, MIN_SELF_STAKE, stakersOnChain2.get(0));
assertThat(block4Staking).isNotNull();
// verify stakers from stakersOnChain2 exist and stakersOnChain1 and stakersOnBothChains are not present
verifyEffectiveSelfStake(stakersOnChain1, secondChain, block1Unity, BigInteger.ZERO);
verifyEffectiveSelfStake(stakersOnChain2, secondChain, block1Unity, MIN_SELF_STAKE);
verifyEffectiveSelfStake(stakersOnBothChains, secondChain, block1Unity, BigInteger.ZERO);
// importing block2Unity on secondChain (side chain)
result = secondChain.tryToConnectAndFetchSummary(block2Unity);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_NOT_BEST);
verifyReceipts(result.getRight().getReceipts(), 3, true);
// importing block3Staking on secondChain (main chain after re-branch)
result = secondChain.tryToConnectAndFetchSummary(block3Staking);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
verifyReceipts(result.getRight().getReceipts(), 3, true);
// verify stakers from stakersOnChain1 and stakersOnBothChains exist and stakersOnChain2 are not present
verifyEffectiveSelfStake(stakersOnChain1, secondChain, block3Staking, MIN_SELF_STAKE);
verifyEffectiveSelfStake(stakersOnChain2, secondChain, block3Staking, BigInteger.ZERO);
verifyEffectiveSelfStake(stakersOnBothChains, secondChain, block3Staking, MIN_SELF_STAKE);
// ensuring the same state root for the two import paths
assertThat(secondChain.getRepository().getRoot()).isEqualTo(firstChain.getRepository().getRoot());
/* Import blocks 4 and 5 such that a re-branching occurs on secondChain:
* (gen)->(staker-registry)->(block1Unity)->(block4Staking)->(block5Mining)
* ->(block2Unity)->(block3Staking)
*/
// importing block4Staking on secondChain (side chain)
result = secondChain.tryToConnectAndFetchSummary(block4Staking);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_NOT_BEST);
verifyReceipts(result.getRight().getReceipts(), 3, true);
// create diverse set of transactions
List<AionTransaction> txs = generateMixedTransactions(secondChain, block4Staking, resourceProvider, stakersOnChain1, stakersOnBothChains, stakersOnChain2);
assertThat(txs.size()).isEqualTo(8);
// create mining block on top of block4Staking
Block block5Mining = BlockchainTestUtils.generateNextMiningBlock(secondChain, block4Staking, txs);
// importing block5Mining on secondChain (main chain after re-branch)
result = secondChain.tryToConnectAndFetchSummary(block5Mining);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
verifyReceipts(result.getRight().getReceipts(), 8, false);
// verify stakers updates
verifyEffectiveSelfStake(stakersOnChain1, secondChain, block5Mining, MIN_SELF_STAKE);
verifyEffectiveSelfStake(stakersOnBothChains, secondChain, block5Mining, MIN_SELF_STAKE.multiply(BigInteger.TWO));
verifyEffectiveSelfStake(List.of(stakersOnChain2.get(0), stakersOnChain2.get(1)), secondChain, block5Mining, BigInteger.ZERO);
verifyEffectiveSelfStake(List.of(stakersOnChain2.get(2)), secondChain, block5Mining, MIN_SELF_STAKE);
/* Import blocks such that a re-branching occurs on the first mining block after Unity.
* The firstChain imports blocks without re-org for state comparison:
* (gen)->(staker-registry)->(block2Unity)->(block3Staking)->(block6Mining)->(block7Staking)
* The secondChain imports blocks 6 and 7 in the order of their indices, causing a re-org:
* (gen)->(staker-registry)->(block1Unity)->(block4Staking)->(block5Mining)
* ->(block2Unity)->(block3Staking)->(block6Mining)->(block7Staking)
*/
// create diverse set of transactions
txs = generateMixedTransactions(firstChain, block3Staking, resourceProvider, stakersOnChain2, stakersOnChain1, stakersOnBothChains);
assertThat(txs.size()).isEqualTo(8);
// create alternative mining block on top of block3Staking
Block block6Mining = BlockchainTestUtils.generateNextMiningBlock(firstChain, block3Staking, txs);
// import block6Mining on firstChain (main chain)
result = firstChain.tryToConnectAndFetchSummary(block6Mining);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
verifyReceipts(result.getRight().getReceipts(), 8, false);
// create staking block on top of block6Mining
Block block7Staking = BlockchainTestUtils.generateNextStakingBlock(firstChain, block6Mining, Collections.emptyList(), stakersOnChain1.get(2));
assertThat(block7Staking).isNotNull();
// import block7Staking on firstChain (main chain)
result = firstChain.tryToConnectAndFetchSummary(block7Staking);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
// import block6Mining on secondChain (side chain)
result = secondChain.tryToConnectAndFetchSummary(block6Mining);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_NOT_BEST);
verifyReceipts(result.getRight().getReceipts(), 8, false);
// import block7Staking on secondChain (main chain after re-branch)
result = secondChain.tryToConnectAndFetchSummary(block7Staking);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
// verify stakers updates
verifyEffectiveSelfStake(stakersOnChain2, secondChain, block7Staking, MIN_SELF_STAKE);
verifyEffectiveSelfStake(stakersOnChain1, secondChain, block7Staking, MIN_SELF_STAKE.multiply(BigInteger.TWO));
verifyEffectiveSelfStake(List.of(stakersOnBothChains.get(0), stakersOnBothChains.get(1)), secondChain, block7Staking, BigInteger.ZERO);
verifyEffectiveSelfStake(List.of(stakersOnBothChains.get(2)), secondChain, block7Staking, MIN_SELF_STAKE);
// ensuring the same state root for the two import paths
assertThat(secondChain.getRepository().getRoot()).isEqualTo(firstChain.getRepository().getRoot());
// fast forward 58 blocks to check that the stake was transferred
// this resets logging to warnings to avoid spam
AionLoggerFactory.initAll();
List<ECKey> stakers = new ArrayList<>();
stakers.addAll(stakersOnChain2);
stakers.addAll(stakersOnChain1);
stakers.add(stakersOnBothChains.get(2));
BlockchainTestUtils.generateRandomUnityChain(firstChain, resourceProvider, 58, 1, stakers, stakingRegistryOwner, 10);
// finalize transfer and verify
AionTransaction tx = BlockchainTestUtils.generateTransferFinalizeTransactions(firstChain, firstChain.getBestBlock(), resourceProvider, stakersOnBothChains.get(1), 0L);
assertThat(firstChain.getBestBlock().getHeader().getSealType()).isEqualTo(Seal.PROOF_OF_STAKE);
Block finalizeTransferBlock = BlockchainTestUtils.generateNextMiningBlock(firstChain, firstChain.getBestBlock(), List.of(tx));
result = firstChain.tryToConnectAndFetchSummary(finalizeTransferBlock);
assertThat(result.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
verifyReceipts(result.getRight().getReceipts(), 1, false);
verifyEffectiveSelfStake(List.of(stakersOnBothChains.get(2)), firstChain, firstChain.getBestBlock(), MIN_SELF_STAKE.multiply(BigInteger.TWO));
}
Aggregations