Class Network
Constructors
Name | Description |
this
(lookupUpdate)
|
Ctor
|
Methods
Name | Description |
addChannel
(chan_conf)
|
Add a Channel to the network
|
getPaymentPath
(from_pk, to_pk, amount, ignore_chans)
|
Build a path between two nodes in the network
|
removeChannel
(chan_conf)
|
Remove a Channel from the network
|
Example
import std.range;
import std.algorithm;
auto ln = new Network((Hash chan_id, Point) {
return ChannelUpdate(chan_id, PaymentDirection.TowardsPeer, Amount(1), Amount(0));
});
Point[] pks;
iota(5).each!(idx => pks ~= Scalar.random().toPoint());
ChannelConfig conf;
conf.capacity = 1.coins;
conf.funder_pk = pks[0];
conf.peer_pk = pks[1];
conf.chan_id = hashFull(1);
ln.addChannel(conf);
// #0 -- #1
conf.funder_pk = pks[0];
conf.peer_pk = pks[2];
conf.chan_id = hashFull(2);
ln.addChannel(conf);
// #0 -- #1
// \__ #2
auto path = ln.getPaymentPath(pks[0], pks[1], Amount(1));
assert(path.length == 1);
assert(path[0].pub_key == pks[1]);
assert(path[0].chan_id == hashFull(1));
path = ln.getPaymentPath(pks[0], pks[2], Amount(1));
assert(path.length == 1);
assert(path[0].pub_key == pks[2]);
assert(path[0].chan_id == hashFull(2));
path = ln.getPaymentPath(pks[1], pks[2], Amount(1));
assert(path.length == 2);
assert(path[0].pub_key == pks[0]);
assert(path[0].chan_id == hashFull(1));
assert(path[1].pub_key == pks[2]);
assert(path[1].chan_id == hashFull(2));
conf.funder_pk = pks[3];
conf.peer_pk = pks[4];
conf.chan_id = hashFull(3);
ln.addChannel(conf);
// #0 -- #1
// \__ #2 #3 -- #4
foreach (node1; 0 .. 3)
foreach (node2; 3 .. 5)
assert(ln.getPaymentPath(pks[node1], pks[node2], Amount(1)) == null);
path = ln.getPaymentPath(pks[3], pks[4], Amount(1));
assert(path.length == 1);
assert(path[0].pub_key == pks[4]);
assert(path[0].chan_id == hashFull(3));
conf.funder_pk = pks[1];
conf.peer_pk = pks[2];
conf.chan_id = hashFull(4);
ln.addChannel(conf);
// #0 -- #1
// \ |
// \__ #2 #3 -- #4
path = ln.getPaymentPath(pks[1], pks[2], Amount(1));
assert(path.length == 1);
assert(path[0].pub_key == pks[2]);
assert(path[0].chan_id == hashFull(4));
// Ignore the direct channel between #0 and #2
path = ln.getPaymentPath(pks[0], pks[2], Amount(1), Set!Hash.from([hashFull(2)]));
assert(path.length == 2);
assert(path[0].pub_key == pks[1]);
assert(path[0].chan_id == hashFull(1));
assert(path[1].pub_key == pks[2]);
assert(path[1].chan_id == hashFull(4));
// Can't route 2.coins
path = ln.getPaymentPath(pks[0], pks[2], 2.coins);
assert(path == null);
// unknown keys
path = ln.getPaymentPath(Scalar.random().toPoint(), pks[1], Amount(1));
assert(path is null);
conf.funder_pk = pks[2];
conf.peer_pk = pks[3];
conf.chan_id = hashFull(5);
conf.is_private = true;
ln.addChannel(conf);
// #0 -- #1
// \ |
// \__ #2 -p- #3 -- #4
// anything that should use private channel as a hop should fail
foreach (node1; 0 .. 2)
assert(ln.getPaymentPath(pks[node1], pks[4], Amount(1)) == null);
foreach (node2; 0 .. 2)
assert(ln.getPaymentPath(pks[4], pks[node2], Amount(1)) == null);
// should be able to route directly between #2 and #3
path = ln.getPaymentPath(pks[2], pks[3], Amount(1));
assert(path.length == 1);
assert(path[0].pub_key == pks[3]);
assert(path[0].chan_id == hashFull(5));
path = ln.getPaymentPath(pks[3], pks[2], Amount(1));
assert(path.length == 1);
assert(path[0].pub_key == pks[2]);
assert(path[0].chan_id == hashFull(5));
// should not be able to route from left part of the graph to #3
foreach (node1; 0 .. 2)
assert(ln.getPaymentPath(pks[node1], pks[3], Amount(1)) == null);
// should be able to route from right part of the graph to #2
path = ln.getPaymentPath(pks[4], pks[2], Amount(1));
assert(path[$-1].pub_key == pks[2]);
assert(path[$-1].chan_id == hashFull(5));