From 51587208b43a76086bf6a8e8ac28056cafa1c818 Mon Sep 17 00:00:00 2001 From: Jordan Hrycaj Date: Mon, 19 Apr 2021 10:15:35 +0100 Subject: [PATCH] verifying new op handler tables layout against original tables why: the previous approach was replacing the function-lets in opcode_impl.nim by the particulate table handlers. the test functions will verify the the handler functions are sort of correct but not the assignments in the fork tables. the handler names of old and new for tables are checked here. caveat: verifying tables currently takes a while at compile time. --- nimbus/vm2/interpreter/op_handlers.nim | 12 +- .../op_handlers/oph_arithmetic.nim | 25 ++ .../interpreter/op_handlers/oph_blockdata.nim | 12 +- .../vm2/interpreter/op_handlers/oph_call.nim | 8 +- .../interpreter/op_handlers/oph_create.nim | 4 +- .../vm2/interpreter/op_handlers/oph_defs.nim | 3 +- .../interpreter/op_handlers/oph_envinfo.nim | 26 +- .../vm2/interpreter/op_handlers/oph_hash.nim | 1 + .../interpreter/op_handlers/oph_helpers.nim | 5 +- .../vm2/interpreter/op_handlers/oph_log.nim | 2 +- .../interpreter/op_handlers/oph_memory.nim | 37 ++- .../interpreter/op_handlers/oph_sysops.nim | 9 +- nimbus/vm2/interpreter/op_handlers_verify.nim | 289 ++++++++++++++++++ nimbus/vm2/interpreter/opcodes_impl.nim | 3 +- 14 files changed, 408 insertions(+), 28 deletions(-) create mode 100644 nimbus/vm2/interpreter/op_handlers_verify.nim diff --git a/nimbus/vm2/interpreter/op_handlers.nim b/nimbus/vm2/interpreter/op_handlers.nim index a8626a189..26ca4ba7a 100644 --- a/nimbus/vm2/interpreter/op_handlers.nim +++ b/nimbus/vm2/interpreter/op_handlers.nim @@ -59,6 +59,8 @@ proc mkOpTable(select: Fork): array[Op,Vm2OpExec] {.compileTime.} = if select notin result[op].forks: result[op] = result[Invalid] result[op].opCode = op + if op == Stop: + result[op].name = "toBeReplacedByBreak" # ------------------------------------------------------------------------------ # Public handler tables @@ -71,16 +73,6 @@ const rc[w] = w.mkOpTable rc - # vm2OpTabFrontier* = vm2OpHandlers[FkFrontier] - # vm2OpTabHomestead* = vm2OpHandlers[FkHomestead] - # vm2OpTabTangerine* = vm2OpHandlers[FkTangerine] - # vm2OpTabSpurious* = vm2OpHandlers[FkSpurious] - # vm2OpTabByzantium* = vm2OpHandlers[FkByzantium] - # vm2OpTabConstantinople* = vm2OpHandlers[FkConstantinople] - # vm2OpTabPetersburg* = vm2OpHandlers[FkPetersburg] - # vm2OpTabIstanbul* = vm2OpHandlers[FkIstanbul] - # vm2OpTabBerlin* = vm2OpHandlers[FkBerlin] - # ------------------------------------------------------------------------------ # Debugging ... # ------------------------------------------------------------------------------ diff --git a/nimbus/vm2/interpreter/op_handlers/oph_arithmetic.nim b/nimbus/vm2/interpreter/op_handlers/oph_arithmetic.nim index 078449f59..ba91d66a7 100644 --- a/nimbus/vm2/interpreter/op_handlers/oph_arithmetic.nim +++ b/nimbus/vm2/interpreter/op_handlers/oph_arithmetic.nim @@ -334,6 +334,7 @@ const (opCode: Add, ## 0x01, Addition forks: Vm2OpAllForks, + name: "add", info: "Addition operation", exec: (prep: vm2OpIgnore, run: addOp, @@ -341,6 +342,7 @@ const (opCode: Mul, ## 0x02, Multiplication forks: Vm2OpAllForks, + name: "mul", info: "Multiplication operation", exec: (prep: vm2OpIgnore, run: mulOp, @@ -348,6 +350,7 @@ const (opCode: Sub, ## 0x03, Subtraction forks: Vm2OpAllForks, + name: "sub", info: "Subtraction operation", exec: (prep: vm2OpIgnore, run: subOp, @@ -355,6 +358,7 @@ const (opCode: Div, ## 0x04, Division forks: Vm2OpAllForks, + name: "divide", info: "Integer division operation", exec: (prep: vm2OpIgnore, run: divideOp, @@ -362,6 +366,7 @@ const (opCode: Sdiv, ## 0x05, Signed division forks: Vm2OpAllForks, + name: "sdiv", info: "Signed integer division operation (truncated)", exec: (prep: vm2OpIgnore, run: sdivOp, @@ -369,6 +374,7 @@ const (opCode: Mod, ## 0x06, Modulo forks: Vm2OpAllForks, + name: "modulo", info: "Modulo remainder operation", exec: (prep: vm2OpIgnore, run: moduloOp, @@ -376,6 +382,7 @@ const (opCode: Smod, ## 0x07, Signed modulo forks: Vm2OpAllForks, + name: "smod", info: "Signed modulo remainder operation", exec: (prep: vm2OpIgnore, run: smodOp, @@ -384,6 +391,7 @@ const (opCode: AddMod, ## 0x08, Modulo addition, Intermediate ## computations do not roll over at 2^256 forks: Vm2OpAllForks, + name: "addmod", info: "Modulo addition operation", exec: (prep: vm2OpIgnore, run: addmodOp, @@ -392,6 +400,7 @@ const (opCode: MulMod, ## 0x09, Modulo multiplication, Intermediate ## computations do not roll over at 2^256 forks: Vm2OpAllForks, + name: "mulmod", info: "Modulo multiplication operation", exec: (prep: vm2OpIgnore, run: mulmodOp, @@ -399,6 +408,7 @@ const (opCode: Exp, ## 0x0a, Exponentiation forks: Vm2OpAllForks, + name: "exp", info: "Exponentiation operation", exec: (prep: vm2OpIgnore, run: expOp, @@ -406,6 +416,7 @@ const (opCode: SignExtend, ## 0x0b, Extend 2's complemet length forks: Vm2OpAllForks, + name: "signExtend", info: "Extend length of two’s complement signed integer", exec: (prep: vm2OpIgnore, run: signExtendOp, @@ -413,6 +424,7 @@ const (opCode: Lt, ## 0x10, Less-than forks: Vm2OpAllForks, + name: "lt", info: "Less-than comparison", exec: (prep: vm2OpIgnore, run: ltOp, @@ -420,6 +432,7 @@ const (opCode: Gt, ## 0x11, Greater-than forks: Vm2OpAllForks, + name: "gt", info: "Greater-than comparison", exec: (prep: vm2OpIgnore, run: gtOp, @@ -427,6 +440,7 @@ const (opCode: Slt, ## 0x12, Signed less-than forks: Vm2OpAllForks, + name: "slt", info: "Signed less-than comparison", exec: (prep: vm2OpIgnore, run: sltOp, @@ -434,6 +448,7 @@ const (opCode: Sgt, ## 0x13, Signed greater-than forks: Vm2OpAllForks, + name: "sgt", info: "Signed greater-than comparison", exec: (prep: vm2OpIgnore, run: sgtOp, @@ -441,6 +456,7 @@ const (opCode: Eq, ## 0x14, Equality forks: Vm2OpAllForks, + name: "eq", info: "Equality comparison", exec: (prep: vm2OpIgnore, run: eqOp, @@ -448,6 +464,7 @@ const (opCode: IsZero, ## 0x15, Not operator forks: Vm2OpAllForks, + name: "isZero", info: "Simple not operator (Note: real Yellow Paper description)", exec: (prep: vm2OpIgnore, run: isZeroOp, @@ -455,6 +472,7 @@ const (opCode: And, ## 0x16, AND forks: Vm2OpAllForks, + name: "andOp", info: "Bitwise AND operation", exec: (prep: vm2OpIgnore, run: andOp, @@ -462,6 +480,7 @@ const (opCode: Or, ## 0x17, OR forks: Vm2OpAllForks, + name: "orOp", info: "Bitwise OR operation", exec: (prep: vm2OpIgnore, run: orOp, @@ -469,6 +488,7 @@ const (opCode: Xor, ## 0x18, XOR forks: Vm2OpAllForks, + name: "xorOp", info: "Bitwise XOR operation", exec: (prep: vm2OpIgnore, run: xorOp, @@ -476,6 +496,7 @@ const (opCode: Not, ## 0x19, NOT forks: Vm2OpAllForks, + name: "notOp", info: "Bitwise NOT operation", exec: (prep: vm2OpIgnore, run: notOp, @@ -483,6 +504,7 @@ const (opCode: Byte, ## 0x1a, Retrieve byte forks: Vm2OpAllForks, + name: "byteOp", info: "Retrieve single byte from word", exec: (prep: vm2OpIgnore, run: byteOp, @@ -492,6 +514,7 @@ const (opCode: Shl, ## 0x1b, Shift left forks: Vm2OpConstantinopleAndLater, + name: "shlOp", info: "Shift left", exec: (prep: vm2OpIgnore, run: shlOp, @@ -499,6 +522,7 @@ const (opCode: Shr, ## 0x1c, Shift right logical forks: Vm2OpConstantinopleAndLater, + name: "shrOp", info: "Logical shift right", exec: (prep: vm2OpIgnore, run: shrOp, @@ -506,6 +530,7 @@ const (opCode: Sar, ## 0x1d, Shift right arithmetic forks: Vm2OpConstantinopleAndLater, + name: "sarOp", info: "Arithmetic shift right", exec: (prep: vm2OpIgnore, run: sarOp, diff --git a/nimbus/vm2/interpreter/op_handlers/oph_blockdata.nim b/nimbus/vm2/interpreter/op_handlers/oph_blockdata.nim index 1451c64e2..f068e9c3c 100644 --- a/nimbus/vm2/interpreter/op_handlers/oph_blockdata.nim +++ b/nimbus/vm2/interpreter/op_handlers/oph_blockdata.nim @@ -115,6 +115,7 @@ const (opCode: Blockhash, ## 0x40, Hash of some most recent complete block forks: Vm2OpAllForks, + name: "blockhash", info: "Get the hash of one of the 256 most recent complete blocks", exec: (prep: vm2OpIgnore, run: blockhashOp, @@ -122,6 +123,7 @@ const (opCode: Coinbase, ## 0x41, Beneficiary address forks: Vm2OpAllForks, + name: "coinbase", info: "Get the block's beneficiary address", exec: (prep: vm2OpIgnore, run: coinBaseOp, @@ -129,6 +131,7 @@ const (opCode: Timestamp, ## 0x42, Block timestamp. forks: Vm2OpAllForks, + name: "timestamp", info: "Get the block's timestamp", exec: (prep: vm2OpIgnore, run: timestampOp, @@ -136,6 +139,7 @@ const (opCode: Number, ## 0x43, Block number forks: Vm2OpAllForks, + name: "blockNumber", info: "Get the block's number", exec: (prep: vm2OpIgnore, run: blocknumberOp, @@ -143,6 +147,7 @@ const (opCode: Difficulty, ## 0x44, Block difficulty forks: Vm2OpAllForks, + name: "difficulty", info: "Get the block's difficulty", exec: (prep: vm2OpIgnore, run: difficultyOp, @@ -150,20 +155,23 @@ const (opCode: GasLimit, ## 0x45, Block gas limit forks: Vm2OpAllForks, + name: "gasLimit", info: "Get the block's gas limit", exec: (prep: vm2OpIgnore, run: gasLimitOp, post: vm2OpIgnore)), (opCode: ChainId, ## 0x46, EIP-155 chain identifier - forks: Vm2OpAllForks, + forks: Vm2OpIstanbulAndLater, + name: "chainId", info: "Get current chain’s EIP-155 unique identifier", exec: (prep: vm2OpIgnore, run: chainIdOp, post: vm2OpIgnore)), (opCode: SelfBalance, ## 0x47, Contract balance. - forks: Vm2OpAllForks, + forks: Vm2OpIstanbulAndLater, + name: "selfBalance", info: "Get current contract's balance", exec: (prep: vm2OpIgnore, run: selfBalanceOp, diff --git a/nimbus/vm2/interpreter/op_handlers/oph_call.nim b/nimbus/vm2/interpreter/op_handlers/oph_call.nim index 4b28804e4..1513c9cfd 100644 --- a/nimbus/vm2/interpreter/op_handlers/oph_call.nim +++ b/nimbus/vm2/interpreter/op_handlers/oph_call.nim @@ -529,6 +529,7 @@ const (opCode: Call, ## 0xf1, Message-Call into an account forks: Vm2OpAllForks, + name: "call", info: "Message-Call into an account", exec: (prep: vm2OpIgnore, run: callOp, @@ -536,13 +537,15 @@ const (opCode: CallCode, ## 0xf2, Message-Call with alternative code forks: Vm2OpAllForks, + name: "callCode", info: "Message-call into this account with alternative account's code", exec: (prep: vm2OpIgnore, run: callCodeOp, post: vm2OpIgnore)), (opCode: DelegateCall, ## 0xf4, CallCode with persisting sender and value - forks: Vm2OpAllForks, + forks: Vm2OpHomesteadAndLater, + name: "delegateCall", info: "Message-call into this account with an alternative account's " & "code but persisting the current values for sender and value.", exec: (prep: vm2OpIgnore, @@ -550,7 +553,8 @@ const post: vm2OpIgnore)), (opCode: StaticCall, ## 0xfa, Static message-call into an account - forks: Vm2OpAllForks, + forks: Vm2OpByzantiumAndLater, + name: "staticCall", info: "Static message-call into an account", exec: (prep: vm2OpIgnore, run: staticCallOp, diff --git a/nimbus/vm2/interpreter/op_handlers/oph_create.nim b/nimbus/vm2/interpreter/op_handlers/oph_create.nim index 9f426fd48..5d915c534 100644 --- a/nimbus/vm2/interpreter/op_handlers/oph_create.nim +++ b/nimbus/vm2/interpreter/op_handlers/oph_create.nim @@ -238,13 +238,15 @@ const (opCode: Create, ## 0xf0, Create a new account with associated code forks: Vm2OpAllForks, + name: "create", info: "Create a new account with associated code", exec: (prep: vm2OpIgnore, run: createOp, post: vm2OpIgnore)), (opCode: Create2, ## 0xf5, Create using keccak256 - forks: Vm2OpAllForks, + forks: Vm2OpConstantinopleAndLater, + name: "create2", info: "Behaves identically to CREATE, except using keccak256", exec: (prep: vm2OpIgnore, run: create2Op, diff --git a/nimbus/vm2/interpreter/op_handlers/oph_defs.nim b/nimbus/vm2/interpreter/op_handlers/oph_defs.nim index 22c919e66..43c9c762f 100644 --- a/nimbus/vm2/interpreter/op_handlers/oph_defs.nim +++ b/nimbus/vm2/interpreter/op_handlers/oph_defs.nim @@ -104,7 +104,8 @@ type Vm2OpExec* = tuple ## op code handler entry opCode: Op ## index back-reference forks: set[Fork] ## forks applicable for this operation - info: string ## pretty option name, info + name: string ## handler name + info: string ## handter info, explainer exec: Vm2OpHanders # ------------------------------------------------------------------------------ diff --git a/nimbus/vm2/interpreter/op_handlers/oph_envinfo.nim b/nimbus/vm2/interpreter/op_handlers/oph_envinfo.nim index baf0f8783..3a59ffd20 100644 --- a/nimbus/vm2/interpreter/op_handlers/oph_envinfo.nim +++ b/nimbus/vm2/interpreter/op_handlers/oph_envinfo.nim @@ -336,6 +336,7 @@ const (opCode: Address, ## 0x20, Address forks: Vm2OpAllForks, + name: "address", info: "Get address of currently executing account", exec: (prep: vm2OpIgnore, run: addressOp, @@ -343,6 +344,7 @@ const (opCode: Balance, ## 0x31, Balance forks: Vm2OpAllForks - Vm2OpBerlinAndLater, + name: "balance", info: "Get balance of the given account", exec: (prep: vm2OpIgnore, run: balanceOp, @@ -350,6 +352,7 @@ const (opCode: Balance, ## 0x31, Balance for Berlin and later forks: Vm2OpBerlinAndLater, + name: "balanceEIP2929", info: "EIP2929: Get balance of the given account", exec: (prep: vm2OpIgnore, run: balanceEIP2929Op, @@ -357,6 +360,7 @@ const (opCode: Origin, ## 0x32, Origination address forks: Vm2OpAllForks, + name: "origin", info: "Get execution origination address", exec: (prep: vm2OpIgnore, run: originOp, @@ -364,6 +368,7 @@ const (opCode: Caller, ## 0x33, Caller address forks: Vm2OpAllForks, + name: "caller", info: "Get caller address", exec: (prep: vm2OpIgnore, run: callerOp, @@ -371,6 +376,7 @@ const (opCode: CallValue, ## 0x34, Execution deposited value forks: Vm2OpAllForks, + name: "callValue", info: "Get deposited value by the instruction/transaction " & "responsible for this execution", exec: (prep: vm2OpIgnore, @@ -379,6 +385,7 @@ const (opCode: CallDataLoad, ## 0x35, Input data forks: Vm2OpAllForks, + name: "callDataLoad", info: "Get input data of current environment", exec: (prep: vm2OpIgnore, run: callDataLoadOp, @@ -386,6 +393,7 @@ const (opCode: CallDataSize, ## 0x36, Size of input data forks: Vm2OpAllForks, + name: "callDataSize", info: "Get size of input data in current environment", exec: (prep: vm2OpIgnore, run: callDataSizeOp, @@ -393,6 +401,7 @@ const (opCode: CallDataCopy, ## 0x37, Copy input data to memory. forks: Vm2OpAllForks, + name: "callDataCopy", info: "Copy input data in current environment to memory", exec: (prep: vm2OpIgnore, run: callDataCopyOp, @@ -400,6 +409,7 @@ const (opCode: CodeSize, ## 0x38, Size of code forks: Vm2OpAllForks, + name: "codeSize", info: "Get size of code running in current environment", exec: (prep: vm2OpIgnore, run: codeSizeOp, @@ -407,6 +417,7 @@ const (opCode: CodeCopy, ## 0x39, Copy code to memory. forks: Vm2OpAllForks, + name: "codeCopy", info: "Copy code running in current environment to memory", exec: (prep: vm2OpIgnore, run: codeCopyOp, @@ -414,6 +425,7 @@ const (opCode: GasPrice, ## 0x3a, Gas price forks: Vm2OpAllForks, + name: "gasPrice", info: "Get price of gas in current environment", exec: (prep: vm2OpIgnore, run: gasPriceOp, @@ -421,6 +433,7 @@ const (opCode: ExtCodeSize, ## 0x3b, Account code size forks: Vm2OpAllForks - Vm2OpBerlinAndLater, + name: "extCodeSize", info: "Get size of an account's code", exec: (prep: vm2OpIgnore, run: extCodeSizeOp, @@ -428,6 +441,7 @@ const (opCode: ExtCodeSize, ## 0x3b, Account code size for Berlin and later forks: Vm2OpBerlinAndLater, + name: "extCodeSizeEIP2929", info: "EIP2929: Get size of an account's code", exec: (prep: vm2OpIgnore, run: extCodeSizeEIP2929Op, @@ -435,6 +449,7 @@ const (opCode: ExtCodeCopy, ## 0x3c, Account code copy to memory. forks: Vm2OpAllForks - Vm2OpBerlinAndLater, + name: "extCodeCopy", info: "Copy an account's code to memory", exec: (prep: vm2OpIgnore, run: extCodeCopyOp, @@ -442,13 +457,15 @@ const (opCode: ExtCodeCopy, ## 0x3c, Account Code-copy for Berlin and later forks: Vm2OpBerlinAndLater, + name: "extCodeCopyEIP2929", info: "EIP2929: Copy an account's code to memory", exec: (prep: vm2OpIgnore, run: extCodeCopyEIP2929Op, post: vm2OpIgnore)), (opCode: ReturnDataSize, ## 0x3d, Previous call output data size - forks: Vm2OpAllForks, + forks: Vm2OpByzantiumAndLater, + name: "returnDataSize", info: "Get size of output data from the previous call " & "from the current environment", exec: (prep: vm2OpIgnore, @@ -456,14 +473,16 @@ const post: vm2OpIgnore)), (opCode: ReturnDataCopy, ## 0x3e, Previous call output data copy to memory - forks: Vm2OpAllForks, + forks: Vm2OpByzantiumAndLater, + name: "returnDataCopy", info: "Copy output data from the previous call to memory", exec: (prep: vm2OpIgnore, run: returnDataCopyOp, post: vm2OpIgnore)), (opCode: ExtCodeHash, ## 0x3f, Contract hash - forks: Vm2OpAllForks - Vm2OpBerlinAndLater, + forks: Vm2OpConstantinopleAndLater - Vm2OpBerlinAndLater, + name: "extCodeHash", info: "Returns the keccak256 hash of a contract’s code", exec: (prep: vm2OpIgnore, run: extCodeHashOp, @@ -471,6 +490,7 @@ const (opCode: ExtCodeHash, ## 0x3f, Contract hash for berlin and later forks: Vm2OpBerlinAndLater, + name: "extCodeHashEIP2929", info: "EIP2929: Returns the keccak256 hash of a contract’s code", exec: (prep: vm2OpIgnore, run: extCodeHashEIP2929Op, diff --git a/nimbus/vm2/interpreter/op_handlers/oph_hash.nim b/nimbus/vm2/interpreter/op_handlers/oph_hash.nim index 9855d8c0b..612727171 100644 --- a/nimbus/vm2/interpreter/op_handlers/oph_hash.nim +++ b/nimbus/vm2/interpreter/op_handlers/oph_hash.nim @@ -115,6 +115,7 @@ const (opCode: Op.Sha3, ## 0x20, Keccak-256 forks: Vm2OpAllForks, + name: "sha3", info: "Compute Keccak-256 hash", exec: (prep: vm2OpIgnore, run: sha3Op, diff --git a/nimbus/vm2/interpreter/op_handlers/oph_helpers.nim b/nimbus/vm2/interpreter/op_handlers/oph_helpers.nim index 8b974f153..dc1279866 100644 --- a/nimbus/vm2/interpreter/op_handlers/oph_helpers.nim +++ b/nimbus/vm2/interpreter/op_handlers/oph_helpers.nim @@ -20,7 +20,8 @@ import ../../../errors, ./oph_defs, macros, - stint + stint, + strutils type OphNumToTextFn* = proc(n: int): string @@ -156,9 +157,11 @@ macro genOphList*(runHandler: static[OphNumToTextFn]; ## var records = nnkBracket.newTree() for n in inxList: + var handlerName = n.runHandler.multiReplace(("Op",""),("OP","")) records.add nnkPar.newTree( "opCode".asIdent(n.opCode), "forks".asIdent(recForkSet), + "name".asText(handlerName), "info".asText(n.handlerInfo), nnkExprColonExpr.newTree( newIdentNode("exec"), diff --git a/nimbus/vm2/interpreter/op_handlers/oph_log.nim b/nimbus/vm2/interpreter/op_handlers/oph_log.nim index 9e62b22d3..1905d0311 100644 --- a/nimbus/vm2/interpreter/op_handlers/oph_log.nim +++ b/nimbus/vm2/interpreter/op_handlers/oph_log.nim @@ -87,7 +87,7 @@ else: # ------------------------------------------------------------------------------ proc fnName(n: int): string {.compileTime.} = - &"Log{n}Op" + &"log{n}Op" proc opName(n: int): string {.compileTime.} = &"Log{n}" diff --git a/nimbus/vm2/interpreter/op_handlers/oph_memory.nim b/nimbus/vm2/interpreter/op_handlers/oph_memory.nim index f4c16cf1e..e0ec62f65 100644 --- a/nimbus/vm2/interpreter/op_handlers/oph_memory.nim +++ b/nimbus/vm2/interpreter/op_handlers/oph_memory.nim @@ -381,6 +381,7 @@ const (opCode: Pop, ## x50, Remove item from stack forks: Vm2OpAllForks, + name: "pop", info: "Remove item from stack", exec: (prep: vm2OpIgnore, run: popOp, @@ -388,6 +389,7 @@ const (opCode: Mload, ## 0x51, Load word from memory forks: Vm2OpAllForks, + name: "mload", info: "Load word from memory", exec: (prep: vm2OpIgnore, run: mloadOp, @@ -395,6 +397,7 @@ const (opCode: Mstore, ## 0x52, Save word to memory forks: Vm2OpAllForks, + name: "mstore", info: "Save word to memory", exec: (prep: vm2OpIgnore, run: mstoreOp, @@ -402,6 +405,7 @@ const (opCode: Mstore8, ## 0x53, Save byte to memory forks: Vm2OpAllForks, + name: "mstore8", info: "Save byte to memory", exec: (prep: vm2OpIgnore, run: mstore8Op, @@ -409,6 +413,7 @@ const (opCode: Sload, ## 0x54, Load word from storage forks: Vm2OpAllForks - Vm2OpBerlinAndLater, + name: "sload", info: "Load word from storage", exec: (prep: vm2OpIgnore, run: sloadOp, @@ -416,6 +421,7 @@ const (opCode: Sload, ## 0x54, sload for Berlin and later forks: Vm2OpBerlinAndLater, + name: "sloadEIP2929", info: "EIP2929: sload for Berlin and later", exec: (prep: vm2OpIgnore, run: sloadEIP2929Op, @@ -423,20 +429,31 @@ const (opCode: Sstore, ## 0x55, Save word forks: Vm2OpAllForks - Vm2OpConstantinopleAndLater, + name: "sstore", info: "Save word to storage", exec: (prep: vm2OpIgnore, run: sstoreOp, post: vm2OpIgnore)), (opCode: Sstore, ## 0x55, sstore for Constantinople and later - forks: Vm2OpConstantinopleAndLater - Vm2OpIstanbulAndLater, + forks: Vm2OpConstantinopleAndLater - Vm2OpPetersburgAndLater, + name: "sstoreEIP1283", info: "EIP1283: sstore for Constantinople and later", exec: (prep: vm2OpIgnore, run: sstoreEIP1283Op, post: vm2OpIgnore)), + (opCode: Sstore, ## 0x55, sstore for Petersburg and later + forks: Vm2OpPetersburgAndLater - Vm2OpIstanbulAndLater, + name: "sstore", + info: "sstore for Constantinople and later", + exec: (prep: vm2OpIgnore, + run: sstoreOp, + post: vm2OpIgnore)), + (opCode: Sstore, ## 0x55, sstore for Istanbul and later forks: Vm2OpIstanbulAndLater - Vm2OpBerlinAndLater, + name: "sstoreEIP2200", info: "EIP2200: sstore for Istanbul and later", exec: (prep: vm2OpIgnore, run: sstoreEIP2200Op, @@ -444,13 +461,15 @@ const (opCode: Sstore, ## 0x55, sstore for Berlin and later forks: Vm2OpBerlinAndLater, + name: "sstoreEIP2929", info: "EIP2929: sstore for Istanbul and later", exec: (prep: vm2OpIgnore, run: sstoreEIP2929Op, post: vm2OpIgnore)), (opCode: Jump, ## 0x56, Jump - forks: Vm2OpIstanbulAndLater, + forks: Vm2OpAllForks, + name: "jump", info: "Alter the program counter", exec: (prep: vm2OpIgnore, run: jumpOp, @@ -458,6 +477,7 @@ const (opCode: JumpI, ## 0x57, Conditional jump forks: Vm2OpAllForks, + name: "jumpI", info: "Conditionally alter the program counter", exec: (prep: vm2OpIgnore, run: jumpIOp, @@ -465,6 +485,7 @@ const (opCode: Pc, ## 0x58, Program counter prior to instruction forks: Vm2OpAllForks, + name: "pc", info: "Get the value of the program counter prior to the increment "& "corresponding to this instruction", exec: (prep: vm2OpIgnore, @@ -473,6 +494,7 @@ const (opCode: Msize, ## 0x59, Memory size forks: Vm2OpAllForks, + name: "msize", info: "Get the size of active memory in bytes", exec: (prep: vm2OpIgnore, run: msizeOp, @@ -480,6 +502,7 @@ const (opCode: Gas, ## 0x5a, Get available gas forks: Vm2OpAllForks, + name: "gas", info: "Get the amount of available gas, including the corresponding "& "reduction for the cost of this instruction", exec: (prep: vm2OpIgnore, @@ -489,27 +512,31 @@ const (opCode: JumpDest, ## 0x5b, Mark jump target. This operation has no effect ## on machine state during execution forks: Vm2OpAllForks, + name: "jumpDest", info: "Mark a valid destination for jumps", exec: (prep: vm2OpIgnore, run: jumpDestOp, post: vm2OpIgnore)), (opCode: BeginSub, ## 0x5c, Begin subroutine - forks: Vm2OpAllForks, + forks: Vm2OpBerlinAndLater, + name: "beginSub", info: " Marks the entry point to a subroutine", exec: (prep: vm2OpIgnore, run: beginSubOp, post: vm2OpIgnore)), (opCode: ReturnSub, ## 0x5d, Return - forks: Vm2OpAllForks, + forks: Vm2OpBerlinAndLater, + name: "returnSub", info: "Returns control to the caller of a subroutine", exec: (prep: vm2OpIgnore, run: returnSubOp, post: vm2OpIgnore)), (opCode: JumpSub, ## 0x5e, Call subroutine - forks: Vm2OpAllForks, + forks: Vm2OpBerlinAndLater, + name: "jumpSub", info: "Transfers control to a subroutine", exec: (prep: vm2OpIgnore, run: jumpSubOp, diff --git a/nimbus/vm2/interpreter/op_handlers/oph_sysops.nim b/nimbus/vm2/interpreter/op_handlers/oph_sysops.nim index a72ca33c5..dc63f5e74 100644 --- a/nimbus/vm2/interpreter/op_handlers/oph_sysops.nim +++ b/nimbus/vm2/interpreter/op_handlers/oph_sysops.nim @@ -215,13 +215,15 @@ const (opCode: Return, ## 0xf3, Halt execution returning output data. forks: Vm2OpAllForks, + name: "returnOp", info: "Halt execution returning output data", exec: (prep: vm2OpIgnore, run: returnOp, post: vm2OpIgnore)), (opCode: Revert, ## 0xfd, Halt and revert state changes - forks: Vm2OpAllForks, + forks: Vm2OpByzantiumAndLater, + name: "revert", info: "Halt execution reverting state changes but returning data " & "and remaining gas", exec: (prep: vm2OpIgnore, @@ -230,6 +232,7 @@ const (opCode: Invalid, ## 0xfe, invalid instruction. forks: Vm2OpAllForks, + name: "invalidInstruction", info: "Designated invalid instruction", exec: (prep: vm2OpIgnore, run: invalidOp, @@ -237,6 +240,7 @@ const (opCode: SelfDestruct, ## 0xff, Halt execution, prep for later deletion forks: Vm2OpAllForks - Vm2OpTangerineAndLater, + name: "selfDestruct", info: "Halt execution and register account for later deletion", exec: (prep: vm2OpIgnore, run: selfDestructOp, @@ -244,6 +248,7 @@ const (opCode: SelfDestruct, ## 0xff, EIP150: self destruct, Tangerine forks: Vm2OpTangerineAndLater - Vm2OpSpuriousAndLater, + name: "selfDestructEIP150", info: "EIP150: Halt execution and register account for later deletion", exec: (prep: vm2OpIgnore, run: selfDestructEIP150Op, @@ -251,6 +256,7 @@ const (opCode: SelfDestruct, ## 0xff, EIP161: self destruct, Spurious and later forks: Vm2OpSpuriousAndLater - Vm2OpBerlinAndLater, + name: "selfDestructEIP161", info: "EIP161: Halt execution and register account for later deletion", exec: (prep: vm2OpIgnore, run: selfDestructEIP161Op, @@ -258,6 +264,7 @@ const (opCode: SelfDestruct, ## 0xff, EIP2929: self destruct, Berlin and later forks: Vm2OpBerlinAndLater, + name: "selfDestructEIP2929", info: "EIP2929: Halt execution and register account for later deletion", exec: (prep: vm2OpIgnore, run: selfDestructEIP2929Op, diff --git a/nimbus/vm2/interpreter/op_handlers_verify.nim b/nimbus/vm2/interpreter/op_handlers_verify.nim new file mode 100644 index 000000000..c597746bc --- /dev/null +++ b/nimbus/vm2/interpreter/op_handlers_verify.nim @@ -0,0 +1,289 @@ +# Nimbus +# Copyright (c) 2018 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or +# http://www.apache.org/licenses/LICENSE-2.0) +# * MIT license ([LICENSE-MIT](LICENSE-MIT) or +# http://opensource.org/licenses/MIT) +# at your option. This file may not be copied, modified, or distributed except +# according to those terms. + +import + ./forks_list, + ./op_codes, + ./op_handlers, + ./utils/macros_gen_opcodes, + macros, + strformat + +# ------------------------------------------------------------------------------ +# The follwong is mostly original code excerpt from interpreter_dispatch.nim +# This module has no production use, rather it is used to verify the +# implementation in interpreter_dispatch_tables.nim. +# ------------------------------------------------------------------------------ + +let FrontierOpDispatch {.compileTime.}: array[Op, NimNode] = block: + fill_enum_table_holes(Op, newIdentNode("invalidInstruction")): + [ + Stop: newIdentNode "toBeReplacedByBreak", + Add: newIdentNode "add", + Mul: newIdentNode "mul", + Sub: newIdentNode "sub", + Div: newIdentNode "divide", + Sdiv: newIdentNode "sdiv", + Mod: newIdentNode "modulo", + Smod: newIdentNode "smod", + Addmod: newIdentNode "addmod", + Mulmod: newIdentNode "mulmod", + Exp: newIdentNode "exp", + SignExtend: newIdentNode "signExtend", + + # 10s: Comparison & Bitwise Logic Operations + Lt: newIdentNode "lt", + Gt: newIdentNode "gt", + Slt: newIdentNode "slt", + Sgt: newIdentNode "sgt", + Eq: newIdentNode "eq", + IsZero: newIdentNode "isZero", + And: newIdentNode "andOp", + Or: newIdentNode "orOp", + Xor: newIdentNode "xorOp", + Not: newIdentNode "notOp", + Byte: newIdentNode "byteOp", + + # 20s: SHA3 + Sha3: newIdentNode "sha3", + + # 30s: Environmental Information + Address: newIdentNode "address", + Balance: newIdentNode "balance", + Origin: newIdentNode "origin", + Caller: newIdentNode "caller", + CallValue: newIdentNode "callValue", + CallDataLoad: newIdentNode "callDataLoad", + CallDataSize: newIdentNode "callDataSize", + CallDataCopy: newIdentNode "callDataCopy", + CodeSize: newIdentNode "codeSize", + CodeCopy: newIdentNode "codeCopy", + GasPrice: newIdentNode "gasPrice", + ExtCodeSize: newIdentNode "extCodeSize", + ExtCodeCopy: newIdentNode "extCodeCopy", + # ReturnDataSize: introduced in Byzantium + # ReturnDataCopy: introduced in Byzantium + + # 40s: Block Information + Blockhash: newIdentNode "blockhash", + Coinbase: newIdentNode "coinbase", + Timestamp: newIdentNode "timestamp", + Number: newIdentNode "blockNumber", + Difficulty: newIdentNode "difficulty", + GasLimit: newIdentNode "gasLimit", + + # 50s: Stack, Memory, Storage and Flow Operations + Pop: newIdentNode "pop", + Mload: newIdentNode "mload", + Mstore: newIdentNode "mstore", + Mstore8: newIdentNode "mstore8", + Sload: newIdentNode "sload", + Sstore: newIdentNode "sstore", + Jump: newIdentNode "jump", + JumpI: newIdentNode "jumpI", + Pc: newIdentNode "pc", + Msize: newIdentNode "msize", + Gas: newIdentNode "gas", + JumpDest: newIdentNode "jumpDest", + + # 60s & 70s: Push Operations. + Push1: newIdentNode "push1", + Push2: newIdentNode "push2", + Push3: newIdentNode "push3", + Push4: newIdentNode "push4", + Push5: newIdentNode "push5", + Push6: newIdentNode "push6", + Push7: newIdentNode "push7", + Push8: newIdentNode "push8", + Push9: newIdentNode "push9", + Push10: newIdentNode "push10", + Push11: newIdentNode "push11", + Push12: newIdentNode "push12", + Push13: newIdentNode "push13", + Push14: newIdentNode "push14", + Push15: newIdentNode "push15", + Push16: newIdentNode "push16", + Push17: newIdentNode "push17", + Push18: newIdentNode "push18", + Push19: newIdentNode "push19", + Push20: newIdentNode "push20", + Push21: newIdentNode "push21", + Push22: newIdentNode "push22", + Push23: newIdentNode "push23", + Push24: newIdentNode "push24", + Push25: newIdentNode "push25", + Push26: newIdentNode "push26", + Push27: newIdentNode "push27", + Push28: newIdentNode "push28", + Push29: newIdentNode "push29", + Push30: newIdentNode "push30", + Push31: newIdentNode "push31", + Push32: newIdentNode "push32", + + # 80s: Duplication Operations + Dup1: newIdentNode "dup1", + Dup2: newIdentNode "dup2", + Dup3: newIdentNode "dup3", + Dup4: newIdentNode "dup4", + Dup5: newIdentNode "dup5", + Dup6: newIdentNode "dup6", + Dup7: newIdentNode "dup7", + Dup8: newIdentNode "dup8", + Dup9: newIdentNode "dup9", + Dup10: newIdentNode "dup10", + Dup11: newIdentNode "dup11", + Dup12: newIdentNode "dup12", + Dup13: newIdentNode "dup13", + Dup14: newIdentNode "dup14", + Dup15: newIdentNode "dup15", + Dup16: newIdentNode "dup16", + + # 90s: Exchange Operations + Swap1: newIdentNode "swap1", + Swap2: newIdentNode "swap2", + Swap3: newIdentNode "swap3", + Swap4: newIdentNode "swap4", + Swap5: newIdentNode "swap5", + Swap6: newIdentNode "swap6", + Swap7: newIdentNode "swap7", + Swap8: newIdentNode "swap8", + Swap9: newIdentNode "swap9", + Swap10: newIdentNode "swap10", + Swap11: newIdentNode "swap11", + Swap12: newIdentNode "swap12", + Swap13: newIdentNode "swap13", + Swap14: newIdentNode "swap14", + Swap15: newIdentNode "swap15", + Swap16: newIdentNode "swap16", + + # a0s: Logging Operations + Log0: newIdentNode "log0", + Log1: newIdentNode "log1", + Log2: newIdentNode "log2", + Log3: newIdentNode "log3", + Log4: newIdentNode "log4", + + # f0s: System operations + Create: newIdentNode "create", + Call: newIdentNode "call", + CallCode: newIdentNode "callCode", + Return: newIdentNode "returnOp", + # StaticCall: introduced in Byzantium + # Revert: introduced in Byzantium + # Invalid: newIdentNode "invalid", + SelfDestruct: newIdentNode "selfDestruct" + ] + +proc genHomesteadJumpTable(ops: array[Op, NimNode]): array[Op, NimNode] {.compileTime.} = + result = ops + result[DelegateCall] = newIdentNode "delegateCall" + +let HomesteadOpDispatch {.compileTime.}: array[Op, NimNode] = genHomesteadJumpTable(FrontierOpDispatch) + +proc genTangerineJumpTable(ops: array[Op, NimNode]): array[Op, NimNode] {.compileTime.} = + result = ops + result[SelfDestruct] = newIdentNode "selfDestructEIP150" + +let TangerineOpDispatch {.compileTime.}: array[Op, NimNode] = genTangerineJumpTable(HomesteadOpDispatch) + +proc genSpuriousJumpTable(ops: array[Op, NimNode]): array[Op, NimNode] {.compileTime.} = + result = ops + result[SelfDestruct] = newIdentNode "selfDestructEIP161" + +let SpuriousOpDispatch {.compileTime.}: array[Op, NimNode] = genSpuriousJumpTable(TangerineOpDispatch) + +proc genByzantiumJumpTable(ops: array[Op, NimNode]): array[Op, NimNode] {.compileTime.} = + result = ops + result[Revert] = newIdentNode "revert" + result[ReturnDataSize] = newIdentNode "returnDataSize" + result[ReturnDataCopy] = newIdentNode "returnDataCopy" + result[StaticCall] = newIdentNode"staticCall" + +let ByzantiumOpDispatch {.compileTime.}: array[Op, NimNode] = genByzantiumJumpTable(SpuriousOpDispatch) + +proc genConstantinopleJumpTable(ops: array[Op, NimNode]): array[Op, NimNode] {.compileTime.} = + result = ops + result[Shl] = newIdentNode "shlOp" + result[Shr] = newIdentNode "shrOp" + result[Sar] = newIdentNode "sarOp" + result[ExtCodeHash] = newIdentNode "extCodeHash" + result[Create2] = newIdentNode "create2" + result[SStore] = newIdentNode "sstoreEIP1283" + +let ConstantinopleOpDispatch {.compileTime.}: array[Op, NimNode] = genConstantinopleJumpTable(ByzantiumOpDispatch) + +proc genPetersburgJumpTable(ops: array[Op, NimNode]): array[Op, NimNode] {.compileTime.} = + result = ops + result[SStore] = newIdentNode "sstore" # disable EIP-1283 + +let PetersburgOpDispatch {.compileTime.}: array[Op, NimNode] = genPetersburgJumpTable(ConstantinopleOpDispatch) + +proc genIstanbulJumpTable(ops: array[Op, NimNode]): array[Op, NimNode] {.compileTime.} = + result = ops + result[ChainId] = newIdentNode "chainId" + result[SelfBalance] = newIdentNode "selfBalance" + result[SStore] = newIdentNode "sstoreEIP2200" + +let IstanbulOpDispatch {.compileTime.}: array[Op, NimNode] = genIstanbulJumpTable(PetersburgOpDispatch) + +proc genBerlinJumpTable(ops: array[Op, NimNode]): array[Op, NimNode] {.compileTime.} = + result = ops + result[BeginSub] = newIdentNode "beginSub" + result[ReturnSub] = newIdentNode "returnSub" + result[JumpSub] = newIdentNode "jumpSub" + + result[Balance] = newIdentNode "balanceEIP2929" + result[ExtCodeHash] = newIdentNode "extCodeHashEIP2929" + result[ExtCodeSize] = newIdentNode "extCodeSizeEIP2929" + result[ExtCodeCopy] = newIdentNode "extCodeCopyEIP2929" + result[SelfDestruct] = newIdentNode "selfDestructEIP2929" + result[SLoad] = newIdentNode "sloadEIP2929" + result[SStore] = newIdentNode "sstoreEIP2929" + +let BerlinOpDispatch {.compileTime.}: array[Op, NimNode] = genBerlinJumpTable(IstanbulOpDispatch) + +# ------------------------------------------------------------------------------ +# Public +# ------------------------------------------------------------------------------ + +static: + let OrigAllOpDispatch = block: + var rc: array[Fork, array[Op, NimNode]] + rc[FkFrontier] = FrontierOpDispatch + rc[FkHomestead] = HomesteadOpDispatch + rc[FkTangerine] = TangerineOpDispatch + rc[FkSpurious] = SpuriousOpDispatch + rc[FkByzantium] = ByzantiumOpDispatch + rc[FkConstantinople] = ConstantinopleOpDispatch + rc[FkPetersburg] = PetersburgOpDispatch + rc[FkIstanbul] = IstanbulOpDispatch + rc[FkBerlin] = BerlinOpDispatch + rc + + echo "*** verifying op handler tables will take a while ..." + + var vm2OpHandlerErrors = 0 + for fork in Fork: + for op in Op: + + var + vm2OpName = vm2OpHandlers[fork][op].name + origName = OrigAllOpDispatch[fork][op].strVal + + if origName != vm2OpName: + vm2OpHandlerErrors.inc + echo "*** problem: vm2OpHandlers", + & "[{fork}][{op}].name is \"{vm2OpName}\" expected \"{origName}\"" + + doAssert vm2OpHandlerErrors == 0 + +# ------------------------------------------------------------------------------ +# End +# ------------------------------------------------------------------------------ diff --git a/nimbus/vm2/interpreter/opcodes_impl.nim b/nimbus/vm2/interpreter/opcodes_impl.nim index b93ca0ce2..915b4208c 100644 --- a/nimbus/vm2/interpreter/opcodes_impl.nim +++ b/nimbus/vm2/interpreter/opcodes_impl.nim @@ -7,6 +7,7 @@ import ./op_handlers/oph_defs, + ./op_handlers_verify, ./op_handlers # ################################## @@ -68,7 +69,7 @@ opHandler extCodeCopyEIP2929, Op.ExtCodeCopy opHandler returnDataSize, Op.ReturnDataSize opHandler returnDataCopy, Op.ReturnDataCopy -opHandler extCodeHash, Op.ExtCodeHash, FkFrontier +opHandler extCodeHash, Op.ExtCodeHash, FkConstantinople opHandler extCodeHashEIP2929, Op.ExtCodeHash opHandler blockhash, Op.Blockhash