nimbus-eth1/tests/test_pow.nim

161 lines
5.4 KiB
Nim
Raw Permalink Normal View History

# Nimbus
Core db and aristo updates for destructor and tx logic (#1894) * Disable `TransactionID` related functions from `state_db.nim` why: Functions `getCommittedStorage()` and `updateOriginalRoot()` from the `state_db` module are nowhere used. The emulation of a legacy `TransactionID` type functionality is administratively expensive to provide by `Aristo` (the legacy DB version is only partially implemented, anyway). As there is no other place where `TransactionID`s are used, they will not be provided by the `Aristo` variant of the `CoreDb`. For the legacy DB API, nothing will change. * Fix copyright headers in source code * Get rid of compiler warning * Update Aristo code, remove unused `merge()` variant, export `hashify()` why: Adapt to upcoming `CoreDb` wrapper * Remove synced tx feature from `Aristo` why: + This feature allowed to synchronise transaction methods like begin, commit, and rollback for a group of descriptors. + The feature is over engineered and not needed for `CoreDb`, neither is it complete (some convergence features missing.) * Add debugging helpers to `Kvt` also: Update database iterator, add count variable yield argument similar to `Aristo`. * Provide optional destructors for `CoreDb` API why; For the upcoming Aristo wrapper, this allows to control when certain smart destruction and update can take place. The auto destructor works fine in general when the storage/cache strategy is known and acceptable when creating descriptors. * Add update option for `CoreDb` API function `hash()` why; The hash function is typically used to get the state root of the MPT. Due to lazy hashing, this might be not available on the `Aristo` DB. So the `update` function asks for re-hashing the gurrent state changes if needed. * Update API tracking log mode: `info` => `debug * Use shared `Kvt` descriptor in new Ledger API why: No need to create a new descriptor all the time
2023-11-16 19:35:03 +00:00
# Copyright (c) 2022-2023 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.
import
std/[os, sequtils, strformat, strutils, times],
./replay/[pp, gunzip],
2022-12-02 04:39:12 +00:00
../nimbus/core/[pow, pow/pow_cache, pow/pow_dataset],
eth/[common],
stew/endians2,
unittest2
const
baseDir = [".", "tests", ".." / "tests", $DirSep] # path containg repo
repoDir = ["replay"] # alternative repos
specsDump = "mainspecs2k.txt.gz"
# ------------------------------------------------------------------------------
# Helpers
# ------------------------------------------------------------------------------
proc say*(noisy = false; pfx = "***"; args: varargs[string, `$`]) =
if noisy:
if args.len == 0:
echo "*** ", pfx
elif 0 < pfx.len and pfx[^1] != ' ':
echo pfx, " ", args.toSeq.join
else:
echo pfx, args.toSeq.join
proc findFilePath(file: string): string =
result = "?unknown?" / file
for dir in baseDir:
for repo in repoDir:
let path = dir / repo / file
if path.fileExists:
return path
# ------------------------------------------------------------------------------
# Test Runners
# ------------------------------------------------------------------------------
proc runPowTests(noisy = true; file = specsDump;
nVerify = int.high; nFakeMiner = 0, nRealMiner = 0) =
let
filePath = file.findFilePath
fileInfo = file.splitFile.name.split(".")[0]
powCache = PowCacheRef.new # so we can inspect the LRU caches
powDataset = PowDatasetRef.new(cache = powCache)
pow = PowRef.new(powCache, powDataset)
var
specsList: seq[PowSpecs]
suite &"PoW: Header test specs from {fileInfo} capture":
block:
test "Loading from capture":
for (lno,line) in gunzipLines(filePath):
let specs = line.undumpPowSpecs
if 0 < specs.blockNumber:
specsList.add specs
check line == specs.dumpPowSpecs
noisy.say "***", " block range #",
specsList[0].blockNumber, " .. #", specsList[^1].blockNumber
# Adjust number of tests
let
startVerify = max(0, specsList.len - nVerify)
startFakeMiner = max(0, specsList.len - nFakeMiner)
startRealMiner = max(0, specsList.len - nRealMiner)
nDoVerify = specsList.len - startVerify
nDoFakeMiner = specsList.len - startFakeMiner
nDoRealMiner = specsList.len - startRealMiner
backStep = 1u64 shl 11
block:
test &"Running single getPowDigest() to fill the cache":
if nVerify <= 0:
skip()
else:
noisy.showElapsed(&"first getPowDigest() instance"):
let p = specsList[startVerify]
check pow.getPowDigest(p).mixDigest == p.mixDigest
test &"Running getPowDigest() on {nDoVerify} specs records":
if nVerify <= 0:
skip()
else:
noisy.showElapsed(&"all {nDoVerify} getPowDigest() instances"):
for n in startVerify ..< specsList.len:
let p = specsList[n]
check pow.getPowDigest(p).mixDigest == p.mixDigest
test &"Generate PoW mining dataset (slow proocess)":
if nDoFakeMiner <= 0 and nRealMiner <= 0:
skip()
else:
noisy.showElapsed "generate PoW dataset":
pow.generatePowDataset(specsList[startFakeMiner].blockNumber)
test &"Running getNonce() on {nDoFakeMiner} instances with start" &
&" nonce {backStep} before result":
if nDoFakeMiner <= 0:
skip()
else:
noisy.showElapsed &"all {nDoFakeMiner} getNonce() instances":
for n in startFakeMiner ..< specsList.len:
let
p = specsList[n]
nonce = toBytesBE(uint64.fromBytesBE(p.nonce) - backStep)
check pow.getNonce(
p.blockNumber, p.miningHash, p.difficulty, nonce) == p.nonce
test &"Running getNonce() mining function" &
&" on {nDoRealMiner} specs records":
if nRealMiner <= 0:
skip()
else:
for n in startRealMiner ..< specsList.len:
let p = specsList[n]
noisy.say "***", " #", p.blockNumber, " needs ", p.nonce.pp
noisy.showElapsed("getNonce()"):
let nonce = pow.getNonce(p)
noisy.say "***", " got ", nonce.pp,
" after ", pow.nGetNonce, " attempts"
if nonce != p.nonce:
var q = p
q.nonce = nonce
check pow.getPowDigest(q).mixDigest == p.mixDigest
# ------------------------------------------------------------------------------
# Main function(s)
# ------------------------------------------------------------------------------
proc powMain*(noisy = defined(debug)) =
noisy.runPowTests(nVerify = 100)
when isMainModule:
# Note:
# 0 < nFakeMiner: allow ~20 minuntes for building lookup table
# 0 < nRealMiner: takes days/months/years ...
true.runPowTests(nVerify = 200, nFakeMiner = 200, nRealMiner = 5)
# ------------------------------------------------------------------------------
# End
# ------------------------------------------------------------------------------