diff --git a/core/state/change_set_writer.go b/core/state/change_set_writer.go index 98aeed1fd..59de3a85f 100644 --- a/core/state/change_set_writer.go +++ b/core/state/change_set_writer.go @@ -2,12 +2,13 @@ package state import ( "fmt" - "github.com/ledgerwatch/erigon-lib/kv/dbutils" "github.com/holiman/uint256" + libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/hexutility" "github.com/ledgerwatch/erigon-lib/kv" + "github.com/ledgerwatch/erigon-lib/kv/dbutils" historyv22 "github.com/ledgerwatch/erigon-lib/kv/temporal/historyv2" "github.com/ledgerwatch/erigon/core/types/accounts" @@ -70,6 +71,8 @@ func accountsEqual(a1, a2 *accounts.Account) bool { return false } else if a1.Balance.Cmp(&a2.Balance) != 0 { return false + } else if a1.Incarnation != a2.Incarnation { + return false } if a1.IsEmptyCodeHash() { if !a2.IsEmptyCodeHash() { diff --git a/core/state/db_state_writer.go b/core/state/db_state_writer.go index 0902a18a5..33c3c7620 100644 --- a/core/state/db_state_writer.go +++ b/core/state/db_state_writer.go @@ -4,13 +4,14 @@ import ( "bytes" "encoding/binary" "fmt" - dbutils2 "github.com/ledgerwatch/erigon-lib/kv/dbutils" "github.com/RoaringBitmap/roaring/roaring64" "github.com/holiman/uint256" + libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/kv/bitmapdb" + dbutils2 "github.com/ledgerwatch/erigon-lib/kv/dbutils" "github.com/ledgerwatch/erigon-lib/kv/temporal/historyv2" "github.com/ledgerwatch/erigon/common/math" @@ -74,6 +75,15 @@ func (dsw *DbStateWriter) UpdateAccountData(address libcommon.Address, original, if err := dsw.db.Put(kv.HashedAccounts, addrHash[:], value); err != nil { return err } + + if account.Incarnation == 0 && original.Incarnation > 0 { + var b [8]byte + binary.BigEndian.PutUint64(b[:], original.Incarnation) + if err := dsw.db.Put(kv.IncarnationMap, address[:], b[:]); err != nil { + return err + } + } + return nil } diff --git a/core/state/intra_block_state.go b/core/state/intra_block_state.go index 9064d22d3..2f2746870 100644 --- a/core/state/intra_block_state.go +++ b/core/state/intra_block_state.go @@ -547,23 +547,25 @@ func (sdb *IntraBlockState) createObject(addr libcommon.Address, previous *state func (sdb *IntraBlockState) CreateAccount(addr libcommon.Address, contractCreation bool) { var prevInc uint64 previous := sdb.getStateObject(addr) - if contractCreation { - if previous != nil && previous.selfdestructed { - prevInc = previous.data.Incarnation + if previous != nil && previous.selfdestructed { + prevInc = previous.data.Incarnation + } else { + if inc, err := sdb.stateReader.ReadAccountIncarnation(addr); err == nil { + prevInc = inc } else { - if inc, err := sdb.stateReader.ReadAccountIncarnation(addr); err == nil { - prevInc = inc - } else { - sdb.savedErr = err - } + sdb.savedErr = err } } + if previous != nil && prevInc < previous.data.PrevIncarnation { + prevInc = previous.data.PrevIncarnation + } newObj := sdb.createObject(addr, previous) if previous != nil && !previous.selfdestructed { newObj.data.Balance.Set(&previous.data.Balance) } newObj.data.Initialised = true + newObj.data.PrevIncarnation = prevInc if contractCreation { newObj.createdContract = true diff --git a/core/state/plain_state_writer.go b/core/state/plain_state_writer.go index 2fd011590..eb3361e58 100644 --- a/core/state/plain_state_writer.go +++ b/core/state/plain_state_writer.go @@ -2,11 +2,12 @@ package state import ( "encoding/binary" - "github.com/ledgerwatch/erigon-lib/kv/dbutils" "github.com/holiman/uint256" + libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/kv" + "github.com/ledgerwatch/erigon-lib/kv/dbutils" "github.com/ledgerwatch/erigon/core/types/accounts" "github.com/ledgerwatch/erigon/turbo/shards" @@ -56,6 +57,14 @@ func (w *PlainStateWriter) UpdateAccountData(address libcommon.Address, original w.accumulator.ChangeAccount(address, account.Incarnation, value) } + if account.Incarnation == 0 && original.Incarnation > 0 { + var b [8]byte + binary.BigEndian.PutUint64(b[:], original.Incarnation) + if err := w.db.Put(kv.IncarnationMap, address[:], b[:]); err != nil { + return err + } + } + return w.db.Put(kv.PlainState, address[:], value) } diff --git a/core/types/accounts/account.go b/core/types/accounts/account.go index a2c284042..c89150c74 100644 --- a/core/types/accounts/account.go +++ b/core/types/accounts/account.go @@ -18,12 +18,13 @@ import ( // These objects are stored in the main account trie. // DESCRIBED: docs/programmers_guide/guide.md#ethereum-state type Account struct { - Initialised bool - Nonce uint64 - Balance uint256.Int - Root libcommon.Hash // merkle root of the storage trie - CodeHash libcommon.Hash // hash of the bytecode - Incarnation uint64 + Initialised bool + Nonce uint64 + Balance uint256.Int + Root libcommon.Hash // merkle root of the storage trie + CodeHash libcommon.Hash // hash of the bytecode + Incarnation uint64 + PrevIncarnation uint64 } const (