@@ -15,7 +15,7 @@ use reth_provider::{
15
15
} ;
16
16
use reth_prune_types:: PruneModes ;
17
17
use reth_stages:: {
18
- sets:: DefaultStages ,
18
+ sets:: { DefaultStages , OfflineStages } ,
19
19
stages:: { ExecutionStage , ExecutionStageThresholds } ,
20
20
Pipeline , StageSet ,
21
21
} ;
@@ -40,6 +40,11 @@ pub struct Command {
40
40
41
41
#[ command( subcommand) ]
42
42
command : Subcommands ,
43
+
44
+ /// If this is enabled, then all stages except headers, bodies, and sender recovery will be
45
+ /// unwound.
46
+ #[ arg( long) ]
47
+ offline : bool ,
43
48
}
44
49
45
50
impl Command {
@@ -52,16 +57,30 @@ impl Command {
52
57
eyre:: bail!( "Cannot unwind genesis block" )
53
58
}
54
59
55
- // Only execute a pipeline unwind if the start of the range overlaps the existing static
56
- // files. If that's the case, then copy all available data from MDBX to static files, and
57
- // only then, proceed with the unwind.
58
- if let Some ( highest_static_block) = provider_factory
60
+ let highest_static_file_block = provider_factory
59
61
. static_file_provider ( )
60
62
. get_highest_static_files ( )
61
63
. max ( )
62
- . filter ( |highest_static_file_block| highest_static_file_block >= range. start ( ) )
63
- {
64
- info ! ( target: "reth::cli" , ?range, ?highest_static_block, "Executing a pipeline unwind." ) ;
64
+ . filter ( |highest_static_file_block| highest_static_file_block >= range. start ( ) ) ;
65
+
66
+ // Execute a pipeline unwind if the start of the range overlaps the existing static
67
+ // files. If that's the case, then copy all available data from MDBX to static files, and
68
+ // only then, proceed with the unwind.
69
+ //
70
+ // We also execute a pipeline unwind if `offline` is specified, because we need to only
71
+ // unwind the data associated with offline stages.
72
+ if highest_static_file_block. is_some ( ) || self . offline {
73
+ if self . offline {
74
+ info ! ( target: "reth::cli" , "Performing an unwind for offline-only data!" ) ;
75
+ }
76
+
77
+ if let Some ( highest_static_file_block) = highest_static_file_block {
78
+ info ! ( target: "reth::cli" , ?range, ?highest_static_file_block, "Executing a pipeline unwind." ) ;
79
+ } else {
80
+ info ! ( target: "reth::cli" , ?range, "Executing a pipeline unwind." ) ;
81
+ }
82
+
83
+ // This will build an offline-only pipeline if the `offline` flag is enabled
65
84
let mut pipeline = self . build_pipeline ( config, provider_factory. clone ( ) ) . await ?;
66
85
67
86
// Move all applicable data from database to static files.
@@ -87,7 +106,7 @@ impl Command {
87
106
provider. commit ( ) ?;
88
107
}
89
108
90
- println ! ( "Unwound {} blocks" , range. count( ) ) ;
109
+ info ! ( target : "reth::cli" , range=?range . clone ( ) , count=range . count ( ) , "Unwound blocks" ) ;
91
110
92
111
Ok ( ( ) )
93
112
}
@@ -105,9 +124,14 @@ impl Command {
105
124
let ( tip_tx, tip_rx) = watch:: channel ( B256 :: ZERO ) ;
106
125
let executor = block_executor ! ( provider_factory. chain_spec( ) ) ;
107
126
108
- let pipeline = Pipeline :: builder ( )
109
- . with_tip_sender ( tip_tx)
110
- . add_stages (
127
+ let builder = if self . offline {
128
+ Pipeline :: builder ( ) . add_stages (
129
+ OfflineStages :: new ( executor, config. stages , PruneModes :: default ( ) )
130
+ . builder ( )
131
+ . disable ( reth_stages:: StageId :: SenderRecovery ) ,
132
+ )
133
+ } else {
134
+ Pipeline :: builder ( ) . with_tip_sender ( tip_tx) . add_stages (
111
135
DefaultStages :: new (
112
136
provider_factory. clone ( ) ,
113
137
tip_rx,
@@ -131,10 +155,12 @@ impl Command {
131
155
ExExManagerHandle :: empty ( ) ,
132
156
) ) ,
133
157
)
134
- . build (
135
- provider_factory. clone ( ) ,
136
- StaticFileProducer :: new ( provider_factory, PruneModes :: default ( ) ) ,
137
- ) ;
158
+ } ;
159
+
160
+ let pipeline = builder. build (
161
+ provider_factory. clone ( ) ,
162
+ StaticFileProducer :: new ( provider_factory, PruneModes :: default ( ) ) ,
163
+ ) ;
138
164
Ok ( pipeline)
139
165
}
140
166
}
0 commit comments