CALL op with in/out data

+ support for return
 + VMComplexText test3 demonstrates the return applied
This commit is contained in:
romanman 2014-06-22 20:20:03 +01:00
parent d2676eda92
commit 0b02376c17
7 changed files with 148 additions and 17 deletions

View File

@ -4,15 +4,16 @@
----------------
- [x] **VM execution:** support CALL op
- [ ] **VM execution:** support CALL op with in/out data
- [x] **VM execution:** support CALL op with in/out data
- [ ] **VM execution:** support CREATE op
- [ ] **VM execution:** SUICIDE op adjust
- [ ] **ProgramPlayDialog** support internal calls
- [ ] **Build:** extract core module and studio application
- [ ] **Performance:** BigInteger math change for constant arrays implementation
economy for memory allocation
- [ ] **Command Line:** add the headless run option
- [ ] **Testing by JSON files:** follow cpp client performs test case by getting json file contains the test describe
- [ ] Serpent new syntax:
- [ ] **SerpentCompiler** Serpent new syntax:
(@> @< @/ @%) - unsigned operations
> < / % - default are all signed operations
+= -= *= /= %= @/= @%= - short form operations
@ -23,7 +24,9 @@ share - code section
##### UnitTest:
----------------
- [ ] **VM complex: CALL testing for in/out arrays
- [ ] **VM complex: CREATE testing
- [x] **VM complex:** CALL testing for in arrays
- [x] **VM complex:** CALL testing for out result
- [ ] **VM complex:** CREATE testing
- [ ] **VM complex:** SUICIDE testing
- [ ] **WorldManager** apply transactions

View File

@ -198,7 +198,7 @@ public class ProgramPlayDialog extends JPanel implements ActionListener,
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
String asmCode ="0 31 MSTORE8 224 MSIZE 224 MSIZE MSTORE 0 192 MSIZE ADD MSTORE8 96 MSIZE 32 ADD MSIZE DUP 32 ADD 11 SWAP MSTORE DUP 64 ADD 22 SWAP MSTORE DUP 96 ADD 33 SWAP MSTORE 128 SWAP MSTORE 0 752278364205682983151548199104072833112320979438 1000 CALL 32 0 MUL 160 ADD 32 ADD MLOAD 0 MSTORE";
String asmCode ="11 0 MSTORE 22 32 MSTORE 33 64 MSTORE 44 96 MSTORE 55 128 MSTORE 66 160 MSTORE 192 0 RETURN";
final byte[] code = SerpentCompiler.compileAssemblyToMachine(asmCode);

View File

@ -286,9 +286,9 @@ public class WorldManager {
// Save the code created by init
byte[] bodyCode = null;
if (result.gethReturn() != null){
if (result.getHReturn() != null){
bodyCode = result.gethReturn().array();
bodyCode = result.getHReturn().array();
}
BigInteger gasPrice =

View File

@ -323,9 +323,20 @@ public class Program {
return;
}
// todo: apply results: result.gethReturn()
// todo: if there is out specified place hReturn on the out
// 3. APPLY RESULTS: result.getHReturn() into out_memory allocated
ByteBuffer buffer = result.getHReturn();
if (buffer != null){
int retSize = buffer.array().length;
int allocSize = outDataSize.intValue();
if (retSize > allocSize){
byte[] outArray = Arrays.copyOf(buffer.array(), allocSize );
this.memorySave(outArray, buffer.array());
} else{
this.memorySave(outDataOffs.getData(), buffer.array());
}
}
detailDB.commitTrack();
chainDB.commitTrack();
@ -333,6 +344,7 @@ public class Program {
stackPush(new DataWord(1));
// the gas spent in any internal outcome
// even if execution was halted by an exception
spendGas(result.getGasUsed(), " 'Total for CALL run' ");
logger.info("The usage of the gas in external call updated", result.getGasUsed());
@ -536,8 +548,8 @@ public class Program {
globalOutput.append(" -- MEMORY -- ").append(memoryData).append("\n");
globalOutput.append(" -- STORAGE -- ").append(storageData).append("\n");
if (result.gethReturn() != null){
globalOutput.append("\n HReturn: ").append(Hex.toHexString(result.gethReturn().array()));
if (result.getHReturn() != null){
globalOutput.append("\n HReturn: ").append(Hex.toHexString(result.getHReturn().array()));
}
// soffisticated assumption that msg.data != codedata

View File

@ -32,7 +32,7 @@ public class ProgramResult {
this.hReturn.put(hReturn);
}
public ByteBuffer gethReturn() {
public ByteBuffer getHReturn() {
return hReturn;
}

View File

@ -114,7 +114,7 @@ public class VMComplexTest {
@Test // contract call recursive with data
@Test // contractB call contractA with data to storage
public void test2(){
/**
@ -216,10 +216,126 @@ public class VMComplexTest {
assertEquals(expectedVal_1, value_1.longValue());
assertEquals(expectedVal_2, value_2.longValue());
}
@Test // contractB call contractA with return expectation
public void test3(){
/**
* #The code will run
* ------------------
contract A: 77045e71a7a2c50903d88e564cd72fab11e82051
---------------
a = 11
b = 22
c = 33
d = 44
e = 55
f = 66
[asm 192 0 RETURN asm]
contract B: 83c5541a6c8d2dbad642f385d8d06ca9b6c731ee
-----------
a = msg((tx.gas / 10 * 8), 0x77045e71a7a2c50903d88e564cd72fab11e82051, 0, [11, 22, 33], 3, 6)
*/
long expectedVal_1 = 11;
long expectedVal_2 = 22;
long expectedVal_3 = 33;
long expectedVal_4 = 44;
long expectedVal_5 = 55;
long expectedVal_6 = 66;
// Set contract into Database
String callerAddr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
String contractA_addr = "77045e71a7a2c50903d88e564cd72fab11e82051";
String contractB_addr = "83c5541a6c8d2dbad642f385d8d06ca9b6c731ee";
String code_a = "600b60005460166020546021604054602c6060546037608054604260a05460c06000f2";
String code_b = "6000601f5560e05b60e05b54600060c05b015560605b6020015b51602001600b5254516040016016525451606001602152546080525460007377045e71a7a2c50903d88e564cd72fab11e820516103e8f1602060000260a00160200153600054";
byte[] caller_addr_bytes = Hex.decode(callerAddr);
byte[] contractA_addr_bytes = Hex.decode(contractA_addr);
byte[] codeA = Hex.decode(code_a);
byte[] codeA_Key = HashUtil.sha3(codeA);
AccountState accountState_a = new AccountState();
accountState_a.setCodeHash(codeA_Key);
WorldManager.instance.worldState.update(contractA_addr_bytes, accountState_a.getEncoded());
byte[] contractB_addr_bytes = Hex.decode(contractB_addr);
byte[] codeB = Hex.decode(code_b);
byte[] codeB_Key = HashUtil.sha3(codeB);
AccountState accountState_b = new AccountState();
accountState_b.setCodeHash(codeB_Key);
WorldManager.instance.worldState.update(contractB_addr_bytes, accountState_a.getEncoded());
AccountState callerAcountState = new AccountState();
callerAcountState.addToBalance(new BigInteger("100000000000000000000"));
WorldManager.instance.worldState.update(caller_addr_bytes, callerAcountState.getEncoded());
WorldManager.instance.chainDB.put(codeA_Key, codeA);
TrackTrie stateDB = new TrackTrie(WorldManager.instance.worldState);
TrackDatabase chainDb = new TrackDatabase(WorldManager.instance.chainDB);
TrackDatabase detaildDB = new TrackDatabase(WorldManager.instance.detaildDB);
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
pi.setDetaildDB(detaildDB);
pi.setChainDb(chainDb);
pi.setStateDB(stateDB);
pi.setDetails(null);
pi.setOwnerAddress(contractB_addr);
// ****************** //
// 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 ============");
AccountState as =
new AccountState(WorldManager.instance.worldState.get(
Hex.decode( contractA_addr) ));
System.out.println("*** Used gas: " + program.result.getGasUsed());
DataWord value1 = program.memoryLoad(new DataWord(32));
DataWord value2 = program.memoryLoad(new DataWord(64));
DataWord value3 = program.memoryLoad(new DataWord(96));
DataWord value4 = program.memoryLoad(new DataWord(128));
DataWord value5 = program.memoryLoad(new DataWord(160));
DataWord value6 = program.memoryLoad(new DataWord(192));
assertEquals(expectedVal_1, value1.longValue());
assertEquals(expectedVal_2, value2.longValue());
assertEquals(expectedVal_3, value3.longValue());
assertEquals(expectedVal_4, value4.longValue());
assertEquals(expectedVal_5, value5.longValue());
assertEquals(expectedVal_6, value6.longValue());
}
}

View File

@ -2141,7 +2141,7 @@ public class VMTest {
vm.step(program);
vm.step(program);
assertEquals(s_expected_1, Hex.toHexString(program.getResult().gethReturn().array()).toUpperCase());
assertEquals(s_expected_1, Hex.toHexString(program.getResult().getHReturn().array()).toUpperCase());
assertTrue(program.stopped);
}
@ -2160,7 +2160,7 @@ public class VMTest {
vm.step(program);
vm.step(program);
assertEquals(s_expected_1, Hex.toHexString(program.getResult().gethReturn().array()).toUpperCase());
assertEquals(s_expected_1, Hex.toHexString(program.getResult().getHReturn().array()).toUpperCase());
assertTrue(program.stopped);
}
@ -2180,7 +2180,7 @@ public class VMTest {
vm.step(program);
vm.step(program);
assertEquals(s_expected_1, Hex.toHexString(program.getResult().gethReturn().array()).toUpperCase());
assertEquals(s_expected_1, Hex.toHexString(program.getResult().getHReturn().array()).toUpperCase());
assertTrue(program.stopped);
}
@ -2201,7 +2201,7 @@ public class VMTest {
vm.step(program);
vm.step(program);
assertEquals(s_expected_1, Hex.toHexString(program.getResult().gethReturn().array()).toUpperCase());
assertEquals(s_expected_1, Hex.toHexString(program.getResult().getHReturn().array()).toUpperCase());
assertTrue(program.stopped);
}