Skip to content

Commit

Permalink
feat: add optional name for activity descriptions
Browse files Browse the repository at this point in the history
  • Loading branch information
Ifeanyichukwu committed Apr 22, 2024
1 parent dc544fa commit 1f29207
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 70 deletions.
115 changes: 65 additions & 50 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,49 @@
# SimLN

SimLN is a simulation tool that can be used to generate realistic
payment activity on any lightning network topology. It is intentionally
environment-agnostic so that it can be used across many environments -
from integration tests to public signets.
SimLN is a simulation tool that can be used to generate realistic
payment activity on any lightning network topology. It is intentionally
environment-agnostic so that it can be used across many environments -
from integration tests to public signets.

This tool is intended to serve developers who are familiar with
This tool is intended to serve developers who are familiar with
lightning network development. It may be useful to you if you are:
* A protocol developer looking to test proposals.
* An application developer load-testing your application.
* A signet operator interested in a hands-off way to run an active node.
* A researcher generating synthetic data for a target topology.

- A protocol developer looking to test proposals.
- An application developer load-testing your application.
- A signet operator interested in a hands-off way to run an active node.
- A researcher generating synthetic data for a target topology.

## Pre-Requisites
SimLN requires you to "bring your own network" to generate activity

SimLN requires you to "bring your own network" to generate activity
on. You will need:
* A [lightning network](#lightning-environments) connected with any

- A [lightning network](#lightning-environments) connected with any
topology of channels.
* Access to execute commands on _at least_ one node in the network.
* Rust compiler [installed](https://www.rust-lang.org/tools/install).
- Access to execute commands on _at least_ one node in the network.
- Rust compiler [installed](https://www.rust-lang.org/tools/install).

## LN Implementation Support
* LND ✅
* CLN ✅
* Eclair 🏗️
* LDK-node 🏗️

- LND ✅
- CLN ✅
- Eclair 🏗️
- LDK-node 🏗️

See our [tracking issue](https://github.com/bitcoin-dev-project/sim-ln/issues/26)
for updates on implementation support (contributions welcome!).

## Getting Started
Clone the repo:

Clone the repo:

```
git clone https://github.com/bitcoin-dev-project/sim-ln
cd sim-ln
```

Install the CLI:
Install the CLI:

```
cargo install --locked --path sim-cli/
```
Expand All @@ -52,9 +59,10 @@ Run `sim-cli -h` for details on `--data-dir` and `--sim-file` options that allow
Interested in contributing to the project? See [CONTRIBUTING](CONTRIBUTING.md) for more details.

### Simulation File Setup
The simulator requires access details for a set of `nodes` that you
have permission to execute commands on. Note that the current version
of the simulator uses keysend to execute payments, which must be

The simulator requires access details for a set of `nodes` that you
have permission to execute commands on. Note that the current version
of the simulator uses keysend to execute payments, which must be
enabled in LND using `--accept-keysend` (for CLN node it is enabled by default).

The required access details will depend on the node implementation. For LND, the following
Expand All @@ -72,7 +80,7 @@ information is required:
Whereas for CLN nodes, the following information is required:

```
{
{
"id": <node_id>,
"address": https://<ip:port or domain:port>,
"ca_cert": <path_to_ca_cert>,
Expand All @@ -84,17 +92,18 @@ Whereas for CLN nodes, the following information is required:
**Note that node addresses must be declare with HTTPS transport, i.e. <https://ip-or-domain:port>**

Payment activity can be simulated in two different ways:
* Random activity: generate random activity on the `nodes` provided,

- Random activity: generate random activity on the `nodes` provided,
using the graph topology to determine payment frequency and size.
* Defined activity: provide descriptions of specific payments that
- Defined activity: provide descriptions of specific payments that
you would like the generator to execute.

### Setup - Random Activity

To run the simulator with random activity generation, you just need to
provide a set of nodes and the simulator will generate activity based
on the topology of the underlying graph. Note that payments will only
be sent between the `nodes` that are provided so that liquidity does
To run the simulator with random activity generation, you just need to
provide a set of nodes and the simulator will generate activity based
on the topology of the underlying graph. Note that payments will only
be sent between the `nodes` that are provided so that liquidity does
not "drain" from the simulation.

```
Expand All @@ -106,7 +115,7 @@ not "drain" from the simulation.
"macaroon": "/path/admin.macaroon",
"cert": "/path/tls.cert"
},
{
{
"id": "0230a16a05c5ca120136b3a770a2adfdad88a68d526e63448a9eef88bddd6a30d8",
"address": "https://localhost:10013",
"ca_cert": "/path/ca.pem",
Expand All @@ -118,27 +127,29 @@ not "drain" from the simulation.
```

Nodes can be identified by an arbitrary string ("Alice", "CLN1", etc) or
by their node public key. If a valid public key is provided it *must*
by their node public key. If a valid public key is provided it _must_
match the public key reported by the node.

There are a few cli flags that can be used to toggle the characteristics
of the random activity that is generated:
* `--expected-payment-amount`: the approximate average amount that
There are a few cli flags that can be used to toggle the characteristics
of the random activity that is generated:

- `--expected-payment-amount`: the approximate average amount that
will be sent by nodes, randomness will be introduced such that larger
nodes send a wider variety of payment sizes around this expectation.
* `--capacity-multiplier`: the number of times over that each node in
- `--capacity-multiplier`: the number of times over that each node in
the network sends their capacity in a calendar month, for example:
* `capacity-multiplier=2` means that each node sends double their
capacity in a month.
* `capacity-multiplier=0.5` means that each node sends half their
- `capacity-multiplier=2` means that each node sends double their
capacity in a month.
- `capacity-multiplier=0.5` means that each node sends half their
capacity in a month.

### Setup - Defined Activity
If you would like SimLN to generate a specific payments between source
and destination nodes, you can provide `activity` descriptions of the
source, destination, frequency and amount for payments that you'd like
to execute. Note that `source` nodes *must* be contained in `nodes`,
but destination nodes can be any public node in the network (though

If you would like SimLN to generate a specific payments between source
and destination nodes, you can provide `activity` descriptions of the
source, destination, frequency and amount for payments that you'd like
to execute. Note that `source` nodes _must_ be contained in `nodes`,
but destination nodes can be any public node in the network (though
this may result in liquidity draining over time).

Required fields:
Expand Down Expand Up @@ -166,6 +177,7 @@ The example simulation file below sets up the following simulation:
* Dispatch 140000 msat payments from `Bob` to `Alice` every 50 seconds.
* Dispatch 1000 msat payments from `Bob` to `Dave` every 2 seconds.
* Dispatch 10 payments (5000 msat each) from `Erin` to `Frank` at 2 second intervals, starting 20 seconds into the sim.

```
{
"nodes": [
Expand Down Expand Up @@ -200,7 +212,8 @@ The example simulation file below sets up the following simulation:
"source": "Alice",
"destination": "02d804ad31429c8cc29e20ec43b4129553eb97623801e534ab5a66cdcd2149dbed",
"interval_secs": 1,
"amount_msat": 2000
"amount_msat": 2000,
"activity_name": "Daily Contribution"
},
{
"source": "0230a16a05c5ca120136b3a770a2adfdad88a68d526e63448a9eef88bddd6a30d8",
Expand Down Expand Up @@ -228,10 +241,10 @@ The example simulation file below sets up the following simulation:

**Note that node addresses must be declare with HTTPS transport, i.e <https://ip-or-domain>**

Nodes can be identified by their public key or an id string (as
described above). Activity sources and destinations may reference the
`id` defined in `nodes`, but destinations that are not listed in `nodes`
*must* provide a valid public key.
Nodes can be identified by their public key or an id string (as
described above). Activity sources and destinations may reference the
`id` defined in `nodes`, but destinations that are not listed in `nodes`
_must_ provide a valid public key.

### Simulation Output

Expand All @@ -242,10 +255,12 @@ Run `sim-cli -h` for details on data directory (`--data-dir`) and other options
which affect how simulation outputs are persisted

## Lightning Environments

If you're looking to get started with local lightning development, we
recommend [polar](https://lightningpolar.com/). For larger deployments,
see the [Scaling Lightning](https://github.com/scaling-lightning/scaling-lightning)
recommend [polar](https://lightningpolar.com/). For larger deployments,
see the [Scaling Lightning](https://github.com/scaling-lightning/scaling-lightning)
project.

## Docker

If you want to run the cli in a containerized environment, see the docker set up docs [here](./docker/README.md)
13 changes: 12 additions & 1 deletion sim-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ async fn main() -> anyhow::Result<()> {
let mut clients: HashMap<PublicKey, Arc<Mutex<dyn LightningNode>>> = HashMap::new();
let mut pk_node_map = HashMap::new();
let mut alias_node_map = HashMap::new();
let mut activity_name_map = HashMap::new();

for connection in nodes {
// TODO: Feels like there should be a better way of doing this without having to Arc<Mutex<T>>> it at this time.
Expand Down Expand Up @@ -132,7 +133,7 @@ async fn main() -> anyhow::Result<()> {
alias_node_map.insert(node_info.alias.clone(), node_info);
}

let mut validated_activities = vec![];
let mut validated_activities: Vec<ActivityDefinition> = vec![];
// Make all the activities identifiable by PK internally
for act in activity.into_iter() {
// We can only map aliases to nodes we control, so if either the source or destination alias
Expand Down Expand Up @@ -182,13 +183,23 @@ async fn main() -> anyhow::Result<()> {
},
};

if activity_name_map.contains_key(&act.activity_name) {
anyhow::bail!(LightningError::ValidationError(format!(
"Duplicate activity name {:?} is not allowed.",
act.activity_name.unwrap()
),));
}

activity_name_map.insert(act.activity_name.clone(), act.clone());

validated_activities.push(ActivityDefinition {
source,
destination,
start_secs: act.start_secs,
count: act.count,
interval_secs: act.interval_secs,
amount_msat: act.amount_msat,
activity_name: act.activity_name,
});
}

Expand Down
Loading

0 comments on commit 1f29207

Please sign in to comment.