mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
daemon: introduce union htlc_staging for proposed changes to HTLCs.
This encapsulates proposals more cleanly, and is important when we change the protocol to have more than one outstanding at a time. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
b8911cde98
commit
cc16f46621
@ -140,11 +140,12 @@ Pkt *pkt_htlc_add(const tal_t *ctx, const struct peer *peer,
|
||||
UpdateAddHtlc *u = tal(ctx, UpdateAddHtlc);
|
||||
|
||||
update_add_htlc__init(u);
|
||||
assert(htlc_prog->stage.type == HTLC_ADD);
|
||||
|
||||
u->revocation_hash = sha256_to_proto(u, &htlc_prog->our_revocation_hash);
|
||||
u->amount_msat = htlc_prog->htlc->msatoshis;
|
||||
u->r_hash = sha256_to_proto(u, &htlc_prog->htlc->rhash);
|
||||
u->expiry = abs_locktime_to_proto(u, &htlc_prog->htlc->expiry);
|
||||
u->amount_msat = htlc_prog->stage.add.htlc.msatoshis;
|
||||
u->r_hash = sha256_to_proto(u, &htlc_prog->stage.add.htlc.rhash);
|
||||
u->expiry = abs_locktime_to_proto(u, &htlc_prog->stage.add.htlc.expiry);
|
||||
|
||||
return make_pkt(ctx, PKT__PKT_UPDATE_ADD_HTLC, u);
|
||||
}
|
||||
@ -155,9 +156,10 @@ Pkt *pkt_htlc_fulfill(const tal_t *ctx, const struct peer *peer,
|
||||
UpdateFulfillHtlc *f = tal(ctx, UpdateFulfillHtlc);
|
||||
|
||||
update_fulfill_htlc__init(f);
|
||||
assert(htlc_prog->stage.type == HTLC_FULFILL);
|
||||
|
||||
f->revocation_hash = sha256_to_proto(f, &htlc_prog->our_revocation_hash);
|
||||
f->r = sha256_to_proto(f, &htlc_prog->r);
|
||||
f->r = sha256_to_proto(f, &htlc_prog->stage.fulfill.r);
|
||||
|
||||
return make_pkt(ctx, PKT__PKT_UPDATE_FULFILL_HTLC, f);
|
||||
}
|
||||
@ -166,11 +168,14 @@ Pkt *pkt_htlc_fail(const tal_t *ctx, const struct peer *peer,
|
||||
const struct htlc_progress *htlc_prog)
|
||||
{
|
||||
UpdateFailHtlc *f = tal(ctx, UpdateFailHtlc);
|
||||
const struct channel_htlc *htlc;
|
||||
|
||||
update_fail_htlc__init(f);
|
||||
assert(htlc_prog->stage.type == HTLC_FAIL);
|
||||
|
||||
htlc = &peer->cstate->b.htlcs[htlc_prog->stage.fail.index];
|
||||
f->revocation_hash = sha256_to_proto(f, &htlc_prog->our_revocation_hash);
|
||||
f->r_hash = sha256_to_proto(f, &htlc_prog->htlc->rhash);
|
||||
f->r_hash = sha256_to_proto(f, &htlc->rhash);
|
||||
|
||||
return make_pkt(ctx, PKT__PKT_UPDATE_FAIL_HTLC, f);
|
||||
}
|
||||
@ -419,29 +424,29 @@ Pkt *accept_pkt_htlc_add(const tal_t *ctx,
|
||||
struct htlc_progress *cur = tal(peer, struct htlc_progress);
|
||||
Pkt *err;
|
||||
|
||||
cur->htlc = tal(cur, struct channel_htlc);
|
||||
cur->htlc->msatoshis = u->amount_msat;
|
||||
proto_to_sha256(u->r_hash, &cur->htlc->rhash);
|
||||
cur->stage.add.add = HTLC_ADD;
|
||||
cur->stage.add.htlc.msatoshis = u->amount_msat;
|
||||
proto_to_sha256(u->r_hash, &cur->stage.add.htlc.rhash);
|
||||
proto_to_sha256(u->revocation_hash, &cur->their_revocation_hash);
|
||||
if (!proto_to_abs_locktime(u->expiry, &cur->htlc->expiry)) {
|
||||
if (!proto_to_abs_locktime(u->expiry, &cur->stage.add.htlc.expiry)) {
|
||||
err = pkt_err(ctx, "Invalid HTLC expiry");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* FIXME: Handle block-based expiry! */
|
||||
if (!abs_locktime_is_seconds(&cur->htlc->expiry)) {
|
||||
if (!abs_locktime_is_seconds(&cur->stage.add.htlc.expiry)) {
|
||||
*decline = decline_htlc(ctx,
|
||||
"HTLC expiry in blocks not supported!");
|
||||
goto decline;
|
||||
}
|
||||
|
||||
if (abs_locktime_to_seconds(&cur->htlc->expiry) <
|
||||
if (abs_locktime_to_seconds(&cur->stage.add.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) >
|
||||
if (abs_locktime_to_seconds(&cur->stage.add.htlc.expiry) >
|
||||
controlled_time().ts.tv_sec + peer->dstate->config.max_expiry) {
|
||||
*decline = decline_htlc(ctx, "HTLC expiry too far!");
|
||||
goto decline;
|
||||
@ -449,16 +454,18 @@ Pkt *accept_pkt_htlc_add(const tal_t *ctx,
|
||||
|
||||
cur->cstate = copy_funding(cur, peer->cstate);
|
||||
if (!funding_delta(peer->anchor.satoshis,
|
||||
0, cur->htlc->msatoshis,
|
||||
0, cur->stage.add.htlc.msatoshis,
|
||||
&cur->cstate->b, &cur->cstate->a)) {
|
||||
err = pkt_err(ctx, "Cannot afford %"PRIu64" milli-satoshis",
|
||||
cur->htlc->msatoshis);
|
||||
cur->stage.add.htlc.msatoshis);
|
||||
goto fail;
|
||||
}
|
||||
/* Add the htlc to their side of channel. */
|
||||
funding_add_htlc(&cur->cstate->b, cur->htlc->msatoshis,
|
||||
&cur->htlc->expiry, &cur->htlc->rhash);
|
||||
peer_add_htlc_expiry(peer, &cur->htlc->expiry);
|
||||
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,
|
||||
&cur->our_revocation_hash);
|
||||
@ -495,6 +502,7 @@ 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);
|
||||
@ -505,15 +513,17 @@ Pkt *accept_pkt_htlc_fail(const tal_t *ctx, struct peer *peer, const Pkt *pkt)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
cur->htlc = tal_dup(cur, struct channel_htlc, &peer->cstate->a.htlcs[i]);
|
||||
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 */
|
||||
cur->cstate = copy_funding(cur, peer->cstate);
|
||||
if (!funding_delta(peer->anchor.satoshis,
|
||||
0, -cur->htlc->msatoshis,
|
||||
0, -htlc->msatoshis,
|
||||
&cur->cstate->a, &cur->cstate->b)) {
|
||||
fatal("Unexpected failure fulfilling HTLC of %"PRIu64
|
||||
" milli-satoshis", cur->htlc->msatoshis);
|
||||
" milli-satoshis", htlc->msatoshis);
|
||||
}
|
||||
funding_remove_htlc(&cur->cstate->a, i);
|
||||
/* FIXME: Remove timer. */
|
||||
@ -543,27 +553,31 @@ Pkt *accept_pkt_htlc_fulfill(const tal_t *ctx,
|
||||
struct htlc_progress *cur = tal(peer, struct htlc_progress);
|
||||
Pkt *err;
|
||||
size_t i;
|
||||
struct sha256 rhash, r;
|
||||
struct sha256 rhash;
|
||||
struct channel_htlc *htlc;
|
||||
|
||||
cur->stage.fulfill.fulfill = HTLC_FULFILL;
|
||||
proto_to_sha256(f->r, &cur->stage.fulfill.r);
|
||||
|
||||
proto_to_sha256(f->r, &r);
|
||||
proto_to_sha256(f->revocation_hash, &cur->their_revocation_hash);
|
||||
sha256(&rhash, &r, sizeof(r));
|
||||
sha256(&rhash, &cur->stage.fulfill.r, sizeof(cur->stage.fulfill.r));
|
||||
i = funding_find_htlc(&peer->cstate->a, &rhash);
|
||||
if (i == tal_count(peer->cstate->a.htlcs)) {
|
||||
err = pkt_err(ctx, "Unknown HTLC");
|
||||
goto fail;
|
||||
}
|
||||
cur->stage.fulfill.index = i;
|
||||
|
||||
cur->htlc = tal_dup(cur, struct channel_htlc, &peer->cstate->a.htlcs[i]);
|
||||
htlc = &peer->cstate->a.htlcs[i];
|
||||
|
||||
/* Removing it should not fail: they gain HTLC amount */
|
||||
cur->cstate = copy_funding(cur, peer->cstate);
|
||||
if (!funding_delta(peer->anchor.satoshis,
|
||||
-cur->htlc->msatoshis,
|
||||
-cur->htlc->msatoshis,
|
||||
-htlc->msatoshis,
|
||||
-htlc->msatoshis,
|
||||
&cur->cstate->a, &cur->cstate->b)) {
|
||||
fatal("Unexpected failure fulfilling HTLC of %"PRIu64
|
||||
" milli-satoshis", cur->htlc->msatoshis);
|
||||
" milli-satoshis", htlc->msatoshis);
|
||||
}
|
||||
funding_remove_htlc(&cur->cstate->a, i);
|
||||
|
||||
|
@ -1283,18 +1283,14 @@ const struct json_command getpeers_command = {
|
||||
static void set_htlc_command(struct peer *peer,
|
||||
struct channel_state *cstate,
|
||||
struct command *jsoncmd,
|
||||
struct channel_htlc *htlc,
|
||||
enum state_input cmd,
|
||||
const struct sha256 *r_fulfill)
|
||||
const union htlc_staging *stage)
|
||||
{
|
||||
assert(!peer->current_htlc);
|
||||
|
||||
peer->current_htlc = tal(peer, struct htlc_progress);
|
||||
peer->current_htlc->cstate = tal_steal(peer->current_htlc, cstate);
|
||||
peer->current_htlc->htlc = tal_dup(peer->current_htlc,
|
||||
struct channel_htlc, htlc);
|
||||
if (r_fulfill)
|
||||
peer->current_htlc->r = *r_fulfill;
|
||||
peer->current_htlc->stage = *stage;
|
||||
|
||||
peer_get_revocation_hash(peer, peer->commit_tx_counter+1,
|
||||
&peer->current_htlc->our_revocation_hash);
|
||||
@ -1308,6 +1304,9 @@ static void set_htlc_command(struct peer *peer,
|
||||
static void check_htlc_expiry(struct peer *peer, void *unused)
|
||||
{
|
||||
size_t i;
|
||||
union htlc_staging stage;
|
||||
|
||||
stage.fail.fail = HTLC_FAIL;
|
||||
|
||||
/* Check their htlcs for expiry. */
|
||||
for (i = 0; i < tal_count(peer->cstate->b.htlcs); i++) {
|
||||
@ -1334,9 +1333,9 @@ static void check_htlc_expiry(struct peer *peer, void *unused)
|
||||
" milli-satoshis", htlc->msatoshis);
|
||||
}
|
||||
funding_remove_htlc(&cstate->b, i);
|
||||
|
||||
set_htlc_command(peer, cstate, NULL, htlc,
|
||||
CMD_SEND_HTLC_FAIL, NULL);
|
||||
stage.fail.index = i;
|
||||
set_htlc_command(peer, cstate, NULL, CMD_SEND_HTLC_FAIL,
|
||||
&stage);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1369,6 +1368,10 @@ struct newhtlc {
|
||||
static void do_newhtlc(struct peer *peer, struct newhtlc *newhtlc)
|
||||
{
|
||||
struct channel_state *cstate;
|
||||
union htlc_staging stage;
|
||||
|
||||
stage.add.add = HTLC_ADD;
|
||||
stage.add.htlc = newhtlc->htlc;
|
||||
|
||||
/* Can we even offer this much? We check now, just before we
|
||||
* execute. */
|
||||
@ -1390,8 +1393,7 @@ static void do_newhtlc(struct peer *peer, struct newhtlc *newhtlc)
|
||||
peer_add_htlc_expiry(peer, &newhtlc->htlc.expiry);
|
||||
|
||||
set_htlc_command(peer, cstate, newhtlc->jsoncmd,
|
||||
&cstate->a.htlcs[tal_count(cstate->a.htlcs)-1],
|
||||
CMD_SEND_HTLC_ADD, NULL);
|
||||
CMD_SEND_HTLC_ADD, &stage);
|
||||
}
|
||||
|
||||
static void json_newhtlc(struct command *cmd,
|
||||
@ -1487,6 +1489,10 @@ static void do_fullfill(struct peer *peer,
|
||||
struct sha256 rhash;
|
||||
size_t i;
|
||||
struct channel_htlc *htlc;
|
||||
union htlc_staging stage;
|
||||
|
||||
stage.fulfill.fulfill = HTLC_FULFILL;
|
||||
stage.fulfill.r = fulfillhtlc->r;
|
||||
|
||||
sha256(&rhash, &fulfillhtlc->r, sizeof(fulfillhtlc->r));
|
||||
|
||||
@ -1496,6 +1502,7 @@ static void do_fullfill(struct peer *peer,
|
||||
"preimage htlc not found");
|
||||
return;
|
||||
}
|
||||
stage.fulfill.index = i;
|
||||
/* Point at current one, since we remove from new cstate. */
|
||||
htlc = &peer->cstate->b.htlcs[i];
|
||||
|
||||
@ -1511,8 +1518,8 @@ static void do_fullfill(struct peer *peer,
|
||||
}
|
||||
funding_remove_htlc(&cstate->b, i);
|
||||
|
||||
set_htlc_command(peer, cstate, fulfillhtlc->jsoncmd, htlc,
|
||||
CMD_SEND_HTLC_FULFILL, &fulfillhtlc->r);
|
||||
set_htlc_command(peer, cstate, fulfillhtlc->jsoncmd,
|
||||
CMD_SEND_HTLC_FULFILL, &stage);
|
||||
}
|
||||
|
||||
static void json_fulfillhtlc(struct command *cmd,
|
||||
@ -1570,12 +1577,16 @@ 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;
|
||||
|
||||
i = funding_find_htlc(&peer->cstate->b, &failhtlc->rhash);
|
||||
if (i == tal_count(peer->cstate->b.htlcs)) {
|
||||
command_fail(failhtlc->jsoncmd, "htlc not found");
|
||||
return;
|
||||
}
|
||||
stage.fail.index = i;
|
||||
/* Point to current one, since we remove from new cstate. */
|
||||
htlc = &peer->cstate->b.htlcs[i];
|
||||
|
||||
@ -1592,8 +1603,8 @@ static void do_failhtlc(struct peer *peer,
|
||||
}
|
||||
funding_remove_htlc(&cstate->b, i);
|
||||
|
||||
set_htlc_command(peer, cstate, failhtlc->jsoncmd, htlc,
|
||||
CMD_SEND_HTLC_FAIL, NULL);
|
||||
set_htlc_command(peer, cstate, failhtlc->jsoncmd,
|
||||
CMD_SEND_HTLC_FAIL, &stage);
|
||||
}
|
||||
|
||||
static void json_failhtlc(struct command *cmd,
|
||||
|
@ -13,6 +13,35 @@
|
||||
#include <ccan/list/list.h>
|
||||
#include <ccan/time/time.h>
|
||||
|
||||
enum htlc_stage_type {
|
||||
HTLC_ADD,
|
||||
HTLC_FULFILL,
|
||||
HTLC_FAIL
|
||||
};
|
||||
|
||||
struct htlc_add {
|
||||
enum htlc_stage_type add;
|
||||
struct channel_htlc htlc;
|
||||
};
|
||||
|
||||
struct htlc_fulfill {
|
||||
enum htlc_stage_type fulfill;
|
||||
size_t index;
|
||||
struct sha256 r;
|
||||
};
|
||||
|
||||
struct htlc_fail {
|
||||
enum htlc_stage_type fail;
|
||||
size_t index;
|
||||
};
|
||||
|
||||
union htlc_staging {
|
||||
enum htlc_stage_type type;
|
||||
struct htlc_add add;
|
||||
struct htlc_fulfill fulfill;
|
||||
struct htlc_fail fail;
|
||||
};
|
||||
|
||||
struct peer_visible_state {
|
||||
/* CMD_OPEN_WITH_ANCHOR or CMD_OPEN_WITHOUT_ANCHOR */
|
||||
enum state_input offer_anchor;
|
||||
@ -32,11 +61,8 @@ struct peer_visible_state {
|
||||
|
||||
struct htlc_progress {
|
||||
/* The HTLC we're working on. */
|
||||
struct channel_htlc *htlc;
|
||||
union htlc_staging stage;
|
||||
|
||||
/* Set if we're fulfilling. */
|
||||
struct sha256 r;
|
||||
|
||||
/* Our next state. */
|
||||
/* Channel funding state, after we've completed htlc. */
|
||||
struct channel_state *cstate;
|
||||
|
Loading…
Reference in New Issue
Block a user