Skip to content

Commit 32de5f0

Browse files
committed
feat: can import headers from cbor files
Signed-off-by: Pascal Grange <pascal@grange.nom.fr>
1 parent dade065 commit 32de5f0

2 files changed

Lines changed: 34 additions & 37 deletions

File tree

Makefile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ fetch-chain-headers: $(CONFIG_FOLDER)/$(NETWORK)/ ## Fetch chain headers from th
9090

9191
bootstrap: clear-dbs ## Bootstrap the node from scratch
9292
cargo run --profile $(BUILD_PROFILE) -- bootstrap \
93-
--peer-address $(PEER_ADDRESS) \
9493
--config-dir $(CONFIG_FOLDER) \
9594
--ledger-dir $(LEDGER_DIR) \
9695
--chain-dir $(CHAIN_DIR) \

crates/amaru/src/bin/amaru/cmd/bootstrap.rs

Lines changed: 34 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,31 @@
1313
// limitations under the License.
1414

1515
use super::{
16-
import_headers::import_headers,
1716
import_ledger_state::import_all_from_directory,
1817
import_nonces::{InitialNonces, import_nonces},
1918
};
2019
use crate::cmd::DEFAULT_NETWORK;
2120
use amaru::snapshots_dir;
22-
use amaru_kernel::{Point, default_chain_dir, default_ledger_dir, network::NetworkName};
21+
use amaru_consensus::IsHeader;
22+
use amaru_consensus::consensus::store::ChainStore;
23+
use amaru_kernel::{
24+
Header, default_chain_dir, default_ledger_dir, from_cbor, network::NetworkName,
25+
};
26+
use amaru_stores::rocksdb::consensus::RocksDBStore;
2327
use async_compression::tokio::bufread::GzipDecoder;
2428
use clap::{Parser, arg};
2529
use futures_util::TryStreamExt;
30+
use gasket::framework::WorkerError;
2631
use serde::Deserialize;
2732
use std::{
2833
error::Error,
29-
io,
34+
io::{self},
3035
path::{Path, PathBuf},
3136
};
3237
use thiserror::Error;
3338
use tokio::{
3439
fs::{self, File},
35-
io::BufReader,
40+
io::{AsyncReadExt, BufReader},
3641
};
3742
use tokio_util::io::StreamReader;
3843
use tracing::info;
@@ -74,24 +79,10 @@ pub struct Args {
7479
verbatim_doc_comment
7580
)]
7681
config_dir: PathBuf,
77-
78-
/// Address of the node to connect to for retrieving chain data.
79-
/// The node should be accessible via the node-2-node protocol, which
80-
/// means the remote node should be running as a validator and not
81-
/// as a client node.
82-
///
83-
/// Address is given in the usual `host:port` format, for example: "1.2.3.4:3000".
84-
#[arg(
85-
long,
86-
value_name = "NETWORK_ADDRESS",
87-
default_value = "127.0.0.1:3001",
88-
verbatim_doc_comment
89-
)]
90-
peer_address: String,
9182
}
9283

9384
pub async fn run(args: Args) -> Result<(), Box<dyn Error>> {
94-
info!(config=?args.config_dir, ledger_dir=?args.ledger_dir, chain_dir=?args.chain_dir, peer=%args.peer_address, network=%args.network,
85+
info!(config=?args.config_dir, ledger_dir=?args.ledger_dir, chain_dir=?args.chain_dir, network=%args.network,
9586
"bootstrapping",
9687
);
9788

@@ -116,34 +107,41 @@ pub async fn run(args: Args) -> Result<(), Box<dyn Error>> {
116107

117108
import_nonces_for_network(network, &network_dir, &chain_dir).await?;
118109

119-
import_headers_for_network(network, &args.peer_address, &network_dir, &chain_dir).await?;
110+
import_headers_for_network(network, &network_dir, &chain_dir).await?;
120111

121112
Ok(())
122113
}
123114

115+
#[allow(clippy::unwrap_used)]
124116
async fn import_headers_for_network(
125117
network: NetworkName,
126-
peer_address: &str,
127118
config_dir: &Path,
128119
chain_dir: &PathBuf,
129120
) -> Result<(), Box<dyn Error>> {
130-
let headers_file: PathBuf = config_dir.join("headers.json");
131-
let content = tokio::fs::read_to_string(headers_file).await?;
132-
let points: Vec<String> = serde_json::from_str(&content)?;
133-
let mut initial_headers = Vec::new();
134-
for point in points {
135-
match Point::try_from(point.as_str()) {
136-
Ok(point) => initial_headers.push(point),
137-
Err(e) => tracing::warn!("Ignoring malformed header point '{}': {}", point, e),
121+
let era_history = network.into();
122+
let mut db = RocksDBStore::new(chain_dir, era_history)?;
123+
124+
for entry in std::fs::read_dir(config_dir.join("headers"))? {
125+
let entry = entry?;
126+
let path = entry.path();
127+
if path.is_file()
128+
&& let Some(filename) = path.file_name().and_then(|f| f.to_str())
129+
&& filename.starts_with("header.")
130+
&& filename.ends_with(".cbor")
131+
{
132+
let mut file = File::open(&path).await
133+
.inspect_err(|reason| tracing::error!(file = %path.display(), reason = %reason, "Failed to open header file"))
134+
.map_err(|_| WorkerError::Panic)?;
135+
let mut cbor_data = Vec::new();
136+
file.read_to_end(&mut cbor_data).await
137+
.inspect_err(|reason| tracing::error!(file = %path.display(), reason = %reason, "Failed to read header file"))
138+
.map_err(|_| WorkerError::Panic)?;
139+
let header_from_file: Header = from_cbor(&cbor_data).unwrap();
140+
let hash = header_from_file.hash();
141+
db.store_header(&hash, &header_from_file)
142+
.map_err(|_| WorkerError::Panic)?;
138143
}
139144
}
140-
for hdr in initial_headers {
141-
// FIXME: why do we only import 2 headers for each header listed in the
142-
// config file? The 2 headers make sense, but why starting from more than
143-
// one header?
144-
const NUM_HEADERS_TO_IMPORT: usize = 2;
145-
import_headers(peer_address, network, chain_dir, hdr, NUM_HEADERS_TO_IMPORT).await?;
146-
}
147145

148146
Ok(())
149147
}

0 commit comments

Comments
 (0)