From 37db9a55ee3dc4b376450e2825c590178bd9a765 Mon Sep 17 00:00:00 2001 From: andri lim Date: Tue, 5 May 2020 15:21:39 +0700 Subject: [PATCH] deals with touched/not touched account code --- stateless/test_block_witness.nim | 6 +++--- stateless/tree_from_witness.nim | 14 ++++++++++++-- stateless/witness_from_tree.nim | 25 +++++++++++++++---------- stateless/witness_types.nim | 1 + 4 files changed, 31 insertions(+), 15 deletions(-) diff --git a/stateless/test_block_witness.nim b/stateless/test_block_witness.nim index cde4b2635..90d3e8bee 100644 --- a/stateless/test_block_witness.nim +++ b/stateless/test_block_witness.nim @@ -31,9 +31,9 @@ proc testGetBranch(tester: Tester, rootHash: KeccakHash, testStatusIMPL: var Tes check root.data == rootHash.data let newTrie = initSecureHexaryTrie(tb.getDB(), root) - for address in tester.keys.addresses: - let account = rlp.decode(trie.get(address), Account) - let recordFound = newTrie.get(address) + for kd in tester.keys.keys: + let account = rlp.decode(trie.get(kd.address), Account) + let recordFound = newTrie.get(kd.address) if recordFound.len > 0: let acc = rlp.decode(recordFound, Account) doAssert acc == account diff --git a/stateless/tree_from_witness.nim b/stateless/tree_from_witness.nim index 4a9060242..dfe252b23 100644 --- a/stateless/tree_from_witness.nim +++ b/stateless/tree_from_witness.nim @@ -332,10 +332,11 @@ proc accountNode(t: var TreeBuilder, depth: int): NodeKey = nonce: UInt256.fromBytesBE(t.read(32), false).truncate(AccountNonce) ) - if accountType == SimpleAccountType: + case accountType + of SimpleAccountType: acc.codeHash = blankStringHash acc.storageRoot = emptyRlpHash - else: + of ExtendedAccountType: let codeLen = t.safeReadU32() if wfEIP170 in t.flags and codeLen > EIP170_CODE_SIZE_LIMIT: raise newException(ContractCodeError, "code len exceed EIP170 code size limit") @@ -348,6 +349,15 @@ proc accountNode(t: var TreeBuilder, depth: int): NodeKey = let storageRoot = t.treeNode(0, storageMode = true) doAssert(storageRoot.usedBytes == 32) acc.storageRoot.data = storageRoot.data + of CodeUntouched: + # TODO: should we check it is a hashNode ? + let codeHash = t.treeNode(depth) + doAssert(codeHash.usedBytes == 32) + acc.codeHash.data = codeHash.data + + let storageRoot = t.treeNode(0, storageMode = true) + doAssert(storageRoot.usedBytes == 32) + acc.storageRoot.data = storageRoot.data r.append rlp.encode(acc) diff --git a/stateless/witness_from_tree.nim b/stateless/witness_from_tree.nim index d60e53f6c..1a06ab1a4 100644 --- a/stateless/witness_from_tree.nim +++ b/stateless/witness_from_tree.nim @@ -107,8 +107,8 @@ proc writeHashNode(wb: var WitnessBuilder, node: openArray[byte]) = proc getBranchRecurseAux(wb: var WitnessBuilder, z: var StackElem) {.raises: [ContractCodeError, IOError, Defect, CatchableError, Exception].} -proc writeAccountNode(wb: var WitnessBuilder, storageKeys: MultikeysRef, address: EthAddress, - acc: Account, nibbles: NibblesSeq, node: openArray[byte], depth: int) {.raises: [ContractCodeError, IOError, Defect, CatchableError, Exception].} = +proc writeAccountNode(wb: var WitnessBuilder, kd: KeyData, acc: Account, nibbles: NibblesSeq, + node: openArray[byte], depth: int) {.raises: [ContractCodeError, IOError, Defect, CatchableError, Exception].} = # write type wb.output.append(AccountNodeType.byte) @@ -121,17 +121,22 @@ proc writeAccountNode(wb: var WitnessBuilder, storageKeys: MultikeysRef, address wb.output.append(depth.byte) doAssert(nibbles.len == 64 - depth) - let accountType = if acc.codeHash == blankStringHash and acc.storageRoot == emptyRlpHash: SimpleAccountType + var accountType = if acc.codeHash == blankStringHash and acc.storageRoot == emptyRlpHash: SimpleAccountType else: ExtendedAccountType + if not kd.codeTouched: + accountType = CodeUntouched + wb.output.append(accountType.byte) wb.writeNibbles(nibbles, false) - wb.output.append(address) + wb.output.append(kd.address) wb.output.append(acc.balance.toBytesBE) wb.output.append(acc.nonce.u256.toBytesBE) - if accountType == ExtendedAccountType: - if acc.codeHash != blankStringHash: + if accountType != SimpleAccountType: + if not kd.codeTouched: + wb.writeHashNode(acc.codeHash.data) + elif acc.codeHash != blankStringHash: let code = get(wb.db, contractHashKey(acc.codeHash).toOpenArray) if wfEIP170 in wb.flags and code.len > EIP170_CODE_SIZE_LIMIT: raise newException(ContractCodeError, "code len exceed EIP170 code size limit") @@ -140,14 +145,14 @@ proc writeAccountNode(wb: var WitnessBuilder, storageKeys: MultikeysRef, address else: wb.writeU32(0'u32) - if storageKeys.isNil: + if kd.storageKeys.isNil: # we have storage but not touched by EVM wb.writeHashNode(acc.storageRoot.data) elif acc.storageRoot != emptyRlpHash: var zz = StackElem( node: wb.db.get(acc.storageRoot.data), - parentGroup: storageKeys.initGroup(), - keys: storageKeys, + parentGroup: kd.storageKeys.initGroup(), + keys: kd.storageKeys, depth: 0, # reset depth storageMode: true # switch to storage mode ) @@ -212,7 +217,7 @@ proc getBranchRecurseAux(wb: var WitnessBuilder, z: var StackElem) = writeAccountStorageLeafNode(wb, kd.storageSlot, value.toBytes.decode(UInt256), k, z.node, z.depth) else: doAssert(not kd.storageMode) - writeAccountNode(wb, kd.storageKeys, kd.address, value.toBytes.decode(Account), k, z.node, z.depth) + writeAccountNode(wb, kd, value.toBytes.decode(Account), k, z.node, z.depth) if not match: writeHashNode(wb, keccak(z.node).data) of 17: diff --git a/stateless/witness_types.nim b/stateless/witness_types.nim index 13119778e..cd9ca2e0c 100644 --- a/stateless/witness_types.nim +++ b/stateless/witness_types.nim @@ -10,6 +10,7 @@ type AccountType* = enum SimpleAccountType ExtendedAccountType + CodeUntouched WitnessFlag* = enum wfNoFlag