CALL op with in/out data
+ support for return + VMComplexText test3 demonstrates the return applied
This commit is contained in:
parent
d2676eda92
commit
0b02376c17
|
@ -4,15 +4,16 @@
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
- [x] **VM execution:** support CALL op
|
- [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:** support CREATE op
|
||||||
|
- [ ] **VM execution:** SUICIDE op adjust
|
||||||
- [ ] **ProgramPlayDialog** support internal calls
|
- [ ] **ProgramPlayDialog** support internal calls
|
||||||
- [ ] **Build:** extract core module and studio application
|
- [ ] **Build:** extract core module and studio application
|
||||||
- [ ] **Performance:** BigInteger math change for constant arrays implementation
|
- [ ] **Performance:** BigInteger math change for constant arrays implementation
|
||||||
economy for memory allocation
|
economy for memory allocation
|
||||||
- [ ] **Command Line:** add the headless run option
|
- [ ] **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
|
- [ ] **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
|
(@> @< @/ @%) - unsigned operations
|
||||||
> < / % - default are all signed operations
|
> < / % - default are all signed operations
|
||||||
+= -= *= /= %= @/= @%= - short form operations
|
+= -= *= /= %= @/= @%= - short form operations
|
||||||
|
@ -23,7 +24,9 @@ share - code section
|
||||||
##### UnitTest:
|
##### UnitTest:
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
- [ ] **VM complex: CALL testing for in/out arrays
|
- [x] **VM complex:** CALL testing for in arrays
|
||||||
- [ ] **VM complex: CREATE testing
|
- [x] **VM complex:** CALL testing for out result
|
||||||
|
- [ ] **VM complex:** CREATE testing
|
||||||
|
- [ ] **VM complex:** SUICIDE testing
|
||||||
- [ ] **WorldManager** apply transactions
|
- [ ] **WorldManager** apply transactions
|
||||||
|
|
||||||
|
|
|
@ -198,7 +198,7 @@ public class ProgramPlayDialog extends JPanel implements ActionListener,
|
||||||
//Schedule a job for the event-dispatching thread:
|
//Schedule a job for the event-dispatching thread:
|
||||||
//creating and showing this application's GUI.
|
//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);
|
final byte[] code = SerpentCompiler.compileAssemblyToMachine(asmCode);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -286,9 +286,9 @@ public class WorldManager {
|
||||||
|
|
||||||
// Save the code created by init
|
// Save the code created by init
|
||||||
byte[] bodyCode = null;
|
byte[] bodyCode = null;
|
||||||
if (result.gethReturn() != null){
|
if (result.getHReturn() != null){
|
||||||
|
|
||||||
bodyCode = result.gethReturn().array();
|
bodyCode = result.getHReturn().array();
|
||||||
}
|
}
|
||||||
|
|
||||||
BigInteger gasPrice =
|
BigInteger gasPrice =
|
||||||
|
|
|
@ -323,9 +323,20 @@ public class Program {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: apply results: result.gethReturn()
|
// 3. APPLY RESULTS: result.getHReturn() into out_memory allocated
|
||||||
// todo: if there is out specified place hReturn on the out
|
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();
|
detailDB.commitTrack();
|
||||||
chainDB.commitTrack();
|
chainDB.commitTrack();
|
||||||
|
@ -333,6 +344,7 @@ public class Program {
|
||||||
stackPush(new DataWord(1));
|
stackPush(new DataWord(1));
|
||||||
|
|
||||||
// the gas spent in any internal outcome
|
// the gas spent in any internal outcome
|
||||||
|
// even if execution was halted by an exception
|
||||||
spendGas(result.getGasUsed(), " 'Total for CALL run' ");
|
spendGas(result.getGasUsed(), " 'Total for CALL run' ");
|
||||||
logger.info("The usage of the gas in external call updated", result.getGasUsed());
|
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(" -- MEMORY -- ").append(memoryData).append("\n");
|
||||||
globalOutput.append(" -- STORAGE -- ").append(storageData).append("\n");
|
globalOutput.append(" -- STORAGE -- ").append(storageData).append("\n");
|
||||||
|
|
||||||
if (result.gethReturn() != null){
|
if (result.getHReturn() != null){
|
||||||
globalOutput.append("\n HReturn: ").append(Hex.toHexString(result.gethReturn().array()));
|
globalOutput.append("\n HReturn: ").append(Hex.toHexString(result.getHReturn().array()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// soffisticated assumption that msg.data != codedata
|
// soffisticated assumption that msg.data != codedata
|
||||||
|
|
|
@ -32,7 +32,7 @@ public class ProgramResult {
|
||||||
this.hReturn.put(hReturn);
|
this.hReturn.put(hReturn);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer gethReturn() {
|
public ByteBuffer getHReturn() {
|
||||||
return hReturn;
|
return hReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ public class VMComplexTest {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Test // contract call recursive with data
|
@Test // contractB call contractA with data to storage
|
||||||
public void test2(){
|
public void test2(){
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -216,10 +216,126 @@ public class VMComplexTest {
|
||||||
assertEquals(expectedVal_1, value_1.longValue());
|
assertEquals(expectedVal_1, value_1.longValue());
|
||||||
assertEquals(expectedVal_2, value_2.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());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2141,7 +2141,7 @@ public class VMTest {
|
||||||
vm.step(program);
|
vm.step(program);
|
||||||
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);
|
assertTrue(program.stopped);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2160,7 +2160,7 @@ public class VMTest {
|
||||||
vm.step(program);
|
vm.step(program);
|
||||||
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);
|
assertTrue(program.stopped);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2180,7 +2180,7 @@ public class VMTest {
|
||||||
vm.step(program);
|
vm.step(program);
|
||||||
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);
|
assertTrue(program.stopped);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2201,7 +2201,7 @@ public class VMTest {
|
||||||
vm.step(program);
|
vm.step(program);
|
||||||
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);
|
assertTrue(program.stopped);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue