Implement duplication and block, add more opcodes, improve math support
This commit is contained in:
parent
637b56fa4c
commit
72c8ad4877
|
@ -0,0 +1,10 @@
|
|||
mode = ScriptMode.Verbose
|
||||
|
||||
packageName = "nimbus"
|
||||
version = "0.1.0"
|
||||
author = "Status Research & Development GmbH"
|
||||
description = "An Ethereum 2.0 Sharding Client for Resource-Restricted Devices"
|
||||
license = "Apache License 2.0"
|
||||
skipDirs = @["tests"]
|
||||
|
||||
requires "nim >= 0.17.0"
|
|
@ -1,5 +1,5 @@
|
|||
import
|
||||
strformat, strutils, sequtils, tables, macros,
|
||||
strformat, strutils, sequtils, tables, macros, bigints,
|
||||
constants, errors, utils/hexadecimal, utils_numeric, validation, vm_state, logging,
|
||||
vm / [code_stream, gas_meter, memory, message, stack]
|
||||
|
||||
|
@ -86,7 +86,7 @@ method prepareChildMessage*(
|
|||
# ? kwargs.setdefault('sender', self.msg.storage_address)
|
||||
|
||||
var childOptions = options
|
||||
childOptions.depth = c.msg.depth + 1.Int256
|
||||
childOptions.depth = c.msg.depth + 1.int256
|
||||
result = newMessage(
|
||||
gas,
|
||||
c.msg.gasPrice,
|
||||
|
@ -104,20 +104,20 @@ method extendMemory*(c: var BaseComputation, startPosition: Int256, size: Int256
|
|||
# validate_uint256(start_position, title="Memory start position")
|
||||
# validate_uint256(size, title="Memory size")
|
||||
|
||||
let beforeSize = ceil32(len(c.memory).Int256)
|
||||
let beforeSize = ceil32(len(c.memory).int256)
|
||||
let afterSize = ceil32(startPosition + size)
|
||||
|
||||
let beforeCost = memoryGasCost(beforeSize)
|
||||
let afterCost = memoryGasCost(afterSize)
|
||||
|
||||
c.logger.debug(%"MEMORY: size ({beforeSize} -> {afterSize}) | cost ({beforeCost} -> {afterCost})")
|
||||
c.logger.debug(&"MEMORY: size ({beforeSize} -> {afterSize}) | cost ({beforeCost} -> {afterCost})")
|
||||
|
||||
if size > 0:
|
||||
if beforeCost < afterCost:
|
||||
var gasFee = afterCost - beforeCost
|
||||
c.gasMeter.consumeGas(
|
||||
gasFee,
|
||||
reason = %"Expanding memory {beforeSize} -> {afterSize}")
|
||||
reason = &"Expanding memory {beforeSize} -> {afterSize}")
|
||||
|
||||
c.memory.extend(startPosition, size)
|
||||
|
||||
|
@ -132,7 +132,7 @@ method `output=`*(c: var BaseComputation, value: cstring) =
|
|||
|
||||
macro generateChildBaseComputation*(t: typed, vmState: typed, childMsg: typed): untyped =
|
||||
var typ = repr(getType(t)[1]).split(":", 1)[0]
|
||||
var name = ident(%"new{typ}")
|
||||
var name = ident(&"new{typ}")
|
||||
var typName = ident(typ)
|
||||
result = quote:
|
||||
block:
|
||||
|
@ -194,19 +194,19 @@ method getLogEntries*(c: BaseComputation): seq[(cstring, seq[Int256], cstring)]
|
|||
|
||||
method getGasRefund*(c: BaseComputation): Int256 =
|
||||
if c.isError:
|
||||
result = 0.Int256
|
||||
result = 0.int256
|
||||
else:
|
||||
result = c.gasMeter.gasRefunded + c.children.mapIt(it.getGasRefund()).foldl(a + b, 0.Int256)
|
||||
result = c.gasMeter.gasRefunded + c.children.mapIt(it.getGasRefund()).foldl(a + b, 0.int256)
|
||||
|
||||
method getGasUsed*(c: BaseComputation): Int256 =
|
||||
if c.shouldBurnGas:
|
||||
result = c.msg.gas
|
||||
else:
|
||||
result = max(0.Int256, c.msg.gas - c.gasMeter.gasRemaining)
|
||||
result = max(0.int256, c.msg.gas - c.gasMeter.gasRemaining)
|
||||
|
||||
method getGasRemaining*(c: BaseComputation): Int256 =
|
||||
if c.shouldBurnGas:
|
||||
result = 0.Int256
|
||||
result = 0.int256
|
||||
else:
|
||||
result = c.gasMeter.gasRemaining
|
||||
|
||||
|
@ -258,7 +258,7 @@ template inComputation*(c: untyped, handler: untyped): untyped =
|
|||
macro applyComputation(t: typed, vmState: untyped, message: untyped): untyped =
|
||||
# Perform the computation that would be triggered by the VM message
|
||||
var typ = repr(getType(t)[1]).split(":", 1)[0]
|
||||
var name = ident(%"new{typ}")
|
||||
var name = ident(&"new{typ}")
|
||||
var typName = ident(typ)
|
||||
result = quote:
|
||||
block:
|
||||
|
|
|
@ -1,205 +1,185 @@
|
|||
|
||||
import
|
||||
math, strutils, tables #, eth_utils
|
||||
bigints, math, strutils, tables, utils/padding
|
||||
|
||||
type
|
||||
TypeHint* {.pure.} = enum UInt256, Bytes, Any
|
||||
|
||||
Int256* = distinct int # TODO
|
||||
Int256* = BigInt #distinct int # TODO
|
||||
|
||||
proc int256*(i: int): Int256 =
|
||||
i.initBigInt
|
||||
|
||||
# TODO
|
||||
# We'll have a fast fixed Int256, for now this
|
||||
|
||||
proc `==`*(a: Int256, b: Int256): bool =
|
||||
a.int == b.int
|
||||
# We'll have a fast fixed int256, for now this works
|
||||
|
||||
proc `==`*(a: Int256, b: int): bool =
|
||||
a.int == b
|
||||
|
||||
proc `!=`*(a: Int256, b: Int256): bool =
|
||||
a.int != b.int
|
||||
a == b.int256
|
||||
|
||||
proc `!=`*(a: Int256, b: int): bool =
|
||||
a.int != b
|
||||
a != b.int256
|
||||
|
||||
proc `^`*(a: Int256, b: Int256): Int256 =
|
||||
(a.int ^ b.int).Int256
|
||||
proc `^`*(base: int; exp: int): Int256 =
|
||||
let base = base.initBigInt
|
||||
var ex = exp
|
||||
result = 1.initBigInt
|
||||
while ex > 0:
|
||||
result *= base
|
||||
dec(ex)
|
||||
|
||||
proc `^`*(a: Int256, b: int): Int256 =
|
||||
(a.int ^ b).Int256
|
||||
|
||||
proc `>`*(a: Int256, b: Int256): bool =
|
||||
a.int > b.int
|
||||
proc `^`*(left: Int256, right: int): Int256 =
|
||||
var value = right.initBigInt
|
||||
result = 1.initBigInt
|
||||
var m = right.int256
|
||||
while value > 0.int256:
|
||||
result = result * m
|
||||
value -= 1.int256
|
||||
|
||||
proc `>`*(a: Int256, b: int): bool =
|
||||
a.int > b
|
||||
|
||||
proc `>=`*(a: Int256, b: Int256): bool =
|
||||
a.int >= b.int
|
||||
|
||||
proc `<`*(a: Int256, b: Int256): bool =
|
||||
a.int < b.int
|
||||
a > b.int256
|
||||
|
||||
proc `<`*(a: Int256, b: int): bool =
|
||||
a.int < b
|
||||
|
||||
proc `<=`*(a: Int256, b: Int256): bool =
|
||||
a.int <= b.int
|
||||
|
||||
proc `$`*(a: Int256): string =
|
||||
$(a.int)
|
||||
|
||||
proc `-`*(a: Int256, b: Int256): Int256 =
|
||||
(a.int - b.int).Int256
|
||||
|
||||
proc `+`*(a: Int256, b: Int256): Int256 =
|
||||
(a.int + b.int).Int256
|
||||
|
||||
proc `-=`*(a: var Int256, b: Int256) =
|
||||
a = (a - b).Int256
|
||||
|
||||
proc `+=`*(a: var Int256, b: Int256) =
|
||||
a = (a + b).Int256
|
||||
|
||||
proc `*`*(a: Int256, b: Int256): Int256 =
|
||||
(a.int * b.int).Int256
|
||||
|
||||
proc `mod`*(a: Int256, b: Int256): Int256 =
|
||||
(a.int mod b.int).Int256
|
||||
a < b.int256
|
||||
|
||||
proc `mod`*(a: Int256, b: int): Int256 =
|
||||
(a.int mod b).Int256
|
||||
|
||||
proc `div`*(a: Int256, b: Int256): Int256 =
|
||||
(a.int div b.int).Int256
|
||||
a mod b.int256
|
||||
|
||||
proc `div`*(a: Int256, b: int): Int256 =
|
||||
(a.int div b).Int256
|
||||
a div b.int256
|
||||
|
||||
proc setXLen[T](s: var seq[T]; newlen: Natural) =
|
||||
if s.isNil:
|
||||
s = newSeq[T](newlen)
|
||||
else:
|
||||
s.setLen(newlen)
|
||||
|
||||
template mapOp(op: untyped): untyped =
|
||||
proc `op`*(left: Int256, right: Int256): Int256 =
|
||||
result = left.initBigInt
|
||||
var maxRight = right.initBigInt
|
||||
var l = max(left.limbs.len, right.limbs.len)
|
||||
result.limbs.setXLen(l)
|
||||
maxRight.limbs.setXLen(l)
|
||||
for z in 0 ..< l:
|
||||
result.limbs[z] = `op`(result.limbs[z], maxRight.limbs[z])
|
||||
|
||||
mapOp(`and`)
|
||||
mapOp(`or`)
|
||||
mapOp(`xor`)
|
||||
|
||||
proc `abs`*(a: Int256): Int256 =
|
||||
a.int.abs.Int256
|
||||
if a >= 0.int256: a else: -a
|
||||
|
||||
proc `and`*(a: Int256, b: Int256): Int256 =
|
||||
(a.int and b.int).Int256
|
||||
proc `getInt`*(a: Int256): int =
|
||||
a.limbs[0].int
|
||||
|
||||
proc `or`*(a: Int256, b: Int256): Int256 =
|
||||
(a.int or b.int).Int256
|
||||
let
|
||||
UINT_256_MAX*: Int256 = 2 ^ 256 - 1
|
||||
UINT_256_CEILING*: Int256 = 2 ^ 256
|
||||
UINT_255_MAX*: Int256 = 2 ^ (256 - 1) - 1
|
||||
UINT_255_CEILING*: Int256 = 2 ^ (256 - 1)
|
||||
|
||||
proc `xor`*(a: Int256, b: Int256): Int256 =
|
||||
(a.int xor b.int).Int256
|
||||
NULLBYTE* = cstring"\x00"
|
||||
EMPTYWORD* = repeat(NULLBYTE, 32)
|
||||
UINT160CEILING*: Int256 = 2 ^ 160
|
||||
CREATE_CONTRACT_ADDRESS* = cstring""
|
||||
ZERO_ADDRESS* = repeat(cstring"\x00", 20)
|
||||
ZERO_HASH32* = repeat(cstring"\x00", 20)
|
||||
STACKDEPTHLIMIT* = 1024
|
||||
|
||||
GAS_NULL* = 0.int256
|
||||
GAS_ZERO* = 0.int256
|
||||
GAS_BASE* = 2.int256
|
||||
GAS_VERY_LOW* = 3.int256
|
||||
GAS_LOW* = 5.int256
|
||||
GAS_MID* = 8.int256
|
||||
GAS_HIGH* = 10.int256
|
||||
GAS_EXT_CODE* = 20.int256
|
||||
GAS_BALANCE* = 20.int256
|
||||
GAS_SLOAD* = 50.int256
|
||||
GAS_JUMP_DEST* = 1.int256
|
||||
GAS_SSET* = 20_000.int256
|
||||
GAS_SRESET* = 5000.int256
|
||||
|
||||
REFUNDS_CLEAR* = 15_000.int256
|
||||
|
||||
GAS_SELF_DESTRUCT* = 0.int256
|
||||
GAS_SELF_DESTRUCT_NEW_ACCOUNT* = 25_000.int256
|
||||
GAS_CREATE* = 32_000.int256
|
||||
GAS_CALL* = 40.int256
|
||||
GASCALLVALUE = 9_000.int256
|
||||
GAS_CALL_STIPEND* = 2_300.int256
|
||||
GAS_NEW_ACCOUNT* = 25_000.int256
|
||||
|
||||
GAS_EXP* = 10.int256
|
||||
GAS_EXP_BYTE* = 10.int256
|
||||
GAS_MEMORY* = 3.int256
|
||||
GAS_TX_CREATE* = 32_000.int256
|
||||
GAS_TX_DATA_ZERO* = 4.int256
|
||||
GAS_TX_DATA_NON_ZERO* = 68.int256
|
||||
GAS_TX* = 21_000.int256
|
||||
GAS_LOG* = 375.int256
|
||||
GAS_LOG_DATA* = 8.int256
|
||||
GAS_LOG_TOPIC* = 375.int256
|
||||
GAS_SHA3* = 30.int256
|
||||
GAS_SHA3_WORD* = 6.int256
|
||||
GAS_COPY* = 3.int256
|
||||
GAS_BLOCK_HASH* = 20.int256
|
||||
GAS_CODE_DEPOSIT* = 200.int256
|
||||
GAS_MEMORY_QUADRATIC_DENOMINATOR* = 512.int256
|
||||
GAS_SHA256* = 60.int256
|
||||
GAS_SHA256WORD* = 12.int256
|
||||
GAS_RIP_EMD160* = 600.int256
|
||||
GAS_RIP_EMD160WORD* = 120.int256
|
||||
GAS_IDENTITY* = 15.int256
|
||||
GAS_IDENTITY_WORD* = 3
|
||||
GAS_ECRECOVER* = 3_000.int256
|
||||
GAS_ECADD* = 500.int256
|
||||
GAS_ECMUL* = 40_000.int256
|
||||
GAS_ECPAIRING_BASE* = 100_000.int256
|
||||
GAS_ECPAIRING_PER_POINT* = 80_000.int256
|
||||
GAS_LIMIT_EMA_DENOMINATOR* = 1_024.int256
|
||||
GAS_LIMIT_ADJUSTMENT_FACTOR* = 1_024.int256
|
||||
GAS_LIMIT_MAXIMUM*: Int256 = 2 ^ 63 - 1
|
||||
GAS_LIMIT_USAGE_ADJUSTMENT_NUMERATOR* = 3.int256
|
||||
GAS_LIMIT_USAGE_ADJUSTMENT_DENOMINATOR* = 2.int256
|
||||
|
||||
DIFFICULTY_ADJUSTMENT_DENOMINATOR* = 2_048.int256
|
||||
DIFFICULTY_MINIMUM* = 131_072.int256
|
||||
|
||||
BOMB_EXPONENTIAL_PERIOD* = 100_000.int256
|
||||
BOMB_EXPONENTIAL_FREE_PERIODS* = 2.int256
|
||||
|
||||
BLOCK_REWARD* = 5.int256 * 2.int256 # denoms.ether
|
||||
|
||||
UNCLE_DEPTH_PENALTY_FACTOR* = 8.int256
|
||||
|
||||
MAX_UNCLE_DEPTH* = 6.int256
|
||||
MAX_UNCLES* = 2.int256
|
||||
|
||||
SECPK1_P*: Int256 = 2 ^ 256 - 2 ^ 32 - 977
|
||||
SECPK1_N*: Int256 = "115792089237316195423570985008687907852837564279074904382605163141518161494337".initBigInt
|
||||
SECPK1_A* = 0.int256
|
||||
SECPK1_B* = 7.int256
|
||||
SECPK1_Gx* = 0.int256
|
||||
SECPK1_Gy* = 0.int256
|
||||
SECPK1_G* = (SECPK1Gx, SECPK1Gy)
|
||||
|
||||
EMPTY_UNCLE_HASH* = cstring"\x1d\xccM\xe8\xde\xc7]z\xab\x85\xb5g\xb6\xcc\xd4\x1a\xd3\x12E\x1b\x94\x8at\x13\xf0\xa1B\xfd@\xd4\x93G"
|
||||
|
||||
GENESIS_BLOCK_NUMBER* = 0.int256
|
||||
GENESIS_DIFFICULTY* = 131_072.int256
|
||||
GENESIS_GAS_LIMIT* = 3_141_592.int256
|
||||
GENESIS_PARENT_HASH* = ZERO_HASH32
|
||||
GENESIS_COINBASE* = ZERO_ADDRESS
|
||||
GENESIS_NONCE* = cstring"\x00\x00\x00\x00\x00\x00\x00B"
|
||||
GENESIS_MIX_HASH* = ZERO_HASH32
|
||||
GENESIS_EXTRA_DATA = cstring""
|
||||
|
||||
EMPTYSHA3 = cstring"\xc5\xd2F\x01\x86\xf7#<\x92~}\xb2\xdc\xc7\x03\xc0\xe5\x00\xb6S\xca\x82';{\xfa\xd8\x04]\x85\xa4p"
|
||||
BLANK_ROOT_HASH* = cstring"V\xe8\x1f\x17\x1b\xccU\xa6\xff\x83E\xe6\x92\xc0\xf8n[H\xe0\x1b\x99l\xad\xc0\x01b/\xb5\xe3c\xb4!"
|
||||
|
||||
GAS_MOD_EXP_QUADRATIC_DENOMINATOR* = 20.int256
|
||||
|
||||
proc max*(a: Int256, b: Int256): Int256 =
|
||||
max(a.int, b.int).Int256
|
||||
MAX_PREV_HEADER_DEPTH* = 256.int256
|
||||
|
||||
proc min*(a: Int256, b: Int256): Int256 =
|
||||
min(a.int, b.int).Int256
|
||||
|
||||
proc `-`*(a: Int256): Int256 =
|
||||
(-(a.int)).Int256
|
||||
|
||||
proc `shl`*(a: Int256, b: Int256): Int256 =
|
||||
(a.int shl b.int).Int256
|
||||
|
||||
proc `shr`*(a: Int256, b: Int256): Int256 =
|
||||
(a.int shr b.int).Int256
|
||||
|
||||
proc repeat(b: cstring, count: int): cstring =
|
||||
# TODO: faster
|
||||
var s = $b
|
||||
result = cstring(repeat(s, count))
|
||||
|
||||
const
|
||||
X = 62 # 256
|
||||
UINT_256_MAX* = (2 ^ X - 1).Int256
|
||||
UINT_256_CEILING* = (2 ^ X).Int256
|
||||
UINT_255_MAX* = (2 ^ (X - 1) - 1).Int256
|
||||
UINT_255_CEILING* = (2 ^ (X - 1)).Int256
|
||||
NULLBYTE = cstring"\x00"
|
||||
EMPTYWORD = repeat(NULLBYTE, 32)
|
||||
# UINT160CEILING = 2 ^ 160
|
||||
CREATE_CONTRACT_ADDRESS* = cstring""
|
||||
ZERO_ADDRESS* = repeat(cstring"\x00", 20)
|
||||
ZERO_HASH32* = repeat(cstring"\x00", 20)
|
||||
STACKDEPTHLIMIT* = 1024
|
||||
GAS_NULL* = 0.Int256
|
||||
GAS_ZERO* = 0.Int256
|
||||
GAS_BASE* = 2.Int256
|
||||
GAS_VERY_LOW* = 3.Int256
|
||||
GAS_LOW* = 5.Int256
|
||||
GAS_MID* = 8.Int256
|
||||
GAS_HIGH* = 10.Int256
|
||||
GAS_EXT_CODE* = 20.Int256
|
||||
GAS_BALANCE* = 20.Int256
|
||||
GAS_SLOAD* = 50.Int256
|
||||
GAS_JUMP_DEST* = 1.Int256
|
||||
GAS_SSET* = 20000.Int256
|
||||
GAS_SRESET* = 5000.Int256
|
||||
REFUNDSCLEAR = 15000
|
||||
GASSELFDESTRUCT = 0
|
||||
GASSELFDESTRUCTNEWACCOUNT = 25000
|
||||
GASCREATE = 32000
|
||||
GASCALL = 40
|
||||
GASCALLVALUE = 9000
|
||||
GASCALLSTIPEND = 2300
|
||||
GASNEWACCOUNT = 25000
|
||||
GASEXP = 10
|
||||
GASEXPBYTE = 10
|
||||
GAS_MEMORY* = 3.Int256
|
||||
GAS_TX_CREATE* = 32000.Int256
|
||||
GAS_TX_DATA_ZERO* = 4.Int256
|
||||
GAS_TX_DATA_NON_ZERO* = 68.Int256
|
||||
GAS_TX* = 21000.Int256
|
||||
GAS_LOG* = 375.Int256
|
||||
GASLOGDATA = 8
|
||||
GASLOGTOPIC = 375
|
||||
GASSHA3 = 30
|
||||
GASSHA3WORD = 6
|
||||
GASCOPY = 3
|
||||
GASBLOCKHASH = 20
|
||||
GASCODEDEPOSIT = 200
|
||||
GAS_MEMORY_QUADRATIC_DENOMINATOR* = 512.Int256
|
||||
GAS_SHA256 = 60.Int256
|
||||
GASSHA256WORD = 12
|
||||
GASRIPEMD160 = 600
|
||||
GASRIPEMD160WORD = 120
|
||||
GASIDENTITY = 15
|
||||
GASIDENTITYWORD = 3
|
||||
GASECRECOVER = 3000
|
||||
GASECADD = 500
|
||||
GASECMUL = 40000
|
||||
GASECPAIRINGBASE = 100000
|
||||
GASECPAIRINGPERPOINT = 80000
|
||||
GASLIMITEMADENOMINATOR = 1024
|
||||
GASLIMITADJUSTMENTFACTOR = 1024
|
||||
GASLIMITMINIMUM = 5000
|
||||
# GASLIMITMAXIMUM = 2 ^ 63 - 1
|
||||
GAS_LIMIT_USAGE_ADJUSTMENT_NUMERATOR* = 3.Int256
|
||||
GAS_LIMIT_USAGE_ADJUSTMENT_DENOMINATOR* = 2.Int256
|
||||
DIFFICULTY_ADJUSTMENT_DENOMINATOR* = 2_048.Int256
|
||||
DIFFICULTY_MINIMUM* = 131_072.Int256
|
||||
BOMB_EXPONENTIAL_PERIOD* = 100_000.Int256
|
||||
BOMB_EXPONENTIAL_FREE_PERIODS* = 2.Int256
|
||||
BLOCK_REWARD* = 5.Int256 * 2.Int256 # denoms.ether
|
||||
UNCLE_DEPTH_PENALTY_FACTOR* = 8.Int256
|
||||
MAXUNCLEDEPTH = 6
|
||||
MAXUNCLES = 2
|
||||
# SECPK1P = 2 ^ 256 - 2 ^ 32 - 977
|
||||
SECPK1N = 0
|
||||
SECPK1A = 0
|
||||
SECPK1B = 7
|
||||
SECPK1Gx = 0
|
||||
SECPK1Gy = 0
|
||||
SECPK1G = (SECPK1Gx, SECPK1Gy)
|
||||
EMPTYUNCLEHASH = cstring"\x1d\xccM\xe8\xde\xc7]z\xab\x85\xb5g\xb6\xcc\xd4\x1a\xd3\x12E\x1b\x94\x8at\x13\xf0\xa1B\xfd@\xd4\x93G"
|
||||
GENESIS_BLOCK_NUMBER* = 0.Int256
|
||||
GENESIS_DIFFICULTY* = 131_072.Int256
|
||||
GENESIS_GAS_LIMIT* = 3_141_592.Int256
|
||||
GENESIS_PARENT_HASH* = ZERO_HASH32
|
||||
GENESIS_COINBASE* = ZERO_ADDRESS
|
||||
GENESIS_NONCE* = cstring"\x00\x00\x00\x00\x00\x00\x00B"
|
||||
GENESIS_MIX_HASH* = ZERO_HASH32
|
||||
GENESIS_EXTRA_DATA = cstring""
|
||||
EMPTYSHA3 = cstring"\xc5\xd2F\x01\x86\xf7#<\x92~}\xb2\xdc\xc7\x03\xc0\xe5\x00\xb6S\xca\x82';{\xfa\xd8\x04]\x85\xa4p"
|
||||
BLANK_ROOT_HASH* = cstring"V\xe8\x1f\x17\x1b\xccU\xa6\xff\x83E\xe6\x92\xc0\xf8n[H\xe0\x1b\x99l\xad\xc0\x01b/\xb5\xe3c\xb4!"
|
||||
GAS_MOD_EXP_QUADRATIC_DENOMINATOR* = 20
|
||||
MAX_PREV_HEADER_DEPTH* = 256
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import
|
||||
../constants, ../utils_numeric, ../computation,
|
||||
.. / vm / [gas_meter, stack],
|
||||
helpers
|
||||
helpers, bigints
|
||||
|
||||
proc add*(computation: var BaseComputation) =
|
||||
# Addition
|
||||
|
@ -14,7 +14,7 @@ proc addmod*(computation: var BaseComputation) =
|
|||
# Modulo Addition
|
||||
var (left, right, arg) = computation.stack.popInt(3)
|
||||
|
||||
var res = if arg == 0: 0.Int256 else: (left + right) mod arg
|
||||
var res = if arg == 0: 0.int256 else: (left + right) mod arg
|
||||
pushRes()
|
||||
|
||||
proc sub*(computation: var BaseComputation) =
|
||||
|
@ -29,7 +29,7 @@ proc modulo*(computation: var BaseComputation) =
|
|||
# Modulo
|
||||
var (value, arg) = computation.stack.popInt(2)
|
||||
|
||||
var res = if arg == 0: 0.Int256 else: value mod arg
|
||||
var res = if arg == 0: 0.int256 else: value mod arg
|
||||
pushRes()
|
||||
|
||||
proc smod*(computation: var BaseComputation) =
|
||||
|
@ -38,8 +38,8 @@ proc smod*(computation: var BaseComputation) =
|
|||
value = unsignedToSigned(value)
|
||||
arg = unsignedToSigned(value)
|
||||
|
||||
var posOrNeg = if value < 0: -1.Int256 else: 1.Int256
|
||||
var res = if arg == 0: 0.Int256 else: ((value.abs mod arg.abs) * posOrNeg) and constants.UINT_256_MAX
|
||||
var posOrNeg = if value < 0: -1.int256 else: 1.int256
|
||||
var res = if arg == 0: 0.int256 else: ((value.abs mod arg.abs) * posOrNeg) and constants.UINT_256_MAX
|
||||
res = signedToUnsigned(res)
|
||||
pushRes()
|
||||
|
||||
|
@ -54,14 +54,14 @@ proc mulmod*(computation: var BaseComputation) =
|
|||
# Modulo Multiplication
|
||||
var (left, right, arg) = computation.stack.popInt(3)
|
||||
|
||||
var res = if arg == 0: 0.Int256 else: (left * right) mod arg
|
||||
var res = if arg == 0: 0.int256 else: (left * right) mod arg
|
||||
pushRes()
|
||||
|
||||
proc divide*(computation: var BaseComputation) =
|
||||
# Division
|
||||
var (numerator, denominator) = computation.stack.popInt(2)
|
||||
|
||||
var res = if denominator == 0: 0.Int256 else: (numerator div denominator) and constants.UINT_256_MAX
|
||||
var res = if denominator == 0: 0.int256 else: (numerator div denominator) and constants.UINT_256_MAX
|
||||
pushRes()
|
||||
|
||||
proc sdiv*(computation: var BaseComputation) =
|
||||
|
@ -70,8 +70,8 @@ proc sdiv*(computation: var BaseComputation) =
|
|||
numerator = unsignedToSigned(numerator)
|
||||
denominator = unsignedToSigned(denominator)
|
||||
|
||||
var posOrNeg = if numerator * denominator < 0: -1.Int256 else: 1.Int256
|
||||
var res = if denominator == 0: 0.Int256 else: (posOrNeg * (numerator.abs div denominator.abs))
|
||||
var posOrNeg = if numerator * denominator < 0: -1.int256 else: 1.int256
|
||||
var res = if denominator == 0: 0.int256 else: (posOrNeg * (numerator.abs div denominator.abs))
|
||||
res = unsignedToSigned(res)
|
||||
pushRes()
|
||||
|
||||
|
@ -80,9 +80,9 @@ proc exp*(computation: var BaseComputation, gasPerByte: Int256) =
|
|||
# Exponentiation
|
||||
var (base, exponent) = computation.stack.popInt(2)
|
||||
|
||||
var bitSize = 0.Int256 # TODO exponent.bitLength()
|
||||
var bitSize = 0.int256 # TODO exponent.bitLength()
|
||||
var byteSize = ceil8(bitSize) div 8
|
||||
var res = if base == 0: 0.Int256 else: (base ^ exponent) mod constants.UINT_256_CEILING
|
||||
var res = if base == 0: 0.int256 else: (base ^ exponent.getInt) mod constants.UINT_256_CEILING
|
||||
computation.gasMeter.consumeGas(
|
||||
gasPerByte * byteSize,
|
||||
reason="EXP: exponent bytes"
|
||||
|
@ -94,10 +94,10 @@ proc signextend(computation: var BaseComputation) =
|
|||
var (bits, value) = computation.stack.popInt(2)
|
||||
|
||||
var res: Int256
|
||||
if bits <= 31.Int256:
|
||||
var testBit = bits * 8.Int256 + 7.Int256
|
||||
var signBit = (1.Int256 shl testBit)
|
||||
res = if value != 0 and signBit != 0: value or (constants.UINT_256_CEILING - signBit) else: value and (signBit - 1.Int256)
|
||||
if bits <= 31.int256:
|
||||
var testBit = bits.getInt * 8 + 7
|
||||
var signBit = (1.int256 shl testBit)
|
||||
res = if value != 0 and signBit != 0: value or (constants.UINT_256_CEILING - signBit) else: value and (signBit - 1.int256)
|
||||
else:
|
||||
res = value
|
||||
pushRes()
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
import
|
||||
../constants, ../computation, ../vm/stack, ../vm_state
|
||||
|
||||
proc blockhash*(computation: var BaseComputation) =
|
||||
var blockNumber = computation.stack.popInt()
|
||||
var blockHash = computation.vmState.getAncestorHash(blockNumber)
|
||||
computation.stack.push(blockHash)
|
||||
|
||||
proc coinbase*(computation: var BaseComputation) =
|
||||
computation.stack.push(computation.vmState.coinbase)
|
||||
|
||||
proc timestamp*(computation: var BaseComputation) =
|
||||
computation.stack.push(computation.vmState.timestamp.int256)
|
||||
|
||||
proc difficulty*(computation: var BaseComputation) =
|
||||
computation.stack.push(computation.vmState.difficulty)
|
||||
|
||||
proc gaslimit*(computation: var BaseComputation) =
|
||||
computation.stack.push(computation.vmState.gasLimit)
|
|
@ -1,6 +1,6 @@
|
|||
import
|
||||
../constants, ../utils_numeric, ../computation, ../vm/stack,
|
||||
helpers
|
||||
helpers, bigints
|
||||
|
||||
quasiBoolean(lt, `<`) # Lesser Comparison
|
||||
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
import
|
||||
macros, strformat,
|
||||
../computation, ../vm/stack
|
||||
|
||||
macro dupXX(position: static[int]): untyped =
|
||||
let name = ident(&"dup{position}")
|
||||
result = quote:
|
||||
proc `name`*(computation: var BaseComputation) =
|
||||
computation.stack.dup(`position`)
|
||||
|
||||
dupXX(1)
|
||||
dupXX(2)
|
||||
dupXX(3)
|
||||
dupXX(4)
|
||||
dupXX(5)
|
||||
dupXX(6)
|
||||
dupXX(7)
|
||||
dupXX(8)
|
||||
dupXX(9)
|
||||
dupXX(10)
|
||||
dupXX(11)
|
||||
dupXX(12)
|
||||
dupXX(13)
|
||||
dupXX(14)
|
||||
dupXX(15)
|
||||
dupXX(16)
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
import
|
||||
strformat, bigints,
|
||||
../constants, ../opcode_values, ../logging, ../errors, ../computation, .. /vm / [code_stream, stack]
|
||||
|
||||
proc stop*(computation: var BaseComputation) =
|
||||
raise newException(Halt, "STOP")
|
||||
|
||||
|
||||
proc jump*(computation: var BaseComputation) =
|
||||
var jumpDest = computation.stack.popInt.getInt
|
||||
|
||||
computation.code.pc = jumpDest
|
||||
|
||||
let nextOpcode = computation.code.peek()
|
||||
|
||||
if nextOpcode != JUMPDEST:
|
||||
raise newException(InvalidJumpDestination, "Invalid Jump Destination")
|
||||
|
||||
if not computation.code.isValidOpcode(jumpDest):
|
||||
raise newException(InvalidInstruction, "Jump resulted in invalid instruction")
|
||||
|
||||
proc jumpi*(computation: var BaseComputation) =
|
||||
var (jumpDest, checkValue) = computation.stack.popInt(2)
|
||||
|
||||
if checkValue > 0:
|
||||
computation.code.pc = jumpDest.getInt
|
||||
|
||||
let nextOpcode = computation.code.peek()
|
||||
|
||||
if nextOpcode != JUMPDEST:
|
||||
raise newException(InvalidJumpDestination, "Invalid Jump Destination")
|
||||
|
||||
if not computation.code.isValidOpcode(jumpDest.getInt):
|
||||
raise newException(InvalidInstruction, "Jump resulted in invalid instruction")
|
||||
|
||||
proc jumpdest*(computation: var BaseComputation) =
|
||||
discard
|
||||
|
||||
proc pc*(computation: var BaseComputation) =
|
||||
var pc = max(computation.code.pc - 1, 0)
|
||||
computation.stack.push(pc)
|
||||
|
||||
proc gas*(computation: var BaseComputation) =
|
||||
var gasRemaining = computation.gasMeter.gasRemaining
|
||||
computation.stack.push(gasRemaining)
|
|
@ -1,9 +1,10 @@
|
|||
import macros
|
||||
|
||||
|
||||
template pushRes* =
|
||||
macro pushRes*: untyped =
|
||||
let resNode = ident("res")
|
||||
computation.stack.push(`resNode`)
|
||||
result = quote:
|
||||
computation.stack.push(`resNode`)
|
||||
|
||||
macro quasiBoolean*(name: untyped, op: untyped, signed: untyped = nil, nonzero: untyped = nil): untyped =
|
||||
var signedNode = newEmptyNode()
|
||||
|
@ -28,6 +29,6 @@ macro quasiBoolean*(name: untyped, op: untyped, signed: untyped = nil, nonzero:
|
|||
var (`leftNode`, `rightNode`) = computation.stack.popInt(2)
|
||||
`signedNode`
|
||||
|
||||
var `resNode` = if `test`: 1.Int256 else: 0.Int256
|
||||
var `resNode` = if `test`: 1.int256 else: 0.int256
|
||||
`finishSignedNode`
|
||||
computation.stack.push(`resNode`)
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
import
|
||||
../constants, ../computation, .. / vm / [stack, memory], ../utils/padding
|
||||
|
||||
|
||||
proc mstoreX(computation: var BaseComputation, x: int) =
|
||||
let start = computation.stack.popInt()
|
||||
let value = computation.stack.popBinary()
|
||||
|
||||
let paddedValue = pad_left(value, x, cstring"\x00")
|
||||
let normalizedValue = cstring(($paddedValue)[^x .. ^1])
|
||||
|
||||
computation.extendMemory(start, x.int256)
|
||||
computation.memory.write(start, 32.int256, normalizedValue)
|
||||
|
||||
template mstore*(computation: var BaseComputation) =
|
||||
mstoreX(32)
|
||||
|
||||
template mstore8*(computation: var BaseComputation) =
|
||||
mstoreX(1)
|
||||
|
||||
proc mload*(computation: var BaseComputation) =
|
||||
let start = computation.stack.popInt()
|
||||
|
||||
computation.extendMemory(start, 32.int256)
|
||||
|
||||
let value = computation.memory.read(start, 32.int256)
|
||||
computation.stack.push(value)
|
||||
|
||||
proc msize*(computation: var BaseComputation) =
|
||||
computation.stack.push(computation.memory.len)
|
|
@ -0,0 +1,28 @@
|
|||
import
|
||||
macros, strformat,
|
||||
../computation, ../vm/stack
|
||||
|
||||
macro swapXX(position: static[int]): untyped =
|
||||
let name = ident(&"swap{position}")
|
||||
result = quote:
|
||||
proc `name`*(computation: var BaseComputation) =
|
||||
computation.stack.swap(`position`)
|
||||
|
||||
swapXX(0)
|
||||
swapXX(1)
|
||||
swapXX(2)
|
||||
swapXX(3)
|
||||
swapXX(4)
|
||||
swapXX(5)
|
||||
swapXX(6)
|
||||
swapXX(7)
|
||||
swapXX(8)
|
||||
swapXX(9)
|
||||
swapXX(10)
|
||||
swapXX(11)
|
||||
swapXX(12)
|
||||
swapXX(13)
|
||||
swapXX(14)
|
||||
swapXX(15)
|
||||
swapXX(16)
|
||||
|
|
@ -30,36 +30,54 @@ const
|
|||
ADDRESS* = 48.byte
|
||||
BALANCE* = 49.byte
|
||||
ORIGIN* = 50.byte
|
||||
|
||||
CALLER* = 51.byte
|
||||
CALLVALUE* = 52.byte
|
||||
CALLDATALOAD* = 53.byte
|
||||
CALLDATASIZE* = 54.byte
|
||||
CALLDATACOPY* = 55.byte
|
||||
|
||||
CODESIZE* = 56.byte
|
||||
CODECOPY* = 57.byte
|
||||
|
||||
GASPRICE* = 58.byte
|
||||
|
||||
EXTCODESIZE* = 59.byte
|
||||
EXTCODECOPY* = 60.byte
|
||||
|
||||
RETURNDATASIZE* = 61.byte
|
||||
RETURNDATACOPY* = 62.byte
|
||||
|
||||
BLOCKHASH* = 64.byte
|
||||
|
||||
COINBASE* = 65.byte
|
||||
|
||||
TIMESTAMP* = 66.byte
|
||||
|
||||
NUMBER* = 67.byte
|
||||
|
||||
DIFFICULTY* = 68.byte
|
||||
|
||||
GASLIMIT* = 69.byte
|
||||
|
||||
POP* = 80.byte
|
||||
|
||||
MLOAD* = 81.byte
|
||||
MSTORE* = 82.byte
|
||||
MSTORE8 = 83.byte
|
||||
|
||||
SLOAD* = 84.byte
|
||||
SSTORE* = 85.byte
|
||||
|
||||
JUMP* = 86.byte
|
||||
JUMPI* = 87.byte
|
||||
|
||||
PC* = 88.byte
|
||||
|
||||
MSIZE* = 89.byte
|
||||
|
||||
GAS* = 90.byte
|
||||
|
||||
JUMPDEST* = 91.byte
|
||||
|
||||
PUSH1* = 96.byte
|
||||
|
@ -94,48 +112,48 @@ const
|
|||
PUSH30* = 125.byte
|
||||
PUSH31* = 126.byte
|
||||
PUSH32* = 127.byte
|
||||
DUP1* = 128.byte
|
||||
DUP2* = 129.byte
|
||||
DUP3* = 130.byte
|
||||
DUP4* = 131.byte
|
||||
DUP5* = 132.byte
|
||||
DUP6* = 133.byte
|
||||
DUP7* = 134.byte
|
||||
DUP8* = 135.byte
|
||||
DUP9* = 136.byte
|
||||
DUP10* = 137.byte
|
||||
DUP11* = 138.byte
|
||||
DUP12* = 139.byte
|
||||
DUP13* = 140.byte
|
||||
DUP14* = 141.byte
|
||||
DUP15* = 142.byte
|
||||
DUP16* = 143.byte
|
||||
SWAP1* = 144.byte
|
||||
SWAP2* = 145.byte
|
||||
SWAP3* = 146.byte
|
||||
SWAP4* = 147.byte
|
||||
SWAP5* = 148.byte
|
||||
SWAP6* = 149.byte
|
||||
SWAP7* = 150.byte
|
||||
SWAP8* = 151.byte
|
||||
SWAP9* = 152.byte
|
||||
SWAP10* = 153.byte
|
||||
SWAP11* = 154.byte
|
||||
SWAP12* = 155.byte
|
||||
SWAP13* = 156.byte
|
||||
SWAP14* = 157.byte
|
||||
SWAP15* = 158.byte
|
||||
SWAP16* = 159.byte
|
||||
LOG0* = 160.byte
|
||||
LOG1* = 161.byte
|
||||
LOG2* = 162.byte
|
||||
LOG3* = 163.byte
|
||||
LOG4* = 164.byte
|
||||
CREATE* = 240.byte
|
||||
CALL* = 241.byte
|
||||
CALLCODE* = 242.byte
|
||||
RETURN* = 243.byte
|
||||
DELEGATECALL* = 244.byte
|
||||
DUP1* = 128.byte
|
||||
DUP2* = 129.byte
|
||||
DUP3* = 130.byte
|
||||
DUP4* = 131.byte
|
||||
DUP5* = 132.byte
|
||||
DUP6* = 133.byte
|
||||
DUP7* = 134.byte
|
||||
DUP8* = 135.byte
|
||||
DUP9* = 136.byte
|
||||
DUP10* = 137.byte
|
||||
DUP11* = 138.byte
|
||||
DUP12* = 139.byte
|
||||
DUP13* = 140.byte
|
||||
DUP14* = 141.byte
|
||||
DUP15* = 142.byte
|
||||
DUP16* = 143.byte
|
||||
SWAP1* = 144.byte
|
||||
SWAP2* = 145.byte
|
||||
SWAP3* = 146.byte
|
||||
SWAP4* = 147.byte
|
||||
SWAP5* = 148.byte
|
||||
SWAP6* = 149.byte
|
||||
SWAP7* = 150.byte
|
||||
SWAP8* = 151.byte
|
||||
SWAP9* = 152.byte
|
||||
SWAP10* = 153.byte
|
||||
SWAP11* = 154.byte
|
||||
SWAP12* = 155.byte
|
||||
SWAP13* = 156.byte
|
||||
SWAP14* = 157.byte
|
||||
SWAP15* = 158.byte
|
||||
SWAP16* = 159.byte
|
||||
LOG0* = 160.byte
|
||||
LOG1* = 161.byte
|
||||
LOG2* = 162.byte
|
||||
LOG3* = 163.byte
|
||||
LOG4* = 164.byte
|
||||
CREATE* = 240.byte
|
||||
CALL* = 241.byte
|
||||
CALLCODE* = 242.byte
|
||||
RETURN* = 243.byte
|
||||
DELEGATECALL* = 244.byte
|
||||
STATICCALL* = 250.byte
|
||||
REVERT* = 253.byte
|
||||
SELFDESTRUCT* = 255.byte
|
||||
REVERT* = 253.byte
|
||||
SELFDESTRUCT* = 255.byte
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import
|
||||
constants, errors
|
||||
constants, bigints, errors
|
||||
|
||||
type
|
||||
BaseTransaction* = ref object
|
||||
|
@ -27,7 +27,7 @@ proc intrinsicGas*(t: BaseTransaction): Int256 =
|
|||
proc validate*(t: BaseTransaction) =
|
||||
# Hook called during instantiation to ensure that all transaction
|
||||
# parameters pass validation rules
|
||||
if t.intrinsic_gas() > t.gas:
|
||||
if t.intrinsicGas() > t.gas:
|
||||
raise newException(ValidationError, "Insufficient gas")
|
||||
# self.check_signature_validity()
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@ type
|
|||
timestamp*: int
|
||||
difficulty*: Int256
|
||||
blockNumber*: Int256
|
||||
hash*: cstring
|
||||
coinbase*: cstring
|
||||
# TODO
|
||||
|
||||
proc generateHeaderFromParentHeader*(
|
||||
|
@ -47,8 +49,8 @@ proc computeGasLimit*(header: Header, gasLimitFloor: Int256): Int256 =
|
|||
|
||||
proc gasUsed*(header: Header): Int256 =
|
||||
# TODO
|
||||
0.Int256
|
||||
0.int256
|
||||
|
||||
proc gasLimit*(header: Header): Int256 =
|
||||
# TODO
|
||||
0.Int256
|
||||
0.int256
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
import strformat, strutils
|
||||
|
||||
proc repeat*(b: cstring, count: int): cstring =
|
||||
# TODO
|
||||
result = cstring(repeat($b, count))
|
||||
|
||||
proc pad(value: cstring, size: int, with: cstring, left: bool): cstring =
|
||||
let padAmount = size - value.len
|
||||
if padAmount > 0:
|
||||
let fill = repeat(($with), padAmount)
|
||||
if left:
|
||||
result = cstring(&"{fill}{value}")
|
||||
else:
|
||||
result = cstring(&"{value}{fill}")
|
||||
else:
|
||||
result = value
|
||||
|
||||
|
||||
template padLeft*(value: cstring, size: int, with: cstring): cstring =
|
||||
pad(value, size, with, true)
|
||||
|
||||
template padRight*(value: cstring, size: int, with: cstring): cstring =
|
||||
pad(value, size, with, false)
|
||||
|
||||
template zpadRight*(value: cstring, size: int): cstring =
|
||||
padRight(value, size, with=cstring"\x00")
|
||||
|
||||
template zpadLeft*(value: cstring, size: int): cstring =
|
||||
padLeft(value, size, with=cstring"\x00")
|
||||
|
||||
template pad32*(value: cstring): cstring =
|
||||
zpadLeft(value, size=32)
|
||||
|
||||
template pad32r*(value: cstring): cstring =
|
||||
zpadRight(value, size=32)
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import constants, strformat, macros
|
||||
import bigints, constants, strformat, macros
|
||||
|
||||
proc intToBigEndian*(value: Int256): cstring =
|
||||
result = cstring""
|
||||
|
||||
proc bigEndianToInt*(value: cstring): Int256 =
|
||||
result = 0.Int256
|
||||
result = 0.int256
|
||||
|
||||
proc unsignedToSigned*(value: Int256): Int256 =
|
||||
if value <= UINT_255_MAX:
|
||||
|
@ -19,14 +19,14 @@ proc signedToUnsigned*(value: Int256): Int256 =
|
|||
return value
|
||||
|
||||
macro ceilXX(ceiling: static[int]): untyped =
|
||||
var name = ident(%"ceil{ceiling}")
|
||||
var name = ident(&"ceil{ceiling}")
|
||||
result = quote:
|
||||
proc `name`*(value: Int256): Int256 =
|
||||
var remainder = value mod `ceiling`.Int256
|
||||
var remainder = value mod `ceiling`.int256
|
||||
if remainder == 0:
|
||||
return value
|
||||
else:
|
||||
return value + `ceiling`.Int256 - remainder
|
||||
return value + `ceiling`.int256 - remainder
|
||||
|
||||
|
||||
ceilXX(32)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import
|
||||
strformat,
|
||||
errors, constants
|
||||
errors, constants, bigints
|
||||
|
||||
proc validateCanonicalAddress*(value: cstring, title: string = "Value") =
|
||||
if len(value) != 20:
|
||||
|
@ -13,12 +13,12 @@ proc validateCanonicalAddress*(value: cstring, title: string = "Value") =
|
|||
|
||||
|
||||
proc validateGte*(value: Int256, minimum: int, title: string = "Value") =
|
||||
if value <= minimum.Int256:
|
||||
if value <= minimum.int256:
|
||||
raise newException(ValidationError,
|
||||
fmt"{title} {value} is not greater than or equal to {minimum}")
|
||||
|
||||
proc validateGt*(value: Int256, minimum: int, title: string = "Value") =
|
||||
if value < minimum.Int256:
|
||||
if value < minimum.int256:
|
||||
raise newException(ValidationError,
|
||||
fmt"{title} {value} is not greater than or equal to {minimum}")
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import
|
||||
strformat,
|
||||
../logging, ../errors, ../constants
|
||||
../logging, ../errors, ../constants, bigints
|
||||
|
||||
type
|
||||
GasMeter* = ref object
|
||||
|
@ -13,28 +13,28 @@ proc newGasMeter*(startGas: Int256): GasMeter =
|
|||
new(result)
|
||||
result.startGas = startGas
|
||||
result.gasRemaining = result.startGas
|
||||
result.gasRefunded = 0.Int256
|
||||
result.gasRefunded = 0.int256
|
||||
|
||||
proc consumeGas*(gasMeter: var GasMeter; amount: Int256; reason: string) =
|
||||
if amount < 0.Int256:
|
||||
if amount < 0.int256:
|
||||
raise newException(ValidationError, "Gas consumption amount must be positive")
|
||||
if amount > gasMeter.gasRemaining:
|
||||
raise newException(OutOfGas,
|
||||
%"Out of gas: Needed {amount} - Remaining {gasMeter.gasRemaining} - Reason: {reason}")
|
||||
&"Out of gas: Needed {amount} - Remaining {gasMeter.gasRemaining} - Reason: {reason}")
|
||||
gasMeter.gasRemaining -= amount
|
||||
gasMeter.logger.trace(
|
||||
%"GAS CONSUMPTION: {gasMeter.gasRemaining + amount} - {amount} -> {gasMeter.gasRemaining} ({reason})")
|
||||
&"GAS CONSUMPTION: {gasMeter.gasRemaining + amount} - {amount} -> {gasMeter.gasRemaining} ({reason})")
|
||||
|
||||
proc returnGas*(gasMeter: var GasMeter; amount: Int256) =
|
||||
if amount < 0.Int256:
|
||||
if amount < 0.int256:
|
||||
raise newException(ValidationError, "Gas return amount must be positive")
|
||||
gasMeter.gasRemaining += amount
|
||||
gasMeter.logger.trace(
|
||||
%"GAS RETURNED: {gasMeter.gasRemaining - amount} + {amount} -> {gasMeter.gasRemaining}")
|
||||
&"GAS RETURNED: {gasMeter.gasRemaining - amount} + {amount} -> {gasMeter.gasRemaining}")
|
||||
|
||||
proc refundGas*(gasMeter: var GasMeter; amount: Int256) =
|
||||
if amount < 0.Int256:
|
||||
if amount < 0.int256:
|
||||
raise newException(ValidationError, "Gas refund amount must be positive")
|
||||
gasMeter.gasRefunded += amount
|
||||
gasMeter.logger.trace(
|
||||
%"GAS REFUND: {gasMeter.gasRemaining - amount} + {amount} -> {gasMeter.gasRefunded}")
|
||||
&"GAS REFUND: {gasMeter.gasRemaining - amount} + {amount} -> {gasMeter.gasRefunded}")
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import
|
||||
sequtils,
|
||||
sequtils, bigints,
|
||||
../constants, ../errors, ../logging, ../validation, ../utils_numeric
|
||||
|
||||
type
|
||||
|
@ -19,10 +19,13 @@ proc extend*(memory: var Memory; startPosition: Int256; size: Int256) =
|
|||
if size == 0:
|
||||
return
|
||||
var newSize = ceil32(startPosition + size)
|
||||
if newSize <= len(memory).Int256:
|
||||
if newSize <= len(memory).int256:
|
||||
return
|
||||
var sizeToExtend = newSize.int - len(memory)
|
||||
memory.bytes = memory.bytes.concat(repeat(0.byte, sizeToExtend))
|
||||
var sizeToExtend = newSize - len(memory).int256
|
||||
memory.bytes = memory.bytes.concat(repeat(0.byte, sizeToExtend.getInt))
|
||||
|
||||
proc read*(self: var Memory; startPosition: Int256; size: Int256): cstring =
|
||||
return cstring""
|
||||
|
||||
proc write*(self: var Memory, startPosition: Int256, size: Int256, value: cstring) =
|
||||
echo value
|
||||
|
|
|
@ -51,7 +51,7 @@ proc `storageAddress=`*(message: var Message, value: cstring) =
|
|||
|
||||
proc newMessageOptions*(
|
||||
origin: cstring = nil,
|
||||
depth: Int256 = 0.Int256,
|
||||
depth: Int256 = 0.int256,
|
||||
createAddress: cstring = nil,
|
||||
codeAddress: cstring = nil,
|
||||
shouldTransferValue: bool = true,
|
||||
|
|
|
@ -26,7 +26,7 @@ proc push*(stack: var Stack; value: int) =
|
|||
## Push an integer onto the stack
|
||||
ensureStackLimit()
|
||||
|
||||
stack.values.add(Value(kind: VInt, i: value.Int256))
|
||||
stack.values.add(Value(kind: VInt, i: value.int256))
|
||||
|
||||
proc push*(stack: var Stack; value: Int256) =
|
||||
## Push an integer onto the stack
|
||||
|
@ -93,7 +93,7 @@ proc popInt*(stack: var Stack): Int256 =
|
|||
result = elements[0]
|
||||
|
||||
macro internalPopTuple(numItems: static[int]): untyped =
|
||||
var name = ident(%"internalPopTuple{numItems}")
|
||||
var name = ident(&"internalPopTuple{numItems}")
|
||||
var typ = nnkPar.newTree()
|
||||
var t = ident("T")
|
||||
var resultNode = ident("result")
|
||||
|
@ -128,7 +128,7 @@ macro popInt*(stack: typed; numItems: static[int]): untyped =
|
|||
result = quote:
|
||||
`stack`.internalPop(`numItems`, Int256)
|
||||
else:
|
||||
var name = ident(%"internalPopTuple{numItems}")
|
||||
var name = ident(&"internalPopTuple{numItems}")
|
||||
result = quote:
|
||||
`name`(`stack`, Int256)
|
||||
|
||||
|
@ -157,7 +157,7 @@ proc swap*(stack: var Stack; position: int) =
|
|||
(stack.values[^1], stack.values[^idx]) = (stack.values[^idx], stack.values[^1])
|
||||
else:
|
||||
raise newException(InsufficientStack,
|
||||
%"Insufficient stack items for SWAP{position}")
|
||||
&"Insufficient stack items for SWAP{position}")
|
||||
|
||||
proc dup*(stack: var Stack; position: int) =
|
||||
## Perform a DUP operation on the stack
|
||||
|
@ -165,5 +165,5 @@ proc dup*(stack: var Stack; position: int) =
|
|||
stack.push(stack.values[^position])
|
||||
else:
|
||||
raise newException(InsufficientStack,
|
||||
%"Insufficient stack items for DUP{position}")
|
||||
&"Insufficient stack items for DUP{position}")
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import
|
||||
strformat, tables,
|
||||
logging, constants, errors, transaction, db/chain, utils/state, utils/header
|
||||
logging, constants, bigints, errors, transaction, db/chain, utils/state, utils/header
|
||||
|
||||
type
|
||||
BaseVMState* = ref object of RootObj
|
||||
|
@ -22,4 +22,31 @@ proc newBaseVMState*: BaseVMState =
|
|||
# result.receipts = nil
|
||||
|
||||
method logger*(vmState: BaseVMState): Logger =
|
||||
logging.getLogger(%"evm.vmState.{vmState.name}")
|
||||
logging.getLogger(&"evm.vmState.{vmState.name}")
|
||||
|
||||
method blockhash*(vmState: BaseVMState): cstring =
|
||||
vmState.blockHeader.hash
|
||||
|
||||
method coinbase*(vmState: BaseVMState): cstring =
|
||||
vmState.blockHeader.coinbase
|
||||
|
||||
method timestamp*(vmState: BaseVMState): int =
|
||||
vmState.blockHeader.timestamp
|
||||
|
||||
method blockBumber*(vmState: BaseVMState): Int256 =
|
||||
vmState.blockHeader.blockNumber
|
||||
|
||||
method difficulty*(vmState: BaseVMState): Int256 =
|
||||
vmState.blockHeader.difficulty
|
||||
|
||||
method gasLimit*(vmState: BaseVMState): Int256 =
|
||||
vmState.blockHeader.gasLimit
|
||||
|
||||
method getAncestorHash*(vmState: BaseVMState, blockNumber: Int256): cstring =
|
||||
var ancestorDepth = vmState.blockHeader.blockNumber - blockNumber - 1.int256
|
||||
if ancestorDepth >= constants.MAX_PREV_HEADER_DEPTH or
|
||||
ancestorDepth < 0 or
|
||||
ancestorDepth >= vmState.prevHeaders.len.int256:
|
||||
return cstring""
|
||||
var header = vmState.prevHeaders[ancestorDepth.getInt]
|
||||
result = header.hash
|
||||
|
|
Loading…
Reference in New Issue