From 4e387ee51a284c94998908f79a91c5b475d9f8c6 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Fri, 22 Nov 2024 21:14:36 +0530 Subject: [PATCH 01/10] Filter transaction --- core/state/statedb.go | 21 +++++++++++++++++++++ core/vm/interface.go | 4 ++++ 2 files changed, 25 insertions(+) diff --git a/core/state/statedb.go b/core/state/statedb.go index acdad20481..96cbca89c2 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -19,6 +19,7 @@ package state import ( "bytes" + "errors" "fmt" "maps" "math/big" @@ -86,6 +87,7 @@ func (m *mutation) isDelete() bool { // commit states. type StateDB struct { arbExtraData *ArbitrumExtraData // must be a pointer - can't be a part of StateDB allocation, otherwise its finalizer might not get called + arbTxFilter int db Database prefetcher *triePrefetcher @@ -219,6 +221,19 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error) return sdb, nil } +func (s *StateDB) FilterTx(withBlock bool) { + if s.arbTxFilter == 0 { + s.arbTxFilter = 1 + if withBlock { + s.arbTxFilter = 2 + } + } +} + +func (s *StateDB) IsTxValid() bool { + return s.arbTxFilter == 1 +} + // SetLogger sets the logger for account update hooks. func (s *StateDB) SetLogger(l *tracing.Hooks) { s.logger = l @@ -835,6 +850,9 @@ func (s *StateDB) RevertToSnapshot(revid int) { revision := s.validRevisions[idx] snapshot := revision.journalIndex s.arbExtraData.unexpectedBalanceDelta = new(big.Int).Set(revision.unexpectedBalanceDelta) + if s.arbTxFilter == 1 { + s.arbTxFilter = 0 + } // Replay the journal to undo changes and remove invalidated snapshots s.journal.revert(s, snapshot) @@ -1220,6 +1238,9 @@ func (s *StateDB) GetTrie() Trie { // The associated block number of the state transition is also provided // for more chain context. func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, error) { + if s.arbTxFilter == 2 { + return common.Hash{}, errors.New("internal error") + } // Short circuit in case any database failure occurred earlier. if s.dbErr != nil { return common.Hash{}, fmt.Errorf("commit aborted due to earlier error: %v", s.dbErr) diff --git a/core/vm/interface.go b/core/vm/interface.go index 9b7e26ad59..99e94031cd 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -48,6 +48,10 @@ type StateDB interface { // Arbitrum: preserve old empty account behavior CreateZombieIfDeleted(common.Address) + // Arbitrum + FilterTx(bool) + IsTxValid() bool + Deterministic() bool Database() state.Database From 4bc2200ded26c931bff6f52ac30e2b1e1b5ef091 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Fri, 22 Nov 2024 21:21:28 +0530 Subject: [PATCH 02/10] rectify method name --- core/state/statedb.go | 2 +- core/vm/interface.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/state/statedb.go b/core/state/statedb.go index 96cbca89c2..7ad7ff7e6c 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -230,7 +230,7 @@ func (s *StateDB) FilterTx(withBlock bool) { } } -func (s *StateDB) IsTxValid() bool { +func (s *StateDB) IsTxInvalid() bool { return s.arbTxFilter == 1 } diff --git a/core/vm/interface.go b/core/vm/interface.go index 99e94031cd..f36fc8ffcc 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -50,7 +50,7 @@ type StateDB interface { // Arbitrum FilterTx(bool) - IsTxValid() bool + IsTxInvalid() bool Deterministic() bool Database() state.Database From cf0ca286a6e6cb435fc2331078a382f5efdaadb3 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Tue, 26 Nov 2024 15:29:08 +0530 Subject: [PATCH 03/10] address PR comments --- core/state/statedb.go | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/core/state/statedb.go b/core/state/statedb.go index 7ad7ff7e6c..c3534cabfd 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -74,6 +74,15 @@ func (m *mutation) isDelete() bool { return m.typ == deletion } +type arbFiltered int + +const ( + txFiltered arbFiltered = 1 + iota + blockFiltered +) + +var ErrArbTxFilter error = errors.New("internal error") + // StateDB structs within the ethereum protocol are used to store anything // within the merkle trie. StateDBs take care of caching and storing // nested states. It's the general query interface to retrieve: @@ -87,7 +96,7 @@ func (m *mutation) isDelete() bool { // commit states. type StateDB struct { arbExtraData *ArbitrumExtraData // must be a pointer - can't be a part of StateDB allocation, otherwise its finalizer might not get called - arbTxFilter int + arbTxFilter arbFiltered db Database prefetcher *triePrefetcher @@ -223,15 +232,15 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error) func (s *StateDB) FilterTx(withBlock bool) { if s.arbTxFilter == 0 { - s.arbTxFilter = 1 + s.arbTxFilter = txFiltered if withBlock { - s.arbTxFilter = 2 + s.arbTxFilter = blockFiltered } } } func (s *StateDB) IsTxInvalid() bool { - return s.arbTxFilter == 1 + return s.arbTxFilter == txFiltered } // SetLogger sets the logger for account update hooks. @@ -850,7 +859,7 @@ func (s *StateDB) RevertToSnapshot(revid int) { revision := s.validRevisions[idx] snapshot := revision.journalIndex s.arbExtraData.unexpectedBalanceDelta = new(big.Int).Set(revision.unexpectedBalanceDelta) - if s.arbTxFilter == 1 { + if s.arbTxFilter == txFiltered { s.arbTxFilter = 0 } @@ -1238,8 +1247,8 @@ func (s *StateDB) GetTrie() Trie { // The associated block number of the state transition is also provided // for more chain context. func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, error) { - if s.arbTxFilter == 2 { - return common.Hash{}, errors.New("internal error") + if s.arbTxFilter == blockFiltered { + return common.Hash{}, ErrArbTxFilter } // Short circuit in case any database failure occurred earlier. if s.dbErr != nil { From b2541cfd2120a39bc7bbd1854b96718583506c56 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Tue, 26 Nov 2024 16:06:59 +0530 Subject: [PATCH 04/10] add unfiltered to enum --- core/state/statedb.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/state/statedb.go b/core/state/statedb.go index c3534cabfd..cfb692e6b3 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -77,7 +77,8 @@ func (m *mutation) isDelete() bool { type arbFiltered int const ( - txFiltered arbFiltered = 1 + iota + unFiltered arbFiltered = iota + txFiltered blockFiltered ) @@ -231,7 +232,7 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error) } func (s *StateDB) FilterTx(withBlock bool) { - if s.arbTxFilter == 0 { + if s.arbTxFilter == unFiltered { s.arbTxFilter = txFiltered if withBlock { s.arbTxFilter = blockFiltered @@ -860,7 +861,7 @@ func (s *StateDB) RevertToSnapshot(revid int) { snapshot := revision.journalIndex s.arbExtraData.unexpectedBalanceDelta = new(big.Int).Set(revision.unexpectedBalanceDelta) if s.arbTxFilter == txFiltered { - s.arbTxFilter = 0 + s.arbTxFilter = unFiltered } // Replay the journal to undo changes and remove invalidated snapshots From 30abfa28d13911257bc4a94631268ae46934db43 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Mon, 2 Dec 2024 15:10:43 -0600 Subject: [PATCH 05/10] typo fix --- core/state/statedb.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/state/statedb.go b/core/state/statedb.go index cfb692e6b3..d8f56fa05b 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -77,7 +77,7 @@ func (m *mutation) isDelete() bool { type arbFiltered int const ( - unFiltered arbFiltered = iota + notFiltered arbFiltered = iota txFiltered blockFiltered ) @@ -232,7 +232,7 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error) } func (s *StateDB) FilterTx(withBlock bool) { - if s.arbTxFilter == unFiltered { + if s.arbTxFilter == notFiltered { s.arbTxFilter = txFiltered if withBlock { s.arbTxFilter = blockFiltered @@ -861,7 +861,7 @@ func (s *StateDB) RevertToSnapshot(revid int) { snapshot := revision.journalIndex s.arbExtraData.unexpectedBalanceDelta = new(big.Int).Set(revision.unexpectedBalanceDelta) if s.arbTxFilter == txFiltered { - s.arbTxFilter = unFiltered + s.arbTxFilter = notFiltered } // Replay the journal to undo changes and remove invalidated snapshots From 418b28420ad8b83b1f5333f87e76ac52c9285b5e Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Tue, 10 Dec 2024 15:09:59 -0600 Subject: [PATCH 06/10] address PR comments --- core/state/statedb.go | 7 +++++-- core/vm/interface.go | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/core/state/statedb.go b/core/state/statedb.go index d8f56fa05b..def979c4a7 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -240,7 +240,7 @@ func (s *StateDB) FilterTx(withBlock bool) { } } -func (s *StateDB) IsTxInvalid() bool { +func (s *StateDB) IsTxFiltered() bool { return s.arbTxFilter == txFiltered } @@ -842,6 +842,9 @@ func (s *StateDB) Copy() *StateDB { // Snapshot returns an identifier for the current revision of the state. func (s *StateDB) Snapshot() int { + if s.arbTxFilter == txFiltered { + panic("trying to create a new snapshot when the previous transaction applied to this state was filtered. RevertToSnapshot should be called before moving on to the next transaction") + } id := s.nextRevisionId s.nextRevisionId++ s.validRevisions = append(s.validRevisions, revision{id, s.journal.length(), new(big.Int).Set(s.arbExtraData.unexpectedBalanceDelta)}) @@ -1248,7 +1251,7 @@ func (s *StateDB) GetTrie() Trie { // The associated block number of the state transition is also provided // for more chain context. func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, error) { - if s.arbTxFilter == blockFiltered { + if s.arbTxFilter == blockFiltered || s.arbTxFilter == txFiltered { return common.Hash{}, ErrArbTxFilter } // Short circuit in case any database failure occurred earlier. diff --git a/core/vm/interface.go b/core/vm/interface.go index f36fc8ffcc..d91727a826 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -50,7 +50,7 @@ type StateDB interface { // Arbitrum FilterTx(bool) - IsTxInvalid() bool + IsTxFiltered() bool Deterministic() bool Database() state.Database From c7f6a0386939b3f2dc9366613d8bae7f6c9812f7 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Tue, 10 Dec 2024 16:02:53 -0600 Subject: [PATCH 07/10] revert panic on snapshot --- core/state/statedb.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/core/state/statedb.go b/core/state/statedb.go index def979c4a7..eb7f12f4f7 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -842,9 +842,6 @@ func (s *StateDB) Copy() *StateDB { // Snapshot returns an identifier for the current revision of the state. func (s *StateDB) Snapshot() int { - if s.arbTxFilter == txFiltered { - panic("trying to create a new snapshot when the previous transaction applied to this state was filtered. RevertToSnapshot should be called before moving on to the next transaction") - } id := s.nextRevisionId s.nextRevisionId++ s.validRevisions = append(s.validRevisions, revision{id, s.journal.length(), new(big.Int).Set(s.arbExtraData.unexpectedBalanceDelta)}) From e9a5f8af11e82a85510ff1c00932dc1a13e5cc7c Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Wed, 11 Dec 2024 10:28:20 -0600 Subject: [PATCH 08/10] make arbTxFilter a boolean --- core/state/statedb.go | 30 +++++++++--------------------- core/vm/interface.go | 2 +- 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/core/state/statedb.go b/core/state/statedb.go index eb7f12f4f7..1a0f22f8df 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -52,6 +52,7 @@ type revision struct { // Arbitrum: track the total balance change across all accounts unexpectedBalanceDelta *big.Int + arbTxFilter bool } type mutationType int @@ -74,14 +75,6 @@ func (m *mutation) isDelete() bool { return m.typ == deletion } -type arbFiltered int - -const ( - notFiltered arbFiltered = iota - txFiltered - blockFiltered -) - var ErrArbTxFilter error = errors.New("internal error") // StateDB structs within the ethereum protocol are used to store anything @@ -97,7 +90,7 @@ var ErrArbTxFilter error = errors.New("internal error") // commit states. type StateDB struct { arbExtraData *ArbitrumExtraData // must be a pointer - can't be a part of StateDB allocation, otherwise its finalizer might not get called - arbTxFilter arbFiltered + arbTxFilter bool db Database prefetcher *triePrefetcher @@ -231,17 +224,14 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error) return sdb, nil } -func (s *StateDB) FilterTx(withBlock bool) { - if s.arbTxFilter == notFiltered { - s.arbTxFilter = txFiltered - if withBlock { - s.arbTxFilter = blockFiltered - } +func (s *StateDB) FilterTx() { + if !s.arbTxFilter { + s.arbTxFilter = true } } func (s *StateDB) IsTxFiltered() bool { - return s.arbTxFilter == txFiltered + return s.arbTxFilter } // SetLogger sets the logger for account update hooks. @@ -844,7 +834,7 @@ func (s *StateDB) Copy() *StateDB { func (s *StateDB) Snapshot() int { id := s.nextRevisionId s.nextRevisionId++ - s.validRevisions = append(s.validRevisions, revision{id, s.journal.length(), new(big.Int).Set(s.arbExtraData.unexpectedBalanceDelta)}) + s.validRevisions = append(s.validRevisions, revision{id, s.journal.length(), new(big.Int).Set(s.arbExtraData.unexpectedBalanceDelta), s.arbTxFilter}) return id } @@ -860,9 +850,7 @@ func (s *StateDB) RevertToSnapshot(revid int) { revision := s.validRevisions[idx] snapshot := revision.journalIndex s.arbExtraData.unexpectedBalanceDelta = new(big.Int).Set(revision.unexpectedBalanceDelta) - if s.arbTxFilter == txFiltered { - s.arbTxFilter = notFiltered - } + s.arbTxFilter = revision.arbTxFilter // Replay the journal to undo changes and remove invalidated snapshots s.journal.revert(s, snapshot) @@ -1248,7 +1236,7 @@ func (s *StateDB) GetTrie() Trie { // The associated block number of the state transition is also provided // for more chain context. func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, error) { - if s.arbTxFilter == blockFiltered || s.arbTxFilter == txFiltered { + if s.arbTxFilter { return common.Hash{}, ErrArbTxFilter } // Short circuit in case any database failure occurred earlier. diff --git a/core/vm/interface.go b/core/vm/interface.go index d91727a826..46a4537dd3 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -49,7 +49,7 @@ type StateDB interface { CreateZombieIfDeleted(common.Address) // Arbitrum - FilterTx(bool) + FilterTx() IsTxFiltered() bool Deterministic() bool From 6205f5effbcc8286f14cea045a9fcabb7c894413 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Wed, 11 Dec 2024 15:23:41 -0600 Subject: [PATCH 09/10] address PR comments --- core/state/statedb.go | 17 ++++++----------- core/state/statedb_arbitrum.go | 3 +++ 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/core/state/statedb.go b/core/state/statedb.go index 1a0f22f8df..b566586141 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -19,7 +19,6 @@ package state import ( "bytes" - "errors" "fmt" "maps" "math/big" @@ -75,8 +74,6 @@ func (m *mutation) isDelete() bool { return m.typ == deletion } -var ErrArbTxFilter error = errors.New("internal error") - // StateDB structs within the ethereum protocol are used to store anything // within the merkle trie. StateDBs take care of caching and storing // nested states. It's the general query interface to retrieve: @@ -90,7 +87,6 @@ var ErrArbTxFilter error = errors.New("internal error") // commit states. type StateDB struct { arbExtraData *ArbitrumExtraData // must be a pointer - can't be a part of StateDB allocation, otherwise its finalizer might not get called - arbTxFilter bool db Database prefetcher *triePrefetcher @@ -225,13 +221,11 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error) } func (s *StateDB) FilterTx() { - if !s.arbTxFilter { - s.arbTxFilter = true - } + s.arbExtraData.arbTxFilter = true } func (s *StateDB) IsTxFiltered() bool { - return s.arbTxFilter + return s.arbExtraData.arbTxFilter } // SetLogger sets the logger for account update hooks. @@ -751,6 +745,7 @@ func (s *StateDB) Copy() *StateDB { recentWasms: s.arbExtraData.recentWasms.Copy(), openWasmPages: s.arbExtraData.openWasmPages, everWasmPages: s.arbExtraData.everWasmPages, + arbTxFilter: s.arbExtraData.arbTxFilter, }, db: s.db, @@ -834,7 +829,7 @@ func (s *StateDB) Copy() *StateDB { func (s *StateDB) Snapshot() int { id := s.nextRevisionId s.nextRevisionId++ - s.validRevisions = append(s.validRevisions, revision{id, s.journal.length(), new(big.Int).Set(s.arbExtraData.unexpectedBalanceDelta), s.arbTxFilter}) + s.validRevisions = append(s.validRevisions, revision{id, s.journal.length(), new(big.Int).Set(s.arbExtraData.unexpectedBalanceDelta), s.arbExtraData.arbTxFilter}) return id } @@ -850,7 +845,7 @@ func (s *StateDB) RevertToSnapshot(revid int) { revision := s.validRevisions[idx] snapshot := revision.journalIndex s.arbExtraData.unexpectedBalanceDelta = new(big.Int).Set(revision.unexpectedBalanceDelta) - s.arbTxFilter = revision.arbTxFilter + s.arbExtraData.arbTxFilter = revision.arbTxFilter // Replay the journal to undo changes and remove invalidated snapshots s.journal.revert(s, snapshot) @@ -1236,7 +1231,7 @@ func (s *StateDB) GetTrie() Trie { // The associated block number of the state transition is also provided // for more chain context. func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, error) { - if s.arbTxFilter { + if s.arbExtraData.arbTxFilter { return common.Hash{}, ErrArbTxFilter } // Short circuit in case any database failure occurred earlier. diff --git a/core/state/statedb_arbitrum.go b/core/state/statedb_arbitrum.go index 3a1cd28ce3..2f34effed1 100644 --- a/core/state/statedb_arbitrum.go +++ b/core/state/statedb_arbitrum.go @@ -164,6 +164,8 @@ func (s *StateDB) Deterministic() bool { return s.deterministic } +var ErrArbTxFilter error = errors.New("internal error") + type ArbitrumExtraData struct { unexpectedBalanceDelta *big.Int // total balance change across all accounts userWasms UserWasms // user wasms encountered during execution @@ -171,6 +173,7 @@ type ArbitrumExtraData struct { everWasmPages uint16 // largest number of pages ever allocated during this tx's execution activatedWasms map[common.Hash]ActivatedWasm // newly activated WASMs recentWasms RecentWasms + arbTxFilter bool } func (s *StateDB) SetArbFinalizer(f func(*ArbitrumExtraData)) { From 313432e2a408f5d7d0f50c9ad4ccf515c8d21a56 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Mon, 16 Dec 2024 18:13:08 -0600 Subject: [PATCH 10/10] address PR comments --- core/state/statedb.go | 8 +++++--- core/vm/interface.go | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/core/state/statedb.go b/core/state/statedb.go index b566586141..ca9f778e0a 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -51,7 +51,6 @@ type revision struct { // Arbitrum: track the total balance change across all accounts unexpectedBalanceDelta *big.Int - arbTxFilter bool } type mutationType int @@ -224,6 +223,10 @@ func (s *StateDB) FilterTx() { s.arbExtraData.arbTxFilter = true } +func (s *StateDB) ClearTxFilter() { + s.arbExtraData.arbTxFilter = false +} + func (s *StateDB) IsTxFiltered() bool { return s.arbExtraData.arbTxFilter } @@ -829,7 +832,7 @@ func (s *StateDB) Copy() *StateDB { func (s *StateDB) Snapshot() int { id := s.nextRevisionId s.nextRevisionId++ - s.validRevisions = append(s.validRevisions, revision{id, s.journal.length(), new(big.Int).Set(s.arbExtraData.unexpectedBalanceDelta), s.arbExtraData.arbTxFilter}) + s.validRevisions = append(s.validRevisions, revision{id, s.journal.length(), new(big.Int).Set(s.arbExtraData.unexpectedBalanceDelta)}) return id } @@ -845,7 +848,6 @@ func (s *StateDB) RevertToSnapshot(revid int) { revision := s.validRevisions[idx] snapshot := revision.journalIndex s.arbExtraData.unexpectedBalanceDelta = new(big.Int).Set(revision.unexpectedBalanceDelta) - s.arbExtraData.arbTxFilter = revision.arbTxFilter // Replay the journal to undo changes and remove invalidated snapshots s.journal.revert(s, snapshot) diff --git a/core/vm/interface.go b/core/vm/interface.go index 46a4537dd3..c04aec6f8c 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -50,6 +50,7 @@ type StateDB interface { // Arbitrum FilterTx() + ClearTxFilter() IsTxFiltered() bool Deterministic() bool