Git Product home page Git Product logo

ln-jamming-simulator's People

Contributors

s-tikhomirov avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

ln-jamming-simulator's Issues

Run experiments with different success-case fees

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.

Explore alternatives to NetworkX

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 PriorityQueues 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:

Collect graph stats in a readable form

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.

Mixed simulation (jamming alongside honest payment flow)

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 Payments), 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.

Pick another dust limit?

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?

Weigh routes by fees

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).

Achieve 100% test coverage

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%

Further research ideas

Potential directions for exploration of adjacent topics:

  • implement reputation strategies, simulate attacks in the presence of reputation scores
  • explore error attribution ideas (somewhat related to reputation)
  • define attack success metrics (locked-up channels, routes, nodes, decreased success rates of honest payments, ...)
  • measure attacker's costs (locked-up capital, unconditional fees)
  • calculate attack effectiveness (unit of attack success per unit of cost)
  • explore more broad fee strategies (inbound fees, bidirectional fees, etc - see overview)
  • explore fee amount calculation based on factual payment resolution time (what additional trust assumptions does it entail? - see Jamming book
  • investigate the applicability of unconditional fees to incentivizing watchtowers (such as The eye of Satoshi)
  • measure the effects on balance probing attacks

See also: the "Future work" section of the paper.

Thinking about choosing between parallel channels

Two nodes may share multiple (parallel) channels. These channels may have different fee policies.

This is relevant at least twice:

  1. At the route construction stage. To choose the cheapest channel, in the general case, we need to account for amount as well (fee functions are first-degree polynomials, but are not zero at zero).
  2. At the payment routing stage. Each routing node, given a payment to forward, can decide which channel to the next node to use.

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:

  1. How are fees considered at route construction? Does the sender always prefer cheapest channels? How do weigh fees vs capacity (i.e., do we choose a cheap small channel where the failure probability is higher, or a more expensive high-capacity channel)?
  2. How are fees accounted for at payment forwarding? In case there are multiple parallel channels with different fees, does the routing node always choose the cheapest? If the payment fails when being forwarded through the cheapest channel, would the sender retry the same route in the hope that the routing node would now try the second-cheapest channel?
  3. How does the jammer account for fees? Does the jammer adapt the jams for different fee levels to jam parallel channels as cheaply as possible?

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.