Remove POST / rename CALLSTATELESS to CALLCODE + add unit test and switch EXTCODESIZE and EXTCODECOPY
This commit is contained in:
parent
ee442c4e34
commit
e0e99baa29
|
@ -83,8 +83,10 @@ public class TestRunner {
|
||||||
long gaslimit = new BigInteger(env.getCurrentGasLimit()).longValue();
|
long gaslimit = new BigInteger(env.getCurrentGasLimit()).longValue();
|
||||||
|
|
||||||
// Origin and caller need to exist in order to be able to execute
|
// Origin and caller need to exist in order to be able to execute
|
||||||
repository.createAccount(origin);
|
if(repository.getAccountState(origin) == null)
|
||||||
repository.createAccount(caller);
|
repository.createAccount(origin);
|
||||||
|
if(repository.getAccountState(caller) == null)
|
||||||
|
repository.createAccount(caller);
|
||||||
|
|
||||||
ProgramInvoke programInvoke = new ProgramInvokeImpl(address, origin, caller, balance,
|
ProgramInvoke programInvoke = new ProgramInvokeImpl(address, origin, caller, balance,
|
||||||
gasPrice, gas, callValue, msgData, lastHash, coinbase,
|
gasPrice, gas, callValue, msgData, lastHash, coinbase,
|
||||||
|
|
|
@ -101,12 +101,13 @@ public enum OpCode {
|
||||||
/** (0x3a) Get price of gas in current
|
/** (0x3a) Get price of gas in current
|
||||||
* environment */
|
* environment */
|
||||||
GASPRICE(0x3a),
|
GASPRICE(0x3a),
|
||||||
/** (0x3b) Copy code running in current
|
/** (0x3b) Get size of code running in
|
||||||
* environment to memory with given offset */
|
|
||||||
EXTCODECOPY(0x3b),
|
|
||||||
/** (0x3c) Get size of code running in
|
|
||||||
* current environment with given offset */
|
* current environment with given offset */
|
||||||
EXTCODESIZE(0x3c),
|
EXTCODESIZE(0x3b),
|
||||||
|
/** (0x3c) Copy code running in current
|
||||||
|
* environment to memory with given offset */
|
||||||
|
EXTCODECOPY(0x3c),
|
||||||
|
|
||||||
|
|
||||||
/* Block Information */
|
/* Block Information */
|
||||||
|
|
||||||
|
@ -149,6 +150,8 @@ public enum OpCode {
|
||||||
MSIZE(0x5b),
|
MSIZE(0x5b),
|
||||||
/** (0x5c) Get the amount of available gas */
|
/** (0x5c) Get the amount of available gas */
|
||||||
GAS(0x5c),
|
GAS(0x5c),
|
||||||
|
/** (0x5d) */
|
||||||
|
JUMPDEST(0x5d),
|
||||||
|
|
||||||
/* Push Operations */
|
/* Push Operations */
|
||||||
|
|
||||||
|
@ -296,16 +299,9 @@ public enum OpCode {
|
||||||
CALL(0xf1), // [out_data_size] [out_data_start] [in_data_size] [in_data_start] [value] [to_addr] [gas] CALL
|
CALL(0xf1), // [out_data_size] [out_data_start] [in_data_size] [in_data_start] [value] [to_addr] [gas] CALL
|
||||||
/** (0xf2) Halt execution returning output data */
|
/** (0xf2) Halt execution returning output data */
|
||||||
RETURN(0xf2),
|
RETURN(0xf2),
|
||||||
/** (0xf3) Same as call, except 5 arguments in
|
/** (0xf3) Calls self, but grabbing the code from the
|
||||||
* and 0 arguments out, and instead of immediately
|
|
||||||
* calling it adds the call to a postqueue, to be
|
|
||||||
* executed after everything else
|
|
||||||
* (including prior-created posts) within the scope
|
|
||||||
* of that transaction execution is executed */
|
|
||||||
POST(0xf3),
|
|
||||||
/** (0xf4) Calls self, but grabbing the code from the
|
|
||||||
* TO argument instead of from one's own address */
|
* TO argument instead of from one's own address */
|
||||||
CALLSTATELESS(0xf4),
|
CALLCODE(0xf3),
|
||||||
/** (0xff) Halt execution and register account for
|
/** (0xff) Halt execution and register account for
|
||||||
* later deletion */
|
* later deletion */
|
||||||
SUICIDE(0xff);
|
SUICIDE(0xff);
|
||||||
|
|
|
@ -14,9 +14,7 @@ import java.nio.ByteBuffer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Queue;
|
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,14 +29,6 @@ public class Program {
|
||||||
private int invokeHash;
|
private int invokeHash;
|
||||||
private ProgramListener listener;
|
private ProgramListener listener;
|
||||||
|
|
||||||
/**
|
|
||||||
* Instead of immediately executing a POST message call,
|
|
||||||
* it is added to a post-queue, to be executed after everything else
|
|
||||||
* (including prior-created posts) within the scope
|
|
||||||
* of that transaction execution is executed.
|
|
||||||
*/
|
|
||||||
private static Queue<MessageCall> messageQueue = new LinkedList<>();
|
|
||||||
|
|
||||||
Stack<DataWord> stack = new Stack<>();
|
Stack<DataWord> stack = new Stack<>();
|
||||||
ByteBuffer memory = null;
|
ByteBuffer memory = null;
|
||||||
DataWord programAddress;
|
DataWord programAddress;
|
||||||
|
@ -344,10 +334,6 @@ public class Program {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Queue<MessageCall> getMessageQueue() {
|
|
||||||
return messageQueue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* That method is for internal code invocations
|
* That method is for internal code invocations
|
||||||
|
@ -378,7 +364,7 @@ public class Program {
|
||||||
if (this.getGas().longValue() - msg.getGas().longValue() < 0 ) {
|
if (this.getGas().longValue() - msg.getGas().longValue() < 0 ) {
|
||||||
logger.info("No gas for the internal call, \n" +
|
logger.info("No gas for the internal call, \n" +
|
||||||
"fromAddress={}, codeAddress={}",
|
"fromAddress={}, codeAddress={}",
|
||||||
Hex.toHexString(senderAddress), Hex.toHexString(contextAddress));
|
Hex.toHexString(senderAddress), Hex.toHexString(codeAddress));
|
||||||
this.stackPushZero();
|
this.stackPushZero();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -477,6 +463,10 @@ public class Program {
|
||||||
throw new OutOfGasException();
|
throw new OutOfGasException();
|
||||||
result.spendGas(gasValue);
|
result.spendGas(gasValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void spendAllGas() {
|
||||||
|
spendGas(invokeData.getGas().longValue() - result.getGasUsed(), "Spending all remaining");
|
||||||
|
}
|
||||||
|
|
||||||
public void refundGas(long gasValue, String cause) {
|
public void refundGas(long gasValue, String cause) {
|
||||||
gasLogger.info("[{}] Refund for cause: [{}], gas: [{}]", invokeHash, cause, gasValue);
|
gasLogger.info("[{}] Refund for cause: [{}], gas: [{}]", invokeHash, cause, gasValue);
|
||||||
|
|
|
@ -17,9 +17,12 @@ public class ProgramInvokeMockImpl implements ProgramInvoke {
|
||||||
|
|
||||||
|
|
||||||
private Repository repository = null;
|
private Repository repository = null;
|
||||||
private String ownerAddress = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
private byte[] ownerAddress = Hex.decode("cd2a3d9f938e13cd947ec05abc7fe734df8dd826");
|
||||||
private String contractAddress = "471fd3ad3e9eeadeec4608b92d16ce6b500704cc";
|
private byte[] contractAddress = Hex.decode("471fd3ad3e9eeadeec4608b92d16ce6b500704cc");
|
||||||
|
|
||||||
|
// default for most tests. This can be overwritten by the test
|
||||||
|
private long gasLimit = 1000000;
|
||||||
|
|
||||||
public ProgramInvokeMockImpl(byte[] msgDataRaw) {
|
public ProgramInvokeMockImpl(byte[] msgDataRaw) {
|
||||||
this();
|
this();
|
||||||
this.msgData = msgDataRaw;
|
this.msgData = msgDataRaw;
|
||||||
|
@ -27,10 +30,10 @@ public class ProgramInvokeMockImpl implements ProgramInvoke {
|
||||||
|
|
||||||
public ProgramInvokeMockImpl() {
|
public ProgramInvokeMockImpl() {
|
||||||
this.repository = new RepositoryImpl("blockchainMoc", "detailsMoc", "stateMoc");
|
this.repository = new RepositoryImpl("blockchainMoc", "detailsMoc", "stateMoc");
|
||||||
this.repository.createAccount(Hex.decode(ownerAddress));
|
this.repository.createAccount(ownerAddress);
|
||||||
|
|
||||||
this.repository.createAccount(Hex.decode(contractAddress));
|
this.repository.createAccount(contractAddress);
|
||||||
this.repository.saveCode(Hex.decode(contractAddress),
|
this.repository.saveCode(contractAddress,
|
||||||
Hex.decode("385E60076000396000605f556014600054601e60"
|
Hex.decode("385E60076000396000605f556014600054601e60"
|
||||||
+ "205463abcddcba6040545b51602001600a525451"
|
+ "205463abcddcba6040545b51602001600a525451"
|
||||||
+ "6040016014525451606001601e52545160800160"
|
+ "6040016014525451606001601e52545160800160"
|
||||||
|
@ -45,8 +48,7 @@ public class ProgramInvokeMockImpl implements ProgramInvoke {
|
||||||
|
|
||||||
/* ADDRESS op */
|
/* ADDRESS op */
|
||||||
public DataWord getOwnerAddress() {
|
public DataWord getOwnerAddress() {
|
||||||
byte[] addr = Hex.decode(ownerAddress);
|
return new DataWord(ownerAddress);
|
||||||
return new DataWord(addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BALANCE op */
|
/* BALANCE op */
|
||||||
|
@ -82,8 +84,8 @@ public class ProgramInvokeMockImpl implements ProgramInvoke {
|
||||||
|
|
||||||
/* GAS op */
|
/* GAS op */
|
||||||
public DataWord getGas() {
|
public DataWord getGas() {
|
||||||
byte[] minGasPrice = Hex.decode("0F4240");
|
|
||||||
return new DataWord(minGasPrice);
|
return new DataWord(gasLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CALLVALUE op */
|
/* CALLVALUE op */
|
||||||
|
@ -170,11 +172,14 @@ public class ProgramInvokeMockImpl implements ProgramInvoke {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataWord getGaslimit() {
|
public DataWord getGaslimit() {
|
||||||
long gasLimit = 1000000;
|
|
||||||
return new DataWord(gasLimit);
|
return new DataWord(gasLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setGasLimit(long gasLimit) {
|
||||||
|
this.gasLimit = gasLimit;
|
||||||
|
}
|
||||||
|
|
||||||
public void setOwnerAddress(String ownerAddress) {
|
public void setOwnerAddress(byte[] ownerAddress) {
|
||||||
this.ownerAddress = ownerAddress;
|
this.ownerAddress = ownerAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,7 +152,7 @@ public class VM {
|
||||||
program.stackRequire(4);
|
program.stackRequire(4);
|
||||||
newMemSize = memNeeded(stack.get(stack.size()-2), stack.get(stack.size()-4));
|
newMemSize = memNeeded(stack.get(stack.size()-2), stack.get(stack.size()-4));
|
||||||
break;
|
break;
|
||||||
case CALL: case CALLSTATELESS:
|
case CALL: case CALLCODE:
|
||||||
program.stackRequire(7);
|
program.stackRequire(7);
|
||||||
gasCost = GasCost.CALL;
|
gasCost = GasCost.CALL;
|
||||||
DataWord callGasWord = stack.get(stack.size()-1);
|
DataWord callGasWord = stack.get(stack.size()-1);
|
||||||
|
@ -164,10 +164,6 @@ public class VM {
|
||||||
BigInteger out = memNeeded(stack.get(stack.size()-6), stack.get(stack.size()-7)); // out offset+size
|
BigInteger out = memNeeded(stack.get(stack.size()-6), stack.get(stack.size()-7)); // out offset+size
|
||||||
newMemSize = in.max(out);
|
newMemSize = in.max(out);
|
||||||
break;
|
break;
|
||||||
case POST:
|
|
||||||
program.stackRequire(5);
|
|
||||||
// TODO calculate POST gas cost
|
|
||||||
break;
|
|
||||||
case CREATE:
|
case CREATE:
|
||||||
program.stackRequire(3);
|
program.stackRequire(3);
|
||||||
gasCost = GasCost.CREATE;
|
gasCost = GasCost.CREATE;
|
||||||
|
@ -804,6 +800,8 @@ public class VM {
|
||||||
case JUMP:{
|
case JUMP:{
|
||||||
program.stackRequire(1);
|
program.stackRequire(1);
|
||||||
DataWord pos = program.stackPop();
|
DataWord pos = program.stackPop();
|
||||||
|
// if (!pos.equals(DataWord.ZERO) && OpCode.code(program.getCurrentOp()) != OpCode.JUMPDEST)
|
||||||
|
// throw new BadJumpDestinationException();
|
||||||
|
|
||||||
if (logger.isInfoEnabled())
|
if (logger.isInfoEnabled())
|
||||||
hint = "~> " + pos.value();
|
hint = "~> " + pos.value();
|
||||||
|
@ -814,10 +812,12 @@ public class VM {
|
||||||
program.stackRequire(2);
|
program.stackRequire(2);
|
||||||
DataWord pos = program.stackPop();
|
DataWord pos = program.stackPop();
|
||||||
DataWord cond = program.stackPop();
|
DataWord cond = program.stackPop();
|
||||||
|
// if (!pos.isZero() && OpCode.code(program.getCurrentOp()) != OpCode.JUMPDEST)
|
||||||
|
// throw new BadJumpDestinationException();
|
||||||
|
|
||||||
if (!cond.isZero()) {
|
if (!cond.isZero()) {
|
||||||
program.setPC(pos);
|
program.setPC(pos);
|
||||||
} else{
|
} else {
|
||||||
program.step();
|
program.step();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -867,6 +867,8 @@ public class VM {
|
||||||
|
|
||||||
program.stackPush(data);
|
program.stackPush(data);
|
||||||
} break;
|
} break;
|
||||||
|
case JUMPDEST:{
|
||||||
|
} break;
|
||||||
case CREATE:{
|
case CREATE:{
|
||||||
program.stackRequire(3);
|
program.stackRequire(3);
|
||||||
DataWord value = program.stackPop();
|
DataWord value = program.stackPop();
|
||||||
|
@ -883,7 +885,7 @@ public class VM {
|
||||||
|
|
||||||
program.step();
|
program.step();
|
||||||
} break;
|
} break;
|
||||||
case CALL: case CALLSTATELESS: {
|
case CALL: case CALLCODE: {
|
||||||
DataWord gas = program.stackPop();
|
DataWord gas = program.stackPop();
|
||||||
DataWord codeAddress = program.stackPop();
|
DataWord codeAddress = program.stackPop();
|
||||||
DataWord value = program.stackPop();
|
DataWord value = program.stackPop();
|
||||||
|
@ -913,32 +915,6 @@ public class VM {
|
||||||
|
|
||||||
program.step();
|
program.step();
|
||||||
} break;
|
} break;
|
||||||
case POST:{
|
|
||||||
program.stackRequire(5);
|
|
||||||
DataWord gas = program.stackPop();
|
|
||||||
DataWord codeAddress= program.stackPop();
|
|
||||||
DataWord value = program.stackPop();
|
|
||||||
|
|
||||||
DataWord inDataOffs = program.stackPop();
|
|
||||||
DataWord inDataSize = program.stackPop();
|
|
||||||
|
|
||||||
if (logger.isInfoEnabled()) {
|
|
||||||
hint = "addr: " + Hex.toHexString(codeAddress.getLast20Bytes())
|
|
||||||
+ " gas: " + gas.shortHex()
|
|
||||||
+ " inOff: " + inDataOffs.shortHex()
|
|
||||||
+ " inSize: " + inDataSize.shortHex();
|
|
||||||
logger.info(logString, program.getPC(),
|
|
||||||
String.format("%-12s", op.name()),
|
|
||||||
program.getGas().value(),
|
|
||||||
program.invokeData.getCallDeep(), hint);
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageCall msgCall = new MessageCall(MsgType.POST, gas,
|
|
||||||
codeAddress, value, inDataOffs, inDataSize);
|
|
||||||
program.getMessageQueue().add(msgCall);
|
|
||||||
|
|
||||||
program.step();
|
|
||||||
} break;
|
|
||||||
case RETURN:{
|
case RETURN:{
|
||||||
program.stackRequire(2);
|
program.stackRequire(2);
|
||||||
DataWord offset = program.stackPop();
|
DataWord offset = program.stackPop();
|
||||||
|
@ -977,8 +953,10 @@ public class VM {
|
||||||
|
|
||||||
vmCounter++;
|
vmCounter++;
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
if(e instanceof OutOfGasException)
|
if(e instanceof OutOfGasException) {
|
||||||
logger.warn("OutOfGasException occurred", e);
|
logger.warn("OutOfGasException occurred", e);
|
||||||
|
program.spendAllGas();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
logger.error("VM halted", e);
|
logger.error("VM halted", e);
|
||||||
program.stop();
|
program.stop();
|
||||||
|
@ -1080,4 +1058,8 @@ public class VM {
|
||||||
gasBefore, gasCost, memWords);
|
gasBefore, gasCost, memWords);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public class BadJumpDestinationException extends RuntimeException {}
|
||||||
|
|
||||||
}
|
}
|
|
@ -92,6 +92,4 @@ public class GitHubJSONTestSuiteTest {
|
||||||
Assert.assertTrue(result.isEmpty());
|
Assert.assertTrue(result.isEmpty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ public class VMComplexTest {
|
||||||
accountState.setCodeHash(codeKey);
|
accountState.setCodeHash(codeKey);
|
||||||
|
|
||||||
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
|
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
|
||||||
pi.setOwnerAddress("77045e71a7a2c50903d88e564cd72fab11e82051");
|
pi.setOwnerAddress(contractAddrB);
|
||||||
Repository repository = pi.getRepository();
|
Repository repository = pi.getRepository();
|
||||||
|
|
||||||
repository.createAccount(callerAddrB);
|
repository.createAccount(callerAddrB);
|
||||||
|
@ -132,13 +132,13 @@ public class VMComplexTest {
|
||||||
byte[] contractA_addr_bytes = Hex.decode(contractA_addr);
|
byte[] contractA_addr_bytes = Hex.decode(contractA_addr);
|
||||||
byte[] codeA = Hex.decode(code_a);
|
byte[] codeA = Hex.decode(code_a);
|
||||||
|
|
||||||
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
|
|
||||||
pi.setOwnerAddress(contractB_addr);
|
|
||||||
Repository repository = pi.getRepository();
|
|
||||||
|
|
||||||
byte[] contractB_addr_bytes = Hex.decode(contractB_addr);
|
byte[] contractB_addr_bytes = Hex.decode(contractB_addr);
|
||||||
byte[] codeB = Hex.decode(code_b);
|
byte[] codeB = Hex.decode(code_b);
|
||||||
|
|
||||||
|
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
|
||||||
|
pi.setOwnerAddress(contractB_addr_bytes);
|
||||||
|
Repository repository = pi.getRepository();
|
||||||
|
|
||||||
repository.createAccount(contractA_addr_bytes);
|
repository.createAccount(contractA_addr_bytes);
|
||||||
repository.saveCode(contractA_addr_bytes, codeA);
|
repository.saveCode(contractA_addr_bytes, codeA);
|
||||||
|
|
||||||
|
@ -216,24 +216,16 @@ public class VMComplexTest {
|
||||||
long expectedVal_6 = 66;
|
long expectedVal_6 = 66;
|
||||||
|
|
||||||
// Set contract into Database
|
// Set contract into Database
|
||||||
String callerAddr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
byte[] caller_addr_bytes = Hex.decode("cd2a3d9f938e13cd947ec05abc7fe734df8dd826");
|
||||||
|
|
||||||
String contractA_addr = "77045e71a7a2c50903d88e564cd72fab11e82051";
|
byte[] contractA_addr_bytes = Hex.decode("77045e71a7a2c50903d88e564cd72fab11e82051");
|
||||||
String contractB_addr = "83c5541a6c8d2dbad642f385d8d06ca9b6c731ee";
|
byte[] contractB_addr_bytes = Hex.decode("83c5541a6c8d2dbad642f385d8d06ca9b6c731ee");
|
||||||
|
|
||||||
String code_a = "600b60005460166020546021604054602c6060546037608054604260a05460c06000f2";
|
byte[] codeA = Hex.decode("600b60005460166020546021604054602c6060546037608054604260a05460c06000f2");
|
||||||
String code_b = "6000601f5560e05b60e05b54600060c05b015560605b6020015b80602001600b9054806040016016905480606001602190546080905460007377045e71a7a2c50903d88e564cd72fab11e820516103e8f1602060000260a00160200153600054";
|
byte[] codeB = Hex.decode("6000601f5560e05b60e05b54600060c05b015560605b6020015b80602001600b9054806040016016905480606001602190546080905460007377045e71a7a2c50903d88e564cd72fab11e820516103e8f1602060000260a00160200153600054");
|
||||||
|
|
||||||
byte[] caller_addr_bytes = Hex.decode(callerAddr);
|
|
||||||
|
|
||||||
byte[] contractA_addr_bytes = Hex.decode(contractA_addr);
|
|
||||||
byte[] codeA = Hex.decode(code_a);
|
|
||||||
|
|
||||||
byte[] contractB_addr_bytes = Hex.decode(contractB_addr);
|
|
||||||
byte[] codeB = Hex.decode(code_b);
|
|
||||||
|
|
||||||
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
|
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
|
||||||
pi.setOwnerAddress(contractB_addr);
|
pi.setOwnerAddress(contractB_addr_bytes);
|
||||||
Repository repository = pi.getRepository();
|
Repository repository = pi.getRepository();
|
||||||
repository.createAccount(contractA_addr_bytes);
|
repository.createAccount(contractA_addr_bytes);
|
||||||
repository.saveCode(contractA_addr_bytes, codeA);
|
repository.saveCode(contractA_addr_bytes, codeA);
|
||||||
|
@ -303,25 +295,20 @@ public class VMComplexTest {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Set contract into Database
|
// Set contract into Database
|
||||||
String callerAddr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
byte[] caller_addr_bytes = Hex.decode("cd2a3d9f938e13cd947ec05abc7fe734df8dd826");
|
||||||
|
|
||||||
String contractA_addr = "77045e71a7a2c50903d88e564cd72fab11e82051";
|
byte[] contractA_addr_bytes = Hex.decode("77045e71a7a2c50903d88e564cd72fab11e82051");
|
||||||
|
|
||||||
String code_a = "7f7f60c860005461012c602054000000000000" +
|
byte[] codeA = Hex.decode("7f7f60c860005461012c602054000000000000" +
|
||||||
"00000000000000000000000000006000547e60" +
|
"00000000000000000000000000006000547e60" +
|
||||||
"005460206000f2000000000000000000000000" +
|
"005460206000f2000000000000000000000000" +
|
||||||
"0000000000000000000000602054602960006064f0";
|
"0000000000000000000000602054602960006064f0");
|
||||||
|
|
||||||
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
|
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
|
||||||
pi.setOwnerAddress(contractA_addr);
|
pi.setOwnerAddress(contractA_addr_bytes);
|
||||||
|
|
||||||
Repository repository = pi.getRepository();
|
Repository repository = pi.getRepository();
|
||||||
|
|
||||||
byte[] caller_addr_bytes = Hex.decode(callerAddr);
|
|
||||||
|
|
||||||
byte[] contractA_addr_bytes = Hex.decode(contractA_addr);
|
|
||||||
byte[] codeA = Hex.decode(code_a);
|
|
||||||
|
|
||||||
repository.createAccount(contractA_addr_bytes);
|
repository.createAccount(contractA_addr_bytes);
|
||||||
repository.saveCode(contractA_addr_bytes, codeA);
|
repository.saveCode(contractA_addr_bytes, codeA);
|
||||||
|
|
||||||
|
@ -354,22 +341,80 @@ public class VMComplexTest {
|
||||||
// TODO CALL contract with gas > gasRemaining && gas > Long.MAX_VALUE
|
// TODO CALL contract with gas > gasRemaining && gas > Long.MAX_VALUE
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // CALLSTATELESS contract
|
@Test // contractB call itself with code from contractA
|
||||||
@Ignore
|
|
||||||
public void test6() {
|
public void test6() {
|
||||||
// TODO
|
/**
|
||||||
}
|
* #The code will run
|
||||||
|
* ------------------
|
||||||
@Test // POST contract
|
|
||||||
@Ignore
|
|
||||||
public void test7() {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test // POST after tx runs out of gas
|
|
||||||
@Ignore
|
|
||||||
public void test8() {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
|
contract A: 945304eb96065b2a98b57a48a06ae28d285a71b5
|
||||||
|
---------------
|
||||||
|
|
||||||
|
PUSH1 0 CALLDATALOAD SLOAD NOT PUSH1 9 JUMPI STOP
|
||||||
|
PUSH1 32 CALLDATALOAD PUSH1 0 CALLDATALOAD SSTORE
|
||||||
|
|
||||||
|
contract B: 0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6
|
||||||
|
-----------
|
||||||
|
{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
|
||||||
|
(MSTORE 32 0xaaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa)
|
||||||
|
[[ 0 ]] (CALLSTATELESS 1000000 0x945304eb96065b2a98b57a48a06ae28d285a71b5 23 0 64 64 0)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Set contract into Database
|
||||||
|
byte[] caller_addr_bytes = Hex.decode("cd1722f3947def4cf144679da39c4c32bdc35681");
|
||||||
|
|
||||||
|
byte[] contractA_addr_bytes = Hex.decode("945304eb96065b2a98b57a48a06ae28d285a71b5");
|
||||||
|
byte[] contractB_addr_bytes = Hex.decode("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6");
|
||||||
|
|
||||||
|
byte[] codeA = Hex.decode("600035560f6009590060203560003557");
|
||||||
|
byte[] codeB = Hex.decode("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000547faaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa6020546000604060406000601773945304eb96065b2a98b57a48a06ae28d285a71b5620f4240f3600057");
|
||||||
|
|
||||||
|
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
|
||||||
|
pi.setOwnerAddress(contractB_addr_bytes);
|
||||||
|
pi.setGasLimit(10000000000000l);
|
||||||
|
|
||||||
|
Repository repository = pi.getRepository();
|
||||||
|
repository.createAccount(contractA_addr_bytes);
|
||||||
|
repository.saveCode(contractA_addr_bytes, codeA);
|
||||||
|
repository.addBalance(contractA_addr_bytes, BigInteger.valueOf(23));
|
||||||
|
|
||||||
|
repository.createAccount(contractB_addr_bytes);
|
||||||
|
repository.saveCode(contractB_addr_bytes, codeB);
|
||||||
|
repository.addBalance(contractB_addr_bytes, new BigInteger("1000000000000000000"));
|
||||||
|
|
||||||
|
repository.createAccount(caller_addr_bytes);
|
||||||
|
repository.addBalance(caller_addr_bytes, new BigInteger("100000000000000000000"));
|
||||||
|
|
||||||
|
// ****************** //
|
||||||
|
// Play the program //
|
||||||
|
// ****************** //
|
||||||
|
VM vm = new VM();
|
||||||
|
Program program = new Program(codeB, pi);
|
||||||
|
|
||||||
|
try {
|
||||||
|
while(!program.isStopped())
|
||||||
|
vm.step(program);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
program.setRuntimeFailure(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
System.out.println("============ Results ============");
|
||||||
|
System.out.println("*** Used gas: " + program.result.getGasUsed());
|
||||||
|
|
||||||
|
DataWord memValue1 = program.memoryLoad(new DataWord(0));
|
||||||
|
DataWord memValue2 = program.memoryLoad(new DataWord(32));
|
||||||
|
|
||||||
|
DataWord storeValue1 = repository.getStorageValue(contractB_addr_bytes, new DataWord(00));
|
||||||
|
|
||||||
|
repository.close();
|
||||||
|
|
||||||
|
assertEquals("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", memValue1.toString());
|
||||||
|
assertEquals("aaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa", memValue2.toString());
|
||||||
|
|
||||||
|
assertEquals("0x1", storeValue1.shortHex());
|
||||||
|
|
||||||
|
// TODO: check that the value pushed after exec is 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2546,7 +2546,7 @@ public class VMTest {
|
||||||
|
|
||||||
VM vm = new VM();
|
VM vm = new VM();
|
||||||
Program program =
|
Program program =
|
||||||
new Program(Hex.decode("60036007600073471FD3AD3E9EEADEEC4608B92D16CE6B500704CC3B123456"), new ProgramInvokeMockImpl());
|
new Program(Hex.decode("60036007600073471FD3AD3E9EEADEEC4608B92D16CE6B500704CC3C123456"), new ProgramInvokeMockImpl());
|
||||||
String m_expected_1 = "6000600000000000000000000000000000000000000000000000000000000000";
|
String m_expected_1 = "6000600000000000000000000000000000000000000000000000000000000000";
|
||||||
|
|
||||||
vm.step(program);
|
vm.step(program);
|
||||||
|
@ -2564,7 +2564,7 @@ public class VMTest {
|
||||||
|
|
||||||
VM vm = new VM();
|
VM vm = new VM();
|
||||||
Program program =
|
Program program =
|
||||||
new Program(Hex.decode("603E6007600073471FD3AD3E9EEADEEC4608B92D16CE6B500704CC3B6000605f556014600054601e60205463abcddcba6040545b51602001600a5254516040016014525451606001601e5254516080016028525460a052546016604860003960166000f26000603f556103e75660005460005360200235602054"),
|
new Program(Hex.decode("603E6007600073471FD3AD3E9EEADEEC4608B92D16CE6B500704CC3C6000605f556014600054601e60205463abcddcba6040545b51602001600a5254516040016014525451606001601e5254516080016028525460a052546016604860003960166000f26000603f556103e75660005460005360200235602054"),
|
||||||
new ProgramInvokeMockImpl());
|
new ProgramInvokeMockImpl());
|
||||||
String m_expected_1 = "6000605F556014600054601E60205463ABCDDCBA6040545B51602001600A5254516040016014525451606001601E5254516080016028525460A0525460160000";
|
String m_expected_1 = "6000605F556014600054601E60205463ABCDDCBA6040545B51602001600A5254516040016014525451606001601E5254516080016028525460A0525460160000";
|
||||||
|
|
||||||
|
@ -2582,7 +2582,7 @@ public class VMTest {
|
||||||
public void testEXTCODECOPY_3() {
|
public void testEXTCODECOPY_3() {
|
||||||
VM vm = new VM();
|
VM vm = new VM();
|
||||||
Program program =
|
Program program =
|
||||||
new Program(Hex.decode("605E6007600073471FD3AD3E9EEADEEC4608B92D16CE6B500704CC3B6000605f556014600054601e60205463abcddcba6040545b51602001600a5254516040016014525451606001601e5254516080016028525460a052546016604860003960166000f26000603f556103e75660005460005360200235"),
|
new Program(Hex.decode("605E6007600073471FD3AD3E9EEADEEC4608B92D16CE6B500704CC3C6000605f556014600054601e60205463abcddcba6040545b51602001600a5254516040016014525451606001601e5254516080016028525460a052546016604860003960166000f26000603f556103e75660005460005360200235"),
|
||||||
new ProgramInvokeMockImpl());
|
new ProgramInvokeMockImpl());
|
||||||
|
|
||||||
vm.step(program);
|
vm.step(program);
|
||||||
|
@ -2600,7 +2600,7 @@ public class VMTest {
|
||||||
|
|
||||||
VM vm = new VM();
|
VM vm = new VM();
|
||||||
Program program =
|
Program program =
|
||||||
new Program(Hex.decode("605E6007600073471FD3AD3E9EEADEEC4608B92D16CE6B500704CC3B6000605f556014600054601e60205463abcddcba6040545b51602001600a5254516040016014525451606001601e5254516080016028525460a052546016604860003960166000f26000603f556103e756600054600053602002351234"),
|
new Program(Hex.decode("605E6007600073471FD3AD3E9EEADEEC4608B92D16CE6B500704CC3C6000605f556014600054601e60205463abcddcba6040545b51602001600a5254516040016014525451606001601e5254516080016028525460a052546016604860003960166000f26000603f556103e756600054600053602002351234"),
|
||||||
new ProgramInvokeMockImpl());
|
new ProgramInvokeMockImpl());
|
||||||
|
|
||||||
vm.step(program);
|
vm.step(program);
|
||||||
|
@ -2617,7 +2617,7 @@ public class VMTest {
|
||||||
public void testEXTCODECOPY_5() {
|
public void testEXTCODECOPY_5() {
|
||||||
VM vm = new VM();
|
VM vm = new VM();
|
||||||
Program program =
|
Program program =
|
||||||
new Program(Hex.decode("611234600054615566602054603E6000602073471FD3AD3E9EEADEEC4608B92D16CE6B500704CC3B6000605f556014600054601e60205463abcddcba6040545b51602001600a5254516040016014525451606001601e5254516080016028525460a052546016604860003960166000f26000603f556103e756600054600053602002351234"),
|
new Program(Hex.decode("611234600054615566602054603E6000602073471FD3AD3E9EEADEEC4608B92D16CE6B500704CC3C6000605f556014600054601e60205463abcddcba6040545b51602001600a5254516040016014525451606001601e5254516080016028525460a052546016604860003960166000f26000603f556103e756600054600053602002351234"),
|
||||||
new ProgramInvokeMockImpl());
|
new ProgramInvokeMockImpl());
|
||||||
|
|
||||||
vm.step(program);
|
vm.step(program);
|
||||||
|
@ -2641,7 +2641,7 @@ public class VMTest {
|
||||||
public void testEXTCODECOPY_6() {
|
public void testEXTCODECOPY_6() {
|
||||||
VM vm = new VM();
|
VM vm = new VM();
|
||||||
Program program =
|
Program program =
|
||||||
new Program(Hex.decode("605E600773471FD3AD3E9EEADEEC4608B92D16CE6B500704CC3B"),
|
new Program(Hex.decode("605E600773471FD3AD3E9EEADEEC4608B92D16CE6B500704CC3C"),
|
||||||
new ProgramInvokeMockImpl());
|
new ProgramInvokeMockImpl());
|
||||||
try {
|
try {
|
||||||
vm.step(program);
|
vm.step(program);
|
||||||
|
@ -3359,17 +3359,15 @@ public class VMTest {
|
||||||
|
|
||||||
public ProgramInvoke createProgramInvoke_1() {
|
public ProgramInvoke createProgramInvoke_1() {
|
||||||
|
|
||||||
String ownerAddress = "77045E71A7A2C50903D88E564CD72FAB11E82051";
|
byte[] ownerAddress = Hex.decode("77045E71A7A2C50903D88E564CD72FAB11E82051");
|
||||||
byte[] address = Hex.decode(ownerAddress);
|
|
||||||
|
|
||||||
byte[] msgData = Hex.decode("00000000000000000000000000000000000000000000000000000000000000A1" +
|
byte[] msgData = Hex.decode("00000000000000000000000000000000000000000000000000000000000000A1" +
|
||||||
"00000000000000000000000000000000000000000000000000000000000000B1");
|
"00000000000000000000000000000000000000000000000000000000000000B1");
|
||||||
|
|
||||||
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl(msgData);
|
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl(msgData);
|
||||||
pi.setOwnerAddress(ownerAddress);
|
pi.setOwnerAddress(ownerAddress);
|
||||||
|
|
||||||
pi.getRepository().createAccount(address);
|
pi.getRepository().createAccount(ownerAddress);
|
||||||
pi.getRepository().addBalance(address, BigInteger.valueOf(1000L));
|
pi.getRepository().addBalance(ownerAddress, BigInteger.valueOf(1000L));
|
||||||
|
|
||||||
return pi;
|
return pi;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue