From ff9a16e5f0b00d9292e103ff13028f8425d0197b Mon Sep 17 00:00:00 2001 From: Kolby Moroz Liebl <31669092+KolbyML@users.noreply.github.com> Date: Wed, 19 Nov 2025 11:39:03 -0700 Subject: [PATCH 1/2] Fix RecentWasms cache bug by using pointers in methods --- core/state/statedb_arbitrum.go | 6 +-- core/state/statedb_arbitrum_test.go | 67 +++++++++++++++++++++++++++++ core/state/statedb_hooked.go | 2 +- core/vm/interface.go | 2 +- 4 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 core/state/statedb_arbitrum_test.go diff --git a/core/state/statedb_arbitrum.go b/core/state/statedb_arbitrum.go index bd8da24355..dba4c30f5a 100644 --- a/core/state/statedb_arbitrum.go +++ b/core/state/statedb_arbitrum.go @@ -330,8 +330,8 @@ func (s *StateDB) RecordEvictWasm(wasm EvictWasm) { s.journal.entries = append(s.journal.entries, wasm) } -func (s *StateDB) GetRecentWasms() RecentWasms { - return s.arbExtraData.recentWasms +func (s *StateDB) GetRecentWasms() *RecentWasms { + return &s.arbExtraData.recentWasms } // Type for managing recent program access. @@ -346,7 +346,7 @@ func NewRecentWasms() RecentWasms { } // Inserts a new item, returning true if already present. -func (p RecentWasms) Insert(item common.Hash, retain uint16) bool { +func (p *RecentWasms) Insert(item common.Hash, retain uint16) bool { if p.cache == nil { cache := lru.NewBasicLRU[common.Hash, struct{}](int(retain)) p.cache = &cache diff --git a/core/state/statedb_arbitrum_test.go b/core/state/statedb_arbitrum_test.go new file mode 100644 index 0000000000..027e5a4edd --- /dev/null +++ b/core/state/statedb_arbitrum_test.go @@ -0,0 +1,67 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package state + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +func TestRecentWasmsInsertAndCopy(t *testing.T) { + db := NewDatabaseForTesting() + state, err := New(types.EmptyRootHash, db) + if err != nil { + t.Fatalf("failed to create state: %v", err) + } + + const retain = uint16(8) + + hash1 := common.HexToHash("0x01") + hash2 := common.HexToHash("0x02") + hash3 := common.HexToHash("0x03") + + if hit := state.GetRecentWasms().Insert(hash1, retain); hit { + t.Fatalf("first insert of hash1 should be a miss") + } + + if hit := state.GetRecentWasms().Insert(hash1, retain); !hit { + t.Fatalf("second insert of hash1 should be a hit (cache not persisting)") + } + + if hit := state.GetRecentWasms().Insert(hash2, retain); hit { + t.Fatalf("first insert of hash2 should be a miss") + } + + copy := state.Copy() + + if hit := copy.GetRecentWasms().Insert(hash1, retain); !hit { + t.Fatalf("copy: expected hit for hash1 present before copy") + } + if hit := copy.GetRecentWasms().Insert(hash2, retain); !hit { + t.Fatalf("copy: expected hit for hash2 present before copy") + } + + if hit := copy.GetRecentWasms().Insert(hash3, retain); hit { + t.Fatalf("copy: first insert of hash3 should be a miss") + } + + if hit := state.GetRecentWasms().Insert(hash3, retain); hit { + t.Fatalf("original: first insert of hash3 should be a miss (must be independent of copy)") + } +} diff --git a/core/state/statedb_hooked.go b/core/state/statedb_hooked.go index 673a9dc74d..c718d508fc 100644 --- a/core/state/statedb_hooked.go +++ b/core/state/statedb_hooked.go @@ -321,7 +321,7 @@ func (s *hookedStateDB) RecordEvictWasm(wasm EvictWasm) { s.inner.RecordEvictWasm(wasm) } -func (s *hookedStateDB) GetRecentWasms() RecentWasms { +func (s *hookedStateDB) GetRecentWasms() *RecentWasms { return s.inner.GetRecentWasms() } diff --git a/core/vm/interface.go b/core/vm/interface.go index ce92dcb53b..48dda58233 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -38,7 +38,7 @@ type StateDB interface { ActivatedAsmMap(targets []rawdb.WasmTarget, moduleHash common.Hash) (asmMap map[rawdb.WasmTarget][]byte, missingTargets []rawdb.WasmTarget, err error) RecordCacheWasm(wasm state.CacheWasm) RecordEvictWasm(wasm state.EvictWasm) - GetRecentWasms() state.RecentWasms + GetRecentWasms() *state.RecentWasms // Arbitrum: track stylus's memory footprint GetStylusPages() (uint16, uint16) From dfd63684af55b6d4b96dd68c0f284ca34cbbe8bb Mon Sep 17 00:00:00 2001 From: Kolby Moroz Liebl <31669092+KolbyML@users.noreply.github.com> Date: Fri, 21 Nov 2025 09:37:24 -0700 Subject: [PATCH 2/2] Resolve PR concern --- core/state/statedb_arbitrum_test.go | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/core/state/statedb_arbitrum_test.go b/core/state/statedb_arbitrum_test.go index 027e5a4edd..87f2b65b2e 100644 --- a/core/state/statedb_arbitrum_test.go +++ b/core/state/statedb_arbitrum_test.go @@ -1,19 +1,3 @@ -// Copyright 2016 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - package state import (