Skip to content

Commit 4559e2a

Browse files
committed
Update exporter
1 parent 366a866 commit 4559e2a

File tree

2 files changed

+107
-13
lines changed

2 files changed

+107
-13
lines changed

database_manager/src/blobs_manager/cli.rs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,22 +95,42 @@ pub struct ExportBlobs {
9595
display_order = 0
9696
)]
9797
pub output_dir: PathBuf,
98-
9998
#[clap(
10099
long,
101100
value_name = "SLOT",
102101
help = "The slot at which to start exporting blobs from.",
103-
display_order = 0
102+
display_order = 0,
103+
conflicts_with_all = &["start_epoch", "end_epoch"]
104104
)]
105-
pub start_slot: u64,
105+
pub start_slot: Option<u64>,
106106

107107
#[clap(
108108
long,
109109
value_name = "SLOT",
110110
help = "The slot at which to stop exporting blobs to (inclusive).",
111-
display_order = 0
111+
display_order = 0,
112+
conflicts_with_all = &["start_epoch", "end_epoch"]
113+
)]
114+
pub end_slot: Option<u64>,
115+
116+
#[clap(
117+
long,
118+
value_name = "EPOCH",
119+
help = "The epoch at which to start exporting blobs from.",
120+
display_order = 0,
121+
conflicts_with_all = &["start_slot", "end_slot"]
112122
)]
113-
pub end_slot: u64,
123+
pub start_epoch: Option<u64>,
124+
125+
#[clap(
126+
long,
127+
value_name = "EPOCH",
128+
help = "The epoch at which to stop exporting blobs to (inclusive).",
129+
display_order = 0,
130+
conflicts_with_all = &["start_slot", "end_slot"]
131+
)]
132+
pub end_epoch: Option<u64>,
133+
114134
#[clap(
115135
long,
116136
help = "Attempt export even if the beacon node is not synced",

database_manager/src/blobs_manager/export.rs

Lines changed: 82 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,28 @@
11
use crate::blobs_manager::{cli::ExportBlobs, ensure_node_synced};
22
use eth2::{
3-
types::{BlobSidecarList, BlockId, ChainSpec, EthSpec, Slot},
3+
types::{BlobSidecarList, BlockId, ChainSpec, Epoch, EthSpec, Slot},
44
BeaconNodeHttpClient, Timeouts,
55
};
66
use sensitive_url::SensitiveUrl;
77
use ssz::Encode;
88
use std::time::Duration;
99
use tracing::{info, warn};
1010

11+
#[derive(PartialEq, Eq)]
12+
enum ExportMode {
13+
Epochs,
14+
Slots,
15+
}
16+
17+
impl std::fmt::Display for ExportMode {
18+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19+
match self {
20+
ExportMode::Epochs => write!(f, "epoch"),
21+
ExportMode::Slots => write!(f, "slot"),
22+
}
23+
}
24+
}
25+
1126
pub async fn export_blobs<E: EthSpec>(
1227
config: &ExportBlobs,
1328
spec: &ChainSpec,
@@ -26,22 +41,81 @@ pub async fn export_blobs<E: EthSpec>(
2641
}
2742
}
2843

29-
let start_slot = config.start_slot;
30-
let end_slot = config.end_slot;
44+
// Ensure Deneb fork is enabled.
45+
let deneb_fork_epoch = if let Some(deneb_fork_epoch) = spec.deneb_fork_epoch {
46+
deneb_fork_epoch.as_u64()
47+
} else {
48+
return Err("Deneb fork epoch not set in chain spec".to_string());
49+
};
50+
51+
let mut export_mode = ExportMode::Epochs;
52+
53+
// Export either epochs or slots. Defaults to epochs.
54+
let start = if let Some(start_epoch) = config.start_epoch {
55+
start_epoch
56+
} else if let Some(start_slot) = config.start_slot {
57+
// Since start_slot and start_epoch are mutually exclusive, we can safely assume that we are in slot mode.
58+
export_mode = ExportMode::Slots;
59+
start_slot
60+
} else {
61+
deneb_fork_epoch
62+
};
63+
64+
let end = if let Some(end_epoch) = config.end_epoch {
65+
end_epoch
66+
} else if let Some(end_slot) = config.end_slot {
67+
end_slot
68+
} else {
69+
return Err(format!("End {export_mode} not set"));
70+
};
71+
72+
if end <= start {
73+
return Err(format!(
74+
"End {export_mode} must be greater than start {export_mode}"
75+
));
76+
}
77+
78+
// Ensure start is at or after Deneb fork
79+
if export_mode == ExportMode::Epochs {
80+
if start < deneb_fork_epoch {
81+
return Err(format!(
82+
"Start epoch {} is before Deneb fork epoch {}",
83+
start, deneb_fork_epoch
84+
));
85+
}
86+
} else {
87+
let deneb_start_slot = Epoch::new(deneb_fork_epoch)
88+
.start_slot(E::slots_per_epoch())
89+
.as_u64();
90+
if start < deneb_start_slot {
91+
return Err(format!(
92+
"Start slot {} is before Deneb fork start slot {}",
93+
start, deneb_start_slot
94+
));
95+
}
96+
}
3197

3298
if !config.output_dir.is_dir() {
3399
return Err("Please set `--output-dir` to a valid directory.".to_string());
34100
}
35101

36-
let filename = config
37-
.output_dir
38-
.join(format!("{start_slot}_{end_slot}.ssz"));
102+
let filename = config.output_dir.join(format!("{start}_{end}.ssz"));
39103

40104
// TODO(blob_manager): Ensure node is synced for start_slot -> end_slot.
41105

42106
let mut blobs_to_export: Vec<BlobSidecarList<E>> = vec![];
43107

44-
info!(end_slot, start_slot, output_dir = ?config.output_dir, "Beginning blob export");
108+
// Generate start and end slots for each mode.
109+
let (start_slot, end_slot) = if export_mode == ExportMode::Epochs {
110+
info!(start_epoch = start, end_epoch = end, output_dir = ?config.output_dir, "Beginning blob export");
111+
(
112+
Epoch::new(start).start_slot(E::slots_per_epoch()).as_u64(),
113+
Epoch::new(end).end_slot(E::slots_per_epoch()).as_u64(),
114+
)
115+
} else {
116+
info!(start_slot = start, end_slot = end, output_dir = ?config.output_dir, "Beginning blob export");
117+
(start, end)
118+
};
45119

46120
for slot in start_slot..=end_slot {
47121
if let Some(blobs) = client
@@ -70,7 +144,7 @@ pub async fn export_blobs<E: EthSpec>(
70144
"Completed blob export"
71145
);
72146
} else {
73-
warn!("No blobs were found for this slot range");
147+
warn!("No blobs were found for this {} range", export_mode);
74148
}
75149

76150
Ok(())

0 commit comments

Comments
 (0)