mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-22 14:42:40 +01:00
funding: make funding_htlc_by_id() return pointer, not offset.
While the pointer is only valid until the funding changes, that's also true of the offset; and a pointer has a convenient "not found" sentinal value. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
156d1be9ed
commit
eeb9b9de84
3 changed files with 67 additions and 61 deletions
|
@ -208,7 +208,7 @@ void queue_pkt_htlc_add(struct peer *peer, const struct channel_htlc *htlc)
|
||||||
void queue_pkt_htlc_fulfill(struct peer *peer, u64 id, const struct rval *r)
|
void queue_pkt_htlc_fulfill(struct peer *peer, u64 id, const struct rval *r)
|
||||||
{
|
{
|
||||||
UpdateFulfillHtlc *f = tal(peer, UpdateFulfillHtlc);
|
UpdateFulfillHtlc *f = tal(peer, UpdateFulfillHtlc);
|
||||||
size_t n;
|
struct channel_htlc *htlc;
|
||||||
union htlc_staging stage;
|
union htlc_staging stage;
|
||||||
|
|
||||||
update_fulfill_htlc__init(f);
|
update_fulfill_htlc__init(f);
|
||||||
|
@ -220,9 +220,9 @@ void queue_pkt_htlc_fulfill(struct peer *peer, u64 id, const struct rval *r)
|
||||||
* The sending node MUST add the HTLC fulfill/fail to the
|
* The sending node MUST add the HTLC fulfill/fail to the
|
||||||
* unacked changeset for its remote commitment
|
* unacked changeset for its remote commitment
|
||||||
*/
|
*/
|
||||||
n = funding_htlc_by_id(peer->remote.staging_cstate, f->id, THEIRS);
|
htlc = funding_htlc_by_id(peer->remote.staging_cstate, f->id, THEIRS);
|
||||||
assert(n != -1);
|
assert(htlc);
|
||||||
funding_fulfill_htlc(peer->remote.staging_cstate, n, THEIRS);
|
funding_fulfill_htlc(peer->remote.staging_cstate, htlc, THEIRS);
|
||||||
|
|
||||||
stage.fulfill.fulfill = HTLC_FULFILL;
|
stage.fulfill.fulfill = HTLC_FULFILL;
|
||||||
stage.fulfill.id = f->id;
|
stage.fulfill.id = f->id;
|
||||||
|
@ -237,7 +237,7 @@ void queue_pkt_htlc_fulfill(struct peer *peer, u64 id, const struct rval *r)
|
||||||
void queue_pkt_htlc_fail(struct peer *peer, u64 id)
|
void queue_pkt_htlc_fail(struct peer *peer, u64 id)
|
||||||
{
|
{
|
||||||
UpdateFailHtlc *f = tal(peer, UpdateFailHtlc);
|
UpdateFailHtlc *f = tal(peer, UpdateFailHtlc);
|
||||||
size_t n;
|
struct channel_htlc *htlc;
|
||||||
union htlc_staging stage;
|
union htlc_staging stage;
|
||||||
|
|
||||||
update_fail_htlc__init(f);
|
update_fail_htlc__init(f);
|
||||||
|
@ -252,9 +252,9 @@ void queue_pkt_htlc_fail(struct peer *peer, u64 id)
|
||||||
* The sending node MUST add the HTLC fulfill/fail to the
|
* The sending node MUST add the HTLC fulfill/fail to the
|
||||||
* unacked changeset for its remote commitment
|
* unacked changeset for its remote commitment
|
||||||
*/
|
*/
|
||||||
n = funding_htlc_by_id(peer->remote.staging_cstate, f->id, THEIRS);
|
htlc = funding_htlc_by_id(peer->remote.staging_cstate, f->id, THEIRS);
|
||||||
assert(n != -1);
|
assert(htlc);
|
||||||
funding_fail_htlc(peer->remote.staging_cstate, n, THEIRS);
|
funding_fail_htlc(peer->remote.staging_cstate, htlc, THEIRS);
|
||||||
|
|
||||||
stage.fail.fail = HTLC_FAIL;
|
stage.fail.fail = HTLC_FAIL;
|
||||||
stage.fail.id = f->id;
|
stage.fail.id = f->id;
|
||||||
|
@ -328,14 +328,14 @@ static void apply_changeset(struct peer *peer,
|
||||||
size_t num_changes)
|
size_t num_changes)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
size_t n;
|
struct channel_htlc *htlc;
|
||||||
|
|
||||||
for (i = 0; i < num_changes; i++) {
|
for (i = 0; i < num_changes; i++) {
|
||||||
switch (changes[i].type) {
|
switch (changes[i].type) {
|
||||||
case HTLC_ADD:
|
case HTLC_ADD:
|
||||||
n = funding_htlc_by_id(which->staging_cstate,
|
htlc = funding_htlc_by_id(which->staging_cstate,
|
||||||
changes[i].add.htlc.id, side);
|
changes[i].add.htlc.id, side);
|
||||||
if (n != -1)
|
if (htlc)
|
||||||
fatal("Can't add duplicate HTLC id %"PRIu64,
|
fatal("Can't add duplicate HTLC id %"PRIu64,
|
||||||
changes[i].add.htlc.id);
|
changes[i].add.htlc.id);
|
||||||
if (!funding_add_htlc(which->staging_cstate,
|
if (!funding_add_htlc(which->staging_cstate,
|
||||||
|
@ -347,20 +347,20 @@ static void apply_changeset(struct peer *peer,
|
||||||
side == OURS ? "ours" : "theirs");
|
side == OURS ? "ours" : "theirs");
|
||||||
continue;
|
continue;
|
||||||
case HTLC_FAIL:
|
case HTLC_FAIL:
|
||||||
n = funding_htlc_by_id(which->staging_cstate,
|
htlc = funding_htlc_by_id(which->staging_cstate,
|
||||||
changes[i].fail.id, !side);
|
changes[i].fail.id, !side);
|
||||||
if (n == -1)
|
if (!htlc)
|
||||||
fatal("Can't fail non-exisent HTLC id %"PRIu64,
|
fatal("Can't fail non-exisent HTLC id %"PRIu64,
|
||||||
changes[i].fail.id);
|
changes[i].fail.id);
|
||||||
funding_fail_htlc(which->staging_cstate, n, !side);
|
funding_fail_htlc(which->staging_cstate, htlc, !side);
|
||||||
continue;
|
continue;
|
||||||
case HTLC_FULFILL:
|
case HTLC_FULFILL:
|
||||||
n = funding_htlc_by_id(which->staging_cstate,
|
htlc = funding_htlc_by_id(which->staging_cstate,
|
||||||
changes[i].fulfill.id, !side);
|
changes[i].fulfill.id, !side);
|
||||||
if (n == -1)
|
if (!htlc)
|
||||||
fatal("Can't fulfill non-exisent HTLC id %"PRIu64,
|
fatal("Can't fulfill non-exisent HTLC id %"PRIu64,
|
||||||
changes[i].fulfill.id);
|
changes[i].fulfill.id);
|
||||||
funding_fulfill_htlc(which->staging_cstate, n, !side);
|
funding_fulfill_htlc(which->staging_cstate, htlc, !side);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
abort();
|
abort();
|
||||||
|
@ -628,13 +628,13 @@ Pkt *accept_pkt_htlc_add(struct peer *peer, const Pkt *pkt)
|
||||||
/* Note that it's not *our* problem if they do this, it's
|
/* Note that it's not *our* problem if they do this, it's
|
||||||
* theirs (future confusion). Nonetheless, we detect and
|
* theirs (future confusion). Nonetheless, we detect and
|
||||||
* error for them. */
|
* error for them. */
|
||||||
if (funding_htlc_by_id(peer->remote.staging_cstate, u->id, THEIRS) != -1
|
if (funding_htlc_by_id(peer->remote.staging_cstate, u->id, THEIRS)
|
||||||
|| funding_htlc_by_id(peer->remote.commit->cstate, u->id, THEIRS) != -1) {
|
|| funding_htlc_by_id(peer->remote.commit->cstate, u->id, THEIRS)) {
|
||||||
return pkt_err(peer, "HTLC id %"PRIu64" clashes for you", u->id);
|
return pkt_err(peer, "HTLC id %"PRIu64" clashes for you", u->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (funding_htlc_by_id(peer->local.staging_cstate, u->id, THEIRS) != -1
|
if (funding_htlc_by_id(peer->local.staging_cstate, u->id, THEIRS)
|
||||||
|| funding_htlc_by_id(peer->local.commit->cstate, u->id, THEIRS) != -1) {
|
|| funding_htlc_by_id(peer->local.commit->cstate, u->id, THEIRS)) {
|
||||||
return pkt_err(peer, "HTLC id %"PRIu64" clashes for you", u->id);
|
return pkt_err(peer, "HTLC id %"PRIu64" clashes for you", u->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -672,9 +672,10 @@ Pkt *accept_pkt_htlc_add(struct peer *peer, const Pkt *pkt)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Pkt *find_commited_htlc(struct peer *peer, uint64_t id, size_t *n_local)
|
static Pkt *find_commited_htlc(struct peer *peer, uint64_t id,
|
||||||
|
struct channel_htlc **local_htlc)
|
||||||
{
|
{
|
||||||
size_t n;
|
struct channel_htlc *htlc;
|
||||||
|
|
||||||
/* BOLT #2:
|
/* BOLT #2:
|
||||||
*
|
*
|
||||||
|
@ -682,13 +683,13 @@ static Pkt *find_commited_htlc(struct peer *peer, uint64_t id, size_t *n_local)
|
||||||
* current commitment transaction, and MUST fail the
|
* current commitment transaction, and MUST fail the
|
||||||
* connection if it does not.
|
* connection if it does not.
|
||||||
*/
|
*/
|
||||||
n = funding_htlc_by_id(peer->local.commit->cstate, id, OURS);
|
htlc = funding_htlc_by_id(peer->local.commit->cstate, id, OURS);
|
||||||
if (n == -1)
|
if (!htlc)
|
||||||
return pkt_err(peer, "Did not find HTLC %"PRIu64, id);
|
return pkt_err(peer, "Did not find HTLC %"PRIu64, id);
|
||||||
|
|
||||||
/* They must not fail/fulfill twice, so it should be in staging, too. */
|
/* They must not fail/fulfill twice, so it should be in staging, too. */
|
||||||
*n_local = funding_htlc_by_id(peer->local.staging_cstate, id, OURS);
|
*local_htlc = funding_htlc_by_id(peer->local.staging_cstate, id, OURS);
|
||||||
if (*n_local == -1)
|
if (!*local_htlc)
|
||||||
return pkt_err(peer, "Already removed HTLC %"PRIu64, id);
|
return pkt_err(peer, "Already removed HTLC %"PRIu64, id);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -697,17 +698,17 @@ static Pkt *find_commited_htlc(struct peer *peer, uint64_t id, size_t *n_local)
|
||||||
Pkt *accept_pkt_htlc_fail(struct peer *peer, const Pkt *pkt)
|
Pkt *accept_pkt_htlc_fail(struct peer *peer, const Pkt *pkt)
|
||||||
{
|
{
|
||||||
const UpdateFailHtlc *f = pkt->update_fail_htlc;
|
const UpdateFailHtlc *f = pkt->update_fail_htlc;
|
||||||
size_t n_local;
|
struct channel_htlc *htlc;
|
||||||
Pkt *err;
|
Pkt *err;
|
||||||
union htlc_staging stage;
|
union htlc_staging stage;
|
||||||
|
|
||||||
err = find_commited_htlc(peer, f->id, &n_local);
|
err = find_commited_htlc(peer, f->id, &htlc);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
/* FIXME: Save reason. */
|
/* FIXME: Save reason. */
|
||||||
|
|
||||||
funding_fail_htlc(peer->local.staging_cstate, n_local, OURS);
|
funding_fail_htlc(peer->local.staging_cstate, htlc, OURS);
|
||||||
|
|
||||||
/* BOLT #2:
|
/* BOLT #2:
|
||||||
*
|
*
|
||||||
|
@ -723,13 +724,13 @@ Pkt *accept_pkt_htlc_fail(struct peer *peer, const Pkt *pkt)
|
||||||
Pkt *accept_pkt_htlc_fulfill(struct peer *peer, const Pkt *pkt)
|
Pkt *accept_pkt_htlc_fulfill(struct peer *peer, const Pkt *pkt)
|
||||||
{
|
{
|
||||||
const UpdateFulfillHtlc *f = pkt->update_fulfill_htlc;
|
const UpdateFulfillHtlc *f = pkt->update_fulfill_htlc;
|
||||||
size_t n_local;
|
struct channel_htlc *htlc;
|
||||||
struct sha256 rhash;
|
struct sha256 rhash;
|
||||||
struct rval r;
|
struct rval r;
|
||||||
Pkt *err;
|
Pkt *err;
|
||||||
union htlc_staging stage;
|
union htlc_staging stage;
|
||||||
|
|
||||||
err = find_commited_htlc(peer, f->id, &n_local);
|
err = find_commited_htlc(peer, f->id, &htlc);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -737,7 +738,7 @@ Pkt *accept_pkt_htlc_fulfill(struct peer *peer, const Pkt *pkt)
|
||||||
proto_to_rval(f->r, &r);
|
proto_to_rval(f->r, &r);
|
||||||
sha256(&rhash, &r, sizeof(r));
|
sha256(&rhash, &r, sizeof(r));
|
||||||
|
|
||||||
if (!structeq(&rhash, &peer->local.staging_cstate->side[OURS].htlcs[n_local].rhash))
|
if (!structeq(&rhash, &htlc->rhash))
|
||||||
return pkt_err(peer, "Invalid r for %"PRIu64, f->id);
|
return pkt_err(peer, "Invalid r for %"PRIu64, f->id);
|
||||||
|
|
||||||
/* BOLT #2:
|
/* BOLT #2:
|
||||||
|
@ -745,7 +746,7 @@ Pkt *accept_pkt_htlc_fulfill(struct peer *peer, const Pkt *pkt)
|
||||||
* ... and the receiving node MUST add the HTLC fulfill/fail
|
* ... and the receiving node MUST add the HTLC fulfill/fail
|
||||||
* to the unacked changeset for its local commitment.
|
* to the unacked changeset for its local commitment.
|
||||||
*/
|
*/
|
||||||
funding_fulfill_htlc(peer->local.staging_cstate, n_local, OURS);
|
funding_fulfill_htlc(peer->local.staging_cstate, htlc, OURS);
|
||||||
|
|
||||||
stage.fulfill.fulfill = HTLC_FULFILL;
|
stage.fulfill.fulfill = HTLC_FULFILL;
|
||||||
stage.fulfill.id = f->id;
|
stage.fulfill.id = f->id;
|
||||||
|
|
33
funding.c
33
funding.c
|
@ -251,45 +251,48 @@ struct channel_htlc *funding_add_htlc(struct channel_state *cstate,
|
||||||
static void remove_htlc(struct channel_state *cstate,
|
static void remove_htlc(struct channel_state *cstate,
|
||||||
enum channel_side creator,
|
enum channel_side creator,
|
||||||
enum channel_side beneficiary,
|
enum channel_side beneficiary,
|
||||||
size_t i)
|
struct channel_htlc *htlc)
|
||||||
{
|
{
|
||||||
size_t n = tal_count(cstate->side[creator].htlcs);
|
|
||||||
size_t nondust;
|
size_t nondust;
|
||||||
|
size_t n = tal_count(cstate->side[creator].htlcs);
|
||||||
|
const struct channel_htlc *end;
|
||||||
|
|
||||||
assert(i < n);
|
end = cstate->side[creator].htlcs + n;
|
||||||
|
|
||||||
|
assert(htlc >= cstate->side[creator].htlcs && htlc < end);
|
||||||
|
|
||||||
/* Remember to remove this one in total txsize if not dust! */
|
/* Remember to remove this one in total txsize if not dust! */
|
||||||
nondust = total_nondust_htlcs(cstate);
|
nondust = total_nondust_htlcs(cstate);
|
||||||
if (!is_dust_amount(cstate->side[creator].htlcs[i].msatoshis / 1000)) {
|
if (!is_dust_amount(htlc->msatoshis / 1000)) {
|
||||||
assert(nondust > 0);
|
assert(nondust > 0);
|
||||||
nondust--;
|
nondust--;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Can't fail since msatoshis is positive. */
|
/* Can't fail since msatoshis is positive. */
|
||||||
if (!change_funding(cstate->anchor, cstate->fee_rate,
|
if (!change_funding(cstate->anchor, cstate->fee_rate,
|
||||||
-(int64_t)cstate->side[creator].htlcs[i].msatoshis,
|
-(int64_t)htlc->msatoshis,
|
||||||
&cstate->side[beneficiary],
|
&cstate->side[beneficiary],
|
||||||
&cstate->side[!beneficiary], nondust))
|
&cstate->side[!beneficiary], nondust))
|
||||||
abort();
|
abort();
|
||||||
|
|
||||||
/* Actually remove the HTLC. */
|
/* Actually remove the HTLC. */
|
||||||
memmove(cstate->side[creator].htlcs + i,
|
memmove(htlc, htlc + 1, (end - htlc - 1) * sizeof(*htlc));
|
||||||
cstate->side[creator].htlcs + i + 1,
|
|
||||||
(n - i - 1) * sizeof(*cstate->side[creator].htlcs));
|
|
||||||
tal_resize(&cstate->side[creator].htlcs, n-1);
|
tal_resize(&cstate->side[creator].htlcs, n-1);
|
||||||
cstate->changes++;
|
cstate->changes++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void funding_fail_htlc(struct channel_state *cstate, size_t index,
|
void funding_fail_htlc(struct channel_state *cstate,
|
||||||
|
struct channel_htlc *htlc,
|
||||||
enum channel_side side)
|
enum channel_side side)
|
||||||
{
|
{
|
||||||
remove_htlc(cstate, side, side, index);
|
remove_htlc(cstate, side, side, htlc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void funding_fulfill_htlc(struct channel_state *cstate, size_t index,
|
void funding_fulfill_htlc(struct channel_state *cstate,
|
||||||
|
struct channel_htlc *htlc,
|
||||||
enum channel_side side)
|
enum channel_side side)
|
||||||
{
|
{
|
||||||
remove_htlc(cstate, side, !side, index);
|
remove_htlc(cstate, side, !side, htlc);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t funding_find_htlc(const struct channel_state *cstate,
|
size_t funding_find_htlc(const struct channel_state *cstate,
|
||||||
|
@ -305,7 +308,7 @@ size_t funding_find_htlc(const struct channel_state *cstate,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t funding_htlc_by_id(const struct channel_state *cstate,
|
struct channel_htlc *funding_htlc_by_id(const struct channel_state *cstate,
|
||||||
uint64_t id,
|
uint64_t id,
|
||||||
enum channel_side side)
|
enum channel_side side)
|
||||||
{
|
{
|
||||||
|
@ -313,9 +316,9 @@ size_t funding_htlc_by_id(const struct channel_state *cstate,
|
||||||
|
|
||||||
for (i = 0; i < tal_count(cstate->side[side].htlcs); i++) {
|
for (i = 0; i < tal_count(cstate->side[side].htlcs); i++) {
|
||||||
if (cstate->side[side].htlcs[i].id == id)
|
if (cstate->side[side].htlcs[i].id == id)
|
||||||
return i;
|
return &cstate->side[side].htlcs[i];
|
||||||
}
|
}
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct channel_state *copy_funding(const tal_t *ctx,
|
struct channel_state *copy_funding(const tal_t *ctx,
|
||||||
|
|
14
funding.h
14
funding.h
|
@ -82,25 +82,27 @@ struct channel_htlc *funding_add_htlc(struct channel_state *cstate,
|
||||||
/**
|
/**
|
||||||
* funding_fail_htlc: remove an HTLC, funds to the side which offered it.
|
* funding_fail_htlc: remove an HTLC, funds to the side which offered it.
|
||||||
* @cstate: The channel state
|
* @cstate: The channel state
|
||||||
* @index: the index into cstate->side[dir].htlcs[].
|
* @htlc: the htlc in cstate->side[dir].htlcs[].
|
||||||
* @side: OURS or THEIRS
|
* @side: OURS or THEIRS
|
||||||
*
|
*
|
||||||
* This will remove the @index'th entry in cstate->side[dir].htlcs[], and credit
|
* This will remove the @index'th entry in cstate->side[dir].htlcs[], and credit
|
||||||
* the value of the HTLC (back) to cstate->side[dir].
|
* the value of the HTLC (back) to cstate->side[dir].
|
||||||
*/
|
*/
|
||||||
void funding_fail_htlc(struct channel_state *cstate, size_t index,
|
void funding_fail_htlc(struct channel_state *cstate,
|
||||||
|
struct channel_htlc *htlc,
|
||||||
enum channel_side side);
|
enum channel_side side);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* funding_fulfill_htlc: remove an HTLC, funds to side which accepted it.
|
* funding_fulfill_htlc: remove an HTLC, funds to side which accepted it.
|
||||||
* @cstate: The channel state
|
* @cstate: The channel state
|
||||||
* @index: the index into cstate->a.htlcs[].
|
* @htlc: the htlc in cstate->side[dir].htlcs[].
|
||||||
* @side: OURS or THEIRS
|
* @side: OURS or THEIRS
|
||||||
*
|
*
|
||||||
* This will remove the @index'th entry in cstate->side[dir].htlcs[], and credit
|
* This will remove the @index'th entry in cstate->side[dir].htlcs[], and credit
|
||||||
* the value of the HTLC to cstate->side[!dir].
|
* the value of the HTLC to cstate->side[!dir].
|
||||||
*/
|
*/
|
||||||
void funding_fulfill_htlc(struct channel_state *cstate, size_t index,
|
void funding_fulfill_htlc(struct channel_state *cstate,
|
||||||
|
struct channel_htlc *htlc,
|
||||||
enum channel_side side);
|
enum channel_side side);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -139,9 +141,9 @@ size_t funding_find_htlc(const struct channel_state *cstate,
|
||||||
* @id: id for HTLC.
|
* @id: id for HTLC.
|
||||||
* @side: OURS or THEIRS
|
* @side: OURS or THEIRS
|
||||||
*
|
*
|
||||||
* Returns a number < tal_count(cstate->side[dir].htlcs), or -1 on fail.
|
* Returns a pointer into cstate->side[@side].htlcs, or NULL.
|
||||||
*/
|
*/
|
||||||
size_t funding_htlc_by_id(const struct channel_state *cstate,
|
struct channel_htlc *funding_htlc_by_id(const struct channel_state *cstate,
|
||||||
uint64_t id,
|
uint64_t id,
|
||||||
enum channel_side side);
|
enum channel_side side);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue