2020-04-21 10:21:06 +00:00
|
|
|
import
|
|
|
|
unittest2, os, json, strutils,
|
|
|
|
eth/[common, rlp], eth/trie/[hexary, db, trie_defs],
|
2020-04-22 04:21:39 +00:00
|
|
|
stew/byteutils, faststreams/input_stream,
|
2020-04-28 02:30:10 +00:00
|
|
|
../tests/[test_helpers, test_config],
|
2020-04-29 05:46:50 +00:00
|
|
|
../nimbus/db/accounts_cache, ./witness_types,
|
2020-05-05 06:50:31 +00:00
|
|
|
../stateless/[witness_from_tree, tree_from_witness],
|
|
|
|
./multi_keys
|
2020-04-21 10:21:06 +00:00
|
|
|
|
|
|
|
type
|
|
|
|
Tester = object
|
2020-05-05 06:50:31 +00:00
|
|
|
keys: MultikeysRef
|
2020-04-21 10:21:06 +00:00
|
|
|
memDB: TrieDatabaseRef
|
|
|
|
|
|
|
|
proc testGetBranch(tester: Tester, rootHash: KeccakHash, testStatusIMPL: var TestStatus) =
|
2020-05-03 01:11:04 +00:00
|
|
|
var trie = initSecureHexaryTrie(tester.memdb, rootHash)
|
2020-04-29 05:46:50 +00:00
|
|
|
let flags = {wfEIP170}
|
2020-04-22 04:21:39 +00:00
|
|
|
|
2020-04-29 05:46:50 +00:00
|
|
|
try:
|
2020-05-05 06:50:31 +00:00
|
|
|
var wb = initWitnessBuilder(tester.memdb, rootHash, flags)
|
|
|
|
var witness = wb.buildWitness(tester.keys)
|
2020-04-29 05:46:50 +00:00
|
|
|
|
2020-05-05 06:50:31 +00:00
|
|
|
var db = newMemoryDB()
|
|
|
|
when defined(useInputStream):
|
|
|
|
var input = memoryInput(witness)
|
|
|
|
var tb = initTreeBuilder(input, db, flags)
|
|
|
|
else:
|
|
|
|
var tb = initTreeBuilder(witness, db, flags)
|
2020-04-29 05:46:50 +00:00
|
|
|
|
2020-05-05 06:50:31 +00:00
|
|
|
var root = tb.buildTree()
|
|
|
|
check root.data == rootHash.data
|
2020-05-03 01:11:04 +00:00
|
|
|
|
2020-05-05 06:50:31 +00:00
|
|
|
let newTrie = initSecureHexaryTrie(tb.getDB(), root)
|
2020-05-05 08:21:39 +00:00
|
|
|
for kd in tester.keys.keys:
|
|
|
|
let account = rlp.decode(trie.get(kd.address), Account)
|
|
|
|
let recordFound = newTrie.get(kd.address)
|
2020-05-03 01:11:04 +00:00
|
|
|
if recordFound.len > 0:
|
|
|
|
let acc = rlp.decode(recordFound, Account)
|
|
|
|
doAssert acc == account
|
|
|
|
else:
|
|
|
|
doAssert(false, "BUG IN TREE BUILDER")
|
|
|
|
|
2020-04-29 05:46:50 +00:00
|
|
|
except ContractCodeError as e:
|
|
|
|
debugEcho "CONTRACT CODE ERROR: ", e.msg
|
2020-04-21 10:21:06 +00:00
|
|
|
|
|
|
|
func parseHash256(n: JsonNode, name: string): Hash256 =
|
|
|
|
hexToByteArray(n[name].getStr(), result.data)
|
|
|
|
|
|
|
|
proc setupStateDB(tester: var Tester, wantedState: JsonNode, stateDB: var AccountsCache): Hash256 =
|
2020-05-05 06:50:31 +00:00
|
|
|
var keys = newSeqOfCap[AccountKey](wantedState.len)
|
|
|
|
|
2020-04-21 10:21:06 +00:00
|
|
|
for ac, accountData in wantedState:
|
|
|
|
let account = ethAddressFromHex(ac)
|
2020-05-05 06:50:31 +00:00
|
|
|
let slotVals = accountData{"storage"}
|
|
|
|
var storageKeys = newSeqOfCap[StorageSlot](slotVals.len)
|
|
|
|
|
|
|
|
for slotStr, value in slotVals:
|
|
|
|
let slot = fromHex(UInt256, slotStr)
|
|
|
|
storageKeys.add(slot.toBytesBE)
|
|
|
|
stateDB.setStorage(account, slot, fromHex(UInt256, value.getStr))
|
|
|
|
|
2020-04-21 10:21:06 +00:00
|
|
|
let nonce = accountData{"nonce"}.getHexadecimalInt.AccountNonce
|
|
|
|
let code = accountData{"code"}.getStr.safeHexToSeqByte
|
|
|
|
let balance = UInt256.fromHex accountData{"balance"}.getStr
|
|
|
|
|
|
|
|
stateDB.setNonce(account, nonce)
|
|
|
|
stateDB.setCode(account, code)
|
|
|
|
stateDB.setBalance(account, balance)
|
|
|
|
|
2020-05-05 08:05:17 +00:00
|
|
|
let sKeys = if storageKeys.len != 0: newMultiKeys(storageKeys) else: MultikeysRef(nil)
|
|
|
|
let codeTouched = code.len > 0
|
|
|
|
keys.add((account, codeTouched, sKeys))
|
|
|
|
|
2020-05-05 06:50:31 +00:00
|
|
|
tester.keys = newMultiKeys(keys)
|
2020-04-21 10:21:06 +00:00
|
|
|
stateDB.persist()
|
|
|
|
result = stateDB.rootHash
|
|
|
|
|
|
|
|
proc testBlockWitness(node: JsonNode, rootHash: Hash256, testStatusIMPL: var TestStatus) =
|
|
|
|
var
|
|
|
|
tester = Tester(memDB: newMemoryDB())
|
|
|
|
ac = AccountsCache.init(tester.memDB, emptyRlpHash, true)
|
|
|
|
|
|
|
|
let root = tester.setupStateDB(node, ac)
|
|
|
|
if rootHash != emptyRlpHash:
|
|
|
|
check root == rootHash
|
|
|
|
|
|
|
|
tester.testGetBranch(root, testStatusIMPL)
|
|
|
|
|
|
|
|
proc testFixtureBC(node: JsonNode, testStatusIMPL: var TestStatus) =
|
|
|
|
for fixtureName, fixture in node:
|
|
|
|
let rootHash = parseHash256(fixture["genesisBlockHeader"], "stateRoot")
|
|
|
|
fixture["pre"].testBlockWitness(rootHash, testStatusIMPL)
|
|
|
|
|
|
|
|
proc testFixtureGST(node: JsonNode, testStatusIMPL: var TestStatus) =
|
|
|
|
var fixture: JsonNode
|
|
|
|
|
|
|
|
for fixtureName, child in node:
|
|
|
|
fixture = child
|
|
|
|
break
|
|
|
|
|
|
|
|
fixture["pre"].testBlockWitness(emptyRlpHash, testStatusIMPL)
|
|
|
|
|
2020-04-28 02:30:10 +00:00
|
|
|
proc blockWitnessMain*(debugMode = false) =
|
|
|
|
if paramCount() == 0 or not debugMode:
|
|
|
|
# run all test fixtures
|
|
|
|
suite "Block Witness":
|
|
|
|
jsonTest("newBlockChainTests", "witnessBuilderBC", testFixtureBC)
|
|
|
|
suite "Block Witness":
|
|
|
|
jsonTest("GeneralStateTests", "witnessBuilderGST", testFixtureGST)
|
|
|
|
else:
|
|
|
|
# execute single test in debug mode
|
|
|
|
let config = getConfiguration()
|
|
|
|
if config.testSubject.len == 0:
|
|
|
|
echo "missing test subject"
|
|
|
|
quit(QuitFailure)
|
|
|
|
|
|
|
|
let folder = if config.legacy: "GeneralStateTests" else: "newGeneralStateTests"
|
|
|
|
let path = "tests" / "fixtures" / folder
|
|
|
|
let n = json.parseFile(path / config.testSubject)
|
|
|
|
var testStatusIMPL: TestStatus
|
2020-04-29 05:46:50 +00:00
|
|
|
testFixtureGST(n, testStatusIMPL)
|
2020-04-28 02:30:10 +00:00
|
|
|
|
|
|
|
when isMainModule:
|
|
|
|
var message: string
|
|
|
|
|
|
|
|
## Processing command line arguments
|
|
|
|
if processArguments(message) != Success:
|
|
|
|
echo message
|
|
|
|
quit(QuitFailure)
|
|
|
|
else:
|
|
|
|
if len(message) > 0:
|
|
|
|
echo message
|
|
|
|
quit(QuitSuccess)
|
|
|
|
blockWitnessMain(true)
|