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);
}
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);
}
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);
}
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;
}
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);
}
Aggregations