mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-17 19:03:42 +01:00
daemon: use fee rates rather than absolute fees (BOLT #2)
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 <rusty@rustcorp.com.au>
This commit is contained in:
parent
ba2854e835
commit
8c468c1e15
@ -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");
|
||||
@ -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;
|
||||
@ -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);
|
||||
/* 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_min > dstate->config.commitment_fee)
|
||||
fatal("Minumum fee %"PRIu64
|
||||
" can't exceed commitment fee %"PRIu64,
|
||||
dstate->config.commitment_fee_min,
|
||||
dstate->config.commitment_fee);
|
||||
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)
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
@ -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)
|
||||
@ -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");
|
||||
@ -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);
|
||||
@ -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,
|
||||
@ -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,
|
||||
@ -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);
|
||||
@ -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,
|
||||
@ -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);
|
||||
@ -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);
|
||||
|
||||
@ -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? */
|
||||
|
||||
|
149
daemon/peer.c
149
daemon/peer.c
@ -376,8 +376,7 @@ static struct peer *new_peer(struct lightningd_state *dstate,
|
||||
fatal("Invalid locktime configuration %u",
|
||||
dstate->config.rel_locktime);
|
||||
peer->us.mindepth = dstate->config.anchor_confirms;
|
||||
/* FIXME: Make this dynamic. */
|
||||
peer->us.commit_fee = dstate->config.commitment_fee;
|
||||
peer->us.commit_fee_rate = dstate->config.commitment_fee_rate;
|
||||
|
||||
peer->us.commit = peer->them.commit = NULL;
|
||||
|
||||
@ -831,6 +830,17 @@ static void spend_tx_done(struct peer *peer, int depth,
|
||||
state_event(peer, ptr2int(done), NULL);
|
||||
}
|
||||
|
||||
uint64_t commit_tx_fee(const struct bitcoin_tx *commit, uint64_t anchor_satoshis)
|
||||
{
|
||||
uint64_t i, total = 0;
|
||||
|
||||
for (i = 0; i < commit->output_count; i++)
|
||||
total += commit->output[i].amount;
|
||||
|
||||
assert(anchor_satoshis >= total);
|
||||
return anchor_satoshis - total;
|
||||
}
|
||||
|
||||
/* Watch this tx until it's buried enough to be forgotten. */
|
||||
void peer_watch_tx(struct peer *peer,
|
||||
const struct bitcoin_tx *tx,
|
||||
@ -855,9 +865,12 @@ struct bitcoin_tx *peer_create_close_tx(const tal_t *ctx,
|
||||
|
||||
/* We don't need a deep copy here, just fee levels. */
|
||||
cstate = *peer->cstate;
|
||||
if (!adjust_fee(peer->anchor.satoshis, fee,
|
||||
&cstate.a, &cstate.b))
|
||||
if (!force_fee(&cstate, fee)) {
|
||||
log_unusual(peer->log,
|
||||
"peer_create_close_tx: can't afford fee %"PRIu64,
|
||||
fee);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
log_debug(peer->log,
|
||||
"creating close-tx with fee %"PRIu64": to %02x%02x%02x%02x/%02x%02x%02x%02x, amounts %u/%u",
|
||||
@ -881,14 +894,36 @@ struct bitcoin_tx *peer_create_close_tx(const tal_t *ctx,
|
||||
|
||||
void peer_calculate_close_fee(struct peer *peer)
|
||||
{
|
||||
/* Use actual worst-case length of close tx: based on BOLT#02's
|
||||
* commitment tx numbers, but only 1 byte for output count */
|
||||
const uint64_t txsize = 41 + 221 + 10 + 32 + 32;
|
||||
uint64_t maxfee;
|
||||
|
||||
/* FIXME: Dynamic fee */
|
||||
peer->closing.our_fee
|
||||
= fee_by_feerate(txsize, peer->dstate->config.closing_fee_rate);
|
||||
|
||||
/* BOLT #2:
|
||||
* The sender MUST set `close_fee` lower than or equal to the
|
||||
* fee of the final commitment transaction, and MUST set
|
||||
* fee of the final commitment transaction and MUST set
|
||||
* `close_fee` to an even number of satoshis.
|
||||
*/
|
||||
maxfee = commit_tx_fee(peer->us.commit, peer->anchor.satoshis);
|
||||
if (peer->closing.our_fee > maxfee) {
|
||||
/* This shouldn't happen: we never accept a commit fee
|
||||
* less than the min_rate, which is greater than the
|
||||
* closing_fee_rate. Also, our txsize estimate for
|
||||
* the closing tx is 2 bytes smaller than the commitment tx. */
|
||||
log_unusual(peer->log,
|
||||
"Closing fee %"PRIu64" exceeded commit fee %"PRIu64", reducing.",
|
||||
peer->closing.our_fee, maxfee);
|
||||
peer->closing.our_fee = maxfee;
|
||||
|
||||
/* FIXME: Dynamic fee! */
|
||||
peer->closing.our_fee = peer->dstate->config.closing_fee;
|
||||
/* This can happen if actual commit txfee is odd. */
|
||||
if (peer->closing.our_fee & 1)
|
||||
peer->closing.our_fee--;
|
||||
}
|
||||
assert(!(peer->closing.our_fee & 1));
|
||||
}
|
||||
|
||||
bool peer_has_close_sig(const struct peer *peer)
|
||||
@ -1056,7 +1091,7 @@ const struct bitcoin_tx *bitcoin_close(const tal_t *ctx, struct peer *peer)
|
||||
const struct bitcoin_tx *bitcoin_spend_ours(const tal_t *ctx,
|
||||
const struct peer *peer)
|
||||
{
|
||||
u8 *redeemscript;
|
||||
u8 *redeemscript, *linear;
|
||||
const struct bitcoin_tx *commit = peer->us.commit;
|
||||
struct bitcoin_signature sig;
|
||||
struct bitcoin_tx *tx;
|
||||
@ -1075,30 +1110,46 @@ const struct bitcoin_tx *bitcoin_spend_ours(const tal_t *ctx,
|
||||
p2sh_out = find_p2sh_out(commit, redeemscript);
|
||||
tx->input[0].index = p2sh_out;
|
||||
tx->input[0].input_amount = commit->output[p2sh_out].amount;
|
||||
/* FIXME: Dynamic fee! */
|
||||
tx->fee = peer->dstate->config.closing_fee;
|
||||
|
||||
tx->input[0].sequence_number = bitcoin_nsequence(&peer->them.locktime);
|
||||
|
||||
/* FIXME: In this case, we shouldn't do anything (not worth
|
||||
* collecting) */
|
||||
if (commit->output[p2sh_out].amount <= tx->fee)
|
||||
fatal("Amount of %"PRIu64" won't cover fee",
|
||||
commit->output[p2sh_out].amount);
|
||||
|
||||
tx->output[0].amount = commit->output[p2sh_out].amount - tx->fee;
|
||||
tx->output[0].amount = commit->output[p2sh_out].amount;
|
||||
tx->output[0].script = scriptpubkey_p2sh(tx,
|
||||
bitcoin_redeem_single(tx, &peer->us.finalkey));
|
||||
tx->output[0].script_length = tal_count(tx->output[0].script);
|
||||
|
||||
/* Now get signature, to set up input script. */
|
||||
/* Use signature, until we have fee. */
|
||||
sig.stype = SIGHASH_ALL;
|
||||
peer_sign_spend(peer, tx, redeemscript, &sig.sig);
|
||||
|
||||
tx->input[0].script = scriptsig_p2sh_secret(tx, NULL, 0, &sig,
|
||||
redeemscript,
|
||||
tal_count(redeemscript));
|
||||
tx->input[0].script_length = tal_count(tx->input[0].script);
|
||||
|
||||
/* FIXME: Figure out length first, then calc fee! */
|
||||
|
||||
/* Now, calculate the fee, given length. */
|
||||
/* FIXME: Dynamic fees! */
|
||||
linear = linearize_tx(ctx, tx);
|
||||
tx->fee = fee_by_feerate(tal_count(linear),
|
||||
peer->dstate->config.closing_fee_rate);
|
||||
|
||||
/* FIXME: Fail gracefully in these cases (not worth collecting) */
|
||||
if (tx->fee > tx->output[0].amount
|
||||
|| is_dust_amount(tx->output[0].amount - tx->fee))
|
||||
fatal("Amount of %"PRIu64" won't cover fee %"PRIu64,
|
||||
tx->output[0].amount, tx->fee);
|
||||
|
||||
/* Re-sign with the real values. */
|
||||
tx->input[0].script_length = 0;
|
||||
tx->output[0].amount -= tx->fee;
|
||||
peer_sign_spend(peer, tx, redeemscript, &sig.sig);
|
||||
|
||||
tx->input[0].script = scriptsig_p2sh_secret(tx, NULL, 0, &sig,
|
||||
redeemscript,
|
||||
tal_count(redeemscript));
|
||||
tx->input[0].script_length = tal_count(tx->input[0].script);
|
||||
|
||||
return tx;
|
||||
}
|
||||
|
||||
@ -1161,19 +1212,17 @@ static void created_anchor(struct lightningd_state *dstate,
|
||||
const struct bitcoin_tx *tx,
|
||||
struct peer *peer)
|
||||
{
|
||||
size_t commitfee;
|
||||
|
||||
bitcoin_txid(tx, &peer->anchor.txid);
|
||||
peer->anchor.index = find_p2sh_out(tx, peer->anchor.redeemscript);
|
||||
assert(peer->anchor.satoshis == tx->output[peer->anchor.index].amount);
|
||||
/* We'll need this later, when we're told to broadcast it. */
|
||||
peer->anchor.tx = tal_steal(peer, tx);
|
||||
|
||||
commitfee = commit_fee(peer->them.commit_fee, peer->us.commit_fee);
|
||||
/* FIXME: Check their cstate too (different fee rate!) */
|
||||
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)
|
||||
fatal("Insufficient anchor funds for commitfee");
|
||||
|
||||
@ -1245,8 +1294,10 @@ void make_commit_txs(const tal_t *ctx,
|
||||
our_revocation_hash,
|
||||
cstate);
|
||||
|
||||
/* Shallow copy: we don't touch HTLCs, just amounts and fees. */
|
||||
their_cstate = *cstate;
|
||||
invert_cstate(&their_cstate);
|
||||
adjust_fee(&their_cstate, peer->them.commit_fee_rate);
|
||||
*theirs = create_commit_tx(ctx,
|
||||
&peer->them.finalkey,
|
||||
&peer->us.finalkey,
|
||||
@ -1377,16 +1428,7 @@ static void check_htlc_expiry(struct peer *peer, void *unused)
|
||||
continue;
|
||||
|
||||
cstate = copy_funding(peer, peer->cstate);
|
||||
|
||||
/* This should never fail! */
|
||||
if (!funding_delta(peer->anchor.satoshis,
|
||||
0,
|
||||
-htlc->msatoshis,
|
||||
&cstate->b, &cstate->a)) {
|
||||
fatal("Unexpected failure expirint HTLC of %"PRIu64
|
||||
" milli-satoshis", htlc->msatoshis);
|
||||
}
|
||||
funding_remove_htlc(&cstate->b, i);
|
||||
funding_b_fail_htlc(cstate, i);
|
||||
stage.fail.index = i;
|
||||
set_htlc_command(peer, cstate, NULL, CMD_SEND_HTLC_FAIL,
|
||||
&stage);
|
||||
@ -1430,9 +1472,8 @@ static void do_newhtlc(struct peer *peer, struct newhtlc *newhtlc)
|
||||
/* Can we even offer this much? We check now, just before we
|
||||
* execute. */
|
||||
cstate = copy_funding(newhtlc, peer->cstate);
|
||||
if (!funding_delta(peer->anchor.satoshis,
|
||||
0, newhtlc->htlc.msatoshis,
|
||||
&cstate->a, &cstate->b)) {
|
||||
if (!funding_a_add_htlc(cstate, newhtlc->htlc.msatoshis,
|
||||
&newhtlc->htlc.expiry, &newhtlc->htlc.rhash)) {
|
||||
command_fail(newhtlc->jsoncmd,
|
||||
"Cannot afford %"PRIu64" milli-satoshis",
|
||||
newhtlc->htlc.msatoshis);
|
||||
@ -1440,10 +1481,6 @@ static void do_newhtlc(struct peer *peer, struct newhtlc *newhtlc)
|
||||
}
|
||||
|
||||
/* FIXME: Never propose duplicate rvalues? */
|
||||
|
||||
/* Add the htlc to our side of channel. */
|
||||
funding_add_htlc(&cstate->a, newhtlc->htlc.msatoshis,
|
||||
&newhtlc->htlc.expiry, &newhtlc->htlc.rhash);
|
||||
peer_add_htlc_expiry(peer, &newhtlc->htlc.expiry);
|
||||
|
||||
set_htlc_command(peer, cstate, newhtlc->jsoncmd,
|
||||
@ -1541,7 +1578,6 @@ static void do_fullfill(struct peer *peer,
|
||||
struct channel_state *cstate;
|
||||
struct sha256 rhash;
|
||||
size_t i;
|
||||
struct channel_htlc *htlc;
|
||||
union htlc_staging stage;
|
||||
|
||||
stage.fulfill.fulfill = HTLC_FULFILL;
|
||||
@ -1556,20 +1592,8 @@ static void do_fullfill(struct peer *peer,
|
||||
return;
|
||||
}
|
||||
stage.fulfill.index = i;
|
||||
/* Point at current one, since we remove from new cstate. */
|
||||
htlc = &peer->cstate->b.htlcs[i];
|
||||
|
||||
cstate = copy_funding(fulfillhtlc, peer->cstate);
|
||||
/* This should never fail! */
|
||||
if (!funding_delta(peer->anchor.satoshis,
|
||||
-htlc->msatoshis,
|
||||
-htlc->msatoshis,
|
||||
&cstate->b, &cstate->a)) {
|
||||
fatal("Unexpected failure fulfilling HTLC of %"PRIu64
|
||||
" milli-satoshis", htlc->msatoshis);
|
||||
return;
|
||||
}
|
||||
funding_remove_htlc(&cstate->b, i);
|
||||
funding_b_fulfill_htlc(cstate, i);
|
||||
|
||||
set_htlc_command(peer, cstate, fulfillhtlc->jsoncmd,
|
||||
CMD_SEND_HTLC_FULFILL, &stage);
|
||||
@ -1628,7 +1652,6 @@ static void do_failhtlc(struct peer *peer,
|
||||
{
|
||||
struct channel_state *cstate;
|
||||
size_t i;
|
||||
struct channel_htlc *htlc;
|
||||
union htlc_staging stage;
|
||||
|
||||
stage.fail.fail = HTLC_FAIL;
|
||||
@ -1639,21 +1662,9 @@ static void do_failhtlc(struct peer *peer,
|
||||
return;
|
||||
}
|
||||
stage.fail.index = i;
|
||||
/* Point to current one, since we remove from new cstate. */
|
||||
htlc = &peer->cstate->b.htlcs[i];
|
||||
|
||||
cstate = copy_funding(failhtlc, peer->cstate);
|
||||
|
||||
/* This should never fail! */
|
||||
if (!funding_delta(peer->anchor.satoshis,
|
||||
0,
|
||||
-htlc->msatoshis,
|
||||
&cstate->b, &cstate->a)) {
|
||||
fatal("Unexpected failure routefailing HTLC of %"PRIu64
|
||||
" milli-satoshis", htlc->msatoshis);
|
||||
return;
|
||||
}
|
||||
funding_remove_htlc(&cstate->b, i);
|
||||
funding_b_fail_htlc(cstate, i);
|
||||
|
||||
set_htlc_command(peer, cstate, failhtlc->jsoncmd,
|
||||
CMD_SEND_HTLC_FAIL, &stage);
|
||||
|
@ -52,7 +52,7 @@ struct peer_visible_state {
|
||||
/* Minimum depth of anchor before channel usable. */
|
||||
unsigned int mindepth;
|
||||
/* Commitment fee they're offering (satoshi). */
|
||||
u64 commit_fee;
|
||||
u64 commit_fee_rate;
|
||||
/* Revocation hash for latest commit tx. */
|
||||
struct sha256 revocation_hash;
|
||||
/* Revocation hash for next commit tx. */
|
||||
@ -187,4 +187,6 @@ void peer_add_htlc_expiry(struct peer *peer,
|
||||
struct bitcoin_tx *peer_create_close_tx(const tal_t *ctx,
|
||||
const struct peer *peer, u64 fee);
|
||||
|
||||
uint64_t commit_tx_fee(const struct bitcoin_tx *commit,
|
||||
uint64_t anchor_satoshis);
|
||||
#endif /* LIGHTNING_DAEMON_PEER_H */
|
||||
|
@ -16,6 +16,17 @@ REDIRERR1="$DIR1/errors"
|
||||
REDIRERR2="$DIR2/errors"
|
||||
FGREP="fgrep -q"
|
||||
|
||||
# setup.sh gives us 0.00999999 bitcoin, = 999999 satoshi = 999999000 millisatoshi
|
||||
AMOUNT=999999000
|
||||
|
||||
# Default fee rate per kb.
|
||||
FEE_RATE=200000
|
||||
|
||||
# Fee in millisatoshi if we have no htlcs (note rounding to make it even)
|
||||
NO_HTLCS_FEE=$((338 * $FEE_RATE / 2000 * 2000))
|
||||
ONE_HTLCS_FEE=$(( (338 + 32) * $FEE_RATE / 2000 * 2000))
|
||||
EXTRA_FEE=$(($ONE_HTLCS_FEE - $NO_HTLCS_FEE))
|
||||
|
||||
# Always use valgrind.
|
||||
PREFIX="valgrind -q --error-exitcode=7"
|
||||
|
||||
@ -240,7 +251,11 @@ sleep 2
|
||||
lcli1 getpeers | $FGREP STATE_NORMAL_HIGHPRIO
|
||||
lcli2 getpeers | $FGREP STATE_NORMAL_LOWPRIO
|
||||
|
||||
check_status 949999000 50000000 "" 0 0 ""
|
||||
A_AMOUNT=$(($AMOUNT - $NO_HTLCS_FEE))
|
||||
A_FEE=$NO_HTLCS_FEE
|
||||
B_AMOUNT=0
|
||||
B_FEE=0
|
||||
check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE ""
|
||||
|
||||
EXPIRY=$(( $(date +%s) + 1000))
|
||||
SECRET=1de08917a61cb2b62ed5937d38577f6a7bfe59c176781c6d8128018e8b5ccdfd
|
||||
@ -248,29 +263,43 @@ RHASH=`lcli1 dev-rhash $SECRET | sed 's/.*"\([0-9a-f]*\)".*/\1/'`
|
||||
lcli1 newhtlc $ID2 1000000 $EXPIRY $RHASH
|
||||
|
||||
# Check channel status
|
||||
check_status 948999000 50000000 '{ "msatoshis" : 1000000, "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH'" } ' 0 0 ""
|
||||
A_AMOUNT=$(($A_AMOUNT - $EXTRA_FEE - 1000000))
|
||||
A_FEE=$(($A_FEE + $EXTRA_FEE))
|
||||
check_status $A_AMOUNT $A_FEE '{ "msatoshis" : 1000000, "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH'" } ' $B_AMOUNT $B_FEE ""
|
||||
|
||||
lcli2 fulfillhtlc $ID1 $SECRET
|
||||
|
||||
# We've transferred the HTLC amount to 2, who now has to pay fees.
|
||||
check_status 949999000 49000000 "" 0 1000000 ""
|
||||
# We've transferred the HTLC amount to 2, who now has to pay fees,
|
||||
# so no net change for A who saves on fees.
|
||||
B_FEE=1000000
|
||||
# With no HTLCs, extra fee no longer required.
|
||||
A_FEE=$(($A_FEE - $EXTRA_FEE - $B_FEE))
|
||||
A_AMOUNT=$(($A_AMOUNT + $EXTRA_FEE + 1000000))
|
||||
|
||||
check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE ""
|
||||
|
||||
# A new one, at 10x the amount.
|
||||
lcli1 newhtlc $ID2 10000000 $EXPIRY $RHASH
|
||||
|
||||
# Check channel status
|
||||
check_status 939999000 49000000 '{ "msatoshis" : 10000000, "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH'" } ' 0 1000000 ""
|
||||
A_AMOUNT=$(($A_AMOUNT - $EXTRA_FEE - 10000000))
|
||||
A_FEE=$(($A_FEE + $EXTRA_FEE))
|
||||
check_status $A_AMOUNT $A_FEE '{ "msatoshis" : 10000000, "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH'" } ' $B_AMOUNT $B_FEE ""
|
||||
|
||||
lcli2 failhtlc $ID1 $RHASH
|
||||
|
||||
# Back to how we were before.
|
||||
check_status 949999000 49000000 "" 0 1000000 ""
|
||||
A_AMOUNT=$(($A_AMOUNT + $EXTRA_FEE + 10000000))
|
||||
A_FEE=$(($A_FEE - $EXTRA_FEE))
|
||||
check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE ""
|
||||
|
||||
# Same again, but this time it expires.
|
||||
lcli1 newhtlc $ID2 10000000 $EXPIRY $RHASH
|
||||
|
||||
# Check channel status
|
||||
check_status 939999000 49000000 '{ "msatoshis" : 10000000, "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH'" } ' 0 1000000 ""
|
||||
A_AMOUNT=$(($A_AMOUNT - $EXTRA_FEE - 10000000))
|
||||
A_FEE=$(($A_FEE + $EXTRA_FEE))
|
||||
check_status $A_AMOUNT $A_FEE '{ "msatoshis" : 10000000, "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH'" } ' $B_AMOUNT $B_FEE ""
|
||||
|
||||
# Make sure node1 accepts the expiry packet.
|
||||
lcli1 dev-mocktime $(($EXPIRY))
|
||||
@ -280,7 +309,9 @@ lcli2 dev-mocktime $(($EXPIRY + 31))
|
||||
sleep 1
|
||||
|
||||
# Back to how we were before.
|
||||
check_status 949999000 49000000 "" 0 1000000 ""
|
||||
A_AMOUNT=$(($A_AMOUNT + $EXTRA_FEE + 10000000))
|
||||
A_FEE=$(($A_FEE - $EXTRA_FEE))
|
||||
check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE ""
|
||||
|
||||
lcli1 close $ID2
|
||||
|
||||
|
374
funding.c
374
funding.c
@ -4,34 +4,35 @@
|
||||
#include <ccan/structeq/structeq.h>
|
||||
#include <string.h>
|
||||
|
||||
static bool subtract_fees(uint64_t *funder, uint64_t *non_funder,
|
||||
uint64_t *funder_fee, uint64_t *non_funder_fee,
|
||||
bool non_funder_paying, uint64_t fee)
|
||||
uint64_t fee_by_feerate(size_t txsize, uint32_t fee_rate)
|
||||
{
|
||||
/* Funder gets 1 millisatsoshi rounding benefit! */
|
||||
*non_funder_fee = fee - fee / 2;
|
||||
/* BOLT #2:
|
||||
*
|
||||
* The fee for a commitment transaction MUST be calculated by
|
||||
* the multiplying this bytescount by the fee rate, dividing
|
||||
* by 1000 and truncating (rounding down) the result to an
|
||||
* even number of satoshis.
|
||||
*/
|
||||
return txsize * fee_rate / 2000 * 2;
|
||||
}
|
||||
|
||||
if (*non_funder < *non_funder_fee) {
|
||||
/*
|
||||
* This happens initially, as funder has all the money.
|
||||
* That's OK, but don't let non-funder spend if they can't
|
||||
* cover fee.
|
||||
*/
|
||||
if (non_funder_paying)
|
||||
return false;
|
||||
static uint64_t calculate_fee_msat(size_t num_nondust_htlcs,
|
||||
uint32_t fee_rate)
|
||||
{
|
||||
uint64_t bytes;
|
||||
|
||||
/* Pay everything they can, funder pays rest. */
|
||||
*non_funder_fee = *non_funder;
|
||||
}
|
||||
/* BOLT #2:
|
||||
*
|
||||
* A node MUST use the formula 338 + 32 bytes for every
|
||||
* non-dust HTLC as the bytecount for calculating commitment
|
||||
* transaction fees. Note that the fee requirement is
|
||||
* unchanged, even if the elimination of dust HTLC outputs has
|
||||
* caused a non-zero fee already.
|
||||
*/
|
||||
bytes = 338 + 32 * num_nondust_htlcs;
|
||||
|
||||
/* Funder must always ensure they can pay their share. */
|
||||
*funder_fee = fee - *non_funder_fee;
|
||||
if (*funder < *funder_fee)
|
||||
return false;
|
||||
|
||||
*non_funder -= *non_funder_fee;
|
||||
*funder -= *funder_fee;
|
||||
return true;
|
||||
/* milli-satoshis */
|
||||
return fee_by_feerate(bytes, fee_rate) * 1000;
|
||||
}
|
||||
|
||||
/* Total, in millisatoshi. */
|
||||
@ -45,130 +46,170 @@ static uint64_t htlcs_total(const struct channel_htlc *htlcs)
|
||||
return total;
|
||||
}
|
||||
|
||||
static bool change_funding(uint64_t anchor_satoshis,
|
||||
int64_t delta_a_msat,
|
||||
int64_t htlc_msat,
|
||||
uint64_t a, uint64_t b, uint64_t fee,
|
||||
struct channel_oneside *a_side,
|
||||
struct channel_oneside *b_side)
|
||||
/* Pay this much fee, if possible. Return amount unpaid. */
|
||||
static uint64_t pay_fee(struct channel_oneside *side, uint64_t fee_msat)
|
||||
{
|
||||
uint64_t a_fee, b_fee;
|
||||
int64_t delta_b_msat;
|
||||
bool got_fees;
|
||||
|
||||
assert(a + b + htlcs_total(a_side->htlcs) + htlcs_total(b_side->htlcs)
|
||||
== anchor_satoshis * 1000);
|
||||
assert(a_side->offered_anchor != b_side->offered_anchor);
|
||||
|
||||
/* B gets whatever A gives. */
|
||||
delta_b_msat = -delta_a_msat;
|
||||
/* A also pays for the htlc (if any). */
|
||||
delta_a_msat -= htlc_msat;
|
||||
|
||||
/* Transferring more than we have? */
|
||||
if (delta_b_msat < 0 && -delta_b_msat > b)
|
||||
return false;
|
||||
if (delta_a_msat < 0 && -delta_a_msat > a)
|
||||
return false;
|
||||
|
||||
/* Adjust amounts. */
|
||||
a += delta_a_msat;
|
||||
b += delta_b_msat;
|
||||
|
||||
/* Take off fee from both parties if possible. */
|
||||
if (a_side->offered_anchor)
|
||||
got_fees = subtract_fees(&a, &b, &a_fee, &b_fee,
|
||||
delta_b_msat < 0, fee);
|
||||
else
|
||||
got_fees = subtract_fees(&b, &a, &b_fee, &a_fee,
|
||||
delta_a_msat < 0, fee);
|
||||
|
||||
if (!got_fees)
|
||||
return false;
|
||||
|
||||
/* Now we know we're succeeding, update caller's state */
|
||||
a_side->pay_msat = a;
|
||||
b_side->pay_msat = b;
|
||||
a_side->fee_msat = a_fee;
|
||||
b_side->fee_msat = b_fee;
|
||||
return true;
|
||||
if (side->pay_msat >= fee_msat) {
|
||||
side->pay_msat -= fee_msat;
|
||||
side->fee_msat += fee_msat;
|
||||
return 0;
|
||||
} else {
|
||||
uint64_t remainder = fee_msat - side->pay_msat;
|
||||
side->fee_msat += side->pay_msat;
|
||||
side->pay_msat = 0;
|
||||
return remainder;
|
||||
}
|
||||
}
|
||||
|
||||
bool funding_delta(uint64_t anchor_satoshis,
|
||||
int64_t delta_a_msat,
|
||||
int64_t htlc_msat,
|
||||
struct channel_oneside *a_side,
|
||||
struct channel_oneside *b_side)
|
||||
/* Charge the fee as per BOLT #2 */
|
||||
static void recalculate_fees(struct channel_oneside *a,
|
||||
struct channel_oneside *b,
|
||||
uint64_t fee_msat)
|
||||
{
|
||||
uint64_t a, b;
|
||||
uint64_t fee;
|
||||
uint64_t remainder;
|
||||
|
||||
/* Start with A and B's current contributions, and maintain fee. */
|
||||
a = a_side->pay_msat + a_side->fee_msat;
|
||||
b = b_side->pay_msat + b_side->fee_msat;
|
||||
fee = a_side->fee_msat + b_side->fee_msat;
|
||||
/* Fold in fees, to recalcuate again below. */
|
||||
a->pay_msat += a->fee_msat;
|
||||
b->pay_msat += b->fee_msat;
|
||||
a->fee_msat = b->fee_msat = 0;
|
||||
|
||||
return change_funding(anchor_satoshis,
|
||||
delta_a_msat, htlc_msat,
|
||||
a, b, fee,
|
||||
a_side, b_side);
|
||||
/* BOLT #2:
|
||||
*
|
||||
* 1. If each nodes can afford half the fee from their
|
||||
* to-`final_key` output, reduce the two to-`final_key`
|
||||
* outputs accordingly.
|
||||
*
|
||||
* 2. Otherwise, reduce the to-`final_key` output of one node
|
||||
* which cannot afford the fee to zero (resulting in that
|
||||
* entire output paying fees). If the remaining
|
||||
* to-`final_key` output is greater than the fee remaining,
|
||||
* reduce it accordingly, otherwise reduce it to zero to
|
||||
* pay as much fee as possible.
|
||||
*/
|
||||
remainder = pay_fee(a, fee_msat / 2) + pay_fee(b, fee_msat / 2);
|
||||
|
||||
/* If there's anything left, the other side tries to pay for it. */
|
||||
remainder = pay_fee(a, remainder);
|
||||
pay_fee(b, remainder);
|
||||
}
|
||||
|
||||
/* a transfers htlc_msat to a HTLC (gains it, if -ve) */
|
||||
static bool change_funding(uint64_t anchor_satoshis,
|
||||
uint32_t fee_rate,
|
||||
int64_t htlc_msat,
|
||||
struct channel_oneside *a,
|
||||
struct channel_oneside *b,
|
||||
size_t num_nondust_htlcs)
|
||||
{
|
||||
uint64_t fee_msat;
|
||||
|
||||
assert(a->pay_msat + a->fee_msat
|
||||
+ b->pay_msat + b->fee_msat
|
||||
+ htlcs_total(a->htlcs) + htlcs_total(b->htlcs)
|
||||
== anchor_satoshis * 1000);
|
||||
|
||||
fee_msat = calculate_fee_msat(num_nondust_htlcs, fee_rate);
|
||||
|
||||
/* If A is paying, can it afford it? */
|
||||
if (htlc_msat > 0) {
|
||||
if (htlc_msat + fee_msat / 2 > a->pay_msat + a->fee_msat)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* OK, now adjust funds for A, then recalculate fees. */
|
||||
a->pay_msat -= htlc_msat;
|
||||
recalculate_fees(a, b, fee_msat);
|
||||
|
||||
assert(a->pay_msat + a->fee_msat
|
||||
+ b->pay_msat + b->fee_msat
|
||||
+ htlcs_total(a->htlcs) + htlcs_total(b->htlcs) + htlc_msat
|
||||
== anchor_satoshis * 1000);
|
||||
return true;
|
||||
}
|
||||
|
||||
struct channel_state *initial_funding(const tal_t *ctx,
|
||||
bool am_funder,
|
||||
uint64_t anchor_satoshis,
|
||||
uint64_t fee)
|
||||
uint32_t fee_rate)
|
||||
{
|
||||
uint64_t fee_msat;
|
||||
struct channel_state *cstate = talz(ctx, struct channel_state);
|
||||
|
||||
cstate->a.htlcs = tal_arr(cstate, struct channel_htlc, 0);
|
||||
cstate->b.htlcs = tal_arr(cstate, struct channel_htlc, 0);
|
||||
|
||||
if (fee > anchor_satoshis)
|
||||
cstate->fee_rate = fee_rate;
|
||||
cstate->anchor = anchor_satoshis;
|
||||
|
||||
/* Anchor must fit in 32 bit. */
|
||||
if (anchor_satoshis >= (1ULL << 32) / 1000)
|
||||
return tal_free(cstate);
|
||||
|
||||
if (anchor_satoshis > (1ULL << 32) / 1000)
|
||||
fee_msat = calculate_fee_msat(0, fee_rate);
|
||||
if (fee_msat > anchor_satoshis * 1000)
|
||||
return tal_free(cstate);
|
||||
|
||||
|
||||
/* Initially, all goes back to funder. */
|
||||
cstate->a.pay_msat = anchor_satoshis * 1000 - fee * 1000;
|
||||
cstate->a.fee_msat = fee * 1000;
|
||||
cstate->a.offered_anchor = true;
|
||||
cstate->b.offered_anchor = false;
|
||||
cstate->a.pay_msat = anchor_satoshis * 1000 - fee_msat;
|
||||
cstate->a.fee_msat = fee_msat;
|
||||
|
||||
/* If B (not A) is funder, invert. */
|
||||
if (!am_funder)
|
||||
invert_cstate(cstate);
|
||||
|
||||
/* Make sure it checks out. */
|
||||
assert(funding_delta(anchor_satoshis, 0, 0, &cstate->a, &cstate->b));
|
||||
assert(change_funding(anchor_satoshis, fee_rate, 0,
|
||||
&cstate->a, &cstate->b, 0));
|
||||
if (am_funder) {
|
||||
assert(cstate->a.fee_msat == fee_msat);
|
||||
assert(cstate->b.fee_msat == 0);
|
||||
} else {
|
||||
assert(cstate->b.fee_msat == fee_msat);
|
||||
assert(cstate->a.fee_msat == 0);
|
||||
}
|
||||
return cstate;
|
||||
}
|
||||
|
||||
bool adjust_fee(uint64_t anchor_satoshis,
|
||||
uint64_t fee_satoshis,
|
||||
struct channel_oneside *a_side,
|
||||
struct channel_oneside *b_side)
|
||||
/* Dust is defined as an output < 546*minRelayTxFee/1000.
|
||||
* minRelayTxFee defaults to 1000 satoshi. */
|
||||
bool is_dust_amount(uint64_t satoshis)
|
||||
{
|
||||
uint64_t a, b;
|
||||
return satoshis < 546;
|
||||
}
|
||||
|
||||
a = a_side->pay_msat + a_side->fee_msat;
|
||||
b = b_side->pay_msat + b_side->fee_msat;
|
||||
static size_t count_nondust_htlcs(const struct channel_htlc *htlcs)
|
||||
{
|
||||
size_t i, n = tal_count(htlcs), nondust = 0;
|
||||
|
||||
/* No HTLC or delta, just fee recalculate. */
|
||||
return change_funding(anchor_satoshis,
|
||||
0, 0, a, b, fee_satoshis * 1000,
|
||||
a_side, b_side);
|
||||
for (i = 0; i < n; i++)
|
||||
if (!is_dust_amount(htlcs[i].msatoshis / 1000))
|
||||
nondust++;
|
||||
return nondust;
|
||||
}
|
||||
|
||||
static size_t total_nondust_htlcs(const struct channel_state *cstate)
|
||||
{
|
||||
return count_nondust_htlcs(cstate->a.htlcs)
|
||||
+ count_nondust_htlcs(cstate->b.htlcs);
|
||||
}
|
||||
|
||||
void adjust_fee(struct channel_state *cstate, uint32_t fee_rate)
|
||||
{
|
||||
uint64_t fee_msat;
|
||||
|
||||
fee_msat = calculate_fee_msat(total_nondust_htlcs(cstate), fee_rate);
|
||||
|
||||
recalculate_fees(&cstate->a, &cstate->b, fee_msat);
|
||||
}
|
||||
|
||||
bool force_fee(struct channel_state *cstate, uint64_t fee)
|
||||
{
|
||||
/* Beware overflow! */
|
||||
if (fee > 0xFFFFFFFFFFFFFFFFULL / 1000)
|
||||
return false;
|
||||
recalculate_fees(&cstate->a, &cstate->b, fee * 1000);
|
||||
return cstate->a.fee_msat + cstate->b.fee_msat == fee * 1000;
|
||||
}
|
||||
|
||||
/* We take the minimum. If one side offers too little, it should be rejected */
|
||||
uint64_t commit_fee(uint64_t a_satoshis, uint64_t b_satoshis)
|
||||
{
|
||||
if (a_satoshis < b_satoshis)
|
||||
return a_satoshis;
|
||||
return b_satoshis;
|
||||
}
|
||||
|
||||
void invert_cstate(struct channel_state *cstate)
|
||||
{
|
||||
struct channel_oneside tmp;
|
||||
@ -178,11 +219,28 @@ void invert_cstate(struct channel_state *cstate)
|
||||
cstate->b = tmp;
|
||||
}
|
||||
|
||||
void funding_add_htlc(struct channel_oneside *creator,
|
||||
u32 msatoshis, const struct abs_locktime *expiry,
|
||||
const struct sha256 *rhash)
|
||||
/* Add a HTLC to @creator if it can afford it. */
|
||||
static bool add_htlc(const struct channel_state *cstate,
|
||||
struct channel_oneside *creator,
|
||||
struct channel_oneside *recipient,
|
||||
u32 msatoshis, const struct abs_locktime *expiry,
|
||||
const struct sha256 *rhash)
|
||||
{
|
||||
size_t n = tal_count(creator->htlcs);
|
||||
size_t n, nondust;
|
||||
|
||||
assert((creator == &cstate->a && recipient == &cstate->b)
|
||||
|| (creator == &cstate->b && recipient == &cstate->a));
|
||||
|
||||
/* Remember to count the new one in total txsize if not dust! */
|
||||
nondust = total_nondust_htlcs(cstate);
|
||||
if (!is_dust_amount(msatoshis / 1000))
|
||||
nondust++;
|
||||
|
||||
if (!change_funding(cstate->anchor, cstate->fee_rate,
|
||||
msatoshis, creator, recipient, nondust))
|
||||
return false;
|
||||
|
||||
n = tal_count(creator->htlcs);
|
||||
tal_resize(&creator->htlcs, n+1);
|
||||
|
||||
creator->htlcs[n].msatoshis = msatoshis;
|
||||
@ -191,6 +249,77 @@ void funding_add_htlc(struct channel_oneside *creator,
|
||||
memcheck(&creator->htlcs[n].msatoshis,
|
||||
sizeof(creator->htlcs[n].msatoshis));
|
||||
memcheck(&creator->htlcs[n].rhash, sizeof(creator->htlcs[n].rhash));
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Remove htlc from creator, credit it to beneficiary. */
|
||||
static void remove_htlc(const struct channel_state *cstate,
|
||||
struct channel_oneside *creator,
|
||||
struct channel_oneside *beneficiary,
|
||||
struct channel_oneside *non_beneficiary,
|
||||
size_t i)
|
||||
{
|
||||
size_t n = tal_count(creator->htlcs);
|
||||
size_t nondust;
|
||||
|
||||
assert(i < n);
|
||||
assert(creator == &cstate->a || creator == &cstate->b);
|
||||
assert((beneficiary == &cstate->a && non_beneficiary == &cstate->b)
|
||||
|| (beneficiary == &cstate->b && non_beneficiary == &cstate->a));
|
||||
|
||||
/* Remember to remove this one in total txsize if not dust! */
|
||||
nondust = total_nondust_htlcs(cstate);
|
||||
if (!is_dust_amount(creator->htlcs[i].msatoshis / 1000)) {
|
||||
assert(nondust > 0);
|
||||
nondust--;
|
||||
}
|
||||
|
||||
/* Can't fail since msatoshis is positive. */
|
||||
if (!change_funding(cstate->anchor, cstate->fee_rate,
|
||||
-(int64_t)creator->htlcs[i].msatoshis,
|
||||
beneficiary, non_beneficiary, nondust))
|
||||
abort();
|
||||
|
||||
/* Actually remove the HTLC. */
|
||||
memmove(creator->htlcs + i, creator->htlcs + i + 1,
|
||||
(n - i - 1) * sizeof(*creator->htlcs));
|
||||
tal_resize(&creator->htlcs, n-1);
|
||||
}
|
||||
|
||||
bool funding_a_add_htlc(struct channel_state *cstate,
|
||||
u32 msatoshis, const struct abs_locktime *expiry,
|
||||
const struct sha256 *rhash)
|
||||
{
|
||||
return add_htlc(cstate, &cstate->a, &cstate->b,
|
||||
msatoshis, expiry, rhash);
|
||||
}
|
||||
|
||||
bool funding_b_add_htlc(struct channel_state *cstate,
|
||||
u32 msatoshis, const struct abs_locktime *expiry,
|
||||
const struct sha256 *rhash)
|
||||
{
|
||||
return add_htlc(cstate, &cstate->b, &cstate->a,
|
||||
msatoshis, expiry, rhash);
|
||||
}
|
||||
|
||||
void funding_a_fail_htlc(struct channel_state *cstate, size_t index)
|
||||
{
|
||||
remove_htlc(cstate, &cstate->a, &cstate->a, &cstate->b, index);
|
||||
}
|
||||
|
||||
void funding_b_fail_htlc(struct channel_state *cstate, size_t index)
|
||||
{
|
||||
remove_htlc(cstate, &cstate->b, &cstate->b, &cstate->a, index);
|
||||
}
|
||||
|
||||
void funding_a_fulfill_htlc(struct channel_state *cstate, size_t index)
|
||||
{
|
||||
remove_htlc(cstate, &cstate->a, &cstate->b, &cstate->a, index);
|
||||
}
|
||||
|
||||
void funding_b_fulfill_htlc(struct channel_state *cstate, size_t index)
|
||||
{
|
||||
remove_htlc(cstate, &cstate->b, &cstate->a, &cstate->b, index);
|
||||
}
|
||||
|
||||
size_t funding_find_htlc(struct channel_oneside *creator,
|
||||
@ -205,15 +334,6 @@ size_t funding_find_htlc(struct channel_oneside *creator,
|
||||
return i;
|
||||
}
|
||||
|
||||
void funding_remove_htlc(struct channel_oneside *creator, size_t i)
|
||||
{
|
||||
size_t n = tal_count(creator->htlcs);
|
||||
assert(i < n);
|
||||
memmove(creator->htlcs + i, creator->htlcs + i + 1,
|
||||
(n - i - 1) * sizeof(*creator->htlcs));
|
||||
tal_resize(&creator->htlcs, n-1);
|
||||
}
|
||||
|
||||
struct channel_state *copy_funding(const tal_t *ctx,
|
||||
const struct channel_state *cstate)
|
||||
{
|
||||
|
113
funding.h
113
funding.h
@ -15,13 +15,15 @@ struct channel_htlc {
|
||||
struct channel_oneside {
|
||||
/* Payment and fee is in millisatoshi. */
|
||||
uint32_t pay_msat, fee_msat;
|
||||
/* Did we offer the anchor? */
|
||||
bool offered_anchor;
|
||||
/* Use tal_count to get the number */
|
||||
struct channel_htlc *htlcs;
|
||||
};
|
||||
|
||||
struct channel_state {
|
||||
/* Satoshis paid by anchor. */
|
||||
uint64_t anchor;
|
||||
/* Satoshis per 1000 bytes. */
|
||||
uint32_t fee_rate;
|
||||
struct channel_oneside a, b;
|
||||
};
|
||||
|
||||
@ -30,14 +32,14 @@ struct channel_state {
|
||||
* @ctx: tal context to allocate return value from.
|
||||
* @am_funder: am I paying for the anchor?
|
||||
* @anchor_satoshis: The anchor amount.
|
||||
* @fee: amount to pay in fees (in satoshi).
|
||||
* @fee_rate: amount to pay in fees per kb (in satoshi).
|
||||
*
|
||||
* Returns state, or NULL if malformed.
|
||||
*/
|
||||
struct channel_state *initial_funding(const tal_t *ctx,
|
||||
bool am_funder,
|
||||
uint64_t anchor_satoshis,
|
||||
uint64_t fee);
|
||||
uint32_t fee_rate);
|
||||
|
||||
/**
|
||||
* copy_funding: Make a deep copy of channel_state
|
||||
@ -48,37 +50,64 @@ struct channel_state *copy_funding(const tal_t *ctx,
|
||||
const struct channel_state *cstate);
|
||||
|
||||
/**
|
||||
* funding_delta: With this change, what's the new state?
|
||||
* @anchor_satoshis: The anchor amount.
|
||||
* @delta_a: How many millisatoshi A changes (-ve => A pay B, +ve => B pays A)
|
||||
* @htlc: Millisatoshi A is putting into a HTLC (-ve if htlc is cancelled)
|
||||
* @a_side: channel a's state to update.
|
||||
* @b_side: channel b's state to update.
|
||||
* funding_a_add_htlc: append an HTLC to A's side of cstate if it can afford it
|
||||
* @cstate: The channel state
|
||||
* @msatoshis: Millisatoshi A is putting into a HTLC
|
||||
* @expiry: time it expires
|
||||
* @rhash: hash of redeem secret
|
||||
*
|
||||
* If A can't afford the HTLC (or still owes its half of the fees),
|
||||
* this will return false and leave @cstate unchanged. Otherwise
|
||||
* cstate->a.htlcs will have the HTLC appended, and pay_msat and
|
||||
* fee_msat are adjusted accordingly.
|
||||
*/
|
||||
bool funding_delta(uint64_t anchor_satoshis,
|
||||
int64_t delta_a_msat,
|
||||
int64_t htlc_msat,
|
||||
struct channel_oneside *a_side,
|
||||
struct channel_oneside *b_side);
|
||||
bool funding_a_add_htlc(struct channel_state *cstate,
|
||||
u32 msatoshis, const struct abs_locktime *expiry,
|
||||
const struct sha256 *rhash);
|
||||
|
||||
bool funding_b_add_htlc(struct channel_state *cstate,
|
||||
u32 msatoshis, const struct abs_locktime *expiry,
|
||||
const struct sha256 *rhash);
|
||||
|
||||
/**
|
||||
* adjust_fee: Change fee.
|
||||
* @anchor_satoshis: The anchor amount.
|
||||
* @fee_satoshis: The new fee amount.
|
||||
* @a_side: channel a's state to update.
|
||||
* @b_side: channel b's state to update.
|
||||
* funding_a_fail_htlc: remove an HTLC from A's side of cstate, funds to A
|
||||
* @cstate: The channel state
|
||||
* @index: the index into cstate->a.htlcs[].
|
||||
*
|
||||
* This will remove the @index'th entry in cstate->a.htlcs[], and credit
|
||||
* the value of the HTLC (back) to A.
|
||||
*/
|
||||
bool adjust_fee(uint64_t anchor_satoshis,
|
||||
uint64_t fee_satoshis,
|
||||
struct channel_oneside *a_side,
|
||||
struct channel_oneside *b_side);
|
||||
void funding_a_fail_htlc(struct channel_state *cstate, size_t index);
|
||||
void funding_b_fail_htlc(struct channel_state *cstate, size_t index);
|
||||
|
||||
/**
|
||||
* commit_fee: Fee amount for commit tx.
|
||||
* @a_satoshis: A's openchannel->commitment_fee offer
|
||||
* @b_satoshis: B's openchannel->commitment_fee offer
|
||||
* funding_a_fulfill_htlc: remove an HTLC from A's side of cstate, funds to B
|
||||
* @cstate: The channel state
|
||||
* @index: the index into cstate->a.htlcs[].
|
||||
*
|
||||
* This will remove the @index'th entry in cstate->a.htlcs[], and credit
|
||||
* the value of the HTLC to B.
|
||||
*/
|
||||
uint64_t commit_fee(uint64_t a_satoshis, uint64_t b_satoshis);
|
||||
void funding_a_fulfill_htlc(struct channel_state *cstate, size_t index);
|
||||
void funding_b_fulfill_htlc(struct channel_state *cstate, size_t index);
|
||||
|
||||
/**
|
||||
* adjust_fee: Change fee rate.
|
||||
* @cstate: The channel state
|
||||
* @fee_rate: fee in satoshi per 1000 bytes.
|
||||
*/
|
||||
void adjust_fee(struct channel_state *cstate, uint32_t fee_rate);
|
||||
|
||||
/**
|
||||
* force_fee: Change fee to a specific value.
|
||||
* @cstate: The channel state
|
||||
* @fee: fee in satoshi.
|
||||
*
|
||||
* This is used for the close transaction, which specifies an exact fee.
|
||||
* If the fee cannot be paid in full, this return false (but cstate will
|
||||
* still be altered).
|
||||
*/
|
||||
bool force_fee(struct channel_state *cstate, uint64_t fee);
|
||||
|
||||
/**
|
||||
* invert_cstate: Get the other side's state.
|
||||
@ -86,17 +115,6 @@ uint64_t commit_fee(uint64_t a_satoshis, uint64_t b_satoshis);
|
||||
*/
|
||||
void invert_cstate(struct channel_state *cstate);
|
||||
|
||||
/**
|
||||
* funding_add_htlc: append an HTLC to this side of the channel.
|
||||
* @creator: channel_state->a or channel_state->b, whichever originated htlc
|
||||
* @msatoshis: amount in millisatoshi
|
||||
* @expiry: time it expires
|
||||
* @rhash: hash of redeem secret
|
||||
*/
|
||||
void funding_add_htlc(struct channel_oneside *creator,
|
||||
u32 msatoshis, const struct abs_locktime *expiry,
|
||||
const struct sha256 *rhash);
|
||||
|
||||
/**
|
||||
* funding_find_htlc: find an HTLC on this side of the channel.
|
||||
* @creator: channel_state->a or channel_state->b, whichever originated htlc
|
||||
@ -109,10 +127,19 @@ size_t funding_find_htlc(struct channel_oneside *creator,
|
||||
const struct sha256 *rhash);
|
||||
|
||||
/**
|
||||
* funding_remove_htlc: remove an HTLC from this side of the channel.
|
||||
* @creator: channel_state->a or channel_state->b, whichever originated htlc
|
||||
* @i: index returned from funding_find_htlc.
|
||||
* fee_for_feerate: calculate the fee (in satoshi) for a given fee_rate.
|
||||
* @txsize: transaction size in bytes.
|
||||
* @fee_rate: satoshi per 1000 bytes.
|
||||
*/
|
||||
void funding_remove_htlc(struct channel_oneside *creator, size_t i);
|
||||
uint64_t fee_by_feerate(size_t txsize, uint32_t fee_rate);
|
||||
|
||||
/**
|
||||
* is_dust_amount: is an output of this value considered dust?
|
||||
* @satoshis: number of satoshis.
|
||||
*
|
||||
* Transactions with dust outputs will not be relayed by the bitcoin
|
||||
* network. It's not an exact definition, unfortunately.
|
||||
*/
|
||||
bool is_dust_amount(uint64_t satoshis);
|
||||
|
||||
#endif /* LIGHTNING_FUNDING_H */
|
||||
|
@ -1413,12 +1413,12 @@ static const ProtobufCFieldDescriptor open_channel__field_descriptors[8] =
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"commitment_fee",
|
||||
"initial_fee_rate",
|
||||
7,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_UINT64,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(OpenChannel, commitment_fee),
|
||||
offsetof(OpenChannel, initial_fee_rate),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
@ -1440,9 +1440,9 @@ static const ProtobufCFieldDescriptor open_channel__field_descriptors[8] =
|
||||
static const unsigned open_channel__field_indices_by_name[] = {
|
||||
4, /* field[4] = anch */
|
||||
2, /* field[2] = commit_key */
|
||||
6, /* field[6] = commitment_fee */
|
||||
0, /* field[0] = delay */
|
||||
3, /* field[3] = final_key */
|
||||
6, /* field[6] = initial_fee_rate */
|
||||
5, /* field[5] = min_depth */
|
||||
7, /* field[7] = next_revocation_hash */
|
||||
1, /* field[1] = revocation_hash */
|
||||
|
@ -200,7 +200,7 @@ struct _OpenChannel
|
||||
/*
|
||||
* How much fee would I like on commitment tx?
|
||||
*/
|
||||
uint64_t commitment_fee;
|
||||
uint64_t initial_fee_rate;
|
||||
};
|
||||
#define OPEN_CHANNEL__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&open_channel__descriptor) \
|
||||
|
@ -84,7 +84,7 @@ message open_channel {
|
||||
optional uint32 min_depth = 6 [ default = 0 ];
|
||||
|
||||
// How much fee would I like on commitment tx?
|
||||
required uint64 commitment_fee = 7;
|
||||
required uint64 initial_fee_rate = 7;
|
||||
}
|
||||
|
||||
// Whoever is supplying anchor sends this.
|
||||
|
Loading…
Reference in New Issue
Block a user