Skip to content

Commit

Permalink
Merge pull request #1767 from OffchainLabs/cache-storage-keys
Browse files Browse the repository at this point in the history
Cache storage keys
  • Loading branch information
joshuacolvin0 authored Oct 24, 2023
2 parents 923a852 + b5b5e5d commit 5386672
Show file tree
Hide file tree
Showing 12 changed files with 284 additions and 153 deletions.
92 changes: 47 additions & 45 deletions arbos/addressSet/addressSet.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

package addressSet

// TODO lowercase this package name

import (
"errors"

Expand All @@ -26,49 +28,49 @@ func Initialize(sto *storage.Storage) error {

func OpenAddressSet(sto *storage.Storage) *AddressSet {
return &AddressSet{
sto,
sto.OpenStorageBackedUint64(0),
sto.OpenSubStorage([]byte{0}),
backingStorage: sto.WithoutCache(),
size: sto.OpenStorageBackedUint64(0),
byAddress: sto.OpenSubStorage([]byte{0}),
}
}

func (aset *AddressSet) Size() (uint64, error) {
return aset.size.Get()
func (as *AddressSet) Size() (uint64, error) {
return as.size.Get()
}

func (aset *AddressSet) IsMember(addr common.Address) (bool, error) {
value, err := aset.byAddress.Get(util.AddressToHash(addr))
func (as *AddressSet) IsMember(addr common.Address) (bool, error) {
value, err := as.byAddress.Get(util.AddressToHash(addr))
return value != (common.Hash{}), err
}

func (aset *AddressSet) GetAnyMember() (*common.Address, error) {
size, err := aset.size.Get()
func (as *AddressSet) GetAnyMember() (*common.Address, error) {
size, err := as.size.Get()
if err != nil || size == 0 {
return nil, err
}
sba := aset.backingStorage.OpenStorageBackedAddressOrNil(1)
sba := as.backingStorage.OpenStorageBackedAddressOrNil(1)
addr, err := sba.Get()
return addr, err
}

func (aset *AddressSet) Clear() error {
size, err := aset.size.Get()
func (as *AddressSet) Clear() error {
size, err := as.size.Get()
if err != nil || size == 0 {
return err
}
for i := uint64(1); i <= size; i++ {
contents, _ := aset.backingStorage.GetByUint64(i)
_ = aset.backingStorage.ClearByUint64(i)
err = aset.byAddress.Clear(contents)
contents, _ := as.backingStorage.GetByUint64(i)
_ = as.backingStorage.ClearByUint64(i)
err = as.byAddress.Clear(contents)
if err != nil {
return err
}
}
return aset.size.Clear()
return as.size.Clear()
}

func (aset *AddressSet) AllMembers(maxNumToReturn uint64) ([]common.Address, error) {
size, err := aset.size.Get()
func (as *AddressSet) AllMembers(maxNumToReturn uint64) ([]common.Address, error) {
size, err := as.size.Get()
if err != nil {
return nil, err
}
Expand All @@ -77,7 +79,7 @@ func (aset *AddressSet) AllMembers(maxNumToReturn uint64) ([]common.Address, err
}
ret := make([]common.Address, size)
for i := range ret {
sba := aset.backingStorage.OpenStorageBackedAddress(uint64(i + 1))
sba := as.backingStorage.OpenStorageBackedAddress(uint64(i + 1))
ret[i], err = sba.Get()
if err != nil {
return nil, err
Expand All @@ -86,38 +88,38 @@ func (aset *AddressSet) AllMembers(maxNumToReturn uint64) ([]common.Address, err
return ret, nil
}

func (aset *AddressSet) ClearList() error {
size, err := aset.size.Get()
func (as *AddressSet) ClearList() error {
size, err := as.size.Get()
if err != nil || size == 0 {
return err
}
for i := uint64(1); i <= size; i++ {
err = aset.backingStorage.ClearByUint64(i)
err = as.backingStorage.ClearByUint64(i)
if err != nil {
return err
}
}
return aset.size.Clear()
return as.size.Clear()
}

func (aset *AddressSet) RectifyMapping(addr common.Address) error {
isOwner, err := aset.IsMember(addr)
func (as *AddressSet) RectifyMapping(addr common.Address) error {
isOwner, err := as.IsMember(addr)
if !isOwner || err != nil {
return errors.New("RectifyMapping: Address is not an owner")
}

// If the mapping is correct, RectifyMapping shouldn't do anything
// Additional safety check to avoid corruption of mapping after the initial fix
addrAsHash := common.BytesToHash(addr.Bytes())
slot, err := aset.byAddress.GetUint64(addrAsHash)
slot, err := as.byAddress.GetUint64(addrAsHash)
if err != nil {
return err
}
atSlot, err := aset.backingStorage.GetByUint64(slot)
atSlot, err := as.backingStorage.GetByUint64(slot)
if err != nil {
return err
}
size, err := aset.size.Get()
size, err := as.size.Get()
if err != nil {
return err
}
Expand All @@ -126,72 +128,72 @@ func (aset *AddressSet) RectifyMapping(addr common.Address) error {
}

// Remove the owner from map and add them as a new owner
err = aset.byAddress.Clear(addrAsHash)
err = as.byAddress.Clear(addrAsHash)
if err != nil {
return err
}

return aset.Add(addr)
return as.Add(addr)
}

func (aset *AddressSet) Add(addr common.Address) error {
present, err := aset.IsMember(addr)
func (as *AddressSet) Add(addr common.Address) error {
present, err := as.IsMember(addr)
if present || err != nil {
return err
}
size, err := aset.size.Get()
size, err := as.size.Get()
if err != nil {
return err
}
slot := util.UintToHash(1 + size)
addrAsHash := common.BytesToHash(addr.Bytes())
err = aset.byAddress.Set(addrAsHash, slot)
err = as.byAddress.Set(addrAsHash, slot)
if err != nil {
return err
}
sba := aset.backingStorage.OpenStorageBackedAddress(1 + size)
sba := as.backingStorage.OpenStorageBackedAddress(1 + size)
err = sba.Set(addr)
if err != nil {
return err
}
_, err = aset.size.Increment()
_, err = as.size.Increment()
return err
}

func (aset *AddressSet) Remove(addr common.Address, arbosVersion uint64) error {
func (as *AddressSet) Remove(addr common.Address, arbosVersion uint64) error {
addrAsHash := common.BytesToHash(addr.Bytes())
slot, err := aset.byAddress.GetUint64(addrAsHash)
slot, err := as.byAddress.GetUint64(addrAsHash)
if slot == 0 || err != nil {
return err
}
err = aset.byAddress.Clear(addrAsHash)
err = as.byAddress.Clear(addrAsHash)
if err != nil {
return err
}
size, err := aset.size.Get()
size, err := as.size.Get()
if err != nil {
return err
}
if slot < size {
atSize, err := aset.backingStorage.GetByUint64(size)
atSize, err := as.backingStorage.GetByUint64(size)
if err != nil {
return err
}
err = aset.backingStorage.SetByUint64(slot, atSize)
err = as.backingStorage.SetByUint64(slot, atSize)
if err != nil {
return err
}
if arbosVersion >= 11 {
err = aset.byAddress.Set(atSize, util.UintToHash(slot))
err = as.byAddress.Set(atSize, util.UintToHash(slot))
if err != nil {
return err
}
}
}
err = aset.backingStorage.ClearByUint64(size)
err = as.backingStorage.ClearByUint64(size)
if err != nil {
return err
}
_, err = aset.size.Decrement()
_, err = as.size.Decrement()
return err
}
4 changes: 3 additions & 1 deletion arbos/addressTable/addressTable.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

package addressTable

// TODO lowercase this package name

import (
"bytes"
"errors"
Expand All @@ -25,7 +27,7 @@ func Initialize(sto *storage.Storage) {

func Open(sto *storage.Storage) *AddressTable {
numItems := sto.OpenStorageBackedUint64(0)
return &AddressTable{sto, sto.OpenSubStorage([]byte{}), numItems}
return &AddressTable{sto.WithoutCache(), sto.OpenSubStorage([]byte{}), numItems}
}

func (atab *AddressTable) Register(addr common.Address) (uint64, error) {
Expand Down
32 changes: 16 additions & 16 deletions arbos/arbosState/arbosstate.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,13 @@ func OpenArbosState(stateDB vm.StateDB, burner burn.Burner) (*ArbosState, error)
backingStorage.OpenStorageBackedUint64(uint64(upgradeVersionOffset)),
backingStorage.OpenStorageBackedUint64(uint64(upgradeTimestampOffset)),
backingStorage.OpenStorageBackedAddress(uint64(networkFeeAccountOffset)),
l1pricing.OpenL1PricingState(backingStorage.OpenSubStorage(l1PricingSubspace)),
l2pricing.OpenL2PricingState(backingStorage.OpenSubStorage(l2PricingSubspace)),
retryables.OpenRetryableState(backingStorage.OpenSubStorage(retryablesSubspace), stateDB),
addressTable.Open(backingStorage.OpenSubStorage(addressTableSubspace)),
addressSet.OpenAddressSet(backingStorage.OpenSubStorage(chainOwnerSubspace)),
merkleAccumulator.OpenMerkleAccumulator(backingStorage.OpenSubStorage(sendMerkleSubspace)),
blockhash.OpenBlockhashes(backingStorage.OpenSubStorage(blockhashesSubspace)),
l1pricing.OpenL1PricingState(backingStorage.OpenCachedSubStorage(l1PricingSubspace)),
l2pricing.OpenL2PricingState(backingStorage.OpenCachedSubStorage(l2PricingSubspace)),
retryables.OpenRetryableState(backingStorage.OpenCachedSubStorage(retryablesSubspace), stateDB),
addressTable.Open(backingStorage.OpenCachedSubStorage(addressTableSubspace)),
addressSet.OpenAddressSet(backingStorage.OpenCachedSubStorage(chainOwnerSubspace)),
merkleAccumulator.OpenMerkleAccumulator(backingStorage.OpenCachedSubStorage(sendMerkleSubspace)),
blockhash.OpenBlockhashes(backingStorage.OpenCachedSubStorage(blockhashesSubspace)),
backingStorage.OpenStorageBackedBigInt(uint64(chainIdOffset)),
backingStorage.OpenStorageBackedBytes(chainConfigSubspace),
backingStorage.OpenStorageBackedUint64(uint64(genesisBlockNumOffset)),
Expand Down Expand Up @@ -225,14 +225,14 @@ func InitializeArbosState(stateDB vm.StateDB, burner burn.Burner, chainConfig *p
if desiredArbosVersion >= 2 {
initialRewardsRecipient = initialChainOwner
}
_ = l1pricing.InitializeL1PricingState(sto.OpenSubStorage(l1PricingSubspace), initialRewardsRecipient, initMessage.InitialL1BaseFee)
_ = l2pricing.InitializeL2PricingState(sto.OpenSubStorage(l2PricingSubspace))
_ = retryables.InitializeRetryableState(sto.OpenSubStorage(retryablesSubspace))
addressTable.Initialize(sto.OpenSubStorage(addressTableSubspace))
merkleAccumulator.InitializeMerkleAccumulator(sto.OpenSubStorage(sendMerkleSubspace))
blockhash.InitializeBlockhashes(sto.OpenSubStorage(blockhashesSubspace))

ownersStorage := sto.OpenSubStorage(chainOwnerSubspace)
_ = l1pricing.InitializeL1PricingState(sto.OpenCachedSubStorage(l1PricingSubspace), initialRewardsRecipient, initMessage.InitialL1BaseFee)
_ = l2pricing.InitializeL2PricingState(sto.OpenCachedSubStorage(l2PricingSubspace))
_ = retryables.InitializeRetryableState(sto.OpenCachedSubStorage(retryablesSubspace))
addressTable.Initialize(sto.OpenCachedSubStorage(addressTableSubspace))
merkleAccumulator.InitializeMerkleAccumulator(sto.OpenCachedSubStorage(sendMerkleSubspace))
blockhash.InitializeBlockhashes(sto.OpenCachedSubStorage(blockhashesSubspace))

ownersStorage := sto.OpenCachedSubStorage(chainOwnerSubspace)
_ = addressSet.Initialize(ownersStorage)
_ = addressSet.OpenAddressSet(ownersStorage).Add(initialChainOwner)

Expand Down Expand Up @@ -428,7 +428,7 @@ func (state *ArbosState) ChainOwners() *addressSet.AddressSet {

func (state *ArbosState) SendMerkleAccumulator() *merkleAccumulator.MerkleAccumulator {
if state.sendMerkle == nil {
state.sendMerkle = merkleAccumulator.OpenMerkleAccumulator(state.backingStorage.OpenSubStorage(sendMerkleSubspace))
state.sendMerkle = merkleAccumulator.OpenMerkleAccumulator(state.backingStorage.OpenCachedSubStorage(sendMerkleSubspace))
}
return state.sendMerkle
}
Expand Down
2 changes: 1 addition & 1 deletion arbos/arbosState/arbosstate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func TestStorageBackedInt64(t *testing.T) {

func TestStorageSlots(t *testing.T) {
state, _ := NewArbosMemoryBackedArbOSState()
sto := state.BackingStorage().OpenSubStorage([]byte{})
sto := state.BackingStorage().OpenCachedSubStorage([]byte{})

println("nil address", colors.Blue, storage.NilAddressRepresentation.String(), colors.Clear)

Expand Down
2 changes: 1 addition & 1 deletion arbos/blockhash/blockhash.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func InitializeBlockhashes(backingStorage *storage.Storage) {
}

func OpenBlockhashes(backingStorage *storage.Storage) *Blockhashes {
return &Blockhashes{backingStorage, backingStorage.OpenStorageBackedUint64(0)}
return &Blockhashes{backingStorage.WithoutCache(), backingStorage.OpenStorageBackedUint64(0)}
}

func (bh *Blockhashes) L1BlockNumber() (uint64, error) {
Expand Down
4 changes: 2 additions & 2 deletions arbos/l1pricing/batchPoster.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ func InitializeBatchPostersTable(storage *storage.Storage) error {
if err := totalFundsDue.SetChecked(common.Big0); err != nil {
return err
}
return addressSet.Initialize(storage.OpenSubStorage(PosterAddrsKey))
return addressSet.Initialize(storage.OpenCachedSubStorage(PosterAddrsKey))
}

func OpenBatchPostersTable(storage *storage.Storage) *BatchPostersTable {
return &BatchPostersTable{
posterAddrs: addressSet.OpenAddressSet(storage.OpenSubStorage(PosterAddrsKey)),
posterAddrs: addressSet.OpenAddressSet(storage.OpenCachedSubStorage(PosterAddrsKey)),
posterInfo: storage.OpenSubStorage(PosterInfoKey),
totalFundsDue: storage.OpenStorageBackedBigInt(totalFundsDueOffset),
}
Expand Down
4 changes: 2 additions & 2 deletions arbos/l1pricing/l1pricing.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ var InitialEquilibrationUnitsV0 = arbmath.UintToBig(60 * params.TxDataNonZeroGas
var InitialEquilibrationUnitsV6 = arbmath.UintToBig(params.TxDataNonZeroGasEIP2028 * 10000000)

func InitializeL1PricingState(sto *storage.Storage, initialRewardsRecipient common.Address, initialL1BaseFee *big.Int) error {
bptStorage := sto.OpenSubStorage(BatchPosterTableKey)
bptStorage := sto.OpenCachedSubStorage(BatchPosterTableKey)
if err := InitializeBatchPostersTable(bptStorage); err != nil {
return err
}
Expand Down Expand Up @@ -118,7 +118,7 @@ func InitializeL1PricingState(sto *storage.Storage, initialRewardsRecipient comm
func OpenL1PricingState(sto *storage.Storage) *L1PricingState {
return &L1PricingState{
sto,
OpenBatchPostersTable(sto.OpenSubStorage(BatchPosterTableKey)),
OpenBatchPostersTable(sto.OpenCachedSubStorage(BatchPosterTableKey)),
sto.OpenStorageBackedAddress(payRewardsToOffset),
sto.OpenStorageBackedBigUint(equilibrationUnitsOffset),
sto.OpenStorageBackedUint64(inertiaOffset),
Expand Down
2 changes: 1 addition & 1 deletion arbos/queue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (

func TestQueue(t *testing.T) {
state, statedb := arbosState.NewArbosMemoryBackedArbOSState()
sto := state.BackingStorage().OpenSubStorage([]byte{})
sto := state.BackingStorage().OpenCachedSubStorage([]byte{})
Require(t, storage.InitializeQueue(sto))
q := storage.OpenQueue(sto)

Expand Down
5 changes: 3 additions & 2 deletions arbos/retryables/retryable.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ var (
)

func InitializeRetryableState(sto *storage.Storage) error {
return storage.InitializeQueue(sto.OpenSubStorage(timeoutQueueKey))
return storage.InitializeQueue(sto.OpenCachedSubStorage(timeoutQueueKey))
}

func OpenRetryableState(sto *storage.Storage, statedb vm.StateDB) *RetryableState {
return &RetryableState{
sto,
storage.OpenQueue(sto.OpenSubStorage(timeoutQueueKey)),
storage.OpenQueue(sto.OpenCachedSubStorage(timeoutQueueKey)),
}
}

Expand Down Expand Up @@ -150,6 +150,7 @@ func (rs *RetryableState) DeleteRetryable(id common.Hash, evm *vm.EVM, scenario
return false, err
}

// we ignore returned error as we expect that if one ClearByUint64 fails, than all consecutive calls to ClearByUint64 will fail with the same error (not modifying state), and then ClearBytes will also fail with the same error (also not modifying state) - and this one we check and return
_ = retStorage.ClearByUint64(numTriesOffset)
_ = retStorage.ClearByUint64(fromOffset)
_ = retStorage.ClearByUint64(toOffset)
Expand Down
2 changes: 1 addition & 1 deletion arbos/storage/queue.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func InitializeQueue(sto *Storage) error {

func OpenQueue(sto *Storage) *Queue {
return &Queue{
sto,
sto.WithoutCache(),
sto.OpenStorageBackedUint64(0),
sto.OpenStorageBackedUint64(1),
}
Expand Down
Loading

0 comments on commit 5386672

Please sign in to comment.