Search in sources :

Example 1 with VmFatalException

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;
    }
}
Also used : AionAddress(org.aion.types.AionAddress) Block(org.aion.zero.impl.types.Block) VmFatalException(org.aion.zero.impl.vm.common.VmFatalException)

Example 2 with VmFatalException

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;
}
Also used : TransactionResult(org.aion.types.TransactionResult) AionTxExecSummary(org.aion.base.AionTxExecSummary) ArrayList(java.util.ArrayList) IAvmFutureResult(org.aion.avm.stub.IAvmFutureResult) AionTransaction(org.aion.base.AionTransaction) VmFatalException(org.aion.zero.impl.vm.common.VmFatalException) AvmVersion(org.aion.avm.stub.AvmVersion) TimeoutException(java.util.concurrent.TimeoutException)

Example 3 with VmFatalException

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;
}
Also used : IExternalStateForFvm(org.aion.fastvm.IExternalStateForFvm) FvmWrappedTransactionResult(org.aion.fastvm.FvmWrappedTransactionResult) TransactionResult(org.aion.types.TransactionResult) AionAddress(org.aion.types.AionAddress) AionTxExecSummary(org.aion.base.AionTxExecSummary) ArrayList(java.util.ArrayList) TransactionStatus(org.aion.types.TransactionStatus) AionTransaction(org.aion.base.AionTransaction) FvmWrappedTransactionResult(org.aion.fastvm.FvmWrappedTransactionResult) IExternalStateForFvm(org.aion.fastvm.IExternalStateForFvm) VmFatalException(org.aion.zero.impl.vm.common.VmFatalException) RepositoryCache(org.aion.base.db.RepositoryCache)

Example 4 with VmFatalException

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);
}
Also used : AionAddress(org.aion.types.AionAddress) AionBlockSummary(org.aion.zero.impl.types.AionBlockSummary) AionTxExecSummary(org.aion.base.AionTxExecSummary) ArrayList(java.util.ArrayList) VmFatalException(org.aion.zero.impl.vm.common.VmFatalException) BigInteger(java.math.BigInteger) AionTxReceipt(org.aion.base.AionTxReceipt)

Example 5 with VmFatalException

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);
}
Also used : AionAddress(org.aion.types.AionAddress) RetValidPreBlock(org.aion.zero.impl.types.RetValidPreBlock) AionTxExecSummary(org.aion.base.AionTxExecSummary) ArrayList(java.util.ArrayList) AionTransaction(org.aion.base.AionTransaction) VmFatalException(org.aion.zero.impl.vm.common.VmFatalException) BigInteger(java.math.BigInteger) AionTxReceipt(org.aion.base.AionTxReceipt)

Aggregations

VmFatalException (org.aion.zero.impl.vm.common.VmFatalException)8 ArrayList (java.util.ArrayList)4 AionTransaction (org.aion.base.AionTransaction)4 AionTxExecSummary (org.aion.base.AionTxExecSummary)4 AionAddress (org.aion.types.AionAddress)4 BigInteger (java.math.BigInteger)3 AionTxReceipt (org.aion.base.AionTxReceipt)3 RepositoryCache (org.aion.base.db.RepositoryCache)3 TransactionResult (org.aion.types.TransactionResult)2 TimeoutException (java.util.concurrent.TimeoutException)1 AvmVersion (org.aion.avm.stub.AvmVersion)1 IAvmFutureResult (org.aion.avm.stub.IAvmFutureResult)1 IAvmResourceFactory (org.aion.avm.stub.IAvmResourceFactory)1 FvmWrappedTransactionResult (org.aion.fastvm.FvmWrappedTransactionResult)1 IExternalStateForFvm (org.aion.fastvm.IExternalStateForFvm)1 TransactionStatus (org.aion.types.TransactionStatus)1 AionBlockSummary (org.aion.zero.impl.types.AionBlockSummary)1 Block (org.aion.zero.impl.types.Block)1 RetValidPreBlock (org.aion.zero.impl.types.RetValidPreBlock)1