ln-service 53.17.4 → 53.19.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 +15 -1
- package/README.md +67 -1
- package/index.js +2 -0
- package/package.json +8 -8
- package/test/integration/test_get_closed_channels.js +4 -2
- 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 +244 -0
- package/test/invoicesrpc-integration/test_get_sweep_transactions.js +11 -4
- package/test/signerrpc-integration/test_sign_bytes.js +17 -0
- package/test/signerrpc-integration/test_verify_bytes_signature.js +24 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
# Versions
|
|
2
2
|
|
|
3
|
-
## 53.
|
|
3
|
+
## 53.19.0
|
|
4
|
+
|
|
5
|
+
- `signBytes`: Add `type` and support for specifying `schnorr` type signing
|
|
6
|
+
- `verifyBytesSignature`: Add support for verifying Schnorr signatures
|
|
7
|
+
|
|
8
|
+
## 53.18.0
|
|
9
|
+
|
|
10
|
+
- `getChannels`: Add support for `is_trusted_funding` and `other_ids`
|
|
11
|
+
- `getClosedChannels`: Add support for `other_ids`
|
|
12
|
+
- `getEphemeralChannelIds`: Add method to get other channel ids
|
|
13
|
+
- `openChannels`: Add support for `is_trusted_funding` for instant opening
|
|
14
|
+
- `subscribeToChannels`: Add support for `is_trusted_funding`, `other_ids`
|
|
15
|
+
- `subscribeToOpenRequests`: Add support for `is_trusted_funding`
|
|
16
|
+
|
|
17
|
+
## 53.17.5
|
|
4
18
|
|
|
5
19
|
- `signTransaction`: Add `root_hash` to support Taproot signatures with scripts
|
|
6
20
|
|
package/README.md
CHANGED
|
@@ -151,6 +151,7 @@ for `unlocker` methods.
|
|
|
151
151
|
- [getChannels](#getchannels) - Get all open channels
|
|
152
152
|
- [getClosedChannels](#getclosedchannels) - Get previously open channels
|
|
153
153
|
- [getConnectedWatchtowers](#getconnectedwatchtowers) - Get connected towers
|
|
154
|
+
- [getEphemeralChannelIds](#getephemeralchannelids) - Get other channel ids
|
|
154
155
|
- [getFailedPayments](#getfailedpayments) - Get payments that were failed back
|
|
155
156
|
- [getFeeRates](#getfeerates) - Get current routing fee rates
|
|
156
157
|
- [getForwardingConfidence](#getforwardingconfidence) - Get pairwise confidence
|
|
@@ -1602,6 +1603,8 @@ Requires `offchain:read` permission
|
|
|
1602
1603
|
`in_channel`, `in_payment`, `is_forward`, `out_channel`, `out_payment`,
|
|
1603
1604
|
`payment` are not supported on LND 0.11.1 and below
|
|
1604
1605
|
|
|
1606
|
+
`is_trusted_funding` is not supported on LND 0.15.0 and below
|
|
1607
|
+
|
|
1605
1608
|
{
|
|
1606
1609
|
[is_active]: <Limit Results To Only Active Channels Bool> // false
|
|
1607
1610
|
[is_offline]: <Limit Results To Only Offline Channels Bool> // false
|
|
@@ -1625,14 +1628,16 @@ Requires `offchain:read` permission
|
|
|
1625
1628
|
is_opening: <Channel Is Opening Bool>
|
|
1626
1629
|
is_partner_initiated: <Channel Partner Opened Channel Bool>
|
|
1627
1630
|
is_private: <Channel Is Private Bool>
|
|
1631
|
+
[is_trusted_funding]: <Funding Output is Trusted Bool>
|
|
1628
1632
|
local_balance: <Local Balance Tokens Number>
|
|
1629
1633
|
[local_csv]: <Local CSV Blocks Delay Number>
|
|
1630
|
-
[local_dust]: <
|
|
1634
|
+
[local_dust]: <Local Non-Enforceable Amount Tokens Number>
|
|
1631
1635
|
[local_given]: <Local Initially Pushed Tokens Number>
|
|
1632
1636
|
[local_max_htlcs]: <Local Maximum Attached HTLCs Number>
|
|
1633
1637
|
[local_max_pending_mtokens]: <Local Maximum Pending Millitokens String>
|
|
1634
1638
|
[local_min_htlc_mtokens]: <Local Minimum HTLC Millitokens String>
|
|
1635
1639
|
local_reserve: <Local Reserved Tokens Number>
|
|
1640
|
+
other_ids: [<Other Channel Id String>]
|
|
1636
1641
|
partner_public_key: <Channel Partner Public Key String>
|
|
1637
1642
|
past_states: <Total Count of Past Channel States Number>
|
|
1638
1643
|
pending_payments: [{
|
|
@@ -1682,6 +1687,8 @@ Multiple close type flags are supported.
|
|
|
1682
1687
|
|
|
1683
1688
|
Requires `offchain:read` permission
|
|
1684
1689
|
|
|
1690
|
+
`other_ids is not supported on LND 0.15.0 and below
|
|
1691
|
+
|
|
1685
1692
|
{
|
|
1686
1693
|
[is_breach_close]: <Only Return Breach Close Channels Bool>
|
|
1687
1694
|
[is_cooperative_close]: <Only Return Cooperative Close Channels Bool>
|
|
@@ -1719,6 +1726,7 @@ Requires `offchain:read` permission
|
|
|
1719
1726
|
[is_partner_closed]: <Channel Was Closed By Channel Peer Bool>
|
|
1720
1727
|
[is_partner_initiated]: <Channel Was Initiated By Channel Peer Bool>
|
|
1721
1728
|
is_remote_force_close: <Is Remote Force Close Bool>
|
|
1729
|
+
other_ids: [<Other Channel Id String>]
|
|
1722
1730
|
partner_public_key: <Partner Public Key Hex String>
|
|
1723
1731
|
transaction_id: <Channel Funding Transaction Id Hex String>
|
|
1724
1732
|
transaction_vout: <Channel Funding Output Index Number>
|
|
@@ -1776,6 +1784,35 @@ const {getConnectedWatchtowers} = require('ln-service');
|
|
|
1776
1784
|
const {towers} = (await getConnectedWatchtowers({lnd}));
|
|
1777
1785
|
```
|
|
1778
1786
|
|
|
1787
|
+
### getEphemeralChannelIds
|
|
1788
|
+
|
|
1789
|
+
Get ephemeral channel ids
|
|
1790
|
+
|
|
1791
|
+
Requires `offchain:read` permission
|
|
1792
|
+
|
|
1793
|
+
This method is not supported on LND 0.15.0 and below
|
|
1794
|
+
|
|
1795
|
+
{
|
|
1796
|
+
lnd: <Authenticated LND API Object>
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
@returns via cbk or Promise
|
|
1800
|
+
{
|
|
1801
|
+
channels: [{
|
|
1802
|
+
other_ids: [<Channel Identifier String>]
|
|
1803
|
+
reference_id: <Top Level Channel Identifier String>
|
|
1804
|
+
}]
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1807
|
+
Example:
|
|
1808
|
+
|
|
1809
|
+
```node
|
|
1810
|
+
const {getEphemeralChannelIds} = require('ln-service');
|
|
1811
|
+
|
|
1812
|
+
// Get the list of ephemeral ids related to channels
|
|
1813
|
+
const {channels} = await getEphemeralChannelIds({lnd});
|
|
1814
|
+
```
|
|
1815
|
+
|
|
1779
1816
|
### getFailedPayments
|
|
1780
1817
|
|
|
1781
1818
|
Get failed payments made through channels.
|
|
@@ -1860,6 +1897,15 @@ Requires `offchain:read` permission
|
|
|
1860
1897
|
[next]: <Next Opaque Paging Token String>
|
|
1861
1898
|
}
|
|
1862
1899
|
|
|
1900
|
+
Example:
|
|
1901
|
+
|
|
1902
|
+
```node
|
|
1903
|
+
const {getFailedPayments} = require('ln-service');
|
|
1904
|
+
|
|
1905
|
+
// Get the list of failed payments
|
|
1906
|
+
const {payments} = await getFailedPayments({lnd});
|
|
1907
|
+
```
|
|
1908
|
+
|
|
1863
1909
|
### getFeeRates
|
|
1864
1910
|
|
|
1865
1911
|
Get a rundown on fees for channels
|
|
@@ -3550,12 +3596,17 @@ channel that was not funded.
|
|
|
3550
3596
|
Use `is_avoiding_broadcast` only when self-publishing the raw transaction
|
|
3551
3597
|
after the funding step.
|
|
3552
3598
|
|
|
3599
|
+
`is_trusted_funding` is not supported on LND 0.15.0 and below and requires
|
|
3600
|
+
`--protocol.option-scid-alias` and `--protocol.zero-conf` set on both sides
|
|
3601
|
+
as well as a channel open request listener to accept the trusted funding.
|
|
3602
|
+
|
|
3553
3603
|
{
|
|
3554
3604
|
channels: [{
|
|
3555
3605
|
capacity: <Channel Capacity Tokens Number>
|
|
3556
3606
|
[cooperative_close_address]: <Restrict Coop Close To Address String>
|
|
3557
3607
|
[give_tokens]: <Tokens to Gift To Partner Number> // Defaults to zero
|
|
3558
3608
|
[is_private]: <Channel is Private Bool> // Defaults to false
|
|
3609
|
+
[is_trusted_funding]: <Peer Should Avoid Waiting For Confirmation Bool>
|
|
3559
3610
|
[min_htlc_mtokens]: <Minimum HTLC Millitokens String>
|
|
3560
3611
|
[partner_csv_delay]: <Peer Output CSV Delay Number>
|
|
3561
3612
|
partner_public_key: <Public Key Hex String>
|
|
@@ -4684,15 +4735,20 @@ await settleHodlInvoice({lnd, secret});
|
|
|
4684
4735
|
|
|
4685
4736
|
Sign a sha256 hash of arbitrary bytes
|
|
4686
4737
|
|
|
4738
|
+
Supported signature types: `ecdsa`, `schnorr`
|
|
4739
|
+
|
|
4687
4740
|
Requires LND built with `signrpc` build tag
|
|
4688
4741
|
|
|
4689
4742
|
Requires `signer:generate` permission
|
|
4690
4743
|
|
|
4744
|
+
`schnorr` signature type is not supported on LND 0.15.0 and below
|
|
4745
|
+
|
|
4691
4746
|
{
|
|
4692
4747
|
key_family: <Key Family Number>
|
|
4693
4748
|
key_index: <Key Index Number>
|
|
4694
4749
|
lnd: <Authenticated LND gRPC API Object>
|
|
4695
4750
|
preimage: <Bytes To Hash and Sign Hex Encoded String>
|
|
4751
|
+
[type]: <Signature Type String>
|
|
4696
4752
|
}
|
|
4697
4753
|
|
|
4698
4754
|
@returns via cbk or Promise
|
|
@@ -5002,6 +5058,8 @@ Subscribe to channel updates
|
|
|
5002
5058
|
|
|
5003
5059
|
Requires `offchain:read` permission
|
|
5004
5060
|
|
|
5061
|
+
`is_trusted_funding`, `other_ids` are not supported on LND 0.15.0 and below
|
|
5062
|
+
|
|
5005
5063
|
{
|
|
5006
5064
|
lnd: <Authenticated LND API Object>
|
|
5007
5065
|
}
|
|
@@ -5046,6 +5104,7 @@ Requires `offchain:read` permission
|
|
|
5046
5104
|
[is_partner_closed]: <Channel Was Closed By Channel Peer Bool>
|
|
5047
5105
|
[is_partner_initiated]: <Channel Was Initiated By Channel Peer Bool>
|
|
5048
5106
|
is_remote_force_close: <Is Remote Force Close Bool>
|
|
5107
|
+
other_ids: [<Other Channel Id String>]
|
|
5049
5108
|
partner_public_key: <Partner Public Key Hex String>
|
|
5050
5109
|
transaction_id: <Channel Funding Transaction Id Hex String>
|
|
5051
5110
|
transaction_vout: <Channel Funding Output Index Number>
|
|
@@ -5064,6 +5123,7 @@ Requires `offchain:read` permission
|
|
|
5064
5123
|
is_opening: <Channel Is Opening Bool>
|
|
5065
5124
|
is_partner_initiated: <Channel Partner Opened Channel Bool>
|
|
5066
5125
|
is_private: <Channel Is Private Bool>
|
|
5126
|
+
[is_trusted_funding]: <Funding Output is Trusted Bool>
|
|
5067
5127
|
local_balance: <Local Balance Tokens Number>
|
|
5068
5128
|
[local_given]: <Local Initially Pushed Tokens Number>
|
|
5069
5129
|
local_reserve: <Local Reserved Tokens Number>
|
|
@@ -5452,6 +5512,8 @@ listeners to `channel_request`
|
|
|
5452
5512
|
|
|
5453
5513
|
LND 0.11.1 and below do not support `accept` or `reject` arguments
|
|
5454
5514
|
|
|
5515
|
+
LND 0.15.0 and below do not support `is_trusted_funding`
|
|
5516
|
+
|
|
5455
5517
|
{
|
|
5456
5518
|
lnd: <Authenticated LND API Object>
|
|
5457
5519
|
}
|
|
@@ -7039,10 +7101,14 @@ const isValid = (await verifyBackups({backup, channels, lnd})).is_valid;
|
|
|
7039
7101
|
|
|
7040
7102
|
Verify signature of arbitrary bytes
|
|
7041
7103
|
|
|
7104
|
+
When passing a schnorr signature, a BIP-340 x-only public key should be given
|
|
7105
|
+
|
|
7042
7106
|
Requires LND built with `signrpc` build tag
|
|
7043
7107
|
|
|
7044
7108
|
Requires `signer:read` permission
|
|
7045
7109
|
|
|
7110
|
+
Validating `schnorr` signatures is unsupported in LND 0.15.0 and below
|
|
7111
|
+
|
|
7046
7112
|
{
|
|
7047
7113
|
lnd: <Authenticated LND API Object>
|
|
7048
7114
|
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
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
"bolt07": "1.8.2",
|
|
11
11
|
"cors": "2.8.5",
|
|
12
12
|
"express": "4.18.1",
|
|
13
|
-
"invoices": "2.0
|
|
14
|
-
"lightning": "5.
|
|
13
|
+
"invoices": "2.1.0",
|
|
14
|
+
"lightning": "5.18.0",
|
|
15
15
|
"macaroon": "3.0.4",
|
|
16
16
|
"morgan": "1.10.0",
|
|
17
|
-
"ws": "8.8.
|
|
17
|
+
"ws": "8.8.1"
|
|
18
18
|
},
|
|
19
19
|
"description": "Interaction helper for your Lightning Network daemon",
|
|
20
20
|
"devDependencies": {
|
|
@@ -24,14 +24,14 @@
|
|
|
24
24
|
"asyncjs-util": "1.2.10",
|
|
25
25
|
"bip32": "3.0.1",
|
|
26
26
|
"bip66": "1.1.5",
|
|
27
|
-
"bitcoinjs-lib": "6.0.
|
|
27
|
+
"bitcoinjs-lib": "6.0.2",
|
|
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.3",
|
|
32
32
|
"p2tr": "1.3.1",
|
|
33
|
-
"portfinder": "1.0.
|
|
34
|
-
"psbt": "2.
|
|
33
|
+
"portfinder": "1.0.32",
|
|
34
|
+
"psbt": "2.7.1",
|
|
35
35
|
"rimraf": "3.0.2",
|
|
36
36
|
"secp256k1": "4.0.3",
|
|
37
37
|
"tiny-secp256k1": "2.2.1",
|
|
@@ -71,5 +71,5 @@
|
|
|
71
71
|
"integration-test-0.12.0": "DOCKER_LND_VERSION=v0.12.0-beta npm run test",
|
|
72
72
|
"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
73
|
},
|
|
74
|
-
"version": "53.
|
|
74
|
+
"version": "53.19.0"
|
|
75
75
|
}
|
|
@@ -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');
|
|
@@ -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,244 @@
|
|
|
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, 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
|
+
equal(channel.id, '16000000x0x0', '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 ephemeral ids');
|
|
136
|
+
equal(event.id, '16000000x0x0', 'Channel id is faked');
|
|
137
|
+
equal(event.is_trusted_funding, true, 'Channel 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
|
+
strictSame(confirmed.other_ids, ['16000000x0x0'], 'Got ephemeral ids');
|
|
160
|
+
|
|
161
|
+
await closeChannel({lnd, id: confirmed.id});
|
|
162
|
+
|
|
163
|
+
// Propose a private channel to the peer
|
|
164
|
+
const openPrivate = await asyncRetry({interval, times}, async () => {
|
|
165
|
+
return await openChannels({
|
|
166
|
+
lnd,
|
|
167
|
+
channels: [{
|
|
168
|
+
capacity,
|
|
169
|
+
is_private: true,
|
|
170
|
+
is_trusted_funding: true,
|
|
171
|
+
partner_public_key: target.id,
|
|
172
|
+
}],
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// Setup funding to the 2:2 output for the private channel
|
|
177
|
+
const fundPrivate = await fundPsbt({lnd, outputs: openPrivate.pending});
|
|
178
|
+
|
|
179
|
+
// Sign the private funding
|
|
180
|
+
const signedPrivate = await signPsbt({lnd, psbt: fundPrivate.psbt});
|
|
181
|
+
|
|
182
|
+
// Fund the private channel
|
|
183
|
+
await fundPendingChannels({
|
|
184
|
+
lnd,
|
|
185
|
+
channels: openPrivate.pending.map(({id}) => id),
|
|
186
|
+
funding: signedPrivate.psbt,
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// Generate the channel into a block
|
|
190
|
+
await broadcastChainTransaction({
|
|
191
|
+
lnd,
|
|
192
|
+
transaction: signedPrivate.transaction,
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
const privateConfirmed = await asyncRetry({interval, times}, async () => {
|
|
196
|
+
await generate({});
|
|
197
|
+
|
|
198
|
+
const [confirmed] = (await getChannels({lnd})).channels;
|
|
199
|
+
|
|
200
|
+
const shut = await getClosedChannels({lnd});
|
|
201
|
+
|
|
202
|
+
if (!shut.channels.length) {
|
|
203
|
+
throw new Error('ExpectedClosedChannel');
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (!confirmed.other_ids.length) {
|
|
207
|
+
throw new Error('ExpectedChangeToRealPrivateChannelId');
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return confirmed;
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
strictSame(privateConfirmed.other_ids, ['16000000x0x1'], 'Got private id');
|
|
214
|
+
|
|
215
|
+
const [closedChannel] = (await getClosedChannels({lnd})).channels;
|
|
216
|
+
|
|
217
|
+
equal(closedChannel.id, confirmed.id, 'Closed channel shows confirmed id');
|
|
218
|
+
strictSame(closedChannel.other_ids, confirmed.other_ids, 'Saved temp id');
|
|
219
|
+
|
|
220
|
+
const [closeEvent] = closings;
|
|
221
|
+
|
|
222
|
+
equal(closeEvent.id, confirmed.id, 'Closed event shows confirmed id');
|
|
223
|
+
strictSame(closeEvent.other_ids, confirmed.other_ids, 'Got temporary id');
|
|
224
|
+
|
|
225
|
+
const ephemeralIds = await getEphemeralChannelIds({lnd});
|
|
226
|
+
|
|
227
|
+
strictSame(
|
|
228
|
+
ephemeralIds,
|
|
229
|
+
{
|
|
230
|
+
channels: [
|
|
231
|
+
{other_ids: [], reference_id: '16000000x0x0'},
|
|
232
|
+
{other_ids: [], reference_id: '16000000x0x1'},
|
|
233
|
+
],
|
|
234
|
+
},
|
|
235
|
+
'Ephemeral ids are returned'
|
|
236
|
+
);
|
|
237
|
+
} catch (err) {
|
|
238
|
+
equal(err, null, 'No error is reported');
|
|
239
|
+
} finally {
|
|
240
|
+
return await kill({});
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return end();
|
|
244
|
+
});
|
|
@@ -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');
|
|
@@ -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();
|