@ -23,7 +23,6 @@ import (
"maps"
"maps"
"math/big"
"math/big"
"slices"
"slices"
"sort"
"sync"
"sync"
"sync/atomic"
"sync/atomic"
"time"
"time"
@ -48,11 +47,6 @@ import (
// TriesInMemory represents the number of layers that are kept in RAM.
// TriesInMemory represents the number of layers that are kept in RAM.
const TriesInMemory = 128
const TriesInMemory = 128
type revision struct {
id int
journalIndex int
}
type mutationType int
type mutationType int
const (
const (
@ -143,9 +137,7 @@ type StateDB struct {
// Journal of state modifications. This is the backbone of
// Journal of state modifications. This is the backbone of
// Snapshot and RevertToSnapshot.
// Snapshot and RevertToSnapshot.
journal * journal
journal * journal
validRevisions [ ] revision
nextRevisionId int
// State witness if cross validation is needed
// State witness if cross validation is needed
witness * stateless . Witness
witness * stateless . Witness
@ -258,7 +250,7 @@ func (s *StateDB) Error() error {
}
}
func ( s * StateDB ) AddLog ( log * types . Log ) {
func ( s * StateDB ) AddLog ( log * types . Log ) {
s . journal . append ( addLogChange { txhash : s . thash } )
s . journal . logChange ( s . thash )
log . TxHash = s . thash
log . TxHash = s . thash
log . TxIndex = uint ( s . txIndex )
log . TxIndex = uint ( s . txIndex )
@ -292,7 +284,6 @@ func (s *StateDB) Logs() []*types.Log {
// AddPreimage records a SHA3 preimage seen by the VM.
// AddPreimage records a SHA3 preimage seen by the VM.
func ( s * StateDB ) AddPreimage ( hash common . Hash , preimage [ ] byte ) {
func ( s * StateDB ) AddPreimage ( hash common . Hash , preimage [ ] byte ) {
if _ , ok := s . preimages [ hash ] ; ! ok {
if _ , ok := s . preimages [ hash ] ; ! ok {
s . journal . append ( addPreimageChange { hash : hash } )
s . preimages [ hash ] = slices . Clone ( preimage )
s . preimages [ hash ] = slices . Clone ( preimage )
}
}
}
}
@ -304,14 +295,14 @@ func (s *StateDB) Preimages() map[common.Hash][]byte {
// AddRefund adds gas to the refund counter
// AddRefund adds gas to the refund counter
func ( s * StateDB ) AddRefund ( gas uint64 ) {
func ( s * StateDB ) AddRefund ( gas uint64 ) {
s . journal . append ( refundChange { prev : s . refund } )
s . journal . refundChange ( s . refund )
s . refund += gas
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 . append ( refundChange { prev : s . refund } )
s . journal . refundChange ( s . refund )
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 ) )
}
}
@ -508,20 +499,17 @@ func (s *StateDB) SelfDestruct(addr common.Address) {
if stateObject == nil {
if stateObject == nil {
return
return
}
}
var (
// Regardless of whether it is already destructed or not, we do have to
prev = new ( uint256 . Int ) . Set ( stateObject . Balance ( ) )
// journal the balance-change, if we set it to zero here.
n = new ( uint256 . Int )
if ! stateObject . Balance ( ) . IsZero ( ) {
)
stateObject . SetBalance ( new ( uint256 . Int ) , tracing . BalanceDecreaseSelfdestruct )
s . journal . append ( selfDestructChange {
}
account : & addr ,
// If it is already marked as self-destructed, we do not need to add it
prev : stateObject . selfDestructed ,
// for journalling a second time.
prevbalance : prev ,
if ! stateObject . selfDestructed {
} )
s . journal . destruct ( addr )
if s . logger != nil && s . logger . OnBalanceChange != nil && prev . Sign ( ) > 0 {
stateObject . markSelfdestructed ( )
s . logger . OnBalanceChange ( addr , prev . ToBig ( ) , n . ToBig ( ) , tracing . BalanceDecreaseSelfdestruct )
}
}
stateObject . markSelfdestructed ( )
stateObject . data . Balance = n
}
}
func ( s * StateDB ) Selfdestruct6780 ( addr common . Address ) {
func ( s * StateDB ) Selfdestruct6780 ( addr common . Address ) {
@ -542,11 +530,7 @@ func (s *StateDB) SetTransientState(addr common.Address, key, value common.Hash)
if prev == value {
if prev == value {
return
return
}
}
s . journal . append ( transientStorageChange {
s . journal . transientStateChange ( addr , key , prev )
account : & addr ,
key : key ,
prevalue : prev ,
} )
s . setTransientState ( addr , key , value )
s . setTransientState ( addr , key , value )
}
}
@ -668,7 +652,7 @@ func (s *StateDB) getOrNewStateObject(addr common.Address) *stateObject {
// existing account with the given address, otherwise it will be silently overwritten.
// existing account with the given address, otherwise it will be silently overwritten.
func ( s * StateDB ) createObject ( addr common . Address ) * stateObject {
func ( s * StateDB ) createObject ( addr common . Address ) * stateObject {
obj := newObject ( s , addr , nil )
obj := newObject ( s , addr , nil )
s . journal . append ( createObjectChange { account : & addr } )
s . journal . createObject ( addr )
s . setStateObject ( obj )
s . setStateObject ( obj )
return obj
return obj
}
}
@ -690,7 +674,7 @@ func (s *StateDB) CreateContract(addr common.Address) {
obj := s . getStateObject ( addr )
obj := s . getStateObject ( addr )
if ! obj . newContract {
if ! obj . newContract {
obj . newContract = true
obj . newContract = true
s . journal . append ( createContractChange { account : addr } )
s . journal . createContract ( addr )
}
}
}
}
@ -714,8 +698,6 @@ func (s *StateDB) Copy() *StateDB {
logSize : s . logSize ,
logSize : s . logSize ,
preimages : maps . Clone ( s . preimages ) ,
preimages : maps . Clone ( s . preimages ) ,
journal : s . journal . copy ( ) ,
journal : s . journal . copy ( ) ,
validRevisions : slices . Clone ( s . validRevisions ) ,
nextRevisionId : s . nextRevisionId ,
// In order for the block producer to be able to use and make additions
// In order for the block producer to be able to use and make additions
// to the snapshot tree, we need to copy that as well. Otherwise, any
// to the snapshot tree, we need to copy that as well. Otherwise, any
@ -761,26 +743,12 @@ 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 {
id := s . nextRevisionId
return s . journal . snapshot ( )
s . nextRevisionId ++
s . validRevisions = append ( s . validRevisions , revision { id , s . journal . length ( ) } )
return id
}
}
// 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 ) {
// Find the snapshot in the stack of valid snapshots.
s . journal . revertToSnapshot ( revid , s )
idx := sort . Search ( len ( s . validRevisions ) , func ( i int ) bool {
return s . validRevisions [ i ] . id >= revid
} )
if idx == len ( s . validRevisions ) || s . validRevisions [ idx ] . id != revid {
panic ( fmt . Errorf ( "revision id %v cannot be reverted" , revid ) )
}
snapshot := s . validRevisions [ idx ] . journalIndex
// Replay the journal to undo changes and remove invalidated snapshots
s . journal . revert ( s , snapshot )
s . validRevisions = s . validRevisions [ : idx ]
}
}
// GetRefund returns the current value of the refund counter.
// GetRefund returns the current value of the refund counter.
@ -996,11 +964,8 @@ func (s *StateDB) SetTxContext(thash common.Hash, ti int) {
}
}
func ( s * StateDB ) clearJournalAndRefund ( ) {
func ( s * StateDB ) clearJournalAndRefund ( ) {
if len ( s . journal . entries ) > 0 {
s . journal . reset ( )
s . journal = newJournal ( )
s . refund = 0
s . refund = 0
}
s . validRevisions = s . validRevisions [ : 0 ] // Snapshots can be created without journal entries
}
}
// fastDeleteStorage is the function that efficiently deletes the storage trie
// fastDeleteStorage is the function that efficiently deletes the storage trie
@ -1431,7 +1396,7 @@ func (s *StateDB) Prepare(rules params.Rules, sender, coinbase common.Address, d
// AddAddressToAccessList adds the given address to the access list
// AddAddressToAccessList adds the given address to the access list
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 . append ( accessListAddAccountChange { & addr } )
s . journal . accessListAddAccount ( addr )
}
}
}
}
@ -1443,13 +1408,10 @@ func (s *StateDB) AddSlotToAccessList(addr common.Address, slot common.Hash) {
// scope of 'address' without having the 'address' become already added
// scope of 'address' without having the 'address' become already added
// 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 . append ( accessListAddAccountChange { & addr } )
s . journal . accessListAddAccount ( addr )
}
}
if slotMod {
if slotMod {
s . journal . append ( accessListAddSlotChange {
s . journal . accessListAddSlot ( addr , slot )
address : & addr ,
slot : & slot ,
} )
}
}
}
}