ln-service 59.4.0 → 59.5.0

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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # Versions
2
2
 
3
+ ## 59.5.0
4
+
5
+ - `createSignedRequest`: Add support for signing BLIP39 path payment requests
6
+ - `createUnsignedRequest`: Add support for specifying BLIP39 payment req paths
7
+ - `parsePaymentRequest`: Add support for parsing BLIP39 payment request paths
8
+
9
+ ## 59.4.1
10
+
11
+ - `subscribeToForwardRequests`: Invalid requests to forward more than the
12
+ inbound HTLC amount or with an outbound CLTV past the inbound CLTV are no
13
+ longer emitted and are released for LND to fail
14
+
3
15
  ## 59.4.0
4
16
 
5
17
  - `sendMessage`: Add method to send a network onion message
package/README.md CHANGED
@@ -5882,6 +5882,9 @@ Subscribe to requests to forward payments
5882
5882
  Note that the outbound channel is only the requested channel, another may be
5883
5883
  selected internally to complete the forward.
5884
5884
 
5885
+ Invalid requests that have invalid fees or CLTVs cannot be forwarded and are
5886
+ not emitted, they are released for LND to fail
5887
+
5885
5888
  Requires `offchain:read`, `offchain:write` permission
5886
5889
 
5887
5890
  `onion` is not supported in LND 0.11.1 and below
package/package.json CHANGED
@@ -13,8 +13,8 @@
13
13
  },
14
14
  "dependencies": {
15
15
  "bolt07": "2.0.0",
16
- "invoices": "6.1.4",
17
- "lightning": "12.3.0",
16
+ "invoices": "6.2.0",
17
+ "lightning": "12.3.1",
18
18
  "macaroon": "3.0.4"
19
19
  },
20
20
  "description": "Interaction helper for your Lightning Network daemon",
@@ -24,12 +24,12 @@
24
24
  "asyncjs-util": "1.2.12",
25
25
  "bip32": "5.0.1",
26
26
  "bip66": "2.0.0",
27
- "bolt04": "1.0.0",
27
+ "bolt04": "1.2.0",
28
28
  "ecpair": "3.0.2",
29
29
  "ln-docker-daemons": "8.0.5",
30
30
  "p2tr": "3.0.0",
31
31
  "portfinder": "1.0.38",
32
- "psbt": "6.0.3",
32
+ "psbt": "6.0.4",
33
33
  "tiny-secp256k1": "2.2.4"
34
34
  },
35
35
  "engines": {
@@ -61,5 +61,5 @@
61
61
  "integration-test-0.20.0": "DOCKER_LND_VERSION=v0.20.0-beta npm run test",
62
62
  "test": "echo $DOCKER_LND_VERSION && node test/runner"
63
63
  },
64
- "version": "59.4.0"
64
+ "version": "59.5.0"
65
65
  }
@@ -1,13 +1,20 @@
1
1
  const asyncRetry = require('async/retry');
2
+ const {equal} = require('node:assert').strict;
2
3
  const {strictEqual} = require('node:assert').strict;
3
4
  const test = require('node:test');
4
5
 
6
+ const {paymentPathFromChannels} = require('bolt04');
5
7
  const {setupChannel} = require('ln-docker-daemons');
6
8
  const {spawnLightningCluster} = require('ln-docker-daemons');
7
9
 
8
10
  const {addPeer} = require('./../../');
9
11
  const {createInvoice} = require('./../../');
12
+ const {createSignedRequest} = require('./../../');
13
+ const {createUnsignedRequest} = require('./../../');
10
14
  const {decodePaymentRequest} = require('./../../');
15
+ const {getChannel} = require('./../../');
16
+ const {getHeight} = require('./../../');
17
+ const {getInvoice} = require('./../../');
11
18
  const {getWalletInfo} = require('./../../');
12
19
  const {parsePaymentRequest} = require('./../../');
13
20
  const {pay} = require('./../../');
@@ -15,13 +22,14 @@ const {pay} = require('./../../');
15
22
  const count = 100;
16
23
  const expiry = () => new Date(Date.now() + (4 * 60 * 60 * 1000)).toISOString();
17
24
  const give = 500000;
25
+ const hopCount = 5;
18
26
  const interval = 100;
19
27
  const size = 3;
20
28
  const times = 10000;
21
29
  const tokens = 100;
22
30
 
23
31
  // Paying to an encrypted routes invoice should result in a payment
24
- test(`Create an invoice`, async () => {
32
+ test(`Create an encrypted routes invoice`, async () => {
25
33
  const {kill, nodes} = await spawnLightningCluster({size});
26
34
 
27
35
  const [{generate, lnd}, target, remote] = nodes;
@@ -29,11 +37,16 @@ test(`Create an invoice`, async () => {
29
37
  await generate({count});
30
38
 
31
39
  try {
32
- await setupChannel({generate, lnd, give_tokens: give, to: target});
40
+ const channel1 = await setupChannel({
41
+ generate,
42
+ lnd,
43
+ give_tokens: give,
44
+ to: target,
45
+ });
33
46
 
34
47
  await addPeer({lnd, public_key: remote.id, socket: remote.socket});
35
48
 
36
- await setupChannel({
49
+ const channel2 = await setupChannel({
37
50
  generate: target.generate,
38
51
  give_tokens: give,
39
52
  lnd: target.lnd,
@@ -55,6 +68,89 @@ test(`Create an invoice`, async () => {
55
68
  await pay({lnd: remote.lnd, request: invoice.request});
56
69
  });
57
70
 
71
+ // Try padded variations on encrypted routes
72
+ const remoteInvoice = await createInvoice({tokens, lnd: remote.lnd});
73
+ const targetInvoice = await createInvoice({tokens, lnd: target.lnd});
74
+
75
+ const remotePaymentDetails = parsePaymentRequest({
76
+ request: remoteInvoice.request,
77
+ });
78
+
79
+ const targetPaymentDetails = parsePaymentRequest({
80
+ request: targetInvoice.request,
81
+ });
82
+
83
+ const remoteHeight = await getHeight({lnd: remote.lnd});
84
+ const targetHeight = await getHeight({lnd: target.lnd});
85
+
86
+ // Paying to a direct peer but with dummy hops to hide that
87
+ const targetPath = paymentPathFromChannels({
88
+ channels: [],
89
+ cltv_delta: targetPaymentDetails.cltv_delta + 3,
90
+ destination: targetPaymentDetails.destination,
91
+ current_block_height: targetHeight.current_block_height,
92
+ hop_count: hopCount,
93
+ id: targetPaymentDetails.payment,
94
+ max_mtokens: targetPaymentDetails.mtokens,
95
+ });
96
+
97
+ // Paying to an indirect peer with a receiver fee added
98
+ const remotePath = paymentPathFromChannels({
99
+ channels: [await getChannel({lnd: remote.lnd, id: channel2.id})],
100
+ cltv_delta: remotePaymentDetails.cltv_delta + 3,
101
+ destination: remotePaymentDetails.destination,
102
+ current_block_height: remoteHeight.current_block_height,
103
+ hop_count: hopCount,
104
+ id: remotePaymentDetails.payment,
105
+ max_mtokens: remotePaymentDetails.mtokens,
106
+ receiver_base_fee_mtokens: '1000',
107
+ receiver_fee_rate: 10000,
108
+ });
109
+
110
+ equal(remotePath.hops.length, hopCount, 'Got expected hops for target');
111
+ equal(targetPath.hops.length, hopCount, 'Got expected hops for remote');
112
+
113
+ // Try paying a remote path
114
+ {
115
+ // Make a blinded version of the invoice
116
+ const {hrp, tags} = createUnsignedRequest({
117
+ description: remotePaymentDetails.description,
118
+ expires_at: remotePaymentDetails.expires_at,
119
+ features: [{bit: 8}, {bit: 15}, {bit: 24}, {bit: 262}],
120
+ id: remotePaymentDetails.id,
121
+ mtokens: remotePaymentDetails.mtokens,
122
+ network: 'regtest',
123
+ paths: [remotePath],
124
+ });
125
+
126
+ const request = createSignedRequest({hrp, tags}).request;
127
+
128
+ await pay({lnd, request});
129
+
130
+ const received = await getInvoice({
131
+ id: remotePaymentDetails.id,
132
+ lnd: remote.lnd,
133
+ });
134
+
135
+ equal(received.received_mtokens, '102001', 'Got receiver fee');
136
+ }
137
+
138
+ // Try paying a peer path to target
139
+ {
140
+ // Make a blinded version of the invoice
141
+ const {hrp, tags} = createUnsignedRequest({
142
+ description: targetPaymentDetails.description,
143
+ expires_at: targetPaymentDetails.expires_at,
144
+ features: [{bit: 8}, {bit: 15}, {bit: 24}, {bit: 262}],
145
+ id: targetPaymentDetails.id,
146
+ mtokens: targetPaymentDetails.mtokens,
147
+ network: 'regtest',
148
+ paths: [targetPath],
149
+ });
150
+
151
+ await pay({lnd, request: createSignedRequest({hrp, tags}).request});
152
+ }
153
+
58
154
  await kill({});
59
155
  } catch (err) {
60
156
  await kill({});
@@ -235,18 +235,22 @@ test(`Open unconfirmed channels`, async () => {
235
235
 
236
236
  // Confirm the private channel
237
237
  const privateConfirmed = await asyncRetry({interval, times}, async () => {
238
- // Generate the channel into a block
239
- await broadcastChainTransaction({
240
- lnd,
241
- transaction: signedPrivate.transaction,
242
- });
243
-
244
238
  await generate({});
245
239
 
246
240
  const [confirmed] = (await getChannels({lnd})).channels;
247
241
 
248
242
  const shut = await getClosedChannels({lnd});
249
243
 
244
+ if (!!shut.channels.length) {
245
+ return confirmed;
246
+ }
247
+
248
+ // Generate the channel into a block
249
+ await broadcastChainTransaction({
250
+ lnd,
251
+ transaction: signedPrivate.transaction,
252
+ });
253
+
250
254
  if (!shut.channels.length) {
251
255
  throw new Error('ExpectedClosedChannel');
252
256
  }
@@ -54,6 +54,8 @@ test('Probe for route', async () => {
54
54
  await addPeer({lnd, public_key: remote.id, socket: remote.socket});
55
55
  });
56
56
 
57
+ await generate({});
58
+
57
59
  await setupChannel({
58
60
  generate,
59
61
  lnd,
@@ -61,6 +63,8 @@ test('Probe for route', async () => {
61
63
  to: target,
62
64
  });
63
65
 
66
+ await target.generate({});
67
+
64
68
  await setupChannel({
65
69
  capacity: channelCapacityTokens,
66
70
  lnd: target.lnd,
@@ -68,7 +72,6 @@ test('Probe for route', async () => {
68
72
  give_tokens: Math.round(channelCapacityTokens / 2),
69
73
  to: remote,
70
74
  });
71
-
72
75
  const invoice = await createInvoice({tokens, lnd: remote.lnd});
73
76
 
74
77
  await delay(1000);