Merge pull request #516 from status-im/validate_block_witness

syncing with PoA chain
This commit is contained in:
andri lim 2020-06-22 11:56:56 +07:00 committed by GitHub
commit 6ea488e037
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 256 additions and 62 deletions

View File

@ -33,6 +33,7 @@ type
trie: SecureHexaryTrie
savePoint: SavePoint
witnessCache: Table[EthAddress, WitnessData]
isDirty: bool
ReadOnlyStateDB* = distinct AccountsCache
@ -46,7 +47,17 @@ type
cache: Table[EthAddress, RefAccount]
state: TransactionState
const emptyAcc = newAccount()
const
emptyAcc = newAccount()
resetFlags = {
IsDirty,
IsNew,
IsTouched,
IsClone,
CodeChanged,
StorageChanged
}
proc beginSavepoint*(ac: var AccountsCache): SavePoint {.gcsafe.}
@ -66,7 +77,7 @@ proc rootHash*(ac: AccountsCache): KeccakHash =
# make sure all savepoint already committed
doAssert(ac.savePoint.parentSavePoint.isNil)
# make sure all cache already committed
doAssert(ac.savePoint.cache.len == 0)
doAssert(ac.isDirty == false)
ac.trie.rootHash
proc beginSavepoint*(ac: var AccountsCache): SavePoint =
@ -222,14 +233,20 @@ proc persistMode(acc: RefAccount): PersistMode =
proc persistCode(acc: RefAccount, db: TrieDatabaseRef) =
if acc.code.len != 0:
db.put(contractHashKey(acc.account.codeHash).toOpenArray, acc.code)
when defined(geth):
db.put(acc.account.codeHash.data, acc.code)
else:
db.put(contractHashKey(acc.account.codeHash).toOpenArray, acc.code)
proc persistStorage(acc: RefAccount, db: TrieDatabaseRef) =
proc persistStorage(acc: RefAccount, db: TrieDatabaseRef, clearCache: bool) =
if acc.overlayStorage.len == 0:
# TODO: remove the storage too if we figure out
# how to create 'virtual' storage room for each account
return
if not clearCache and acc.originalStorage.isNil:
acc.originalStorage = newTable[UInt256, UInt256]()
var accountTrie = getAccountTrie(db, acc)
for slot, value in acc.overlayStorage:
@ -246,9 +263,21 @@ proc persistStorage(acc: RefAccount, db: TrieDatabaseRef) =
# slotHash can be obtained from accountTrie.put?
let slotHash = keccakHash(slotAsKey)
db.put(slotHashToSlotKey(slotHash.data).toOpenArray, rlp.encode(slot))
if not clearCache:
# if we preserve cache, move the overlayStorage
# to originalStorage, related to EIP2200, EIP1283
for slot, value in acc.overlayStorage:
if value > 0:
acc.originalStorage[slot] = value
else:
acc.originalStorage.del(slot)
acc.overlayStorage.clear()
acc.account.storageRoot = accountTrie.rootHash
proc makeDirty(ac: AccountsCache, address: EthAddress, cloneStorage = true): RefAccount =
ac.isDirty = true
result = ac.getAccount(address)
if address in ac.savePoint.cache:
# it's already in latest savepoint
@ -283,7 +312,11 @@ proc getCode*(ac: AccountsCache, address: EthAddress): seq[byte] =
if CodeLoaded in acc.flags or CodeChanged in acc.flags:
result = acc.code
else:
let data = ac.db.get(contractHashKey(acc.account.codeHash).toOpenArray)
when defined(geth):
let data = ac.db.get(acc.account.codeHash.data)
else:
let data = ac.db.get(contractHashKey(acc.account.codeHash).toOpenArray)
acc.code = data
acc.flags.incl CodeLoaded
result = acc.code
@ -384,9 +417,11 @@ proc deleteAccount*(ac: var AccountsCache, address: EthAddress) =
let acc = ac.getAccount(address)
acc.kill()
proc persist*(ac: var AccountsCache) =
proc persist*(ac: var AccountsCache, clearCache: bool = true) =
# make sure all savepoint already committed
doAssert(ac.savePoint.parentSavePoint.isNil)
var cleanAccounts = initHashSet[EthAddress]()
for address, acc in ac.savePoint.cache:
case acc.persistMode()
of Update:
@ -395,13 +430,24 @@ proc persist*(ac: var AccountsCache) =
if StorageChanged in acc.flags:
# storageRoot must be updated first
# before persisting account into merkle trie
acc.persistStorage(ac.db)
acc.persistStorage(ac.db, clearCache)
ac.trie.put address, rlp.encode(acc.account)
of Remove:
ac.trie.del address
if not clearCache:
#
cleanAccounts.incl address
of DoNothing:
discard
ac.savePoint.cache.clear()
acc.flags = acc.flags - resetFlags
if clearCache:
ac.savePoint.cache.clear()
else:
for x in cleanAccounts:
ac.savePoint.cache.del x
ac.isDirty = false
iterator storage*(ac: AccountsCache, address: EthAddress): (UInt256, UInt256) =
# beware that if the account not persisted,
@ -411,10 +457,11 @@ iterator storage*(ac: AccountsCache, address: EthAddress): (UInt256, UInt256) =
let storageRoot = acc.account.storageRoot
var trie = initHexaryTrie(ac.db, storageRoot)
for slot, value in trie:
if slot.len != 0:
var keyData = ac.db.get(slotHashToSlotKey(slot).toOpenArray)
yield (rlp.decode(keyData, UInt256), rlp.decode(value, UInt256))
for slotHash, value in trie:
if slotHash.len == 0: continue
let keyData = ac.db.get(slotHashToSlotKey(slotHash).toOpenArray)
if keyData.len == 0: continue
yield (rlp.decode(keyData, UInt256), rlp.decode(value, UInt256))
proc getStorageRoot*(ac: AccountsCache, address: EthAddress): Hash256 =
# beware that if the account not persisted,

35
nimbus/db/geth_db.nim Normal file
View File

@ -0,0 +1,35 @@
import eth/[rlp, common], db_chain, eth/trie/db
const
headerPrefix = 'h'.byte # headerPrefix + num (uint64 big endian) + hash -> header
headerHashSuffix = 'n'.byte # headerPrefix + num (uint64 big endian) + headerHashSuffix -> hash
blockBodyPrefix = 'b'.byte # blockBodyPrefix + num (uint64 big endian) + hash -> block body
proc headerHash*(db: BaseChainDB, number: uint64): Hash256 =
var key: array[10, byte]
key[0] = headerPrefix
key[1..8] = toBytesBE(number)[0..^1]
key[^1] = headerHashSuffix
let res = db.db.get(key)
doAssert(res.len == 32)
result.data[0..31] = res[0..31]
proc blockHeader*(db: BaseChainDB, hash: Hash256, number: uint64): BlockHeader =
var key: array[41, byte]
key[0] = headerPrefix
key[1..8] = toBytesBE(number)[0..^1]
key[9..40] = hash.data[0..^1]
let res = db.db.get(key)
result = rlp.decode(res, BlockHeader)
proc blockHeader*(db: BaseChainDB, number: uint64): BlockHeader =
let hash = db.headerHash(number)
db.blockHeader(hash, number)
proc blockBody*(db: BaseChainDB, hash: Hash256, number: uint64): BlockBody =
var key: array[41, byte]
key[0] = blockBodyPrefix
key[1..8] = toBytesBE(number)[0..^1]
key[9..40] = hash.data[0..^1]
let res = db.db.get(key)
result = rlp.decode(res, BlockBody)

View File

@ -36,7 +36,7 @@ method getAncestorHeader*(c: Chain, h: BlockHeader, output: var BlockHeader, ski
method getBlockBody*(c: Chain, blockHash: KeccakHash): BlockBodyRef =
result = nil
method persistBlocks*(c: Chain, headers: openarray[BlockHeader], bodies: openarray[BlockBody]): ValidationResult =
method persistBlocks*(c: Chain, headers: openarray[BlockHeader], bodies: openarray[BlockBody]): ValidationResult {.gcsafe.} =
# Run the VM here
if headers.len != bodies.len:
debug "Number of headers not matching number of bodies"

View File

@ -26,16 +26,18 @@ proc processTransaction*(tx: Transaction, sender: EthAddress, vmState: BaseVMSta
vmState.cumulativeGasUsed += result
let miner = vmState.coinbase()
vmState.mutateStateDB:
# miner fee
let txFee = result.u256 * tx.gasPrice.u256
db.addBalance(vmState.blockHeader.coinbase, txFee)
db.addBalance(miner, txFee)
for deletedAccount in vmState.suicides:
db.deleteAccount deletedAccount
if fork >= FkSpurious:
vmState.touchedAccounts.incl(vmState.blockHeader.coinbase)
vmState.touchedAccounts.incl(miner)
# EIP158/161 state clearing
for account in vmState.touchedAccounts:
if db.accountExists(account) and db.isEmptyAccount(account):
@ -44,7 +46,7 @@ proc processTransaction*(tx: Transaction, sender: EthAddress, vmState: BaseVMSta
if vmState.generateWitness:
vmState.accountDb.collectWitnessData()
vmState.accountDb.persist()
vmState.accountDb.persist(clearCache = false)
type
# TODO: these types need to be removed
@ -93,6 +95,25 @@ const
eth2 # FkIstanbul
]
proc calculateReward(fork: Fork, header: BlockHeader, body: BlockBody, vmState: BaseVMState) =
# PoA consensus engine have no reward for miner
if vmState.consensusEnginePoA: return
let blockReward = blockRewards[fork]
var mainReward = blockReward
for uncle in body.uncles:
var uncleReward = uncle.blockNumber.u256 + 8.u256
uncleReward -= header.blockNumber.u256
uncleReward = uncleReward * blockReward
uncleReward = uncleReward div 8.u256
vmState.mutateStateDB:
db.addBalance(uncle.coinbase, uncleReward)
mainReward += blockReward div 32.u256
vmState.mutateStateDB:
db.addBalance(header.coinbase, mainReward)
proc processBlock*(chainDB: BaseChainDB, header: BlockHeader, body: BlockBody, vmState: BaseVMState): ValidationResult =
var dbTx = chainDB.db.beginTransaction()
defer: dbTx.dispose()
@ -125,32 +146,26 @@ proc processBlock*(chainDB: BaseChainDB, header: BlockHeader, body: BlockBody, v
return ValidationResult.Error
vmState.receipts[txIndex] = makeReceipt(vmState, fork)
let blockReward = blockRewards[fork]
var mainReward = blockReward
if header.ommersHash != EMPTY_UNCLE_HASH:
let h = chainDB.persistUncles(body.uncles)
if h != header.ommersHash:
debug "Uncle hash mismatch"
return ValidationResult.Error
for uncle in body.uncles:
var uncleReward = uncle.blockNumber.u256 + 8.u256
uncleReward -= header.blockNumber.u256
uncleReward = uncleReward * blockReward
uncleReward = uncleReward div 8.u256
vmState.mutateStateDB:
db.addBalance(uncle.coinbase, uncleReward)
mainReward += blockReward div 32.u256
calculateReward(fork, header, body, vmState)
# Reward beneficiary
vmState.mutateStateDB:
db.addBalance(header.coinbase, mainReward)
if vmState.generateWitness:
db.collectWitnessData()
db.persist()
db.persist(ClearCache in vmState.flags)
let stateDb = vmState.accountDb
if header.stateRoot != stateDb.rootHash:
error "Wrong state root in block", blockNumber=header.blockNumber, expected=header.stateRoot, actual=stateDb.rootHash, arrivedFrom=chainDB.getCanonicalHead().stateRoot
when defined(geth):
error "Wrong state root in block", blockNumber=header.blockNumber, expected=header.stateRoot, actual=stateDb.rootHash
else:
error "Wrong state root in block", blockNumber=header.blockNumber, expected=header.stateRoot, actual=stateDb.rootHash, arrivedFrom=chainDB.getCanonicalHead().stateRoot
# this one is a show stopper until we are confident in our VM's
# compatibility with the main chain
return ValidationResult.Error

View File

@ -86,11 +86,10 @@ proc binarySearchGas(vmState: var BaseVMState, transaction: Transaction, sender:
proc setupEthRpc*(node: EthereumNode, chain: BaseChainDB, rpcsrv: RpcServer) =
func getAccountDb(header: BlockHeader): ReadOnlyStateDB =
proc getAccountDb(header: BlockHeader): ReadOnlyStateDB =
## Retrieves the account db from canonical head
# TODO: header.stateRoot to prevStateRoot
let vmState = newBaseVMState(header.stateRoot, header, chain)
result = vmState.readOnlyStateDB()
let ac = AccountsCache.init(chain.db, header.stateRoot, chain.pruneTrie)
result = ReadOnlyStateDB(ac)
proc accountDbFromTag(tag: string, readOnly = true): ReadOnlyStateDB =
result = getAccountDb(chain.headerFromTag(tag))

View File

@ -5,8 +5,15 @@ import
chronicles, rpc/hexstrings, launcher,
vm/interpreter/vm_forks, ./config
proc getParentHeader(self: BaseChainDB, header: BlockHeader): BlockHeader =
self.getBlockHeader(header.parentHash)
when defined(geth):
import db/geth_db
proc getParentHeader(db: BaseChainDB, header: BlockHeader): BlockHeader =
db.blockHeader(header.blockNumber.truncate(uint64) - 1)
else:
proc getParentHeader(self: BaseChainDB, header: BlockHeader): BlockHeader =
self.getBlockHeader(header.parentHash)
proc `%`(x: openArray[byte]): JsonNode =
result = %toHex(x, false)
@ -80,7 +87,7 @@ proc traceTransaction*(chainDB: BaseChainDB, header: BlockHeader,
memoryDB = newMemoryDB()
captureDB = newCaptureDB(chainDB.db, memoryDB)
captureTrieDB = trieDB captureDB
captureChainDB = newBaseChainDB(captureTrieDB, false) # prune or not prune?
captureChainDB = newBaseChainDB(captureTrieDB, false, PublicNetWork(chainDB.config.chainId)) # prune or not prune?
vmState = newBaseVMState(parent.stateRoot, header, captureChainDB, tracerFlags + {EnableAccount})
var stateDb = vmState.accountDb
@ -96,7 +103,9 @@ proc traceTransaction*(chainDB: BaseChainDB, header: BlockHeader,
stateDiff = %{"before": before, "after": after}
beforeRoot: Hash256
let fork = chainDB.config.toFork(header.blockNumber)
let
fork = chainDB.config.toFork(header.blockNumber)
miner = vmState.coinbase()
for idx, tx in body.transactions:
let sender = tx.getSender
@ -106,7 +115,7 @@ proc traceTransaction*(chainDB: BaseChainDB, header: BlockHeader,
vmState.enableTracing()
before.captureAccount(stateDb, sender, senderName)
before.captureAccount(stateDb, recipient, recipientName)
before.captureAccount(stateDb, header.coinbase, minerName)
before.captureAccount(stateDb, miner, minerName)
stateDb.persist()
stateDiff["beforeRoot"] = %($stateDb.rootHash)
beforeRoot = stateDb.rootHash
@ -116,8 +125,8 @@ proc traceTransaction*(chainDB: BaseChainDB, header: BlockHeader,
if idx == txIndex:
after.captureAccount(stateDb, sender, senderName)
after.captureAccount(stateDb, recipient, recipientName)
after.captureAccount(stateDb, header.coinbase, minerName)
vmState.removeTracedAccounts(sender, recipient, header.coinbase)
after.captureAccount(stateDb, miner, minerName)
vmState.removeTracedAccounts(sender, recipient, miner)
stateDb.persist()
stateDiff["afterRoot"] = %($stateDb.rootHash)
break
@ -146,9 +155,10 @@ proc dumpBlockState*(db: BaseChainDB, header: BlockHeader, body: BlockBody, dump
memoryDB = newMemoryDB()
captureDB = newCaptureDB(db.db, memoryDB)
captureTrieDB = trieDB captureDB
captureChainDB = newBaseChainDB(captureTrieDB, false)
captureChainDB = newBaseChainDB(captureTrieDB, false, PublicNetWork(db.config.chainId))
# we only need stack dump if we want to scan for internal transaction address
vmState = newBaseVMState(parent.stateRoot, header, captureChainDB, {EnableTracing, DisableMemory, DisableStorage, EnableAccount})
miner = vmState.coinbase()
var
before = newJArray()
@ -161,7 +171,7 @@ proc dumpBlockState*(db: BaseChainDB, header: BlockHeader, body: BlockBody, dump
before.captureAccount(stateBefore, sender, senderName & $idx)
before.captureAccount(stateBefore, recipient, recipientName & $idx)
before.captureAccount(stateBefore, header.coinbase, minerName)
before.captureAccount(stateBefore, miner, minerName)
for idx, uncle in body.uncles:
before.captureAccount(stateBefore, uncle.coinbase, uncleName & $idx)
@ -177,8 +187,8 @@ proc dumpBlockState*(db: BaseChainDB, header: BlockHeader, body: BlockBody, dump
after.captureAccount(stateAfter, recipient, recipientName & $idx)
vmState.removeTracedAccounts(sender, recipient)
after.captureAccount(stateAfter, header.coinbase, minerName)
vmState.removeTracedAccounts(header.coinbase)
after.captureAccount(stateAfter, miner, minerName)
vmState.removeTracedAccounts(miner)
for idx, uncle in body.uncles:
after.captureAccount(stateAfter, uncle.coinbase, uncleName & $idx)
@ -202,7 +212,7 @@ proc traceBlock*(chainDB: BaseChainDB, header: BlockHeader, body: BlockBody, tra
memoryDB = newMemoryDB()
captureDB = newCaptureDB(chainDB.db, memoryDB)
captureTrieDB = trieDB captureDB
captureChainDB = newBaseChainDB(captureTrieDB, false)
captureChainDB = newBaseChainDB(captureTrieDB, false, PublicNetWork(chainDB.config.chainId))
vmState = newBaseVMState(parent.stateRoot, header, captureChainDB, tracerFlags + {EnableTracing})
if header.txRoot == BLANK_ROOT_HASH: return newJNull()
@ -236,7 +246,7 @@ proc dumpDebuggingMetaData*(chainDB: BaseChainDB, header: BlockHeader,
memoryDB = newMemoryDB()
captureDB = newCaptureDB(chainDB.db, memoryDB)
captureTrieDB = trieDB captureDB
captureChainDB = newBaseChainDB(captureTrieDB, false)
captureChainDB = newBaseChainDB(captureTrieDB, false, PublicNetWork(chainDB.config.chainId))
bloom = createBloom(vmState.receipts)
let blockSummary = %{

View File

@ -7,11 +7,11 @@
import
macros, strformat, tables, sets, options,
eth/common,
vm/interpreter/[vm_forks, gas_costs],
eth/[common, keys, rlp], nimcrypto/keccak,
vm/interpreter/[vm_forks, gas_costs], ./errors,
./constants, ./db/[db_chain, accounts_cache],
./utils, json, vm_types, vm/transaction_tracer,
./config
./config, ../stateless/[multi_keys, witness_from_tree, witness_types]
proc newAccessLogs*: AccessLogs =
AccessLogs(reads: initTable[string, string](), writes: initTable[string, string]())
@ -26,6 +26,8 @@ proc `$`*(vmState: BaseVMState): string =
else:
result = &"VMState {vmState.name}:\n header: {vmState.blockHeader}\n chaindb: {vmState.chaindb}"
proc getMinerAddress(vmState: BaseVMState): EthAddress
proc init*(self: BaseVMState, prevStateRoot: Hash256, header: BlockHeader,
chainDB: BaseChainDB, tracerFlags: set[TracerFlags] = {}) =
self.prevHeaders = @[]
@ -37,12 +39,20 @@ proc init*(self: BaseVMState, prevStateRoot: Hash256, header: BlockHeader,
self.logEntries = @[]
self.accountDb = AccountsCache.init(chainDB.db, prevStateRoot, chainDB.pruneTrie)
self.touchedAccounts = initHashSet[EthAddress]()
{.gcsafe.}:
self.minerAddress = self.getMinerAddress()
proc newBaseVMState*(prevStateRoot: Hash256, header: BlockHeader,
chainDB: BaseChainDB, tracerFlags: set[TracerFlags] = {}): BaseVMState =
new result
result.init(prevStateRoot, header, chainDB, tracerFlags)
proc newBaseVMState*(prevStateRoot: Hash256,
chainDB: BaseChainDB, tracerFlags: set[TracerFlags] = {}): BaseVMState =
new result
var header: BlockHeader
result.init(prevStateRoot, header, chainDB, tracerFlags)
proc setupTxContext*(vmState: BaseVMState, origin: EthAddress, gasPrice: GasInt, forkOverride=none(Fork)) =
## this proc will be called each time a new transaction
## is going to be executed
@ -55,11 +65,63 @@ proc setupTxContext*(vmState: BaseVMState, origin: EthAddress, gasPrice: GasInt,
vmState.chainDB.config.toFork(vmState.blockHeader.blockNumber)
vmState.gasCosts = vmState.fork.forkToSchedule
proc consensusEnginePoA*(vmState: BaseVMState): bool =
let chainId = PublicNetwork(vmState.chainDB.config.chainId)
# PoA consensus engine have no reward for miner
result = chainId in {GoerliNet, RinkebyNet, KovanNet}
proc getSignature(bytes: openArray[byte], output: var Signature): bool =
let sig = Signature.fromRaw(bytes)
if sig.isOk:
output = sig[]
return true
return false
proc headerHashOriExtraData(vmState: BaseVMState): Hash256 =
var tmp = vmState.blockHeader
tmp.extraData.setLen(tmp.extraData.len-65)
result = keccak256.digest(rlp.encode(tmp))
proc calcMinerAddress(sigRaw: openArray[byte], vmState: BaseVMState, output: var EthAddress): bool =
var sig: Signature
if sigRaw.getSignature(sig):
let headerHash = headerHashOriExtraData(vmState)
let pubkey = recover(sig, headerHash)
if pubkey.isOk:
output = pubkey[].toCanonicalAddress()
result = true
proc getMinerAddress(vmState: BaseVMState): EthAddress =
if not vmState.consensusEnginePoA:
return vmState.blockHeader.coinbase
template data: untyped =
vmState.blockHeader.extraData
let len = data.len
doAssert(len >= 65)
var miner: EthAddress
if calcMinerAddress(data.toOpenArray(len - 65, len-1), vmState, miner):
result = miner
else:
raise newException(ValidationError, "Could not derive miner address from header extradata")
proc updateBlockHeader*(vmState: BaseVMState, header: BlockHeader) =
vmState.blockHeader = header
vmState.touchedAccounts.clear()
vmState.suicides.clear()
if EnableTracing in vmState.tracer.flags:
vmState.tracer.initTracer(vmState.tracer.flags)
vmState.logEntries = @[]
vmState.receipts = @[]
vmState.minerAddress = vmState.getMinerAddress()
method blockhash*(vmState: BaseVMState): Hash256 {.base, gcsafe.} =
vmState.blockHeader.hash
method coinbase*(vmState: BaseVMState): EthAddress {.base, gcsafe.} =
vmState.blockHeader.coinbase
vmState.minerAddress
method timestamp*(vmState: BaseVMState): EthTime {.base, gcsafe.} =
vmState.blockHeader.timestamp
@ -75,6 +137,9 @@ method difficulty*(vmState: BaseVMState): UInt256 {.base, gcsafe.} =
method gasLimit*(vmState: BaseVMState): GasInt {.base, gcsafe.} =
vmState.blockHeader.gasLimit
when defined(geth):
import db/geth_db
method getAncestorHash*(vmState: BaseVMState, blockNumber: BlockNumber): Hash256 {.base, gcsafe.} =
var ancestorDepth = vmState.blockHeader.blockNumber - blockNumber - 1
if ancestorDepth >= constants.MAX_PREV_HEADER_DEPTH:
@ -82,7 +147,10 @@ method getAncestorHash*(vmState: BaseVMState, blockNumber: BlockNumber): Hash256
if blockNumber >= vmState.blockHeader.blockNumber:
return
result = vmState.chainDB.getBlockHash(blockNumber)
when defined(geth):
result = vmState.chainDB.headerHash(blockNumber.truncate(uint64))
else:
result = vmState.chainDB.getBlockHash(blockNumber)
#TODO: should we use deque here?
# someday we may revive this code when
# we already have working miner
@ -143,3 +211,12 @@ proc generateWitness*(vmState: BaseVMState): bool {.inline.} =
proc `generateWitness=`*(vmState: BaseVMState, status: bool) =
if status: vmState.flags.incl GenerateWitness
else: vmState.flags.excl GenerateWitness
proc buildWitness*(vmState: BaseVMState): seq[byte] =
let rootHash = vmState.accountDb.rootHash
let mkeys = vmState.accountDb.makeMultiKeys()
let flags = if vmState.fork >= FKSpurious: {wfEIP170} else: {}
# build witness from tree
var wb = initWitnessBuilder(vmState.chainDB.db, rootHash, flags)
result = wb.buildWitness(mkeys)

View File

@ -19,6 +19,7 @@ type
VMFlag* = enum
ExecutionOK
GenerateWitness
ClearCache
BaseVMState* = ref object of RootObj
prevHeaders* : seq[BlockHeader]
@ -38,6 +39,7 @@ type
txGasPrice* : GasInt
gasCosts* : GasCosts
fork* : Fork
minerAddress* : EthAddress
AccessLogs* = ref object
reads*: Table[string, string]

View File

@ -1,5 +1,5 @@
import stint, os, parseopt, strutils
from ../nimbus/config import getDefaultDataDir, ConfigStatus, processInteger
from ../nimbus/config import getDefaultDataDir, ConfigStatus, processInteger, PublicNetwork
export ConfigStatus
@ -9,6 +9,7 @@ type
head*: Uint256
maxBlocks*: int
numCommits*: int
netId*: PublicNetwork
var premixConfig {.threadvar.}: PremixConfiguration
@ -23,6 +24,7 @@ proc initConfiguration(): PremixConfiguration =
result.head = 0.u256
result.maxBlocks = 0
result.numCommits = 128
result.netId = MainNet
proc getConfiguration*(): PremixConfiguration =
if isNil(premixConfig):
@ -36,6 +38,15 @@ proc processU256(val: string, o: var Uint256): ConfigStatus =
o = parse(val, Uint256)
result = Success
proc processNetId(val: string, o: var PublicNetwork): ConfigStatus =
case val.toLowerAscii()
of "main": o = MainNet
of "morden": o = MordenNet
of "ropsten": o = RopstenNet
of "rinkeby": o = RinkebyNet
of "goerli": o = GoerliNet
of "kovan": o = KovanNet
template checkArgument(fun, o: untyped) =
## Checks if arguments got processed successfully
var res = (fun)(value, o)
@ -72,6 +83,8 @@ proc processArguments*(msg: var string): ConfigStatus =
of "numcommits":
checkArgument processInteger, config.numCommits
config.numCommits = max(config.numCommits, 512)
of "netid":
checkArgument processNetId, config.netId
else:
msg = "Unknown option " & key
if value.len > 0: msg = msg & " : " & value

View File

@ -3,7 +3,7 @@
import
eth/[common, rlp], stint,
chronicles, downloader, configuration,
../nimbus/errors
../nimbus/[errors, config]
import
eth/trie/[hexary, db],
@ -34,10 +34,10 @@ proc main() =
# 52029 first block with receipts logs
# 66407 failed transaction
let conf = getConfiguration()
let conf = configuration.getConfiguration()
let db = newChainDb(conf.dataDir)
let trieDB = trieDB db
let chainDB = newBaseChainDB(trieDB, false)
let chainDB = newBaseChainDB(trieDB, false, conf.netId)
# move head to block number ...
if conf.head != 0.u256:
@ -93,7 +93,7 @@ when isMainModule:
var message: string
## Processing command line arguments
if processArguments(message) != Success:
if configuration.processArguments(message) != Success:
echo message
quit(QuitFailure)
else:

View File

@ -18,7 +18,7 @@ import
../nimbus/utils/header,
../nimbus/p2p/[executor, dao],
../nimbus/config,
../stateless/[multi_keys, tree_from_witness, witness_from_tree, witness_types]
../stateless/[tree_from_witness, witness_types]
type
SealEngine = enum
@ -283,13 +283,9 @@ proc parseTester(fixture: JsonNode, testStatusIMPL: var TestStatus): Tester =
proc blockWitness(vmState: BaseVMState, fork: Fork, chainDB: BaseChainDB) =
let rootHash = vmState.accountDb.rootHash
let mkeys = vmState.accountDb.makeMultiKeys()
let witness = vmState.buildWitness()
let flags = if fork >= FKSpurious: {wfEIP170} else: {}
# build witness from tree
var wb = initWitnessBuilder(chainDB.db, rootHash, flags)
let witness = wb.buildWitness(mkeys)
# build tree from witness
var db = newMemoryDB()
when defined(useInputStream):