mirror of
https://github.com/aljazceru/lightning.git
synced 2026-01-06 07:34:21 +01:00
mfc: invert some more
Move only.
This commit is contained in:
@@ -51,6 +51,12 @@ size_t dest_count(const struct multifundchannel_command *mfc,
|
||||
return count;
|
||||
}
|
||||
|
||||
/* Return true if this destination failed, false otherwise. */
|
||||
static bool dest_failed(struct multifundchannel_destination *dest)
|
||||
{
|
||||
return dest->state == MULTIFUNDCHANNEL_FAILED;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
Command Cleanup
|
||||
-----------------------------------------------------------------------------*/
|
||||
@@ -581,304 +587,6 @@ connect_dest(struct multifundchannel_destination *dest)
|
||||
send_outreq(cmd->plugin, req);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*~ Create an initial funding PSBT.
|
||||
|
||||
This creation of the initial funding PSBT is solely to reserve inputs for
|
||||
our use.
|
||||
This lets us initiate later with fundchannel_start with confidence that we
|
||||
can actually afford the channels we will create.
|
||||
*/
|
||||
|
||||
static struct command_result *
|
||||
perform_channel_start(struct multifundchannel_command *mfc);
|
||||
|
||||
static struct command_result *
|
||||
mfc_psbt_acquired(struct multifundchannel_command *mfc)
|
||||
{
|
||||
/* Add serials to all of our input/outputs, so they're stable
|
||||
* for the life of the tx */
|
||||
psbt_add_serials(mfc->psbt, TX_INITIATOR);
|
||||
|
||||
/* We also mark all of our inputs as *ours*, so we
|
||||
* can easily identify them for `signpsbt`, later */
|
||||
for (size_t i = 0; i < mfc->psbt->num_inputs; i++)
|
||||
psbt_input_mark_ours(mfc->psbt, &mfc->psbt->inputs[i]);
|
||||
|
||||
return perform_channel_start(mfc);
|
||||
}
|
||||
|
||||
static struct command_result *
|
||||
after_newaddr(struct command *cmd,
|
||||
const char *buf,
|
||||
const jsmntok_t *result,
|
||||
struct multifundchannel_command *mfc)
|
||||
{
|
||||
const jsmntok_t *field;
|
||||
|
||||
field = json_get_member(buf, result, "bech32");
|
||||
if (!field)
|
||||
plugin_err(cmd->plugin,
|
||||
"No bech32 field in newaddr result: %.*s",
|
||||
json_tok_full_len(result),
|
||||
json_tok_full(buf, result));
|
||||
if (json_to_address_scriptpubkey(mfc, chainparams, buf, field,
|
||||
&mfc->change_scriptpubkey)
|
||||
!= ADDRESS_PARSE_SUCCESS)
|
||||
plugin_err(cmd->plugin,
|
||||
"Unparseable bech32 field in newaddr result: %.*s",
|
||||
json_tok_full_len(result),
|
||||
json_tok_full(buf, result));
|
||||
|
||||
return mfc_psbt_acquired(mfc);
|
||||
}
|
||||
|
||||
static struct command_result *
|
||||
acquire_change_address(struct multifundchannel_command *mfc)
|
||||
{
|
||||
struct out_req *req;
|
||||
req = jsonrpc_request_start(mfc->cmd->plugin, mfc->cmd,
|
||||
"newaddr",
|
||||
&after_newaddr, &mfc_forward_error,
|
||||
mfc);
|
||||
json_add_string(req->js, "addresstype", "bech32");
|
||||
return send_outreq(mfc->cmd->plugin, req);
|
||||
}
|
||||
|
||||
static struct command_result *
|
||||
handle_mfc_change(struct multifundchannel_command *mfc)
|
||||
{
|
||||
size_t change_weight;
|
||||
struct amount_sat change_fee, fee_paid, total_fee;
|
||||
struct amount_sat change_min_limit;
|
||||
|
||||
/* Determine if adding a change output is worth it.
|
||||
* Get the weight of a change output and how much it
|
||||
* costs.
|
||||
*/
|
||||
change_weight = bitcoin_tx_output_weight(
|
||||
BITCOIN_SCRIPTPUBKEY_P2WPKH_LEN);
|
||||
|
||||
/* To avoid 'off-by-one' errors due to rounding down
|
||||
* (which we do in `amount_tx_fee`), we find the total calculated
|
||||
* fees (estimated_weight + change weight @ feerate) and subtract
|
||||
* the originally calculated fees (estimated_weight @ feerate) */
|
||||
fee_paid = amount_tx_fee(mfc->feerate_per_kw,
|
||||
mfc->estimated_final_weight);
|
||||
total_fee = amount_tx_fee(mfc->feerate_per_kw,
|
||||
mfc->estimated_final_weight + change_weight);
|
||||
if (!amount_sat_sub(&change_fee, total_fee, fee_paid))
|
||||
abort();
|
||||
|
||||
/* The limit is equal to the change_fee plus the dust limit. */
|
||||
if (!amount_sat_add(&change_min_limit,
|
||||
change_fee, chainparams->dust_limit))
|
||||
plugin_err(mfc->cmd->plugin,
|
||||
"Overflow dust limit and change fee.");
|
||||
|
||||
/* Is the excess over the limit? */
|
||||
if (amount_sat_greater(mfc->excess_sat, change_min_limit)) {
|
||||
bool ok = amount_sat_sub(&mfc->change_amount,
|
||||
mfc->excess_sat, change_fee);
|
||||
assert(ok);
|
||||
mfc->change_needed = true;
|
||||
if (!mfc->change_scriptpubkey)
|
||||
return acquire_change_address(mfc);
|
||||
} else
|
||||
mfc->change_needed = false;
|
||||
|
||||
return mfc_psbt_acquired(mfc);
|
||||
}
|
||||
|
||||
/* If one of the destinations specified "all", figure out how much that is. */
|
||||
static struct command_result *
|
||||
compute_mfc_all(struct multifundchannel_command *mfc)
|
||||
{
|
||||
size_t all_index = SIZE_MAX;
|
||||
struct multifundchannel_destination *all_dest;
|
||||
|
||||
assert(has_all(mfc));
|
||||
|
||||
for (size_t i = 0; i < tal_count(mfc->destinations); ++i) {
|
||||
struct multifundchannel_destination *dest;
|
||||
dest = &mfc->destinations[i];
|
||||
if (dest->all) {
|
||||
assert(all_index == SIZE_MAX);
|
||||
all_index = i;
|
||||
continue;
|
||||
}
|
||||
/* Subtract the amount from the excess. */
|
||||
if (!amount_sat_sub(&mfc->excess_sat,
|
||||
mfc->excess_sat, dest->amount))
|
||||
/* Not enough funds! */
|
||||
return mfc_fail(mfc, FUND_CANNOT_AFFORD,
|
||||
"Insufficient funds.");
|
||||
}
|
||||
assert(all_index != SIZE_MAX);
|
||||
all_dest = &mfc->destinations[all_index];
|
||||
|
||||
/* Is the excess above the dust amount? */
|
||||
if (amount_sat_less(mfc->excess_sat, chainparams->dust_limit))
|
||||
return mfc_fail(mfc, FUND_OUTPUT_IS_DUST,
|
||||
"Output 'all' %s would be dust",
|
||||
type_to_string(tmpctx, struct amount_sat,
|
||||
&mfc->excess_sat));
|
||||
|
||||
/* Assign the remainder to the 'all' output. */
|
||||
all_dest->amount = mfc->excess_sat;
|
||||
if (!feature_negotiated(plugin_feature_set(mfc->cmd->plugin),
|
||||
all_dest->their_features,
|
||||
OPT_LARGE_CHANNELS)
|
||||
&& amount_sat_greater(all_dest->amount,
|
||||
chainparams->max_funding))
|
||||
all_dest->amount = chainparams->max_funding;
|
||||
/* Remove it from the excess. */
|
||||
bool ok = amount_sat_sub(&mfc->excess_sat,
|
||||
mfc->excess_sat, all_dest->amount);
|
||||
assert(ok);
|
||||
/* Remove the 'all' flag. */
|
||||
all_dest->all = false;
|
||||
|
||||
/* Continue. */
|
||||
return handle_mfc_change(mfc);
|
||||
}
|
||||
|
||||
static struct command_result *
|
||||
after_fundpsbt(struct command *cmd,
|
||||
const char *buf,
|
||||
const jsmntok_t *result,
|
||||
struct multifundchannel_command *mfc)
|
||||
{
|
||||
const jsmntok_t *field;
|
||||
|
||||
plugin_log(mfc->cmd->plugin, LOG_DBG,
|
||||
"mfc %"PRIu64": %s done.",
|
||||
mfc->id, mfc->utxos_str ? "utxopsbt" : "fundpsbt");
|
||||
|
||||
field = json_get_member(buf, result, "psbt");
|
||||
if (!field)
|
||||
goto fail;
|
||||
|
||||
mfc->psbt = psbt_from_b64(mfc,
|
||||
buf + field->start,
|
||||
field->end - field->start);
|
||||
if (!mfc->psbt)
|
||||
goto fail;
|
||||
|
||||
field = json_get_member(buf, result, "feerate_per_kw");
|
||||
if (!field || !json_to_u32(buf, field, &mfc->feerate_per_kw))
|
||||
goto fail;
|
||||
|
||||
field = json_get_member(buf, result, "estimated_final_weight");
|
||||
if (!field || !json_to_u32(buf, field, &mfc->estimated_final_weight))
|
||||
goto fail;
|
||||
|
||||
/* msat LOL. */
|
||||
field = json_get_member(buf, result, "excess_msat");
|
||||
if (!field || !parse_amount_sat(&mfc->excess_sat,
|
||||
buf + field->start,
|
||||
field->end - field->start))
|
||||
goto fail;
|
||||
|
||||
if (has_all(mfc))
|
||||
return compute_mfc_all(mfc);
|
||||
return handle_mfc_change(mfc);
|
||||
|
||||
fail:
|
||||
plugin_err(mfc->cmd->plugin,
|
||||
"Unexpected result from fundpsbt/utxopsbt: %.*s",
|
||||
json_tok_full_len(result),
|
||||
json_tok_full(buf, result));
|
||||
|
||||
}
|
||||
|
||||
|
||||
static struct command_result *
|
||||
perform_fundpsbt(struct multifundchannel_command *mfc)
|
||||
{
|
||||
struct out_req *req;
|
||||
|
||||
/* If the user specified utxos we should use utxopsbt instead
|
||||
* of fundpsbt. */
|
||||
if (mfc->utxos_str) {
|
||||
plugin_log(mfc->cmd->plugin, LOG_DBG,
|
||||
"mfc %"PRIu64": utxopsbt.",
|
||||
mfc->id);
|
||||
|
||||
req = jsonrpc_request_start(mfc->cmd->plugin,
|
||||
mfc->cmd,
|
||||
"utxopsbt",
|
||||
&after_fundpsbt,
|
||||
&mfc_forward_error,
|
||||
mfc);
|
||||
json_add_jsonstr(req->js, "utxos", mfc->utxos_str);
|
||||
json_add_bool(req->js, "reservedok", false);
|
||||
} else {
|
||||
plugin_log(mfc->cmd->plugin, LOG_DBG,
|
||||
"mfc %"PRIu64": fundpsbt.",
|
||||
mfc->id);
|
||||
|
||||
req = jsonrpc_request_start(mfc->cmd->plugin,
|
||||
mfc->cmd,
|
||||
"fundpsbt",
|
||||
&after_fundpsbt,
|
||||
&mfc_forward_error,
|
||||
mfc);
|
||||
json_add_u32(req->js, "minconf", mfc->minconf);
|
||||
}
|
||||
|
||||
/* The entire point is to reserve the inputs. */
|
||||
json_add_bool(req->js, "reserve", true);
|
||||
/* How much do we need to reserve? */
|
||||
if (has_all(mfc))
|
||||
json_add_string(req->js, "satoshi", "all");
|
||||
else {
|
||||
struct amount_sat sum = AMOUNT_SAT(0);
|
||||
for (size_t i = 0; i < tal_count(mfc->destinations); ++i) {
|
||||
if (!amount_sat_add(&sum,
|
||||
sum, mfc->destinations[i].amount))
|
||||
return mfc_fail(mfc, JSONRPC2_INVALID_PARAMS,
|
||||
"Overflow while summing "
|
||||
"destination values.");
|
||||
}
|
||||
json_add_string(req->js, "satoshi",
|
||||
type_to_string(tmpctx, struct amount_sat,
|
||||
&sum));
|
||||
}
|
||||
json_add_string(req->js, "feerate",
|
||||
mfc->feerate_str ? mfc->feerate_str : "normal");
|
||||
|
||||
{
|
||||
size_t startweight;
|
||||
size_t num_outs = tal_count(mfc->destinations);
|
||||
/* Assume 1 input.
|
||||
* As long as lightningd does not select more than 252
|
||||
* inputs, that estimation should be correct.
|
||||
*/
|
||||
startweight = bitcoin_tx_core_weight(1, num_outs)
|
||||
+ ( bitcoin_tx_output_weight(
|
||||
BITCOIN_SCRIPTPUBKEY_P2WSH_LEN)
|
||||
* num_outs
|
||||
);
|
||||
json_add_string(req->js, "startweight",
|
||||
tal_fmt(tmpctx, "%zu", startweight));
|
||||
}
|
||||
|
||||
/* If we've got v2 opens, we need to use a min weight of 110. */
|
||||
/* BOLT-f53ca2301232db780843e894f55d95d512f297f9 #3:
|
||||
* The minimum witness weight for an input is 110.
|
||||
*/
|
||||
if (dest_count(mfc, OPEN_CHANNEL) > 0) {
|
||||
json_add_string(req->js, "min_witness_weight",
|
||||
tal_fmt(tmpctx, "%u", 110));
|
||||
}
|
||||
|
||||
|
||||
return send_outreq(mfc->cmd->plugin, req);
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*~
|
||||
@@ -1627,12 +1335,6 @@ fundchannel_complete_dest(struct multifundchannel_destination *dest)
|
||||
send_outreq(cmd->plugin, req);
|
||||
}
|
||||
|
||||
/* Return true if this destination failed, false otherwise. */
|
||||
static bool dest_failed(struct multifundchannel_destination *dest)
|
||||
{
|
||||
return dest->state == MULTIFUNDCHANNEL_FAILED;
|
||||
}
|
||||
|
||||
void fail_destination(struct multifundchannel_destination *dest,
|
||||
char *error TAKES)
|
||||
{
|
||||
@@ -1644,21 +1346,302 @@ void fail_destination(struct multifundchannel_destination *dest,
|
||||
dest->error = tal_strdup(dest->mfc, error);
|
||||
}
|
||||
|
||||
static struct command_result *param_positive_number(struct command *cmd,
|
||||
const char *name,
|
||||
const char *buffer,
|
||||
const jsmntok_t *tok,
|
||||
unsigned int **num)
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*~ Create an initial funding PSBT.
|
||||
|
||||
This creation of the initial funding PSBT is solely to reserve inputs for
|
||||
our use.
|
||||
This lets us initiate later with fundchannel_start with confidence that we
|
||||
can actually afford the channels we will create.
|
||||
*/
|
||||
|
||||
static struct command_result *
|
||||
mfc_psbt_acquired(struct multifundchannel_command *mfc)
|
||||
{
|
||||
struct command_result *res = param_number(cmd, name, buffer, tok, num);
|
||||
if (res)
|
||||
return res;
|
||||
if (**num == 0)
|
||||
return command_fail_badparam(cmd, name, buffer, tok,
|
||||
"should be a positive integer");
|
||||
return NULL;
|
||||
/* Add serials to all of our input/outputs, so they're stable
|
||||
* for the life of the tx */
|
||||
psbt_add_serials(mfc->psbt, TX_INITIATOR);
|
||||
|
||||
/* We also mark all of our inputs as *ours*, so we
|
||||
* can easily identify them for `signpsbt`, later */
|
||||
for (size_t i = 0; i < mfc->psbt->num_inputs; i++)
|
||||
psbt_input_mark_ours(mfc->psbt, &mfc->psbt->inputs[i]);
|
||||
|
||||
return perform_channel_start(mfc);
|
||||
}
|
||||
|
||||
static struct command_result *
|
||||
after_newaddr(struct command *cmd,
|
||||
const char *buf,
|
||||
const jsmntok_t *result,
|
||||
struct multifundchannel_command *mfc)
|
||||
{
|
||||
const jsmntok_t *field;
|
||||
|
||||
field = json_get_member(buf, result, "bech32");
|
||||
if (!field)
|
||||
plugin_err(cmd->plugin,
|
||||
"No bech32 field in newaddr result: %.*s",
|
||||
json_tok_full_len(result),
|
||||
json_tok_full(buf, result));
|
||||
if (json_to_address_scriptpubkey(mfc, chainparams, buf, field,
|
||||
&mfc->change_scriptpubkey)
|
||||
!= ADDRESS_PARSE_SUCCESS)
|
||||
plugin_err(cmd->plugin,
|
||||
"Unparseable bech32 field in newaddr result: %.*s",
|
||||
json_tok_full_len(result),
|
||||
json_tok_full(buf, result));
|
||||
|
||||
return mfc_psbt_acquired(mfc);
|
||||
}
|
||||
|
||||
static struct command_result *
|
||||
acquire_change_address(struct multifundchannel_command *mfc)
|
||||
{
|
||||
struct out_req *req;
|
||||
req = jsonrpc_request_start(mfc->cmd->plugin, mfc->cmd,
|
||||
"newaddr",
|
||||
&after_newaddr, &mfc_forward_error,
|
||||
mfc);
|
||||
json_add_string(req->js, "addresstype", "bech32");
|
||||
return send_outreq(mfc->cmd->plugin, req);
|
||||
}
|
||||
|
||||
static struct command_result *
|
||||
handle_mfc_change(struct multifundchannel_command *mfc)
|
||||
{
|
||||
size_t change_weight;
|
||||
struct amount_sat change_fee, fee_paid, total_fee;
|
||||
struct amount_sat change_min_limit;
|
||||
|
||||
/* Determine if adding a change output is worth it.
|
||||
* Get the weight of a change output and how much it
|
||||
* costs.
|
||||
*/
|
||||
change_weight = bitcoin_tx_output_weight(
|
||||
BITCOIN_SCRIPTPUBKEY_P2WPKH_LEN);
|
||||
|
||||
/* To avoid 'off-by-one' errors due to rounding down
|
||||
* (which we do in `amount_tx_fee`), we find the total calculated
|
||||
* fees (estimated_weight + change weight @ feerate) and subtract
|
||||
* the originally calculated fees (estimated_weight @ feerate) */
|
||||
fee_paid = amount_tx_fee(mfc->feerate_per_kw,
|
||||
mfc->estimated_final_weight);
|
||||
total_fee = amount_tx_fee(mfc->feerate_per_kw,
|
||||
mfc->estimated_final_weight + change_weight);
|
||||
if (!amount_sat_sub(&change_fee, total_fee, fee_paid))
|
||||
abort();
|
||||
|
||||
/* The limit is equal to the change_fee plus the dust limit. */
|
||||
if (!amount_sat_add(&change_min_limit,
|
||||
change_fee, chainparams->dust_limit))
|
||||
plugin_err(mfc->cmd->plugin,
|
||||
"Overflow dust limit and change fee.");
|
||||
|
||||
/* Is the excess over the limit? */
|
||||
if (amount_sat_greater(mfc->excess_sat, change_min_limit)) {
|
||||
bool ok = amount_sat_sub(&mfc->change_amount,
|
||||
mfc->excess_sat, change_fee);
|
||||
assert(ok);
|
||||
mfc->change_needed = true;
|
||||
if (!mfc->change_scriptpubkey)
|
||||
return acquire_change_address(mfc);
|
||||
} else
|
||||
mfc->change_needed = false;
|
||||
|
||||
return mfc_psbt_acquired(mfc);
|
||||
}
|
||||
|
||||
/* If one of the destinations specified "all", figure out how much that is. */
|
||||
static struct command_result *
|
||||
compute_mfc_all(struct multifundchannel_command *mfc)
|
||||
{
|
||||
size_t all_index = SIZE_MAX;
|
||||
struct multifundchannel_destination *all_dest;
|
||||
|
||||
assert(has_all(mfc));
|
||||
|
||||
for (size_t i = 0; i < tal_count(mfc->destinations); ++i) {
|
||||
struct multifundchannel_destination *dest;
|
||||
dest = &mfc->destinations[i];
|
||||
if (dest->all) {
|
||||
assert(all_index == SIZE_MAX);
|
||||
all_index = i;
|
||||
continue;
|
||||
}
|
||||
/* Subtract the amount from the excess. */
|
||||
if (!amount_sat_sub(&mfc->excess_sat,
|
||||
mfc->excess_sat, dest->amount))
|
||||
/* Not enough funds! */
|
||||
return mfc_fail(mfc, FUND_CANNOT_AFFORD,
|
||||
"Insufficient funds.");
|
||||
}
|
||||
assert(all_index != SIZE_MAX);
|
||||
all_dest = &mfc->destinations[all_index];
|
||||
|
||||
/* Is the excess above the dust amount? */
|
||||
if (amount_sat_less(mfc->excess_sat, chainparams->dust_limit))
|
||||
return mfc_fail(mfc, FUND_OUTPUT_IS_DUST,
|
||||
"Output 'all' %s would be dust",
|
||||
type_to_string(tmpctx, struct amount_sat,
|
||||
&mfc->excess_sat));
|
||||
|
||||
/* Assign the remainder to the 'all' output. */
|
||||
all_dest->amount = mfc->excess_sat;
|
||||
if (!feature_negotiated(plugin_feature_set(mfc->cmd->plugin),
|
||||
all_dest->their_features,
|
||||
OPT_LARGE_CHANNELS)
|
||||
&& amount_sat_greater(all_dest->amount,
|
||||
chainparams->max_funding))
|
||||
all_dest->amount = chainparams->max_funding;
|
||||
/* Remove it from the excess. */
|
||||
bool ok = amount_sat_sub(&mfc->excess_sat,
|
||||
mfc->excess_sat, all_dest->amount);
|
||||
assert(ok);
|
||||
/* Remove the 'all' flag. */
|
||||
all_dest->all = false;
|
||||
|
||||
/* Continue. */
|
||||
return handle_mfc_change(mfc);
|
||||
}
|
||||
|
||||
static struct command_result *
|
||||
after_fundpsbt(struct command *cmd,
|
||||
const char *buf,
|
||||
const jsmntok_t *result,
|
||||
struct multifundchannel_command *mfc)
|
||||
{
|
||||
const jsmntok_t *field;
|
||||
|
||||
plugin_log(mfc->cmd->plugin, LOG_DBG,
|
||||
"mfc %"PRIu64": %s done.",
|
||||
mfc->id, mfc->utxos_str ? "utxopsbt" : "fundpsbt");
|
||||
|
||||
field = json_get_member(buf, result, "psbt");
|
||||
if (!field)
|
||||
goto fail;
|
||||
|
||||
mfc->psbt = psbt_from_b64(mfc,
|
||||
buf + field->start,
|
||||
field->end - field->start);
|
||||
if (!mfc->psbt)
|
||||
goto fail;
|
||||
|
||||
field = json_get_member(buf, result, "feerate_per_kw");
|
||||
if (!field || !json_to_u32(buf, field, &mfc->feerate_per_kw))
|
||||
goto fail;
|
||||
|
||||
field = json_get_member(buf, result, "estimated_final_weight");
|
||||
if (!field || !json_to_u32(buf, field, &mfc->estimated_final_weight))
|
||||
goto fail;
|
||||
|
||||
/* msat LOL. */
|
||||
field = json_get_member(buf, result, "excess_msat");
|
||||
if (!field || !parse_amount_sat(&mfc->excess_sat,
|
||||
buf + field->start,
|
||||
field->end - field->start))
|
||||
goto fail;
|
||||
|
||||
if (has_all(mfc))
|
||||
return compute_mfc_all(mfc);
|
||||
return handle_mfc_change(mfc);
|
||||
|
||||
fail:
|
||||
plugin_err(mfc->cmd->plugin,
|
||||
"Unexpected result from fundpsbt/utxopsbt: %.*s",
|
||||
json_tok_full_len(result),
|
||||
json_tok_full(buf, result));
|
||||
|
||||
}
|
||||
|
||||
|
||||
static struct command_result *
|
||||
perform_fundpsbt(struct multifundchannel_command *mfc)
|
||||
{
|
||||
struct out_req *req;
|
||||
|
||||
/* If the user specified utxos we should use utxopsbt instead
|
||||
* of fundpsbt. */
|
||||
if (mfc->utxos_str) {
|
||||
plugin_log(mfc->cmd->plugin, LOG_DBG,
|
||||
"mfc %"PRIu64": utxopsbt.",
|
||||
mfc->id);
|
||||
|
||||
req = jsonrpc_request_start(mfc->cmd->plugin,
|
||||
mfc->cmd,
|
||||
"utxopsbt",
|
||||
&after_fundpsbt,
|
||||
&mfc_forward_error,
|
||||
mfc);
|
||||
json_add_jsonstr(req->js, "utxos", mfc->utxos_str);
|
||||
json_add_bool(req->js, "reservedok", false);
|
||||
} else {
|
||||
plugin_log(mfc->cmd->plugin, LOG_DBG,
|
||||
"mfc %"PRIu64": fundpsbt.",
|
||||
mfc->id);
|
||||
|
||||
req = jsonrpc_request_start(mfc->cmd->plugin,
|
||||
mfc->cmd,
|
||||
"fundpsbt",
|
||||
&after_fundpsbt,
|
||||
&mfc_forward_error,
|
||||
mfc);
|
||||
json_add_u32(req->js, "minconf", mfc->minconf);
|
||||
}
|
||||
|
||||
/* The entire point is to reserve the inputs. */
|
||||
json_add_bool(req->js, "reserve", true);
|
||||
/* How much do we need to reserve? */
|
||||
if (has_all(mfc))
|
||||
json_add_string(req->js, "satoshi", "all");
|
||||
else {
|
||||
struct amount_sat sum = AMOUNT_SAT(0);
|
||||
for (size_t i = 0; i < tal_count(mfc->destinations); ++i) {
|
||||
if (!amount_sat_add(&sum,
|
||||
sum, mfc->destinations[i].amount))
|
||||
return mfc_fail(mfc, JSONRPC2_INVALID_PARAMS,
|
||||
"Overflow while summing "
|
||||
"destination values.");
|
||||
}
|
||||
json_add_string(req->js, "satoshi",
|
||||
type_to_string(tmpctx, struct amount_sat,
|
||||
&sum));
|
||||
}
|
||||
json_add_string(req->js, "feerate",
|
||||
mfc->feerate_str ? mfc->feerate_str : "normal");
|
||||
|
||||
{
|
||||
size_t startweight;
|
||||
size_t num_outs = tal_count(mfc->destinations);
|
||||
/* Assume 1 input.
|
||||
* As long as lightningd does not select more than 252
|
||||
* inputs, that estimation should be correct.
|
||||
*/
|
||||
startweight = bitcoin_tx_core_weight(1, num_outs)
|
||||
+ ( bitcoin_tx_output_weight(
|
||||
BITCOIN_SCRIPTPUBKEY_P2WSH_LEN)
|
||||
* num_outs
|
||||
);
|
||||
json_add_string(req->js, "startweight",
|
||||
tal_fmt(tmpctx, "%zu", startweight));
|
||||
}
|
||||
|
||||
/* If we've got v2 opens, we need to use a min weight of 110. */
|
||||
/* BOLT-f53ca2301232db780843e894f55d95d512f297f9 #3:
|
||||
* The minimum witness weight for an input is 110.
|
||||
*/
|
||||
if (dest_count(mfc, OPEN_CHANNEL) > 0) {
|
||||
json_add_string(req->js, "min_witness_weight",
|
||||
tal_fmt(tmpctx, "%u", 110));
|
||||
}
|
||||
|
||||
|
||||
return send_outreq(mfc->cmd->plugin, req);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
Starting
|
||||
-----------------------------------------------------------------------------*/
|
||||
@@ -1819,6 +1802,22 @@ redo_multifundchannel(struct multifundchannel_command *mfc,
|
||||
/*-----------------------------------------------------------------------------
|
||||
Command Entry Point
|
||||
-----------------------------------------------------------------------------*/
|
||||
static struct command_result *
|
||||
param_positive_number(struct command *cmd,
|
||||
const char *name,
|
||||
const char *buffer,
|
||||
const jsmntok_t *tok,
|
||||
unsigned int **num)
|
||||
{
|
||||
struct command_result *res = param_number(cmd, name, buffer, tok, num);
|
||||
if (res)
|
||||
return res;
|
||||
if (**num == 0)
|
||||
return command_fail_badparam(cmd, name, buffer, tok,
|
||||
"should be a positive integer");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Entry function. */
|
||||
static struct command_result *
|
||||
|
||||
Reference in New Issue
Block a user