2020-04-22 11:04:19 +00:00
|
|
|
import
|
2020-05-05 06:50:31 +00:00
|
|
|
randutils, random, unittest,
|
2020-04-28 09:58:16 +00:00
|
|
|
eth/[common, rlp], eth/trie/[hexary, db, trie_defs],
|
2020-04-29 09:22:39 +00:00
|
|
|
faststreams/input_stream, nimcrypto/sysrand,
|
2020-04-29 05:12:24 +00:00
|
|
|
../stateless/[witness_from_tree, tree_from_witness],
|
2020-05-05 06:50:31 +00:00
|
|
|
../nimbus/db/storage_types, ./witness_types, ./multi_keys
|
2020-04-22 11:04:19 +00:00
|
|
|
|
2020-04-28 09:58:16 +00:00
|
|
|
type
|
|
|
|
DB = TrieDatabaseRef
|
|
|
|
|
2020-05-05 06:50:31 +00:00
|
|
|
StorageKeys = tuple[hash: Hash256, keys: MultikeysRef]
|
|
|
|
|
|
|
|
AccountDef = object
|
|
|
|
storageKeys: MultiKeysRef
|
|
|
|
account: Account
|
|
|
|
|
2020-04-28 02:30:10 +00:00
|
|
|
proc randU256(): UInt256 =
|
|
|
|
var bytes: array[32, byte]
|
|
|
|
discard randomBytes(bytes[0].addr, sizeof(result))
|
|
|
|
result = UInt256.fromBytesBE(bytes)
|
|
|
|
|
2020-05-05 06:50:31 +00:00
|
|
|
proc randStorageSlot(): StorageSlot =
|
|
|
|
discard randomBytes(result[0].addr, sizeof(result))
|
|
|
|
|
2020-04-28 02:30:10 +00:00
|
|
|
proc randNonce(): AccountNonce =
|
|
|
|
discard randomBytes(result.addr, sizeof(result))
|
|
|
|
|
2020-04-28 09:58:16 +00:00
|
|
|
proc randCode(db: DB): Hash256 =
|
|
|
|
if rand(0..1) == 0:
|
|
|
|
result = blankStringHash
|
|
|
|
else:
|
|
|
|
let codeLen = rand(1..150)
|
|
|
|
let code = randList(byte, rng(0, 255), codeLen, unique = false)
|
|
|
|
result = hexary.keccak(code)
|
2020-04-29 05:12:24 +00:00
|
|
|
db.put(contractHashKey(result).toOpenArray, code)
|
2020-04-28 09:58:16 +00:00
|
|
|
|
2020-05-05 06:50:31 +00:00
|
|
|
proc randStorage(db: DB): StorageKeys =
|
2020-04-28 14:06:37 +00:00
|
|
|
if rand(0..1) == 0:
|
2020-05-05 06:50:31 +00:00
|
|
|
result = (emptyRlpHash, MultikeysRef(nil))
|
2020-04-28 14:06:37 +00:00
|
|
|
else:
|
|
|
|
var trie = initSecureHexaryTrie(db)
|
2020-05-05 06:50:31 +00:00
|
|
|
let numPairs = rand(1..10)
|
|
|
|
var keys = newSeq[StorageSlot](numPairs)
|
2020-04-28 14:06:37 +00:00
|
|
|
|
|
|
|
for i in 0..<numPairs:
|
2020-05-05 06:50:31 +00:00
|
|
|
keys[i] = randStorageSlot()
|
|
|
|
trie.put(keys[i], rlp.encode(randU256()))
|
|
|
|
|
|
|
|
if rand(0..1) == 0:
|
|
|
|
result = (trie.rootHash, MultikeysRef(nil))
|
|
|
|
else:
|
|
|
|
var m = newMultikeys(keys)
|
|
|
|
result = (trie.rootHash, m)
|
2020-04-28 02:30:10 +00:00
|
|
|
|
2020-05-05 06:50:31 +00:00
|
|
|
proc randAccount(db: DB): AccountDef =
|
|
|
|
result.account.nonce = randNonce()
|
|
|
|
result.account.balance = randU256()
|
|
|
|
result.account.codeHash = randCode(db)
|
|
|
|
(result.account.storageRoot, result.storageKeys) = randStorage(db)
|
2020-04-28 02:30:10 +00:00
|
|
|
|
2020-04-29 04:12:15 +00:00
|
|
|
proc randAddress(): EthAddress =
|
|
|
|
discard randomBytes(result.addr, sizeof(result))
|
|
|
|
|
2020-05-05 06:50:31 +00:00
|
|
|
proc runTest(numPairs: int, testStatusIMPL: var TestStatus) =
|
2020-04-22 11:04:19 +00:00
|
|
|
var memDB = newMemoryDB()
|
2020-04-28 09:58:16 +00:00
|
|
|
var trie = initSecureHexaryTrie(memDB)
|
2020-05-05 06:50:31 +00:00
|
|
|
var addrs = newSeq[AccountKey](numPairs)
|
2020-05-03 01:11:04 +00:00
|
|
|
var accs = newSeq[Account](numPairs)
|
2020-04-22 11:04:19 +00:00
|
|
|
|
|
|
|
for i in 0..<numPairs:
|
2020-05-05 06:50:31 +00:00
|
|
|
let acc = randAccount(memDB)
|
|
|
|
addrs[i] = (randAddress(), acc.storageKeys)
|
|
|
|
accs[i] = acc.account
|
|
|
|
trie.put(addrs[i].address, rlp.encode(accs[i]))
|
2020-04-22 11:04:19 +00:00
|
|
|
|
2020-05-05 06:50:31 +00:00
|
|
|
var mkeys = newMultiKeys(addrs)
|
2020-04-22 11:04:19 +00:00
|
|
|
let rootHash = trie.rootHash
|
|
|
|
|
2020-05-05 06:50:31 +00:00
|
|
|
var wb = initWitnessBuilder(memDB, rootHash, {wfEIP170})
|
|
|
|
var witness = wb.buildWitness(mkeys)
|
|
|
|
var db = newMemoryDB()
|
|
|
|
when defined(useInputStream):
|
|
|
|
var input = memoryInput(witness)
|
|
|
|
var tb = initTreeBuilder(input, db, {wfEIP170})
|
|
|
|
else:
|
|
|
|
var tb = initTreeBuilder(witness, db, {wfEIP170})
|
|
|
|
let 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)
|
|
|
|
for i in 0..<numPairs:
|
|
|
|
let recordFound = newTrie.get(addrs[i].address)
|
2020-05-03 01:11:04 +00:00
|
|
|
if recordFound.len > 0:
|
|
|
|
let acc = rlp.decode(recordFound, Account)
|
2020-05-05 06:50:31 +00:00
|
|
|
check acc == accs[i]
|
2020-05-03 01:11:04 +00:00
|
|
|
else:
|
2020-05-05 06:50:31 +00:00
|
|
|
debugEcho "BUG IN TREE BUILDER"
|
|
|
|
check false
|
2020-04-22 11:04:19 +00:00
|
|
|
|
|
|
|
proc main() =
|
2020-05-05 06:50:31 +00:00
|
|
|
suite "random keys block witness roundtrip test":
|
|
|
|
randomize()
|
|
|
|
|
|
|
|
test "random multiple keys":
|
|
|
|
for i in 0..<100:
|
|
|
|
runTest(rand(1..30), testStatusIMPL)
|
2020-04-24 08:58:36 +00:00
|
|
|
|
2020-05-05 06:50:31 +00:00
|
|
|
test "there is no short node":
|
|
|
|
let acc = newAccount()
|
|
|
|
let rlpBytes = rlp.encode(acc)
|
|
|
|
check rlpBytes.len > 32
|
2020-04-22 11:04:19 +00:00
|
|
|
|
|
|
|
main()
|