ln-service 59.4.1 → 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,11 @@
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
+
3
9
  ## 59.4.1
4
10
 
5
11
  - `subscribeToForwardRequests`: Invalid requests to forward more than the
package/package.json CHANGED
@@ -13,7 +13,7 @@
13
13
  },
14
14
  "dependencies": {
15
15
  "bolt07": "2.0.0",
16
- "invoices": "6.1.4",
16
+ "invoices": "6.2.0",
17
17
  "lightning": "12.3.1",
18
18
  "macaroon": "3.0.4"
19
19
  },
@@ -24,7 +24,7 @@
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",
@@ -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.1"
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);