@@ -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,7 @@ func (d *DeltaView) SlotInAccessList(sk types.SlotAddress) (addressOk bool, slot
523519 return addressFound , true
524520 }
525521 }
526- return addressFound , false
522+ return d . parent . SlotInAccessList ( sk )
527523}
528524
529525// AddSlotToAccessList adds a slot to the access list
@@ -584,3 +580,64 @@ func (d *DeltaView) DirtySlots() map[types.SlotAddress]struct{} {
584580 }
585581 return dirtySlots
586582}
583+
584+ // hasData returns whether any state modifications are recorded in this view
585+ func (d * DeltaView ) hasData () bool {
586+ if len (d .dirtyAddresses ) > 0 {
587+ return true
588+ }
589+
590+ if len (d .created ) > 0 {
591+ return true
592+ }
593+
594+ if len (d .newContract ) > 0 {
595+ return true
596+ }
597+
598+ if len (d .toBeDestructed ) > 0 {
599+ return true
600+ }
601+
602+ if len (d .recreated ) > 0 {
603+ return true
604+ }
605+
606+ if len (d .balances ) > 0 {
607+ return true
608+ }
609+
610+ if len (d .nonces ) > 0 {
611+ return true
612+ }
613+
614+ if len (d .codes ) > 0 {
615+ return true
616+ }
617+
618+ if len (d .codeHashes ) > 0 {
619+ return true
620+ }
621+
622+ if len (d .slots ) > 0 {
623+ return true
624+ }
625+
626+ if len (d .transient ) > 0 {
627+ return true
628+ }
629+
630+ if len (d .accessListAddresses ) > 0 {
631+ return true
632+ }
633+
634+ if len (d .accessListSlots ) > 0 {
635+ return true
636+ }
637+
638+ if d .refund > 0 {
639+ return true
640+ }
641+
642+ return false
643+ }
0 commit comments