Header for Contract VM runnable structure

This commit is contained in:
romanman 2014-05-28 20:20:46 +03:00
parent 71e185d9eb
commit dc5cda4ddb
4 changed files with 80 additions and 6 deletions

View File

@ -3,7 +3,9 @@ package org.ethereum.serpent;
import org.antlr.v4.runtime.tree.ParseTree;
import org.ethereum.util.ByteUtil;
import org.ethereum.vm.OpCode;
import org.spongycastle.util.Arrays;
import org.spongycastle.util.BigIntegers;
import org.spongycastle.util.encoders.Hex;
import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
@ -51,12 +53,14 @@ public class SerpentCompiler {
if (lexa.equals("asm]")){
skiping = false;
lexaList.remove(i);
lexa = lexaList.get(i);
--i;
continue;
}
if (lexa.equals("[asm")){
skiping = true;
lexaList.remove(i);
--i;
continue;
}
@ -140,6 +144,29 @@ public class SerpentCompiler {
}
public static byte[] encodeMachineCodeForVMRun(byte[] code){
if (code == null || code.length == 0) throw new RuntimeException("code can't be empty code: " + code);
int numBytes = ByteUtil.numBytes(code.length + "");
byte[] lenBytes = BigInteger.valueOf(code.length).toByteArray();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < lenBytes.length; ++i){
sb.append(Hex.toHexString(lenBytes, i, 1)).append(" ");
}
// calc real code start position (after the init header)
int pos = 10 + numBytes * 2;
// @push_len @len PUSH1 @src_start PUSH1 0 CODECOPY @push_len @len 0 PUSH1 0 RETURN
String header = String.format("[asm %s %s PUSH1 %d PUSH1 0 CODECOPY %s %s PUSH1 0 RETURN asm]",
"PUSH" + numBytes, sb.toString(), pos , "PUSH" + numBytes, sb.toString());
byte[] headerMachine = compileAssemblyToMachine(header);
return Arrays.concatenate(headerMachine, code);
}
}

View File

@ -54,7 +54,7 @@ public enum OpCode {
CALLDATASIZE(0x36),
CALLDATACOPY(0x37),
CODESIZE(0x38),
CODECOPY(0x39),
CODECOPY(0x39), // [len src_start target_start CODECOPY]
GASPRICE(0x3a),
/**

View File

@ -0,0 +1,32 @@
package org.ethereum.serpent;
import org.ethereum.gui.GUIUtils;
import org.junit.Assert;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 28/05/2014 20:05
*/
public class MachineCompileTest {
@Test //
public void test1(){
String code = "a=2";
String expected = "6005600c60003960056000f26002600054";
String asm = SerpentCompiler.compile(code);
byte[] machineCode = SerpentCompiler.compileAssemblyToMachine(asm);
byte[] vmReadyCode = SerpentCompiler.encodeMachineCodeForVMRun(machineCode);
System.out.println(GUIUtils.getHexStyledText(vmReadyCode));
String result = Hex.toHexString(vmReadyCode);
Assert.assertEquals(expected, result);
}
}

View File

@ -275,7 +275,7 @@ public class SerpentCompileTest {
@Test // expression test 10
public void test15(){
String code = "a = not ( 1 + 2 * 9 | 8 == 2)";
String code = "a = !( 1 + 2 * 9 | 8 == 2)";
String expected = "2 8 EQ 9 2 MUL 1 ADD OR NOT 0 MSTORE";
SerpentParser parser = ParserUtils.getParser(SerpentLexer.class, SerpentParser.class,
@ -1245,15 +1245,30 @@ public class SerpentCompileTest {
}
/*
todo: more to implement
# 1) send(1, 2, 3)
# 2) create(1, 2, 3, 4)
# 3) x = sha3(v)
# 4) x = byte(y,z)
# 5) v = getch(x,i)
# 6) setch(x,i,v)
# 7) a=array(30)
# 8) x = bytes(n)
*/
/**
*
* todo: return(1) testing
* return (1,2) testing
* todo: return (1,2) testing
* todo: msg.data testing
* todo: contract.storage testing
* todo: contract.storage get/set testing
* todo: [asm asm] testing
* todo: suicide(1) testing
* todo: stop test
* todo: stop testing
*
*
*/