Skip to content

Commit 37b3d72

Browse files
chainimport: determine header sync modes
1 parent b03e496 commit 37b3d72

File tree

2 files changed

+162
-3
lines changed

2 files changed

+162
-3
lines changed

chainimport/headers_import.go

Lines changed: 112 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,76 @@ type processingRegions struct {
4343
newHeaders headerRegion
4444
}
4545

46+
// syncModes encapsulates the verification and append modes for header
47+
// synchronization. It is specifically designed for handling the divergence
48+
// and new headers regions internally between import and target sources.
49+
//
50+
// Target sources may have divergence (different heights for block vs filter
51+
// stores) due to interrupted prior imports or partial sync failures. This
52+
// requires flexible sync modes to validate the leading store and catch up the
53+
// lagging store independently.
54+
type syncModes struct {
55+
// verify specifies the verification strategy for the divergence headers
56+
// region.
57+
verify verifyMode
58+
59+
// append specifies the append strategy for divergence and new headers
60+
// regions.
61+
append appendMode
62+
}
63+
64+
// verifyMode represents the verification strategy for the divergence headers
65+
// region.
66+
type verifyMode uint8
67+
68+
const (
69+
// verifyBlockAndFilter indicates both block and filter headers should
70+
// be verified against the corresponding block and filter headers from
71+
// import source. Reserved for scenarios requiring verification of both
72+
// types.
73+
verifyBlockAndFilter verifyMode = iota
74+
75+
// verifyBlockOnly indicates only block headers should be verified
76+
// against the corresponding block headers from import source. This
77+
// happens in case of divergence headers region where the target block
78+
// headers store leads the target filter headers store.
79+
verifyBlockOnly
80+
81+
// verifyFilterOnly indicates only filter headers should be verified
82+
// against the corresponding filter headers from import source. This
83+
// happens in case of divergence headers region where the target
84+
// filter headers store leads the target block headers store.
85+
verifyFilterOnly
86+
)
87+
88+
// appendMode specifies which header types to append during synchronization. It
89+
// is specifically designed for handling the divergence and new headers regions
90+
// internally between import and target sources.
91+
type appendMode uint8
92+
93+
const (
94+
// appendBlockAndFilter indicates both block and filter headers should
95+
// be appended during synchronization using the corresponding block and
96+
// filter headers from import sources. This happens in case of new
97+
// headers region where the target stores are at same height with no
98+
// divergence detected.
99+
appendBlockAndFilter appendMode = iota
100+
101+
// appendBlockOnly indicates only block headers should be appended
102+
// during synchronization using the corresponding block headers from
103+
// import source. This happens in case of divergence headers region
104+
// where the target block headers store lags behind the target filter
105+
// headers store.
106+
appendBlockOnly
107+
108+
// appendFilterOnly indicates only filter headers should be appended
109+
// during synchronization using corresponding filter headers from
110+
// import source. This happens in case of divergence headers region
111+
// where the target filter headers store lags behind the target block
112+
// headers store.
113+
appendFilterOnly
114+
)
115+
46116
// headerRegion represents a contiguous range of headers.
47117
type headerRegion struct {
48118
// start is the beginning height of this header region.
@@ -53,6 +123,9 @@ type headerRegion struct {
53123

54124
// exists indicates whether this region has headers to process.
55125
exists bool
126+
127+
// syncModes contains the synchronization modes for the header region.
128+
syncModes syncModes
56129
}
57130

58131
// headersImport orchestrates the import of blockchain headers from external
@@ -458,10 +531,15 @@ func (h *headersImport) determineProcessingRegions() (*processingRegions, error)
458531
// reconciliation.
459532
divergeStart := effectiveTipHeight + 1
460533
divergeEnd := min(max(bTipHeight, fTipHeight), importEndHeight)
534+
divergeExists := bTipHeight != fTipHeight && divergeStart <= divergeEnd
535+
divergenceSyncModes := h.determineDivergenceSyncModes(
536+
bTipHeight, fTipHeight,
537+
)
461538
regions.divergence = headerRegion{
462-
start: divergeStart,
463-
end: divergeEnd,
464-
exists: bTipHeight != fTipHeight && divergeStart <= divergeEnd,
539+
start: divergeStart,
540+
end: divergeEnd,
541+
exists: divergeExists,
542+
syncModes: divergenceSyncModes,
465543
}
466544

467545
// 2. New Headers region.
@@ -482,11 +560,42 @@ func (h *headersImport) determineProcessingRegions() (*processingRegions, error)
482560
start: newStart,
483561
end: newEnd,
484562
exists: newStart <= newEnd,
563+
syncModes: syncModes{
564+
append: appendBlockAndFilter,
565+
},
485566
}
486567

487568
return regions, nil
488569
}
489570

571+
// determineDivergenceSyncModes determines the appropriate sync modes for
572+
// processing divergence headers region based on which target store is leading.
573+
// It returns different verification and append strategies depending on whether
574+
// the block or filter headers store has a higher tip height.
575+
func (h *headersImport) determineDivergenceSyncModes(blockTipHeight,
576+
filterTipHeight uint32) syncModes {
577+
578+
switch {
579+
case blockTipHeight > filterTipHeight:
580+
return syncModes{
581+
verify: verifyBlockOnly,
582+
append: appendFilterOnly,
583+
}
584+
585+
case blockTipHeight < filterTipHeight:
586+
return syncModes{
587+
verify: verifyFilterOnly,
588+
append: appendBlockOnly,
589+
}
590+
591+
default:
592+
return syncModes{
593+
verify: verifyBlockAndFilter,
594+
append: appendBlockAndFilter,
595+
}
596+
}
597+
}
598+
490599
// processNewHeadersRegion imports headers from the specified region into the
491600
// target stores. This method handles the case where headers exist in the import
492601
// source but not in the target stores.

chainimport/headers_import_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5388,6 +5388,10 @@ func TestHeaderProcessing(t *testing.T) {
53885388
start: 41,
53895389
end: 70,
53905390
exists: true,
5391+
syncModes: syncModes{
5392+
verify: verifyFilterOnly,
5393+
append: appendBlockOnly,
5394+
},
53915395
}
53925396
require.Equal(v.tc, dRE, dR)
53935397
},
@@ -5441,6 +5445,10 @@ func TestHeaderProcessing(t *testing.T) {
54415445
start: 41,
54425446
end: 70,
54435447
exists: true,
5448+
syncModes: syncModes{
5449+
verify: verifyFilterOnly,
5450+
append: appendBlockOnly,
5451+
},
54445452
}
54455453
require.Equal(v.tc, dRE, dR)
54465454

@@ -5449,6 +5457,9 @@ func TestHeaderProcessing(t *testing.T) {
54495457
start: 71,
54505458
end: 90,
54515459
exists: true,
5460+
syncModes: syncModes{
5461+
append: appendBlockAndFilter,
5462+
},
54525463
}
54535464
require.Equal(v.tc, nHRE, nHR)
54545465
},
@@ -5505,6 +5516,10 @@ func TestHeaderProcessing(t *testing.T) {
55055516
start: 41,
55065517
end: 70,
55075518
exists: true,
5519+
syncModes: syncModes{
5520+
verify: verifyBlockOnly,
5521+
append: appendFilterOnly,
5522+
},
55085523
}
55095524
require.Equal(v.tc, dRE, dR)
55105525
},
@@ -5561,6 +5576,10 @@ func TestHeaderProcessing(t *testing.T) {
55615576
start: 71,
55625577
end: 90,
55635578
exists: true,
5579+
syncModes: syncModes{
5580+
verify: verifyBlockOnly,
5581+
append: appendFilterOnly,
5582+
},
55645583
}
55655584
require.Equal(v.tc, dRE, dR)
55665585
},
@@ -5614,6 +5633,10 @@ func TestHeaderProcessing(t *testing.T) {
56145633
start: 41,
56155634
end: 50,
56165635
exists: true,
5636+
syncModes: syncModes{
5637+
verify: verifyFilterOnly,
5638+
append: appendBlockOnly,
5639+
},
56175640
}
56185641
require.Equal(v.tc, dRE, dR)
56195642

@@ -5622,6 +5645,9 @@ func TestHeaderProcessing(t *testing.T) {
56225645
start: 51,
56235646
end: 90,
56245647
exists: true,
5648+
syncModes: syncModes{
5649+
append: appendBlockAndFilter,
5650+
},
56255651
}
56265652
require.Equal(v.tc, nHRE, nHR)
56275653
},
@@ -6287,6 +6313,9 @@ func TestHeaderStorageOnNewHeadersRegion(t *testing.T) {
62876313
start: 1,
62886314
end: 100,
62896315
exists: true,
6316+
syncModes: syncModes{
6317+
append: appendBlockAndFilter,
6318+
},
62906319
},
62916320
importResult: &ImportResult{},
62926321
prep: func() prep {
@@ -6313,6 +6342,9 @@ func TestHeaderStorageOnNewHeadersRegion(t *testing.T) {
63136342
start: 1,
63146343
end: 100,
63156344
exists: true,
6345+
syncModes: syncModes{
6346+
append: appendBlockAndFilter,
6347+
},
63166348
},
63176349
importResult: &ImportResult{},
63186350
prep: func() prep {
@@ -6368,6 +6400,9 @@ func TestHeaderStorageOnNewHeadersRegion(t *testing.T) {
63686400
start: 1,
63696401
end: 100,
63706402
exists: true,
6403+
syncModes: syncModes{
6404+
append: appendBlockAndFilter,
6405+
},
63716406
},
63726407
importResult: &ImportResult{},
63736408
prep: func() prep {
@@ -6425,6 +6460,9 @@ func TestHeaderStorageOnNewHeadersRegion(t *testing.T) {
64256460
start: 1,
64266461
end: 100,
64276462
exists: true,
6463+
syncModes: syncModes{
6464+
append: appendBlockAndFilter,
6465+
},
64286466
},
64296467
importResult: &ImportResult{},
64306468
prep: func() prep {
@@ -6483,6 +6521,9 @@ func TestHeaderStorageOnNewHeadersRegion(t *testing.T) {
64836521
start: 1,
64846522
end: 100,
64856523
exists: true,
6524+
syncModes: syncModes{
6525+
append: appendBlockAndFilter,
6526+
},
64866527
},
64876528
importResult: &ImportResult{},
64886529
prep: func() prep {
@@ -6542,6 +6583,9 @@ func TestHeaderStorageOnNewHeadersRegion(t *testing.T) {
65426583
start: 1,
65436584
end: 100,
65446585
exists: true,
6586+
syncModes: syncModes{
6587+
append: appendBlockAndFilter,
6588+
},
65456589
},
65466590
importResult: &ImportResult{},
65476591
prep: func() prep {
@@ -6601,6 +6645,9 @@ func TestHeaderStorageOnNewHeadersRegion(t *testing.T) {
66016645
start: 1,
66026646
end: 100,
66036647
exists: true,
6648+
syncModes: syncModes{
6649+
append: appendBlockAndFilter,
6650+
},
66046651
},
66056652
importResult: &ImportResult{},
66066653
prep: func() prep {
@@ -6670,6 +6717,9 @@ func TestHeaderStorageOnNewHeadersRegion(t *testing.T) {
66706717
start: 1,
66716718
end: 4,
66726719
exists: true,
6720+
syncModes: syncModes{
6721+
append: appendBlockAndFilter,
6722+
},
66736723
},
66746724
importResult: &ImportResult{},
66756725
prep: func() prep {

0 commit comments

Comments
 (0)