quorum/core/vm/opcodes.go

519 lines
9.2 KiB
Go
Raw Normal View History

2015-07-06 17:54:22 -07:00
// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
2015-07-06 17:54:22 -07:00
//
// The go-ethereum library is free software: you can redistribute it and/or modify
2015-07-06 17:54:22 -07:00
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
2015-07-06 17:54:22 -07:00
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2015-07-06 17:54:22 -07:00
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
2015-07-06 17:54:22 -07:00
2014-10-18 04:31:20 -07:00
package vm
import (
"fmt"
)
// OpCode is an EVM opcode
type OpCode byte
func (op OpCode) IsPush() bool {
switch op {
case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32:
return true
}
return false
}
core, core/vm: dual state & read only EVM This commit implements a dual state approach. The dual state approach separates public and private state by making the core vm environment context aware. Although not currently implemented it will need to prohibit value transfers and it must initialise all transactions from accounts on the public state. This means that sending transactions increments the account nonce on the public state and contract addresses are derived from the public state when initialised by a transaction. For obvious reasons, contract created by private contracts are still derived from public state. This is required in order to have consensus over the public state at all times as non-private participants would still process the transaction on the public state even though private payload can not be decrypted. This means that participants of a private group must do the same in order to have public consensus. However the creation of the contract and interaction still occurs on the private state. It implements support for the following calling model: S: sender, (X): private, X: public, ->: direction, [ ]: read only mode 1. S -> A -> B 2. S -> (A) -> (B) 3. S -> (A) -> [ B -> C ] It does not support 1. (S) -> A 2. (S) -> (A) 3. S -> (A) -> B Implemented "read only" mode for the EVM. Read only mode is checked during any opcode that could potentially modify the state. If such an opcode is encountered during "read only", it throws an exception. The EVM is flagged "read only" when a private contract calls in to public state.
2016-10-31 04:46:40 -07:00
func (op OpCode) isMutating() bool {
switch op {
case SUICIDE, CREATE, SSTORE, LOG0, LOG1, LOG2, LOG3, LOG4:
return true
default:
return false
}
}
func (op OpCode) IsStaticJump() bool {
return op == JUMP
}
const (
// 0x0 range - arithmetic ops
2014-10-31 17:18:03 -07:00
STOP OpCode = iota
ADD
MUL
SUB
DIV
SDIV
MOD
SMOD
ADDMOD
MULMOD
EXP
SIGNEXTEND
)
2014-10-31 17:18:03 -07:00
const (
LT OpCode = iota + 0x10
GT
SLT
SGT
EQ
ISZERO
AND
OR
XOR
NOT
BYTE
SHA3 = 0x20
2014-10-31 17:18:03 -07:00
)
2014-10-31 17:18:03 -07:00
const (
// 0x30 range - closure state
2014-10-31 17:18:03 -07:00
ADDRESS OpCode = 0x30 + iota
BALANCE
ORIGIN
CALLER
CALLVALUE
CALLDATALOAD
CALLDATASIZE
CALLDATACOPY
CODESIZE
CODECOPY
GASPRICE
EXTCODESIZE
EXTCODECOPY
)
const (
// 0x40 range - block operations
BLOCKHASH OpCode = 0x40 + iota
2014-10-31 17:18:03 -07:00
COINBASE
TIMESTAMP
NUMBER
DIFFICULTY
GASLIMIT
)
2014-10-31 17:18:03 -07:00
const (
// 0x50 range - 'storage' and execution
2014-10-31 17:18:03 -07:00
POP OpCode = 0x50 + iota
MLOAD
MSTORE
MSTORE8
SLOAD
SSTORE
JUMP
JUMPI
PC
MSIZE
GAS
JUMPDEST
)
2014-10-31 17:18:03 -07:00
const (
// 0x60 range
2014-10-31 17:18:03 -07:00
PUSH1 OpCode = 0x60 + iota
PUSH2
PUSH3
PUSH4
PUSH5
PUSH6
PUSH7
PUSH8
PUSH9
PUSH10
PUSH11
PUSH12
PUSH13
PUSH14
PUSH15
PUSH16
PUSH17
PUSH18
PUSH19
PUSH20
PUSH21
PUSH22
PUSH23
PUSH24
PUSH25
PUSH26
PUSH27
PUSH28
PUSH29
PUSH30
PUSH31
PUSH32
DUP1
DUP2
DUP3
DUP4
DUP5
DUP6
DUP7
DUP8
DUP9
DUP10
DUP11
DUP12
DUP13
DUP14
DUP15
DUP16
SWAP1
SWAP2
SWAP3
SWAP4
SWAP5
SWAP6
SWAP7
SWAP8
SWAP9
SWAP10
SWAP11
SWAP12
SWAP13
SWAP14
SWAP15
SWAP16
)
2014-10-27 03:44:16 -07:00
2014-10-31 17:18:03 -07:00
const (
LOG0 OpCode = 0xa0 + iota
LOG1
LOG2
LOG3
LOG4
)
2015-10-12 04:33:46 -07:00
// unofficial opcodes used for parsing
const (
PUSH OpCode = 0xb0 + iota
DUP
SWAP
)
2014-10-31 17:18:03 -07:00
const (
// 0xf0 range - closures
2014-10-31 17:18:03 -07:00
CREATE OpCode = 0xf0 + iota
CALL
CALLCODE
RETURN
DELEGATECALL
SUICIDE = 0xff
)
// Since the opcodes aren't all in order we can't use a regular slice
var opCodeToString = map[OpCode]string{
// 0x0 range - arithmetic ops
STOP: "STOP",
ADD: "ADD",
MUL: "MUL",
SUB: "SUB",
DIV: "DIV",
SDIV: "SDIV",
MOD: "MOD",
SMOD: "SMOD",
EXP: "EXP",
NOT: "NOT",
LT: "LT",
GT: "GT",
SLT: "SLT",
SGT: "SGT",
EQ: "EQ",
ISZERO: "ISZERO",
SIGNEXTEND: "SIGNEXTEND",
// 0x10 range - bit ops
2014-08-21 10:23:54 -07:00
AND: "AND",
OR: "OR",
XOR: "XOR",
BYTE: "BYTE",
ADDMOD: "ADDMOD",
MULMOD: "MULMOD",
// 0x20 range - crypto
SHA3: "SHA3",
// 0x30 range - closure state
ADDRESS: "ADDRESS",
BALANCE: "BALANCE",
ORIGIN: "ORIGIN",
CALLER: "CALLER",
CALLVALUE: "CALLVALUE",
CALLDATALOAD: "CALLDATALOAD",
CALLDATASIZE: "CALLDATASIZE",
CALLDATACOPY: "CALLDATACOPY",
CODESIZE: "CODESIZE",
CODECOPY: "CODECOPY",
GASPRICE: "GASPRICE",
// 0x40 range - block operations
BLOCKHASH: "BLOCKHASH",
2014-09-07 15:49:25 -07:00
COINBASE: "COINBASE",
TIMESTAMP: "TIMESTAMP",
NUMBER: "NUMBER",
DIFFICULTY: "DIFFICULTY",
GASLIMIT: "GASLIMIT",
EXTCODESIZE: "EXTCODESIZE",
EXTCODECOPY: "EXTCODECOPY",
// 0x50 range - 'storage' and execution
2014-08-21 11:25:02 -07:00
POP: "POP",
//DUP: "DUP",
//SWAP: "SWAP",
2014-10-08 03:01:14 -07:00
MLOAD: "MLOAD",
MSTORE: "MSTORE",
MSTORE8: "MSTORE8",
SLOAD: "SLOAD",
SSTORE: "SSTORE",
JUMP: "JUMP",
JUMPI: "JUMPI",
PC: "PC",
MSIZE: "MSIZE",
GAS: "GAS",
JUMPDEST: "JUMPDEST",
// 0x60 range - push
PUSH1: "PUSH1",
PUSH2: "PUSH2",
PUSH3: "PUSH3",
PUSH4: "PUSH4",
PUSH5: "PUSH5",
PUSH6: "PUSH6",
PUSH7: "PUSH7",
PUSH8: "PUSH8",
PUSH9: "PUSH9",
PUSH10: "PUSH10",
PUSH11: "PUSH11",
PUSH12: "PUSH12",
PUSH13: "PUSH13",
PUSH14: "PUSH14",
PUSH15: "PUSH15",
PUSH16: "PUSH16",
PUSH17: "PUSH17",
PUSH18: "PUSH18",
PUSH19: "PUSH19",
PUSH20: "PUSH20",
PUSH21: "PUSH21",
PUSH22: "PUSH22",
PUSH23: "PUSH23",
PUSH24: "PUSH24",
PUSH25: "PUSH25",
PUSH26: "PUSH26",
PUSH27: "PUSH27",
PUSH28: "PUSH28",
PUSH29: "PUSH29",
PUSH30: "PUSH30",
PUSH31: "PUSH31",
PUSH32: "PUSH32",
2014-08-21 10:23:54 -07:00
DUP1: "DUP1",
DUP2: "DUP2",
DUP3: "DUP3",
DUP4: "DUP4",
DUP5: "DUP5",
DUP6: "DUP6",
DUP7: "DUP7",
DUP8: "DUP8",
DUP9: "DUP9",
DUP10: "DUP10",
DUP11: "DUP11",
DUP12: "DUP12",
DUP13: "DUP13",
DUP14: "DUP14",
DUP15: "DUP15",
DUP16: "DUP16",
SWAP1: "SWAP1",
SWAP2: "SWAP2",
SWAP3: "SWAP3",
SWAP4: "SWAP4",
SWAP5: "SWAP5",
SWAP6: "SWAP6",
SWAP7: "SWAP7",
SWAP8: "SWAP8",
SWAP9: "SWAP9",
SWAP10: "SWAP10",
SWAP11: "SWAP11",
SWAP12: "SWAP12",
SWAP13: "SWAP13",
SWAP14: "SWAP14",
SWAP15: "SWAP15",
SWAP16: "SWAP16",
LOG0: "LOG0",
LOG1: "LOG1",
LOG2: "LOG2",
LOG3: "LOG3",
LOG4: "LOG4",
2014-08-21 10:23:54 -07:00
// 0xf0 range
CREATE: "CREATE",
CALL: "CALL",
RETURN: "RETURN",
CALLCODE: "CALLCODE",
DELEGATECALL: "DELEGATECALL",
SUICIDE: "SUICIDE",
2015-10-12 04:33:46 -07:00
PUSH: "PUSH",
DUP: "DUP",
SWAP: "SWAP",
}
func (o OpCode) String() string {
str := opCodeToString[o]
if len(str) == 0 {
return fmt.Sprintf("Missing opcode 0x%x", int(o))
}
return str
}
2015-07-09 04:30:04 -07:00
var stringToOp = map[string]OpCode{
"STOP": STOP,
"ADD": ADD,
"MUL": MUL,
"SUB": SUB,
"DIV": DIV,
"SDIV": SDIV,
"MOD": MOD,
"SMOD": SMOD,
"EXP": EXP,
"NOT": NOT,
"LT": LT,
"GT": GT,
"SLT": SLT,
"SGT": SGT,
"EQ": EQ,
"ISZERO": ISZERO,
"SIGNEXTEND": SIGNEXTEND,
"AND": AND,
"OR": OR,
"XOR": XOR,
"BYTE": BYTE,
"ADDMOD": ADDMOD,
"MULMOD": MULMOD,
"SHA3": SHA3,
"ADDRESS": ADDRESS,
"BALANCE": BALANCE,
"ORIGIN": ORIGIN,
"CALLER": CALLER,
"CALLVALUE": CALLVALUE,
"CALLDATALOAD": CALLDATALOAD,
"CALLDATASIZE": CALLDATASIZE,
"CALLDATACOPY": CALLDATACOPY,
"DELEGATECALL": DELEGATECALL,
2015-07-09 04:30:04 -07:00
"CODESIZE": CODESIZE,
"CODECOPY": CODECOPY,
"GASPRICE": GASPRICE,
"BLOCKHASH": BLOCKHASH,
"COINBASE": COINBASE,
"TIMESTAMP": TIMESTAMP,
"NUMBER": NUMBER,
"DIFFICULTY": DIFFICULTY,
"GASLIMIT": GASLIMIT,
"EXTCODESIZE": EXTCODESIZE,
"EXTCODECOPY": EXTCODECOPY,
"POP": POP,
"MLOAD": MLOAD,
"MSTORE": MSTORE,
"MSTORE8": MSTORE8,
"SLOAD": SLOAD,
"SSTORE": SSTORE,
"JUMP": JUMP,
"JUMPI": JUMPI,
"PC": PC,
"MSIZE": MSIZE,
"GAS": GAS,
"JUMPDEST": JUMPDEST,
"PUSH1": PUSH1,
"PUSH2": PUSH2,
"PUSH3": PUSH3,
"PUSH4": PUSH4,
"PUSH5": PUSH5,
"PUSH6": PUSH6,
"PUSH7": PUSH7,
"PUSH8": PUSH8,
"PUSH9": PUSH9,
"PUSH10": PUSH10,
"PUSH11": PUSH11,
"PUSH12": PUSH12,
"PUSH13": PUSH13,
"PUSH14": PUSH14,
"PUSH15": PUSH15,
"PUSH16": PUSH16,
"PUSH17": PUSH17,
"PUSH18": PUSH18,
"PUSH19": PUSH19,
"PUSH20": PUSH20,
"PUSH21": PUSH21,
"PUSH22": PUSH22,
"PUSH23": PUSH23,
"PUSH24": PUSH24,
"PUSH25": PUSH25,
"PUSH26": PUSH26,
"PUSH27": PUSH27,
"PUSH28": PUSH28,
"PUSH29": PUSH29,
"PUSH30": PUSH30,
"PUSH31": PUSH31,
"PUSH32": PUSH32,
"DUP1": DUP1,
"DUP2": DUP2,
"DUP3": DUP3,
"DUP4": DUP4,
"DUP5": DUP5,
"DUP6": DUP6,
"DUP7": DUP7,
"DUP8": DUP8,
"DUP9": DUP9,
"DUP10": DUP10,
"DUP11": DUP11,
"DUP12": DUP12,
"DUP13": DUP13,
"DUP14": DUP14,
"DUP15": DUP15,
"DUP16": DUP16,
"SWAP1": SWAP1,
"SWAP2": SWAP2,
"SWAP3": SWAP3,
"SWAP4": SWAP4,
"SWAP5": SWAP5,
"SWAP6": SWAP6,
"SWAP7": SWAP7,
"SWAP8": SWAP8,
"SWAP9": SWAP9,
"SWAP10": SWAP10,
"SWAP11": SWAP11,
"SWAP12": SWAP12,
"SWAP13": SWAP13,
"SWAP14": SWAP14,
"SWAP15": SWAP15,
"SWAP16": SWAP16,
"LOG0": LOG0,
"LOG1": LOG1,
"LOG2": LOG2,
"LOG3": LOG3,
"LOG4": LOG4,
"CREATE": CREATE,
"CALL": CALL,
"RETURN": RETURN,
"CALLCODE": CALLCODE,
"SUICIDE": SUICIDE,
}
func StringToOp(str string) OpCode {
return stringToOp[str]
}