Merge tag 'v1.10.23' into feature/merge-v1.10.23

This commit is contained in:
philip-morlier 2022-08-24 07:03:36 -07:00
commit a2de453fd1
6 changed files with 76 additions and 13 deletions

View File

@ -79,7 +79,10 @@ func (beacon *Beacon) Author(header *types.Header) (common.Address, error) {
// VerifyHeader checks whether a header conforms to the consensus rules of the // VerifyHeader checks whether a header conforms to the consensus rules of the
// stock Ethereum consensus engine. // stock Ethereum consensus engine.
func (beacon *Beacon) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error { func (beacon *Beacon) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error {
reached, _ := IsTTDReached(chain, header.ParentHash, header.Number.Uint64()-1) reached, err := IsTTDReached(chain, header.ParentHash, header.Number.Uint64()-1)
if err != nil {
return err
}
if !reached { if !reached {
return beacon.ethone.VerifyHeader(chain, header, seal) return beacon.ethone.VerifyHeader(chain, header, seal)
} }
@ -116,11 +119,14 @@ func (beacon *Beacon) VerifyHeaders(chain consensus.ChainHeaderReader, headers [
if len(preHeaders) == 0 { if len(preHeaders) == 0 {
// All the headers are pos headers. Verify that the parent block reached total terminal difficulty. // All the headers are pos headers. Verify that the parent block reached total terminal difficulty.
if reached, _ := IsTTDReached(chain, headers[0].ParentHash, headers[0].Number.Uint64()-1); !reached { if reached, err := IsTTDReached(chain, headers[0].ParentHash, headers[0].Number.Uint64()-1); !reached {
// TTD not reached for the first block, mark subsequent with invalid terminal block // TTD not reached for the first block, mark subsequent with invalid terminal block
if err == nil {
err = consensus.ErrInvalidTerminalBlock
}
results := make(chan error, len(headers)) results := make(chan error, len(headers))
for i := 0; i < len(headers); i++ { for i := 0; i < len(headers); i++ {
results <- consensus.ErrInvalidTerminalBlock results <- err
} }
return make(chan struct{}), results return make(chan struct{}), results
} }

View File

@ -137,6 +137,9 @@ func (bc *BlockChain) HasBlock(hash common.Hash, number uint64) bool {
if bc.blockCache.Contains(hash) { if bc.blockCache.Contains(hash) {
return true return true
} }
if !bc.HasHeader(hash, number) {
return false
}
return rawdb.HasBody(bc.db, hash, number) return rawdb.HasBody(bc.db, hash, number)
} }

View File

@ -914,3 +914,43 @@ func TestStateDBAccessList(t *testing.T) {
t.Fatalf("expected empty, got %d", got) t.Fatalf("expected empty, got %d", got)
} }
} }
// Tests that account and storage tries are flushed in the correct order and that
// no data loss occurs.
func TestFlushOrderDataLoss(t *testing.T) {
// Create a state trie with many accounts and slots
var (
memdb = rawdb.NewMemoryDatabase()
statedb = NewDatabase(memdb)
state, _ = New(common.Hash{}, statedb, nil)
)
for a := byte(0); a < 10; a++ {
state.CreateAccount(common.Address{a})
for s := byte(0); s < 10; s++ {
state.SetState(common.Address{a}, common.Hash{a, s}, common.Hash{a, s})
}
}
root, err := state.Commit(false)
if err != nil {
t.Fatalf("failed to commit state trie: %v", err)
}
statedb.TrieDB().Reference(root, common.Hash{})
if err := statedb.TrieDB().Cap(1024); err != nil {
t.Fatalf("failed to cap trie dirty cache: %v", err)
}
if err := statedb.TrieDB().Commit(root, false, nil); err != nil {
t.Fatalf("failed to commit state trie: %v", err)
}
// Reopen the state trie from flushed disk and verify it
state, err = New(root, NewDatabase(memdb), nil)
if err != nil {
t.Fatalf("failed to reopen state trie: %v", err)
}
for a := byte(0); a < 10; a++ {
for s := byte(0); s < 10; s++ {
if have := state.GetState(common.Address{a}, common.Hash{a, s}); have != (common.Hash{a, s}) {
t.Errorf("account %d: slot %d: state mismatch: have %x, want %x", a, s, have, common.Hash{a, s})
}
}
}
}

View File

@ -358,6 +358,7 @@ func (s *skeleton) sync(head *types.Header) (*types.Header, error) {
// If the sync is already done, resume the backfiller. When the loop stops, // If the sync is already done, resume the backfiller. When the loop stops,
// terminate the backfiller too. // terminate the backfiller too.
linked := len(s.progress.Subchains) == 1 && linked := len(s.progress.Subchains) == 1 &&
rawdb.HasHeader(s.db, s.progress.Subchains[0].Next, s.scratchHead) &&
rawdb.HasBody(s.db, s.progress.Subchains[0].Next, s.scratchHead) && rawdb.HasBody(s.db, s.progress.Subchains[0].Next, s.scratchHead) &&
rawdb.HasReceipts(s.db, s.progress.Subchains[0].Next, s.scratchHead) rawdb.HasReceipts(s.db, s.progress.Subchains[0].Next, s.scratchHead)
if linked { if linked {
@ -946,12 +947,12 @@ func (s *skeleton) processResponse(res *headerResponse) (linked bool, merged boo
// In the case of full sync it would be enough to check for the body, // In the case of full sync it would be enough to check for the body,
// but even a full syncing node will generate a receipt once block // but even a full syncing node will generate a receipt once block
// processing is done, so it's just one more "needless" check. // processing is done, so it's just one more "needless" check.
var ( //
hasBody = rawdb.HasBody(s.db, header.ParentHash, header.Number.Uint64()-1) // The weird cascading checks are done to minimize the database reads.
hasReceipt = rawdb.HasReceipts(s.db, header.ParentHash, header.Number.Uint64()-1) linked = rawdb.HasHeader(s.db, header.ParentHash, header.Number.Uint64()-1) &&
) rawdb.HasBody(s.db, header.ParentHash, header.Number.Uint64()-1) &&
if hasBody && hasReceipt { rawdb.HasReceipts(s.db, header.ParentHash, header.Number.Uint64()-1)
linked = true if linked {
break break
} }
} }

View File

@ -23,7 +23,7 @@ import (
const ( const (
VersionMajor = 1 // Major version component of the current release VersionMajor = 1 // Major version component of the current release
VersionMinor = 10 // Minor version component of the current release VersionMinor = 10 // Minor version component of the current release
VersionPatch = 22 // Patch version component of the current release VersionPatch = 23 // Patch version component of the current release
VersionMeta = "stable" // Version metadata to append to the version string VersionMeta = "stable" // Version metadata to append to the version string
) )

View File

@ -776,9 +776,22 @@ func (db *Database) Update(nodes *MergedNodeSet) error {
// Insert dirty nodes into the database. In the same tree, it must be // Insert dirty nodes into the database. In the same tree, it must be
// ensured that children are inserted first, then parent so that children // ensured that children are inserted first, then parent so that children
// can be linked with their parent correctly. The order of writing between // can be linked with their parent correctly.
// different tries(account trie, storage tries) is not required. //
for owner, subset := range nodes.sets { // Note, the storage tries must be flushed before the account trie to
// retain the invariant that children go into the dirty cache first.
var order []common.Hash
for owner := range nodes.sets {
if owner == (common.Hash{}) {
continue
}
order = append(order, owner)
}
if _, ok := nodes.sets[common.Hash{}]; ok {
order = append(order, common.Hash{})
}
for _, owner := range order {
subset := nodes.sets[owner]
for _, path := range subset.paths { for _, path := range subset.paths {
n, ok := subset.nodes[path] n, ok := subset.nodes[path]
if !ok { if !ok {