Skip to content

simln-lib/feature: Add ability to run with mocked ln network #248

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

100 changes: 100 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,106 @@ project.
## Docker
If you want to run the cli in a containerized environment, see the docker set up docs [here](./docker/README.md)

## Advanced Usage - Network Simulation

If you are looking to simulate payments are large lightning networks
without the resource consumption of setting up a large cluster of nodes,
you may be interested in dispatching payments on a simulated network.

To run on a simulated network, you will need to provide the desired
topology and channel policies for each edge in the graph. The nodes in
the network will be inferred from the edges provided. Simulation of
payments on both a mocked and real lightning network is not supported,
so the `sim_network` field is mutually exclusive with the `nodes` section
described above.

The example that follows will execute random payments on a network
consisting of three nodes and two channels. You may specify defined
activity to execute on the mocked network, though you must refer to
nodes by their pubkey (aliases are not yet supported).

```
{
"sim_network": [
{
"scid": 1,
"capacity_msat": 250000,
"node_1": {
"pubkey": "0344f37d544896dcc95a08ddd9bdfc2b756bf3f91b3f65bce588bd9d0228c24977",
"max_htlc_count": 483,
"max_in_flight_msat": 250000,
"min_htlc_size_msat": 1,
"max_htlc_size_msat": 100000,
"cltv_expiry_delta": 40,
"base_fee": 1000,
"fee_rate_prop": 100
},
"node_2": {
"pubkey": "020a30431ce58843eedf8051214dbfadb65b107cc598b8277f14bb9b33c9cd026f",
"max_htlc_count": 15,
"max_in_flight_msat": 100000,
"min_htlc_size_msat": 1,
"max_htlc_size_msat": 50000,
"cltv_expiry_delta": 80,
"base_fee": 2000,
"fee_rate_prop": 500
}
},
{
"scid": 2,
"capacity_msat": 100000,
"node_1": {
"pubkey": "020a30431ce58843eedf8051214dbfadb65b107cc598b8277f14bb9b33c9cd026f",
"max_htlc_count": 200,
"max_in_flight_msat": 100000,
"min_htlc_size_msat": 1,
"max_htlc_size_msat": 25000,
"cltv_expiry_delta": 40,
"base_fee": 1750,
"fee_rate_prop": 100
},
"node_2": {
"pubkey": "035c0b392725bb7298d56bf1bcb23634fc509d86a39a8141d435f9d4d6cd4b12eb",
"max_htlc_count": 15,
"max_in_flight_msat": 50000,
"min_htlc_size_msat": 1,
"max_htlc_size_msat": 50000,
"cltv_expiry_delta": 80,
"base_fee": 3000,
"fee_rate_prop": 5
}
}
]
}
```

Note that you need to provide forwarding policies in each direction,
because each participant in the channel sets their own forwarding
policy and restrictions on their counterparty.

### Inclusions and Limitations

The simulator will execute payments on the mocked out network as it
would for a network of real nodes. See the inclusions and exclusions
listed below for a description of the functionality covered by the
simulated network.

Included:
* Routing Policy Enforcement: mocked channels enforce fee and CLTV
requirements.
* Channel restrictions: mocked channels abide by the in-flight
count and value limitations set on channel creation.
* Liquidity checks: HTLCs are only forwarded if the node has sufficient
liquidity in the mocked channel.

Not included:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a followup: we should also mention that we don't have a concept of expiry/force closes in the simulator

* Channel reserve: the required minimum reserve balance is not
subtracted from a node's available balance.
* On chain fees: the simulation does not subtract on chain fees from
available liquidity.
* Dust limits: the simulation node not account for restrictions on dust
HTLCs.

## Developers

* [Developer documentation](docs/DEVELOPER.md)
Expand Down
1 change: 1 addition & 0 deletions sim-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ anyhow = { version = "1.0.69", features = ["backtrace"] }
clap = { version = "4.1.6", features = ["derive", "env", "std", "help", "usage", "error-context", "suggestions"], default-features = false }
dialoguer = "0.11.0"
log = "0.4.20"
triggered = "0.1.2"
serde = "1.0.183"
serde_json = "1.0.104"
simple_logger = "4.2.0"
Expand Down
16 changes: 13 additions & 3 deletions sim-cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use clap::Parser;
use log::LevelFilter;
use sim_cli::parsing::{create_simulation, Cli};
use sim_cli::parsing::{create_simulation, create_simulation_with_network, parse_sim_params, Cli};
use simple_logger::SimpleLogger;
use tokio_util::task::TaskTracker;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
Expand All @@ -12,6 +13,7 @@ async fn main() -> anyhow::Result<()> {
}

let cli = Cli::parse();
let sim_params = parse_sim_params(&cli).await?;

SimpleLogger::new()
.with_level(LevelFilter::Warn)
Expand All @@ -20,15 +22,23 @@ async fn main() -> anyhow::Result<()> {
.init()
.unwrap();

let sim = create_simulation(&cli).await?;
cli.validate(&sim_params)?;

let tasks = TaskTracker::new();

let (sim, validated_activities) = if sim_params.sim_network.is_empty() {
create_simulation(&cli, &sim_params, tasks.clone()).await?
} else {
create_simulation_with_network(&cli, &sim_params, tasks.clone()).await?
};
let sim2 = sim.clone();

ctrlc::set_handler(move || {
log::info!("Shutting down simulation.");
sim2.shutdown();
})?;

sim.run().await?;
sim.run(&validated_activities).await?;

Ok(())
}
Loading