Search in sources :

Example 1 with TransactionResult

use of org.aion.types.TransactionResult in project aion by aionnetwork.

the class AvmProviderTest method testBalanceTransferTransactionVersion2.

@Test
public void testBalanceTransferTransactionVersion2() throws Exception {
    Assert.assertTrue(AvmProvider.tryAcquireLock(1, TimeUnit.MINUTES));
    AvmProvider.enableAvmVersion(AvmVersion.VERSION_2, this.projectRootDir);
    AvmProvider.startAvm(AvmVersion.VERSION_2);
    // Set up the repo and give the sender account some balance.
    RepositoryCache repository = newRepository();
    AionAddress sender = randomAddress();
    AionAddress recipient = randomAddress();
    addBalance(repository, sender, BigInteger.valueOf(1_000_000));
    // Run the transaction.
    RepositoryCache repositoryChild = repository.startTracking();
    IAvmExternalState externalState = newExternalState(AvmVersion.VERSION_2, repositoryChild, newEnergyRules());
    Transaction transaction = newBalanceTransferTransaction(sender, recipient, BigInteger.TEN);
    IAionVirtualMachine avm = AvmProvider.getAvm(AvmVersion.VERSION_2);
    IAvmFutureResult[] futures = avm.run(externalState, new Transaction[] { transaction }, AvmExecutionType.MINING, 0);
    // Assert the result and state changes we expect.
    Assert.assertEquals(1, futures.length);
    TransactionResult result = futures[0].getResult();
    Assert.assertTrue(result.transactionStatus.isSuccess());
    Assert.assertEquals(BigInteger.TEN, repositoryChild.getBalance(recipient));
    AvmProvider.shutdownAvm(AvmVersion.VERSION_2);
    AvmProvider.disableAvmVersion(AvmVersion.VERSION_2);
    AvmProvider.releaseLock();
}
Also used : IAvmExternalState(org.aion.avm.stub.IAvmExternalState) TransactionResult(org.aion.types.TransactionResult) AionAddress(org.aion.types.AionAddress) Transaction(org.aion.types.Transaction) IAvmFutureResult(org.aion.avm.stub.IAvmFutureResult) RepositoryCache(org.aion.base.db.RepositoryCache) IAionVirtualMachine(org.aion.avm.stub.IAionVirtualMachine) Test(org.junit.Test)

Example 2 with TransactionResult

use of org.aion.types.TransactionResult in project aion by aionnetwork.

the class AvmProviderTest method testBalanceTransferTransactionVersion2WithCoinbaseLock.

@Test
public void testBalanceTransferTransactionVersion2WithCoinbaseLock() throws Exception {
    Assert.assertTrue(AvmProvider.tryAcquireLock(1, TimeUnit.MINUTES));
    AvmProvider.enableAvmVersion(AvmVersion.VERSION_2, this.projectRootDir);
    AvmProvider.startAvm(AvmVersion.VERSION_2, true);
    // Set up the repo and give the sender account some balance.
    RepositoryCache repository = newRepository();
    AionAddress sender = randomAddress();
    AionAddress recipient = randomAddress();
    addBalance(repository, sender, BigInteger.valueOf(1_000_000));
    // Run the transaction.
    RepositoryCache repositoryChild = repository.startTracking();
    IAvmExternalState externalState = newExternalState(AvmVersion.VERSION_2, repositoryChild, newEnergyRules());
    Transaction transaction = newBalanceTransferTransaction(sender, recipient, BigInteger.TEN);
    IAionVirtualMachine avm = AvmProvider.getAvm(AvmVersion.VERSION_2);
    IAvmFutureResult[] futures = avm.run(externalState, new Transaction[] { transaction }, AvmExecutionType.MINING, 0);
    // Assert the result and state changes we expect.
    Assert.assertEquals(1, futures.length);
    TransactionResult result = futures[0].getResult();
    Assert.assertTrue(result.transactionStatus.isSuccess());
    Assert.assertEquals(BigInteger.TEN, repositoryChild.getBalance(recipient));
    AvmProvider.shutdownAvm(AvmVersion.VERSION_2);
    AvmProvider.disableAvmVersion(AvmVersion.VERSION_2);
    AvmProvider.releaseLock();
}
Also used : IAvmExternalState(org.aion.avm.stub.IAvmExternalState) TransactionResult(org.aion.types.TransactionResult) AionAddress(org.aion.types.AionAddress) Transaction(org.aion.types.Transaction) IAvmFutureResult(org.aion.avm.stub.IAvmFutureResult) RepositoryCache(org.aion.base.db.RepositoryCache) IAionVirtualMachine(org.aion.avm.stub.IAionVirtualMachine) Test(org.junit.Test)

Example 3 with TransactionResult

use of org.aion.types.TransactionResult 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 4 with TransactionResult

use of org.aion.types.TransactionResult 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 5 with TransactionResult

use of org.aion.types.TransactionResult in project aion by aionnetwork.

the class AvmProviderTest method testBalanceTransferTransactionVersion1.

@Test
public void testBalanceTransferTransactionVersion1() throws Exception {
    Assert.assertTrue(AvmProvider.tryAcquireLock(1, TimeUnit.MINUTES));
    AvmProvider.enableAvmVersion(AvmVersion.VERSION_1, this.projectRootDir);
    AvmProvider.startAvm(AvmVersion.VERSION_1);
    // Set up the repo and give the sender account some balance.
    RepositoryCache repository = newRepository();
    AionAddress sender = randomAddress();
    AionAddress recipient = randomAddress();
    addBalance(repository, sender, BigInteger.valueOf(1_000_000));
    // Run the transaction.
    RepositoryCache repositoryChild = repository.startTracking();
    IAvmExternalState externalState = newExternalState(AvmVersion.VERSION_1, repositoryChild, newEnergyRules());
    Transaction transaction = newBalanceTransferTransaction(sender, recipient, BigInteger.TEN);
    IAionVirtualMachine avm = AvmProvider.getAvm(AvmVersion.VERSION_1);
    IAvmFutureResult[] futures = avm.run(externalState, new Transaction[] { transaction }, AvmExecutionType.MINING, 0);
    // Assert the result and state changes we expect.
    Assert.assertEquals(1, futures.length);
    TransactionResult result = futures[0].getResult();
    Assert.assertTrue(result.transactionStatus.isSuccess());
    Assert.assertEquals(BigInteger.TEN, repositoryChild.getBalance(recipient));
    AvmProvider.shutdownAvm(AvmVersion.VERSION_1);
    AvmProvider.disableAvmVersion(AvmVersion.VERSION_1);
    AvmProvider.releaseLock();
}
Also used : IAvmExternalState(org.aion.avm.stub.IAvmExternalState) TransactionResult(org.aion.types.TransactionResult) AionAddress(org.aion.types.AionAddress) Transaction(org.aion.types.Transaction) IAvmFutureResult(org.aion.avm.stub.IAvmFutureResult) RepositoryCache(org.aion.base.db.RepositoryCache) IAionVirtualMachine(org.aion.avm.stub.IAionVirtualMachine) Test(org.junit.Test)

Aggregations

TransactionResult (org.aion.types.TransactionResult)6 RepositoryCache (org.aion.base.db.RepositoryCache)5 AionAddress (org.aion.types.AionAddress)5 IAvmFutureResult (org.aion.avm.stub.IAvmFutureResult)4 ArrayList (java.util.ArrayList)3 IAionVirtualMachine (org.aion.avm.stub.IAionVirtualMachine)3 IAvmExternalState (org.aion.avm.stub.IAvmExternalState)3 AionTransaction (org.aion.base.AionTransaction)3 AionTxExecSummary (org.aion.base.AionTxExecSummary)3 Transaction (org.aion.types.Transaction)3 Test (org.junit.Test)3 TransactionStatus (org.aion.types.TransactionStatus)2 VmFatalException (org.aion.zero.impl.vm.common.VmFatalException)2 TimeoutException (java.util.concurrent.TimeoutException)1 AvmVersion (org.aion.avm.stub.AvmVersion)1 FvmWrappedTransactionResult (org.aion.fastvm.FvmWrappedTransactionResult)1 IExternalStateForFvm (org.aion.fastvm.IExternalStateForFvm)1 IExternalStateForPrecompiled (org.aion.precompiled.type.IExternalStateForPrecompiled)1 PrecompiledWrappedTransactionResult (org.aion.precompiled.type.PrecompiledWrappedTransactionResult)1