forked from cerc-io/laconicd-deprecated
evm: use TransientStore for AccessList (#75)
* evm: use transient store for access list * evm: remove address and slot access list mappings * update tests * update * changelog * update types
This commit is contained in:
@@ -45,12 +45,6 @@ type Keeper struct {
|
||||
// Ethermint concrete implementation on the EVM StateDB interface
|
||||
CommitStateDB *types.CommitStateDB
|
||||
|
||||
// Per-transaction access list
|
||||
// See EIP-2930 for more info: https://eips.ethereum.org/EIPS/eip-2930
|
||||
// TODO: (@fedekunze) for how long should we persist the entries in the access list?
|
||||
// same block (i.e Transient Store)? 2 or more (KVStore with module Parameter which resets the state after that window)?
|
||||
accessList *types.AccessListMappings
|
||||
|
||||
// hash header for the current height. Reset during abci.RequestBeginBlock
|
||||
headerHash common.Hash
|
||||
}
|
||||
@@ -73,8 +67,7 @@ func NewKeeper(
|
||||
bankKeeper: bankKeeper,
|
||||
storeKey: storeKey,
|
||||
transientKey: transientKey,
|
||||
CommitStateDB: types.NewCommitStateDB(sdk.Context{}, storeKey, paramSpace, ak, bankKeeper),
|
||||
accessList: types.NewAccessListMappings(),
|
||||
CommitStateDB: types.NewCommitStateDB(sdk.Context{}, storeKey, transientKey, paramSpace, ak, bankKeeper),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+26
-15
@@ -493,37 +493,48 @@ func (k *Keeper) PrepareAccessList(sender common.Address, dest *common.Address,
|
||||
}
|
||||
}
|
||||
|
||||
// AddressInAccessList returns true if the address is registered on the access list map.
|
||||
// AddressInAccessList returns true if the address is registered on the transient store.
|
||||
func (k *Keeper) AddressInAccessList(addr common.Address) bool {
|
||||
return k.accessList.ContainsAddress(addr)
|
||||
ts := prefix.NewStore(k.ctx.TransientStore(k.transientKey), types.KeyPrefixTransientAccessListAddress)
|
||||
return ts.Has(addr.Bytes())
|
||||
}
|
||||
|
||||
// SlotInAccessList checks if the address and the slots are registered in the transient store
|
||||
func (k *Keeper) SlotInAccessList(addr common.Address, slot common.Hash) (addressOk bool, slotOk bool) {
|
||||
return k.accessList.Contains(addr, slot)
|
||||
addressOk = k.AddressInAccessList(addr)
|
||||
slotOk = k.addressSlotInAccessList(addr, slot)
|
||||
return addressOk, slotOk
|
||||
}
|
||||
|
||||
// AddAddressToAccessList adds the given address to the access list. This operation is safe to perform
|
||||
// even if the feature/fork is not active yet
|
||||
// addressSlotInAccessList returns true if the address's slot is registered on the transient store.
|
||||
func (k *Keeper) addressSlotInAccessList(addr common.Address, slot common.Hash) bool {
|
||||
ts := prefix.NewStore(k.ctx.TransientStore(k.transientKey), types.KeyPrefixTransientAccessListSlot)
|
||||
key := append(addr.Bytes(), slot.Bytes()...)
|
||||
return ts.Has(key)
|
||||
}
|
||||
|
||||
// AddAddressToAccessList adds the given address to the access list. If the address is already
|
||||
// in the access list, this function performs a no-op.
|
||||
func (k *Keeper) AddAddressToAccessList(addr common.Address) {
|
||||
// NOTE: only update the access list during DeliverTx
|
||||
if k.ctx.IsCheckTx() || k.ctx.IsReCheckTx() {
|
||||
if k.AddressInAccessList(addr) {
|
||||
return
|
||||
}
|
||||
|
||||
// NOTE: ignore change return bool because we don't have to keep a journal for state changes
|
||||
_ = k.accessList.AddAddress(addr)
|
||||
ts := prefix.NewStore(k.ctx.TransientStore(k.transientKey), types.KeyPrefixTransientAccessListAddress)
|
||||
ts.Set(addr.Bytes(), []byte{0x1})
|
||||
}
|
||||
|
||||
// AddSlotToAccessList adds the given (address,slot) to the access list. This operation is safe to perform
|
||||
// even if the feature/fork is not active yet
|
||||
// AddSlotToAccessList adds the given (address, slot) to the access list. If the address and slot are
|
||||
// already in the access list, this function performs a no-op.
|
||||
func (k *Keeper) AddSlotToAccessList(addr common.Address, slot common.Hash) {
|
||||
// NOTE: only update the access list during DeliverTx
|
||||
if k.ctx.IsCheckTx() || k.ctx.IsReCheckTx() {
|
||||
k.AddAddressToAccessList(addr)
|
||||
if k.addressSlotInAccessList(addr, slot) {
|
||||
return
|
||||
}
|
||||
|
||||
// NOTE: ignore change return booleans because we don't have to keep a journal for state changes
|
||||
_, _ = k.accessList.AddSlot(addr, slot)
|
||||
ts := prefix.NewStore(k.ctx.TransientStore(k.transientKey), types.KeyPrefixTransientAccessListSlot)
|
||||
key := append(addr.Bytes(), slot.Bytes()...)
|
||||
ts.Set(key, []byte{0x1})
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -506,7 +506,7 @@ func (suite *KeeperTestSuite) TestAddLog() {
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestAccessList() {
|
||||
func (suite *KeeperTestSuite) TestPrepareAccessList() {
|
||||
dest := tests.GenerateAddress()
|
||||
precompiles := []common.Address{tests.GenerateAddress(), tests.GenerateAddress()}
|
||||
accesses := ethtypes.AccessList{
|
||||
@@ -526,12 +526,52 @@ func (suite *KeeperTestSuite) TestAccessList() {
|
||||
for _, access := range accesses {
|
||||
for _, key := range access.StorageKeys {
|
||||
addrOK, slotOK := suite.app.EvmKeeper.SlotInAccessList(access.Address, key)
|
||||
suite.Require().True(addrOK)
|
||||
suite.Require().True(slotOK)
|
||||
suite.Require().True(addrOK, access.Address.Hex())
|
||||
suite.Require().True(slotOK, key.Hex())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestAddAddressToAccessList() {
|
||||
testCases := []struct {
|
||||
name string
|
||||
addr common.Address
|
||||
}{
|
||||
{"new address", suite.address},
|
||||
{"existing address", suite.address},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.app.EvmKeeper.AddAddressToAccessList(tc.addr)
|
||||
addrOk := suite.app.EvmKeeper.AddressInAccessList(tc.addr)
|
||||
suite.Require().True(addrOk, tc.addr.Hex())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) AddSlotToAccessList() {
|
||||
testCases := []struct {
|
||||
name string
|
||||
addr common.Address
|
||||
slot common.Hash
|
||||
}{
|
||||
{"new address and slot (1)", tests.GenerateAddress(), common.BytesToHash([]byte("hash"))},
|
||||
{"new address and slot (2)", suite.address, common.Hash{}},
|
||||
{"existing address and slot", suite.address, common.Hash{}},
|
||||
{"existing address, new slot", suite.address, common.BytesToHash([]byte("hash"))},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.app.EvmKeeper.AddSlotToAccessList(tc.addr, tc.slot)
|
||||
addrOk, slotOk := suite.app.EvmKeeper.SlotInAccessList(tc.addr, tc.slot)
|
||||
suite.Require().True(addrOk, tc.addr.Hex())
|
||||
suite.Require().True(slotOk, tc.slot.Hex())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestForEachStorage() {
|
||||
var storage types.Storage
|
||||
|
||||
|
||||
Reference in New Issue
Block a user