forked from cerc-io/laconicd-deprecated
deps: update go-ethereum to v1.9.24 (#594)
* update to go-ethereum v1.9.24 * go mod tidy * add YoloV2 to chain config * add accessList and implement csdb accessList funcs * cleanup * access list tests * changelog * add stateDB test * test Copy Co-authored-by: Federico Kunze <federico.kunze94@gmail.com>
This commit is contained in:
parent
73e5eb5e98
commit
2796f55b02
@ -51,6 +51,10 @@ corresponding Ethereum API namespace:
|
||||
|
||||
* (evm) [\#588](https://github.com/cosmos/ethermint/pull/588) The EVM transaction CLI has been removed in favor of the JSON-RPC.
|
||||
|
||||
### Improvements
|
||||
|
||||
* (deps) [\#594](https://github.com/cosmos/ethermint/pull/594) Bump go-ethereum version to [v1.9.24](https://github.com/ethereum/go-ethereum/releases/tag/v1.9.24)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* (ante) [\#597](https://github.com/cosmos/ethermint/pull/597) Fix incorrect fee check on `AnteHandler`.
|
||||
|
2
go.mod
2
go.mod
@ -9,7 +9,7 @@ require (
|
||||
github.com/cespare/cp v1.1.1 // indirect
|
||||
github.com/cosmos/cosmos-sdk v0.39.1
|
||||
github.com/deckarep/golang-set v1.7.1 // indirect
|
||||
github.com/ethereum/go-ethereum v1.9.21
|
||||
github.com/ethereum/go-ethereum v1.9.24
|
||||
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
|
12
go.sum
12
go.sum
@ -164,6 +164,7 @@ github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbT
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dvsekhvalnov/jose2go v0.0.0-20180829124132-7f401d37b68a h1:mq+R6XEM6lJX5VlLyZIrUSP8tSuJp82xTK89hvBwJbU=
|
||||
github.com/dvsekhvalnov/jose2go v0.0.0-20180829124132-7f401d37b68a/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM=
|
||||
github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
|
||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
@ -178,8 +179,8 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/ethereum/go-ethereum v1.9.5/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY=
|
||||
github.com/ethereum/go-ethereum v1.9.21 h1:8qRlhzrItnmUGdVlBzZLI2Tb46S0RdSNjFwICo781ws=
|
||||
github.com/ethereum/go-ethereum v1.9.21/go.mod h1:RXAVzbGrSGmDkDnHymruTAIEjUR3E4TX0EOpaj702sI=
|
||||
github.com/ethereum/go-ethereum v1.9.24 h1:6AK+ORt3EMDO+FTjzXy/AQwHMbu52J2nYHIjyQX9azQ=
|
||||
github.com/ethereum/go-ethereum v1.9.24/go.mod h1:JIfVb6esrqALTExdz9hRYvrP0xBDf6wCncIu1hNwHpM=
|
||||
github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ=
|
||||
github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64=
|
||||
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A=
|
||||
@ -264,6 +265,8 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64=
|
||||
github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
@ -703,6 +706,7 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
|
||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
@ -716,10 +720,12 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mobile v0.0.0-20200801112145-973feb4309de/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee h1:WG0RUwxtNT4qqaXX3DPA8zHFNm/D9xaBpxzHt1WcA/E=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@ -834,7 +840,9 @@ golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtn
|
||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200221224223-e1da425f72fd h1:hHkvGJK23seRCflePJnVa9IMv8fsuavSCWKd11kDQFs=
|
||||
golang.org/x/tools v0.0.0-20200221224223-e1da425f72fd/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -62,7 +62,7 @@ func (suite *KeeperTestSuite) TestBloomFilter() {
|
||||
} else {
|
||||
// get logs bloom from the log
|
||||
bloomInt := ethtypes.LogsBloom(logs)
|
||||
bloomFilter := ethtypes.BytesToBloom(bloomInt.Bytes())
|
||||
bloomFilter := ethtypes.BytesToBloom(bloomInt)
|
||||
suite.Require().True(ethtypes.BloomLookup(bloomFilter, contractAddress), tc.name)
|
||||
suite.Require().False(ethtypes.BloomLookup(bloomFilter, ethcmn.BigToAddress(big.NewInt(2))), tc.name)
|
||||
}
|
||||
|
134
x/evm/types/access_list.go
Normal file
134
x/evm/types/access_list.go
Normal file
@ -0,0 +1,134 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
// accessList is copied from go-ethereum
|
||||
// https://github.com/ethereum/go-ethereum/blob/cf856ea1ad96ac39ea477087822479b63417036a/core/state/access_list.go#L23
|
||||
type accessList struct {
|
||||
addresses map[common.Address]int
|
||||
slots []map[common.Hash]struct{}
|
||||
}
|
||||
|
||||
// ContainsAddress returns true if the address is in the access list.
|
||||
func (al *accessList) ContainsAddress(address common.Address) bool {
|
||||
_, ok := al.addresses[address]
|
||||
return ok
|
||||
}
|
||||
|
||||
// Contains checks if a slot within an account is present in the access list, returning
|
||||
// separate flags for the presence of the account and the slot respectively.
|
||||
func (al *accessList) Contains(address common.Address, slot common.Hash) (addressPresent bool, slotPresent bool) {
|
||||
idx, ok := al.addresses[address]
|
||||
if !ok {
|
||||
// no such address (and hence zero slots)
|
||||
return false, false
|
||||
}
|
||||
if idx == -1 {
|
||||
// address yes, but no slots
|
||||
return true, false
|
||||
}
|
||||
|
||||
if idx >= len(al.slots) {
|
||||
// return in case of out-of-range
|
||||
return true, false
|
||||
}
|
||||
|
||||
_, slotPresent = al.slots[idx][slot]
|
||||
return true, slotPresent
|
||||
}
|
||||
|
||||
// newAccessList creates a new accessList.
|
||||
func newAccessList() *accessList {
|
||||
return &accessList{
|
||||
addresses: make(map[common.Address]int),
|
||||
}
|
||||
}
|
||||
|
||||
// Copy creates an independent copy of an accessList.
|
||||
func (al *accessList) Copy() *accessList {
|
||||
cp := newAccessList()
|
||||
for k, v := range al.addresses {
|
||||
cp.addresses[k] = v
|
||||
}
|
||||
cp.slots = make([]map[common.Hash]struct{}, len(al.slots))
|
||||
for i, slotMap := range al.slots {
|
||||
newSlotmap := make(map[common.Hash]struct{}, len(slotMap))
|
||||
for k := range slotMap {
|
||||
newSlotmap[k] = struct{}{}
|
||||
}
|
||||
cp.slots[i] = newSlotmap
|
||||
}
|
||||
return cp
|
||||
}
|
||||
|
||||
// AddAddress adds an address to the access list, and returns 'true' if the operation
|
||||
// caused a change (addr was not previously in the list).
|
||||
func (al *accessList) AddAddress(address common.Address) bool {
|
||||
if _, present := al.addresses[address]; present {
|
||||
return false
|
||||
}
|
||||
al.addresses[address] = -1
|
||||
return true
|
||||
}
|
||||
|
||||
// AddSlot adds the specified (addr, slot) combo to the access list.
|
||||
// Return values are:
|
||||
// - address added
|
||||
// - slot added
|
||||
// For any 'true' value returned, a corresponding journal entry must be made.
|
||||
func (al *accessList) AddSlot(address common.Address, slot common.Hash) (addrChange bool, slotChange bool) {
|
||||
idx, addrPresent := al.addresses[address]
|
||||
if !addrPresent || idx == -1 {
|
||||
// Address not present, or addr present but no slots there
|
||||
al.addresses[address] = len(al.slots)
|
||||
slotmap := map[common.Hash]struct{}{slot: {}}
|
||||
al.slots = append(al.slots, slotmap)
|
||||
return !addrPresent, true
|
||||
}
|
||||
|
||||
if idx >= len(al.slots) {
|
||||
// return in case of out-of-range
|
||||
return false, false
|
||||
}
|
||||
|
||||
// There is already an (address,slot) mapping
|
||||
slotmap := al.slots[idx]
|
||||
if _, ok := slotmap[slot]; !ok {
|
||||
slotmap[slot] = struct{}{}
|
||||
// Journal add slot change
|
||||
return false, true
|
||||
}
|
||||
// No changes required
|
||||
return false, false
|
||||
}
|
||||
|
||||
// DeleteSlot removes an (address, slot)-tuple from the access list.
|
||||
// This operation needs to be performed in the same order as the addition happened.
|
||||
// This method is meant to be used by the journal, which maintains ordering of
|
||||
// operations.
|
||||
func (al *accessList) DeleteSlot(address common.Address, slot common.Hash) {
|
||||
idx, addrOk := al.addresses[address]
|
||||
// There are two ways this can fail
|
||||
if !addrOk {
|
||||
panic("reverting slot change, address not present in list")
|
||||
}
|
||||
slotmap := al.slots[idx]
|
||||
delete(slotmap, slot)
|
||||
// If that was the last (first) slot, remove it
|
||||
// Since additions and rollbacks are always performed in order,
|
||||
// we can delete the item without worrying about screwing up later indices
|
||||
if len(slotmap) == 0 {
|
||||
al.slots = al.slots[:idx]
|
||||
al.addresses[address] = -1
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteAddress removes an address from the access list. This operation
|
||||
// needs to be performed in the same order as the addition happened.
|
||||
// This method is meant to be used by the journal, which maintains ordering of
|
||||
// operations.
|
||||
func (al *accessList) DeleteAddress(address common.Address) {
|
||||
delete(al.addresses, address)
|
||||
}
|
242
x/evm/types/access_list_test.go
Normal file
242
x/evm/types/access_list_test.go
Normal file
@ -0,0 +1,242 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
|
||||
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
|
||||
)
|
||||
|
||||
type AccessListTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
address ethcmn.Address
|
||||
accessList *accessList
|
||||
}
|
||||
|
||||
func (suite *AccessListTestSuite) SetupTest() {
|
||||
privkey, err := ethsecp256k1.GenerateKey()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.address = ethcmn.BytesToAddress(privkey.PubKey().Address().Bytes())
|
||||
suite.accessList = newAccessList()
|
||||
suite.accessList.addresses[suite.address] = 1
|
||||
}
|
||||
|
||||
func TestAccessListTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(AccessListTestSuite))
|
||||
}
|
||||
|
||||
func (suite *AccessListTestSuite) TestContainsAddress() {
|
||||
found := suite.accessList.ContainsAddress(suite.address)
|
||||
suite.Require().True(found)
|
||||
}
|
||||
|
||||
func (suite *AccessListTestSuite) TestContains() {
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func()
|
||||
expAddrPresent bool
|
||||
expSlotPresent bool
|
||||
}{
|
||||
{"out of range", func() {}, true, false},
|
||||
{
|
||||
"address, no slots",
|
||||
func() {
|
||||
suite.accessList.addresses[suite.address] = -1
|
||||
}, true, false,
|
||||
},
|
||||
{
|
||||
"no address, no slots",
|
||||
func() {
|
||||
delete(suite.accessList.addresses, suite.address)
|
||||
}, false, false,
|
||||
},
|
||||
{
|
||||
"address, slot not present",
|
||||
func() {
|
||||
suite.accessList.addresses[suite.address] = 0
|
||||
suite.accessList.slots = make([]map[ethcmn.Hash]struct{}, 1)
|
||||
}, true, false,
|
||||
},
|
||||
{
|
||||
"address, slots",
|
||||
func() {
|
||||
suite.accessList.addresses[suite.address] = 0
|
||||
suite.accessList.slots = make([]map[ethcmn.Hash]struct{}, 1)
|
||||
suite.accessList.slots[0] = make(map[ethcmn.Hash]struct{})
|
||||
suite.accessList.slots[0][ethcmn.Hash{}] = struct{}{}
|
||||
}, true, true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc.malleate()
|
||||
|
||||
addrPresent, slotPresent := suite.accessList.Contains(suite.address, ethcmn.Hash{})
|
||||
|
||||
suite.Require().Equal(tc.expAddrPresent, addrPresent, tc.name)
|
||||
suite.Require().Equal(tc.expSlotPresent, slotPresent, tc.name)
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *AccessListTestSuite) TestCopy() {
|
||||
expAccessList := newAccessList()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func()
|
||||
}{
|
||||
{"empty", func() {
|
||||
expAccessList.slots = make([]map[ethcmn.Hash]struct{}, 0)
|
||||
}},
|
||||
{
|
||||
"single address", func() {
|
||||
expAccessList = newAccessList()
|
||||
expAccessList.slots = make([]map[ethcmn.Hash]struct{}, 0)
|
||||
expAccessList.addresses[suite.address] = -1
|
||||
},
|
||||
},
|
||||
{
|
||||
"single address, single slot",
|
||||
func() {
|
||||
expAccessList = newAccessList()
|
||||
expAccessList.addresses[suite.address] = 0
|
||||
expAccessList.slots = make([]map[ethcmn.Hash]struct{}, 1)
|
||||
expAccessList.slots[0] = make(map[ethcmn.Hash]struct{})
|
||||
expAccessList.slots[0][ethcmn.Hash{}] = struct{}{}
|
||||
},
|
||||
},
|
||||
{
|
||||
"multiple addresses, single slot each",
|
||||
func() {
|
||||
expAccessList = newAccessList()
|
||||
expAccessList.slots = make([]map[ethcmn.Hash]struct{}, 10)
|
||||
for i := 0; i < 10; i++ {
|
||||
expAccessList.addresses[ethcmn.BytesToAddress([]byte(fmt.Sprintf("%d", i)))] = i
|
||||
expAccessList.slots[i] = make(map[ethcmn.Hash]struct{})
|
||||
expAccessList.slots[i][ethcmn.BytesToHash([]byte(fmt.Sprintf("%d", i)))] = struct{}{}
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
"multiple addresses, multiple slots each",
|
||||
func() {
|
||||
expAccessList = newAccessList()
|
||||
expAccessList.slots = make([]map[ethcmn.Hash]struct{}, 10)
|
||||
for i := 0; i < 10; i++ {
|
||||
expAccessList.addresses[ethcmn.BytesToAddress([]byte(fmt.Sprintf("%d", i)))] = i
|
||||
expAccessList.slots[i] = make(map[ethcmn.Hash]struct{})
|
||||
for j := 0; j < 10; j++ {
|
||||
expAccessList.slots[i][ethcmn.BytesToHash([]byte(fmt.Sprintf("%d-%d", i, j)))] = struct{}{}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc.malleate()
|
||||
|
||||
accessList := expAccessList.Copy()
|
||||
suite.Require().EqualValues(expAccessList, accessList, tc.name)
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *AccessListTestSuite) TestAddAddress() {
|
||||
testCases := []struct {
|
||||
name string
|
||||
address ethcmn.Address
|
||||
ok bool
|
||||
}{
|
||||
{"already present", suite.address, false},
|
||||
{"ok", ethcmn.Address{}, true},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
ok := suite.accessList.AddAddress(tc.address)
|
||||
suite.Require().Equal(tc.ok, ok, tc.name)
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *AccessListTestSuite) TestAddSlot() {
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func()
|
||||
expAddrChange bool
|
||||
expSlotChange bool
|
||||
}{
|
||||
{"out of range", func() {}, false, false},
|
||||
{
|
||||
"address not present added, slot added",
|
||||
func() {
|
||||
delete(suite.accessList.addresses, suite.address)
|
||||
}, true, true,
|
||||
},
|
||||
{
|
||||
"address present, slot not present added",
|
||||
func() {
|
||||
suite.accessList.addresses[suite.address] = 0
|
||||
suite.accessList.slots = make([]map[ethcmn.Hash]struct{}, 1)
|
||||
suite.accessList.slots[0] = make(map[ethcmn.Hash]struct{})
|
||||
}, false, true,
|
||||
},
|
||||
{
|
||||
"address present, slot present",
|
||||
func() {
|
||||
suite.accessList.addresses[suite.address] = 0
|
||||
suite.accessList.slots = make([]map[ethcmn.Hash]struct{}, 1)
|
||||
suite.accessList.slots[0] = make(map[ethcmn.Hash]struct{})
|
||||
suite.accessList.slots[0][ethcmn.Hash{}] = struct{}{}
|
||||
}, false, false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc.malleate()
|
||||
|
||||
addrChange, slotChange := suite.accessList.AddSlot(suite.address, ethcmn.Hash{})
|
||||
suite.Require().Equal(tc.expAddrChange, addrChange, tc.name)
|
||||
suite.Require().Equal(tc.expSlotChange, slotChange, tc.name)
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *AccessListTestSuite) TestDeleteSlot() {
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func()
|
||||
expPanic bool
|
||||
}{
|
||||
{"panics, out of range", func() {}, true},
|
||||
{"panics, address not found", func() {
|
||||
delete(suite.accessList.addresses, suite.address)
|
||||
}, true},
|
||||
{
|
||||
"single slot present",
|
||||
func() {
|
||||
suite.accessList.addresses[suite.address] = 0
|
||||
suite.accessList.slots = make([]map[ethcmn.Hash]struct{}, 1)
|
||||
suite.accessList.slots[0] = make(map[ethcmn.Hash]struct{})
|
||||
suite.accessList.slots[0][ethcmn.Hash{}] = struct{}{}
|
||||
}, false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc.malleate()
|
||||
|
||||
if tc.expPanic {
|
||||
suite.Require().Panics(func() {
|
||||
suite.accessList.DeleteSlot(suite.address, ethcmn.Hash{})
|
||||
}, tc.name)
|
||||
} else {
|
||||
suite.Require().NotPanics(func() {
|
||||
suite.accessList.DeleteSlot(suite.address, ethcmn.Hash{})
|
||||
}, tc.name)
|
||||
}
|
||||
}
|
||||
}
|
@ -40,7 +40,7 @@ type ChainConfig struct {
|
||||
IstanbulBlock sdk.Int `json:"istanbul_block" yaml:"istanbul_block"` // Istanbul switch block (< 0 no fork, 0 = already on istanbul)
|
||||
MuirGlacierBlock sdk.Int `json:"muir_glacier_block" yaml:"muir_glacier_block"` // Eip-2384 (bomb delay) switch block (< 0 no fork, 0 = already activated)
|
||||
|
||||
YoloV1Block sdk.Int `json:"yoloV1_block" yaml:"yoloV1_block"` // YOLO v1: https://github.com/ethereum/EIPs/pull/2657 (Ephemeral testnet)
|
||||
YoloV2Block sdk.Int `json:"yoloV2_block" yaml:"yoloV2_block"` // YOLO v1: https://github.com/ethereum/EIPs/pull/2657 (Ephemeral testnet)
|
||||
EWASMBlock sdk.Int `json:"ewasm_block" yaml:"ewasm_block"` // EWASM switch block (< 0 no fork, 0 = already activated)
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ func (cc ChainConfig) EthereumConfig(chainID *big.Int) *params.ChainConfig {
|
||||
PetersburgBlock: getBlockValue(cc.PetersburgBlock),
|
||||
IstanbulBlock: getBlockValue(cc.IstanbulBlock),
|
||||
MuirGlacierBlock: getBlockValue(cc.MuirGlacierBlock),
|
||||
YoloV1Block: getBlockValue(cc.YoloV1Block),
|
||||
YoloV2Block: getBlockValue(cc.YoloV2Block),
|
||||
EWASMBlock: getBlockValue(cc.EWASMBlock),
|
||||
}
|
||||
}
|
||||
@ -87,7 +87,7 @@ func DefaultChainConfig() ChainConfig {
|
||||
PetersburgBlock: sdk.ZeroInt(),
|
||||
IstanbulBlock: sdk.NewInt(-1),
|
||||
MuirGlacierBlock: sdk.NewInt(-1),
|
||||
YoloV1Block: sdk.NewInt(-1),
|
||||
YoloV2Block: sdk.NewInt(-1),
|
||||
EWASMBlock: sdk.NewInt(-1),
|
||||
}
|
||||
}
|
||||
@ -136,8 +136,8 @@ func (cc ChainConfig) Validate() error {
|
||||
if err := validateBlock(cc.MuirGlacierBlock); err != nil {
|
||||
return sdkerrors.Wrap(err, "muirGlacierBlock")
|
||||
}
|
||||
if err := validateBlock(cc.YoloV1Block); err != nil {
|
||||
return sdkerrors.Wrap(err, "yoloV1Block")
|
||||
if err := validateBlock(cc.YoloV2Block); err != nil {
|
||||
return sdkerrors.Wrap(err, "yoloV2Block")
|
||||
}
|
||||
if err := validateBlock(cc.EWASMBlock); err != nil {
|
||||
return sdkerrors.Wrap(err, "eWASMBlock")
|
||||
|
@ -33,7 +33,7 @@ func TestChainConfigValidate(t *testing.T) {
|
||||
PetersburgBlock: sdk.OneInt(),
|
||||
IstanbulBlock: sdk.OneInt(),
|
||||
MuirGlacierBlock: sdk.OneInt(),
|
||||
YoloV1Block: sdk.OneInt(),
|
||||
YoloV2Block: sdk.OneInt(),
|
||||
EWASMBlock: sdk.OneInt(),
|
||||
},
|
||||
false,
|
||||
@ -176,7 +176,7 @@ func TestChainConfigValidate(t *testing.T) {
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid YoloV1Block",
|
||||
"invalid YoloV2Block",
|
||||
ChainConfig{
|
||||
HomesteadBlock: sdk.OneInt(),
|
||||
DAOForkBlock: sdk.OneInt(),
|
||||
@ -189,7 +189,7 @@ func TestChainConfigValidate(t *testing.T) {
|
||||
PetersburgBlock: sdk.OneInt(),
|
||||
IstanbulBlock: sdk.OneInt(),
|
||||
MuirGlacierBlock: sdk.OneInt(),
|
||||
YoloV1Block: sdk.Int{},
|
||||
YoloV2Block: sdk.Int{},
|
||||
},
|
||||
true,
|
||||
},
|
||||
@ -207,7 +207,7 @@ func TestChainConfigValidate(t *testing.T) {
|
||||
PetersburgBlock: sdk.OneInt(),
|
||||
IstanbulBlock: sdk.OneInt(),
|
||||
MuirGlacierBlock: sdk.OneInt(),
|
||||
YoloV1Block: sdk.OneInt(),
|
||||
YoloV2Block: sdk.OneInt(),
|
||||
EWASMBlock: sdk.Int{},
|
||||
},
|
||||
true,
|
||||
@ -238,7 +238,7 @@ constantinople_block: "0"
|
||||
petersburg_block: "0"
|
||||
istanbul_block: "-1"
|
||||
muir_glacier_block: "-1"
|
||||
yoloV1_block: "-1"
|
||||
yoloV2_block: "-1"
|
||||
ewasm_block: "-1"
|
||||
`
|
||||
require.Equal(t, configStr, DefaultChainConfig().String())
|
||||
|
@ -186,10 +186,18 @@ type (
|
||||
// prev bool
|
||||
// prevDirty bool
|
||||
}
|
||||
accessListAddAccountChange struct {
|
||||
address *ethcmn.Address
|
||||
}
|
||||
accessListAddSlotChange struct {
|
||||
address *ethcmn.Address
|
||||
slot *ethcmn.Hash
|
||||
}
|
||||
)
|
||||
|
||||
func (ch createObjectChange) revert(s *CommitStateDB) {
|
||||
delete(s.stateObjectsDirty, *ch.account)
|
||||
|
||||
idx, exists := s.addressToObjectIndex[*ch.account]
|
||||
if !exists {
|
||||
// perform no-op
|
||||
@ -342,3 +350,28 @@ func (ch addPreimageChange) revert(s *CommitStateDB) {
|
||||
func (ch addPreimageChange) dirtied() *ethcmn.Address {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ch accessListAddAccountChange) revert(s *CommitStateDB) {
|
||||
/*
|
||||
One important invariant here, is that whenever a (addr, slot) is added, if the
|
||||
addr is not already present, the add causes two journal entries:
|
||||
- one for the address,
|
||||
- one for the (address,slot)
|
||||
Therefore, when unrolling the change, we can always blindly delete the
|
||||
(addr) at this point, since no storage adds can remain when come upon
|
||||
a single (addr) change.
|
||||
*/
|
||||
s.accessList.DeleteAddress(*ch.address)
|
||||
}
|
||||
|
||||
func (ch accessListAddAccountChange) dirtied() *ethcmn.Address {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ch accessListAddSlotChange) revert(s *CommitStateDB) {
|
||||
s.accessList.DeleteSlot(*ch.address, *ch.slot)
|
||||
}
|
||||
|
||||
func (ch accessListAddSlotChange) dirtied() *ethcmn.Address {
|
||||
return nil
|
||||
}
|
||||
|
@ -220,6 +220,12 @@ func (suite *JournalTestSuite) TestJournal_append_revert() {
|
||||
txhash: ethcmn.BytesToHash([]byte("txhash")),
|
||||
},
|
||||
},
|
||||
{
|
||||
"accessListAddAccountChange",
|
||||
accessListAddAccountChange{
|
||||
address: &suite.address,
|
||||
},
|
||||
},
|
||||
}
|
||||
var dirtyCount int
|
||||
for i, tc := range testCases {
|
||||
|
@ -159,7 +159,7 @@ func (st StateTransition) TransitionDb(ctx sdk.Context, config ChainConfig) (*Ex
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bloomInt = ethtypes.LogsBloom(logs)
|
||||
bloomInt = big.NewInt(0).SetBytes(ethtypes.LogsBloom(logs))
|
||||
bloomFilter = ethtypes.BytesToBloom(bloomInt.Bytes())
|
||||
}
|
||||
|
||||
|
@ -77,6 +77,9 @@ type CommitStateDB struct {
|
||||
validRevisions []revision
|
||||
nextRevisionID int
|
||||
|
||||
// Per-transaction access list
|
||||
accessList *accessList
|
||||
|
||||
// mutex for state deep copying
|
||||
lock sync.Mutex
|
||||
}
|
||||
@ -100,6 +103,7 @@ func NewCommitStateDB(
|
||||
preimages: []preimageEntry{},
|
||||
hashToPreimageIndex: make(map[ethcmn.Hash]int),
|
||||
journal: newJournal(),
|
||||
accessList: newAccessList(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -243,6 +247,41 @@ func (csdb *CommitStateDB) SubRefund(gas uint64) {
|
||||
csdb.refund -= gas
|
||||
}
|
||||
|
||||
// AddAddressToAccessList adds the given address to the access list
|
||||
func (csdb *CommitStateDB) AddAddressToAccessList(addr ethcmn.Address) {
|
||||
if csdb.accessList.AddAddress(addr) {
|
||||
csdb.journal.append(accessListAddAccountChange{&addr})
|
||||
}
|
||||
}
|
||||
|
||||
// AddSlotToAccessList adds the given (address, slot)-tuple to the access list
|
||||
func (csdb *CommitStateDB) AddSlotToAccessList(addr ethcmn.Address, slot ethcmn.Hash) {
|
||||
addrMod, slotMod := csdb.accessList.AddSlot(addr, slot)
|
||||
if addrMod {
|
||||
// In practice, this should not happen, since there is no way to enter the
|
||||
// scope of 'address' without having the 'address' become already added
|
||||
// to the access list (via call-variant, create, etc).
|
||||
// Better safe than sorry, though
|
||||
csdb.journal.append(accessListAddAccountChange{&addr})
|
||||
}
|
||||
if slotMod {
|
||||
csdb.journal.append(accessListAddSlotChange{
|
||||
address: &addr,
|
||||
slot: &slot,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// AddressInAccessList returns true if the given address is in the access list.
|
||||
func (csdb *CommitStateDB) AddressInAccessList(addr ethcmn.Address) bool {
|
||||
return csdb.accessList.ContainsAddress(addr)
|
||||
}
|
||||
|
||||
// SlotInAccessList returns true if the given (address, slot)-tuple is in the access list.
|
||||
func (csdb *CommitStateDB) SlotInAccessList(addr ethcmn.Address, slot ethcmn.Hash) (bool, bool) {
|
||||
return csdb.accessList.Contains(addr, slot)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Getters
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -113,8 +113,8 @@ func (suite *StateDBTestSuite) TestBloomFilter() {
|
||||
}
|
||||
} else {
|
||||
// get logs bloom from the log
|
||||
bloomInt := ethtypes.LogsBloom(logs)
|
||||
bloomFilter := ethtypes.BytesToBloom(bloomInt.Bytes())
|
||||
bloomBytes := ethtypes.LogsBloom(logs)
|
||||
bloomFilter := ethtypes.BytesToBloom(bloomBytes)
|
||||
suite.Require().True(ethtypes.BloomLookup(bloomFilter, contractAddress), tc.name)
|
||||
suite.Require().False(ethtypes.BloomLookup(bloomFilter, ethcmn.BigToAddress(big.NewInt(2))), tc.name)
|
||||
}
|
||||
@ -695,3 +695,21 @@ func (suite *StateDBTestSuite) TestCommitStateDB_ForEachStorage() {
|
||||
storage = types.Storage{}
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *StateDBTestSuite) TestCommitStateDB_AccessList() {
|
||||
addr := ethcmn.Address([20]byte{77})
|
||||
hash := ethcmn.Hash([32]byte{99})
|
||||
|
||||
suite.Require().False(suite.stateDB.AddressInAccessList(addr))
|
||||
|
||||
suite.stateDB.AddAddressToAccessList(addr)
|
||||
suite.Require().True(suite.stateDB.AddressInAccessList(addr))
|
||||
addrIn, slotIn := suite.stateDB.SlotInAccessList(addr, hash)
|
||||
suite.Require().True(addrIn)
|
||||
suite.Require().False(slotIn)
|
||||
|
||||
suite.stateDB.AddSlotToAccessList(addr, hash)
|
||||
addrIn, slotIn = suite.stateDB.SlotInAccessList(addr, hash)
|
||||
suite.Require().True(addrIn)
|
||||
suite.Require().True(slotIn)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user