bitxhub/internal/ledger/access_list.go

104 lines
2.3 KiB
Go

package ledger
import "github.com/meshplus/bitxhub-kit/types"
type AccessList []AccessTuple
type AccessTuple struct {
Address types.Address `json:"address" gencodec:"required"`
StorageKeys []types.Hash `json:"storageKeys" gencodec:"required"`
}
func (al AccessList) StorageKeys() int {
sum := 0
for _, tuple := range al {
sum += len(tuple.StorageKeys)
}
return sum
}
type accessList struct {
addresses map[types.Address]int
slots []map[types.Hash]struct{}
}
func (al *accessList) ContainsAddress(addr types.Address) bool {
_, ok := al.addresses[addr]
return ok
}
func (al *accessList) Contains(addr types.Address, slot types.Hash) (bool, bool) {
idx, ok := al.addresses[addr]
if !ok {
return false, false
}
if idx == -1 {
return true, false
}
_, slotPresent := al.slots[idx][slot]
return true, slotPresent
}
func newAccessList() *accessList {
return &accessList{
addresses: make(map[types.Address]int),
}
}
func (al *accessList) Copy() *accessList {
cp := newAccessList()
for k, v := range al.addresses {
cp.addresses[k] = v
}
cp.slots = make([]map[types.Hash]struct{}, len(al.slots))
for i, slotMap := range al.slots {
newSlotmap := make(map[types.Hash]struct{}, len(slotMap))
for k := range slotMap {
newSlotmap[k] = struct{}{}
}
cp.slots[i] = newSlotmap
}
return cp
}
func (al *accessList) AddAddress(address types.Address) bool {
if _, present := al.addresses[address]; present {
return false
}
al.addresses[address] = -1
return true
}
func (al *accessList) AddSlot(address types.Address, slot types.Hash) (bool, bool) {
idx, addrPresent := al.addresses[address]
if !addrPresent || idx == -1 {
al.addresses[address] = len(al.slots)
slotmap := map[types.Hash]struct{}{slot: {}}
al.slots = append(al.slots, slotmap)
return !addrPresent, true
}
slotmap := al.slots[idx]
if _, ok := slotmap[slot]; !ok {
slotmap[slot] = struct{}{}
return false, true
}
return false, false
}
func (al *accessList) DeleteSlot(address types.Address, slot types.Hash) {
idx, ok := al.addresses[address]
if !ok {
panic("reverting slot change, address not present in list")
}
slotmap := al.slots[idx]
delete(slotmap, slot)
if len(slotmap) == 0 {
al.slots = al.slots[:idx]
al.addresses[address] = -1
}
}
func (al *accessList) DeleteAddress(address types.Address) {
delete(al.addresses, address)
}