BatchOpenChannel
BatchOpenChannel attempts to open multiple single-funded channels in a single transaction in an atomic way. This means either all channel open requests succeed at once or all attempts are aborted if any of them fail. This is the safer variant of using PSBTs to manually fund a batch of channels through the OpenChannel RPC.
Source: lightning.proto
gRPC
rpc BatchOpenChannel (BatchOpenChannelRequest) returns (BatchOpenChannelResponse);
REST
HTTP Method | Path |
---|---|
POST | /v1/channels/batch |
Code Samples
- gRPC
- REST
- Shell
- Javascript
- Python
const fs = require('fs');
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const GRPC_HOST = 'localhost:10009'
const MACAROON_PATH = 'LND_DIR/data/chain/bitcoin/regtest/admin.macaroon'
const TLS_PATH = 'LND_DIR/tls.cert'
const loaderOptions = {
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true,
};
const packageDefinition = protoLoader.loadSync('lightning.proto', loaderOptions);
const lnrpc = grpc.loadPackageDefinition(packageDefinition).lnrpc;
process.env.GRPC_SSL_CIPHER_SUITES = 'HIGH+ECDSA';
const tlsCert = fs.readFileSync(TLS_PATH);
const sslCreds = grpc.credentials.createSsl(tlsCert);
const macaroon = fs.readFileSync(MACAROON_PATH).toString('hex');
const macaroonCreds = grpc.credentials.createFromMetadataGenerator(function(args, callback) {
let metadata = new grpc.Metadata();
metadata.add('macaroon', macaroon);
callback(null, metadata);
});
let creds = grpc.credentials.combineChannelCredentials(sslCreds, macaroonCreds);
let client = new lnrpc.Lightning(GRPC_HOST, creds);
let request = {
channels: <BatchOpenChannel>,
target_conf: <int32>,
sat_per_vbyte: <int64>,
min_confs: <int32>,
spend_unconfirmed: <bool>,
label: <string>,
};
client.batchOpenChannel(request, function(err, response) {
console.log(response);
});
// Console output:
// {
// "pending_channels": <PendingUpdate>,
// }
import codecs, grpc, os
# Generate the following 2 modules by compiling the lightning.proto with the grpcio-tools.
# See https://github.com/lightningnetwork/lnd/blob/master/docs/grpc/python.md for instructions.
import lightning_pb2 as lnrpc, lightning_pb2_grpc as lightningstub
GRPC_HOST = 'localhost:10009'
MACAROON_PATH = 'LND_DIR/data/chain/bitcoin/regtest/admin.macaroon'
TLS_PATH = 'LND_DIR/tls.cert'
# create macaroon credentials
macaroon = codecs.encode(open(MACAROON_PATH, 'rb').read(), 'hex')
def metadata_callback(context, callback):
callback([('macaroon', macaroon)], None)
auth_creds = grpc.metadata_call_credentials(metadata_callback)
# create SSL credentials
os.environ['GRPC_SSL_CIPHER_SUITES'] = 'HIGH+ECDSA'
cert = open(TLS_PATH, 'rb').read()
ssl_creds = grpc.ssl_channel_credentials(cert)
# combine macaroon and SSL credentials
combined_creds = grpc.composite_channel_credentials(ssl_creds, auth_creds)
# make the request
channel = grpc.secure_channel(GRPC_HOST, combined_creds)
stub = lightningstub.LightningStub(channel)
request = lnrpc.BatchOpenChannelRequest(
channels=<BatchOpenChannel>,
target_conf=<int32>,
sat_per_vbyte=<int64>,
min_confs=<int32>,
spend_unconfirmed=<bool>,
label=<string>,
)
response = stub.BatchOpenChannel(request)
print(response)
# {
# "pending_channels": <PendingUpdate>,
# }
- Javascript
- Python
const fs = require('fs');
const request = require('request');
const REST_HOST = 'localhost:8080'
const MACAROON_PATH = 'LND_DIR/data/chain/bitcoin/regtest/admin.macaroon'
let requestBody = {
channels: <array>, // <BatchOpenChannel>
target_conf: <integer>, // <int32>
sat_per_vbyte: <string>, // <int64>
min_confs: <integer>, // <int32>
spend_unconfirmed: <boolean>, // <bool>
label: <string>, // <string>
};
let options = {
url: `https://${REST_HOST}/v1/channels/batch`,
// Work-around for self-signed certificates.
rejectUnauthorized: false,
json: true,
headers: {
'Grpc-Metadata-macaroon': fs.readFileSync(MACAROON_PATH).toString('hex'),
},
form: JSON.stringify(requestBody),
}
request.post(options, function(error, response, body) {
console.log(body);
});
// Console output:
// {
// "pending_channels": <array>, // <PendingUpdate>
// }
import base64, codecs, json, requests
REST_HOST = 'localhost:8080'
MACAROON_PATH = 'LND_DIR/data/chain/bitcoin/regtest/admin.macaroon'
TLS_PATH = 'LND_DIR/tls.cert'
url = f'https://{REST_HOST}/v1/channels/batch'
macaroon = codecs.encode(open(MACAROON_PATH, 'rb').read(), 'hex')
headers = {'Grpc-Metadata-macaroon': macaroon}
data = {
'channels': <BatchOpenChannel>,
'target_conf': <int32>,
'sat_per_vbyte': <int64>,
'min_confs': <int32>,
'spend_unconfirmed': <bool>,
'label': <string>,
}
r = requests.post(url, headers=headers, data=json.dumps(data), verify=TLS_PATH)
print(r.json())
# {
# "pending_channels": <PendingUpdate>,
# }
$ lncli batchopenchannel --help
NAME:
lncli batchopenchannel - Open multiple channels to existing peers in a single transaction.
USAGE:
lncli batchopenchannel [command options] channels-json
CATEGORY:
Channels
DESCRIPTION:
Attempt to open one or more new channels to an existing peer with the
given node-keys.
Example:
lncli batchopenchannel --sat_per_vbyte=5 '[{
"node_pubkey": "02abcdef...",
"local_funding_amount": 500000,
"private": true,
"close_address": "bc1qxxx..."
}, {
"node_pubkey": "03fedcba...",
"local_funding_amount": 200000,
"remote_csv_delay": 288
}]'
All nodes listed must already be connected peers, otherwise funding will
fail.
The channel will be initialized with local_funding_amount satoshis
locally and push_sat satoshis for the remote node. Note that specifying
push_sat means you give that amount to the remote node as part of the
channel opening. Once the channel is open, a channelPoint (txid:vout) of
the funding output is returned.
If the remote peer supports the option upfront shutdown feature bit
(query listpeers to see their supported feature bits), an address to
enforce payout of funds on cooperative close can optionally be provided.
Note that if you set this value, you will not be able to cooperatively
close out to another address.
One can manually set the fee to be used for the funding transaction via
either the --conf_target or --sat_per_vbyte arguments. This is optional.
OPTIONS:
--conf_target value (optional) the number of blocks that the transaction *should* confirm in, will be used for fee estimation (default: 0)
--sat_per_vbyte value (optional) a manual fee expressed in sat/vByte that should be used when crafting the transaction (default: 0)
--min_confs value (optional) the minimum number of confirmations each one of your outputs used for the funding transaction must satisfy (default: 1)
--label value (optional) a label to attach to the batch transaction when storing it to the local wallet after publishing it
Messages
lnrpc.BatchOpenChannelRequest
Source: lightning.proto
Field | gRPC Type | REST Type | REST Placement |
---|---|---|---|
channels | BatchOpenChannel[] | array | body |
target_conf | int32 | integer | body |
sat_per_vbyte | int64 | string | body |
min_confs | int32 | integer | body |
spend_unconfirmed | bool | boolean | body |
label | string | string | body |
lnrpc.BatchOpenChannelResponse
Source: lightning.proto
Field | gRPC Type | REST Type |
---|---|---|
pending_channels | PendingUpdate[] | array |
Nested Messages
lnrpc.BatchOpenChannel
Field | gRPC Type | REST Type |
---|---|---|
node_pubkey | bytes | string |
local_funding_amount | int64 | string |
push_sat | int64 | string |
private | bool | boolean |
min_htlc_msat | int64 | string |
remote_csv_delay | uint32 | integer |
close_address | string | string |
pending_chan_id | bytes | string |
commitment_type | CommitmentType | string |
lnrpc.PendingUpdate
Field | gRPC Type | REST Type |
---|---|---|
txid | bytes | string |
output_index | uint32 | integer |
Enums
lnrpc.CommitmentType
Name | Number |
---|---|
UNKNOWN_COMMITMENT_TYPE | 0 |
LEGACY | 1 |
STATIC_REMOTE_KEY | 2 |
ANCHORS | 3 |
SCRIPT_ENFORCED_LEASE | 4 |