diff --git a/blast_cli/src/configure.rs b/blast_cli/src/configure.rs index 3d88e9f..8a166f9 100644 --- a/blast_cli/src/configure.rs +++ b/blast_cli/src/configure.rs @@ -101,18 +101,18 @@ impl BlastTab for ConfigureTab { [Constraint::Percentage(5), Constraint::Percentage(95)], ) .split(area); - + let layout1 = Layout::new( Direction::Horizontal, [Constraint::Percentage(50), Constraint::Percentage(50)], ) .split(l[1]); - + let layout = Layout::new( Direction::Vertical, [Constraint::Percentage(33), Constraint::Percentage(33), Constraint::Percentage(33)], ).split(layout1[1]); - + let e: Vec = self.events.items.clone().iter() .map(|i| ListItem::new(vec![text::Line::from(Span::raw(i.clone()))])).collect(); let etasks = List::new(e) @@ -120,7 +120,7 @@ impl BlastTab for ConfigureTab { .highlight_style(Style::default().fg(Color::LightYellow).add_modifier(Modifier::BOLD)) .highlight_symbol("> "); frame.render_stateful_widget(etasks, layout[0], &mut self.events.state); - + let c: Vec = self.channels.items.clone().iter() .map(|i| ListItem::new(vec![text::Line::from(Span::raw(i.clone()))])).collect(); let ctasks = List::new(c) @@ -128,7 +128,7 @@ impl BlastTab for ConfigureTab { .highlight_style(Style::default().fg(Color::LightYellow).add_modifier(Modifier::BOLD)) .highlight_symbol("> "); frame.render_stateful_widget(ctasks, layout[1], &mut self.channels.state); - + let a: Vec = self.activity.items.clone().iter() .map(|i| ListItem::new(vec![text::Line::from(Span::raw(i.clone()))])).collect(); let atasks = List::new(a) @@ -136,13 +136,13 @@ impl BlastTab for ConfigureTab { .highlight_style(Style::default().fg(Color::LightYellow).add_modifier(Modifier::BOLD)) .highlight_symbol("> "); frame.render_stateful_widget(atasks, layout[2], &mut self.activity.state); - + let vertical = Layout::vertical([ Constraint::Length(3), Constraint::Min(1), ]); let [input_area, messages_area] = vertical.areas(layout1[0]); - + let msg = vec![ "Use ".into(), "stop".bold(), @@ -157,7 +157,7 @@ impl BlastTab for ConfigureTab { let text = Text::from(Line::from(msg)).patch_style(Style::default()); let help_message = Paragraph::new(text); frame.render_widget(help_message, l[0]); - + let input = Paragraph::new(self.input.as_str()) .style(match self.current_section { ConfigureSection::Command => Style::default().fg(Color::LightYellow), @@ -165,7 +165,7 @@ impl BlastTab for ConfigureTab { }) .block(Block::bordered().title("Command")); frame.render_widget(input, input_area); - + match self.current_section { ConfigureSection::Command => { #[allow(clippy::cast_possible_truncation)] diff --git a/blast_cli/src/load.rs b/blast_cli/src/load.rs index 619bd89..b03767a 100644 --- a/blast_cli/src/load.rs +++ b/blast_cli/src/load.rs @@ -50,7 +50,7 @@ impl BlastTab for LoadTab { .iter() .map(|i| ListItem::new(vec![text::Line::from(Span::raw(i.clone()))])) .collect(); - + let tasks = List::new(tasks) .block(Block::bordered().title("Simulations")) .highlight_style(Style::default().fg(Color::LightYellow).add_modifier(Modifier::BOLD)) diff --git a/blast_cli/src/main.rs b/blast_cli/src/main.rs index 949b0d3..e2d8280 100644 --- a/blast_cli/src/main.rs +++ b/blast_cli/src/main.rs @@ -228,7 +228,7 @@ async fn run(terminal: &mut Terminal, mut blast_cli: BlastCli) -> Err(e) => { failed = true; error_str = e; - } + } } // Start the simulation @@ -375,7 +375,7 @@ fn ui(frame: &mut Frame, tab: &mut dyn BlastTab, error: Option) { .block(Block::bordered().title("Error")); let area = centered_rect(60, 20, chunks[1]); frame.render_widget(Clear, area); - frame.render_widget(error_msg, area); + frame.render_widget(error_msg, area); }, None => { // Draw the current page @@ -572,7 +572,7 @@ async fn run_command(blast: &mut blast_core::Blast, cmd: String) -> Vec let msg = format!("Unable to open channel: {}", e); output.push(msg); } - } + } }, "connect_peer" => { let source = String::from(words.next().unwrap_or("")); diff --git a/blast_cli/src/new.rs b/blast_cli/src/new.rs index 2814edf..aa5fe73 100644 --- a/blast_cli/src/new.rs +++ b/blast_cli/src/new.rs @@ -50,7 +50,7 @@ impl BlastTab for NewTab { .iter() .map(|i| ListItem::new(i.clone())) .collect(); - + let tasks = List::new(tasks) .block(Block::bordered().title("Models")) .highlight_style(Style::default().fg(Color::LightYellow).add_modifier(Modifier::BOLD)) diff --git a/blast_cli/src/run.rs b/blast_cli/src/run.rs index 28588e3..72325df 100644 --- a/blast_cli/src/run.rs +++ b/blast_cli/src/run.rs @@ -50,7 +50,7 @@ impl BlastTab for RunTab { [Constraint::Percentage(5), Constraint::Percentage(10), Constraint::Percentage(85)], ) .split(area); - + let msg = vec![ "Press ".into(), "s".bold(), @@ -61,26 +61,26 @@ impl BlastTab for RunTab { let text = Text::from(Line::from(msg)).patch_style(Style::default()); let help_message = Paragraph::new(text); frame.render_widget(help_message, layout[0]); - + let line_gauge = LineGauge::default() .block(Block::new().title("Simulation Progress:")) .filled_style(Style::default().fg(Color::LightBlue)) .line_set(symbols::line::THICK) .ratio(self.progress); frame.render_widget(line_gauge, layout[1]); - + let layout2 = Layout::new( Direction::Horizontal, [Constraint::Percentage(50), Constraint::Percentage(50)], ) .split(layout[2]); - + let layout3 = Layout::new( Direction::Vertical, [Constraint::Percentage(33), Constraint::Percentage(50), Constraint::Percentage(33)], ) .split(layout2[0]); - + let e: Vec = self.events.items.clone().iter() .map(|i| ListItem::new(vec![text::Line::from(Span::raw(i.clone()))])).collect(); let etasks = List::new(e) @@ -88,7 +88,7 @@ impl BlastTab for RunTab { .highlight_style(Style::default().fg(Color::LightYellow).add_modifier(Modifier::BOLD)) .highlight_symbol("> "); frame.render_stateful_widget(etasks, layout3[0], &mut self.events.state); - + let a: Vec = self.activity.items.clone().iter() .map(|i| ListItem::new(vec![text::Line::from(Span::raw(i.clone()))])).collect(); let atasks = List::new(a) @@ -96,7 +96,7 @@ impl BlastTab for RunTab { .highlight_style(Style::default().fg(Color::LightYellow).add_modifier(Modifier::BOLD)) .highlight_symbol("> "); frame.render_stateful_widget(atasks, layout3[1], &mut self.activity.state); - + let s: Vec = self.stats.items.clone().iter() .map(|i| ListItem::new(vec![text::Line::from(Span::raw(i.clone()))])).collect(); let stasks = List::new(s) @@ -104,7 +104,7 @@ impl BlastTab for RunTab { .highlight_style(Style::default().fg(Color::LightYellow).add_modifier(Modifier::BOLD)) .highlight_symbol("> "); frame.render_stateful_widget(stasks, layout3[2], &mut self.stats.state); - + let x_labels = vec![ Span::styled( format!("{}", self.window[0]), @@ -259,7 +259,7 @@ impl BlastTab for RunTab { for i in 0..20 { self.success_rate_data[i] = self.success_rate_data[i + 1]; } - + self.success_rate_data[20] = (frame as f64, succes_rate); } } diff --git a/blast_cli/src/shared.rs b/blast_cli/src/shared.rs index e400079..1eaa7ee 100644 --- a/blast_cli/src/shared.rs +++ b/blast_cli/src/shared.rs @@ -7,11 +7,11 @@ use ratatui::{ // BLAST constants pub const BANNER: &str = r" - ____ _ _____ _______ + ____ _ _____ _______ | _ \| | /\ / ____|__ __| - | |_) | | / \ | (___ | | - | _ <| | / /\ \ \___ \ | | - | |_) | |____ / ____ \ ____) | | | + | |_) | | / \ | (___ | | + | _ <| | / /\ \ \___ \ | | + | |_) | |____ / ____ \ ____) | | | |____/|______/_/ \_\_____/ |_| "; pub const TAB_TITLES: [&'static str; 4] = ["New", "Load", "Configure", "Run"]; diff --git a/blast_core/src/blast_event_manager.rs b/blast_core/src/blast_event_manager.rs index 47a7356..c583a5a 100644 --- a/blast_core/src/blast_event_manager.rs +++ b/blast_core/src/blast_event_manager.rs @@ -195,7 +195,7 @@ impl BlastEventManager { Ok(n) => n, Err(e) => return Err(format!("Error parsing argument: {}", e)) }; - + let blast_event = BlastEvent::CloseChannelEvent(arg0, arg1); self.push_event(frame_num, blast_event); Ok(()) @@ -208,7 +208,7 @@ impl BlastEventManager { Ok(n) => n, Err(e) => return Err(format!("Error parsing argument: {}", e)) }; - + let blast_event = BlastEvent::OnChainTransaction(arg0, arg1, arg2); self.push_event(frame_num, blast_event); Ok(()) diff --git a/blast_core/src/blast_model_manager.rs b/blast_core/src/blast_model_manager.rs index 3bd3ac9..e20ba57 100644 --- a/blast_core/src/blast_model_manager.rs +++ b/blast_core/src/blast_model_manager.rs @@ -122,7 +122,7 @@ impl BlastModelManager { return Err(format!("Failed to get the current directory: {:?}", e)); } }; - + // Get the full path to the model executable current_dir.push("../blast_models/".to_owned()+&model.config.name+"/"+&model.config.start); let model_exe = current_dir.to_string_lossy().into_owned(); @@ -211,7 +211,7 @@ impl BlastModelManager { let request = tonic::Request::new(BlastLoadRequest { sim: sim_name }); - + // Execute the load RPC let response = match client.load(request).await { Ok(r) => r, @@ -225,7 +225,7 @@ impl BlastModelManager { Ok(()) } else { Err(String::from("Model did not load successfully")) - } + } } /// Tell a model to save its current state @@ -237,7 +237,7 @@ impl BlastModelManager { let request = tonic::Request::new(BlastSaveRequest { sim: sim_name }); - + // Execute the save RPC let response = match client.save(request).await { Ok(r) => r, @@ -251,7 +251,7 @@ impl BlastModelManager { Ok(()) } else { Err(String::from("Model did not save successfully")) - } + } } /// Get a list of the currently available models @@ -261,7 +261,7 @@ impl BlastModelManager { Err(String::from("No models available")) } else { Ok(keys) - } + } } /// Start a given number of nodes for the given model name @@ -273,7 +273,7 @@ impl BlastModelManager { let request = tonic::Request::new(BlastStartRequest { num_nodes: num_nodes, }); - + // Execute the start RPC let response = match client.start_nodes(request).await { Ok(r) => r, @@ -369,7 +369,7 @@ impl BlastModelManager { return Err(format!("RPC wallet_balance failed: {:?}", e)); } }; - + Ok(response.get_ref().balance.clone()) } @@ -393,7 +393,7 @@ impl BlastModelManager { return Err(format!("RPC channel_balance failed: {:?}", e)); } }; - + Ok(response.get_ref().balance.clone()) } @@ -417,7 +417,7 @@ impl BlastModelManager { return Err(format!("RPC list_channels failed: {:?}", e)); } }; - + Ok(response.get_ref().channels.clone()) } @@ -480,7 +480,7 @@ impl BlastModelManager { return Err(format!("RPC open_channel failed: {:?}", e)); } }; - + // Determine if the RPC was successful if response.get_ref().success { Ok(()) @@ -489,7 +489,7 @@ impl BlastModelManager { } } - /// Close a channel with chan_id from a node with source_id + /// Close a channel with chan_id from a node with source_id pub async fn close_channel(&mut self, source_id: String, chan_id: i64) -> Result<(), String> { // Get the model name from the node_id (example node_id: model_name-0000) let model_name: String = get_model_from_node(source_id.clone()); @@ -510,7 +510,7 @@ impl BlastModelManager { return Err(format!("RPC close_channel failed: {:?}", e)); } }; - + // Determine if the RPC was successful if response.get_ref().success { Ok(()) @@ -544,7 +544,7 @@ impl BlastModelManager { return Err(format!("RPC connect_peer failed: {:?}", e)); } }; - + // Determine if the RPC was successful if response.get_ref().success { Ok(()) @@ -576,7 +576,7 @@ impl BlastModelManager { return Err(format!("RPC disconnect_peer failed: {:?}", e)); } }; - + // Determine if the RPC was successful if response.get_ref().success { Ok(()) @@ -605,7 +605,7 @@ impl BlastModelManager { return Err(format!("RPC get_btc_address failed: {:?}", e)); } }; - + Ok(response.get_ref().address.clone()) } @@ -629,7 +629,7 @@ impl BlastModelManager { return Err(format!("RPC get_listen_address failed: {:?}", e)); } }; - + Ok(response.get_ref().address.clone()) } @@ -655,7 +655,7 @@ impl BlastModelManager { fn get_model_from_node(node_id: String) -> String { // Split the input string on the '-' character let parts: Vec<&str> = node_id.split('-').collect(); - + // Return the first part, or an empty string if the input was empty parts.get(0).unwrap_or(&"").to_string() } diff --git a/blast_core/src/blast_simln_manager.rs b/blast_core/src/blast_simln_manager.rs index 22dd749..8bdcc33 100644 --- a/blast_core/src/blast_simln_manager.rs +++ b/blast_core/src/blast_simln_manager.rs @@ -253,7 +253,7 @@ impl BlastSimLnManager { Ok(()) }, None => return Err(anyhow!("Simln not setup. Call set_simln before starting the simulation")), - } + } } /// Stop SimLn simulation diff --git a/blast_core/src/lib.rs b/blast_core/src/lib.rs index 1aeae7d..9fedb00 100644 --- a/blast_core/src/lib.rs +++ b/blast_core/src/lib.rs @@ -245,7 +245,7 @@ impl Blast { events_path.push_str("/"); events_path.push_str("events.json"); self.blast_event_manager.set_event_json(&events_path)?; - + // Get simln let mut simln_path: String = folder_path.display().to_string(); simln_path.push_str("/"); @@ -281,7 +281,7 @@ impl Blast { Ok(_) => {}, Err(e) => return Err(format!("Could not load bitcoind: {}", e)), }; - + // Get network from models.json file let mut models_path: String = folder_path.display().to_string(); models_path.push_str("/"); @@ -610,7 +610,7 @@ impl Blast { async fn stop_model(&mut self, model: String) -> Result<(), String>{ self.blast_model_manager.stop_model(model).await } - + /// Start a given number of nodes for the given model name async fn start_nodes(&mut self, model: String, num_nodes: i32) -> Result<(), String> { match self.blast_model_manager.start_nodes(model, num_nodes).await { diff --git a/blast_example/src/main.rs b/blast_example/src/main.rs index 58bfde8..95afb41 100644 --- a/blast_example/src/main.rs +++ b/blast_example/src/main.rs @@ -75,7 +75,7 @@ async fn new_simulation() { // Print information about the current network println!("----------------------------------------------- GET NETWORK INFO -----------------------------------------------"); - + for node_id in blast.get_nodes() { match blast.get_pub_key(node_id.clone()).await { Ok(s) => { @@ -339,7 +339,7 @@ async fn new_simulation() { Ok(_) => {}, Err(e) => { println!("{}", format!("Error saving simulation: {}", e)); - } + } } // Run the simulation @@ -352,7 +352,7 @@ async fn new_simulation() { Err(e) => { println!("Failed to finalize the simulation: {:?}", e); return; - } + } } // Start the simulation @@ -434,7 +434,7 @@ async fn new_simulation() { Ok(_) => {}, Err(e) => { println!("{}", format!("Error saving simulation: {}", e)); - } + } } // Run the simulation again @@ -447,7 +447,7 @@ async fn new_simulation() { Err(e) => { println!("Failed to finalize the simulation: {:?}", e); return; - } + } } // Start the simulation @@ -491,7 +491,7 @@ async fn new_simulation() { match blast.stop_network().await { Ok(_) => {}, Err(e) => { - println!("Failed to stop the network: {:?}", e); + println!("Failed to stop the network: {:?}", e); } } @@ -535,7 +535,7 @@ async fn load_simulation(name: String) { match blast.stop_network().await { Ok(_) => {}, Err(e) => { - println!("Failed to stop the network: {:?}", e); + println!("Failed to stop the network: {:?}", e); } } return @@ -621,7 +621,7 @@ async fn load_simulation(name: String) { Err(e) => { println!("Failed to finalize the simulation: {:?}", e); return; - } + } } // Start the simulation @@ -665,7 +665,7 @@ async fn load_simulation(name: String) { match blast.stop_network().await { Ok(_) => {}, Err(e) => { - println!("Failed to stop the network: {:?}", e); + println!("Failed to stop the network: {:?}", e); } } diff --git a/blast_models/blast_cln/blast_cln/src/main.rs b/blast_models/blast_cln/blast_cln/src/main.rs index 0507b31..c48380c 100644 --- a/blast_models/blast_cln/blast_cln/src/main.rs +++ b/blast_models/blast_cln/blast_cln/src/main.rs @@ -81,6 +81,7 @@ struct ClnChannel { chan_id: String } +// The CLN data that will be saved to disk when a simulation is saved #[derive(Serialize, Deserialize, Debug)] struct BlastClnData { simln_data: SimJsonFile, @@ -159,17 +160,16 @@ impl BlastClnServer { } } + /// Load the saved nodes using the saved data async fn load_nodes(&self, data: BlastClnData) -> Result,Status> { let mut bcln = self.blast_cln.lock().await; let mut nodes: HashMap> = HashMap::new(); - - // Start the requested number of cln nodes for n in &data.simln_data.nodes { // Create a node id, get available ports and set the cert paths let node_id = n.id.clone(); let port = &data.ports.get(&node_id).unwrap().0.clone(); let rpcport = &data.ports.get(&node_id).unwrap().1.clone(); - + // Create a new client from the connected channel let (_,c) = self.start_node(node_id.clone(), port.to_string().clone(), rpcport.clone()).await?; nodes.insert(node_id.clone(), c); @@ -184,10 +184,11 @@ impl BlastClnServer { Ok(response) } + /// Start a node with a given id and ports async fn start_node(&self, node_id: String, port: String, rpcport: String) -> Result<(SimLnNode,NodeClient),Status> { + // Set the node file paths and address let home = self.get_home()?; let data_dir = PathBuf::from(home).join(DATA_DIR).display().to_string(); - let cln_dir = format!("{}/{}", data_dir, node_id); let addr = format!("{}:{}", "https://localhost", rpcport.to_string()); let ca_path = format!("{}{}", cln_dir, "/regtest/ca.pem"); @@ -261,6 +262,8 @@ impl BlastClnServer { impl BlastRpc for BlastClnServer { /// Start a certain number of nodes async fn start_nodes(&self, request: Request) -> Result,Status> { + log::info!("BlastClnServer: RPC start_nodes"); + let num_nodes = request.get_ref().num_nodes; let mut bcln = self.blast_cln.lock().await; @@ -270,7 +273,7 @@ impl BlastRpc for BlastClnServer { let node_id = format!("{}{:04}", "blast_cln-", i); let port = self.get_available_port(8000, 9000)?; let rpcport = self.get_available_port(port+1, 9000)?.to_string(); - + // Create a new client from the connected channel let (n,c) = self.start_node(node_id.clone(), port.to_string().clone(), rpcport.clone()).await?; bcln.nodes.insert(node_id.clone(), c); @@ -287,6 +290,8 @@ impl BlastRpc for BlastClnServer { /// Get the sim-ln data for this model async fn get_sim_ln(&self, _request: Request) -> Result, Status> { + log::info!("BlastClnServer: RPC get_sim_ln"); + // Serialize the SimLn data into a json string let bcln = self.blast_cln.lock().await; let data = match serde_json::to_string(&bcln.cln_data.simln_data) { @@ -305,9 +310,10 @@ impl BlastRpc for BlastClnServer { /// Blast requests the pub key of a node that is controlled by this model async fn get_pub_key(&self, request: Request,) -> Result, Status> { + log::info!("BlastClnServer: RPC get_pub_key"); + let node_id = &request.get_ref().node; let mut node = self.get_node(node_id.to_string()).await?; - let cln_resp = match node.getinfo(GetinfoRequest{}).await { Ok(r) => { r.into_inner() @@ -324,9 +330,10 @@ impl BlastRpc for BlastClnServer { /// Blast requests the list of peers for a node that is controlled by this model async fn list_peers(&self, request: Request,) -> Result, Status> { + log::info!("BlastClnServer: RPC list_peers"); + let node_id = &request.get_ref().node; let mut node = self.get_node(node_id.to_string()).await?; - let cln_resp = match node.list_peers(ListpeersRequest{id: None, level: None}).await { Ok(r) => { r.into_inner() @@ -336,6 +343,9 @@ impl BlastRpc for BlastClnServer { } }; + log::info!("Peers: {:?}", cln_resp.peers); + + // TODO: format in a consistent way let peers = format!("{:?}", cln_resp.peers); let peers_response = BlastPeersResponse { peers: peers }; @@ -345,9 +355,10 @@ impl BlastRpc for BlastClnServer { /// Blast requests the wallet balance of a node that is controlled by this model async fn wallet_balance(&self, request: Request) -> Result, Status> { + log::info!("BlastClnServer: RPC wallet_balance"); + let node_id = &request.get_ref().node; let mut node = self.get_node(node_id.to_string()).await?; - let cln_resp = match node.list_funds(ListfundsRequest{spent: None}).await { Ok(r) => { r.into_inner() @@ -357,8 +368,11 @@ impl BlastRpc for BlastClnServer { } }; + log::info!("Wallet balance: {:?}", cln_resp.outputs); + + // TODO: format in a consistent way let balance = format!("{:?}", cln_resp.outputs); - + let balance_response = BlastWalletBalanceResponse { balance: balance }; let response = Response::new(balance_response); Ok(response) @@ -366,9 +380,10 @@ impl BlastRpc for BlastClnServer { /// Blast requests the channel balance of a node that is controlled by this model async fn channel_balance(&self, request: Request) -> Result, Status> { + log::info!("BlastClnServer: RPC channel_balance"); + let node_id = &request.get_ref().node; let mut node = self.get_node(node_id.to_string()).await?; - let cln_resp = match node.list_funds(ListfundsRequest{spent: None}).await { Ok(r) => { r.into_inner() @@ -378,6 +393,9 @@ impl BlastRpc for BlastClnServer { } }; + log::info!("Channel balance: {:?}", cln_resp.channels); + + // TODO: format in a consistent way let balance = format!("{:?}", cln_resp.channels); let balance_response = BlastChannelBalanceResponse { balance: balance }; @@ -387,9 +405,10 @@ impl BlastRpc for BlastClnServer { /// Blast requests the list of channels for a node that is controlled by this model async fn list_channels(&self, request: Request) -> Result, Status> { + log::info!("BlastClnServer: RPC list_channels"); + let node_id = &request.get_ref().node; let mut node = self.get_node(node_id.to_string()).await?; - let cln_resp = match node.list_channels(ListchannelsRequest{short_channel_id: None, source: None, destination: None}).await { Ok(r) => { r.into_inner() @@ -399,6 +418,9 @@ impl BlastRpc for BlastClnServer { } }; + log::info!("Channels: {:?}", cln_resp.channels); + + // TODO: format in a consistent way let channels = format!("{:?}", cln_resp.channels); let chan_response = BlastListChannelsResponse { channels: channels }; @@ -408,6 +430,9 @@ impl BlastRpc for BlastClnServer { /// Blast requests that a node controlled by this model opens a channel async fn open_channel(&self, request: Request) -> Result, Status> { + log::info!("BlastClnServer: RPC open_channel"); + + // Set the channel details let req = &request.get_ref(); let node_id = &req.node; let peer = &req.peer_pub_key; @@ -418,13 +443,13 @@ impl BlastRpc for BlastClnServer { let id = req.channel_id; let amount = req.amount; let push = Amount { msat: req.push_amout as u64 }; - - let mut node = self.get_node(node_id.to_string()).await?; - let a = Amount { msat: amount as u64 }; let v = Value::Amount(a); let aora = AmountOrAll { value: Some(v) }; + // Attempt to open the channel + log::info!("Opening channel from {} to {} for the amount: {}", node_id, peer.to_string(), amount); + let mut node = self.get_node(node_id.to_string()).await?; let cln_resp = match node.fund_channel(FundchannelRequest{ amount: Some(aora), announce: None, @@ -448,6 +473,8 @@ impl BlastRpc for BlastClnServer { } }; + // Saving channel details + log::info!("Channel opened, saving details"); let chanid = hex::encode(cln_resp.channel_id); let mut bcln = self.blast_cln.lock().await; bcln.cln_data.open_channels.insert(id, ClnChannel { source: node_id.to_string(), dest_pk: peer.to_string(), chan_id: chanid }); @@ -460,6 +487,9 @@ impl BlastRpc for BlastClnServer { /// Blast requests that a node controlled by this model closes a channel async fn close_channel(&self, request: Request) -> Result, Status> { + log::info!("BlastClnServer: RPC close_channel"); + + // Set the channel details let req = &request.get_ref(); let node_id = &req.node; let id = &req.channel_id; @@ -472,6 +502,8 @@ impl BlastRpc for BlastClnServer { } }; + // Attempt to close the channel + log::info!("Closing channel: {}", chanid.to_string()); match node.close(CloseRequest{ id: chanid.to_string(), unilateraltimeout: None, @@ -501,7 +533,6 @@ impl BlastRpc for BlastClnServer { for (key, value) in &bcln.cln_data.open_channels { result.push_str(&format!("{}: {} -> {},", key, &value.source, value.dest_pk)); } - result.pop(); let chan_response = BlastGetModelChannelsResponse { channels: result }; @@ -511,8 +542,10 @@ impl BlastRpc for BlastClnServer { /// Blast requests that a node controlled by this model connects to a peer async fn connect_peer(&self, request: Request) -> Result, Status> { - let req = &request.get_ref(); + log::info!("BlastClnServer: RPC connect_peer"); + // Set the peer details + let req = &request.get_ref(); let peer_pub = &req.peer_pub_key; let fulladdr = req.peer_addr.clone(); let parts: Vec<&str> = fulladdr.split(':').collect(); @@ -525,9 +558,9 @@ impl BlastRpc for BlastClnServer { }; // Attempt to connect to the peer from this node + log::info!("Connecting to peer: {}", peer_pub); let node_id = &request.get_ref().node; let mut node = self.get_node(node_id.to_string()).await?; - match node.connect_peer(ConnectRequest{id: String::from(peer_pub), host: Some(String::from(addr)), port: Some(port)}).await { Ok(_) => { let connect_response = BlastConnectResponse { success: true }; @@ -542,14 +575,19 @@ impl BlastRpc for BlastClnServer { /// Blast requests that a node controlled by this model disconnects from a peer async fn disconnect_peer(&self, request: Request) -> Result, Status> { + log::info!("BlastClnServer: RPC disconnect_peer"); + + // Get the node and the peer id let req = &request.get_ref(); let node_id = &request.get_ref().node; let mut node = self.get_node(node_id.to_string()).await?; - let id = match hex::decode(&req.peer_pub_key) { Ok(i) => { i } Err(_) => return Err(Status::new(Code::Unknown, "Could not decode the peer pub key.")), }; + + // Attempt to disconnect + log::info!("Disconnecting from peer: {}", &req.peer_pub_key); match node.disconnect(DisconnectRequest{id: id, force: None}).await { Ok(_) => { let connect_response = BlastDisconnectResponse { success: true }; @@ -564,9 +602,13 @@ impl BlastRpc for BlastClnServer { /// Get a BTC address for a node async fn get_btc_address(&self, request: Request) -> Result, Status> { + log::info!("BlastClnServer: RPC get_btc_address"); + let node_id = &request.get_ref().node; let mut node = self.get_node(node_id.to_string()).await?; + // Get a new on-chain address + log::info!("Getting new address for node: {}", node_id); let cln_resp = match node.new_addr(NewaddrRequest{addresstype: Some(3)}).await { Ok(r) => { r.into_inner() @@ -580,6 +622,10 @@ impl BlastRpc for BlastClnServer { Some(a) => { a }, None => return Err(Status::new(Code::Unknown, "Could not get btc address.")), }; + + log::info!("Got new btc address: {}", addr); + + // Send the RPC response let addr_response = BlastBtcAddressResponse { address: addr }; let response = Response::new(addr_response); Ok(response) @@ -587,16 +633,18 @@ impl BlastRpc for BlastClnServer { /// Get the listen address for a node async fn get_listen_address(&self, request: Request) -> Result, Status> { + log::info!("BlastClnServer: RPC get_listen_address"); + let node_id = &request.get_ref().node; let bcln = self.blast_cln.lock().await; - let addr = match bcln.cln_data.addresses.get(node_id) { Some(a) => a, None => { return Err(Status::new(Code::InvalidArgument, format!("No addresses"))); } }; - + + // Send the RPC response let listen_response = BlastListenAddressResponse { address: addr.clone() }; let response = Response::new(listen_response); Ok(response) @@ -604,10 +652,14 @@ impl BlastRpc for BlastClnServer { /// Shutdown the nodes async fn stop_model(&self, _request: Request) -> Result, Status> { + log::info!("BlastClnServer: RPC stop_model"); + let home = self.get_home()?; let data_dir = PathBuf::from(home.clone()).join(DATA_DIR).display().to_string(); let socket_dir = PathBuf::from(home).join(".blast/clightning/sockets").display().to_string(); + // Loop through the nodes and call stop. If the stop call fails, kills the process + log::info!("Attempting to stop all nodes"); let mut bcln = self.blast_cln.lock().await; for (id, node) in &mut bcln.nodes { match node.stop(StopRequest{}).await { @@ -626,10 +678,13 @@ impl BlastRpc for BlastClnServer { } } + // Cleanup node data + log::info!("Removing node data"); let _ = bcln.shutdown_sender.take().unwrap().send(()); let _ = fs::remove_dir_all(data_dir); let _ = fs::remove_dir_all(socket_dir); + // Send the RPC response let stop_response = BlastStopModelResponse { success: true }; let response = Response::new(stop_response); Ok(response) @@ -637,6 +692,9 @@ impl BlastRpc for BlastClnServer { /// Load a previous state of this model async fn load(&self, request: Request) -> Result, Status> { + log::info!("BlastClnServer: RPC load"); + + // Set the simulation name and sim directory let req = &request.get_ref(); let sim_name = &req.sim; let home_dir = self.get_home()?; @@ -648,17 +706,18 @@ impl BlastRpc for BlastClnServer { let json_path = Path::new(&sim_model_dir).join(format!("{}_data.json", sim_name)); // Open the .tar.gz file + log::info!("Opening the tar archive"); let tar_gz = File::open(archive_path)?; let decompressor = GzDecoder::new(tar_gz); let mut archive = Archive::new(decompressor); - // Extract the archive into the specified directory let home = self.get_home()?; let data_dir = PathBuf::from(home).join(DATA_DIR).display().to_string(); let data_path = Path::new(&data_dir); fs::create_dir_all(data_path).unwrap(); archive.unpack(data_path).unwrap(); - // Count the number of nodes to start and remove the old symlink + // Remove old log file and pid file + log::info!("Clearing out old temporary files"); for entry in fs::read_dir(data_path).unwrap() { let entry = match entry { Ok(e) => e, @@ -694,16 +753,22 @@ impl BlastRpc for BlastClnServer { } } + // Deserialize the json data file + log::info!("Loading the json data file"); let file = File::open(json_path).unwrap(); let reader = BufReader::new(file); let data: BlastClnData = serde_json::from_reader(reader).unwrap(); // Attempt to start the nodes + log::info!("Loading the cln nodes"); Ok(self.load_nodes(data).await?) } /// Save this models current state async fn save(&self, request: Request) -> Result, Status> { + log::info!("BlastClnServer: RPC save"); + + // Set the simulation name and directory let req = &request.get_ref(); let sim_name = &req.sim; let home_dir = self.get_home()?; @@ -715,6 +780,7 @@ impl BlastRpc for BlastClnServer { let json_path = Path::new(&sim_model_dir).join(format!("{}_data.json", sim_name)); // Create the .tar.gz archive + log::info!("Creating tar archive"); let home = self.get_home()?; let data_dir = PathBuf::from(home).join(DATA_DIR).display().to_string(); if let Some(parent) = archive_path.parent() { @@ -726,10 +792,13 @@ impl BlastRpc for BlastClnServer { tar.append_dir_all(".", data_dir).unwrap(); // Serialize the data to JSON and write to a file + log::info!("Creating json data file"); let bcln = self.blast_cln.lock().await; let json_string = serde_json::to_string_pretty(&bcln.cln_data).unwrap(); fs::write(&json_path, json_string)?; + // Send the RPC response + log::info!("Simulation {} saved successfully", sim_name); let save_response = BlastSaveResponse { success: true }; let response = Response::new(save_response); Ok(response) @@ -748,6 +817,8 @@ async fn main() -> Result<(), Box> { File::create(folder_path).unwrap(), ); + // Create the cln RPC server + log::info!("Starting the blast_cln model"); let addr = RPC_ADDR.parse()?; let (shutdown_sender, shutdown_receiver) = oneshot::channel::<()>(); let mut bcln = BlastCln::new(); @@ -773,6 +844,7 @@ async fn main() -> Result<(), Box> { let _ = server.await; log::info!("Shutting down gRPC server at {}", addr); + log::info!("Stopping the blast_cln model"); Ok(()) } diff --git a/blast_models/blast_cln/blast_cln/start_cln.sh b/blast_models/blast_cln/blast_cln/start_cln.sh index cab72b1..62723c6 100644 --- a/blast_models/blast_cln/blast_cln/start_cln.sh +++ b/blast_models/blast_cln/blast_cln/start_cln.sh @@ -19,7 +19,6 @@ dev-fast-gossip dev-bitcoind-poll=5 experimental-dual-fund experimental-splicing -experimental-offers funder-policy=match funder-policy-mod=100 funder-min-their-funding=10000 diff --git a/blast_models/blast_cln/build.sh b/blast_models/blast_cln/build.sh index aabd36c..fcb527c 100755 --- a/blast_models/blast_cln/build.sh +++ b/blast_models/blast_cln/build.sh @@ -15,7 +15,7 @@ else git clone "$DOWNLOAD_URL" "$TARGET_DIR" cd "$TARGET_DIR" - git checkout v24.08.2 + git checkout v24.11rc3 ./configure make diff --git a/blast_models/blast_ldk/blast_ldk/Cargo.toml b/blast_models/blast_ldk/blast_ldk/Cargo.toml index 3ef0662..97f20f5 100644 --- a/blast_models/blast_ldk/blast_ldk/Cargo.toml +++ b/blast_models/blast_ldk/blast_ldk/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -ldk-node = "0.4.0" +ldk-node = "0.4.2" tonic = "0.11.0" tokio = { version = "1.37.0", features = ["full"] } prost = "0.12" diff --git a/blast_models/blast_ldk/blast_ldk/src/main.rs b/blast_models/blast_ldk/blast_ldk/src/main.rs index 35af4f1..30cac48 100644 --- a/blast_models/blast_ldk/blast_ldk/src/main.rs +++ b/blast_models/blast_ldk/blast_ldk/src/main.rs @@ -118,6 +118,7 @@ impl<'de> Deserialize<'de> for Channel { } } +// The LDK data that will be saved to disk when a simulation is saved #[derive(Serialize, Deserialize)] struct BlastLdkData { simln_data: SimJsonFile, @@ -196,17 +197,18 @@ impl BlastLdkServer { } } + /// Load the saved nodes using the saved data async fn load_nodes(&self, data: BlastLdkData) -> Result,Status> { let mut bldk = self.blast_ldk.lock().await; let mut nodes: HashMap> = HashMap::new(); - // Start the requested number of cln nodes + // Start the requested number of ldk nodes for n in &data.simln_data.nodes { // Create a node id, get available ports and set the cert paths let node_id = n.id.clone(); let port = &data.ports.get(&node_id).unwrap().0.clone(); let rpcport = &data.ports.get(&node_id).unwrap().1.clone(); - + // Create a new client from the connected channel let (_,c) = self.start_node(node_id.clone(), port.to_string().clone(), rpcport.clone()).await?; nodes.insert(node_id.clone(), c); @@ -221,6 +223,7 @@ impl BlastLdkServer { Ok(response) } + /// Start a node with a given id and ports async fn start_node(&self, node_id: String, port: String, rpcport: String) -> Result<(SimLnNode,Arc),Status> { let home = self.get_home()?; let data_dir = PathBuf::from(home).join(DATA_DIR).display().to_string(); @@ -291,7 +294,10 @@ impl BlastLdkServer { impl BlastRpc for BlastLdkServer { /// Start a certain number of nodes async fn start_nodes(&self, request: Request) -> Result,Status> { + log::info!("BlastLdkServer: RPC start_nodes"); + let num_nodes = request.get_ref().num_nodes; + let mut bldk = self.blast_ldk.lock().await; // Start the requested number of ldk nodes for i in 0..num_nodes { @@ -303,7 +309,6 @@ impl BlastRpc for BlastLdkServer { let (n,node) = self.start_node(node_id.clone(), port.to_string().clone(), rpcport.clone()).await?; // Add the node to the model's list of nodes and to the SimLn data list - let mut bldk = self.blast_ldk.lock().await; bldk.nodes.insert(node_id.clone(), node.clone()); bldk.ldk_data.simln_data.nodes.push(n); bldk.ldk_data.ports.insert(node_id.clone(), (port.to_string().clone(), rpcport.clone())); @@ -317,6 +322,8 @@ impl BlastRpc for BlastLdkServer { /// Get the sim-ln data for this model async fn get_sim_ln(&self, _request: Request) -> Result, Status> { + log::info!("BlastLdkServer: RPC get_sim_ln"); + // Serialize the SimLn data into a json string let bldk = self.blast_ldk.lock().await; let data = match serde_json::to_string(&bldk.ldk_data.simln_data) { @@ -335,9 +342,10 @@ impl BlastRpc for BlastLdkServer { /// Blast requests the pub key of a node that is controlled by this model async fn get_pub_key(&self, request: Request,) -> Result, Status> { + log::info!("BlastLdkServer: RPC get_pub_key"); + let node_id = &request.get_ref().node; let node = self.get_node(node_id.to_string()).await?; - let pub_key = node.node_id().to_string(); let key_response = BlastPubKeyResponse { pub_key: pub_key }; @@ -347,10 +355,16 @@ impl BlastRpc for BlastLdkServer { /// Blast requests the list of peers for a node that is controlled by this model async fn list_peers(&self, request: Request,) -> Result, Status> { + log::info!("BlastLdkServer: RPC list_peers"); + let node_id = &request.get_ref().node; let node = self.get_node(node_id.to_string()).await?; + let peers_resp = node.list_peers(); - let peers = format!("{:?}", node.list_peers()); + log::info!("Peers: {:?}", peers_resp); + + // TODO: format in a consistent way + let peers = format!("{:?}", peers_resp); let peers_response = BlastPeersResponse { peers: peers }; let response = Response::new(peers_response); @@ -359,34 +373,52 @@ impl BlastRpc for BlastLdkServer { /// Blast requests the wallet balance of a node that is controlled by this model async fn wallet_balance(&self, request: Request) -> Result, Status> { + log::info!("BlastLdkServer: RPC wallet_balance"); + let node_id = &request.get_ref().node; let node = self.get_node(node_id.to_string()).await?; - let balance = node.list_balances().total_onchain_balance_sats; - let balance_response = BlastWalletBalanceResponse { balance: balance.to_string() }; + log::info!("Wallet balance: {:?}", balance.to_string()); + + // TODO: format in a consistent way + let b = balance.to_string(); + + let balance_response = BlastWalletBalanceResponse { balance: b }; let response = Response::new(balance_response); Ok(response) } /// Blast requests the channel balance of a node that is controlled by this model async fn channel_balance(&self, request: Request) -> Result, Status> { + log::info!("BlastLdkServer: RPC channel_balance"); + let node_id = &request.get_ref().node; let node = self.get_node(node_id.to_string()).await?; - let balance = node.list_balances().total_lightning_balance_sats; - let balance_response = BlastChannelBalanceResponse { balance: balance.to_string() }; + log::info!("Channel balance: {:?}", balance.to_string()); + + // TODO: format in a consistent way + let b = balance.to_string(); + + let balance_response = BlastChannelBalanceResponse { balance: b }; let response = Response::new(balance_response); Ok(response) } /// Blast requests the list of channels for a node that is controlled by this model async fn list_channels(&self, request: Request) -> Result, Status> { + log::info!("BlastLdkServer: RPC list_channels"); + let node_id = &request.get_ref().node; let node = self.get_node(node_id.to_string()).await?; + let c = node.list_channels(); + + log::info!("Channels: {:?}", c); - let chans = format!("{:?}", node.list_channels()); + // TODO: format in a consistent way + let chans = format!("{:?}", c); let chan_response = BlastListChannelsResponse { channels: chans }; let response = Response::new(chan_response); @@ -395,18 +427,19 @@ impl BlastRpc for BlastLdkServer { /// Blast requests that a node controlled by this model opens a channel async fn open_channel(&self, request: Request) -> Result, Status> { - let req = &request.get_ref(); + log::info!("BlastLdkServer: RPC open_channel"); // Get the source node from the id + let req = &request.get_ref(); let node_id = &req.node; let node = self.get_node(node_id.to_string()).await?; + // Get the peer public key from the request and convert it to a PublicKey object let peer = match hex::decode(&req.peer_pub_key) { Ok(p) => { p } Err(_) => return Err(Status::new(Code::Unknown, "Could not decode the peer pub key.")), }; - // Get the peer public key from the request and convert it to a PublicKey object let peer_pub = match PublicKey::from_slice(peer.as_slice()) { Ok(k) => k, Err(_) => { @@ -430,6 +463,7 @@ impl BlastRpc for BlastLdkServer { let id = req.channel_id; // Attempt to open a channel from this node + log::info!("Opening channel from {} to {} for the amount: {}", node_id, peer_pub, amount); let chan_id = match node.open_announced_channel(peer_pub, peer_addr, amount as u64, Some(push as u64), None) { Ok(id) => id, Err(_) => { @@ -438,6 +472,7 @@ impl BlastRpc for BlastLdkServer { }; // Add the channel to the model's list of open channels + log::info!("Channel opened, saving details"); let mut bldk = self.blast_ldk.lock().await; bldk.ldk_data.open_channels.insert(id, Channel{source: node_id.to_string(), id: chan_id, pk: peer_pub}); @@ -449,9 +484,10 @@ impl BlastRpc for BlastLdkServer { /// Blast requests that a node controlled by this model closes a channel async fn close_channel(&self, request: Request) -> Result, Status> { - let req = &request.get_ref(); + log::info!("BlastLdkServer: RPC close_channel"); // Get the source node from the id + let req = &request.get_ref(); let node_id = &req.node; let node = self.get_node(node_id.to_string()).await?; @@ -466,20 +502,20 @@ impl BlastRpc for BlastLdkServer { }; // Attempt to close the channel + log::info!("Closing channel: {}", id); match node.close_channel(&channel.id, channel.pk) { - Ok(_) => {}, + Ok(_) => { + // Remove the channel from the model's list of open channels + bldk.ldk_data.open_channels.remove(&id); + // Respond to the close channel request + let chan_response = BlastCloseChannelResponse { success: true }; + let response = Response::new(chan_response); + Ok(response) + }, Err(_) => { return Err(Status::new(Code::Unknown, format!("Could not close channel."))); } } - - // Remove the channel from the model's list of open channels - bldk.ldk_data.open_channels.remove(&id); - - // Respond to the close channel request - let chan_response = BlastCloseChannelResponse { success: true }; - let response = Response::new(chan_response); - Ok(response) } /// Create a comma separated list of open channels that this model has control over @@ -489,7 +525,6 @@ impl BlastRpc for BlastLdkServer { for (key, value) in &bldk.ldk_data.open_channels { result.push_str(&format!("{}: {} -> {},", key, &value.source, value.pk.to_string())); } - result.pop(); let chan_response = BlastGetModelChannelsResponse { channels: result }; @@ -499,14 +534,15 @@ impl BlastRpc for BlastLdkServer { /// Blast requests that a node controlled by this model connects to a peer async fn connect_peer(&self, request: Request) -> Result, Status> { - let req = &request.get_ref(); + log::info!("BlastLdkServer: RPC connect_peer"); + // Get the peer public key from the request and convert it to a PublicKey object + let req = &request.get_ref(); let peer = match hex::decode(&req.peer_pub_key) { Ok(p) => { p } Err(_) => return Err(Status::new(Code::Unknown, "Could not decode the peer pub key.")), }; - // Get the peer public key from the request and convert it to a PublicKey object let peer_pub = match PublicKey::from_slice(peer.as_slice()) { Ok(k) => k, Err(_) => { @@ -527,6 +563,7 @@ impl BlastRpc for BlastLdkServer { // Attempt to connect to the peer from this node let node_id = &req.node; let node = self.get_node(node_id.to_string()).await?; + log::info!("Connecting to peer: {}", peer_pub); match node.connect(peer_pub, peer_addr, true) { Ok(_) => { let connect_response = BlastConnectResponse { success: true }; @@ -543,14 +580,15 @@ impl BlastRpc for BlastLdkServer { /// Blast requests that a node controlled by this model disconnects from a peer async fn disconnect_peer(&self, request: Request) -> Result, Status> { - let req = &request.get_ref(); + log::info!("BlastLdkServer: RPC disconnect_peer"); + // Get the peer public key from the request and convert it to a PublicKey object + let req = &request.get_ref(); let peer = match hex::decode(&req.peer_pub_key) { Ok(p) => { p } Err(_) => return Err(Status::new(Code::Unknown, "Could not decode the peer pub key.")), }; - // Get the peer public key from the request and convert it to a PublicKey object let peer_pub = match PublicKey::from_slice(peer.as_slice()) { Ok(k) => k, Err(_) => { @@ -561,6 +599,7 @@ impl BlastRpc for BlastLdkServer { // Attempt to disconnect from the peer let node_id = &req.node; let node = self.get_node(node_id.to_string()).await?; + log::info!("Disconnecting from peer: {}", peer_pub); match node.disconnect(peer_pub) { Ok(_) => { let connect_response = BlastDisconnectResponse { success: true }; @@ -577,9 +616,13 @@ impl BlastRpc for BlastLdkServer { /// Get a BTC address for a node async fn get_btc_address(&self, request: Request) -> Result, Status> { + log::info!("BlastLdkServer: RPC get_btc_address"); + let node_id = &request.get_ref().node; let node = self.get_node(node_id.to_string()).await?; - + + // Get a new on-chain address + log::info!("Getting new address for node: {}", node_id); let address = match node.onchain_payment().new_address() { Ok(a) => a, Err(_) => { @@ -587,6 +630,8 @@ impl BlastRpc for BlastLdkServer { } }; + log::info!("Got new btc address: {}", address); + let addr_response = BlastBtcAddressResponse { address: address.to_string() }; let response = Response::new(addr_response); Ok(response) @@ -594,9 +639,10 @@ impl BlastRpc for BlastLdkServer { /// Get the listen address for a node async fn get_listen_address(&self, request: Request) -> Result, Status> { + log::info!("BlastLdkServer: RPC get_listen_address"); + let node_id = &request.get_ref().node; let node = self.get_node(node_id.to_string()).await?; - let addr = match node.config().listening_addresses { Some(a) => a, None => { @@ -611,8 +657,6 @@ impl BlastRpc for BlastLdkServer { } }; - log::info!("------------------------ {}", a.clone().to_string()); - let listen_response = BlastListenAddressResponse { address: a.clone().to_string() }; let response = Response::new(listen_response); Ok(response) @@ -620,6 +664,10 @@ impl BlastRpc for BlastLdkServer { /// Shutdown the nodes async fn stop_model(&self, _request: Request) -> Result, Status> { + log::info!("BlastLdkServer: RPC stop_model"); + + // Loop through the nodes and call stop + log::info!("Attempting to stop all nodes"); let mut bldk = self.blast_ldk.lock().await; for (_, node) in &bldk.nodes { match node.stop() { @@ -627,12 +675,15 @@ impl BlastRpc for BlastLdkServer { Err(_) => {}, } } - let _ = bldk.shutdown_sender.take().unwrap().send(()); + // Cleanup node data + log::info!("Removing node data"); + let _ = bldk.shutdown_sender.take().unwrap().send(()); let home = self.get_home()?; let data_dir = PathBuf::from(home).join(DATA_DIR).display().to_string(); let _ = fs::remove_dir_all(data_dir); + // Send the RPC response let stop_response = BlastStopModelResponse { success: true }; let response = Response::new(stop_response); Ok(response) @@ -640,28 +691,31 @@ impl BlastRpc for BlastLdkServer { /// Load a previous state of this model async fn load(&self, request: Request) -> Result, Status> { + log::info!("BlastLdkServer: RPC load"); + + // Set the simulation name and sim directory let req = &request.get_ref(); let sim_name = &req.sim; let home_dir = self.get_home()?; let sim_dir = String::from(SIM_DIR); - let sim_model_dir = format!("{}/{}/{}/{}/", home_dir, sim_dir, sim_name, MODEL_NAME); + let sim_model_dir = format!("{}/{}/{}/{}/", home_dir.clone(), sim_dir, sim_name, MODEL_NAME); // Set paths for the archive and JSON file let archive_path = Path::new(&sim_model_dir).join(format!("{}.tar.gz", sim_name)); let json_path = Path::new(&sim_model_dir).join(format!("{}_data.json", sim_name)); // Open the .tar.gz file + log::info!("Opening the tar archive"); let tar_gz = File::open(archive_path)?; let decompressor = GzDecoder::new(tar_gz); let mut archive = Archive::new(decompressor); - // Extract the archive into the specified directory - let home = self.get_home()?; - let data_dir = PathBuf::from(home).join(DATA_DIR).display().to_string(); + let data_dir = PathBuf::from(home_dir.clone()).join(DATA_DIR).display().to_string(); let data_path = Path::new(&data_dir); fs::create_dir_all(data_path).unwrap(); archive.unpack(data_path).unwrap(); - // Count the number of nodes to start and remove the old symlink + // Remove old log file + log::info!("Clearing out old temporary files"); for entry in fs::read_dir(data_path).unwrap() { let entry = match entry { Ok(e) => e, @@ -690,28 +744,35 @@ impl BlastRpc for BlastLdkServer { } } + // Deserialize the json data file + log::info!("Loading the json data file"); let file = File::open(json_path).unwrap(); let reader = BufReader::new(file); let data: BlastLdkData = serde_json::from_reader(reader).unwrap(); + // Attempt to start the nodes + log::info!("Loading the ldk nodes"); Ok(self.load_nodes(data).await?) } /// Save this models current state async fn save(&self, request: Request) -> Result, Status> { + log::info!("BlastLdkServer: RPC save"); + + // Set the simulation name and directory let req = &request.get_ref(); let sim_name = &req.sim; let home_dir = self.get_home()?; let sim_dir = String::from(SIM_DIR); - let sim_model_dir = format!("{}/{}/{}/{}/", home_dir, sim_dir, sim_name, MODEL_NAME); + let sim_model_dir = format!("{}/{}/{}/{}/", home_dir.clone(), sim_dir, sim_name, MODEL_NAME); // Set paths for the archive and JSON file let archive_path = Path::new(&sim_model_dir).join(format!("{}.tar.gz", sim_name)); let json_path = Path::new(&sim_model_dir).join(format!("{}_data.json", sim_name)); // Create the .tar.gz archive - let home = self.get_home()?; - let data_dir = PathBuf::from(home).join(DATA_DIR).display().to_string(); + log::info!("Creating tar archive"); + let data_dir = PathBuf::from(home_dir.clone()).join(DATA_DIR).display().to_string(); if let Some(parent) = archive_path.parent() { fs::create_dir_all(parent).unwrap(); } @@ -720,11 +781,14 @@ impl BlastRpc for BlastLdkServer { let mut tar = TarBuilder::new(enc); tar.append_dir_all(".", data_dir).unwrap(); - // Serialize the HashMap to JSON and write to a file + // Serialize the data to JSON and write to a file + log::info!("Creating json data file"); let bldk = self.blast_ldk.lock().await; let json_string = serde_json::to_string_pretty(&bldk.ldk_data).unwrap(); fs::write(&json_path, json_string)?; + // Send the RPC response + log::info!("Simulation {} saved successfully", sim_name); let save_response = BlastSaveResponse { success: true }; let response = Response::new(save_response); Ok(response) @@ -749,6 +813,7 @@ fn main() -> Result<(), Box> { .unwrap()); // Create the BlastLdkServer object + log::info!("Starting the blast_ldk model"); let addr = RPC_ADDR.parse()?; let (shutdown_sender, shutdown_receiver) = oneshot::channel::<()>(); let mut bldk = BlastLdk::new(); @@ -777,6 +842,7 @@ fn main() -> Result<(), Box> { }); log::info!("Shutting down gRPC server at {}", addr); + log::info!("Stopping the blast_ldk model"); Ok(()) } diff --git a/blast_models/blast_lnd/blast_lnd.go b/blast_models/blast_lnd/blast_lnd.go index ebc294f..163d246 100644 --- a/blast_models/blast_lnd/blast_lnd.go +++ b/blast_models/blast_lnd/blast_lnd.go @@ -129,6 +129,8 @@ func main() { } blast_data_dir := dir + "/" + DATA_DIR + blast_lnd_log("Starting blast_lnd model") + // Create the main blast_lnd struct and start the RPC server so that blast can connect to this model blast_lnd := BlastLnd{clients: make(map[string]lnrpc.LightningClient), listen_addresses: make(map[string]string), rpc_addresses: make(map[string]string), shutdown_ch: shutdown_channel, home_dir: dir, data_dir: blast_data_dir, open_channels: make(map[string]ChannelPoint), wg: &wg} server := start_grpc_server(&wg, &blast_lnd) @@ -558,7 +560,6 @@ func ensure_directory_exists(filePath string) error { // found to the tar writer; the purpose for accepting multiple writers is to allow // for multiple outputs (for example a file, or md5 hash) func Tar(src string, writers ...io.Writer) error { - // ensure the src actually exists before trying to tar it if _, err := os.Stat(src); err != nil { return fmt.Errorf("unable to tar files - %v", err.Error()) } @@ -571,46 +572,35 @@ func Tar(src string, writers ...io.Writer) error { tw := tar.NewWriter(gzw) defer tw.Close() - // walk path return filepath.Walk(src, func(file string, fi os.FileInfo, err error) error { - - // return on any error if err != nil { return err } - // return on non-regular files (thanks to [kumo](https://medium.com/@komuw/just-like-you-did-fbdd7df829d3) for this suggested update) if !fi.Mode().IsRegular() { return nil } - // create a new dir/file header header, err := tar.FileInfoHeader(fi, fi.Name()) if err != nil { return err } - // update the name to correctly reflect the desired destination when untaring header.Name = strings.TrimPrefix(strings.Replace(file, src, "", -1), string(filepath.Separator)) - // write the header if err := tw.WriteHeader(header); err != nil { return err } - // open files for taring f, err := os.Open(file) if err != nil { return err } - // copy file data into tar writer if _, err := io.Copy(tw, f); err != nil { return err } - // manually close here after each file operation; defering would cause each file close - // to wait until all operations have completed. f.Close() return nil @@ -620,7 +610,6 @@ func Tar(src string, writers ...io.Writer) error { // Untar takes a destination path and a reader; a tar reader loops over the tarfile // creating the file structure at 'dst' along the way, and writing any files func Untar(dst string, r io.Reader) error { - gzr, err := gzip.NewReader(r) if err != nil { return err @@ -633,39 +622,23 @@ func Untar(dst string, r io.Reader) error { header, err := tr.Next() switch { - - // if no more files are found return case err == io.EOF: return nil - - // return any other error case err != nil: return err - - // if the header is nil, just skip it (not sure how this happens) case header == nil: continue } - // the target location where the dir/file should be created target := filepath.Join(dst, header.Name) - // the following switch could also be done using fi.Mode(), not sure if there - // a benefit of using one vs. the other. - // fi := header.FileInfo() - - // check the file type switch header.Typeflag { - - // if its a dir and it doesn't exist create it case tar.TypeDir: if _, err := os.Stat(target); err != nil { if err := os.MkdirAll(target, 0755); err != nil { return err } } - - // if it's a file create it case tar.TypeReg: ensure_directory_exists(target) f, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode)) @@ -673,13 +646,10 @@ func Untar(dst string, r io.Reader) error { return err } - // copy over contents if _, err := io.Copy(f, tr); err != nil { return err } - // manually close here after each file operation; defering would cause each file close - // to wait until all operations have completed. f.Close() } } @@ -687,6 +657,8 @@ func Untar(dst string, r io.Reader) error { // Start the blast RPC server so that the blast framework can connect to this model func start_grpc_server(wg *sync.WaitGroup, blnd *BlastLnd) *grpc.Server { + blast_lnd_log("Starting GRPC server") + server := grpc.NewServer() pb.RegisterBlastRpcServer(server, &BlastRpcServer{blast_lnd: blnd}) @@ -711,7 +683,6 @@ func start_grpc_server(wg *sync.WaitGroup, blnd *BlastLnd) *grpc.Server { // Start an lnd node func start_lnd(cfg *lnd.Config, implCfg *lnd.ImplementationCfg, interceptor signal.Interceptor, wg *sync.WaitGroup) { defer wg.Done() - if err := lnd.Main(cfg, lnd.ListenerCfg{}, implCfg, interceptor); err != nil { blast_lnd_log("Could not start lnd: " + err.Error()) } diff --git a/blast_models/blast_lnd/go.mod b/blast_models/blast_lnd/go.mod index 7182605..c5a7c5a 100644 --- a/blast_models/blast_lnd/go.mod +++ b/blast_models/blast_lnd/go.mod @@ -2,13 +2,12 @@ module blast_lnd require ( github.com/jessevdk/go-flags v1.4.0 - github.com/lightningnetwork/lnd v0.17.4-beta.rc1 + github.com/lightningnetwork/lnd v0.18.4-beta.rc1 github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 ) require ( github.com/jackc/pgx/v5 v5.3.1 // indirect - github.com/klauspost/compress v1.17.9 // indirect github.com/lightningnetwork/lnd/sqldb v1.0.4 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect @@ -24,18 +23,18 @@ require ( github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect github.com/aead/siphash v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/btcsuite/btcd v0.24.2-beta.rc1.0.20240625142744-cc26860b4026 // indirect - github.com/btcsuite/btcd/btcec/v2 v2.3.3 // indirect + github.com/btcsuite/btcd v0.24.3-0.20240921052913-67b8efd3ba53 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect github.com/btcsuite/btcd/btcutil v1.1.5 // indirect github.com/btcsuite/btcd/btcutil/psbt v1.1.8 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect - github.com/btcsuite/btcwallet v0.16.10-0.20240809133323-7d3434c65ae2 // indirect + github.com/btcsuite/btcwallet v0.16.10-0.20240912233857-ffb143c77cc5 // indirect github.com/btcsuite/btcwallet/wallet/txauthor v1.3.5 // indirect github.com/btcsuite/btcwallet/wallet/txrules v1.2.2 // indirect github.com/btcsuite/btcwallet/wallet/txsizes v1.2.5 // indirect - github.com/btcsuite/btcwallet/walletdb v1.4.3 // indirect - github.com/btcsuite/btcwallet/wtxmgr v1.5.3 // indirect + github.com/btcsuite/btcwallet/walletdb v1.4.4 // indirect + github.com/btcsuite/btcwallet/wtxmgr v1.5.4 // indirect github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect github.com/btcsuite/winsvc v1.0.0 // indirect @@ -102,7 +101,7 @@ require ( github.com/lightningnetwork/lightning-onion v1.2.1-0.20240712235311-98bd56499dfb // indirect github.com/lightningnetwork/lnd/cert v1.2.2 // indirect github.com/lightningnetwork/lnd/clock v1.1.1 // indirect - github.com/lightningnetwork/lnd/fn v1.2.1 // indirect + github.com/lightningnetwork/lnd/fn v1.2.3 // indirect github.com/lightningnetwork/lnd/healthcheck v1.2.5 // indirect github.com/lightningnetwork/lnd/kvdb v1.4.10 // indirect github.com/lightningnetwork/lnd/queue v1.1.1 // indirect @@ -144,7 +143,7 @@ require ( github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec // indirect - go.etcd.io/bbolt v1.3.7 // indirect + go.etcd.io/bbolt v1.3.11 // indirect go.etcd.io/etcd/api/v3 v3.5.7 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.7 // indirect go.etcd.io/etcd/client/v2 v2.305.7 // indirect @@ -174,7 +173,7 @@ require ( golang.org/x/tools v0.19.0 // indirect google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect google.golang.org/grpc v1.59.0 - google.golang.org/protobuf v1.33.0 + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/errgo.v1 v1.0.1 // indirect gopkg.in/macaroon-bakery.v2 v2.0.1 // indirect gopkg.in/macaroon.v2 v2.0.0 // indirect @@ -193,7 +192,7 @@ require ( replace google.golang.org/protobuf => github.com/lightninglabs/protobuf-go-hex-display v1.30.0-hex-display -replace github.com/lightningnetwork/lnd => github.com/bjohnson5/lnd v0.0.0-20240921135743-3ce7f95afe2f +//replace github.com/lightningnetwork/lnd => github.com/bjohnson5/lnd v0.0.0-20240921135743-3ce7f95afe2f replace github.com/btcsuite/btcwallet => github.com/bjohnson5/btcwallet v0.0.0-20240902191325-b4a3fb7e32b6 diff --git a/blast_models/blast_lnd/go.sum b/blast_models/blast_lnd/go.sum index 36a04fc..ad1d37d 100644 --- a/blast_models/blast_lnd/go.sum +++ b/blast_models/blast_lnd/go.sum @@ -70,17 +70,15 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bjohnson5/btcwallet v0.0.0-20240902191325-b4a3fb7e32b6 h1:x2mGyxKzfSFnmnMUOnSQ9p32Z3nICzxbufK1MheapQ8= github.com/bjohnson5/btcwallet v0.0.0-20240902191325-b4a3fb7e32b6/go.mod h1:qnTHVdyS08VjFBn87IBWVzv94RIY98S+/G6U46TkjmY= -github.com/bjohnson5/lnd v0.0.0-20240921135743-3ce7f95afe2f h1:G6gfqwTsuPQ/hjeXb6vfz4HLlpY9LvGHFkyYOER95Dc= -github.com/bjohnson5/lnd v0.0.0-20240921135743-3ce7f95afe2f/go.mod h1:Y4sP4cQS+V8IpDn6hD6zEyX3dkIwUqLkCPtHfXNaVY0= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= -github.com/btcsuite/btcd v0.24.2-beta.rc1.0.20240625142744-cc26860b4026 h1:s8/96vQSj05bqLl9RyM/eMX8gLtiayEj520TVE4YGy0= -github.com/btcsuite/btcd v0.24.2-beta.rc1.0.20240625142744-cc26860b4026/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg= +github.com/btcsuite/btcd v0.24.3-0.20240921052913-67b8efd3ba53 h1:XOZ/wRGHkKv0AqxfDks5IkzaQ1Ge6fq322ZOOG5VIkU= +github.com/btcsuite/btcd v0.24.3-0.20240921052913-67b8efd3ba53/go.mod h1:zHK7t7sw8XbsCkD64WePHE3r3k9/XoGAcf6mXV14c64= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= -github.com/btcsuite/btcd/btcec/v2 v2.3.3 h1:6+iXlDKE8RMtKsvK0gshlXIuPbyWM/h84Ensb7o3sC0= -github.com/btcsuite/btcd/btcec/v2 v2.3.3/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= @@ -100,10 +98,10 @@ github.com/btcsuite/btcwallet/wallet/txrules v1.2.2 h1:YEO+Lx1ZJJAtdRrjuhXjWrYsm github.com/btcsuite/btcwallet/wallet/txrules v1.2.2/go.mod h1:4v+grppsDpVn91SJv+mZT7B8hEV4nSmpREM4I8Uohws= github.com/btcsuite/btcwallet/wallet/txsizes v1.2.5 h1:93o5Xz9dYepBP4RMFUc9RGIFXwqP2volSWRkYJFrNtI= github.com/btcsuite/btcwallet/wallet/txsizes v1.2.5/go.mod h1:lQ+e9HxZ85QP7r3kdxItkiMSloSLg1PEGis5o5CXUQw= -github.com/btcsuite/btcwallet/walletdb v1.4.3 h1:p+7jg0vtdy13H/viCfMO0k3StbkcpSIi5Q43on9xYn8= -github.com/btcsuite/btcwallet/walletdb v1.4.3/go.mod h1:b/1zFerQnhO843LTpO1lPoem8E6uvaSjtjJBKsCDrN8= -github.com/btcsuite/btcwallet/wtxmgr v1.5.3 h1:QrWCio9Leh3DwkWfp+A1SURj8pYn3JuTLv3waP5uEro= -github.com/btcsuite/btcwallet/wtxmgr v1.5.3/go.mod h1:M4nQpxGTXiDlSOODKXboXX7NFthmiBNjzAKKNS7Fhjg= +github.com/btcsuite/btcwallet/walletdb v1.4.4 h1:BDel6iT/ltYSIYKs0YbjwnEDi7xR3yzABIsQxN2F1L8= +github.com/btcsuite/btcwallet/walletdb v1.4.4/go.mod h1:jk/hvpLFINF0C1kfTn0bfx2GbnFT+Nvnj6eblZALfjs= +github.com/btcsuite/btcwallet/wtxmgr v1.5.4 h1:hJjHy1h/dJwSfD9uDsCwcH21D1iOrus6OrI5gR9E/O0= +github.com/btcsuite/btcwallet/wtxmgr v1.5.4/go.mod h1:lAv0b1Vj9Ig5U8QFm0yiJ9WqPl8yGO/6l7JxdHY1PKE= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/golangcrypto v0.0.0-20150304025918-53f62d9b43e8/go.mod h1:tYvUd8KLhm/oXvUeSEs2VlLghFjQt9+ZaF9ghH0JNjc= @@ -407,8 +405,6 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/kkdai/bstream v1.0.0 h1:Se5gHwgp2VT2uHfDrkbbgbgEvV9cimLELwrPJctSjg8= github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA= -github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= -github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -437,12 +433,14 @@ github.com/lightninglabs/protobuf-go-hex-display v1.30.0-hex-display h1:pRdza2wl github.com/lightninglabs/protobuf-go-hex-display v1.30.0-hex-display/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= github.com/lightningnetwork/lightning-onion v1.2.1-0.20240712235311-98bd56499dfb h1:yfM05S8DXKhuCBp5qSMZdtSwvJ+GFzl94KbXMNB1JDY= github.com/lightningnetwork/lightning-onion v1.2.1-0.20240712235311-98bd56499dfb/go.mod h1:c0kvRShutpj3l6B9WtTsNTBUtjSmjZXbJd9ZBRQOSKI= +github.com/lightningnetwork/lnd v0.18.4-beta.rc1 h1:z6hFKvtbfo8udPrIb81GbSoKlUWd06d4LRxTkD19IMQ= +github.com/lightningnetwork/lnd v0.18.4-beta.rc1/go.mod h1:nPRQzLla5uHPQFyyZn8r9Vgddkd23PBUDa9rggEPOfY= github.com/lightningnetwork/lnd/cert v1.2.2 h1:71YK6hogeJtxSxw2teq3eGeuy4rHGKcFf0d0Uy4qBjI= github.com/lightningnetwork/lnd/cert v1.2.2/go.mod h1:jQmFn/Ez4zhDgq2hnYSw8r35bqGVxViXhX6Cd7HXM6U= github.com/lightningnetwork/lnd/clock v1.1.1 h1:OfR3/zcJd2RhH0RU+zX/77c0ZiOnIMsDIBjgjWdZgA0= github.com/lightningnetwork/lnd/clock v1.1.1/go.mod h1:mGnAhPyjYZQJmebS7aevElXKTFDuO+uNFFfMXK1W8xQ= -github.com/lightningnetwork/lnd/fn v1.2.1 h1:pPsVGrwi9QBwdLJzaEGK33wmiVKOxs/zc8H7+MamFf0= -github.com/lightningnetwork/lnd/fn v1.2.1/go.mod h1:SyFohpVrARPKH3XVAJZlXdVe+IwMYc4OMAvrDY32kw0= +github.com/lightningnetwork/lnd/fn v1.2.3 h1:Q1OrgNSgQynVheBNa16CsKVov1JI5N2AR6G07x9Mles= +github.com/lightningnetwork/lnd/fn v1.2.3/go.mod h1:SyFohpVrARPKH3XVAJZlXdVe+IwMYc4OMAvrDY32kw0= github.com/lightningnetwork/lnd/healthcheck v1.2.5 h1:aTJy5xeBpcWgRtW/PGBDe+LMQEmNm/HQewlQx2jt7OA= github.com/lightningnetwork/lnd/healthcheck v1.2.5/go.mod h1:G7Tst2tVvWo7cx6mSBEToQC5L1XOGxzZTPB29g9Rv2I= github.com/lightningnetwork/lnd/kvdb v1.4.10 h1:vK89IVv1oVH9ubQWU+EmoCQFeVRaC8kfmOrqHbY5zoY= @@ -604,8 +602,8 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec h1:FpfFs4EhNehiVfzQttTuxanPIT43FtkkCFypIod8LHo= gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec/go.mod h1:BZ1RAoRPbCxum9Grlv5aeksu2H8BiKehBYooU2LFiOQ= -go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= -go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0= +go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I= go.etcd.io/etcd/api/v3 v3.5.7 h1:sbcmosSVesNrWOJ58ZQFitHMdncusIifYcrBfwrlJSY= go.etcd.io/etcd/api/v3 v3.5.7/go.mod h1:9qew1gCdDDLu+VwmeG+iFpL+QlpHTo7iubavdVDgCAA= go.etcd.io/etcd/client/pkg/v3 v3.5.7 h1:y3kf5Gbp4e4q7egZdn5T7W9TSHUvkClN6u+Rq9mEOmg= @@ -1051,6 +1049,8 @@ modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= +pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=