use of org.aion.zero.impl.types.Block in project aion by aionnetwork.
the class TaskImportBlocksTest method testIsAlreadyStored.
@Test
public void testIsAlreadyStored() {
StandaloneBlockchain.Bundle bundle = builder.withValidatorConfiguration("simple").withDefaultAccounts(accounts).build();
StandaloneBlockchain chain = bundle.bc;
// populate chain at random
generateRandomChain(chain, 3, 1, accounts, 10);
Block current = chain.getBestBlock();
while (current.getNumber() > 0) {
// will pass both checks
assertThat(chain.isBlockStored(current.getHash(), current.getNumber())).isTrue();
current = chain.getBlockByHash(current.getParentHash());
}
// will fail the max number check
current = generateNextBlock(chain, accounts, 10);
assertThat(chain.isBlockStored(current.getHash(), current.getNumber())).isFalse();
assertThat(chain.tryToConnect(current)).isEqualTo(ImportResult.IMPORTED_BEST);
assertThat(chain.isBlockStored(current.getHash(), current.getNumber())).isTrue();
// will fail the existence check
current = generateNewBlock(chain, chain.getGenesis(), accounts, 10);
assertThat(chain.isBlockStored(current.getHash(), current.getNumber())).isFalse();
assertThat(chain.tryToConnect(current)).isEqualTo(IMPORTED_NOT_BEST);
assertThat(chain.isBlockStored(current.getHash(), current.getNumber())).isTrue();
}
use of org.aion.zero.impl.types.Block in project aion by aionnetwork.
the class AvmBulkTransactionTest method sendTransactionsInBulkInSingleBlock.
private AionBlockSummary sendTransactionsInBulkInSingleBlock(List<AionTransaction> transactions) {
Block parentBlock = this.blockchain.getBestBlock();
MiningBlock block = this.blockchain.createBlock(parentBlock, transactions, false, parentBlock.getTimestamp());
Pair<ImportResult, AionBlockSummary> connectResult = this.blockchain.tryToConnectAndFetchSummary(block);
assertEquals(ImportResult.IMPORTED_BEST, connectResult.getLeft());
return connectResult.getRight();
}
use of org.aion.zero.impl.types.Block in project aion by aionnetwork.
the class AionBlockchainImpl method tryConnectAndFork.
/**
* Not thread safe, currently only run in {@link #tryToConnect(Block)}, assumes that the
* environment is already locked
*
* @param blockWrapper
* @return
*/
private AionBlockSummary tryConnectAndFork(final BlockWrapper blockWrapper) {
Block block = blockWrapper.block;
this.fork = true;
State savedState = null;
AionBlockSummary summary = null;
try {
savedState = pushState(block.getParentHash());
summary = add(blockWrapper).getLeft();
kernelStateUpdate(block, summary);
} catch (Exception e) {
LOG.error("Unexpected error: ", e);
} finally {
this.fork = false;
}
if (summary != null && savedState != null && isMoreThan(totalDifficulty.get(), savedState.td)) {
if (LOG.isInfoEnabled()) {
LOG.info("branching: from = {}/{}, to = {}/{}", savedState.savedBest.getNumber(), toHexString(savedState.savedBest.getHash()), block.getNumber(), toHexString(block.getHash()));
}
// main branch become this branch cause we proved that total difficulty is greater
forkLevel = repository.getBlockStore().reBranch(block);
// The main repository rebranch
this.repository = savedState.savedRepo;
this.repository.syncToRoot(block.getStateRoot());
// flushing
flush();
dropState();
clearBlockTemplate();
} else {
// Stay on previous branch
popState();
}
return summary;
}
use of org.aion.zero.impl.types.Block in project aion by aionnetwork.
the class AionBlockchainImpl method add.
/**
* @Param flushRepo true for the kernel runtime import and false for the DBUtil
*/
private Pair<AionBlockSummary, RepositoryCache> add(BlockWrapper blockWrapper) {
// reset cached VMs before processing the block
repository.clearCachedVMs();
Block block = blockWrapper.block;
if (!blockWrapper.validatedHeader && !isValid(block)) {
LOG.error("Attempting to add {} block.", (block == null ? "NULL" : "INVALID"));
return Pair.of(null, null);
}
track = repository.startTracking();
byte[] origRoot = repository.getRoot();
// (if not reconstructing old blocks) keep chain continuity
if (!blockWrapper.reBuild && !Arrays.equals(bestBlock.getHash(), block.getParentHash())) {
LOG.error("Attempting to add NON-SEQUENTIAL block.");
return Pair.of(null, null);
}
if (blockWrapper.reBuild) {
// when recovering blocks do not touch the cache
executionTypeForAVM = BlockCachingContext.DEEP_SIDECHAIN;
cachedBlockNumberForAVM = 0;
}
AionBlockSummary summary = processBlock(block);
List<AionTxExecSummary> transactionSummaries = summary.getSummaries();
List<AionTxReceipt> receipts = summary.getReceipts();
if (!isValidBlock(block, transactionSummaries, receipts, isException(block.getNumber()), LOG)) {
track.rollback();
return Pair.of(null, null);
}
if (blockWrapper.skipRepoFlush) {
return Pair.of(summary, track);
}
track.flushTo(repository, true);
repository.commitCachedVMs(block.getHashWrapper());
if (blockWrapper.reBuild) {
List<AionTxExecSummary> execSummaries = summary.getSummaries();
for (int i = 0; i < receipts.size(); i++) {
AionTxInfo infoWithInternalTxs = AionTxInfo.newInstanceWithInternalTransactions(receipts.get(i), block.getHashWrapper(), i, execSummaries.get(i).getInternalTransactions());
if (storeInternalTransactions) {
transactionStore.putTxInfoToBatch(infoWithInternalTxs);
} else {
AionTxInfo info = AionTxInfo.newInstance(receipts.get(i), block.getHashWrapper(), i);
transactionStore.putTxInfoToBatch(info);
}
if (execSummaries.get(i).getInternalTransactions().size() > 0) {
transactionStore.putAliasesToBatch(infoWithInternalTxs);
}
}
transactionStore.flushBatch();
repository.commitBlock(block.getHashWrapper(), block.getNumber(), block.getStateRoot());
LOG.debug("Block rebuilt: number: {}, hash: {}, TD: {}", block.getNumber(), block.getShortHash(), getTotalDifficulty());
} else {
if (!isValidStateRoot(block, repository.getRoot(), LOG)) {
// block is bad so 'rollback' the state root to the original state
repository.setRoot(origRoot);
return Pair.of(null, null);
}
}
return Pair.of(summary, null);
}
use of org.aion.zero.impl.types.Block in project aion by aionnetwork.
the class AionBlockchainImpl method getStartHash.
private byte[] getStartHash(long blockNumber, int qty) {
long startNumber;
startNumber = blockNumber + qty - 1;
Block block = getBlockByNumber(startNumber);
if (block == null) {
return null;
}
return block.getHash();
}
Aggregations