use of org.aion.zero.impl.types.MiningBlock in project aion by aionnetwork.
the class BlockchainRewardTest method testBlockchainRewardMonotonicallyIncreasing.
/**
* Test that blocks between the lower and upper bounds follow a certain function [0, 259200]
*
* <p>Note: this test is resource consuming!
*
* <p>Check {@link org.aion.zero.impl.core.RewardsCalculator} for algorithm related to the
* ramp-up block time
*/
@Ignore
@Test
public void testBlockchainRewardMonotonicallyIncreasing() {
StandaloneBlockchain.Bundle bundle = new StandaloneBlockchain.Builder().withDefaultAccounts().withValidatorConfiguration("simple").build();
StandaloneBlockchain bc = bundle.bc;
MiningBlock block = bc.createNewMiningBlock(bc.getBestBlock(), Collections.EMPTY_LIST, true);
ImportResult res = bc.tryToConnect(block);
assertThat(res).isEqualTo(ImportResult.IMPORTED_BEST);
AionAddress coinbase = block.getCoinbase();
BigInteger previousBalance = bc.getRepository().getBalance(coinbase);
// first block already sealed
for (int i = 2; i < 99999; i++) {
MiningBlock b = bc.createNewMiningBlock(bc.getBestBlock(), Collections.EMPTY_LIST, true);
ImportResult r = bc.tryToConnect(b);
assertThat(r).isEqualTo(ImportResult.IMPORTED_BEST);
// note the assumption here that blocks are mined by one coinbase
BigInteger balance = bc.getRepository().getBalance(coinbase);
assertThat(balance).isGreaterThan(previousBalance);
previousBalance = balance;
if (b.getNumber() % 1000 == 0)
System.out.println("added block #: " + i);
}
}
use of org.aion.zero.impl.types.MiningBlock in project aion by aionnetwork.
the class BlockchainAccountStateBenchmark method testExpandOneAccountStorage.
@Ignore
@Test
public void testExpandOneAccountStorage() throws InterruptedException {
try {
StandaloneBlockchain.Bundle bundle = this.bundle;
StandaloneBlockchain bc = bundle.bc;
ECKey senderKey = bundle.privateKeys.get(0);
// deploy contract
Pair<MiningBlock, byte[]> res = createContract(bc, senderKey, bc.getGenesis());
bc.tryToConnect(res.getLeft());
AionTxInfo info = bc.getTransactionInfo(res.getRight());
assertThat(info.getReceipt().isValid()).isTrue();
AionTransaction tx = info.getReceipt().getTransaction();
AionAddress contractAddress = TxUtil.calculateContractAddress(tx);
byte[] contractCode = bc.getRepository().getCode(contractAddress);
System.out.println("deployed contract code: " + ByteUtil.toHexString(contractCode));
System.out.println("deployed at: " + contractAddress);
for (int i = 0; i < 100; i++) createContractBundle(bc, senderKey, bc.getBestBlock(), contractAddress);
} catch (Exception e) {
e.printStackTrace();
} finally {
bundle.bc.getRepository().close();
Thread.sleep(1000L);
}
}
use of org.aion.zero.impl.types.MiningBlock in project aion by aionnetwork.
the class BlockchainConcurrencyTest method testPublishBestBlockSafely.
@Test
public void testPublishBestBlockSafely() {
ExecutorService blockCreationService = Executors.newSingleThreadExecutor();
ExecutorService getBlockService = Executors.newSingleThreadExecutor();
StandaloneBlockchain.Bundle bundle = new StandaloneBlockchain.Builder().withDefaultAccounts().withValidatorConfiguration("simple").build();
StandaloneBlockchain bc = bundle.bc;
final int MAX_COUNT = 100000;
final CountDownLatch endLatch = new CountDownLatch(2);
// this will not definitively prove
try {
blockCreationService.submit(() -> {
int count = 0;
List<AionTransaction> txList = Collections.emptyList();
MiningBlock block = null;
try {
block = bc.createNewMiningBlock(bc.genesis, Collections.emptyList(), false);
} catch (Exception e) {
e.printStackTrace();
}
while (!Thread.currentThread().isInterrupted() && count < MAX_COUNT) {
try {
block = bc.createNewMiningBlock(block, txList, false);
} catch (Exception e) {
e.printStackTrace();
}
count++;
}
System.out.println("completed block creation");
endLatch.countDown();
});
getBlockService.submit(() -> {
int count = 0;
long prevNumber = bc.getBestBlock().getNumber();
while (!Thread.currentThread().isInterrupted() && count < MAX_COUNT) {
// all three of these methods use {@link
// AionBlockchainImpl#pubBestBlock}
assertThat(bc.getBestBlockHash()).isNotNull();
bc.getSize();
Block block = bc.getBestBlock();
assertThat(block).isNotNull();
assertThat(block.getNumber()).isAtLeast(prevNumber);
prevNumber = block.getNumber();
count++;
}
endLatch.countDown();
});
} finally {
blockCreationService.shutdown();
getBlockService.shutdown();
}
}
use of org.aion.zero.impl.types.MiningBlock in project aion by aionnetwork.
the class BlockchainDataRecoveryTest method testRecoverIndex_wDeletedBlock.
@Test
public void testRecoverIndex_wDeletedBlock() {
// build a blockchain with a few blocks
StandaloneBlockchain.Builder builder = new StandaloneBlockchain.Builder();
StandaloneBlockchain.Bundle bundle = builder.withValidatorConfiguration("simple").withDefaultAccounts(accounts).build();
StandaloneBlockchain chain = bundle.bc;
AionRepositoryImpl repo = chain.getRepository();
BlockContext context;
List<AionTransaction> txs;
// all blocks will be incorrect
long time = System.currentTimeMillis();
Map<Long, byte[]> blocksToDelete = new HashMap<>();
List<MiningBlock> blocksToImport = new ArrayList<>();
for (int i = 0; i < NUMBER_OF_BLOCKS; i++) {
txs = BlockchainTestUtils.generateTransactions(MAX_TX_PER_BLOCK, accounts, repo);
context = chain.createNewMiningBlockInternal(chain.getBestBlock(), txs, true, time / 10000L);
assertThat(chain.tryToConnect(context.block)).isEqualTo(ImportResult.IMPORTED_BEST);
blocksToDelete.put(context.block.getNumber(), context.block.getHash());
// skipping middle block
if (context.block.getNumber() != NUMBER_OF_BLOCKS / 2) {
blocksToImport.add(context.block);
}
}
Block bestBlock = chain.getBestBlock();
assertThat(bestBlock.getNumber()).isEqualTo(NUMBER_OF_BLOCKS);
// delete middle block from db
Block middle = chain.getBlockByNumber(NUMBER_OF_BLOCKS / 2);
MockDB database = (MockDB) repo.getBlockDatabase();
database.deleteAndCommit(middle.getHash());
// delete index entries from the database
MockDB indexDatabase = (MockDB) repo.getIndexDatabase();
// 1: direct recovery call
repo.flush();
Map<Long, byte[]> deletedInfo = new HashMap<>();
for (Map.Entry<Long, byte[]> entry : blocksToDelete.entrySet()) {
byte[] indexKey = ByteUtil.intToBytes(entry.getKey().intValue());
// saving the data for checking recovery
deletedInfo.put(entry.getKey(), indexDatabase.get(indexKey).get());
// deleting the block info
indexDatabase.deleteAndCommit(indexKey);
// ensure that the index was corrupted
assertThat(repo.isIndexed(entry.getValue(), entry.getKey())).isFalse();
}
// ensure that the index was corrupted
assertThat(repo.isIndexed(bestBlock.getHash(), bestBlock.getNumber())).isFalse();
// call the recovery functionality
assertThat(chain.recoverIndexEntry(repo, bestBlock)).isFalse();
// ensure that the blockchain is ok
assertThat(chain.getBestBlockHash()).isEqualTo(bestBlock.getHash());
// ensure that the index was recovered
assertThat(repo.isIndexed(bestBlock.getHash(), bestBlock.getNumber())).isFalse();
// 2: recovery at import
repo.flush();
for (Map.Entry<Long, byte[]> entry : blocksToDelete.entrySet()) {
byte[] indexKey = ByteUtil.intToBytes(entry.getKey().intValue());
// deleting the block info
indexDatabase.deleteAndCommit(indexKey);
// ensure that the index was corrupted
assertThat(repo.isIndexed(entry.getValue(), entry.getKey())).isFalse();
}
// ensure that the index was corrupted
assertThat(repo.isIndexed(bestBlock.getHash(), bestBlock.getNumber())).isFalse();
// call the recovery functionality indirectly
for (MiningBlock block : blocksToImport) {
// index missing before import
assertThat(repo.isIndexed(block.getHash(), block.getNumber())).isFalse();
assertThat(chain.tryToConnect(block)).isEqualTo(ImportResult.EXIST);
if (block.getNumber() < middle.getNumber()) {
// index present after import
assertThat(repo.isIndexed(block.getHash(), block.getNumber())).isTrue();
} else {
// blocks after missing one cannot be recovered
assertThat(repo.isIndexed(block.getHash(), block.getNumber())).isFalse();
}
}
// ensure that the blockchain is ok
assertThat(chain.getBestBlockHash()).isEqualTo(bestBlock.getHash());
// ensure that the index was recovered
assertThat(repo.isIndexed(bestBlock.getHash(), bestBlock.getNumber())).isFalse();
// importing middle block
assertThat(chain.tryToConnect(middle)).isEqualTo(ImportResult.IMPORTED_NOT_BEST);
// call the recovery functionality indirectly
for (MiningBlock block : blocksToImport) {
// checking only failed blocks from before
if (block.getNumber() > middle.getNumber()) {
// index missing before import
assertThat(repo.isIndexed(block.getHash(), block.getNumber())).isFalse();
assertThat(chain.tryToConnect(block)).isEqualTo(ImportResult.EXIST);
// index present after import
assertThat(repo.isIndexed(block.getHash(), block.getNumber())).isTrue();
}
}
// ensure that the blockchain is ok
assertThat(chain.getBestBlockHash()).isEqualTo(bestBlock.getHash());
// ensure that the index was recovered
assertThat(repo.isIndexed(bestBlock.getHash(), bestBlock.getNumber())).isTrue();
// check that the index information is correct at database level
for (Long key : blocksToDelete.keySet()) {
// checking at database level
byte[] indexKey = ByteUtil.intToBytes(key.intValue());
assertThat(deletedInfo.get(key)).isEqualTo(indexDatabase.get(indexKey).get());
}
}
use of org.aion.zero.impl.types.MiningBlock in project aion by aionnetwork.
the class BlockchainDataRecoveryTest method testRecoverWorldStateWithStartFromGenesis.
/**
* Test the recovery of the world state with start from the state of the genesis block.
*/
@Test
public void testRecoverWorldStateWithStartFromGenesis() {
// build a blockchain with a few blocks
StandaloneBlockchain.Builder builder = new StandaloneBlockchain.Builder();
StandaloneBlockchain.Bundle bundle = builder.withValidatorConfiguration("simple").withDefaultAccounts(accounts).build();
StandaloneBlockchain chain = bundle.bc;
AionRepositoryImpl repo = chain.getRepository();
BlockContext context;
List<AionTransaction> txs;
// all blocks will be incorrect
long time = System.currentTimeMillis();
List<byte[]> statesToDelete = new ArrayList<>();
List<MiningBlock> blocksToImport = new ArrayList<>();
for (int i = 0; i < NUMBER_OF_BLOCKS; i++) {
txs = BlockchainTestUtils.generateTransactions(MAX_TX_PER_BLOCK, accounts, repo);
context = chain.createNewMiningBlockInternal(chain.getBestBlock(), txs, true, time / 10000L);
assertThat(chain.tryToConnect(context.block)).isEqualTo(ImportResult.IMPORTED_BEST);
statesToDelete.add(context.block.getStateRoot());
blocksToImport.add(context.block);
}
Block bestBlock = chain.getBestBlock();
assertThat(bestBlock.getNumber()).isEqualTo(NUMBER_OF_BLOCKS);
// delete some world state root entries from the database
TrieImpl trie = (TrieImpl) repo.getWorldState();
MockDB database = (MockDB) repo.getStateDatabase();
// 1: direct recovery call
repo.flush();
for (byte[] key : statesToDelete) {
database.deleteAndCommit(key);
assertThat(trie.isValidRoot(key)).isFalse();
}
// ensure that the world state was corrupted
assertThat(trie.isValidRoot(chain.getBestBlock().getStateRoot())).isFalse();
// call the recovery functionality
boolean worked = chain.recoverWorldState(repo, bestBlock);
// ensure that the blockchain is ok
assertThat(chain.getBestBlockHash()).isEqualTo(bestBlock.getHash());
// ensure that the world state is ok
assertThat(worked).isTrue();
assertThat(trie.isValidRoot(chain.getBestBlock().getStateRoot())).isTrue();
// 2: recovery at import
repo.flush();
for (byte[] key : statesToDelete) {
database.deleteAndCommit(key);
assertThat(trie.isValidRoot(key)).isFalse();
}
// ensure that the world state was corrupted
assertThat(trie.isValidRoot(chain.getBestBlock().getStateRoot())).isFalse();
// call the recovery functionality indirectly
for (MiningBlock block : blocksToImport) {
// state missing before import
assertThat(trie.isValidRoot(block.getStateRoot())).isFalse();
assertThat(chain.tryToConnect(block)).isEqualTo(ImportResult.EXIST);
// state present after import
assertThat(trie.isValidRoot(block.getStateRoot())).isTrue();
}
// ensure that the blockchain is ok
assertThat(chain.getBestBlockHash()).isEqualTo(bestBlock.getHash());
// ensure that the world state is ok
assertThat(trie.isValidRoot(chain.getBestBlock().getStateRoot())).isTrue();
}
Aggregations