maintenance update

why:
  some handy features were intended to support the unit test from
  the clique/clique_test.go source (the other one is from
  clique/snapshot_test.go.)
  as this test cannot realistically be implemented without the full
  api (includes mining support), it is left as that
This commit is contained in:
Jordan Hrycaj 2021-06-16 16:12:51 +01:00 committed by Jordan Hrycaj
parent 90b012ad3f
commit 82e6cd991d
5 changed files with 105 additions and 58 deletions

View File

@ -230,7 +230,7 @@ proc setDebug*(rs: var RecentSnaps; debug: bool) =
proc getRecentSnaps*(rs: var RecentSnaps; args: RecentArgs): auto {.
gcsafe, raises: [Defect,CatchableError].} =
## Get snapshot from cache or disk
rs.say "getRecentSnap #", args.blockNumber.truncate(uint64)
rs.say "getRecentSnap #", args.blockNumber
rs.cache.getLruItem:
RecentDesc(cfg: rs.cfg,
debug: rs.debug,

View File

@ -74,7 +74,6 @@ proc getPrettyPrinters(s: var Snapshot): var PrettyPrinters =
proc pp(s: var Snapshot; h: var AddressHistory): string =
ppExceptionWrap:
toSeq(h.keys)
.mapIt(it.truncate(uint64))
.sorted
.mapIt("#" & $it & ":" & s.pp(h[it.u256]))
.join(",")
@ -85,7 +84,7 @@ proc pp(s: var Snapshot; v: Vote): string =
ppExceptionWrap:
"(" & &"address={s.pp(v.address)}" &
&",signer={s.pp(v.signer)}" &
&",blockNumber={v.blockNumber.truncate(uint64)}" &
&",blockNumber={v.blockNumber}" &
&",{authorized(v.authorize)}" & ")"
proc votesList(s: var Snapshot; sep: string): string =
@ -234,7 +233,7 @@ proc applySnapshot*(s: var Snapshot;
header = headers[headersIndex]
number = header.blockNumber
s.say "applySnapshot processing #", number.truncate(uint64)
s.say "applySnapshot processing #", number
# Remove any votes on checkpoint blocks
if (number mod s.cfg.epoch) == 0:

View File

@ -17,6 +17,7 @@ import
stint,
unittest2
# clique/snapshot_test.go(99): func TestClique(t *testing.T) {
proc cliqueMain*(noisy = defined(debug)) =
## Clique PoA Snapshot
@ -27,12 +28,11 @@ proc cliqueMain*(noisy = defined(debug)) =
##
suite "Clique PoA Snapshot":
var
pool = newTesterPool()
pool = newVoterPool().setDebug(noisy)
const
skipSet = {999}
testSet = {0 .. 999}
pool.setDebug(noisy)
# clique/snapshot_test.go(379): for i, tt := range tests {
for tt in voterSamples.filterIt(it.id in testSet):
@ -45,12 +45,11 @@ proc cliqueMain*(noisy = defined(debug)) =
else:
# Assemble a chain of headers from the cast votes
# see clique/snapshot_test.go(407): config := *params.TestChainConfig
pool.resetVoterChain(tt.signers, tt.epoch)
# see clique/snapshot_test.go(425): for j, block := range blocks {
for voter in tt.votes:
pool.appendVoter(voter)
pool.commitVoterChain
pool
.resetVoterChain(tt.signers, tt.epoch)
# see clique/snapshot_test.go(425): for j, block := range blocks {
.appendVoter(tt.votes)
.commitVoterChain
# see clique/snapshot_test.go(476): snap, err := engine.snapshot( [..]
let topHeader = pool.topVoterHeader

View File

@ -51,19 +51,18 @@ type
# Private Helpers
# ------------------------------------------------------------------------------
proc bespokeGenesis(file: string): CustomGenesis =
## Find genesis block
if file == "":
let networkId = getConfiguration().net.networkId
result.genesis = defaultGenesisBlockForNetwork(networkId)
else:
doAssert file.loadCustomGenesis(result)
result.config.poaEngine = true
proc chain(ap: TesterPool): BaseChainDB =
## Getter
ap.engine.cfgInternal.dbChain
proc getBlockHeader(ap: TesterPool; number: BlockNumber): BlockHeader =
## Shortcut => db/db_chain.getBlockHeader()
doAssert ap.chain.getBlockHeader(number, result)
proc getBlockHeader(ap: TesterPool; hash: Hash256): BlockHeader =
## Shortcut => db/db_chain.getBlockHeader()
doAssert ap.chain.getBlockHeader(hash, result)
proc isZero(a: openArray[byte]): bool =
result = true
for w in a:
@ -189,12 +188,32 @@ proc ppBlockHeader(ap: TesterPool; v: BlockHeader; delim: string): string =
&"{sep}nonce={ap.ppNonce(v.nonce)}" &
&"{sep}extraData={ap.ppExtraData(v.extraData)})"
# ------------------------------------------------------------------------------
# Private: Constructor helpers
# ------------------------------------------------------------------------------
proc initPrettyPrinters(pp: var PrettyPrinters; ap: TesterPool) =
pp.nonce = proc(v:BlockNonce): string = ap.ppNonce(v)
pp.address = proc(v:EthAddress): string = ap.ppAddress(v)
pp.extraData = proc(v:Blob): string = ap.ppExtraData(v)
pp.blockHeader = proc(v:BlockHeader; d:string): string = ap.ppBlockHeader(v,d)
proc initTesterPool(ap: TesterPool): TesterPool {.discardable.} =
result = ap
result.boot.config.poaEngine = true
result.prng = initRand(prngSeed)
result.batch = @[newSeq[BlockHeader]()]
result.accounts = initTable[string,PrivateKey]()
result.xSeals = initTable[XSealKey,XSealValue]()
result.names = initTable[EthAddress,string]()
result.engine = newCliqueCfg(
dbChain = BaseChainDB(),
period = initDuration(seconds = 1))
.initClique
result.engine.setDebug(false)
result.engine.cfgInternal.prettyPrint.initPrettyPrinters(result)
result.resetChainDb(@[])
# ------------------------------------------------------------------------------
# Public functions
# ------------------------------------------------------------------------------
@ -203,33 +222,26 @@ proc getPrettyPrinters*(t: TesterPool): var PrettyPrinters =
## Mixin for pretty printers, see `clique/clique_cfg.pp()`
t.engine.cfgInternal.prettyPrint
proc setDebug*(ap: TesterPool; debug=true): TesterPool {.inline,discardable,} =
## Set debugging mode on/off
result = ap
ap.debug = debug
ap.engine.setDebug(debug)
proc say*(t: TesterPool; v: varargs[string,`$`]) =
if t.debug:
stderr.write v.join & "\n"
proc newTesterPool*(epoch = 0.u256; genesisTemplate = ""): TesterPool =
new result
result.boot = genesisTemplate.bespokeGenesis
result.prng = initRand(prngSeed)
result.batch = @[newSeq[BlockHeader]()]
result.accounts = initTable[string,PrivateKey]()
result.xSeals = initTable[XSealKey,XSealValue]()
result.names = initTable[EthAddress,string]()
result.engine = newCliqueCfg(
dbChain = BaseChainDB(),
period = initDuration(seconds = 1),
epoch = epoch)
.initClique
result.engine.setDebug(false)
result.engine.cfgInternal.prettyPrint.initPrettyPrinters(result)
result.resetChainDb(@[])
proc setDebug*(ap: TesterPool; debug = true) =
## Set debugging mode on/off
ap.debug = debug
ap.engine.setDebug(debug)
proc sayHeaderChain*(ap: TesterPool; indent = 0): TesterPool {.discardable.} =
result = ap
let pfx = ' '.repeat(indent)
var top = if 0 < ap.batch[^1].len: ap.batch[^1][^1]
else: ap.getBlockHeader(0.u256)
ap.say pfx, " top header: " & ap.pp(top, 16+indent)
while not top.blockNumber.isZero:
top = ap.getBlockHeader(top.parentHash)
ap.say pfx, "parent header: " & ap.pp(top, 16+indent)
# clique/snapshot_test.go(62): func (ap *testerAccountPool) address(account [..]
@ -277,13 +289,9 @@ proc snapshot*(ap: TesterPool; number: BlockNumber; hash: Hash256;
parent: openArray[BlockHeader]): auto =
## Call p2p/clique.snapshotInternal()
if ap.debug:
var header = ap.chain.getBlockHeader(number)
ap.say "*** snapshot argument: ", ap.pp(header,24)
while true:
doAssert ap.chain.getBlockHeader(header.parentHash,header)
ap.say " parent header: ", ap.pp(header,24)
if header.blockNumber.isZero:
break
var header = ap.getBlockHeader(number)
ap.say "*** snapshot argument: #", number
ap.sayHeaderChain(8)
when false: # all addresses are typically pp-mappable
ap.say " address map: ", toSeq(ap.names.pairs)
.mapIt(&"@{it[1]}:{it[0]}")
@ -292,13 +300,41 @@ proc snapshot*(ap: TesterPool; number: BlockNumber; hash: Hash256;
ap.engine.snapshotInternal(number, hash, parent)
# ------------------------------------------------------------------------------
# Public: Constructor
# ------------------------------------------------------------------------------
proc newVoterPool*(genesisTemplate = ""): TesterPool =
new result
if genesisTemplate == "":
let networkId = getConfiguration().net.networkId
result.boot.genesis = defaultGenesisBlockForNetwork(networkId)
else:
# Find genesis block
doAssert genesisTemplate.loadCustomGenesis(result.boot)
result.initTesterPool
proc newVoterPool*(customGenesis: CustomGenesis): TesterPool =
TesterPool(boot: customGenesis).initTesterPool
# ------------------------------------------------------------------------------
# Public: set up & manage voter database
# ------------------------------------------------------------------------------
proc resetVoterChain*(ap: TesterPool;
signers: openArray[string]; epoch: uint64) =
proc setVoterAccount*(ap: TesterPool; account: string;
prvKey: PrivateKey): TesterPool {.discardable.} =
## Manually define/import account
result = ap
ap.accounts[account] = prvKey
let address = prvKey.toPublicKey.toCanonicalAddress
ap.names[address] = account
proc resetVoterChain*(ap: TesterPool; signers: openArray[string];
epoch = 0): TesterPool {.discardable.} =
## Reset the batch list for voter headers and update genesis block
result = ap
ap.batch = @[newSeq[BlockHeader]()]
# clique/snapshot_test.go(384): signers := make([]common.Address, [..]
@ -315,15 +351,18 @@ proc resetVoterChain*(ap: TesterPool;
# store modified genesis block and epoch
ap.resetChainDb(extraData)
ap.engine.cfgInternal.epoch = epoch
ap.engine.cfgInternal.epoch = epoch.uint
# clique/snapshot_test.go(415): blocks, _ := core.GenerateChain(&config, [..]
proc appendVoter*(ap: TesterPool; voter: TesterVote) =
proc appendVoter*(ap: TesterPool;
voter: TesterVote): TesterPool {.discardable.} =
## Append a voter header to the block chain batch list
result = ap
doAssert 0 < ap.batch.len # see initTesterPool() and resetVoterChain()
let parent = if ap.batch[^1].len == 0:
ap.chain.getBlockHeader(0.u256)
ap.getBlockHeader(0.u256)
else:
ap.batch[^1][^1]
@ -361,8 +400,18 @@ proc appendVoter*(ap: TesterPool; voter: TesterVote) =
ap.batch[^1].add header
proc commitVoterChain*(ap: TesterPool) =
proc appendVoter*(ap: TesterPool;
voters: openArray[TesterVote]): TesterPool {.discardable.} =
## Append a list of voter headers to the block chain batch list
result = ap
for voter in voters:
ap.appendVoter(voter)
proc commitVoterChain*(ap: TesterPool): TesterPool {.discardable.} =
## Write the headers from the voter header batch list to the block chain DB
result = ap
# Create a pristine blockchain with the genesis injected
for headers in ap.batch:
if 0 < headers.len:

View File

@ -29,7 +29,7 @@ type
TestSpecs* = object ## Define the various voting scenarios to test
id*: int ## Test id
info*: string ## Test description
epoch*: uint64 ## Number of blocks in an epoch (unset = 30000)
epoch*: int ## Number of blocks in an epoch (unset = 30000)
signers*: seq[string] ## Initial list of authorized signers in the
## genesis
votes*: seq[TesterVote] ## Chain of signed blocks, potentially influencing