Search in sources :

Example 6 with AccountState

use of org.aion.base.AccountState in project aion by aionnetwork.

the class AvmBulkTransactionTest method importBlockWithContractAndCallsForBothVMsWhereFVMContractHashStorageOnly.

/**
 * Ensures that a block containing the transactions described below is processed correctly:
 *
 * <ol>
 *   <li>an FVM contract deployment with storage (interpreted as empty),
 *   <li>an AVM contract deployment,
 *   <li>an FVM call to the first contract,
 *   <li>an AVM call to the second contract.
 * </ol>
 */
@Test
public void importBlockWithContractAndCallsForBothVMsWhereFVMContractHashStorageOnly() {
    BigInteger expectedNonce = getNonce(deployerKey);
    BigInteger initialBalance = getBalance(deployerKey);
    List<AionTransaction> transactions = new ArrayList<>();
    // Deploy storage-only FVM contract with data [PUSH1 0x80 PUSH1 0x80 SSTORE] (the storage change will not be registered by the kernel).
    AionTransaction deployTxFVM = AionTransaction.create(deployerKey, expectedNonce.toByteArray(), null, BigInteger.ZERO.toByteArray(), Hex.decode("6080608055"), 5_000_000L, energyPrice, TransactionTypes.DEFAULT, null);
    AionAddress fvmContract = TxUtil.calculateContractAddress(deployTxFVM);
    transactions.add(deployTxFVM);
    expectedNonce = expectedNonce.add(BigInteger.ONE);
    // Deploy AVM contract.
    AionTransaction deployTxAVM = makeAvmContractCreateTransaction(deployerKey, expectedNonce);
    AionAddress avmContract = TxUtil.calculateContractAddress(deployTxAVM);
    transactions.add(deployTxAVM);
    expectedNonce = expectedNonce.add(BigInteger.ONE);
    // Call FVM contract with code data that will be ignored by the VM because the contract has no code.
    AionTransaction contractCallTx = AionTransaction.create(deployerKey, expectedNonce.toByteArray(), fvmContract, BigInteger.ZERO.toByteArray(), Hex.decode("6080608055"), 2_000_000L, energyPrice, TransactionTypes.DEFAULT, null);
    transactions.add(contractCallTx);
    expectedNonce = expectedNonce.add(BigInteger.ONE);
    // Call AVM contract.
    transactions.add(makeAvmContractCallTransaction(deployerKey, expectedNonce, avmContract));
    expectedNonce = expectedNonce.add(BigInteger.ONE);
    // Process the 4 transactions in a single block.
    AionBlockSummary blockSummary = sendTransactionsInBulkInSingleBlock(transactions);
    // Verify that all transactions were successful.
    assertThat(blockSummary.getSummaries().size()).isEqualTo(4);
    BigInteger expectedBalance = initialBalance;
    for (AionTxExecSummary transactionSummary : blockSummary.getSummaries()) {
        AionTxReceipt receipt = transactionSummary.getReceipt();
        assertThat(receipt.isSuccessful()).isTrue();
        // Compute the expected balance.
        expectedBalance = expectedBalance.subtract(BigInteger.valueOf(receipt.getEnergyUsed()).multiply(BigInteger.valueOf(energyPrice)));
    }
    AccountState fvm = (AccountState) blockchain.getRepository().startTracking().getAccountState(fvmContract);
    // The current implementation does not allow storage-only contracts. They result in empty storage and code.
    assertThat(fvm.getStateRoot()).isEqualTo(EMPTY_TRIE_HASH);
    assertThat(fvm.getCodeHash()).isEqualTo(EMPTY_DATA_HASH);
    assertThat(getBalance(deployerKey)).isEqualTo(expectedBalance);
    assertThat(getNonce(deployerKey)).isEqualTo(expectedNonce);
}
Also used : AionAddress(org.aion.types.AionAddress) AionBlockSummary(org.aion.zero.impl.types.AionBlockSummary) AionTxExecSummary(org.aion.base.AionTxExecSummary) ArrayList(java.util.ArrayList) BigInteger(java.math.BigInteger) AionTransaction(org.aion.base.AionTransaction) AionTxReceipt(org.aion.base.AionTxReceipt) AccountState(org.aion.base.AccountState) Test(org.junit.Test)

Example 7 with AccountState

use of org.aion.base.AccountState in project aion by aionnetwork.

the class AvmBulkTransactionTest method importBlockWithContractAndCallsForAvmOnTopOfAddressWithBalance.

@Test
public void importBlockWithContractAndCallsForAvmOnTopOfAddressWithBalance() {
    BigInteger initialNonce = getNonce(deployerKey);
    // One transaction will be made to add balance to the expected contract address before the contract deployment.
    BigInteger expectedNonce = initialNonce.add(BigInteger.ONE);
    BigInteger initialBalance = getBalance(deployerKey);
    List<AionTransaction> transactions = new ArrayList<>();
    // Deploy AVM contract.
    AionTransaction deployTxAVM = makeAvmContractCreateTransaction(deployerKey, expectedNonce);
    AionAddress avmContract = TxUtil.calculateContractAddress(deployTxAVM);
    transactions.add(deployTxAVM);
    expectedNonce = expectedNonce.add(BigInteger.ONE);
    // Call AVM contract.
    transactions.add(makeAvmContractCallTransaction(deployerKey, expectedNonce, avmContract));
    expectedNonce = expectedNonce.add(BigInteger.ONE);
    // First send balance to the future contract.
    AionTransaction balanceTransferToAVM = AionTransaction.create(deployerKey, initialNonce.toByteArray(), avmContract, BigInteger.TEN.toByteArray(), new byte[0], 2_000_000L, energyPrice, TransactionTypes.DEFAULT, null);
    AionBlockSummary blockSummary = sendTransactionsInBulkInSingleBlock(List.of(balanceTransferToAVM));
    // Verify that the transaction was successful.
    assertThat(blockSummary.getSummaries().size()).isEqualTo(1);
    AionTxReceipt receipt = blockSummary.getSummaries().get(0).getReceipt();
    assertThat(receipt.isSuccessful()).isTrue();
    BigInteger expectedBalance = initialBalance.subtract(BigInteger.TEN).subtract(BigInteger.valueOf(receipt.getEnergyUsed()).multiply(BigInteger.valueOf(energyPrice)));
    AccountState contractState = (AccountState) blockchain.getRepository().startTracking().getAccountState(avmContract);
    assertThat(contractState.getBalance()).isEqualTo(BigInteger.TEN);
    assertThat(contractState.getStateRoot()).isEqualTo(EMPTY_TRIE_HASH);
    assertThat(contractState.getCodeHash()).isEqualTo(EMPTY_DATA_HASH);
    // Next, process the 2 transactions in a single block.
    blockSummary = sendTransactionsInBulkInSingleBlock(transactions);
    // Verify that all transactions were successful.
    assertThat(blockSummary.getSummaries().size()).isEqualTo(2);
    for (AionTxExecSummary transactionSummary : blockSummary.getSummaries()) {
        receipt = transactionSummary.getReceipt();
        assertThat(receipt.isSuccessful()).isTrue();
        // Compute the expected balance.
        expectedBalance = expectedBalance.subtract(BigInteger.valueOf(receipt.getEnergyUsed()).multiply(BigInteger.valueOf(energyPrice)));
    }
    contractState = (AccountState) blockchain.getRepository().startTracking().getAccountState(avmContract);
    assertThat(contractState.getBalance()).isEqualTo(BigInteger.TEN);
    assertThat(contractState.getStateRoot()).isNotEqualTo(EMPTY_TRIE_HASH);
    assertThat(contractState.getCodeHash()).isNotEqualTo(EMPTY_DATA_HASH);
    assertThat(getBalance(deployerKey)).isEqualTo(expectedBalance);
    assertThat(getNonce(deployerKey)).isEqualTo(expectedNonce);
}
Also used : AionAddress(org.aion.types.AionAddress) AionBlockSummary(org.aion.zero.impl.types.AionBlockSummary) AionTxExecSummary(org.aion.base.AionTxExecSummary) ArrayList(java.util.ArrayList) BigInteger(java.math.BigInteger) AionTransaction(org.aion.base.AionTransaction) AionTxReceipt(org.aion.base.AionTxReceipt) AccountState(org.aion.base.AccountState) Test(org.junit.Test)

Example 8 with AccountState

use of org.aion.base.AccountState in project aion by aionnetwork.

the class GenesisSpecificationTest method overrideGenesisBlockTest.

/**
 * Test that the genesis block can be overrode by certain configuration options that correspond
 * to the options provided by {@link AionGenesis.Builder}
 */
@Test
public void overrideGenesisBlockTest() {
    AionGenesis.Builder genesisBuilder = new AionGenesis.Builder();
    // values to override defaults with
    byte[] overrideHash = ByteUtil.hexStringToBytes("DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF");
    byte[] overrideAddress = ByteUtil.hexStringToBytes("DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF");
    BigInteger overrideValue = BigInteger.valueOf(1337);
    AccountState defaultAccountState = new AccountState(overrideValue, overrideValue);
    HashSet<AionAddress> accountStateSet = new HashSet<>();
    accountStateSet.add(new AionAddress(overrideHash));
    genesisBuilder.withParentHash(overrideHash).withCoinbase(new AionAddress(overrideAddress)).withDifficulty(overrideValue.toByteArray()).withEnergyLimit(overrideValue.longValue()).withNonce(overrideHash).withNumber(overrideValue.longValue()).withTimestamp(overrideValue.longValue()).addPreminedAccount(new AionAddress(overrideAddress), defaultAccountState);
    AionGenesis genesis = genesisBuilder.buildForTest();
    assertThat(genesis.getParentHash()).isEqualTo(overrideHash);
    assertThat(genesis.getCoinbase().toByteArray()).isEqualTo(overrideAddress);
    assertThat(genesis.getDifficulty()).isEqualTo(overrideValue.toByteArray());
    assertThat(genesis.getDifficultyBI()).isEqualTo(overrideValue);
    assertThat(genesis.getTimestamp()).isEqualTo(overrideValue.longValue());
    assertThat(genesis.getNrgConsumed()).isEqualTo(0);
    assertThat(genesis.getNrgLimit()).isEqualTo(overrideValue.longValue());
    assertThat(genesis.getTxTrieRoot()).isEqualTo(ConstantUtil.EMPTY_TRIE_HASH);
    assertThat(genesis.getReceiptsRoot()).isEqualTo(ConstantUtil.EMPTY_TRIE_HASH);
    assertThat(genesis.getDifficultyBI()).isEqualTo(overrideValue);
    assertThat(genesis.getTransactionsList().isEmpty()).isEqualTo(true);
    assertThat(genesis.getPremine().keySet()).isEqualTo(accountStateSet);
}
Also used : AionAddress(org.aion.types.AionAddress) BigInteger(java.math.BigInteger) AccountState(org.aion.base.AccountState) HashSet(java.util.HashSet) Test(org.junit.Test)

Example 9 with AccountState

use of org.aion.base.AccountState in project aion by aionnetwork.

the class ExternalStateForAvm method getVmType.

private InternalVmType getVmType(AionAddress destination) {
    // will load contract into memory otherwise leading to consensus issues
    RepositoryCache track = repositoryCache.startTracking();
    AccountState accountState = track.getAccountState(destination);
    InternalVmType vm;
    if (accountState == null) {
        // the address doesn't exist yet, so it can be used by either vm
        vm = InternalVmType.EITHER;
    } else {
        vm = repositoryCache.getVMUsed(destination, accountState.getCodeHash());
        // UNKNOWN is returned when there was no contract information stored
        if (vm == InternalVmType.UNKNOWN) {
            // use the in-memory value
            vm = track.getVmType(destination);
        }
    }
    return vm;
}
Also used : InternalVmType(org.aion.base.InternalVmType) RepositoryCache(org.aion.base.db.RepositoryCache) AccountState(org.aion.base.AccountState)

Example 10 with AccountState

use of org.aion.base.AccountState in project aion by aionnetwork.

the class AionBlockchainImpl method balanceRollback.

/**
 * SQ4-142
 * Rollback the balance for the mistake transactions
 */
private void balanceRollback() {
    List<byte[]> rollbackTxHash = CfgAion.inst().getFork().getRollbackTx();
    if (rollbackTxHash == null) {
        LOG.debug("no rollback transaction");
        return;
    }
    int accountDeleted = 0;
    for (byte[] hash : rollbackTxHash) {
        AionTxInfo info = getTransactionInfo(hash);
        if (info == null) {
            throw new IllegalStateException("the database missing the rollback transaction:" + ByteUtil.toHexString(hash) + "\n" + "Please re-sync your database.");
        }
        AionAddress sender = info.getReceipt().getTransaction().getSenderAddress();
        AionAddress receiver = info.getReceipt().getTransaction().getDestinationAddress();
        BigInteger balance = info.getReceipt().getTransaction().getValueBI();
        LOG.debug("sender {}, receiver {}, balance {}", sender, receiver, balance);
        AccountState stateReceiver = track.getAccountState(receiver);
        if (stateReceiver == null) {
            throw new IllegalStateException("missing receiver's state of the rollback transaction: " + receiver);
        }
        if (stateReceiver.isDeleted()) {
            throw new IllegalStateException("the receiver's state has been deleted: " + receiver);
        }
        if (stateReceiver.getBalance().compareTo(balance) >= 0) {
            track.addBalance(sender, balance);
            track.addBalance(receiver, balance.negate());
        } else {
            throw new IllegalStateException("the receiver state of the balance cannot be negative: " + receiver);
        }
        if (stateReceiver.getBalance().equals(ZERO)) {
            track.deleteAccount(receiver);
            accountDeleted++;
            LOG.debug("deletedAccount: {}", receiver);
        }
    }
    LOG.debug("rollback transactions: {}, account deleted: {}", rollbackTxHash.size(), accountDeleted);
}
Also used : AionAddress(org.aion.types.AionAddress) AionTxInfo(org.aion.zero.impl.types.AionTxInfo) BigInteger(java.math.BigInteger) AccountState(org.aion.base.AccountState)

Aggregations

AccountState (org.aion.base.AccountState)71 AionAddress (org.aion.types.AionAddress)54 Test (org.junit.Test)46 AionTransaction (org.aion.base.AionTransaction)40 RepositoryCache (org.aion.base.db.RepositoryCache)38 AionTxExecSummary (org.aion.base.AionTxExecSummary)37 Block (org.aion.zero.impl.types.Block)21 ImportResult (org.aion.zero.impl.core.ImportResult)20 BigInteger (java.math.BigInteger)18 InternalTransaction (org.aion.types.InternalTransaction)17 AionBlockchainImpl.getPostExecutionWorkForGeneratePreBlock (org.aion.zero.impl.blockchain.AionBlockchainImpl.getPostExecutionWorkForGeneratePreBlock)16 AionTxReceipt (org.aion.base.AionTxReceipt)11 AionBlockSummary (org.aion.zero.impl.types.AionBlockSummary)10 ArrayList (java.util.ArrayList)8 InternalVmType (org.aion.base.InternalVmType)5 IOException (java.io.IOException)4 HashMap (java.util.HashMap)4 Map (java.util.Map)4 JSONObject (org.json.JSONObject)4 Hex.toHexString (org.aion.util.conversions.Hex.toHexString)3