Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Amend incarnation logic #8954

Merged
merged 16 commits into from
Dec 12, 2023
5 changes: 4 additions & 1 deletion core/state/change_set_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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() {
Expand Down
12 changes: 11 additions & 1 deletion core/state/db_state_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 {
Copy link
Collaborator

@AskAlexSharov AskAlexSharov Dec 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not if original.Incarnation > account.Incarnation { ?

Copy link
Member Author

@yperbasis yperbasis Dec 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that in that case IncarnationMap isn't too relevant. My understanding is that IncarnationMap is relevant when a contract is self-destructed and then recreated as a smart contract. Within a block, IntraBlockState rather than IncarnationMap is used to determine the right incarnation. But here we're treating a special corner case when at the end of the block a contract is destroyed and then re-recreated as a non-smart account (account.Incarnation == 0).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here the lines I'm adding to UpdateAccountData are copy-pasted from DeleteAccount.

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
}

Expand Down
18 changes: 10 additions & 8 deletions core/state/intra_block_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 10 additions & 1 deletion core/state/plain_state_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
}

Expand Down
13 changes: 7 additions & 6 deletions core/types/accounts/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down
Loading