From 37a76b06c06401ef43843e6aa2f150e36e432a5b Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Tue, 9 Apr 2019 14:13:08 -0400 Subject: [PATCH] Change the FVM.run() to receive an array of TRansactionInterfaces instead of TransactionContexts - This change is because the AVM does not require TRansactionContexts - The change makes the FVM immediately create the TransactionContext[], and then operate as before - SideEffects are now returned in the TransactionResult object --- .../src/org/aion/fastvm/ExecutionContext.java | 8 +-- .../org/aion/fastvm/FastVirtualMachine.java | 60 ++++++++++++++++++- .../aion/fastvm/FastVmTransactionResult.java | 16 ++++- modFastVM/test/org/aion/fastvm/CacheTest.java | 10 +++- .../org/aion/fastvm/CallbackUnitTest.java | 21 ++++++- .../test/org/aion/fastvm/ContractTest.java | 12 +++- .../org/aion/fastvm/DoSBlockGasLimitTest.java | 30 +++++++++- .../aion/fastvm/DoSUnexpectedThrowTest.java | 12 +++- .../test/org/aion/fastvm/FastVMTest.java | 12 +++- .../test/org/aion/fastvm/MultiThreadTest.java | 10 +++- .../test/org/aion/fastvm/NrgCostTest.java | 12 +++- 11 files changed, 180 insertions(+), 23 deletions(-) diff --git a/modFastVM/src/org/aion/fastvm/ExecutionContext.java b/modFastVM/src/org/aion/fastvm/ExecutionContext.java index ad0299b..250dff8 100644 --- a/modFastVM/src/org/aion/fastvm/ExecutionContext.java +++ b/modFastVM/src/org/aion/fastvm/ExecutionContext.java @@ -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; /** @@ -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; @@ -95,7 +95,7 @@ public class ExecutionContext implements TransactionContext { * length 32. */ public ExecutionContext( - Transaction transaction, + TransactionInterface transaction, byte[] txHash, Address destination, Address origin, @@ -313,7 +313,7 @@ public byte[] getHashOfOriginTransaction() { } @Override - public Transaction getTransaction() { + public TransactionInterface getTransaction() { return this.transaction; } } diff --git a/modFastVM/src/org/aion/fastvm/FastVirtualMachine.java b/modFastVM/src/org/aion/fastvm/FastVirtualMachine.java index 3fa75a8..ba9098e 100644 --- a/modFastVM/src/org/aion/fastvm/FastVirtualMachine.java +++ b/modFastVM/src/org/aion/fastvm/FastVirtualMachine.java @@ -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 { @@ -38,10 +41,16 @@ public void shutdown() { */ @Override public SimpleFuture[] 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[] transactionResults = @@ -76,6 +85,7 @@ public SimpleFuture[] run( List
accountsToDelete = contexts[i].getSideEffects().getAddressesToBeDeleted(); updateSnapshot(txResult, transaction, miner, accountsToDelete); + txResult.getSideEffects().merge(contexts[i].getSideEffects()); } return transactionResults; @@ -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 implements SimpleFuture { private R result; diff --git a/modFastVM/src/org/aion/fastvm/FastVmTransactionResult.java b/modFastVM/src/org/aion/fastvm/FastVmTransactionResult.java index 3596c99..b2eab65 100644 --- a/modFastVM/src/org/aion/fastvm/FastVmTransactionResult.java +++ b/modFastVM/src/org/aion/fastvm/FastVmTransactionResult.java @@ -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; } /** @@ -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; } /** @@ -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(); } /** @@ -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 + "}"; diff --git a/modFastVM/test/org/aion/fastvm/CacheTest.java b/modFastVM/test/org/aion/fastvm/CacheTest.java index ee08159..fd896cd 100644 --- a/modFastVM/test/org/aion/fastvm/CacheTest.java +++ b/modFastVM/test/org/aion/fastvm/CacheTest.java @@ -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) { diff --git a/modFastVM/test/org/aion/fastvm/CallbackUnitTest.java b/modFastVM/test/org/aion/fastvm/CallbackUnitTest.java index a68f26f..e19b001 100644 --- a/modFastVM/test/org/aion/fastvm/CallbackUnitTest.java +++ b/modFastVM/test/org/aion/fastvm/CallbackUnitTest.java @@ -1793,13 +1793,26 @@ private Pair 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))); @@ -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()); } } diff --git a/modFastVM/test/org/aion/fastvm/ContractTest.java b/modFastVM/test/org/aion/fastvm/ContractTest.java index d6d49a8..b82f5e5 100644 --- a/modFastVM/test/org/aion/fastvm/ContractTest.java +++ b/modFastVM/test/org/aion/fastvm/ContractTest.java @@ -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() { diff --git a/modFastVM/test/org/aion/fastvm/DoSBlockGasLimitTest.java b/modFastVM/test/org/aion/fastvm/DoSBlockGasLimitTest.java index 9fe5ef9..ac13a7e 100644 --- a/modFastVM/test/org/aion/fastvm/DoSBlockGasLimitTest.java +++ b/modFastVM/test/org/aion/fastvm/DoSBlockGasLimitTest.java @@ -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()); } @@ -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()); } @@ -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()); } diff --git a/modFastVM/test/org/aion/fastvm/DoSUnexpectedThrowTest.java b/modFastVM/test/org/aion/fastvm/DoSUnexpectedThrowTest.java index cfaef32..1bc4ca1 100644 --- a/modFastVM/test/org/aion/fastvm/DoSUnexpectedThrowTest.java +++ b/modFastVM/test/org/aion/fastvm/DoSUnexpectedThrowTest.java @@ -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); } } diff --git a/modFastVM/test/org/aion/fastvm/FastVMTest.java b/modFastVM/test/org/aion/fastvm/FastVMTest.java index 5c49871..3b8969a 100644 --- a/modFastVM/test/org/aion/fastvm/FastVMTest.java +++ b/modFastVM/test/org/aion/fastvm/FastVMTest.java @@ -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() { diff --git a/modFastVM/test/org/aion/fastvm/MultiThreadTest.java b/modFastVM/test/org/aion/fastvm/MultiThreadTest.java index 2552bf4..1fc8226 100644 --- a/modFastVM/test/org/aion/fastvm/MultiThreadTest.java +++ b/modFastVM/test/org/aion/fastvm/MultiThreadTest.java @@ -102,7 +102,15 @@ public void run() { vm.run( code, ctx, - new KernelInterfaceForFastVM(repo, true, false)); + new KernelInterfaceForFastVM( + repo, + true, + false, + blockDifficulty, + blockNumber, + blockTimestamp, + blockNrgLimit, + blockCoinbase)); assertEquals(FastVmResultCode.SUCCESS, result.getResultCode()); } }); diff --git a/modFastVM/test/org/aion/fastvm/NrgCostTest.java b/modFastVM/test/org/aion/fastvm/NrgCostTest.java index da8d895..bdbf54b 100644 --- a/modFastVM/test/org/aion/fastvm/NrgCostTest.java +++ b/modFastVM/test/org/aion/fastvm/NrgCostTest.java @@ -631,8 +631,16 @@ public void testDB() { } } - 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() {