nimbus-eth1/nimbus/utils/utils.nim

160 lines
4.8 KiB
Nim

# Nimbus
# Copyright (c) 2018-2024 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.
{.push raises: [].}
import
std/[math, times, strutils],
eth/[common/eth_types_rlp, trie/ordered_trie],
stew/byteutils,
nimcrypto/sha2,
../constants
export eth_types_rlp
template calcTxRoot*(transactions: openArray[Transaction]): Root =
orderedTrieRoot(transactions)
template calcWithdrawalsRoot*(withdrawals: openArray[Withdrawal]): Root =
orderedTrieRoot(withdrawals)
template calcReceiptsRoot*(receipts: openArray[Receipt]): Root =
orderedTrieRoot(receipts)
func calcRequestsHash*(requests: varargs[seq[byte]]): Hash32 =
func calcHash(reqType: byte, data: openArray[byte]): Hash32 =
var ctx: sha256
ctx.init()
ctx.update([reqType]) # request type
ctx.update data
ctx.finish(result.data)
ctx.clear()
var ctx: sha256
ctx.init()
for i, data in requests:
ctx.update(calcHash(i.byte, data).data)
ctx.finish(result.data)
ctx.clear()
func calcRequestsHash*(reqs: Opt[array[3, seq[byte]]]): Opt[Hash32] =
if reqs.isNone:
Opt.none(Hash32)
else:
Opt.some(calcRequestsHash(reqs.get()[0], reqs.get()[1], reqs.get()[2]))
func sumHash*(hashes: varargs[Hash32]): Hash32 =
var ctx: sha256
ctx.init()
for hash in hashes:
ctx.update hash.data
ctx.finish result.data
ctx.clear()
proc sumHash*(body: BlockBody): Hash32 {.gcsafe, raises: []} =
let txRoot = calcTxRoot(body.transactions)
let ommersHash = keccak256(rlp.encode(body.uncles))
let wdRoot = if body.withdrawals.isSome:
calcWithdrawalsRoot(body.withdrawals.get)
else: EMPTY_ROOT_HASH
sumHash(txRoot, ommersHash, wdRoot)
proc sumHash*(header: Header): Hash32 =
let wdRoot = if header.withdrawalsRoot.isSome:
header.withdrawalsRoot.get
else: EMPTY_ROOT_HASH
sumHash(header.txRoot, header.ommersHash, wdRoot)
func hasBody*(h: Header): bool =
h.txRoot != EMPTY_ROOT_HASH or
h.ommersHash != EMPTY_UNCLE_HASH or
h.withdrawalsRoot.get(EMPTY_ROOT_HASH) != EMPTY_ROOT_HASH
func generateAddress*(address: Address, nonce: AccountNonce): Address =
result.data[0..19] = keccak256(rlp.encodeList(address, nonce)).data.toOpenArray(12, 31)
type ContractSalt* = object
bytes*: array[32, byte]
const ZERO_CONTRACTSALT* = default(ContractSalt)
func generateSafeAddress*(address: Address, salt: ContractSalt,
data: openArray[byte]): Address =
const prefix = [0xff.byte]
let
dataHash = keccak256(data)
hashResult = withKeccak256:
h.update(prefix)
h.update(address.data)
h.update(salt.bytes)
h.update(dataHash.data)
hashResult.to(Address)
proc crc32*(crc: uint32, buf: openArray[byte]): uint32 =
const kcrc32 = [ 0'u32, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190,
0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320'u32, 0xf00f9344'u32, 0xd6d6a3e8'u32,
0xcb61b38c'u32, 0x9b64c2b0'u32, 0x86d3d2d4'u32, 0xa00ae278'u32, 0xbdbdf21c'u32]
var crcu32 = not crc
for b in buf:
crcu32 = (crcu32 shr 4) xor kcrc32[int((crcu32 and 0xF) xor (uint32(b) and 0xF'u32))]
crcu32 = (crcu32 shr 4) xor kcrc32[int((crcu32 and 0xF) xor (uint32(b) shr 4'u32))]
result = not crcu32
proc short*(h: Hash32): string =
var bytes: array[6, byte]
bytes[0..2] = h.data[0..2]
bytes[^3..^1] = h.data[^3..^1]
bytes.toHex
proc short*(h: Bytes32): string =
var bytes: array[6, byte]
bytes[0..2] = h.data[0..2]
bytes[^3..^1] = h.data[^3..^1]
bytes.toHex
func short*(x: Duration): string =
let parts = x.toParts
if parts[Hours] > 0:
result.add $parts[Hours]
result.add ':'
result.add intToStr(parts[Minutes].int, 2)
result.add ':'
result.add intToStr(parts[Seconds].int, 2)
proc decompose*(rlp: var Rlp,
header: var Header,
body: var BlockBody) {.gcsafe, raises: [RlpError].} =
var blk = rlp.read(Block)
header = system.move(blk.header)
body.transactions = system.move(blk.txs)
body.uncles = system.move(blk.uncles)
body.withdrawals = system.move(blk.withdrawals)
proc decompose*(rlpBytes: openArray[byte],
header: var Header,
body: var BlockBody) {.gcsafe, raises: [RlpError].} =
var rlp = rlpFromBytes(rlpBytes)
rlp.decompose(header, body)
func gwei*(n: uint64): GasInt =
GasInt(n * (10'u64 ^ 9'u64))
# Helper types to convert gwei into wei more easily
func weiAmount*(w: Withdrawal): UInt256 =
w.amount.u256 * (10'u64 ^ 9'u64).u256
func isGenesis*(header: Header): bool =
header.number == 0'u64 and
header.parentHash == GENESIS_PARENT_HASH