ln-docker-daemons 1.2.0 → 2.2.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,25 @@
1
1
  # Versions
2
2
 
3
+ ## 2.2.0
4
+
5
+ - `spawnLightningCluster`, `spawnLightningDocker`: Add `lnd_configuration` to
6
+ allow specifying additional LND configuration parameters
7
+
8
+ ## 2.1.1
9
+
10
+ - `DOCKER_LND_VERSION`: add environment variable to control docker lnd image
11
+
12
+ ## 2.0.0
13
+
14
+ - `spawnLightningCluster`: add `socket` to reveal node LN p2p sockets
15
+ - `spawnLightningDocker`: add `add_chain_peer` method to add a chain peer
16
+ - `spawnLightningDocker`: add `chain_socket` method for the chain p2p socket
17
+ - `spawnLightningDocker`: add `ln_socket` method for the chain p2p socket
18
+
19
+ ### Breaking Changes
20
+
21
+ - Node 12+ is required
22
+
3
23
  ## 1.2.0
4
24
 
5
25
  - `spawnLightningCluster` add `generate` to generate coins for a node
package/README.md CHANGED
@@ -18,6 +18,16 @@ const publicKey = (await getIdentity({lnd})).public_key;
18
18
  await kill({});
19
19
  ```
20
20
 
21
+ ## Environment Variables
22
+
23
+ - `DOCKER_LND_VERSION`: set this to use a custom LND docker image
24
+
25
+ Example:
26
+
27
+ ```shell
28
+ export DOCKER_LND_VERSION="v0.14.0-beta"
29
+ ```
30
+
21
31
  ## spawnBitcoindDocker
22
32
 
23
33
  Spawn a Bitcoin Core Docker image
@@ -31,6 +41,7 @@ Spawn a Bitcoin Core Docker image
31
41
 
32
42
  @returns via cbk or Promise
33
43
  {
44
+ host: <Host String>
34
45
  kill: ({}, [cbk]) => <Kill Promise>
35
46
  rpc_pass: <RPC Password String>
36
47
  rpc_user: <RPC Username String>
@@ -58,6 +69,7 @@ await kill({});
58
69
  Spawn a cluster of nodes
59
70
 
60
71
  {
72
+ [lnd_configuration]: [<LND Configuration Argument String>]
61
73
  [size]: <Total Lightning Nodes Number>
62
74
  }
63
75
 
@@ -68,6 +80,7 @@ Spawn a cluster of nodes
68
80
  id: <Node Public Key Hex String>
69
81
  kill: <Kill Function> ({}, cbk) => {}
70
82
  lnd: <Authenticated LND API Object>
83
+ socket: <Node Socket String>
71
84
  }]
72
85
  }
73
86
 
@@ -81,11 +94,10 @@ const {spawnLightningCluster} = require('ln-docker-daemons');
81
94
  const {nodes} = await spawnLightningCluster({});
82
95
  const [{lnd, generate, kill}] = nodes;
83
96
 
84
- const pubilcKey = (await getIdentity({lnd})).public_key;
97
+ const publicKey = (await getIdentity({lnd})).public_key;
85
98
 
86
99
  // Generate some coins for the wallet
87
- const {address} = await createChainAddress({lnd, format: 'p2wpkh'});
88
- await generate({address, count: 500});
100
+ await generate({count: 500});
89
101
 
90
102
  // Stop the image
91
103
  await kill({});
@@ -103,12 +115,16 @@ Spawn an LND Docker
103
115
  generate_address: <Generate Blocks to Address String>
104
116
  lightning_p2p_port: <Lightning Network P2P Listen Port Number>
105
117
  lightning_rpc_port: <Lightning Node RPC Port Number>
118
+ [lnd_configuration]: [<LND Configuration Argument String>]
106
119
  }
107
120
 
108
121
  @returns via cbk or Promise
109
122
  {
123
+ add_chain_peer: <Add Peer Function> ({socket}) => {}
110
124
  cert: <LND Base64 Serialized TLS Cert>
125
+ chain_socket: <Chain P2P Socket String>
111
126
  kill: ({}, [cbk]) => <Kill LND Daemon Promise>
127
+ ln_socket: <LN P2P Socket String>
112
128
  macaroon: <LND Base64 Serialized Macaroon String>
113
129
  public_key: <Identity Public Key Hex String>
114
130
  socket: <LND RPC Host:Port Network Address String>
@@ -30,6 +30,7 @@ const trim = string => string.replace(/=+$/g, '');
30
30
 
31
31
  @returns via cbk or Promise
32
32
  {
33
+ host: <Host String>
33
34
  kill: ({}, [cbk]) => <Kill Promise>
34
35
  rpc_pass: <RPC Password String>
35
36
  rpc_user: <RPC Username String>
@@ -75,6 +76,7 @@ module.exports = (args, cbk) => {
75
76
  return spawnDockerImage({
76
77
  arguments: [
77
78
  '--disablewallet',
79
+ '--listen=1',
78
80
  '--persistmempool=false',
79
81
  '--printtoconsole',
80
82
  '--regtest',
@@ -86,12 +88,6 @@ module.exports = (args, cbk) => {
86
88
  `--zmqpubrawblock=tcp://*:${args.zmq_block_port}`,
87
89
  `--zmqpubrawtx=tcp://*:${args.zmq_tx_port}`,
88
90
  ],
89
- expose: [
90
- '18443/tcp',
91
- '18444/tcp',
92
- [`${args.zmq_block_port}/tcp`],
93
- [`${args.zmq_tx_port}/tcp`],
94
- ],
95
91
  image: dockerBitcoindImage,
96
92
  ports: {
97
93
  '18443/tcp': args.rpc_port,
@@ -0,0 +1,54 @@
1
+ const asyncAuto = require('async/auto');
2
+ const {returnResult} = require('asyncjs-util');
3
+
4
+ const rpc = require('./rpc');
5
+
6
+ const action = 'add';
7
+ const cmd = 'addnode';
8
+ const host = 'localhost';
9
+
10
+ /** Add a node as a peer
11
+
12
+ {
13
+ pass: <RPC Password String>
14
+ port: <RPC Port Number>
15
+ socket: <Socket to Connect to String>
16
+ user: <RPC Username String>
17
+ }
18
+
19
+ @returns via cbk or Promise
20
+ */
21
+ module.exports = ({pass, port, socket, user}, cbk) => {
22
+ return new Promise((resolve, reject) => {
23
+ return asyncAuto({
24
+ // Check arguments
25
+ validate: cbk => {
26
+ if (!pass) {
27
+ return cbk([400, 'ExpectedRpcPasswordToAddChainPeer']);
28
+ }
29
+
30
+ if (!port) {
31
+ return cbk([400, 'ExpectedRpcPortNumberToAddChainPeer']);
32
+ }
33
+
34
+ if (!socket) {
35
+ return cbk([400, 'ExpectedSocketToAddChainPeer']);
36
+ }
37
+
38
+ if (!user) {
39
+ return cbk([400, 'ExpectedRpcUsernameToAddChainPeer']);
40
+ }
41
+
42
+ return cbk();
43
+ },
44
+
45
+ // Execute request
46
+ request: ['validate', ({}, cbk) => {
47
+ const params = [socket, action];
48
+
49
+ return rpc({cmd, host, pass, params, port, user}, cbk);
50
+ }],
51
+ },
52
+ returnResult({reject, resolve}, cbk));
53
+ });
54
+ };
@@ -0,0 +1,57 @@
1
+ const asyncAuto = require('async/auto');
2
+ const {returnResult} = require('asyncjs-util');
3
+
4
+ const rpc = require('./rpc');
5
+
6
+ const cmd = 'getblock';
7
+ const host = 'localhost';
8
+ const infoVerbosityFlag = 1;
9
+
10
+ /** Get block info from Bitcoin Core daemon
11
+
12
+ {
13
+ id: <Block Hash Hex String>
14
+ pass: <RPC Password String>
15
+ port: <RPC Port Number>
16
+ user: <RPC Username String>
17
+ }
18
+
19
+ @returns via cbk or Promise
20
+ {
21
+ tx: [<Transaction Id Hex String>]
22
+ }
23
+ */
24
+ module.exports = ({id, pass, port, user}, cbk) => {
25
+ return new Promise((resolve, reject) => {
26
+ return asyncAuto({
27
+ // Check arguments
28
+ validate: cbk => {
29
+ if (!id) {
30
+ return cbk([400, 'ExpectedBlockIdToGetBlockInfo']);
31
+ }
32
+
33
+ if (!pass) {
34
+ return cbk([400, 'ExpectedRpcPasswordToGetBlockInfo']);
35
+ }
36
+
37
+ if (!port) {
38
+ return cbk([400, 'ExpectedRpcPortNumberToGetBlockInfo']);
39
+ }
40
+
41
+ if (!user) {
42
+ return cbk([400, 'ExpectedRpcUsernameToGetBlockInfo']);
43
+ }
44
+
45
+ return cbk();
46
+ },
47
+
48
+ // Execute request
49
+ request: ['validate', ({}, cbk) => {
50
+ const params = [id, infoVerbosityFlag];
51
+
52
+ return rpc({cmd, host, pass, params, port, user}, cbk);
53
+ }],
54
+ },
55
+ returnResult({reject, resolve, of: 'request'}, cbk));
56
+ });
57
+ };
@@ -1,4 +1,11 @@
1
+ const addPeer = require('./add_peer');
1
2
  const generateToAddress = require('./generate_to_address');
3
+ const getBlockInfo = require('./get_block_info');
2
4
  const getBlockchainInfo = require('./get_blockchain_info');
3
5
 
4
- module.exports = {generateToAddress, getBlockchainInfo};
6
+ module.exports = {
7
+ addPeer,
8
+ generateToAddress,
9
+ getBlockInfo,
10
+ getBlockchainInfo,
11
+ };
package/bitcoinrpc/rpc.js CHANGED
@@ -88,10 +88,6 @@ module.exports = ({cert, cmd, host, params, pass, port, user}, cbk) => {
88
88
 
89
89
  const {result} = await response.json();
90
90
 
91
- if (!result) {
92
- throw [503, 'ExpectedResultOfRpcRequest'];
93
- }
94
-
95
91
  return result;
96
92
  } catch (err) {
97
93
  if (err.code === 'ECONNRESET') {
@@ -1,85 +1,154 @@
1
1
  const asyncAuto = require('async/auto');
2
+ const asyncEach = require('async/each');
2
3
  const asyncMap = require('async/map');
4
+ const asyncRetry = require('async/retry');
3
5
  const {authenticatedLndGrpc} = require('lightning');
6
+ const {createChainAddress} = require('lightning');
4
7
  const {findFreePorts} = require('find-free-ports');
8
+ const {getUtxos} = require('lightning');
5
9
  const {getIdentity} = require('lightning');
6
10
  const {returnResult} = require('asyncjs-util');
7
11
 
8
12
  const {spawnLightningDocker} = require('./../lnd');
9
13
 
14
+ const between = (min, max) => Math.floor(Math.random() * (max - min) + min);
10
15
  const chunk = (arr, n, size) => [...Array(size)].map(_ => arr.splice(0, n));
11
16
  const count = size => size || 1;
17
+ const endPort = 65000;
12
18
  const generateAddress = '2N8hwP1WmJrFF5QWABn38y63uYLhnJYJYTF';
19
+ const interval = 10;
20
+ const makeAddress = ({lnd}) => createChainAddress({lnd});
21
+ const maturity = 100;
22
+ const pairs = n => n.map((x, i) => n.slice(i + 1).map(y => [x, y])).flat();
13
23
  const portsPerLnd = 6;
24
+ const startPort = 1025;
25
+ const times = 3000;
14
26
 
15
27
  /** Spawn a cluster of nodes
16
28
 
17
29
  {
30
+ [lnd_configuration]: [<LND Configuration Argument String>]
18
31
  [size]: <Total Lightning Nodes Number>
19
32
  }
20
33
 
21
34
  @returns via cbk or Promise
22
35
  {
23
36
  nodes: [{
24
- generate: ({address}, [cbk]) => {}
37
+ generate: ({address, count}, [cbk]) => {}
25
38
  id: <Node Public Key Hex String>
26
39
  kill: <Kill Function> ({}, cbk) => {}
27
40
  lnd: <Authenticated LND API Object>
41
+ socket: <Node Socket String>
28
42
  }]
29
43
  }
30
44
  */
31
- module.exports = ({size}, cbk) => {
45
+ module.exports = (args, cbk) => {
32
46
  return new Promise((resolve, reject) => {
33
47
  return asyncAuto({
34
- // Find ports for the requested daemons
35
- findPorts: async () => {
36
- return await findFreePorts(portsPerLnd * count(size));
37
- },
38
-
39
48
  // Spawn nodes
40
- spawn: ['findPorts', async ({findPorts}) => {
41
- const nodes = chunk(findPorts, portsPerLnd, count(size));
42
-
43
- return await asyncMap(nodes, async (ports) => {
44
- const [
45
- chainP2pPort,
46
- chainRpcPort,
47
- chainZmqBlockPort,
48
- chainZmqTxPort,
49
- lightningP2pPort,
50
- lightningRpcPort,
51
- ] = ports;
52
-
53
- const lightningDocker = await spawnLightningDocker({
54
- chain_p2p_port: chainP2pPort,
55
- chain_rpc_port: chainRpcPort,
56
- chain_zmq_block_port: chainZmqBlockPort,
57
- chain_zmq_tx_port: chainZmqTxPort,
58
- generate_address: generateAddress,
59
- lightning_p2p_port: lightningP2pPort,
60
- lightning_rpc_port: lightningRpcPort,
61
- });
49
+ spawn: async () => {
50
+ return await asyncRetry({interval, times: 25}, async () => {
51
+ const options = {startPort: between(startPort, endPort)};
52
+
53
+ // Find ports for the requested daemons
54
+ const findPorts = await findFreePorts(
55
+ portsPerLnd * count(args.size),
56
+ options
57
+ );
58
+
59
+ const nodes = chunk(findPorts, portsPerLnd, count(args.size));
60
+
61
+ return await asyncMap(nodes, async (ports) => {
62
+ const [
63
+ chainP2pPort,
64
+ chainRpcPort,
65
+ chainZmqBlockPort,
66
+ chainZmqTxPort,
67
+ lightningP2pPort,
68
+ lightningRpcPort,
69
+ ] = ports;
70
+
71
+ const lightningDocker = await spawnLightningDocker({
72
+ chain_p2p_port: chainP2pPort,
73
+ chain_rpc_port: chainRpcPort,
74
+ chain_zmq_block_port: chainZmqBlockPort,
75
+ chain_zmq_tx_port: chainZmqTxPort,
76
+ generate_address: generateAddress,
77
+ lightning_p2p_port: lightningP2pPort,
78
+ lightning_rpc_port: lightningRpcPort,
79
+ lnd_configuration: args.lnd_configuration,
80
+ });
81
+
82
+ const {lnd} = authenticatedLndGrpc({
83
+ cert: lightningDocker.cert,
84
+ macaroon: lightningDocker.macaroon,
85
+ socket: lightningDocker.socket,
86
+ });
62
87
 
63
- const {lnd} = authenticatedLndGrpc({
64
- cert: lightningDocker.cert,
65
- macaroon: lightningDocker.macaroon,
66
- socket: lightningDocker.socket,
88
+ const id = (await getIdentity({lnd})).public_key;
89
+
90
+ return {
91
+ id,
92
+ lnd,
93
+ chain: {
94
+ addPeer: lightningDocker.add_chain_peer,
95
+ generateToAddress: lightningDocker.generate,
96
+ getBlockInfo: lightningDocker.get_block_info,
97
+ socket: lightningDocker.chain_socket,
98
+ },
99
+ generate: ({address, count}) => {
100
+ return new Promise(async (resolve, reject) => {
101
+ await lightningDocker.generate({
102
+ count,
103
+ address: address || (await makeAddress({lnd})).address,
104
+ });
105
+
106
+ if (!count || count < maturity) {
107
+ return resolve();
108
+ }
109
+
110
+ await asyncRetry({interval, times}, async () => {
111
+ const [utxo] = (await getUtxos({lnd})).utxos;
112
+
113
+ if (!utxo) {
114
+ throw new Error('ExpectedUtxoInUtxos');
115
+ }
116
+
117
+ return utxo;
118
+ });
119
+
120
+ return resolve();
121
+ });
122
+ },
123
+ kill: lightningDocker.kill,
124
+ public_key: id,
125
+ socket: lightningDocker.ln_socket,
126
+ };
67
127
  });
128
+ });
129
+ },
68
130
 
69
- const id = (await getIdentity({lnd})).public_key;
131
+ // Connect nodes in the cluster to each other
132
+ connect: ['spawn', async ({spawn}) => {
133
+ return await asyncEach(pairs(spawn), async pair => {
134
+ const [a, b] = pair.map(({chain}) => chain);
70
135
 
71
- return {
72
- id,
73
- lnd,
74
- generate: lightningDocker.generate,
75
- kill: lightningDocker.kill,
76
- };
136
+ return await a.addPeer({socket: b.socket});
77
137
  });
78
138
  }],
79
139
 
80
140
  // Final set of nodes
81
- nodes: ['spawn', async ({spawn}) => {
82
- return {nodes: spawn};
141
+ nodes: ['connect', 'spawn', async ({spawn}) => {
142
+ return {
143
+ kill: ({}) => asyncEach(spawn, async ({kill}) => await kill({})),
144
+ nodes: spawn.map(node => ({
145
+ generate: node.generate,
146
+ id: node.id,
147
+ kill: node.kill,
148
+ lnd: node.lnd,
149
+ socket: node.socket,
150
+ })),
151
+ };
83
152
  }],
84
153
  },
85
154
  returnResult({reject, resolve, of: 'nodes'}, cbk));
@@ -1,4 +1,5 @@
1
1
  const asyncAuto = require('async/auto');
2
+ const asyncRetry = require('async/retry');
2
3
  const Dockerode = require('dockerode');
3
4
  const {returnResult} = require('asyncjs-util');
4
5
 
@@ -66,6 +67,8 @@ module.exports = ({arguments, expose, image, ports}, cbk) => {
66
67
  throw [503, 'CannotConnectToDockerDaemon'];
67
68
  }
68
69
 
70
+ console.log("ERR", err);
71
+
69
72
  throw [503, 'UnexpectedErrorGettingDockerImage', {err}];
70
73
  }
71
74
  }],
@@ -125,13 +128,16 @@ module.exports = ({arguments, expose, image, ports}, cbk) => {
125
128
 
126
129
  // Start the image
127
130
  start: ['container', 'docker', ({container, docker}, cbk) => {
128
- return container.start(err => {
129
- if (!!err) {
130
- return cbk([503, 'UnexpectedErrorStartingDockerContainer', {err}]);
131
- }
131
+ return asyncRetry({}, cbk => {
132
+ return container.start(err => {
133
+ if (!!err) {
134
+ return cbk([503, 'UnexpectedErrorStartingContainer', {err}]);
135
+ }
132
136
 
133
- return cbk();
134
- });
137
+ return cbk();
138
+ });
139
+ },
140
+ cbk);
135
141
  }],
136
142
 
137
143
  // Get the details about the container
@@ -1,3 +1,3 @@
1
1
  {
2
- "dockerLndImage": "lightninglabs/lnd:v0.13.1-beta"
2
+ "dockerLndImage": "lightninglabs/lnd:v0.14.0-beta"
3
3
  }
@@ -1,7 +1,9 @@
1
1
  const asyncAuto = require('async/auto');
2
2
  const {returnResult} = require('asyncjs-util');
3
3
 
4
+ const {addPeer} = require('./../bitcoinrpc');
4
5
  const {generateToAddress} = require('./../bitcoinrpc');
6
+ const {getBlockInfo} = require('./../bitcoinrpc');
5
7
  const {killDockers} = require('./../docker');
6
8
  const {spawnBitcoindDocker} = require('./../bitcoind');
7
9
  const spawnLndDocker = require('./spawn_lnd_docker');
@@ -16,13 +18,18 @@ const spawnLndDocker = require('./spawn_lnd_docker');
16
18
  generate_address: <Generate Blocks to Address String>
17
19
  lightning_p2p_port: <Lightning Network P2P Listen Port Number>
18
20
  lightning_rpc_port: <Lightning Node RPC Port Number>
21
+ [lnd_configuration]: [<LND Configuration Argument String>]
19
22
  }
20
23
 
21
24
  @returns via cbk or Promise
22
25
  {
26
+ add_chain_peer: <Add Peer Function> ({socket}) => {}
23
27
  cert: <LND Base64 Serialized TLS Cert>
28
+ chain_socket: <Chain P2P Socket String>
24
29
  generate: ({address, count}, cbk) => <Generate to Address Promise>
30
+ get_block_info: <Get Block Info Function> ({id}) => {}
25
31
  kill: ({}, [cbk]) => <Kill LND Daemon Promise>
32
+ ln_socket: <LN P2P Socket String>
26
33
  macaroon: <LND Base64 Serialized Macaroon String>
27
34
  public_key: <Identity Public Key Hex String>
28
35
  socket: <LND RPC Host:Port Network Address String>
@@ -93,6 +100,7 @@ module.exports = (args, cbk) => {
93
100
  ({spawnChainDaemon}, cbk) =>
94
101
  {
95
102
  return spawnLndDocker({
103
+ configuration: args.lnd_configuration,
96
104
  bitcoind_rpc_host: spawnChainDaemon.host,
97
105
  bitcoind_rpc_pass: spawnChainDaemon.rpc_pass,
98
106
  bitcoind_rpc_port: args.chain_rpc_port,
@@ -114,7 +122,14 @@ module.exports = (args, cbk) => {
114
122
  const dockers = [spawnChainDaemon, spawnLightningDaemon];
115
123
 
116
124
  return cbk(null, {
125
+ add_chain_peer: ({socket}) => addPeer({
126
+ socket,
127
+ pass: spawnChainDaemon.rpc_pass,
128
+ port: args.chain_rpc_port,
129
+ user: spawnChainDaemon.rpc_user,
130
+ }),
117
131
  cert: spawnLightningDaemon.cert,
132
+ chain_socket: `${spawnChainDaemon.host}`,
118
133
  generate: ({address, count}) => generateToAddress({
119
134
  address,
120
135
  count,
@@ -122,8 +137,15 @@ module.exports = (args, cbk) => {
122
137
  port: args.chain_rpc_port,
123
138
  user: spawnChainDaemon.rpc_user,
124
139
  }),
140
+ get_block_info: ({id}) => getBlockInfo({
141
+ id,
142
+ pass: spawnChainDaemon.rpc_pass,
143
+ port: args.chain_rpc_port,
144
+ user: spawnChainDaemon.rpc_user,
145
+ }),
125
146
  kill: ({}, cbk) => killDockers({dockers}, cbk),
126
147
  macaroon: spawnLightningDaemon.macaroon,
148
+ ln_socket: `${spawnLightningDaemon.host}:9735`,
127
149
  public_key: spawnLightningDaemon.public_key,
128
150
  socket: spawnLightningDaemon.socket,
129
151
  });
@@ -8,7 +8,8 @@ const {unauthenticatedLndGrpc} = require('lightning');
8
8
  const {dockerLndImage} = require('./constants');
9
9
  const {spawnDockerImage} = require('./../docker');
10
10
 
11
- const interval = 50;
11
+ const imageName = ver => !!ver ? `lightninglabs/lnd:${ver}` : dockerLndImage;
12
+ const interval = 100;
12
13
  const macaroonPath = '/root/.lnd/data/chain/bitcoin/regtest/admin.macaroon';
13
14
  const times = 500;
14
15
  const tlsCertPath = '/root/.lnd/tls.cert';
@@ -22,6 +23,7 @@ const tlsCertPath = '/root/.lnd/tls.cert';
22
23
  bitcoind_rpc_user: <Bitcoin Core RPC Username String>
23
24
  bitcoind_zmq_block_port: <Bitcoin Core ZMQ Block Port Number>
24
25
  bitcoind_zmq_tx_port: <Bitcoin Core ZMQ Transaction Port Number>
26
+ [configuration]: [<LND Configuration Argument String>]
25
27
  p2p_port: <LND Peer to Peer Listen Port Number>
26
28
  rpc_port: <LND RPC Port Number>
27
29
  }
@@ -77,29 +79,33 @@ module.exports = (args, cbk) => {
77
79
  const zmqBlockPort = args.bitcoind_zmq_block_port;
78
80
  const zmqTxPort = args.bitcoind_zmq_tx_port;
79
81
 
82
+ const arguments = [
83
+ '--accept-keysend',
84
+ '--allow-circular-route',
85
+ '--autopilot.heuristic=externalscore:0.5',
86
+ '--autopilot.heuristic=preferential:0.5',
87
+ '--bitcoin.active',
88
+ '--bitcoin.minhtlc=1000',
89
+ '--bitcoin.node=bitcoind',
90
+ '--bitcoin.regtest',
91
+ `--bitcoind.rpchost=${chainHost}:18443`,
92
+ `--bitcoind.rpcpass=${args.bitcoind_rpc_pass}`,
93
+ `--bitcoind.rpcuser=${args.bitcoind_rpc_user}`,
94
+ `--bitcoind.zmqpubrawblock=tcp://${chainHost}:${zmqBlockPort}`,
95
+ `--bitcoind.zmqpubrawtx=tcp://${chainHost}:${zmqTxPort}`,
96
+ '--debuglevel=trace',
97
+ `--externalip=127.0.0.1:9735`,
98
+ '--historicalsyncinterval=1s',
99
+ `--listen=0.0.0.0:9735`,
100
+ '--nobootstrap',
101
+ `--rpclisten=0.0.0.0:10009`,
102
+ '--trickledelay=1',
103
+ '--unsafe-disconnect',
104
+ ];
105
+
80
106
  return spawnDockerImage({
81
- arguments: [
82
- '--autopilot.heuristic=externalscore:0.5',
83
- '--autopilot.heuristic=preferential:0.5',
84
- '--bitcoin.active',
85
- '--bitcoin.minhtlc=1000',
86
- '--bitcoin.node=bitcoind',
87
- '--bitcoin.regtest',
88
- `--bitcoind.rpchost=${chainHost}:18443`,
89
- `--bitcoind.rpcpass=${args.bitcoind_rpc_pass}`,
90
- `--bitcoind.rpcuser=${args.bitcoind_rpc_user}`,
91
- `--bitcoind.zmqpubrawblock=tcp://${chainHost}:${zmqBlockPort}`,
92
- `--bitcoind.zmqpubrawtx=tcp://${chainHost}:${zmqTxPort}`,
93
- '--debuglevel=trace',
94
- `--externalip=127.0.0.1:9735`,
95
- '--historicalsyncinterval=1s',
96
- `--listen=0.0.0.0:9735`,
97
- '--nobootstrap',
98
- `--rpclisten=0.0.0.0:10009`,
99
- '--trickledelay=1',
100
- '--unsafe-disconnect',
101
- ],
102
- image: dockerLndImage,
107
+ arguments: arguments.concat(args.configuration || []),
108
+ image: imageName(process.env.DOCKER_LND_VERSION),
103
109
  ports: {
104
110
  '9735/tcp': args.p2p_port,
105
111
  '10009/tcp': args.rpc_port,
@@ -123,23 +129,26 @@ module.exports = (args, cbk) => {
123
129
 
124
130
  const {lnd} = unauthenticatedLndGrpc({cert, socket});
125
131
 
126
- lnd.unlocker.genSeed({}, (err, res) => {
127
- if (!!err) {
128
- return cbk([503, 'UnexpectedErrorGeneratingSeed', {err}]);
129
- }
130
-
131
- lnd.unlocker.initWallet({
132
- cipher_seed_mnemonic: res.cipher_seed_mnemonic,
133
- wallet_password: Buffer.from('password', 'utf8'),
134
- },
135
- err => {
132
+ return asyncRetry({interval, times}, cbk => {
133
+ return lnd.unlocker.genSeed({}, (err, res) => {
136
134
  if (!!err) {
137
- return cbk([503, 'UnexpectedErrorInitializingWallet', {err}]);
135
+ return cbk([503, 'UnexpectedErrorGeneratingSeed', {err}]);
138
136
  }
139
137
 
140
- return cbk();
138
+ lnd.unlocker.initWallet({
139
+ cipher_seed_mnemonic: res.cipher_seed_mnemonic,
140
+ wallet_password: Buffer.from('password', 'utf8'),
141
+ },
142
+ err => {
143
+ if (!!err) {
144
+ return cbk([503, 'UnexpectedErrorInitializingWallet', {err}]);
145
+ }
146
+
147
+ return cbk();
148
+ });
141
149
  });
142
- });
150
+ },
151
+ cbk);
143
152
  }],
144
153
 
145
154
  // Get the macaroon out of the docker image
@@ -183,6 +192,7 @@ module.exports = (args, cbk) => {
183
192
  {
184
193
  return cbk(null, {
185
194
  cert: getCertificate.file.toString('base64'),
195
+ host: spawnDocker.host,
186
196
  kill: spawnDocker.kill,
187
197
  macaroon: getMacaroon.file.toString('base64'),
188
198
  public_key: waitForRpc.public_key,
package/package.json CHANGED
@@ -8,11 +8,11 @@
8
8
  },
9
9
  "dependencies": {
10
10
  "@alexbosworth/node-fetch": "2.6.2",
11
- "async": "3.2.1",
12
- "asyncjs-util": "1.2.6",
11
+ "async": "3.2.3",
12
+ "asyncjs-util": "1.2.8",
13
13
  "dockerode": "3.3.1",
14
14
  "find-free-ports": "3.0.0",
15
- "lightning": "4.10.7",
15
+ "lightning": "5.3.1",
16
16
  "tar-stream": "2.2.0"
17
17
  },
18
18
  "description": "Spawn and control LN Docker daemons",
@@ -20,7 +20,7 @@
20
20
  "@alexbosworth/tap": "15.0.10"
21
21
  },
22
22
  "engines": {
23
- "node": ">=10.12.0"
23
+ "node": ">=12"
24
24
  },
25
25
  "keywords": [
26
26
  "docker"
@@ -35,5 +35,5 @@
35
35
  "scripts": {
36
36
  "test": "tap --branches=1 --functions=1 --lines=1 --statements=1 -j 1 test/bitcoind/*.js test/lnd/*.js"
37
37
  },
38
- "version": "1.2.0"
38
+ "version": "2.2.0"
39
39
  }