mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-21 19:20:39 +00:00
Adds access list sorting (#8933)
Because access lists use maps with the `StorageKey` as the key, they are subject to inconsistent ordering in the results of the `.accessList()` method. To get around this, an `accessListSorted` method has been added, and exposed with the same name. The `equal` method has also been exposed to allow for equality checks at this level outside of this module. Co-authored-by: 3commascapital <8562488-3commascapital@users.noreply.gitlab.com>
This commit is contained in:
parent
e006db6ed9
commit
07331f900f
@ -17,6 +17,8 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/holiman/uint256"
|
||||
libcommon "github.com/ledgerwatch/erigon-lib/common"
|
||||
types2 "github.com/ledgerwatch/erigon-lib/types"
|
||||
@ -94,6 +96,10 @@ func (al accessList) equal(other accessList) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (al accessList) Equal(other accessList) bool {
|
||||
return al.equal(other)
|
||||
}
|
||||
|
||||
// accesslist converts the accesslist to a types2.AccessList.
|
||||
func (al accessList) accessList() types2.AccessList {
|
||||
acl := make(types2.AccessList, 0, len(al))
|
||||
@ -107,6 +113,25 @@ func (al accessList) accessList() types2.AccessList {
|
||||
return acl
|
||||
}
|
||||
|
||||
// accesslist converts the accesslist to a types2.AccessList.
|
||||
func (al accessList) accessListSorted() types2.AccessList {
|
||||
acl := make(types2.AccessList, 0, len(al))
|
||||
for addr, slots := range al {
|
||||
storageKeys := make([]libcommon.Hash, 0, len(slots))
|
||||
for slot := range slots {
|
||||
storageKeys = append(storageKeys, slot)
|
||||
}
|
||||
sort.Slice(storageKeys, func(i, j int) bool {
|
||||
return storageKeys[i].String() < storageKeys[j].String()
|
||||
})
|
||||
acl = append(acl, types2.AccessTuple{
|
||||
Address: addr,
|
||||
StorageKeys: storageKeys,
|
||||
})
|
||||
}
|
||||
return acl
|
||||
}
|
||||
|
||||
// AccessListTracer is a tracer that accumulates touched accounts and storage
|
||||
// slots into an internal set.
|
||||
type AccessListTracer struct {
|
||||
@ -227,6 +252,11 @@ func (a *AccessListTracer) AccessList() types2.AccessList {
|
||||
return a.list.accessList()
|
||||
}
|
||||
|
||||
// AccessList returns the current accesslist maintained by the tracer.
|
||||
func (a *AccessListTracer) AccessListSorted() types2.AccessList {
|
||||
return a.list.accessListSorted()
|
||||
}
|
||||
|
||||
// CreatedContracts returns the set of all addresses of contracts created during tx execution.
|
||||
func (a *AccessListTracer) CreatedContracts() map[libcommon.Address]struct{} {
|
||||
return a.createdContracts
|
||||
|
40
eth/tracers/logger/access_list_tracer_test.go
Normal file
40
eth/tracers/logger/access_list_tracer_test.go
Normal file
@ -0,0 +1,40 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ledgerwatch/erigon-lib/common"
|
||||
types2 "github.com/ledgerwatch/erigon-lib/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var (
|
||||
addr = common.BytesToAddress([]byte{0x01, 0x71})
|
||||
|
||||
slot1 = common.BytesToHash([]byte{0x01})
|
||||
slot2 = common.BytesToHash([]byte{0x02})
|
||||
slot3 = common.BytesToHash([]byte{0x03})
|
||||
slot4 = common.BytesToHash([]byte{0x04})
|
||||
|
||||
ordered = types2.AccessList{{
|
||||
Address: addr,
|
||||
StorageKeys: []common.Hash{
|
||||
slot1,
|
||||
slot2,
|
||||
slot3,
|
||||
slot4,
|
||||
},
|
||||
}}
|
||||
)
|
||||
|
||||
func TestTracer_AccessList_Order(t *testing.T) {
|
||||
al := newAccessList()
|
||||
al.addAddress(addr)
|
||||
al.addSlot(addr, slot1)
|
||||
al.addSlot(addr, slot4)
|
||||
al.addSlot(addr, slot3)
|
||||
al.addSlot(addr, slot2)
|
||||
require.NotEqual(t, ordered, al.accessList())
|
||||
require.Equal(t, ordered, al.accessListSorted())
|
||||
require.True(t, al.Equal(al))
|
||||
}
|
Loading…
Reference in New Issue
Block a user