1313// limitations under the License.
1414
1515use super :: {
16- import_headers:: import_headers,
1716 import_ledger_state:: import_all_from_directory,
1817 import_nonces:: { InitialNonces , import_nonces} ,
1918} ;
2019use crate :: cmd:: DEFAULT_NETWORK ;
2120use 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 ;
2327use async_compression:: tokio:: bufread:: GzipDecoder ;
2428use clap:: { Parser , arg} ;
2529use futures_util:: TryStreamExt ;
30+ use gasket:: framework:: WorkerError ;
2631use serde:: Deserialize ;
2732use std:: {
2833 error:: Error ,
29- io,
34+ io:: { self } ,
3035 path:: { Path , PathBuf } ,
3136} ;
3237use thiserror:: Error ;
3338use tokio:: {
3439 fs:: { self , File } ,
35- io:: BufReader ,
40+ io:: { AsyncReadExt , BufReader } ,
3641} ;
3742use tokio_util:: io:: StreamReader ;
3843use 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
9384pub 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) ]
124116async 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