s-tikhomirov / ln-jamming-simulator Goto Github PK
View Code? Open in Web Editor NEWSimulating countermeasures against jamming attacks in the Lightning Network
License: MIT License
Simulating countermeasures against jamming attacks in the Lightning Network
License: MIT License
Currently, experiments are run with all channels having the same success-case base fee (1 sat) and fee rate (5 ppm). This doesn't matter much as long as the experiments are on small topologies. For full-network experiments, assign success-case fees as per the snapshot.
We currently use a Python library called NetworkX for graph modeling. In particular, our route calculation uses NetworkX's all_shortest_paths
.
Alternative graph libraries reportedly are much more performant. Examples include: igraph, graph-tool, networkit. Is it worth switching to another graph library?
Note that the current version of the simulator can't be (easily) parallelized. We need to update in-flight HTLCs in channels, which are stored in Python's PriorityQueue
s inside each ChannelDirection
. We use single-threaded functions to get and put elements in / out of the queue. Parallelizing the code would require us to correctly handle the cases where the same queue is updated at the same time from different threads.
We also use (single-threaded) priority queues in Schedule
, but the task of creating a schedule doesn't need to be parallelized to begin with.
Further reading:
It may be useful to calculate some statistics about the graph and output it alongside experiment results. Such as: distribution of capacities, fee coefficients, some connectivity metrics, etc.
Virtual environment, requirements.txt
, etc etc.
We currently simulate two distinct scenarios: only honest payment flow (with HonestSchedule
) or only jamming (JammingSchedule
). Implement a mixed more, where jams are sent alongside honest payment. This should be possible with a generic Schedule
class. It is important to make sure the routing works correctly: honest payment are re-sent until they succeed (up to some maximum number of attempts), while jams are re-sent until all target hops are jammed (up to another maximum number of attempts).
To the same point, a single event in the schedule has a somewhat different semantics depending on whether it is honest (desired_result == True
) or a jam (desired_result == False
). An "honest" event simply corresponds to a single Payment
(which may be re-tried if it fails, but it can be thought of as one payment anyway). A "jamming" event, on the other hand, can be thought of as encoding a batch of jams. Initially, a jamming schedule contains a single event. Upon handling this event (i.e., sending the jams as Payment
s), the simulator pushes another jamming event into the schedule, encoding the next batch. This piece of logic is unique to jamming simulations: for HonestSchedule
, nothing is pushed into the schedule after it's created.
All that must be accounted for in implementing a "mixed" simulation mode with jams and honest payments in one schedule.
Put all tests into their own directory, figure out the packages / init files / whatever.
See Structuring your project from The Hitchhiker’s Guide to Python.
See also: Modularizing Pytest Fixtures.
We assume jams are slot-based. Their amount must just be high enough to not be trimmed. BOLT3 lists different dust thresholds for different output type. We currently use the "unknown segwit version" dust limit of 354 satoshis.
Should we pick another (maximum?) dust limit, or calculate an average of multiple dust limit values?
Channels with disabled = false
are not included into LNModel
. Should they be included? It only makes sense if we implement some kind of "enable channel - disable channel" logic (i.e., dynamic graph model).
Currently, HonestSimulator
chooses shortest routes, and JammingSimulator
constructs routes in a multi-step process so that they touch as many target hops as possible. Fees are not accounted for in route construction (which doesn't matter for small-graph experiments, as all channels are assigned the same success-case fees).
Prefer cheapest routes instead of shortest (at least in the honest case). Note the potential issues related to parallel channels (#2).
Some lines remain uncovered by tests, fix this.
As of 9dae687, running the tests produces this output:
$ coverage run -m pytest --verbose -o log_cli=true --log-cli-level=warning
================================================ test session starts =================================================
platform linux -- Python 3.8.10, pytest-7.1.2, pluggy-1.0.0 -- /home/sergei/Documents/ln-jamming-simulator/env/bin/python3
cachedir: .pytest_cache
rootdir: /home/sergei/Documents/ln-jamming-simulator
collected 57 items
channel_test.py::test_channel_setup PASSED [ 1%]
channel_test.py::test_channel_can_forward PASSED [ 3%]
channelindirection_test.py::test_set_get_fee PASSED [ 5%]
channelindirection_test.py::test_channel_direction PASSED [ 7%]
channelindirection_test.py::test_reset_slots PASSED [ 8%]
channelindirection_test.py::test_is_jammed PASSED [ 10%]
channelindirection_test.py::test_unsuccessful_ensure_free_slot PASSED [ 12%]
direction_test.py::test_direction PASSED [ 14%]
event_test.py::test_event PASSED [ 15%]
experiment_test.py::test_simulator_jamming_schedule PASSED [ 17%]
experiment_test.py::test_simulator_honest_schedule PASSED [ 19%]
experiment_test.py::test_simulator_jamming_fixed_route PASSED [ 21%]
hop_test.py::test_hop_create PASSED [ 22%]
hop_test.py::test_is_jammed PASSED [ 24%]
htlc_test.py::test_htlc_creation PASSED [ 26%]
htlc_test.py::test_htlc_compare PASSED [ 28%]
lnmodel_test.py::test_get_hop_graph_from_json PASSED [ 29%]
lnmodel_test.py::test_get_routing_graph_from_json PASSED [ 31%]
lnmodel_test.py::test_revenue PASSED [ 33%]
lnmodel_test.py::test_get_routing_graph_for_amount PASSED [ 35%]
lnmodel_test.py::test_get_routes PASSED [ 36%]
lnmodel_test.py::test_directionality PASSED [ 38%]
lnmodel_test.py::test_disabled_channel_direction PASSED [ 40%]
lnmodel_test.py::test_set_fee_for_all PASSED [ 42%]
lnmodel_test.py::test_get_shortest_routes_wrong_nodes
--------------------------------------------------- live log call ----------------------------------------------------
WARNING lnmodel:lnmodel.py:176 Can't find route from Alice to Zoe!
WARNING lnmodel:lnmodel.py:177 Sender Alice in graph? True
WARNING lnmodel:lnmodel.py:178 Sender Zoe in graph? False
PASSED [ 43%]
lnmodel_test.py::test_get_channels_can_forward_by_fee PASSED [ 45%]
lnmodel_test.py::test_balance_failure PASSED [ 47%]
payment_test.py::test_manual_payment_creation PASSED [ 49%]
payment_test.py::test_route_payment_creation PASSED [ 50%]
router_test.py::test_get_routes_via_target_node_pairs_simple PASSED [ 52%]
router_test.py::test_routes_wheel PASSED [ 54%]
router_test.py::test_pre_calculate_paths PASSED [ 56%]
router_test.py::test_get_shortest_route_via_hops PASSED [ 57%]
router_test.py::test_get_routes_via_target_node_pairs PASSED [ 59%]
router_test.py::test_is_hop_in_path PASSED [ 61%]
router_test.py::test_is_permutation_in_path PASSED [ 63%]
router_test.py::test_first_permutation_element_index_not_in_path PASSED [ 64%]
router_test.py::test_discard_route_with_repeated_hop PASSED [ 66%]
router_test.py::test_shorten_ids PASSED [ 68%]
schedule_test.py::test_schedule_get_put PASSED [ 70%]
schedule_test.py::test_get_all_events PASSED [ 71%]
schedule_test.py::test_event_same_sender_receiver PASSED [ 73%]
schedule_test.py::test_populate_schedule_with_one_event PASSED [ 75%]
schedule_test.py::test_generate_honest_schedule PASSED [ 77%]
schedule_test.py::test_generate_jamming_schedule PASSED [ 78%]
schedule_test.py::test_generate_jamming_schedule_hop_to_jam_with_own_batch PASSED [ 80%]
simulator_test.py::test_no_routes PASSED [ 82%]
simulator_test.py::test_not_enough_attempts
--------------------------------------------------- live log call ----------------------------------------------------
WARNING simulator:simulator.py:406 No route from Alice to Dave via any of [('Mary', 'Charlie')]
WARNING simulator:simulator.py:449 Couldn't jam 1 target node pairs after 2 routes at time 0.
WARNING simulator:simulator.py:450 Unjammed target node pairs: [(['Mary', 'Charli'], False, 0)]
PASSED [ 84%]
simulator_test.py::test_jammer_jammed
--------------------------------------------------- live log call ----------------------------------------------------
WARNING simulator:simulator.py:418 Jammer's node is in a jammed hop ('JammerSender', 'Alice'). Assign more slots to the jammer!
WARNING simulator:simulator.py:406 No route from JammerSender to Dave via any of [('Charlie', 'Dave')]
WARNING simulator:simulator.py:449 Couldn't jam 1 target node pairs after 2 routes at time 0.
WARNING simulator:simulator.py:450 Unjammed target node pairs: [(['Charli', 'Dave'], False, 1)]
PASSED [ 85%]
simulator_test.py::test_simulator_one_successful_payment PASSED [ 87%]
simulator_test.py::test_simulator_one_jam_batch PASSED [ 89%]
simulator_test.py::test_simulator_end_htlc_resolution PASSED [ 91%]
simulator_test.py::test_simulator_with_random_schedule PASSED [ 92%]
simulator_test.py::test_simulator_jamming PASSED [ 94%]
simulator_test.py::test_body_for_amount_function PASSED [ 96%]
simulator_test.py::test_error_response_honest PASSED [ 98%]
simulator_test.py::test_error_response_jamming
--------------------------------------------------- live log call ----------------------------------------------------
WARNING simulator:simulator.py:449 Couldn't jam 1 target node pairs after 2 routes at time 0.
WARNING simulator:simulator.py:450 Unjammed target node pairs: [(['Mary', 'Charli'], False, 0)]
WARNING simulator:simulator.py:449 Couldn't jam 1 target node pairs after 2 routes at time 4.
WARNING simulator:simulator.py:450 Unjammed target node pairs: [(['Mary', 'Charli'], False, 0)]
PASSED [100%]
================================================= 57 passed in 2.95s =================================================
$ coverage report -m
Name Stmts Miss Cover Missing
----------------------------------------------------------
channel.py 45 0 100%
channel_test.py 19 0 100%
channelindirection.py 85 0 100%
channelindirection_test.py 62 0 100%
direction.py 20 0 100%
direction_test.py 12 0 100%
enumtypes.py 9 0 100%
event.py 17 0 100%
event_test.py 6 0 100%
experiment_test.py 89 0 100%
hop.py 37 0 100%
hop_test.py 52 0 100%
htlc.py 11 0 100%
htlc_test.py 11 0 100%
lnmodel.py 228 2 99% 329-330
lnmodel_test.py 179 0 100%
params.py 6 0 100%
payment.py 45 1 98% 104
payment_test.py 59 0 100%
router.py 120 4 97% 68, 70, 120, 140
router_test.py 116 0 100%
schedule.py 54 0 100%
schedule_test.py 72 0 100%
simulator.py 358 33 91% 137, 147, 154, 278-318, 508, 539-540, 545-547, 549
simulator_test.py 220 0 100%
utils.py 6 0 100%
----------------------------------------------------------
TOTAL 1938 40 98%
Potential directions for exploration of adjacent topics:
See also: the "Future work" section of the paper.
Two nodes may share multiple (parallel) channels. These channels may have different fee policies.
This is relevant at least twice:
Currently, this doesn't matter much, as all channels are assigned the same default values for success-case fees. The "cheapest" channel is preferred at payment routing (though all of them are technically cheapest).
If we were to reflect the protocol more generically, we need to answer the following questions:
More generally, the notion of "cheapest" can be generalized to the notion of "best" channel w.r.t. the sender's preferences not only about fees, but about other things as well (timelocks, estimated failure probability, ...). The sender and the routing nodes may have different utility functions, so the channel that the sender thinks is "best" may not be the best from the router's standpoint.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.