use of org.aion.zero.impl.vm.common.VmFatalException in project aion by aionnetwork.
the class AionPendingStateImpl method executeTx.
private AionTxExecSummary executeTx(AionTransaction tx) {
Block bestBlk = currentBestBlock.get();
LOGGER_TX.debug("executeTx: {}", Hex.toHexString(tx.getTransactionHash()));
try {
// Booleans moved out here so their meaning is explicit.
boolean isLocalCall = false;
boolean incrementSenderNonce = true;
boolean checkBlockEnergyLimit = false;
// this parameter should not be relevant to execution
byte[] difficulty = bestBlk.getDifficulty();
// the pending state is executed on top of the best block
long currentBlockNumber = bestBlk.getNumber() + 1;
// simulating future block
long timestamp = bestBlk.getTimestamp() + 1;
// the limit is not checked so making it unlimited
long blockNrgLimit = Long.MAX_VALUE;
// assuming same person will mine the future block
AionAddress miner = bestBlk.getCoinbase();
return BulkExecutor.executeTransactionWithNoPostExecutionWork(difficulty, currentBlockNumber, timestamp, blockNrgLimit, miner, tx, pendingState, isLocalCall, incrementSenderNonce, blockchain.forkUtility.is040ForkActive(currentBlockNumber), checkBlockEnergyLimit, LOGGER_VM, BlockCachingContext.PENDING, bestBlk.getNumber(), blockchain.forkUtility.isUnityForkActive(currentBlockNumber), blockchain.forkUtility.isSignatureSwapForkActive(currentBlockNumber));
} catch (VmFatalException e) {
LOGGER_VM.error("Shutdown due to a VM fatal error.", e);
System.exit(SystemExitCodes.FATAL_VM_ERROR);
return null;
}
}
use of org.aion.zero.impl.vm.common.VmFatalException in project aion by aionnetwork.
the class AvmTransactionExecutor method executeTransactions.
/**
* Executes the specified transactions using the avm, and returns the execution summaries of
* each of the transactions.
*
* This method does not perform any checks on its inputs! It operates under the assumption that
* the caller has ensured the input parameters are correct!
*
* In particular, every object supplied must be non-null with the exception of
* {@code postExecutionWork}, which may be null. Also, we must have
* {@code initialBlockEnergyLimit <= blockEnergyLimit}.
*
* @param repository The current state of the world.
* @param blockDifficulty The block difficulty.
* @param blockNumber The current block number.
* @param blockTimestamp The block timestamp.
* @param blockEnergyLimit The energy limit of the block.
* @param miner The miner address.
* @param transactions The transactions to execute.
* @param postExecutionWork The post-execution work to be applied after executing the transactions.
* @param decrementBlockEnergyLimit Whether or not to check the block energy limit.
* @param allowNonceIncrement Whether to increment the sender's nonce or not.
* @param isLocalCall Whether this is a local call (ie. is to cause no state changes).
* @param remainingBlockEnergy The amount of energy remaining in the block.
* @param executionType The avm execution type.
* @param cachedBlockNumber The cached block number.
* @param unityForkEnabled the flag shows the unityfork feature enabled/disabled
* @param signatureSchemeSwapEnabled the flag shows the signatureSchemeSwap feature enabled/disabled
* @return the execution summaries of the transactions.
* @throws VmFatalException If a fatal error occurred and the kernel must be shut down.
*/
public static List<AionTxExecSummary> executeTransactions(RepositoryCache repository, BigInteger blockDifficulty, long blockNumber, long blockTimestamp, long blockEnergyLimit, AionAddress miner, AionTransaction[] transactions, PostExecutionWork postExecutionWork, boolean decrementBlockEnergyLimit, boolean allowNonceIncrement, boolean isLocalCall, long remainingBlockEnergy, AvmExecutionType executionType, long cachedBlockNumber, boolean unityForkEnabled, boolean signatureSchemeSwapEnabled) throws VmFatalException {
List<AionTxExecSummary> transactionSummaries = new ArrayList<>();
long blockEnergy = remainingBlockEnergy;
try {
// We need to acquire the provider's lock before we can do anything meaningful.
if (!AvmProvider.tryAcquireLock(10, TimeUnit.MINUTES)) {
throw new TimeoutException("Timed out waiting to acquire the avm provider lock!");
}
// Ensure that the vm is in the correct state and grab the version of the avm we need to use for this block.
AvmVersion versionToUse = updateAvmsAndGetVersionToUse(AvmConfigurations.getProjectRootDirectory(), blockNumber, signatureSchemeSwapEnabled);
IAvmFutureResult[] futures = invokeAvm(versionToUse, repository, blockDifficulty, blockNumber, blockTimestamp, blockEnergyLimit, miner, transactions, allowNonceIncrement, isLocalCall, executionType, cachedBlockNumber, unityForkEnabled);
// Process the transaction results.
int index = 0;
for (IAvmFutureResult future : futures) {
TransactionResult result = future.getResult();
if (result.transactionStatus.isFatal()) {
throw new VmFatalException(result.transactionStatus.causeOfError);
}
// Check the block energy limit and reject if necessary.
AionTransaction transaction = transactions[index];
if (result.energyUsed > blockEnergy) {
result = markAsBlockEnergyLimitExceeded(result, transaction.getEnergyLimit());
}
AionTxExecSummary summary = buildSummaryAndUpdateState(future, transaction, result, versionToUse, repository, blockDifficulty, blockNumber, blockTimestamp, blockEnergyLimit, miner, allowNonceIncrement, isLocalCall);
// Do any post execution work if any is specified.
if (postExecutionWork != null) {
postExecutionWork.doWork(repository, summary, transaction);
}
// Update the remaining block energy.
if (!result.transactionStatus.isRejected() && decrementBlockEnergyLimit) {
blockEnergy -= summary.getReceipt().getEnergyUsed();
}
transactionSummaries.add(summary);
index++;
}
} catch (Throwable e) {
// If we get here then something unexpected went wrong, we treat this as a fatal situation since shutting down is our only recovery.
System.err.println("Encountered an unexpected error while processing the transactions in the avm: " + e.toString());
throw new VmFatalException(e);
} finally {
AvmProvider.releaseLock();
}
return transactionSummaries;
}
use of org.aion.zero.impl.vm.common.VmFatalException in project aion by aionnetwork.
the class FvmTransactionExecutor method executeTransactions.
/**
* Executes the specified array of transactions using the FVM and returns a list of transaction
* summaries, such that the i'th summary pertains to the i'th transaction in the input.
*
* <p>If no post-execution work is specified then none will be run. Otherwise, the
* post-execution work will be applied in such a way that it appears, from the caller's
* perspective, as if it was run immediately after each transaction sequentially.
*
* @param repository The current snapshot of the kernel's repository layer.
* @param blockDifficulty The current best block's difficulty.
* @param blockNumber The current best block number.
* @param blockTimestamp The current best block timestamp.
* @param blockNrgLimit The current best block energy limit.
* @param blockCoinbase The address of the miner.
* @param transactions The transactions to execute.
* @param postExecutionWork The post-execute work, if any, to be run immediately after each
* transaction completes.
* @param logger A logger.
* @param decrementBlockEnergyLimit Whether to decrement the block energy limit (ie. if no
* decrement implication is block overflow won't be checked)
* @param allowNonceIncrement Whether to increment the sender nonce.
* @param isLocalCall Whether this is a local call or not.
* @param fork040enabled Whether or not the 0.4.0 fork is enabled.
* @param initialBlockEnergyLimit The initial block energy limit at the time of running these
* transactions.
* @return a list of transaction summaries pertaining to the transactions.
*/
public static List<AionTxExecSummary> executeTransactions(RepositoryCache repository, byte[] blockDifficulty, long blockNumber, long blockTimestamp, long blockNrgLimit, AionAddress blockCoinbase, AionTransaction[] transactions, PostExecutionWork postExecutionWork, Logger logger, boolean decrementBlockEnergyLimit, boolean allowNonceIncrement, boolean isLocalCall, boolean fork040enabled, long initialBlockEnergyLimit, boolean unityForkEnabled, boolean signatureSwapForkEnabled) throws VmFatalException {
List<AionTxExecSummary> transactionSummaries = new ArrayList<>();
long blockRemainingEnergy = initialBlockEnergyLimit;
// Run the transactions.
IExternalStateForFvm externalState = new ExternalStateForFvm(repository, blockCoinbase, getDifficultyAsDataWord(blockDifficulty), isLocalCall, allowNonceIncrement, fork040enabled, blockNumber, blockTimestamp, blockNrgLimit, unityForkEnabled, signatureSwapForkEnabled);
// Process the results of the transactions.
for (AionTransaction transaction : transactions) {
FvmWrappedTransactionResult wrappedResult = FastVirtualMachine.run(externalState, new ExternalCapabilitiesForFvm(), toAionTypesTransaction(transaction), fork040enabled);
TransactionResult result = wrappedResult.result;
List<AionAddress> deletedAddresses = wrappedResult.deletedAddresses;
if (result.transactionStatus.isFatal()) {
throw new VmFatalException(result.toString());
}
// Check the block energy limit & reject if necessary.
if (result.energyUsed > blockRemainingEnergy) {
TransactionStatus status = TransactionStatus.rejection("Invalid Energy Limit");
result = new TransactionResult(status, result.logs, result.internalTransactions, 0, ByteUtil.EMPTY_BYTE_ARRAY);
}
// Build the transaction summary.
AionTxExecSummary summary = buildTransactionSummary(transaction, result, deletedAddresses);
// If the transaction was not rejected, then commit the state changes.
if (!result.transactionStatus.isRejected()) {
externalState.commit();
}
// For non-rejected non-local transactions, make some final repository updates.
if (!isLocalCall && !summary.isRejected()) {
RepositoryCache repositoryTracker = repository.startTracking();
refundSender(repositoryTracker, summary, transaction, result);
payMiner(repositoryTracker, blockCoinbase, summary);
deleteAccountsMarkedForDeletion(repositoryTracker, summary.getDeletedAccounts(), result);
repositoryTracker.flushTo(repository, true);
}
// Do any post execution work.
if (postExecutionWork != null) {
postExecutionWork.doWork(repository, summary, transaction);
}
// Update the remaining block energy.
if (!result.transactionStatus.isRejected() && decrementBlockEnergyLimit) {
blockRemainingEnergy -= summary.getReceipt().getEnergyUsed();
}
if (logger.isDebugEnabled()) {
logger.debug("Transaction receipt: {}", summary.getReceipt());
logger.debug("Transaction logs: {}", summary.getLogs());
}
transactionSummaries.add(summary);
}
return transactionSummaries;
}
use of org.aion.zero.impl.vm.common.VmFatalException 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.zero.impl.vm.common.VmFatalException 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