Skip to content

Commit

Permalink
daemon: use fee rates rather than absolute fees (BOLT ElementsProject#2)
Browse files Browse the repository at this point in the history
And divide fees as specified there.

We still use fixed values rather than floating, and we don't send or
handle update_fee messages.

Signed-off-by: Rusty Russell <[email protected]>
  • Loading branch information
rustyrussell committed Mar 24, 2016
1 parent ba2854e commit 8c468c1
Show file tree
Hide file tree
Showing 11 changed files with 497 additions and 330 deletions.
60 changes: 29 additions & 31 deletions daemon/lightningd.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,15 @@ static void config_register_opts(struct lightningd_state *dstate)
opt_register_arg("--forever-confirms", opt_set_u32, opt_show_u32,
&dstate->config.forever_confirms,
"Confirmations after which we consider a reorg impossible");
opt_register_arg("--commit-fee", opt_set_u64, opt_show_u64,
&dstate->config.commitment_fee,
"Satoshis to offer for commitment transaction fee");
opt_register_arg("--min-commit-fee", opt_set_u64, opt_show_u64,
&dstate->config.commitment_fee_min,
"Minimum satoshis to accept for commitment transaction fee");
opt_register_arg("--closing-fee", opt_set_u64, opt_show_u64,
&dstate->config.closing_fee,
"Satoshis to use for mutual close transaction fee");
opt_register_arg("--commit-fee-rate", opt_set_u64, opt_show_u64,
&dstate->config.commitment_fee_rate,
"Satoshis to offer for commitment transaction fee (per kb)");
opt_register_arg("--min-commit-fee-rate", opt_set_u64, opt_show_u64,
&dstate->config.commitment_fee_rate_min,
"Minimum satoshis to accept for commitment transaction fee (per kb)");
opt_register_arg("--closing-fee-rate", opt_set_u64, opt_show_u64,
&dstate->config.closing_fee_rate,
"Satoshis to use for mutual close transaction fee (per kb)");
opt_register_arg("--min-expiry", opt_set_u32, opt_show_u32,
&dstate->config.min_expiry,
"Minimum number of seconds to accept an HTLC before expiry");
Expand Down Expand Up @@ -128,14 +128,14 @@ static void default_config(struct config *config)

/* FIXME: These should float with bitcoind's recommendations! */

/* Pay hefty fee (10x current suggested minimum). */
config->commitment_fee = 50000;
/* Pay hefty fee (double historic high of ~100k). */
config->commitment_fee_rate = 200000;

/* Don't accept less than double the current standard fee. */
config->commitment_fee_min = 10000;
/* Don't accept less than double the average 2-block fee. */
config->commitment_fee_rate_min = 50000;

/* Use this for mutual close. */
config->closing_fee = 10000;
config->closing_fee_rate = 20000;

/* Don't bother me unless I have 6 hours to collect. */
config->min_expiry = 6 * HOURS;
Expand All @@ -149,24 +149,22 @@ static void check_config(struct lightningd_state *dstate)
{
/* BOLT #2:
* The sender MUST set `close_fee` lower than or equal to the
* fee of the final commitment transaction, and MUST set
* `close_fee` to an even number of satoshis.
* fee of the final commitment transaction.
*/
if (dstate->config.closing_fee > dstate->config.commitment_fee)
fatal("Closing fee %"PRIu64
" can't exceed commitment fee %"PRIu64,
dstate->config.closing_fee,
dstate->config.commitment_fee);

if (dstate->config.closing_fee & 1)
fatal("Closing fee %"PRIu64 "must be even.",
dstate->config.closing_fee);

if (dstate->config.commitment_fee_min > dstate->config.commitment_fee)
fatal("Minumum fee %"PRIu64
" can't exceed commitment fee %"PRIu64,
dstate->config.commitment_fee_min,
dstate->config.commitment_fee);

/* We do this by ensuring it's less than the minimum we would accept. */
if (dstate->config.closing_fee_rate > dstate->config.commitment_fee_rate_min)
fatal("Closing fee rate %"PRIu64
" can't exceed minimum commitment fee rate %"PRIu64,
dstate->config.closing_fee_rate,
dstate->config.commitment_fee_rate_min);

if (dstate->config.commitment_fee_rate_min
> dstate->config.commitment_fee_rate)
fatal("Minumum fee rate %"PRIu64
" can't exceed commitment fee rate %"PRIu64,
dstate->config.commitment_fee_rate_min,
dstate->config.commitment_fee_rate);
}

static struct lightningd_state *lightningd_state(void)
Expand Down
10 changes: 5 additions & 5 deletions daemon/lightningd.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ struct config {
/* How many blocks until we stop watching a close commit? */
u32 forever_confirms;

/* What are we prepared to pay in commitment fee (satoshis). */
u64 commitment_fee;
/* What are we prepared to pay in commitment fee (satoshis/kb). */
u64 commitment_fee_rate;

/* How little are we prepared to have them pay? */
u64 commitment_fee_min;
u64 commitment_fee_rate_min;

/* What fee we use for the closing transaction (satoshis) */
u64 closing_fee;
/* What fee we use for the closing transaction (satoshis/kb) */
u64 closing_fee_rate;

/* Minimum/maximum time for an expiring HTLC (seconds). */
u32 min_expiry, max_expiry;
Expand Down
64 changes: 21 additions & 43 deletions daemon/packets.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ Pkt *pkt_open(const tal_t *ctx, const struct peer *peer,
locktime__init(o->delay);
o->delay->locktime_case = LOCKTIME__LOCKTIME_SECONDS;
o->delay->seconds = rel_locktime_to_seconds(&peer->us.locktime);
o->commitment_fee = peer->us.commit_fee;
o->initial_fee_rate = peer->us.commit_fee_rate;
if (anchor == OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR)
assert(peer->us.offer_anchor == CMD_OPEN_WITH_ANCHOR);
else {
Expand Down Expand Up @@ -289,8 +289,8 @@ Pkt *accept_pkt_open(const tal_t *ctx,
return pkt_err(ctx, "Delay too great");
if (o->min_depth > peer->dstate->config.anchor_confirms_max)
return pkt_err(ctx, "min_depth too great");
if (o->commitment_fee < peer->dstate->config.commitment_fee_min)
return pkt_err(ctx, "Commitment fee too low");
if (o->initial_fee_rate < peer->dstate->config.commitment_fee_rate_min)
return pkt_err(ctx, "Commitment fee rate too low");
if (o->anch == OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR)
peer->them.offer_anchor = CMD_OPEN_WITH_ANCHOR;
else if (o->anch == OPEN_CHANNEL__ANCHOR_OFFER__WONT_CREATE_ANCHOR)
Expand All @@ -304,7 +304,7 @@ Pkt *accept_pkt_open(const tal_t *ctx,
if (!proto_to_rel_locktime(o->delay, &peer->them.locktime))
return pkt_err(ctx, "Malformed locktime");
peer->them.mindepth = o->min_depth;
peer->them.commit_fee = o->commitment_fee;
peer->them.commit_fee_rate = o->initial_fee_rate;
if (!proto_to_pubkey(peer->dstate->secpctx,
o->commit_key, &peer->them.commitkey))
return pkt_err(ctx, "Bad commitkey");
Expand All @@ -326,7 +326,6 @@ Pkt *accept_pkt_anchor(const tal_t *ctx,
const Pkt *pkt)
{
const OpenAnchor *a = pkt->open_anchor;
u64 commitfee;

/* They must be offering anchor for us to try accepting */
assert(peer->us.offer_anchor == CMD_OPEN_WITHOUT_ANCHOR);
Expand All @@ -336,15 +335,13 @@ Pkt *accept_pkt_anchor(const tal_t *ctx,
peer->anchor.index = a->output_index;
peer->anchor.satoshis = a->amount;

/* Create funder's cstate, invert to get ours. */
commitfee = commit_fee(peer->them.commit_fee, peer->us.commit_fee);
/* Create our cstate. */
peer->cstate = initial_funding(peer,
peer->us.offer_anchor,
peer->us.offer_anchor == CMD_OPEN_WITH_ANCHOR,
peer->anchor.satoshis,
commitfee);
peer->us.commit_fee_rate);
if (!peer->cstate)
return pkt_err(ctx, "Insufficient funds for fee");
invert_cstate(peer->cstate);

/* Now we can make initial (unsigned!) commit txs. */
make_commit_txs(peer, peer,
Expand Down Expand Up @@ -449,18 +446,14 @@ Pkt *accept_pkt_htlc_add(const tal_t *ctx,
}

cur->cstate = copy_funding(cur, peer->cstate);
if (!funding_delta(peer->anchor.satoshis,
0, cur->stage.add.htlc.msatoshis,
&cur->cstate->b, &cur->cstate->a)) {
if (!funding_b_add_htlc(cur->cstate,
cur->stage.add.htlc.msatoshis,
&cur->stage.add.htlc.expiry,
&cur->stage.add.htlc.rhash)) {
err = pkt_err(ctx, "Cannot afford %"PRIu64" milli-satoshis",
cur->stage.add.htlc.msatoshis);
goto fail;
}
/* Add the htlc to their side of channel. */
funding_add_htlc(&cur->cstate->b,
cur->stage.add.htlc.msatoshis,
&cur->stage.add.htlc.expiry,
&cur->stage.add.htlc.rhash);
peer_add_htlc_expiry(peer, &cur->stage.add.htlc.expiry);

peer_get_revocation_hash(peer, peer->commit_tx_counter+1,
Expand Down Expand Up @@ -498,7 +491,6 @@ Pkt *accept_pkt_htlc_fail(const tal_t *ctx, struct peer *peer, const Pkt *pkt)
Pkt *err;
size_t i;
struct sha256 rhash;
struct channel_htlc *htlc;

proto_to_sha256(f->revocation_hash, &cur->their_revocation_hash);
proto_to_sha256(f->r_hash, &rhash);
Expand All @@ -511,17 +503,10 @@ Pkt *accept_pkt_htlc_fail(const tal_t *ctx, struct peer *peer, const Pkt *pkt)

cur->stage.fail.fail = HTLC_FAIL;
cur->stage.fail.index = i;
htlc = &peer->cstate->a.htlcs[i];

/* Removing it should not fail: we regain HTLC amount */
/* We regain HTLC amount */
cur->cstate = copy_funding(cur, peer->cstate);
if (!funding_delta(peer->anchor.satoshis,
0, -htlc->msatoshis,
&cur->cstate->a, &cur->cstate->b)) {
fatal("Unexpected failure fulfilling HTLC of %"PRIu64
" milli-satoshis", htlc->msatoshis);
}
funding_remove_htlc(&cur->cstate->a, i);
funding_a_fail_htlc(cur->cstate, i);
/* FIXME: Remove timer. */

peer_get_revocation_hash(peer, peer->commit_tx_counter+1,
Expand Down Expand Up @@ -550,7 +535,6 @@ Pkt *accept_pkt_htlc_fulfill(const tal_t *ctx,
Pkt *err;
size_t i;
struct sha256 rhash;
struct channel_htlc *htlc;

cur->stage.fulfill.fulfill = HTLC_FULFILL;
proto_to_sha256(f->r, &cur->stage.fulfill.r);
Expand All @@ -564,19 +548,10 @@ Pkt *accept_pkt_htlc_fulfill(const tal_t *ctx,
}
cur->stage.fulfill.index = i;

htlc = &peer->cstate->a.htlcs[i];

/* Removing it should not fail: they gain HTLC amount */
/* Removing it: they gain HTLC amount */
cur->cstate = copy_funding(cur, peer->cstate);
if (!funding_delta(peer->anchor.satoshis,
-htlc->msatoshis,
-htlc->msatoshis,
&cur->cstate->a, &cur->cstate->b)) {
fatal("Unexpected failure fulfilling HTLC of %"PRIu64
" milli-satoshis", htlc->msatoshis);
}
funding_remove_htlc(&cur->cstate->a, i);

funding_a_fulfill_htlc(cur->cstate, i);

peer_get_revocation_hash(peer, peer->commit_tx_counter+1,
&cur->our_revocation_hash);

Expand Down Expand Up @@ -729,13 +704,16 @@ Pkt *accept_pkt_close_sig(const tal_t *ctx, struct peer *peer, const Pkt *pkt,
struct bitcoin_signature theirsig;

/* BOLT #2:
*
* The sender MUST set `close_fee` lower than or equal to the fee of the
* final commitment transaction, and MUST set `close_fee` to an even
* number of satoshis.
*/
if (c->close_fee & 1 || c->close_fee > peer->them.commit_fee)
if ((c->close_fee & 1)
|| c->close_fee > commit_tx_fee(peer->them.commit,
peer->anchor.satoshis)) {
return pkt_err(ctx, "Invalid close fee");
}

/* FIXME: Don't accept tiny fee at all? */

Expand Down
Loading

0 comments on commit 8c468c1

Please sign in to comment.