github.com/MetalBlockchain/subnet-evm@v0.4.9/core/state/access_list.go (about)

     1  // (c) 2019-2021, Ava Labs, Inc.
     2  //
     3  // This file is a derived work, based on the go-ethereum library whose original
     4  // notices appear below.
     5  //
     6  // It is distributed under a license compatible with the licensing terms of the
     7  // original code from which it is derived.
     8  //
     9  // Much love to the original authors for their work.
    10  // **********
    11  // Copyright 2020 The go-ethereum Authors
    12  // This file is part of the go-ethereum library.
    13  //
    14  // The go-ethereum library is free software: you can redistribute it and/or modify
    15  // it under the terms of the GNU Lesser General Public License as published by
    16  // the Free Software Foundation, either version 3 of the License, or
    17  // (at your option) any later version.
    18  //
    19  // The go-ethereum library is distributed in the hope that it will be useful,
    20  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    21  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    22  // GNU Lesser General Public License for more details.
    23  //
    24  // You should have received a copy of the GNU Lesser General Public License
    25  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    26  
    27  package state
    28  
    29  import (
    30  	"github.com/ethereum/go-ethereum/common"
    31  )
    32  
    33  type accessList struct {
    34  	addresses map[common.Address]int
    35  	slots     []map[common.Hash]struct{}
    36  }
    37  
    38  // ContainsAddress returns true if the address is in the access list.
    39  func (al *accessList) ContainsAddress(address common.Address) bool {
    40  	_, ok := al.addresses[address]
    41  	return ok
    42  }
    43  
    44  // Contains checks if a slot within an account is present in the access list, returning
    45  // separate flags for the presence of the account and the slot respectively.
    46  func (al *accessList) Contains(address common.Address, slot common.Hash) (addressPresent bool, slotPresent bool) {
    47  	idx, ok := al.addresses[address]
    48  	if !ok {
    49  		// no such address (and hence zero slots)
    50  		return false, false
    51  	}
    52  	if idx == -1 {
    53  		// address yes, but no slots
    54  		return true, false
    55  	}
    56  	_, slotPresent = al.slots[idx][slot]
    57  	return true, slotPresent
    58  }
    59  
    60  // newAccessList creates a new accessList.
    61  func newAccessList() *accessList {
    62  	return &accessList{
    63  		addresses: make(map[common.Address]int),
    64  	}
    65  }
    66  
    67  // Copy creates an independent copy of an accessList.
    68  func (a *accessList) Copy() *accessList {
    69  	cp := newAccessList()
    70  	for k, v := range a.addresses {
    71  		cp.addresses[k] = v
    72  	}
    73  	cp.slots = make([]map[common.Hash]struct{}, len(a.slots))
    74  	for i, slotMap := range a.slots {
    75  		newSlotmap := make(map[common.Hash]struct{}, len(slotMap))
    76  		for k := range slotMap {
    77  			newSlotmap[k] = struct{}{}
    78  		}
    79  		cp.slots[i] = newSlotmap
    80  	}
    81  	return cp
    82  }
    83  
    84  // AddAddress adds an address to the access list, and returns 'true' if the operation
    85  // caused a change (addr was not previously in the list).
    86  func (al *accessList) AddAddress(address common.Address) bool {
    87  	if _, present := al.addresses[address]; present {
    88  		return false
    89  	}
    90  	al.addresses[address] = -1
    91  	return true
    92  }
    93  
    94  // AddSlot adds the specified (addr, slot) combo to the access list.
    95  // Return values are:
    96  // - address added
    97  // - slot added
    98  // For any 'true' value returned, a corresponding journal entry must be made.
    99  func (al *accessList) AddSlot(address common.Address, slot common.Hash) (addrChange bool, slotChange bool) {
   100  	idx, addrPresent := al.addresses[address]
   101  	if !addrPresent || idx == -1 {
   102  		// Address not present, or addr present but no slots there
   103  		al.addresses[address] = len(al.slots)
   104  		slotmap := map[common.Hash]struct{}{slot: {}}
   105  		al.slots = append(al.slots, slotmap)
   106  		return !addrPresent, true
   107  	}
   108  	// There is already an (address,slot) mapping
   109  	slotmap := al.slots[idx]
   110  	if _, ok := slotmap[slot]; !ok {
   111  		slotmap[slot] = struct{}{}
   112  		// Journal add slot change
   113  		return false, true
   114  	}
   115  	// No changes required
   116  	return false, false
   117  }
   118  
   119  // DeleteSlot removes an (address, slot)-tuple from the access list.
   120  // This operation needs to be performed in the same order as the addition happened.
   121  // This method is meant to be used  by the journal, which maintains ordering of
   122  // operations.
   123  func (al *accessList) DeleteSlot(address common.Address, slot common.Hash) {
   124  	idx, addrOk := al.addresses[address]
   125  	// There are two ways this can fail
   126  	if !addrOk {
   127  		panic("reverting slot change, address not present in list")
   128  	}
   129  	slotmap := al.slots[idx]
   130  	delete(slotmap, slot)
   131  	// If that was the last (first) slot, remove it
   132  	// Since additions and rollbacks are always performed in order,
   133  	// we can delete the item without worrying about screwing up later indices
   134  	if len(slotmap) == 0 {
   135  		al.slots = al.slots[:idx]
   136  		al.addresses[address] = -1
   137  	}
   138  }
   139  
   140  // DeleteAddress removes an address from the access list. This operation
   141  // needs to be performed in the same order as the addition happened.
   142  // This method is meant to be used  by the journal, which maintains ordering of
   143  // operations.
   144  func (al *accessList) DeleteAddress(address common.Address) {
   145  	delete(al.addresses, address)
   146  }