Search in sources :

Example 1 with AvmVersion

use of org.aion.avm.stub.AvmVersion in project aion by aionnetwork.

the class ContractIntegTest method testDeployAvmContractToAnExistedAccount.

@Test
public void testDeployAvmContractToAnExistedAccount() {
    AvmVersion version = AvmVersion.VERSION_1;
    if (txType == TransactionTypes.DEFAULT) {
        return;
    }
    long nrg = 1_000_000;
    long nrgPrice = energyPrice;
    BigInteger value = BigInteger.ONE;
    AionAddress avmAddress = TxUtil.calculateContractAddress(deployer.toByteArray(), deployerNonce);
    // create a tx the sender send some balance to the account the deployer will deploy in the
    // feature.
    AionTransaction tx = AionTransaction.create(senderKey, senderNonce.toByteArray(), avmAddress, value.toByteArray(), new byte[0], nrg, nrgPrice, TransactionTypes.DEFAULT, null);
    assertFalse(tx.isContractCreationTransaction());
    MiningBlock block = makeBlock(tx);
    assertEquals(1, block.getTransactionsList().size());
    Pair<ImportResult, AionBlockSummary> result = blockchain.tryToConnectAndFetchSummary(block);
    assertTrue(result.getLeft().isSuccessful());
    RepositoryCache repo = blockchain.getRepository().startTracking();
    assertEquals(BigInteger.ONE, repo.getBalance(avmAddress));
    BigInteger txCost = BigInteger.valueOf(nrgPrice).multiply(BigInteger.valueOf(result.getRight().getReceipts().get(0).getEnergyUsed()));
    assertEquals(senderBalance.subtract(BigInteger.ONE).subtract(txCost), repo.getBalance(sender));
    senderNonce = senderNonce.add(BigInteger.ONE);
    AionAddress avmDeployedAddress = deployAvmContract(version, deployerNonce);
    assertNotNull(avmAddress);
    assertEquals(avmAddress, avmDeployedAddress);
    repo = blockchain.getRepository().startTracking();
    IAvmResourceFactory factory = (version == AvmVersion.VERSION_1) ? this.resourceProvider.factoryForVersion1 : this.resourceProvider.factoryForVersion2;
    byte[] avmCode = factory.newContractFactory().getJarBytes(AvmContract.HELLO_WORLD);
    assertArrayEquals(avmCode, repo.getCode(avmAddress));
    assertEquals(BigInteger.ONE, repo.getBalance(avmAddress));
    byte[] call = getCallArguments(version);
    tx = AionTransaction.create(deployerKey, deployerNonce.add(BigInteger.ONE).toByteArray(), avmAddress, BigInteger.ZERO.toByteArray(), call, 2_000_000, nrgPrice, TransactionTypes.DEFAULT, null);
    block = this.blockchain.createNewMiningBlock(this.blockchain.getBestBlock(), Collections.singletonList(tx), false);
    Pair<ImportResult, AionBlockSummary> connectResult = this.blockchain.tryToConnectAndFetchSummary(block);
    AionTxReceipt receipt = connectResult.getRight().getReceipts().get(0);
    // Check the block was imported and the transaction was successful.
    assertThat(connectResult.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
    assertThat(receipt.isSuccessful()).isTrue();
}
Also used : AionAddress(org.aion.types.AionAddress) ImportResult(org.aion.zero.impl.core.ImportResult) AionTransaction(org.aion.base.AionTransaction) MiningBlock(org.aion.zero.impl.types.MiningBlock) AionBlockSummary(org.aion.zero.impl.types.AionBlockSummary) IAvmResourceFactory(org.aion.avm.stub.IAvmResourceFactory) BigInteger(java.math.BigInteger) AionRepositoryCache(org.aion.zero.impl.db.AionRepositoryCache) RepositoryCache(org.aion.base.db.RepositoryCache) AionTxReceipt(org.aion.base.AionTxReceipt) AvmVersion(org.aion.avm.stub.AvmVersion) Test(org.junit.Test)

Example 2 with AvmVersion

use of org.aion.avm.stub.AvmVersion in project aion by aionnetwork.

the class AvmLogAndInternalTransactionTest method testLogAndInternalTransactionsOnSuccess.

@Test
public void testLogAndInternalTransactionsOnSuccess() {
    AvmVersion version = AvmVersion.VERSION_1;
    AionAddress contract = deployContract(version, BigInteger.ZERO);
    AionAddress other = deployContract(version, BigInteger.ONE);
    Pair<ImportResult, AionBlockSummary> connectResult = callFireLogs(version, BigInteger.TWO, contract, other, "fireLogsOnSuccess");
    AionBlockSummary summary = connectResult.getRight();
    assertThat(connectResult.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
    AionTxReceipt receipt = summary.getReceipts().get(0);
    assertTrue(receipt.isSuccessful());
    List<Log> logs = receipt.getLogInfoList();
    List<InternalTransaction> internalTransactions = summary.getSummaries().get(0).getInternalTransactions();
    assertEquals(3, logs.size());
    assertEquals(1, internalTransactions.size());
}
Also used : AionAddress(org.aion.types.AionAddress) ImportResult(org.aion.zero.impl.core.ImportResult) AionBlockSummary(org.aion.zero.impl.types.AionBlockSummary) Log(org.aion.types.Log) AionTxReceipt(org.aion.base.AionTxReceipt) InternalTransaction(org.aion.types.InternalTransaction) AvmVersion(org.aion.avm.stub.AvmVersion) Test(org.junit.Test)

Example 3 with AvmVersion

use of org.aion.avm.stub.AvmVersion in project aion by aionnetwork.

the class AvmLogAndInternalTransactionTest method testLogAndInternalTransactionsOnFailure.

@Test
public void testLogAndInternalTransactionsOnFailure() {
    AvmVersion version = AvmVersion.VERSION_1;
    AionAddress contract = deployContract(version, BigInteger.ZERO);
    AionAddress other = deployContract(version, BigInteger.ONE);
    Pair<ImportResult, AionBlockSummary> connectResult = callFireLogs(version, BigInteger.TWO, contract, other, "fireLogsAndFail");
    AionBlockSummary summary = connectResult.getRight();
    assertThat(connectResult.getLeft()).isEqualTo(ImportResult.IMPORTED_BEST);
    AionTxReceipt receipt = summary.getReceipts().get(0);
    assertFalse(receipt.isSuccessful());
    List<InternalTransaction> internalTransactions = summary.getSummaries().get(0).getInternalTransactions();
    List<Log> logs = receipt.getLogInfoList();
    assertEquals(0, logs.size());
    assertEquals(1, internalTransactions.size());
}
Also used : AionAddress(org.aion.types.AionAddress) ImportResult(org.aion.zero.impl.core.ImportResult) AionBlockSummary(org.aion.zero.impl.types.AionBlockSummary) Log(org.aion.types.Log) AionTxReceipt(org.aion.base.AionTxReceipt) InternalTransaction(org.aion.types.InternalTransaction) AvmVersion(org.aion.avm.stub.AvmVersion) Test(org.junit.Test)

Example 4 with AvmVersion

use of org.aion.avm.stub.AvmVersion 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 5 with AvmVersion

use of org.aion.avm.stub.AvmVersion in project aion by aionnetwork.

the class StatefulnessTest method testUsingCallInContract.

@Test
public void testUsingCallInContract() {
    AvmVersion version = AvmVersion.VERSION_1;
    if (txType == TransactionTypes.DEFAULT) {
        // skip this test cause the contract can't deploy successfully in the FVM.
        return;
    }
    AionTxReceipt receipt = deployContract(version);
    // Check the contract has the Avm prefix, and deployment succeeded, and grab the address.
    assertEquals(AddressSpecs.A0_IDENTIFIER, receipt.getTransactionOutput()[0]);
    assertTrue(receipt.isSuccessful());
    AionAddress contract = new AionAddress(receipt.getTransactionOutput());
    BigInteger deployerInitialNonce = getNonce(this.deployer);
    BigInteger contractInitialNonce = getNonce(contract);
    BigInteger deployerInitialBalance = getBalance(this.deployer);
    BigInteger contractInitialBalance = getBalance(contract);
    BigInteger fundsToSendToContract = BigInteger.valueOf(1000);
    // Transfer some value to the contract so we can do a 'call' from within it.
    receipt = transferValueTo(contract, fundsToSendToContract);
    assertTrue(receipt.isSuccessful());
    // verify that the sender and contract balances are correct after the transfer.
    BigInteger transferEnergyCost = BigInteger.valueOf(receipt.getEnergyUsed()).multiply(BigInteger.valueOf(this.energyPrice));
    BigInteger deployerBalanceAfterTransfer = deployerInitialBalance.subtract(fundsToSendToContract).subtract(transferEnergyCost);
    BigInteger contractBalanceAfterTransfer = contractInitialBalance.add(fundsToSendToContract);
    BigInteger deployerNonceAfterTransfer = deployerInitialNonce.add(BigInteger.ONE);
    assertEquals(deployerBalanceAfterTransfer, getBalance(this.deployer));
    assertEquals(contractBalanceAfterTransfer, getBalance(contract));
    assertEquals(deployerNonceAfterTransfer, getNonce(this.deployer));
    assertEquals(contractInitialNonce, getNonce(contract));
    // Generate a random beneficiary to transfer funds to via the contract.
    AionAddress beneficiary = randomAddress();
    long valueForContractToSend = fundsToSendToContract.longValue() / 2;
    // Call the contract to send value using an internal call.
    receipt = callContract(version, contract, "transferValue", beneficiary.toByteArray(), valueForContractToSend);
    assertTrue(receipt.isSuccessful());
    // Verify the accounts have the expected state.
    BigInteger deployerBalanceAfterCall = getBalance(this.deployer);
    BigInteger contractBalanceAfterCall = getBalance(contract);
    BigInteger beneficiaryBalanceAfterCall = getBalance(beneficiary);
    BigInteger callEnergyCost = BigInteger.valueOf(receipt.getEnergyUsed()).multiply(BigInteger.valueOf(this.energyPrice));
    assertEquals(deployerBalanceAfterTransfer.subtract(callEnergyCost), deployerBalanceAfterCall);
    assertEquals(contractBalanceAfterTransfer.subtract(BigInteger.valueOf(valueForContractToSend)), contractBalanceAfterCall);
    assertEquals(BigInteger.valueOf(valueForContractToSend), beneficiaryBalanceAfterCall);
    assertEquals(deployerNonceAfterTransfer.add(BigInteger.ONE), getNonce(this.deployer));
    // The contract nonce increases because it fires off an internal transaction.
    assertEquals(contractInitialNonce.add(BigInteger.ONE), getNonce(contract));
}
Also used : AionAddress(org.aion.types.AionAddress) BigInteger(java.math.BigInteger) AionTxReceipt(org.aion.base.AionTxReceipt) AvmVersion(org.aion.avm.stub.AvmVersion) Test(org.junit.Test)

Aggregations

AvmVersion (org.aion.avm.stub.AvmVersion)7 AionTxReceipt (org.aion.base.AionTxReceipt)5 AionAddress (org.aion.types.AionAddress)5 Test (org.junit.Test)5 ImportResult (org.aion.zero.impl.core.ImportResult)4 AionBlockSummary (org.aion.zero.impl.types.AionBlockSummary)4 AionTransaction (org.aion.base.AionTransaction)3 BigInteger (java.math.BigInteger)2 IAvmResourceFactory (org.aion.avm.stub.IAvmResourceFactory)2 InternalTransaction (org.aion.types.InternalTransaction)2 Log (org.aion.types.Log)2 MiningBlock (org.aion.zero.impl.types.MiningBlock)2 ArrayList (java.util.ArrayList)1 TimeoutException (java.util.concurrent.TimeoutException)1 IAvmFutureResult (org.aion.avm.stub.IAvmFutureResult)1 AionTxExecSummary (org.aion.base.AionTxExecSummary)1 RepositoryCache (org.aion.base.db.RepositoryCache)1 TransactionResult (org.aion.types.TransactionResult)1 AionRepositoryCache (org.aion.zero.impl.db.AionRepositoryCache)1 AvmVersionSchedule (org.aion.zero.impl.vm.avm.schedule.AvmVersionSchedule)1