Implement ADDMOD and MULMOD with unit tests

This commit is contained in:
nicksavers 2014-09-14 17:12:51 +02:00
parent 0f8b51158a
commit 332707df0f
3 changed files with 199 additions and 36 deletions

View File

@ -340,22 +340,44 @@ public class Program {
}
}
}
/**
* That method implement internal calls
* and code invocations
* That method implement internal code invocations.
*
* Instead of immediately calling it adds the call
* to a post-queue, to be executed after everything else
* (including prior-created posts) within the scope
* of that transaction execution is executed.
*
* @param gas - gas to pay for the call, remaining gas will be refunded to the caller
* @param toAddressDW - address to call
* @param storageAddressDW - address of the storage to use
* @param endowmentValue - the value that can be transfer along with the code execution
* @param inDataOffs - start of memory to be input data to the call
* @param inDataSize - size of memory to be input data to the call
*/
public void postToAddress(DataWord gas, DataWord toAddressDW, DataWord storageAddressDW,
DataWord endowmentValue, DataWord inDataOffs, DataWord inDataSize) {
// TODO implement code
}
/**
* That method implement internal code invocations
*
* @param gas - gas to pay for the call, remaining gas will be refunded to the caller
* @param toAddressDW - address to call
* @param storageAddressDW - address of the storage to use
* @param endowmentValue - the value that can be transfer along with the code execution
* @param inDataOffs - start of memory to be input data to the call
* @param inDataSize - size of memory to be input data to the call
* @param outDataOffs - start of memory to be output of the call
* @param outDataSize - size of memory to be output data to the call
*/
public void callToAddress(DataWord gas, DataWord toAddressDW, DataWord endowmentValue,
public void callToAddress(DataWord gas, DataWord toAddressDW, DataWord storageAddressDW, DataWord endowmentValue,
DataWord inDataOffs, DataWord inDataSize,DataWord outDataOffs, DataWord outDataSize) {
// TODO: update code for CALLSTATELESS
ByteBuffer data = memoryChunk(inDataOffs, inDataSize);
// FETCH THE SAVED STORAGE

View File

@ -144,7 +144,7 @@ public class VM {
program.stackRequire(3);
newMemSize = stack.peek().value().add(stack.get(stack.size()-3).value());
break;
case CALL:
case CALL: case CALLSTATELESS:
program.stackRequire(7);
gasCost = GasCost.CALL;
BigInteger callGasWord = stack.get(stack.size()-1).value();
@ -156,12 +156,6 @@ public class VM {
BigInteger y = stack.get(stack.size()-6).value().add(stack.get(stack.size()-7).value()); // out offset+size
newMemSize = x.max(y);
break;
case CALLSTATELESS:
program.stackRequire(7);
// TODO
// runGas = c_callGas + m_stack[m_stack.size() - 1];
// newTempSize = std::max(memNeed(m_stack[m_stack.size() - 6], m_stack[m_stack.size() - 7]), memNeed(m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5]));
break;
case POST:
program.stackRequire(5);
// TODO
@ -478,12 +472,18 @@ public class VM {
program.step();
} break;
case ADDMOD:{
program.stackRequire(3);
// TODO: Implement new opcodes
program.stackRequire(3);
DataWord word1 = program.stackPop();
word1.add(program.stackPop());
word1.mod(program.stackPop());
program.stackPush(word1);
} break;
case MULMOD:{
program.stackRequire(3);
// TODO: Implement new opcodes
program.stackRequire(3);
DataWord word1 = program.stackPop();
word1.mul(program.stackPop());
word1.mod(program.stackPop());
program.stackPush(word1);
} break;
/**
@ -862,7 +862,7 @@ public class VM {
program.step();
} break;
case CALL: {
case CALL: case CALLSTATELESS: {
program.stackRequire(7);
DataWord gas = program.stackPop();
DataWord toAddress = program.stackPop();
@ -885,16 +885,35 @@ public class VM {
program.invokeData.getCallDeep(), hint);
}
program.callToAddress(gas, toAddress, value, inDataOffs, inDataSize, outDataOffs, outDataSize);
program.callToAddress(gas, toAddress, op.equals(CALL) ? toAddress
: program.getOwnerAddress(), value, inDataOffs,
inDataSize, outDataOffs, outDataSize);
program.step();
} break;
case POST:{
program.stackRequire(5);
// TODO: Implement POST execution
} break;
case CALLSTATELESS:{
// TODO: Implement CALLSTATELESS (almost same as CALL)
DataWord gas = program.stackPop();
DataWord toAddress = program.stackPop();
DataWord value = program.stackPop();
DataWord inDataOffs = program.stackPop();
DataWord inDataSize = program.stackPop();
if (logger.isInfoEnabled()) {
hint = "addr: " + Hex.toHexString(toAddress.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);
}
program.postToAddress(gas, toAddress, toAddress, value, inDataOffs, inDataSize);
program.step();
} break;
case RETURN:{
program.stackRequire(2);

View File

@ -1177,7 +1177,7 @@ public class VMTest {
*
* @param n in DUPn
*/
public void testDUPN_1(int n) {
private void testDUPN_1(int n) {
VM vm = new VM();
byte operation = (byte) (OpCode.DUP1.val() + n - 1);
@ -1218,7 +1218,7 @@ public class VMTest {
@Test // SWAP1...SWAP16 OP
public void testSWAPS() {
for (int i = 1; i < 17; i++) {
testSWAPN(i);
testSWAPN_1(i);
}
}
@ -1227,7 +1227,7 @@ public class VMTest {
*
* @param n in SWAPn
*/
public void testSWAPN(int n) {
private void testSWAPN_1(int n) {
VM vm = new VM();
byte operation = (byte) (OpCode.SWAP1.val() + n - 1);
@ -1253,7 +1253,7 @@ public class VMTest {
}
@Test(expected=StackTooSmallException.class) // SWAPN OP mal data
public void testSWAPN_3() {
public void testSWAPN_2() {
VM vm = new VM();
Program program = new Program(Hex.decode("90"), new ProgramInvokeMockImpl());
@ -1845,9 +1845,70 @@ public class VMTest {
assertTrue(program.isStopped());
}
}
@Test // ADDMOD OP mal
public void testADDMOD_1() {
VM vm = new VM();
Program program = new Program(Hex.decode("60026002600314"), new ProgramInvokeMockImpl());
String s_expected_1 = "0000000000000000000000000000000000000000000000000000000000000001";
@Test // MULL OP
public void testMULL_1() {
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
DataWord item1 = program.stack.pop();
program.getResult().getRepository().close();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test // ADDMOD OP
public void testADDMOD_2() {
VM vm = new VM();
Program program = new Program(Hex.decode("611000600261100214"), new ProgramInvokeMockImpl());
String s_expected_1 = "0000000000000000000000000000000000000000000000000000000000000004";
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
DataWord item1 = program.stack.pop();
program.getResult().getRepository().close();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test // ADDMOD OP
public void testADDMOD_3() {
VM vm = new VM();
Program program = new Program(Hex.decode("61100265123456789009600214"), new ProgramInvokeMockImpl());
String s_expected_1 = "000000000000000000000000000000000000000000000000000000000000093B";
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
DataWord item1 = program.stack.pop();
program.getResult().getRepository().close();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test(expected=StackTooSmallException.class) // ADDMOD OP mal
public void testADDMOD_4() {
VM vm = new VM();
Program program = new Program(Hex.decode("61123414"), new ProgramInvokeMockImpl());
try {
vm.step(program);
vm.step(program);
} finally {
program.getResult().getRepository().close();
assertTrue(program.isStopped());
}
}
@Test // MUL OP
public void testMUL_1() {
VM vm = new VM();
Program program = new Program(Hex.decode("6003600202"), new ProgramInvokeMockImpl());
@ -1862,8 +1923,8 @@ public class VMTest {
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test // MULL OP
public void testMULL_2() {
@Test // MUL OP
public void testMUL_2() {
VM vm = new VM();
Program program = new Program(Hex.decode("62222222600302"), new ProgramInvokeMockImpl());
@ -1878,8 +1939,8 @@ public class VMTest {
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test // MULL OP
public void testMULL_3() {
@Test // MUL OP
public void testMUL_3() {
VM vm = new VM();
Program program = new Program(Hex.decode("622222226233333302"), new ProgramInvokeMockImpl());
@ -1894,8 +1955,8 @@ public class VMTest {
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test(expected=StackTooSmallException.class) // MULL OP mal
public void testMULL_4() {
@Test(expected=StackTooSmallException.class) // MUL OP mal
public void testMUL_4() {
VM vm = new VM();
Program program = new Program(Hex.decode("600102"), new ProgramInvokeMockImpl());
@ -1907,6 +1968,67 @@ public class VMTest {
assertTrue(program.isStopped());
}
}
@Test // MULMOD OP
public void testMULMOD_1() {
VM vm = new VM();
Program program = new Program(Hex.decode("60036002600415"), new ProgramInvokeMockImpl());
String s_expected_1 = "0000000000000000000000000000000000000000000000000000000000000002";
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
DataWord item1 = program.stack.pop();
program.getResult().getRepository().close();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test // MULMOD OP
public void testMULMOD_2() {
VM vm = new VM();
Program program = new Program(Hex.decode("622222226003600415"), new ProgramInvokeMockImpl());
String s_expected_1 = "000000000000000000000000000000000000000000000000000000000000000C";
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
DataWord item1 = program.stack.pop();
program.getResult().getRepository().close();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test // MULMOD OP
public void testMULMOD_3() {
VM vm = new VM();
Program program = new Program(Hex.decode("62222222623333336244444415"), new ProgramInvokeMockImpl());
String s_expected_1 = "0000000000000000000000000000000000000000000000000000000000000000";
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
DataWord item1 = program.stack.pop();
program.getResult().getRepository().close();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test(expected=StackTooSmallException.class) // MULMOD OP mal
public void testMULMOD_4() {
VM vm = new VM();
Program program = new Program(Hex.decode("600115"), new ProgramInvokeMockImpl());
try {
vm.step(program);
vm.step(program);
} finally {
program.getResult().getRepository().close();
assertTrue(program.isStopped());
}
}
@Test // DIV OP
public void testDIV_1() {
@ -2834,14 +2956,14 @@ public class VMTest {
program.getResult().getRepository().close();
assertTrue(program.isStopped());
}
}
}
@Test // MOD OP
public void testMOD_1() {
VM vm = new VM();
Program program = new Program(Hex.decode("6003600406"), new ProgramInvokeMockImpl());
String s_expected_1 = "0000000000000000000000000000000000000000000000000000000000000001";
vm.step(program);
vm.step(program);
vm.step(program);