ln-service 53.5.2 → 53.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/README.md +51 -2
- package/index.js +4 -2
- package/package.json +16 -5
- package/test/integration/test_add_peer.js +25 -19
- package/test/integration/test_delete_pending_channel.js +18 -11
- package/test/integration/test_get_failed_payments.js +123 -119
- package/test/integration/test_get_node.js +48 -44
- package/test/integration/test_get_pending_force.js +8 -1
- package/test/integration/test_get_wallet_info.js +30 -15
- package/test/integration/test_open_channels.js +21 -14
- package/test/integration/test_propose_channel.js +438 -421
- package/test/integration/test_subscribe_to_channels.js +1 -1
- package/test/integration/test_subscribe_to_peer_messages.js +77 -71
- package/test/integration/test_subscribe_to_peers.js +23 -19
- package/test/routerrpc-integration/test_get_forwarding_reputations.js +64 -60
- package/test/routerrpc-integration/test_get_route_confidence.js +38 -34
- package/test/routerrpc-integration/test_get_route_through_hops.js +33 -14
- package/test/routerrpc-integration/test_pay_via_payment_details.js +118 -110
- package/test/routerrpc-integration/test_pay_via_routes.js +19 -1
- package/test/routerrpc-integration/test_probe_for_route.js +75 -71
- package/test/routerrpc-integration/test_subscribe_to_forward_requests.js +2 -2
- package/test/routerrpc-integration/test_subscribe_to_forwards.js +508 -504
- package/test/walletrpc-integration/test_fund_psbt.js +4 -1
- package/test/walletrpc-integration/test_partially_sign_psbt.js +216 -0
- package/test/walletrpc-integration/test_sign_psbt.js +4 -1
|
@@ -16,7 +16,7 @@ const defaultFee = 1e3;
|
|
|
16
16
|
const giveTokens = 1e5;
|
|
17
17
|
const interval = 100;
|
|
18
18
|
const size = 2;
|
|
19
|
-
const times =
|
|
19
|
+
const times = 200;
|
|
20
20
|
|
|
21
21
|
// Subscribing to channels should trigger channel events
|
|
22
22
|
test('Subscribe to channels', async ({end, equal, fail}) => {
|
|
@@ -16,98 +16,104 @@ test(`Subscribe to peer messages`, async ({end, equal, strictSame}) => {
|
|
|
16
16
|
|
|
17
17
|
const [{lnd}, target, remote] = nodes;
|
|
18
18
|
|
|
19
|
-
await addPeer({
|
|
20
|
-
lnd,
|
|
21
|
-
public_key: target.id,
|
|
22
|
-
socket: target.socket,
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
await addPeer({
|
|
26
|
-
lnd: target.lnd,
|
|
27
|
-
public_key: remote.id,
|
|
28
|
-
socket: remote.socket,
|
|
29
|
-
});
|
|
30
|
-
|
|
31
19
|
try {
|
|
32
|
-
await
|
|
20
|
+
await addPeer({
|
|
33
21
|
lnd,
|
|
34
|
-
message: Buffer.from('message').toString('hex'),
|
|
35
22
|
public_key: target.id,
|
|
23
|
+
socket: target.socket,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
await addPeer({
|
|
27
|
+
lnd: target.lnd,
|
|
28
|
+
public_key: remote.id,
|
|
29
|
+
socket: remote.socket,
|
|
36
30
|
});
|
|
37
|
-
} catch (err) {
|
|
38
|
-
const [code] = err;
|
|
39
31
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
32
|
+
try {
|
|
33
|
+
await sendMessageToPeer({
|
|
34
|
+
lnd,
|
|
35
|
+
message: Buffer.from('message').toString('hex'),
|
|
36
|
+
public_key: target.id,
|
|
37
|
+
});
|
|
38
|
+
} catch (err) {
|
|
39
|
+
const [code] = err;
|
|
43
40
|
|
|
44
|
-
|
|
41
|
+
// Send message to peer is not supported on LND 0.13.4 or lower
|
|
42
|
+
if (code === 501) {
|
|
43
|
+
await kill({});
|
|
44
|
+
|
|
45
|
+
return end();
|
|
46
|
+
}
|
|
45
47
|
}
|
|
46
|
-
}
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
const messages = [];
|
|
50
|
+
const targetSub = subscribeToPeerMessages({lnd: target.lnd});
|
|
51
|
+
const remoteSub = subscribeToPeerMessages({lnd: remote.lnd});
|
|
52
|
+
const targetMessages = [];
|
|
52
53
|
|
|
53
|
-
|
|
54
|
+
remoteSub.on('message_received', message => messages.push(message));
|
|
54
55
|
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
targetSub.on('message_received', async ({message, type}) => {
|
|
57
|
+
targetMessages.push(message);
|
|
57
58
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
if (type !== 40805) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Wait for message to appear
|
|
64
|
+
return await asyncRetry({interval, times}, async () => {
|
|
65
|
+
// Relay message from control to remote
|
|
66
|
+
await sendMessageToPeer({
|
|
67
|
+
message,
|
|
68
|
+
type,
|
|
69
|
+
lnd: target.lnd,
|
|
70
|
+
public_key: remote.id,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
if (!messages.length) {
|
|
74
|
+
throw new Error('ExpectedMessage');
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
});
|
|
61
78
|
|
|
62
79
|
// Wait for message to appear
|
|
63
|
-
|
|
64
|
-
|
|
80
|
+
await asyncRetry({interval, times}, async () => {
|
|
81
|
+
// Control send a message to target peer
|
|
65
82
|
await sendMessageToPeer({
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
83
|
+
lnd,
|
|
84
|
+
message: Buffer.from('message to remote').toString('hex'),
|
|
85
|
+
public_key: target.id,
|
|
86
|
+
type: 40805,
|
|
70
87
|
});
|
|
71
88
|
|
|
72
|
-
if (!
|
|
73
|
-
throw new Error('
|
|
89
|
+
if (!targetMessages.length) {
|
|
90
|
+
throw new Error('ExpectedTargetMessageReceived');
|
|
74
91
|
}
|
|
75
92
|
});
|
|
76
|
-
});
|
|
77
93
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
message: Buffer.from('message to remote').toString('hex'),
|
|
84
|
-
public_key: target.id,
|
|
85
|
-
type: 40805,
|
|
94
|
+
// Wait for message to appear
|
|
95
|
+
await asyncRetry({interval, times}, async () => {
|
|
96
|
+
if (!messages.length) {
|
|
97
|
+
throw new Error('ExpectedMessage');
|
|
98
|
+
}
|
|
86
99
|
});
|
|
87
100
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
public_key: target.id,
|
|
105
|
-
type: 40805,
|
|
106
|
-
}],
|
|
107
|
-
'Message successfully relayed through target'
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
await kill({});
|
|
101
|
+
const [message] = messages;
|
|
102
|
+
|
|
103
|
+
strictSame(
|
|
104
|
+
message,
|
|
105
|
+
{
|
|
106
|
+
message: Buffer.from('message to remote').toString('hex'),
|
|
107
|
+
public_key: target.id,
|
|
108
|
+
type: 40805,
|
|
109
|
+
},
|
|
110
|
+
'Message successfully relayed through target'
|
|
111
|
+
);
|
|
112
|
+
} catch (err) {
|
|
113
|
+
equal(err, null, 'Expected no error');
|
|
114
|
+
} finally {
|
|
115
|
+
await kill({});
|
|
116
|
+
}
|
|
111
117
|
|
|
112
118
|
return end();
|
|
113
119
|
});
|
|
@@ -20,36 +20,40 @@ test(`Subscribe to peers`, async ({end, equal}) => {
|
|
|
20
20
|
|
|
21
21
|
const [{generate, lnd}, target] = nodes;
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
try {
|
|
24
|
+
const sub = subscribeToPeers({lnd});
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
sub.on('error', () => {});
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
await asyncRetry({interval, times}, async () => {
|
|
29
|
+
await addPeer({lnd, public_key: target.id, socket: target.socket});
|
|
30
|
+
});
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
const disconnect = removePeer({lnd, public_key: target.id});
|
|
33
|
+
const receiveDisconnect = once(sub, 'disconnected');
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
const [disconectMessage] = await all([receiveDisconnect, disconnect]);
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
const [disconnected] = disconectMessage;
|
|
37
38
|
|
|
38
|
-
|
|
39
|
+
equal(disconnected.public_key, target.id, 'Got d/c event');
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
const connect = asyncRetry({interval, times}, async () => {
|
|
42
|
+
return addPeer({lnd, public_key: target.id, socket: target.socket});
|
|
43
|
+
});
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
const receiveConnectMessage = once(sub, 'connected');
|
|
45
46
|
|
|
46
|
-
|
|
47
|
+
const [connectMessage] = await all([receiveConnectMessage, connect]);
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
const [connected] = connectMessage;
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
equal(connected.public_key, target.id, 'Got connected');
|
|
52
|
+
} catch (err) {
|
|
53
|
+
equal(err, null, 'Expected no error');
|
|
54
|
+
} finally {
|
|
55
|
+
await kill({});
|
|
56
|
+
}
|
|
53
57
|
|
|
54
58
|
return end();
|
|
55
59
|
});
|
|
@@ -26,66 +26,70 @@ test('Get forwarding reputations', async ({end, equal}) => {
|
|
|
26
26
|
|
|
27
27
|
const [{generate, id, lnd}, target, remote] = cluster.nodes;
|
|
28
28
|
|
|
29
|
-
await generate({count:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
await
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
29
|
+
await generate({count: 100});
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
// Create a channel from the control to the target node
|
|
33
|
+
await setupChannel({
|
|
34
|
+
generate,
|
|
35
|
+
lnd,
|
|
36
|
+
capacity: channelCapacityTokens * 2,
|
|
37
|
+
to: target,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const targetToRemoteChan = await setupChannel({
|
|
41
|
+
generate: target.generate,
|
|
42
|
+
give: Math.round(channelCapacityTokens / 2),
|
|
43
|
+
lnd: target.lnd,
|
|
44
|
+
to: remote,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
await asyncRetry({interval, times}, async () => {
|
|
48
|
+
await addPeer({lnd, public_key: remote.id, socket: remote.socket});
|
|
49
|
+
|
|
50
|
+
const {channels} = await getChannels({lnd: remote.lnd});
|
|
51
|
+
|
|
52
|
+
await waitForRoute({lnd, tokens, destination: remote.id});
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
const res = await probeForRoute({
|
|
56
|
+
lnd,
|
|
57
|
+
tokens,
|
|
58
|
+
destination: remote.id,
|
|
59
|
+
is_ignoring_past_failures: true,
|
|
60
|
+
});
|
|
61
|
+
} catch (err) {
|
|
62
|
+
equal(err, null, 'Expected no error probing');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const {nodes} = await getForwardingReputations({lnd});
|
|
66
|
+
|
|
67
|
+
const [node] = nodes;
|
|
68
|
+
|
|
69
|
+
if (!node) {
|
|
70
|
+
throw new Error('ExpectedForwardingNode');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
equal(!!node.public_key, true, 'Temp fail node added');
|
|
74
|
+
|
|
75
|
+
const [peer] = node.peers;
|
|
76
|
+
|
|
77
|
+
if (!peer) {
|
|
78
|
+
throw new Error('ExpectedNodePeer');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!peer.last_failed_forward_at) {
|
|
82
|
+
throw new Error('ExpectedLastFailTimeReturned');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
equal(!!peer.last_failed_forward_at, true, 'Last fail time returned');
|
|
86
|
+
equal(!!peer.to_public_key, true, 'Got peer pub key');
|
|
87
|
+
});
|
|
88
|
+
} catch (err) {
|
|
89
|
+
equal(err, null, 'Expected no error');
|
|
90
|
+
} finally {
|
|
91
|
+
await cluster.kill({});
|
|
92
|
+
}
|
|
89
93
|
|
|
90
94
|
return end();
|
|
91
95
|
});
|
|
@@ -17,41 +17,45 @@ test('Get route confidence', async ({end, equal}) => {
|
|
|
17
17
|
|
|
18
18
|
const [{generate, lnd}, target, remote] = nodes;
|
|
19
19
|
|
|
20
|
-
// Create a channel from the control to the target node
|
|
21
|
-
await setupChannel({
|
|
22
|
-
generate,
|
|
23
|
-
lnd,
|
|
24
|
-
capacity: channelCapacityTokens * 2,
|
|
25
|
-
to: target,
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
// Create a too-small channel from target to remote
|
|
29
|
-
await setupChannel({
|
|
30
|
-
generate: target.generate,
|
|
31
|
-
give: Math.round(channelCapacityTokens / 2),
|
|
32
|
-
lnd: target.lnd,
|
|
33
|
-
to: remote,
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
await addPeer({lnd, public_key: remote.id, socket: remote.socket});
|
|
37
|
-
|
|
38
|
-
const destination = remote.id;
|
|
39
|
-
|
|
40
|
-
// Allow time for graph sync to complete
|
|
41
|
-
const {routes} = await waitForRoute({destination, lnd, tokens});
|
|
42
|
-
|
|
43
|
-
// Run into a failure to inform future pathfinding
|
|
44
20
|
try {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
21
|
+
// Create a channel from the control to the target node
|
|
22
|
+
await setupChannel({
|
|
23
|
+
generate,
|
|
24
|
+
lnd,
|
|
25
|
+
capacity: channelCapacityTokens * 2,
|
|
26
|
+
to: target,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// Create a too-small channel from target to remote
|
|
30
|
+
await setupChannel({
|
|
31
|
+
generate: target.generate,
|
|
32
|
+
give: Math.round(channelCapacityTokens / 2),
|
|
33
|
+
lnd: target.lnd,
|
|
34
|
+
to: remote,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
await addPeer({lnd, public_key: remote.id, socket: remote.socket});
|
|
38
|
+
|
|
39
|
+
const destination = remote.id;
|
|
40
|
+
|
|
41
|
+
// Allow time for graph sync to complete
|
|
42
|
+
const {routes} = await waitForRoute({destination, lnd, tokens});
|
|
43
|
+
|
|
44
|
+
// Run into a failure to inform future pathfinding
|
|
45
|
+
try {
|
|
46
|
+
await probeForRoute({destination, lnd, tokens});
|
|
47
|
+
} catch (err) {}
|
|
48
|
+
|
|
49
|
+
const [{hops}] = routes;
|
|
50
|
+
|
|
51
|
+
const {confidence} = await getRouteConfidence({lnd, hops});
|
|
52
|
+
|
|
53
|
+
equal((confidence / 1e6) < 0.1, true, 'Due to fail, odds of success low');
|
|
54
|
+
} catch (err) {
|
|
55
|
+
equal(err, null, 'Expected no error');
|
|
56
|
+
} finally {
|
|
57
|
+
await kill({});
|
|
58
|
+
}
|
|
55
59
|
|
|
56
60
|
return end();
|
|
57
61
|
});
|
|
@@ -8,6 +8,7 @@ const {addPeer} = require('./../../');
|
|
|
8
8
|
const {createInvoice} = require('./../../');
|
|
9
9
|
const {decodePaymentRequest} = require('./../../');
|
|
10
10
|
const {getInvoice} = require('./../../');
|
|
11
|
+
const {getNetworkGraph} = require('./../../');
|
|
11
12
|
const {getRouteThroughHops} = require('./../../');
|
|
12
13
|
const {getRouteToDestination} = require('./../../');
|
|
13
14
|
const {getWalletInfo} = require('./../../');
|
|
@@ -17,8 +18,10 @@ const {setupChannel} = require('./../macros');
|
|
|
17
18
|
const {waitForRoute} = require('./../macros');
|
|
18
19
|
|
|
19
20
|
const confirmationCount = 6;
|
|
21
|
+
const interval = 10;
|
|
20
22
|
const messages = [{type: '1000000', value: '01'}];
|
|
21
23
|
const size = 3;
|
|
24
|
+
const times = 1000;
|
|
22
25
|
const tokens = 100;
|
|
23
26
|
|
|
24
27
|
// Getting a route through hops should result in a route through specified hops
|
|
@@ -40,7 +43,7 @@ test(`Get route through hops`, async ({end, equal, strictSame}) => {
|
|
|
40
43
|
|
|
41
44
|
await target.generate({count: confirmationCount});
|
|
42
45
|
|
|
43
|
-
await asyncRetry({interval
|
|
46
|
+
await asyncRetry({interval, times}, async () => {
|
|
44
47
|
const wallet = await getWalletInfo({lnd: remote.lnd});
|
|
45
48
|
|
|
46
49
|
await addPeer({lnd, public_key: remote.id, socket: remote.socket});
|
|
@@ -59,21 +62,37 @@ test(`Get route through hops`, async ({end, equal, strictSame}) => {
|
|
|
59
62
|
|
|
60
63
|
await waitForRoute({lnd, destination: remote.id, tokens: invoice.tokens});
|
|
61
64
|
|
|
62
|
-
const {route} = await
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
const {route} = await asyncRetry({interval, times}, async () => {
|
|
66
|
+
return await getRouteToDestination({
|
|
67
|
+
lnd,
|
|
68
|
+
cltv_delta: decodedRequest.cltv_delta,
|
|
69
|
+
destination: decodedRequest.destination,
|
|
70
|
+
tokens: invoice.tokens,
|
|
71
|
+
});
|
|
67
72
|
});
|
|
68
73
|
|
|
69
|
-
|
|
70
|
-
lnd
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
await asyncRetry({interval, times}, async () => {
|
|
75
|
+
const {nodes} = await getNetworkGraph({lnd});
|
|
76
|
+
|
|
77
|
+
const limitedFeatures = nodes.find(node => {
|
|
78
|
+
return !node.features.find(n => n.bit === 14);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
if (!!limitedFeatures) {
|
|
82
|
+
throw new Error('NetworkGraphSyncIncomplete');
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const res = await asyncRetry({interval, times}, async () => {
|
|
87
|
+
return await getRouteThroughHops({
|
|
88
|
+
lnd,
|
|
89
|
+
messages,
|
|
90
|
+
cltv_delta: decodedRequest.cltv_delta + 6,
|
|
91
|
+
mtokens: (BigInt(invoice.tokens) * BigInt(1e3)).toString(),
|
|
92
|
+
payment: decodedRequest.payment,
|
|
93
|
+
public_keys: route.hops.map(n => n.public_key),
|
|
94
|
+
total_mtokens: invoice.mtokens,
|
|
95
|
+
});
|
|
77
96
|
});
|
|
78
97
|
|
|
79
98
|
await payViaRoutes({lnd, id: invoice.id, routes: [res.route]});
|