-
Notifications
You must be signed in to change notification settings - Fork 906
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
closingd: configurable closing fee negotiation step #3390
Conversation
To complete this PR:
Specifying the negotiation step and starting fee if we are not the side that initiated the channel close is left away from this PR. |
Would not an option to the
Given that the closing fee is paid for by the side which opened the channel ("initiator pays" principle which closes some active griefing attacks), perhaps it should only matter for such channels where I opened but the other side wants to close? In such a case perhaps it should be stubborn as well. Detecting the stubborn closing behavior from the closing peer might also be an option to trigger stubborn closing behavior on our side when we are not the one initiating the close. |
@ZmnSCPxj yes, an option to the We have two new config options (per channel): 1. closing negotiation step (as What about this:
|
@ZmnSCPxj, What would be the best way to pass an option of the close command to the fee negotiating code? That is - adding a new option to the close command would mean that json_close() will receive it and then it needs to pass it somehow down the call chain, through the daemons towards closingd. |
Not sure, maybe add a field to |
Yes, I did exactly that after some staring at the code! Need to clean up the patch and will push it here. I am not yet sure what would happen if lightningd gets restarted during the close fee negotiation. I guess the newly added option telling it how to negotiate would be lost. |
Done, ready for review. The first commit (mocks re-record) belongs to a separate PR, but then this PR would depend on it. Should I create a separate PR for it? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find it really cool to be able to greed on closing fees, could it be made to directly set the step for even more customability ?
Yes, this would be even more flexible. So we have an interval, lets say The current code chooses This PR adds an option to pick What about instead of adding a close parameter
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking forward to test it along with https://github.com/darosior/lightning/tree/set_closing_fees !
Fwiw I opted for another command in the above for the we-don't-initiated-the-close case.
closingd/closingd.c
Outdated
* one from our previous proposal. So, if the user requested a | ||
* step of 1 satoshi at a time we should just return our end of | ||
* the range from this function. */ | ||
step = (struct amount_sat){fee_negotiation_step - 1}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
amount_sat_from_u64()
? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean to add a new function amount_sat_from_u64()
? Are there other places in the code that would benefit from it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok I confused with msat_from_u64()
...
Line 375 in e99ab03
void amount_msat_from_u64(struct amount_msat *msat, u64 millisatoshis) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That can still be used, but I think would be too cumbersome:
struct amount_msat step_msat;
...
amount_msat_from_u64(&step_msat, (fee_negotiation_step - 1) * MSAT_PER_SAT);
step = amount_msat_to_sat_round_down(step_msat);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done that way with amount_msat_from_u64()
because the typecast was upsetting make check-amount-access
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you are still better off adding the helper for sat
, but it can be done in a follow up cleanup, I think?
662c351
to
9ab236a
Compare
7b99bd8
to
6cb74f8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 6cb74f8
1202797
to
45d9d9f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
re-ACK 45d9d9f
Use `LC_ALL=C sort` instead of `sort` so that mocks get sorted in the same way on all developers' environments. Re-record the result of `make update-mocks`. Changelog-None
When negotiating the transaction fee for closing a channel [1], we used to always pick the middle of the range between our proposal and the peer's proposal. Introduce a new option `fee_negotiation_step` to the close command, so the peer who initiates the close can choose his back off step. Partially resolves ElementsProject#3270 [1] https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md#closing-negotiation-closing_signed Changelog-Added: New optional parameter to the `close` command to control the closing transaction fee negotiation back off step
Rebased due to conflicts with master. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ack 26c25ca
Minor nits which can be fixed after, IMHO.
CLOSING_FEE_NEGOTIATION_STEP_UNIT_PERCENTAGE | ||
? "%" | ||
: "sat"); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tal_fmt() is generally safer than snprintf, BTW.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was using tal_fmt()
in a previous incarnation of this PR. However, that ended up with an obscure use-after-free:
- create the string with
tal_fmt()
fromtmpctx
- print the string with
status_debug()
- call
do_reconnect()
which callsclosing_read_peer_msg()
which callsclean_tmpctx()
which freestmpctx
- try to print the string with
peer_billboard()
, but it is already freed
different than our estimate. On every negotiation step we must give up | ||
some amount from our proposal towards the peer's proposal. This parameter | ||
can be an integer in which case it is interpreted as number of satoshis | ||
to step at a time. Or it can be an integer followed by "%s" to designate |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"%s"? Not sure where the 's' came from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in a followup PR. I must have been in C-mode-autopilot when writing the .md file.
|
||
if (!param(cmd, buffer, params, | ||
p_req("id", param_tok, &idtok), | ||
p_opt_def("unilateraltimeout", param_number, &timeout, | ||
48 * 3600), | ||
p_opt("destination", param_bitcoin_address, &close_to_script), | ||
p_opt("fee_negotiation_step", param_string, | ||
&fee_negotiation_step_str), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally better to write a param handler for this: that way "check" calls it and does more checking for the caller.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something like this:
patch
commit ef31b2b4
Parent: 48fa053f
Author: Vasil Dimov <[email protected]>
AuthorDate: Tue Apr 7 12:03:24 2020 +0200
Commit: Vasil Dimov <[email protected]>
CommitDate: Tue Apr 7 12:04:43 2020 +0200
gpg: Signature made Tue Apr 7 12:04:43 2020 CEST
gpg: using RSA key E64D8D45614DB07545D9CCC154DF06F64B55CBBF
gpg: Good signature from "Vasil Dimov <[email protected]>" [ultimate]
gpg: aka "Vasil Dimov <[email protected]>" [ultimate]
gpg: aka "Vasil Dimov <[email protected]>" [ultimate]
json: add JSON handler for num or num%
Add a generic handler that accepts either a bare number or a bare number
followed by "%". Use that one when taking the "close fee negotiation
step" argument of the close command.
Changelog-None
diff --git a/common/json.c b/common/json.c
index b5af5e06..e1671622 100644
--- a/common/json.c
+++ b/common/json.c
@@ -76,12 +76,27 @@ bool json_to_u64(const char *buffer, const jsmntok_t *tok,
if (*num != l)
return false;
return true;
}
+bool json_to_u64_or_u64pct(const char *buffer, const jsmntok_t *tok,
+ struct u64_or_u64pct *result)
+{
+ jsmntok_t tok_copy = *tok;
+
+ if (buffer[tok_copy.end - 1] == '%') {
+ tok_copy.end--;
+ result->is_pct = true;
+ } else {
+ result->is_pct = false;
+ }
+
+ return json_to_u64(buffer, &tok_copy, &result->n);
+}
+
bool json_to_s64(const char *buffer, const jsmntok_t *tok, s64 *num)
{
char *end;
long long l;
l = strtoll(buffer + tok->start, &end, 0);
diff --git a/common/json.h b/common/json.h
index f92a634d..10c33e51 100644
--- a/common/json.h
+++ b/common/json.h
@@ -1,12 +1,13 @@
#ifndef LIGHTNING_COMMON_JSON_H
#define LIGHTNING_COMMON_JSON_H
#include "config.h"
#include <ccan/short_types/short_types.h>
#include <ccan/tal/tal.h>
#include <common/errcode.h>
+#include <common/utils.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#define JSMN_STRICT 1
# include <external/jsmn/jsmn.h>
@@ -55,12 +56,17 @@ bool json_to_number(const char *buffer, const jsmntok_t *tok,
unsigned int *num);
/* Extract number from this (may be a string, or a number literal) */
bool json_to_u64(const char *buffer, const jsmntok_t *tok,
uint64_t *num);
+/* Extract a non-negative integer or an integer percentage (an integer in
+ * [0, 100] followed by "%"). */
+bool json_to_u64_or_u64pct(const char *buffer, const jsmntok_t *tok,
+ struct u64_or_u64pct *result);
+
/* Extract signed 64 bit integer from this (may be a string, or a number literal) */
bool json_to_s64(const char *buffer, const jsmntok_t *tok, s64 *num);
/* Extract number from this (may be a string, or a number literal) */
bool json_to_u32(const char *buffer, const jsmntok_t *tok,
uint32_t *num);
diff --git a/common/json_tok.c b/common/json_tok.c
index a08de9e0..e33f933d 100644
--- a/common/json_tok.c
+++ b/common/json_tok.c
@@ -5,12 +5,13 @@
#include <common/amount.h>
#include <common/json_command.h>
#include <common/json_helpers.h>
#include <common/json_tok.h>
#include <common/jsonrpc_errors.h>
#include <common/param.h>
+#include <common/utils.h>
struct command_result *param_array(struct command *cmd, const char *name,
const char *buffer, const jsmntok_t *tok,
const jsmntok_t **arr)
{
if (tok->type == JSMN_ARRAY) {
@@ -139,12 +140,28 @@ struct command_result *param_u64(struct command *cmd, const char *name,
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"'%s' should be an unsigned 64 bit integer, not '%.*s'",
name, tok->end - tok->start, buffer + tok->start);
}
+struct command_result *param_u64_or_u64pct(struct command *cmd,
+ const char *name, const char *buffer,
+ const jsmntok_t *tok,
+ struct u64_or_u64pct **result)
+{
+ *result = tal(cmd, struct u64_or_u64pct);
+
+ if (json_to_u64_or_u64pct(buffer, tok, *result))
+ return NULL;
+
+ return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
+ "'%s' should be an unsigned 64 bit integer "
+ "optionally followed by %%, not '%.*s'",
+ name, tok->end - tok->start, buffer + tok->start);
+}
+
struct command_result *param_tok(struct command *cmd, const char *name,
const char *buffer, const jsmntok_t * tok,
const jsmntok_t **out)
{
*out = tok;
return NULL;
diff --git a/common/json_tok.h b/common/json_tok.h
index 038015a8..ef811b37 100644
--- a/common/json_tok.h
+++ b/common/json_tok.h
@@ -3,12 +3,13 @@
#define LIGHTNING_COMMON_JSON_TOK_H
#include "config.h"
#include <ccan/short_types/short_types.h>
#include <common/json.h>
#include <common/node_id.h>
#include <common/sphinx.h>
+#include <common/utils.h>
#include <wire/wire.h>
struct amount_msat;
struct amount_sat;
struct command;
struct command_result;
@@ -63,12 +64,19 @@ struct command_result *param_sha256(struct command *cmd, const char *name,
/* Extract number from this (may be a string, or a number literal) */
struct command_result *param_u64(struct command *cmd, const char *name,
const char *buffer, const jsmntok_t *tok,
uint64_t **num);
+/* Extract a non-negative integer or an integer percentage (an integer in
+ * [0, 100] followed by "%"). */
+struct command_result *param_u64_or_u64pct(struct command *cmd,
+ const char *name, const char *buffer,
+ const jsmntok_t *tok,
+ struct u64_or_u64pct **result);
+
/* Extract msatoshi amount from this string */
struct command_result *param_msat(struct command *cmd, const char *name,
const char *buffer, const jsmntok_t *tok,
struct amount_msat **msat);
/* Extract satoshi amount from this string */
diff --git a/common/utils.h b/common/utils.h
index 484da8ea..0510c952 100644
--- a/common/utils.h
+++ b/common/utils.h
@@ -5,12 +5,17 @@
#include <ccan/crypto/sha256/sha256.h>
#include <ccan/short_types/short_types.h>
#include <ccan/structeq/structeq.h>
#include <ccan/tal/tal.h>
#include <secp256k1.h>
+struct u64_or_u64pct {
+ u64 n;
+ bool is_pct;
+};
+
extern secp256k1_context *secp256k1_ctx;
extern const struct chainparams *chainparams;
/* Simple accessor function for our own dependencies to use, in order to avoid
* circular dependencies (should only be used in `bitcoin/y`). */
diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c
index ae7d4ae5..619b93a0 100644
--- a/lightningd/peer_control.c
+++ b/lightningd/peer_control.c
@@ -1285,22 +1285,24 @@ static struct command_result *json_close(struct command *cmd,
struct channel *channel COMPILER_WANTS_INIT("gcc 7.3.0 fails, 8.3 OK");
unsigned int *timeout = NULL;
bool force = true;
bool do_timeout;
const u8 *close_to_script = NULL;
bool close_script_set;
- const char *fee_negotiation_step_str;
- char* end;
+ struct u64_or_u64pct *fee_negotiation_step;
+ struct u64_or_u64pct fee_negotiation_step_default = {.n = 50,
+ .is_pct = true};
if (!param(cmd, buffer, params,
p_req("id", param_tok, &idtok),
p_opt_def("unilateraltimeout", param_number, &timeout,
48 * 3600),
p_opt("destination", param_bitcoin_address, &close_to_script),
- p_opt("fee_negotiation_step", param_string,
- &fee_negotiation_step_str),
+ p_opt_def("fee_negotiation_step", param_u64_or_u64pct,
+ &fee_negotiation_step,
+ fee_negotiation_step_default),
NULL))
return command_param_failed();
do_timeout = (*timeout != 0);
peer = peer_from_json(cmd->ld, buffer, idtok);
@@ -1360,48 +1362,34 @@ static struct command_result *json_close(struct command *cmd,
= p2wpkh_for_keyidx(channel, cmd->ld, channel->final_key_idx);
/* We don't save the default to disk */
close_script_set = false;
} else
close_script_set = false;
- if (fee_negotiation_step_str == NULL) {
- channel->closing_fee_negotiation_step = 50;
- channel->closing_fee_negotiation_step_unit =
- CLOSING_FEE_NEGOTIATION_STEP_UNIT_PERCENTAGE;
- } else {
- channel->closing_fee_negotiation_step =
- strtoull(fee_negotiation_step_str, &end, 10);
-
- if (channel->closing_fee_negotiation_step == 0)
- return command_fail(
- cmd, JSONRPC2_INVALID_PARAMS,
- "Wrong value given for fee_negotiation_step: "
- "\"%s\", must be positive",
- fee_negotiation_step_str);
- else if (*end == '%') {
- if (channel->closing_fee_negotiation_step > 100)
- return command_fail(
- cmd, JSONRPC2_INVALID_PARAMS,
- "Wrong value given for "
- "fee_negotiation_step: \"%s\", the "
- "percentage should be between 1 and 100",
- fee_negotiation_step_str);
- channel->closing_fee_negotiation_step_unit =
- CLOSING_FEE_NEGOTIATION_STEP_UNIT_PERCENTAGE;
- } else if (*end == '\0')
- channel->closing_fee_negotiation_step_unit =
- CLOSING_FEE_NEGOTIATION_STEP_UNIT_SATOSHI;
- else
- return command_fail(
- cmd, JSONRPC2_INVALID_PARAMS,
- "Wrong value given for fee_negotiation_step: "
- "\"%s\", should be an integer or an integer "
- "followed by %%",
- fee_negotiation_step_str);
+ if (fee_negotiation_step->n == 0) {
+ return command_fail(
+ cmd, JSONRPC2_INVALID_PARAMS,
+ "Wrong value given for fee_negotiation_step: \"%" PRIu64
+ "\", it should be a positive number",
+ fee_negotiation_step->n);
+ }
+
+ if (fee_negotiation_step->is_pct && fee_negotiation_step->n > 100) {
+ return command_fail(
+ cmd, JSONRPC2_INVALID_PARAMS,
+ "Wrong value given for fee_negotiation_step: \"%" PRIu64
+ "\", the percentage should be between 1 and 100",
+ fee_negotiation_step->n);
}
+ channel->closing_fee_negotiation_step = fee_negotiation_step->n;
+ channel->closing_fee_negotiation_step_unit =
+ fee_negotiation_step->is_pct
+ ? CLOSING_FEE_NEGOTIATION_STEP_UNIT_PERCENTAGE
+ : CLOSING_FEE_NEGOTIATION_STEP_UNIT_SATOSHI;
+
/* Normal case.
* We allow states shutting down and sigexchange; a previous
* close command may have timed out, and this current command
* will continue waiting for the effects of the previous
* close command. */
diff --git a/common/test/run-sphinx.c b/common/test/run-sphinx.c
index f73bc74e..a75dae8e 100644
--- a/common/test/run-sphinx.c
+++ b/common/test/run-sphinx.c
@@ -44,15 +44,12 @@ bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
/* Generated stub for bigsize_get */
size_t bigsize_get(const u8 *p UNNEEDED, size_t max UNNEEDED, bigsize_t *val UNNEEDED)
{ fprintf(stderr, "bigsize_get called!\n"); abort(); }
/* Generated stub for bigsize_put */
size_t bigsize_put(u8 buf[BIGSIZE_MAX_LEN] UNNEEDED, bigsize_t v UNNEEDED)
{ fprintf(stderr, "bigsize_put called!\n"); abort(); }
-/* Generated stub for ecdh */
-void ecdh(const struct pubkey *point UNNEEDED, struct secret *ss UNNEEDED)
-{ fprintf(stderr, "ecdh called!\n"); abort(); }
/* Generated stub for pubkey_from_node_id */
bool pubkey_from_node_id(struct pubkey *key UNNEEDED, const struct node_id *id UNNEEDED)
{ fprintf(stderr, "pubkey_from_node_id called!\n"); abort(); }
/* AUTOGENERATED MOCKS END */
extern secp256k1_context *secp256k1_ctx;
diff --git a/connectd/test/run-responder-success.c b/connectd/test/run-responder-success.c
index cd9410cb..5657d178 100644
--- a/connectd/test/run-responder-success.c
+++ b/connectd/test/run-responder-success.c
@@ -37,15 +37,12 @@ const void *fromwire_fail(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
u8 *fromwire_tal_arrn(const tal_t *ctx UNNEEDED,
const u8 **cursor UNNEEDED, size_t *max UNNEEDED, size_t num UNNEEDED)
{ fprintf(stderr, "fromwire_tal_arrn called!\n"); abort(); }
/* Generated stub for fromwire_u16 */
u16 fromwire_u16(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_u16 called!\n"); abort(); }
-/* Generated stub for notleak_ */
-void *notleak_(const void *ptr UNNEEDED, bool plus_children UNNEEDED)
-{ fprintf(stderr, "notleak_ called!\n"); abort(); }
/* Generated stub for towire_u16 */
void towire_u16(u8 **pptr UNNEEDED, u16 v UNNEEDED)
{ fprintf(stderr, "towire_u16 called!\n"); abort(); }
/* Generated stub for towire_u8_array */
void towire_u8_array(u8 **pptr UNNEEDED, const u8 *arr UNNEEDED, size_t num UNNEEDED)
{ fprintf(stderr, "towire_u8_array called!\n"); abort(); }
diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c
index 2392f76f..6f054ae9 100644
--- a/lightningd/test/run-invoice-select-inchan.c
+++ b/lightningd/test/run-invoice-select-inchan.c
@@ -20,13 +20,13 @@ void bitcoind_getutxout_(struct bitcoind *bitcoind UNNEEDED,
const struct bitcoin_tx_output *txout UNNEEDED,
void *arg) UNNEEDED,
void *arg UNNEEDED)
{ fprintf(stderr, "bitcoind_getutxout_ called!\n"); abort(); }
/* Generated stub for bolt11_decode */
struct bolt11 *bolt11_decode(const tal_t *ctx UNNEEDED, const char *str UNNEEDED,
- const struct feature_set *fset UNNEEDED,
+ const struct feature_set *our_features UNNEEDED,
const char *description UNNEEDED, char **fail UNNEEDED)
{ fprintf(stderr, "bolt11_decode called!\n"); abort(); }
/* Generated stub for bolt11_encode_ */
char *bolt11_encode_(const tal_t *ctx UNNEEDED,
const struct bolt11 *b11 UNNEEDED, bool n_field UNNEEDED,
bool (*sign)(const u5 *u5bytes UNNEEDED,
@@ -45,15 +45,12 @@ void broadcast_tx(struct chain_topology *topo UNNEEDED,
/* Generated stub for channel_tell_depth */
bool channel_tell_depth(struct lightningd *ld UNNEEDED,
struct channel *channel UNNEEDED,
const struct bitcoin_txid *txid UNNEEDED,
u32 depth UNNEEDED)
{ fprintf(stderr, "channel_tell_depth called!\n"); abort(); }
-/* Generated stub for command_check_only */
-bool command_check_only(const struct command *cmd UNNEEDED)
-{ fprintf(stderr, "command_check_only called!\n"); abort(); }
/* Generated stub for command_fail */
struct command_result *command_fail(struct command *cmd UNNEEDED, errcode_t code UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "command_fail called!\n"); abort(); }
/* Generated stub for command_failed */
@@ -100,18 +97,12 @@ const u8 *failmsg_incorrect_or_unknown(const tal_t *ctx UNNEEDED,
/* Generated stub for fatal */
void fatal(const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "fatal called!\n"); abort(); }
/* Generated stub for feature_is_set */
bool feature_is_set(const u8 *features UNNEEDED, size_t bit UNNEEDED)
{ fprintf(stderr, "feature_is_set called!\n"); abort(); }
-/* Generated stub for featurebits_or */
-u8 *featurebits_or(const tal_t *ctx UNNEEDED, const u8 *f1 TAKES UNNEEDED, const u8 *f2 TAKES UNNEEDED)
-{ fprintf(stderr, "featurebits_or called!\n"); abort(); }
-/* Generated stub for fixup_htlcs_out */
-void fixup_htlcs_out(struct lightningd *ld UNNEEDED)
-{ fprintf(stderr, "fixup_htlcs_out called!\n"); abort(); }
/* Generated stub for fmt_wireaddr_without_port */
char *fmt_wireaddr_without_port(const tal_t *ctx UNNEEDED, const struct wireaddr *a UNNEEDED)
{ fprintf(stderr, "fmt_wireaddr_without_port called!\n"); abort(); }
/* Generated stub for fromwire_channel_dev_memleak_reply */
bool fromwire_channel_dev_memleak_reply(const void *p UNNEEDED, bool *leak UNNEEDED)
{ fprintf(stderr, "fromwire_channel_dev_memleak_reply called!\n"); abort(); }
@@ -348,12 +339,18 @@ struct command_result *param_tok(struct command *cmd UNNEEDED, const char *name
{ fprintf(stderr, "param_tok called!\n"); abort(); }
/* Generated stub for param_u64 */
struct command_result *param_u64(struct command *cmd UNNEEDED, const char *name UNNEEDED,
const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
uint64_t **num UNNEEDED)
{ fprintf(stderr, "param_u64 called!\n"); abort(); }
+/* Generated stub for param_u64_or_u64pct */
+struct command_result *param_u64_or_u64pct(struct command *cmd UNNEEDED,
+ const char *name UNNEEDED, const char *buffer UNNEEDED,
+ const jsmntok_t *tok UNNEEDED,
+ struct u64_or_u64pct **result UNNEEDED)
+{ fprintf(stderr, "param_u64_or_u64pct called!\n"); abort(); }
/* Generated stub for peer_get_owning_subd */
struct subd *peer_get_owning_subd(struct peer *peer UNNEEDED)
{ fprintf(stderr, "peer_get_owning_subd called!\n"); abort(); }
/* Generated stub for peer_memleak_done */
void peer_memleak_done(struct command *cmd UNNEEDED, struct subd *leaker UNNEEDED)
{ fprintf(stderr, "peer_memleak_done called!\n"); abort(); }
diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c
index 5d71b7be..62d838b8 100644
--- a/wallet/test/run-wallet.c
+++ b/wallet/test/run-wallet.c
@@ -55,15 +55,12 @@ void broadcast_tx(struct chain_topology *topo UNNEEDED,
/* Generated stub for channel_tell_depth */
bool channel_tell_depth(struct lightningd *ld UNNEEDED,
struct channel *channel UNNEEDED,
const struct bitcoin_txid *txid UNNEEDED,
u32 depth UNNEEDED)
{ fprintf(stderr, "channel_tell_depth called!\n"); abort(); }
-/* Generated stub for command_check_only */
-bool command_check_only(const struct command *cmd UNNEEDED)
-{ fprintf(stderr, "command_check_only called!\n"); abort(); }
/* Generated stub for command_fail */
struct command_result *command_fail(struct command *cmd UNNEEDED, errcode_t code UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "command_fail called!\n"); abort(); }
/* Generated stub for command_param_failed */
@@ -339,21 +336,12 @@ void json_object_start(struct json_stream *ks UNNEEDED, const char *fieldname UN
/* Generated stub for json_strdup */
char *json_strdup(const tal_t *ctx UNNEEDED, const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED)
{ fprintf(stderr, "json_strdup called!\n"); abort(); }
/* Generated stub for json_stream_success */
struct json_stream *json_stream_success(struct command *cmd UNNEEDED)
{ fprintf(stderr, "json_stream_success called!\n"); abort(); }
-/* Generated stub for json_to_address_scriptpubkey */
-enum address_parse_result json_to_address_scriptpubkey(const tal_t *ctx UNNEEDED,
- const struct chainparams *chainparams UNNEEDED,
- const char *buffer UNNEEDED,
- const jsmntok_t *tok UNNEEDED, const u8 **scriptpubkey UNNEEDED)
-{ fprintf(stderr, "json_to_address_scriptpubkey called!\n"); abort(); }
-/* Generated stub for json_to_bool */
-bool json_to_bool(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, bool *b UNNEEDED)
-{ fprintf(stderr, "json_to_bool called!\n"); abort(); }
/* Generated stub for json_to_node_id */
bool json_to_node_id(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct node_id *id UNNEEDED)
{ fprintf(stderr, "json_to_node_id called!\n"); abort(); }
/* Generated stub for json_to_number */
bool json_to_number(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
@@ -489,22 +477,23 @@ struct command_result *param_number(struct command *cmd UNNEEDED, const char *na
struct command_result *param_short_channel_id(struct command *cmd UNNEEDED,
const char *name UNNEEDED,
const char *buffer UNNEEDED,
const jsmntok_t *tok UNNEEDED,
struct short_channel_id **scid UNNEEDED)
{ fprintf(stderr, "param_short_channel_id called!\n"); abort(); }
-/* Generated stub for param_string */
-struct command_result *param_string(struct command *cmd UNNEEDED, const char *name UNNEEDED,
- const char * buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
- const char **str UNNEEDED)
-{ fprintf(stderr, "param_string called!\n"); abort(); }
/* Generated stub for param_tok */
struct command_result *param_tok(struct command *cmd UNNEEDED, const char *name UNNEEDED,
const char *buffer UNNEEDED, const jsmntok_t * tok UNNEEDED,
const jsmntok_t **out UNNEEDED)
{ fprintf(stderr, "param_tok called!\n"); abort(); }
+/* Generated stub for param_u64_or_u64pct */
+struct command_result *param_u64_or_u64pct(struct command *cmd UNNEEDED,
+ const char *name UNNEEDED, const char *buffer UNNEEDED,
+ const jsmntok_t *tok UNNEEDED,
+ struct u64_or_u64pct **result UNNEEDED)
+{ fprintf(stderr, "param_u64_or_u64pct called!\n"); abort(); }
/* Generated stub for parse_onionpacket */
enum onion_type parse_onionpacket(const u8 *src UNNEEDED,
const size_t srclen UNNEEDED,
struct onionpacket *dest UNNEEDED)
{ fprintf(stderr, "parse_onionpacket called!\n"); abort(); }
/* Generated stub for payment_failed */
If that does not look like too much code, then I can append it to #3629.
When negotiating the transaction fee for closing a channel [1], we used
to always pick the middle of the range between our proposal and the
peer's proposal.
Introduce a new option
fee_negotiation_step
to the close command, sothe peer who initiates the close can choose his back off step.
Partially resolves #3270
[1] https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md#closing-negotiation-closing_signed
Changelog-Added: New optional parameter to the
close
command to control the closing transaction fee negotiation back off step