mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-25 14:16:44 +00:00
add parallel exe with simulated prestate
This commit is contained in:
parent
45501be321
commit
c25104f696
4 changed files with 250 additions and 34 deletions
|
|
@ -3,7 +3,7 @@ package core
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"sync"
|
"runtime"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc"
|
"github.com/ethereum/go-ethereum/consensus/misc"
|
||||||
|
|
@ -11,8 +11,18 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type PreStateType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
BALPreState PreStateType = iota
|
||||||
|
SeqPreState // Only for debug
|
||||||
|
)
|
||||||
|
|
||||||
|
const preStateType = SeqPreState
|
||||||
|
|
||||||
type ParallelStateProcessor struct {
|
type ParallelStateProcessor struct {
|
||||||
config *params.ChainConfig // Chain configuration options
|
config *params.ChainConfig // Chain configuration options
|
||||||
chain *HeaderChain // Canonical header chain
|
chain *HeaderChain // Canonical header chain
|
||||||
|
|
@ -66,30 +76,45 @@ func (p *ParallelStateProcessor) executeParallel(block *types.Block, statedb *st
|
||||||
blockHash = block.Hash()
|
blockHash = block.Hash()
|
||||||
blockNumber = block.Number()
|
blockNumber = block.Number()
|
||||||
allLogs []*types.Log
|
allLogs []*types.Log
|
||||||
wg sync.WaitGroup
|
|
||||||
preStatedb = statedb.Copy()
|
preStatedb = statedb.Copy()
|
||||||
sequentialEvm = vm.NewEVM(*blockContext, preStatedb, p.config, cfg)
|
preStateProvider PreStateProvider
|
||||||
seqUsedGas = new(uint64)
|
workers errgroup.Group
|
||||||
)
|
)
|
||||||
|
workers.SetLimit(runtime.NumCPU() / 2)
|
||||||
// Fetch prestate for each tx
|
// Fetch prestate for each tx
|
||||||
|
|
||||||
|
// todo: handle gp with RW lock
|
||||||
|
switch preStateType {
|
||||||
|
case BALPreState:
|
||||||
|
panic("unimplemented")
|
||||||
|
case SeqPreState:
|
||||||
|
{
|
||||||
|
gpcp := *gp
|
||||||
|
preStateProvider = &SequentialPrestateProvider{
|
||||||
|
statedb: preStatedb,
|
||||||
|
block: block,
|
||||||
|
gp: &gpcp,
|
||||||
|
signer: signer,
|
||||||
|
usedGas: new(uint64),
|
||||||
|
evm: vm.NewEVM(*blockContext, preStatedb, p.config, cfg),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Parallel executing the transaction
|
// Parallel executing the transaction
|
||||||
postStates := make([]*state.StateDB, len(block.Transactions()))
|
|
||||||
postEntries := make([][]state.JournalEntry, len(block.Transactions()))
|
postEntries := make([][]state.JournalEntry, len(block.Transactions()))
|
||||||
for i, tx := range block.Transactions() {
|
for i, tx := range block.Transactions() {
|
||||||
postStates[i] = preStatedb.Copy() // Copy the state for each transaction
|
cleanStatedb, err := preStateProvider.PrestateAtIndex(i)
|
||||||
cleanStatedb := postStates[i]
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
i := i
|
i := i
|
||||||
|
workers.Go(func() error {
|
||||||
wg.Add(1)
|
|
||||||
go func() {
|
|
||||||
defer wg.Done()
|
|
||||||
|
|
||||||
usedGas := new(uint64)
|
usedGas := new(uint64)
|
||||||
msg, err := TransactionToMessage(tx, signer, header.BaseFee)
|
msg, err := TransactionToMessage(tx, signer, header.BaseFee)
|
||||||
// todo: handle error: break all routines and return error
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("could not apply tx %d [%v]: %v", i, tx.Hash().Hex(), err)
|
return err
|
||||||
}
|
}
|
||||||
cleanStatedb.SetTxContext(tx.Hash(), i)
|
cleanStatedb.SetTxContext(tx.Hash(), i)
|
||||||
|
|
||||||
|
|
@ -97,26 +122,22 @@ func (p *ParallelStateProcessor) executeParallel(block *types.Block, statedb *st
|
||||||
|
|
||||||
receipt, entries, err := ApplyTransactionWithParallelEVM(msg, gp, cleanStatedb, blockNumber, blockHash, tx, usedGas, evm)
|
receipt, entries, err := ApplyTransactionWithParallelEVM(msg, gp, cleanStatedb, blockNumber, blockHash, tx, usedGas, evm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("could not apply parallel tx %d [%v]: %v", i, tx.Hash().Hex(), err)
|
return err
|
||||||
}
|
}
|
||||||
receipts[i] = receipt
|
receipts[i] = receipt
|
||||||
postEntries[i] = entries
|
postEntries[i] = entries
|
||||||
}()
|
|
||||||
|
|
||||||
// execute the transaction again to simulate the state changes
|
// if i == len(block.Transactions())-1 {
|
||||||
msg, err := TransactionToMessage(tx, signer, header.BaseFee)
|
// *statedb = *cleanStatedb
|
||||||
|
// }
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
err := workers.Wait()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not apply tx to msg %d [%v]: %w", i, tx.Hash().Hex(), err)
|
return nil, err
|
||||||
}
|
}
|
||||||
preStatedb.SetTxContext(tx.Hash(), i)
|
|
||||||
|
|
||||||
_, err = ApplyTransactionWithEVM(msg, gp, preStatedb, blockNumber, blockHash, tx, seqUsedGas, sequentialEvm)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wg.Wait()
|
|
||||||
// Merge state changes
|
// Merge state changes
|
||||||
// - Append receipts
|
// - Append receipts
|
||||||
// - Sum usedGas
|
// - Sum usedGas
|
||||||
|
|
@ -196,3 +217,45 @@ func ApplyTransactionWithParallelEVM(msg *Message, gp *GasPool, statedb *state.S
|
||||||
|
|
||||||
return MakeReceipt(evm, result, statedb, blockNumber, blockHash, tx, *usedGas, root), entries, nil
|
return MakeReceipt(evm, result, statedb, blockNumber, blockHash, tx, *usedGas, root), entries, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PreStateProvider interface {
|
||||||
|
PrestateAtIndex(i int) (*state.StateDB, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type SequentialPrestateProvider struct {
|
||||||
|
statedb *state.StateDB
|
||||||
|
block *types.Block
|
||||||
|
gp *GasPool
|
||||||
|
signer types.Signer
|
||||||
|
// contex
|
||||||
|
usedGas *uint64
|
||||||
|
evm *vm.EVM
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SequentialPrestateProvider) PrestateAtIndex(i int) (*state.StateDB, error) {
|
||||||
|
if i < 0 || i > len(s.block.Transactions()) {
|
||||||
|
return nil, fmt.Errorf("tx index %d out of range [0, %d)", i, len(s.block.Transactions()))
|
||||||
|
}
|
||||||
|
if i == 0 {
|
||||||
|
return s.statedb.Copy(), nil // first transaction uses the original state
|
||||||
|
}
|
||||||
|
i = i - 1
|
||||||
|
tx := s.block.Transactions()[i]
|
||||||
|
signer := s.signer
|
||||||
|
header := s.block.Header()
|
||||||
|
statedb := s.statedb
|
||||||
|
blockHash := s.block.Hash()
|
||||||
|
blockNumber := s.block.Number()
|
||||||
|
// execute the transaction again to simulate the state changes
|
||||||
|
msg, err := TransactionToMessage(tx, signer, header.BaseFee)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
|
||||||
|
}
|
||||||
|
statedb.SetTxContext(tx.Hash(), i)
|
||||||
|
|
||||||
|
_, err = ApplyTransactionWithEVM(msg, s.gp, statedb, blockNumber, blockHash, tx, s.usedGas, s.evm)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
|
||||||
|
}
|
||||||
|
return statedb.Copy(), nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,34 @@ func newJournal() *journal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func PrintJournal(entries []JournalEntry) {
|
||||||
|
for _, entry := range entries {
|
||||||
|
if entry == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
switch v := entry.(type) {
|
||||||
|
case createObjectChange:
|
||||||
|
fmt.Println("createObjectChange")
|
||||||
|
case createContractChange:
|
||||||
|
fmt.Println("createContractChange", v)
|
||||||
|
case selfDestructChange:
|
||||||
|
fmt.Println("selfDestructChange")
|
||||||
|
case balanceChange:
|
||||||
|
fmt.Println("balanceChange", v)
|
||||||
|
case nonceChange:
|
||||||
|
fmt.Println("nonceChange", v)
|
||||||
|
case storageChange:
|
||||||
|
fmt.Println("storageChange", v)
|
||||||
|
case codeChange:
|
||||||
|
fmt.Println("codeChange")
|
||||||
|
case refundChange:
|
||||||
|
fmt.Println("refundChange")
|
||||||
|
default:
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// reset clears the journal, after this operation the journal can be used anew.
|
// reset clears the journal, after this operation the journal can be used anew.
|
||||||
// It is semantically similar to calling 'newJournal', but the underlying slices
|
// It is semantically similar to calling 'newJournal', but the underlying slices
|
||||||
// can be reused.
|
// can be reused.
|
||||||
|
|
@ -108,6 +136,21 @@ func (j *journal) revertToSnapshot(revid int, s *StateDB) {
|
||||||
j.validRevisions = j.validRevisions[:idx]
|
j.validRevisions = j.validRevisions[:idx]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (j *journal) revertToSnapshotWithoutRevertState(revid int, s *StateDB) {
|
||||||
|
// Find the snapshot in the stack of valid snapshots.
|
||||||
|
idx := sort.Search(len(j.validRevisions), func(i int) bool {
|
||||||
|
return j.validRevisions[i].id >= revid
|
||||||
|
})
|
||||||
|
if idx == len(j.validRevisions) || j.validRevisions[idx].id != revid {
|
||||||
|
panic(fmt.Errorf("revision id %v cannot be reverted", revid))
|
||||||
|
}
|
||||||
|
snapshot := j.validRevisions[idx].journalIndex
|
||||||
|
|
||||||
|
// Replay the journal to undo journal changes and remove invalidated snapshots
|
||||||
|
j.revertWithoutRevertState(s, snapshot)
|
||||||
|
j.validRevisions = j.validRevisions[:idx]
|
||||||
|
}
|
||||||
|
|
||||||
// append inserts a new modification entry to the end of the change journal.
|
// append inserts a new modification entry to the end of the change journal.
|
||||||
func (j *journal) append(entry journalEntry) {
|
func (j *journal) append(entry journalEntry) {
|
||||||
j.entries = append(j.entries, entry)
|
j.entries = append(j.entries, entry)
|
||||||
|
|
@ -133,6 +176,18 @@ func (j *journal) revert(statedb *StateDB, snapshot int) {
|
||||||
j.entries = j.entries[:snapshot]
|
j.entries = j.entries[:snapshot]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (j *journal) revertWithoutRevertState(statedb *StateDB, snapshot int) {
|
||||||
|
for i := len(j.entries) - 1; i >= snapshot; i-- {
|
||||||
|
// Drop any dirty tracking induced by the change
|
||||||
|
if addr := j.entries[i].dirtied(); addr != nil {
|
||||||
|
if j.dirties[*addr]--; j.dirties[*addr] == 0 {
|
||||||
|
delete(j.dirties, *addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
j.entries = j.entries[:snapshot]
|
||||||
|
}
|
||||||
|
|
||||||
// dirty explicitly sets an address to dirty, even if the change entries would
|
// dirty explicitly sets an address to dirty, even if the change entries would
|
||||||
// otherwise suggest it as clean. This method is an ugly hack to handle the RIPEMD
|
// otherwise suggest it as clean. This method is an ugly hack to handle the RIPEMD
|
||||||
// precompile consensus exception.
|
// precompile consensus exception.
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,7 @@ func (s *stateObject) markSelfdestructed() {
|
||||||
|
|
||||||
func (s *stateObject) touch() {
|
func (s *stateObject) touch() {
|
||||||
s.db.journal.touchChange(s.address)
|
s.db.journal.touchChange(s.address)
|
||||||
|
s.db.updateJournal.touchChange(s.address)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getTrie returns the associated storage trie. The trie will be opened if it's
|
// getTrie returns the associated storage trie. The trie will be opened if it's
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,11 @@
|
||||||
package state
|
package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"maps"
|
"maps"
|
||||||
|
"os"
|
||||||
"slices"
|
"slices"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
@ -159,6 +161,84 @@ type StateDB struct {
|
||||||
StorageDeleted atomic.Int64 // Number of storage slots deleted during the state transition
|
StorageDeleted atomic.Int64 // Number of storage slots deleted during the state transition
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BALType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
OnlyKey BALType = iota
|
||||||
|
WithAddrKeySlotV
|
||||||
|
WithAllKV
|
||||||
|
BalKeyConstruction
|
||||||
|
BalKeyValConstruction
|
||||||
|
BalPreblockKeysPostValues
|
||||||
|
)
|
||||||
|
|
||||||
|
type BALs struct {
|
||||||
|
Pre map[uint64]types.AccessList `json:"pre"`
|
||||||
|
Post map[uint64]map[int]TxPostValues `json:"post"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AcctPostValues struct {
|
||||||
|
Nonce uint64 `json:"nonce"`
|
||||||
|
Balance *uint256.Int `json:"balance"`
|
||||||
|
Code []byte `json:"code"`
|
||||||
|
StorageKV map[common.Hash]common.Hash `json:"storageKV"`
|
||||||
|
Destruct bool `json:"destruct"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// For acccount destruct or storage clearing corresponding values would be 0
|
||||||
|
type TxPostValues map[common.Address]*AcctPostValues
|
||||||
|
|
||||||
|
var (
|
||||||
|
AllBlockBal = BALs{}
|
||||||
|
AllBlockAccessLists = map[uint64]types.AccessList{}
|
||||||
|
// Blocknumber => TxIndex => TxPostValues
|
||||||
|
AllBlockTxPostValues = map[uint64]map[int]TxPostValues{}
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
balType = BalPreblockKeysPostValues
|
||||||
|
// balType = OnlyKey
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// load the access lists for all blocks
|
||||||
|
println("Importing BAL:", balType)
|
||||||
|
var (
|
||||||
|
fileName string
|
||||||
|
)
|
||||||
|
switch balType {
|
||||||
|
case OnlyKey:
|
||||||
|
{
|
||||||
|
println("bal onlykey")
|
||||||
|
fileName = "access_lists.2000.json"
|
||||||
|
}
|
||||||
|
case WithAddrKeySlotV:
|
||||||
|
case WithAllKV:
|
||||||
|
case BalKeyConstruction:
|
||||||
|
{
|
||||||
|
}
|
||||||
|
case BalPreblockKeysPostValues:
|
||||||
|
{
|
||||||
|
println("bal preblock keys post values")
|
||||||
|
fileName = "access_lists_kpostv.json"
|
||||||
|
data, err := os.ReadFile(fileName)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to load access lists", "err", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(data, &AllBlockBal); err != nil {
|
||||||
|
panic("Failed to unmarshal access lists")
|
||||||
|
}
|
||||||
|
|
||||||
|
AllBlockAccessLists = AllBlockBal.Pre
|
||||||
|
AllBlockTxPostValues = AllBlockBal.Post
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println("Imported BAL", fileName)
|
||||||
|
println("Access lists loaded:", len(AllBlockAccessLists), "blocks with pre-block-keys, ", len(AllBlockTxPostValues), "blocks with post values")
|
||||||
|
}
|
||||||
|
|
||||||
// New creates a new state from a given trie.
|
// New creates a new state from a given trie.
|
||||||
func New(root common.Hash, db Database) (*StateDB, error) {
|
func New(root common.Hash, db Database) (*StateDB, error) {
|
||||||
reader, err := db.Reader(root)
|
reader, err := db.Reader(root)
|
||||||
|
|
@ -245,6 +325,7 @@ func (s *StateDB) Error() error {
|
||||||
|
|
||||||
func (s *StateDB) AddLog(log *types.Log) {
|
func (s *StateDB) AddLog(log *types.Log) {
|
||||||
s.journal.logChange(s.thash)
|
s.journal.logChange(s.thash)
|
||||||
|
s.updateJournal.logChange(s.thash)
|
||||||
|
|
||||||
log.TxHash = s.thash
|
log.TxHash = s.thash
|
||||||
log.TxIndex = uint(s.txIndex)
|
log.TxIndex = uint(s.txIndex)
|
||||||
|
|
@ -288,6 +369,7 @@ func (s *StateDB) Preimages() map[common.Hash][]byte {
|
||||||
func (s *StateDB) AddRefund(gas uint64) {
|
func (s *StateDB) AddRefund(gas uint64) {
|
||||||
s.journal.refundChange(s.refund)
|
s.journal.refundChange(s.refund)
|
||||||
s.refund += gas
|
s.refund += gas
|
||||||
|
s.updateJournal.refundChange(s.refund)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StateDB) JournalEntriesCopy() []JournalEntry {
|
func (s *StateDB) JournalEntriesCopy() []JournalEntry {
|
||||||
|
|
@ -320,16 +402,23 @@ func (s *StateDB) MergeState(entries []JournalEntry) {
|
||||||
}
|
}
|
||||||
case codeChange:
|
case codeChange:
|
||||||
s.SetCode(v.account, v.prevCode)
|
s.SetCode(v.account, v.prevCode)
|
||||||
|
case refundChange:
|
||||||
|
s.setRefund(v.prev)
|
||||||
default:
|
default:
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *StateDB) setRefund(gas uint64) {
|
||||||
|
s.refund = gas
|
||||||
|
}
|
||||||
|
|
||||||
// SubRefund removes gas from the refund counter.
|
// SubRefund removes gas from the refund counter.
|
||||||
// This method will panic if the refund counter goes below zero
|
// This method will panic if the refund counter goes below zero
|
||||||
func (s *StateDB) SubRefund(gas uint64) {
|
func (s *StateDB) SubRefund(gas uint64) {
|
||||||
s.journal.refundChange(s.refund)
|
s.journal.refundChange(s.refund)
|
||||||
|
s.updateJournal.refundChange(s.refund - gas)
|
||||||
if gas > s.refund {
|
if gas > s.refund {
|
||||||
panic(fmt.Sprintf("Refund counter below zero (gas: %d > refund: %d)", gas, s.refund))
|
panic(fmt.Sprintf("Refund counter below zero (gas: %d > refund: %d)", gas, s.refund))
|
||||||
}
|
}
|
||||||
|
|
@ -581,6 +670,7 @@ func (s *StateDB) SetTransientState(addr common.Address, key, value common.Hash)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.journal.transientStateChange(addr, key, prev)
|
s.journal.transientStateChange(addr, key, prev)
|
||||||
|
s.updateJournal.transientStateChange(addr, key, prev)
|
||||||
s.setTransientState(addr, key, value)
|
s.setTransientState(addr, key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -764,12 +854,15 @@ func (s *StateDB) Copy() *StateDB {
|
||||||
|
|
||||||
// Snapshot returns an identifier for the current revision of the state.
|
// Snapshot returns an identifier for the current revision of the state.
|
||||||
func (s *StateDB) Snapshot() int {
|
func (s *StateDB) Snapshot() int {
|
||||||
|
s.updateJournal.snapshot()
|
||||||
return s.journal.snapshot()
|
return s.journal.snapshot()
|
||||||
}
|
}
|
||||||
|
|
||||||
// RevertToSnapshot reverts all state changes made since the given revision.
|
// RevertToSnapshot reverts all state changes made since the given revision.
|
||||||
func (s *StateDB) RevertToSnapshot(revid int) {
|
func (s *StateDB) RevertToSnapshot(revid int) {
|
||||||
s.journal.revertToSnapshot(revid, s)
|
s.journal.revertToSnapshot(revid, s)
|
||||||
|
s.updateJournal.revertToSnapshotWithoutRevertState(revid, s)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRefund returns the current value of the refund counter.
|
// GetRefund returns the current value of the refund counter.
|
||||||
|
|
@ -981,6 +1074,7 @@ func (s *StateDB) SetTxContext(thash common.Hash, ti int) {
|
||||||
|
|
||||||
func (s *StateDB) clearJournalAndRefund() {
|
func (s *StateDB) clearJournalAndRefund() {
|
||||||
s.journal.reset()
|
s.journal.reset()
|
||||||
|
s.updateJournal.reset()
|
||||||
s.refund = 0
|
s.refund = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1429,6 +1523,7 @@ func (s *StateDB) Prepare(rules params.Rules, sender, coinbase common.Address, d
|
||||||
func (s *StateDB) AddAddressToAccessList(addr common.Address) {
|
func (s *StateDB) AddAddressToAccessList(addr common.Address) {
|
||||||
if s.accessList.AddAddress(addr) {
|
if s.accessList.AddAddress(addr) {
|
||||||
s.journal.accessListAddAccount(addr)
|
s.journal.accessListAddAccount(addr)
|
||||||
|
s.updateJournal.accessListAddAccount(addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1441,9 +1536,11 @@ func (s *StateDB) AddSlotToAccessList(addr common.Address, slot common.Hash) {
|
||||||
// to the access list (via call-variant, create, etc).
|
// to the access list (via call-variant, create, etc).
|
||||||
// Better safe than sorry, though
|
// Better safe than sorry, though
|
||||||
s.journal.accessListAddAccount(addr)
|
s.journal.accessListAddAccount(addr)
|
||||||
|
s.updateJournal.accessListAddAccount(addr)
|
||||||
}
|
}
|
||||||
if slotMod {
|
if slotMod {
|
||||||
s.journal.accessListAddSlot(addr, slot)
|
s.journal.accessListAddSlot(addr, slot)
|
||||||
|
s.updateJournal.accessListAddSlot(addr, slot)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue