Exported blobs and some scripts to parallel project nimbus-eth1-blobs (#995)
why: TDD data and test script that are not needed for CI are externally held. This saves space. also: Added support for test-custom_networks.nim to run import Devnet5 dump.
This commit is contained in:
parent
b00ac490a9
commit
ed0e882387
|
@ -275,6 +275,12 @@ rm vendor/Nim/bin/nim
|
||||||
make -j8 build-nim
|
make -j8 build-nim
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- some programs in the _tests_ subdirectory do a replay of blockchain
|
||||||
|
database dumps when compiled and run locally. The dumps are found in
|
||||||
|
[this](https://github.com/status-im/nimbus-eth1-blobs) module which
|
||||||
|
need to be cloned as _nimbus-eth1-blobs_ parellel to the _nimbus-eth1_
|
||||||
|
file system root.
|
||||||
|
|
||||||
#### Git submodule workflow
|
#### Git submodule workflow
|
||||||
|
|
||||||
Working on a dependency:
|
Working on a dependency:
|
||||||
|
|
115
run-nimbus-sync
115
run-nimbus-sync
|
@ -1,115 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
#
|
|
||||||
# Script to run Nimbus-eth1 on the same networks Geth supports by name,
|
|
||||||
# with a trusted connection to a dedicated peer for that network.
|
|
||||||
#
|
|
||||||
# All protocols are disabled other than the minimum we need for block sync.
|
|
||||||
#
|
|
||||||
# This is very helpful for debugging and improving pipelined sync, and for
|
|
||||||
# improving the database and other processing, even though p2p sync is the
|
|
||||||
# endgame.
|
|
||||||
#
|
|
||||||
# - Discovery protocols are turned off
|
|
||||||
# - NAT hole punching protocols are turned off
|
|
||||||
# - Whisper protocol is turned off (`--protocols:eth`)
|
|
||||||
# - The only connection is to a single, active Geth for that network.
|
|
||||||
# - Each network's data is stored in a different location to avoid conflicts.
|
|
||||||
# - Each network is accessed by binding to a different port locally,
|
|
||||||
# so we can run several at the same time.
|
|
||||||
# - Log level is set to `TRACE` because we can read them when we're not
|
|
||||||
# swamped with discovery messages. Sync isn't fast enough yet.
|
|
||||||
#
|
|
||||||
# The enode URLs below are public facing Geth instances that are syncing to
|
|
||||||
# each of the networks. Nimbus-eth1 devs are free to use them for testing
|
|
||||||
# while they remain up. However, better results will be obtained if those nodes
|
|
||||||
# also have the Nimbus instances as "trusted peers".
|
|
||||||
#
|
|
||||||
set -e -u -o pipefail
|
|
||||||
|
|
||||||
# First argument says which testnet, or use mainnet for that.
|
|
||||||
# Defaults to goerli if omitted.
|
|
||||||
testnet=${1:-goerli}
|
|
||||||
|
|
||||||
# Additional arguments after the first are passed to Nimbus.
|
|
||||||
shift || :
|
|
||||||
|
|
||||||
staticnode_geth_mainnet='enode://7af995207d620d363ffbdac3216c45140c8fc31a1a30cac94dfad94713ba6b03efeb4f8dd4c0d676ec3e32a9eac2804560c3d3001c7551a2bb955c1e5ce22d17@mainnet.geth.ethereum.arxlogic.com:30303'
|
|
||||||
staticnode_geth_goerli='enode://9a8651c02d14ffbf7e328cd6c31307d90c9411673deeec819a1b7a205eed121c7eea192146937958608eaebff25dcd232fce958f031bf82ba3d55deaac3d0715@goerli.geth.ethereum.arxlogic.com:30303';
|
|
||||||
staticnode_geth_ropsten='enode://861f2b16e3da33f2af677de97087dd489b17f9a0685fdaf751fb524fdf171cd4b8f02a5dc9e25a2730d1aa1b22176f5c88397b7f01180d032375d1526a8e1421@ropsten.geth.ethereum.arxlogic.com:30303'
|
|
||||||
staticnode_geth_rinkeby='enode://bb34c7a91c9895769f782cd1f0da88025f302960beebac305010b7395912b3835eb954426b3cf4be1b47bae4c32973d87688ace8cce412a3efb88baabc77bd98@rinkeby.geth.ethereum.arxlogic.com:30303'
|
|
||||||
staticnode_geth_yolov3='enode://a11e7ed2a1a21b9464619f77734b9dec76befbc5ebb95ac7820f45728bc42c30f9bd406a83ddc28b28141bc0a8469638467ad6a48065977e1ac8e8f1c7a1e6b4@yolov3.geth.ethereum.arxlogic.com:30303'
|
|
||||||
|
|
||||||
case $testnet in
|
|
||||||
mainnet)
|
|
||||||
net_option= port=30193 staticnodes=$staticnode_geth_mainnet ;;
|
|
||||||
goerli)
|
|
||||||
net_option=--goerli port=30194 staticnodes=$staticnode_geth_goerli ;;
|
|
||||||
ropsten)
|
|
||||||
net_option=--ropsten port=30195 staticnodes=$staticnode_geth_ropsten ;;
|
|
||||||
rinkeby)
|
|
||||||
net_option=--rinkeby port=30196 staticnodes=$staticnode_geth_rinkeby ;;
|
|
||||||
yolov3)
|
|
||||||
net_option=--yolov3 port=30197 staticnodes=$staticnode_geth_yolov3 ;;
|
|
||||||
*)
|
|
||||||
echo "Unrecognised network: $testnet" 1>&2; exit 1 ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Perform DNS name lookup for enodes with names.
|
|
||||||
# Geth supports this nowadays, but Nimbus does not.
|
|
||||||
resolve_enodes() {
|
|
||||||
local node prefix suffix host port ip
|
|
||||||
set --
|
|
||||||
for node in $staticnodes; do
|
|
||||||
case $node in
|
|
||||||
enode://*@*:*)
|
|
||||||
prefix=${node%@*} suffix=${node##*@}
|
|
||||||
host=${suffix%:*} port=${suffix##*:}
|
|
||||||
case $host in
|
|
||||||
*[^0-9.]*)
|
|
||||||
ip=$(host -t a "$host" 2>/dev/null)
|
|
||||||
case $ip in
|
|
||||||
"$host has address "[0-9]*)
|
|
||||||
ip=${ip##* has address }
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Name lookup for $host failed" 1>&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
node=$prefix@$ip:$port
|
|
||||||
esac
|
|
||||||
esac
|
|
||||||
set -- "$@" "$node"
|
|
||||||
done
|
|
||||||
staticnodes="$*"
|
|
||||||
}
|
|
||||||
resolve_enodes
|
|
||||||
|
|
||||||
datadir="$HOME"/.nimbus/"$testnet"
|
|
||||||
|
|
||||||
# Use a stable nodekey if we have one, to ensure the remote Geth almost always
|
|
||||||
# accepts our connections. The nodekey's corresponding `enode` URL must be
|
|
||||||
# added with `admin.addTrustedPeer` to the remote Geth. This isn't perfect.
|
|
||||||
# Sometimes Geth is too busy even for a trusted peer. But usually it works.
|
|
||||||
#
|
|
||||||
# Note, this nodekey file isn't created automatically by nimbus-eth1 at the
|
|
||||||
# moment. We have to have done it manually before now.
|
|
||||||
#
|
|
||||||
if [ -e "$datadir"/nimbus/nodekey ]; then
|
|
||||||
nodekey=$(cat "$datadir"/nimbus/nodekey)
|
|
||||||
if [ -n "$nodekey" ]; then
|
|
||||||
set -- --nodekey:"$nodekey"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# So the process name shows up without a path in `netstat`.
|
|
||||||
export PATH=$HOME/Status/nimbus-eth1/build:$PATH
|
|
||||||
|
|
||||||
exec nimbus \
|
|
||||||
--datadir:"$datadir" $net_option \
|
|
||||||
--prune:full \
|
|
||||||
--logMetrics --logMetricsInterval:5 \
|
|
||||||
--log-level:TRACE \
|
|
||||||
--nodiscover --nat:none --port:$port --protocols:eth \
|
|
||||||
--staticnodes:"$staticnodes" \
|
|
||||||
"$@"
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"config": {
|
"config": {
|
||||||
"chainId": 1337702,
|
"chainId": 1337752,
|
||||||
"homesteadBlock": 0,
|
"homesteadBlock": 0,
|
||||||
"eip150Block": 0,
|
"eip150Block": 0,
|
||||||
"eip155Block": 0,
|
"eip155Block": 0,
|
File diff suppressed because one or more lines are too long
|
@ -12,73 +12,21 @@
|
||||||
## ----------------------------------------------------
|
## ----------------------------------------------------
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[sequtils, strformat, strutils, tables, times],
|
std/[tables, times],
|
||||||
../../nimbus/[chain_config, constants],
|
./pp_light,
|
||||||
eth/[common, trie/trie_defs]
|
../../nimbus/chain_config,
|
||||||
|
eth/common
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
export
|
||||||
# Public functions, units pretty printer
|
pp_light
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
proc ppMs*(elapsed: Duration): string =
|
|
||||||
result = $elapsed.inMilliSeconds
|
|
||||||
let ns = elapsed.inNanoSeconds mod 1_000_000
|
|
||||||
if ns != 0:
|
|
||||||
# to rounded deca milli seconds
|
|
||||||
let dm = (ns + 5_000i64) div 10_000i64
|
|
||||||
result &= &".{dm:02}"
|
|
||||||
result &= "ms"
|
|
||||||
|
|
||||||
proc ppSecs*(elapsed: Duration): string =
|
|
||||||
result = $elapsed.inSeconds
|
|
||||||
let ns = elapsed.inNanoseconds mod 1_000_000_000
|
|
||||||
if ns != 0:
|
|
||||||
# to rounded decs seconds
|
|
||||||
let ds = (ns + 5_000_000i64) div 10_000_000i64
|
|
||||||
result &= &".{ds:02}"
|
|
||||||
result &= "s"
|
|
||||||
|
|
||||||
proc toKMG*[T](s: T): string =
|
|
||||||
proc subst(s: var string; tag, new: string): bool =
|
|
||||||
if tag.len < s.len and s[s.len - tag.len ..< s.len] == tag:
|
|
||||||
s = s[0 ..< s.len - tag.len] & new
|
|
||||||
return true
|
|
||||||
result = $s
|
|
||||||
for w in [("000", "K"),("000K","M"),("000M","G"),("000G","T"),
|
|
||||||
("000T","P"),("000P","E"),("000E","Z"),("000Z","Y")]:
|
|
||||||
if not result.subst(w[0],w[1]):
|
|
||||||
return
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Public functions, pretty printer
|
# Public functions, pretty printer
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc pp*(s: string; hex = false): string =
|
|
||||||
if hex:
|
|
||||||
let n = (s.len + 1) div 2
|
|
||||||
(if s.len < 20: s else: s[0 .. 5] & ".." & s[s.len-8 .. s.len-1]) &
|
|
||||||
"[" & (if 0 < n: "#" & $n else: "") & "]"
|
|
||||||
elif s.len <= 30:
|
|
||||||
s
|
|
||||||
else:
|
|
||||||
(if (s.len and 1) == 0: s[0 ..< 8] else: "0" & s[0 ..< 7]) &
|
|
||||||
"..(" & $s.len & ").." & s[s.len-16 ..< s.len]
|
|
||||||
|
|
||||||
proc pp*(b: Blob): string =
|
proc pp*(b: Blob): string =
|
||||||
b.mapIt(it.toHex(2)).join.toLowerAscii.pp(hex = true)
|
b.mapIt(it.toHex(2)).join.toLowerAscii.pp(hex = true)
|
||||||
|
|
||||||
proc pp*(a: Hash256; collapse = true): string =
|
|
||||||
if not collapse:
|
|
||||||
a.data.mapIt(it.toHex(2)).join.toLowerAscii
|
|
||||||
elif a == emptyRlpHash:
|
|
||||||
"emptyRlpHash"
|
|
||||||
elif a == EMPTY_UNCLE_HASH:
|
|
||||||
"EMPTY_UNCLE_HASH"
|
|
||||||
elif a == EMPTY_SHA3:
|
|
||||||
"EMPTY_SHA3"
|
|
||||||
else:
|
|
||||||
a.data.mapIt(it.toHex(2)).join[56 .. 63].toLowerAscii
|
|
||||||
|
|
||||||
proc pp*(a: EthAddress): string =
|
proc pp*(a: EthAddress): string =
|
||||||
a.mapIt(it.toHex(2)).join[32 .. 39].toLowerAscii
|
a.mapIt(it.toHex(2)).join[32 .. 39].toLowerAscii
|
||||||
|
|
||||||
|
@ -119,6 +67,7 @@ proc pp*(g: Genesis; sep = " "): string =
|
||||||
&"parentHash={g.parentHash.pp}{sep}" &
|
&"parentHash={g.parentHash.pp}{sep}" &
|
||||||
&"baseFeePerGas={g.baseFeePerGas}"
|
&"baseFeePerGas={g.baseFeePerGas}"
|
||||||
|
|
||||||
|
|
||||||
proc pp*(h: BlockHeader; indent: int): string =
|
proc pp*(h: BlockHeader; indent: int): string =
|
||||||
h.pp("\n" & " ".repeat(max(1,indent)))
|
h.pp("\n" & " ".repeat(max(1,indent)))
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,160 @@
|
||||||
|
# Nimbus
|
||||||
|
# Copyright (c) 2018-2019 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.
|
||||||
|
|
||||||
|
## Pretty printing, an alternative to `$` for debugging
|
||||||
|
## ----------------------------------------------------
|
||||||
|
##
|
||||||
|
## minimal dependencies, avoiding circular import
|
||||||
|
|
||||||
|
import
|
||||||
|
std/[sequtils, strformat, strutils, tables, times],
|
||||||
|
nimcrypto/hash
|
||||||
|
|
||||||
|
export
|
||||||
|
sequtils, strformat, strutils
|
||||||
|
|
||||||
|
const
|
||||||
|
ZeroHash256 = MDigest[256].default
|
||||||
|
|
||||||
|
EmptyUncleHash = ( "1dcc4de8dec75d7aab85b567b6ccd41a" &
|
||||||
|
"d312451b948a7413f0a142fd40d49347" ).toDigest
|
||||||
|
|
||||||
|
BlankRootHash = ( "56e81f171bcc55a6ff8345e692c0f86e" &
|
||||||
|
"5b48e01b996cadc001622fb5e363b421" ).toDigest
|
||||||
|
|
||||||
|
EmptySha3 = ( "c5d2460186f7233c927e7db2dcc703c0" &
|
||||||
|
"e500b653ca82273b7bfad8045d85a470" ).toDigest
|
||||||
|
|
||||||
|
EmptyRlpHash = ( "56e81f171bcc55a6ff8345e692c0f86e" &
|
||||||
|
"5b48e01b996cadc001622fb5e363b421" ).toDigest
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Helpers
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
proc reGroup(q: openArray[int]; itemsPerSegment = 16): seq[seq[int]] =
|
||||||
|
var top = 0
|
||||||
|
while top < q.len:
|
||||||
|
let w = top
|
||||||
|
top = min(w + itemsPerSegment, q.len)
|
||||||
|
result.add q[w ..< top]
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Public functions, units pretty printer
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
proc ppMs*(elapsed: Duration): string =
|
||||||
|
result = $elapsed.inMilliSeconds
|
||||||
|
let ns = elapsed.inNanoSeconds mod 1_000_000
|
||||||
|
if ns != 0:
|
||||||
|
# to rounded deca milli seconds
|
||||||
|
let dm = (ns + 5_000i64) div 10_000i64
|
||||||
|
result &= &".{dm:02}"
|
||||||
|
result &= "ms"
|
||||||
|
|
||||||
|
proc ppSecs*(elapsed: Duration): string =
|
||||||
|
result = $elapsed.inSeconds
|
||||||
|
let ns = elapsed.inNanoseconds mod 1_000_000_000
|
||||||
|
if ns != 0:
|
||||||
|
# to rounded decs seconds
|
||||||
|
let ds = (ns + 5_000_000i64) div 10_000_000i64
|
||||||
|
result &= &".{ds:02}"
|
||||||
|
result &= "s"
|
||||||
|
|
||||||
|
proc toKMG*[T](s: T): string =
|
||||||
|
proc subst(s: var string; tag, new: string): bool =
|
||||||
|
if tag.len < s.len and s[s.len - tag.len ..< s.len] == tag:
|
||||||
|
s = s[0 ..< s.len - tag.len] & new
|
||||||
|
return true
|
||||||
|
result = $s
|
||||||
|
for w in [("000", "K"),("000K","M"),("000M","G"),("000G","T"),
|
||||||
|
("000T","P"),("000P","E"),("000E","Z"),("000Z","Y")]:
|
||||||
|
if not result.subst(w[0],w[1]):
|
||||||
|
return
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Public functions, pretty printer
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
proc pp*(s: string; hex = false): string =
|
||||||
|
if hex:
|
||||||
|
let n = (s.len + 1) div 2
|
||||||
|
(if s.len < 20: s else: s[0 .. 5] & ".." & s[s.len-8 .. s.len-1]) &
|
||||||
|
"[" & (if 0 < n: "#" & $n else: "") & "]"
|
||||||
|
elif s.len <= 30:
|
||||||
|
s
|
||||||
|
else:
|
||||||
|
(if (s.len and 1) == 0: s[0 ..< 8] else: "0" & s[0 ..< 7]) &
|
||||||
|
"..(" & $s.len & ").." & s[s.len-16 ..< s.len]
|
||||||
|
|
||||||
|
proc pp*(q: openArray[int]; itemsPerLine: int; lineSep: string): string =
|
||||||
|
doAssert q == q.reGroup(itemsPerLine).concat
|
||||||
|
q.reGroup(itemsPerLine)
|
||||||
|
.mapIt(it.mapIt(&"0x{it:02x}").join(", "))
|
||||||
|
.join("," & lineSep)
|
||||||
|
|
||||||
|
proc pp*(a: MDigest[256]; collapse = true): string =
|
||||||
|
if not collapse:
|
||||||
|
a.data.mapIt(it.toHex(2)).join.toLowerAscii
|
||||||
|
elif a == EmptyRlpHash:
|
||||||
|
"emptyRlpHash"
|
||||||
|
elif a == EmptyUncleHash:
|
||||||
|
"emptyUncleHash"
|
||||||
|
elif a == EmptySha3:
|
||||||
|
"EmptySha3"
|
||||||
|
elif a == ZeroHash256:
|
||||||
|
"zeroHash256"
|
||||||
|
else:
|
||||||
|
a.data.mapIt(it.toHex(2)).join[56 .. 63].toLowerAscii
|
||||||
|
|
||||||
|
proc pp*(a: openArray[MDigest[256]]; collapse = true): string =
|
||||||
|
"@[" & a.toSeq.mapIt(it.pp).join(" ") & "]"
|
||||||
|
|
||||||
|
proc pp*(q: openArray[int]; itemsPerLine: int; indent: int): string =
|
||||||
|
q.pp(itemsPerLine = itemsPerLine, lineSep = "\n" & " ".repeat(max(1,indent)))
|
||||||
|
|
||||||
|
proc pp*(q: openArray[byte]; noHash = false): string =
|
||||||
|
if q.len == 32 and not noHash:
|
||||||
|
var a: array[32,byte]
|
||||||
|
for n in 0..31: a[n] = q[n]
|
||||||
|
MDigest[256](data: a).pp
|
||||||
|
else:
|
||||||
|
q.toSeq.mapIt(it.toHex(2)).join.toLowerAscii.pp(hex = true)
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Elapsed time pretty printer
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template showElapsed*(noisy: bool; info: string; code: untyped) =
|
||||||
|
block:
|
||||||
|
let start = getTime()
|
||||||
|
code
|
||||||
|
if noisy:
|
||||||
|
let elpd {.inject.} = getTime() - start
|
||||||
|
if 0 < times.inSeconds(elpd):
|
||||||
|
echo "*** ", info, &": {elpd.ppSecs:>4}"
|
||||||
|
else:
|
||||||
|
echo "*** ", info, &": {elpd.ppMs:>4}"
|
||||||
|
|
||||||
|
template catchException*(info: string; trace: bool; code: untyped) =
|
||||||
|
block:
|
||||||
|
try:
|
||||||
|
code
|
||||||
|
except CatchableError as e:
|
||||||
|
if trace:
|
||||||
|
echo "*** ", info, ": exception ", e.name, "(", e.msg, ")"
|
||||||
|
echo " ", e.getStackTrace.strip.replace("\n","\n ")
|
||||||
|
|
||||||
|
template catchException*(info: string; code: untyped) =
|
||||||
|
catchException(info, false, code)
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# End
|
||||||
|
# ------------------------------------------------------------------------------
|
|
@ -67,6 +67,7 @@ proc dumpGroupNl*(db: BaseChainDB; headers: openArray[BlockHeader];
|
||||||
## `p2p/chain/persist_blocks.persistBlocksImpl()`:
|
## `p2p/chain/persist_blocks.persistBlocksImpl()`:
|
||||||
## ::
|
## ::
|
||||||
## dumpStream.write c.db.dumpGroupNl(headers,bodies)
|
## dumpStream.write c.db.dumpGroupNl(headers,bodies)
|
||||||
|
## dumpStream.flushFile
|
||||||
##
|
##
|
||||||
## where `dumpStream` is some stream (think of `stdout`) of type `File`
|
## where `dumpStream` is some stream (think of `stdout`) of type `File`
|
||||||
## that could be initialised with
|
## that could be initialised with
|
||||||
|
|
|
@ -20,19 +20,56 @@
|
||||||
## from `issue 932` <https://github.com/status-im/nimbus-eth1/issues/932>`_.
|
## from `issue 932` <https://github.com/status-im/nimbus-eth1/issues/932>`_.
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[distros, os, strformat, strutils, sequtils],
|
std/[distros, os],
|
||||||
../nimbus/[chain_config, config, genesis],
|
../nimbus/[chain_config, config, genesis],
|
||||||
../nimbus/db/[db_chain, select_backend],
|
../nimbus/db/[db_chain, select_backend],
|
||||||
./replay/pp,
|
../nimbus/p2p/chain,
|
||||||
|
./replay/[undump, pp],
|
||||||
|
chronicles,
|
||||||
eth/[common, p2p, trie/db],
|
eth/[common, p2p, trie/db],
|
||||||
nimcrypto/hash,
|
nimcrypto/hash,
|
||||||
|
stew/results,
|
||||||
unittest2
|
unittest2
|
||||||
|
|
||||||
const
|
type
|
||||||
baseDir = [".", "tests", ".." / "tests", $DirSep] # path containg repo
|
ReplaySession = object
|
||||||
repoDir = ["customgenesis", "."] # alternative repo paths
|
fancyName: string # display name
|
||||||
jFile = "kintsugi.json"
|
genesisFile: string # json file base name
|
||||||
|
termTotalDff: UInt256 # terminal total difficulty (to verify)
|
||||||
|
captureFile: string # gzipped RPL data dump
|
||||||
|
ttdReachedAt: uint64 # block number where total difficulty becomes `true`
|
||||||
|
failBlockAt: uint64 # stop here and expect that block to fail
|
||||||
|
|
||||||
|
const
|
||||||
|
baseDir = [".", "..", ".."/"..", $DirSep]
|
||||||
|
repoDir = [".", "tests"/"replay", "tests"/"customgenesis",
|
||||||
|
"nimbus-eth1-blobs"/"replay",
|
||||||
|
"nimbus-eth1-blobs"/"custom-network"]
|
||||||
|
|
||||||
|
devnet4 = ReplaySession(
|
||||||
|
fancyName: "Devnet4",
|
||||||
|
genesisFile: "devnet4.json",
|
||||||
|
captureFile: "devnetfour5664.txt.gz",
|
||||||
|
termTotalDff: 5_000_000_000.u256,
|
||||||
|
ttdReachedAt: 5645,
|
||||||
|
# Previously failed at `ttdReachedAt` (needed `state.nim` fix/update)
|
||||||
|
failBlockAt: 99999999)
|
||||||
|
|
||||||
|
devnet5 = ReplaySession(
|
||||||
|
fancyName: "Devnet5",
|
||||||
|
genesisFile: "devnet5.json",
|
||||||
|
captureFile: "devnetfive43968.txt.gz",
|
||||||
|
termTotalDff: 500_000_000_000.u256,
|
||||||
|
ttdReachedAt: 43711,
|
||||||
|
failBlockAt: 99999999)
|
||||||
|
|
||||||
|
kiln = ReplaySession(
|
||||||
|
fancyName: "Kiln",
|
||||||
|
genesisFile: "kiln.json",
|
||||||
|
captureFile: "kiln25872.txt.gz",
|
||||||
|
termTotalDff: 20_000_000_000_000.u256,
|
||||||
|
ttdReachedAt: 9999999,
|
||||||
|
failBlockAt: 9999999)
|
||||||
|
|
||||||
when not defined(linux):
|
when not defined(linux):
|
||||||
const isUbuntu32bit = false
|
const isUbuntu32bit = false
|
||||||
|
@ -58,6 +95,18 @@ let
|
||||||
#
|
#
|
||||||
disablePersistentDB = isUbuntu32bit
|
disablePersistentDB = isUbuntu32bit
|
||||||
|
|
||||||
|
# Block chains shared between test suites
|
||||||
|
var
|
||||||
|
mdb: BaseChainDB # memory DB
|
||||||
|
ddb: BaseChainDB # perstent DB on disk
|
||||||
|
ddbDir: string # data directory for disk database
|
||||||
|
sSpcs: ReplaySession # current replay session specs
|
||||||
|
|
||||||
|
const
|
||||||
|
# FIXED: Persistent database crash on `Devnet4` replay if the database
|
||||||
|
# directory was acidentally deleted (due to a stray "defer:" directive.)
|
||||||
|
ddbCrashBlockNumber = 2105
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Helpers
|
# Helpers
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
@ -71,6 +120,7 @@ proc findFilePath(file: string): string =
|
||||||
return path
|
return path
|
||||||
|
|
||||||
proc flushDbDir(s: string) =
|
proc flushDbDir(s: string) =
|
||||||
|
if s != "":
|
||||||
let dataDir = s / "nimbus"
|
let dataDir = s / "nimbus"
|
||||||
if (dataDir / "data").dirExists:
|
if (dataDir / "data").dirExists:
|
||||||
# Typically under Windows: there might be stale file locks.
|
# Typically under Windows: there might be stale file locks.
|
||||||
|
@ -85,37 +135,90 @@ proc say*(noisy = false; pfx = "***"; args: varargs[string, `$`]) =
|
||||||
else:
|
else:
|
||||||
echo pfx, args.toSeq.join
|
echo pfx, args.toSeq.join
|
||||||
|
|
||||||
|
proc setTraceLevel =
|
||||||
|
discard
|
||||||
|
when defined(chronicles_runtime_filtering) and loggingEnabled:
|
||||||
|
setLogLevel(LogLevel.TRACE)
|
||||||
|
|
||||||
|
proc setErrorLevel =
|
||||||
|
discard
|
||||||
|
when defined(chronicles_runtime_filtering) and loggingEnabled:
|
||||||
|
setLogLevel(LogLevel.ERROR)
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Private functions
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
proc ddbCleanUp(dir: string) =
|
||||||
|
if not disablePersistentDB:
|
||||||
|
ddbDir = dir
|
||||||
|
dir.flushDbDir
|
||||||
|
|
||||||
|
proc ddbCleanUp =
|
||||||
|
ddbDir.ddbCleanUp
|
||||||
|
|
||||||
|
proc isOK(rc: ValidationResult): bool =
|
||||||
|
rc == ValidationResult.OK
|
||||||
|
|
||||||
|
proc ttdReached(db: BaseChainDB): bool =
|
||||||
|
if db.config.terminalTotalDifficulty.isSome:
|
||||||
|
return db.config.terminalTotalDifficulty.get <= db.totalDifficulty
|
||||||
|
|
||||||
|
proc importBlocks(c: Chain; h: seq[BlockHeader]; b: seq[BlockBody];
|
||||||
|
noisy = false): bool =
|
||||||
|
## On error, the block number of the failng block is returned
|
||||||
|
let
|
||||||
|
(first, last) = (h[0].blockNumber, h[^1].blockNumber)
|
||||||
|
nTxs = b.mapIt(it.transactions.len).foldl(a+b)
|
||||||
|
nUnc = b.mapIt(it.uncles.len).foldl(a+b)
|
||||||
|
tddOk = c.db.ttdReached
|
||||||
|
bRng = if 1 < h.len: &"s [#{first}..#{last}]={h.len}" else: &" #{first}"
|
||||||
|
blurb = &"persistBlocks([#{first}..#"
|
||||||
|
|
||||||
|
noisy.say "***", &"block{bRng} #txs={nTxs} #uncles={nUnc}"
|
||||||
|
|
||||||
|
catchException("persistBlocks()", trace = true):
|
||||||
|
if c.persistBlocks(h, b).isOk:
|
||||||
|
if not tddOk and c.db.ttdReached:
|
||||||
|
noisy.say "***", &"block{bRng} => tddReached"
|
||||||
|
return true
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Test Runner
|
# Test Runner
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc runner(noisy = true; file = jFile) =
|
proc genesisLoadRunner(noisy = true;
|
||||||
|
captureSession = devnet4;
|
||||||
|
persistPruneTrie = true) =
|
||||||
|
sSpcs = captureSession
|
||||||
|
|
||||||
let
|
let
|
||||||
fileInfo = file.splitFile.name.split(".")[0]
|
gFileInfo = sSpcs.genesisFile.splitFile.name.split(".")[0]
|
||||||
filePath = file.findFilePath
|
gFilePath = sSpcs.genesisFile.findFilePath
|
||||||
|
|
||||||
tmpDir = if disablePersistentDB: "*notused*"
|
tmpDir = if disablePersistentDB: "*notused*"
|
||||||
else: filePath.splitFile.dir / "tmp"
|
else: gFilePath.splitFile.dir / "tmp"
|
||||||
|
|
||||||
defer:
|
persistPruneInfo = if persistPruneTrie: "pruning enabled"
|
||||||
if not disablePersistentDB: tmpDir.flushDbDir
|
else: "no pruning"
|
||||||
|
|
||||||
suite "Kintsugi custom network test scenario":
|
suite &"{sSpcs.fancyName} custom network genesis & database setup":
|
||||||
var
|
var
|
||||||
params: NetworkParams
|
params: NetworkParams
|
||||||
mdb, ddb: BaseChainDB
|
|
||||||
|
|
||||||
test &"Load params from {fileInfo}":
|
test &"Load params from {gFileInfo}":
|
||||||
noisy.say "***", "custom-file=", filePath
|
noisy.say "***", "custom-file=", gFilePath
|
||||||
check filePath.loadNetworkParams(params)
|
check gFilePath.loadNetworkParams(params)
|
||||||
|
|
||||||
test "Construct in-memory BaseChainDB":
|
test "Construct in-memory BaseChainDB, pruning enabled":
|
||||||
mdb = newBaseChainDB(
|
mdb = newBaseChainDB(
|
||||||
newMemoryDb(),
|
newMemoryDb(),
|
||||||
id = params.config.chainID.NetworkId,
|
id = params.config.chainID.NetworkId,
|
||||||
params = params)
|
params = params)
|
||||||
|
|
||||||
test &"Construct persistent BaseChainDB on {tmpDir}":
|
check mdb.ttd == sSpcs.termTotalDff
|
||||||
|
|
||||||
|
test &"Construct persistent BaseChainDB on {tmpDir}, {persistPruneInfo}":
|
||||||
if disablePersistentDB:
|
if disablePersistentDB:
|
||||||
skip()
|
skip()
|
||||||
else:
|
else:
|
||||||
|
@ -123,15 +226,17 @@ proc runner(noisy = true; file = jFile) =
|
||||||
# cleared. There might be left overs from a previous crash or
|
# cleared. There might be left overs from a previous crash or
|
||||||
# because there were file locks under Windows which prevented a
|
# because there were file locks under Windows which prevented a
|
||||||
# previous clean up.
|
# previous clean up.
|
||||||
tmpDir.flushDbDir
|
tmpDir.ddbCleanUp
|
||||||
|
|
||||||
# Constructor ...
|
# Constructor ...
|
||||||
ddb = newBaseChainDB(
|
ddb = newBaseChainDB(
|
||||||
tmpDir.newChainDb.trieDB,
|
tmpDir.newChainDb.trieDB,
|
||||||
id = params.config.chainID.NetworkId,
|
id = params.config.chainID.NetworkId,
|
||||||
pruneTrie = true,
|
pruneTrie = persistPruneTrie,
|
||||||
params = params)
|
params = params)
|
||||||
|
|
||||||
|
check mdb.ttd == sSpcs.termTotalDff
|
||||||
|
|
||||||
test "Initialise in-memory Genesis":
|
test "Initialise in-memory Genesis":
|
||||||
mdb.initializeEmptyDb
|
mdb.initializeEmptyDb
|
||||||
|
|
||||||
|
@ -156,17 +261,109 @@ proc runner(noisy = true; file = jFile) =
|
||||||
onTheFlyHeaderPP = ddb.toGenesisHeader.pp
|
onTheFlyHeaderPP = ddb.toGenesisHeader.pp
|
||||||
check storedhHeaderPP == onTheFlyHeaderPP
|
check storedhHeaderPP == onTheFlyHeaderPP
|
||||||
|
|
||||||
|
|
||||||
|
proc testnetChainRunner(noisy = true;
|
||||||
|
memoryDB = true;
|
||||||
|
stopAfterBlock = 999999999) =
|
||||||
|
let
|
||||||
|
cFileInfo = sSpcs.captureFile.splitFile.name.split(".")[0]
|
||||||
|
cFilePath = sSpcs.captureFile.findFilePath
|
||||||
|
dbInfo = if memoryDB: "in-memory" else: "persistent"
|
||||||
|
|
||||||
|
pivotBlockNumber = sSpcs.failBlockAt.u256
|
||||||
|
lastBlockNumber = stopAfterBlock.u256
|
||||||
|
ttdBlockNumber = sSpcs.ttdReachedAt.u256
|
||||||
|
|
||||||
|
suite &"Block chain DB inspector for {sSpcs.fancyName}":
|
||||||
|
var
|
||||||
|
bdb: BaseChainDB
|
||||||
|
chn: Chain
|
||||||
|
pivotHeader: BlockHeader
|
||||||
|
pivotBody: BlockBody
|
||||||
|
|
||||||
|
test &"Inherit {dbInfo} block chain DB from previous session":
|
||||||
|
check not mdb.isNil
|
||||||
|
check not ddb.isNil
|
||||||
|
|
||||||
|
# Whatever DB suits, mdb: in-memory, ddb: persistet/on-disk
|
||||||
|
bdb = if memoryDB: mdb else: ddb
|
||||||
|
|
||||||
|
chn = bdb.newChain
|
||||||
|
noisy.say "***", "ttd",
|
||||||
|
" db.config.TTD=", chn.db.config.terminalTotalDifficulty
|
||||||
|
# " db.arrowGlacierBlock=0x", chn.db.config.arrowGlacierBlock.toHex
|
||||||
|
|
||||||
|
test &"Replay {cFileInfo} capture, may fail ~#{pivotBlockNumber} "&
|
||||||
|
&"(slow -- time for coffee break)":
|
||||||
|
noisy.say "***", "capture-file=", cFilePath
|
||||||
|
discard
|
||||||
|
|
||||||
|
test &"Processing {sSpcs.fancyName} blocks":
|
||||||
|
for w in cFilePath.undumpNextGroup:
|
||||||
|
let (fromBlock, toBlock) = (w[0][0].blockNumber, w[0][^1].blockNumber)
|
||||||
|
|
||||||
|
# Install & verify Genesis
|
||||||
|
if w[0][0].blockNumber == 0.u256:
|
||||||
|
doAssert w[0][0] == bdb.getBlockHeader(0.u256)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Persist blocks, full range before `pivotBlockNumber`
|
||||||
|
if toBlock < pivotBlockNumber:
|
||||||
|
if not chn.importBlocks(w[0], w[1], noisy):
|
||||||
|
# Just a guess -- might be any block in that range
|
||||||
|
(pivotHeader, pivotBody) = (w[0][0],w[1][0])
|
||||||
|
break
|
||||||
|
if chn.db.ttdReached:
|
||||||
|
check ttdBlockNumber <= toBlock
|
||||||
|
else:
|
||||||
|
check toBlock < ttdBlockNumber
|
||||||
|
if lastBlockNumber <= toBlock:
|
||||||
|
break
|
||||||
|
|
||||||
|
else:
|
||||||
|
let top = (pivotBlockNumber - fromBlock).truncate(uint64).int
|
||||||
|
|
||||||
|
# Load the blocks before the pivot block
|
||||||
|
if 0 < top:
|
||||||
|
check chn.importBlocks(w[0][0 ..< top],w[1][0 ..< top], noisy)
|
||||||
|
|
||||||
|
(pivotHeader, pivotBody) = (w[0][top],w[1][top])
|
||||||
|
break
|
||||||
|
|
||||||
|
test &"Processing {sSpcs.fancyName} block #{pivotHeader.blockNumber}, "&
|
||||||
|
&"persistBlocks() will fail":
|
||||||
|
|
||||||
|
setTraceLevel()
|
||||||
|
|
||||||
|
if pivotHeader.blockNumber == 0:
|
||||||
|
skip()
|
||||||
|
else:
|
||||||
|
# Expecting that the import fails at the current block ...
|
||||||
|
check not chn.importBlocks(@[pivotHeader], @[pivotBody], noisy)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Main function(s)
|
# Main function(s)
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc customNetworkMain*(noisy = defined(debug)) =
|
proc customNetworkMain*(noisy = defined(debug)) =
|
||||||
noisy.runner
|
defer: ddbCleanUp()
|
||||||
|
noisy.genesisLoadRunner
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
var noisy = defined(debug)
|
let noisy = defined(debug) or true
|
||||||
noisy = true
|
setErrorLevel()
|
||||||
noisy.runner
|
|
||||||
|
noisy.showElapsed("customNetwork"):
|
||||||
|
defer: ddbCleanUp()
|
||||||
|
|
||||||
|
noisy.genesisLoadRunner(
|
||||||
|
# any of: devnet4, devnet5, kiln, etc.
|
||||||
|
captureSession = devnet4)
|
||||||
|
|
||||||
|
# Note that the `testnetChainRunner()` finds the replay dump files
|
||||||
|
# typically on the `nimbus-eth1-blobs` module.
|
||||||
|
noisy.testnetChainRunner(
|
||||||
|
stopAfterBlock = 999999999)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# End
|
# End
|
||||||
|
|
|
@ -5,7 +5,7 @@ import
|
||||||
|
|
||||||
const
|
const
|
||||||
baseDir = [".", "tests", ".."/"tests", $DirSep] # path containg repo
|
baseDir = [".", "tests", ".."/"tests", $DirSep] # path containg repo
|
||||||
repoDir = ["customgenesis", "status"] # alternative repo paths
|
repoDir = [".", "customgenesis"] # alternative repo paths
|
||||||
|
|
||||||
proc findFilePath(file: string): string =
|
proc findFilePath(file: string): string =
|
||||||
result = "?unknown?" / file
|
result = "?unknown?" / file
|
||||||
|
@ -56,9 +56,9 @@ proc customGenesisTest() =
|
||||||
check cg.config.cliquePeriod == 30
|
check cg.config.cliquePeriod == 30
|
||||||
check cg.config.cliqueEpoch == 30000
|
check cg.config.cliqueEpoch == 30000
|
||||||
|
|
||||||
test "kintsugi.json":
|
test "Devnet4.json (aka Kintsugi in all but chainId)":
|
||||||
var cg: NetworkParams
|
var cg: NetworkParams
|
||||||
check loadNetworkParams("kintsugi.json".findFilePath, cg)
|
check loadNetworkParams("devnet4.json".findFilePath, cg)
|
||||||
let h = cg.toGenesisHeader
|
let h = cg.toGenesisHeader
|
||||||
let stateRoot = "3b84f313bfd49c03cc94729ade2e0de220688f813c0c895a99bd46ecc9f45e1e".toDigest
|
let stateRoot = "3b84f313bfd49c03cc94729ade2e0de220688f813c0c895a99bd46ecc9f45e1e".toDigest
|
||||||
let genesisHash = "a28d8d73e087a01d09d8cb806f60863652f30b6b6dfa4e0157501ff07d422399".toDigest
|
let genesisHash = "a28d8d73e087a01d09d8cb806f60863652f30b6b6dfa4e0157501ff07d422399".toDigest
|
||||||
|
@ -66,6 +66,16 @@ proc customGenesisTest() =
|
||||||
check h.blockHash == genesisHash
|
check h.blockHash == genesisHash
|
||||||
check cg.config.poaEngine == false
|
check cg.config.poaEngine == false
|
||||||
|
|
||||||
|
test "Devnet5.json (aka Kiln in all but chainId and TTD)":
|
||||||
|
var cg: NetworkParams
|
||||||
|
check loadNetworkParams("devnet5.json".findFilePath, cg)
|
||||||
|
let h = cg.toGenesisHeader
|
||||||
|
let stateRoot = "52e628c7f35996ba5a0402d02b34535993c89ff7fc4c430b2763ada8554bee62".toDigest
|
||||||
|
let genesisHash = "51c7fe41be669f69c45c33a56982cbde405313342d9e2b00d7c91a7b284dd4f8".toDigest
|
||||||
|
check h.stateRoot == stateRoot
|
||||||
|
check h.blockHash == genesisHash
|
||||||
|
check cg.config.poaEngine == false
|
||||||
|
|
||||||
proc genesisMain*() =
|
proc genesisMain*() =
|
||||||
genesisTest()
|
genesisTest()
|
||||||
customGenesisTest()
|
customGenesisTest()
|
||||||
|
|
|
@ -10,14 +10,14 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[os, sequtils, strformat, strutils, times],
|
std/[os, sequtils, strformat, strutils, times],
|
||||||
./replay/gunzip,
|
./replay/[pp, gunzip],
|
||||||
../nimbus/utils/[pow, pow/pow_cache, pow/pow_dataset],
|
../nimbus/utils/[pow, pow/pow_cache, pow/pow_dataset],
|
||||||
eth/[common],
|
eth/[common],
|
||||||
unittest2
|
unittest2
|
||||||
|
|
||||||
const
|
const
|
||||||
baseDir = [".", "tests", ".." / "tests", $DirSep] # path containg repo
|
baseDir = [".", "tests", ".." / "tests", $DirSep] # path containg repo
|
||||||
repoDir = ["test_pow", "status"] # alternative repos
|
repoDir = ["replay"] # alternative repos
|
||||||
|
|
||||||
specsDump = "mainspecs2k.txt.gz"
|
specsDump = "mainspecs2k.txt.gz"
|
||||||
|
|
||||||
|
@ -25,45 +25,6 @@ const
|
||||||
# Helpers
|
# Helpers
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc ppMs*(elapsed: Duration): string =
|
|
||||||
result = $elapsed.inMilliSeconds
|
|
||||||
let ns = elapsed.inNanoSeconds mod 1_000_000
|
|
||||||
if ns != 0:
|
|
||||||
# to rounded deca milli seconds
|
|
||||||
let dm = (ns + 5_000i64) div 10_000i64
|
|
||||||
result &= &".{dm:02}"
|
|
||||||
result &= "ms"
|
|
||||||
|
|
||||||
proc ppSecs*(elapsed: Duration): string =
|
|
||||||
result = $elapsed.inSeconds
|
|
||||||
let ns = elapsed.inNanoseconds mod 1_000_000_000
|
|
||||||
if ns != 0:
|
|
||||||
# to rounded decs seconds
|
|
||||||
let ds = (ns + 5_000_000i64) div 10_000_000i64
|
|
||||||
result &= &".{ds:02}"
|
|
||||||
result &= "s"
|
|
||||||
|
|
||||||
proc toKMG*[T](s: T): string =
|
|
||||||
proc subst(s: var string; tag, new: string): bool =
|
|
||||||
if tag.len < s.len and s[s.len - tag.len ..< s.len] == tag:
|
|
||||||
s = s[0 ..< s.len - tag.len] & new
|
|
||||||
return true
|
|
||||||
result = $s
|
|
||||||
for w in [("000", "K"),("000K","M"),("000M","G"),("000G","T"),
|
|
||||||
("000T","P"),("000P","E"),("000E","Z"),("000Z","Y")]:
|
|
||||||
if not result.subst(w[0],w[1]):
|
|
||||||
return
|
|
||||||
|
|
||||||
template showElapsed*(noisy: bool; info: string; code: untyped) =
|
|
||||||
let start = getTime()
|
|
||||||
code
|
|
||||||
if noisy:
|
|
||||||
let elpd {.inject.} = getTime() - start
|
|
||||||
if 0 < elpd.inSeconds:
|
|
||||||
echo "*** ", info, &": {elpd.ppSecs:>4}"
|
|
||||||
else:
|
|
||||||
echo "*** ", info, &": {elpd.ppMs:>4}"
|
|
||||||
|
|
||||||
proc say*(noisy = false; pfx = "***"; args: varargs[string, `$`]) =
|
proc say*(noisy = false; pfx = "***"; args: varargs[string, `$`]) =
|
||||||
if noisy:
|
if noisy:
|
||||||
if args.len == 0:
|
if args.len == 0:
|
||||||
|
@ -73,13 +34,6 @@ proc say*(noisy = false; pfx = "***"; args: varargs[string, `$`]) =
|
||||||
else:
|
else:
|
||||||
echo pfx, args.toSeq.join
|
echo pfx, args.toSeq.join
|
||||||
|
|
||||||
proc pp*(a: BlockNonce): string =
|
|
||||||
a.mapIt(it.toHex(2)).join.toLowerAscii
|
|
||||||
|
|
||||||
proc pp*(a: Hash256): string =
|
|
||||||
a.data.mapIt(it.toHex(2)).join[24 .. 31].toLowerAscii
|
|
||||||
|
|
||||||
|
|
||||||
proc findFilePath(file: string): string =
|
proc findFilePath(file: string): string =
|
||||||
result = "?unknown?" / file
|
result = "?unknown?" / file
|
||||||
for dir in baseDir:
|
for dir in baseDir:
|
||||||
|
|
|
@ -29,8 +29,8 @@ type
|
||||||
const
|
const
|
||||||
prngSeed = 42
|
prngSeed = 42
|
||||||
|
|
||||||
baseDir = [".", "tests", ".." / "tests", $DirSep] # path containg repo
|
baseDir = [".", "..", ".."/"..", $DirSep]
|
||||||
repoDir = ["replay", "status"] # alternative repos
|
repoDir = [".", "tests"/"replay", "nimbus-eth1-blobs"/"replay"]
|
||||||
|
|
||||||
goerliCapture: CaptureSpecs = (
|
goerliCapture: CaptureSpecs = (
|
||||||
network: GoerliNet,
|
network: GoerliNet,
|
||||||
|
@ -134,6 +134,16 @@ proc findFilePath(file: string): string =
|
||||||
if path.fileExists:
|
if path.fileExists:
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
proc setTraceLevel =
|
||||||
|
discard
|
||||||
|
when defined(chronicles_runtime_filtering) and loggingEnabled:
|
||||||
|
setLogLevel(LogLevel.TRACE)
|
||||||
|
|
||||||
|
proc setErrorLevel =
|
||||||
|
discard
|
||||||
|
when defined(chronicles_runtime_filtering) and loggingEnabled:
|
||||||
|
setLogLevel(LogLevel.ERROR)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Test Runners
|
# Test Runners
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
@ -894,11 +904,13 @@ when isMainModule:
|
||||||
const
|
const
|
||||||
noisy = defined(debug)
|
noisy = defined(debug)
|
||||||
capts0: CaptureSpecs = goerliCapture
|
capts0: CaptureSpecs = goerliCapture
|
||||||
capts1: CaptureSpecs = (GoerliNet, "goerli504192.txt.gz", 30000, 500, 1500)
|
capts1: CaptureSpecs = (GoerliNet, "goerli482304.txt.gz", 30000, 500, 1500)
|
||||||
# Note: mainnet has the leading 45k blocks without any transactions
|
# Note: mainnet has the leading 45k blocks without any transactions
|
||||||
capts2: CaptureSpecs = (MainNet, "mainnet843841.txt.gz", 30000, 500, 1500)
|
capts2: CaptureSpecs = (MainNet, "mainnet332160.txt.gz", 30000, 500, 1500)
|
||||||
|
|
||||||
noisy.runTxLoader(capture = capts2)
|
setErrorLevel()
|
||||||
|
|
||||||
|
noisy.runTxLoader(capture = capts1)
|
||||||
noisy.runTxPoolTests
|
noisy.runTxPoolTests
|
||||||
true.runTxPackerTests
|
true.runTxPackerTests
|
||||||
|
|
||||||
|
|
|
@ -186,16 +186,6 @@ proc isOK*(rc: ValidationResult): bool =
|
||||||
proc toHex*(acc: EthAddress): string =
|
proc toHex*(acc: EthAddress): string =
|
||||||
acc.toSeq.mapIt(it.toHex(2)).join
|
acc.toSeq.mapIt(it.toHex(2)).join
|
||||||
|
|
||||||
template showElapsed*(noisy: bool; info: string; code: untyped) =
|
|
||||||
let start = getTime()
|
|
||||||
code
|
|
||||||
if noisy:
|
|
||||||
let elpd {.inject.} = getTime() - start
|
|
||||||
if 0 < elpd.inSeconds:
|
|
||||||
echo "*** ", info, &": {elpd.ppSecs:>4}"
|
|
||||||
else:
|
|
||||||
echo "*** ", info, &": {elpd.ppMs:>4}"
|
|
||||||
|
|
||||||
proc say*(noisy = false; pfx = "***"; args: varargs[string, `$`]) =
|
proc say*(noisy = false; pfx = "***"; args: varargs[string, `$`]) =
|
||||||
if noisy:
|
if noisy:
|
||||||
if args.len == 0:
|
if args.len == 0:
|
||||||
|
|
Loading…
Reference in New Issue