mirror of https://github.com/ethereum/go-ethereum
parent
086acd122b
commit
ca13e3b105
@ -0,0 +1,126 @@ |
|||||||
|
package ethchain |
||||||
|
|
||||||
|
import ( |
||||||
|
"fmt" |
||||||
|
"github.com/ethereum/eth-go/ethutil" |
||||||
|
"math/big" |
||||||
|
"regexp" |
||||||
|
) |
||||||
|
|
||||||
|
func CompileInstr(s interface{}) ([]byte, error) { |
||||||
|
switch s.(type) { |
||||||
|
case string: |
||||||
|
str := s.(string) |
||||||
|
isOp := IsOpCode(str) |
||||||
|
if isOp { |
||||||
|
return []byte{OpCodes[str]}, nil |
||||||
|
} |
||||||
|
|
||||||
|
num := new(big.Int) |
||||||
|
_, success := num.SetString(str, 0) |
||||||
|
// Assume regular bytes during compilation
|
||||||
|
if !success { |
||||||
|
num.SetBytes([]byte(str)) |
||||||
|
} else { |
||||||
|
// tmp fix for 32 bytes
|
||||||
|
n := ethutil.BigToBytes(num, 256) |
||||||
|
return n, nil |
||||||
|
} |
||||||
|
|
||||||
|
return num.Bytes(), nil |
||||||
|
case int: |
||||||
|
num := ethutil.BigToBytes(big.NewInt(int64(s.(int))), 256) |
||||||
|
return num, nil |
||||||
|
case []byte: |
||||||
|
return ethutil.BigD(s.([]byte)).Bytes(), nil |
||||||
|
} |
||||||
|
|
||||||
|
return nil, nil |
||||||
|
} |
||||||
|
|
||||||
|
// Script compilation functions
|
||||||
|
// Compiles strings to machine code
|
||||||
|
func Assemble(instructions ...interface{}) (script []byte) { |
||||||
|
//script = make([]string, len(instructions))
|
||||||
|
|
||||||
|
for _, val := range instructions { |
||||||
|
instr, _ := CompileInstr(val) |
||||||
|
|
||||||
|
//script[i] = string(instr)
|
||||||
|
script = append(script, instr...) |
||||||
|
} |
||||||
|
|
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
func Disassemble(script []byte) (asm []string) { |
||||||
|
pc := new(big.Int) |
||||||
|
for { |
||||||
|
if pc.Cmp(big.NewInt(int64(len(script)))) >= 0 { |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
// Get the memory location of pc
|
||||||
|
val := script[pc.Int64()] |
||||||
|
// Get the opcode (it must be an opcode!)
|
||||||
|
op := OpCode(val) |
||||||
|
|
||||||
|
asm = append(asm, fmt.Sprintf("%v", op)) |
||||||
|
|
||||||
|
switch op { |
||||||
|
case oPUSH: // Push PC+1 on to the stack
|
||||||
|
pc.Add(pc, ethutil.Big1) |
||||||
|
data := script[pc.Int64() : pc.Int64()+32] |
||||||
|
val := ethutil.BigD(data) |
||||||
|
|
||||||
|
var b []byte |
||||||
|
if val.Int64() == 0 { |
||||||
|
b = []byte{0} |
||||||
|
} else { |
||||||
|
b = val.Bytes() |
||||||
|
} |
||||||
|
|
||||||
|
asm = append(asm, fmt.Sprintf("0x%x", b)) |
||||||
|
|
||||||
|
pc.Add(pc, big.NewInt(31)) |
||||||
|
case oPUSH20: |
||||||
|
pc.Add(pc, ethutil.Big1) |
||||||
|
data := script[pc.Int64() : pc.Int64()+20] |
||||||
|
val := ethutil.BigD(data) |
||||||
|
var b []byte |
||||||
|
if val.Int64() == 0 { |
||||||
|
b = []byte{0} |
||||||
|
} else { |
||||||
|
b = val.Bytes() |
||||||
|
} |
||||||
|
|
||||||
|
asm = append(asm, fmt.Sprintf("0x%x", b)) |
||||||
|
|
||||||
|
pc.Add(pc, big.NewInt(19)) |
||||||
|
} |
||||||
|
|
||||||
|
pc.Add(pc, ethutil.Big1) |
||||||
|
} |
||||||
|
|
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
func PreProcess(data string) (mainInput, initInput string) { |
||||||
|
reg := "\\(\\)\\s*{([\\d\\w\\W\\n\\s]+?)}" |
||||||
|
mainReg := regexp.MustCompile("main" + reg) |
||||||
|
initReg := regexp.MustCompile("init" + reg) |
||||||
|
|
||||||
|
main := mainReg.FindStringSubmatch(data) |
||||||
|
if len(main) > 0 { |
||||||
|
mainInput = main[1] |
||||||
|
} else { |
||||||
|
mainInput = data |
||||||
|
} |
||||||
|
|
||||||
|
init := initReg.FindStringSubmatch(data) |
||||||
|
if len(init) > 0 { |
||||||
|
initInput = init[1] |
||||||
|
} |
||||||
|
|
||||||
|
return |
||||||
|
} |
@ -0,0 +1,230 @@ |
|||||||
|
package ethchain |
||||||
|
|
||||||
|
type OpCode int |
||||||
|
|
||||||
|
// Op codes
|
||||||
|
const ( |
||||||
|
// 0x0 range - arithmetic ops
|
||||||
|
oSTOP = 0x00 |
||||||
|
oADD = 0x01 |
||||||
|
oMUL = 0x02 |
||||||
|
oSUB = 0x03 |
||||||
|
oDIV = 0x04 |
||||||
|
oSDIV = 0x05 |
||||||
|
oMOD = 0x06 |
||||||
|
oSMOD = 0x07 |
||||||
|
oEXP = 0x08 |
||||||
|
oNEG = 0x09 |
||||||
|
oLT = 0x0a |
||||||
|
oGT = 0x0b |
||||||
|
oEQ = 0x0c |
||||||
|
oNOT = 0x0d |
||||||
|
|
||||||
|
// 0x10 range - bit ops
|
||||||
|
oAND = 0x10 |
||||||
|
oOR = 0x11 |
||||||
|
oXOR = 0x12 |
||||||
|
oBYTE = 0x13 |
||||||
|
|
||||||
|
// 0x20 range - crypto
|
||||||
|
oSHA3 = 0x20 |
||||||
|
|
||||||
|
// 0x30 range - closure state
|
||||||
|
oADDRESS = 0x30 |
||||||
|
oBALANCE = 0x31 |
||||||
|
oORIGIN = 0x32 |
||||||
|
oCALLER = 0x33 |
||||||
|
oCALLVALUE = 0x34 |
||||||
|
oCALLDATA = 0x35 |
||||||
|
oCALLDATASIZE = 0x36 |
||||||
|
oGASPRICE = 0x37 |
||||||
|
|
||||||
|
// 0x40 range - block operations
|
||||||
|
oPREVHASH = 0x40 |
||||||
|
oCOINBASE = 0x41 |
||||||
|
oTIMESTAMP = 0x42 |
||||||
|
oNUMBER = 0x43 |
||||||
|
oDIFFICULTY = 0x44 |
||||||
|
oGASLIMIT = 0x45 |
||||||
|
|
||||||
|
// 0x50 range - 'storage' and execution
|
||||||
|
oPUSH = 0x50 |
||||||
|
oPUSH20 = 0x80 |
||||||
|
oPOP = 0x51 |
||||||
|
oDUP = 0x52 |
||||||
|
oSWAP = 0x53 |
||||||
|
oMLOAD = 0x54 |
||||||
|
oMSTORE = 0x55 |
||||||
|
oMSTORE8 = 0x56 |
||||||
|
oSLOAD = 0x57 |
||||||
|
oSSTORE = 0x58 |
||||||
|
oJUMP = 0x59 |
||||||
|
oJUMPI = 0x5a |
||||||
|
oPC = 0x5b |
||||||
|
oMSIZE = 0x5c |
||||||
|
|
||||||
|
// 0x60 range - closures
|
||||||
|
oCREATE = 0x60 |
||||||
|
oCALL = 0x61 |
||||||
|
oRETURN = 0x62 |
||||||
|
|
||||||
|
// 0x70 range - other
|
||||||
|
oLOG = 0x70 // XXX Unofficial
|
||||||
|
oSUICIDE = 0x7f |
||||||
|
) |
||||||
|
|
||||||
|
// Since the opcodes aren't all in order we can't use a regular slice
|
||||||
|
var opCodeToString = map[OpCode]string{ |
||||||
|
// 0x0 range - arithmetic ops
|
||||||
|
oSTOP: "STOP", |
||||||
|
oADD: "ADD", |
||||||
|
oMUL: "MUL", |
||||||
|
oSUB: "SUB", |
||||||
|
oDIV: "DIV", |
||||||
|
oSDIV: "SDIV", |
||||||
|
oMOD: "MOD", |
||||||
|
oSMOD: "SMOD", |
||||||
|
oEXP: "EXP", |
||||||
|
oNEG: "NEG", |
||||||
|
oLT: "LT", |
||||||
|
oGT: "GT", |
||||||
|
oEQ: "EQ", |
||||||
|
oNOT: "NOT", |
||||||
|
|
||||||
|
// 0x10 range - bit ops
|
||||||
|
oAND: "AND", |
||||||
|
oOR: "OR", |
||||||
|
oXOR: "XOR", |
||||||
|
oBYTE: "BYTE", |
||||||
|
|
||||||
|
// 0x20 range - crypto
|
||||||
|
oSHA3: "SHA3", |
||||||
|
|
||||||
|
// 0x30 range - closure state
|
||||||
|
oADDRESS: "ADDRESS", |
||||||
|
oBALANCE: "BALANCE", |
||||||
|
oORIGIN: "ORIGIN", |
||||||
|
oCALLER: "CALLER", |
||||||
|
oCALLVALUE: "CALLVALUE", |
||||||
|
oCALLDATA: "CALLDATA", |
||||||
|
oCALLDATASIZE: "CALLDATASIZE", |
||||||
|
oGASPRICE: "TXGASPRICE", |
||||||
|
|
||||||
|
// 0x40 range - block operations
|
||||||
|
oPREVHASH: "PREVHASH", |
||||||
|
oCOINBASE: "COINBASE", |
||||||
|
oTIMESTAMP: "TIMESTAMP", |
||||||
|
oNUMBER: "NUMBER", |
||||||
|
oDIFFICULTY: "DIFFICULTY", |
||||||
|
oGASLIMIT: "GASLIMIT", |
||||||
|
|
||||||
|
// 0x50 range - 'storage' and execution
|
||||||
|
oPUSH: "PUSH", |
||||||
|
oPOP: "POP", |
||||||
|
oDUP: "DUP", |
||||||
|
oSWAP: "SWAP", |
||||||
|
oMLOAD: "MLOAD", |
||||||
|
oMSTORE: "MSTORE", |
||||||
|
oMSTORE8: "MSTORE8", |
||||||
|
oSLOAD: "SLOAD", |
||||||
|
oSSTORE: "SSTORE", |
||||||
|
oJUMP: "JUMP", |
||||||
|
oJUMPI: "JUMPI", |
||||||
|
oPC: "PC", |
||||||
|
oMSIZE: "MSIZE", |
||||||
|
|
||||||
|
// 0x60 range - closures
|
||||||
|
oCREATE: "CREATE", |
||||||
|
oCALL: "CALL", |
||||||
|
oRETURN: "RETURN", |
||||||
|
|
||||||
|
// 0x70 range - other
|
||||||
|
oLOG: "LOG", |
||||||
|
oSUICIDE: "SUICIDE", |
||||||
|
} |
||||||
|
|
||||||
|
func (o OpCode) String() string { |
||||||
|
return opCodeToString[o] |
||||||
|
} |
||||||
|
|
||||||
|
// Op codes for assembling
|
||||||
|
var OpCodes = map[string]byte{ |
||||||
|
// 0x0 range - arithmetic ops
|
||||||
|
"STOP": 0x00, |
||||||
|
"ADD": 0x01, |
||||||
|
"MUL": 0x02, |
||||||
|
"SUB": 0x03, |
||||||
|
"DIV": 0x04, |
||||||
|
"SDIV": 0x05, |
||||||
|
"MOD": 0x06, |
||||||
|
"SMOD": 0x07, |
||||||
|
"EXP": 0x08, |
||||||
|
"NEG": 0x09, |
||||||
|
"LT": 0x0a, |
||||||
|
"GT": 0x0b, |
||||||
|
"EQ": 0x0c, |
||||||
|
"NOT": 0x0d, |
||||||
|
|
||||||
|
// 0x10 range - bit ops
|
||||||
|
"AND": 0x10, |
||||||
|
"OR": 0x11, |
||||||
|
"XOR": 0x12, |
||||||
|
"BYTE": 0x13, |
||||||
|
|
||||||
|
// 0x20 range - crypto
|
||||||
|
"SHA3": 0x20, |
||||||
|
|
||||||
|
// 0x30 range - closure state
|
||||||
|
"ADDRESS": 0x30, |
||||||
|
"BALANCE": 0x31, |
||||||
|
"ORIGIN": 0x32, |
||||||
|
"CALLER": 0x33, |
||||||
|
"CALLVALUE": 0x34, |
||||||
|
"CALLDATA": 0x35, |
||||||
|
"CALLDATASIZE": 0x36, |
||||||
|
"GASPRICE": 0x38, |
||||||
|
|
||||||
|
// 0x40 range - block operations
|
||||||
|
"PREVHASH": 0x40, |
||||||
|
"COINBASE": 0x41, |
||||||
|
"TIMESTAMP": 0x42, |
||||||
|
"NUMBER": 0x43, |
||||||
|
"DIFFICULTY": 0x44, |
||||||
|
"GASLIMIT": 0x45, |
||||||
|
|
||||||
|
// 0x50 range - 'storage' and execution
|
||||||
|
"PUSH": 0x50, |
||||||
|
|
||||||
|
"PUSH20": 0x80, |
||||||
|
|
||||||
|
"POP": 0x51, |
||||||
|
"DUP": 0x52, |
||||||
|
"SWAP": 0x53, |
||||||
|
"MLOAD": 0x54, |
||||||
|
"MSTORE": 0x55, |
||||||
|
"MSTORE8": 0x56, |
||||||
|
"SLOAD": 0x57, |
||||||
|
"SSTORE": 0x58, |
||||||
|
"JUMP": 0x59, |
||||||
|
"JUMPI": 0x5a, |
||||||
|
"PC": 0x5b, |
||||||
|
"MSIZE": 0x5c, |
||||||
|
|
||||||
|
// 0x60 range - closures
|
||||||
|
"CREATE": 0x60, |
||||||
|
"CALL": 0x61, |
||||||
|
"RETURN": 0x62, |
||||||
|
|
||||||
|
// 0x70 range - other
|
||||||
|
"LOG": 0x70, |
||||||
|
"SUICIDE": 0x7f, |
||||||
|
} |
||||||
|
|
||||||
|
func IsOpCode(s string) bool { |
||||||
|
for key, _ := range OpCodes { |
||||||
|
if key == s { |
||||||
|
return true |
||||||
|
} |
||||||
|
} |
||||||
|
return false |
||||||
|
} |
Loading…
Reference in new issue