ln-service 53.17.5 → 53.20.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 +20 -0
- package/README.md +89 -4
- package/index.js +2 -0
- package/package.json +4 -5
- package/test/integration/test_add_peer.js +1 -1
- package/test/integration/test_delete_pending_channel.js +12 -0
- package/test/integration/test_get_chain_transactions.js +5 -1
- package/test/integration/test_get_closed_channels.js +6 -4
- package/test/integration/test_get_node.js +0 -2
- package/test/integration/test_get_pending_coop.js +50 -46
- package/test/integration/test_propose_channel.js +1 -1
- package/test/integration/test_remove_peer.js +11 -3
- package/test/integration/test_subscribe_to_channels.js +3 -1
- package/test/integration/test_trusted_funding.js +248 -0
- package/test/invoicesrpc-integration/test_get_sweep_transactions.js +11 -4
- package/test/routerrpc-integration/test_multipath_payment.js +52 -10
- package/test/routerrpc-integration/test_subscribe_to_forward_requests.js +15 -7
- package/test/signerrpc-integration/test_sign_bytes.js +17 -0
- package/test/signerrpc-integration/test_verify_bytes_signature.js +24 -0
- package/test/walletrpc-integration/test_sign_psbt.js +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Versions
|
|
2
2
|
|
|
3
|
+
## 53.20.0
|
|
4
|
+
|
|
5
|
+
- `closeChannel`: Add support for `max_tokens_per_vbyte` to set max fee rate
|
|
6
|
+
- `getChainTransactions`: Add `inputs` support for previous outpoints
|
|
7
|
+
- `subscribeToTransactions`: Add `inputs` support for previous outpoints
|
|
8
|
+
|
|
9
|
+
## 53.19.0
|
|
10
|
+
|
|
11
|
+
- `signBytes`: Add `type` and support for specifying `schnorr` type signing
|
|
12
|
+
- `verifyBytesSignature`: Add support for verifying Schnorr signatures
|
|
13
|
+
|
|
14
|
+
## 53.18.0
|
|
15
|
+
|
|
16
|
+
- `getChannels`: Add support for `is_trusted_funding` and `other_ids`
|
|
17
|
+
- `getClosedChannels`: Add support for `other_ids`
|
|
18
|
+
- `getEphemeralChannelIds`: Add method to get other channel ids
|
|
19
|
+
- `openChannels`: Add support for `is_trusted_funding` for instant opening
|
|
20
|
+
- `subscribeToChannels`: Add support for `is_trusted_funding`, `other_ids`
|
|
21
|
+
- `subscribeToOpenRequests`: Add support for `is_trusted_funding`
|
|
22
|
+
|
|
3
23
|
## 53.17.5
|
|
4
24
|
|
|
5
25
|
- `signTransaction`: Add `root_hash` to support Taproot signatures with scripts
|
package/README.md
CHANGED
|
@@ -13,7 +13,6 @@ Supported LND versions:
|
|
|
13
13
|
- v0.14.0-beta to v0.14.3-beta
|
|
14
14
|
- v0.13.0-beta to v0.13.4-beta
|
|
15
15
|
- v0.12.0-beta to v0.12.1-beta
|
|
16
|
-
- v0.11.0-beta to v0.11.1-beta
|
|
17
16
|
|
|
18
17
|
For typescript-ready methods, check out https://github.com/alexbosworth/lightning#readme
|
|
19
18
|
|
|
@@ -151,6 +150,7 @@ for `unlocker` methods.
|
|
|
151
150
|
- [getChannels](#getchannels) - Get all open channels
|
|
152
151
|
- [getClosedChannels](#getclosedchannels) - Get previously open channels
|
|
153
152
|
- [getConnectedWatchtowers](#getconnectedwatchtowers) - Get connected towers
|
|
153
|
+
- [getEphemeralChannelIds](#getephemeralchannelids) - Get other channel ids
|
|
154
154
|
- [getFailedPayments](#getfailedpayments) - Get payments that were failed back
|
|
155
155
|
- [getFeeRates](#getfeerates) - Get current routing fee rates
|
|
156
156
|
- [getForwardingConfidence](#getforwardingconfidence) - Get pairwise confidence
|
|
@@ -528,17 +528,23 @@ Either an id or a transaction id / transaction output index is required
|
|
|
528
528
|
|
|
529
529
|
If cooperatively closing, pass a public key and socket to connect
|
|
530
530
|
|
|
531
|
-
|
|
531
|
+
`max_tokens_per_vbyte` will be ignored when closing a peer initiated channel
|
|
532
|
+
|
|
533
|
+
Requires `info:read`, `offchain:write`, `onchain:write`, `peers:write`
|
|
534
|
+
permissions
|
|
535
|
+
|
|
536
|
+
`max_tokens_per_vbyte` is not supported in LND 0.15.0 and below
|
|
532
537
|
|
|
533
538
|
{
|
|
534
539
|
[address]: <Request Sending Local Channel Funds To Address String>
|
|
535
540
|
[id]: <Standard Format Channel Id String>
|
|
536
541
|
[is_force_close]: <Is Force Close Bool>
|
|
537
542
|
lnd: <Authenticated LND API Object>
|
|
543
|
+
[max_tokens_per_vbyte]: <Fail Cooperative Close Above Fee Rate Number>
|
|
538
544
|
[public_key]: <Peer Public Key String>
|
|
539
545
|
[socket]: <Peer Socket String>
|
|
540
546
|
[target_confirmations]: <Confirmation Target Number>
|
|
541
|
-
[tokens_per_vbyte]: <Tokens Per Virtual Byte Number>
|
|
547
|
+
[tokens_per_vbyte]: <Target Tokens Per Virtual Byte Number>
|
|
542
548
|
[transaction_id]: <Transaction Id Hex String>
|
|
543
549
|
[transaction_vout]: <Transaction Output Index Number>
|
|
544
550
|
}
|
|
@@ -1485,10 +1491,12 @@ Get chain transactions.
|
|
|
1485
1491
|
|
|
1486
1492
|
Requires `onchain:read` permission
|
|
1487
1493
|
|
|
1494
|
+
`inputs` are not supported on LND 0.15.0 and below
|
|
1495
|
+
|
|
1488
1496
|
{
|
|
1489
1497
|
[after]: <Confirmed After Current Best Chain Block Height Number>
|
|
1490
1498
|
[before]: <Confirmed Before Current Best Chain Block Height Number>
|
|
1491
|
-
lnd: <Authenticated LND Object>
|
|
1499
|
+
lnd: <Authenticated LND API Object>
|
|
1492
1500
|
}
|
|
1493
1501
|
|
|
1494
1502
|
@returns via cbk or Promise
|
|
@@ -1501,6 +1509,11 @@ Requires `onchain:read` permission
|
|
|
1501
1509
|
[description]: <Transaction Label String>
|
|
1502
1510
|
[fee]: <Fees Paid Tokens Number>
|
|
1503
1511
|
id: <Transaction Id String>
|
|
1512
|
+
inputs: [{
|
|
1513
|
+
is_local: <Spent Outpoint is Local Bool>
|
|
1514
|
+
transaction_id: <Transaction Id Hex String>
|
|
1515
|
+
transaction_vout: <Transaction Output Index Number>
|
|
1516
|
+
}]
|
|
1504
1517
|
is_confirmed: <Is Confirmed Bool>
|
|
1505
1518
|
is_outgoing: <Transaction Outbound Bool>
|
|
1506
1519
|
output_addresses: [<Address String>]
|
|
@@ -1602,6 +1615,8 @@ Requires `offchain:read` permission
|
|
|
1602
1615
|
`in_channel`, `in_payment`, `is_forward`, `out_channel`, `out_payment`,
|
|
1603
1616
|
`payment` are not supported on LND 0.11.1 and below
|
|
1604
1617
|
|
|
1618
|
+
`is_trusted_funding` is not supported on LND 0.15.0 and below
|
|
1619
|
+
|
|
1605
1620
|
{
|
|
1606
1621
|
[is_active]: <Limit Results To Only Active Channels Bool> // false
|
|
1607
1622
|
[is_offline]: <Limit Results To Only Offline Channels Bool> // false
|
|
@@ -1625,6 +1640,7 @@ Requires `offchain:read` permission
|
|
|
1625
1640
|
is_opening: <Channel Is Opening Bool>
|
|
1626
1641
|
is_partner_initiated: <Channel Partner Opened Channel Bool>
|
|
1627
1642
|
is_private: <Channel Is Private Bool>
|
|
1643
|
+
[is_trusted_funding]: <Funding Output is Trusted Bool>
|
|
1628
1644
|
local_balance: <Local Balance Tokens Number>
|
|
1629
1645
|
[local_csv]: <Local CSV Blocks Delay Number>
|
|
1630
1646
|
[local_dust]: <Local Non-Enforceable Amount Tokens Number>
|
|
@@ -1633,6 +1649,7 @@ Requires `offchain:read` permission
|
|
|
1633
1649
|
[local_max_pending_mtokens]: <Local Maximum Pending Millitokens String>
|
|
1634
1650
|
[local_min_htlc_mtokens]: <Local Minimum HTLC Millitokens String>
|
|
1635
1651
|
local_reserve: <Local Reserved Tokens Number>
|
|
1652
|
+
other_ids: [<Other Channel Id String>]
|
|
1636
1653
|
partner_public_key: <Channel Partner Public Key String>
|
|
1637
1654
|
past_states: <Total Count of Past Channel States Number>
|
|
1638
1655
|
pending_payments: [{
|
|
@@ -1682,6 +1699,8 @@ Multiple close type flags are supported.
|
|
|
1682
1699
|
|
|
1683
1700
|
Requires `offchain:read` permission
|
|
1684
1701
|
|
|
1702
|
+
`other_ids is not supported on LND 0.15.0 and below
|
|
1703
|
+
|
|
1685
1704
|
{
|
|
1686
1705
|
[is_breach_close]: <Only Return Breach Close Channels Bool>
|
|
1687
1706
|
[is_cooperative_close]: <Only Return Cooperative Close Channels Bool>
|
|
@@ -1719,6 +1738,7 @@ Requires `offchain:read` permission
|
|
|
1719
1738
|
[is_partner_closed]: <Channel Was Closed By Channel Peer Bool>
|
|
1720
1739
|
[is_partner_initiated]: <Channel Was Initiated By Channel Peer Bool>
|
|
1721
1740
|
is_remote_force_close: <Is Remote Force Close Bool>
|
|
1741
|
+
other_ids: [<Other Channel Id String>]
|
|
1722
1742
|
partner_public_key: <Partner Public Key Hex String>
|
|
1723
1743
|
transaction_id: <Channel Funding Transaction Id Hex String>
|
|
1724
1744
|
transaction_vout: <Channel Funding Output Index Number>
|
|
@@ -1776,6 +1796,35 @@ const {getConnectedWatchtowers} = require('ln-service');
|
|
|
1776
1796
|
const {towers} = (await getConnectedWatchtowers({lnd}));
|
|
1777
1797
|
```
|
|
1778
1798
|
|
|
1799
|
+
### getEphemeralChannelIds
|
|
1800
|
+
|
|
1801
|
+
Get ephemeral channel ids
|
|
1802
|
+
|
|
1803
|
+
Requires `offchain:read` permission
|
|
1804
|
+
|
|
1805
|
+
This method is not supported on LND 0.15.0 and below
|
|
1806
|
+
|
|
1807
|
+
{
|
|
1808
|
+
lnd: <Authenticated LND API Object>
|
|
1809
|
+
}
|
|
1810
|
+
|
|
1811
|
+
@returns via cbk or Promise
|
|
1812
|
+
{
|
|
1813
|
+
channels: [{
|
|
1814
|
+
other_ids: [<Channel Identifier String>]
|
|
1815
|
+
reference_id: <Top Level Channel Identifier String>
|
|
1816
|
+
}]
|
|
1817
|
+
}
|
|
1818
|
+
|
|
1819
|
+
Example:
|
|
1820
|
+
|
|
1821
|
+
```node
|
|
1822
|
+
const {getEphemeralChannelIds} = require('ln-service');
|
|
1823
|
+
|
|
1824
|
+
// Get the list of ephemeral ids related to channels
|
|
1825
|
+
const {channels} = await getEphemeralChannelIds({lnd});
|
|
1826
|
+
```
|
|
1827
|
+
|
|
1779
1828
|
### getFailedPayments
|
|
1780
1829
|
|
|
1781
1830
|
Get failed payments made through channels.
|
|
@@ -1860,6 +1909,15 @@ Requires `offchain:read` permission
|
|
|
1860
1909
|
[next]: <Next Opaque Paging Token String>
|
|
1861
1910
|
}
|
|
1862
1911
|
|
|
1912
|
+
Example:
|
|
1913
|
+
|
|
1914
|
+
```node
|
|
1915
|
+
const {getFailedPayments} = require('ln-service');
|
|
1916
|
+
|
|
1917
|
+
// Get the list of failed payments
|
|
1918
|
+
const {payments} = await getFailedPayments({lnd});
|
|
1919
|
+
```
|
|
1920
|
+
|
|
1863
1921
|
### getFeeRates
|
|
1864
1922
|
|
|
1865
1923
|
Get a rundown on fees for channels
|
|
@@ -3550,12 +3608,17 @@ channel that was not funded.
|
|
|
3550
3608
|
Use `is_avoiding_broadcast` only when self-publishing the raw transaction
|
|
3551
3609
|
after the funding step.
|
|
3552
3610
|
|
|
3611
|
+
`is_trusted_funding` is not supported on LND 0.15.0 and below and requires
|
|
3612
|
+
`--protocol.option-scid-alias` and `--protocol.zero-conf` set on both sides
|
|
3613
|
+
as well as a channel open request listener to accept the trusted funding.
|
|
3614
|
+
|
|
3553
3615
|
{
|
|
3554
3616
|
channels: [{
|
|
3555
3617
|
capacity: <Channel Capacity Tokens Number>
|
|
3556
3618
|
[cooperative_close_address]: <Restrict Coop Close To Address String>
|
|
3557
3619
|
[give_tokens]: <Tokens to Gift To Partner Number> // Defaults to zero
|
|
3558
3620
|
[is_private]: <Channel is Private Bool> // Defaults to false
|
|
3621
|
+
[is_trusted_funding]: <Peer Should Avoid Waiting For Confirmation Bool>
|
|
3559
3622
|
[min_htlc_mtokens]: <Minimum HTLC Millitokens String>
|
|
3560
3623
|
[partner_csv_delay]: <Peer Output CSV Delay Number>
|
|
3561
3624
|
partner_public_key: <Public Key Hex String>
|
|
@@ -4684,15 +4747,20 @@ await settleHodlInvoice({lnd, secret});
|
|
|
4684
4747
|
|
|
4685
4748
|
Sign a sha256 hash of arbitrary bytes
|
|
4686
4749
|
|
|
4750
|
+
Supported signature types: `ecdsa`, `schnorr`
|
|
4751
|
+
|
|
4687
4752
|
Requires LND built with `signrpc` build tag
|
|
4688
4753
|
|
|
4689
4754
|
Requires `signer:generate` permission
|
|
4690
4755
|
|
|
4756
|
+
`schnorr` signature type is not supported on LND 0.15.0 and below
|
|
4757
|
+
|
|
4691
4758
|
{
|
|
4692
4759
|
key_family: <Key Family Number>
|
|
4693
4760
|
key_index: <Key Index Number>
|
|
4694
4761
|
lnd: <Authenticated LND gRPC API Object>
|
|
4695
4762
|
preimage: <Bytes To Hash and Sign Hex Encoded String>
|
|
4763
|
+
[type]: <Signature Type String>
|
|
4696
4764
|
}
|
|
4697
4765
|
|
|
4698
4766
|
@returns via cbk or Promise
|
|
@@ -5002,6 +5070,8 @@ Subscribe to channel updates
|
|
|
5002
5070
|
|
|
5003
5071
|
Requires `offchain:read` permission
|
|
5004
5072
|
|
|
5073
|
+
`is_trusted_funding`, `other_ids` are not supported on LND 0.15.0 and below
|
|
5074
|
+
|
|
5005
5075
|
{
|
|
5006
5076
|
lnd: <Authenticated LND API Object>
|
|
5007
5077
|
}
|
|
@@ -5046,6 +5116,7 @@ Requires `offchain:read` permission
|
|
|
5046
5116
|
[is_partner_closed]: <Channel Was Closed By Channel Peer Bool>
|
|
5047
5117
|
[is_partner_initiated]: <Channel Was Initiated By Channel Peer Bool>
|
|
5048
5118
|
is_remote_force_close: <Is Remote Force Close Bool>
|
|
5119
|
+
other_ids: [<Other Channel Id String>]
|
|
5049
5120
|
partner_public_key: <Partner Public Key Hex String>
|
|
5050
5121
|
transaction_id: <Channel Funding Transaction Id Hex String>
|
|
5051
5122
|
transaction_vout: <Channel Funding Output Index Number>
|
|
@@ -5064,6 +5135,7 @@ Requires `offchain:read` permission
|
|
|
5064
5135
|
is_opening: <Channel Is Opening Bool>
|
|
5065
5136
|
is_partner_initiated: <Channel Partner Opened Channel Bool>
|
|
5066
5137
|
is_private: <Channel Is Private Bool>
|
|
5138
|
+
[is_trusted_funding]: <Funding Output is Trusted Bool>
|
|
5067
5139
|
local_balance: <Local Balance Tokens Number>
|
|
5068
5140
|
[local_given]: <Local Initially Pushed Tokens Number>
|
|
5069
5141
|
local_reserve: <Local Reserved Tokens Number>
|
|
@@ -5452,6 +5524,8 @@ listeners to `channel_request`
|
|
|
5452
5524
|
|
|
5453
5525
|
LND 0.11.1 and below do not support `accept` or `reject` arguments
|
|
5454
5526
|
|
|
5527
|
+
LND 0.15.0 and below do not support `is_trusted_funding`
|
|
5528
|
+
|
|
5455
5529
|
{
|
|
5456
5530
|
lnd: <Authenticated LND API Object>
|
|
5457
5531
|
}
|
|
@@ -6553,6 +6627,8 @@ Subscribe to transactions
|
|
|
6553
6627
|
|
|
6554
6628
|
Requires `onchain:read` permission
|
|
6555
6629
|
|
|
6630
|
+
`inputs` are not supported on LND 0.15.0 and below
|
|
6631
|
+
|
|
6556
6632
|
{
|
|
6557
6633
|
lnd: <Authenticated LND API Object>
|
|
6558
6634
|
}
|
|
@@ -6571,6 +6647,11 @@ Requires `onchain:read` permission
|
|
|
6571
6647
|
created_at: <Created ISO 8601 Date String>
|
|
6572
6648
|
[fee]: <Fees Paid Tokens Number>
|
|
6573
6649
|
id: <Transaction Id String>
|
|
6650
|
+
inputs: [{
|
|
6651
|
+
is_local: <Spent Outpoint is Local Bool>
|
|
6652
|
+
transaction_id: <Transaction Id Hex String>
|
|
6653
|
+
transaction_vout: <Transaction Output Index Number>
|
|
6654
|
+
}]
|
|
6574
6655
|
is_confirmed: <Is Confirmed Bool>
|
|
6575
6656
|
is_outgoing: <Transaction Outbound Bool>
|
|
6576
6657
|
output_addresses: [<Address String>]
|
|
@@ -7039,10 +7120,14 @@ const isValid = (await verifyBackups({backup, channels, lnd})).is_valid;
|
|
|
7039
7120
|
|
|
7040
7121
|
Verify signature of arbitrary bytes
|
|
7041
7122
|
|
|
7123
|
+
When passing a schnorr signature, a BIP-340 x-only public key should be given
|
|
7124
|
+
|
|
7042
7125
|
Requires LND built with `signrpc` build tag
|
|
7043
7126
|
|
|
7044
7127
|
Requires `signer:read` permission
|
|
7045
7128
|
|
|
7129
|
+
Validating `schnorr` signatures is unsupported in LND 0.15.0 and below
|
|
7130
|
+
|
|
7046
7131
|
{
|
|
7047
7132
|
lnd: <Authenticated LND API Object>
|
|
7048
7133
|
preimage: <Message Preimage Bytes Hex Encoded String>
|
package/index.js
CHANGED
|
@@ -42,6 +42,7 @@ const {getChannelBalance} = require('lightning');
|
|
|
42
42
|
const {getChannels} = require('lightning');
|
|
43
43
|
const {getClosedChannels} = require('lightning');
|
|
44
44
|
const {getConnectedWatchtowers} = require('lightning');
|
|
45
|
+
const {getEphemeralChannelIds} = require('lightning');
|
|
45
46
|
const {getFailedPayments} = require('lightning');
|
|
46
47
|
const {getFeeRates} = require('lightning');
|
|
47
48
|
const {getForwardingConfidence} = require('lightning');
|
|
@@ -191,6 +192,7 @@ module.exports = {
|
|
|
191
192
|
getChannels,
|
|
192
193
|
getClosedChannels,
|
|
193
194
|
getConnectedWatchtowers,
|
|
195
|
+
getEphemeralChannelIds,
|
|
194
196
|
getFailedPayments,
|
|
195
197
|
getFeeRates,
|
|
196
198
|
getForwardingConfidence,
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"cors": "2.8.5",
|
|
12
12
|
"express": "4.18.1",
|
|
13
13
|
"invoices": "2.1.0",
|
|
14
|
-
"lightning": "5.
|
|
14
|
+
"lightning": "5.19.0",
|
|
15
15
|
"macaroon": "3.0.4",
|
|
16
16
|
"morgan": "1.10.0",
|
|
17
17
|
"ws": "8.8.1"
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
"bn.js": "5.2.1",
|
|
29
29
|
"bs58check": "2.1.2",
|
|
30
30
|
"ecpair": "2.0.1",
|
|
31
|
-
"ln-docker-daemons": "2.3.
|
|
31
|
+
"ln-docker-daemons": "2.3.4",
|
|
32
32
|
"p2tr": "1.3.1",
|
|
33
|
-
"portfinder": "1.0.
|
|
33
|
+
"portfinder": "1.0.32",
|
|
34
34
|
"psbt": "2.7.1",
|
|
35
35
|
"rimraf": "3.0.2",
|
|
36
36
|
"secp256k1": "4.0.3",
|
|
@@ -56,7 +56,6 @@
|
|
|
56
56
|
"url": "https://github.com/alexbosworth/ln-service.git"
|
|
57
57
|
},
|
|
58
58
|
"scripts": {
|
|
59
|
-
"integration-test-daily-lnd-build": "DOCKER_LND_VERSION=daily-testing-only npm run test",
|
|
60
59
|
"integration-test-0.15.0": "DOCKER_LND_VERSION=v0.15.0-beta npm run test",
|
|
61
60
|
"integration-test-0.14.3": "DOCKER_LND_VERSION=v0.14.3-beta npm run test",
|
|
62
61
|
"integration-test-0.14.2": "DOCKER_LND_VERSION=v0.14.2-beta npm run test",
|
|
@@ -71,5 +70,5 @@
|
|
|
71
70
|
"integration-test-0.12.0": "DOCKER_LND_VERSION=v0.12.0-beta npm run test",
|
|
72
71
|
"test": "echo $DOCKER_LND_VERSION && tap -j 2 --branches=1 --functions=1 --lines=1 --statements=1 -t 200 test/autopilotrpc-integration/*.js test/chainrpc-integration/*.js test/integration/*.js test/invoicesrpc-integration/*.js test/peersrpc-integration/*.js test/routerrpc-integration/*.js test/signerrpc-integration/*.js test/tower_clientrpc-integration/*.js test/tower_serverrpc-integration/*.js test/walletrpc-integration/*.js"
|
|
73
72
|
},
|
|
74
|
-
"version": "53.
|
|
73
|
+
"version": "53.20.0"
|
|
75
74
|
}
|
|
@@ -18,6 +18,7 @@ const {fundPsbt} = require('./../../');
|
|
|
18
18
|
const {getChainBalance} = require('./../../');
|
|
19
19
|
const {getChannels} = require('./../../');
|
|
20
20
|
const {getLockedUtxos} = require('./../../');
|
|
21
|
+
const {getMasterPublicKeys} = require('./../../');
|
|
21
22
|
const {getPendingChannels} = require('./../../');
|
|
22
23
|
const {openChannels} = require('./../../');
|
|
23
24
|
const {signPsbt} = require('./../../');
|
|
@@ -41,6 +42,17 @@ test(`Forfeit pending channel`, async ({end, equal, strictSame}) => {
|
|
|
41
42
|
|
|
42
43
|
const {generate, lnd} = control;
|
|
43
44
|
|
|
45
|
+
try {
|
|
46
|
+
const {keys} = await getMasterPublicKeys({lnd});
|
|
47
|
+
} catch (err) {
|
|
48
|
+
// LND 0.13.3 and below should not be tested
|
|
49
|
+
strictSame(err, [501, 'GetMasterPublicKeysMethodNotSupported'], 'Got err');
|
|
50
|
+
|
|
51
|
+
await kill({});
|
|
52
|
+
|
|
53
|
+
return end();
|
|
54
|
+
}
|
|
55
|
+
|
|
44
56
|
try {
|
|
45
57
|
await control.generate({count});
|
|
46
58
|
|
|
@@ -20,12 +20,16 @@ test(`Get chain transactions`, async ({end, equal, strictSame}) => {
|
|
|
20
20
|
// Generate some funds for LND
|
|
21
21
|
await generate({count});
|
|
22
22
|
|
|
23
|
-
await asyncRetry({interval: 10, times:
|
|
23
|
+
await asyncRetry({interval: 10, times: 2000}, async () => {
|
|
24
24
|
const wallet = await getWalletInfo({lnd});
|
|
25
25
|
|
|
26
26
|
if (!wallet.is_synced_to_chain) {
|
|
27
27
|
throw new Error('ExpectedWalletSyncedToChain');
|
|
28
28
|
}
|
|
29
|
+
|
|
30
|
+
if (wallet.current_block_height !== count + 1) {
|
|
31
|
+
throw new Error('ExpectedFullySyncedToChain');
|
|
32
|
+
}
|
|
29
33
|
});
|
|
30
34
|
|
|
31
35
|
// Wait for generation to be over
|
|
@@ -72,11 +72,13 @@ test(`Get closed channels`, async ({end, equal}) => {
|
|
|
72
72
|
|
|
73
73
|
equal(channels.length, [channelOpen].length, 'Channel close listed');
|
|
74
74
|
|
|
75
|
+
const spend = maxChanTokens - channel.final_local_balance;
|
|
76
|
+
|
|
75
77
|
// LND 0.11.1 and below do not use anchors
|
|
76
78
|
if (isAnchors) {
|
|
77
|
-
equal(
|
|
79
|
+
equal([53345, 2810].includes(spend), true, 'Final');
|
|
78
80
|
} else {
|
|
79
|
-
equal(
|
|
81
|
+
equal(spend, 9050, 'Final');
|
|
80
82
|
}
|
|
81
83
|
|
|
82
84
|
equal(channel.capacity, maxChanTokens, 'Channel capacity reflected');
|
|
@@ -217,14 +219,14 @@ test(`Get closed channels`, async ({end, equal}) => {
|
|
|
217
219
|
equal(!!settleHtlc.transaction_id, true, 'Output tx id');
|
|
218
220
|
equal(settleHtlc.transaction_vout !== undefined, true, 'Output tx vout');
|
|
219
221
|
|
|
220
|
-
const alsoDead = await asyncRetry({interval:
|
|
222
|
+
const alsoDead = await asyncRetry({interval: 20, times: 7000}, async () => {
|
|
221
223
|
const {channels} = await getClosedChannels({lnd: target.lnd});
|
|
222
224
|
|
|
223
225
|
if (channels.length === [toForceClose, channelOpen].length) {
|
|
224
226
|
return channels;
|
|
225
227
|
}
|
|
226
228
|
|
|
227
|
-
await target.generate({
|
|
229
|
+
await target.generate({});
|
|
228
230
|
|
|
229
231
|
throw new Error('WaitingForTargetForceClose');
|
|
230
232
|
});
|
|
@@ -17,60 +17,64 @@ test(`Get pending channels`, async ({end, equal}) => {
|
|
|
17
17
|
|
|
18
18
|
const [{generate, lnd}, target] = nodes;
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
try {
|
|
21
|
+
const {features} = await getWalletInfo({lnd});
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
const isAnchors = !!features.find(n => n.bit === anchorsFeatureBit);
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
// Target starts a channel with control
|
|
26
|
+
const coopChan = await setupChannel({generate, give, lnd, to: target});
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
// Target closes the channel
|
|
29
|
+
const niceClose = await closeChannel({
|
|
30
|
+
lnd: target.lnd,
|
|
31
|
+
tokens_per_vbyte: 100,
|
|
32
|
+
transaction_id: coopChan.transaction_id,
|
|
33
|
+
transaction_vout: coopChan.transaction_vout,
|
|
34
|
+
});
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
// Control views their pending channels
|
|
37
|
+
const {channel} = await waitForPendingChannel({
|
|
38
|
+
lnd,
|
|
39
|
+
id: coopChan.transaction_id,
|
|
40
|
+
});
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
if (channel.is_partner_initiated !== undefined) {
|
|
43
|
+
equal(channel.is_partner_initiated, false, 'Channel was initiated');
|
|
44
|
+
}
|
|
44
45
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
46
|
+
// LND 0.11.1 and below do not support anchor channels
|
|
47
|
+
if (isAnchors) {
|
|
48
|
+
equal(channel.local_balance, 986530, 'Original balance');
|
|
49
|
+
equal(channel.pending_balance, 986530, 'Waiting on balance');
|
|
50
|
+
} else {
|
|
51
|
+
equal(channel.local_balance, 980950, 'Original balance');
|
|
52
|
+
equal(channel.pending_balance, 980950, 'Waiting on balance');
|
|
53
|
+
}
|
|
53
54
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
55
|
+
equal(channel.capacity, 1000000, 'Got channel capacity');
|
|
56
|
+
equal(channel.close_transaction_id, undefined, 'No close tx id');
|
|
57
|
+
equal(channel.is_active, false, 'Ended');
|
|
58
|
+
equal(channel.is_closing, true, 'Closing');
|
|
59
|
+
equal(channel.is_opening, false, 'Not Opening');
|
|
60
|
+
equal(channel.local_reserve, 10000, 'Local reserve');
|
|
61
|
+
equal(channel.partner_public_key, target.id, 'Target public key');
|
|
62
|
+
equal(channel.pending_payments, undefined, 'No pending payments');
|
|
63
|
+
equal(channel.received, 0, 'Never received');
|
|
64
|
+
equal(channel.recovered_tokens, undefined, 'Nothing to recover in sweep');
|
|
65
|
+
equal(channel.remote_reserve, 10000, 'Remote reserve');
|
|
66
|
+
equal(channel.sent, 0, 'Never sent anything');
|
|
67
|
+
equal(channel.timelock_expiration, undefined, 'No timelock in coop mode');
|
|
68
|
+
equal(channel.transaction_fee, null, 'No transaction fee data');
|
|
69
|
+
equal(channel.transaction_id, coopChan.transaction_id, 'funding tx id');
|
|
70
|
+
equal(channel.transaction_vout, coopChan.transaction_vout, 'funding vout');
|
|
71
|
+
equal(channel.transaction_weight, null, 'No funding tx weight data');
|
|
71
72
|
|
|
72
|
-
|
|
73
|
-
|
|
73
|
+
if (!!channel.remote_balance) {
|
|
74
|
+
equal(channel.remote_balance, give, 'Opposing channel balance');
|
|
75
|
+
}
|
|
76
|
+
} catch (err) {
|
|
77
|
+
equal(err, null, 'Expected no error');
|
|
74
78
|
}
|
|
75
79
|
|
|
76
80
|
await kill({});
|
|
@@ -6,7 +6,9 @@ const {addPeer} = require('./../../');
|
|
|
6
6
|
const {getPeers} = require('./../../');
|
|
7
7
|
const {removePeer} = require('./../../');
|
|
8
8
|
|
|
9
|
+
const interval = 10;
|
|
9
10
|
const size = 2;
|
|
11
|
+
const times = 2000;
|
|
10
12
|
|
|
11
13
|
// Removing peers should result in a removed peer
|
|
12
14
|
test(`Remove a peer`, async ({end, equal}) => {
|
|
@@ -15,7 +17,7 @@ test(`Remove a peer`, async ({end, equal}) => {
|
|
|
15
17
|
const [{id, lnd}, target] = nodes;
|
|
16
18
|
|
|
17
19
|
try {
|
|
18
|
-
await asyncRetry({interval
|
|
20
|
+
await asyncRetry({interval, times}, async () => {
|
|
19
21
|
await addPeer({lnd, public_key: target.id, socket: target.socket});
|
|
20
22
|
});
|
|
21
23
|
|
|
@@ -27,9 +29,15 @@ test(`Remove a peer`, async ({end, equal}) => {
|
|
|
27
29
|
|
|
28
30
|
await removePeer({lnd, public_key: targetPeer.public_key});
|
|
29
31
|
|
|
30
|
-
|
|
32
|
+
await asyncRetry({interval, times}, async () => {
|
|
33
|
+
const postRemovalPeers = await getPeers({lnd});
|
|
31
34
|
|
|
32
|
-
|
|
35
|
+
if (!!postRemovalPeers.peers.length) {
|
|
36
|
+
throw new Error('ExpectedPeerRemoved');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
equal(postRemovalPeers.peers.length, [].length, 'Peer is removed');
|
|
40
|
+
});
|
|
33
41
|
} catch (err) {
|
|
34
42
|
equal(err, null, 'Expected no error');
|
|
35
43
|
}
|
|
@@ -148,7 +148,9 @@ test('Subscribe to channels', async ({end, equal, fail}) => {
|
|
|
148
148
|
const closeEvent = channelClosed.pop();
|
|
149
149
|
|
|
150
150
|
if (isAnchors) {
|
|
151
|
-
|
|
151
|
+
const final = closeEvent.final_local_balance;
|
|
152
|
+
|
|
153
|
+
equal([897190, 846655].includes(final), true, 'Close final local balance');
|
|
152
154
|
} else {
|
|
153
155
|
equal(closeEvent.final_local_balance, 890950, 'Close final local balance');
|
|
154
156
|
}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
const asyncRetry = require('async/retry');
|
|
2
|
+
const {spawnLightningCluster} = require('ln-docker-daemons');
|
|
3
|
+
const {test} = require('@alexbosworth/tap');
|
|
4
|
+
|
|
5
|
+
const {addPeer} = require('./../../');
|
|
6
|
+
const {broadcastChainTransaction} = require('./../../');
|
|
7
|
+
const {closeChannel} = require('./../../');
|
|
8
|
+
const {createInvoice} = require('./../../');
|
|
9
|
+
const {fundPendingChannels} = require('./../../');
|
|
10
|
+
const {fundPsbt} = require('./../../');
|
|
11
|
+
const {getChannels} = require('./../../');
|
|
12
|
+
const {getClosedChannels} = require('./../../');
|
|
13
|
+
const {getEphemeralChannelIds} = require('./../../');
|
|
14
|
+
const {getPendingChannels} = require('./../../');
|
|
15
|
+
const {openChannels} = require('./../../');
|
|
16
|
+
const {pay} = require('./../../');
|
|
17
|
+
const {signPsbt} = require('./../../');
|
|
18
|
+
const {subscribeToChannels} = require('./../../');
|
|
19
|
+
const {subscribeToOpenRequests} = require('./../../');
|
|
20
|
+
|
|
21
|
+
const capacity = 1e6;
|
|
22
|
+
const interval = 10;
|
|
23
|
+
const maturity = 100;
|
|
24
|
+
const size = 2;
|
|
25
|
+
const times = 2000;
|
|
26
|
+
|
|
27
|
+
// Opening unconfirmed channels should in immediate channel opening
|
|
28
|
+
test(`Open unconfirmed channels`, async ({end, equal, match, strictSame}) => {
|
|
29
|
+
// Unconfirmed channels are not supported on LND 0.15.0 and below
|
|
30
|
+
{
|
|
31
|
+
const {kill, nodes} = await spawnLightningCluster({});
|
|
32
|
+
|
|
33
|
+
const [{lnd}] = nodes;
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
await getEphemeralChannelIds({lnd});
|
|
37
|
+
} catch (err) {
|
|
38
|
+
strictSame(err, [501, 'ListAliasesMethodNotSupported']);
|
|
39
|
+
|
|
40
|
+
await kill({});
|
|
41
|
+
|
|
42
|
+
return end();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const {kill, nodes} = await spawnLightningCluster({
|
|
47
|
+
size,
|
|
48
|
+
lnd_configuration: [
|
|
49
|
+
'--maxpendingchannels=10',
|
|
50
|
+
'--protocol.option-scid-alias',
|
|
51
|
+
'--protocol.zero-conf',
|
|
52
|
+
],
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const [{generate, lnd}, target] = nodes;
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
// Make some funds to use
|
|
59
|
+
await generate({count: maturity});
|
|
60
|
+
|
|
61
|
+
// Connect to the peer
|
|
62
|
+
await addPeer({lnd, public_key: target.id, socket: target.socket});
|
|
63
|
+
|
|
64
|
+
// Wait for channel to be receptive to opens
|
|
65
|
+
await asyncRetry({interval, times}, async () => {
|
|
66
|
+
return await openChannels({
|
|
67
|
+
lnd,
|
|
68
|
+
channels: [{capacity, partner_public_key: target.id}],
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const acceptSub = subscribeToOpenRequests({lnd: target.lnd});
|
|
73
|
+
const channelsSub = subscribeToChannels({lnd});
|
|
74
|
+
|
|
75
|
+
const closings = [];
|
|
76
|
+
const opened = [];
|
|
77
|
+
|
|
78
|
+
channelsSub.on('channel_closed', update => closings.push(update));
|
|
79
|
+
channelsSub.on('channel_opened', update => opened.push(update));
|
|
80
|
+
|
|
81
|
+
acceptSub.on('channel_request', request => {
|
|
82
|
+
equal(request.is_trusted_funding, true, 'Request is trusted funding');
|
|
83
|
+
|
|
84
|
+
return request.accept({is_trusted_funding: true});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Propose the channel to the peer
|
|
88
|
+
const {pending} = await openChannels({
|
|
89
|
+
lnd,
|
|
90
|
+
channels: [{
|
|
91
|
+
capacity,
|
|
92
|
+
is_trusted_funding: true,
|
|
93
|
+
partner_public_key: target.id,
|
|
94
|
+
}],
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Setup funding to the 2:2 output
|
|
98
|
+
const fundTarget = await fundPsbt({lnd, outputs: pending});
|
|
99
|
+
|
|
100
|
+
// Sign the funding to the 2:2 output
|
|
101
|
+
const {psbt, transaction} = await signPsbt({lnd, psbt: fundTarget.psbt});
|
|
102
|
+
|
|
103
|
+
// Fund the channel
|
|
104
|
+
await fundPendingChannels({
|
|
105
|
+
lnd,
|
|
106
|
+
channels: pending.map(({id}) => id),
|
|
107
|
+
funding: psbt,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const invoice = await createInvoice({
|
|
111
|
+
lnd: target.lnd,
|
|
112
|
+
tokens: 100,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const channel = await asyncRetry({interval, times}, async () => {
|
|
116
|
+
const {channels} = await getChannels({lnd, is_active: true});
|
|
117
|
+
|
|
118
|
+
if (!channels.length) {
|
|
119
|
+
throw new Error('ExpectedTrustedChannelToAppear');
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const [channel] = channels;
|
|
123
|
+
|
|
124
|
+
return channel;
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// Make sure the channel reflects that it is trusted funding
|
|
128
|
+
strictSame(channel.other_ids, [], 'Got no ephemeral ids');
|
|
129
|
+
match(channel.id, /16000000x0/, 'Channel id is faked');
|
|
130
|
+
equal(channel.is_trusted_funding, true, 'Channel funding is trusted');
|
|
131
|
+
|
|
132
|
+
// Make sure the open channel event reflected that it was trusted funding
|
|
133
|
+
const [event] = opened;
|
|
134
|
+
|
|
135
|
+
strictSame(event.other_ids, [], 'Got no event ephemeral ids');
|
|
136
|
+
match(event.id, /16000000x0/, 'Channel event id is faked');
|
|
137
|
+
equal(event.is_trusted_funding, true, 'Channel event funding is trusted');
|
|
138
|
+
|
|
139
|
+
// Make sure the channel can be used immediately
|
|
140
|
+
await pay({lnd, request: invoice.request});
|
|
141
|
+
|
|
142
|
+
// Generate the channel into a block
|
|
143
|
+
await broadcastChainTransaction({lnd, transaction});
|
|
144
|
+
|
|
145
|
+
const confirmed = await asyncRetry({interval, times}, async () => {
|
|
146
|
+
await generate({});
|
|
147
|
+
|
|
148
|
+
const [confirmed] = (await getChannels({lnd})).channels;
|
|
149
|
+
|
|
150
|
+
if (confirmed.id === channel.id) {
|
|
151
|
+
throw new Error('ExpectedChangeToRealChannelId');
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return confirmed;
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
equal(confirmed.id, '102x1x0', 'Channel id is real now');
|
|
158
|
+
equal(confirmed.is_trusted_funding, true, 'Channel funding was trusted');
|
|
159
|
+
equal(confirmed.other_ids.length, 1, 'Got ephemeral id');
|
|
160
|
+
|
|
161
|
+
const [otherId] = confirmed.other_ids;
|
|
162
|
+
|
|
163
|
+
match(otherId, /16000000x0/, 'Got ephemeral id');
|
|
164
|
+
|
|
165
|
+
await closeChannel({lnd, id: confirmed.id});
|
|
166
|
+
|
|
167
|
+
// Propose a private channel to the peer
|
|
168
|
+
const openPrivate = await asyncRetry({interval, times}, async () => {
|
|
169
|
+
return await openChannels({
|
|
170
|
+
lnd,
|
|
171
|
+
channels: [{
|
|
172
|
+
capacity,
|
|
173
|
+
is_private: true,
|
|
174
|
+
is_trusted_funding: true,
|
|
175
|
+
partner_public_key: target.id,
|
|
176
|
+
}],
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// Setup funding to the 2:2 output for the private channel
|
|
181
|
+
const fundPrivate = await fundPsbt({lnd, outputs: openPrivate.pending});
|
|
182
|
+
|
|
183
|
+
// Sign the private funding
|
|
184
|
+
const signedPrivate = await signPsbt({lnd, psbt: fundPrivate.psbt});
|
|
185
|
+
|
|
186
|
+
// Fund the private channel
|
|
187
|
+
await fundPendingChannels({
|
|
188
|
+
lnd,
|
|
189
|
+
channels: openPrivate.pending.map(({id}) => id),
|
|
190
|
+
funding: signedPrivate.psbt,
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// Generate the channel into a block
|
|
194
|
+
await broadcastChainTransaction({
|
|
195
|
+
lnd,
|
|
196
|
+
transaction: signedPrivate.transaction,
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
const privateConfirmed = await asyncRetry({interval, times}, async () => {
|
|
200
|
+
await generate({});
|
|
201
|
+
|
|
202
|
+
const [confirmed] = (await getChannels({lnd})).channels;
|
|
203
|
+
|
|
204
|
+
const shut = await getClosedChannels({lnd});
|
|
205
|
+
|
|
206
|
+
if (!shut.channels.length) {
|
|
207
|
+
throw new Error('ExpectedClosedChannel');
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (!confirmed.other_ids.length) {
|
|
211
|
+
throw new Error('ExpectedChangeToRealPrivateChannelId');
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return confirmed;
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
equal(privateConfirmed.other_ids.length, 1, 'Got private ephemeral ids');
|
|
218
|
+
|
|
219
|
+
const [privateOtherId] = privateConfirmed.other_ids;
|
|
220
|
+
|
|
221
|
+
match(privateOtherId, /16000000x0/, 'Got private id');
|
|
222
|
+
|
|
223
|
+
const [closedChannel] = (await getClosedChannels({lnd})).channels;
|
|
224
|
+
|
|
225
|
+
equal(closedChannel.id, confirmed.id, 'Closed channel shows confirmed id');
|
|
226
|
+
strictSame(closedChannel.other_ids, confirmed.other_ids, 'Saved temp id');
|
|
227
|
+
|
|
228
|
+
const [closeEvent] = closings;
|
|
229
|
+
|
|
230
|
+
equal(closeEvent.id, confirmed.id, 'Closed event shows confirmed id');
|
|
231
|
+
strictSame(closeEvent.other_ids, confirmed.other_ids, 'Got temporary id');
|
|
232
|
+
|
|
233
|
+
const ephemeralIds = await getEphemeralChannelIds({lnd});
|
|
234
|
+
|
|
235
|
+
equal(ephemeralIds.channels.length, 2, 'Got ephemeral channel ids');
|
|
236
|
+
|
|
237
|
+
const [firstChannel, secondChannel] = ephemeralIds.channels;
|
|
238
|
+
|
|
239
|
+
match(firstChannel.reference_id, /16000000x0/, 'Got first channel id');
|
|
240
|
+
match(secondChannel.reference_id, /16000000x0/, 'Got second channel id');
|
|
241
|
+
} catch (err) {
|
|
242
|
+
equal(err, null, 'No error is reported');
|
|
243
|
+
} finally {
|
|
244
|
+
return await kill({});
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return end();
|
|
248
|
+
});
|
|
@@ -26,9 +26,9 @@ const channelCapacityTokens = 1e6;
|
|
|
26
26
|
const confirmationCount = 6;
|
|
27
27
|
const defaultFee = 1e3;
|
|
28
28
|
const give = 1e5;
|
|
29
|
-
const interval =
|
|
29
|
+
const interval = 50;
|
|
30
30
|
const size = 2;
|
|
31
|
-
const times =
|
|
31
|
+
const times = 10000;
|
|
32
32
|
const tokens = 100;
|
|
33
33
|
|
|
34
34
|
// Force close a channel and get the resulting sweep transaction
|
|
@@ -76,8 +76,15 @@ test(`Get sweep transactions`, async ({end, equal}) => {
|
|
|
76
76
|
.map(n => n.tokens).sort();
|
|
77
77
|
|
|
78
78
|
equal(transactions.length, 2, 'Got closed channel sweep');
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
|
|
80
|
+
// LND 0.15.0 and before have different sweep tokens
|
|
81
|
+
if (sweepTokens === 890455) {
|
|
82
|
+
equal(anchorTokens, 149, 'Sweep has tokens amount');
|
|
83
|
+
equal(sweepTokens, 890455, 'Sweep has tokens amount');
|
|
84
|
+
} else {
|
|
85
|
+
equal(anchorTokens, 136, 'Sweep has tokens amount');
|
|
86
|
+
equal(sweepTokens, 889855, 'Sweep has tokens amount');
|
|
87
|
+
}
|
|
81
88
|
} else {
|
|
82
89
|
equal(transactions.length, [channel].length, 'Got closed channel sweep');
|
|
83
90
|
equal(transaction.spends.length, 1, 'Sweep has spends');
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
const asyncRetry = require('async/retry');
|
|
1
2
|
const {spawnLightningCluster} = require('ln-docker-daemons');
|
|
2
3
|
const {test} = require('@alexbosworth/tap');
|
|
3
4
|
|
|
4
5
|
const {createInvoice} = require('./../../');
|
|
6
|
+
const {getChannelBalance} = require('./../../');
|
|
7
|
+
const {getChannels} = require('./../../');
|
|
5
8
|
const {getInvoice} = require('./../../');
|
|
6
9
|
const {getRouteToDestination} = require('./../../');
|
|
7
10
|
const {parsePaymentRequest} = require('./../../');
|
|
@@ -13,8 +16,11 @@ const {waitForRoute} = require('./../macros');
|
|
|
13
16
|
const all = promise => Promise.all(promise);
|
|
14
17
|
const capacity = 1e6;
|
|
15
18
|
const {ceil} = Math;
|
|
19
|
+
const interval = 10;
|
|
20
|
+
const maturity = 100;
|
|
16
21
|
const {round} = Math;
|
|
17
22
|
const size = 2;
|
|
23
|
+
const times = 2000;
|
|
18
24
|
|
|
19
25
|
// Paying using multiple paths should execute the payment across paths
|
|
20
26
|
test(`Pay with multiple paths`, async ({end, equal, rejects, strictSame}) => {
|
|
@@ -22,22 +28,50 @@ test(`Pay with multiple paths`, async ({end, equal, rejects, strictSame}) => {
|
|
|
22
28
|
|
|
23
29
|
const [{generate, lnd}, target] = nodes;
|
|
24
30
|
|
|
25
|
-
await generate({count:
|
|
31
|
+
await generate({count: maturity});
|
|
26
32
|
|
|
27
33
|
const channel1 = await setupChannel({
|
|
28
34
|
capacity,
|
|
29
35
|
generate,
|
|
30
36
|
lnd,
|
|
37
|
+
hidden: true,
|
|
31
38
|
to: target,
|
|
32
39
|
});
|
|
33
40
|
|
|
41
|
+
await asyncRetry({interval, times}, async () => {
|
|
42
|
+
const {channels} = await getChannels({lnd});
|
|
43
|
+
|
|
44
|
+
await generate({});
|
|
45
|
+
|
|
46
|
+
if (!channels.length) {
|
|
47
|
+
throw new Error('ExpectedChannelCreated');
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
34
51
|
const channel2 = await setupChannel({
|
|
35
52
|
capacity,
|
|
36
53
|
generate,
|
|
37
54
|
lnd,
|
|
55
|
+
hidden: true,
|
|
38
56
|
to: target,
|
|
39
57
|
});
|
|
40
58
|
|
|
59
|
+
await asyncRetry({interval, times}, async () => {
|
|
60
|
+
const {channels} = await getChannels({lnd, is_active: true});
|
|
61
|
+
|
|
62
|
+
await generate({});
|
|
63
|
+
|
|
64
|
+
if (channels.length < size) {
|
|
65
|
+
throw new Error('ExpectedSecondChannelCreated');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const balance = await getChannelBalance({lnd});
|
|
69
|
+
|
|
70
|
+
if (balance.channel_balance < capacity) {
|
|
71
|
+
throw new Error('ExpectedChannelBalancePresent');
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
41
75
|
const channels = [channel1, channel2];
|
|
42
76
|
|
|
43
77
|
const payParts = [
|
|
@@ -50,15 +84,23 @@ test(`Pay with multiple paths`, async ({end, equal, rejects, strictSame}) => {
|
|
|
50
84
|
const {request} = await createInvoice({tokens, lnd: target.lnd});
|
|
51
85
|
|
|
52
86
|
// Payment should fail with only 1 path
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
err
|
|
58
|
-
|
|
59
|
-
'
|
|
60
|
-
|
|
61
|
-
|
|
87
|
+
await asyncRetry({interval, times}, async () => {
|
|
88
|
+
try {
|
|
89
|
+
await payViaPaymentRequest({lnd, request, max_paths: [channel1].length});
|
|
90
|
+
} catch (err) {
|
|
91
|
+
const [, message] = err;
|
|
92
|
+
|
|
93
|
+
if (message !== 'PaymentPathfindingFailedToFindPossibleRoute') {
|
|
94
|
+
throw err;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
strictSame(
|
|
98
|
+
err,
|
|
99
|
+
[503, 'PaymentPathfindingFailedToFindPossibleRoute'],
|
|
100
|
+
'No path'
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
62
104
|
|
|
63
105
|
// Payment should succeed with 2 paths
|
|
64
106
|
try {
|
|
@@ -75,10 +75,15 @@ test(`Subscribe to requests`, async ({end, equal, rejects, strictSame}) => {
|
|
|
75
75
|
|
|
76
76
|
await once(pay, 'failed');
|
|
77
77
|
|
|
78
|
+
equal(failures.length, 1, 'Got a failure');
|
|
79
|
+
|
|
80
|
+
const [failed] = failures;
|
|
81
|
+
|
|
82
|
+
delete failed.channel;
|
|
83
|
+
|
|
78
84
|
strictSame(
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
channel: channel.id,
|
|
85
|
+
failed,
|
|
86
|
+
{
|
|
82
87
|
index: 1,
|
|
83
88
|
mtokens: '101000',
|
|
84
89
|
public_key: target.id,
|
|
@@ -114,7 +119,7 @@ test(`Subscribe to requests`, async ({end, equal, rejects, strictSame}) => {
|
|
|
114
119
|
tokens: 101,
|
|
115
120
|
total_mtokens: '100000',
|
|
116
121
|
},
|
|
117
|
-
}
|
|
122
|
+
},
|
|
118
123
|
'Failure is emitted'
|
|
119
124
|
);
|
|
120
125
|
|
|
@@ -135,10 +140,13 @@ test(`Subscribe to requests`, async ({end, equal, rejects, strictSame}) => {
|
|
|
135
140
|
equal(!!pending.created_at, true, 'Has creation date');
|
|
136
141
|
equal(pending.id, invoice.id, 'Payment id is present');
|
|
137
142
|
equal(pending.mtokens, invoice.mtokens, 'Pending payment mtokens');
|
|
143
|
+
equal(pending.paths.length, 1, 'Path is present');
|
|
144
|
+
|
|
145
|
+
const [path] = pending.paths;
|
|
138
146
|
|
|
139
147
|
strictSame(
|
|
140
|
-
|
|
141
|
-
|
|
148
|
+
path,
|
|
149
|
+
{
|
|
142
150
|
fee: 1,
|
|
143
151
|
fee_mtokens: '1000',
|
|
144
152
|
hops: [
|
|
@@ -168,7 +176,7 @@ test(`Subscribe to requests`, async ({end, equal, rejects, strictSame}) => {
|
|
|
168
176
|
timeout: height + 40 + 43,
|
|
169
177
|
tokens: 101,
|
|
170
178
|
total_mtokens: '100000',
|
|
171
|
-
}
|
|
179
|
+
},
|
|
172
180
|
'Paths are present'
|
|
173
181
|
);
|
|
174
182
|
|
|
@@ -51,6 +51,23 @@ test(`Sign bytes`, async ({end, equal}) => {
|
|
|
51
51
|
equal(message, 'ExpectedSignerRpcLndBuildTagToSignBytes', 'Invalid LND');
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
try {
|
|
55
|
+
const schnorr = await signBytes({
|
|
56
|
+
lnd,
|
|
57
|
+
key_family: 6,
|
|
58
|
+
key_index: 0,
|
|
59
|
+
preimage: Buffer.alloc(32).toString('hex'),
|
|
60
|
+
type: 'schnorr',
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
equal(schnorr.signature.length, 64 * 2, 'Got schnorr signature for bytes');
|
|
64
|
+
} catch (err) {
|
|
65
|
+
const [code, message] = Array.isArray(err) ? err : [];
|
|
66
|
+
|
|
67
|
+
equal(code, 503, 'A 503 code is thrown if schnorr is unsupported');
|
|
68
|
+
equal(message, 'UnexpectedSignatureLengthInSignBytesResponse', 'Sig len');
|
|
69
|
+
}
|
|
70
|
+
|
|
54
71
|
await kill({});
|
|
55
72
|
|
|
56
73
|
return end();
|
|
@@ -72,6 +72,30 @@ test(`Verify bytes signature`, async ({end, equal}) => {
|
|
|
72
72
|
equal(message, 'ExpectedSignerRpcLndBuildTagToSignBytes', 'Invalid LND');
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
try {
|
|
76
|
+
const schnorr = await signBytes({
|
|
77
|
+
lnd,
|
|
78
|
+
key_family: 6,
|
|
79
|
+
key_index: 0,
|
|
80
|
+
preimage: Buffer.alloc(32).toString('hex'),
|
|
81
|
+
type: 'schnorr',
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const validity = await verifyBytesSignature({
|
|
85
|
+
lnd,
|
|
86
|
+
preimage: Buffer.alloc(32).toString('hex'),
|
|
87
|
+
public_key: id.slice(2),
|
|
88
|
+
signature: schnorr.signature,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
equal(validity.is_valid, true, 'Schnorr signature is valid');
|
|
92
|
+
} catch (err) {
|
|
93
|
+
const [code, message] = Array.isArray(err) ? err : [];
|
|
94
|
+
|
|
95
|
+
equal(code, 503, 'A 503 code is thrown if schnorr is unsupported');
|
|
96
|
+
equal(message, 'UnexpectedSignatureLengthInSignBytesResponse', 'Sig len');
|
|
97
|
+
}
|
|
98
|
+
|
|
75
99
|
await kill({});
|
|
76
100
|
|
|
77
101
|
return end();
|
|
@@ -10,7 +10,6 @@ const {broadcastChainTransaction} = require('./../../');
|
|
|
10
10
|
const {createChainAddress} = require('./../../');
|
|
11
11
|
const {fundPsbt} = require('./../../');
|
|
12
12
|
const {getChainBalance} = require('./../../');
|
|
13
|
-
const {getChainTransactions} = require('./../../');
|
|
14
13
|
const {getUtxos} = require('./../../');
|
|
15
14
|
const {sendToChainAddress} = require('./../../');
|
|
16
15
|
const {signPsbt} = require('./../../');
|