Basic Documentation¶
In the steps below we suppose that you have already installed lnsimulator
and downloaded the related LN data.
If it is not the case then should follow the instructions in the Getting Started section first.
Prepare LN data¶
In order to run the simulation you need to provide LN snapshots as well as information about merchants nodes.
LN snapshots¶
The network structure is fed to lnsimulator
in the form of LN snapshots. Raw JSON files as well as preprocessed payment channel data can be used as input.
a.) Load data from JSON file¶
from lnsimulator.ln_utils import preprocess_json_file
data_dir = "..." # path to the ln_data folder that contains the downloaded data
directed_edges = preprocess_json_file("%s/sample.json" % data_dir)
b.) Load preprocessed LN snapshots¶
In this case you should select data related to a given daily snapshot
import pandas as pd
snapshot_id = 0
snapshots = pd.read_csv("%s/ln_edges.csv" % data_dir)
directed_edges = snapshots[snapshots["snapshot_id"]==snapshot_id]
Note that the preprocessed data format is identical to the output of the preprocess_json_file
function.
Merchants¶
We provided the list of LN merchants that we used in our experiments. This merchant information was collected in early 2019.
import pandas as pd
node_meta = pd.read_csv("%s/1ml_meta_data.csv" % data_dir)
providers = list(node_meta["pub_key"])
Configuration¶
First we give you the list of main parameters. By the word “transaction” we refer to LN payments.
Parameter | Description |
---|---|
amount |
value of each simulated transaction in satoshis |
count |
number of random transactions to sample |
epsilon |
ratio of merchants among transactions endpoints |
drop_disabled |
drop temporarily disabled channels |
drop_low_cap |
drop channels with capacity less than amount |
with_depletion |
the available channel capacity is maintained for both endpoints |
You can initialize the traffic simulator by providing the network structure, merchants information and the former parameters.
import lnsimulator.simulator.transaction_simulator as ts
amount = 60000
count = 7000
epsilon = 0.8
drop_disabled = True
drop_low_cap = True
with_depletion = True
simulator = ts.TransactionSimulator(directed_edges, providers, amount, count, drop_disabled=drop_disabled, drop_low_cap=drop_low_cap, eps=epsilon, with_depletion=with_depletion)
Estimating daily income and traffic¶
i.) Transactions¶
The simulator samples a set of random transactions (during the initialization) that will be used for the estimation of daily node traffic and routing income. You can access the sampled transactions in the form of a pandas.DataFrame
.
transactions = simulator.transactions
print(transactions.head())
print(transactions.shape)
ii.) Run simulation¶
In this step the simulator searches for cheapest payment paths from transaction senders to its receivers. Channel capacity changes are well maintained during the simulation.
cheapest_paths, _, all_router_fees, _ = simulator.simulate(weight="total_fee", with_node_removals=False)
print(all_router_fees.head())
iii.) Results¶
After payment simulation you can export the results as well as calculate traffic and income statistics for LN nodes.
output_dir = "test"
total_income, total_fee = simulator.export(output_dir)
In order to get stable daily LN node statistics, we recommend to run the simulator for multiple times over several consecutive snapshots. Node statistics in each output file below are restricted to a single traffic simulator experiment! You can find these file in the output_dir
folder.
a.) lengths_distrib.csv¶
Distribution of payment path length for the sampled transactions. Due to the source routing nature of LN, we assumed that transactions are executed on the cheapest path between the sender and the recipient.
Column | Description |
---|---|
First | Payment path length |
Second | Number of sampled transactions with given length |
Note: the length is marked -1 if the payment failed (there was no available path for routing)
Note: the sum of transactions in the second column could be less then the predefined number of payments to simulate. The difference is the number of randomly sampled loop transactions with identical sender and recipient node.
b.) router_incomes.csv¶
Contains statistics on nodes that forwarded payments in the simulation. We refer to these nodes as routers.
Column | Description |
---|---|
node | LN node public key |
fee | routing income |
num_trans | number of routed transactions |
c.) source_fees.csv¶
Contains statistics on payment initiator nodes (senders).
Column | Description |
---|---|
source | LN node that initiated the payment (sender node) |
num_trans | the number of transactions initiated by this node in the simulation |
mean_fee | the mean transaction cost per payment |
Useful function calls¶
There are alternative ways to interact with the simulator object beside exporting the results (with the simulator.export(output_dir)
function). Please follow the examples below.
Top nodes with highest daily income¶
You can search for the identity of these nodes on 1ml.com.
total_income.sort_values("fee", ascending=False).set_index("node").head(5)
Top nodes with highest daily traffic¶
total_income.sort_values("num_trans", ascending=False).set_index("node").head(5)
Payment path length distribution¶
Note: the length is marked -1 if the payment failed (there was no available path for routing)
cheapest_paths["length"].value_counts()
Payment succes ratio¶
(cheapest_paths["length"] > -1).value_counts() / len(cheapest_paths)
Payment cost statistics¶
cheapest_paths["original_cost"].describe()
Most frequent payment receivers¶
simulator.transactions["target"].value_counts().head(5)
Number of unique payment senders and receivers¶
simulator.transactions["source"].nunique(), simulator.transactions["target"].nunique()