use of org.aion.base.AionTxExecSummary in project aion by aionnetwork.
the class AvmBulkTransactionTest method sendValueTransferTransactionsInBulkTest.
@Test
public void sendValueTransferTransactionsInBulkTest() {
int numTransactions = 50;
// Create the accounts.
List<ECKey> accounts = getRandomAccounts(numTransactions);
// Grab the initial data we need to track.
BigInteger expectedDeployerNonce = getNonce(this.deployerKey);
BigInteger initialBalanceDeployer = getBalance(this.deployerKey);
// Declare the various transfer amounts.
List<BigInteger> transferAmounts = getRandomValues(numTransactions, 500, 5_000_000);
printValuesUsed(transferAmounts);
// Make the transactions, then bundle them up together.
List<AionTransaction> transactions = new ArrayList<>();
for (int i = 0; i < numTransactions; i++) {
transactions.add(makeValueTransferTransaction(this.deployerKey, accounts.get(i), transferAmounts.get(i), expectedDeployerNonce));
expectedDeployerNonce = expectedDeployerNonce.add(BigInteger.ONE);
}
// Process the transactions in bulk.
AionBlockSummary blockSummary = sendTransactionsInBulkInSingleBlock(transactions);
// Verify all transactions were successful.
assertEquals(numTransactions, blockSummary.getSummaries().size());
for (AionTxExecSummary transactionSummary : blockSummary.getSummaries()) {
assertTrue(transactionSummary.getReceipt().isSuccessful());
}
BigInteger expectedDeployerBalance = initialBalanceDeployer;
for (int i = 0; i < numTransactions; i++) {
BigInteger energyUsed = BigInteger.valueOf(blockSummary.getSummaries().get(i).getReceipt().getEnergyUsed());
expectedDeployerBalance = expectedDeployerBalance.subtract(energyUsed.multiply(BigInteger.valueOf(energyPrice))).subtract(transferAmounts.get(i));
}
// Verify account states after the transactions have been processed.
for (int i = 0; i < numTransactions; i++) {
assertEquals(transferAmounts.get(i), getBalance(accounts.get(i)));
assertEquals(BigInteger.ZERO, getNonce(accounts.get(i)));
}
assertEquals(expectedDeployerBalance, getBalance(this.deployerKey));
assertEquals(expectedDeployerNonce, getNonce(this.deployerKey));
}
use of org.aion.base.AionTxExecSummary in project aion by aionnetwork.
the class AvmBulkTransactionTest method importBlockWithContractDeploysAndSubsequentCalls.
/**
* Ensures that AVM contracts can be deployed and called within the same block.
*/
@Test
public void importBlockWithContractDeploysAndSubsequentCalls() {
BigInteger expectedNonce = getNonce(deployerKey);
BigInteger initialBalance = getBalance(deployerKey);
// note: 3 contract deployments would pass the block energy limit
int nbCreateTransactions = 2;
int nbCallTransactions = 2;
int nbTransactions = nbCreateTransactions + nbCreateTransactions * nbCallTransactions;
List<AionTransaction> transactions = new ArrayList<>();
for (int j = 0; j < nbCreateTransactions; j++) {
// create contract transaction
AionTransaction deployTx = makeAvmContractCreateTransaction(deployerKey, expectedNonce);
expectedNonce = expectedNonce.add(BigInteger.ONE);
AionAddress deployedContract = TxUtil.calculateContractAddress(deployTx);
transactions.add(deployTx);
// subsequent call transactions
for (int i = 0; i < nbCallTransactions; i++) {
transactions.add(makeAvmContractCallTransaction(deployerKey, expectedNonce, deployedContract));
expectedNonce = expectedNonce.add(BigInteger.ONE);
}
}
// process the transactions in bulk
AionBlockSummary blockSummary = sendTransactionsInBulkInSingleBlock(transactions);
// verify all transactions were successful
assertEquals(nbTransactions, blockSummary.getSummaries().size());
for (AionTxExecSummary transactionSummary : blockSummary.getSummaries()) {
System.out.println(transactionSummary.getReceipt());
assertTrue(transactionSummary.getReceipt().isSuccessful());
}
BigInteger expectedBalance = initialBalance;
for (int i = 0; i < nbTransactions; i++) {
BigInteger energyUsed = BigInteger.valueOf(blockSummary.getSummaries().get(i).getReceipt().getEnergyUsed());
expectedBalance = expectedBalance.subtract(energyUsed.multiply(BigInteger.valueOf(energyPrice)));
}
assertEquals(expectedBalance, getBalance(deployerKey));
assertEquals(expectedNonce, getNonce(deployerKey));
}
use of org.aion.base.AionTxExecSummary 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.base.AionTxExecSummary in project aion by aionnetwork.
the class AionBlockchainImpl method applyBlock.
private AionBlockSummary applyBlock(Block block) {
long saveTime = System.nanoTime();
List<AionTxReceipt> receipts = new ArrayList<>();
List<AionTxExecSummary> summaries = new ArrayList<>();
if (!block.getTransactionsList().isEmpty()) {
// might apply the block before the 040 fork point.
boolean fork040Enable = forkUtility.is040ForkActive(block.getNumber());
if (fork040Enable) {
TransactionTypeRule.allowAVMContractTransaction();
}
if (forkUtility.isSignatureSwapForkActive(block.getNumber())) {
HashUtil.setAfterSignatureSwap();
} else {
HashUtil.setBeforeSignatureSwap();
}
try {
// Booleans moved out here so their meaning is explicit.
boolean isLocalCall = false;
boolean incrementSenderNonce = true;
boolean checkBlockEnergyLimit = false;
List<AionTxExecSummary> executionSummaries = BulkExecutor.executeAllTransactionsInBlock(block.getDifficulty(), block.getNumber(), block.getTimestamp(), block.getNrgLimit(), block.getCoinbase(), block.getTransactionsList(), track, isLocalCall, incrementSenderNonce, fork040Enable, checkBlockEnergyLimit, LOGGER_VM, getPostExecutionWorkForApplyBlock(repository), executionTypeForAVM, cachedBlockNumberForAVM, forkUtility.isUnityForkActive(block.getNumber()), forkUtility.isSignatureSwapForkActive(block.getNumber()));
// Check for rejected transaction already included in the chain.
if (isException(block.getNumber())) {
for (AionTxExecSummary summary : executionSummaries) {
if (summary.isRejected()) {
AionTxReceipt receipt = summary.getReceipt();
receipt.setNrgUsed(receipt.getTransaction().getEnergyLimit());
}
}
}
for (AionTxExecSummary summary : executionSummaries) {
receipts.add(summary.getReceipt());
summaries.add(summary);
}
} catch (VmFatalException e) {
LOG.error("Shutdown due to a VM fatal error.", e);
System.exit(SystemExitCodes.FATAL_VM_ERROR);
}
}
Map<AionAddress, BigInteger> rewards = addReward(block);
return new AionBlockSummary(block, rewards, receipts, summaries);
}
use of org.aion.base.AionTxExecSummary in project aion by aionnetwork.
the class AionBlockchainImpl method generatePreBlock.
/**
* For generating the necessary transactions for a block
*
* @param block
* @return
*/
private RetValidPreBlock generatePreBlock(Block block) {
long saveTime = System.nanoTime();
List<AionTxReceipt> receipts = new ArrayList<>();
List<AionTxExecSummary> summaries = new ArrayList<>();
List<AionTransaction> transactions = new ArrayList<>();
if (!block.getTransactionsList().isEmpty()) {
boolean fork040Enable = forkUtility.is040ForkActive(block.getNumber());
if (fork040Enable) {
TransactionTypeRule.allowAVMContractTransaction();
}
try {
// Booleans moved out here so their meaning is explicit.
boolean isLocalCall = false;
boolean incrementSenderNonce = true;
boolean checkBlockEnergyLimit = true;
List<AionTxExecSummary> executionSummaries = BulkExecutor.executeAllTransactionsInBlock(block.getDifficulty(), block.getNumber(), block.getTimestamp(), block.getNrgLimit(), block.getCoinbase(), block.getTransactionsList(), track, isLocalCall, incrementSenderNonce, fork040Enable, checkBlockEnergyLimit, LOGGER_VM, getPostExecutionWorkForGeneratePreBlock(repository), BlockCachingContext.PENDING, bestBlock.getNumber(), forkUtility.isUnityForkActive(block.getNumber()), forkUtility.isSignatureSwapForkActive(block.getNumber()));
for (AionTxExecSummary summary : executionSummaries) {
if (!summary.isRejected()) {
transactions.add(summary.getTransaction());
receipts.add(summary.getReceipt());
summaries.add(summary);
}
}
} catch (VmFatalException e) {
LOG.error("Shutdown due to a VM fatal error.", e);
System.exit(SystemExitCodes.FATAL_VM_ERROR);
}
}
Map<AionAddress, BigInteger> rewards = addReward(block);
return new RetValidPreBlock(transactions, rewards, receipts, summaries);
}
Aggregations