-
Couldn't load subscription status.
- Fork 39
Add Custom Pathfinding #303
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shared some thoughts.
simln-lib/src/sim_node.rs
Outdated
| amount_msat: u64, | ||
| pathfinding_graph: &LdkNetworkGraph, | ||
| ) -> Result<Route, SimulationError> { | ||
| let scorer_graph = NetworkGraph::new(bitcoin::Network::Regtest, Arc::new(WrappedLog {})); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it makes more sense to pass in this graph rather than instantiating it every time.
| use super::*; | ||
|
|
||
| #[test] | ||
| fn test_create_activity() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if this helper function is still needed in this PR
sim-cli/src/parsing.rs
Outdated
| ======= | ||
| pub async fn create_simulation_with_network<P: for<'a> PathFinder<'a> + Clone + 'static>( | ||
| cli: &Cli, | ||
| >>>>>>> 59dbbe6 (Add pathfinder trait) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some of the commits in between seem to have these from conflicts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah - will fix before taking it out of draft. Thanks!
simln-lib/src/sim_node.rs
Outdated
| let scorer_graph = NetworkGraph::new(bitcoin::Network::Regtest, Arc::new(WrappedLog {})); | ||
| let mut scorers = self.scorers.lock().await; | ||
| let scorer = scorers.entry(*source).or_insert_with(|| { | ||
| ProbabilisticScorer::new( | ||
| ProbabilisticScoringDecayParameters::default(), | ||
| Arc::new(scorer_graph), | ||
| Arc::new(WrappedLog {}), | ||
| ) | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not following - could you explain why does it need a map and one scorer per sender?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my understanding, having one scorer per node gives us more realistic pathfinding as this is close to the real-world behaviour of the Lightning Network (each node is responsible for its own pathfinding), so simulations would be run under real-world conditions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right, I'm wondering because each SimNode has a Pathfinder and each time a node is being instantiated in ln_node_from_graph, the pathfinder is cloned. So IIUC, the entire map with all scorers will be cloned on every SimNode. Perhaps it should be in an Arc?
edit: I'm wrong - I see the map in ScorersMap is behind an Arc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, here it's creating a new empty graph for each scorer. Shouldn't it use the already existing graph
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On a second look, I'm still not sure on why we need a map to keep track of all scorers. If each SimNode has a Pathfinder then I don't see why it's needed for the DefaultPathfinder of every SimNode to have that map. Each Pathfinder for each SimNode would only need its own scorer + the network graph no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, here it's creating a new empty graph for each scorer. Shouldn't it use the already existing graph
Yeah, you are right - left a comment about that above . Still thinking of the best approach as the type needed for the scorer graph is slightly different from the type of network graph we have currently.
On a second look, I'm still not sure on why we need a map to keep track of all scorers. If each
SimNodehas aPathfinderthen I don't see why it's needed for theDefaultPathfinderof everySimNodeto have that map. EachPathfinderfor eachSimNodewould only need its own scorer + the network graph no?
Yeah this makes sense! If the DefaultPathfinder holds its own scorer, that gives us one scorer per node.
simln-lib/src/sim_node.rs
Outdated
| pub struct DefaultPathFinder { | ||
| scorers: ScorersMap, | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
feels like this should have a NetworkGraph
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah - thought of that but also considering allowing the user pass in the NetworkGraph (for scoring) directly into the find_route method as an Option or perhaps we could somehow still use the pathfinding_graph already being passed into find_route - What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmmmm API-wise not sure what's best but I'd think that find_route in the Pathfinder could do without having to pass the network graph? A pathfinder impl can have it's own view of the network and based on sender and destination pubkeys and the amount return a Route.
Edit: internally the DefaultPathfinder could use the graph we already have for scoring.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Edit: internally the
DefaultPathfindercould use the graph we already have for scoring.
Yeah! That makes sense.
d4423a0 to
04842b1
Compare
| routing_graph.clone(), | ||
| clock.clone(), | ||
| )?)), | ||
| pathfinder.clone(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wouldn't cloning the pathfinder here cause every SimNode to have the same scorer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the issue here is that the scorer in DefaultPathfinder is wrapped in an Arc which prevents pathfinder.clone() from creating a unique deep copy of the mutable scorer state for each SimNode. I'll push a fix to remove the Arc and implement the necessary custom Clone logic to ensure isolation.
| ); | ||
|
|
||
| // Create the pathfinder instance | ||
| let pathfinder = DefaultPathFinder::new(routing_graph.clone()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not pass the pathfinder to create_simulation_with_network? there should be a way to create a simulation with a custom one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that makes sense though since DefaultPathFinder depends on the network graph, we would probably have to pass the graph into create_simulation_with_network too which seems unnecessary to me.
If a user needs to create a simulation with a custom pathfinder, don't you think they can simply instantiate their custom pathfinder here? Moreso, if they have a custom pathfinder, they would probably be comfortable using simln-lib directly, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we would probably have to pass the graph into
create_simulation_with_networktoo
yeah... don't see any other way.
If a user needs to create a simulation with a custom pathfinder, don't you think they can simply instantiate their custom pathfinder here? Moreso, if they have a custom pathfinder, they would probably be comfortable using
simln-libdirectly, no?
here how? If using simln as a lib, this create_simulation_with_network function is the one they would use to create a Simulation. They can setup their own custom pathfinder but would need a way to pass it somehow to simln-lib so that a Simulation can be setup using their custom pathfinder.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's my perspective - sim-cli is the application layer which should have the default settings which can be used to run a simulation out-of-the-box and simln-lib is the library which users can depend on and which they can pass custom values to, to run custom simulations that are not possible with the default sim-cli application. From what you are saying, the user would be expected to depend on both sim-cli as well as simln-lib. Shouldn't the user just depend on simln-lib (this is making me think create_simulation and create_simulation_with_network methods belong to simln-lib and not sim-cli)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hehe woops, my bad, I just realized that create_simulation and create_simulation_with_network are in sim-cli.
(this is making me think
create_simulationandcreate_simulation_with_networkmethods belong tosimln-liband notsim-cli)?
I saw those (create_simulation and create_simulation_with_network) as lib utils since having users do everything that is in there seemed like a handful. But you made me realize they are not in simln-lib 😅 so what you said makes sense.
This PR builds upon the work done here #273
This PR introduces a new
PathFindertrait which allows for more flexible pathfinding. Instead of being locked into the LDK pathfinding algorithm, custom pathfinding algorithms can be swapped in. ADefaultPathFinderhas been provided to maintain backwards compatibility.