Skip to content

Commit

Permalink
Merge pull request #57 from aionnetwork/txContext-0.4
Browse files Browse the repository at this point in the history
Object graph + transaction context
  • Loading branch information
AlexandraRoatis authored Apr 11, 2019
2 parents 6d4a64b + 292e628 commit 21ff3fc
Show file tree
Hide file tree
Showing 13 changed files with 205 additions and 23 deletions.
8 changes: 4 additions & 4 deletions modFastVM/src/org/aion/fastvm/ExecutionContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@
import org.aion.mcf.vm.types.DataWordImpl;
import org.aion.mcf.vm.types.DoubleDataWord;
import org.aion.types.Address;
import org.aion.interfaces.tx.Transaction;
import org.aion.interfaces.vm.DataWord;
import org.aion.vm.api.interfaces.TransactionContext;
import org.aion.vm.api.interfaces.TransactionInterface;
import org.aion.vm.api.interfaces.TransactionSideEffects;

/**
Expand All @@ -54,7 +54,7 @@ public class ExecutionContext implements TransactionContext {
private Address origin;
private byte[] originalTxHash;

private Transaction transaction;
private TransactionInterface transaction;

public Address address;
public Address sender;
Expand Down Expand Up @@ -95,7 +95,7 @@ public class ExecutionContext implements TransactionContext {
* length 32.
*/
public ExecutionContext(
Transaction transaction,
TransactionInterface transaction,
byte[] txHash,
Address destination,
Address origin,
Expand Down Expand Up @@ -313,7 +313,7 @@ public byte[] getHashOfOriginTransaction() {
}

@Override
public Transaction getTransaction() {
public TransactionInterface getTransaction() {
return this.transaction;
}
}
60 changes: 59 additions & 1 deletion modFastVM/src/org/aion/fastvm/FastVirtualMachine.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@
import java.util.List;
import org.aion.interfaces.db.RepositoryCache;
import org.aion.interfaces.tx.Transaction;
import org.aion.mcf.vm.types.DataWordImpl;
import org.aion.mcf.vm.types.KernelInterfaceForFastVM;
import org.aion.types.Address;
import org.aion.vm.api.interfaces.KernelInterface;
import org.aion.vm.api.interfaces.SimpleFuture;
import org.aion.vm.api.interfaces.TransactionContext;
import org.aion.vm.api.interfaces.TransactionInterface;
import org.aion.vm.api.interfaces.TransactionResult;
import org.aion.vm.api.interfaces.VirtualMachine;
import org.aion.zero.types.AionTransaction;
import org.apache.commons.lang3.ArrayUtils;

public class FastVirtualMachine implements VirtualMachine {

Expand All @@ -38,10 +41,16 @@ public void shutdown() {
*/
@Override
public SimpleFuture<TransactionResult>[] run(
KernelInterface kernel, TransactionContext[] contexts) {
KernelInterface kernel, TransactionInterface[] transactions) {
if (kernel == null) {
throw new NullPointerException("Cannot set null KernelInterface.");
}

TransactionContext[] contexts = new TransactionContext[transactions.length];
for (int i = 0; i < transactions.length; i++) {
contexts[i] = constructTransactionContext(transactions[i], kernel);
}

this.kernelSnapshot = kernel.makeChildKernelInterface();

FastVmSimpleFuture<TransactionResult>[] transactionResults =
Expand Down Expand Up @@ -76,6 +85,7 @@ public SimpleFuture<TransactionResult>[] run(
List<Address> accountsToDelete = contexts[i].getSideEffects().getAddressesToBeDeleted();

updateSnapshot(txResult, transaction, miner, accountsToDelete);
txResult.getSideEffects().merge(contexts[i].getSideEffects());
}

return transactionResults;
Expand Down Expand Up @@ -127,6 +137,54 @@ private BigInteger computeMiningFee(AionTransaction transaction, long energyUsed
return energyConsumed.multiply(energyPrice);
}

private ExecutionContext constructTransactionContext(
TransactionInterface transaction, KernelInterface kernel) {
byte[] txHash = transaction.getTransactionHash();
Address address =
transaction.isContractCreationTransaction()
? transaction.getContractAddress()
: transaction.getDestinationAddress();
Address origin = transaction.getSenderAddress();
Address caller = transaction.getSenderAddress();

DataWordImpl nrgPrice = new DataWordImpl(transaction.getEnergyPrice());
long nrg = transaction.getEnergyLimit() - transaction.getTransactionCost();
DataWordImpl callValue = new DataWordImpl(ArrayUtils.nullToEmpty(transaction.getValue()));
byte[] callData = ArrayUtils.nullToEmpty(transaction.getData());

int depth = 0;
int kind =
transaction.isContractCreationTransaction()
? ExecutionContext.CREATE
: ExecutionContext.CALL;
int flags = 0;

Address blockCoinbase = kernel.getMinerAddress();
long blockNumber = kernel.getBlockNumber();
long blockTimestamp = kernel.getBlockTimestamp();
long blockNrgLimit = kernel.getBlockEnergyLimit();
DataWordImpl blockDifficulty = new DataWordImpl(kernel.getBlockDifficulty());

return new ExecutionContext(
transaction,
txHash,
address,
origin,
caller,
nrgPrice,
nrg,
callValue,
callData,
depth,
kind,
flags,
blockCoinbase,
blockNumber,
blockTimestamp,
blockNrgLimit,
blockDifficulty);
}

private class FastVmSimpleFuture<R> implements SimpleFuture {
private R result;

Expand Down
16 changes: 14 additions & 2 deletions modFastVM/src/org/aion/fastvm/FastVmTransactionResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,24 @@
import org.aion.vm.api.interfaces.KernelInterface;
import org.aion.vm.api.interfaces.ResultCode;
import org.aion.vm.api.interfaces.TransactionResult;
import org.aion.vm.api.interfaces.TransactionSideEffects;

public final class FastVmTransactionResult implements TransactionResult {
private KernelInterface kernel;
private FastVmResultCode code;
private byte[] output;
private long energyRemaining;
private SideEffects sideEffects;

/**
* Constructs a new {@code TransactionResult} with no side-effects, with zero energy remaining,
* with an empty byte array as its output and {@link FastVmResultCode#SUCCESS} as its result code.
*/
public FastVmTransactionResult() {
setKernelAndSideEffects();
this.code = FastVmResultCode.SUCCESS;
this.output = new byte[0];
this.energyRemaining = 0;
this.kernel = null;
}

/**
Expand All @@ -31,10 +33,10 @@ public FastVmTransactionResult() {
* @param energyRemaining The energy remaining after executing the transaction.
*/
public FastVmTransactionResult(FastVmResultCode code, long energyRemaining) {
setKernelAndSideEffects();
this.code = code;
this.energyRemaining = energyRemaining;
this.output = new byte[0];
this.kernel = null;
}

/**
Expand All @@ -46,10 +48,15 @@ public FastVmTransactionResult(FastVmResultCode code, long energyRemaining) {
* @param output The output of executing the transaction.
*/
public FastVmTransactionResult(FastVmResultCode code, long energyRemaining, byte[] output) {
setKernelAndSideEffects();
this.code = code;
this.output = (output == null) ? new byte[0] : output;
this.energyRemaining = energyRemaining;
}

private void setKernelAndSideEffects() {
this.kernel = null;
sideEffects = new SideEffects();
}

/**
Expand Down Expand Up @@ -158,6 +165,11 @@ public String toString() {
// + ", output = " + ByteUtil.toHexString(this.output) + " }";
}

@Override
public TransactionSideEffects getSideEffects() {
return sideEffects;
}

public String toStringWithSideEffects() {
return "TransactionResult { code = " + this.code
+ ", energy remaining = " + this.energyRemaining + "}";
Expand Down
5 changes: 5 additions & 0 deletions modFastVM/src/org/aion/fastvm/TransactionExecutor.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
package org.aion.fastvm;

import java.math.BigInteger;
import org.aion.mcf.vm.types.KernelInterfaceForFastVM;
import org.aion.precompiled.ContractFactory;
import org.aion.precompiled.type.PrecompiledContract;
import org.aion.types.Address;
Expand Down Expand Up @@ -227,6 +228,10 @@ private void executeContractCreationTransaction() {

// create account
this.kernelGrandChild.createAccount(contractAddress);
if (this.kernelGrandChild instanceof KernelInterfaceForFastVM) {
// TODO: refactor to use the implementation directly
((KernelInterfaceForFastVM) this.kernelGrandChild).setVmType(contractAddress);
}

// execute contract deployer
if (!ArrayUtils.isEmpty(transaction.getData())) {
Expand Down
10 changes: 9 additions & 1 deletion modFastVM/test/org/aion/fastvm/CacheTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,15 @@ public void testCache() {
vm.run(
code,
ctx,
new KernelInterfaceForFastVM(new DummyRepository(), true, false));
new KernelInterfaceForFastVM(
new DummyRepository(),
true,
false,
blockDifficulty,
blockNumber,
blockTimestamp,
blockNrgLimit,
blockCoinbase));
assertEquals(FastVmResultCode.SUCCESS, result.getResultCode());

if (i % 100 == 0) {
Expand Down
21 changes: 18 additions & 3 deletions modFastVM/test/org/aion/fastvm/CallbackUnitTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1793,13 +1793,26 @@ private Pair<TransactionContext, KernelInterfaceForFastVM> mockPair() {
Pair pair = mock(Pair.class);
when(pair.getLeft()).thenReturn(context);
when(pair.getRight())
.thenReturn(new KernelInterfaceForFastVM(new DummyRepository(), true, false));
.thenReturn(
new KernelInterfaceForFastVM(
new DummyRepository(),
true,
false,
new DataWordImpl(),
0L,
0L,
0L,
Address.ZERO_ADDRESS()));
return pair;
}

private ExecutionContext mockContext() {
ExecutionContext context = mock(ExecutionContext.class);
when(context.getBlockNumber()).thenReturn(RandomUtils.nextLong(0, 10_000));
when(context.getBlockTimestamp()).thenReturn(RandomUtils.nextLong(0, 10_000));
when(context.getBlockDifficulty()).thenReturn(RandomUtils.nextLong(0, 10_000));
when(context.getBlockEnergyLimit()).thenReturn(RandomUtils.nextLong(0, 10_000));
when(context.getMinerAddress()).thenReturn(getNewAddress());
when(context.getSenderAddress()).thenReturn(getNewAddress());
when(context.getTransactionData())
.thenReturn(RandomUtils.nextBytes(RandomUtils.nextInt(0, 50)));
Expand Down Expand Up @@ -2595,7 +2608,9 @@ private void checkCreateBalances(
}
}

private static KernelInterfaceForFastVM wrapInKernelInterface(RepositoryCache cache) {
return new KernelInterfaceForFastVM(cache, true, false);
private static KernelInterfaceForFastVM wrapInKernelInterface(
RepositoryCache cache) {
return new KernelInterfaceForFastVM(
cache, true, false, new DataWordImpl(), 0L, 0L, 0L, Address.ZERO_ADDRESS());
}
}
12 changes: 10 additions & 2 deletions modFastVM/test/org/aion/fastvm/ContractTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,16 @@ public void testRecursive3() throws IOException {
assertEquals(FastVmResultCode.REVERT, result.getResultCode());
}

private static KernelInterfaceForFastVM wrapInKernelInterface(RepositoryCache cache) {
return new KernelInterfaceForFastVM(cache, true, false);
private KernelInterfaceForFastVM wrapInKernelInterface(RepositoryCache cache) {
return new KernelInterfaceForFastVM(
cache,
true,
false,
blockDifficulty,
blockNumber,
blockTimestamp,
blockNrgLimit,
blockCoinbase);
}

private ExecutionContext newExecutionContext() {
Expand Down
30 changes: 27 additions & 3 deletions modFastVM/test/org/aion/fastvm/DoSBlockGasLimitTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,15 @@ public void testGasOverLimit() throws IOException {
ExecutionContext ctx = newExecutionContext();
FastVM vm = new FastVM();
FastVmTransactionResult result =
vm.run(contract, ctx, new KernelInterfaceForFastVM(repo, true, false));
vm.run(contract, ctx, new KernelInterfaceForFastVM(
repo,
true,
false,
blockDifficulty,
blockNumber,
blockTimestamp,
blockNrgLimit,
blockCoinbase));
System.out.println(result);
assertEquals(FastVmResultCode.SUCCESS, result.getResultCode());
}
Expand All @@ -84,7 +92,15 @@ public void testGasOverLimitFail1() throws IOException {
ExecutionContext ctx = newExecutionContext();
FastVM vm = new FastVM();
FastVmTransactionResult result =
vm.run(contract, ctx, new KernelInterfaceForFastVM(repo, true, false));
vm.run(contract, ctx, new KernelInterfaceForFastVM(
repo,
true,
false,
blockDifficulty,
blockNumber,
blockTimestamp,
blockNrgLimit,
blockCoinbase));
System.out.println(result);
assertEquals(FastVmResultCode.OUT_OF_NRG, result.getResultCode());
}
Expand All @@ -106,7 +122,15 @@ public void testGasOverLimitFail2() throws IOException {
ExecutionContext ctx = newExecutionContext();
FastVM vm = new FastVM();
FastVmTransactionResult result =
vm.run(contract, ctx, new KernelInterfaceForFastVM(repo, true, false));
vm.run(contract, ctx, new KernelInterfaceForFastVM(
repo,
true,
false,
blockDifficulty,
blockNumber,
blockTimestamp,
blockNrgLimit,
blockCoinbase));
System.out.println(result);
assertEquals(FastVmResultCode.OUT_OF_NRG, result.getResultCode());
}
Expand Down
12 changes: 10 additions & 2 deletions modFastVM/test/org/aion/fastvm/DoSUnexpectedThrowTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,15 @@ public void testUnexpectedThrowRefundAllFail() throws IOException {
assertEquals(FastVmResultCode.OUT_OF_NRG, result.getResultCode());
}

private static KernelInterfaceForFastVM wrapInKernelInterface(RepositoryCache cache) {
return new KernelInterfaceForFastVM(cache, true, false);
private KernelInterfaceForFastVM wrapInKernelInterface(RepositoryCache cache) {
return new KernelInterfaceForFastVM(
cache,
true,
false,
blockDifficulty,
blockNumber,
blockTimestamp,
blockNrgLimit,
blockCoinbase);
}
}
12 changes: 10 additions & 2 deletions modFastVM/test/org/aion/fastvm/FastVMTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -775,8 +775,16 @@ public void testLocalVarDepth() throws IOException {
@After
public void teardown() {}

private static KernelInterfaceForFastVM wrapInKernelInterface(RepositoryCache cache) {
return new KernelInterfaceForFastVM(cache, true, false);
private KernelInterfaceForFastVM wrapInKernelInterface(RepositoryCache cache) {
return new KernelInterfaceForFastVM(
cache,
true,
false,
blockDifficulty,
blockNumber,
blockTimestamp,
blockNrgLimit,
blockCoinbase);
}

private ExecutionContext newExecutionContext() {
Expand Down
Loading

0 comments on commit 21ff3fc

Please sign in to comment.