Skip to content

Commit c570e94

Browse files
committed
fix: provide parent header during EuclidV2 transition verification
1 parent 2500647 commit c570e94

File tree

9 files changed

+26
-48
lines changed

9 files changed

+26
-48
lines changed

consensus/clique/clique.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ func (c *Clique) VerifyHeader(chain consensus.ChainHeaderReader, header *types.H
226226
// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers. The
227227
// method returns a quit channel to abort the operations and a results channel to
228228
// retrieve the async verifications (the order is that of the input slice).
229-
func (c *Clique) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
229+
func (c *Clique) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool, parent *types.Header) (chan<- struct{}, <-chan error) {
230230
abort := make(chan struct{})
231231
results := make(chan error, len(headers))
232232

consensus/consensus.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ type Engine interface {
7171
// concurrently. The method returns a quit channel to abort the operations and
7272
// a results channel to retrieve the async verifications (the order is that of
7373
// the input slice).
74-
VerifyHeaders(chain ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error)
74+
VerifyHeaders(chain ChainHeaderReader, headers []*types.Header, seals []bool, parent *types.Header) (chan<- struct{}, <-chan error)
7575

7676
// VerifyUncles verifies that the given block's uncles conform to the consensus
7777
// rules of a given engine.

consensus/ethash/consensus.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ func (ethash *Ethash) VerifyHeader(chain consensus.ChainHeaderReader, header *ty
119119
// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers
120120
// concurrently. The method returns a quit channel to abort the operations and
121121
// a results channel to retrieve the async verifications.
122-
func (ethash *Ethash) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
122+
func (ethash *Ethash) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool, parent *types.Header) (chan<- struct{}, <-chan error) {
123123
// If we're running a full engine faking, accept any input as valid
124124
if ethash.config.PowMode == ModeFullFake || len(headers) == 0 {
125125
abort, results := make(chan struct{}), make(chan error, len(headers))

consensus/system_contract/consensus.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,18 @@ func (s *SystemContract) VerifyHeader(chain consensus.ChainHeaderReader, header
8686
// concurrently. The method returns a quit channel to abort the operations and
8787
// a results channel to retrieve the async verifications (the order is that of
8888
// the input slice).
89-
func (s *SystemContract) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
89+
func (s *SystemContract) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool, parent *types.Header) (chan<- struct{}, <-chan error) {
9090
abort := make(chan struct{})
9191
results := make(chan error, len(headers))
9292

9393
go func() {
9494
for i, header := range headers {
95-
err := s.verifyHeader(chain, header, headers[:i])
95+
parents := headers[:i]
96+
if len(parents) == 0 && parent != nil {
97+
parents = []*types.Header{parent}
98+
}
99+
100+
err := s.verifyHeader(chain, header, parents)
96101
if err != nil {
97102
log.Error("Error verifying headers", "err", err)
98103
}

consensus/wrapper/consensus.go

Lines changed: 8 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package wrapper
22

33
import (
44
"math/big"
5-
"time"
65

76
"github.com/scroll-tech/go-ethereum/common"
87
"github.com/scroll-tech/go-ethereum/consensus"
@@ -59,34 +58,9 @@ func (ue *UpgradableEngine) VerifyHeader(chain consensus.ChainHeaderReader, head
5958
return ue.chooseEngine(header.Time).VerifyHeader(chain, header, seal)
6059
}
6160

62-
func waitForHeader(chain consensus.ChainHeaderReader, header *types.Header) {
63-
hash, number := header.Hash(), header.Number.Uint64()
64-
65-
// poll every 2 seconds, should succeed after a few tries
66-
ticker := time.NewTicker(2 * time.Second)
67-
defer ticker.Stop()
68-
69-
// we give up after 2 minutes
70-
timeout := time.After(120 * time.Second)
71-
72-
for {
73-
select {
74-
case <-ticker.C:
75-
// try reading from chain, if the header is present then we are ready
76-
if h := chain.GetHeader(hash, number); h != nil {
77-
return
78-
}
79-
80-
case <-timeout:
81-
log.Warn("Unable to find last pre-EuclidV2 header in chain", "hash", hash.Hex(), "number", number)
82-
return
83-
}
84-
}
85-
}
86-
8761
// VerifyHeaders verifies a batch of headers concurrently. In our use-case,
8862
// headers can only be all system, all clique, or start with clique and then switch once to system.
89-
func (ue *UpgradableEngine) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
63+
func (ue *UpgradableEngine) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool, parent *types.Header) (chan<- struct{}, <-chan error) {
9064
abort := make(chan struct{})
9165
results := make(chan error, len(headers))
9266

@@ -102,12 +76,12 @@ func (ue *UpgradableEngine) VerifyHeaders(chain consensus.ChainHeaderReader, hea
10276

10377
// If the first header is system, then all headers must be system.
10478
if firstEngine == ue.system {
105-
return firstEngine.VerifyHeaders(chain, headers, seals)
79+
return firstEngine.VerifyHeaders(chain, headers, seals, nil)
10680
}
10781

10882
// If first and last headers are both clique, then all headers are clique.
10983
if firstEngine == lastEngine {
110-
return firstEngine.VerifyHeaders(chain, headers, seals)
84+
return firstEngine.VerifyHeaders(chain, headers, seals, nil)
11185
}
11286

11387
// Otherwise, headers start as clique then switch to system. Since we assume
@@ -135,7 +109,7 @@ func (ue *UpgradableEngine) VerifyHeaders(chain consensus.ChainHeaderReader, hea
135109

136110
// Verify clique headers.
137111
log.Info("Start EuclidV2 transition verification in Clique section", "startBlockNumber", cliqueHeaders[0].Number, "endBlockNumber", cliqueHeaders[len(cliqueHeaders)-1].Number)
138-
abortClique, cliqueResults := ue.clique.VerifyHeaders(chain, cliqueHeaders, cliqueSeals)
112+
abortClique, cliqueResults := ue.clique.VerifyHeaders(chain, cliqueHeaders, cliqueSeals, nil)
139113

140114
// Note: cliqueResults is not closed so we cannot directly iterate over it
141115
for i := 0; i < len(cliqueHeaders); i++ {
@@ -149,14 +123,13 @@ func (ue *UpgradableEngine) VerifyHeaders(chain consensus.ChainHeaderReader, hea
149123
}
150124
}
151125

152-
// `VerifyHeader` will try to call `chain.GetHeader`, which will race with `InsertHeaderChain`.
153-
// This might result in "unknown ancestor" header validation error.
154-
// This should be temporary, so we solve this by waiting here.
155-
waitForHeader(chain, cliqueHeaders[len(cliqueHeaders)-1])
126+
// Since the Clique part of the header chain might not yet be stored in the local chain,
127+
// provide a hint to the SystemContract consensus engine.
128+
lastCliqueHeader := cliqueHeaders[len(cliqueHeaders)-1]
156129

157130
// Verify system contract headers.
158131
log.Info("Start EuclidV2 transition verification in SystemContract section", "startBlockNumber", systemHeaders[0].Number, "endBlockNumber", systemHeaders[len(systemHeaders)-1].Number)
159-
abortSystem, systemResults := ue.system.VerifyHeaders(chain, systemHeaders, systemSeals)
132+
abortSystem, systemResults := ue.system.VerifyHeaders(chain, systemHeaders, systemSeals, lastCliqueHeader)
160133

161134
// Note: systemResults is not closed so we cannot directly iterate over it
162135
for i := 0; i < len(systemHeaders); i++ {

core/block_validator_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,10 @@ func TestHeaderVerification(t *testing.T) {
5151

5252
if valid {
5353
engine := ethash.NewFaker()
54-
_, results = engine.VerifyHeaders(chain, []*types.Header{headers[i]}, []bool{true})
54+
_, results = engine.VerifyHeaders(chain, []*types.Header{headers[i]}, []bool{true}, nil)
5555
} else {
5656
engine := ethash.NewFakeFailer(headers[i].Number.Uint64())
57-
_, results = engine.VerifyHeaders(chain, []*types.Header{headers[i]}, []bool{true})
57+
_, results = engine.VerifyHeaders(chain, []*types.Header{headers[i]}, []bool{true}, nil)
5858
}
5959
// Wait for the verification result
6060
select {
@@ -107,11 +107,11 @@ func testHeaderConcurrentVerification(t *testing.T, threads int) {
107107

108108
if valid {
109109
chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil)
110-
_, results = chain.engine.VerifyHeaders(chain, headers, seals)
110+
_, results = chain.engine.VerifyHeaders(chain, headers, seals, nil)
111111
chain.Stop()
112112
} else {
113113
chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeFailer(uint64(len(headers)-1)), vm.Config{}, nil, nil)
114-
_, results = chain.engine.VerifyHeaders(chain, headers, seals)
114+
_, results = chain.engine.VerifyHeaders(chain, headers, seals, nil)
115115
chain.Stop()
116116
}
117117
// Wait for all the verification results
@@ -176,7 +176,7 @@ func testHeaderConcurrentAbortion(t *testing.T, threads int) {
176176
chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeDelayer(time.Millisecond), vm.Config{}, nil, nil)
177177
defer chain.Stop()
178178

179-
abort, results := chain.engine.VerifyHeaders(chain, headers, seals)
179+
abort, results := chain.engine.VerifyHeaders(chain, headers, seals, nil)
180180
close(abort)
181181

182182
// Deplete the results channel

core/blockchain.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1546,7 +1546,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, er
15461546
headers[i] = block.Header()
15471547
seals[i] = verifySeals
15481548
}
1549-
abort, results := bc.engine.VerifyHeaders(bc, headers, seals)
1549+
abort, results := bc.engine.VerifyHeaders(bc, headers, seals, nil)
15501550
defer close(abort)
15511551

15521552
// Peek the error for the first block to decide the directing import logic

core/headerchain.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ func (hc *HeaderChain) ValidateHeaderChain(chain []*types.Header, checkFreq int)
339339
seals[len(seals)-1] = true
340340
}
341341

342-
abort, results := hc.engine.VerifyHeaders(hc, chain, seals)
342+
abort, results := hc.engine.VerifyHeaders(hc, chain, seals, nil)
343343
defer close(abort)
344344

345345
// Iterate over the headers and ensure they all check out

params/version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import (
2424
const (
2525
VersionMajor = 5 // Major version component of the current release
2626
VersionMinor = 8 // Minor version component of the current release
27-
VersionPatch = 46 // Patch version component of the current release
27+
VersionPatch = 47 // Patch version component of the current release
2828
VersionMeta = "mainnet" // Version metadata to append to the version string
2929
)
3030

0 commit comments

Comments
 (0)