Here are the examples of the java api org.aion.types.AionAddress taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.
851 Examples
19
Source : DirectoryDeployerIntegrationTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
public clreplaced DirectoryDeployerIntegrationTest {
private static AionAddress DEPLOYER = Helpers.randomAddress();
private static TestingBlock BLOCK = new TestingBlock(new byte[32], 1, DEPLOYER, System.currentTimeMillis(), new byte[0]);
private static long ENERGY_LIMIT = 5_000_000L;
private static long ENERGY_PRICE = 1L;
@Rule
public TemporaryFolder folder = new TemporaryFolder();
@Test
public void compare() throws Exception {
// The test we are interested in is is seeing if the histogram caused by deploying a basic contract is the same when in-process and out-of-process.
ByteArrayOutputStream captureStream = new ByteArrayOutputStream();
TestingState kernel = new TestingState(BLOCK);
kernel.adjustBalance(DEPLOYER, new BigInteger("10000000000000000000000"));
IExternalCapabilities capabilities = new StandardCapabilities();
AvmConfiguration config = new AvmConfiguration();
config.deploymentDataHistorgramOutput = new PrintStream(captureStream);
config.contractCaptureDirectory = folder.newFolder();
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(capabilities, config);
byte[] deployment = new CodeAndArguments(UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(SimpleStackDemo.clreplaced), null).encodeToBytes();
Transaction transaction = AvmTransactionUtil.create(DEPLOYER, kernel.getNonce(DEPLOYER), BigInteger.ZERO, deployment, ENERGY_LIMIT, ENERGY_PRICE);
TransactionResult result = avm.run(kernel, new Transaction[] { transaction }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
AionAddress contractAddress = new AionAddress(result.copyOfTransactionOutput().orElseThrow());
String hexContract = Helpers.bytesToHexString(contractAddress.toByteArray());
avm.shutdown();
// By this point, we should be able to capture the output.
String totalHistorgram = new String(captureStream.toByteArray(), StandardCharsets.UTF_8);
// Make sure that we see the contract in that directory.
replacedert.replacedertEquals(1, config.contractCaptureDirectory.listFiles((file) -> file.getName().equals(hexContract)).length);
// Now, invoke the DirectoryDeployer on the captured directory and make sure its output has this histogram at the end.
PrintStream originalStdOut = System.out;
ByteArrayOutputStream fakeStdOutBuffer = new ByteArrayOutputStream();
System.setOut(new PrintStream(fakeStdOutBuffer));
DirectoryDeployer.main(new String[] { config.contractCaptureDirectory.getAbsolutePath() });
System.setOut(originalStdOut);
String fromCli = new String(fakeStdOutBuffer.toByteArray(), StandardCharsets.UTF_8);
replacedert.replacedertTrue(fromCli.endsWith(totalHistorgram));
}
}
19
Source : TrsTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
private TransactionResult withdrawFromTrs(AionAddress recipient) {
return callContract(recipient, "withdraw");
}
19
Source : PocExchangeTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
public clreplaced PocExchangeTest {
private static IExternalState kernel;
private static AvmImpl avm;
private static byte[] testERC20Jar;
private static byte[] testExchangeJar;
@BeforeClreplaced
public static void setup() {
TestingBlock block = new TestingBlock(new byte[32], 1, Helpers.randomAddress(), System.currentTimeMillis(), new byte[0]);
kernel = new TestingState(block);
avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new StandardCapabilities(), new AvmConfiguration());
testERC20Jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(CoinController.clreplaced, ERC20Token.clreplaced);
testExchangeJar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(ExchangeController.clreplaced, Exchange.clreplaced, ExchangeTransaction.clreplaced, ERC20Token.clreplaced);
}
@AfterClreplaced
public static void tearDown() {
avm.shutdown();
}
private long energyLimit = 6_000_0000;
private AionAddress pepeMinter = Helpers.randomAddress();
private AionAddress memeMinter = Helpers.randomAddress();
private AionAddress exchangeOwner = Helpers.randomAddress();
private AionAddress usr1 = Helpers.randomAddress();
private AionAddress usr2 = Helpers.randomAddress();
private AionAddress usr3 = Helpers.randomAddress();
clreplaced CoinContract {
private AionAddress addr;
private AionAddress minter;
CoinContract(AionAddress contractAddr, AionAddress minter, byte[] jar, byte[] arguments) {
kernel.adjustBalance(minter, BigInteger.valueOf(1_000_000_000L));
kernel.adjustBalance(pepeMinter, BigInteger.valueOf(1_000_000_000L));
kernel.adjustBalance(memeMinter, BigInteger.valueOf(1_000_000_000L));
kernel.adjustBalance(exchangeOwner, BigInteger.valueOf(1_000_000_000L));
kernel.adjustBalance(usr1, BigInteger.valueOf(1_000_000_000L));
kernel.adjustBalance(usr2, BigInteger.valueOf(1_000_000_000L));
kernel.adjustBalance(usr3, BigInteger.valueOf(1_000_000_000L));
this.addr = contractAddr;
this.minter = minter;
this.addr = initCoin(jar, arguments);
}
private AionAddress initCoin(byte[] jar, byte[] arguments) {
Transaction createTransaction = AvmTransactionUtil.create(minter, kernel.getNonce(minter), BigInteger.ZERO, new CodeAndArguments(jar, arguments).encodeToBytes(), energyLimit, 1L);
TransactionResult createResult = avm.run(kernel, new Transaction[] { createTransaction }, ExecutionType.replacedUME_MAINCHAIN, 0)[0].getResult();
replacedert.replacedertTrue(createResult.transactionStatus.isSuccess());
return new AionAddress(createResult.copyOfTransactionOutput().orElseThrow());
}
public TransactionResult callTotalSupply() {
byte[] args = ABIUtil.encodeMethodArguments("totalSupply");
return call(minter, args);
}
private TransactionResult callBalanceOf(AionAddress toQuery) {
byte[] args = ABIUtil.encodeMethodArguments("balanceOf", new Address(toQuery.toByteArray()));
return call(minter, args);
}
private TransactionResult callMint(AionAddress receiver, long amount) {
byte[] args = ABIUtil.encodeMethodArguments("mint", new Address(receiver.toByteArray()), amount);
return call(minter, args);
}
private TransactionResult callTransfer(AionAddress sender, AionAddress receiver, long amount) {
byte[] args = ABIUtil.encodeMethodArguments("transfer", new Address(receiver.toByteArray()), amount);
return call(sender, args);
}
private TransactionResult callAllowance(AionAddress owner, AionAddress spender) {
byte[] args = ABIUtil.encodeMethodArguments("allowance", new Address(owner.toByteArray()), new Address(spender.toByteArray()));
return call(minter, args);
}
private TransactionResult callApprove(AionAddress owner, AionAddress spender, long amount) {
byte[] args = ABIUtil.encodeMethodArguments("approve", new Address(spender.toByteArray()), amount);
return call(owner, args);
}
private TransactionResult callTransferFrom(AionAddress executor, AionAddress from, AionAddress to, long amount) {
byte[] args = ABIUtil.encodeMethodArguments("transferFrom", new Address(from.toByteArray()), new Address(to.toByteArray()), amount);
return call(executor, args);
}
private TransactionResult call(AionAddress sender, byte[] args) {
Transaction callTransaction = AvmTransactionUtil.call(sender, addr, kernel.getNonce(sender), BigInteger.ZERO, args, energyLimit, 1l);
TransactionResult callResult = avm.run(kernel, new Transaction[] { callTransaction }, ExecutionType.replacedUME_MAINCHAIN, 0)[0].getResult();
replacedert.replacedertTrue(callResult.transactionStatus.isSuccess());
return callResult;
}
}
clreplaced ExchangeContract {
private AionAddress addr;
private AionAddress owner;
ExchangeContract(AionAddress contractAddr, AionAddress owner, byte[] jar) {
this.addr = contractAddr;
this.owner = owner;
this.addr = initExchange(jar, null);
}
private AionAddress initExchange(byte[] jar, byte[] arguments) {
Transaction createTransaction = AvmTransactionUtil.create(owner, kernel.getNonce(owner), BigInteger.ZERO, new CodeAndArguments(jar, arguments).encodeToBytes(), energyLimit, 1L);
TransactionResult createResult = avm.run(kernel, new Transaction[] { createTransaction }, ExecutionType.replacedUME_MAINCHAIN, 0)[0].getResult();
replacedert.replacedertTrue(createResult.transactionStatus.isSuccess());
return new AionAddress(createResult.copyOfTransactionOutput().orElseThrow());
}
public TransactionResult callListCoin(String name, AionAddress coinAddr) {
byte[] args = ABIUtil.encodeMethodArguments("listCoin", name.toCharArray(), new Address(coinAddr.toByteArray()));
return call(owner, args);
}
public TransactionResult callRequestTransfer(String name, AionAddress from, AionAddress to, long amount) {
byte[] args = ABIUtil.encodeMethodArguments("requestTransfer", name.toCharArray(), new Address(to.toByteArray()), amount);
return call(from, args);
}
public TransactionResult callProcessExchangeTransaction(AionAddress sender) {
byte[] args = ABIUtil.encodeMethodArguments("processExchangeTransaction");
return call(sender, args);
}
private TransactionResult call(AionAddress sender, byte[] args) {
Transaction callTransaction = AvmTransactionUtil.call(sender, addr, kernel.getNonce(sender), BigInteger.ZERO, args, energyLimit, 1l);
TransactionResult callResult = avm.run(kernel, new Transaction[] { callTransaction }, ExecutionType.replacedUME_MAINCHAIN, 0)[0].getResult();
replacedert.replacedertTrue(callResult.transactionStatus.isSuccess());
return callResult;
}
}
@Test
public void testERC20() {
TransactionResult res;
byte[] arguments = ABIUtil.encodeDeploymentArguments("Pepe", "PEPE", 8);
CoinContract pepe = new CoinContract(null, pepeMinter, testERC20Jar, arguments);
res = pepe.callTotalSupply();
replacedert.replacedertEquals(0L, new ABIDecoder(res.copyOfTransactionOutput().orElseThrow()).decodeOneLong());
res = pepe.callBalanceOf(usr1);
replacedert.replacedertEquals(0L, new ABIDecoder(res.copyOfTransactionOutput().orElseThrow()).decodeOneLong());
res = pepe.callBalanceOf(usr2);
replacedert.replacedertEquals(0L, new ABIDecoder(res.copyOfTransactionOutput().orElseThrow()).decodeOneLong());
res = pepe.callMint(usr1, 5000L);
replacedert.replacedertEquals(true, new ABIDecoder(res.copyOfTransactionOutput().orElseThrow()).decodeOneBoolean());
res = pepe.callBalanceOf(usr1);
replacedert.replacedertEquals(5000L, new ABIDecoder(res.copyOfTransactionOutput().orElseThrow()).decodeOneLong());
res = pepe.callMint(usr2, 10000L);
replacedert.replacedertEquals(true, new ABIDecoder(res.copyOfTransactionOutput().orElseThrow()).decodeOneBoolean());
res = pepe.callBalanceOf(usr2);
replacedert.replacedertEquals(10000L, new ABIDecoder(res.copyOfTransactionOutput().orElseThrow()).decodeOneLong());
res = pepe.callTransfer(usr1, usr2, 2000L);
replacedert.replacedertEquals(true, new ABIDecoder(res.copyOfTransactionOutput().orElseThrow()).decodeOneBoolean());
res = pepe.callBalanceOf(usr1);
replacedert.replacedertEquals(3000L, new ABIDecoder(res.copyOfTransactionOutput().orElseThrow()).decodeOneLong());
res = pepe.callBalanceOf(usr2);
replacedert.replacedertEquals(12000L, new ABIDecoder(res.copyOfTransactionOutput().orElseThrow()).decodeOneLong());
res = pepe.callAllowance(usr1, usr2);
replacedert.replacedertEquals(0L, new ABIDecoder(res.copyOfTransactionOutput().orElseThrow()).decodeOneLong());
res = pepe.callApprove(usr1, usr3, 1000L);
replacedert.replacedertEquals(true, new ABIDecoder(res.copyOfTransactionOutput().orElseThrow()).decodeOneBoolean());
res = pepe.callAllowance(usr1, usr3);
replacedert.replacedertEquals(1000L, new ABIDecoder(res.copyOfTransactionOutput().orElseThrow()).decodeOneLong());
res = pepe.callTransferFrom(usr3, usr1, usr2, 500L);
replacedert.replacedertEquals(true, new ABIDecoder(res.copyOfTransactionOutput().orElseThrow()).decodeOneBoolean());
res = pepe.callAllowance(usr1, usr3);
replacedert.replacedertEquals(500L, new ABIDecoder(res.copyOfTransactionOutput().orElseThrow()).decodeOneLong());
res = pepe.callBalanceOf(usr1);
replacedert.replacedertEquals(2500L, new ABIDecoder(res.copyOfTransactionOutput().orElseThrow()).decodeOneLong());
res = pepe.callBalanceOf(usr2);
replacedert.replacedertEquals(12500L, new ABIDecoder(res.copyOfTransactionOutput().orElseThrow()).decodeOneLong());
}
@Test
public void testExchange() {
byte[] arguments = ABIUtil.encodeDeploymentArguments("Pepe", "PEPE", 8);
CoinContract pepe = new CoinContract(null, pepeMinter, testERC20Jar, arguments);
arguments = ABIUtil.encodeDeploymentArguments("Meme", "MEME", 8);
CoinContract meme = new CoinContract(null, memeMinter, testERC20Jar, arguments);
ExchangeContract ex = new ExchangeContract(null, exchangeOwner, testExchangeJar);
TransactionResult res;
res = ex.callListCoin("PEPE", pepe.addr);
replacedert.replacedertEquals(true, new ABIDecoder(res.copyOfTransactionOutput().orElseThrow()).decodeOneBoolean());
res = ex.callListCoin("MEME", meme.addr);
replacedert.replacedertEquals(true, new ABIDecoder(res.copyOfTransactionOutput().orElseThrow()).decodeOneBoolean());
res = pepe.callMint(usr1, 5000L);
res = pepe.callMint(usr2, 5000L);
res = pepe.callApprove(usr1, ex.addr, 2000L);
replacedert.replacedertEquals(true, new ABIDecoder(res.copyOfTransactionOutput().orElseThrow()).decodeOneBoolean());
res = ex.callRequestTransfer("PEPE", usr1, usr2, 1000L);
replacedert.replacedertEquals(true, new ABIDecoder(res.copyOfTransactionOutput().orElseThrow()).decodeOneBoolean());
res = ex.callProcessExchangeTransaction(exchangeOwner);
replacedert.replacedertEquals(true, new ABIDecoder(res.copyOfTransactionOutput().orElseThrow()).decodeOneBoolean());
res = pepe.callBalanceOf(usr1);
replacedert.replacedertEquals(4000L, new ABIDecoder(res.copyOfTransactionOutput().orElseThrow()).decodeOneLong());
res = pepe.callBalanceOf(usr2);
replacedert.replacedertEquals(6000L, new ABIDecoder(res.copyOfTransactionOutput().orElseThrow()).decodeOneLong());
res = pepe.callAllowance(usr1, ex.addr);
replacedert.replacedertEquals(1000L, new ABIDecoder(res.copyOfTransactionOutput().orElseThrow()).decodeOneLong());
}
}
19
Source : DemoTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
public clreplaced DemoTest {
// NOTE: Output is ONLY produced if REPORT is set to true.
private static final boolean REPORT = false;
private long energyLimit = 5_000_0000;
private long energyPrice = 1;
private AionAddress pepeMinter = Helpers.randomAddress();
private AionAddress deployer = Helpers.randomAddress();
private AionAddress owner1 = Helpers.randomAddress();
private AionAddress owner2 = Helpers.randomAddress();
private AionAddress receiver = Helpers.randomAddress();
@Test
public void testWallet() {
IExternalState kernel = new TestingState();
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new StandardCapabilities(), new AvmConfiguration());
kernel.adjustBalance(pepeMinter, BigInteger.valueOf(1_000_000_000L));
kernel.adjustBalance(deployer, BigInteger.valueOf(1_000_000_000L));
kernel.adjustBalance(owner1, BigInteger.valueOf(1_000_000_000L));
kernel.adjustBalance(owner2, BigInteger.valueOf(1_000_000_000L));
// ================
// DEPLOY
// ================
report(">> Deploy \"PEPE\" ERC20 token Dapp...");
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(CoinController.clreplaced, ERC20Token.clreplaced);
byte[] arguments = ABIUtil.encodeDeploymentArguments("Pepe", "PEPE", 8);
// CoinContract pepe = new CoinContract(null, pepeMinter, testERC20Jar, arguments);
Transaction createTransaction = AvmTransactionUtil.create(pepeMinter, kernel.getNonce(pepeMinter), BigInteger.ZERO, new CodeAndArguments(jar, arguments).encodeToBytes(), energyLimit, energyPrice);
TransactionResult txResult = avm.run(kernel, new Transaction[] { createTransaction }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedertTrue(txResult.transactionStatus.isSuccess());
Address tokenDapp = new Address(txResult.copyOfTransactionOutput().orElseThrow());
report(">> \"PEPE\" ERC20 token Dapp is deployed. (Address " + Helpers.bytesToHexString(txResult.copyOfTransactionOutput().orElseThrow()) + ")");
report("\n>> Deploy the Multi-sig Wallet Dapp...");
jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(Main.clreplaced, Wallet.clreplaced, Bytes32.clreplaced);
int confirmationsRequired = 2;
arguments = ABIUtil.encodeDeploymentArguments(new Address(owner1.toByteArray()), new Address(owner2.toByteArray()), confirmationsRequired);
Transaction tx = AvmTransactionUtil.create(deployer, kernel.getNonce(deployer), BigInteger.ZERO, new CodeAndArguments(jar, arguments).encodeToBytes(), energyLimit, energyPrice);
txResult = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedertTrue(txResult.transactionStatus.isSuccess());
Address walletDapp = new Address(txResult.copyOfTransactionOutput().orElseThrow());
report(">> Wallet Dapp is deployed. (Address " + Helpers.bytesToHexString(txResult.copyOfTransactionOutput().orElseThrow()) + ")");
report(">> Owners List:");
report(">> Deployer - (Address " + deployer + ")");
report(">> Owner 1 - (Address " + owner1 + ")");
report(">> Owner 2 - (Address " + owner2 + ")");
report(">> Minimum number of owners to approve a transaction: " + confirmationsRequired);
// ================
// FUNDING and CHECK BALANCE
// ================
arguments = ABIUtil.encodeMethodArguments("mint", walletDapp, 5000L);
tx = AvmTransactionUtil.call(pepeMinter, new AionAddress(tokenDapp.toByteArray()), kernel.getNonce(pepeMinter), BigInteger.ZERO, arguments, energyLimit, energyPrice);
txResult = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedertTrue(txResult.transactionStatus.isSuccess());
report("\n>> PEPE Mint to deliver 5000 tokens to the wallet: " + new ABIDecoder(txResult.copyOfTransactionOutput().orElseThrow()).decodeOneBoolean());
arguments = ABIUtil.encodeMethodArguments("balanceOf", walletDapp);
tx = AvmTransactionUtil.call(pepeMinter, new AionAddress(tokenDapp.toByteArray()), kernel.getNonce(pepeMinter), BigInteger.ZERO, arguments, energyLimit, energyPrice);
txResult = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedertTrue(txResult.transactionStatus.isSuccess());
report(">> balance of wallet: " + new ABIDecoder(txResult.copyOfTransactionOutput().orElseThrow()).decodeOneLong());
arguments = ABIUtil.encodeMethodArguments("balanceOf", new Address(receiver.toByteArray()));
tx = AvmTransactionUtil.call(pepeMinter, new AionAddress(tokenDapp.toByteArray()), kernel.getNonce(pepeMinter), BigInteger.ZERO, arguments, energyLimit, energyPrice);
txResult = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedertTrue(txResult.transactionStatus.isSuccess());
report(">> balance of receiver: " + new ABIDecoder(txResult.copyOfTransactionOutput().orElseThrow()).decodeOneLong());
// ================
// PROPOSE
// ================
byte[] data = ABIUtil.encodeMethodArguments("transfer", new Address(receiver.toByteArray()), 3000L);
arguments = ABIUtil.encodeMethodArguments("propose", tokenDapp, 0L, data, energyLimit);
tx = AvmTransactionUtil.call(deployer, new AionAddress(walletDapp.toByteArray()), kernel.getNonce(deployer), BigInteger.ZERO, arguments, 2_000_000L, energyPrice);
txResult = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedertTrue(txResult.transactionStatus.isSuccess());
byte[] pendingTx = new ABIDecoder(txResult.copyOfTransactionOutput().orElseThrow()).decodeOneByteArray();
report("\n>> Deployer to propose a transaction of 3000 PEPE tokens to Receiver. (Tx ID " + Helpers.bytesToHexString(pendingTx) + ")");
// ================
// CONFIRM #1
// ================
arguments = ABIUtil.encodeMethodArguments("confirm", pendingTx);
tx = AvmTransactionUtil.call(owner1, new AionAddress(walletDapp.toByteArray()), kernel.getNonce(owner1), BigInteger.ZERO, arguments, energyLimit, energyPrice);
txResult = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedertTrue(txResult.transactionStatus.isSuccess());
report(">> Transaction confirmed by Owner 1: " + new ABIDecoder(txResult.copyOfTransactionOutput().orElseThrow()).decodeOneBoolean());
// ================
// CONFIRM #2
// ================
arguments = ABIUtil.encodeMethodArguments("confirm", pendingTx);
tx = AvmTransactionUtil.call(owner2, new AionAddress(walletDapp.toByteArray()), kernel.getNonce(owner2), BigInteger.ZERO, arguments, energyLimit, energyPrice);
txResult = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedertTrue(txResult.transactionStatus.isSuccess());
report(">> Transaction confirmed by Owner 2: " + new ABIDecoder(txResult.copyOfTransactionOutput().orElseThrow()).decodeOneBoolean());
report("\n>> Number of confirmations reach to " + confirmationsRequired + ". Transaction is processed.");
// ================
// CHECK BALANCE
// ================
arguments = ABIUtil.encodeMethodArguments("balanceOf", walletDapp);
tx = AvmTransactionUtil.call(pepeMinter, new AionAddress(tokenDapp.toByteArray()), kernel.getNonce(pepeMinter), BigInteger.ZERO, arguments, energyLimit, energyPrice);
txResult = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedertTrue(txResult.transactionStatus.isSuccess());
report("\n>> balance of wallet: " + new ABIDecoder(txResult.copyOfTransactionOutput().orElseThrow()).decodeOneLong());
arguments = ABIUtil.encodeMethodArguments("balanceOf", new Address(receiver.toByteArray()));
tx = AvmTransactionUtil.call(pepeMinter, new AionAddress(tokenDapp.toByteArray()), kernel.getNonce(pepeMinter), BigInteger.ZERO, arguments, energyLimit, energyPrice);
txResult = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedertTrue(txResult.transactionStatus.isSuccess());
report(">> balance of receiver: " + new ABIDecoder(txResult.copyOfTransactionOutput().orElseThrow()).decodeOneLong());
avm.shutdown();
}
private static void report(String report) {
if (REPORT) {
System.out.println(report);
}
}
}
19
Source : CryptoUtilMethodFeeBenchmarkTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
/**
* To more accurately benchmark the amount of time(resource) used for each crypto method calls,
* we will use the following mechanism for each test:
* - Make a few calls to method warm up the system.
* - Make several individual calls to a single method and record the time in ns.
* - Average these times to get a relatively accurate setup time.
* - Make large number of calls to a single method and benchmark the result.
* - Remove the setup time before averaging the time used for each call.
*
* Note:
* - This test suite does explicitly cover correctness.
* - All counters are set to 1 to avoid excess time used when running test over the whole AVM.
* - In general, time/call will decrease logarithmically.
*
* Please be aware that these benchmark will have some inaccuracies, if you would like a even more
* precise benchmark consider the following:
* - using a profiler software such as visualvm
* - record the times in DAppExecutor clreplaced, example [surrounding: "byte[] ret = dapp.callMain();"]
* long st, et;
* st = System.nanoTime();
* byte[] ret = dapp.callMain();
* et = System.nanoTime();
* System.out.println(et-st + "");
*
* Our summary of from the benchmark:
* - the 3 hash functions have relatively similar speed (within 5% difference on average;
* - edverify calls are much slower, can take anywhere between 50 to 100 times longer.
* - length of the message has negligible effect on resources used to hash, but we should still
* consider adding a little extra fees corresponding to msg length.
*/
public clreplaced CryptoUtilMethodFeeBenchmarkTest {
// NOTE: Output is ONLY produced if REPORT is set to true.
private static final boolean REPORT = false;
private long energyLimit = 100_000_000_000L;
private long energyPrice = 1L;
private AionAddress deployer = TestingState.PREMINED_ADDRESS;
private AionAddress dappAddress;
private TestingState kernel;
private AvmImpl avm;
private byte[] hashMessage = "benchmark testing".getBytes();
private byte[] hashMessageLong = "long benchmark testing 0123456789abcdef 0123456789abcdef 0123456789abcdef 0123456789abcdef 0123456789abcdef".getBytes();
private static final String ALPHA_NUMERIC_STRING = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
private static final String blake2bMethodName = "callBlake2b";
private static final String shaMethodName = "callSha";
private static final String keccakMethodName = "callKeccak";
private static final String edverifyMethodName = "callEdverify";
/**
* todo: when benchmarking, modify some of these values see more accurate results.
* Suggest:
* - WARMUP_COUNT >= 1000
* - LOOP_COUNT >= 10000
* - AVG_COUNT = 1
* - LIST_OF_STRING_COUNT = 10000
* - FACTOR = 100, must be a factor of LIST_OF_STRING_COUNT
* - should focus on relative time of each method call as different systems will yield different numbers.
*/
private static final int WARMUP_COUNT = 1;
private static final int LOOP_COUNT = 2;
private static final int AVG_COUNT = 1;
private static final int LIST_OF_STRING_COUNT = 5;
private static final int FACTOR = 1;
@Before
public void setup() {
byte[] basicAppTestJar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(CryptoUtilMethodFeeBenchmarkTestTargetClreplaced.clreplaced);
byte[] txData = new CodeAndArguments(basicAppTestJar, null).encodeToBytes();
this.kernel = new TestingState();
this.avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new StandardCapabilities(), new AvmConfiguration());
Transaction tx = AvmTransactionUtil.create(deployer, kernel.getNonce(deployer), BigInteger.ZERO, txData, energyLimit, energyPrice);
dappAddress = new AionAddress(avm.run(this.kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, 0)[0].getResult().copyOfTransactionOutput().orElseThrow());
replacedert.replacedertNotNull(dappAddress);
}
@After
public void tearDown() {
this.avm.shutdown();
}
/**
* For the basic hash api benchmarks (testBlake2b, testSha, testKeccak), they should be ran
* individually 1 by 1. Running them in sequence WILL have some effect on the results.
*/
@Test
public void testBlake2b() {
// warm up
for (int i = 0; i < WARMUP_COUNT; i++) {
getAvgCallTime(blake2bMethodName, AVG_COUNT, 1, hashMessage);
}
// call method and record result, measure average call time
long recordSum = 0;
for (int i = 0; i < LOOP_COUNT; i++) {
recordSum = recordSum + getCallTime(blake2bMethodName, 1, hashMessage);
}
report("Average time per api call for blake2b hashing: " + recordSum / LOOP_COUNT + "ns");
}
@Test
public void testSha() {
// warm up
for (int i = 0; i < WARMUP_COUNT; i++) {
getAvgCallTime(shaMethodName, AVG_COUNT, 1, hashMessage);
}
// call method and record result, measure average call time
long recordSum = 0;
for (int i = 0; i < LOOP_COUNT; i++) {
recordSum = recordSum + getCallTime(shaMethodName, 1, hashMessage);
}
report("Average time per api call for sha hashing: " + recordSum / LOOP_COUNT + "ns");
}
@Test
public void testKeccak() {
// warm up
for (int i = 0; i < WARMUP_COUNT; i++) {
getAvgCallTime(keccakMethodName, AVG_COUNT, 1, hashMessage);
}
// call method and record result, measure average call time
long recordSum = 0;
for (int i = 0; i < LOOP_COUNT; i++) {
recordSum = recordSum + getCallTime(keccakMethodName, 1, hashMessage);
}
report("Average time per api call for keccak hashing: " + recordSum / LOOP_COUNT + "ns");
}
/**
* Compare making looping calls from outside of dapp
*/
@Test
public void testAll3HashFunctionsAndCompare() {
long blake2bSum = 0;
long shaSum = 0;
long keccakSum = 0;
// change this message to see variance in result
byte[] msg = hashMessageLong;
for (int i = 0; i < LOOP_COUNT; i++) {
if (i < WARMUP_COUNT) {
getCallTime(blake2bMethodName, 1, msg);
getCallTime(shaMethodName, 1, msg);
getCallTime(keccakMethodName, 1, msg);
} else {
blake2bSum = blake2bSum + getCallTime(blake2bMethodName, 1, msg);
shaSum = shaSum + getCallTime(shaMethodName, 1, msg);
keccakSum = keccakSum + getCallTime(keccakMethodName, 1, msg);
}
}
long blake2bTimePerCall = blake2bSum / (LOOP_COUNT - WARMUP_COUNT);
long shaTimePerCall = shaSum / (LOOP_COUNT - WARMUP_COUNT);
long keccakTimePerCall = keccakSum / (LOOP_COUNT - WARMUP_COUNT);
report("blake2b avg: " + blake2bTimePerCall);
report("sha avg: " + shaTimePerCall + ", is " + String.format("%.3f", (double) shaTimePerCall / blake2bTimePerCall) + " times speed comparing to blake2b");
report("keccak avg: " + keccakTimePerCall + ", is " + String.format("%.3f", (double) keccakTimePerCall / blake2bTimePerCall) + " times speed comparing to blake2b");
}
/**
* Compare making looping calls from within the dapp
*/
@Test
public void testAll3HashFunctionsAndCompare2() {
// following values should be increased for a more accurate result
// recommended values are 1000, 1000000
int warmUp = WARMUP_COUNT;
int loopCount = LOOP_COUNT;
// change this message to see variance in result
byte[] msg = hashMessageLong;
// warm up blake2b, then make multiple calls within the dapp
for (int i = 0; i < warmUp; i++) {
getAvgCallTime(blake2bMethodName, AVG_COUNT, 1, hashMessage);
}
long blake2bTime = getCallTime(blake2bMethodName, loopCount, msg);
report("blake2b avg: " + blake2bTime);
// warm up sha, then make multiple calls within the dapp
for (int i = 0; i < warmUp; i++) {
getAvgCallTime(shaMethodName, AVG_COUNT, 1, hashMessage);
}
long shaSumTime = getCallTime(shaMethodName, loopCount, msg);
report("sha avg: " + shaSumTime + ", is " + String.format("%.3f", (double) shaSumTime / blake2bTime) + " times speed comparing to blake2b");
// warm up keccak, then make multiple calls within the dapp
for (int i = 0; i < warmUp; i++) {
getAvgCallTime(keccakMethodName, AVG_COUNT, 1, hashMessage);
}
long keccakTime = getCallTime(keccakMethodName, loopCount, msg);
report("keccak avg: " + keccakTime + ", is " + String.format("%.3f", (double) keccakTime / blake2bTime) + " times speed comparing to blake2b");
}
@Test
public void testAll3HashFunctionsLargeInput() {
int loopCount = LOOP_COUNT;
int messageSize = 100000;
for (int i = 0; i < WARMUP_COUNT; i++) {
getAvgCallTime(blake2bMethodName, AVG_COUNT, 1, hashMessage);
}
double blake2bAvg = getAvgCallTime("blake2bLargeInput", AVG_COUNT, loopCount, messageSize);
report("blake2b avg for " + messageSize + " bytes input:" + blake2bAvg);
for (int i = 0; i < WARMUP_COUNT; i++) {
getAvgCallTime(shaMethodName, AVG_COUNT, 1, hashMessage);
}
double sha256Sum = getAvgCallTime("shaLargeInput", AVG_COUNT, loopCount, messageSize);
report("sha256 avg for " + messageSize + " bytes input:" + sha256Sum);
for (int i = 0; i < WARMUP_COUNT; i++) {
getAvgCallTime(keccakMethodName, AVG_COUNT, 1, hashMessage);
}
double keccakSum = getAvgCallTime("keccakLargeInput", AVG_COUNT, loopCount, messageSize);
report("keccak avg for " + messageSize + " bytes input:" + keccakSum);
}
/**
* Compare edverify to blake2b
*/
@Test
public void testEdverifyComparisionToBlake2bInDepth() {
// following values should be increased for a more accurate result
int warmUp = WARMUP_COUNT;
int loopCount = LOOP_COUNT;
// change this message to see variance in result
byte[] msg = hashMessageLong;
// warm up blake2b, then make multiple calls within the dapp
for (int i = 0; i < warmUp; i++) {
getAvgCallTime(blake2bMethodName, AVG_COUNT, 1, hashMessage);
}
long blake2bTime = getCallTime(blake2bMethodName, loopCount, msg);
report("blake2b avg: " + blake2bTime);
// warm up blake2b, then make multiple calls within the dapp
for (int i = 0; i < warmUp; i++) {
getAvgCallTime(edverifyMethodName, AVG_COUNT, 1, hashMessage);
}
long edverifyTime = getCallTime(edverifyMethodName, loopCount, msg);
report("edverify avg: " + edverifyTime + ", which is " + String.format("%.3f", (double) edverifyTime / blake2bTime) + " times speed comparing to blake2b");
}
/**
* benchmark how message length can affect time it takes to hash for each algorithm
*/
@Test
public void testBlake2bMessageLength() {
String[] listOfMessage = generateListOfStrings(LIST_OF_STRING_COUNT);
for (int i = 0; i < LIST_OF_STRING_COUNT; i = i + FACTOR) {
long time = getCallTime(blake2bMethodName, 1, listOfMessage[i].getBytes());
report("Signing using blake2b: msg length = " + i + 1 + " time = " + time);
}
}
@Test
public void testShaMessageLength() {
String[] listOfMessage = generateListOfStrings(LIST_OF_STRING_COUNT);
for (int i = 0; i < LIST_OF_STRING_COUNT; i = i + FACTOR) {
long time = getCallTime(shaMethodName, 1, listOfMessage[i].getBytes());
report("Signing using sha: msg length = " + i + 1 + " time = " + time);
}
}
@Test
public void testKeccakMessageLength() {
String[] listOfMessage = generateListOfStrings(LIST_OF_STRING_COUNT);
for (int i = 0; i < LIST_OF_STRING_COUNT; i = i + FACTOR) {
long time = getCallTime(keccakMethodName, 1, listOfMessage[i].getBytes());
report("Signing using keccak: msg length = " + i + 1 + " time = " + time);
}
}
/**
* Helper methods for benchmark
*/
private double getAvgCallTime(String methodName, int loopCount, Object... arguments) {
long sum = 0;
for (int i = 0; i < loopCount; i++) {
sum = sum + getCallTime(methodName, arguments);
}
return sum / loopCount;
}
private long getCallTime(String methodName, Object... arguments) {
long st;
long et;
Transaction tx = setupTransaction(methodName, arguments);
st = System.nanoTime();
TransactionResult result = avm.run(this.kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, 0)[0].getResult();
et = System.nanoTime();
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
return et - st;
}
private Transaction setupTransaction(String methodName, java.lang.Object... arguments) {
byte[] txData = ABIUtil.encodeMethodArguments(methodName, arguments);
return AvmTransactionUtil.call(deployer, dappAddress, kernel.getNonce(deployer), BigInteger.ZERO, txData, energyLimit, energyPrice);
}
private String[] generateListOfStrings(int count) {
String[] listOfString = new String[count];
for (int i = 0; i < count; i = i + FACTOR) {
listOfString[i] = generateString(i + 1);
}
return listOfString;
}
private String generateString(int count) {
StringBuilder builder = new StringBuilder();
while (count-- != 0) {
double n = (Math.random() * ALPHA_NUMERIC_STRING.length());
builder.append(ALPHA_NUMERIC_STRING.charAt((int) n));
}
return builder.toString();
}
private static void report(String output) {
if (REPORT) {
System.out.println(output);
}
}
}
19
Source : AionBufferPerfTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
public clreplaced AionBufferPerfTest {
// NOTE: Output is ONLY produced if REPORT is set to true.
private static final boolean REPORT = false;
private AionAddress from = TestingState.PREMINED_ADDRESS;
private long energyLimit = 100_000_000L;
private long energyPrice = 1;
private byte[] buildBufferPerfJar() {
return UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(AionBufferPerfContract.clreplaced);
}
private TransactionResult deploy(IExternalState kernel, AvmImpl avm, byte[] testJar) {
byte[] testWalletArguments = new byte[0];
Transaction createTransaction = AvmTransactionUtil.create(from, kernel.getNonce(from), BigInteger.ZERO, new CodeAndArguments(testJar, testWalletArguments).encodeToBytes(), energyLimit, energyPrice);
TransactionResult createResult = avm.run(kernel, new Transaction[] { createTransaction }, ExecutionType.replacedUME_MAINCHAIN, 0)[0].getResult();
replacedert.replacedertTrue(createResult.transactionStatus.isSuccess());
return createResult;
}
private TransactionResult call(IExternalState kernel, AvmImpl avm, AionAddress contract, AionAddress sender, byte[] args) {
Transaction callTransaction = AvmTransactionUtil.call(sender, contract, kernel.getNonce(sender), BigInteger.ZERO, args, energyLimit, 1L);
TransactionResult callResult = avm.run(kernel, new Transaction[] { callTransaction }, ExecutionType.replacedUME_MAINCHAIN, 0)[0].getResult();
replacedert.replacedertTrue(callResult.transactionStatus.isSuccess());
return callResult;
}
@Test
public void testBuffer() {
report(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
report(">> Energy measurements for AionBuffer\n>>");
byte[] args;
TestingBlock block = new TestingBlock(new byte[32], 1, Helpers.randomAddress(), System.currentTimeMillis(), new byte[0]);
IExternalState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new StandardCapabilities(), new AvmConfiguration());
TransactionResult deployRes = deploy(kernel, avm, buildBufferPerfJar());
AionAddress contract = new AionAddress(deployRes.copyOfTransactionOutput().orElseThrow());
args = ABIUtil.encodeMethodArguments("callPutByte");
TransactionResult putByteResult = call(kernel, avm, contract, from, args);
report(">> putByte() : " + putByteResult.energyUsed / AionBufferPerfContract.NUM_ELEMENTS);
args = ABIUtil.encodeMethodArguments("callGetByte");
TransactionResult getByteResult = call(kernel, avm, contract, from, args);
report(">> getByte() : " + getByteResult.energyUsed / AionBufferPerfContract.NUM_ELEMENTS);
args = ABIUtil.encodeMethodArguments("callPutChar");
TransactionResult putCharResult = call(kernel, avm, contract, from, args);
report(">> putChar() : " + putCharResult.energyUsed / AionBufferPerfContract.NUM_ELEMENTS);
args = ABIUtil.encodeMethodArguments("callGetChar");
TransactionResult getCharResult = call(kernel, avm, contract, from, args);
report(">> getChar() : " + getCharResult.energyUsed / AionBufferPerfContract.NUM_ELEMENTS);
args = ABIUtil.encodeMethodArguments("callPutShort");
TransactionResult putShortResult = call(kernel, avm, contract, from, args);
report(">> putShort() : " + putShortResult.energyUsed / AionBufferPerfContract.NUM_ELEMENTS);
args = ABIUtil.encodeMethodArguments("callGetShort");
TransactionResult getShortResult = call(kernel, avm, contract, from, args);
report(">> getShort() : " + getShortResult.energyUsed / AionBufferPerfContract.NUM_ELEMENTS);
args = ABIUtil.encodeMethodArguments("callPutInt");
TransactionResult putIntResult = call(kernel, avm, contract, from, args);
report(">> putInt() : " + putIntResult.energyUsed / AionBufferPerfContract.NUM_ELEMENTS);
args = ABIUtil.encodeMethodArguments("callGetInt");
TransactionResult getIntResult = call(kernel, avm, contract, from, args);
report(">> getInt() : " + getIntResult.energyUsed / AionBufferPerfContract.NUM_ELEMENTS);
args = ABIUtil.encodeMethodArguments("callPutFloat");
TransactionResult putFloatResult = call(kernel, avm, contract, from, args);
report(">> putFloat() : " + putFloatResult.energyUsed / AionBufferPerfContract.NUM_ELEMENTS);
args = ABIUtil.encodeMethodArguments("callGetFloat");
TransactionResult getFloatResult = call(kernel, avm, contract, from, args);
report(">> getFloat() : " + getFloatResult.energyUsed / AionBufferPerfContract.NUM_ELEMENTS);
args = ABIUtil.encodeMethodArguments("callPutLong");
TransactionResult putLongResult = call(kernel, avm, contract, from, args);
report(">> putLong() : " + putLongResult.energyUsed / AionBufferPerfContract.NUM_ELEMENTS);
args = ABIUtil.encodeMethodArguments("callGetLong");
TransactionResult getLongResult = call(kernel, avm, contract, from, args);
report(">> getLong() : " + getLongResult.energyUsed / AionBufferPerfContract.NUM_ELEMENTS);
args = ABIUtil.encodeMethodArguments("callPutDouble");
TransactionResult putDoubleResult = call(kernel, avm, contract, from, args);
report(">> putDouble() : " + putDoubleResult.energyUsed / AionBufferPerfContract.NUM_ELEMENTS);
args = ABIUtil.encodeMethodArguments("callGetDouble");
TransactionResult getDoubleResult = call(kernel, avm, contract, from, args);
report(">> getDouble() : " + getDoubleResult.energyUsed / AionBufferPerfContract.NUM_ELEMENTS);
args = ABIUtil.encodeMethodArguments("callPutAddress");
TransactionResult putAddressResult = call(kernel, avm, contract, from, args);
report(">> putAddress() : " + putAddressResult.energyUsed / AionBufferPerfContract.BIG_ELT_COUNT);
args = ABIUtil.encodeMethodArguments("callGetAddress");
TransactionResult getAddressResult = call(kernel, avm, contract, from, args);
report(">> getAddress() : " + getAddressResult.energyUsed / AionBufferPerfContract.BIG_ELT_COUNT);
args = ABIUtil.encodeMethodArguments("callPutBigInt");
TransactionResult putBigIntResult = call(kernel, avm, contract, from, args);
report(">> putBigInt() : " + putBigIntResult.energyUsed / AionBufferPerfContract.BIG_ELT_COUNT);
args = ABIUtil.encodeMethodArguments("callGetBigInt");
TransactionResult getBigIntResult = call(kernel, avm, contract, from, args);
report(">> getBigInt() : " + getBigIntResult.energyUsed / AionBufferPerfContract.BIG_ELT_COUNT);
args = ABIUtil.encodeMethodArguments("callTransferBytesToBuffer");
TransactionResult putResult = call(kernel, avm, contract, from, args);
report(">> put() : " + putResult.energyUsed / AionBufferPerfContract.NUM_ELEMENTS + " (for transfers of " + AionBufferPerfContract.TRANSFER_SIZE + " bytes)");
args = ABIUtil.encodeMethodArguments("callTransferBytesFromBuffer");
TransactionResult getResult = call(kernel, avm, contract, from, args);
report(">> get() : " + getResult.energyUsed / AionBufferPerfContract.NUM_ELEMENTS + " (for transfers of " + AionBufferPerfContract.TRANSFER_SIZE + " bytes)");
args = ABIUtil.encodeMethodArguments("callEquals");
TransactionResult equalsResult = call(kernel, avm, contract, from, args);
report(">> equals() : " + equalsResult.energyUsed / AionBufferPerfContract.NUM_ELEMENTS);
avm.shutdown();
report("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
}
private static void report(String output) {
if (REPORT) {
System.out.println(output);
}
}
}
19
Source : DirectoryDeployer.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
/**
* A tool to run our data collection histogram against pre-created contracts.
* Point this at a directory containing code and argument data and it will deploy every contract found, with corresponding argument data.
* The expected shape of the directory given is produced by the AvmConfiguration.contractCaptureDirectory option.
*
* NOTE: This currently deploys 1 contract at a time, in the order they are found in the directory, using the same emulated block.
* In the future, this may be changed to deploy them in the order and blocks defined by the other meta-data.
*/
public clreplaced DirectoryDeployer {
private static AionAddress DEPLOYER = Helpers.randomAddress();
private static TestingBlock BLOCK = new TestingBlock(new byte[32], 1, DEPLOYER, System.currentTimeMillis(), new byte[0]);
private static long ENERGY_LIMIT = 5_000_000L;
private static long ENERGY_PRICE = 1L;
public static void main(String[] args) {
TestingState kernel = new TestingState(BLOCK);
kernel.adjustBalance(DEPLOYER, new BigInteger("10000000000000000000000"));
IExternalCapabilities capabilities = new StandardCapabilities();
AvmConfiguration config = new AvmConfiguration();
config.deploymentDataHistorgramOutput = System.out;
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(capabilities, config);
File rootDirectory = new File(args[0]);
replacedertTrue(rootDirectory.isDirectory());
int preplacedCount = 0;
int failCount = 0;
for (String name : rootDirectory.list()) {
try {
Transaction transaction = createTransaction(kernel, new File(rootDirectory, name));
FutureResult[] futures = avm.run(kernel, new Transaction[] { transaction }, ExecutionType.replacedUME_MAINCHAIN, 0);
boolean success = futures[0].getResult().transactionStatus.isSuccess();
if (success) {
preplacedCount += 1;
} else {
failCount += 1;
}
System.out.println(name + ": " + (success ? "Preplaced" : "FAIL"));
} catch (IOException e) {
System.err.println(name);
e.printStackTrace();
System.exit(1);
}
}
System.out.println("Attempted " + (preplacedCount + failCount) + " deployments (" + preplacedCount + " preplaceded, " + failCount + " failed)");
avm.shutdown();
}
private static Transaction createTransaction(IExternalState kernel, File directory) throws IOException {
// For now, we will only load the code and the arguments.
byte[] code = Files.readAllBytes(new File(directory, "code.jar").toPath());
File argFile = new File(directory, "arguments.bin");
byte[] args = argFile.exists() ? Files.readAllBytes(argFile.toPath()) : new byte[0];
byte[] createData = new CodeAndArguments(code, args).encodeToBytes();
return AvmTransactionUtil.create(DEPLOYER, kernel.getNonce(DEPLOYER), BigInteger.ZERO, createData, ENERGY_LIMIT, ENERGY_PRICE);
}
private static void replacedertTrue(boolean flag) {
// We use a private helper to manage the replacedertions since the JDK default disables them.
if (!flag) {
throw new replacedertionError("Case must be true");
}
}
}
19
Source : AvmCLI.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
public static void reportDeployRequest(IEnvironment env, String storagePath, String jarPath, AionAddress sender) {
lineSeparator(env);
env.logLine("DApp deployment request");
env.logLine("Storage : " + storagePath);
env.logLine("Dapp Jar : " + jarPath);
env.logLine("Sender : " + sender);
}
19
Source : AvmCLI.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
private static void reportCallRequest(IEnvironment env, String storagePath, AionAddress contract, AionAddress sender, String method, Object[] args) {
lineSeparator(env);
env.logLine("DApp call request");
env.logLine("Storage : " + storagePath);
env.logLine("Dapp Address : " + contract);
env.logLine("Sender : " + sender);
env.logLine("Method : " + method);
env.logLine("Arguments : ");
for (int i = 0; i < args.length; i += 2) {
env.logLine(" : " + args[i]);
}
}
19
Source : AvmParallelTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
public clreplaced AvmParallelTest {
private AionAddress preminedAddress = TestingState.PREMINED_ADDRESS;
private TestingBlock block = new TestingBlock(new byte[32], 1, Helpers.randomAddress(), System.currentTimeMillis(), new byte[0]);
@Test
public void basicConcurrencyTest() {
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
AionAddress usr1 = new AionAddress(Helpers.hexStringToBytes("1111111111111111111111111111111111111111111111111111111111111111"));
BigInteger expected1 = BigInteger.ZERO;
Transaction t0 = AvmTransactionUtil.call(preminedAddress, usr1, BigInteger.ZERO, BigInteger.valueOf(500_000), new byte[0], 100000L, 1);
Transaction t1 = AvmTransactionUtil.call(preminedAddress, usr1, BigInteger.ONE, BigInteger.valueOf(500_000), new byte[0], 100000L, 1);
Transaction t2 = AvmTransactionUtil.call(preminedAddress, usr1, BigInteger.TWO, BigInteger.valueOf(500_000), new byte[0], 100000L, 1);
Transaction t3 = AvmTransactionUtil.call(preminedAddress, usr1, BigInteger.valueOf(3), BigInteger.valueOf(500_000), new byte[0], 100000L, 1);
Transaction t4 = AvmTransactionUtil.call(preminedAddress, usr1, BigInteger.valueOf(4), BigInteger.valueOf(500_000), new byte[0], 100000L, 1);
Transaction[] batch = new Transaction[] { t0, t1, t2, t3, t4 };
FutureResult[] results = avm.run(kernel, batch, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1);
for (FutureResult f : results) {
f.getResult();
}
expected1 = expected1.add(BigInteger.valueOf(500_000 * 5));
replacedert.replacedertEquals(expected1, kernel.getBalance(usr1));
AionAddress usr2 = new AionAddress(Helpers.hexStringToBytes("2222222222222222222222222222222222222222222222222222222222222222"));
BigInteger expected2 = BigInteger.ZERO;
t0 = AvmTransactionUtil.call(usr1, usr2, BigInteger.ZERO, BigInteger.valueOf(100_000), new byte[0], 100000L, 1);
t1 = AvmTransactionUtil.call(usr1, usr2, BigInteger.ONE, BigInteger.valueOf(100_000), new byte[0], 100000L, 1);
t2 = AvmTransactionUtil.call(usr1, usr2, BigInteger.TWO, BigInteger.valueOf(100_000), new byte[0], 100000L, 1);
t3 = AvmTransactionUtil.call(usr1, usr2, BigInteger.valueOf(3), BigInteger.valueOf(100_000), new byte[0], 100000L, 1);
t4 = AvmTransactionUtil.call(usr1, usr2, BigInteger.valueOf(4), BigInteger.valueOf(100_000), new byte[0], 100000L, 1);
batch = new Transaction[] { t0, t1, t2, t3, t4 };
results = avm.run(kernel, batch, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1);
for (FutureResult f : results) {
f.getResult();
}
expected1 = expected1.subtract(BigInteger.valueOf(100_000 * 5)).subtract(BigInteger.valueOf(BillingRules.getBasicTransactionCost(t1.copyOfTransactionData()) * 5));
expected2 = BigInteger.valueOf(100_000 * 5);
replacedert.replacedertEquals(expected1, kernel.getBalance(usr1));
replacedert.replacedertEquals(expected2, kernel.getBalance(usr2));
t0 = AvmTransactionUtil.call(usr1, usr2, BigInteger.ZERO, BigInteger.valueOf(100_000), new byte[0], 100000L, 1);
t1 = AvmTransactionUtil.call(usr2, usr1, BigInteger.ONE, BigInteger.valueOf(100_000), new byte[0], 100000L, 1);
int iteration = 10;
batch = new Transaction[iteration * 2];
for (int i = 0; i < iteration; i++) {
batch[i * 2] = AvmTransactionUtil.call(usr1, usr2, BigInteger.valueOf(5 + i), BigInteger.valueOf(100_000), new byte[0], 100000L, 1);
batch[i * 2 + 1] = AvmTransactionUtil.call(usr2, usr1, BigInteger.valueOf(i), BigInteger.valueOf(100_000), new byte[0], 100000L, 1);
}
results = avm.run(kernel, batch, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1);
for (FutureResult f : results) {
f.getResult();
}
expected1 = expected1.subtract(BigInteger.valueOf(BillingRules.getBasicTransactionCost(t0.copyOfTransactionData()) * iteration));
expected2 = expected2.subtract(BigInteger.valueOf(BillingRules.getBasicTransactionCost(t1.copyOfTransactionData()) * iteration));
replacedert.replacedertEquals(expected1, kernel.getBalance(usr1));
replacedert.replacedertEquals(expected2, kernel.getBalance(usr2));
avm.shutdown();
}
@Test
public void cyclicWaitTest() {
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
AionAddress usr1 = new AionAddress(Helpers.hexStringToBytes("1111111111111111111111111111111111111111111111111111111111111111"));
AionAddress usr2 = new AionAddress(Helpers.hexStringToBytes("2222222222222222222222222222222222222222222222222222222222222222"));
AionAddress usr3 = new AionAddress(Helpers.hexStringToBytes("3333333333333333333333333333333333333333333333333333333333333333"));
AionAddress usr4 = new AionAddress(Helpers.hexStringToBytes("4444444444444444444444444444444444444444444444444444444444444444"));
Transaction t0 = AvmTransactionUtil.call(preminedAddress, usr1, BigInteger.ZERO, BigInteger.valueOf(5_000_000), new byte[0], 100000L, 1);
Transaction t1 = AvmTransactionUtil.call(usr1, usr2, BigInteger.ZERO, BigInteger.valueOf(4_000_000), new byte[0], 100000L, 1);
Transaction t2 = AvmTransactionUtil.call(usr2, usr3, BigInteger.ZERO, BigInteger.valueOf(3_000_000), new byte[0], 100000L, 1);
Transaction t3 = AvmTransactionUtil.call(usr3, usr4, BigInteger.ZERO, BigInteger.valueOf(2_000_000), new byte[0], 100000L, 1);
Transaction t4 = AvmTransactionUtil.call(usr4, usr1, BigInteger.ZERO, BigInteger.valueOf(1_000_000), new byte[0], 100000L, 1);
Transaction[] batch = new Transaction[] { t0, t1, t2, t3, t4 };
FutureResult[] results = avm.run(kernel, batch, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1);
for (FutureResult f : results) {
f.getResult();
}
avm.shutdown();
}
@Test
public void internalTransactionTest() {
byte[] code = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(TestContract.clreplaced);
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
AionAddress usr1 = new AionAddress(Helpers.hexStringToBytes("1111111111111111111111111111111111111111111111111111111111111111"));
AionAddress usr2 = new AionAddress(Helpers.hexStringToBytes("2222222222222222222222222222222222222222222222222222222222222222"));
AionAddress usr3 = new AionAddress(Helpers.hexStringToBytes("3333333333333333333333333333333333333333333333333333333333333333"));
AionAddress usr4 = new AionAddress(Helpers.hexStringToBytes("4444444444444444444444444444444444444444444444444444444444444444"));
Transaction t0 = AvmTransactionUtil.call(preminedAddress, usr1, BigInteger.ZERO, BigInteger.valueOf(5_000_000), new byte[0], 100000L, 1);
Transaction t1 = AvmTransactionUtil.call(preminedAddress, usr2, BigInteger.ONE, BigInteger.valueOf(5_000_000), new byte[0], 100000L, 1);
Transaction t2 = AvmTransactionUtil.call(preminedAddress, usr3, BigInteger.TWO, BigInteger.valueOf(5_000_000), new byte[0], 100000L, 1);
Transaction t3 = AvmTransactionUtil.call(preminedAddress, usr4, BigInteger.valueOf(3), BigInteger.valueOf(15_000_000), new byte[0], 100000L, 1);
Transaction t4 = AvmTransactionUtil.create(usr4, BigInteger.ZERO, BigInteger.ZERO, new CodeAndArguments(code, null).encodeToBytes(), 10_000_000L, 1);
Transaction[] batch = new Transaction[] { t0, t1, t2, t3, t4 };
FutureResult[] results = avm.run(kernel, batch, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1);
for (FutureResult f : results) {
f.getResult();
}
TransactionResult res = results[4].getResult();
AionAddress contractAddr = new AionAddress(res.copyOfTransactionOutput().orElseThrow());
byte[] args = encodeNoArgsMethodCall("doTransfer");
byte[] args2 = encodeNoArgsMethodCall("addValue");
t0 = AvmTransactionUtil.call(preminedAddress, contractAddr, BigInteger.valueOf(4), BigInteger.valueOf(5_000_000), args2, 100000L, 1);
t1 = AvmTransactionUtil.call(usr1, contractAddr, BigInteger.ZERO, BigInteger.ZERO, args, 200000L, 1);
t2 = AvmTransactionUtil.call(usr2, contractAddr, BigInteger.ZERO, BigInteger.ZERO, args, 200000L, 1);
t3 = AvmTransactionUtil.call(usr3, contractAddr, BigInteger.ZERO, BigInteger.ZERO, args, 200000L, 1);
t4 = AvmTransactionUtil.call(usr4, contractAddr, BigInteger.ONE, BigInteger.ZERO, args, 200000L, 1);
batch = new Transaction[] { t0, t1, t2, t3, t4 };
results = avm.run(kernel, batch, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1);
for (FutureResult f : results) {
f.getResult();
}
avm.shutdown();
}
/**
* This test attempts to transfer to 100 users and then from those to 1 user. This will cause heavy abort behaviour because this is a data hazard.
*/
@Test
public void heavyAbortTest() {
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
// We will send 2x the value to these accounts, initially, and they will send 1x to the target.
int iterations = 100;
long valueToSend = 1_000_000L;
AionAddress targetUser = Helpers.randomAddress();
AionAddress[] tempUsers = new AionAddress[iterations];
// First batch - disperse funds.
Transaction[] firstBatch = new Transaction[iterations];
for (int i = 0; i < iterations; ++i) {
tempUsers[i] = Helpers.randomAddress();
firstBatch[i] = AvmTransactionUtil.call(preminedAddress, tempUsers[i], BigInteger.valueOf(i), BigInteger.valueOf(2L * valueToSend), new byte[0], 100_000L, 1L);
}
FutureResult[] results = avm.run(kernel, firstBatch, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1);
for (FutureResult f : results) {
replacedert.replacedertTrue(f.getResult().transactionStatus.isSuccess());
}
// Second batch - collect funds.
Transaction[] secondBatch = new Transaction[iterations];
for (int i = 0; i < iterations; ++i) {
secondBatch[i] = AvmTransactionUtil.call(tempUsers[i], targetUser, BigInteger.ZERO, BigInteger.valueOf(valueToSend), new byte[0], 100_000L, 1L);
}
results = avm.run(kernel, secondBatch, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1);
for (FutureResult f : results) {
replacedert.replacedertTrue(f.getResult().transactionStatus.isSuccess());
}
// Check that this had the expected result.
replacedert.replacedertEquals(BigInteger.valueOf((long) iterations * valueToSend), kernel.getBalance(targetUser));
avm.shutdown();
}
@Test
public void reentrantAbort() {
byte[] code = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(TestContract.clreplaced);
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
int length = 5;
AionAddress[] user = new AionAddress[length];
Transaction[] ctx = new Transaction[length];
for (int i = 0; i < user.length; i++) {
user[i] = Helpers.randomAddress();
kernel.adjustBalance(user[i], BigInteger.TEN.pow(20));
ctx[i] = AvmTransactionUtil.create(user[i], BigInteger.ZERO, BigInteger.ZERO, new CodeAndArguments(code, null).encodeToBytes(), 5_000_000L, 1);
}
FutureResult[] results = avm.run(kernel, ctx, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1);
AionAddress[] contractAddresses = new AionAddress[results.length];
for (int i = 0; i < results.length; i++) {
contractAddresses[i] = new AionAddress(results[i].getResult().copyOfTransactionOutput().orElseThrow());
}
Transaction[] tx = new Transaction[results.length - 1];
// A->A->B, B->B->C, C->C->D
for (int i = 0; i < results.length - 1; i++) {
byte[] internalCallData = new ABIStreamingEncoder().encodeOneString("doCallOther").encodeOneAddress(new Address(contractAddresses[i + 1].toByteArray())).encodeOneByteArray(new ABIStreamingEncoder().encodeOneString("addValue").toBytes()).toBytes();
byte[] data = new ABIStreamingEncoder().encodeOneString("doCallThis").encodeOneByteArray(internalCallData).toBytes();
tx[i] = AvmTransactionUtil.call(user[i], contractAddresses[i], kernel.getNonce(user[i]), BigInteger.ZERO, data, 5_000_000, 1);
}
results = avm.run(kernel, tx, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1);
for (FutureResult f : results) {
f.getResult();
}
// validate the state of contracts
for (int i = 0; i < length - 1; i++) {
byte[] getCallCount = new ABIStreamingEncoder().encodeOneString("getCallCount").toBytes();
tx[i] = AvmTransactionUtil.call(user[i], contractAddresses[i], kernel.getNonce(user[i]), BigInteger.ZERO, getCallCount, 5_000_000, 1);
}
results = avm.run(kernel, tx, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1);
for (FutureResult f : results) {
replacedert.replacedertEquals(2, new ABIDecoder(f.getResult().copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
for (int i = 1; i < length - 1; i++) {
byte[] getValue = new ABIStreamingEncoder().encodeOneString("getValue").toBytes();
tx[i] = AvmTransactionUtil.call(user[i], contractAddresses[i], kernel.getNonce(user[i]), BigInteger.ZERO, getValue, 5_000_000, 1);
}
results = avm.run(kernel, new Transaction[] { tx[1], tx[2], tx[3] }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1);
for (FutureResult f : results) {
replacedert.replacedertEquals(1, new ABIDecoder(f.getResult().copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
avm.shutdown();
}
@Test
public void internalTransactionAbort() {
byte[] code = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(TestContract.clreplaced);
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
int length = 4;
AionAddress[] user = new AionAddress[length];
Transaction[] ctx = new Transaction[length];
for (int i = 0; i < length; i++) {
user[i] = Helpers.randomAddress();
kernel.adjustBalance(user[i], BigInteger.TEN.pow(20));
ctx[i] = AvmTransactionUtil.create(user[i], BigInteger.ZERO, BigInteger.ZERO, new CodeAndArguments(code, null).encodeToBytes(), 5_000_000L, 1);
}
FutureResult[] results = avm.run(kernel, ctx, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1);
AionAddress[] contractAddresses = new AionAddress[results.length];
for (int i = 0; i < results.length; i++) {
contractAddresses[i] = new AionAddress(results[i].getResult().copyOfTransactionOutput().orElseThrow());
}
Transaction[] tx = new Transaction[results.length - 1];
// u1->A->B, u2->B->C, u3->C->D
for (int i = 0; i < results.length - 1; i++) {
byte[] callData = new ABIStreamingEncoder().encodeOneString("doCallOther").encodeOneAddress(new Address(contractAddresses[i + 1].toByteArray())).encodeOneByteArray(new ABIStreamingEncoder().encodeOneString("addValue").toBytes()).toBytes();
tx[i] = AvmTransactionUtil.call(user[i], contractAddresses[i], kernel.getNonce(user[i]), BigInteger.ZERO, callData, 5_000_000, 1);
}
results = avm.run(kernel, tx, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1);
for (FutureResult f : results) {
f.getResult();
}
// validate the state of contracts
for (int i = 0; i < length - 1; i++) {
byte[] getCallCount = new ABIStreamingEncoder().encodeOneString("getCallCount").toBytes();
tx[i] = AvmTransactionUtil.call(user[i], contractAddresses[i], kernel.getNonce(user[i]), BigInteger.ZERO, getCallCount, 5_000_000, 1);
}
results = avm.run(kernel, tx, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1);
for (FutureResult f : results) {
replacedert.replacedertEquals(1, new ABIDecoder(f.getResult().copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
for (int i = 1; i < length - 1; i++) {
byte[] getValue = new ABIStreamingEncoder().encodeOneString("getValue").toBytes();
tx[i] = AvmTransactionUtil.call(user[i], contractAddresses[i], kernel.getNonce(user[i]), BigInteger.ZERO, getValue, 5_000_000, 1);
}
Transaction[] batch = new Transaction[] { tx[1], tx[2] };
results = avm.run(kernel, batch, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1);
for (FutureResult f : results) {
replacedert.replacedertEquals(1, new ABIDecoder(f.getResult().copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
avm.shutdown();
}
@Test
public void internalTransactionAbortDuringTransformation() {
byte[] code = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(TestContract.clreplaced);
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
int length = 4;
AionAddress[] user = new AionAddress[length];
Transaction[] ctx = new Transaction[length];
for (int i = 0; i < length; i++) {
user[i] = Helpers.randomAddress();
kernel.adjustBalance(user[i], BigInteger.TEN.pow(20));
ctx[i] = AvmTransactionUtil.create(user[i], BigInteger.ZERO, BigInteger.ZERO, new CodeAndArguments(code, null).encodeToBytes(), 5_000_000L, 1);
}
FutureResult[] results = avm.run(kernel, ctx, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1);
AionAddress[] contractAddresses = new AionAddress[results.length];
for (int i = 0; i < results.length; i++) {
contractAddresses[i] = new AionAddress(results[i].getResult().copyOfTransactionOutput().orElseThrow());
kernel.setTransformedCode(contractAddresses[i], null);
}
Transaction[] tx = new Transaction[results.length - 1];
// u1->A->B, u2->B->C, u3->C->D
for (int i = 0; i < results.length - 1; i++) {
byte[] callData = new ABIStreamingEncoder().encodeOneString("doCallOther").encodeOneAddress(new Address(contractAddresses[i + 1].toByteArray())).encodeOneByteArray(new ABIStreamingEncoder().encodeOneString("addValue").toBytes()).toBytes();
tx[i] = AvmTransactionUtil.call(user[i], contractAddresses[i], kernel.getNonce(user[i]), BigInteger.ZERO, callData, 5_000_000, 1);
}
for (AionAddress contractAddress : contractAddresses) {
kernel.setTransformedCode(contractAddress, null);
}
results = avm.run(kernel, tx, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1);
for (FutureResult f : results) {
f.getResult();
}
// validate the state of contracts
for (int i = 0; i < length - 1; i++) {
byte[] getCallCount = new ABIStreamingEncoder().encodeOneString("getCallCount").toBytes();
tx[i] = AvmTransactionUtil.call(user[i], contractAddresses[i], kernel.getNonce(user[i]), BigInteger.ZERO, getCallCount, 5_000_000, 1);
}
results = avm.run(kernel, tx, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1);
for (FutureResult f : results) {
replacedert.replacedertEquals(1, new ABIDecoder(f.getResult().copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
avm.shutdown();
}
@Test
public void testCoinbaseLock() {
byte[] code = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(TestContract.clreplaced);
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
int length = 3;
AionAddress[] user = new AionAddress[length];
Transaction[] ctx = new Transaction[length];
for (int i = 0; i < length; i++) {
user[i] = Helpers.randomAddress();
kernel.adjustBalance(user[i], BigInteger.TEN.pow(20));
ctx[i] = AvmTransactionUtil.create(user[i], BigInteger.ZERO, BigInteger.ZERO, new CodeAndArguments(code, null).encodeToBytes(), 5_000_000L, 1);
}
FutureResult[] results = avm.run(kernel, ctx, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1);
AionAddress[] contractAddresses = new AionAddress[results.length];
for (int i = 0; i < results.length; i++) {
contractAddresses[i] = new AionAddress(results[i].getResult().copyOfTransactionOutput().orElseThrow());
}
kernel.generateBlock();
byte[][] callData = new byte[length][];
Address minerAddress = new Address(kernel.getMinerAddress().toByteArray());
callData[0] = new ABIStreamingEncoder().encodeOneString("getBalance").encodeOneAddress(new Address(Helpers.randomBytes(32))).encodeOneInteger(1000).toBytes();
callData[1] = new ABIStreamingEncoder().encodeOneString("addValue").toBytes();
callData[2] = new ABIStreamingEncoder().encodeOneString("getBalance").encodeOneAddress(minerAddress).encodeOneInteger(1000).toBytes();
Transaction[] tx = new Transaction[length];
for (int i = 0; i < length; i++) {
tx[i] = AvmTransactionUtil.call(user[i], contractAddresses[i], kernel.getNonce(user[i]), BigInteger.ZERO, callData[i], 10_000_000, 1);
}
BigInteger initialBalance = kernel.getBalance(kernel.getMinerAddress());
// Specifically tests the issue mentioned in AKI-644
results = avm.run(kernel, tx, ExecutionType.MINING, kernel.getBlockNumber() - 1);
replacedert.replacedertEquals(BigInteger.ZERO, new ABIDecoder(results[0].getResult().copyOfTransactionOutput().orElseThrow()).decodeOneBigInteger());
replacedert.replacedertEquals(initialBalance.add(BigInteger.valueOf(results[0].getResult().energyUsed)).add(BigInteger.valueOf(results[1].getResult().energyUsed)), new ABIDecoder(results[2].getResult().copyOfTransactionOutput().orElseThrow()).decodeOneBigInteger());
avm.shutdown();
}
private static byte[] encodeNoArgsMethodCall(String methodName) {
return new ABIStreamingEncoder().encodeOneString(methodName).toBytes();
}
}
19
Source : Blake2bTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
public clreplaced Blake2bTest {
private long energyLimit = 10_000_000L;
private long energyPrice = 1L;
private AionAddress deployer = TestingState.PREMINED_ADDRESS;
private AionAddress dappAddress;
private TestingState kernel;
private AvmImpl avm;
@Before
public void setup() {
TestingBlock block = new TestingBlock(new byte[32], 1, Helpers.randomAddress(), System.currentTimeMillis(), new byte[0]);
this.kernel = new TestingState(block);
this.avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
byte[] jar = JarBuilder.buildJarForMainClreplacedAndExplicitClreplacedNamesAndBytecode(Main.clreplaced, Collections.emptyMap(), Blake2b.clreplaced);
byte[] arguments = null;
Transaction tx = AvmTransactionUtil.create(deployer, kernel.getNonce(deployer), BigInteger.ZERO, new CodeAndArguments(jar, arguments).encodeToBytes(), energyLimit, energyPrice);
TransactionResult txResult = avm.run(this.kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(txResult.transactionStatus.isSuccess());
dappAddress = new AionAddress(txResult.copyOfTransactionOutput().orElseThrow());
replacedertNotNull(dappAddress);
}
@After
public void tearDown() {
this.avm.shutdown();
}
@Test
public void testBlake2b() {
Blake2b mac = Blake2b.Mac.newInstance("key".getBytes());
byte[] hash = mac.digest("input".getBytes());
Transaction tx = AvmTransactionUtil.call(deployer, dappAddress, kernel.getNonce(deployer), BigInteger.ZERO, new byte[0], energyLimit, energyPrice);
TransactionResult txResult = avm.run(this.kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(txResult.transactionStatus.isSuccess());
replacedertArrayEquals(hash, txResult.copyOfTransactionOutput().orElseThrow());
}
}
19
Source : FunctionShadowTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
public clreplaced FunctionShadowTest {
private static final long ENERGY_LIMIT = 6_000_000L;
private static final long ERNGY_PRICE = 1L;
private static final AionAddress FROM = TestingState.PREMINED_ADDRESS;
private static TestingState kernel;
private static AvmImpl avm;
@BeforeClreplaced
public static void setup() {
TestingBlock block = new TestingBlock(new byte[32], 1, Helpers.randomAddress(), System.currentTimeMillis(), new byte[0]);
kernel = new TestingState(block);
AvmConfiguration config = new AvmConfiguration();
config.preserveDebuggability = true;
avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), config);
}
@AfterClreplaced
public static void tearDown() {
avm.shutdown();
}
@Test
public void testNonWhitelistFunction() {
Clreplaced<?> testClreplaced = FunctionShadowFailSupplierResource.clreplaced;
AionAddress dappAddr = deployTest(testClreplaced);
// We expect a deployment failure.
replacedert.replacedertNull(dappAddr);
}
@Test
public void testParameterFunction() {
Clreplaced<?> testClreplaced = FunctionShadowFailArgsResource.clreplaced;
AionAddress dappAddr = deployTest(testClreplaced);
// We expect a deployment failure.
replacedert.replacedertNull(dappAddr);
}
@Test
public void testSafeParameterFunction() {
Clreplaced<?> testClreplaced = FunctionShadowPreplacedArgsResource.clreplaced;
AionAddress dappAddr = deployTest(testClreplaced);
// This case should succeed.
replacedert.replacedertNotNull(dappAddr);
}
@Test
public void testNoComparableFunction() {
Clreplaced<?> testClreplaced = FunctionShadowFailComparableResource.clreplaced;
AionAddress dappAddr = deployTest(testClreplaced);
// We expect a deployment failure.
replacedert.replacedertNull(dappAddr);
}
@Test
public void testLambdaRunnable() {
// deploy it
Clreplaced<?> testClreplaced = FunctionShadowResource.clreplaced;
AionAddress dappAddr = deployTest(testClreplaced);
// call transactions and validate the results
oneCall(dappAddr, 0);
}
@Test
public void testLambdaFunction() {
// deploy it
Clreplaced<?> testClreplaced = FunctionShadowResource.clreplaced;
AionAddress dappAddr = deployTest(testClreplaced);
// call transactions and validate the results
oneCall(dappAddr, 1);
}
@Test
public void testSerializedLambdaRunnable() {
// deploy it
Clreplaced<?> testClreplaced = FunctionShadowResource.clreplaced;
AionAddress dappAddr = deployTest(testClreplaced);
// Call the setup routine (2)
oneCall(dappAddr, 2);
// Call the check routine (3)
oneCall(dappAddr, 3);
}
@Test
public void testSerializedLambdaFunction() {
// deploy it
Clreplaced<?> testClreplaced = FunctionShadowResource.clreplaced;
AionAddress dappAddr = deployTest(testClreplaced);
// Call the setup routine (4)
oneCall(dappAddr, 4);
// Call the check routine (5)
oneCall(dappAddr, 5);
}
@Test
public void testReferenceFunction() {
// deploy it
Clreplaced<?> testClreplaced = FunctionShadowResource.clreplaced;
AionAddress dappAddr = deployTest(testClreplaced);
// call transactions and validate the results
oneCall(dappAddr, 6);
}
@Test
public void testNonSharedLambdas() {
// deploy it
Clreplaced<?> testClreplaced = FunctionShadowResource.clreplaced;
AionAddress dappAddr = deployTest(testClreplaced);
// call transactions and validate the results
oneCall(dappAddr, 7);
}
@Test
public void testExceptionInLambdas() {
// deploy it
Clreplaced<?> testClreplaced = FunctionShadowResource.clreplaced;
AionAddress dappAddr = deployTest(testClreplaced);
// call transactions and validate the results
oneCall(dappAddr, 8);
}
private AionAddress deployTest(Clreplaced<?> testClreplaced) {
byte[] testJar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(testClreplaced);
byte[] txData = new CodeAndArguments(testJar, null).encodeToBytes();
Transaction tx = AvmTransactionUtil.create(FROM, kernel.getNonce(FROM), BigInteger.ZERO, txData, ENERGY_LIMIT, ERNGY_PRICE);
Optional<byte[]> optionalOutput = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult().copyOfTransactionOutput();
return (optionalOutput.isPresent()) ? new AionAddress(optionalOutput.get()) : null;
}
private void oneCall(AionAddress dappAddr, int transactionNumber) {
Transaction tx = AvmTransactionUtil.call(FROM, dappAddr, kernel.getNonce(FROM), BigInteger.ZERO, new byte[] { (byte) transactionNumber }, ENERGY_LIMIT, ERNGY_PRICE);
TransactionResult result = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
}
}
19
Source : FunctionShadowTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
@Test
public void testNoComparableFunction() {
Clreplaced<?> testClreplaced = FunctionShadowFailComparableResource.clreplaced;
AionAddress dappAddr = deployTest(testClreplaced);
// We expect a deployment failure.
replacedert.replacedertNull(dappAddr);
}
19
Source : FunctionShadowTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
@Test
public void testParameterFunction() {
Clreplaced<?> testClreplaced = FunctionShadowFailArgsResource.clreplaced;
AionAddress dappAddr = deployTest(testClreplaced);
// We expect a deployment failure.
replacedert.replacedertNull(dappAddr);
}
19
Source : FunctionShadowTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
@Test
public void testExceptionInLambdas() {
// deploy it
Clreplaced<?> testClreplaced = FunctionShadowResource.clreplaced;
AionAddress dappAddr = deployTest(testClreplaced);
// call transactions and validate the results
oneCall(dappAddr, 8);
}
19
Source : FunctionShadowTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
@Test
public void testNonSharedLambdas() {
// deploy it
Clreplaced<?> testClreplaced = FunctionShadowResource.clreplaced;
AionAddress dappAddr = deployTest(testClreplaced);
// call transactions and validate the results
oneCall(dappAddr, 7);
}
19
Source : FunctionShadowTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
@Test
public void testReferenceFunction() {
// deploy it
Clreplaced<?> testClreplaced = FunctionShadowResource.clreplaced;
AionAddress dappAddr = deployTest(testClreplaced);
// call transactions and validate the results
oneCall(dappAddr, 6);
}
19
Source : FunctionShadowTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
@Test
public void testNonWhitelistFunction() {
Clreplaced<?> testClreplaced = FunctionShadowFailSupplierResource.clreplaced;
AionAddress dappAddr = deployTest(testClreplaced);
// We expect a deployment failure.
replacedert.replacedertNull(dappAddr);
}
19
Source : FunctionShadowTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
@Test
public void testSerializedLambdaFunction() {
// deploy it
Clreplaced<?> testClreplaced = FunctionShadowResource.clreplaced;
AionAddress dappAddr = deployTest(testClreplaced);
// Call the setup routine (4)
oneCall(dappAddr, 4);
// Call the check routine (5)
oneCall(dappAddr, 5);
}
19
Source : FunctionShadowTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
@Test
public void testSafeParameterFunction() {
Clreplaced<?> testClreplaced = FunctionShadowPreplacedArgsResource.clreplaced;
AionAddress dappAddr = deployTest(testClreplaced);
// This case should succeed.
replacedert.replacedertNotNull(dappAddr);
}
19
Source : FunctionShadowTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
@Test
public void testLambdaRunnable() {
// deploy it
Clreplaced<?> testClreplaced = FunctionShadowResource.clreplaced;
AionAddress dappAddr = deployTest(testClreplaced);
// call transactions and validate the results
oneCall(dappAddr, 0);
}
19
Source : FunctionShadowTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
@Test
public void testSerializedLambdaRunnable() {
// deploy it
Clreplaced<?> testClreplaced = FunctionShadowResource.clreplaced;
AionAddress dappAddr = deployTest(testClreplaced);
// Call the setup routine (2)
oneCall(dappAddr, 2);
// Call the check routine (3)
oneCall(dappAddr, 3);
}
19
Source : FunctionShadowTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
@Test
public void testLambdaFunction() {
// deploy it
Clreplaced<?> testClreplaced = FunctionShadowResource.clreplaced;
AionAddress dappAddr = deployTest(testClreplaced);
// call transactions and validate the results
oneCall(dappAddr, 1);
}
19
Source : DefaultMethodIntegrationTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
/**
* Tests that we fail in a meaningful way when a DApp throws an exception due to a missing method.
*/
public clreplaced DefaultMethodIntegrationTest {
private static AionAddress deployer = TestingState.PREMINED_ADDRESS;
private static TestingState kernel;
private static AvmImpl avm;
@BeforeClreplaced
public static void setup() {
TestingBlock block = new TestingBlock(new byte[32], 1, Helpers.randomAddress(), System.currentTimeMillis(), new byte[0]);
kernel = new TestingState(block);
avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
}
@AfterClreplaced
public static void tearDown() {
avm.shutdown();
}
@Test
public void testMissingDefaultInClinit() throws Exception {
byte[] jar = JarBuilder.buildJarForMainClreplacedAndExplicitClreplacedNamesAndBytecode(TestDefaultMethodInClinitResource.clreplaced, Collections.emptyMap(), AionMap.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
// Deploy.
long energyLimit = 2_000_000l;
long energyPrice = 1l;
Transaction create = AvmTransactionUtil.create(deployer, kernel.getNonce(deployer), BigInteger.ZERO, txData, energyLimit, energyPrice);
// The NoSuchMethodError triggers a "FAILED_EXCEPTION" state.
TransactionResult result = avm.run(kernel, new Transaction[] { create }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertEquals(AvmInternalError.FAILED_EXCEPTION.error, result.transactionStatus.causeOfError);
}
@Test
public void testMissingDefaultInMain() throws Exception {
byte[] jar = JarBuilder.buildJarForMainClreplacedAndExplicitClreplacedNamesAndBytecode(TestDefaultMethodInMainResource.clreplaced, Collections.emptyMap(), AionMap.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
// Deploy.
long energyLimit = 2_000_000l;
long energyPrice = 1l;
Transaction create = AvmTransactionUtil.create(deployer, kernel.getNonce(deployer), BigInteger.ZERO, txData, energyLimit, energyPrice);
TransactionResult createResult = avm.run(kernel, new Transaction[] { create }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(createResult.transactionStatus.isSuccess());
AionAddress contractAddr = new AionAddress(createResult.copyOfTransactionOutput().orElseThrow());
// Setup the call (parameters are currently ignored).
byte[] argData = new byte[0];
Transaction call = AvmTransactionUtil.call(deployer, contractAddr, kernel.getNonce(deployer), BigInteger.ZERO, argData, energyLimit, 1l);
// The NoSuchMethodError triggers a "FAILED_EXCEPTION" state.
TransactionResult result = avm.run(kernel, new Transaction[] { call }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertEquals(AvmInternalError.FAILED_EXCEPTION.error, result.transactionStatus.causeOfError);
}
}
19
Source : ResultTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
private static byte[] encodeForTransfer(AionAddress target, byte[] data) {
return new ABIStreamingEncoder().encodeOneString("testTransfer").encodeOneAddress(new Address(target.toByteArray())).encodeOneByteArray(data).toBytes();
}
19
Source : ResultTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
private static byte[] encodeForCall(AionAddress target, byte[] data, boolean expectToPreplaced) {
return new ABIStreamingEncoder().encodeOneString("testCall").encodeOneAddress(new Address(target.toByteArray())).encodeOneByteArray(data).encodeOneBoolean(expectToPreplaced).toBytes();
}
19
Source : RejectVirtualMachineErrorIntegrationTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
/**
* Implemented as part of issue-303 to demonstrate that user code is not able to catch, throw, sub-clreplaced, or even instantiate any
* java.lang.VirtualMachineError type.
* Since the rejection will be made at the clreplaced level, we need several test clreplacedes.
*
* We need to run these as integration tests since, although many are just testing the rejection phase, some have runtime considerations
* since Throwable can be caught, but none of the VirtualMachineError instances should actually appear there.
*/
public clreplaced RejectVirtualMachineErrorIntegrationTest {
private static AionAddress FROM = TestingState.PREMINED_ADDRESS;
private static long ENERGY_LIMIT = 5_000_000L;
private static long ENERGY_PRICE = 1L;
private static IExternalState externalState;
private static AvmImpl avm;
@BeforeClreplaced
public static void setup() {
TestingBlock BLOCK = new TestingBlock(new byte[32], 1, Helpers.randomAddress(), System.currentTimeMillis(), new byte[0]);
externalState = new TestingState(BLOCK);
avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
}
@AfterClreplaced
public static void tearDown() {
avm.shutdown();
}
@Test
public void rejectCatchError() throws Exception {
byte[] jar = JarBuilder.buildJarForMainClreplacedAndExplicitClreplacedNamesAndBytecode(RejectCatchError.clreplaced, Collections.emptyMap());
// Deploy.
TransactionResult createResult = deployJar(jar);
replacedert.replacedertEquals(AvmInternalError.FAILED_REJECTED_CLreplaced.error, createResult.transactionStatus.causeOfError);
}
@Test
public void rejectInstantiateError() throws Exception {
byte[] jar = JarBuilder.buildJarForMainClreplacedAndExplicitClreplacedNamesAndBytecode(RejectInstantiateError.clreplaced, Collections.emptyMap());
// Deploy.
TransactionResult createResult = deployJar(jar);
replacedert.replacedertEquals(AvmInternalError.FAILED_REJECTED_CLreplaced.error, createResult.transactionStatus.causeOfError);
}
@Test
public void rejectSubclreplacedError() throws Exception {
byte[] jar = JarBuilder.buildJarForMainClreplacedAndExplicitClreplacedNamesAndBytecode(RejectSubclreplacedError.clreplaced, Collections.emptyMap());
// Deploy.
TransactionResult createResult = deployJar(jar);
replacedert.replacedertEquals(AvmInternalError.FAILED_REJECTED_CLreplaced.error, createResult.transactionStatus.causeOfError);
}
private TransactionResult deployJar(byte[] jar) {
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
Transaction transaction = AvmTransactionUtil.create(FROM, externalState.getNonce(FROM), BigInteger.ZERO, txData, ENERGY_LIMIT, ENERGY_PRICE);
return avm.run(RejectVirtualMachineErrorIntegrationTest.externalState, new Transaction[] { transaction }, ExecutionType.replacedUME_MAINCHAIN, externalState.getBlockNumber() - 1)[0].getResult();
}
}
19
Source : ClassShapeRuleTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
public clreplaced ClreplacedShapeRuleTest {
private static AionAddress DEPLOYER = TestingState.PREMINED_ADDRESS;
private static TestingBlock BLOCK = new TestingBlock(new byte[32], 1, Helpers.randomAddress(), System.currentTimeMillis(), new byte[0]);
@Test
public void testLimitNoop() throws Exception {
String clreplacedName = "ClreplacedName";
byte[] clreplacedBytes = createNoopClreplaced(clreplacedName, ConsensusLimitConstants.MAX_METHOD_BYTE_LENGTH);
boolean didDeploy = deployOnAvm(clreplacedName, clreplacedBytes);
replacedert.replacedertTrue(didDeploy);
}
@Test
public void testLongNoop() throws Exception {
String clreplacedName = "ClreplacedName";
byte[] clreplacedBytes = createNoopClreplaced(clreplacedName, ConsensusLimitConstants.MAX_METHOD_BYTE_LENGTH + 1);
boolean didDeploy = deployOnAvm(clreplacedName, clreplacedBytes);
replacedert.replacedertFalse(didDeploy);
}
@Test
public void testLimitCatch() throws Exception {
String clreplacedName = "ClreplacedName";
byte[] clreplacedBytes = createLongThrowClreplaced(clreplacedName, ConsensusLimitConstants.MAX_EXCEPTION_TABLE_ENTRIES);
boolean didDeploy = deployOnAvm(clreplacedName, clreplacedBytes);
replacedert.replacedertTrue(didDeploy);
}
@Test
public void testDeepCatch() throws Exception {
String clreplacedName = "ClreplacedName";
byte[] clreplacedBytes = createLongThrowClreplaced(clreplacedName, ConsensusLimitConstants.MAX_EXCEPTION_TABLE_ENTRIES + 1);
boolean didDeploy = deployOnAvm(clreplacedName, clreplacedBytes);
replacedert.replacedertFalse(didDeploy);
}
@Test
public void testLimitIntPush() throws Exception {
String clreplacedName = "ClreplacedName";
byte[] clreplacedBytes = createDeepPushClreplaced(clreplacedName, ConsensusLimitConstants.MAX_OPERAND_STACK_DEPTH, false);
boolean didDeploy = deployOnAvm(clreplacedName, clreplacedBytes);
replacedert.replacedertTrue(didDeploy);
}
@Test
public void testDeepIntPush() throws Exception {
String clreplacedName = "ClreplacedName";
byte[] clreplacedBytes = createDeepPushClreplaced(clreplacedName, ConsensusLimitConstants.MAX_OPERAND_STACK_DEPTH + 1, false);
boolean didDeploy = deployOnAvm(clreplacedName, clreplacedBytes);
replacedert.replacedertFalse(didDeploy);
}
@Test
public void testLimitLongPush() throws Exception {
String clreplacedName = "ClreplacedName";
byte[] clreplacedBytes = createDeepPushClreplaced(clreplacedName, ceilingDivideByTwo(ConsensusLimitConstants.MAX_OPERAND_STACK_DEPTH), true);
boolean didDeploy = deployOnAvm(clreplacedName, clreplacedBytes);
replacedert.replacedertTrue(didDeploy);
}
@Test
public void testDeepLongPush() throws Exception {
String clreplacedName = "ClreplacedName";
byte[] clreplacedBytes = createDeepPushClreplaced(clreplacedName, ceilingDivideByTwo(ConsensusLimitConstants.MAX_OPERAND_STACK_DEPTH) + 1, true);
boolean didDeploy = deployOnAvm(clreplacedName, clreplacedBytes);
replacedert.replacedertFalse(didDeploy);
}
@Test
public void testLimitIntVars() throws Exception {
String clreplacedName = "ClreplacedName";
byte[] clreplacedBytes = createVarHeavyClreplaced(clreplacedName, ConsensusLimitConstants.MAX_LOCAL_VARIABLES, false);
boolean didDeploy = deployOnAvm(clreplacedName, clreplacedBytes);
replacedert.replacedertTrue(didDeploy);
}
@Test
public void testFailIntVars() throws Exception {
String clreplacedName = "ClreplacedName";
byte[] clreplacedBytes = createVarHeavyClreplaced(clreplacedName, ConsensusLimitConstants.MAX_LOCAL_VARIABLES + 1, false);
boolean didDeploy = deployOnAvm(clreplacedName, clreplacedBytes);
replacedert.replacedertFalse(didDeploy);
}
@Test
public void testLimitLongVars() throws Exception {
String clreplacedName = "ClreplacedName";
byte[] clreplacedBytes = createVarHeavyClreplaced(clreplacedName, ConsensusLimitConstants.MAX_LOCAL_VARIABLES - 1, true);
boolean didDeploy = deployOnAvm(clreplacedName, clreplacedBytes);
replacedert.replacedertTrue(didDeploy);
}
@Test
public void testFailLongVars() throws Exception {
String clreplacedName = "ClreplacedName";
byte[] clreplacedBytes = createVarHeavyClreplaced(clreplacedName, ConsensusLimitConstants.MAX_LOCAL_VARIABLES, true);
boolean didDeploy = deployOnAvm(clreplacedName, clreplacedBytes);
replacedert.replacedertFalse(didDeploy);
}
@Test
public void testLimitMethodCount() throws Exception {
String clreplacedName = "ClreplacedName";
byte[] clreplacedBytes = createMethodHeavyClreplaced(clreplacedName, ConsensusLimitConstants.MAX_METHOD_COUNT);
boolean didDeploy = deployOnAvm(clreplacedName, clreplacedBytes);
replacedert.replacedertTrue(didDeploy);
}
@Test
public void testFailMethodCount() throws Exception {
String clreplacedName = "ClreplacedName";
byte[] clreplacedBytes = createMethodHeavyClreplaced(clreplacedName, ConsensusLimitConstants.MAX_METHOD_COUNT + 1);
boolean didDeploy = deployOnAvm(clreplacedName, clreplacedBytes);
replacedert.replacedertFalse(didDeploy);
}
@Test
public void testLimitConstantPoolEntries() throws Exception {
String clreplacedName = "ClreplacedName";
byte[] clreplacedBytes = createConstantHeavyClreplaced(clreplacedName, ConsensusLimitConstants.MAX_CONSTANT_POOL_ENTRIES);
boolean didDeploy = deployOnAvm(clreplacedName, clreplacedBytes);
replacedert.replacedertTrue(didDeploy);
}
@Test
public void testFailConstantPoolEntries() throws Exception {
String clreplacedName = "ClreplacedName";
byte[] clreplacedBytes = createConstantHeavyClreplaced(clreplacedName, ConsensusLimitConstants.MAX_CONSTANT_POOL_ENTRIES + 1);
boolean didDeploy = deployOnAvm(clreplacedName, clreplacedBytes);
replacedert.replacedertFalse(didDeploy);
}
private static byte[] createNoopClreplaced(String clreplacedName, int instructionCount) {
ClreplacedWriter writer = new ClreplacedWriter(ClreplacedWriter.COMPUTE_FRAMES | ClreplacedWriter.COMPUTE_MAXS);
writer.visit(Opcodes.V10, Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER, clreplacedName, null, "java/lang/Object", new String[0]);
MethodVisitor method = writer.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "main", "()[B", null, null);
for (int i = 0; i < (instructionCount - 2); ++i) {
method.visitInsn(Opcodes.NOP);
}
method.visitInsn(Opcodes.ACONST_NULL);
method.visitInsn(Opcodes.ARETURN);
method.visitMaxs(0, 0);
method.visitEnd();
writer.visitEnd();
return writer.toByteArray();
}
private static byte[] createLongThrowClreplaced(String clreplacedName, int catchDepth) {
// Note that the way this test writes the method, catchDepth MUST be at least 1.
replacedert.replacedertTrue(catchDepth >= 1);
ClreplacedWriter writer = new ClreplacedWriter(ClreplacedWriter.COMPUTE_FRAMES | ClreplacedWriter.COMPUTE_MAXS);
writer.visit(Opcodes.V10, Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER, clreplacedName, null, "java/lang/Object", new String[0]);
// To test on filesystem, use "([Ljava/lang/String;)V".
MethodVisitor method = writer.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "main", "()[B", null, null);
Label start = new Label();
Label end = new Label();
Label handler = new Label();
method.visitTryCatchBlock(start, end, handler, "java/lang/NullPointerException");
method.visitLabel(start);
method.visitInsn(Opcodes.ACONST_NULL);
method.visitTypeInsn(Opcodes.CHECKCAST, "[Ljava/lang/Object;");
method.visitInsn(Opcodes.ARRAYLENGTH);
method.visitInsn(Opcodes.ACONST_NULL);
method.visitInsn(Opcodes.ARETURN);
method.visitLabel(end);
for (int i = 0; i < (catchDepth - 1); ++i) {
method.visitLabel(handler);
start = new Label();
end = new Label();
handler = new Label();
method.visitTryCatchBlock(start, end, handler, "java/lang/NullPointerException");
method.visitLabel(start);
method.visitInsn(Opcodes.ATHROW);
method.visitLabel(end);
}
method.visitLabel(handler);
method.visitInsn(Opcodes.ACONST_NULL);
method.visitInsn(Opcodes.ARETURN);
method.visitMaxs(0, 0);
method.visitEnd();
writer.visitEnd();
return writer.toByteArray();
}
private static byte[] createDeepPushClreplaced(String clreplacedName, int pushCount, boolean isLong) {
// Note that the setup for the method requires at least 2 stack depth.
replacedert.replacedertTrue(pushCount >= 2);
ClreplacedWriter writer = new ClreplacedWriter(ClreplacedWriter.COMPUTE_FRAMES | ClreplacedWriter.COMPUTE_MAXS);
writer.visit(Opcodes.V10, Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER, clreplacedName, null, "java/lang/Object", new String[0]);
MethodVisitor method = writer.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "main", "()[B", null, null);
Object oneLong = Long.valueOf(1L);
Object oneInt = Integer.valueOf(1);
Object value = isLong ? oneLong : oneInt;
// visitLdcInsn uses a type check so make sure that we got the type we were expecting (some compilers try to get clever here).
if (isLong) {
replacedert.replacedertTrue(value instanceof Long);
} else {
replacedert.replacedertTrue(value instanceof Integer);
}
method.visitLdcInsn(value);
int storeOpcode = isLong ? Opcodes.LSTORE : Opcodes.ISTORE;
method.visitVarInsn(storeOpcode, 0);
int loadOpcode = isLong ? Opcodes.LLOAD : Opcodes.ILOAD;
// Reduce the push count by 1 since we have at least one more slot for the return value.
for (int i = 0; i < (pushCount - 1); ++i) {
method.visitVarInsn(loadOpcode, 0);
}
method.visitInsn(Opcodes.ACONST_NULL);
method.visitInsn(Opcodes.ARETURN);
method.visitMaxs(0, 0);
method.visitEnd();
writer.visitEnd();
return writer.toByteArray();
}
private static byte[] createVarHeavyClreplaced(String clreplacedName, int varCount, boolean isLong) {
ClreplacedWriter writer = new ClreplacedWriter(ClreplacedWriter.COMPUTE_FRAMES | ClreplacedWriter.COMPUTE_MAXS);
writer.visit(Opcodes.V10, Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER, clreplacedName, null, "java/lang/Object", new String[0]);
MethodVisitor method = writer.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "main", "()[B", null, null);
Object oneLong = Long.valueOf(1L);
Object oneInt = Integer.valueOf(1);
Object value = isLong ? oneLong : oneInt;
int storeOpcode = isLong ? Opcodes.LSTORE : Opcodes.ISTORE;
// visitLdcInsn uses a type check so make sure that we got the type we were expecting (some compilers try to get clever here).
if (isLong) {
replacedert.replacedertTrue(value instanceof Long);
} else {
replacedert.replacedertTrue(value instanceof Integer);
}
// Note that we will actually invalidate the local variable n-1 when writing a long, but this is just to verify that it reserves the next slot.
for (int i = 0; i < varCount; ++i) {
method.visitLdcInsn(value);
method.visitVarInsn(storeOpcode, i);
}
method.visitInsn(Opcodes.ACONST_NULL);
method.visitInsn(Opcodes.ARETURN);
method.visitMaxs(0, 0);
method.visitEnd();
writer.visitEnd();
return writer.toByteArray();
}
private static byte[] createMethodHeavyClreplaced(String clreplacedName, int methodCount) {
// Note that the clreplaced will have the main so we need at least one method.
replacedert.replacedertTrue(methodCount >= 1);
String methodPrefix = "method_";
String methodDescriptor = "()V";
ClreplacedWriter writer = new ClreplacedWriter(ClreplacedWriter.COMPUTE_FRAMES | ClreplacedWriter.COMPUTE_MAXS);
writer.visit(Opcodes.V10, Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER, clreplacedName, null, "java/lang/Object", new String[0]);
MethodVisitor method = writer.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "main", "()[B", null, null);
for (int i = 0; i < (methodCount - 1); ++i) {
String methodName = methodPrefix + i;
method.visitMethodInsn(Opcodes.INVOKESTATIC, clreplacedName, methodName, methodDescriptor, false);
}
method.visitInsn(Opcodes.ACONST_NULL);
method.visitInsn(Opcodes.ARETURN);
method.visitMaxs(0, 0);
method.visitEnd();
for (int i = 0; i < (methodCount - 1); ++i) {
String methodName = methodPrefix + i;
MethodVisitor targetMethod = writer.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, methodName, methodDescriptor, null, null);
targetMethod.visitInsn(Opcodes.RETURN);
targetMethod.visitMaxs(0, 0);
targetMethod.visitEnd();
}
writer.visitEnd();
return writer.toByteArray();
}
private static byte[] createConstantHeavyClreplaced(String clreplacedName, int constantCount) {
ClreplacedWriter writer = new ClreplacedWriter(ClreplacedWriter.COMPUTE_FRAMES | ClreplacedWriter.COMPUTE_MAXS);
writer.visit(Opcodes.V10, Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER, clreplacedName, null, "java/lang/Object", new String[0]);
MethodVisitor method = writer.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "main", "()[B", null, null);
// Note that we don't want to hit the method size limit so restrict this to 1000 constants per method.
int constantsPerMethod = 1000;
int methodCount = (constantCount + constantsPerMethod - 1) / constantsPerMethod;
String methodPrefix = "method_";
String methodDescriptor = "()V";
// Note that the clreplaced will have constants for names, etc, so make sure we at least specify enough for that.
// Specifically, there are 8 constants plus 3 per method generated.
int baseConstantsAdded = 8 + (methodCount * 3);
replacedert.replacedertTrue(constantCount >= baseConstantsAdded);
int constantsToLoad = constantCount - baseConstantsAdded;
for (int i = 0; i < methodCount; ++i) {
String methodName = methodPrefix + i;
method.visitMethodInsn(Opcodes.INVOKESTATIC, clreplacedName, methodName, methodDescriptor, false);
}
method.visitInsn(Opcodes.ACONST_NULL);
method.visitInsn(Opcodes.ARETURN);
method.visitMaxs(0, 0);
method.visitEnd();
int constantsCreated = 0;
for (int i = 0; i < methodCount; ++i) {
String methodName = methodPrefix + i;
MethodVisitor targetMethod = writer.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, methodName, methodDescriptor, null, null);
int constantsInMethod = Math.min((constantsToLoad - constantsCreated), constantsPerMethod);
for (int j = 0; j < constantsInMethod; ++j) {
targetMethod.visitLdcInsn(Integer.valueOf(constantsCreated + j));
targetMethod.visitInsn(Opcodes.POP);
}
constantsCreated += constantsInMethod;
targetMethod.visitInsn(Opcodes.RETURN);
targetMethod.visitMaxs(0, 0);
targetMethod.visitEnd();
}
writer.visitEnd();
return writer.toByteArray();
}
private boolean deployOnAvm(String clreplacedName, byte[] clreplacedBytes) {
byte[] jar = JarBuilder.buildJarForExplicitClreplacedNamesAndBytecode(clreplacedName, clreplacedBytes, Collections.emptyMap());
byte[] deployment = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(BLOCK);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
long energyLimit = 5_000_000l;
long energyPrice = 1l;
Transaction deploymentTransaction = AvmTransactionUtil.create(DEPLOYER, kernel.getNonce(DEPLOYER), BigInteger.ZERO, deployment, energyLimit, energyPrice);
TransactionResult deploymentResult = avm.run(kernel, new Transaction[] { deploymentTransaction }, ExecutionType.replacedUME_MAINCHAIN, 0)[0].getResult();
boolean didDeploy = deploymentResult.transactionStatus.isSuccess();
// If the deployment was a success, we also want to send a basic call which should always succeed.
if (didDeploy) {
AionAddress contractAddress = new AionAddress(deploymentResult.copyOfTransactionOutput().orElseThrow());
Transaction callTransaction = AvmTransactionUtil.call(DEPLOYER, contractAddress, kernel.getNonce(DEPLOYER), BigInteger.ZERO, new byte[0], energyLimit, energyPrice);
TransactionResult result = avm.run(kernel, new Transaction[] { callTransaction }, ExecutionType.replacedUME_MAINCHAIN, 0)[0].getResult();
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
}
// Now, shut down and return whether or not the deployment was a success.
avm.shutdown();
return didDeploy;
}
private int ceilingDivideByTwo(int value) {
return (value + 1) / 2;
}
}
19
Source : PocWalletTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
/**
* Our current thinking is that we will use a JUnit launcher for the proof-of-concept demonstration. This is that entry-point.
* See issue-124 for more of the background.
*/
public clreplaced PocWalletTest {
// For now, we will just reuse the from, to, and block for each call (in the future, this will change).
private static AionAddress from = TestingState.PREMINED_ADDRESS;
private static long energyLimit = 10_000_000_000L;
private static long energyPrice = 1;
private static IExternalState externalState;
private static AvmImpl avm;
private static IExternalCapabilities externalCapabilities;
@BeforeClreplaced
public static void setup() {
TestingBlock block = new TestingBlock(new byte[32], 1, Helpers.randomAddress(), System.currentTimeMillis(), new byte[0]);
externalState = new TestingState(block);
externalCapabilities = new EmptyCapabilities() {
@Override
public byte[] blake2b(byte[] data) {
// NOTE: This test relies on calling blake2b but doesn't rely on the answer being correct so just return the input.
return data;
}
};
avm = CommonAvmFactory.buildAvmInstanceForConfiguration(externalCapabilities, new AvmConfiguration());
}
@AfterClreplaced
public static void tearDown() {
avm.shutdown();
}
private byte[] buildTestWalletJar() {
return UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(Wallet.clreplaced, Multiowned.clreplaced, ByteArrayWrapper.clreplaced, Operation.clreplaced, ByteArrayHelpers.clreplaced, BytesKey.clreplaced, RequireFailedException.clreplaced, Daylimit.clreplaced, EventLogger.clreplaced);
}
/**
* Tests that a deploy call will store the code for the Wallet JAR.
* This means that it transformed it correctly and nothing was missing.
*/
@Test
public void testDeployWritesCode() {
byte[] testWalletJar = buildTestWalletJar();
byte[] testWalletArguments = new byte[0];
Transaction createTransaction = AvmTransactionUtil.create(from, externalState.getNonce(from), BigInteger.ZERO, new CodeAndArguments(testWalletJar, testWalletArguments).encodeToBytes(), energyLimit, energyPrice);
TransactionResult createResult = avm.run(externalState, new Transaction[] { createTransaction }, ExecutionType.replacedUME_MAINCHAIN, externalState.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(createResult.transactionStatus.isSuccess());
replacedert.replacedertNotNull(externalState.getTransformedCode(new AionAddress(createResult.copyOfTransactionOutput().orElseThrow())));
}
/**
* Tests that we can run init on the deployed code, albeit as a second transaction (since we haven't yet decided how to invoke init on deploy).
*/
@Test
public void testDeployAndCallInit() throws Exception {
// Constructor args.
AionAddress extra1 = Helpers.randomAddress();
AionAddress extra2 = Helpers.randomAddress();
int requiredVotes = 2;
long dailyLimit = 5000;
byte[] testWalletJar = buildTestWalletJar();
byte[] testWalletArguments = new byte[0];
Transaction createTransaction = AvmTransactionUtil.create(from, externalState.getNonce(from), BigInteger.ZERO, new CodeAndArguments(testWalletJar, testWalletArguments).encodeToBytes(), energyLimit, energyPrice);
TransactionResult createResult = avm.run(externalState, new Transaction[] { createTransaction }, ExecutionType.replacedUME_MAINCHAIN, externalState.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(createResult.transactionStatus.isSuccess());
// contract address is stored in return data
AionAddress contractAddress = new AionAddress(createResult.copyOfTransactionOutput().orElseThrow());
byte[] initArgs = CallEncoder.init(new Address(extra1.toByteArray()), new Address(extra2.toByteArray()), requiredVotes, dailyLimit);
Transaction initTransaction = AvmTransactionUtil.call(from, contractAddress, externalState.getNonce(from), BigInteger.ZERO, initArgs, energyLimit, energyPrice);
TransactionResult initResult = avm.run(externalState, new Transaction[] { initTransaction }, ExecutionType.replacedUME_MAINCHAIN, externalState.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(initResult.transactionStatus.isSuccess());
}
/**
* Tests that inner clreplacedes work properly within the serialization system (since their constructors need to be marked accessible).
*/
@Test
public void testExecuteWithInnerClreplacedes() throws Exception {
// Constructor args.
AionAddress extra1 = Helpers.randomAddress();
AionAddress extra2 = Helpers.randomAddress();
int requiredVotes = 2;
long dailyLimit = 5000;
// Deploy.
AionAddress contractAddress = new AionAddress(deployTestWallet());
// Run the init.
runInit(contractAddress, new Address(extra1.toByteArray()), new Address(extra2.toByteArray()), requiredVotes, dailyLimit);
// Call "execute" with something above the daily limit so we will create the "Transaction" inner clreplaced instance.
AionAddress to = Helpers.randomAddress();
byte[] data = Helpers.randomBytes(AionAddress.LENGTH);
byte[] execArgs = CallEncoder.execute(new Address(to.toByteArray()), dailyLimit + 1, data);
Transaction executeTransaction = AvmTransactionUtil.call(from, contractAddress, externalState.getNonce(from), BigInteger.ZERO, execArgs, energyLimit, energyPrice);
TransactionResult executeResult = avm.run(externalState, new Transaction[] { executeTransaction }, ExecutionType.replacedUME_MAINCHAIN, externalState.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(executeResult.transactionStatus.isSuccess());
byte[] toConfirm = new ABIDecoder(executeResult.copyOfTransactionOutput().orElseThrow()).decodeOneByteArray();
// Now, confirm as one of the other owners to observe we can instantiate the Transaction instance, from storage.
externalState.adjustBalance(extra1, BigInteger.valueOf(1_000_000_000_000L));
byte[] confirmArgs = CallEncoder.confirm(toConfirm);
Transaction confirmTransaction = AvmTransactionUtil.call(extra1, contractAddress, externalState.getNonce(extra1), BigInteger.ZERO, confirmArgs, energyLimit, energyPrice);
TransactionResult confirmResult = avm.run(externalState, new Transaction[] { confirmTransaction }, ExecutionType.replacedUME_MAINCHAIN, externalState.getBlockNumber() - 1)[0].getResult();
// transfer to non-existing accounts
replacedert.replacedertTrue(confirmResult.transactionStatus.isSuccess());
}
private void runInit(AionAddress contractAddress, Address extra1, Address extra2, int requiredVotes, long dailyLimit) throws Exception {
byte[] initArgs = CallEncoder.init(extra1, extra2, requiredVotes, dailyLimit);
Transaction initTransaction = AvmTransactionUtil.call(from, contractAddress, externalState.getNonce(from), BigInteger.ZERO, initArgs, energyLimit, energyPrice);
TransactionResult initResult = avm.run(externalState, new Transaction[] { initTransaction }, ExecutionType.replacedUME_MAINCHAIN, externalState.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(initResult.transactionStatus.isSuccess());
}
private byte[] deployTestWallet() {
byte[] testWalletJar = buildTestWalletJar();
byte[] testWalletArguments = new byte[0];
Transaction createTransaction = AvmTransactionUtil.create(from, externalState.getNonce(from), BigInteger.ZERO, new CodeAndArguments(testWalletJar, testWalletArguments).encodeToBytes(), energyLimit, energyPrice);
TransactionResult createResult = avm.run(externalState, new Transaction[] { createTransaction }, ExecutionType.replacedUME_MAINCHAIN, externalState.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(createResult.transactionStatus.isSuccess());
// contract address is stored in return data
byte[] contractAddress = createResult.copyOfTransactionOutput().orElseThrow();
return contractAddress;
}
}
19
Source : TransformedCodeCacheTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
public clreplaced TransformedCodeCacheTest {
private static AionAddress deployer = TestingState.PREMINED_ADDRESS;
private static TestingBlock block;
private static AvmImpl avm;
@Before
public void setupClreplaced() {
block = new TestingBlock(new byte[32], 1, Helpers.randomAddress(), System.currentTimeMillis(), new byte[0]);
avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
}
@After
public void tearDown() {
avm.shutdown();
}
@Test
public void notWriteToCacheAfterSuccessfulTransactionTest() {
TestingState kernel = new TestingState(block);
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
AionAddress dappAddress = deploy(deployer, kernel, txData);
kernel.generateBlock();
// remove the transformed code. This means the avm version has changed.
// transformed code cache is empty.
kernel.setTransformedCode(dappAddress, null);
// this transaction will force a re-transformation operation to be done
TransactionResult result = callDappNoArgument(kernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, 500_000);
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
// transformed code should be written to the database
replacedert.replacedertNotNull(kernel.getTransformedCode(dappAddress));
kernel.generateBlock();
// validate in a successful transaction cache is not updated
// This should force the re-transformation step to be done again since the cache is empty. Code is set to byte[0] to make re-transformation to fail.
kernel.putCode(dappAddress, new byte[0]);
kernel.setTransformedCode(dappAddress, null);
// since it's not reading from the cache the result of the operation is failed
result = callDappNoArgument(kernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, 500_000);
replacedert.replacedertTrue(result.transactionStatus.isFailed());
replacedert.replacedertEquals("Failed: re-transformation failure", result.transactionStatus.causeOfError);
}
@Test
public void writeToCacheAfterFailedTransactionTest() {
TestingState kernel = new TestingState(block);
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
AionAddress dappAddress = deploy(deployer, kernel, txData);
kernel.generateBlock();
// remove the transformed code. This means the avm version has changed.
// transformed code cache is empty.
kernel.setTransformedCode(dappAddress, null);
// this transaction will run out of energy. It should write back the transformed code to cache
TransactionResult result = callDappNoArgument(kernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, 25_000);
replacedert.replacedertTrue(result.transactionStatus.isFailed());
replacedert.replacedertEquals("Failed: out of energy", result.transactionStatus.causeOfError);
replacedert.replacedertNull(kernel.getTransformedCode(dappAddress));
// this should read from the cache. Code is set to byte[0] to make sure re-transformation step is not performed
kernel.putCode(dappAddress, new byte[0]);
kernel.generateBlock();
// since it's reading from the cache the result of the operation is success
result = callDappNoArgument(kernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, 2_000_000);
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
// since the transaction is successful, the transformed code should not be written back to the cache
kernel.putCode(dappAddress, new byte[0]);
kernel.setTransformedCode(dappAddress, null);
// since it's not reading from the cache the result of the operation is failed
result = callDappNoArgument(kernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, 500_000);
replacedert.replacedertTrue(result.transactionStatus.isFailed());
replacedert.replacedertEquals("Failed: re-transformation failure", result.transactionStatus.causeOfError);
}
@Test
public void reorganizationTest() {
TestingState kernel = new TestingState(block);
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
AionAddress dappAddress = deploy(deployer, kernel, txData);
// remove the transformed code. This means the avm version has changed.
// transformed code cache is empty.
kernel.setTransformedCode(dappAddress, null);
// this transaction will run out of energy. It should write back the transformed code to cache
TransactionResult result = callDappNoArgument(kernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, 25_000);
replacedert.replacedertTrue(result.transactionStatus.isFailed());
replacedert.replacedertEquals("Failed: out of energy", result.transactionStatus.causeOfError);
replacedert.replacedertNull(kernel.getTransformedCode(dappAddress));
// If the chain the reorganizes and the transformed code for Avm1 is present, that should be used
kernel.setTransformedCode(dappAddress, new byte[0]);
// byte[0] as the transformed code will return null as a dApp, thus no code is executed
result = callDappNoArgument(kernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, 2_000_000);
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
replacedert.replacedertFalse(result.copyOfTransactionOutput().isPresent());
}
@Test
public void internalTransactionTest() {
TestingState kernel = new TestingState(block);
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
AionAddress dappAddress1 = deploy(deployer, kernel, txData);
AionAddress dappAddress2 = deploy(deployer, kernel, txData);
// remove the transformed code. This means the avm version has changed.
// transformed code cache is empty.
kernel.setTransformedCode(dappAddress1, null);
kernel.setTransformedCode(dappAddress2, null);
// this transaction will run out of energy. It should write back the transformed code to cache
TransactionResult result = callDappNoArgument(kernel, deployer, dappAddress2, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, 25_000);
replacedert.replacedertTrue(result.transactionStatus.isFailed());
replacedert.replacedertNull(kernel.getTransformedCode(dappAddress2));
// this ensures that only the cache is read and re-transformation is not done
kernel.putCode(dappAddress2, new byte[0]);
byte[] data = new ABIStreamingEncoder().encodeOneString("revert").toBytes();
byte[] encodedData = new ABIStreamingEncoder().encodeOneString("makeCall").encodeOneAddress(new Address(dappAddress2.toByteArray())).encodeOneByteArray(data).toBytes();
result = callDappArguments(kernel, deployer, dappAddress1, encodedData);
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
replacedert.replacedertNull(kernel.getTransformedCode(dappAddress2));
}
@Test
public void selfDestructTest() {
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
AionAddress dappAddress = deploy(deployer, kernel, txData);
kernel.generateBlock();
kernel.setTransformedCode(dappAddress, null);
// transformed code is added to the cache
callDappNoArgument(kernel, deployer, dappAddress, "selfDestruct", ExecutionType.replacedUME_MAINCHAIN, 2_000_000);
replacedert.replacedertNull(kernel.getTransformedCode(dappAddress));
replacedert.replacedertNull(kernel.getCode(dappAddress));
kernel.generateBlock();
TransactionResult result = callDappNoArgument(kernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, 2_000_000);
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
replacedert.replacedertFalse(result.copyOfTransactionOutput().isPresent());
}
@Test
public void notWriteToCacheAfterEthCallTest() {
TestingState kernel = new TestingState(block);
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
AionAddress dappAddress = deploy(deployer, kernel, txData);
kernel.generateBlock();
// remove the transformed code. This means the avm version has changed.
// transformed code cache is empty.
kernel.setTransformedCode(dappAddress, null);
// this transaction will force a re-transformation operation to be done
TransactionResult result = callDappNoArgument(kernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.ETH_CALL, 500_000);
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
kernel.generateBlock();
// validate in a successful transaction cache is not updated
// This should force the re-transformation step to be done again since the cache is empty. Code is set to byte[0] to make re-transformation to fail.
kernel.putCode(dappAddress, new byte[0]);
kernel.setTransformedCode(dappAddress, null);
// since it's not reading from the cache the result of the operation is failed
result = callDappNoArgument(kernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, 500_000);
replacedert.replacedertTrue(result.transactionStatus.isFailed());
replacedert.replacedertEquals("Failed: re-transformation failure", result.transactionStatus.causeOfError);
}
@Test
public void writeBackToCacheAfterEthCallTest() {
TestingState kernel = new TestingState(block);
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
AionAddress dappAddress = deploy(deployer, kernel, txData);
kernel.generateBlock();
// remove the transformed code. This means the avm version has changed.
// transformed code cache is empty.
kernel.setTransformedCode(dappAddress, null);
TransactionResult result = callDappNoArgument(kernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, 25_000);
replacedert.replacedertTrue(result.transactionStatus.isFailed());
// this transaction will read from the cache and write back
result = callDappNoArgument(kernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.ETH_CALL, 500_000);
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
kernel.generateBlock();
// Code is set to byte[0] to make re-transformation is not performed.
kernel.putCode(dappAddress, new byte[0]);
kernel.setTransformedCode(dappAddress, null);
result = callDappNoArgument(kernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, 500_000);
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
replacedert.replacedertEquals(20, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
@Test
public void writeBackToCacheAfterMiningTest() {
TestingState kernel = new TestingState(block);
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
AionAddress dappAddress = deploy(deployer, kernel, txData);
kernel.generateBlock();
// remove the transformed code. This means the avm version has changed.
// transformed code cache is empty.
kernel.setTransformedCode(dappAddress, null);
// this transaction will run out of energy. It should write back the transformed code to cache
TransactionResult result = callDappNoArgument(kernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, 25_000);
replacedert.replacedertTrue(result.transactionStatus.isFailed());
replacedert.replacedertNull(kernel.getTransformedCode(dappAddress));
kernel.generateBlock();
kernel.putCode(dappAddress, new byte[0]);
// this transaction must read from the cache, thus should succeed
result = callDappNoArgument(kernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.MINING, 500_000);
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
kernel.setTransformedCode(dappAddress, null);
// this transaction must read from the cache, thus should succeed
result = callDappNoArgument(kernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_SIDECHAIN, 500_000);
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
replacedert.replacedertEquals(20, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
@Test
public void deepSidechainTest() {
TestingState kernel = new TestingState(block);
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
AionAddress dappAddress = deploy(deployer, kernel, txData);
kernel.generateBlock();
// remove the transformed code. This means the avm version has changed.
// transformed code cache is empty.
kernel.setTransformedCode(dappAddress, null);
// this transaction will run out of energy. It should write back the transformed code to cache
TransactionResult result = callDappNoArgument(kernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, 25_000);
replacedert.replacedertTrue(result.transactionStatus.isFailed());
replacedert.replacedertNull(kernel.getTransformedCode(dappAddress));
kernel.generateBlock();
kernel.putCode(dappAddress, new byte[0]);
// since it's not reading from the cache the result of the operation is failed
result = callDappNoArgument(kernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_DEEP_SIDECHAIN, 500_000);
replacedert.replacedertTrue(result.transactionStatus.isFailed());
}
private static AionAddress deploy(AionAddress deployer, TestingState kernel, byte[] txData) {
Transaction tx1 = AvmTransactionUtil.create(deployer, kernel.getNonce(deployer), BigInteger.ZERO, txData, 5_000_000, 1);
TransactionResult result = avm.run(kernel, new Transaction[] { tx1 }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedertTrue(result.transactionStatus.isSuccess());
return new AionAddress(result.copyOfTransactionOutput().orElseThrow());
}
private static TransactionResult callDappNoArgument(TestingState kernel, AionAddress sender, AionAddress dappAddress, String methodName, ExecutionType executionType, long energyLimit) {
ABIStreamingEncoder encoder = new ABIStreamingEncoder().encodeOneString(methodName);
byte[] data = encoder.toBytes();
long commonBlockNumber = executionType == ExecutionType.replacedUME_DEEP_SIDECHAIN ? 0 : kernel.getBlockNumber() - 1;
Transaction tx = AvmTransactionUtil.call(sender, dappAddress, kernel.getNonce(sender), BigInteger.ZERO, data, energyLimit, 1);
return avm.run(kernel, new Transaction[] { tx }, executionType, commonBlockNumber)[0].getResult();
}
private static TransactionResult callDappArguments(TestingState kernel, AionAddress sender, AionAddress dappAddress, byte[] encodedData) {
Transaction tx = AvmTransactionUtil.call(sender, dappAddress, kernel.getNonce(sender), BigInteger.ZERO, encodedData, (long) 2_000_000, 1);
return avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
}
}
19
Source : HotObjectTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
public clreplaced HotObjectTest {
// NOTE: Output is ONLY produced if REPORT is set to true.
private static final boolean REPORT = false;
private static AionAddress deployer = TestingState.PREMINED_ADDRESS;
private static TestingBlock block;
private static AvmImpl avm;
private static long energyLimit = 2_000_000L;
private static long energyPrice = 1L;
@Before
public void setupClreplaced() {
block = new TestingBlock(new byte[32], 1, Helpers.randomAddress(), System.currentTimeMillis(), new byte[0]);
avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
}
@After
public void tearDown() {
avm.shutdown();
}
/**
* Demonstrates executing two transactions to the same contract in one block
* The code cache is invalidated before the execution of the tx3 since both transactions are in the same block
*/
@Test
public void executeMultipleTransactionSameBlock() {
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
AionAddress dappAddress = deploy(deployer, kernel, txData);
TransactionResult result = callDapp(kernel, deployer, dappAddress, "doubleStaticValue");
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
kernel.adjustBalance(kernel.getMinerAddress(), BigInteger.TEN.pow(10));
kernel.generateBlock();
byte[] data = new ABIStreamingEncoder().encodeOneString("doubleStaticValue").toBytes();
// read from the cache
Transaction tx2 = AvmTransactionUtil.call(deployer, dappAddress, kernel.getNonce(deployer), BigInteger.ZERO, data, energyLimit, energyPrice);
// read from DB
Transaction tx3 = AvmTransactionUtil.call(kernel.getMinerAddress(), dappAddress, kernel.getNonce(kernel.getMinerAddress()), BigInteger.ZERO, data, energyLimit, energyPrice);
FutureResult[] result2 = avm.run(kernel, new Transaction[] { tx2, tx3 }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1);
replacedert.replacedertEquals(20, new ABIDecoder((result2[0].getResult()).copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
replacedert.replacedertEquals(40, new ABIDecoder((result2[1].getResult()).copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
/**
* Demonstrates caching will not be used for an earlier block than the dapp's loaded block number
*/
@Test
public void executeTransactionEarlierBlock() {
// setup kernel
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel1 = new TestingState(block);
AionAddress dapp1 = deploy(deployer, kernel1, txData);
TestingState kernel2 = new TestingState(block);
AionAddress dapp2 = deploy(deployer, kernel2, txData);
// advance the block number
kernel2.generateBlock();
kernel2.generateBlock();
replacedert.replacedertEquals(dapp1, dapp2);
TransactionResult result = callDapp(kernel2, deployer, dapp2, "doubleStaticValue");
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
// execute same transaction on an earlier block
result = callDapp(kernel1, deployer, dapp1, "doubleStaticValue");
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
/**
* Demonstrates executing same transaction in the same contract in one block
* The storage is reset between executions and field values are read from DB
* The code cache is invalidated before the execution of the second transaction
*/
@Test
public void executeTransactionSameBlock() {
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
AionAddress dappAddress = deploy(deployer, kernel, txData);
byte[] objectGraph = kernel.getObjectGraph(dappAddress);
TransactionResult result = callDapp(kernel, deployer, dappAddress, "doubleStaticValue");
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
// reset the object graph
kernel.putObjectGraph(dappAddress, objectGraph);
result = callDapp(kernel, deployer, dappAddress, "doubleStaticValue");
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
/**
* Demonstrates field value is read from cache not storage for a new block
*/
@Test
public void executeTransactionFromCache() {
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
AionAddress dappAddress = deploy(deployer, kernel, txData);
byte[] objectGraph = kernel.getObjectGraph(dappAddress);
TransactionResult result = callDapp(kernel, deployer, dappAddress, "doubleStaticValue");
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
// reset the object graph
kernel.putObjectGraph(dappAddress, objectGraph);
// reset the transformed code to ensure we're reading from the code cache
kernel.setTransformedCode(dappAddress, new byte[0]);
kernel.generateBlock();
result = callDapp(kernel, deployer, dappAddress, "doubleStaticValue");
replacedert.replacedertEquals(20, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
/**
* Demonstrates the behaviour after revert.
* Dapp code is stored and read from the cache. Dapp data is not written back
*/
@Test
public void executeTransactionRevert() {
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
AionAddress dappAddress = deploy(deployer, kernel, txData);
kernel.generateBlock();
// add dapp to cache
TransactionResult result = callDapp(kernel, deployer, dappAddress, "doubleStaticValue");
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
kernel.generateBlock();
result = callDapp(kernel, deployer, dappAddress, "revert");
replacedert.replacedertTrue(result.transactionStatus.isReverted());
kernel.generateBlock();
// reset the transformed code to ensure we're reading from the code cache
kernel.setTransformedCode(dappAddress, new byte[0]);
result = callDapp(kernel, deployer, dappAddress, "getStr");
replacedert.replacedertEquals("initial", new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneString());
}
/**
* Demonstrates the behaviour after exception.
* Dapp code is stored and read from the cache. Dapp data is not written back.
*/
@Test
public void executeTransactionException() {
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
AionAddress dappAddress = deploy(deployer, kernel, txData);
kernel.generateBlock();
// add dapp to cache
TransactionResult result = callDapp(kernel, deployer, dappAddress, "doubleStaticValue");
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
kernel.generateBlock();
result = callDapp(kernel, deployer, dappAddress, "exception");
replacedert.replacedertEquals(AvmInternalError.FAILED_EXCEPTION.error, result.transactionStatus.causeOfError);
kernel.generateBlock();
// reset the transformed code to ensure we're reading from the code cache
kernel.setTransformedCode(dappAddress, new byte[0]);
result = callDapp(kernel, deployer, dappAddress, "getStr");
replacedert.replacedertEquals("initial", new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneString());
}
/**
* Demonstrates the behaviour after revert in a reentrant call.
* State of Dapp is not updated in cache after the revert
*/
@Test
public void executeReentrantRevert() {
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] deployData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
AionAddress dappAddress = deploy(deployer, kernel, deployData);
kernel.generateBlock();
// add dapp to cache
TransactionResult result = callDapp(kernel, deployer, dappAddress, "doubleStaticValue");
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
kernel.generateBlock();
byte[] data = new ABIStreamingEncoder().encodeOneString("revert").toBytes();
byte[] txData = new ABIStreamingEncoder().encodeOneString("makeCall").encodeOneAddress(new Address(dappAddress.toByteArray())).encodeOneByteArray(data).toBytes();
Transaction tx = AvmTransactionUtil.call(deployer, dappAddress, kernel.getNonce(deployer), BigInteger.ZERO, txData, energyLimit, energyPrice);
result = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
kernel.generateBlock();
result = callDapp(kernel, deployer, dappAddress, "getStr");
replacedert.replacedertEquals("initial", new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneString());
}
/**
* Demonstrates the behaviour in a reentrant call.
* State of Dapp is updated in cache
*/
@Test
public void executeReentrantSuccess() {
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] deployData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
AionAddress dappAddress = deploy(deployer, kernel, deployData);
kernel.generateBlock();
// add dapp to cache
TransactionResult result = callDapp(kernel, deployer, dappAddress, "doubleStaticValue");
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
kernel.generateBlock();
byte[] data = new ABIStreamingEncoder().encodeOneString("doubleStaticValue").toBytes();
byte[] txData = new ABIStreamingEncoder().encodeOneString("makeCall").encodeOneAddress(new Address(dappAddress.toByteArray())).encodeOneByteArray(data).toBytes();
Transaction tx = AvmTransactionUtil.call(deployer, dappAddress, kernel.getNonce(deployer), BigInteger.ZERO, txData, energyLimit, energyPrice);
result = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
kernel.generateBlock();
result = callDapp(kernel, deployer, dappAddress, "getValue");
replacedert.replacedertEquals(20, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
/**
* Demonstrates the difference in performance between reading from data cache and code cache
*/
@Test
public void performanceTest() {
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
AionAddress dappAddress = deploy(deployer, kernel, txData);
// 307168 bytes
byte[] data = new ABIStreamingEncoder().encodeOneString("writeToObjectArray").encodeOneInteger(150).encodeOneInteger(500).toBytes();
Transaction tx = AvmTransactionUtil.call(deployer, dappAddress, kernel.getNonce(deployer), BigInteger.ZERO, data, energyLimit, energyPrice);
TransactionResult result = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
kernel.generateBlock();
long cacheResult = measureMethodExecutionTime(kernel, dappAddress, "getValue", true, 5);
long DBResult = measureMethodExecutionTime(kernel, dappAddress, "getValue", false, 5);
if (REPORT) {
System.out.println("Avg execution time (307168 serialized bytes) using code cache: " + DBResult + ", data cache: " + cacheResult + "(ns). code/data cache ratio: " + (double) DBResult / cacheResult);
}
// 8308 bytes
data = new ABIStreamingEncoder().encodeOneString("writeToObjectArray").encodeOneInteger(15).encodeOneInteger(55).toBytes();
tx = AvmTransactionUtil.call(deployer, dappAddress, kernel.getNonce(deployer), BigInteger.ZERO, data, energyLimit, energyPrice);
result = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
kernel.generateBlock();
cacheResult = measureMethodExecutionTime(kernel, dappAddress, "getValue", true, 5);
DBResult = measureMethodExecutionTime(kernel, dappAddress, "getValue", false, 5);
if (REPORT) {
System.out.println("Avg execution time (8308 serialized bytes) using code cache: " + DBResult + ", data cache: " + cacheResult + "(ns). code/data cache ratio: " + (double) DBResult / cacheResult);
}
}
/**
* Demonstrates the case one contract is making an internal call and updates another contract. All the data is read from the cache
*/
@Test
public void callOtherContractInCache() {
int length = 2;
AionAddress[] dappAddresses = new AionAddress[length];
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] deployData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
for (int i = 0; i < length; i++) {
AionAddress deployer = Helpers.randomAddress();
kernel.adjustBalance(deployer, BigInteger.TEN.pow(20));
dappAddresses[i] = deploy(deployer, kernel, deployData);
// add to cache
TransactionResult result = callDapp(kernel, deployer, dappAddresses[i], "getValue");
replacedert.replacedertEquals(5, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
kernel.generateBlock();
}
byte[] objectGraph = kernel.getObjectGraph(dappAddresses[1]);
// update the cache
byte[] data = new ABIStreamingEncoder().encodeOneString("doubleStaticValue").toBytes();
byte[] txData = new ABIStreamingEncoder().encodeOneString("makeCall").encodeOneAddress(new Address(dappAddresses[1].toByteArray())).encodeOneByteArray(data).toBytes();
Transaction tx = AvmTransactionUtil.call(deployer, dappAddresses[0], kernel.getNonce(deployer), BigInteger.ZERO, txData, energyLimit, energyPrice);
TransactionResult result = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
kernel.generateBlock();
// reset the object graph and transformed code to ensure data is read form cache
for (int i = 0; i < length; i++) {
kernel.putObjectGraph(dappAddresses[i], objectGraph);
kernel.setTransformedCode(dappAddresses[i], new byte[0]);
}
// internal transaction result is not stored in the cache
result = callDapp(kernel, deployer, dappAddresses[1], "getValue");
replacedert.replacedertEquals(5, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
kernel.generateBlock();
result = callDapp(kernel, deployer, dappAddresses[0], "getValue");
replacedert.replacedertEquals(5, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
/**
* Demonstrates the case where 2 contracts make internal calls and update each other. All the data is read from the cache
*/
@Test
public void InternalCallsBetween2Contracts() {
int length = 2;
AionAddress[] dappAddresses = new AionAddress[length];
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] deployData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
for (int i = 0; i < length; i++) {
AionAddress deployer = Helpers.randomAddress();
kernel.adjustBalance(deployer, BigInteger.TEN.pow(20));
dappAddresses[i] = deploy(deployer, kernel, deployData);
// add to cache
TransactionResult result = callDapp(kernel, deployer, dappAddresses[i], "getValue");
replacedert.replacedertEquals(5, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
kernel.generateBlock();
}
byte[] objectGraph = kernel.getObjectGraph(dappAddresses[0]);
// update the cache
byte[] data = new ABIStreamingEncoder().encodeOneString("doubleStaticValue").toBytes();
byte[] dataForCallFrom2To1 = new ABIStreamingEncoder().encodeOneString("makeCall").encodeOneAddress(new Address(dappAddresses[0].toByteArray())).encodeOneByteArray(data).toBytes();
byte[] ForCallFrom1To2 = new ABIStreamingEncoder().encodeOneString("makeCall").encodeOneAddress(new Address(dappAddresses[1].toByteArray())).encodeOneByteArray(dataForCallFrom2To1).toBytes();
Transaction tx = AvmTransactionUtil.call(deployer, dappAddresses[0], kernel.getNonce(deployer), BigInteger.ZERO, ForCallFrom1To2, energyLimit, energyPrice);
TransactionResult result = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
kernel.generateBlock();
// reset the object graph and transformed code to ensure data is read form cache
for (int i = 0; i < length; i++) {
kernel.putObjectGraph(dappAddresses[i], objectGraph);
kernel.setTransformedCode(dappAddresses[i], new byte[0]);
}
// internal transaction result is not stored in the cache
result = callDapp(kernel, deployer, dappAddresses[1], "getCallCount");
replacedert.replacedertEquals(0, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
kernel.generateBlock();
result = callDapp(kernel, deployer, dappAddresses[0], "getCallCount");
replacedert.replacedertEquals(1, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
kernel.generateBlock();
result = callDapp(kernel, deployer, dappAddresses[0], "getValue");
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
/**
* Executes and caches the result of array modifications and reads from the cache while executing transactions concurrently
*/
@Test
public void readConcurrentlyFromCache() {
int length = 4;
AionAddress[] dappAddresses = new AionAddress[length];
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
Transaction[] txs = new Transaction[length];
byte[] readIntArrayData = new ABIStreamingEncoder().encodeOneString("readIntArray").toBytes();
for (int i = 0; i < length; i++) {
AionAddress deployer = Helpers.randomAddress();
kernel.adjustBalance(deployer, BigInteger.TEN.pow(20));
dappAddresses[i] = deploy(deployer, kernel, txData);
// setup concurrent transactions
txs[i] = AvmTransactionUtil.call(deployer, dappAddresses[i], kernel.getNonce(deployer), BigInteger.ZERO, readIntArrayData, energyLimit, energyPrice);
}
// add to cache
for (int i = 0; i < length; i++) {
byte[] data = new ABIStreamingEncoder().encodeOneString("updateIntArray").encodeOneInteger(i).toBytes();
Transaction tx = AvmTransactionUtil.call(deployer, dappAddresses[i], kernel.getNonce(deployer), BigInteger.ZERO, data, energyLimit, energyPrice);
TransactionResult result = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
kernel.generateBlock();
}
// read from cache while executing concurrently
FutureResult[] results = avm.run(kernel, txs, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1);
for (int i = 0; i < length; i++) {
TransactionResult r = results[i].getResult();
replacedert.replacedertTrue(r.transactionStatus.isSuccess());
int[] expectedResult = new int[length];
expectedResult[i] = 10;
replacedert.replacedertArrayEquals(expectedResult, new ABIDecoder(r.copyOfTransactionOutput().orElseThrow()).decodeOneIntegerArray());
}
}
/**
* Executes array modifications for different contracts concurrently, and caches the result. Then reads from the cache.
*/
@Test
public void addToCacheFromConcurrentExecutor() {
int length = 4;
AionAddress[] dappAddresses = new AionAddress[length];
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
Transaction[] txs = new Transaction[length];
for (int i = 0; i < length; i++) {
AionAddress deployer = Helpers.randomAddress();
kernel.adjustBalance(deployer, BigInteger.TEN.pow(20));
dappAddresses[i] = deploy(deployer, kernel, txData);
// add to cache
byte[] data = new ABIStreamingEncoder().encodeOneString("updateIntArray").encodeOneInteger(i).toBytes();
txs[i] = AvmTransactionUtil.call(deployer, dappAddresses[i], kernel.getNonce(deployer), BigInteger.ZERO, data, energyLimit, energyPrice);
}
FutureResult[] results = avm.run(kernel, txs, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1);
for (int i = 0; i < length; i++) {
TransactionResult r = results[i].getResult();
replacedert.replacedertTrue(r.transactionStatus.isSuccess());
}
kernel.generateBlock();
for (int i = 0; i < length; i++) {
byte[] data = new ABIStreamingEncoder().encodeOneString("readIntArray").toBytes();
Transaction tx = AvmTransactionUtil.call(deployer, dappAddresses[i], kernel.getNonce(deployer), BigInteger.ZERO, data, energyLimit, energyPrice);
TransactionResult result = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
int[] expectedResult = new int[length];
expectedResult[i] = 10;
replacedert.replacedertArrayEquals(expectedResult, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneIntegerArray());
kernel.generateBlock();
}
}
@Test
public void abortException() {
int length = 4;
AionAddress[] dappAddresses = new AionAddress[length + 1];
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] deployData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
byte[] dataForInternalCall = new ABIStreamingEncoder().encodeOneString("doubleStaticValue").toBytes();
Transaction[] txs = new Transaction[length];
for (int i = 0; i < length + 1; i++) {
AionAddress deployer = Helpers.randomAddress();
kernel.adjustBalance(deployer, BigInteger.TEN.pow(20));
dappAddresses[i] = deploy(deployer, kernel, deployData);
if (i > 0) {
byte[] txData = new ABIStreamingEncoder().encodeOneString("makeCall").encodeOneAddress(new Address(dappAddresses[i].toByteArray())).encodeOneByteArray(dataForInternalCall).toBytes();
txs[i - 1] = AvmTransactionUtil.call(deployer, dappAddresses[i - 1], kernel.getNonce(deployer), BigInteger.ZERO, txData, energyLimit, energyPrice);
}
}
FutureResult[] results = avm.run(kernel, txs, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1);
for (int i = 0; i < length; i++) {
TransactionResult r = results[i].getResult();
replacedert.replacedertTrue(r.transactionStatus.isSuccess());
}
kernel.generateBlock();
byte[] data = new ABIStreamingEncoder().encodeOneString("getValue").toBytes();
for (int i = 1; i < length; i++) {
Transaction tx = AvmTransactionUtil.call(deployer, dappAddresses[i], kernel.getNonce(deployer), BigInteger.ZERO, data, energyLimit, energyPrice);
TransactionResult result = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
}
@Test
public void selfDestructThenSendTransaction() {
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
AionAddress dappAddress = deploy(deployer, kernel, txData);
TransactionResult result = callDapp(kernel, deployer, dappAddress, "doubleStaticValue");
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
kernel.generateBlock();
callDapp(kernel, deployer, dappAddress, "selfDestruct");
kernel.generateBlock();
result = callDapp(kernel, deployer, dappAddress, "doubleStaticValue");
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
replacedert.replacedertFalse(result.copyOfTransactionOutput().isPresent());
}
/**
* Demonstrates a cross call which fails. The dapp code is read from the cache but the data is cleared
*/
@Test
public void callOtherContractInCacheAndFail() {
int length = 2;
AionAddress[] dappAddresses = new AionAddress[length];
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] deployData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
for (int i = 0; i < length; i++) {
AionAddress deployer = Helpers.randomAddress();
kernel.adjustBalance(deployer, BigInteger.TEN.pow(20));
dappAddresses[i] = deploy(deployer, kernel, deployData);
// add to cache
TransactionResult result = callDapp(kernel, deployer, dappAddresses[i], "getValue");
replacedert.replacedertEquals(5, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
kernel.generateBlock();
}
// save the current state of the object graph. this will be used later to ensure the value is not read from the cache
byte[] objectGraph = kernel.getObjectGraph(dappAddresses[1]);
TransactionResult result = callDapp(kernel, deployer, dappAddresses[1], "doubleStaticValue");
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
// update the cache
byte[] data = new ABIStreamingEncoder().encodeOneString("revert").toBytes();
byte[] txData = new ABIStreamingEncoder().encodeOneString("makeCall").encodeOneAddress(new Address(dappAddresses[1].toByteArray())).encodeOneByteArray(data).toBytes();
Transaction tx = AvmTransactionUtil.call(deployer, dappAddresses[0], kernel.getNonce(deployer), BigInteger.ZERO, txData, energyLimit, energyPrice);
result = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
kernel.generateBlock();
// reset the object graph and transformed code to ensure data is read form cache
for (int i = 0; i < length; i++) {
// object graph at this stage, had the initial value of 5
kernel.putObjectGraph(dappAddresses[i], objectGraph);
kernel.setTransformedCode(dappAddresses[i], new byte[0]);
}
// read the cache
result = callDapp(kernel, deployer, dappAddresses[1], "getValue");
replacedert.replacedertEquals(5, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
kernel.generateBlock();
result = callDapp(kernel, deployer, dappAddresses[0], "getValue");
replacedert.replacedertEquals(5, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
@Test
public void testRevertExternalCall() {
int length = 2;
AionAddress[] dappAddresses = new AionAddress[length];
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] deployData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
for (int i = 0; i < length; i++) {
AionAddress deployer = Helpers.randomAddress();
kernel.adjustBalance(deployer, BigInteger.TEN.pow(20));
dappAddresses[i] = deploy(deployer, kernel, deployData);
}
// update the cache
byte[] data = new ABIStreamingEncoder().encodeOneString("doubleStaticValue").toBytes();
byte[] txData = new ABIStreamingEncoder().encodeOneString("makeCallAndRevert").encodeOneAddress(new Address(dappAddresses[1].toByteArray())).encodeOneByteArray(data).toBytes();
Transaction tx = AvmTransactionUtil.call(deployer, dappAddresses[0], kernel.getNonce(deployer), BigInteger.ZERO, txData, energyLimit, energyPrice);
TransactionResult result = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(result.transactionStatus.isFailed());
kernel.generateBlock();
// reset the code to make sure it's read from the cache
for (int i = 0; i < length; i++) {
kernel.putCode(dappAddresses[i], new byte[0]);
}
// read from the storage
result = callDapp(kernel, deployer, dappAddresses[1], "getValue");
replacedert.replacedertEquals(5, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
kernel.generateBlock();
result = callDapp(kernel, deployer, dappAddresses[0], "getValue");
replacedert.replacedertEquals(5, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
@Test
public void testFailedExternalCall() {
int length = 2;
AionAddress[] dappAddresses = new AionAddress[length];
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] deployData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
for (int i = 0; i < length; i++) {
AionAddress deployer = Helpers.randomAddress();
kernel.adjustBalance(deployer, BigInteger.TEN.pow(20));
dappAddresses[i] = deploy(deployer, kernel, deployData);
}
// update the cache
byte[] data = new ABIStreamingEncoder().encodeOneString("doubleStaticValue").toBytes();
byte[] txData = new ABIStreamingEncoder().encodeOneString("makeCallAndFail").encodeOneAddress(new Address(dappAddresses[1].toByteArray())).encodeOneByteArray(data).toBytes();
Transaction tx = AvmTransactionUtil.call(deployer, dappAddresses[0], kernel.getNonce(deployer), BigInteger.ZERO, txData, 1933022, energyPrice);
TransactionResult result = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(result.transactionStatus.isFailed());
kernel.generateBlock();
// reset the code to make sure it's read from the cache
for (int i = 0; i < length; i++) {
kernel.putCode(dappAddresses[i], new byte[0]);
}
// read from the storage
result = callDapp(kernel, deployer, dappAddresses[1], "getValue");
replacedert.replacedertEquals(5, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
kernel.generateBlock();
result = callDapp(kernel, deployer, dappAddresses[0], "getValue");
replacedert.replacedertEquals(5, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
private static long measureMethodExecutionTime(TestingState kernel, AionAddress dappAddress, String methodName, boolean generateBlock, int rounds) {
long totalDuration = 0l;
for (int i = 0; i < rounds; ++i) {
long start = System.nanoTime();
TransactionResult result = callDapp(kernel, deployer, dappAddress, methodName);
totalDuration += (System.nanoTime() - start);
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
if (generateBlock && i != rounds - 1) {
kernel.generateBlock();
}
}
return totalDuration / rounds;
}
private static AionAddress deploy(AionAddress deployer, TestingState kernel, byte[] txData) {
Transaction tx1 = AvmTransactionUtil.create(deployer, kernel.getNonce(deployer), BigInteger.ZERO, txData, 5_000_000, energyPrice);
TransactionResult result = avm.run(kernel, new Transaction[] { tx1 }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedertTrue(result.transactionStatus.isSuccess());
return new AionAddress(result.copyOfTransactionOutput().orElseThrow());
}
private static TransactionResult callDapp(TestingState kernel, AionAddress sender, AionAddress dappAddress, String methodName, Object... args) {
ABIStreamingEncoder encoder = new ABIStreamingEncoder().encodeOneString(methodName);
for (Object arg : args) {
encoder.encodeOneByteArray((byte[]) arg);
}
byte[] data = encoder.toBytes();
Transaction tx = AvmTransactionUtil.call(sender, dappAddress, kernel.getNonce(sender), BigInteger.ZERO, data, energyLimit, energyPrice);
return avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
}
}
19
Source : ExecutionTypeCacheTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
public clreplaced ExecutionTypeCacheTest {
private static AionAddress deployer = TestingState.PREMINED_ADDRESS;
private static TestingBlock block;
private static AvmImpl avm;
@Before
public void setupClreplaced() {
block = new TestingBlock(new byte[32], 1, Helpers.randomAddress(), System.currentTimeMillis(), new byte[0]);
avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
}
@After
public void tearDown() {
avm.shutdown();
}
/**
* Tests the case where the code cache block is after the common ancestor. Thus, caching will not be used.
*/
@Test
public void sidechainInvalidCodeCache() {
TestingState sidechainKernel = new TestingState(block);
TestingState mainchainKernel = new TestingState(block);
// deploy to both
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
AionAddress dappAddress = deploy(deployer, mainchainKernel, txData);
deploy(deployer, sidechainKernel, txData);
mainchainKernel.generateBlock();
sidechainKernel.generateBlock();
long commonParent = mainchainKernel.getBlockNumber();
mainchainKernel.generateBlock();
// add to cache on mainchain
TransactionResult result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
// generate sidechain block with parent on mainchain
sidechainKernel.generateBlock();
// reset the transformed code on the kernel
sidechainKernel.setTransformedCode(dappAddress, new byte[0]);
// since it's not reading from the cache the result of the revert operation is success
result = callDapp(sidechainKernel, deployer, dappAddress, "revert", ExecutionType.replacedUME_SIDECHAIN, commonParent);
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
// validate mainchain cache is valid
mainchainKernel.generateBlock();
// reset to ensure cache is used
mainchainKernel.setTransformedCode(dappAddress, new byte[0]);
mainchainKernel.putObjectGraph(dappAddress, new byte[0]);
// read from the cache to make sure it's not corrupted
result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(20, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
/**
* Tests the case where both code and data cache have been put before the common ancestor.
* They can both be used but only the code is written back.
*/
@Test
public void sidechainValidCodeCacheValidDataCache() {
TestingState sidechainKernel = new TestingState(block);
TestingState mainchainKernel = new TestingState(block);
// deploy to both
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
AionAddress dappAddress = deploy(deployer, mainchainKernel, txData);
deploy(deployer, sidechainKernel, txData);
mainchainKernel.generateBlock();
sidechainKernel.generateBlock();
// add to cache on mainchain
TransactionResult result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
sidechainKernel.generateBlock();
mainchainKernel.generateBlock();
long commonParent = mainchainKernel.getBlockNumber();
mainchainKernel.generateBlock();
sidechainKernel.generateBlock();
// reset the transformed code on the kernel
sidechainKernel.setTransformedCode(dappAddress, new byte[0]);
// it should only read the code form cache
result = callDapp(sidechainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_SIDECHAIN, commonParent);
replacedert.replacedertEquals(20, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
mainchainKernel.generateBlock();
// update the data cache on mainchain
result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(20, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
/**
* Tests the case where the code cache block number is below and the data cache block number is after the common ancestor
* Code cache will be used but data cache will not be.
* At the end of the transaction dapp code will be written back to the cache
*/
@Test
public void sidechainValidCodeCacheInvalidDataCache() {
TestingState sidechainKernel = new TestingState(block);
TestingState mainchainKernel = new TestingState(block);
// deploy to both
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
AionAddress dappAddress = deploy(deployer, mainchainKernel, txData);
deploy(deployer, sidechainKernel, txData);
mainchainKernel.generateBlock();
sidechainKernel.generateBlock();
// add to cache on mainchain
TransactionResult result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
sidechainKernel.generateBlock();
mainchainKernel.generateBlock();
long commonParent = mainchainKernel.getBlockNumber();
mainchainKernel.generateBlock();
// update the data cache on mainchain
result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(20, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
sidechainKernel.generateBlock();
// reset the transformed code on the kernel
sidechainKernel.setTransformedCode(dappAddress, new byte[0]);
// it should only read the code form cache
result = callDapp(sidechainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_SIDECHAIN, commonParent);
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
// reset the transformed code on the kernel
mainchainKernel.setTransformedCode(dappAddress, new byte[0]);
mainchainKernel.generateBlock();
// update the data cache on mainchain
result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(40, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
/**
* Tests the case where dapp is not included in the cache.
* After the transaction cache will not be updated.
*/
@Test
public void sidechainNotInCache() {
TestingState sidechainKernel = new TestingState(block);
TestingState mainchainKernel = new TestingState(block);
// deploy to both
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
AionAddress dappAddress = deploy(deployer, mainchainKernel, txData);
deploy(deployer, sidechainKernel, txData);
sidechainKernel.generateBlock();
mainchainKernel.generateBlock();
long commonParent = mainchainKernel.getBlockNumber();
mainchainKernel.generateBlock();
sidechainKernel.generateBlock();
// it should only read the code form cache
TransactionResult result = callDapp(sidechainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_SIDECHAIN, commonParent);
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
mainchainKernel.generateBlock();
// update the data cache on mainchain
result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
/**
* It sequentially adds mainchain and deep sidechain blocks.
* Sidechain blocks do not interact with cache while mainchain blocks are stored in both data and code cache
*/
@Test
public void multipleDeepSidechainBlockTest() {
TestingState sidechainKernel = new TestingState(block);
TestingState mainchainKernel = new TestingState(block);
// deploy to both
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
AionAddress dappAddress = deploy(deployer, mainchainKernel, txData);
deploy(deployer, sidechainKernel, txData);
// add to cache
TransactionResult result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
mainchainKernel.generateBlock();
sidechainKernel.generateBlock();
// update cache
result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(20, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
mainchainKernel.generateBlock();
sidechainKernel.generateBlock();
result = callDapp(sidechainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_DEEP_SIDECHAIN, 0);
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(40, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
mainchainKernel.generateBlock();
sidechainKernel.generateBlock();
result = callDapp(sidechainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_DEEP_SIDECHAIN, 0);
replacedert.replacedertEquals(20, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(80, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
/**
* Tests the case where mining is done after a mainchain import
* ensures code is read from cache and written back
*/
@Test
public void miningMainchainMixtureTest() {
TestingState miningKernel = new TestingState(block);
// deploy to both
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
AionAddress dappAddress = deploy(deployer, miningKernel, txData);
miningKernel.generateBlock();
TransactionResult result = callDapp(miningKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.MINING, miningKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
miningKernel.generateBlock();
// add to cache
result = callDapp(miningKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, miningKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(20, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
miningKernel.generateBlock();
// make sure it's read from the cache
miningKernel.setTransformedCode(dappAddress, new byte[0]);
result = callDapp(miningKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.MINING, miningKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(40, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
miningKernel.generateBlock();
// make sure it was written back to cache
miningKernel.setTransformedCode(dappAddress, new byte[0]);
result = callDapp(miningKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, miningKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(80, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
/**
* Tests the case where mining is done after a mainchain import
* ensures data is not written back to the cache
*/
@Test
public void miningMainchainMixtureNoDataTest() {
TestingState miningKernel = new TestingState(block);
// deploy to both
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
AionAddress dappAddress = deploy(deployer, miningKernel, txData);
miningKernel.generateBlock();
byte[] graph = miningKernel.getObjectGraph(dappAddress);
TransactionResult result = callDapp(miningKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.MINING, miningKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
miningKernel.generateBlock();
// add to cache
result = callDapp(miningKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, miningKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(20, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
miningKernel.generateBlock();
// make sure it's read from the cache
miningKernel.setTransformedCode(dappAddress, new byte[0]);
// reset the data in db, to ensure cache data is not read
miningKernel.putObjectGraph(dappAddress, graph);
result = callDapp(miningKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.MINING, miningKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
miningKernel.generateBlock();
// make sure it was wriiten back to cache
miningKernel.setTransformedCode(dappAddress, new byte[0]);
// rest the data to ensure data is not read from the cache
miningKernel.putObjectGraph(dappAddress, graph);
result = callDapp(miningKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, miningKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
miningKernel.generateBlock();
// make sure it was wriiten back to cache
miningKernel.setTransformedCode(dappAddress, new byte[0]);
// rest the data to ensure data is not read from the cache
miningKernel.putObjectGraph(dappAddress, graph);
result = callDapp(miningKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, miningKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(20, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
/**
* It simulates running one transaction in multiple blocks during mining.
* Mining blocks do not interact with cache.
*/
@Test
public void sameMiningBlockTest() {
TestingState miningKernel = new TestingState(block);
// deploy to both
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
AionAddress dappAddress = deploy(deployer, miningKernel, txData);
miningKernel.generateBlock();
AionAddress sender = Helpers.randomAddress();
miningKernel.adjustBalance(sender, BigInteger.TEN.pow(20));
miningKernel.generateBlock();
byte[] graph = miningKernel.getObjectGraph(dappAddress);
TransactionResult result = callDapp(miningKernel, sender, dappAddress, "doubleStaticValue", ExecutionType.MINING, miningKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
miningKernel.generateBlock();
miningKernel.deleteAccount(sender);
miningKernel.adjustBalance(sender, BigInteger.TEN.pow(20));
miningKernel.putObjectGraph(dappAddress, graph);
result = callDapp(miningKernel, sender, dappAddress, "doubleStaticValue", ExecutionType.MINING, miningKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
/**
* Builds mainchain and sidechain simultaneously. Then marks the sidechain as the new mainchain
*/
@Test
public void switchMainchainTest() {
TestingState sidechainKernel = new TestingState(block);
TestingState mainchainKernel = new TestingState(block);
// deploy to both
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
AionAddress dappAddress = deploy(deployer, mainchainKernel, txData);
deploy(deployer, sidechainKernel, txData);
// add to cache for mainchain kernel
TransactionResult result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
// add to cache for sidechain kernel
result = callDapp(sidechainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, sidechainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
long commonParent = mainchainKernel.getBlockNumber();
// fork
mainchainKernel.generateBlock();
sidechainKernel.generateBlock();
// update cache for mainchain kernel
result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(20, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
mainchainKernel.generateBlock();
sidechainKernel.generateBlock();
// update cache for mainchain kernel
result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(40, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
// update db for sidechain kernel
result = callDapp(sidechainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_DEEP_SIDECHAIN, 0);
replacedert.replacedertEquals(20, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
sidechainKernel.generateBlock();
// ensure cache is used
sidechainKernel.setTransformedCode(dappAddress, new byte[0]);
// mark the sidechain as the new mainchain
result = callDapp(sidechainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.SWITCHING_MAINCHAIN, commonParent);
replacedert.replacedertEquals(40, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
/**
* Builds mainchain and sidechain simultaneously. Contract is selfdestructed on the sidechain but still remains in the cache
*/
@Test
public void switchMainchainSelfDestructTest() {
TestingState sidechainKernel = new TestingState(block);
TestingState mainchainKernel = new TestingState(block);
// deploy to both
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
AionAddress dappAddress = deploy(deployer, mainchainKernel, txData);
deploy(deployer, sidechainKernel, txData);
// add to cache for mainchain kernel
TransactionResult result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
// add to cache for sidechain kernel
result = callDapp(sidechainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, sidechainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
long commonParent = mainchainKernel.getBlockNumber();
// fork
mainchainKernel.generateBlock();
sidechainKernel.generateBlock();
// update cache for mainchain kernel
result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(20, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
mainchainKernel.generateBlock();
sidechainKernel.generateBlock();
// update cache for mainchain kernel
result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(40, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
// update db for sidechain kernel
result = callDapp(sidechainKernel, deployer, dappAddress, "selfDestruct", ExecutionType.replacedUME_DEEP_SIDECHAIN, 0);
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
sidechainKernel.generateBlock();
// mark the sidechain as the new mainchain
result = callDapp(sidechainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.SWITCHING_MAINCHAIN, commonParent);
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
replacedert.replacedertFalse(result.copyOfTransactionOutput().isPresent());
}
/**
* Tests ethcall without valid cache. Dapp code will not be written back to the cache
*/
@Test
public void ethCallWithoutCacheValidateCodeNotWrittenBack() {
TestingState mainchainKernel = new TestingState(block);
// deploy to both
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
AionAddress dappAddress = deploy(deployer, mainchainKernel, txData);
mainchainKernel.generateBlock();
mainchainKernel.generateBlock();
TransactionResult result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.ETH_CALL, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
mainchainKernel.generateBlock();
// reset the transformed code and object graph on the kernel
mainchainKernel.setTransformedCode(dappAddress, new byte[0]);
result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertFalse(result.copyOfTransactionOutput().isPresent());
}
/**
* Tests ethcall without valid cache. Dapp data will not be written back to the cache
*/
@Test
public void ethCallWithoutCacheValidateDataNotWrittenBack() {
TestingState mainchainKernel = new TestingState(block);
// deploy to both
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
AionAddress dappAddress = deploy(deployer, mainchainKernel, txData);
mainchainKernel.generateBlock();
byte[] graph = mainchainKernel.getObjectGraph(dappAddress);
mainchainKernel.generateBlock();
TransactionResult result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.ETH_CALL, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
mainchainKernel.generateBlock();
// reset the transformed code and object graph on the kernel
mainchainKernel.putObjectGraph(dappAddress, graph);
result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
/**
* Tests the case where the code cache block is after the common ancestor. Thus, caching will not be used.
*/
@Test
public void ethCallInvalidCodeCache() {
TestingState mainchainKernel = new TestingState(block);
// deploy to both
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
AionAddress dappAddress = deploy(deployer, mainchainKernel, txData);
mainchainKernel.generateBlock();
long commonParent = mainchainKernel.getBlockNumber();
mainchainKernel.generateBlock();
mainchainKernel.generateBlock();
// add to cache on mainchain
TransactionResult result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
// generate sidechain block with parent on mainchain
mainchainKernel.generateBlock();
// reset the transformed code on the kernel
mainchainKernel.setTransformedCode(dappAddress, new byte[0]);
// since it's not reading from the cache the result of the revert operation is success
result = callDapp(mainchainKernel, deployer, dappAddress, "revert", ExecutionType.ETH_CALL, commonParent);
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
// validate mainchain cache is valid
mainchainKernel.generateBlock();
// reset to ensure cache is used
mainchainKernel.setTransformedCode(dappAddress, new byte[0]);
mainchainKernel.putObjectGraph(dappAddress, new byte[0]);
// read from the cache to make sure it's not corrupted
result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(20, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
/**
* Tests the case where both code and data cache have been put before the common ancestor.
* They can both be used but only the code is written back.
*/
@Test
public void ethCallValidCodeCacheValidDataCache() {
TestingState mainchainKernel = new TestingState(block);
// deploy to both
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
AionAddress dappAddress = deploy(deployer, mainchainKernel, txData);
mainchainKernel.generateBlock();
// add to cache on mainchain
TransactionResult result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
mainchainKernel.generateBlock();
long commonParent = mainchainKernel.getBlockNumber();
mainchainKernel.generateBlock();
mainchainKernel.generateBlock();
// reset the transformed code on the kernel
mainchainKernel.setTransformedCode(dappAddress, new byte[0]);
byte[] graph = mainchainKernel.getObjectGraph(dappAddress);
mainchainKernel.putObjectGraph(dappAddress, new byte[0]);
// it should only read the code form cache
result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.ETH_CALL, commonParent);
replacedert.replacedertEquals(20, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
mainchainKernel.generateBlock();
mainchainKernel.setTransformedCode(dappAddress, new byte[0]);
// rest the graph to before the cll
mainchainKernel.putObjectGraph(dappAddress, graph);
// update the data cache on mainchain
result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(20, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
/**
* Tests the case where the code cache block number is below and the data cache block number is after the common ancestor
* Code cache will be used but data cache will not be.
* At the end of the transaction dapp code will be written back to the cache
*/
@Test
public void ethCallValidCodeCacheInvalidDataCache() {
TestingState mainchainKernel = new TestingState(block);
// deploy to both
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(HotObjectContract.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
AionAddress dappAddress = deploy(deployer, mainchainKernel, txData);
mainchainKernel.generateBlock();
// add to cache on mainchain
TransactionResult result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(10, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
mainchainKernel.generateBlock();
long commonParent = mainchainKernel.getBlockNumber();
mainchainKernel.generateBlock();
byte[] graphEthCallBlock = mainchainKernel.getObjectGraph(dappAddress);
// update the data cache on mainchain
result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(20, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
mainchainKernel.generateBlock();
result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(40, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
mainchainKernel.generateBlock();
byte[] graphMainChainLatest = mainchainKernel.getObjectGraph(dappAddress);
// reset the transformed code on the kernel
mainchainKernel.setTransformedCode(dappAddress, new byte[0]);
// rest database to the common parent state. cache reflects value = 40 now and the db reflects value = 10
mainchainKernel.putObjectGraph(dappAddress, graphEthCallBlock);
// it should only read the code form cache
result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.ETH_CALL, commonParent);
replacedert.replacedertEquals(20, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
// reset the transformed code on the kernel
mainchainKernel.setTransformedCode(dappAddress, new byte[0]);
// make sure the db with value = 40 is read and cache is not updated after eth_call
mainchainKernel.putObjectGraph(dappAddress, graphMainChainLatest);
mainchainKernel.generateBlock();
// update the data cache on mainchain
result = callDapp(mainchainKernel, deployer, dappAddress, "doubleStaticValue", ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
replacedert.replacedertEquals(80, new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
/**
* Tests executing sidechain transactions concurrently. all dapps are put back in the cache
*/
@Test
public void concurrentSidechainExecution() {
byte[] code = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(TestContract.clreplaced);
TestingState mainchainKernel = new TestingState(block);
TestingState sidechainKernel = new TestingState(block);
int length = 4;
AionAddress[] user = new AionAddress[length];
Transaction[] ctx = new Transaction[length];
for (int i = 0; i < length; i++) {
user[i] = Helpers.randomAddress();
mainchainKernel.adjustBalance(user[i], BigInteger.TEN.pow(20));
sidechainKernel.adjustBalance(user[i], BigInteger.TEN.pow(20));
ctx[i] = AvmTransactionUtil.create(user[i], BigInteger.ZERO, BigInteger.ZERO, new CodeAndArguments(code, null).encodeToBytes(), 5_000_000L, 1);
}
FutureResult[] results = avm.run(mainchainKernel, ctx, ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
AionAddress[] contractAddresses = new AionAddress[results.length];
for (int i = 0; i < results.length; i++) {
contractAddresses[i] = new AionAddress(results[i].getResult().copyOfTransactionOutput().orElseThrow());
}
results = avm.run(sidechainKernel, ctx, ExecutionType.replacedUME_MAINCHAIN, sidechainKernel.getBlockNumber() - 1);
for (int i = 0; i < results.length; i++) {
contractAddresses[i] = new AionAddress(results[i].getResult().copyOfTransactionOutput().orElseThrow());
}
long commonParent = mainchainKernel.getBlockNumber();
mainchainKernel.generateBlock();
Transaction[] tx = new Transaction[results.length - 1];
// u1->A->B, u2->B->C, u3->C->D
for (int i = 0; i < results.length - 1; i++) {
byte[] callData = new ABIStreamingEncoder().encodeOneString("doCallOther").encodeOneAddress(new Address(contractAddresses[i + 1].toByteArray())).encodeOneByteArray(new ABIStreamingEncoder().encodeOneString("addValue").toBytes()).toBytes();
tx[i] = AvmTransactionUtil.call(user[i], contractAddresses[i], mainchainKernel.getNonce(user[i]), BigInteger.ZERO, callData, 5_000_000, 1);
}
results = avm.run(mainchainKernel, tx, ExecutionType.replacedUME_MAINCHAIN, mainchainKernel.getBlockNumber() - 1);
for (FutureResult f : results) {
f.getResult();
}
sidechainKernel.generateBlock();
// validate the state of contracts
for (int i = 0; i < length - 1; i++) {
byte[] getCallCount = new ABIStreamingEncoder().encodeOneString("getCallCount").toBytes();
tx[i] = AvmTransactionUtil.call(user[i], contractAddresses[i], sidechainKernel.getNonce(user[i]), BigInteger.ZERO, getCallCount, 5_000_000, 1);
}
results = avm.run(sidechainKernel, tx, ExecutionType.replacedUME_SIDECHAIN, commonParent);
for (FutureResult f : results) {
replacedert.replacedertEquals(0, new ABIDecoder(f.getResult().copyOfTransactionOutput().orElseThrow()).decodeOneInteger());
}
}
private static AionAddress deploy(AionAddress deployer, TestingState kernel, byte[] txData) {
Transaction tx1 = AvmTransactionUtil.create(deployer, kernel.getNonce(deployer), BigInteger.ZERO, txData, 5_000_000, 1);
TransactionResult result = avm.run(kernel, new Transaction[] { tx1 }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedertTrue(result.transactionStatus.isSuccess());
return new AionAddress(result.copyOfTransactionOutput().orElseThrow());
}
private static TransactionResult callDapp(TestingState kernel, AionAddress sender, AionAddress dappAddress, String methodName, ExecutionType executionType, long commonMainchainBlockNumber, Object... args) {
ABIStreamingEncoder encoder = new ABIStreamingEncoder().encodeOneString(methodName);
for (Object arg : args) {
encoder.encodeOneByteArray((byte[]) arg);
}
byte[] data = encoder.toBytes();
Transaction tx = AvmTransactionUtil.call(sender, dappAddress, kernel.getNonce(sender), BigInteger.ZERO, data, 2_000_00, 1);
return avm.run(kernel, new Transaction[] { tx }, executionType, commonMainchainBlockNumber)[0].getResult();
}
}
19
Source : PersistanceNameMappingTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
private void runTestLogic(AvmImpl avm) {
kernel.generateBlock();
// Deploy the contract.
AionAddress contract = deployContract(avm, kernel);
kernel.generateBlock();
// Set all the persistant fields.
callContract(avm, kernel, contract, "setFields");
kernel.generateBlock();
// Verify all the persistant fields have been retained.
callContract(avm, kernel, contract, "verifyFields");
}
19
Source : PerformanceTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
public clreplaced PerformanceTest {
// NOTE: Output is ONLY produced if REPORT is set to true.
private static final boolean REPORT = false;
private TestingState kernel;
private AvmImpl avm;
private static final int transactionBlockSize = 10;
private static final int contextNum = 3;
// We want to use the same number for single and batched calls.
private static final int userDappNum = transactionBlockSize * contextNum;
private static final int heavyLevel = 1;
private static final int allocSize = (1 * (1 << 20));
private static long energyLimit = 1_000_000_000_000_000l;
private static long energyPrice = 1l;
private AionAddress[] userAddrs = new AionAddress[userDappNum];
private AionAddress[] contractAddrs = new AionAddress[userDappNum];
@Before
public void setup() {
this.avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
TestingBlock block = new TestingBlock(new byte[32], 1, Helpers.randomAddress(), System.currentTimeMillis(), new byte[0]);
this.kernel = new TestingState(block);
deploy();
}
/**
* Creating a lot of random userAddrs and the same number of dapps of performance test.
*/
public void deploy() {
long startTime = System.currentTimeMillis();
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(PerformanceTestTarget.clreplaced);
byte[] args = ABIEncoder.encodeOneIntegerArray(new int[] { heavyLevel, allocSize });
byte[] txData = new CodeAndArguments(jar, args).encodeToBytes();
// Deploy
for (int i = 0; i < userDappNum; ++i) {
// creating users
AionAddress userAddress = Helpers.randomAddress();
kernel.createAccount(userAddress);
kernel.adjustBalance(userAddress, BigInteger.TEN.pow(18));
userAddrs[i] = userAddress;
// deploying dapp
Transaction create = AvmTransactionUtil.create(userAddress, kernel.getNonce(userAddress), BigInteger.ZERO, txData, energyLimit, energyPrice);
TransactionResult createResult = avm.run(this.kernel, new Transaction[] { create }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(createResult.transactionStatus.isSuccess());
AionAddress contractAddr = new AionAddress(createResult.copyOfTransactionOutput().orElseThrow());
contractAddrs[i] = contractAddr;
}
long endTime = System.currentTimeMillis();
long timeElapsed = endTime - startTime;
if (REPORT) {
System.out.printf("deploy: %d ms\n", timeElapsed);
}
}
@After
public void tearDown() {
this.avm.shutdown();
}
@Test
public void testPerformanceCpuNto1Single() throws Exception {
performanceTestSingle("cpuHeavy", true, "testPerformanceCpuNto1Single");
}
@Test
public void testPerformanceCpuNtoNSingle() throws Exception {
performanceTestSingle("cpuHeavy", false, "testPerformanceCpuNtoNSingle");
}
@Test
public void testPerformanceMemoryNto1Single() throws Exception {
performanceTestSingle("memoryHeavy", true, "testPerformanceMemoryNto1Single");
}
@Test
public void testPerformanceMemoryNtoNSingle() throws Exception {
performanceTestSingle("memoryHeavy", false, "testPerformanceMemoryNtoNSingle");
}
public void performanceTestSingle(String methodName, boolean Nto1, String testName) {
long startTime = System.currentTimeMillis();
for (int i = 0; i < userDappNum; ++i) {
callSingle(userAddrs[i], Nto1 ? contractAddrs[0] : contractAddrs[i], methodName);
}
long endTime = System.currentTimeMillis();
long timeElapsed = endTime - startTime;
if (REPORT) {
System.out.printf("%s: %d ms\n", testName, timeElapsed);
}
}
private void callSingle(AionAddress sender, AionAddress contractAddr, String methodName) {
byte[] argData = new ABIStreamingEncoder().encodeOneString(methodName).toBytes();
Transaction call = AvmTransactionUtil.call(sender, contractAddr, kernel.getNonce(sender), BigInteger.ZERO, argData, energyLimit, energyPrice);
TransactionResult result = avm.run(this.kernel, new Transaction[] { call }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
}
/**
* One transaction context contains a lot of transactions.
*/
@Test
public void testPerformanceCpuNto1Batch() throws Exception {
performanceBatch("cpuHeavy", true, "testPerformanceCpuNto1Batch");
}
@Test
public void testPerformanceCpuNtoNBatch() throws Exception {
performanceBatch("cpuHeavy", false, "testPerformanceCpuNtoNBatch");
}
@Test
public void testPerformanceMemoryNto1Batch() throws Exception {
performanceBatch("memoryHeavy", true, "testPerformanceMemoryNto1Batch");
}
@Test
public void testPerformanceMemoryNtoNBatch() throws Exception {
performanceBatch("memoryHeavy", false, "testPerformanceMemoryNtoNBatch");
}
public void performanceBatch(String methodName, boolean Nto1, String testName) {
long startTime = System.currentTimeMillis();
callBatch(methodName, Nto1);
long endTime = System.currentTimeMillis();
long timeElapsed = endTime - startTime;
if (REPORT) {
System.out.printf("%s: %d ms\n", testName, timeElapsed);
}
}
public void callBatch(String methodName, boolean Nto1) {
byte[] argData = new ABIStreamingEncoder().encodeOneString(methodName).toBytes();
for (int j = 0; j < contextNum; ++j) {
Transaction[] transactionArray = new Transaction[transactionBlockSize];
for (int i = 0; i < transactionBlockSize; ++i) {
AionAddress sender = userAddrs[i];
AionAddress contractAddr = Nto1 ? contractAddrs[0] : contractAddrs[i];
transactionArray[i] = AvmTransactionUtil.call(sender, contractAddr, kernel.getNonce(sender), BigInteger.ZERO, argData, energyLimit, energyPrice);
}
FutureResult[] futures = avm.run(this.kernel, transactionArray, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1);
for (FutureResult future : futures) {
TransactionResult result = future.getResult();
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
// These should all return an empty byte[] (void).
replacedert.replacedertEquals(0, result.copyOfTransactionOutput().orElseThrow().length);
}
}
}
}
19
Source : ExceptionWrappingIntegrationTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
private int callReturnInt(TestingBlock block, TestingState kernel, AvmImpl avm, AionAddress contractAddr, String methodName) {
byte[] result = commonSuccessCall(block, kernel, avm, contractAddr, methodName);
return new ABIDecoder(result).decodeOneInteger();
}
19
Source : ExceptionWrappingIntegrationTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
private byte[] callReturnByteArray(TestingBlock block, TestingState kernel, AvmImpl avm, AionAddress contractAddr, String methodName) {
byte[] result = commonSuccessCall(block, kernel, avm, contractAddr, methodName);
return new ABIDecoder(result).decodeOneByteArray();
}
19
Source : EnergyUsageDebugModeTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
/**
* Difference of energy consumption explained more in issue-345
*/
public clreplaced EnergyUsageDebugModeTest {
private static TestingState kernel;
private static AionAddress deployer = TestingState.PREMINED_ADDRESS;
@BeforeClreplaced
public static void setup() {
TestingBlock block = new TestingBlock(new byte[32], 1, Helpers.randomAddress(), System.currentTimeMillis(), new byte[0]);
kernel = new TestingState(block);
}
/**
* since the debug mode's code blocks are smaller than the normal mode, the energy consumed after throwing an exception (in debug mode) is less
*/
@Test
public void testEnergyConsumptionDivisionFunction() {
long debugEnergyUsageDivision = testEnergyUsedInDebugMode(10, 0);
long normalEnergyUsageDivision = testEnergyUsedInNormalMode(10, 0);
replacedertTrue(debugEnergyUsageDivision < normalEnergyUsageDivision);
}
/**
* since the debug mode's code blocks are smaller, only what is executed will be billed.
* Thus the faster the exception is thrown, the lower the energy consumption.
*/
@Test
public void testEnergyConsumptionInDebug() {
long debugEnergyUsageFailEarly = testEnergyUsedInDebugMode(10, 0);
long debugEnergyUsageFailLate = testEnergyUsedInDebugMode(0, 10);
replacedertTrue(debugEnergyUsageFailEarly < debugEnergyUsageFailLate);
}
private long testEnergyUsedInDebugMode(int a, int b) {
AvmConfiguration config = new AvmConfiguration();
config.preserveDebuggability = true;
config.enableVerboseContractErrors = true;
AvmImpl avmDebugMode = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), config);
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(EnergyUsageDebugModeTarget.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
long energyPrice = 1l;
// deploy in debugMode Mode
Transaction create = AvmTransactionUtil.create(deployer, kernel.getNonce(deployer), BigInteger.ZERO, txData, 10_000_000l, energyPrice);
TransactionResult createResult = avmDebugMode.run(kernel, new Transaction[] { create }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(createResult.transactionStatus.isSuccess());
AionAddress contractAddressDebug = new AionAddress(createResult.copyOfTransactionOutput().orElseThrow());
long energyLimit = 1_000_000l;
byte[] argData = encodeTryToDivideInteger(a, b);
Transaction call = AvmTransactionUtil.call(deployer, contractAddressDebug, kernel.getNonce(deployer), BigInteger.ZERO, argData, energyLimit, 1l);
TransactionResult result = avmDebugMode.run(kernel, new Transaction[] { call }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
replacedert.replacedertEquals(111, new BigInteger(result.copyOfTransactionOutput().orElseThrow()).intValue());
avmDebugMode.shutdown();
return result.energyUsed;
}
private long testEnergyUsedInNormalMode(int a, int b) {
AvmImpl avmNormalMode = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(EnergyUsageDebugModeTarget.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
long energyLimit = 1_000_000l;
long energyPrice = 1l;
// deploy in normal Mode
Transaction create = AvmTransactionUtil.create(deployer, kernel.getNonce(deployer), BigInteger.ZERO, txData, 10_000_000l, energyPrice);
TransactionResult createResult = avmNormalMode.run(kernel, new Transaction[] { create }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(createResult.transactionStatus.isSuccess());
AionAddress contractAddressNormal = new AionAddress(createResult.copyOfTransactionOutput().orElseThrow());
byte[] argData = encodeTryToDivideInteger(a, b);
Transaction call = AvmTransactionUtil.call(deployer, contractAddressNormal, kernel.getNonce(deployer), BigInteger.ZERO, argData, energyLimit, 1l);
TransactionResult result = avmNormalMode.run(kernel, new Transaction[] { call }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(result.transactionStatus.isSuccess());
replacedert.replacedertEquals(111, new BigInteger(result.copyOfTransactionOutput().orElseThrow()).intValue());
avmNormalMode.shutdown();
return result.energyUsed;
}
private static byte[] encodeTryToDivideInteger(int a, int b) {
return new ABIStreamingEncoder().encodeOneString("tryToDivideInteger").encodeOneInteger(a).encodeOneInteger(b).toBytes();
}
}
19
Source : ConstantLoadingIntegrationTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
@Test
public void testPersistence() throws Exception {
AionAddress contractAddr = deploy();
// Run the creation and then test the read calls.
callStatic(contractAddr, 0);
callStatic(contractAddr, 1);
int bareHash = 64;
int bareLength = 6;
int populateHash = 67;
int populateLength = 3;
byte[] bare = callStatic(contractAddr, 2);
byte[] populated = callStatic(contractAddr, 3);
replacedert.replacedertEquals((byte) bareHash, bare[0]);
replacedert.replacedertEquals((byte) bareLength, bare[1]);
replacedert.replacedertEquals((byte) populateHash, populated[0]);
replacedert.replacedertEquals((byte) populateLength, populated[1]);
}
19
Source : ConstantLoadingIntegrationTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
@Test
public void testCreation() throws Exception {
AionAddress contractAddr = deploy();
// Test just the creation modes.
int bareHash = 64;
int bareLength = 6;
int populateHash = 67;
int populateLength = 3;
byte[] bare = callStatic(contractAddr, 0);
byte[] populated = callStatic(contractAddr, 1);
replacedert.replacedertEquals((byte) bareHash, bare[0]);
replacedert.replacedertEquals((byte) bareLength, bare[1]);
replacedert.replacedertEquals((byte) populateHash, populated[0]);
replacedert.replacedertEquals((byte) populateLength, populated[1]);
}
19
Source : ConstantBillingTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
public clreplaced ConstantBillingTest {
private static AionAddress deployer = TestingState.PREMINED_ADDRESS;
private static long energyLimit = 1_000_000;
@Test
public void test() {
byte[] jar = JarBuilder.buildJarForMainClreplacedAndExplicitClreplacedNamesAndBytecode(ConstantBillingTarget.clreplaced, Collections.emptyMap());
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
TestingBlock block = new TestingBlock(new byte[32], 1, Helpers.randomAddress(), System.currentTimeMillis(), new byte[0]);
IExternalState externalState = new TestingState(block);
Transaction tx = AvmTransactionUtil.create(deployer, externalState.getNonce(deployer), BigInteger.ZERO, new CodeAndArguments(jar, new byte[0]).encodeToBytes(), energyLimit, 1);
TransactionResult result = avm.run(externalState, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, externalState.getBlockNumber() - 1)[0].getResult();
replacedertTrue(result.transactionStatus.isSuccess());
BytecodeFeeScheduler feeScheduler = new BytecodeFeeScheduler();
feeScheduler.initialize();
// See AKI-136: static instrumentation code is no longer billed, so we charge for an ldc + putstatic in the clinit now (replacedigning constant to static field)
// rather than a getstatic + putstatic (fetching the constant from our constant instrumentation clreplaced)
long ldcFee = feeScheduler.getFee(Opcodes.LDC);
long putstaticFee = feeScheduler.getFee(Opcodes.PUTSTATIC);
long returnFee = feeScheduler.getFee(Opcodes.RETURN);
long clinitCost = ldcFee + putstaticFee + returnFee;
long basicTransactionCost = BillingRules.getBasicTransactionCost(tx.copyOfTransactionData());
long deploymentFee = BillingRules.getDeploymentFee(1, jar.length);
long storageFee = 141;
long cost = basicTransactionCost + deploymentFee + clinitCost + storageFee;
replacedertEquals(cost, result.energyUsed);
avm.shutdown();
}
}
19
Source : AionCollectionPerfTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
public clreplaced AionCollectionPerfTest {
// NOTE: Output is ONLY produced if REPORT is set to true.
private static final boolean REPORT = false;
private AionAddress from = TestingState.PREMINED_ADDRESS;
private TestingBlock block = new TestingBlock(new byte[32], 1, Helpers.randomAddress(), System.currentTimeMillis(), new byte[0]);
private long energyLimit = 100_000_000L;
private long energyPrice = 1;
private byte[] buildListPerfJar() {
return UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(AionListPerfContract.clreplaced);
}
private byte[] buildSetPerfJar() {
return UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(AionSetPerfContract.clreplaced);
}
private byte[] buildMapPerfJar() {
return UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(AionMapPerfContract.clreplaced);
}
private TransactionResult deploy(IExternalState externalState, AvmImpl avm, byte[] testJar) {
byte[] testWalletArguments = new byte[0];
Transaction createTransaction = AvmTransactionUtil.create(from, externalState.getNonce(from), BigInteger.ZERO, new CodeAndArguments(testJar, testWalletArguments).encodeToBytes(), energyLimit, energyPrice);
TransactionResult createResult = avm.run(externalState, new Transaction[] { createTransaction }, ExecutionType.replacedUME_MAINCHAIN, externalState.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(createResult.transactionStatus.isSuccess());
return createResult;
}
private TransactionResult call(IExternalState externalState, AvmImpl avm, AionAddress contract, AionAddress sender, byte[] args) {
Transaction callTransaction = AvmTransactionUtil.call(sender, contract, externalState.getNonce(sender), BigInteger.ZERO, args, energyLimit, 1l);
TransactionResult callResult = avm.run(externalState, new Transaction[] { callTransaction }, ExecutionType.replacedUME_MAINCHAIN, externalState.getBlockNumber() - 1)[0].getResult();
replacedert.replacedertTrue(callResult.transactionStatus.isSuccess());
return callResult;
}
@Test
public void testList() {
report(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
report(">> Energy measurement for AionList");
byte[] args;
IExternalState externalState = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
TransactionResult deployRes = deploy(externalState, avm, buildListPerfJar());
AionAddress contract = new AionAddress(deployRes.copyOfTransactionOutput().orElseThrow());
args = encodeNoArgsMethodCall("callInit");
TransactionResult initResult = call(externalState, avm, contract, from, args);
replacedert.replacedertTrue(initResult.transactionStatus.isSuccess());
args = encodeNoArgsMethodCall("callAppend");
TransactionResult appendResult = call(externalState, avm, contract, from, args);
report(">> Append : " + appendResult.energyUsed / AionListPerfContract.SIZE);
args = encodeNoArgsMethodCall("callInit");
call(externalState, avm, contract, from, args);
args = encodeNoArgsMethodCall("callInsertHead");
TransactionResult insertHeadResult = call(externalState, avm, contract, from, args);
report(">> Insert Head : " + insertHeadResult.energyUsed / AionListPerfContract.SIZE);
args = encodeNoArgsMethodCall("callInit");
call(externalState, avm, contract, from, args);
args = encodeNoArgsMethodCall("callInsertMiddle");
TransactionResult insertMiddleResult = call(externalState, avm, contract, from, args);
report(">> Insert Middle : " + insertMiddleResult.energyUsed / AionListPerfContract.SIZE);
report("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
avm.shutdown();
}
@Test
public void testSet() {
report(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
report(">> Energy measurement for AionSet");
byte[] args;
IExternalState externalState = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
TransactionResult deployRes = deploy(externalState, avm, buildSetPerfJar());
AionAddress contract = new AionAddress(deployRes.copyOfTransactionOutput().orElseThrow());
args = encodeNoArgsMethodCall("callInit");
TransactionResult initResult = call(externalState, avm, contract, from, args);
replacedert.replacedertTrue(initResult.transactionStatus.isSuccess());
args = encodeNoArgsMethodCall("callAdd");
TransactionResult addResult = call(externalState, avm, contract, from, args);
report(">> Add : " + addResult.energyUsed / AionSetPerfContract.SIZE);
args = encodeNoArgsMethodCall("callContains");
TransactionResult containsResult = call(externalState, avm, contract, from, args);
report(">> Contains : " + containsResult.energyUsed / AionSetPerfContract.SIZE);
args = encodeNoArgsMethodCall("callRemove");
TransactionResult removeReult = call(externalState, avm, contract, from, args);
report(">> Remove : " + removeReult.energyUsed / AionSetPerfContract.SIZE);
report("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
report(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
report(">> Energy measurement for AionPlainSet");
args = encodeNoArgsMethodCall("callInitB");
initResult = call(externalState, avm, contract, from, args);
args = encodeNoArgsMethodCall("callAddB");
addResult = call(externalState, avm, contract, from, args);
report(">> Add : " + addResult.energyUsed / AionSetPerfContract.SIZE);
args = encodeNoArgsMethodCall("callContainsB");
containsResult = call(externalState, avm, contract, from, args);
report(">> Contains : " + containsResult.energyUsed / AionSetPerfContract.SIZE);
args = encodeNoArgsMethodCall("callRemoveB");
removeReult = call(externalState, avm, contract, from, args);
report(">> Remove : " + removeReult.energyUsed / AionSetPerfContract.SIZE);
report("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
avm.shutdown();
}
@Test
public void testMap() {
report(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
report(">> Energy measurement for AionMap");
byte[] args;
IExternalState externalState = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
TransactionResult deployRes = deploy(externalState, avm, buildMapPerfJar());
AionAddress contract = new AionAddress(deployRes.copyOfTransactionOutput().orElseThrow());
args = encodeNoArgsMethodCall("callInit");
TransactionResult initResult = call(externalState, avm, contract, from, args);
replacedert.replacedertTrue(initResult.transactionStatus.isSuccess());
args = encodeNoArgsMethodCall("callPut");
TransactionResult putResult = call(externalState, avm, contract, from, args);
report(">> Put : " + putResult.energyUsed / AionMapPerfContract.SIZE);
args = encodeNoArgsMethodCall("callGet");
TransactionResult getResult = call(externalState, avm, contract, from, args);
report(">> Get : " + getResult.energyUsed / AionMapPerfContract.SIZE);
args = encodeNoArgsMethodCall("callRemove");
TransactionResult removeResult = call(externalState, avm, contract, from, args);
report(">> Remove : " + removeResult.energyUsed / AionMapPerfContract.SIZE);
report("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
report(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
report(">> Energy measurement for AionPlainMap");
args = encodeNoArgsMethodCall("callInitB");
initResult = call(externalState, avm, contract, from, args);
args = encodeNoArgsMethodCall("callPutB");
putResult = call(externalState, avm, contract, from, args);
report(">> Put : " + putResult.energyUsed / AionMapPerfContract.SIZE);
args = encodeNoArgsMethodCall("callGetB");
getResult = call(externalState, avm, contract, from, args);
report(">> Get : " + getResult.energyUsed / AionMapPerfContract.SIZE);
args = encodeNoArgsMethodCall("callRemoveB");
removeResult = call(externalState, avm, contract, from, args);
report(">> Remove : " + removeResult.energyUsed / AionMapPerfContract.SIZE);
report("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
avm.shutdown();
}
private static byte[] encodeNoArgsMethodCall(String methodName) {
return new ABIStreamingEncoder().encodeOneString(methodName).toBytes();
}
private static void report(String output) {
if (REPORT) {
System.out.println(output);
}
}
}
19
Source : ContractBalanceTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
private Address getContractAsAbiAddress(AionAddress contract) {
return new Address(contract.toByteArray());
}
19
Source : AvmImplTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
public clreplaced AvmImplTest {
private static AionAddress deployer = TestingState.PREMINED_ADDRESS;
private static TestingBlock block;
@Rule
public TemporaryFolder folder = new TemporaryFolder();
@BeforeClreplaced
public static void setupClreplaced() {
block = new TestingBlock(new byte[32], 1, Helpers.randomAddress(), System.currentTimeMillis(), new byte[0]);
}
@Test
public void testStateUpdates() {
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
AionAddress from = deployer;
AionAddress to = new AionAddress(new byte[32]);
BigInteger value = BigInteger.valueOf(1000L);
byte[] data = "data".getBytes();
long energyLimit = 50_000L;
long energyPrice = 1L;
Transaction tx = AvmTransactionUtil.call(from, to, kernel.getNonce(from), value, data, energyLimit, energyPrice);
TransactionResult result = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
// verify results
replacedertTrue(result.transactionStatus.isSuccess());
replacedertFalse(result.copyOfTransactionOutput().isPresent());
replacedertEquals(BillingRules.getBasicTransactionCost(tx.copyOfTransactionData()), result.energyUsed);
replacedertEquals(0, result.logs.size());
replacedertEquals(0, result.internalTransactions.size());
// verify state change
replacedertEquals(1, kernel.getNonce(from).intValue());
replacedertEquals(TestingState.PREMINED_AMOUNT.subtract(value).subtract(BigInteger.valueOf(BillingRules.getBasicTransactionCost(tx.copyOfTransactionData()) * energyPrice)), kernel.getBalance(deployer));
replacedertEquals(0, kernel.getNonce(to).intValue());
replacedertEquals(value, kernel.getBalance(to));
avm.shutdown();
}
@Test(expected = IllegalArgumentException.clreplaced)
public void testTransactionWithoutSignBytes() {
TestingState kernel = new TestingState(block);
AionAddress from = deployer;
AionAddress to = new AionAddress(new byte[32]);
// large value that caused issues when not specifically interpreted as a positive integer
BigInteger value = BigInteger.valueOf(13).multiply(BigInteger.TEN.pow(18));
byte[] data = new byte[0];
long energyLimit = 50_000L;
long energyPrice = 1L;
// Verifies that we cannot create a transaction with a negative nonce/value.
AvmTransactionUtil.call(from, to, new BigInteger(omitSignByte(kernel.getNonce(from).toByteArray())), new BigInteger(omitSignByte(value.toByteArray())), data, energyLimit, energyPrice);
}
/**
* Omits sign indication byte. Used by the Aion kernel.
*/
public static byte[] omitSignByte(byte[] data) {
if (data == null) {
return null;
}
if (data.length != 1 && data[0] == 0) {
byte[] tmp = new byte[data.length - 1];
System.arraycopy(data, 1, tmp, 0, tmp.length);
data = tmp;
}
return data;
}
@Test
public void checkMainClreplacedHasProperName() throws IOException {
byte[] jar = JarBuilder.buildJarForMainClreplacedAndExplicitClreplacedNamesAndBytecode(MainClreplaced.clreplaced, Collections.emptyMap());
final RawDappModule dappModule = RawDappModule.readFromJar(jar, false, true);
final String mainClreplacedName = MainClreplaced.clreplaced.getName();
replacedertEquals(mainClreplacedName, dappModule.mainClreplaced);
Map<String, byte[]> clreplacedes = dappModule.clreplacedes;
replacedertEquals(1, clreplacedes.size());
}
@Test
public void testJvmError() {
// Note that we eventually need to test how this interacts with AvmImpl's contract entry-point but this at least proves
// that the hierarchy is correctly put together.
String result = null;
try {
throw new JvmError(new UnknownError("testing"));
} catch (AvmThrowable e) {
result = e.getMessage();
}
replacedertEquals("java.lang.UnknownError: testing", result);
}
/**
* Tests that, if we hit the energy limit, we continue to hit it on every attempt to charge for a new code block.
*/
@Test
public void testPersistentEnergyLimit() {
// Set up the runtime (note that we need to initialize the NodeEnvironment before we attach to the thread)..
Map<String, byte[]> contractClreplacedes = Helpers.mapIncludingHelperBytecode(Collections.emptyMap(), Helpers.loadDefaultHelperBytecode());
AvmClreplacedLoader avmClreplacedLoader = NodeEnvironment.singleton.createInvocationClreplacedLoader(contractClreplacedes);
IRuntimeSetup runtimeSetup = new Helper();
IInstrumentation instrumentation = new CommonInstrumentation();
InstrumentationHelpers.attachThread(instrumentation);
InstrumentationHelpers.pushNewStackFrame(runtimeSetup, avmClreplacedLoader, 5L, 1, null);
// Prove that we can charge 0 without issue.
instrumentation.chargeEnergy(0);
replacedertEquals(5, instrumentation.energyLeft());
// Run the test.
int catchCount = 0;
OutOfEnergyException error = null;
try {
instrumentation.chargeEnergy(10);
} catch (OutOfEnergyException e) {
catchCount += 1;
error = e;
}
// We didn't reset the state so this should still fail.
try {
instrumentation.chargeEnergy(0);
} catch (OutOfEnergyException e) {
catchCount += 1;
// And have the same exception.
replacedertEquals(error, e);
}
replacedertEquals(2, catchCount);
InstrumentationHelpers.popExistingStackFrame(runtimeSetup);
InstrumentationHelpers.detachThread(instrumentation);
}
@Test
public void testHelperStateRestore() {
byte[] jar = JarBuilder.buildJarForMainClreplacedAndExplicitClreplacedNamesAndBytecode(AvmImplTestResource.clreplaced, Collections.emptyMap());
byte[] arguments = new byte[0];
byte[] txData = new CodeAndArguments(jar, arguments).encodeToBytes();
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
// deploy
long energyLimit = 1_000_000l;
long energyPrice = 1l;
Transaction tx1 = AvmTransactionUtil.create(deployer, kernel.getNonce(deployer), BigInteger.ZERO, txData, energyLimit, energyPrice);
TransactionResult result1 = avm.run(kernel, new Transaction[] { tx1 }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedertTrue(result1.transactionStatus.isSuccess());
AionAddress contractAddr = new AionAddress(result1.copyOfTransactionOutput().orElseThrow());
// Account for the cost: deployment, clinit, init call.
long basicCost = BillingRules.getBasicTransactionCost(txData);
long codeInstantiationOfDeploymentFee = BillingRules.getDeploymentFee(1, jar.length);
// Note that the only <clinit> is in the generated constants clreplaced, which is free.
long clinitCost = 0L;
long initialStorageCost = 222;
long transactionCost = basicCost + codeInstantiationOfDeploymentFee + clinitCost + initialStorageCost;
replacedertEquals(transactionCost, result1.energyUsed);
// call (1 -> 2 -> 2)
long transaction2EnergyLimit = 1_000_000l;
Transaction tx2 = AvmTransactionUtil.call(deployer, contractAddr, kernel.getNonce(deployer), BigInteger.ZERO, contractAddr.toByteArray(), transaction2EnergyLimit, energyPrice);
TransactionResult result2 = avm.run(kernel, new Transaction[] { tx2 }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedertTrue(result2.transactionStatus.isSuccess());
replacedertArrayEquals("CALL".getBytes(), result2.copyOfTransactionOutput().orElseThrow());
// Account for the cost: (blocks in call method) + runtime.call
// code block cost for initial call
long costOfBlocks = 51l + 31l + 333l;
// reentrant call cost including code block cost
long costOfRuntimeCall = 51l + 31l + 61l + (100 + 630);
// All persistence load/store cost (note that this is a reentrant call): (2 reads at 74, 2 writes at 222)
long runStorageCost = 74 + 74 + 222 + 222;
// runtime cost of the initial call
long runtimeCost = 100 + 100 + 300 + 100 + 300 + 5000 + 620;
transactionCost = runtimeCost + BillingRules.getBasicTransactionCost(tx2.copyOfTransactionData()) + costOfBlocks + costOfRuntimeCall + runStorageCost;
// NOTE: the numbers are not calculated, but for fee schedule change detection.
replacedertEquals(transactionCost, result2.energyUsed);
avm.shutdown();
}
@Test
public void testNullReturnCrossCall() {
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(ReentrantCrossCallResource.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
// deploy
AionAddress contractAddr = createDApp(kernel, avm, txData);
// Call the callSelfForNull entry-point and it should return null to us.
byte[] argData = encodeNoArgCall("callSelfForNull");
callDAppVoid(kernel, avm, contractAddr, argData);
avm.shutdown();
}
@Test
public void testRecursiveHashCode() {
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(ReentrantCrossCallResource.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
// deploy
long energyLimit = 10_000_000l;
AionAddress contractAddr = createDApp(kernel, avm, txData);
// Try a few invocations of different depths, bearing in mind the change of nextHashCode between each invocation.
// We will do 2 zero-depth calls to see the delta between the 2 calls.
// Then, we will do an indirect call and verify that the delta is greater.
// If the hashcode wasn't restored across reentrant calls, this wouldn't be greater as it wouldn't capture the small cost of the original
// indirect call (since we create at least 1 object in that path).
int zero0 = callRecursiveHash(kernel, avm, energyLimit, contractAddr, 0);
int zero1 = callRecursiveHash(kernel, avm, energyLimit, contractAddr, 0);
int zero2 = callRecursiveHash(kernel, avm, energyLimit, contractAddr, 0);
int one0 = callRecursiveHash(kernel, avm, energyLimit, contractAddr, 1);
int one1 = callRecursiveHash(kernel, avm, energyLimit, contractAddr, 1);
int one2 = callRecursiveHash(kernel, avm, energyLimit, contractAddr, 1);
replacedertEquals(zero1 - zero0, zero2 - zero1);
replacedertEquals(one1 - one0, one2 - one1);
replacedertTrue((one1 - one0) > (zero1 - zero0));
avm.shutdown();
}
/**
* Tests that reentrant calls do have detectable side-effects within the caller's space, when they commit.
*/
@Test
public void testCommitReentrantCalls() {
boolean shouldFail = false;
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(ReentrantCrossCallResource.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
// deploy
AionAddress contractAddr = createDApp(kernel, avm, txData);
// Get direct increments from 1 to 2 and returns 2.
replacedertEquals(2, callReentrantAccess(kernel, avm, contractAddr, "getDirect", shouldFail));
// Get near increments from 1 to 2 and returns 2.
replacedertEquals(2, callReentrantAccess(kernel, avm, contractAddr, "getNear", shouldFail));
// Get far increments from 1 to 2 and returns 2.
replacedertEquals(2, callReentrantAccess(kernel, avm, contractAddr, "getFar", shouldFail));
// Get near increments from 2 to 3 and returns 3.
replacedertEquals(3, callReentrantAccess(kernel, avm, contractAddr, "getNear", shouldFail));
avm.shutdown();
}
/**
* Tests that reentrant calls do NOT have detectable side-effects within the caller's space, when they rollback.
*/
@Test
public void testRollbackReentrantCalls() {
boolean shouldFail = true;
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(ReentrantCrossCallResource.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
// deploy
AionAddress contractAddr = createDApp(kernel, avm, txData);
// We expect these to all fail, so they should be left with the initial values: 1.
replacedertEquals(1, callReentrantAccess(kernel, avm, contractAddr, "getDirect", shouldFail));
replacedertEquals(1, callReentrantAccess(kernel, avm, contractAddr, "getNear", shouldFail));
replacedertEquals(1, callReentrantAccess(kernel, avm, contractAddr, "getFar", shouldFail));
replacedertEquals(1, callReentrantAccess(kernel, avm, contractAddr, "getNear", shouldFail));
avm.shutdown();
}
/**
* Tests that reentrant calls do not accidentally write-back the statics, even when the caller fails.
*/
@Test
public void testRollbackAfterReentrantSuccess() {
boolean shouldFail = true;
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(ReentrantCrossCallResource.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
// deploy
long energyLimit = 1_000_000l;
AionAddress contractAddr = createDApp(kernel, avm, txData);
// Cause the failure.
byte[] nearData = encodeNoArgCall("localFailAfterReentrant");
Transaction tx = AvmTransactionUtil.call(deployer, contractAddr, kernel.getNonce(deployer), BigInteger.ZERO, nearData, energyLimit, 1L);
TransactionResult result2 = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedertEquals(AvmInternalError.FAILED_OUT_OF_ENERGY.error, result2.transactionStatus.causeOfError);
// We shouldn't see any changes, since this failed.
// We expect these to all fail, so they should be left with the initial values: 1.
replacedertEquals(1, callReentrantAccess(kernel, avm, contractAddr, "getDirect", shouldFail));
replacedertEquals(1, callReentrantAccess(kernel, avm, contractAddr, "getNear", shouldFail));
replacedertEquals(1, callReentrantAccess(kernel, avm, contractAddr, "getFar", shouldFail));
replacedertEquals(1, callReentrantAccess(kernel, avm, contractAddr, "getNear", shouldFail));
avm.shutdown();
}
/**
* Tests that reentrant calls do not leave any side-effects within the caller's space when the rollback only during the last part of write-back.
*/
@Test
public void testReentrantRollbackDuringCommit() {
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(ReentrantCrossCallResource.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
// deploy
AionAddress contractAddr = createDApp(kernel, avm, txData);
// We just want to call our special getFar helper with a constrained energy.
// WARNING: This test is very sensitive to storage billing configuration so the energy limit likely needs to be updated when that changes.
// The write-back of the callee attempts to write statics and 2 instances. We want it to fail at 1 instance (14_400L seems to do this).
long failingLimit = 14_400L;
byte[] callData = encodeCallLong("getFarWithEnergy", failingLimit);
boolean result = callDAppBoolean(kernel, avm, contractAddr, callData);
// This returns false since the value didn't change,
replacedertEquals(false, result);
avm.shutdown();
}
/**
* Tests that inner clreplacedes are correctly handled by reentrant calls.
* Also ensures that instances reachable from statics are correctly handled to arbitrary recursive depth.
*/
@Test
public void testReentrantRecursiveNested() {
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(ReentrantCrossCallResource.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
// deploy
AionAddress contractAddr = createDApp(kernel, avm, txData);
// We just want to call our special getFar helper with a constrained energy.
// WARNING: This test is very sensitive to storage billing configuration so the energy limit likely needs to be updated when that changes.
// The write-back of the callee attempts to write statics and 2 instances. We want it to fail at 1 instance (20_000L seems to do this).
byte[] callData = encodeCallIntInt("recursiveChangeNested", 0, 5);
int result = callDAppInteger(kernel, avm, contractAddr, callData);
// We don't want to depend on a specific hashcode (appears to be 19) but just the idea that it needs to be non-zero.
replacedertTrue(0 != result);
avm.shutdown();
}
/**
* Tests that the internal call depth limit is in effect; aka, "CallDepthLimitExceededException"
* is thrown once the limit is reached.
*/
@Test
public void testCallDepthLimit() {
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(ReentrantCrossCallResource.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
// deploy
AionAddress contractAddr = createDApp(kernel, avm, txData);
// Verify the internal call depth limit is in effect.
byte[] callData = encodeCallIntInt("recursiveChangeNested", 0, 10);
Transaction tx = AvmTransactionUtil.call(deployer, contractAddr, kernel.getNonce(deployer), BigInteger.ZERO, callData, 20_000_000l, 1L);
TransactionResult result2 = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedertEquals(AvmInternalError.FAILED_EXCEPTION.error, result2.transactionStatus.causeOfError);
avm.shutdown();
}
/**
* Tests that a DApp can CREATE and then CALL another instance.
*/
@Test
public void testCreateAndCallSubApp() {
byte incrementBy = 2;
byte[] incrementorJar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(IncrementorDApp.clreplaced);
byte[] incrementorCreateData = new CodeAndArguments(incrementorJar, new byte[] { incrementBy }).encodeToBytes();
byte[] spawnerJar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(SpawnerDApp.clreplaced);
byte[] spanerCreateData = new CodeAndArguments(spawnerJar, incrementorCreateData).encodeToBytes();
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
// CREATE the spawner.
AionAddress spawnerAddress = createDApp(kernel, avm, spanerCreateData);
// CALL to create and invoke the incrementor.
byte[] input = new byte[] { 1, 2, 3, 4, 5 };
byte[] incrementorCallData = encodeCallByteArray("incrementArray", input);
byte[] spawnerCallData = encodeCallByteArray("spawnAndCall", incrementorCallData);
byte[] incrementorResult = callDAppByteArray(kernel, avm, spawnerAddress, spawnerCallData);
// We double-encoded the arguments, so double-decode the response.
byte[] spawnerResult = new ABIDecoder(incrementorResult).decodeOneByteArray();
replacedertEquals(input.length, spawnerResult.length);
for (int i = 0; i < input.length; ++i) {
replacedertEquals(incrementBy + input[i], spawnerResult[i]);
}
avm.shutdown();
}
/**
* Tests that a DApp can CREATE for us.
*/
@Test
public void testCreateSubAppCall() {
byte incrementBy = 3;
byte[] incrementorJar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(IncrementorDApp.clreplaced);
byte[] incrementorCreateData = new CodeAndArguments(incrementorJar, new byte[] { incrementBy }).encodeToBytes();
byte[] spawnerJar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(SpawnerDApp.clreplaced);
byte[] spanerCreateData = new CodeAndArguments(spawnerJar, incrementorCreateData).encodeToBytes();
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
// CREATE the spawner.
AionAddress spawnerAddress = createDApp(kernel, avm, spanerCreateData);
// CALL to create and invoke the incrementor.
boolean shouldFail = false;
byte[] spawnerCallData = encodeCallBool("spawnOnly", shouldFail);
Address incrementorAddress = callDAppAddress(kernel, avm, spawnerAddress, spawnerCallData);
// Call the incrementor, directly.
byte[] input = new byte[] { 1, 2, 3, 4, 5 };
byte[] incrementorCallData = encodeCallByteArray("incrementArray", input);
byte[] incrementorResult = callDAppByteArray(kernel, avm, new AionAddress(incrementorAddress.toByteArray()), incrementorCallData);
replacedertEquals(input.length, incrementorResult.length);
for (int i = 0; i < input.length; ++i) {
replacedertEquals(incrementBy + input[i], incrementorResult[i]);
}
avm.shutdown();
}
/**
* Tests that a DApp can CREATE for us (but is reverted on failure).
*/
@Test
public void testCreateSubAppCallFailure() {
byte incrementBy = 3;
byte[] incrementorJar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(IncrementorDApp.clreplaced);
byte[] incrementorCreateData = new CodeAndArguments(incrementorJar, new byte[] { incrementBy }).encodeToBytes();
byte[] spawnerJar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(SpawnerDApp.clreplaced);
byte[] spanerCreateData = new CodeAndArguments(spawnerJar, incrementorCreateData).encodeToBytes();
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
// CREATE the spawner.
AionAddress spawnerAddress = createDApp(kernel, avm, spanerCreateData);
// CALL to create and invoke the incrementor.
boolean shouldFail = true;
byte[] spawnerCallData = encodeCallBool("spawnOnly", shouldFail);
long energyLimit = 1_000_000l;
Transaction tx = AvmTransactionUtil.call(TestingState.PREMINED_ADDRESS, spawnerAddress, kernel.getNonce(deployer), BigInteger.ZERO, spawnerCallData, energyLimit, 1L);
TransactionResult result2 = avm.run(kernel, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, kernel.getBlockNumber() - 1)[0].getResult();
replacedertEquals(AvmInternalError.FAILED_INVALID.error, result2.transactionStatus.causeOfError);
avm.shutdown();
}
/**
* Tests that a DApp can CREATE for us, backed by a directory.
* (same as "testCreateSubAppCall" but uses a directory backing-store).
*/
@Test
public void testCreateSubAppCallOnDirectory() throws Exception {
File directory = folder.newFolder();
byte incrementBy = 3;
byte[] incrementorJar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(IncrementorDApp.clreplaced);
byte[] incrementorCreateData = new CodeAndArguments(incrementorJar, new byte[] { incrementBy }).encodeToBytes();
byte[] spawnerJar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(SpawnerDApp.clreplaced);
byte[] spanerCreateData = new CodeAndArguments(spawnerJar, incrementorCreateData).encodeToBytes();
TestingState kernel = new TestingState(directory, block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
// We always start out with the PREMINE account, but that should be the only one.
replacedertEquals(1, directory.listFiles().length);
// CREATE the spawner (meaning another account). Expect 3 accounts because: deployer, contract, coinbase
AionAddress spawnerAddress = createDApp(kernel, avm, spanerCreateData);
replacedertEquals(3, directory.listFiles().length);
// CALL to create and invoke the incrementor. Expect 4 accounts because: deployer, contract1, contract2, coinbase
boolean shouldFail = false;
byte[] spawnerCallData = encodeCallBool("spawnOnly", shouldFail);
Address incrementorAddress = callDAppAddress(kernel, avm, spawnerAddress, spawnerCallData);
replacedertEquals(4, directory.listFiles().length);
// Restart the AVM.
avm.shutdown();
kernel = new TestingState(directory, block);
avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
// Call the incrementor, directly.
byte[] input = new byte[] { 1, 2, 3, 4, 5 };
byte[] incrementorCallData = encodeCallByteArray("incrementArray", input);
byte[] incrementorResult = callDAppByteArray(kernel, avm, new AionAddress(incrementorAddress.toByteArray()), incrementorCallData);
replacedertEquals(input.length, incrementorResult.length);
for (int i = 0; i < input.length; ++i) {
replacedertEquals(incrementBy + input[i], incrementorResult[i]);
}
// Check the state of the directory we are using to back this (4 accounts, 2 with code and 2 with only a balance).
int codeCount = 0;
int balanceCount = 0;
for (File top : directory.listFiles()) {
for (File account : top.listFiles()) {
if ("code".equals(account.getName())) {
codeCount += 1;
} else if ("balance".equals(account.getName())) {
balanceCount += 1;
}
}
}
replacedertEquals(2, codeCount);
replacedertEquals(4, balanceCount);
avm.shutdown();
}
@Test
public void testDeployFailedWithNullMainClreplaced() {
byte[] jar = JarBuilder.buildJarForMainClreplacedAndExplicitClreplacedNamesAndBytecode(null, Collections.emptyMap(), MainClreplaced.clreplaced);
deployInvalidJar(jar);
}
@Test
public void testDeployFailedWithMissingMainClreplaced() {
byte[] jar = JarBuilder.buildJarForExplicitMainAndClreplacedes("NonExistentClreplaced", MainClreplaced.clreplaced);
deployInvalidJar(jar);
}
@Test
public void testDeployFailedWithInvalidMainClreplaced() {
byte[] jar = JarBuilder.buildJarForExplicitMainAndClreplacedes(".Invalid..Clreplaced.....Name", MainClreplaced.clreplaced);
deployInvalidJar(jar);
}
@Test
public void testDeployFailedWithMissingMainMethod() {
byte[] jar = JarBuilder.buildJarForMainClreplacedAndExplicitClreplacedNamesAndBytecode(InterfaceTestResource.clreplaced, Collections.emptyMap(), MainClreplaced.clreplaced);
deployInvalidJar(jar);
}
@Test
public void testDeployFailedWithInvalidMainClreplacedBytecode() {
byte[] jar = JarBuilder.buildJarForExplicitClreplacedNamesAndBytecode("NotAValidClreplaced", new byte[] { 0x1, 0x2, 0x3 }, Collections.emptyMap());
deployInvalidJar(jar);
}
/**
* Tests that a DApp can CREATE from within its own CREATE, so long as we only go 10 levels down (the limit).
*/
@Test
public void testCreateInClinit_success() {
byte[] spawnerCreateData = buildRecursiveCreate(10);
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
TransactionResult createResult = createDAppCanFail(kernel, avm, spawnerCreateData);
replacedertTrue(createResult.transactionStatus.isSuccess());
AionAddress spawnerAddress = new AionAddress(createResult.copyOfTransactionOutput().orElseThrow());
replacedertNotNull(spawnerAddress);
avm.shutdown();
}
/**
* Tests that a DApp can CREATE from within its own CREATE, and fails after 11 levels down (since 10 is the limit).
*/
@Test
public void testCreateInClinit_failure() {
byte[] spawnerCreateData = buildRecursiveCreate(11);
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
TransactionResult createResult = createDAppCanFail(kernel, avm, spawnerCreateData);
// We are ultimately failing due to the replacedertionError the clreplaced triggers if the create fails.
replacedertEquals(AvmInternalError.FAILED_EXCEPTION.error, createResult.transactionStatus.causeOfError);
avm.shutdown();
}
private int callRecursiveHash(IExternalState externalState, AvmImpl avm, long energyLimit, AionAddress contractAddr, int depth) {
byte[] argData = encodeCallInt("getRecursiveHashCode", depth);
Transaction call = AvmTransactionUtil.call(deployer, contractAddr, externalState.getNonce(deployer), BigInteger.ZERO, argData, energyLimit, 1L);
TransactionResult result = avm.run(externalState, new Transaction[] { call }, ExecutionType.replacedUME_MAINCHAIN, externalState.getBlockNumber() - 1)[0].getResult();
replacedertTrue(result.transactionStatus.isSuccess());
return new ABIDecoder(result.copyOfTransactionOutput().orElseThrow()).decodeOneInteger();
}
private int callReentrantAccess(IExternalState externalState, AvmImpl avm, AionAddress contractAddr, String methodName, boolean shouldFail) {
byte[] nearData = encodeCallBool(methodName, shouldFail);
return callDAppInteger(externalState, avm, contractAddr, nearData);
}
private AionAddress createDApp(IExternalState externalState, AvmImpl avm, byte[] createData) {
TransactionResult result1 = createDAppCanFail(externalState, avm, createData);
replacedertTrue(result1.transactionStatus.isSuccess());
return new AionAddress(result1.copyOfTransactionOutput().orElseThrow());
}
private TransactionResult createDAppCanFail(IExternalState externalState, AvmImpl avm, byte[] createData) {
long energyLimit = 10_000_000l;
long energyPrice = 1l;
Transaction tx1 = AvmTransactionUtil.create(deployer, externalState.getNonce(deployer), BigInteger.ZERO, createData, energyLimit, energyPrice);
return avm.run(externalState, new Transaction[] { tx1 }, ExecutionType.replacedUME_MAINCHAIN, externalState.getBlockNumber() - 1)[0].getResult();
}
private void callDAppVoid(IExternalState externalState, AvmImpl avm, AionAddress dAppAddress, byte[] argData) {
byte[] result = callDAppSuccess(externalState, avm, dAppAddress, argData);
replacedertArrayEquals(new byte[0], result);
}
private boolean callDAppBoolean(IExternalState externalState, AvmImpl avm, AionAddress dAppAddress, byte[] argData) {
byte[] result = callDAppSuccess(externalState, avm, dAppAddress, argData);
return new ABIDecoder(result).decodeOneBoolean();
}
private int callDAppInteger(IExternalState externalState, AvmImpl avm, AionAddress dAppAddress, byte[] argData) {
byte[] result = callDAppSuccess(externalState, avm, dAppAddress, argData);
return new ABIDecoder(result).decodeOneInteger();
}
private byte[] callDAppByteArray(IExternalState externalState, AvmImpl avm, AionAddress dAppAddress, byte[] argData) {
byte[] result = callDAppSuccess(externalState, avm, dAppAddress, argData);
return new ABIDecoder(result).decodeOneByteArray();
}
private Address callDAppAddress(IExternalState externalState, AvmImpl avm, AionAddress dAppAddress, byte[] argData) {
byte[] result = callDAppSuccess(externalState, avm, dAppAddress, argData);
return new ABIDecoder(result).decodeOneAddress();
}
private byte[] callDAppSuccess(IExternalState externalState, AvmImpl avm, AionAddress dAppAddress, byte[] argData) {
long energyLimit = 5_000_000l;
Transaction tx = AvmTransactionUtil.call(deployer, dAppAddress, externalState.getNonce(deployer), BigInteger.ZERO, argData, energyLimit, 1L);
TransactionResult result2 = avm.run(externalState, new Transaction[] { tx }, ExecutionType.replacedUME_MAINCHAIN, externalState.getBlockNumber() - 1)[0].getResult();
replacedertTrue(result2.transactionStatus.isSuccess());
return result2.copyOfTransactionOutput().orElseThrow();
}
private void deployInvalidJar(byte[] jar) {
byte[] deployment = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
long energyLimit = 10_000_000l;
long energyPrice = 1l;
Transaction tx1 = AvmTransactionUtil.create(deployer, kernel.getNonce(deployer), BigInteger.ZERO, deployment, energyLimit, energyPrice);
TransactionResult result1 = avm.run(kernel, new Transaction[] { tx1 }, ExecutionType.replacedUME_MAINCHAIN, 0)[0].getResult();
avm.shutdown();
replacedertEquals(AvmInternalError.FAILED_INVALID_DATA.error, result1.transactionStatus.causeOfError);
}
private byte[] buildRecursiveCreate(int levelsToAdd) {
byte[] args = (levelsToAdd > 1) ? buildRecursiveCreate(levelsToAdd - 1) : new byte[0];
byte[] recursiveSpawner = JarBuilder.buildJarForMainClreplacedAndExplicitClreplacedNamesAndBytecode(RecursiveSpawnerResource.clreplaced, Collections.emptyMap());
return new CodeAndArguments(recursiveSpawner, args).encodeToBytes();
}
private static byte[] encodeNoArgCall(String methodName) {
return new ABIStreamingEncoder().encodeOneString(methodName).toBytes();
}
private static byte[] encodeCallBool(String methodName, boolean arg) {
return new ABIStreamingEncoder().encodeOneString(methodName).encodeOneBoolean(arg).toBytes();
}
private static byte[] encodeCallByteArray(String methodName, byte[] arg) {
return new ABIStreamingEncoder().encodeOneString(methodName).encodeOneByteArray(arg).toBytes();
}
private static byte[] encodeCallLong(String methodName, long arg) {
return new ABIStreamingEncoder().encodeOneString(methodName).encodeOneLong(arg).toBytes();
}
private static byte[] encodeCallInt(String methodName, int arg) {
return new ABIStreamingEncoder().encodeOneString(methodName).encodeOneInteger(arg).toBytes();
}
private static byte[] encodeCallIntInt(String methodName, int arg1, int arg2) {
return new ABIStreamingEncoder().encodeOneString(methodName).encodeOneInteger(arg1).encodeOneInteger(arg2).toBytes();
}
}
19
Source : AvmImplTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
/**
* Tests that a DApp can CREATE for us, backed by a directory.
* (same as "testCreateSubAppCall" but uses a directory backing-store).
*/
@Test
public void testCreateSubAppCallOnDirectory() throws Exception {
File directory = folder.newFolder();
byte incrementBy = 3;
byte[] incrementorJar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(IncrementorDApp.clreplaced);
byte[] incrementorCreateData = new CodeAndArguments(incrementorJar, new byte[] { incrementBy }).encodeToBytes();
byte[] spawnerJar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(SpawnerDApp.clreplaced);
byte[] spanerCreateData = new CodeAndArguments(spawnerJar, incrementorCreateData).encodeToBytes();
TestingState kernel = new TestingState(directory, block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
// We always start out with the PREMINE account, but that should be the only one.
replacedertEquals(1, directory.listFiles().length);
// CREATE the spawner (meaning another account). Expect 3 accounts because: deployer, contract, coinbase
AionAddress spawnerAddress = createDApp(kernel, avm, spanerCreateData);
replacedertEquals(3, directory.listFiles().length);
// CALL to create and invoke the incrementor. Expect 4 accounts because: deployer, contract1, contract2, coinbase
boolean shouldFail = false;
byte[] spawnerCallData = encodeCallBool("spawnOnly", shouldFail);
Address incrementorAddress = callDAppAddress(kernel, avm, spawnerAddress, spawnerCallData);
replacedertEquals(4, directory.listFiles().length);
// Restart the AVM.
avm.shutdown();
kernel = new TestingState(directory, block);
avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
// Call the incrementor, directly.
byte[] input = new byte[] { 1, 2, 3, 4, 5 };
byte[] incrementorCallData = encodeCallByteArray("incrementArray", input);
byte[] incrementorResult = callDAppByteArray(kernel, avm, new AionAddress(incrementorAddress.toByteArray()), incrementorCallData);
replacedertEquals(input.length, incrementorResult.length);
for (int i = 0; i < input.length; ++i) {
replacedertEquals(incrementBy + input[i], incrementorResult[i]);
}
// Check the state of the directory we are using to back this (4 accounts, 2 with code and 2 with only a balance).
int codeCount = 0;
int balanceCount = 0;
for (File top : directory.listFiles()) {
for (File account : top.listFiles()) {
if ("code".equals(account.getName())) {
codeCount += 1;
} else if ("balance".equals(account.getName())) {
balanceCount += 1;
}
}
}
replacedertEquals(2, codeCount);
replacedertEquals(4, balanceCount);
avm.shutdown();
}
19
Source : AvmImplTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
/**
* Tests that reentrant calls do have detectable side-effects within the caller's space, when they commit.
*/
@Test
public void testCommitReentrantCalls() {
boolean shouldFail = false;
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(ReentrantCrossCallResource.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
// deploy
AionAddress contractAddr = createDApp(kernel, avm, txData);
// Get direct increments from 1 to 2 and returns 2.
replacedertEquals(2, callReentrantAccess(kernel, avm, contractAddr, "getDirect", shouldFail));
// Get near increments from 1 to 2 and returns 2.
replacedertEquals(2, callReentrantAccess(kernel, avm, contractAddr, "getNear", shouldFail));
// Get far increments from 1 to 2 and returns 2.
replacedertEquals(2, callReentrantAccess(kernel, avm, contractAddr, "getFar", shouldFail));
// Get near increments from 2 to 3 and returns 3.
replacedertEquals(3, callReentrantAccess(kernel, avm, contractAddr, "getNear", shouldFail));
avm.shutdown();
}
19
Source : AvmImplTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
@Test
public void testRecursiveHashCode() {
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(ReentrantCrossCallResource.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
// deploy
long energyLimit = 10_000_000l;
AionAddress contractAddr = createDApp(kernel, avm, txData);
// Try a few invocations of different depths, bearing in mind the change of nextHashCode between each invocation.
// We will do 2 zero-depth calls to see the delta between the 2 calls.
// Then, we will do an indirect call and verify that the delta is greater.
// If the hashcode wasn't restored across reentrant calls, this wouldn't be greater as it wouldn't capture the small cost of the original
// indirect call (since we create at least 1 object in that path).
int zero0 = callRecursiveHash(kernel, avm, energyLimit, contractAddr, 0);
int zero1 = callRecursiveHash(kernel, avm, energyLimit, contractAddr, 0);
int zero2 = callRecursiveHash(kernel, avm, energyLimit, contractAddr, 0);
int one0 = callRecursiveHash(kernel, avm, energyLimit, contractAddr, 1);
int one1 = callRecursiveHash(kernel, avm, energyLimit, contractAddr, 1);
int one2 = callRecursiveHash(kernel, avm, energyLimit, contractAddr, 1);
replacedertEquals(zero1 - zero0, zero2 - zero1);
replacedertEquals(one1 - one0, one2 - one1);
replacedertTrue((one1 - one0) > (zero1 - zero0));
avm.shutdown();
}
19
Source : AvmImplTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
private byte[] callDAppByteArray(IExternalState externalState, AvmImpl avm, AionAddress dAppAddress, byte[] argData) {
byte[] result = callDAppSuccess(externalState, avm, dAppAddress, argData);
return new ABIDecoder(result).decodeOneByteArray();
}
19
Source : AvmImplTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
/**
* Tests that a DApp can CREATE for us.
*/
@Test
public void testCreateSubAppCall() {
byte incrementBy = 3;
byte[] incrementorJar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(IncrementorDApp.clreplaced);
byte[] incrementorCreateData = new CodeAndArguments(incrementorJar, new byte[] { incrementBy }).encodeToBytes();
byte[] spawnerJar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(SpawnerDApp.clreplaced);
byte[] spanerCreateData = new CodeAndArguments(spawnerJar, incrementorCreateData).encodeToBytes();
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
// CREATE the spawner.
AionAddress spawnerAddress = createDApp(kernel, avm, spanerCreateData);
// CALL to create and invoke the incrementor.
boolean shouldFail = false;
byte[] spawnerCallData = encodeCallBool("spawnOnly", shouldFail);
Address incrementorAddress = callDAppAddress(kernel, avm, spawnerAddress, spawnerCallData);
// Call the incrementor, directly.
byte[] input = new byte[] { 1, 2, 3, 4, 5 };
byte[] incrementorCallData = encodeCallByteArray("incrementArray", input);
byte[] incrementorResult = callDAppByteArray(kernel, avm, new AionAddress(incrementorAddress.toByteArray()), incrementorCallData);
replacedertEquals(input.length, incrementorResult.length);
for (int i = 0; i < input.length; ++i) {
replacedertEquals(incrementBy + input[i], incrementorResult[i]);
}
avm.shutdown();
}
19
Source : AvmImplTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
private Address callDAppAddress(IExternalState externalState, AvmImpl avm, AionAddress dAppAddress, byte[] argData) {
byte[] result = callDAppSuccess(externalState, avm, dAppAddress, argData);
return new ABIDecoder(result).decodeOneAddress();
}
19
Source : AvmImplTest.java
with MIT License
from aionnetwork
with MIT License
from aionnetwork
/**
* Tests that reentrant calls do NOT have detectable side-effects within the caller's space, when they rollback.
*/
@Test
public void testRollbackReentrantCalls() {
boolean shouldFail = true;
byte[] jar = UserlibJarBuilder.buildJarForMainAndClreplacedesAndUserlib(ReentrantCrossCallResource.clreplaced);
byte[] txData = new CodeAndArguments(jar, new byte[0]).encodeToBytes();
TestingState kernel = new TestingState(block);
AvmImpl avm = CommonAvmFactory.buildAvmInstanceForConfiguration(new EmptyCapabilities(), new AvmConfiguration());
// deploy
AionAddress contractAddr = createDApp(kernel, avm, txData);
// We expect these to all fail, so they should be left with the initial values: 1.
replacedertEquals(1, callReentrantAccess(kernel, avm, contractAddr, "getDirect", shouldFail));
replacedertEquals(1, callReentrantAccess(kernel, avm, contractAddr, "getNear", shouldFail));
replacedertEquals(1, callReentrantAccess(kernel, avm, contractAddr, "getFar", shouldFail));
replacedertEquals(1, callReentrantAccess(kernel, avm, contractAddr, "getNear", shouldFail));
avm.shutdown();
}
See More Examples