diff --git a/nimbus.nimble b/nimbus.nimble index f4377bd1d..d516bdd5a 100644 --- a/nimbus.nimble +++ b/nimbus.nimble @@ -9,7 +9,7 @@ skipDirs = @["tests"] requires "nim >= 0.17.0", "https://github.com/status-im/nim-keccak-tiny.git >= 0.1.0", - "https://github.com/status-im/nim-rlp.git >= 1.0.0", + "https://github.com/alehander42/nim-rlp.git#fix-ordinal", "https://github.com/status-im/nim-ttmath >= 0.5.0" diff --git a/src/constants b/src/constants new file mode 100755 index 000000000..b19fc23e7 Binary files /dev/null and b/src/constants differ diff --git a/src/constants.nim b/src/constants.nim index 3213c659f..8c8094f26 100644 --- a/src/constants.nim +++ b/src/constants.nim @@ -7,7 +7,7 @@ import type TypeHint* {.pure.} = enum UInt256, Bytes, Any - Bytes* = seq[byte] + #Bytes* = seq[byte] # Int256* = BigInt #distinct int # TODO diff --git a/src/db/state_db.nim b/src/db/state_db.nim index cb42d4dcb..6c82581df 100644 --- a/src/db/state_db.nim +++ b/src/db/state_db.nim @@ -4,11 +4,11 @@ import type AccountStateDB* = ref object - db*: Table[string, UInt256] + db*: Table[string, Bytes] rootHash*: string # TODO trie proc newAccountStateDB*(db: Table[string, string], readOnly: bool = false): AccountStateDB = - result = AccountStateDB(db: initTable[string, UInt256]()) + result = AccountStateDB(db: initTable[string, Bytes]()) proc logger*(db: AccountStateDB): Logger = logging.getLogger("db.State") @@ -59,16 +59,16 @@ proc setStorage*(db: var AccountStateDB, address: string, slot: UInt256, value: let slotAsKey = slot.intToBigEndian.pad32.toString var storage = db.db # TODO fix - #if value > 0: - # let encodedValue = rlp.encode(value) - # storage[slotAsKey] = encodedValue - #else: - # storage.del(slotAsKey) - storage[slotAsKey] = value + if value > 0: + let encodedValue = rlp.encode(value) + storage[slotAsKey] = encodedValue.bytes[encodedValue.ibegin..= 32.u256: 0.u256 else: (value div (256.u256.pow(31'u - position.getUInt))) mod 256 + var res = if position >= 32.u256: 0.u256 else: (value div (256.u256.pow(31'u64 - position.getUInt))) mod 256 pushRes() diff --git a/src/logic/storage.nim b/src/logic/storage.nim index 07c3e2a06..8470968ee 100644 --- a/src/logic/storage.nim +++ b/src/logic/storage.nim @@ -11,11 +11,12 @@ proc sstore*(computation) = let (slot, value) = stack.popInt(2) var currentValue = 0.u256 + var existing = false computation.vmState.db(readOnly=false): - currentValue = db.getStorage(computation.msg.storageAddress, slot) + (currentValue, existing) = db.getStorage(computation.msg.storageAddress, slot) - let isCurrentlyEmpty = currentValue == 0 + let isCurrentlyEmpty = not existing let isGoingToBeEmpty = value == 0 let gasRefund = if isCurrentlyEmpty or not isGoingToBeEmpty: 0.u256 else: REFUND_SCLEAR diff --git a/src/utils_numeric.nim b/src/utils_numeric.nim index af379447d..e3b3a25e4 100644 --- a/src/utils_numeric.nim +++ b/src/utils_numeric.nim @@ -1,4 +1,4 @@ -import ttmath, constants, strformat, sequtils, endians, macros, utils / padding +import ttmath, constants, strformat, sequtils, endians, macros, utils / padding, rlp # TODO improve diff --git a/src/vm/stack.nim b/src/vm/stack.nim index bd1d46a7a..ca84ff489 100644 --- a/src/vm/stack.nim +++ b/src/vm/stack.nim @@ -1,5 +1,5 @@ import - strformat, strutils, sequtils, macros, + strformat, strutils, sequtils, macros, rlp, value, ../errors, ../validation, ../utils_numeric, ../constants, ttmath, ../logging, .. / utils / bytes type diff --git a/tests/stack_test.nim b/tests/stack_test.nim index a191298f4..937a7b0e5 100644 --- a/tests/stack_test.nim +++ b/tests/stack_test.nim @@ -1,65 +1,73 @@ -import unittest, macros, strformat, strutils, sequtils, constants, opcode_values, errors, vm / [stack, value], ttmath +import unittest, macros, strformat, strutils, sequtils, constants, opcode_values, errors, vm / [stack, value], ttmath, utils / [bytes, padding], utils_numeric + +template testPush(value: untyped, expected: untyped): untyped = + var stack = newStack() + stack.push(`value`) + check(stack.values == @[`expected`]) + +template testFailPush(value: untyped): untyped = + var stack = newStack() + expect(ValidationError): + stack.push(`value`) suite "stack": test "push only valid": - for value in @[0.vint, (pow(2.i256, 256) - 1.i256).vint, "ves".vbinary]: - var stack = newStack() - stack.push(value) - check(stack.values == @[value]) - - for value in @[(-1).vint, (-2).vint, "yzyzyzyzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz".vbinary]: - var stack = newStack() - expect(ValidationError): - stack.push(value) + testPush(0'u, 0.u256) + testPush(UINT_256_MAX, UINT_256_MAX) + testPush("ves".toBytes, "ves".toBytes.bigEndianToInt) + testFailPush("yzyzyzyzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz".toBytes) + test "push does not allow stack to exceed 1024": var stack = newStack() for z in 0 .. < 1024: - stack.push(z) + stack.push(z.uint) check(stack.len == 1024) expect(FullStack): stack.push(1025) + + + test "dup does not allow stack to exceed 1024": var stack = newStack() - stack.push(1.i256) + stack.push(1.u256) for z in 0 ..< 1023: - stack.dup(1.i256) + stack.dup(1) check(stack.len == 1024) expect(FullStack): - stack.dup(1.i256) + stack.dup(1) test "pop returns latest stack item": var stack = newStack() - for element in @[1.vint, 2.vint, 3.vint]: + for element in @[1'u, 2'u, 3'u]: stack.push(element) - check(stack.popInt == 3) + check(stack.popInt == 3.u256) stack = newStack() - for element in @["1".vbinary]: - stack.push(element) - check(stack.popBinary == "1") + stack.push("1".toBytes) + check(stack.popBinary == "1".toBytes.pad32) test "swap correct": var stack = newStack() for z in 0 ..< 5: - stack.push(z) - check(stack.values == @[0.vint, 1.vint, 2.vint, 3.vint, 4.vint]) + stack.push(z.uint) + check(stack.values == @[0.u256, 1.u256, 2.u256, 3.u256, 4.u256]) stack.swap(3) - check(stack.values == @[0.vint, 4.vint, 2.vint, 3.vint, 1.vint]) + check(stack.values == @[0.u256, 4.u256, 2.u256, 3.u256, 1.u256]) stack.swap(1) - check(stack.values == @[0.vint, 4.vint, 2.vint, 1.vint, 3.vint]) + check(stack.values == @[0.u256, 4.u256, 2.u256, 1.u256, 3.u256]) test "dup correct": var stack = newStack() for z in 0 ..< 5: - stack.push(z) - check(stack.values == @[0.vint, 1.vint, 2.vint, 3.vint, 4.vint]) + stack.push(z.uint) + check(stack.values == @[0.u256, 1.u256, 2.u256, 3.u256, 4.u256]) stack.dup(1) - check(stack.values == @[0.vint, 1.vint, 2.vint, 3.vint, 4.vint, 4.vint]) + check(stack.values == @[0.u256, 1.u256, 2.u256, 3.u256, 4.u256, 4.u256]) stack.dup(5) - check(stack.values == @[0.vint, 1.vint, 2.vint, 3.vint, 4.vint, 4.vint, 1.vint]) + check(stack.values == @[0.u256, 1.u256, 2.u256, 3.u256, 4.u256, 4.u256, 1.u256]) test "pop raises InsufficientStack appropriately": var stack = newStack() diff --git a/tests/test_helpers.nim b/tests/test_helpers.nim index 46f348f48..cf688a971 100644 --- a/tests/test_helpers.nim +++ b/tests/test_helpers.nim @@ -15,7 +15,7 @@ macro jsonTest*(s: static[string], handler: untyped): untyped = for filename in walkDirRec("tests" / "fixtures" / s): var (folder, name) = filename.splitPath() #if "Arithmetic" in folder: # - if name.startswith("swap"): + if name.startswith("addmodBigIntCast"): echo name result.add(generateTest(filename, handler)) z += 1