mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 15:14:23 +01:00
fundchannel: use plugin; delete interior impl
Switch over to using the fundchannel plugin.
This commit is contained in:
committed by
Rusty Russell
parent
548672ea0a
commit
a35677fa0f
@@ -269,23 +269,6 @@ wallet_commit_channel(struct lightningd *ld,
|
|||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void funding_broadcast_failed(struct channel *channel,
|
|
||||||
int exitstatus, const char *msg)
|
|
||||||
{
|
|
||||||
struct funding_channel *fc = channel->peer->uncommitted_channel->fc;
|
|
||||||
struct command *cmd = fc->cmd;
|
|
||||||
|
|
||||||
/* Massage output into shape so it doesn't kill the JSON serialization */
|
|
||||||
char *output = tal_strjoin(cmd, tal_strsplit(cmd, msg, "\n", STR_NO_EMPTY), " ", STR_NO_TRAIL);
|
|
||||||
was_pending(command_fail(cmd, FUNDING_BROADCAST_FAIL,
|
|
||||||
"Error broadcasting funding transaction: %s", output));
|
|
||||||
|
|
||||||
/* Frees fc too */
|
|
||||||
tal_free(fc->uc);
|
|
||||||
|
|
||||||
/* Keep in state CHANNELD_AWAITING_LOCKIN until (manual) broadcast */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void funding_success(struct channel *channel)
|
static void funding_success(struct channel *channel)
|
||||||
{
|
{
|
||||||
struct json_stream *response;
|
struct json_stream *response;
|
||||||
@@ -305,33 +288,6 @@ static void funding_success(struct channel *channel)
|
|||||||
was_pending(command_success(cmd, response));
|
was_pending(command_success(cmd, response));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void funding_broadcast_success(struct channel *channel)
|
|
||||||
{
|
|
||||||
struct json_stream *response;
|
|
||||||
struct funding_channel *fc = channel->peer->uncommitted_channel->fc;
|
|
||||||
struct command *cmd = fc->cmd;
|
|
||||||
|
|
||||||
response = json_stream_success(cmd);
|
|
||||||
json_add_string(response, "tx", fc->hextx);
|
|
||||||
json_add_txid(response, "txid", &channel->funding_txid);
|
|
||||||
json_add_string(response, "channel_id",
|
|
||||||
type_to_string(tmpctx, struct channel_id, &fc->cid));
|
|
||||||
was_pending(command_success(cmd, response));
|
|
||||||
|
|
||||||
/* Frees fc too */
|
|
||||||
tal_free(fc->uc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void funding_broadcast_failed_or_success(struct channel *channel,
|
|
||||||
int exitstatus, const char *msg)
|
|
||||||
{
|
|
||||||
if (exitstatus == 0) {
|
|
||||||
funding_broadcast_success(channel);
|
|
||||||
} else {
|
|
||||||
funding_broadcast_failed(channel, exitstatus, msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void funding_started_success(struct funding_channel *fc,
|
static void funding_started_success(struct funding_channel *fc,
|
||||||
u8 *scriptPubkey)
|
u8 *scriptPubkey)
|
||||||
{
|
{
|
||||||
@@ -383,129 +339,6 @@ failed:
|
|||||||
tal_free(fc->uc);
|
tal_free(fc->uc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool compose_and_broadcast_tx(struct lightningd *ld,
|
|
||||||
const u8 *resp,
|
|
||||||
struct funding_channel *fc,
|
|
||||||
struct channel_info *channel_info,
|
|
||||||
struct channel *channel,
|
|
||||||
struct bitcoin_txid *expected_txid,
|
|
||||||
u32 feerate)
|
|
||||||
{
|
|
||||||
u8 *msg;
|
|
||||||
struct pubkey changekey;
|
|
||||||
u16 funding_outnum;
|
|
||||||
struct bitcoin_tx *fundingtx;
|
|
||||||
struct amount_sat change;
|
|
||||||
struct bitcoin_txid funding_txid;
|
|
||||||
const struct chainparams *chainparams = get_chainparams(ld);
|
|
||||||
|
|
||||||
/* Generate the funding tx. */
|
|
||||||
if (!amount_sat_eq(fc->wtx->change, AMOUNT_SAT(0))
|
|
||||||
&& !bip32_pubkey(ld->wallet->bip32_base,
|
|
||||||
&changekey, fc->wtx->change_key_index))
|
|
||||||
fatal("Error deriving change key %u", fc->wtx->change_key_index);
|
|
||||||
|
|
||||||
fundingtx = funding_tx(tmpctx, chainparams, &funding_outnum,
|
|
||||||
fc->wtx->utxos, fc->wtx->amount,
|
|
||||||
&fc->uc->local_funding_pubkey,
|
|
||||||
&channel_info->remote_fundingkey,
|
|
||||||
fc->wtx->change, &changekey,
|
|
||||||
ld->wallet->bip32_base);
|
|
||||||
|
|
||||||
log_debug(fc->uc->log, "Funding tx has %zi inputs, %zu outputs:",
|
|
||||||
fundingtx->wtx->num_inputs,
|
|
||||||
fundingtx->wtx->num_outputs);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < fundingtx->wtx->num_inputs; i++) {
|
|
||||||
struct bitcoin_txid tmptxid;
|
|
||||||
bitcoin_tx_input_get_txid(fundingtx, i, &tmptxid);
|
|
||||||
log_debug(fc->uc->log, "%zi: %s (%s) %s\n",
|
|
||||||
i,
|
|
||||||
type_to_string(tmpctx, struct amount_sat,
|
|
||||||
&fc->wtx->utxos[i]->amount),
|
|
||||||
fc->wtx->utxos[i]->is_p2sh ? "P2SH" : "SEGWIT",
|
|
||||||
type_to_string(tmpctx, struct bitcoin_txid,
|
|
||||||
&tmptxid));
|
|
||||||
}
|
|
||||||
|
|
||||||
bitcoin_txid(fundingtx, &funding_txid);
|
|
||||||
|
|
||||||
if (!bitcoin_txid_eq(&funding_txid, expected_txid)) {
|
|
||||||
log_broken(fc->uc->log,
|
|
||||||
"Funding txid mismatch:"
|
|
||||||
" amount %s change %s"
|
|
||||||
" changeidx %u"
|
|
||||||
" localkey %s remotekey %s",
|
|
||||||
type_to_string(tmpctx, struct amount_sat,
|
|
||||||
&fc->wtx->amount),
|
|
||||||
type_to_string(tmpctx, struct amount_sat,
|
|
||||||
&fc->wtx->change),
|
|
||||||
fc->wtx->change_key_index,
|
|
||||||
type_to_string(fc, struct pubkey,
|
|
||||||
&fc->uc->local_funding_pubkey),
|
|
||||||
type_to_string(fc, struct pubkey,
|
|
||||||
&channel_info->remote_fundingkey));
|
|
||||||
was_pending(command_fail(fc->cmd, JSONRPC2_INVALID_PARAMS,
|
|
||||||
"Funding txid mismatch:"
|
|
||||||
" amount %s change %s"
|
|
||||||
" changeidx %u"
|
|
||||||
" localkey %s remotekey %s",
|
|
||||||
type_to_string(tmpctx,
|
|
||||||
struct amount_sat,
|
|
||||||
&fc->wtx->amount),
|
|
||||||
type_to_string(tmpctx,
|
|
||||||
struct amount_sat,
|
|
||||||
&fc->wtx->change),
|
|
||||||
fc->wtx->change_key_index,
|
|
||||||
type_to_string(fc, struct pubkey,
|
|
||||||
&fc->uc->local_funding_pubkey),
|
|
||||||
type_to_string(fc, struct pubkey,
|
|
||||||
&channel_info->remote_fundingkey)));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get HSM to sign the funding tx. */
|
|
||||||
log_debug(channel->log, "Getting HSM to sign funding tx");
|
|
||||||
|
|
||||||
msg = towire_hsm_sign_funding(tmpctx, channel->funding,
|
|
||||||
fc->wtx->change,
|
|
||||||
fc->wtx->change_key_index,
|
|
||||||
&fc->uc->local_funding_pubkey,
|
|
||||||
&channel_info->remote_fundingkey,
|
|
||||||
fc->wtx->utxos);
|
|
||||||
|
|
||||||
if (!wire_sync_write(ld->hsm_fd, take(msg)))
|
|
||||||
fatal("Could not write to HSM: %s", strerror(errno));
|
|
||||||
|
|
||||||
msg = wire_sync_read(fc, ld->hsm_fd);
|
|
||||||
if (!fromwire_hsm_sign_funding_reply(tmpctx, msg, &fundingtx))
|
|
||||||
fatal("HSM gave bad sign_funding_reply %s",
|
|
||||||
tal_hex(msg, resp));
|
|
||||||
fundingtx->chainparams = chainparams;
|
|
||||||
|
|
||||||
/* Extract the change output and add it to the DB */
|
|
||||||
wallet_extract_owned_outputs(ld->wallet, fundingtx, NULL, &change);
|
|
||||||
|
|
||||||
/* Make sure we recognize our change output by its scriptpubkey in
|
|
||||||
* future. This assumes that we have only two outputs, may not be true
|
|
||||||
* if we add support for multifundchannel */
|
|
||||||
if (fundingtx->wtx->num_outputs == 2)
|
|
||||||
txfilter_add_scriptpubkey(ld->owned_txfilter, bitcoin_tx_output_get_script(tmpctx, fundingtx, !funding_outnum));
|
|
||||||
|
|
||||||
|
|
||||||
/* Send it out and watch for confirms. */
|
|
||||||
broadcast_tx(ld->topology, channel, fundingtx, funding_broadcast_failed_or_success);
|
|
||||||
|
|
||||||
/* Mark consumed outputs as spent */
|
|
||||||
wallet_confirm_utxos(ld->wallet, fc->wtx->utxos);
|
|
||||||
wallet_transaction_annotate(ld->wallet, &funding_txid,
|
|
||||||
TX_CHANNEL_FUNDING, channel->dbid);
|
|
||||||
|
|
||||||
/* We need these to compose cmd's response in funding_broadcast_success */
|
|
||||||
fc->hextx = tal_hex(fc, linearize_tx(fc->cmd, fundingtx));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void opening_funder_finished(struct subd *openingd, const u8 *resp,
|
static void opening_funder_finished(struct subd *openingd, const u8 *resp,
|
||||||
const int *fds,
|
const int *fds,
|
||||||
struct funding_channel *fc)
|
struct funding_channel *fc)
|
||||||
@@ -580,26 +413,9 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp,
|
|||||||
/* Needed for the success statement */
|
/* Needed for the success statement */
|
||||||
derive_channel_id(&fc->cid, &channel->funding_txid, funding_txout);
|
derive_channel_id(&fc->cid, &channel->funding_txid, funding_txout);
|
||||||
|
|
||||||
/* Was this an external wallet initiation ? */
|
funding_success(channel);
|
||||||
if (fc->inflight) {
|
|
||||||
funding_success(channel);
|
|
||||||
|
|
||||||
peer_start_channeld(channel, pps, NULL, false);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!compose_and_broadcast_tx(ld, resp, fc, &channel_info,
|
|
||||||
channel, &funding_txid,
|
|
||||||
feerate))
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
/* Start normal channel daemon. */
|
|
||||||
peer_start_channeld(channel, pps, NULL, false);
|
peer_start_channeld(channel, pps, NULL, false);
|
||||||
|
|
||||||
subd_release_channel(openingd, fc->uc);
|
|
||||||
fc->uc->openingd = NULL;
|
|
||||||
return;
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
subd_release_channel(openingd, fc->uc);
|
subd_release_channel(openingd, fc->uc);
|
||||||
fc->uc->openingd = NULL;
|
fc->uc->openingd = NULL;
|
||||||
@@ -1056,7 +872,6 @@ static unsigned int openingd_msg(struct subd *openingd,
|
|||||||
|
|
||||||
/* We send these! */
|
/* We send these! */
|
||||||
case WIRE_OPENING_INIT:
|
case WIRE_OPENING_INIT:
|
||||||
case WIRE_OPENING_FUNDER:
|
|
||||||
case WIRE_OPENING_FUNDER_START:
|
case WIRE_OPENING_FUNDER_START:
|
||||||
case WIRE_OPENING_FUNDER_COMPLETE:
|
case WIRE_OPENING_FUNDER_COMPLETE:
|
||||||
case WIRE_OPENING_FUNDER_CANCEL:
|
case WIRE_OPENING_FUNDER_CANCEL:
|
||||||
@@ -1231,7 +1046,7 @@ static struct command_result *json_fund_channel_cancel(struct command *cmd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* json_fund_channel_start - Entrypoint for funding an externally funded channel
|
* json_fund_channel_start - Entrypoint for funding a channel
|
||||||
*/
|
*/
|
||||||
static struct command_result *json_fund_channel_start(struct command *cmd,
|
static struct command_result *json_fund_channel_start(struct command *cmd,
|
||||||
const char *buffer,
|
const char *buffer,
|
||||||
@@ -1306,6 +1121,7 @@ static struct command_result *json_fund_channel_start(struct command *cmd,
|
|||||||
return command_fail(cmd, LIGHTNINGD, "Already funding channel");
|
return command_fail(cmd, LIGHTNINGD, "Already funding channel");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME: Support push_msat? */
|
||||||
fc->push = AMOUNT_MSAT(0);
|
fc->push = AMOUNT_MSAT(0);
|
||||||
fc->channel_flags = OUR_CHANNEL_FLAGS;
|
fc->channel_flags = OUR_CHANNEL_FLAGS;
|
||||||
if (!*announce_channel) {
|
if (!*announce_channel) {
|
||||||
@@ -1328,133 +1144,6 @@ static struct command_result *json_fund_channel_start(struct command *cmd,
|
|||||||
return command_still_pending(cmd);
|
return command_still_pending(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* json_fund_channel - Entrypoint for funding a channel
|
|
||||||
*/
|
|
||||||
static struct command_result *json_fund_channel(struct command *cmd,
|
|
||||||
const char *buffer,
|
|
||||||
const jsmntok_t *obj UNNEEDED,
|
|
||||||
const jsmntok_t *params)
|
|
||||||
{
|
|
||||||
struct command_result *res;
|
|
||||||
struct funding_channel * fc = tal(cmd, struct funding_channel);
|
|
||||||
struct node_id *id;
|
|
||||||
struct peer *peer;
|
|
||||||
struct channel *channel;
|
|
||||||
u32 *feerate_per_kw, *minconf, maxheight;
|
|
||||||
bool *announce_channel;
|
|
||||||
u8 *msg;
|
|
||||||
struct amount_sat max_funding_satoshi;
|
|
||||||
const struct utxo **chosen_utxos;
|
|
||||||
|
|
||||||
max_funding_satoshi = get_chainparams(cmd->ld)->max_funding;
|
|
||||||
|
|
||||||
fc->cmd = cmd;
|
|
||||||
fc->cancels = tal_arr(fc, struct command *, 0);
|
|
||||||
fc->uc = NULL;
|
|
||||||
fc->inflight = false;
|
|
||||||
fc->wtx = tal(fc, struct wallet_tx);
|
|
||||||
wtx_init(cmd, fc->wtx, max_funding_satoshi);
|
|
||||||
if (!param(fc->cmd, buffer, params,
|
|
||||||
p_req("id", param_node_id, &id),
|
|
||||||
p_req("satoshi", param_wtx, fc->wtx),
|
|
||||||
p_opt("feerate", param_feerate, &feerate_per_kw),
|
|
||||||
p_opt_def("announce", param_bool, &announce_channel, true),
|
|
||||||
p_opt_def("minconf", param_number, &minconf, 1),
|
|
||||||
p_opt("utxos", param_utxos, &chosen_utxos),
|
|
||||||
NULL))
|
|
||||||
return command_param_failed();
|
|
||||||
|
|
||||||
if (!feerate_per_kw) {
|
|
||||||
feerate_per_kw = tal(cmd, u32);
|
|
||||||
*feerate_per_kw = opening_feerate(cmd->ld->topology);
|
|
||||||
if (!*feerate_per_kw) {
|
|
||||||
return command_fail(cmd, LIGHTNINGD,
|
|
||||||
"Cannot estimate fees");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*feerate_per_kw < feerate_floor()) {
|
|
||||||
return command_fail(cmd, LIGHTNINGD,
|
|
||||||
"Feerate below feerate floor");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!topology_synced(cmd->ld->topology)) {
|
|
||||||
return command_fail(cmd, FUNDING_STILL_SYNCING_BITCOIN,
|
|
||||||
"Still syncing with bitcoin network");
|
|
||||||
}
|
|
||||||
|
|
||||||
peer = peer_by_id(cmd->ld, id);
|
|
||||||
if (!peer) {
|
|
||||||
return command_fail(cmd, LIGHTNINGD, "Unknown peer");
|
|
||||||
}
|
|
||||||
|
|
||||||
channel = peer_active_channel(peer);
|
|
||||||
if (channel) {
|
|
||||||
return command_fail(cmd, LIGHTNINGD, "Peer already %s",
|
|
||||||
channel_state_name(channel));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!peer->uncommitted_channel) {
|
|
||||||
return command_fail(cmd, LIGHTNINGD, "Peer not connected");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (peer->uncommitted_channel->fc) {
|
|
||||||
return command_fail(cmd, LIGHTNINGD, "Already funding channel");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: Support push_msat? */
|
|
||||||
fc->push = AMOUNT_MSAT(0);
|
|
||||||
fc->channel_flags = OUR_CHANNEL_FLAGS;
|
|
||||||
if (!*announce_channel) {
|
|
||||||
fc->channel_flags &= ~CHANNEL_FLAGS_ANNOUNCE_CHANNEL;
|
|
||||||
log_info(peer->ld->log, "Will open private channel with node %s",
|
|
||||||
type_to_string(fc, struct node_id, id));
|
|
||||||
}
|
|
||||||
|
|
||||||
maxheight = minconf_to_maxheight(*minconf, cmd->ld);
|
|
||||||
if (chosen_utxos)
|
|
||||||
res = wtx_from_utxos(fc->wtx, *feerate_per_kw,
|
|
||||||
BITCOIN_SCRIPTPUBKEY_P2WSH_LEN, maxheight, chosen_utxos);
|
|
||||||
else
|
|
||||||
res = wtx_select_utxos(fc->wtx, *feerate_per_kw,
|
|
||||||
BITCOIN_SCRIPTPUBKEY_P2WSH_LEN, maxheight);
|
|
||||||
if (res)
|
|
||||||
return res;
|
|
||||||
|
|
||||||
assert(!amount_sat_greater(fc->wtx->amount, max_funding_satoshi));
|
|
||||||
/* Stash total amount in fc as well, as externally funded
|
|
||||||
* channels don't have a wtx */
|
|
||||||
fc->funding = fc->wtx->amount;
|
|
||||||
|
|
||||||
peer->uncommitted_channel->fc = tal_steal(peer->uncommitted_channel, fc);
|
|
||||||
fc->uc = peer->uncommitted_channel;
|
|
||||||
|
|
||||||
msg = towire_opening_funder(NULL,
|
|
||||||
fc->wtx->amount,
|
|
||||||
fc->push,
|
|
||||||
*feerate_per_kw,
|
|
||||||
fc->wtx->change,
|
|
||||||
fc->wtx->change_key_index,
|
|
||||||
fc->channel_flags,
|
|
||||||
fc->wtx->utxos,
|
|
||||||
cmd->ld->wallet->bip32_base);
|
|
||||||
|
|
||||||
/* Openingd will either succeed, or fail, or tell us the other side
|
|
||||||
* funded first. */
|
|
||||||
subd_send_msg(peer->uncommitted_channel->openingd, take(msg));
|
|
||||||
return command_still_pending(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct json_command fund_channel_command = {
|
|
||||||
"fundchannel",
|
|
||||||
"channels",
|
|
||||||
json_fund_channel,
|
|
||||||
"Fund channel with {id} using {satoshi} (or 'all') satoshis, at optional "
|
|
||||||
"{feerate}. Only use outputs that have {minconf} confirmations."
|
|
||||||
};
|
|
||||||
AUTODATA(json_command, &fund_channel_command);
|
|
||||||
|
|
||||||
static const struct json_command fund_channel_start_command = {
|
static const struct json_command fund_channel_start_command = {
|
||||||
"fundchannel_start",
|
"fundchannel_start",
|
||||||
"channels",
|
"channels",
|
||||||
|
|||||||
@@ -43,21 +43,6 @@ msgdata,opening_got_offer,shutdown_scriptpubkey,u8,shutdown_len
|
|||||||
msgtype,opening_got_offer_reply,6105
|
msgtype,opening_got_offer_reply,6105
|
||||||
msgdata,opening_got_offer_reply,rejection,?wirestring,
|
msgdata,opening_got_offer_reply,rejection,?wirestring,
|
||||||
|
|
||||||
#include <common/bip32.h>
|
|
||||||
#include <common/htlc_wire.h>
|
|
||||||
# Master->openingd: please fund a channel.
|
|
||||||
msgtype,opening_funder,6001
|
|
||||||
msgdata,opening_funder,funding_satoshis,amount_sat,
|
|
||||||
msgdata,opening_funder,push_msat,amount_msat,
|
|
||||||
msgdata,opening_funder,feerate_per_kw,u32,
|
|
||||||
msgdata,opening_funder,change_satoshis,amount_sat,
|
|
||||||
msgdata,opening_funder,change_keyindex,u32,
|
|
||||||
msgdata,opening_funder,channel_flags,u8,
|
|
||||||
#include <common/utxo.h>
|
|
||||||
msgdata,opening_funder,num_inputs,u16,
|
|
||||||
msgdata,opening_funder,inputs,utxo,num_inputs
|
|
||||||
msgdata,opening_funder,bip32,ext_key,
|
|
||||||
|
|
||||||
# Openingd->master: we've successfully offered channel.
|
# Openingd->master: we've successfully offered channel.
|
||||||
# This gives their sig, means we can broadcast tx: we're done.
|
# This gives their sig, means we can broadcast tx: we're done.
|
||||||
msgtype,opening_funder_reply,6101
|
msgtype,opening_funder_reply,6101
|
||||||
|
|||||||
|
@@ -854,261 +854,6 @@ static u8 *funder_channel_complete(struct state *state)
|
|||||||
state->remote_upfront_shutdown_script);
|
state->remote_upfront_shutdown_script);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*~ OK, let's fund a channel! Returns the reply for lightningd on success,
|
|
||||||
* or NULL if something goes wrong. */
|
|
||||||
static u8 *funder_channel(struct state *state,
|
|
||||||
struct amount_sat change,
|
|
||||||
u32 change_keyindex,
|
|
||||||
u8 channel_flags,
|
|
||||||
struct utxo **utxos TAKES,
|
|
||||||
const struct ext_key *bip32_base)
|
|
||||||
{
|
|
||||||
struct channel_id id_in;
|
|
||||||
u8 *msg;
|
|
||||||
struct pubkey *changekey;
|
|
||||||
struct bitcoin_signature sig;
|
|
||||||
struct bitcoin_tx *funding, *tx;
|
|
||||||
struct amount_msat local_msat;
|
|
||||||
|
|
||||||
if (!setup_channel_funder(state))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
/* BOLT #2:
|
|
||||||
*
|
|
||||||
* The sending node:
|
|
||||||
*...
|
|
||||||
* - MUST set `push_msat` to equal or less than 1000 *
|
|
||||||
* `funding_satoshis`.
|
|
||||||
*/
|
|
||||||
if (!amount_sat_sub_msat(&local_msat, state->funding, state->push_msat))
|
|
||||||
status_failed(STATUS_FAIL_MASTER_IO,
|
|
||||||
"push-msat must be < %s",
|
|
||||||
type_to_string(tmpctx, struct amount_sat,
|
|
||||||
&state->funding));
|
|
||||||
/* BOLT #2:
|
|
||||||
*
|
|
||||||
* - if both nodes advertised the `option_upfront_shutdown_script`
|
|
||||||
* feature:
|
|
||||||
* - MUST include either a valid `shutdown_scriptpubkey` as required
|
|
||||||
* by `shutdown` `scriptpubkey`, or a zero-length
|
|
||||||
* `shutdown_scriptpubkey`.
|
|
||||||
* - otherwise:
|
|
||||||
* - MAY include a`shutdown_scriptpubkey`.
|
|
||||||
*/
|
|
||||||
/* We don't use shutdown_scriptpubkey (at least for now), so leave it
|
|
||||||
* NULL. */
|
|
||||||
msg = towire_open_channel_option_upfront_shutdown_script(NULL,
|
|
||||||
&state->chainparams->genesis_blockhash,
|
|
||||||
&state->channel_id,
|
|
||||||
state->funding,
|
|
||||||
state->push_msat,
|
|
||||||
state->localconf.dust_limit,
|
|
||||||
state->localconf.max_htlc_value_in_flight,
|
|
||||||
state->localconf.channel_reserve,
|
|
||||||
state->localconf.htlc_minimum,
|
|
||||||
state->feerate_per_kw,
|
|
||||||
state->localconf.to_self_delay,
|
|
||||||
state->localconf.max_accepted_htlcs,
|
|
||||||
&state->our_funding_pubkey,
|
|
||||||
&state->our_points.revocation,
|
|
||||||
&state->our_points.payment,
|
|
||||||
&state->our_points.delayed_payment,
|
|
||||||
&state->our_points.htlc,
|
|
||||||
&state->first_per_commitment_point[LOCAL],
|
|
||||||
channel_flags,
|
|
||||||
dev_upfront_shutdown_script(tmpctx));
|
|
||||||
sync_crypto_write(state->pps, take(msg));
|
|
||||||
|
|
||||||
/* This is usually a very transient state... */
|
|
||||||
peer_billboard(false,
|
|
||||||
"Funding channel: offered, now waiting for accept_channel");
|
|
||||||
/* ... since their reply should be immediate. */
|
|
||||||
msg = opening_negotiate_msg(tmpctx, state, true);
|
|
||||||
if (!msg)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
/* Default is no shutdown_scriptpubkey: free any leftover one. */
|
|
||||||
state->remote_upfront_shutdown_script
|
|
||||||
= tal_free(state->remote_upfront_shutdown_script);
|
|
||||||
|
|
||||||
/* BOLT #2:
|
|
||||||
*
|
|
||||||
* The receiving node MUST fail the channel if:
|
|
||||||
*...
|
|
||||||
* - `funding_pubkey`, `revocation_basepoint`, `htlc_basepoint`,
|
|
||||||
* `payment_basepoint`, or `delayed_payment_basepoint` are not
|
|
||||||
* valid DER-encoded compressed secp256k1 pubkeys.
|
|
||||||
*/
|
|
||||||
if (local_feature_negotiated(state->localfeatures,
|
|
||||||
LOCAL_UPFRONT_SHUTDOWN_SCRIPT)) {
|
|
||||||
if (!fromwire_accept_channel_option_upfront_shutdown_script(state,
|
|
||||||
msg, &id_in,
|
|
||||||
&state->remoteconf.dust_limit,
|
|
||||||
&state->remoteconf.max_htlc_value_in_flight,
|
|
||||||
&state->remoteconf.channel_reserve,
|
|
||||||
&state->remoteconf.htlc_minimum,
|
|
||||||
&state->minimum_depth,
|
|
||||||
&state->remoteconf.to_self_delay,
|
|
||||||
&state->remoteconf.max_accepted_htlcs,
|
|
||||||
&state->their_funding_pubkey,
|
|
||||||
&state->their_points.revocation,
|
|
||||||
&state->their_points.payment,
|
|
||||||
&state->their_points.delayed_payment,
|
|
||||||
&state->their_points.htlc,
|
|
||||||
&state->first_per_commitment_point[REMOTE],
|
|
||||||
&state->remote_upfront_shutdown_script))
|
|
||||||
peer_failed(state->pps,
|
|
||||||
&state->channel_id,
|
|
||||||
"Parsing accept_channel with option_upfront_shutdown_script %s", tal_hex(msg, msg));
|
|
||||||
} else if (!fromwire_accept_channel(msg, &id_in,
|
|
||||||
&state->remoteconf.dust_limit,
|
|
||||||
&state->remoteconf.max_htlc_value_in_flight,
|
|
||||||
&state->remoteconf.channel_reserve,
|
|
||||||
&state->remoteconf.htlc_minimum,
|
|
||||||
&state->minimum_depth,
|
|
||||||
&state->remoteconf.to_self_delay,
|
|
||||||
&state->remoteconf.max_accepted_htlcs,
|
|
||||||
&state->their_funding_pubkey,
|
|
||||||
&state->their_points.revocation,
|
|
||||||
&state->their_points.payment,
|
|
||||||
&state->their_points.delayed_payment,
|
|
||||||
&state->their_points.htlc,
|
|
||||||
&state->first_per_commitment_point[REMOTE]))
|
|
||||||
peer_failed(state->pps,
|
|
||||||
&state->channel_id,
|
|
||||||
"Parsing accept_channel %s", tal_hex(msg, msg));
|
|
||||||
|
|
||||||
/* BOLT #2:
|
|
||||||
*
|
|
||||||
* The `temporary_channel_id` MUST be the same as the
|
|
||||||
* `temporary_channel_id` in the `open_channel` message. */
|
|
||||||
if (!channel_id_eq(&id_in, &state->channel_id))
|
|
||||||
/* In this case we exit, since we don't know what's going on. */
|
|
||||||
peer_failed(state->pps,
|
|
||||||
&state->channel_id,
|
|
||||||
"accept_channel ids don't match: sent %s got %s",
|
|
||||||
type_to_string(msg, struct channel_id, &id_in),
|
|
||||||
type_to_string(msg, struct channel_id,
|
|
||||||
&state->channel_id));
|
|
||||||
|
|
||||||
/* BOLT #2:
|
|
||||||
*
|
|
||||||
* The receiver:
|
|
||||||
* - if `minimum_depth` is unreasonably large:
|
|
||||||
* - MAY reject the channel.
|
|
||||||
*/
|
|
||||||
if (state->minimum_depth > 10) {
|
|
||||||
/* negotiation_failed just tells peer and lightningd
|
|
||||||
* (hence fundchannel call) that this opening failed. */
|
|
||||||
negotiation_failed(state, true,
|
|
||||||
"minimum_depth %u larger than %u",
|
|
||||||
state->minimum_depth, 10);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* BOLT #2:
|
|
||||||
*
|
|
||||||
* The receiver:
|
|
||||||
*...
|
|
||||||
* - if `channel_reserve_satoshis` is less than `dust_limit_satoshis`
|
|
||||||
* within the `open_channel` message:
|
|
||||||
* - MUST reject the channel.
|
|
||||||
*
|
|
||||||
* - if `channel_reserve_satoshis` from the `open_channel` message is
|
|
||||||
* less than `dust_limit_satoshis`:
|
|
||||||
* - MUST reject the channel.
|
|
||||||
*/
|
|
||||||
if (amount_sat_greater(state->localconf.dust_limit,
|
|
||||||
state->remoteconf.channel_reserve)) {
|
|
||||||
negotiation_failed(state, true,
|
|
||||||
"channel reserve %s"
|
|
||||||
" would be below our dust %s",
|
|
||||||
type_to_string(tmpctx, struct amount_sat,
|
|
||||||
&state->remoteconf.channel_reserve),
|
|
||||||
type_to_string(tmpctx, struct amount_sat,
|
|
||||||
&state->localconf.dust_limit));
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (amount_sat_greater(state->remoteconf.dust_limit,
|
|
||||||
state->localconf.channel_reserve)) {
|
|
||||||
negotiation_failed(state, true,
|
|
||||||
"dust limit %s"
|
|
||||||
" would be above our reserve %s",
|
|
||||||
type_to_string(tmpctx, struct amount_sat,
|
|
||||||
&state->remoteconf.dust_limit),
|
|
||||||
type_to_string(tmpctx, struct amount_sat,
|
|
||||||
&state->localconf.channel_reserve));
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!check_config_bounds(state, &state->remoteconf, true))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
/*~ If lightningd told us to create change, use change index to do
|
|
||||||
* that. */
|
|
||||||
if (!amount_sat_eq(change, AMOUNT_SAT(0))) {
|
|
||||||
changekey = tal(tmpctx, struct pubkey);
|
|
||||||
if (!bip32_pubkey(bip32_base, changekey, change_keyindex))
|
|
||||||
status_failed(STATUS_FAIL_MASTER_IO,
|
|
||||||
"Bad change key %u", change_keyindex);
|
|
||||||
} else
|
|
||||||
changekey = NULL;
|
|
||||||
|
|
||||||
/*~ We (and they) actually just need the funding txid and output
|
|
||||||
* number, so we can create the commitment transaction which spends
|
|
||||||
* it; lightningd will recreate it (and have the HSM sign it) when
|
|
||||||
* we've completed opening negotiation.
|
|
||||||
*/
|
|
||||||
funding = funding_tx(state, state->chainparams, &state->funding_txout,
|
|
||||||
cast_const2(const struct utxo **, utxos),
|
|
||||||
state->funding,
|
|
||||||
&state->our_funding_pubkey,
|
|
||||||
&state->their_funding_pubkey,
|
|
||||||
change, changekey,
|
|
||||||
bip32_base);
|
|
||||||
bitcoin_txid(funding, &state->funding_txid);
|
|
||||||
|
|
||||||
if (!funder_finalize_channel_setup(state, local_msat, &sig, &tx)) {
|
|
||||||
tal_free(funding);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (taken(utxos))
|
|
||||||
tal_free(utxos);
|
|
||||||
|
|
||||||
/* BOLT #2:
|
|
||||||
*
|
|
||||||
* The recipient:
|
|
||||||
*...
|
|
||||||
* - on receipt of a valid `funding_signed`:
|
|
||||||
* - SHOULD broadcast the funding transaction.
|
|
||||||
*/
|
|
||||||
/*~ lightningd will save the new channel to the database, and
|
|
||||||
* broadcast the tx. */
|
|
||||||
return towire_opening_funder_reply(state,
|
|
||||||
&state->remoteconf,
|
|
||||||
tx,
|
|
||||||
&sig,
|
|
||||||
state->pps,
|
|
||||||
&state->their_points.revocation,
|
|
||||||
&state->their_points.payment,
|
|
||||||
&state->their_points.htlc,
|
|
||||||
&state->their_points.delayed_payment,
|
|
||||||
&state->first_per_commitment_point[REMOTE],
|
|
||||||
state->minimum_depth,
|
|
||||||
&state->their_funding_pubkey,
|
|
||||||
&state->funding_txid,
|
|
||||||
state->funding_txout,
|
|
||||||
state->feerate_per_kw,
|
|
||||||
state->localconf.channel_reserve,
|
|
||||||
state->remote_upfront_shutdown_script);
|
|
||||||
|
|
||||||
fail:
|
|
||||||
if (taken(utxos))
|
|
||||||
tal_free(utxos);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*~ The peer sent us an `open_channel`, that means we're the fundee. */
|
/*~ The peer sent us an `open_channel`, that means we're the fundee. */
|
||||||
static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg)
|
static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg)
|
||||||
{
|
{
|
||||||
@@ -1596,31 +1341,11 @@ static u8 *handle_master_in(struct state *state)
|
|||||||
{
|
{
|
||||||
u8 *msg = wire_sync_read(tmpctx, REQ_FD);
|
u8 *msg = wire_sync_read(tmpctx, REQ_FD);
|
||||||
enum opening_wire_type t = fromwire_peektype(msg);
|
enum opening_wire_type t = fromwire_peektype(msg);
|
||||||
struct amount_sat change;
|
|
||||||
u32 change_keyindex;
|
|
||||||
u8 channel_flags;
|
u8 channel_flags;
|
||||||
struct bitcoin_txid funding_txid;
|
struct bitcoin_txid funding_txid;
|
||||||
u16 funding_txout;
|
u16 funding_txout;
|
||||||
struct utxo **utxos;
|
|
||||||
struct ext_key bip32_base;
|
|
||||||
|
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case WIRE_OPENING_FUNDER:
|
|
||||||
if (!fromwire_opening_funder(state, msg,
|
|
||||||
&state->funding,
|
|
||||||
&state->push_msat,
|
|
||||||
&state->feerate_per_kw,
|
|
||||||
&change,
|
|
||||||
&change_keyindex,
|
|
||||||
&channel_flags, &utxos,
|
|
||||||
&bip32_base))
|
|
||||||
master_badmsg(WIRE_OPENING_FUNDER, msg);
|
|
||||||
|
|
||||||
msg = funder_channel(state,
|
|
||||||
change,
|
|
||||||
change_keyindex, channel_flags,
|
|
||||||
take(utxos), &bip32_base);
|
|
||||||
return msg;
|
|
||||||
case WIRE_OPENING_FUNDER_START:
|
case WIRE_OPENING_FUNDER_START:
|
||||||
if (!fromwire_opening_funder_start(msg, &state->funding,
|
if (!fromwire_opening_funder_start(msg, &state->funding,
|
||||||
&state->push_msat,
|
&state->push_msat,
|
||||||
|
|||||||
@@ -420,9 +420,8 @@ static void init(struct plugin_conn *rpc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// id, satoshi, feerate, announce, minconf, utxos
|
|
||||||
static const struct plugin_command commands[] = { {
|
static const struct plugin_command commands[] = { {
|
||||||
"fc",
|
"fundchannel",
|
||||||
"channels",
|
"channels",
|
||||||
"Fund channel with {id} using {satoshi} (or 'all'), at optional {feerate}. "
|
"Fund channel with {id} using {satoshi} (or 'all'), at optional {feerate}. "
|
||||||
"Only use outputs that have {minconf} confirmations.",
|
"Only use outputs that have {minconf} confirmations.",
|
||||||
|
|||||||
@@ -1552,8 +1552,11 @@ def test_option_upfront_shutdown_script(node_factory, bitcoind):
|
|||||||
# Figure out what address it will try to use.
|
# Figure out what address it will try to use.
|
||||||
keyidx = int(l1.db_query("SELECT val FROM vars WHERE name='bip32_max_index';")[0]['val'])
|
keyidx = int(l1.db_query("SELECT val FROM vars WHERE name='bip32_max_index';")[0]['val'])
|
||||||
|
|
||||||
# Expect 1 for change address, 1 for the channel final address.
|
# Expect 1 for change address, 1 for the channel final address,
|
||||||
addr = l1.rpc.call('dev-listaddrs', [keyidx + 2])['addresses'][-1]
|
# which are discarded as the 'scratch' tx that the fundchannel
|
||||||
|
# plugin makes, plus 1 for the funding address of the actual
|
||||||
|
# funding tx.
|
||||||
|
addr = l1.rpc.call('dev-listaddrs', [keyidx + 3])['addresses'][-1]
|
||||||
|
|
||||||
# Now, if we specify upfront and it's OK, all good.
|
# Now, if we specify upfront and it's OK, all good.
|
||||||
l1.stop()
|
l1.stop()
|
||||||
|
|||||||
Reference in New Issue
Block a user