Header for Contract VM runnable structure
This commit is contained in:
parent
71e185d9eb
commit
dc5cda4ddb
|
@ -3,7 +3,9 @@ package org.ethereum.serpent;
|
||||||
import org.antlr.v4.runtime.tree.ParseTree;
|
import org.antlr.v4.runtime.tree.ParseTree;
|
||||||
import org.ethereum.util.ByteUtil;
|
import org.ethereum.util.ByteUtil;
|
||||||
import org.ethereum.vm.OpCode;
|
import org.ethereum.vm.OpCode;
|
||||||
|
import org.spongycastle.util.Arrays;
|
||||||
import org.spongycastle.util.BigIntegers;
|
import org.spongycastle.util.BigIntegers;
|
||||||
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
@ -51,12 +53,14 @@ public class SerpentCompiler {
|
||||||
if (lexa.equals("asm]")){
|
if (lexa.equals("asm]")){
|
||||||
skiping = false;
|
skiping = false;
|
||||||
lexaList.remove(i);
|
lexaList.remove(i);
|
||||||
lexa = lexaList.get(i);
|
--i;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lexa.equals("[asm")){
|
if (lexa.equals("[asm")){
|
||||||
skiping = true;
|
skiping = true;
|
||||||
lexaList.remove(i);
|
lexaList.remove(i);
|
||||||
|
--i;
|
||||||
continue;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ public enum OpCode {
|
||||||
CALLDATASIZE(0x36),
|
CALLDATASIZE(0x36),
|
||||||
CALLDATACOPY(0x37),
|
CALLDATACOPY(0x37),
|
||||||
CODESIZE(0x38),
|
CODESIZE(0x38),
|
||||||
CODECOPY(0x39),
|
CODECOPY(0x39), // [len src_start target_start CODECOPY]
|
||||||
GASPRICE(0x3a),
|
GASPRICE(0x3a),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -275,7 +275,7 @@ public class SerpentCompileTest {
|
||||||
@Test // expression test 10
|
@Test // expression test 10
|
||||||
public void test15(){
|
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";
|
String expected = "2 8 EQ 9 2 MUL 1 ADD OR NOT 0 MSTORE";
|
||||||
|
|
||||||
SerpentParser parser = ParserUtils.getParser(SerpentLexer.class, SerpentParser.class,
|
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
|
* todo: return(1) testing
|
||||||
* return (1,2) testing
|
* todo: return (1,2) testing
|
||||||
* todo: msg.data testing
|
* todo: msg.data testing
|
||||||
* todo: contract.storage testing
|
* todo: contract.storage get/set testing
|
||||||
* todo: [asm asm] testing
|
* todo: [asm asm] testing
|
||||||
* todo: suicide(1) testing
|
* todo: suicide(1) testing
|
||||||
* todo: stop test
|
* todo: stop testing
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue