bolt07 1.8.4 → 1.9.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 +5 -0
- package/ids/chan_number.js +0 -1
- package/package.json +1 -1
- package/routing/hops_from_channels.js +7 -1
- package/routing/policy_fee.js +12 -1
- package/routing/route_from_channels.js +2 -0
- package/routing/route_from_hops.js +2 -0
- package/test/routing/test_hops_from_channels.js +135 -0
- package/test/routing/test_policy_fee.js +27 -1
package/CHANGELOG.md
CHANGED
package/ids/chan_number.js
CHANGED
package/package.json
CHANGED
|
@@ -15,6 +15,8 @@ const payNodesCount = 2;
|
|
|
15
15
|
base_fee_mtokens: <Base Fee Millitokens String>
|
|
16
16
|
cltv_delta: <Locktime Delta Number>
|
|
17
17
|
fee_rate: <Fees Charged Per Million Tokens Number>
|
|
18
|
+
[inbound_base_discount_mtokens]: <Source Base Fee Reduction String>
|
|
19
|
+
[inbound_rate_discount]: <Source Per Million Rate Reduction Number>
|
|
18
20
|
is_disabled: <Channel Is Disabled Bool>
|
|
19
21
|
min_htlc_mtokens: <Minimum HTLC Millitokens Value String>
|
|
20
22
|
public_key: <Node Public Key String>
|
|
@@ -34,6 +36,8 @@ const payNodesCount = 2;
|
|
|
34
36
|
channel_capacity: <Maximum Tokens Number>
|
|
35
37
|
cltv_delta: <CLTV Delta Number>
|
|
36
38
|
fee_rate: <Fee Rate In Millitokens Per Million Number>
|
|
39
|
+
[inbound_base_discount_mtokens]: <Source Base Fee Reduction String>
|
|
40
|
+
[inbound_rate_discount]: <Source Per Million Rate Reduction Number>
|
|
37
41
|
public_key: <Public Key Hex String>
|
|
38
42
|
}]
|
|
39
43
|
}
|
|
@@ -74,7 +78,7 @@ module.exports = ({channels, destination}) => {
|
|
|
74
78
|
const nextPolicy = chans[i + [channel].length];
|
|
75
79
|
let overridePolicy;
|
|
76
80
|
|
|
77
|
-
const peer = channel.policies.find(n => n.public_key === nextHop);
|
|
81
|
+
const peer = channel.policies.find(n => n.public_key === nextHop) || {};
|
|
78
82
|
const policy = channel.policies.find(n => n.public_key !== nextHop);
|
|
79
83
|
|
|
80
84
|
if (!policy) {
|
|
@@ -104,6 +108,8 @@ module.exports = ({channels, destination}) => {
|
|
|
104
108
|
channel_capacity: channel.capacity,
|
|
105
109
|
cltv_delta: cltvDelta || defaultCltvDelta,
|
|
106
110
|
fee_rate: (overridePolicy || policy).fee_rate,
|
|
111
|
+
inbound_base_discount_mtokens: peer.inbound_base_discount_mtokens,
|
|
112
|
+
inbound_rate_discount: peer.inbound_rate_discount,
|
|
107
113
|
public_key: nextHop,
|
|
108
114
|
};
|
|
109
115
|
});
|
package/routing/policy_fee.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const none = '0';
|
|
1
2
|
const rateDivisor = BigInt(1e6);
|
|
2
3
|
|
|
3
4
|
/** Fee for policy
|
|
@@ -7,6 +8,8 @@ const rateDivisor = BigInt(1e6);
|
|
|
7
8
|
policy: {
|
|
8
9
|
base_fee_mtokens: <Base Fee Millitokens String>
|
|
9
10
|
fee_rate: <Fee Rate Number>
|
|
11
|
+
[inbound_base_discount_mtokens]: <Source Base Fee Reduction String>
|
|
12
|
+
[inbound_rate_discount]: <Source Per Million Rate Reduction Number>
|
|
10
13
|
}
|
|
11
14
|
}
|
|
12
15
|
|
|
@@ -38,8 +41,16 @@ module.exports = ({mtokens, policy}) => {
|
|
|
38
41
|
const baseFeeMtokens = BigInt(policy.base_fee_mtokens);
|
|
39
42
|
const feeRate = BigInt(policy.fee_rate);
|
|
40
43
|
const forwardMtokens = BigInt(mtokens);
|
|
44
|
+
const lowerBaseFee = BigInt(policy.inbound_base_discount_mtokens || none);
|
|
45
|
+
const lowerFeeRate = BigInt(policy.inbound_rate_discount || none);
|
|
41
46
|
|
|
47
|
+
const discount = lowerBaseFee + forwardMtokens * lowerFeeRate / rateDivisor;
|
|
42
48
|
const fee = baseFeeMtokens + forwardMtokens * feeRate / rateDivisor;
|
|
43
49
|
|
|
44
|
-
|
|
50
|
+
// Exit early when the discount drowns out the fee
|
|
51
|
+
if (-discount > fee) {
|
|
52
|
+
return {fee_mtokens: none};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return {fee_mtokens: (fee + discount).toString()};
|
|
45
56
|
};
|
|
@@ -17,6 +17,8 @@ const {isArray} = Array;
|
|
|
17
17
|
base_fee_mtokens: <Base Fee Millitokens String>
|
|
18
18
|
cltv_delta: <Locktime Delta Number>
|
|
19
19
|
fee_rate: <Fees Charged in Millitokens Per Million Number>
|
|
20
|
+
[inbound_base_discount_mtokens]: <Source Base Fee Reduction String>
|
|
21
|
+
[inbound_rate_discount]: <Source Per Million Rate Reduction Number>
|
|
20
22
|
is_disabled: <Channel Is Disabled Bool>
|
|
21
23
|
max_htlc_mtokens: <Maximum HTLC Millitokens Value String>
|
|
22
24
|
min_htlc_mtokens: <Minimum HTLC Millitokens Value String>
|
|
@@ -17,6 +17,8 @@ const minFee = 0;
|
|
|
17
17
|
[channel_capacity]: <Channel Capacity Tokens Number>
|
|
18
18
|
cltv_delta: <CLTV Delta Number>
|
|
19
19
|
fee_rate: <Fee Rate In Millitokens Per Million Number>
|
|
20
|
+
[inbound_base_discount_mtokens]: <Source Base Fee Reduction String>
|
|
21
|
+
[inbound_rate_discount]: <Source Per Million Rate Reduction Number>
|
|
20
22
|
public_key: <Next Hop Public Key Hex String>
|
|
21
23
|
}]
|
|
22
24
|
initial_cltv: <Initial CLTV Delta Number>
|
|
@@ -110,6 +110,8 @@ const tests = [
|
|
|
110
110
|
channel_capacity: 16777215,
|
|
111
111
|
cltv_delta: 40,
|
|
112
112
|
fee_rate: 2500,
|
|
113
|
+
inbound_base_discount_mtokens: undefined,
|
|
114
|
+
inbound_rate_discount: undefined,
|
|
113
115
|
public_key: 'b',
|
|
114
116
|
},
|
|
115
117
|
{
|
|
@@ -118,6 +120,8 @@ const tests = [
|
|
|
118
120
|
channel_capacity: 16777215,
|
|
119
121
|
cltv_delta: 30,
|
|
120
122
|
fee_rate: 2500,
|
|
123
|
+
inbound_base_discount_mtokens: undefined,
|
|
124
|
+
inbound_rate_discount: undefined,
|
|
121
125
|
public_key: 'c',
|
|
122
126
|
},
|
|
123
127
|
{
|
|
@@ -126,6 +130,8 @@ const tests = [
|
|
|
126
130
|
channel_capacity: 16777215,
|
|
127
131
|
cltv_delta: 144,
|
|
128
132
|
fee_rate: 1,
|
|
133
|
+
inbound_base_discount_mtokens: undefined,
|
|
134
|
+
inbound_rate_discount: undefined,
|
|
129
135
|
public_key: 'd',
|
|
130
136
|
},
|
|
131
137
|
{
|
|
@@ -134,6 +140,8 @@ const tests = [
|
|
|
134
140
|
channel_capacity: 16777215,
|
|
135
141
|
cltv_delta: 144,
|
|
136
142
|
fee_rate: 1,
|
|
143
|
+
inbound_base_discount_mtokens: undefined,
|
|
144
|
+
inbound_rate_discount: undefined,
|
|
137
145
|
public_key: 'e',
|
|
138
146
|
},
|
|
139
147
|
],
|
|
@@ -151,6 +159,8 @@ const tests = [
|
|
|
151
159
|
channel_capacity: 8429350,
|
|
152
160
|
cltv_delta: 40,
|
|
153
161
|
fee_rate: 2500,
|
|
162
|
+
inbound_base_discount_mtokens: undefined,
|
|
163
|
+
inbound_rate_discount: undefined,
|
|
154
164
|
public_key: '03e50492eab4107a773141bb419e107bda3de3d55652e6e1a41225f06a0bbf2d56',
|
|
155
165
|
},
|
|
156
166
|
{
|
|
@@ -159,6 +169,8 @@ const tests = [
|
|
|
159
169
|
channel_capacity: 2000000,
|
|
160
170
|
cltv_delta: 40,
|
|
161
171
|
fee_rate: 2500,
|
|
172
|
+
inbound_base_discount_mtokens: undefined,
|
|
173
|
+
inbound_rate_discount: undefined,
|
|
162
174
|
public_key: '03bb88ccc444534da7b5b64b4f7b15e1eccb18e102db0e400d4b9cfe93763aa26d',
|
|
163
175
|
},
|
|
164
176
|
{
|
|
@@ -167,6 +179,8 @@ const tests = [
|
|
|
167
179
|
channel_capacity: 400000,
|
|
168
180
|
cltv_delta: 40,
|
|
169
181
|
fee_rate: 100,
|
|
182
|
+
inbound_base_discount_mtokens: undefined,
|
|
183
|
+
inbound_rate_discount: undefined,
|
|
170
184
|
public_key: '028dcc199be86786818c8c32bffe9db8855c5fca98951eec99d1fa335d841605c2',
|
|
171
185
|
},
|
|
172
186
|
{
|
|
@@ -175,6 +189,8 @@ const tests = [
|
|
|
175
189
|
channel_capacity: 364355,
|
|
176
190
|
cltv_delta: 40,
|
|
177
191
|
fee_rate: 1,
|
|
192
|
+
inbound_base_discount_mtokens: undefined,
|
|
193
|
+
inbound_rate_discount: undefined,
|
|
178
194
|
public_key: '03277a99c297a53859b42a9bb8cb2c5c17b9eaa44509bae150e2ea35ca5aa29bd9',
|
|
179
195
|
},
|
|
180
196
|
],
|
|
@@ -189,6 +205,8 @@ const tests = [
|
|
|
189
205
|
channel_capacity: 1000,
|
|
190
206
|
cltv_delta: 40,
|
|
191
207
|
fee_rate: 7,
|
|
208
|
+
inbound_base_discount_mtokens: undefined,
|
|
209
|
+
inbound_rate_discount: undefined,
|
|
192
210
|
public_key: 'alice',
|
|
193
211
|
},
|
|
194
212
|
{
|
|
@@ -197,6 +215,8 @@ const tests = [
|
|
|
197
215
|
channel_capacity: 2000,
|
|
198
216
|
cltv_delta: 40,
|
|
199
217
|
fee_rate: 7,
|
|
218
|
+
inbound_base_discount_mtokens: undefined,
|
|
219
|
+
inbound_rate_discount: undefined,
|
|
200
220
|
public_key: 'bob',
|
|
201
221
|
},
|
|
202
222
|
{
|
|
@@ -205,6 +225,8 @@ const tests = [
|
|
|
205
225
|
channel_capacity: 3000,
|
|
206
226
|
cltv_delta: 40,
|
|
207
227
|
fee_rate: 9,
|
|
228
|
+
inbound_base_discount_mtokens: undefined,
|
|
229
|
+
inbound_rate_discount: undefined,
|
|
208
230
|
public_key: 'charlie',
|
|
209
231
|
},
|
|
210
232
|
],
|
|
@@ -240,6 +262,8 @@ const tests = [
|
|
|
240
262
|
channel_capacity: 100,
|
|
241
263
|
cltv_delta: 40,
|
|
242
264
|
fee_rate: 1,
|
|
265
|
+
inbound_base_discount_mtokens: undefined,
|
|
266
|
+
inbound_rate_discount: undefined,
|
|
243
267
|
public_key: Buffer.alloc(33).toString('hex'),
|
|
244
268
|
}],
|
|
245
269
|
},
|
|
@@ -273,6 +297,117 @@ const tests = [
|
|
|
273
297
|
description: 'Mapping hops from channels requires hop channel ids',
|
|
274
298
|
expected: [],
|
|
275
299
|
},
|
|
300
|
+
{
|
|
301
|
+
args: {
|
|
302
|
+
channels: [
|
|
303
|
+
{
|
|
304
|
+
capacity: 16777215,
|
|
305
|
+
destination: 'b',
|
|
306
|
+
id: '1x1x1',
|
|
307
|
+
policies: [
|
|
308
|
+
{
|
|
309
|
+
_policy_a_has_to_b: true,
|
|
310
|
+
base_fee_mtokens: '0',
|
|
311
|
+
fee_rate: 5000,
|
|
312
|
+
is_disabled: false,
|
|
313
|
+
min_htlc_mtokens: '2000',
|
|
314
|
+
public_key: 'a',
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
_policy_b_has_to_a: true,
|
|
318
|
+
base_fee_mtokens: '0',
|
|
319
|
+
fee_rate: 0,
|
|
320
|
+
inbound_base_discount_mtokens: '-5000',
|
|
321
|
+
inbound_rate_discount: 0,
|
|
322
|
+
is_disabled: false,
|
|
323
|
+
public_key: 'b',
|
|
324
|
+
},
|
|
325
|
+
],
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
capacity: 16777215,
|
|
329
|
+
destination: 'c',
|
|
330
|
+
id: '2x2x2',
|
|
331
|
+
policies: [
|
|
332
|
+
{
|
|
333
|
+
_policy_b_has_to_c: true,
|
|
334
|
+
base_fee_mtokens: '0',
|
|
335
|
+
fee_rate: 50000,
|
|
336
|
+
is_disabled: false,
|
|
337
|
+
min_htlc_mtokens: '2000',
|
|
338
|
+
public_key: 'b',
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
_policy_c_has_to_b: true,
|
|
342
|
+
base_fee_mtokens: '0',
|
|
343
|
+
fee_rate: 0,
|
|
344
|
+
inbound_base_discount_mtokens: '8000',
|
|
345
|
+
inbound_rate_discount: 200000,
|
|
346
|
+
is_disabled: false,
|
|
347
|
+
public_key: 'c',
|
|
348
|
+
},
|
|
349
|
+
],
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
capacity: 16777215,
|
|
353
|
+
destination: 'd',
|
|
354
|
+
id: '3x3x3',
|
|
355
|
+
policies: [
|
|
356
|
+
{
|
|
357
|
+
_policy_c_has_to_d: true,
|
|
358
|
+
base_fee_mtokens: '9000',
|
|
359
|
+
fee_rate: 100000,
|
|
360
|
+
is_disabled: false,
|
|
361
|
+
min_htlc_mtokens: '2000',
|
|
362
|
+
public_key: 'c',
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
_policy_d_has_to_c: true,
|
|
366
|
+
base_fee_mtokens: '0',
|
|
367
|
+
fee_rate: 0,
|
|
368
|
+
inbound_base_discount_mtokens: '-2000',
|
|
369
|
+
inbound_rate_discount: -80000,
|
|
370
|
+
is_disabled: false,
|
|
371
|
+
public_key: 'd',
|
|
372
|
+
},
|
|
373
|
+
],
|
|
374
|
+
},
|
|
375
|
+
],
|
|
376
|
+
},
|
|
377
|
+
description: 'Map channels with inbound fee rates',
|
|
378
|
+
expected: [
|
|
379
|
+
{
|
|
380
|
+
base_fee_mtokens: '0',
|
|
381
|
+
channel: '1x1x1',
|
|
382
|
+
channel_capacity: 16777215,
|
|
383
|
+
cltv_delta: 40,
|
|
384
|
+
fee_rate: 50000,
|
|
385
|
+
inbound_base_discount_mtokens: '-5000',
|
|
386
|
+
inbound_rate_discount: 0,
|
|
387
|
+
public_key: 'b',
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
base_fee_mtokens: '0',
|
|
391
|
+
channel: '2x2x2',
|
|
392
|
+
channel_capacity: 16777215,
|
|
393
|
+
cltv_delta: 40,
|
|
394
|
+
fee_rate: 50000,
|
|
395
|
+
inbound_base_discount_mtokens: '8000',
|
|
396
|
+
inbound_rate_discount: 200000,
|
|
397
|
+
public_key: 'c',
|
|
398
|
+
},
|
|
399
|
+
{
|
|
400
|
+
base_fee_mtokens: '9000',
|
|
401
|
+
channel: '3x3x3',
|
|
402
|
+
channel_capacity: 16777215,
|
|
403
|
+
cltv_delta: 40,
|
|
404
|
+
fee_rate: 100000,
|
|
405
|
+
inbound_base_discount_mtokens: '-2000',
|
|
406
|
+
inbound_rate_discount: -80000,
|
|
407
|
+
public_key: 'd',
|
|
408
|
+
},
|
|
409
|
+
],
|
|
410
|
+
},
|
|
276
411
|
];
|
|
277
412
|
|
|
278
413
|
tests.forEach(({args, description, error, expected}) => {
|
|
@@ -27,9 +27,35 @@ const tests = [
|
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
29
|
args: {mtokens: '1000000', policy: {base_fee_mtokens: '1', fee_rate: 1}},
|
|
30
|
-
description: 'Fee
|
|
30
|
+
description: 'Fee is calculated',
|
|
31
31
|
expected: {fee_mtokens: '2'},
|
|
32
32
|
},
|
|
33
|
+
{
|
|
34
|
+
args: {
|
|
35
|
+
mtokens: '1000000',
|
|
36
|
+
policy: {
|
|
37
|
+
base_fee_mtokens: '1',
|
|
38
|
+
fee_rate: 1,
|
|
39
|
+
inbound_base_discount_mtokens: '-1',
|
|
40
|
+
inbound_rate_discount: -1,
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
description: 'Fee rate with discount is calculated',
|
|
44
|
+
expected: {fee_mtokens: '0'},
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
args: {
|
|
48
|
+
mtokens: '1000000',
|
|
49
|
+
policy: {
|
|
50
|
+
base_fee_mtokens: '1',
|
|
51
|
+
fee_rate: 1,
|
|
52
|
+
inbound_base_discount_mtokens: '-10',
|
|
53
|
+
inbound_rate_discount: -1,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
description: 'Fee rate with big discount is calculated',
|
|
57
|
+
expected: {fee_mtokens: '0'},
|
|
58
|
+
},
|
|
33
59
|
];
|
|
34
60
|
|
|
35
61
|
tests.forEach(({args, description, error, expected}) => {
|