Skip to content
This repository has been archived by the owner on Oct 25, 2024. It is now read-only.

Builder Efficient reverts #90

Merged
merged 57 commits into from
Sep 27, 2023
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
1593828
First attempt
Wazzymandias Jul 13, 2023
39e25e5
Try granular snaps
Wazzymandias Jul 13, 2023
d323b21
Try appending to access list and reverting on bundle failure
Wazzymandias Jul 19, 2023
d51683a
Revert to beginning using extra access list when available
Wazzymandias Jul 19, 2023
2445edb
Add access list and revision after apply to avoid index out of range …
Wazzymandias Jul 19, 2023
de80c00
Try copy before revert and avoid initial environment copy
Wazzymandias Jul 19, 2023
95b97ea
Update revert logic
Wazzymandias Jul 19, 2023
4b77fbe
Add access list parity
Wazzymandias Jul 19, 2023
e369cf6
Initial commit for efficient revert experimentation
Wazzymandias Jul 19, 2023
c2a1a95
Add additional unit tests and fix unit test errors, reduce duplicate …
Wazzymandias Jul 26, 2023
4908ea8
Init BuilderRateLimitResubmitInterval builder config param from comma…
vazha Jul 19, 2023
dc5cc49
Update readme to include greedy-buckets for miner.algotype (#87)
Wazzymandias Jul 24, 2023
4a9e785
Merge remote-tracking branch 'origin/main' into efficient-reverts
Wazzymandias Jul 26, 2023
5ddc19b
Update godoc, remove unused getter for access list, add CLI flag to b…
Wazzymandias Jul 26, 2023
6ccec93
Fix linter errors
Wazzymandias Jul 26, 2023
91b5283
Add retry logic for multi-tx-snapshot block build algorithm
Wazzymandias Jul 28, 2023
da04d6f
Update unit tests to test EnableMultiTxSnap
Wazzymandias Jul 28, 2023
b04fd4b
Rollback retry logic
Wazzymandias Jul 28, 2023
597534f
Fix linter error
Wazzymandias Jul 28, 2023
e1207eb
Merge remote-tracking branch 'origin/main' into efficient-reverts
Wazzymandias Jul 28, 2023
f282589
Change account touch tracer to access list tracer for env changes
Wazzymandias Jul 31, 2023
bacd7e4
Update greedy builder to use passed in algorithm configuration rather…
Wazzymandias Jul 31, 2023
49ba79b
Rollback profit for env changes
Wazzymandias Jul 31, 2023
d8cf812
Fix bugs
Wazzymandias Jul 31, 2023
bf94410
Merge branch 'quickfix-cli' into efficient-reverts
Wazzymandias Aug 1, 2023
e227c37
Merge remote-tracking branch 'origin/main' into efficient-reverts
Wazzymandias Aug 1, 2023
4317b0a
Add new multi-transaction snapshot stack to support more than one act…
Wazzymandias Aug 2, 2023
072890f
Merge remote-tracking branch 'origin/main' into efficient-reverts
Wazzymandias Aug 3, 2023
0e3057b
Clean up code, add comprehensive stack tests with fuzzing, fix edge c…
Wazzymandias Aug 4, 2023
a16791d
Fix linter error
Wazzymandias Aug 4, 2023
d6d5cae
Add refund support to efficient revert so state returns to correct re…
Wazzymandias Aug 7, 2023
52ddc82
Revert some refactor changes
Wazzymandias Aug 7, 2023
f3911d2
Merge remote-tracking branch 'origin/main' into efficient-reverts
Wazzymandias Aug 9, 2023
0d612c6
Add unit tests for state comparison, potential fix for gas and root m…
Wazzymandias Aug 9, 2023
fc32a84
Fix linter error
Wazzymandias Aug 9, 2023
bdc7422
Try using top level changes to avoid env mutations
Wazzymandias Aug 9, 2023
e526d0e
Debug commit
Wazzymandias Aug 9, 2023
da5c54e
DRY profit logic
Wazzymandias Aug 10, 2023
ab3aaaf
Revert commit
Wazzymandias Aug 15, 2023
b116abd
Merge remote-tracking branch 'origin/main' into efficient-reverts
Wazzymandias Aug 15, 2023
4e3bc45
Merge remote-tracking branch 'origin/main' into efficient-reverts
Wazzymandias Aug 16, 2023
1823163
small changes
Wazzymandias Aug 19, 2023
72f182f
Add fuzz state using state smart contract, add Copy method for multi-…
Wazzymandias Aug 21, 2023
0259e06
fix a bug with state reverts of accounts that are not touched accordi…
dvush Aug 21, 2023
3045b14
Lint
Wazzymandias Aug 21, 2023
c1ae873
Simplify test
Wazzymandias Aug 21, 2023
1062c82
Fix linter error
Wazzymandias Aug 21, 2023
c14c299
Use different builders instead of configuration switch since major re…
Wazzymandias Aug 23, 2023
ca7e7a7
Merge remote-tracking branch 'origin/main' into efficient-reverts
Wazzymandias Aug 23, 2023
811b294
Update env changes to reduce redundancy and make control flow easier …
Wazzymandias Aug 23, 2023
49157e8
Fix linter error
Wazzymandias Aug 23, 2023
03dd29c
Remove debug validation
Wazzymandias Aug 23, 2023
f2c5320
Update comments, add touch change to state fuzz test smart contract
Wazzymandias Aug 25, 2023
3695a2b
Merge remote-tracking branch 'origin/main' into efficient-reverts
Wazzymandias Sep 1, 2023
ef00a1f
Add fuzz tests for transient storage and account touch operations
Wazzymandias Sep 8, 2023
2d3c57a
Remove unused code
Wazzymandias Sep 27, 2023
5f07c8c
Merge remote-tracking branch 'origin/main' into efficient-reverts
Wazzymandias Sep 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ var (

builderApiFlags = []cli.Flag{
utils.BuilderEnabled,
utils.BuilderEnableMultiTxSnapshot,
utils.BuilderAlgoTypeFlag,
utils.BuilderPriceCutoffPercentFlag,
utils.BuilderEnableValidatorChecks,
Expand Down
9 changes: 9 additions & 0 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,14 @@ var (
Usage: "Enable the builder",
Category: flags.BuilderCategory,
}
BuilderEnableMultiTxSnapshot = &cli.BoolFlag{
Name: "builder.multi_tx_snapshot",
Usage: "Enable multi-transaction snapshots for block building, " +
"which decrease amount of state copying on bundle reverts (note: experimental)",
EnvVars: []string{"BUILDER_MULTI_TX_SNAPSHOT"},
Value: ethconfig.Defaults.Miner.EnableMultiTransactionSnapshot,
Category: flags.BuilderCategory,
}

// BuilderAlgoTypeFlag replaces MinerAlgoTypeFlag to move away from deprecated miner package
// Note: builder.algotype was previously miner.algotype - this flag is still propagated to the miner configuration,
Expand Down Expand Up @@ -1954,6 +1962,7 @@ func setMiner(ctx *cli.Context, cfg *miner.Config) {
}
}

cfg.EnableMultiTransactionSnapshot = ctx.Bool(BuilderEnableMultiTxSnapshot.Name)
cfg.PriceCutoffPercent = ctx.Int(BuilderPriceCutoffPercentFlag.Name)
}

Expand Down
8 changes: 4 additions & 4 deletions core/state/access_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@ func newAccessList() *accessList {
}

// Copy creates an independent copy of an accessList.
func (a *accessList) Copy() *accessList {
func (al *accessList) Copy() *accessList {
cp := newAccessList()
for k, v := range a.addresses {
for k, v := range al.addresses {
cp.addresses[k] = v
}
cp.slots = make([]map[common.Hash]struct{}, len(a.slots))
for i, slotMap := range a.slots {
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{}{}
Expand Down
234 changes: 234 additions & 0 deletions core/state/multi_tx_snapshot.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
package state

import (
"math/big"

"github.com/ethereum/go-ethereum/common"
)

// MultiTxSnapshot retains StateDB changes for multiple transactions.
type MultiTxSnapshot struct {
invalid bool

numLogsAdded map[common.Hash]int

prevObjects map[common.Address]*stateObject

accountStorage map[common.Address]map[common.Hash]*common.Hash
accountBalance map[common.Address]*big.Int
accountNonce map[common.Address]uint64
accountCode map[common.Address][]byte
accountCodeHash map[common.Address][]byte

accountSuicided map[common.Address]bool
accountDeleted map[common.Address]bool

accountNotPending map[common.Address]struct{}
accountNotDirty map[common.Address]struct{}
// TODO: snapdestructs, snapaccount storage
}

// NewMultiTxSnapshot creates a new MultiTxSnapshot
func NewMultiTxSnapshot() *MultiTxSnapshot {
return &MultiTxSnapshot{
numLogsAdded: make(map[common.Hash]int),
prevObjects: make(map[common.Address]*stateObject),
accountStorage: make(map[common.Address]map[common.Hash]*common.Hash),
accountBalance: make(map[common.Address]*big.Int),
accountNonce: make(map[common.Address]uint64),
accountCode: make(map[common.Address][]byte),
accountCodeHash: make(map[common.Address][]byte),
accountSuicided: make(map[common.Address]bool),
accountDeleted: make(map[common.Address]bool),
accountNotPending: make(map[common.Address]struct{}),
accountNotDirty: make(map[common.Address]struct{}),
}
}

// updateFromJournal updates the snapshot with the changes from the journal.
func (s *MultiTxSnapshot) updateFromJournal(journal *journal) {
for _, journalEntry := range journal.entries {
switch entry := journalEntry.(type) {
case balanceChange:
s.updateBalanceChange(entry)
case nonceChange:
s.updateNonceChange(entry)
case codeChange:
s.updateCodeChange(entry)
case addLogChange:
s.numLogsAdded[entry.txhash]++
case createObjectChange:
s.updateCreateObjectChange(entry)
case resetObjectChange:
s.updateResetObjectChange(entry)
case suicideChange:
s.updateSuicideChange(entry)
}
}
}

// objectChanged returns whether the object was changed (in the set of prevObjects).
Wazzymandias marked this conversation as resolved.
Show resolved Hide resolved
func (s *MultiTxSnapshot) objectChanged(address common.Address) bool {
_, ok := s.prevObjects[address]
return ok
}

// updateBalanceChange updates the snapshot with the balance change.
func (s *MultiTxSnapshot) updateBalanceChange(change balanceChange) {
if s.objectChanged(*change.account) {
return
}
if _, ok := s.accountBalance[*change.account]; !ok {
s.accountBalance[*change.account] = change.prev
}
}

// updateNonceChange updates the snapshot with the nonce change.
func (s *MultiTxSnapshot) updateNonceChange(change nonceChange) {
if s.objectChanged(*change.account) {
return
}
if _, ok := s.accountNonce[*change.account]; !ok {
s.accountNonce[*change.account] = change.prev
}
}

// updateCodeChange updates the snapshot with the code change.
func (s *MultiTxSnapshot) updateCodeChange(change codeChange) {
if s.objectChanged(*change.account) {
return
}
if _, ok := s.accountCode[*change.account]; !ok {
s.accountCode[*change.account] = change.prevcode
s.accountCodeHash[*change.account] = change.prevhash
}
}

// updateResetObjectChange updates the snapshot with the reset object change.
func (s *MultiTxSnapshot) updateResetObjectChange(change resetObjectChange) {
address := change.prev.address
if _, ok := s.prevObjects[address]; !ok {
s.prevObjects[address] = change.prev
}
}

// updateCreateObjectChange updates the snapshot with the createObjectChange.
func (s *MultiTxSnapshot) updateCreateObjectChange(change createObjectChange) {
if _, ok := s.prevObjects[*change.account]; !ok {
s.prevObjects[*change.account] = nil
}
}

// updateSuicideChange updates the snapshot with the suicide change.
func (s *MultiTxSnapshot) updateSuicideChange(change suicideChange) {
if s.objectChanged(*change.account) {
return
}
if _, ok := s.accountSuicided[*change.account]; !ok {
s.accountSuicided[*change.account] = change.prev
}
if _, ok := s.accountBalance[*change.account]; !ok {
s.accountBalance[*change.account] = change.prevbalance
}
}

// updatePendingStorage updates the snapshot with the pending storage change.
func (s *MultiTxSnapshot) updatePendingStorage(address common.Address, key, value common.Hash, ok bool) {
if s.objectChanged(address) {
return
}
if _, ok := s.accountStorage[address]; !ok {
s.accountStorage[address] = make(map[common.Hash]*common.Hash)
}
if _, ok := s.accountStorage[address][key]; ok {
return
}
if ok {
s.accountStorage[address][key] = &value
} else {
s.accountStorage[address][key] = nil
}
}

// updatePendingStatus updates the snapshot with previous pending status.
func (s *MultiTxSnapshot) updatePendingStatus(address common.Address, pending, dirty bool) {
if !pending {
s.accountNotPending[address] = struct{}{}
}
if !dirty {
s.accountNotDirty[address] = struct{}{}
}
}

// updateObjectDeleted updates the snapshot with the object deletion.
func (s *MultiTxSnapshot) updateObjectDeleted(address common.Address, deleted bool) {
if s.objectChanged(address) {
return
}
if _, ok := s.accountDeleted[address]; !ok {
s.accountDeleted[address] = deleted
}
}

// revertState reverts the state to the snapshot.
func (s *MultiTxSnapshot) revertState(st *StateDB) {
// remove all the logs added
for txhash, numLogs := range s.numLogsAdded {
lens := len(st.logs[txhash])
if lens == numLogs {
delete(st.logs, txhash)
} else {
st.logs[txhash] = st.logs[txhash][:lens-numLogs]
}
st.logSize -= uint(numLogs)
}

// restore the objects
for address, object := range s.prevObjects {
if object == nil {
delete(st.stateObjects, address)
} else {
st.stateObjects[address] = object
}
}

// restore storage
for address, storage := range s.accountStorage {
for key, value := range storage {
if value == nil {
delete(st.stateObjects[address].pendingStorage, key)
} else {
st.stateObjects[address].pendingStorage[key] = *value
}
}
}

// restore balance
for address, balance := range s.accountBalance {
st.stateObjects[address].setBalance(balance)
}
// restore nonce
for address, nonce := range s.accountNonce {
st.stateObjects[address].setNonce(nonce)
}
// restore code
for address, code := range s.accountCode {
st.stateObjects[address].setCode(common.BytesToHash(s.accountCodeHash[address]), code)
}
// restore suicided
for address, suicided := range s.accountSuicided {
st.stateObjects[address].suicided = suicided
}
// restore deleted
for address, deleted := range s.accountDeleted {
st.stateObjects[address].deleted = deleted
}

// restore pending status
for address := range s.accountNotPending {
delete(st.stateObjectsPending, address)
}
for address := range s.accountNotDirty {
delete(st.stateObjectsDirty, address)
}
}
Loading
Loading