mirror of https://github.com/ethereum/go-ethereum
parent
bf850974f3
commit
21f8806eed
@ -1,193 +0,0 @@ |
|||||||
package ethutil |
|
||||||
|
|
||||||
import ( |
|
||||||
_ "fmt" |
|
||||||
"math/big" |
|
||||||
_ "regexp" |
|
||||||
) |
|
||||||
|
|
||||||
// Op codes
|
|
||||||
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, |
|
||||||
"CALLDATALOAD": 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, |
|
||||||
} |
|
||||||
|
|
||||||
// Is op code
|
|
||||||
//
|
|
||||||
// Check whether the given string matches anything in
|
|
||||||
// the OpCode list
|
|
||||||
func IsOpCode(s string) bool { |
|
||||||
for key, _ := range OpCodes { |
|
||||||
if key == s { |
|
||||||
return true |
|
||||||
} |
|
||||||
} |
|
||||||
return false |
|
||||||
} |
|
||||||
|
|
||||||
// Compile instruction
|
|
||||||
//
|
|
||||||
// Attempts to compile and parse the given instruction in "s"
|
|
||||||
// and returns the byte sequence
|
|
||||||
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 := BigToBytes(num, 256) |
|
||||||
return n, nil |
|
||||||
} |
|
||||||
|
|
||||||
return num.Bytes(), nil |
|
||||||
case int: |
|
||||||
num := BigToBytes(big.NewInt(int64(s.(int))), 256) |
|
||||||
return num, nil |
|
||||||
case []byte: |
|
||||||
return BigD(s.([]byte)).Bytes(), nil |
|
||||||
} |
|
||||||
|
|
||||||
return nil, nil |
|
||||||
} |
|
||||||
|
|
||||||
// Assemble
|
|
||||||
//
|
|
||||||
// Assembles the given instructions and returns EVM byte 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 |
|
||||||
} |
|
||||||
|
|
||||||
// Pre process script
|
|
||||||
//
|
|
||||||
// Take data apart and attempt to find the "init" section and
|
|
||||||
// "main" section. `main { } init { }`
|
|
||||||
func PreProcess(data string) (mainInput, initInput string) { |
|
||||||
mainInput = getCodeSectionFor("main", data) |
|
||||||
if mainInput == "" { |
|
||||||
mainInput = data |
|
||||||
} |
|
||||||
initInput = getCodeSectionFor("init", data) |
|
||||||
|
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
// Very, very dumb parser. Heed no attention :-)
|
|
||||||
func getCodeSectionFor(blockMatcher, input string) string { |
|
||||||
curCount := -1 |
|
||||||
length := len(blockMatcher) |
|
||||||
matchfst := rune(blockMatcher[0]) |
|
||||||
var currStr string |
|
||||||
|
|
||||||
for i, run := range input { |
|
||||||
// Find init
|
|
||||||
if curCount == -1 && run == matchfst && input[i:i+length] == blockMatcher { |
|
||||||
curCount = 0 |
|
||||||
} else if curCount > -1 { |
|
||||||
if run == '{' { |
|
||||||
curCount++ |
|
||||||
if curCount == 1 { |
|
||||||
continue |
|
||||||
} |
|
||||||
} else if run == '}' { |
|
||||||
curCount-- |
|
||||||
if curCount == 0 { |
|
||||||
// we are done
|
|
||||||
curCount = -1 |
|
||||||
break |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if curCount > 0 { |
|
||||||
currStr += string(run) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return currStr |
|
||||||
} |
|
@ -1,31 +0,0 @@ |
|||||||
package ethutil |
|
||||||
|
|
||||||
import ( |
|
||||||
"fmt" |
|
||||||
"testing" |
|
||||||
) |
|
||||||
|
|
||||||
func TestPreProcess(t *testing.T) { |
|
||||||
main, init := PreProcess(` |
|
||||||
init { |
|
||||||
// init
|
|
||||||
if a > b { |
|
||||||
if {
|
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
main { |
|
||||||
// main
|
|
||||||
if a > b { |
|
||||||
if c > d { |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
`) |
|
||||||
|
|
||||||
fmt.Println("main") |
|
||||||
fmt.Println(main) |
|
||||||
fmt.Println("init") |
|
||||||
fmt.Println(init) |
|
||||||
} |
|
Loading…
Reference in new issue