@@ -67,6 +67,16 @@ var _ types.HotView = &DeltaView{}
6767
6868// NewDeltaView constructs a new delta view
6969func NewDeltaView (parent types.ReadOnlyView ) * DeltaView {
70+ // The root node will be of type `BaseView`, so we should
71+ // check if we are dealing with `DeltaView`, for parent
72+ // skipping
73+ dt , ok := parent .(* DeltaView )
74+ if ok && ! dt .hasData () {
75+ // If my parent doesn't have any writes, I can just
76+ // delegate "upstream" queries to its parent
77+ parent = dt .parent
78+ }
79+
7080 return & DeltaView {
7181 parent : parent ,
7282
@@ -478,21 +488,14 @@ func (d *DeltaView) SubRefund(amount uint64) error {
478488
479489// AddressInAccessList checks if the address is in the access list of
480490// the current view.
481- // NOTE: Due to resource constraints (such as CPU & memory), and the
482- // high-frequency usage of this function from EVM, we do not look up
483- // the parents until the root view or until we find a view that has
484- // the address in its local access list.
485- // As an optimization, the `StateDB.AddressInAccessList` is responsible
486- // for optimally traversing the views, to check if the address is in
487- // the access list.
488491func (d * DeltaView ) AddressInAccessList (addr gethCommon.Address ) bool {
489492 if d .accessListAddresses != nil {
490493 _ , addressFound := d .accessListAddresses [addr ]
491494 if addressFound {
492495 return true
493496 }
494497 }
495- return false
498+ return d . parent . AddressInAccessList ( addr )
496499}
497500
498501// AddAddressToAccessList adds an address to the access list
@@ -508,13 +511,6 @@ func (d *DeltaView) AddAddressToAccessList(addr gethCommon.Address) bool {
508511
509512// SlotInAccessList checks if the slot is in the access list of the
510513// current view.
511- // NOTE: Due to resource constraints (such as CPU & memory), and the
512- // high-frequency usage of this function from EVM, we do not look up
513- // the parents until the root view or until we find a view that has
514- // the slot in its local access list.
515- // As an optimization, the `StateDB.SlotInAccessList` is responsible
516- // for optimally traversing the views, to check if the slot is in
517- // the access list.
518514func (d * DeltaView ) SlotInAccessList (sk types.SlotAddress ) (addressOk bool , slotOk bool ) {
519515 addressFound := d .AddressInAccessList (sk .Address )
520516 if d .accessListSlots != nil {
@@ -523,7 +519,8 @@ func (d *DeltaView) SlotInAccessList(sk types.SlotAddress) (addressOk bool, slot
523519 return addressFound , true
524520 }
525521 }
526- return addressFound , false
522+ _ , slotFound := d .parent .SlotInAccessList (sk )
523+ return addressFound , slotFound
527524}
528525
529526// AddSlotToAccessList adds a slot to the access list
@@ -584,3 +581,64 @@ func (d *DeltaView) DirtySlots() map[types.SlotAddress]struct{} {
584581 }
585582 return dirtySlots
586583}
584+
585+ // hasData returns whether any state modifications are recorded in this view
586+ func (d * DeltaView ) hasData () bool {
587+ if len (d .dirtyAddresses ) > 0 {
588+ return true
589+ }
590+
591+ if len (d .created ) > 0 {
592+ return true
593+ }
594+
595+ if len (d .newContract ) > 0 {
596+ return true
597+ }
598+
599+ if len (d .toBeDestructed ) > 0 {
600+ return true
601+ }
602+
603+ if len (d .recreated ) > 0 {
604+ return true
605+ }
606+
607+ if len (d .balances ) > 0 {
608+ return true
609+ }
610+
611+ if len (d .nonces ) > 0 {
612+ return true
613+ }
614+
615+ if len (d .codes ) > 0 {
616+ return true
617+ }
618+
619+ if len (d .codeHashes ) > 0 {
620+ return true
621+ }
622+
623+ if len (d .slots ) > 0 {
624+ return true
625+ }
626+
627+ if len (d .transient ) > 0 {
628+ return true
629+ }
630+
631+ if len (d .accessListAddresses ) > 0 {
632+ return true
633+ }
634+
635+ if len (d .accessListSlots ) > 0 {
636+ return true
637+ }
638+
639+ if d .refund > 0 {
640+ return true
641+ }
642+
643+ return false
644+ }
0 commit comments