Merge tag 'v1.10.23' into feature/merge-v1.10.23
This commit is contained in:
commit
a2de453fd1
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user