Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor interpreter dispatch #65

Merged
merged 42 commits into from
Jul 6, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
14c9b90
move forks constants, rename errors
mratsim Jun 15, 2018
d3e6dc2
Move vm/utils to vm/interpreter/utils
mratsim Jun 15, 2018
bfd4e0e
initial opcodes refactoring
mratsim Jun 15, 2018
d2aa102
Add refactored Comparison & Bitwise Logic Operations
mratsim Jun 15, 2018
0315c99
Add sha3 and address, simplify macro, support pop 0
mratsim Jun 15, 2018
19df472
balance, origin, caller, callValue
mratsim Jun 15, 2018
26c9352
fix gas copy opcodes gas costs, add callDataLoad/Size/Copy, CodeSize/…
mratsim Jun 19, 2018
82f53e0
Update with 30s, 40s, 50s opcodes + impl of balance + stack improvement
mratsim Jun 20, 2018
49556c9
add push, dup, swap, log, create and call operations
mratsim Jun 23, 2018
e765405
finish opcode implementation
mratsim Jul 2, 2018
2dc0376
Add the new dispatching logic
mratsim Jul 2, 2018
90c014c
Pass the opcode test
mratsim Jul 2, 2018
1befcff
Make test_vm_json compile
mratsim Jul 2, 2018
a8c2c9a
halt execution without exceptions for Return, Revert, selfdestruct (f…
mratsim Jul 2, 2018
cf08fe7
Properly catch and recover from EVM exceptions (stack underflow ...)
mratsim Jul 2, 2018
1221c73
Fix byte op
mratsim Jul 2, 2018
eae2a9e
Fix jump regressions
mratsim Jul 3, 2018
9f3d9e9
Update for latest devel, don't import old dispatch code as quasiBoole…
mratsim Jul 3, 2018
54bb55d
Fix sha3 regression on empty memory slice and until end of range slice
mratsim Jul 3, 2018
f0164e9
Fix padding / range error on expXY_success (gas computation left)
mratsim Jul 3, 2018
2e86b9f
update logging procs
mratsim Jul 3, 2018
8effe7d
Add tracing - expXY_success is not a regression, sload stub was accid…
mratsim Jul 3, 2018
8e31b88
Reuse the same stub as OO implementation
mratsim Jul 3, 2018
2348ea0
Delete previous opcode implementation
mratsim Jul 3, 2018
816b6bc
Delete object oriented fork code
mratsim Jul 3, 2018
b677c1f
Delete exceptions that were used as control flows
mratsim Jul 3, 2018
18e682d
delete base.nim :fire:, yet another OO remnants
mratsim Jul 3, 2018
5226b58
Delete opcode table
mratsim Jul 3, 2018
b4b5543
Enable omputed gotos and compile-time gas fees
mratsim Jul 4, 2018
b5020ff
Revert const gasCosts -> generates SIGSEGV
mratsim Jul 4, 2018
1a5b358
inline push, swap and dup opcodes
mratsim Jul 4, 2018
2a3ae3a
loggers are now template again, why does this pass new tests?
mratsim Jul 4, 2018
6221296
Trigger CI rebuild after rocksdb fix https://github.com/status-im/nim…
mratsim Jul 4, 2018
27545b8
Address review comment on "push" + VMTests in debug mode (not release)
mratsim Jul 5, 2018
b08de18
Address review comment: don't tag fork by default, make opcode impl g…
mratsim Jul 5, 2018
6d53c46
Static compilation fixes after rebasing
mratsim Jul 5, 2018
65330cd
fix the initialization of the VM database
zah Jul 5, 2018
fe312a4
add a missing import
zah Jul 5, 2018
763489c
Deactivate balance and sload test following #59
mratsim Jul 5, 2018
549d722
Reactivate stack check (deactivated in #59, necessary to pass tests)
mratsim Jul 5, 2018
42fd80c
Merge remaining opcodes implementation from #59
mratsim Jul 5, 2018
bd17353
Merge callDataLoad and codeCopy fixes, todo simplify see #67
mratsim Jul 5, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions VMTests.md
Original file line number Diff line number Diff line change
Expand Up @@ -310,15 +310,15 @@ OK: 11/12 Fail: 1/12 Skip: 0/12
+ calldataload0.json OK
+ calldataload1.json OK
+ calldataload2.json OK
+ calldataloadSizeTooHigh.json OK
- calldataloadSizeTooHigh.json Fail
+ calldataloadSizeTooHighPartial.json OK
+ calldataload_BigOffset.json OK
+ calldatasize0.json OK
+ calldatasize1.json OK
+ calldatasize2.json OK
+ caller.json OK
+ callvalue.json OK
- codecopy0.json Fail
+ codecopy0.json OK
+ codecopyZeroMemExpansion.json OK
- codecopy_DataIndexTooHigh.json Fail
+ codesize.json OK
Expand Down Expand Up @@ -445,7 +445,7 @@ OK: 26/52 Fail: 11/52 Skip: 15/52
+ jumpi_at_the_end.json OK
+ jumpifInsidePushWithJumpDest.json OK
+ jumpifInsidePushWithoutJumpDest.json OK
- kv1.json Fail
+ kv1.json OK
+ log1MemExp.json OK
+ loop_stacklimit_1020.json OK
+ loop_stacklimit_1021.json OK
Expand All @@ -461,8 +461,8 @@ OK: 26/52 Fail: 11/52 Skip: 15/52
+ mstore0.json OK
+ mstore1.json OK
+ mstore8MemExp.json OK
- mstore8WordToBigError.json Fail
- mstore8_0.json Fail
+ mstore8WordToBigError.json OK
+ mstore8_0.json OK
- mstore8_1.json Fail
+ mstoreMemExp.json OK
+ mstoreWordToBigError.json OK
Expand All @@ -483,7 +483,7 @@ OK: 26/52 Fail: 11/52 Skip: 15/52
+ swapAt52becameMstore.json OK
+ when.json OK
```
OK: 110/145 Fail: 34/145 Skip: 1/145
OK: 113/145 Fail: 31/145 Skip: 1/145
## vmLogTest
```diff
+ log0_emptyMem.json OK
Expand Down Expand Up @@ -673,10 +673,10 @@ OK: 0/17 Fail: 0/17 Skip: 17/17
- sha3_memSizeQuadraticCost33.json Fail
- sha3_memSizeQuadraticCost63.json Fail
- sha3_memSizeQuadraticCost64.json Fail
- sha3_memSizeQuadraticCost64_2.json Fail
+ sha3_memSizeQuadraticCost64_2.json OK
- sha3_memSizeQuadraticCost65.json Fail
```
OK: 4/18 Fail: 14/18 Skip: 0/18
OK: 5/18 Fail: 13/18 Skip: 0/18
## vmSystemOperations
```diff
ABAcalls0.json Skip
Expand Down Expand Up @@ -719,9 +719,9 @@ OK: 4/18 Fail: 14/18 Skip: 0/18
OK: 0/36 Fail: 0/36 Skip: 36/36
## vmTests
```diff
+ arith.json OK
+ boolean.json OK
+ mktx.json OK
- arith.json Fail
- boolean.json Fail
- mktx.json Fail
+ suicide.json OK
```
OK: 4/4 Fail: 0/4 Skip: 0/4
OK: 1/4 Fail: 3/4 Skip: 0/4
107 changes: 37 additions & 70 deletions nimbus/constants.nim
Original file line number Diff line number Diff line change
Expand Up @@ -5,85 +5,52 @@ import
proc default(t: typedesc): t = discard

# constants

let
UINT_256_MAX*: UInt256 = high(UInt256)
INT_256_MAX_AS_UINT256* = cast[Uint256](high(Int256))
NULLBYTE* = "\x00"
EMPTYWORD* = repeat(NULLBYTE, 32)
UINT160CEILING*: UInt256 = 2.u256.pow(160)
ZERO_ADDRESS* = default(EthAddress)
CREATE_CONTRACT_ADDRESS* = ZERO_ADDRESS
ZERO_HASH32* = Hash256()
STACK_DEPTH_LIMIT* = 1024

GAS_LIMIT_EMA_DENOMINATOR* = 1_024
GAS_LIMIT_ADJUSTMENT_FACTOR* = 1_024
GAS_LIMIT_USAGE_ADJUSTMENT_NUMERATOR* = 3
const
UINT_256_MAX*: UInt256 = high(UInt256)
INT_256_MAX_AS_UINT256* = high(Uint256) shr 1
NULLBYTE* = "\x00"
EMPTYWORD* = repeat(NULLBYTE, 32)
UINT160CEILING*: UInt256 = 2.u256.pow(160)
ZERO_ADDRESS* = default(EthAddress)
CREATE_CONTRACT_ADDRESS* = ZERO_ADDRESS
ZERO_HASH32* = Hash256()
STACK_DEPTH_LIMIT* = 1024

GAS_LIMIT_EMA_DENOMINATOR* = 1_024
GAS_LIMIT_ADJUSTMENT_FACTOR* = 1_024
GAS_LIMIT_USAGE_ADJUSTMENT_NUMERATOR* = 3
GAS_LIMIT_USAGE_ADJUSTMENT_DENOMINATOR* = 2

DIFFICULTY_ADJUSTMENT_DENOMINATOR* = 2_048.u256
DIFFICULTY_MINIMUM* = 131_072.u256
DIFFICULTY_ADJUSTMENT_DENOMINATOR* = 2_048.u256
DIFFICULTY_MINIMUM* = 131_072.u256
BYZANTIUM_DIFFICULTY_ADJUSTMENT_CUTOFF* = 9

BOMB_EXPONENTIAL_PERIOD* = 100_000.u256
BOMB_EXPONENTIAL_FREE_PERIODS* = 2.u256

BLOCK_REWARD* = 5.u256 * 2.u256 # denoms.ether

UNCLE_DEPTH_PENALTY_FACTOR* = 8.u256

MAX_UNCLE_DEPTH* = 6.u256
MAX_UNCLES* = 2.u256

EMPTY_UNCLE_HASH* = "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347".toDigest

GENESIS_BLOCK_NUMBER* = 0.u256
GENESIS_DIFFICULTY* = 131_072.u256
GENESIS_GAS_LIMIT* = 3_141_592
GENESIS_PARENT_HASH* = ZERO_HASH32
GENESIS_COINBASE* = ZERO_ADDRESS
GENESIS_NONCE* = "\x00\x00\x00\x00\x00\x00\x00B"
GENESIS_MIX_HASH* = ZERO_HASH32
GENESIS_EXTRA_DATA* = ""
GAS_LIMIT_MINIMUM* = 5000

BLANK_ROOT_HASH* = "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".toDigest
EMPTY_SHA3* = "883f7328a6c30727a655daff17eba3a86049871bc7839a5b71e2bc26a99c4d4c".toDigest

GAS_MOD_EXP_QUADRATIC_DENOMINATOR* = 20.u256
BOMB_EXPONENTIAL_PERIOD* = 100_000.u256
BOMB_EXPONENTIAL_FREE_PERIODS* = 2.u256

MAX_PREV_HEADER_DEPTH* = 256.toBlockNumber
BLOCK_REWARD* = 5.u256 * 2.u256 # denoms.ether

FORK_ICEAGE_BLKNUM* = 200_000.u256
FORK_HOMESTED_BLKNUM* = 1_150_000.u256
FORK_DAO_BLKNUM* = 1_920_000.u256
FORK_TANGERINE_WHISTLE_BLKNUM* = 2_463_000.u256
FORK_SPURIOUS_DRAGON_BLKNUM* = 2_675_000.u256
FORK_BYZANTIUM_BLKNUM* = 4_370_000.u256
UNCLE_DEPTH_PENALTY_FACTOR* = 8.u256

# TODO: Move the below to a new utils unit?
MAX_UNCLE_DEPTH* = 6.u256
MAX_UNCLES* = 2.u256

type
Fork = enum fkUnknown, fkFrontier, fkIceAge, fkHomested, fkDao, fkTangerineWhistle, fkSpuriousDragon, fkByzantium
UInt256Pair = tuple[a: Uint256, b: Uint256]
EMPTY_UNCLE_HASH* = "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347".toDigest

proc `..`*(a, b: Uint256): UInt256Pair = (a, b)
GENESIS_BLOCK_NUMBER* = 0.u256
GENESIS_DIFFICULTY* = 131_072.u256
GENESIS_GAS_LIMIT* = 3_141_592
GENESIS_PARENT_HASH* = ZERO_HASH32
GENESIS_COINBASE* = ZERO_ADDRESS
GENESIS_NONCE* = "\x00\x00\x00\x00\x00\x00\x00B"
GENESIS_MIX_HASH* = ZERO_HASH32
GENESIS_EXTRA_DATA* = ""
GAS_LIMIT_MINIMUM* = 5000

proc contains*(ab: UInt256Pair, v: UInt256): bool =
return v >= ab[0] and v <= ab[1]
BLANK_ROOT_HASH* = "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".toDigest
EMPTY_SHA3* = "883f7328a6c30727a655daff17eba3a86049871bc7839a5b71e2bc26a99c4d4c".toDigest

proc toFork*(blockNumber: UInt256): Fork =
# TODO - Refactoring: superseded by newNimbusVM for the time being #https://github.com/status-im/nimbus/pull/37
# TODO - Refactoring: redundant with `chain.nim` getVM
result = fkUnknown
let one = u256(1)
if blockNumber in u256(0)..FORK_ICEAGE_BLKNUM - one: result = fkFrontier
elif blockNumber in FORK_ICEAGE_BLKNUM..FORK_HOMESTED_BLKNUM - one: result = fkIceAge
elif blockNumber in FORK_HOMESTED_BLKNUM..FORK_DAO_BLKNUM - one: result = fkHomested
elif blockNumber in FORK_DAO_BLKNUM..FORK_TANGERINE_WHISTLE_BLKNUM - one: result = fkDao
elif blockNumber in FORK_TANGERINE_WHISTLE_BLKNUM..FORK_SPURIOUS_DRAGON_BLKNUM - one: result = fkTangerineWhistle
elif blockNumber in FORK_SPURIOUS_DRAGON_BLKNUM..FORK_BYZANTIUM_BLKNUM - one: result = fkSpuriousDragon
else:
if blockNumber >= FORK_BYZANTIUM_BLKNUM: result = fkByzantium # Update for constantinople when announced
GAS_MOD_EXP_QUADRATIC_DENOMINATOR* = 20.u256

MAX_PREV_HEADER_DEPTH* = 256.toBlockNumber
MaxCallDepth* = 1024
4 changes: 3 additions & 1 deletion nimbus/db/state_db.nim
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,12 @@ proc setNonce*(db: var AccountStateDB, address: EthAddress, nonce: UInt256) =
db.setAccount(address, account)

proc getNonce*(db: AccountStateDB, address: EthAddress): UInt256 =
# TODO it is very strange that we require a var param here

validateCanonicalAddress(address, title="Storage Address")

let account = db.getAccount(address)
return account.nonce
account.nonce

proc toByteRange_Unnecessary*(h: KeccakHash): ByteRange =
## XXX: Another proc used to mark unnecessary conversions it the code
Expand Down
14 changes: 0 additions & 14 deletions nimbus/errors.nim
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ type
EVMError* = object of Exception
## Base error class for all evm errors.

VMNotFound* = object of EVMError
## No VM available for the provided block number.

BlockNotFound* = object of EVMError
## The block with the given number/hash does not exist.

Expand All @@ -24,9 +21,6 @@ type
ValidationError* = object of EVMError
## Error to signal something does not pass a validation check.

Halt* = object of EVMError
## Raised by opcode function to halt vm execution.

VMError* = object of EVMError
## Class of errors which can be raised during VM execution.
erasesReturnData*: bool
Expand Down Expand Up @@ -57,9 +51,6 @@ type
ContractCreationCollision* = object of VMError
## Error signaling that there was an address collision during contract creation.

Revert* = object of VMError
## Error used by the REVERT opcode

WriteProtection* = object of VMError
## Error raised if an attempt to modify the state database is made while
## operating inside of a STATICCALL context.
Expand All @@ -78,8 +69,3 @@ proc makeVMError*: ref VMError =
new(result)
result.burnsGas = true
result.erasesReturnData = true

proc makeRevert*(): ref Revert =
new(result)
result.burnsGas = false
result.erasesReturnData = false
2 changes: 1 addition & 1 deletion nimbus/logging.nim
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ template trace*(l: Logger, msg: string) =
when DEBUG:
l.log(msg, fgBlue)

proc getLogger*(name: string): Logger =
proc getLogger*(name: string): Logger {.inline.}=
result = Logger(name: name)

# proc disableLogging* =
Expand Down
2 changes: 1 addition & 1 deletion nimbus/validation.nim
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ proc validateStackItem*(value: string) =
raise newException(ValidationError,
&"Invalid stack item: expected 32 bytes, got {value.len}: value is {value}")

proc validateStackItem*(value: string | seq[byte]) =
proc validateStackItem*(value: openarray[byte]) =
if value.len > 32:
raise newException(ValidationError,
&"Invalid stack item: expected 32 bytes, got {value.len}: value is {value}")
64 changes: 0 additions & 64 deletions nimbus/vm/base.nim

This file was deleted.

19 changes: 10 additions & 9 deletions nimbus/vm/code_stream.nim
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ proc newCodeStreamFromUnescaped*(code: string): CodeStream =
newCodeStream(codeBytes)

proc read*(c: var CodeStream, size: int): seq[byte] =
# TODO: use openarray[bytes]
if c.pc + size - 1 < c.bytes.len:
result = c.bytes[c.pc .. c.pc + size - 1]
c.pc += size
Expand All @@ -60,18 +61,17 @@ proc readVmWord*(c: var CodeStream, n: int): UInt256 =
let last = min(c.pc + n, c.bytes.len)
let toWrite = last - c.pc
for i in 0 ..< toWrite : result_bytes[i] = c.bytes[last - i - 1]
for j in toWrite ..< 32: result_bytes[j] = 0
c.pc = last

proc len*(c: CodeStream): int =
len(c.bytes)

proc next*(c: var CodeStream): Op =
var nextOpcode = c.read(1)
if nextOpcode.len != 0:
return Op(nextOpcode[0])
if c.pc != c.bytes.len:
result = Op(c.bytes[c.pc])
inc c.pc
else:
return Op.STOP
result = Stop

iterator items*(c: var CodeStream): Op =
var nextOpcode = c.next()
Expand All @@ -83,9 +83,10 @@ proc `[]`*(c: CodeStream, offset: int): Op =
Op(c.bytes[offset])

proc peek*(c: var CodeStream): Op =
var currentPc = c.pc
result = c.next()
c.pc = currentPc
if c.pc <= c.bytes.len:
result = Op(c.bytes[c.pc])
else:
result = Stop

proc updatePc*(c: var CodeStream, value: int) =
c.pc = min(value, len(c))
Expand All @@ -100,7 +101,7 @@ when false:
finally:
cs.pc = anchorPc

proc isValidOpcode*(c: var CodeStream, position: int): bool =
proc isValidOpcode*(c: CodeStream, position: int): bool =
if position >= len(c):
return false
if position in c.invalidPositions:
Expand Down
Loading