2018-04-06 14:52:10 +00:00
|
|
|
# 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.
|
|
|
|
|
2018-06-15 09:11:25 +00:00
|
|
|
import
|
2019-11-13 14:49:39 +00:00
|
|
|
macros,
|
2019-02-05 19:15:50 +00:00
|
|
|
eth/common/eth_types, eth/rlp,
|
2018-07-06 15:08:31 +00:00
|
|
|
../../../constants
|
2018-01-16 17:05:20 +00:00
|
|
|
|
2019-10-26 01:24:43 +00:00
|
|
|
type
|
|
|
|
# cannot use range for unknown reason
|
|
|
|
# Nim bug?
|
|
|
|
GasNatural* = int64 # range[0'i64..high(int64)]
|
|
|
|
|
2018-03-13 14:30:38 +00:00
|
|
|
# some methods based on py-evm utils/numeric
|
|
|
|
|
2018-12-04 13:39:10 +00:00
|
|
|
func log2*[bits: static int](value: StUint[bits]): Natural {.inline.}=
|
2019-05-12 07:41:44 +00:00
|
|
|
(bits - 1) - value.leadingZeros
|
2018-10-05 15:26:20 +00:00
|
|
|
|
2018-07-06 15:08:31 +00:00
|
|
|
func log256*(value: UInt256): Natural {.inline.}=
|
2018-10-05 15:26:20 +00:00
|
|
|
value.log2 shr 3 # div 8 (= log2(256), Logb x = Loga x/Loga b)
|
2018-05-16 08:41:34 +00:00
|
|
|
|
2019-10-26 01:24:43 +00:00
|
|
|
func ceil32*(value: GasNatural): GasNatural {.inline.}=
|
2018-06-12 15:33:47 +00:00
|
|
|
# Round input to the nearest bigger multiple of 32
|
|
|
|
|
|
|
|
result = value
|
2018-01-16 18:42:38 +00:00
|
|
|
|
2018-06-12 15:33:47 +00:00
|
|
|
let remainder = result and 31 # equivalent to modulo 32
|
|
|
|
if remainder != 0:
|
|
|
|
return value + 32 - remainder
|
2018-01-16 17:05:20 +00:00
|
|
|
|
2019-10-26 01:24:43 +00:00
|
|
|
func wordCount*(length: GasNatural): GasNatural {.inline.}=
|
2018-06-12 15:33:47 +00:00
|
|
|
# Returns the number of EVM words corresponding to a specific size.
|
|
|
|
# EVM words is rounded up
|
|
|
|
length.ceil32 shr 5 # equivalent to `div 32` (32 = 2^5)
|
2018-07-18 09:14:28 +00:00
|
|
|
|
|
|
|
proc flipSign(value: var UInt256) =
|
|
|
|
# ⚠ Warning: low(Int256) (binary repr 0b1000...0000) cannot be negated, please handle this special case
|
|
|
|
value = not value
|
|
|
|
value += 1.u256
|
|
|
|
|
|
|
|
proc extractSign*(v: var UInt256, sign: var bool) =
|
|
|
|
sign = v > INT_256_MAX_AS_UINT256
|
|
|
|
if sign:
|
|
|
|
flipSign(v)
|
|
|
|
|
|
|
|
proc setSign*(v: var UInt256, sign: bool) {.inline.} =
|
|
|
|
if sign: flipSign(v)
|
2018-09-18 00:35:41 +00:00
|
|
|
|
|
|
|
func cleanMemRef*(x: UInt256): int {.inline.} =
|
|
|
|
## Sanitize memory addresses, catch negative or impossibly big offsets
|
|
|
|
# See https://github.com/status-im/nimbus/pull/97 for more info
|
|
|
|
# For rationale on shr, see https://github.com/status-im/nimbus/pull/101
|
|
|
|
const upperBound = (high(int32) shr 2).u256
|
|
|
|
if x > upperBound:
|
|
|
|
return high(int32) shr 2
|
2019-11-13 14:49:39 +00:00
|
|
|
return x.truncate(int)
|
2018-10-10 14:26:21 +00:00
|
|
|
|
2019-05-08 14:37:09 +00:00
|
|
|
proc rangeToPadded*[T: StUint](x: openarray[byte], first, last: int, toLen = 0): T =
|
2018-10-10 14:26:21 +00:00
|
|
|
## Convert take a slice of a sequence of bytes interpret it as the big endian
|
|
|
|
## representation of an Uint256. Use padding for sequence shorter than 32 bytes
|
|
|
|
## including 0-length sequences.
|
2019-05-08 14:37:09 +00:00
|
|
|
const N = T.bits div 8
|
2018-10-10 14:26:21 +00:00
|
|
|
|
|
|
|
let lo = max(0, first)
|
2019-05-08 14:37:09 +00:00
|
|
|
let hi = min(min(x.high, last), (lo+N)-1)
|
2018-10-10 14:26:21 +00:00
|
|
|
|
2018-12-04 11:49:48 +00:00
|
|
|
if not(lo <= hi):
|
2018-10-10 14:26:21 +00:00
|
|
|
return # 0
|
|
|
|
|
2019-05-08 14:37:09 +00:00
|
|
|
if toLen > hi-lo+1:
|
|
|
|
var temp: array[N, byte]
|
2019-10-26 01:24:43 +00:00
|
|
|
temp[0..hi-lo] = x.toOpenArray(lo, hi)
|
2019-05-08 14:37:09 +00:00
|
|
|
result = T.fromBytesBE(
|
|
|
|
temp,
|
2019-05-08 16:18:06 +00:00
|
|
|
allowPadding = false
|
2019-05-08 14:37:09 +00:00
|
|
|
)
|
|
|
|
else:
|
|
|
|
result = T.fromBytesBE(
|
|
|
|
x.toOpenArray(lo, hi),
|
|
|
|
allowPadding = true
|
|
|
|
)
|
2019-10-26 01:24:43 +00:00
|
|
|
|
2019-05-08 16:18:06 +00:00
|
|
|
proc rangeToPadded2*[T: StUint](x: openarray[byte], first, last: int, toLen = 0): T =
|
|
|
|
## Convert take a slice of a sequence of bytes interpret it as the big endian
|
|
|
|
## representation of an Uint256. Use padding for sequence shorter than 32 bytes
|
|
|
|
## including 0-length sequences.
|
|
|
|
const N = T.bits div 8
|
|
|
|
|
|
|
|
let lo = max(0, first)
|
|
|
|
let hi = min(min(x.high, last), (lo+N)-1)
|
|
|
|
|
|
|
|
if not(lo <= hi):
|
|
|
|
return # 0
|
|
|
|
|
|
|
|
var temp: array[N, byte]
|
2019-10-26 01:24:43 +00:00
|
|
|
temp[0..hi-lo] = x.toOpenArray(lo, hi)
|
2019-05-08 16:18:06 +00:00
|
|
|
result = T.fromBytesBE(
|
|
|
|
temp.toOpenArray(0, toLen-1),
|
|
|
|
allowPadding = true
|
|
|
|
)
|
2019-05-01 12:21:46 +00:00
|
|
|
|
|
|
|
# calculates the memory size required for a step
|
|
|
|
func calcMemSize*(offset, length: int): int {.inline.} =
|
|
|
|
if length.isZero: return 0
|
|
|
|
result = offset + length
|
|
|
|
|
|
|
|
func safeInt*(x: Uint256): int {.inline.} =
|
|
|
|
result = x.truncate(int)
|
|
|
|
if x > high(int32).u256 or result < 0:
|
|
|
|
result = high(int32)
|