use of org.aion.zero.impl.core.ImportResult in project aion by aionnetwork.
the class PendingStateTest method alreadySealed.
@Test
public void alreadySealed() {
AionTransaction tx = AionTransaction.create(deployerKey, BigInteger.ZERO.toByteArray(), new AionAddress(new byte[32]), ByteUtils.fromHexString("1"), ByteUtils.fromHexString("1"), 1000_000L, energyPrice, TransactionTypes.DEFAULT, null);
AionTransaction tx2 = AionTransaction.create(deployerKey, BigInteger.ZERO.toByteArray(), new AionAddress(new byte[32]), ByteUtils.fromHexString("2"), ByteUtils.fromHexString("2"), 1000_000L, energyPrice * 2, TransactionTypes.DEFAULT, null);
assertEquals(pendingState.addTransactionFromApiServer(tx), TxResponse.SUCCESS);
MiningBlock block = blockchain.createNewMiningBlock(blockchain.getBestBlock(), pendingState.getPendingTransactions(), false);
Pair<ImportResult, AionBlockSummary> connectResult = blockchain.tryToConnectAndFetchSummary(block);
assertEquals(connectResult.getLeft(), ImportResult.IMPORTED_BEST);
assertEquals(pendingState.addTransactionFromApiServer(tx), TxResponse.ALREADY_SEALED);
assertEquals(pendingState.addTransactionFromApiServer(tx2), TxResponse.ALREADY_SEALED);
}
use of org.aion.zero.impl.core.ImportResult in project aion by aionnetwork.
the class PendingStateTest method replayTransactionThatThatInvalidatesMiddleTx.
@Test
public void replayTransactionThatThatInvalidatesMiddleTx() {
BigInteger balance = blockchain.getRepository().getBalance(new AionAddress(deployerKey.getAddress()));
BigInteger value = balance.subtract(BigInteger.valueOf(21000 * 7).multiply(BigInteger.valueOf(energyPrice)));
AionTransaction tx1 = AionTransaction.create(deployerKey, BigInteger.ZERO.toByteArray(), new AionAddress(new byte[32]), value.toByteArray(), new byte[0], 21000, energyPrice, TransactionTypes.DEFAULT, null);
AionTransaction tx2 = AionTransaction.create(deployerKey, BigInteger.ONE.toByteArray(), new AionAddress(new byte[32]), BigInteger.ZERO.toByteArray(), new byte[0], 21000, energyPrice, TransactionTypes.DEFAULT, null);
/* tx1 and tx3 should use the entire balance. If tx2 is removed properly, tx3 should be
* able to replace it in the pending state */
AionTransaction tx3 = AionTransaction.create(deployerKey, BigInteger.ONE.toByteArray(), new AionAddress(new byte[32]), BigInteger.ZERO.toByteArray(), new byte[0], 21000, energyPrice * 4, TransactionTypes.DEFAULT, null);
// This would execute fine on top of tx2, but should have insufficient balance on top of tx3
AionTransaction tx4 = AionTransaction.create(deployerKey, BigInteger.TWO.toByteArray(), new AionAddress(new byte[32]), BigInteger.ZERO.toByteArray(), new byte[0], 21000, energyPrice * 4, TransactionTypes.DEFAULT, null);
AionTransaction tx5 = AionTransaction.create(deployerKey, BigInteger.valueOf(3).toByteArray(), new AionAddress(new byte[32]), BigInteger.ZERO.toByteArray(), new byte[0], 21000, energyPrice, TransactionTypes.DEFAULT, null);
assertEquals(TxResponse.SUCCESS, pendingState.addTransactionFromApiServer(tx1));
assertEquals(TxResponse.SUCCESS, pendingState.addTransactionFromApiServer(tx2));
assertEquals(TxResponse.REPAID, pendingState.addTransactionFromApiServer(tx3));
assertEquals(TxResponse.SUCCESS, pendingState.addTransactionFromApiServer(tx4));
assertEquals(TxResponse.SUCCESS, pendingState.addTransactionFromApiServer(tx5));
assertEquals(4, pendingState.getPendingTxSize());
MiningBlock block = blockchain.createNewMiningBlock(blockchain.getBestBlock(), Collections.emptyList(), false);
Pair<ImportResult, AionBlockSummary> connectResult = blockchain.tryToConnectAndFetchSummary(block);
assertEquals(connectResult.getLeft(), ImportResult.IMPORTED_BEST);
pendingState.applyBlockUpdate(block, connectResult.getRight().getReceipts());
// tx3 should replace tx2, and tx4 will now have insufficient funds so it will get dropped
assertEquals(2, pendingState.getPendingTxSize());
assertEquals(pendingState.getPendingTransactions().get(1), tx3);
}
use of org.aion.zero.impl.core.ImportResult in project aion by aionnetwork.
the class BlockchainConcurrentImportTest method addThread_tryToConnect.
/**
* Adds a new thread for importing a block from the given queue.
*
* @param _threads list of threads to be executed; the current thread will be added to this list
* @param _chain the blockchain where the blocks will be imported
* @param _queue a queue containing new blocks
* @param _imported a list of blocks that have been imported; blocks successfully imported are
* added to this list
*/
private void addThread_tryToConnect(List<Runnable> _threads, StandaloneBlockchain _chain, ConcurrentLinkedQueue<MiningBlock> _queue, ConcurrentLinkedQueue<MiningBlock> _imported) {
_threads.add(() -> {
// get next block from queue
MiningBlock _block = _queue.poll();
if (_block != null) {
testChain.assertEqualTotalDifficulty();
// importing the given block
ImportResult result = _chain.tryToConnect(_block);
testChain.assertEqualTotalDifficulty();
if (DISPLAY_MESSAGES) {
System.out.format("Import block with hash: %s, number: %6d, extra data: %6s, txs: %3d, status: %20s in thread: %20s (from queue)%n", _block.getShortHash(), _block.getNumber(), new String(_block.getExtraData()), _block.getTransactionsList().size(), result.toString(), Thread.currentThread().getName());
}
// checking total difficulty
if (result == ImportResult.IMPORTED_BEST || result == ImportResult.IMPORTED_NOT_BEST) {
AionBlockStore store = _chain.getRepository().getBlockStore();
BigInteger tdFromStore = _chain.getTotalDifficultyForHash(_block.getHash());
BigInteger tdCalculated = _chain.getTotalDifficultyForHash(_block.getParentHash()).add(_block.getDifficultyBI());
assertThat(tdFromStore).isEqualTo(tdCalculated);
assertThat(tdCalculated).isEqualTo(_chain.getTotalDifficultyForHash(_block.getHash()));
if (result == ImportResult.IMPORTED_BEST) {
// can't check for equality since other blocks may have already been
// imported
assertThat(store.getBestBlock().getTotalDifficulty()).isAtLeast(tdFromStore);
}
// save the block for later comparison
_imported.add(_block);
}
} else {
if (DISPLAY_MESSAGES) {
System.out.format("%62sNo block in queue. Skipping import in thread: %20s %n", " ", Thread.currentThread().getName());
}
}
});
}
use of org.aion.zero.impl.core.ImportResult in project aion by aionnetwork.
the class BlockchainConcurrentImportTest method testConcurrent.
@Test
public void testConcurrent() throws InterruptedException {
List<Runnable> threads = new ArrayList<>();
int start = (int) sourceChain.getBestBlock().getNumber() - 1;
ConcurrentLinkedQueue<MiningBlock> queue = new ConcurrentLinkedQueue<>();
ConcurrentLinkedQueue<MiningBlock> imported = new ConcurrentLinkedQueue<>();
int blockCount = CONCURRENT_THREADS_PER_TYPE + 1;
for (MiningBlock blk : knownBlocks) {
// connect to known blocks
addThread_tryToConnect(threads, testChain, blk);
// add new blocks with known parent
addThread_createNewBlock(threads, testChain, blk, blockCount, queue);
blockCount++;
// add new blocks with best block parent
addThread_createNewBlock(threads, testChain, blockCount, queue, start);
blockCount++;
// connect to new blocks
addThread_tryToConnect(threads, testChain, queue, imported);
}
// run threads while not at minimum height
long height, targetHeight = sourceChain.getBestBlock().getNumber() + MAIN_CHAIN_FREQUENCY;
boolean done = false;
while (!done) {
System.out.format("%nRunning the %d generated threads...%n", threads.size());
assertConcurrent("Testing tryToConnect(...) ", threads, TIME_OUT);
// checking height
height = testChain.getBestBlock().getNumber();
done = height >= targetHeight;
System.out.format("Current height = %d. Target height = %d.%n", height, targetHeight);
}
// adding new blocks to source chain
System.out.format("%nAdding new blocks to source chain for testing...%n");
MiningBlock block = imported.poll();
while (block != null) {
ImportResult result = sourceChain.tryToConnect(block);
knownBlocks.add(block);
if (DISPLAY_MESSAGES) {
System.out.format("Importing block with hash: %s, number: %6d, extra data: %6s, txs: %3d, status: %20s%n", block.getShortHash(), block.getNumber(), new String(block.getExtraData()), block.getTransactionsList().size(), result.toString());
}
block = imported.poll();
}
// comparing total diff for the two chains
assertThat(testChain.getTotalDifficulty()).isEqualTo(sourceChain.getTotalDifficulty());
assertThat(testChain.getCachedTotalDifficulty()).isEqualTo(sourceChain.getCachedTotalDifficulty());
testChain.assertEqualTotalDifficulty();
// comparing total diff for each block of the two chains
for (MiningBlock blk : knownBlocks) {
assertThat(testChain.getTotalDifficultyForHash(blk.getHash())).isEqualTo(sourceChain.getTotalDifficultyForHash(blk.getHash()));
byte[] hash = blk.getHash();
assertThat(testChain.getTotalDifficultyForHash(hash)).isEqualTo(sourceChain.getTotalDifficultyForHash(hash));
}
}
use of org.aion.zero.impl.core.ImportResult in project aion by aionnetwork.
the class BlockchainForkingTest method testInvalidFirstBlockDifficulty.
/*-
* Test the general forking case, where an incoming block (b) has a greater total
* difficulty than our current block. In this scenario, we should switch to
* the branch (sub-tree) that has (b) at its tip.
*
* This is the simplest case, where the distance between (a) (our current head) and
* (b) is 2. This implies that the common ancestor is directly adjacent to both blocks.
*
* (common ancestor)
* / \
* / \
* / \
* (a)x(low td) (b)o(higher td)
*
* In this simple case:
* b.td > a.td
* a_worldState === b_worldState
*
*/
@Test
public void testInvalidFirstBlockDifficulty() {
StandaloneBlockchain.Builder builder = new StandaloneBlockchain.Builder();
StandaloneBlockchain.Bundle b = builder.withValidatorConfiguration("simple").build();
StandaloneBlockchain bc = b.bc;
Block bestBlock = bc.getBestBlock();
MiningBlock standardBlock = bc.createNewMiningBlock(bc.getBestBlock(), Collections.emptyList(), true);
ChainConfiguration cc = new ChainConfiguration();
MiningBlock higherDifficultyBlock = new MiningBlock(standardBlock);
MiningBlockHeader newBlockHeader = MiningBlockHeader.Builder.newInstance().withHeader(higherDifficultyBlock.getHeader()).withTimestamp(bestBlock.getTimestamp() + 1).build();
higherDifficultyBlock.updateHeader(newBlockHeader);
BigInteger difficulty = cc.getPreUnityDifficultyCalculator().calculateDifficulty(higherDifficultyBlock.getHeader(), bestBlock.getHeader());
assertThat(difficulty).isGreaterThan(standardBlock.getDifficultyBI());
newBlockHeader = MiningBlockHeader.Builder.newInstance().withHeader(higherDifficultyBlock.getHeader()).withDifficulty(difficulty.toByteArray()).build();
higherDifficultyBlock.updateHeader(newBlockHeader);
System.out.println("before any processing: " + Hex.toHexString(bc.getRepository().getRoot()));
System.out.println("trie: " + bc.getRepository().getWorldState().getTrieDump());
ImportResult result = bc.tryToConnect(standardBlock);
assertThat(result).isEqualTo(ImportResult.IMPORTED_BEST);
// check that the correct caching context was used
Pair<Long, BlockCachingContext> cacheContext = bc.getAvmCachingContext();
assertThat(cacheContext.getLeft()).isEqualTo(standardBlock.getNumber() - 1);
assertThat(cacheContext.getRight()).isEqualTo(BlockCachingContext.MAINCHAIN);
// assert that the block we just inserted (best) is the instance that is returned
assertThat(bc.getBestBlock() == standardBlock).isTrue();
System.out.println(Hex.toHexString(bc.getRepository().getRoot()));
ImportResult higherDifficultyResult = bc.tryToConnect(higherDifficultyBlock);
/**
* With our updates to difficulty verification and calculation, this block is now invalid
*/
assertThat(higherDifficultyResult).isEqualTo(ImportResult.INVALID_BLOCK);
assertThat(bc.getBestBlockHash()).isEqualTo(standardBlock.getHash());
// since the block is second for that height, it is assumed as sidechain
cacheContext = bc.getAvmCachingContext();
assertThat(cacheContext.getLeft()).isEqualTo(standardBlock.getNumber() - 1);
assertThat(cacheContext.getRight()).isEqualTo(BlockCachingContext.SIDECHAIN);
// the object reference here is intentional
assertThat(bc.getBestBlock() == standardBlock).isTrue();
// check for correct state rollback
assertThat(bc.getRepository().getRoot()).isEqualTo(standardBlock.getStateRoot());
assertThat(bc.getTotalDifficulty()).isEqualTo(bc.getTotalDifficultyForHash(standardBlock.getHash()));
}
Aggregations