Browse Source

daemon: HTLC expiry limits.

Don't accept an HTLC which is about to expire, nor one which will take
too long to expire.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 9 years ago
parent
commit
1018823f97
  1. 21
      daemon/lightningd.c
  2. 3
      daemon/lightningd.h
  3. 40
      daemon/packets.c
  4. 18
      daemon/peer.c
  5. 4
      daemon/test/test.sh

21
daemon/lightningd.c

@ -88,21 +88,31 @@ static void config_register_opts(struct lightningd_state *dstate)
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("--min-expiry", opt_set_u32, opt_show_u32,
&dstate->config.min_expiry,
"Minimum number of seconds to accept an HTLC before expiry");
opt_register_arg("--max-expiry", opt_set_u32, opt_show_u32,
&dstate->config.max_expiry,
"Maximum number of seconds to accept an HTLC before expiry");
opt_register_arg("--bitcoind-poll", opt_set_u32, opt_show_u32,
&dstate->config.poll_seconds,
"Seconds between polling for new transactions");
}
#define MINUTES 60
#define HOURS (60 * MINUTES)
#define DAYS (24 * HOURS)
static void default_config(struct config *config)
{
/* aka. "Dude, where's my coins?" */
config->testnet = true;
/* One day to catch cheating attempts. */
config->rel_locktime = 60 * 60 * 24;
config->rel_locktime = 1 * DAYS;
/* They can have up to 3 days. */
config->rel_locktime_max = 60 * 60 * 24 * 3;
config->rel_locktime_max = 2 * DAYS;
/* We're fairly trusting, under normal circumstances. */
config->anchor_confirms = 3;
@ -120,7 +130,12 @@ static void default_config(struct config *config)
/* Use this for mutual close. */
config->closing_fee = 10000;
/* Don't bother me unless I have 6 hours to collect. */
config->min_expiry = 6 * HOURS;
/* Don't lock up channel for more than 5 days. */
config->max_expiry = 5 * DAYS;
config->poll_seconds = 30;
}

3
daemon/lightningd.h

@ -35,6 +35,9 @@ struct config {
/* What fee we use for the closing transaction (satoshis) */
u64 closing_fee;
/* Minimum/maximum time for an expiring HTLC (seconds). */
u32 min_expiry, max_expiry;
/* How long (seconds) between polling bitcoind. */
u32 poll_seconds;
};

40
daemon/packets.c

@ -1,5 +1,6 @@
#include "bitcoin/script.h"
#include "bitcoin/tx.h"
#include "controlled_time.h"
#include "find_p2sh_out.h"
#include "lightningd.h"
#include "log.h"
@ -386,7 +387,19 @@ Pkt *accept_pkt_open_commit_sig(const tal_t *ctx,
return NULL;
}
static Pkt *decline_htlc(const tal_t *ctx, const char *why)
{
UpdateDeclineHtlc *d = tal(ctx, UpdateDeclineHtlc);
update_decline_htlc__init(d);
/* FIXME: Define why in protocol! */
d->reason_case = UPDATE_DECLINE_HTLC__REASON_CANNOT_ROUTE;
d->cannot_route = true;
return make_pkt(ctx, PKT__PKT_UPDATE_DECLINE_HTLC, d);
}
Pkt *accept_pkt_htlc_update(const tal_t *ctx,
struct peer *peer, const Pkt *pkt,
Pkt **decline)
@ -403,6 +416,26 @@ Pkt *accept_pkt_htlc_update(const tal_t *ctx,
err = pkt_err(ctx, "Invalid HTLC expiry");
goto fail;
}
/* FIXME: Handle block-based expiry! */
if (!abs_locktime_is_seconds(&cur->htlc->expiry)) {
*decline = decline_htlc(ctx,
"HTLC expiry in blocks not supported!");
goto decline;
}
if (abs_locktime_to_seconds(&cur->htlc->expiry) <
controlled_time().ts.tv_sec + peer->dstate->config.min_expiry) {
*decline = decline_htlc(ctx, "HTLC expiry too soon!");
goto decline;
}
if (abs_locktime_to_seconds(&cur->htlc->expiry) >
controlled_time().ts.tv_sec + peer->dstate->config.max_expiry) {
*decline = decline_htlc(ctx, "HTLC expiry too far!");
goto decline;
}
cur->cstate = copy_funding(cur, peer->cstate);
if (!funding_delta(peer->them.offer_anchor == CMD_OPEN_WITH_ANCHOR,
peer->anchor.satoshis,
@ -434,6 +467,11 @@ Pkt *accept_pkt_htlc_update(const tal_t *ctx,
fail:
tal_free(cur);
return err;
decline:
assert(*decline);
tal_free(cur);
return NULL;
};
Pkt *accept_pkt_htlc_routefail(const tal_t *ctx,

18
daemon/peer.c

@ -1,6 +1,7 @@
#include "bitcoind.h"
#include "close_tx.h"
#include "commit_tx.h"
#include "controlled_time.h"
#include "cryptopkt.h"
#include "dns.h"
#include "find_p2sh_out.h"
@ -715,7 +716,9 @@ void peer_unexpected_pkt(struct peer *peer, const Pkt *pkt)
/* Someone declined our HTLC: details in pkt (we will also get CMD_FAIL) */
void peer_htlc_declined(struct peer *peer, const Pkt *pkt)
{
FIXME_STUB(peer);
log_unusual(peer->log, "Peer declined htlc, reason %i",
pkt->update_decline_htlc->reason_case);
peer->current_htlc = tal_free(peer->current_htlc);
}
/* Called when their update overrides our update cmd. */
@ -1157,6 +1160,19 @@ static void json_newhtlc(struct command *cmd,
buffer + expirytok->start);
return;
}
if (abs_locktime_to_seconds(&newhtlc->htlc->expiry) <
controlled_time().ts.tv_sec + peer->dstate->config.min_expiry) {
command_fail(cmd, "HTLC expiry too soon!");
return;
}
if (abs_locktime_to_seconds(&newhtlc->htlc->expiry) >
controlled_time().ts.tv_sec + peer->dstate->config.max_expiry) {
command_fail(cmd, "HTLC expiry too far!");
return;
}
if (!hex_decode(buffer + rhashtok->start,
rhashtok->end - rhashtok->start,
&newhtlc->htlc->rhash,

4
daemon/test/test.sh

@ -53,8 +53,8 @@ check_status()
trap "echo Results in $DIR1 and $DIR2" EXIT
mkdir $DIR1 $DIR2
$PREFIX1 ../daemon/lightningd --log-level=debug --bitcoind-poll=1 --lightning-dir=$DIR1 > $REDIR1 &
$PREFIX2 ../daemon/lightningd --log-level=debug --bitcoind-poll=1 --lightning-dir=$DIR2 > $REDIR2 &
$PREFIX1 ../daemon/lightningd --log-level=debug --bitcoind-poll=1 --min-expiry=900 --lightning-dir=$DIR1 > $REDIR1 &
$PREFIX2 ../daemon/lightningd --log-level=debug --bitcoind-poll=1 --min-expiry=900 --lightning-dir=$DIR2 > $REDIR2 &
i=0
while ! $LCLI1 getlog | grep Hello; do

Loading…
Cancel
Save