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