Skip to content

Commit 026c4e9

Browse files
AlexeyAkhunovAlexey Sharp
andauthored
Reorg ropsten solution (#2419)
* Reorg ropsten solution * Add option * Print TD recalc * Correct fix for eip1559 * Try to fix the unwind * Print header progress and hash * Not insert descendants of bad headers * Print some more * Print less * Better way of marking bad headers * Disable inSync * Penalise peers who give incorrect chain pieces * better fix for initial cycle * Clean up Co-authored-by: Alexey Sharp <alexeysharp@Alexeys-iMac.local>
1 parent b957ae9 commit 026c4e9

File tree

9 files changed

+73
-22
lines changed

9 files changed

+73
-22
lines changed

cmd/sentry/download/downloader.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -419,8 +419,11 @@ func (cs *ControlServerImpl) blockHeaders66(ctx context.Context, in *proto_sentr
419419
if penalty == headerdownload.NoPenalty {
420420
var canRequestMore bool
421421
for _, segment := range segments {
422-
requestMore := cs.Hd.ProcessSegment(segment, false /* newBlock */, string(gointerfaces.ConvertH512ToBytes(in.PeerId)))
422+
requestMore, penalties := cs.Hd.ProcessSegment(segment, false /* newBlock */, string(gointerfaces.ConvertH512ToBytes(in.PeerId)))
423423
canRequestMore = canRequestMore || requestMore
424+
if len(penalties) > 0 {
425+
cs.Penalize(ctx, penalties)
426+
}
424427
}
425428

426429
if canRequestMore {
@@ -491,8 +494,11 @@ func (cs *ControlServerImpl) blockHeaders65(ctx context.Context, in *proto_sentr
491494
if penalty == headerdownload.NoPenalty {
492495
var canRequestMore bool
493496
for _, segment := range segments {
494-
requestMore := cs.Hd.ProcessSegment(segment, false /* newBlock */, string(gointerfaces.ConvertH512ToBytes(in.PeerId)))
497+
requestMore, penalties := cs.Hd.ProcessSegment(segment, false /* newBlock */, string(gointerfaces.ConvertH512ToBytes(in.PeerId)))
495498
canRequestMore = canRequestMore || requestMore
499+
if len(penalties) > 0 {
500+
cs.Penalize(ctx, penalties)
501+
}
496502
}
497503

498504
if canRequestMore {

core/state_transition.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,8 @@ func (st *StateTransition) buyGas(gasBailout bool) error {
205205
if st.gasFeeCap != nil {
206206
balanceCheck = st.sharedBuyGasBalance.SetUint64(st.msg.Gas())
207207
balanceCheck = balanceCheck.Mul(balanceCheck, st.gasFeeCap)
208+
balanceCheck.Add(balanceCheck, st.value)
208209
}
209-
balanceCheck.Add(balanceCheck, st.value)
210210
if have, want := st.state.GetBalance(st.msg.From()), balanceCheck; have.Cmp(want) < 0 {
211211
if !gasBailout {
212212
return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From().Hex(), have, want)

eth/backend.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,17 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
440440
if err != nil {
441441
return nil, err
442442
}
443+
if config.BadBlock != 0 {
444+
var badHash common.Hash
445+
if err = chainKv.View(context.Background(), func(tx ethdb.Tx) error {
446+
var hErr error
447+
badHash, hErr = rawdb.ReadCanonicalHash(tx, config.BadBlock)
448+
return hErr
449+
}); err != nil {
450+
return nil, err
451+
}
452+
backend.stagedSync.UnwindTo(config.BadBlock-1, badHash)
453+
}
443454

444455
go txpropagate.BroadcastPendingTxsToNetwork(backend.downloadCtx, backend.txPool, backend.txPoolP2PServer.RecentPeers, backend.downloadServer)
445456

eth/ethconfig/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ type Config struct {
135135

136136
Prune prune.Mode
137137
BatchSize datasize.ByteSize // Batch size for execution stage
138+
BadBlock uint64 // Block marked as bad (for forced reorg)
138139

139140
Snapshot Snapshot
140141

eth/stagedsync/stage_headers.go

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -252,20 +252,34 @@ func HeadersUnwind(u *UnwindState, s *StageState, tx ethdb.RwTx, cfg HeadersCfg)
252252
return err
253253
}
254254
badBlock := u.BadBlock != (common.Hash{})
255-
for blockHeight := headerProgress; blockHeight > u.UnwindPoint; blockHeight-- {
256-
if badBlock {
257-
var hash common.Hash
258-
if hash, err = rawdb.ReadCanonicalHash(tx, blockHeight); err != nil {
255+
if badBlock {
256+
cfg.hd.ReportBadHeader(u.BadBlock)
257+
// Mark all descendants of bad block as bad too
258+
headerCursor, cErr := tx.Cursor(dbutils.HeadersBucket)
259+
if cErr != nil {
260+
return cErr
261+
}
262+
defer headerCursor.Close()
263+
var k, v []byte
264+
for k, v, err = headerCursor.Seek(dbutils.EncodeBlockNumber(u.UnwindPoint + 1)); err == nil && k != nil; k, v, err = headerCursor.Next() {
265+
var h types.Header
266+
if err = rlp.DecodeBytes(v, &h); err != nil {
259267
return err
260268
}
261-
cfg.hd.ReportBadHeader(hash)
269+
if cfg.hd.IsBadHeader(h.ParentHash) {
270+
cfg.hd.ReportBadHeader(h.Hash())
271+
}
262272
}
273+
if err != nil {
274+
return fmt.Errorf("iterate over headers to mark bad headers: %w", err)
275+
}
276+
}
277+
for blockHeight := headerProgress; blockHeight > u.UnwindPoint; blockHeight-- {
263278
if err = rawdb.DeleteCanonicalHash(tx, blockHeight); err != nil {
264279
return err
265280
}
266281
}
267-
if u.BadBlock != (common.Hash{}) {
268-
cfg.hd.ReportBadHeader(u.BadBlock)
282+
if badBlock {
269283
// Find header with biggest TD
270284
tdCursor, cErr := tx.Cursor(dbutils.HeaderTDBucket)
271285
if cErr != nil {
@@ -303,14 +317,17 @@ func HeadersUnwind(u *UnwindState, s *StageState, tx ethdb.RwTx, cfg HeadersCfg)
303317
return err
304318
}
305319
if maxNum == 0 {
306-
// Read genesis hash
307-
if maxHash, err = rawdb.ReadCanonicalHash(tx, 0); err != nil {
320+
maxNum = u.UnwindPoint
321+
if maxHash, err = rawdb.ReadCanonicalHash(tx, maxNum); err != nil {
308322
return err
309323
}
310324
}
311325
if err = rawdb.WriteHeadHeaderHash(tx, maxHash); err != nil {
312326
return err
313327
}
328+
if err = u.Done(tx); err != nil {
329+
return err
330+
}
314331
if err = s.Update(tx, maxNum); err != nil {
315332
return err
316333
}

eth/stagedsync/sync.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,9 @@ func (s *Sync) Run(db ethdb.RwKV, tx ethdb.RwTx, firstCycle bool) error {
202202
if err := s.SetCurrentStage(s.stages[0].ID); err != nil {
203203
return err
204204
}
205+
// If there were unwinds at the start, a heavier but invalid chain may be present, so
206+
// we relax the rules for Stage1
207+
firstCycle = false
205208
}
206209

207210
stage := s.stages[s.currentStage]

turbo/cli/default_flags.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ var DefaultFlags = []cli.Flag{
4040
TLSKeyFlag,
4141
TLSCACertFlag,
4242
SyncLoopThrottleFlag,
43+
BadBlockFlag,
4344
utils.ListenPortFlag,
4445
utils.ListenPort65Flag,
4546
utils.NATFlag,

turbo/cli/flags.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,12 @@ var (
149149
Usage: "Sets the minimum time between sync loop starts (e.g. 1h30m, default is none)",
150150
Value: "",
151151
}
152+
153+
BadBlockFlag = cli.IntFlag{
154+
Name: "bad.block",
155+
Usage: "Marks block with given number bad and forces initial reorg before normal staged sync",
156+
Value: 0,
157+
}
152158
)
153159

154160
func ApplyFlagsForEthConfig(ctx *cli.Context, cfg *ethconfig.Config) {
@@ -201,6 +207,7 @@ func ApplyFlagsForEthConfig(ctx *cli.Context, cfg *ethconfig.Config) {
201207
}
202208
cfg.SyncLoopThrottle = syncLoopThrottle
203209
}
210+
cfg.BadBlock = uint64(ctx.GlobalInt(BadBlockFlag.Name))
204211
}
205212

206213
func ApplyFlagsForEthConfigCobra(f *pflag.FlagSet, cfg *ethconfig.Config) {

turbo/stages/headerdownload/header_algos.go

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ func (hd *HeaderDownload) extendUp(segment *ChainSegment, start, end int) error
187187
}
188188
}
189189

190-
if attachmentLink.persisted {
190+
if _, bad := hd.badHeaders[attachmentLink.hash]; !bad && attachmentLink.persisted {
191191
link := hd.links[linkHeader.Hash()]
192192
hd.insertList = append(hd.insertList, link)
193193
}
@@ -255,21 +255,21 @@ func (hd *HeaderDownload) extendDown(segment *ChainSegment, start, end int) (boo
255255
}
256256

257257
// Connect connects some working trees using anchors of some, and a link of another
258-
func (hd *HeaderDownload) connect(segment *ChainSegment, start, end int) error {
258+
func (hd *HeaderDownload) connect(segment *ChainSegment, start, end int) ([]PenaltyItem, error) {
259259
// Find attachment link again
260260
linkHeader := segment.Headers[end-1]
261261
// Find attachement anchors again
262262
anchorHeader := segment.Headers[start]
263263
attachmentLink, ok1 := hd.getLink(linkHeader.ParentHash)
264264
if !ok1 {
265-
return fmt.Errorf("connect attachment link not found for %x", linkHeader.ParentHash)
265+
return nil, fmt.Errorf("connect attachment link not found for %x", linkHeader.ParentHash)
266266
}
267267
if attachmentLink.preverified && len(attachmentLink.next) > 0 {
268-
return fmt.Errorf("cannot connect to preverified link %d with children", attachmentLink.blockHeight)
268+
return nil, fmt.Errorf("cannot connect to preverified link %d with children", attachmentLink.blockHeight)
269269
}
270270
anchor, ok2 := hd.anchors[anchorHeader.Hash()]
271271
if !ok2 {
272-
return fmt.Errorf("connect attachment anchors not found for %x", anchorHeader.Hash())
272+
return nil, fmt.Errorf("connect attachment anchors not found for %x", anchorHeader.Hash())
273273
}
274274
anchorPreverified := false
275275
for _, link := range anchor.links {
@@ -300,11 +300,15 @@ func (hd *HeaderDownload) connect(segment *ChainSegment, start, end int) error {
300300
// Mark the entire segment as preverified
301301
hd.markPreverified(prevLink)
302302
}
303-
if attachmentLink.persisted {
303+
var penalties []PenaltyItem
304+
if _, bad := hd.badHeaders[attachmentLink.hash]; bad {
305+
hd.invalidateAnchor(anchor)
306+
penalties = append(penalties, PenaltyItem{Penalty: AbandonedAnchorPenalty, PeerID: anchor.peerID})
307+
} else if attachmentLink.persisted {
304308
link := hd.links[linkHeader.Hash()]
305309
hd.insertList = append(hd.insertList, link)
306310
}
307-
return nil
311+
return penalties, nil
308312
}
309313

310314
// if anchor will be abandoned - given peerID will get Penalty
@@ -826,7 +830,7 @@ func (hi *HeaderInserter) BestHeaderChanged() bool {
826830
// it allows higher-level algo immediately request more headers without waiting all stages precessing,
827831
// speeds up visibility of new blocks
828832
// It remember peerID - then later - if anchors created from segments will abandoned - this peerID gonna get Penalty
829-
func (hd *HeaderDownload) ProcessSegment(segment *ChainSegment, newBlock bool, peerID string) (requestMore bool) {
833+
func (hd *HeaderDownload) ProcessSegment(segment *ChainSegment, newBlock bool, peerID string) (requestMore bool, penalties []PenaltyItem) {
830834
log.Debug("processSegment", "from", segment.Headers[0].Number.Uint64(), "to", segment.Headers[len(segment.Headers)-1].Number.Uint64())
831835
hd.lock.Lock()
832836
defer hd.lock.Unlock()
@@ -849,7 +853,8 @@ func (hd *HeaderDownload) ProcessSegment(segment *ChainSegment, newBlock bool, p
849853
if foundAnchor {
850854
if foundTip {
851855
// Connect
852-
if err := hd.connect(segment, start, end); err != nil {
856+
var err error
857+
if penalties, err = hd.connect(segment, start, end); err != nil {
853858
log.Debug("Connect failed", "error", err)
854859
return
855860
}
@@ -919,7 +924,7 @@ func (hd *HeaderDownload) ProcessSegment(segment *ChainSegment, newBlock bool, p
919924
default:
920925
}
921926

922-
return hd.requestChaining && requestMore
927+
return hd.requestChaining && requestMore, penalties
923928
}
924929

925930
func (hd *HeaderDownload) TopSeenHeight() uint64 {

0 commit comments

Comments
 (0)