Skip to content

Commit 1b1f07e

Browse files
authored
Stateless: Simplify the witness table data structure (#3446)
1 parent 8923504 commit 1b1f07e

File tree

3 files changed

+59
-73
lines changed

3 files changed

+59
-73
lines changed

execution_chain/db/ledger.nim

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,13 @@ const
4242

4343
when statelessEnabled:
4444
type
45-
WitnessKey* = object
46-
storageMode*: bool
47-
address*: Address
48-
codeTouched*: bool
49-
storageSlot*: UInt256
45+
WitnessKey* = tuple[
46+
address: Address,
47+
slot: Opt[UInt256]
48+
]
5049

51-
WitnessTable* = OrderedTable[(Address, Hash32), WitnessKey]
50+
# Maps witness keys to the codeTouched flag
51+
WitnessTable* = OrderedTable[WitnessKey, bool]
5252

5353
type
5454
AccountFlag = enum
@@ -98,8 +98,7 @@ type
9898
when statelessEnabled:
9999
witnessKeys: WitnessTable
100100
## Used to collect the keys of all read accounts, code and storage slots.
101-
## Maps a tuple of address and hash of the key (address or slot) to the
102-
## witness key which can be either a storage key or an account key
101+
## Maps a tuple of address and slot (optional) to the codeTouched flag.
103102

104103

105104
ReadOnlyLedger* = distinct LedgerRef
@@ -171,12 +170,9 @@ proc getAccount(
171170
shouldCreate = true;
172171
): AccountRef =
173172
when statelessEnabled:
174-
let lookupKey = (address, address.toAccountKey)
173+
let lookupKey = (address, Opt.none(UInt256))
175174
if not ac.witnessKeys.contains(lookupKey):
176-
ac.witnessKeys[lookupKey] = WitnessKey(
177-
storageMode: false,
178-
address: address,
179-
codeTouched: false)
175+
ac.witnessKeys[lookupKey] = false
180176

181177
# search account from layers of cache
182178
var sp = ac.savePoint
@@ -465,13 +461,10 @@ proc getCode*(ac: LedgerRef,
465461
address: Address,
466462
returnHash: static[bool] = false): auto =
467463
when statelessEnabled:
468-
let lookupKey = (address, address.toAccountKey)
464+
let lookupKey = (address, Opt.none(UInt256))
469465
# We overwrite any existing record here so that codeTouched is always set to
470466
# true even if an account was previously accessed without touching the code
471-
ac.witnessKeys[lookupKey] = WitnessKey(
472-
storageMode: false,
473-
address: address,
474-
codeTouched: true)
467+
ac.witnessKeys[lookupKey] = true
475468

476469
let acc = ac.getAccount(address, false)
477470
if acc.isNil:
@@ -532,11 +525,9 @@ proc getCommittedStorage*(ac: LedgerRef, address: Address, slot: UInt256): UInt2
532525
let acc = ac.getAccount(address, false)
533526

534527
when statelessEnabled:
535-
let lookupKey = (address, slot.toSlotKey)
528+
let lookupKey = (address, Opt.some(slot))
536529
if not ac.witnessKeys.contains(lookupKey):
537-
ac.witnessKeys[lookupKey] = WitnessKey(
538-
storageMode: true,
539-
storageSlot: slot)
530+
ac.witnessKeys[lookupKey] = false
540531

541532
if acc.isNil:
542533
return
@@ -546,11 +537,9 @@ proc getStorage*(ac: LedgerRef, address: Address, slot: UInt256): UInt256 =
546537
let acc = ac.getAccount(address, false)
547538

548539
when statelessEnabled:
549-
let lookupKey = (address, slot.toSlotKey)
540+
let lookupKey = (address, Opt.some(slot))
550541
if not ac.witnessKeys.contains(lookupKey):
551-
ac.witnessKeys[lookupKey] = WitnessKey(
552-
storageMode: true,
553-
storageSlot: slot)
542+
ac.witnessKeys[lookupKey] = false
554543

555544
if acc.isNil:
556545
return
@@ -635,11 +624,9 @@ proc setStorage*(ac: LedgerRef, address: Address, slot, value: UInt256) =
635624
acc.flags.incl {Alive}
636625

637626
when statelessEnabled:
638-
let lookupKey = (address, slot.toSlotKey)
627+
let lookupKey = (address, Opt.some(slot))
639628
if not ac.witnessKeys.contains(lookupKey):
640-
ac.witnessKeys[lookupKey] = WitnessKey(
641-
storageMode: true,
642-
storageSlot: slot)
629+
ac.witnessKeys[lookupKey] = false
643630

644631
let oldValue = acc.storageValue(slot, ac)
645632
if oldValue != value:

portal/evm/async_evm.nim

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -180,23 +180,21 @@ proc callFetchingState(
180180
# state queries are still issued in the background just incase the state is
181181
# needed in the next iteration.
182182
var stateFetchDone = false
183-
for k, v in witnessKeys:
184-
let (adr, _) = k
183+
for k, codeTouched in witnessKeys:
184+
let (adr, maybeSlot) = k
185185
if adr == default(Address):
186186
continue
187187

188-
if v.storageMode:
189-
let slotIdx = (adr, v.storageSlot)
190-
if slotIdx notin fetchedStorage:
191-
debug "Fetching storage slot", address = adr, slotKey = v.storageSlot
192-
let storageFut = evm.backend.getStorage(header, adr, v.storageSlot)
188+
if maybeSlot.isSome():
189+
let slot = maybeSlot.get()
190+
if (adr, slot) notin fetchedStorage:
191+
debug "Fetching storage slot", address = adr, slot
192+
let storageFut = evm.backend.getStorage(header, adr, slot)
193193
if not stateFetchDone:
194-
storageQueries.add(StorageQuery.init(adr, v.storageSlot, storageFut))
194+
storageQueries.add(StorageQuery.init(adr, slot, storageFut))
195195
if not optimisticStateFetch:
196196
stateFetchDone = true
197197
else:
198-
doAssert(adr == v.address)
199-
200198
if adr notin fetchedAccounts:
201199
debug "Fetching account", address = adr
202200
let accFut = evm.backend.getAccount(header, adr)
@@ -205,7 +203,7 @@ proc callFetchingState(
205203
if not optimisticStateFetch:
206204
stateFetchDone = true
207205

208-
if v.codeTouched and adr notin fetchedCode:
206+
if codeTouched and adr notin fetchedCode:
209207
debug "Fetching code", address = adr
210208
let codeFut = evm.backend.getCode(header, adr)
211209
if not stateFetchDone:
@@ -336,13 +334,13 @@ proc createAccessList*(
336334
# returned in the callResult.
337335

338336
var al = access_list.AccessList.init()
339-
for lookupKey, witnessKey in witnessKeys:
340-
let (adr, _) = lookupKey
337+
for k, codeTouched in witnessKeys:
338+
let (adr, maybeSlot) = k
341339
if adr == fromAdr:
342340
continue
343341

344-
if witnessKey.storageMode:
345-
al.add(adr, witnessKey.storageSlot)
342+
if maybeSlot.isSome():
343+
al.add(adr, maybeSlot.get())
346344
else:
347345
al.add(adr)
348346

tests/test_ledger.nim

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -657,11 +657,11 @@ proc runLedgerBasicOperationsTests() =
657657

658658
let
659659
witnessKeys = ac.getWitnessKeys()
660-
keyData = witnessKeys.getOrDefault((addr1, addr1.toAccountKey))
660+
key = (addr1, Opt.none(UInt256))
661661
check:
662662
witnessKeys.len() == 1
663-
keyData.address == addr1
664-
keyData.codeTouched == false
663+
witnessKeys.contains(key)
664+
witnessKeys.getOrDefault(key) == false
665665

666666
test "Witness keys - Get code":
667667
var
@@ -672,11 +672,11 @@ proc runLedgerBasicOperationsTests() =
672672

673673
let
674674
witnessKeys = ac.getWitnessKeys()
675-
keyData = witnessKeys.getOrDefault((addr1, addr1.toAccountKey))
675+
key = (addr1, Opt.none(UInt256))
676676
check:
677677
witnessKeys.len() == 1
678-
keyData.address == addr1
679-
keyData.codeTouched == true
678+
witnessKeys.contains(key)
679+
witnessKeys.getOrDefault(key) == true
680680

681681
test "Witness keys - Get storage":
682682
var
@@ -688,10 +688,11 @@ proc runLedgerBasicOperationsTests() =
688688

689689
let
690690
witnessKeys = ac.getWitnessKeys()
691-
keyData = witnessKeys.getOrDefault((addr1, slot1.toSlotKey))
691+
key = (addr1, Opt.some(slot1))
692692
check:
693693
witnessKeys.len() == 2
694-
keyData.storageSlot == slot1
694+
witnessKeys.contains(key)
695+
witnessKeys.getOrDefault(key) == false
695696

696697
test "Witness keys - Set storage":
697698
var
@@ -703,10 +704,11 @@ proc runLedgerBasicOperationsTests() =
703704

704705
let
705706
witnessKeys = ac.getWitnessKeys()
706-
keyData = witnessKeys.getOrDefault((addr1, slot1.toSlotKey))
707+
key = (addr1, Opt.some(slot1))
707708
check:
708709
witnessKeys.len() == 2
709-
keyData.storageSlot == slot1
710+
witnessKeys.contains(key)
711+
witnessKeys.getOrDefault(key) == false
710712

711713
test "Witness keys - Get account, code and storage":
712714
var
@@ -728,31 +730,30 @@ proc runLedgerBasicOperationsTests() =
728730
let witnessKeys = ac.getWitnessKeys()
729731
check witnessKeys.len() == 5
730732

731-
var keysList = newSeq[(Address, WitnessKey)]()
733+
var keysList = newSeq[(WitnessKey, bool)]()
732734
for k, v in witnessKeys:
733-
let (adr, _) = k
734-
keysList.add((adr, v))
735+
keysList.add((k, v))
735736

736737
check:
737-
keysList[0][0] == addr1
738-
keysList[0][1].address == addr1
739-
keysList[0][1].codeTouched == true
738+
keysList[0][0].address == addr1
739+
keysList[0][0].slot == Opt.none(UInt256)
740+
keysList[0][1] == true
740741

741-
keysList[1][0] == addr2
742-
keysList[1][1].address == addr2
743-
keysList[1][1].codeTouched == true
742+
keysList[1][0].address == addr2
743+
keysList[1][0].slot == Opt.none(UInt256)
744+
keysList[1][1] == true
744745

745-
keysList[2][0] == addr2
746-
keysList[2][1].storageSlot == slot1
747-
748-
keysList[3][0] == addr1
749-
keysList[3][1].storageSlot == slot1
750-
751-
keysList[4][0] == addr3
752-
keysList[4][1].address == addr3
753-
keysList[4][1].codeTouched == false
746+
keysList[2][0].address == addr2
747+
keysList[2][0].slot == Opt.some(slot1)
748+
keysList[2][1] == false
754749

750+
keysList[3][0].address == addr1
751+
keysList[3][0].slot == Opt.some(slot1)
752+
keysList[3][1] == false
755753

754+
keysList[4][0].address == addr3
755+
keysList[4][0].slot == Opt.none(UInt256)
756+
keysList[4][1] == false
756757

757758

758759
# ------------------------------------------------------------------------------

0 commit comments

Comments
 (0)