mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-17 19:03:42 +01:00
daemon: batching of changes as per BOLT #2.
We now keep a list of commitment transaction states for "us" and "them", as well as a "struct channel_state" for staged changes. We manipulate these structures as we send out packets, receive packets, or receive acknowledgement of packets. In particular, we update the other nodes' staging_cstate as we send out our requests, and update our own staging_cstate are we receive acks. When we receive a request, we update both (as we immediately send out our ack). The RPC output is changed; rather than expose the complexity, we expose our last committed state: what would happen if we have to drop to the blockchain now. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
017d199305
commit
5e7b3d02a1
@ -252,6 +252,7 @@ static const struct json_command *cmdlist[] = {
|
||||
&newhtlc_command,
|
||||
&fulfillhtlc_command,
|
||||
&failhtlc_command,
|
||||
&commit_command,
|
||||
&close_command,
|
||||
/* Developer/debugging options. */
|
||||
&echo_command,
|
||||
|
@ -61,6 +61,7 @@ extern const struct json_command getpeers_command;
|
||||
extern const struct json_command newhtlc_command;
|
||||
extern const struct json_command fulfillhtlc_command;
|
||||
extern const struct json_command failhtlc_command;
|
||||
extern const struct json_command commit_command;
|
||||
extern const struct json_command mocktime_command;
|
||||
extern const struct json_command close_command;
|
||||
#endif /* LIGHTNING_DAEMON_JSONRPC_H */
|
||||
|
714
daemon/packets.c
714
daemon/packets.c
@ -1,6 +1,7 @@
|
||||
#include "bitcoin/script.h"
|
||||
#include "bitcoin/tx.h"
|
||||
#include "close_tx.h"
|
||||
#include "commit_tx.h"
|
||||
#include "controlled_time.h"
|
||||
#include "find_p2sh_out.h"
|
||||
#include "lightningd.h"
|
||||
@ -13,6 +14,7 @@
|
||||
#include <ccan/crypto/sha256/sha256.h>
|
||||
#include <ccan/io/io.h>
|
||||
#include <ccan/mem/mem.h>
|
||||
#include <ccan/ptrint/ptrint.h>
|
||||
#include <ccan/str/hex/hex.h>
|
||||
#include <ccan/structeq/structeq.h>
|
||||
#include <ccan/tal/str/str.h>
|
||||
@ -68,13 +70,15 @@ static Pkt *make_pkt(const tal_t *ctx, Pkt__PktCase type, const void *msg)
|
||||
return pkt;
|
||||
}
|
||||
|
||||
static void queue_raw_pkt(struct peer *peer, Pkt *pkt)
|
||||
static void queue_raw_pkt(struct peer *peer, Pkt *pkt,
|
||||
void (*ack_cb)(struct peer *peer, void *arg),
|
||||
void *ack_arg)
|
||||
{
|
||||
size_t n = tal_count(peer->outpkt);
|
||||
tal_resize(&peer->outpkt, n+1);
|
||||
peer->outpkt[n].pkt = pkt;
|
||||
peer->outpkt[n].ack_cb = NULL;
|
||||
peer->outpkt[n].ack_arg = NULL;
|
||||
peer->outpkt[n].ack_cb = ack_cb;
|
||||
peer->outpkt[n].ack_arg = ack_arg;
|
||||
|
||||
/* In case it was waiting for output. */
|
||||
io_wake(peer);
|
||||
@ -82,15 +86,29 @@ static void queue_raw_pkt(struct peer *peer, Pkt *pkt)
|
||||
|
||||
static void queue_pkt(struct peer *peer, Pkt__PktCase type, const void *msg)
|
||||
{
|
||||
queue_raw_pkt(peer, make_pkt(peer, type, msg));
|
||||
queue_raw_pkt(peer, make_pkt(peer, type, msg), NULL, NULL);
|
||||
}
|
||||
|
||||
static void queue_pkt_with_ack(struct peer *peer, Pkt__PktCase type,
|
||||
const void *msg,
|
||||
void (*ack_cb)(struct peer *peer, void *arg),
|
||||
void *ack_arg)
|
||||
{
|
||||
queue_raw_pkt(peer, make_pkt(peer, type, msg), ack_cb, ack_arg);
|
||||
}
|
||||
|
||||
void queue_pkt_open(struct peer *peer, OpenChannel__AnchorOffer anchor)
|
||||
{
|
||||
OpenChannel *o = tal(peer, OpenChannel);
|
||||
|
||||
/* Set up out commit info now: rest gets done in setup_first_commit
|
||||
* once anchor is established. */
|
||||
peer->us.commit = talz(peer, struct commit_info);
|
||||
peer->us.commit->revocation_hash = peer->us.next_revocation_hash;
|
||||
peer_get_revocation_hash(peer, 1, &peer->us.next_revocation_hash);
|
||||
|
||||
open_channel__init(o);
|
||||
o->revocation_hash = sha256_to_proto(o, &peer->us.revocation_hash);
|
||||
o->revocation_hash = sha256_to_proto(o, &peer->us.commit->revocation_hash);
|
||||
o->next_revocation_hash = sha256_to_proto(o, &peer->us.next_revocation_hash);
|
||||
o->commit_key = pubkey_to_proto(o, &peer->us.commitkey);
|
||||
o->final_key = pubkey_to_proto(o, &peer->us.finalkey);
|
||||
@ -113,7 +131,6 @@ void queue_pkt_open(struct peer *peer, OpenChannel__AnchorOffer anchor)
|
||||
|
||||
void queue_pkt_anchor(struct peer *peer)
|
||||
{
|
||||
struct signature sig;
|
||||
OpenAnchor *a = tal(peer, OpenAnchor);
|
||||
|
||||
open_anchor__init(a);
|
||||
@ -121,25 +138,40 @@ void queue_pkt_anchor(struct peer *peer)
|
||||
a->output_index = peer->anchor.index;
|
||||
a->amount = peer->anchor.satoshis;
|
||||
|
||||
/* This shouldn't happen! */
|
||||
if (!setup_first_commit(peer)) {
|
||||
queue_pkt_err(peer,
|
||||
pkt_err(peer,
|
||||
"Own anchor has insufficient funds"));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Sign their commit sig */
|
||||
peer_sign_theircommit(peer, peer->them.commit, &sig);
|
||||
a->commit_sig = signature_to_proto(a, &sig);
|
||||
peer->them.commit->sig = tal(peer->them.commit,
|
||||
struct bitcoin_signature);
|
||||
peer->them.commit->sig->stype = SIGHASH_ALL;
|
||||
peer_sign_theircommit(peer, peer->them.commit->tx,
|
||||
&peer->them.commit->sig->sig);
|
||||
a->commit_sig = signature_to_proto(a, &peer->them.commit->sig->sig);
|
||||
|
||||
queue_pkt(peer, PKT__PKT_OPEN_ANCHOR, a);
|
||||
}
|
||||
|
||||
void queue_pkt_open_commit_sig(struct peer *peer)
|
||||
{
|
||||
struct signature sig;
|
||||
OpenCommitSig *s = tal(peer, OpenCommitSig);
|
||||
|
||||
open_commit_sig__init(s);
|
||||
|
||||
dump_tx("Creating sig for:", peer->them.commit);
|
||||
dump_tx("Creating sig for:", peer->them.commit->tx);
|
||||
dump_key("Using key:", &peer->us.commitkey);
|
||||
|
||||
peer_sign_theircommit(peer, peer->them.commit, &sig);
|
||||
s->sig = signature_to_proto(s, &sig);
|
||||
peer->them.commit->sig = tal(peer->them.commit,
|
||||
struct bitcoin_signature);
|
||||
peer->them.commit->sig->stype = SIGHASH_ALL;
|
||||
peer_sign_theircommit(peer, peer->them.commit->tx,
|
||||
&peer->them.commit->sig->sig);
|
||||
s->sig = signature_to_proto(s, &peer->them.commit->sig->sig);
|
||||
|
||||
queue_pkt(peer, PKT__PKT_OPEN_COMMIT_SIG, s);
|
||||
}
|
||||
@ -152,6 +184,20 @@ void queue_pkt_open_complete(struct peer *peer)
|
||||
queue_pkt(peer, PKT__PKT_OPEN_COMPLETE, o);
|
||||
}
|
||||
|
||||
/* Once they ack, we can add it on our side. */
|
||||
static void add_our_htlc_ourside(struct peer *peer, void *arg)
|
||||
{
|
||||
struct channel_htlc *htlc = arg;
|
||||
|
||||
/* FIXME: must add even if can't pay fee any more! */
|
||||
if (!funding_a_add_htlc(peer->us.staging_cstate,
|
||||
htlc->msatoshis, &htlc->expiry,
|
||||
&htlc->rhash, htlc->id))
|
||||
fatal("FIXME: Failed to add htlc %"PRIu64" to self on ack",
|
||||
htlc->id);
|
||||
tal_free(htlc);
|
||||
}
|
||||
|
||||
void queue_pkt_htlc_add(struct peer *peer,
|
||||
const struct htlc_progress *htlc_prog)
|
||||
{
|
||||
@ -160,91 +206,164 @@ void queue_pkt_htlc_add(struct peer *peer,
|
||||
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->id = htlc_prog->stage.add.htlc.id;
|
||||
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);
|
||||
/* FIXME: routing! */
|
||||
u->route = tal(u, Routing);
|
||||
routing__init(u->route);
|
||||
|
||||
queue_pkt(peer, PKT__PKT_UPDATE_ADD_HTLC, u);
|
||||
/* We're about to send this, so their side will have it from now on. */
|
||||
if (!funding_b_add_htlc(peer->them.staging_cstate,
|
||||
htlc_prog->stage.add.htlc.msatoshis,
|
||||
&htlc_prog->stage.add.htlc.expiry,
|
||||
&htlc_prog->stage.add.htlc.rhash,
|
||||
htlc_prog->stage.add.htlc.id))
|
||||
fatal("Could not add HTLC?");
|
||||
|
||||
peer_add_htlc_expiry(peer, &htlc_prog->stage.add.htlc.expiry);
|
||||
|
||||
queue_pkt_with_ack(peer, PKT__PKT_UPDATE_ADD_HTLC, u,
|
||||
add_our_htlc_ourside,
|
||||
tal_dup(peer, struct channel_htlc,
|
||||
&htlc_prog->stage.add.htlc));
|
||||
}
|
||||
|
||||
/* Once they ack, we can fulfill it on our side. */
|
||||
static void fulfill_their_htlc_ourside(struct peer *peer, void *arg)
|
||||
{
|
||||
size_t n;
|
||||
|
||||
n = funding_htlc_by_id(&peer->us.staging_cstate->b, ptr2int(arg));
|
||||
funding_b_fulfill_htlc(peer->us.staging_cstate, n);
|
||||
}
|
||||
|
||||
void queue_pkt_htlc_fulfill(struct peer *peer,
|
||||
const struct htlc_progress *htlc_prog)
|
||||
{
|
||||
UpdateFulfillHtlc *f = tal(peer, UpdateFulfillHtlc);
|
||||
size_t n;
|
||||
|
||||
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->id = htlc_prog->stage.fulfill.id;
|
||||
f->r = sha256_to_proto(f, &htlc_prog->stage.fulfill.r);
|
||||
|
||||
queue_pkt(peer, PKT__PKT_UPDATE_FULFILL_HTLC, f);
|
||||
/* We're about to send this, so their side will have it from now on. */
|
||||
n = funding_htlc_by_id(&peer->them.staging_cstate->a, f->id);
|
||||
funding_a_fulfill_htlc(peer->them.staging_cstate, n);
|
||||
|
||||
queue_pkt_with_ack(peer, PKT__PKT_UPDATE_FULFILL_HTLC, f,
|
||||
fulfill_their_htlc_ourside, int2ptr(f->id));
|
||||
}
|
||||
|
||||
/* Once they ack, we can fail it on our side. */
|
||||
static void fail_their_htlc_ourside(struct peer *peer, void *arg)
|
||||
{
|
||||
size_t n;
|
||||
|
||||
n = funding_htlc_by_id(&peer->us.staging_cstate->b, ptr2int(arg));
|
||||
funding_b_fail_htlc(peer->us.staging_cstate, n);
|
||||
}
|
||||
|
||||
void queue_pkt_htlc_fail(struct peer *peer,
|
||||
const struct htlc_progress *htlc_prog)
|
||||
{
|
||||
UpdateFailHtlc *f = tal(peer, UpdateFailHtlc);
|
||||
const struct channel_htlc *htlc;
|
||||
size_t n;
|
||||
|
||||
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->rhash);
|
||||
f->id = htlc_prog->stage.fail.id;
|
||||
/* FIXME: reason! */
|
||||
f->reason = tal(f, FailReason);
|
||||
fail_reason__init(f->reason);
|
||||
|
||||
queue_pkt(peer, PKT__PKT_UPDATE_FAIL_HTLC, f);
|
||||
/* We're about to send this, so their side will have it from now on. */
|
||||
n = funding_htlc_by_id(&peer->them.staging_cstate->a, f->id);
|
||||
funding_a_fail_htlc(peer->them.staging_cstate, n);
|
||||
|
||||
queue_pkt_with_ack(peer, PKT__PKT_UPDATE_FAIL_HTLC, f,
|
||||
fail_their_htlc_ourside, int2ptr(f->id));
|
||||
}
|
||||
|
||||
void queue_pkt_update_accept(struct peer *peer)
|
||||
/* OK, we're sending a signature for their pending changes. */
|
||||
void queue_pkt_commit(struct peer *peer)
|
||||
{
|
||||
UpdateAccept *u = tal(peer, UpdateAccept);
|
||||
const struct htlc_progress *cur = peer->current_htlc;
|
||||
struct signature sig;
|
||||
UpdateCommit *u = tal(peer, UpdateCommit);
|
||||
struct commit_info *ci = talz(peer, struct commit_info);
|
||||
|
||||
update_accept__init(u);
|
||||
/* Create new commit info for this commit tx. */
|
||||
ci->prev = peer->them.commit;
|
||||
ci->revocation_hash = peer->them.next_revocation_hash;
|
||||
ci->cstate = copy_funding(ci, peer->them.staging_cstate);
|
||||
ci->tx = create_commit_tx(ci,
|
||||
&peer->them.finalkey,
|
||||
&peer->us.finalkey,
|
||||
&peer->us.locktime,
|
||||
&peer->anchor.txid,
|
||||
peer->anchor.index,
|
||||
peer->anchor.satoshis,
|
||||
&ci->revocation_hash,
|
||||
ci->cstate);
|
||||
|
||||
dump_tx("Signing tx", cur->their_commit);
|
||||
peer_sign_theircommit(peer, cur->their_commit, &sig);
|
||||
u->sig = signature_to_proto(u, &sig);
|
||||
u->revocation_hash
|
||||
= sha256_to_proto(u, &cur->our_revocation_hash);
|
||||
log_debug(peer->log, "Signing tx for %u/%u msatoshis, %zu/%zu htlcs",
|
||||
ci->cstate->a.pay_msat,
|
||||
ci->cstate->b.pay_msat,
|
||||
tal_count(ci->cstate->a.htlcs),
|
||||
tal_count(ci->cstate->b.htlcs));
|
||||
|
||||
queue_pkt(peer, PKT__PKT_UPDATE_ACCEPT, u);
|
||||
/* BOLT #2:
|
||||
*
|
||||
* A node MUST NOT send an `update_commit` message which does
|
||||
* not include any updates.
|
||||
*/
|
||||
assert(ci->prev->cstate->changes != ci->cstate->changes);
|
||||
|
||||
ci->sig = tal(ci, struct bitcoin_signature);
|
||||
ci->sig->stype = SIGHASH_ALL;
|
||||
peer_sign_theircommit(peer, ci->tx, &ci->sig->sig);
|
||||
|
||||
/* Switch to the new commitment. */
|
||||
peer->them.commit = ci;
|
||||
|
||||
/* Now send message */
|
||||
update_commit__init(u);
|
||||
u->sig = signature_to_proto(u, &ci->sig->sig);
|
||||
|
||||
queue_pkt(peer, PKT__PKT_UPDATE_COMMIT, u);
|
||||
}
|
||||
|
||||
void queue_pkt_update_signature(struct peer *peer)
|
||||
/* Send a preimage for the old commit tx. The one we've just committed to is
|
||||
* in peer->us.commit. */
|
||||
void queue_pkt_revocation(struct peer *peer)
|
||||
{
|
||||
UpdateSignature *u = tal(peer, UpdateSignature);
|
||||
const struct htlc_progress *cur = peer->current_htlc;
|
||||
struct signature sig;
|
||||
struct sha256 preimage;
|
||||
UpdateRevocation *u = tal(peer, UpdateRevocation);
|
||||
|
||||
update_signature__init(u);
|
||||
|
||||
peer_sign_theircommit(peer, cur->their_commit, &sig);
|
||||
u->sig = signature_to_proto(u, &sig);
|
||||
assert(peer->commit_tx_counter > 0);
|
||||
peer_get_revocation_preimage(peer, peer->commit_tx_counter-1, &preimage);
|
||||
u->revocation_preimage = sha256_to_proto(u, &preimage);
|
||||
|
||||
queue_pkt(peer, PKT__PKT_UPDATE_SIGNATURE, u);
|
||||
}
|
||||
|
||||
void queue_pkt_update_complete(struct peer *peer)
|
||||
{
|
||||
UpdateComplete *u = tal(peer, UpdateComplete);
|
||||
struct sha256 preimage;
|
||||
|
||||
update_complete__init(u);
|
||||
update_revocation__init(u);
|
||||
|
||||
assert(peer->commit_tx_counter > 0);
|
||||
peer_get_revocation_preimage(peer, peer->commit_tx_counter-1, &preimage);
|
||||
u->revocation_preimage = sha256_to_proto(u, &preimage);
|
||||
assert(peer->us.commit);
|
||||
assert(peer->us.commit->prev);
|
||||
assert(!peer->us.commit->prev->revocation_preimage);
|
||||
|
||||
queue_pkt(peer, PKT__PKT_UPDATE_COMPLETE, u);
|
||||
/* We have their signature on the current one, right? */
|
||||
assert(peer->us.commit->sig);
|
||||
|
||||
peer->us.commit->prev->revocation_preimage
|
||||
= tal(peer->us.commit->prev, struct sha256);
|
||||
peer_get_revocation_preimage(peer, peer->commit_tx_counter-1,
|
||||
peer->us.commit->prev->revocation_preimage);
|
||||
u->revocation_preimage
|
||||
= sha256_to_proto(u, peer->us.commit->prev->revocation_preimage);
|
||||
|
||||
u->next_revocation_hash = sha256_to_proto(u,
|
||||
&peer->us.next_revocation_hash);
|
||||
|
||||
queue_pkt(peer, PKT__PKT_UPDATE_REVOCATION, u);
|
||||
}
|
||||
|
||||
Pkt *pkt_err(struct peer *peer, const char *msg, ...)
|
||||
@ -262,7 +381,7 @@ Pkt *pkt_err(struct peer *peer, const char *msg, ...)
|
||||
|
||||
void queue_pkt_err(struct peer *peer, Pkt *err)
|
||||
{
|
||||
queue_raw_pkt(peer, err);
|
||||
queue_raw_pkt(peer, err, NULL, NULL);
|
||||
}
|
||||
|
||||
void queue_pkt_close_clearing(struct peer *peer)
|
||||
@ -332,8 +451,13 @@ Pkt *accept_pkt_open(struct peer *peer, const Pkt *pkt)
|
||||
if (!proto_to_pubkey(peer->dstate->secpctx,
|
||||
o->final_key, &peer->them.finalkey))
|
||||
return pkt_err(peer, "Bad finalkey");
|
||||
proto_to_sha256(o->revocation_hash, &peer->them.revocation_hash);
|
||||
proto_to_sha256(o->next_revocation_hash, &peer->them.next_revocation_hash);
|
||||
|
||||
/* Set up their commit info now: rest gets done in setup_first_commit
|
||||
* once anchor is established. */
|
||||
peer->them.commit = talz(peer, struct commit_info);
|
||||
proto_to_sha256(o->revocation_hash, &peer->them.commit->revocation_hash);
|
||||
proto_to_sha256(o->next_revocation_hash,
|
||||
&peer->them.next_revocation_hash);
|
||||
|
||||
/* Redeemscript for anchor. */
|
||||
peer->anchor.redeemscript
|
||||
@ -342,6 +466,29 @@ Pkt *accept_pkt_open(struct peer *peer, const Pkt *pkt)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Save and check signature. */
|
||||
static Pkt *check_and_save_commit_sig(struct peer *peer,
|
||||
struct commit_info *ci,
|
||||
const Signature *pb)
|
||||
{
|
||||
assert(!ci->sig);
|
||||
ci->sig = tal(ci, struct bitcoin_signature);
|
||||
ci->sig->stype = SIGHASH_ALL;
|
||||
if (!proto_to_signature(pb, &ci->sig->sig))
|
||||
return pkt_err(peer, "Malformed signature");
|
||||
|
||||
/* Their sig should sign our commit tx. */
|
||||
if (!check_tx_sig(peer->dstate->secpctx,
|
||||
ci->tx, 0,
|
||||
peer->anchor.redeemscript,
|
||||
tal_count(peer->anchor.redeemscript),
|
||||
&peer->them.commitkey,
|
||||
ci->sig))
|
||||
return pkt_err(peer, "Bad signature");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Pkt *accept_pkt_anchor(struct peer *peer, const Pkt *pkt)
|
||||
{
|
||||
const OpenAnchor *a = pkt->open_anchor;
|
||||
@ -354,59 +501,17 @@ Pkt *accept_pkt_anchor(struct peer *peer, const Pkt *pkt)
|
||||
peer->anchor.index = a->output_index;
|
||||
peer->anchor.satoshis = a->amount;
|
||||
|
||||
/* Create our cstate. */
|
||||
peer->cstate = initial_funding(peer,
|
||||
peer->us.offer_anchor == CMD_OPEN_WITH_ANCHOR,
|
||||
peer->anchor.satoshis,
|
||||
peer->us.commit_fee_rate);
|
||||
if (!peer->cstate)
|
||||
if (!setup_first_commit(peer))
|
||||
return pkt_err(peer, "Insufficient funds for fee");
|
||||
|
||||
/* Now we can make initial (unsigned!) commit txs. */
|
||||
make_commit_txs(peer, peer,
|
||||
&peer->us.revocation_hash,
|
||||
&peer->them.revocation_hash,
|
||||
peer->cstate,
|
||||
&peer->us.commit,
|
||||
&peer->them.commit);
|
||||
|
||||
peer->cur_commit.theirsig.stype = SIGHASH_ALL;
|
||||
if (!proto_to_signature(a->commit_sig, &peer->cur_commit.theirsig.sig))
|
||||
return pkt_err(peer, "Malformed signature");
|
||||
|
||||
/* Their sig should sign our commit tx. */
|
||||
if (!check_tx_sig(peer->dstate->secpctx,
|
||||
peer->us.commit, 0,
|
||||
peer->anchor.redeemscript,
|
||||
tal_count(peer->anchor.redeemscript),
|
||||
&peer->them.commitkey,
|
||||
&peer->cur_commit.theirsig))
|
||||
return pkt_err(peer, "Bad signature");
|
||||
|
||||
return NULL;
|
||||
return check_and_save_commit_sig(peer, peer->us.commit, a->commit_sig);
|
||||
}
|
||||
|
||||
Pkt *accept_pkt_open_commit_sig(struct peer *peer, const Pkt *pkt)
|
||||
{
|
||||
const OpenCommitSig *s = pkt->open_commit_sig;
|
||||
|
||||
peer->cur_commit.theirsig.stype = SIGHASH_ALL;
|
||||
if (!proto_to_signature(s->sig, &peer->cur_commit.theirsig.sig))
|
||||
return pkt_err(peer, "Malformed signature");
|
||||
|
||||
dump_tx("Checking sig for:", peer->us.commit);
|
||||
dump_key("Using key:", &peer->them.commitkey);
|
||||
|
||||
/* Their sig should sign our commit tx. */
|
||||
if (!check_tx_sig(peer->dstate->secpctx,
|
||||
peer->us.commit, 0,
|
||||
peer->anchor.redeemscript,
|
||||
tal_count(peer->anchor.redeemscript),
|
||||
&peer->them.commitkey,
|
||||
&peer->cur_commit.theirsig))
|
||||
return pkt_err(peer, "Bad signature");
|
||||
|
||||
return NULL;
|
||||
return check_and_save_commit_sig(peer, peer->us.commit, s->sig);
|
||||
}
|
||||
|
||||
Pkt *accept_pkt_open_complete(struct peer *peer, const Pkt *pkt)
|
||||
@ -414,249 +519,195 @@ Pkt *accept_pkt_open_complete(struct peer *peer, const Pkt *pkt)
|
||||
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_add(struct peer *peer, const Pkt *pkt,
|
||||
Pkt **decline)
|
||||
/*
|
||||
* We add changes to both our staging cstate (as they did when they sent
|
||||
* it) and theirs (as they will when we ack it).
|
||||
*/
|
||||
Pkt *accept_pkt_htlc_add(struct peer *peer, const Pkt *pkt)
|
||||
{
|
||||
const UpdateAddHtlc *u = pkt->update_add_htlc;
|
||||
struct htlc_progress *cur = tal(peer, struct htlc_progress);
|
||||
Pkt *err;
|
||||
struct sha256 rhash;
|
||||
struct abs_locktime expiry;
|
||||
|
||||
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->stage.add.htlc.expiry)) {
|
||||
err = pkt_err(peer, "Invalid HTLC expiry");
|
||||
goto fail;
|
||||
}
|
||||
/* BOLT #2:
|
||||
*
|
||||
* `amount_msat` MUST BE greater than 0.
|
||||
*/
|
||||
if (u->amount_msat == 0)
|
||||
return pkt_err(peer, "Invalid amount_msat");
|
||||
|
||||
proto_to_sha256(u->r_hash, &rhash);
|
||||
if (!proto_to_abs_locktime(u->expiry, &expiry))
|
||||
return pkt_err(peer, "Invalid HTLC expiry");
|
||||
|
||||
/* FIXME: Handle block-based expiry! */
|
||||
if (!abs_locktime_is_seconds(&cur->stage.add.htlc.expiry)) {
|
||||
*decline = decline_htlc(peer,
|
||||
"HTLC expiry in blocks not supported!");
|
||||
goto decline;
|
||||
}
|
||||
if (!abs_locktime_is_seconds(&expiry))
|
||||
return pkt_err(peer, "HTLC expiry in blocks not supported!");
|
||||
|
||||
if (abs_locktime_to_seconds(&cur->stage.add.htlc.expiry) <
|
||||
controlled_time().ts.tv_sec + peer->dstate->config.min_expiry) {
|
||||
*decline = decline_htlc(peer, "HTLC expiry too soon!");
|
||||
goto decline;
|
||||
}
|
||||
/* BOLT #2:
|
||||
*
|
||||
* A node MUST NOT add a HTLC if it would result in it
|
||||
* offering more than 1500 HTLCs in either commitment transaction.
|
||||
*/
|
||||
if (tal_count(peer->them.staging_cstate->a.htlcs) == 1500
|
||||
|| tal_count(peer->us.staging_cstate->b.htlcs) == 1500)
|
||||
return pkt_err(peer, "Too many HTLCs");
|
||||
|
||||
if (abs_locktime_to_seconds(&cur->stage.add.htlc.expiry) >
|
||||
controlled_time().ts.tv_sec + peer->dstate->config.max_expiry) {
|
||||
*decline = decline_htlc(peer, "HTLC expiry too far!");
|
||||
goto decline;
|
||||
}
|
||||
/* BOLT #2:
|
||||
*
|
||||
* A node MUST NOT set `id` equal to another HTLC which is in
|
||||
* the current staged commitment transaction.
|
||||
*/
|
||||
if (funding_htlc_by_id(&peer->them.staging_cstate->a, u->id)
|
||||
< tal_count(peer->them.staging_cstate->a.htlcs))
|
||||
return pkt_err(peer, "HTLC id %"PRIu64" clashes for you", u->id);
|
||||
|
||||
cur->cstate = copy_funding(cur, peer->cstate);
|
||||
if (!funding_b_add_htlc(cur->cstate,
|
||||
cur->stage.add.htlc.msatoshis,
|
||||
&cur->stage.add.htlc.expiry,
|
||||
&cur->stage.add.htlc.rhash, 0)) {
|
||||
err = pkt_err(peer, "Cannot afford %"PRIu64" milli-satoshis",
|
||||
cur->stage.add.htlc.msatoshis);
|
||||
goto fail;
|
||||
}
|
||||
peer_add_htlc_expiry(peer, &cur->stage.add.htlc.expiry);
|
||||
|
||||
peer_get_revocation_hash(peer, peer->commit_tx_counter+1,
|
||||
&cur->our_revocation_hash);
|
||||
memcheck(&cur->their_revocation_hash, sizeof(cur->their_revocation_hash));
|
||||
/* FIXME: Assert this... */
|
||||
/* Note: these should be in sync, so this should be redundant! */
|
||||
if (funding_htlc_by_id(&peer->us.staging_cstate->b, u->id)
|
||||
< tal_count(peer->us.staging_cstate->b.htlcs))
|
||||
return pkt_err(peer, "HTLC id %"PRIu64" clashes for us", u->id);
|
||||
|
||||
/* Now we create the commit tx pair. */
|
||||
make_commit_txs(cur, peer,
|
||||
memcheck(&cur->our_revocation_hash,
|
||||
sizeof(cur->our_revocation_hash)),
|
||||
&cur->their_revocation_hash,
|
||||
cur->cstate,
|
||||
&cur->our_commit, &cur->their_commit);
|
||||
/* BOLT #2:
|
||||
*
|
||||
* A node MUST NOT offer `amount_msat` it cannot pay for in
|
||||
* both commitment transactions at the current `fee_rate` (see
|
||||
* "Fee Calculation" ). A node SHOULD fail the connection if
|
||||
* this occurs.
|
||||
*/
|
||||
|
||||
/* FIXME: This is wrong! We may have already added more txs to
|
||||
* them.staging_cstate, driving that fee up.
|
||||
* We should check against the last version they acknowledged. */
|
||||
if (!funding_a_add_htlc(peer->them.staging_cstate,
|
||||
u->amount_msat, &expiry, &rhash, u->id))
|
||||
return pkt_err(peer, "Cannot afford %"PRIu64" milli-satoshis"
|
||||
" in your commitment tx",
|
||||
u->amount_msat);
|
||||
|
||||
/* If we fail here, we've already changed them.staging_cstate, so
|
||||
* MUST terminate. */
|
||||
if (!funding_b_add_htlc(peer->us.staging_cstate,
|
||||
u->amount_msat, &expiry, &rhash, u->id))
|
||||
return pkt_err(peer, "Cannot afford %"PRIu64" milli-satoshis"
|
||||
" in our commitment tx",
|
||||
u->amount_msat);
|
||||
|
||||
peer_add_htlc_expiry(peer, &expiry);
|
||||
|
||||
/* FIXME: Fees must be sufficient. */
|
||||
*decline = NULL;
|
||||
assert(!peer->current_htlc);
|
||||
peer->current_htlc = cur;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fail:
|
||||
tal_free(cur);
|
||||
return err;
|
||||
static Pkt *find_commited_htlc(struct peer *peer, uint64_t id,
|
||||
size_t *n_us, size_t *n_them)
|
||||
{
|
||||
/* BOLT #2:
|
||||
*
|
||||
* A node MUST check that `id` corresponds to an HTLC in its
|
||||
* current commitment transaction, and MUST fail the
|
||||
* connection if it does not.
|
||||
*/
|
||||
*n_us = funding_htlc_by_id(&peer->us.commit->cstate->a, id);
|
||||
if (*n_us == tal_count(peer->us.commit->cstate->a.htlcs))
|
||||
return pkt_err(peer, "Did not find HTLC %"PRIu64, id);
|
||||
|
||||
/* They must not fail/fulfill twice, so it should be in staging, too. */
|
||||
*n_us = funding_htlc_by_id(&peer->us.staging_cstate->a, id);
|
||||
if (*n_us == tal_count(peer->us.staging_cstate->a.htlcs))
|
||||
return pkt_err(peer, "Already removed HTLC %"PRIu64, id);
|
||||
|
||||
/* FIXME: Assert this... */
|
||||
/* Note: these should match. */
|
||||
*n_them = funding_htlc_by_id(&peer->them.staging_cstate->b, id);
|
||||
if (*n_them == tal_count(peer->them.staging_cstate->b.htlcs))
|
||||
return pkt_err(peer, "Did not find your HTLC %"PRIu64, id);
|
||||
|
||||
decline:
|
||||
assert(*decline);
|
||||
tal_free(cur);
|
||||
return NULL;
|
||||
};
|
||||
}
|
||||
|
||||
Pkt *accept_pkt_htlc_fail(struct peer *peer, const Pkt *pkt)
|
||||
{
|
||||
const UpdateFailHtlc *f = pkt->update_fail_htlc;
|
||||
struct htlc_progress *cur = tal(peer, struct htlc_progress);
|
||||
size_t n_us, n_them;
|
||||
Pkt *err;
|
||||
size_t i;
|
||||
struct sha256 rhash;
|
||||
|
||||
proto_to_sha256(f->revocation_hash, &cur->their_revocation_hash);
|
||||
proto_to_sha256(f->r_hash, &rhash);
|
||||
err = find_commited_htlc(peer, f->id, &n_us, &n_them);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
i = funding_find_htlc(&peer->cstate->a, &rhash);
|
||||
if (i == tal_count(peer->cstate->a.htlcs)) {
|
||||
err = pkt_err(peer, "Unknown HTLC");
|
||||
goto fail;
|
||||
}
|
||||
/* FIXME: Save reason. */
|
||||
|
||||
cur->stage.fail.fail = HTLC_FAIL;
|
||||
cur->stage.fail.index = i;
|
||||
|
||||
/* We regain HTLC amount */
|
||||
cur->cstate = copy_funding(cur, peer->cstate);
|
||||
funding_a_fail_htlc(cur->cstate, i);
|
||||
/* FIXME: Remove timer. */
|
||||
|
||||
peer_get_revocation_hash(peer, peer->commit_tx_counter+1,
|
||||
&cur->our_revocation_hash);
|
||||
|
||||
/* Now we create the commit tx pair. */
|
||||
make_commit_txs(cur, peer, &cur->our_revocation_hash,
|
||||
&cur->their_revocation_hash,
|
||||
cur->cstate,
|
||||
&cur->our_commit, &cur->their_commit);
|
||||
|
||||
assert(!peer->current_htlc);
|
||||
peer->current_htlc = cur;
|
||||
funding_a_fail_htlc(peer->us.staging_cstate, n_us);
|
||||
funding_b_fail_htlc(peer->them.staging_cstate, n_them);
|
||||
return NULL;
|
||||
|
||||
fail:
|
||||
tal_free(cur);
|
||||
return err;
|
||||
}
|
||||
|
||||
Pkt *accept_pkt_htlc_fulfill(struct peer *peer, const Pkt *pkt)
|
||||
{
|
||||
const UpdateFulfillHtlc *f = pkt->update_fulfill_htlc;
|
||||
struct htlc_progress *cur = tal(peer, struct htlc_progress);
|
||||
size_t n_us, n_them;
|
||||
struct sha256 r, rhash;
|
||||
Pkt *err;
|
||||
size_t i;
|
||||
struct sha256 rhash;
|
||||
|
||||
cur->stage.fulfill.fulfill = HTLC_FULFILL;
|
||||
proto_to_sha256(f->r, &cur->stage.fulfill.r);
|
||||
err = find_commited_htlc(peer, f->id, &n_us, &n_them);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
proto_to_sha256(f->revocation_hash, &cur->their_revocation_hash);
|
||||
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(peer, "Unknown HTLC");
|
||||
goto fail;
|
||||
}
|
||||
cur->stage.fulfill.index = i;
|
||||
/* Now, it must solve the HTLC rhash puzzle. */
|
||||
proto_to_sha256(f->r, &r);
|
||||
sha256(&rhash, &r, sizeof(r));
|
||||
|
||||
/* Removing it: they gain HTLC amount */
|
||||
cur->cstate = copy_funding(cur, peer->cstate);
|
||||
funding_a_fulfill_htlc(cur->cstate, i);
|
||||
if (!structeq(&rhash, &peer->us.staging_cstate->a.htlcs[n_us].rhash))
|
||||
return pkt_err(peer, "Invalid r for %"PRIu64, f->id);
|
||||
|
||||
peer_get_revocation_hash(peer, peer->commit_tx_counter+1,
|
||||
&cur->our_revocation_hash);
|
||||
/* Same ID must have same rhash */
|
||||
assert(structeq(&rhash, &peer->them.staging_cstate->b.htlcs[n_them].rhash));
|
||||
|
||||
/* Now we create the commit tx pair. */
|
||||
make_commit_txs(cur, peer, &cur->our_revocation_hash,
|
||||
&cur->their_revocation_hash,
|
||||
cur->cstate,
|
||||
&cur->our_commit, &cur->their_commit);
|
||||
|
||||
assert(!peer->current_htlc);
|
||||
peer->current_htlc = cur;
|
||||
funding_a_fulfill_htlc(peer->us.staging_cstate, n_us);
|
||||
funding_b_fulfill_htlc(peer->them.staging_cstate, n_them);
|
||||
return NULL;
|
||||
|
||||
fail:
|
||||
tal_free(cur);
|
||||
return err;
|
||||
}
|
||||
|
||||
static u64 total_funds(const struct channel_oneside *c)
|
||||
Pkt *accept_pkt_commit(struct peer *peer, const Pkt *pkt)
|
||||
{
|
||||
u64 total = (u64)c->pay_msat + c->fee_msat;
|
||||
size_t i, n = tal_count(c->htlcs);
|
||||
const UpdateCommit *c = pkt->update_commit;
|
||||
Pkt *err;
|
||||
struct commit_info *ci = talz(peer, struct commit_info);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
total += c->htlcs[i].msatoshis;
|
||||
return total;
|
||||
}
|
||||
/* Create new commit info for this commit tx. */
|
||||
ci->prev = peer->us.commit;
|
||||
ci->revocation_hash = peer->us.next_revocation_hash;
|
||||
ci->cstate = copy_funding(ci, peer->us.staging_cstate);
|
||||
ci->tx = create_commit_tx(ci,
|
||||
&peer->us.finalkey,
|
||||
&peer->them.finalkey,
|
||||
&peer->them.locktime,
|
||||
&peer->anchor.txid,
|
||||
peer->anchor.index,
|
||||
peer->anchor.satoshis,
|
||||
&ci->revocation_hash,
|
||||
ci->cstate);
|
||||
|
||||
static void update_to_new_htlcs(struct peer *peer)
|
||||
{
|
||||
struct htlc_progress *cur = peer->current_htlc;
|
||||
|
||||
/* FIXME: Add to shachain too. */
|
||||
|
||||
/* HTLCs can't change total balance in channel! */
|
||||
if (total_funds(&peer->cstate->a) + total_funds(&peer->cstate->b)
|
||||
!= total_funds(&cur->cstate->a) + total_funds(&cur->cstate->b))
|
||||
fatal("Illegal funding transition from %u/%u (total %"PRIu64")"
|
||||
" to %u/%u (total %"PRIu64")",
|
||||
peer->cstate->a.pay_msat, peer->cstate->a.fee_msat,
|
||||
total_funds(&peer->cstate->a),
|
||||
peer->cstate->b.pay_msat, peer->cstate->b.fee_msat,
|
||||
total_funds(&peer->cstate->b));
|
||||
|
||||
/* Now, we consider this channel_state current one. */
|
||||
tal_free(peer->cstate);
|
||||
peer->cstate = tal_steal(peer, cur->cstate);
|
||||
|
||||
tal_free(peer->us.commit);
|
||||
peer->us.commit = tal_steal(peer, cur->our_commit);
|
||||
/* FIXME: Save their old commit details, to steal funds. */
|
||||
tal_free(peer->them.commit);
|
||||
peer->them.commit = tal_steal(peer, cur->their_commit);
|
||||
peer->us.revocation_hash = cur->our_revocation_hash;
|
||||
peer->them.revocation_hash = cur->their_revocation_hash;
|
||||
/* BOLT #2:
|
||||
*
|
||||
* A node MUST NOT send an `update_commit` message which does
|
||||
* not include any updates.
|
||||
*/
|
||||
if (ci->prev->cstate->changes == ci->cstate->changes)
|
||||
return pkt_err(peer, "Empty commit");
|
||||
|
||||
err = check_and_save_commit_sig(peer, ci, c->sig);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Switch to the new commitment. */
|
||||
peer->us.commit = ci;
|
||||
peer->commit_tx_counter++;
|
||||
}
|
||||
|
||||
Pkt *accept_pkt_update_accept(struct peer *peer, const Pkt *pkt)
|
||||
{
|
||||
const UpdateAccept *a = pkt->update_accept;
|
||||
struct htlc_progress *cur = peer->current_htlc;
|
||||
|
||||
proto_to_sha256(a->revocation_hash, &cur->their_revocation_hash);
|
||||
|
||||
cur->their_sig.stype = SIGHASH_ALL;
|
||||
if (!proto_to_signature(a->sig, &cur->their_sig.sig))
|
||||
return pkt_err(peer, "Malformed signature");
|
||||
|
||||
/* Now we can make commit tx pair. */
|
||||
make_commit_txs(cur, peer, &cur->our_revocation_hash,
|
||||
&cur->their_revocation_hash,
|
||||
cur->cstate,
|
||||
&cur->our_commit, &cur->their_commit);
|
||||
|
||||
/* Their sig should sign our new commit tx. */
|
||||
if (!check_tx_sig(peer->dstate->secpctx,
|
||||
cur->our_commit, 0,
|
||||
peer->anchor.redeemscript,
|
||||
tal_count(peer->anchor.redeemscript),
|
||||
&peer->them.commitkey,
|
||||
&cur->their_sig))
|
||||
return pkt_err(peer, "Bad signature");
|
||||
|
||||
/* Our next step will be to send the revocation preimage, so
|
||||
* update to new HTLC now so we never use the old one. */
|
||||
update_to_new_htlcs(peer);
|
||||
peer_get_revocation_hash(peer, peer->commit_tx_counter + 1,
|
||||
&peer->us.next_revocation_hash);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static bool check_preimage(const Sha256Hash *preimage, const struct sha256 *hash)
|
||||
{
|
||||
@ -667,41 +718,30 @@ static bool check_preimage(const Sha256Hash *preimage, const struct sha256 *hash
|
||||
return structeq(&h, hash);
|
||||
}
|
||||
|
||||
Pkt *accept_pkt_update_complete(struct peer *peer, const Pkt *pkt)
|
||||
Pkt *accept_pkt_revocation(struct peer *peer, const Pkt *pkt)
|
||||
{
|
||||
/* FIXME: Check preimage against old tx! */
|
||||
const UpdateRevocation *r = pkt->update_revocation;
|
||||
|
||||
/* FIXME: Save preimage in shachain too. */
|
||||
if (!check_preimage(r->revocation_preimage,
|
||||
&peer->them.commit->prev->revocation_hash))
|
||||
return pkt_err(peer, "complete preimage incorrect");
|
||||
|
||||
/* They're revoking the previous one. */
|
||||
assert(!peer->them.commit->prev->revocation_preimage);
|
||||
peer->them.commit->prev->revocation_preimage
|
||||
= tal(peer->them.commit->prev, struct sha256);
|
||||
|
||||
proto_to_sha256(r->revocation_preimage,
|
||||
peer->them.commit->prev->revocation_preimage);
|
||||
|
||||
/* Save next revocation hash. */
|
||||
proto_to_sha256(r->next_revocation_hash,
|
||||
&peer->them.next_revocation_hash);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Pkt *accept_pkt_update_signature(struct peer *peer,
|
||||
const Pkt *pkt)
|
||||
{
|
||||
const UpdateSignature *s = pkt->update_signature;
|
||||
struct htlc_progress *cur = peer->current_htlc;
|
||||
|
||||
cur->their_sig.stype = SIGHASH_ALL;
|
||||
if (!proto_to_signature(s->sig, &cur->their_sig.sig))
|
||||
return pkt_err(peer, "Malformed signature");
|
||||
|
||||
/* Their sig should sign our new commit tx. */
|
||||
if (!check_tx_sig(peer->dstate->secpctx,
|
||||
cur->our_commit, 0,
|
||||
peer->anchor.redeemscript,
|
||||
tal_count(peer->anchor.redeemscript),
|
||||
&peer->them.commitkey,
|
||||
&cur->their_sig))
|
||||
return pkt_err(peer, "Bad signature");
|
||||
|
||||
/* Check their revocation preimage. */
|
||||
if (!check_preimage(s->revocation_preimage, &peer->them.revocation_hash))
|
||||
return pkt_err(peer, "Bad revocation preimage");
|
||||
|
||||
/* Our next step will be to send the revocation preimage, so
|
||||
* update to new HTLC now so we never use the old one. */
|
||||
update_to_new_htlcs(peer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
Pkt *accept_pkt_close_clearing(struct peer *peer, const Pkt *pkt)
|
||||
{
|
||||
/* FIXME: Reject unknown odd fields? */
|
||||
@ -721,7 +761,7 @@ Pkt *accept_pkt_close_sig(struct peer *peer, const Pkt *pkt, bool *matches)
|
||||
* number of satoshis.
|
||||
*/
|
||||
if ((c->close_fee & 1)
|
||||
|| c->close_fee > commit_tx_fee(peer->them.commit,
|
||||
|| c->close_fee > commit_tx_fee(peer->them.commit->tx,
|
||||
peer->anchor.satoshis)) {
|
||||
return pkt_err(peer, "Invalid close fee");
|
||||
}
|
||||
|
433
daemon/peer.c
433
daemon/peer.c
@ -10,6 +10,7 @@
|
||||
#include "log.h"
|
||||
#include "names.h"
|
||||
#include "peer.h"
|
||||
#include "pseudorand.h"
|
||||
#include "secrets.h"
|
||||
#include "state.h"
|
||||
#include "timeout.h"
|
||||
@ -207,6 +208,36 @@ static void queue_cmd_(struct peer *peer,
|
||||
try_command(peer);
|
||||
};
|
||||
|
||||
/* All unrevoked commit txs must have no HTLCs in them. */
|
||||
bool committed_to_htlcs(const struct peer *peer)
|
||||
{
|
||||
const struct commit_info *i;
|
||||
|
||||
/* Before anchor exchange, we don't even have cstate. */
|
||||
if (!peer->us.commit || !peer->us.commit->cstate)
|
||||
return false;
|
||||
|
||||
i = peer->us.commit;
|
||||
while (i && !i->revocation_preimage) {
|
||||
if (tal_count(i->cstate->a.htlcs))
|
||||
return true;
|
||||
if (tal_count(i->cstate->b.htlcs))
|
||||
return true;
|
||||
i = i->prev;
|
||||
}
|
||||
|
||||
i = peer->them.commit;
|
||||
while (i && !i->revocation_preimage) {
|
||||
if (tal_count(i->cstate->a.htlcs))
|
||||
return true;
|
||||
if (tal_count(i->cstate->b.htlcs))
|
||||
return true;
|
||||
i = i->prev;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void state_event(struct peer *peer,
|
||||
const enum state_input input,
|
||||
const union input *idata)
|
||||
@ -267,8 +298,8 @@ static void do_anchor_offer(struct peer *peer, void *unused)
|
||||
static struct io_plan *peer_crypto_on(struct io_conn *conn, struct peer *peer)
|
||||
{
|
||||
peer_secrets_init(peer);
|
||||
peer_get_revocation_hash(peer, 0, &peer->us.revocation_hash);
|
||||
peer_get_revocation_hash(peer, 1, &peer->us.next_revocation_hash);
|
||||
|
||||
peer_get_revocation_hash(peer, 0, &peer->us.next_revocation_hash);
|
||||
|
||||
assert(peer->state == STATE_INIT);
|
||||
|
||||
@ -345,14 +376,15 @@ static struct peer *new_peer(struct lightningd_state *dstate,
|
||||
peer->outpkt = tal_arr(peer, struct out_pkt, 0);
|
||||
peer->curr_cmd.cmd = INPUT_NONE;
|
||||
list_head_init(&peer->pending_cmd);
|
||||
peer->current_htlc = NULL;
|
||||
peer->commit_tx_counter = 0;
|
||||
peer->cstate = NULL;
|
||||
peer->close_watch_timeout = NULL;
|
||||
peer->anchor.watches = NULL;
|
||||
peer->cur_commit.watch = NULL;
|
||||
peer->closing.their_sig = NULL;
|
||||
peer->cleared = INPUT_NONE;
|
||||
/* Make it different from other node (to catch bugs!), but a
|
||||
* round number for simple eyeballing. */
|
||||
peer->htlc_id_counter = pseudorand(1ULL << 32) * 1000;
|
||||
|
||||
/* If we free peer, conn should be closed, but can't be freed
|
||||
* immediately so don't make peer a parent. */
|
||||
@ -368,7 +400,8 @@ static struct peer *new_peer(struct lightningd_state *dstate,
|
||||
peer->us.commit_fee_rate = dstate->config.commitment_fee_rate;
|
||||
|
||||
peer->us.commit = peer->them.commit = NULL;
|
||||
|
||||
peer->us.staging_cstate = peer->them.staging_cstate = NULL;
|
||||
|
||||
/* FIXME: Attach IO logging for this peer. */
|
||||
tal_add_destructor(peer, destroy_peer);
|
||||
|
||||
@ -615,6 +648,18 @@ static bool txmatch(const struct bitcoin_tx *txa, const struct bitcoin_tx *txb)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* We may have two possible "current" commits; this loop will check them both. */
|
||||
static bool is_unrevoked_commit(const struct commit_info *ci,
|
||||
const struct bitcoin_tx *tx)
|
||||
{
|
||||
while (ci && !ci->revocation_preimage) {
|
||||
if (txmatch(ci->tx, tx))
|
||||
return true;
|
||||
ci = ci->prev;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* A mutual close is a simple 2 output p2sh to the final addresses, but
|
||||
* without knowing fee we can't determine order, so examine each output. */
|
||||
static bool is_mutual_close(const struct peer *peer,
|
||||
@ -663,7 +708,7 @@ static void anchor_spent(struct peer *peer,
|
||||
|
||||
/* FIXME: change type in idata? */
|
||||
idata.btc = (struct bitcoin_event *)tx;
|
||||
if (txmatch(tx, peer->them.commit))
|
||||
if (is_unrevoked_commit(peer->them.commit, tx))
|
||||
state_event(peer, w->theyspent, &idata);
|
||||
else if (is_mutual_close(peer, tx))
|
||||
add_close_tx_watch(peer, peer, tx, close_depth_cb);
|
||||
@ -799,7 +844,8 @@ void peer_watch_delayed(struct peer *peer,
|
||||
{
|
||||
struct sha256_double txid;
|
||||
|
||||
assert(tx == peer->us.commit);
|
||||
/* We only ever spend the last one. */
|
||||
assert(tx == peer->us.commit->tx);
|
||||
bitcoin_txid(tx, &txid);
|
||||
memset(&peer->cur_commit.blockid, 0xFF,
|
||||
sizeof(peer->cur_commit.blockid));
|
||||
@ -852,7 +898,7 @@ struct bitcoin_tx *peer_create_close_tx(struct peer *peer, u64 fee)
|
||||
struct channel_state cstate;
|
||||
|
||||
/* We don't need a deep copy here, just fee levels. */
|
||||
cstate = *peer->cstate;
|
||||
cstate = *peer->us.staging_cstate;
|
||||
if (!force_fee(&cstate, fee)) {
|
||||
log_unusual(peer->log,
|
||||
"peer_create_close_tx: can't afford fee %"PRIu64,
|
||||
@ -896,7 +942,7 @@ void peer_calculate_close_fee(struct peer *peer)
|
||||
* 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);
|
||||
maxfee = commit_tx_fee(peer->us.commit->tx, 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
|
||||
@ -1001,32 +1047,6 @@ void peer_unexpected_pkt(struct peer *peer, const Pkt *pkt)
|
||||
FIXME_STUB(peer);
|
||||
}
|
||||
|
||||
/* Someone declined our HTLC: details in pkt (we will also get CMD_FAIL) */
|
||||
void peer_htlc_declined(struct peer *peer, const Pkt *pkt)
|
||||
{
|
||||
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. */
|
||||
void peer_htlc_ours_deferred(struct peer *peer)
|
||||
{
|
||||
FIXME_STUB(peer);
|
||||
}
|
||||
|
||||
/* Successfully added/fulfilled/timedout/routefail an HTLC. */
|
||||
void peer_htlc_done(struct peer *peer)
|
||||
{
|
||||
peer->current_htlc = tal_free(peer->current_htlc);
|
||||
}
|
||||
|
||||
/* Someone aborted an existing HTLC. */
|
||||
void peer_htlc_aborted(struct peer *peer)
|
||||
{
|
||||
FIXME_STUB(peer);
|
||||
}
|
||||
|
||||
/* An on-chain transaction revealed an R value. */
|
||||
const struct htlc *peer_tx_revealed_r_value(struct peer *peer,
|
||||
const struct bitcoin_event *btc)
|
||||
@ -1034,15 +1054,6 @@ const struct htlc *peer_tx_revealed_r_value(struct peer *peer,
|
||||
FIXME_STUB(peer);
|
||||
}
|
||||
|
||||
bool committed_to_htlcs(const struct peer *peer)
|
||||
{
|
||||
/* This is only set after anchor established. */
|
||||
if (!peer->cstate)
|
||||
return false;
|
||||
return tal_count(peer->cstate->a.htlcs) != 0
|
||||
|| tal_count(peer->cstate->b.htlcs) != 0;
|
||||
}
|
||||
|
||||
void peer_watch_htlcs_cleared(struct peer *peer,
|
||||
enum state_input all_done)
|
||||
{
|
||||
@ -1079,7 +1090,7 @@ const struct bitcoin_tx *bitcoin_close(struct peer *peer)
|
||||
const struct bitcoin_tx *bitcoin_spend_ours(struct peer *peer)
|
||||
{
|
||||
u8 *redeemscript, *linear;
|
||||
const struct bitcoin_tx *commit = peer->us.commit;
|
||||
const struct bitcoin_tx *commit = peer->us.commit->tx;
|
||||
struct bitcoin_signature sig;
|
||||
struct bitcoin_tx *tx;
|
||||
unsigned int p2sh_out;
|
||||
@ -1089,7 +1100,7 @@ const struct bitcoin_tx *bitcoin_spend_ours(struct peer *peer)
|
||||
&peer->us.finalkey,
|
||||
&peer->them.locktime,
|
||||
&peer->them.finalkey,
|
||||
&peer->us.revocation_hash);
|
||||
&peer->us.commit->revocation_hash);
|
||||
|
||||
/* Now, create transaction to spend it. */
|
||||
tx = bitcoin_tx(peer, 1, 1);
|
||||
@ -1161,21 +1172,21 @@ const struct bitcoin_tx *bitcoin_commit(struct peer *peer)
|
||||
struct bitcoin_signature sig;
|
||||
|
||||
/* Can't be signed already! */
|
||||
assert(peer->us.commit->input[0].script_length == 0);
|
||||
assert(peer->us.commit->tx->input[0].script_length == 0);
|
||||
|
||||
sig.stype = SIGHASH_ALL;
|
||||
peer_sign_ourcommit(peer, peer->us.commit, &sig.sig);
|
||||
peer_sign_ourcommit(peer, peer->us.commit->tx, &sig.sig);
|
||||
|
||||
peer->us.commit->input[0].script
|
||||
= scriptsig_p2sh_2of2(peer->us.commit,
|
||||
&peer->cur_commit.theirsig,
|
||||
peer->us.commit->tx->input[0].script
|
||||
= scriptsig_p2sh_2of2(peer->us.commit->tx,
|
||||
peer->us.commit->sig,
|
||||
&sig,
|
||||
&peer->them.commitkey,
|
||||
&peer->us.commitkey);
|
||||
peer->us.commit->input[0].script_length
|
||||
= tal_count(peer->us.commit->input[0].script);
|
||||
peer->us.commit->tx->input[0].script_length
|
||||
= tal_count(peer->us.commit->tx->input[0].script);
|
||||
|
||||
return peer->us.commit;
|
||||
return peer->us.commit->tx;
|
||||
}
|
||||
|
||||
/* Create a HTLC refund collection */
|
||||
@ -1202,22 +1213,6 @@ static void created_anchor(struct lightningd_state *dstate,
|
||||
/* We'll need this later, when we're told to broadcast it. */
|
||||
peer->anchor.tx = tal_steal(peer, tx);
|
||||
|
||||
/* FIXME: Check their cstate too (different fee rate!) */
|
||||
peer->cstate = initial_funding(peer,
|
||||
peer->us.offer_anchor == CMD_OPEN_WITH_ANCHOR,
|
||||
peer->anchor.satoshis,
|
||||
peer->us.commit_fee_rate);
|
||||
if (!peer->cstate)
|
||||
fatal("Insufficient anchor funds for commitfee");
|
||||
|
||||
/* Now we can make initial (unsigned!) commit txs. */
|
||||
make_commit_txs(peer, peer,
|
||||
&peer->us.revocation_hash,
|
||||
&peer->them.revocation_hash,
|
||||
peer->cstate,
|
||||
&peer->us.commit,
|
||||
&peer->them.commit);
|
||||
|
||||
state_event(peer, BITCOIN_ANCHOR_CREATED, NULL);
|
||||
}
|
||||
|
||||
@ -1259,38 +1254,53 @@ const struct bitcoin_tx *bitcoin_anchor(struct peer *peer)
|
||||
return peer->anchor.tx;
|
||||
}
|
||||
|
||||
void make_commit_txs(const tal_t *ctx,
|
||||
const struct peer *peer,
|
||||
const struct sha256 *our_revocation_hash,
|
||||
const struct sha256 *their_revocation_hash,
|
||||
const struct channel_state *cstate,
|
||||
struct bitcoin_tx **ours, struct bitcoin_tx **theirs)
|
||||
/* Sets up the initial cstate and commit tx for both nodes: false if
|
||||
* insufficient funds. */
|
||||
bool setup_first_commit(struct peer *peer)
|
||||
{
|
||||
struct channel_state their_cstate;
|
||||
assert(!peer->us.commit->tx);
|
||||
assert(!peer->them.commit->tx);
|
||||
|
||||
*ours = create_commit_tx(ctx,
|
||||
&peer->us.finalkey,
|
||||
&peer->them.finalkey,
|
||||
&peer->them.locktime,
|
||||
&peer->anchor.txid,
|
||||
peer->anchor.index,
|
||||
peer->anchor.satoshis,
|
||||
our_revocation_hash,
|
||||
cstate);
|
||||
/* Revocation hashes already filled in, from pkt_open */
|
||||
peer->us.commit->cstate = initial_funding(peer,
|
||||
peer->us.offer_anchor
|
||||
== CMD_OPEN_WITH_ANCHOR,
|
||||
peer->anchor.satoshis,
|
||||
peer->us.commit_fee_rate);
|
||||
if (!peer->us.commit->cstate)
|
||||
return false;
|
||||
|
||||
/* 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,
|
||||
&peer->us.locktime,
|
||||
&peer->anchor.txid,
|
||||
peer->anchor.index,
|
||||
peer->anchor.satoshis,
|
||||
their_revocation_hash,
|
||||
&their_cstate);
|
||||
peer->them.commit->cstate = initial_funding(peer,
|
||||
peer->them.offer_anchor
|
||||
== CMD_OPEN_WITH_ANCHOR,
|
||||
peer->anchor.satoshis,
|
||||
peer->them.commit_fee_rate);
|
||||
if (!peer->them.commit->cstate)
|
||||
return false;
|
||||
|
||||
peer->us.commit->tx = create_commit_tx(peer->us.commit,
|
||||
&peer->us.finalkey,
|
||||
&peer->them.finalkey,
|
||||
&peer->them.locktime,
|
||||
&peer->anchor.txid,
|
||||
peer->anchor.index,
|
||||
peer->anchor.satoshis,
|
||||
&peer->us.commit->revocation_hash,
|
||||
peer->us.commit->cstate);
|
||||
|
||||
peer->them.commit->tx = create_commit_tx(peer->them.commit,
|
||||
&peer->them.finalkey,
|
||||
&peer->us.finalkey,
|
||||
&peer->us.locktime,
|
||||
&peer->anchor.txid,
|
||||
peer->anchor.index,
|
||||
peer->anchor.satoshis,
|
||||
&peer->them.commit->revocation_hash,
|
||||
peer->them.commit->cstate);
|
||||
|
||||
peer->us.staging_cstate = copy_funding(peer, peer->us.commit->cstate);
|
||||
peer->them.staging_cstate = copy_funding(peer, peer->them.commit->cstate);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void json_add_abstime(struct json_result *response,
|
||||
@ -1305,16 +1315,13 @@ static void json_add_abstime(struct json_result *response,
|
||||
json_object_end(response);
|
||||
}
|
||||
|
||||
static void json_add_cstate(struct json_result *response,
|
||||
const char *id,
|
||||
const struct channel_oneside *side)
|
||||
static void json_add_htlcs(struct json_result *response,
|
||||
const char *id,
|
||||
const struct channel_oneside *side)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
json_object_start(response, id);
|
||||
json_add_num(response, "pay", side->pay_msat);
|
||||
json_add_num(response, "fee", side->fee_msat);
|
||||
json_array_start(response, "htlcs");
|
||||
json_array_start(response, id);
|
||||
for (i = 0; i < tal_count(side->htlcs); i++) {
|
||||
json_object_start(response, NULL);
|
||||
json_add_u64(response, "msatoshis", side->htlcs[i].msatoshis);
|
||||
@ -1325,9 +1332,21 @@ static void json_add_cstate(struct json_result *response,
|
||||
json_object_end(response);
|
||||
}
|
||||
json_array_end(response);
|
||||
json_object_end(response);
|
||||
}
|
||||
|
||||
/* This is money we can count on. */
|
||||
static const struct channel_state *last_signed_state(const struct commit_info *i)
|
||||
{
|
||||
while (i) {
|
||||
if (i->sig)
|
||||
return i->cstate;
|
||||
i = i->prev;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* FIXME: add history command which shows all prior and current commit txs */
|
||||
|
||||
/* FIXME: Somehow we should show running DNS lookups! */
|
||||
/* FIXME: Show status of peers! */
|
||||
static void json_getpeers(struct command *cmd,
|
||||
@ -1339,6 +1358,8 @@ static void json_getpeers(struct command *cmd,
|
||||
json_object_start(response, NULL);
|
||||
json_array_start(response, "peers");
|
||||
list_for_each(&cmd->dstate->peers, p, list) {
|
||||
const struct channel_state *last;
|
||||
|
||||
json_object_start(response, NULL);
|
||||
json_add_string(response, "name", log_prefix(p->log));
|
||||
json_add_string(response, "state", state_name(p->state));
|
||||
@ -1349,12 +1370,26 @@ static void json_getpeers(struct command *cmd,
|
||||
json_add_hex(response, "peerid",
|
||||
p->id.der, sizeof(p->id.der));
|
||||
|
||||
if (p->cstate) {
|
||||
json_object_start(response, "channel");
|
||||
json_add_cstate(response, "us", &p->cstate->a);
|
||||
json_add_cstate(response, "them", &p->cstate->b);
|
||||
/* FIXME: Report anchor. */
|
||||
|
||||
last = last_signed_state(p->us.commit);
|
||||
if (!last) {
|
||||
json_object_end(response);
|
||||
continue;
|
||||
}
|
||||
|
||||
json_add_num(response, "our_amount", last->a.pay_msat);
|
||||
json_add_num(response, "our_fee", last->a.fee_msat);
|
||||
json_add_num(response, "their_amount", last->b.pay_msat);
|
||||
json_add_num(response, "their_fee", last->b.fee_msat);
|
||||
json_add_htlcs(response, "our_htlcs", &last->a);
|
||||
json_add_htlcs(response, "their_htlcs", &last->b);
|
||||
|
||||
/* Any changes since then? */
|
||||
if (p->us.staging_cstate->changes != last->changes)
|
||||
json_add_num(response, "staged_changes",
|
||||
p->us.staging_cstate->changes
|
||||
- last->changes);
|
||||
json_object_end(response);
|
||||
}
|
||||
json_array_end(response);
|
||||
@ -1370,26 +1405,22 @@ const struct json_command getpeers_command = {
|
||||
};
|
||||
|
||||
static void set_htlc_command(struct peer *peer,
|
||||
struct channel_state *cstate,
|
||||
struct command *jsoncmd,
|
||||
enum state_input cmd,
|
||||
const union htlc_staging *stage)
|
||||
{
|
||||
assert(!peer->current_htlc);
|
||||
/* FIXME: memleak! */
|
||||
/* FIXME: Get rid of struct htlc_progress */
|
||||
struct htlc_progress *progress = tal(peer, struct htlc_progress);
|
||||
|
||||
peer->current_htlc = tal(peer, struct htlc_progress);
|
||||
peer->current_htlc->cstate = tal_steal(peer->current_htlc, cstate);
|
||||
peer->current_htlc->stage = *stage;
|
||||
|
||||
peer_get_revocation_hash(peer, peer->commit_tx_counter+1,
|
||||
&peer->current_htlc->our_revocation_hash);
|
||||
|
||||
/* FIXME: Do we need current_htlc as idata arg? */
|
||||
set_current_command(peer, cmd, peer->current_htlc, jsoncmd);
|
||||
progress->stage = *stage;
|
||||
set_current_command(peer, cmd, progress, jsoncmd);
|
||||
}
|
||||
|
||||
/* FIXME: Keep a timeout for each peer, in case they're unresponsive. */
|
||||
|
||||
|
||||
/* FIXME: Make sure no HTLCs in any unrevoked commit tx are live. */
|
||||
|
||||
static void check_htlc_expiry(struct peer *peer, void *unused)
|
||||
{
|
||||
size_t i;
|
||||
@ -1397,10 +1428,10 @@ static void check_htlc_expiry(struct peer *peer, void *unused)
|
||||
|
||||
stage.fail.fail = HTLC_FAIL;
|
||||
|
||||
/* Check their htlcs for expiry. */
|
||||
for (i = 0; i < tal_count(peer->cstate->b.htlcs); i++) {
|
||||
struct channel_htlc *htlc = &peer->cstate->b.htlcs[i];
|
||||
struct channel_state *cstate;
|
||||
/* Check their currently still-existing htlcs for expiry:
|
||||
* We eliminate them from staging as we go. */
|
||||
for (i = 0; i < tal_count(peer->them.staging_cstate->a.htlcs); i++) {
|
||||
struct channel_htlc *htlc = &peer->them.staging_cstate->a.htlcs[i];
|
||||
|
||||
/* Not a seconds-based expiry? */
|
||||
if (!abs_locktime_is_seconds(&htlc->expiry))
|
||||
@ -1411,11 +1442,8 @@ static void check_htlc_expiry(struct peer *peer, void *unused)
|
||||
< abs_locktime_to_seconds(&htlc->expiry))
|
||||
continue;
|
||||
|
||||
cstate = copy_funding(peer, peer->cstate);
|
||||
funding_b_fail_htlc(cstate, i);
|
||||
stage.fail.index = i;
|
||||
set_htlc_command(peer, cstate, NULL, CMD_SEND_HTLC_FAIL,
|
||||
&stage);
|
||||
stage.fail.id = htlc->id;
|
||||
set_htlc_command(peer, NULL, CMD_SEND_HTLC_FAIL, &stage);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1450,25 +1478,54 @@ static void do_newhtlc(struct peer *peer, struct newhtlc *newhtlc)
|
||||
struct channel_state *cstate;
|
||||
union htlc_staging stage;
|
||||
|
||||
/* Now we can assign counter and guarantee uniqueness. */
|
||||
newhtlc->htlc.id = peer->htlc_id_counter;
|
||||
stage.add.add = HTLC_ADD;
|
||||
stage.add.htlc = newhtlc->htlc;
|
||||
|
||||
/* BOLT #2:
|
||||
*
|
||||
* A node MUST NOT add a HTLC if it would result in it
|
||||
* offering more than 1500 HTLCs in either commitment transaction.
|
||||
*/
|
||||
if (tal_count(peer->us.staging_cstate->a.htlcs) == 1500
|
||||
|| tal_count(peer->them.staging_cstate->b.htlcs) == 1500) {
|
||||
command_fail(newhtlc->jsoncmd, "Too many HTLCs");
|
||||
}
|
||||
|
||||
/* Can we even offer this much? We check now, just before we
|
||||
* execute. */
|
||||
cstate = copy_funding(newhtlc, peer->cstate);
|
||||
if (!funding_a_add_htlc(cstate, newhtlc->htlc.msatoshis,
|
||||
&newhtlc->htlc.expiry, &newhtlc->htlc.rhash, 0)) {
|
||||
|
||||
/* BOLT #2:
|
||||
*
|
||||
* A node MUST NOT offer `amount_msat` it cannot pay for in
|
||||
* both commitment transactions at the current `fee_rate`
|
||||
*/
|
||||
cstate = copy_funding(newhtlc, peer->them.staging_cstate);
|
||||
if (!funding_b_add_htlc(cstate, newhtlc->htlc.msatoshis,
|
||||
&newhtlc->htlc.expiry, &newhtlc->htlc.rhash,
|
||||
newhtlc->htlc.id)) {
|
||||
command_fail(newhtlc->jsoncmd,
|
||||
"Cannot afford %"PRIu64" milli-satoshis",
|
||||
"Cannot afford %"PRIu64
|
||||
" milli-satoshis in their commit tx",
|
||||
newhtlc->htlc.msatoshis);
|
||||
return;
|
||||
}
|
||||
|
||||
/* FIXME: Never propose duplicate rvalues? */
|
||||
peer_add_htlc_expiry(peer, &newhtlc->htlc.expiry);
|
||||
cstate = copy_funding(newhtlc, peer->us.staging_cstate);
|
||||
if (!funding_a_add_htlc(cstate, newhtlc->htlc.msatoshis,
|
||||
&newhtlc->htlc.expiry, &newhtlc->htlc.rhash,
|
||||
newhtlc->htlc.id)) {
|
||||
command_fail(newhtlc->jsoncmd,
|
||||
"Cannot afford %"PRIu64
|
||||
" milli-satoshis in our commit tx",
|
||||
newhtlc->htlc.msatoshis);
|
||||
return;
|
||||
}
|
||||
|
||||
set_htlc_command(peer, cstate, newhtlc->jsoncmd,
|
||||
CMD_SEND_HTLC_ADD, &stage);
|
||||
/* Make sure we never offer the same one twice. */
|
||||
peer->htlc_id_counter++;
|
||||
|
||||
/* FIXME: Never propose duplicate rvalues? */
|
||||
set_htlc_command(peer, newhtlc->jsoncmd, CMD_SEND_HTLC_ADD, &stage);
|
||||
}
|
||||
|
||||
static void json_newhtlc(struct command *cmd,
|
||||
@ -1495,6 +1552,11 @@ static void json_newhtlc(struct command *cmd,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!peer->them.commit || !peer->them.commit->cstate) {
|
||||
command_fail(cmd, "peer not fully established");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Attach to cmd until it's complete. */
|
||||
newhtlc = tal(cmd, struct newhtlc);
|
||||
newhtlc->jsoncmd = cmd;
|
||||
@ -1544,6 +1606,7 @@ static void json_newhtlc(struct command *cmd,
|
||||
queue_cmd(peer, do_newhtlc, newhtlc);
|
||||
}
|
||||
|
||||
/* FIXME: Use HTLC ids, not r values! */
|
||||
const struct json_command newhtlc_command = {
|
||||
"newhtlc",
|
||||
json_newhtlc,
|
||||
@ -1559,7 +1622,6 @@ struct fulfillhtlc {
|
||||
static void do_fullfill(struct peer *peer,
|
||||
struct fulfillhtlc *fulfillhtlc)
|
||||
{
|
||||
struct channel_state *cstate;
|
||||
struct sha256 rhash;
|
||||
size_t i;
|
||||
union htlc_staging stage;
|
||||
@ -1569,17 +1631,13 @@ static void do_fullfill(struct peer *peer,
|
||||
|
||||
sha256(&rhash, &fulfillhtlc->r, sizeof(fulfillhtlc->r));
|
||||
|
||||
i = funding_find_htlc(&peer->cstate->b, &rhash);
|
||||
if (i == tal_count(peer->cstate->b.htlcs)) {
|
||||
command_fail(fulfillhtlc->jsoncmd,
|
||||
"preimage htlc not found");
|
||||
i = funding_find_htlc(&peer->them.staging_cstate->a, &rhash);
|
||||
if (i == tal_count(peer->them.staging_cstate->a.htlcs)) {
|
||||
command_fail(fulfillhtlc->jsoncmd, "preimage htlc not found");
|
||||
return;
|
||||
}
|
||||
stage.fulfill.index = i;
|
||||
cstate = copy_funding(fulfillhtlc, peer->cstate);
|
||||
funding_b_fulfill_htlc(cstate, i);
|
||||
|
||||
set_htlc_command(peer, cstate, fulfillhtlc->jsoncmd,
|
||||
stage.fulfill.id = peer->them.staging_cstate->a.htlcs[i].id;
|
||||
set_htlc_command(peer, fulfillhtlc->jsoncmd,
|
||||
CMD_SEND_HTLC_FULFILL, &stage);
|
||||
}
|
||||
|
||||
@ -1604,6 +1662,11 @@ static void json_fulfillhtlc(struct command *cmd,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!peer->them.commit || !peer->them.commit->cstate) {
|
||||
command_fail(cmd, "peer not fully established");
|
||||
return;
|
||||
}
|
||||
|
||||
fulfillhtlc = tal(cmd, struct fulfillhtlc);
|
||||
fulfillhtlc->jsoncmd = cmd;
|
||||
|
||||
@ -1634,24 +1697,22 @@ struct failhtlc {
|
||||
static void do_failhtlc(struct peer *peer,
|
||||
struct failhtlc *failhtlc)
|
||||
{
|
||||
struct channel_state *cstate;
|
||||
size_t i;
|
||||
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)) {
|
||||
/* Look in peer->them.staging_cstate->a, as that's where we'll
|
||||
* immediately remove it from: avoids double-handling. */
|
||||
/* FIXME: Make sure it's also committed in previous commit tx! */
|
||||
i = funding_find_htlc(&peer->them.staging_cstate->a, &failhtlc->rhash);
|
||||
if (i == tal_count(peer->them.staging_cstate->a.htlcs)) {
|
||||
command_fail(failhtlc->jsoncmd, "htlc not found");
|
||||
return;
|
||||
}
|
||||
stage.fail.index = i;
|
||||
stage.fail.id = peer->them.staging_cstate->a.htlcs[i].id;
|
||||
|
||||
cstate = copy_funding(failhtlc, peer->cstate);
|
||||
funding_b_fail_htlc(cstate, i);
|
||||
|
||||
set_htlc_command(peer, cstate, failhtlc->jsoncmd,
|
||||
CMD_SEND_HTLC_FAIL, &stage);
|
||||
set_htlc_command(peer, failhtlc->jsoncmd, CMD_SEND_HTLC_FAIL, &stage);
|
||||
}
|
||||
|
||||
static void json_failhtlc(struct command *cmd,
|
||||
@ -1675,6 +1736,11 @@ static void json_failhtlc(struct command *cmd,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!peer->them.commit || !peer->them.commit->cstate) {
|
||||
command_fail(cmd, "peer not fully established");
|
||||
return;
|
||||
}
|
||||
|
||||
failhtlc = tal(cmd, struct failhtlc);
|
||||
failhtlc->jsoncmd = cmd;
|
||||
|
||||
@ -1697,6 +1763,51 @@ const struct json_command failhtlc_command = {
|
||||
"Returns an empty result on success"
|
||||
};
|
||||
|
||||
static void do_commit(struct peer *peer, struct command *jsoncmd)
|
||||
{
|
||||
/* We can have changes we suggested, or changes they suggested. */
|
||||
if (peer->them.staging_cstate->changes == peer->them.commit->cstate->changes) {
|
||||
command_fail(jsoncmd, "no changes to commit");
|
||||
return;
|
||||
}
|
||||
|
||||
set_current_command(peer, CMD_SEND_COMMIT, NULL, jsoncmd);
|
||||
}
|
||||
|
||||
static void json_commit(struct command *cmd,
|
||||
const char *buffer, const jsmntok_t *params)
|
||||
{
|
||||
struct peer *peer;
|
||||
jsmntok_t *peeridtok;
|
||||
|
||||
if (!json_get_params(buffer, params,
|
||||
"peerid", &peeridtok,
|
||||
NULL)) {
|
||||
command_fail(cmd, "Need peerid");
|
||||
return;
|
||||
}
|
||||
|
||||
peer = find_peer(cmd->dstate, buffer, peeridtok);
|
||||
if (!peer) {
|
||||
command_fail(cmd, "Could not find peer with that peerid");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!peer->them.commit || !peer->them.commit->cstate) {
|
||||
command_fail(cmd, "peer not fully established");
|
||||
return;
|
||||
}
|
||||
|
||||
queue_cmd(peer, do_commit, cmd);
|
||||
}
|
||||
|
||||
const struct json_command commit_command = {
|
||||
"commit",
|
||||
json_commit,
|
||||
"Commit all staged HTLC changes with {peerid}",
|
||||
"Returns an empty result on success"
|
||||
};
|
||||
|
||||
static void json_close(struct command *cmd,
|
||||
const char *buffer, const jsmntok_t *params)
|
||||
{
|
||||
|
@ -26,13 +26,13 @@ struct htlc_add {
|
||||
|
||||
struct htlc_fulfill {
|
||||
enum htlc_stage_type fulfill;
|
||||
size_t index;
|
||||
u64 id;
|
||||
struct sha256 r;
|
||||
};
|
||||
|
||||
struct htlc_fail {
|
||||
enum htlc_stage_type fail;
|
||||
size_t index;
|
||||
u64 id;
|
||||
};
|
||||
|
||||
union htlc_staging {
|
||||
@ -42,6 +42,21 @@ union htlc_staging {
|
||||
struct htlc_fail fail;
|
||||
};
|
||||
|
||||
struct commit_info {
|
||||
/* Previous one, if any. */
|
||||
struct commit_info *prev;
|
||||
/* Revocation hash. */
|
||||
struct sha256 revocation_hash;
|
||||
/* Commit tx. */
|
||||
struct bitcoin_tx *tx;
|
||||
/* Channel state for this tx. */
|
||||
struct channel_state *cstate;
|
||||
/* Other side's signature for last commit tx (if known) */
|
||||
struct bitcoin_signature *sig;
|
||||
/* Revocation preimage (if known). */
|
||||
struct sha256 *revocation_preimage;
|
||||
};
|
||||
|
||||
struct peer_visible_state {
|
||||
/* CMD_OPEN_WITH_ANCHOR or CMD_OPEN_WITHOUT_ANCHOR */
|
||||
enum state_input offer_anchor;
|
||||
@ -53,24 +68,17 @@ struct peer_visible_state {
|
||||
unsigned int mindepth;
|
||||
/* Commitment fee they're offering (satoshi). */
|
||||
u64 commit_fee_rate;
|
||||
/* Revocation hash for latest commit tx. */
|
||||
struct sha256 revocation_hash;
|
||||
/* Revocation hash for next commit tx. */
|
||||
struct sha256 next_revocation_hash;
|
||||
/* Current commit tx. */
|
||||
struct bitcoin_tx *commit;
|
||||
/* Commit txs: last one is current. */
|
||||
struct commit_info *commit;
|
||||
/* cstate to generate next commitment tx. */
|
||||
struct channel_state *staging_cstate;
|
||||
};
|
||||
|
||||
struct htlc_progress {
|
||||
/* The HTLC we're working on. */
|
||||
union htlc_staging stage;
|
||||
|
||||
/* Our next state. */
|
||||
/* Channel funding state, after we've completed htlc. */
|
||||
struct channel_state *cstate;
|
||||
struct sha256 our_revocation_hash, their_revocation_hash;
|
||||
struct bitcoin_tx *our_commit, *their_commit;
|
||||
struct bitcoin_signature their_sig;
|
||||
};
|
||||
|
||||
struct out_pkt {
|
||||
@ -105,9 +113,6 @@ struct peer {
|
||||
/* Global state. */
|
||||
struct lightningd_state *dstate;
|
||||
|
||||
/* Funding status for current commit tx (from our PoV). */
|
||||
struct channel_state *cstate;
|
||||
|
||||
/* The other end's address. */
|
||||
struct netaddr addr;
|
||||
|
||||
@ -142,11 +147,12 @@ struct peer {
|
||||
struct txwatch *watch;
|
||||
} cur_commit;
|
||||
|
||||
/* Current HTLC, if any. */
|
||||
struct htlc_progress *current_htlc;
|
||||
/* Number of HTLC updates (== number of previous commit txs) */
|
||||
u64 commit_tx_counter;
|
||||
|
||||
/* Counter to make unique HTLC ids. */
|
||||
u64 htlc_id_counter;
|
||||
|
||||
struct {
|
||||
/* Our last suggested closing fee. */
|
||||
u64 our_fee;
|
||||
@ -180,12 +186,8 @@ struct peer {
|
||||
|
||||
void setup_listeners(struct lightningd_state *dstate, unsigned int portnum);
|
||||
|
||||
void make_commit_txs(const tal_t *ctx,
|
||||
const struct peer *peer,
|
||||
const struct sha256 *our_revocation_hash,
|
||||
const struct sha256 *their_revocation_hash,
|
||||
const struct channel_state *cstate,
|
||||
struct bitcoin_tx **ours, struct bitcoin_tx **theirs);
|
||||
/* Populates very first peer->{us,them}.commit->{tx,cstate} */
|
||||
bool setup_first_commit(struct peer *peer);
|
||||
|
||||
void peer_add_htlc_expiry(struct peer *peer,
|
||||
const struct abs_locktime *expiry);
|
||||
|
@ -94,8 +94,8 @@ check_status_single()
|
||||
them_fee=$6
|
||||
them_htlcs="$7"
|
||||
|
||||
if $lcli getpeers | tr -s '\012\011 ' ' ' | $FGREP '"channel" : { "us" : { "pay" : '$us_pay', "fee" : '$us_fee', "htlcs" : [ '"$us_htlcs"'] }, "them" : { "pay" : '$them_pay', "fee" : '$them_fee', "htlcs" : [ '"$them_htlcs"'] } }'; then :; else
|
||||
echo Cannot find $lcli output: '"channel" : { "us" : { "pay" : '$us_pay', "fee" : '$us_fee', "htlcs" : [ '"$us_htlcs"'] }, "them" : { "pay" : '$them_pay', "fee" : '$them_fee', "htlcs" : [ '"$them_htlcs"'] } }' >&2
|
||||
if $lcli getpeers | tr -s '\012\011 ' ' ' | $FGREP '"our_amount" : '$us_pay', "our_fee" : '$us_fee', "their_amount" : '$them_pay', "their_fee" : '$them_fee', "our_htlcs" : [ '"$us_htlcs"'], "their_htlcs" : [ '"$them_htlcs"']'; then :; else
|
||||
echo Cannot find $lcli output: '"our_amount" : '$us_pay', "our_fee" : '$us_fee', "their_amount" : '$them_pay', "their_fee" : '$them_fee', "our_htlcs" : [ '"$us_htlcs"'], "their_htlcs" : [ '"$them_htlcs"']' >&2
|
||||
$lcli getpeers | tr -s '\012\011 ' ' ' >&2
|
||||
return 1
|
||||
fi
|
||||
@ -114,6 +114,18 @@ check_status()
|
||||
check_status_single lcli2 "$them_pay" "$them_fee" "$them_htlcs" "$us_pay" "$us_fee" "$us_htlcs"
|
||||
}
|
||||
|
||||
check_staged()
|
||||
{
|
||||
lcli="$1"
|
||||
num_htlcs="$2"
|
||||
|
||||
if $lcli getpeers | tr -s '\012\011 ' ' ' | $FGREP '"staged_changes" : '$num_htlcs; then :; else
|
||||
echo Cannot find $lcli output: '"staged_changes" : '$num_htlcs >&2
|
||||
$lcli getpeers | tr -s '\012\011 ' ' ' >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_tx_spend()
|
||||
{
|
||||
$CLI generate 1
|
||||
@ -248,8 +260,8 @@ $CLI generate 2
|
||||
# They poll every second, so give them time to process.
|
||||
sleep 2
|
||||
|
||||
lcli1 getpeers | $FGREP STATE_NORMAL_HIGHPRIO
|
||||
lcli2 getpeers | $FGREP STATE_NORMAL_LOWPRIO
|
||||
lcli1 getpeers | $FGREP STATE_NORMAL
|
||||
lcli2 getpeers | $FGREP STATE_NORMAL
|
||||
|
||||
A_AMOUNT=$(($AMOUNT - $NO_HTLCS_FEE))
|
||||
A_FEE=$NO_HTLCS_FEE
|
||||
@ -262,12 +274,32 @@ SECRET=1de08917a61cb2b62ed5937d38577f6a7bfe59c176781c6d8128018e8b5ccdfd
|
||||
RHASH=`lcli1 dev-rhash $SECRET | sed 's/.*"\([0-9a-f]*\)".*/\1/'`
|
||||
lcli1 newhtlc $ID2 1000000 $EXPIRY $RHASH
|
||||
|
||||
# Nothing should have changed!
|
||||
check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE ""
|
||||
# But 2 should register a staged htlc.
|
||||
check_staged lcli2 1
|
||||
|
||||
# Now commit it.
|
||||
lcli1 commit $ID2
|
||||
|
||||
# Node 1 hasn't got it committed, but node2 should have told it to stage.
|
||||
check_status_single lcli1 $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE ""
|
||||
check_staged lcli1 1
|
||||
|
||||
# Check channel status
|
||||
A_AMOUNT=$(($A_AMOUNT - $EXTRA_FEE - 1000000))
|
||||
A_FEE=$(($A_FEE + $EXTRA_FEE))
|
||||
|
||||
# Node 2 has it committed.
|
||||
check_status_single lcli2 $B_AMOUNT $B_FEE "" $A_AMOUNT $A_FEE '{ "msatoshis" : 1000000, "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH'" } '
|
||||
|
||||
# Now node2 gives commitment to node1.
|
||||
lcli2 commit $ID1
|
||||
check_status $A_AMOUNT $A_FEE '{ "msatoshis" : 1000000, "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH'" } ' $B_AMOUNT $B_FEE ""
|
||||
|
||||
lcli2 fulfillhtlc $ID1 $SECRET
|
||||
lcli2 commit $ID1
|
||||
lcli1 commit $ID2
|
||||
|
||||
# We've transferred the HTLC amount to 2, who now has to pay fees,
|
||||
# so no net change for A who saves on fees.
|
||||
@ -280,6 +312,8 @@ check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE ""
|
||||
|
||||
# A new one, at 10x the amount.
|
||||
lcli1 newhtlc $ID2 10000000 $EXPIRY $RHASH
|
||||
lcli1 commit $ID2
|
||||
lcli2 commit $ID1
|
||||
|
||||
# Check channel status
|
||||
A_AMOUNT=$(($A_AMOUNT - $EXTRA_FEE - 10000000))
|
||||
@ -287,6 +321,8 @@ 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
|
||||
lcli2 commit $ID1
|
||||
lcli1 commit $ID2
|
||||
|
||||
# Back to how we were before.
|
||||
A_AMOUNT=$(($A_AMOUNT + $EXTRA_FEE + 10000000))
|
||||
@ -294,22 +330,26 @@ 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
|
||||
lcli1 newhtlc $ID2 10000001 $EXPIRY $RHASH
|
||||
lcli1 commit $ID2
|
||||
lcli2 commit $ID1
|
||||
|
||||
# Check channel status
|
||||
A_AMOUNT=$(($A_AMOUNT - $EXTRA_FEE - 10000000))
|
||||
A_AMOUNT=$(($A_AMOUNT - $EXTRA_FEE - 10000001))
|
||||
A_FEE=$(($A_FEE + $EXTRA_FEE))
|
||||
check_status $A_AMOUNT $A_FEE '{ "msatoshis" : 10000000, "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH'" } ' $B_AMOUNT $B_FEE ""
|
||||
check_status $A_AMOUNT $A_FEE '{ "msatoshis" : 10000001, "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH'" } ' $B_AMOUNT $B_FEE ""
|
||||
|
||||
# Make sure node1 accepts the expiry packet.
|
||||
lcli1 dev-mocktime $(($EXPIRY))
|
||||
|
||||
# This should make node2 send it.
|
||||
lcli2 dev-mocktime $(($EXPIRY + 31))
|
||||
lcli2 commit $ID1
|
||||
lcli1 commit $ID2
|
||||
sleep 1
|
||||
|
||||
# Back to how we were before.
|
||||
A_AMOUNT=$(($A_AMOUNT + $EXTRA_FEE + 10000000))
|
||||
A_AMOUNT=$(($A_AMOUNT + $EXTRA_FEE + 10000001))
|
||||
A_FEE=$(($A_FEE - $EXTRA_FEE))
|
||||
check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE ""
|
||||
|
||||
|
732
lightning.pb-c.c
732
lightning.pb-c.c
@ -437,6 +437,49 @@ void open_complete__free_unpacked
|
||||
assert(message->base.descriptor == &open_complete__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void routing__init
|
||||
(Routing *message)
|
||||
{
|
||||
static Routing init_value = ROUTING__INIT;
|
||||
*message = init_value;
|
||||
}
|
||||
size_t routing__get_packed_size
|
||||
(const Routing *message)
|
||||
{
|
||||
assert(message->base.descriptor == &routing__descriptor);
|
||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
||||
}
|
||||
size_t routing__pack
|
||||
(const Routing *message,
|
||||
uint8_t *out)
|
||||
{
|
||||
assert(message->base.descriptor == &routing__descriptor);
|
||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
||||
}
|
||||
size_t routing__pack_to_buffer
|
||||
(const Routing *message,
|
||||
ProtobufCBuffer *buffer)
|
||||
{
|
||||
assert(message->base.descriptor == &routing__descriptor);
|
||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
||||
}
|
||||
Routing *
|
||||
routing__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data)
|
||||
{
|
||||
return (Routing *)
|
||||
protobuf_c_message_unpack (&routing__descriptor,
|
||||
allocator, len, data);
|
||||
}
|
||||
void routing__free_unpacked
|
||||
(Routing *message,
|
||||
ProtobufCAllocator *allocator)
|
||||
{
|
||||
assert(message->base.descriptor == &routing__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void update_add_htlc__init
|
||||
(UpdateAddHtlc *message)
|
||||
{
|
||||
@ -480,49 +523,6 @@ void update_add_htlc__free_unpacked
|
||||
assert(message->base.descriptor == &update_add_htlc__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void update_decline_htlc__init
|
||||
(UpdateDeclineHtlc *message)
|
||||
{
|
||||
static UpdateDeclineHtlc init_value = UPDATE_DECLINE_HTLC__INIT;
|
||||
*message = init_value;
|
||||
}
|
||||
size_t update_decline_htlc__get_packed_size
|
||||
(const UpdateDeclineHtlc *message)
|
||||
{
|
||||
assert(message->base.descriptor == &update_decline_htlc__descriptor);
|
||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
||||
}
|
||||
size_t update_decline_htlc__pack
|
||||
(const UpdateDeclineHtlc *message,
|
||||
uint8_t *out)
|
||||
{
|
||||
assert(message->base.descriptor == &update_decline_htlc__descriptor);
|
||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
||||
}
|
||||
size_t update_decline_htlc__pack_to_buffer
|
||||
(const UpdateDeclineHtlc *message,
|
||||
ProtobufCBuffer *buffer)
|
||||
{
|
||||
assert(message->base.descriptor == &update_decline_htlc__descriptor);
|
||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
||||
}
|
||||
UpdateDeclineHtlc *
|
||||
update_decline_htlc__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data)
|
||||
{
|
||||
return (UpdateDeclineHtlc *)
|
||||
protobuf_c_message_unpack (&update_decline_htlc__descriptor,
|
||||
allocator, len, data);
|
||||
}
|
||||
void update_decline_htlc__free_unpacked
|
||||
(UpdateDeclineHtlc *message,
|
||||
ProtobufCAllocator *allocator)
|
||||
{
|
||||
assert(message->base.descriptor == &update_decline_htlc__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void update_fulfill_htlc__init
|
||||
(UpdateFulfillHtlc *message)
|
||||
{
|
||||
@ -566,6 +566,49 @@ void update_fulfill_htlc__free_unpacked
|
||||
assert(message->base.descriptor == &update_fulfill_htlc__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void fail_reason__init
|
||||
(FailReason *message)
|
||||
{
|
||||
static FailReason init_value = FAIL_REASON__INIT;
|
||||
*message = init_value;
|
||||
}
|
||||
size_t fail_reason__get_packed_size
|
||||
(const FailReason *message)
|
||||
{
|
||||
assert(message->base.descriptor == &fail_reason__descriptor);
|
||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
||||
}
|
||||
size_t fail_reason__pack
|
||||
(const FailReason *message,
|
||||
uint8_t *out)
|
||||
{
|
||||
assert(message->base.descriptor == &fail_reason__descriptor);
|
||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
||||
}
|
||||
size_t fail_reason__pack_to_buffer
|
||||
(const FailReason *message,
|
||||
ProtobufCBuffer *buffer)
|
||||
{
|
||||
assert(message->base.descriptor == &fail_reason__descriptor);
|
||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
||||
}
|
||||
FailReason *
|
||||
fail_reason__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data)
|
||||
{
|
||||
return (FailReason *)
|
||||
protobuf_c_message_unpack (&fail_reason__descriptor,
|
||||
allocator, len, data);
|
||||
}
|
||||
void fail_reason__free_unpacked
|
||||
(FailReason *message,
|
||||
ProtobufCAllocator *allocator)
|
||||
{
|
||||
assert(message->base.descriptor == &fail_reason__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void update_fail_htlc__init
|
||||
(UpdateFailHtlc *message)
|
||||
{
|
||||
@ -609,133 +652,90 @@ void update_fail_htlc__free_unpacked
|
||||
assert(message->base.descriptor == &update_fail_htlc__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void update_accept__init
|
||||
(UpdateAccept *message)
|
||||
void update_commit__init
|
||||
(UpdateCommit *message)
|
||||
{
|
||||
static UpdateAccept init_value = UPDATE_ACCEPT__INIT;
|
||||
static UpdateCommit init_value = UPDATE_COMMIT__INIT;
|
||||
*message = init_value;
|
||||
}
|
||||
size_t update_accept__get_packed_size
|
||||
(const UpdateAccept *message)
|
||||
size_t update_commit__get_packed_size
|
||||
(const UpdateCommit *message)
|
||||
{
|
||||
assert(message->base.descriptor == &update_accept__descriptor);
|
||||
assert(message->base.descriptor == &update_commit__descriptor);
|
||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
||||
}
|
||||
size_t update_accept__pack
|
||||
(const UpdateAccept *message,
|
||||
size_t update_commit__pack
|
||||
(const UpdateCommit *message,
|
||||
uint8_t *out)
|
||||
{
|
||||
assert(message->base.descriptor == &update_accept__descriptor);
|
||||
assert(message->base.descriptor == &update_commit__descriptor);
|
||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
||||
}
|
||||
size_t update_accept__pack_to_buffer
|
||||
(const UpdateAccept *message,
|
||||
size_t update_commit__pack_to_buffer
|
||||
(const UpdateCommit *message,
|
||||
ProtobufCBuffer *buffer)
|
||||
{
|
||||
assert(message->base.descriptor == &update_accept__descriptor);
|
||||
assert(message->base.descriptor == &update_commit__descriptor);
|
||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
||||
}
|
||||
UpdateAccept *
|
||||
update_accept__unpack
|
||||
UpdateCommit *
|
||||
update_commit__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data)
|
||||
{
|
||||
return (UpdateAccept *)
|
||||
protobuf_c_message_unpack (&update_accept__descriptor,
|
||||
return (UpdateCommit *)
|
||||
protobuf_c_message_unpack (&update_commit__descriptor,
|
||||
allocator, len, data);
|
||||
}
|
||||
void update_accept__free_unpacked
|
||||
(UpdateAccept *message,
|
||||
void update_commit__free_unpacked
|
||||
(UpdateCommit *message,
|
||||
ProtobufCAllocator *allocator)
|
||||
{
|
||||
assert(message->base.descriptor == &update_accept__descriptor);
|
||||
assert(message->base.descriptor == &update_commit__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void update_signature__init
|
||||
(UpdateSignature *message)
|
||||
void update_revocation__init
|
||||
(UpdateRevocation *message)
|
||||
{
|
||||
static UpdateSignature init_value = UPDATE_SIGNATURE__INIT;
|
||||
static UpdateRevocation init_value = UPDATE_REVOCATION__INIT;
|
||||
*message = init_value;
|
||||
}
|
||||
size_t update_signature__get_packed_size
|
||||
(const UpdateSignature *message)
|
||||
size_t update_revocation__get_packed_size
|
||||
(const UpdateRevocation *message)
|
||||
{
|
||||
assert(message->base.descriptor == &update_signature__descriptor);
|
||||
assert(message->base.descriptor == &update_revocation__descriptor);
|
||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
||||
}
|
||||
size_t update_signature__pack
|
||||
(const UpdateSignature *message,
|
||||
size_t update_revocation__pack
|
||||
(const UpdateRevocation *message,
|
||||
uint8_t *out)
|
||||
{
|
||||
assert(message->base.descriptor == &update_signature__descriptor);
|
||||
assert(message->base.descriptor == &update_revocation__descriptor);
|
||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
||||
}
|
||||
size_t update_signature__pack_to_buffer
|
||||
(const UpdateSignature *message,
|
||||
size_t update_revocation__pack_to_buffer
|
||||
(const UpdateRevocation *message,
|
||||
ProtobufCBuffer *buffer)
|
||||
{
|
||||
assert(message->base.descriptor == &update_signature__descriptor);
|
||||
assert(message->base.descriptor == &update_revocation__descriptor);
|
||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
||||
}
|
||||
UpdateSignature *
|
||||
update_signature__unpack
|
||||
UpdateRevocation *
|
||||
update_revocation__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data)
|
||||
{
|
||||
return (UpdateSignature *)
|
||||
protobuf_c_message_unpack (&update_signature__descriptor,
|
||||
return (UpdateRevocation *)
|
||||
protobuf_c_message_unpack (&update_revocation__descriptor,
|
||||
allocator, len, data);
|
||||
}
|
||||
void update_signature__free_unpacked
|
||||
(UpdateSignature *message,
|
||||
void update_revocation__free_unpacked
|
||||
(UpdateRevocation *message,
|
||||
ProtobufCAllocator *allocator)
|
||||
{
|
||||
assert(message->base.descriptor == &update_signature__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void update_complete__init
|
||||
(UpdateComplete *message)
|
||||
{
|
||||
static UpdateComplete init_value = UPDATE_COMPLETE__INIT;
|
||||
*message = init_value;
|
||||
}
|
||||
size_t update_complete__get_packed_size
|
||||
(const UpdateComplete *message)
|
||||
{
|
||||
assert(message->base.descriptor == &update_complete__descriptor);
|
||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
||||
}
|
||||
size_t update_complete__pack
|
||||
(const UpdateComplete *message,
|
||||
uint8_t *out)
|
||||
{
|
||||
assert(message->base.descriptor == &update_complete__descriptor);
|
||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
||||
}
|
||||
size_t update_complete__pack_to_buffer
|
||||
(const UpdateComplete *message,
|
||||
ProtobufCBuffer *buffer)
|
||||
{
|
||||
assert(message->base.descriptor == &update_complete__descriptor);
|
||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
||||
}
|
||||
UpdateComplete *
|
||||
update_complete__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data)
|
||||
{
|
||||
return (UpdateComplete *)
|
||||
protobuf_c_message_unpack (&update_complete__descriptor,
|
||||
allocator, len, data);
|
||||
}
|
||||
void update_complete__free_unpacked
|
||||
(UpdateComplete *message,
|
||||
ProtobufCAllocator *allocator)
|
||||
{
|
||||
assert(message->base.descriptor == &update_complete__descriptor);
|
||||
assert(message->base.descriptor == &update_revocation__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void close_clearing__init
|
||||
@ -1620,16 +1620,54 @@ const ProtobufCMessageDescriptor open_complete__descriptor =
|
||||
(ProtobufCMessageInit) open_complete__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor update_add_htlc__field_descriptors[4] =
|
||||
static const ProtobufCFieldDescriptor routing__field_descriptors[1] =
|
||||
{
|
||||
{
|
||||
"revocation_hash",
|
||||
"info",
|
||||
1,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
PROTOBUF_C_TYPE_BYTES,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(UpdateAddHtlc, revocation_hash),
|
||||
&sha256_hash__descriptor,
|
||||
offsetof(Routing, info),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned routing__field_indices_by_name[] = {
|
||||
0, /* field[0] = info */
|
||||
};
|
||||
static const ProtobufCIntRange routing__number_ranges[1 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 0, 1 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor routing__descriptor =
|
||||
{
|
||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||
"routing",
|
||||
"Routing",
|
||||
"Routing",
|
||||
"",
|
||||
sizeof(Routing),
|
||||
1,
|
||||
routing__field_descriptors,
|
||||
routing__field_indices_by_name,
|
||||
1, routing__number_ranges,
|
||||
(ProtobufCMessageInit) routing__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor update_add_htlc__field_descriptors[5] =
|
||||
{
|
||||
{
|
||||
"id",
|
||||
1,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_UINT64,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(UpdateAddHtlc, id),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
@ -1670,17 +1708,30 @@ static const ProtobufCFieldDescriptor update_add_htlc__field_descriptors[4] =
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"route",
|
||||
5,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(UpdateAddHtlc, route),
|
||||
&routing__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned update_add_htlc__field_indices_by_name[] = {
|
||||
1, /* field[1] = amount_msat */
|
||||
3, /* field[3] = expiry */
|
||||
0, /* field[0] = id */
|
||||
2, /* field[2] = r_hash */
|
||||
0, /* field[0] = revocation_hash */
|
||||
4, /* field[4] = route */
|
||||
};
|
||||
static const ProtobufCIntRange update_add_htlc__number_ranges[1 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 0, 4 }
|
||||
{ 0, 5 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor update_add_htlc__descriptor =
|
||||
{
|
||||
@ -1690,74 +1741,23 @@ const ProtobufCMessageDescriptor update_add_htlc__descriptor =
|
||||
"UpdateAddHtlc",
|
||||
"",
|
||||
sizeof(UpdateAddHtlc),
|
||||
4,
|
||||
5,
|
||||
update_add_htlc__field_descriptors,
|
||||
update_add_htlc__field_indices_by_name,
|
||||
1, update_add_htlc__number_ranges,
|
||||
(ProtobufCMessageInit) update_add_htlc__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor update_decline_htlc__field_descriptors[2] =
|
||||
{
|
||||
{
|
||||
"insufficient_funds",
|
||||
1,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
offsetof(UpdateDeclineHtlc, reason_case),
|
||||
offsetof(UpdateDeclineHtlc, insufficient_funds),
|
||||
&funding__descriptor,
|
||||
NULL,
|
||||
0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"cannot_route",
|
||||
2,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_BOOL,
|
||||
offsetof(UpdateDeclineHtlc, reason_case),
|
||||
offsetof(UpdateDeclineHtlc, cannot_route),
|
||||
NULL,
|
||||
NULL,
|
||||
0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned update_decline_htlc__field_indices_by_name[] = {
|
||||
1, /* field[1] = cannot_route */
|
||||
0, /* field[0] = insufficient_funds */
|
||||
};
|
||||
static const ProtobufCIntRange update_decline_htlc__number_ranges[1 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 0, 2 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor update_decline_htlc__descriptor =
|
||||
{
|
||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||
"update_decline_htlc",
|
||||
"UpdateDeclineHtlc",
|
||||
"UpdateDeclineHtlc",
|
||||
"",
|
||||
sizeof(UpdateDeclineHtlc),
|
||||
2,
|
||||
update_decline_htlc__field_descriptors,
|
||||
update_decline_htlc__field_indices_by_name,
|
||||
1, update_decline_htlc__number_ranges,
|
||||
(ProtobufCMessageInit) update_decline_htlc__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor update_fulfill_htlc__field_descriptors[2] =
|
||||
{
|
||||
{
|
||||
"revocation_hash",
|
||||
"id",
|
||||
1,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
PROTOBUF_C_TYPE_UINT64,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(UpdateFulfillHtlc, revocation_hash),
|
||||
&sha256_hash__descriptor,
|
||||
offsetof(UpdateFulfillHtlc, id),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
@ -1776,8 +1776,8 @@ static const ProtobufCFieldDescriptor update_fulfill_htlc__field_descriptors[2]
|
||||
},
|
||||
};
|
||||
static const unsigned update_fulfill_htlc__field_indices_by_name[] = {
|
||||
0, /* field[0] = id */
|
||||
1, /* field[1] = r */
|
||||
0, /* field[0] = revocation_hash */
|
||||
};
|
||||
static const ProtobufCIntRange update_fulfill_htlc__number_ranges[1 + 1] =
|
||||
{
|
||||
@ -1799,36 +1799,74 @@ const ProtobufCMessageDescriptor update_fulfill_htlc__descriptor =
|
||||
(ProtobufCMessageInit) update_fulfill_htlc__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor fail_reason__field_descriptors[1] =
|
||||
{
|
||||
{
|
||||
"info",
|
||||
1,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_BYTES,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(FailReason, info),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned fail_reason__field_indices_by_name[] = {
|
||||
0, /* field[0] = info */
|
||||
};
|
||||
static const ProtobufCIntRange fail_reason__number_ranges[1 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 0, 1 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor fail_reason__descriptor =
|
||||
{
|
||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||
"fail_reason",
|
||||
"FailReason",
|
||||
"FailReason",
|
||||
"",
|
||||
sizeof(FailReason),
|
||||
1,
|
||||
fail_reason__field_descriptors,
|
||||
fail_reason__field_indices_by_name,
|
||||
1, fail_reason__number_ranges,
|
||||
(ProtobufCMessageInit) fail_reason__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor update_fail_htlc__field_descriptors[2] =
|
||||
{
|
||||
{
|
||||
"revocation_hash",
|
||||
"id",
|
||||
1,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
PROTOBUF_C_TYPE_UINT64,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(UpdateFailHtlc, revocation_hash),
|
||||
&sha256_hash__descriptor,
|
||||
offsetof(UpdateFailHtlc, id),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"r_hash",
|
||||
"reason",
|
||||
2,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(UpdateFailHtlc, r_hash),
|
||||
&sha256_hash__descriptor,
|
||||
offsetof(UpdateFailHtlc, reason),
|
||||
&fail_reason__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned update_fail_htlc__field_indices_by_name[] = {
|
||||
1, /* field[1] = r_hash */
|
||||
0, /* field[0] = revocation_hash */
|
||||
0, /* field[0] = id */
|
||||
1, /* field[1] = reason */
|
||||
};
|
||||
static const ProtobufCIntRange update_fail_htlc__number_ranges[1 + 1] =
|
||||
{
|
||||
@ -1850,7 +1888,7 @@ const ProtobufCMessageDescriptor update_fail_htlc__descriptor =
|
||||
(ProtobufCMessageInit) update_fail_htlc__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor update_accept__field_descriptors[2] =
|
||||
static const ProtobufCFieldDescriptor update_commit__field_descriptors[1] =
|
||||
{
|
||||
{
|
||||
"sig",
|
||||
@ -1858,136 +1896,85 @@ static const ProtobufCFieldDescriptor update_accept__field_descriptors[2] =
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(UpdateAccept, sig),
|
||||
offsetof(UpdateCommit, sig),
|
||||
&signature__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"revocation_hash",
|
||||
2,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(UpdateAccept, revocation_hash),
|
||||
&sha256_hash__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned update_accept__field_indices_by_name[] = {
|
||||
1, /* field[1] = revocation_hash */
|
||||
static const unsigned update_commit__field_indices_by_name[] = {
|
||||
0, /* field[0] = sig */
|
||||
};
|
||||
static const ProtobufCIntRange update_accept__number_ranges[1 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 0, 2 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor update_accept__descriptor =
|
||||
{
|
||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||
"update_accept",
|
||||
"UpdateAccept",
|
||||
"UpdateAccept",
|
||||
"",
|
||||
sizeof(UpdateAccept),
|
||||
2,
|
||||
update_accept__field_descriptors,
|
||||
update_accept__field_indices_by_name,
|
||||
1, update_accept__number_ranges,
|
||||
(ProtobufCMessageInit) update_accept__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor update_signature__field_descriptors[2] =
|
||||
{
|
||||
{
|
||||
"sig",
|
||||
1,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(UpdateSignature, sig),
|
||||
&signature__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"revocation_preimage",
|
||||
2,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(UpdateSignature, revocation_preimage),
|
||||
&sha256_hash__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned update_signature__field_indices_by_name[] = {
|
||||
1, /* field[1] = revocation_preimage */
|
||||
0, /* field[0] = sig */
|
||||
};
|
||||
static const ProtobufCIntRange update_signature__number_ranges[1 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 0, 2 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor update_signature__descriptor =
|
||||
{
|
||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||
"update_signature",
|
||||
"UpdateSignature",
|
||||
"UpdateSignature",
|
||||
"",
|
||||
sizeof(UpdateSignature),
|
||||
2,
|
||||
update_signature__field_descriptors,
|
||||
update_signature__field_indices_by_name,
|
||||
1, update_signature__number_ranges,
|
||||
(ProtobufCMessageInit) update_signature__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor update_complete__field_descriptors[1] =
|
||||
{
|
||||
{
|
||||
"revocation_preimage",
|
||||
1,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(UpdateComplete, revocation_preimage),
|
||||
&sha256_hash__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned update_complete__field_indices_by_name[] = {
|
||||
0, /* field[0] = revocation_preimage */
|
||||
};
|
||||
static const ProtobufCIntRange update_complete__number_ranges[1 + 1] =
|
||||
static const ProtobufCIntRange update_commit__number_ranges[1 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 0, 1 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor update_complete__descriptor =
|
||||
const ProtobufCMessageDescriptor update_commit__descriptor =
|
||||
{
|
||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||
"update_complete",
|
||||
"UpdateComplete",
|
||||
"UpdateComplete",
|
||||
"update_commit",
|
||||
"UpdateCommit",
|
||||
"UpdateCommit",
|
||||
"",
|
||||
sizeof(UpdateComplete),
|
||||
sizeof(UpdateCommit),
|
||||
1,
|
||||
update_complete__field_descriptors,
|
||||
update_complete__field_indices_by_name,
|
||||
1, update_complete__number_ranges,
|
||||
(ProtobufCMessageInit) update_complete__init,
|
||||
update_commit__field_descriptors,
|
||||
update_commit__field_indices_by_name,
|
||||
1, update_commit__number_ranges,
|
||||
(ProtobufCMessageInit) update_commit__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor update_revocation__field_descriptors[2] =
|
||||
{
|
||||
{
|
||||
"revocation_preimage",
|
||||
1,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(UpdateRevocation, revocation_preimage),
|
||||
&sha256_hash__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"next_revocation_hash",
|
||||
2,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(UpdateRevocation, next_revocation_hash),
|
||||
&sha256_hash__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned update_revocation__field_indices_by_name[] = {
|
||||
1, /* field[1] = next_revocation_hash */
|
||||
0, /* field[0] = revocation_preimage */
|
||||
};
|
||||
static const ProtobufCIntRange update_revocation__number_ranges[1 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 0, 2 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor update_revocation__descriptor =
|
||||
{
|
||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||
"update_revocation",
|
||||
"UpdateRevocation",
|
||||
"UpdateRevocation",
|
||||
"",
|
||||
sizeof(UpdateRevocation),
|
||||
2,
|
||||
update_revocation__field_descriptors,
|
||||
update_revocation__field_indices_by_name,
|
||||
1, update_revocation__number_ranges,
|
||||
(ProtobufCMessageInit) update_revocation__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
#define close_clearing__field_descriptors NULL
|
||||
@ -2097,7 +2084,7 @@ const ProtobufCMessageDescriptor error__descriptor =
|
||||
(ProtobufCMessageInit) error__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor pkt__field_descriptors[15] =
|
||||
static const ProtobufCFieldDescriptor pkt__field_descriptors[13] =
|
||||
{
|
||||
{
|
||||
"update_add_htlc",
|
||||
@ -2111,57 +2098,9 @@ static const ProtobufCFieldDescriptor pkt__field_descriptors[15] =
|
||||
0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"update_accept",
|
||||
3,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
offsetof(Pkt, pkt_case),
|
||||
offsetof(Pkt, update_accept),
|
||||
&update_accept__descriptor,
|
||||
NULL,
|
||||
0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"update_signature",
|
||||
4,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
offsetof(Pkt, pkt_case),
|
||||
offsetof(Pkt, update_signature),
|
||||
&update_signature__descriptor,
|
||||
NULL,
|
||||
0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"update_complete",
|
||||
5,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
offsetof(Pkt, pkt_case),
|
||||
offsetof(Pkt, update_complete),
|
||||
&update_complete__descriptor,
|
||||
NULL,
|
||||
0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"update_decline_htlc",
|
||||
6,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
offsetof(Pkt, pkt_case),
|
||||
offsetof(Pkt, update_decline_htlc),
|
||||
&update_decline_htlc__descriptor,
|
||||
NULL,
|
||||
0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"update_fulfill_htlc",
|
||||
7,
|
||||
3,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
offsetof(Pkt, pkt_case),
|
||||
@ -2173,7 +2112,7 @@ static const ProtobufCFieldDescriptor pkt__field_descriptors[15] =
|
||||
},
|
||||
{
|
||||
"update_fail_htlc",
|
||||
9,
|
||||
4,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
offsetof(Pkt, pkt_case),
|
||||
@ -2183,6 +2122,30 @@ static const ProtobufCFieldDescriptor pkt__field_descriptors[15] =
|
||||
0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"update_commit",
|
||||
5,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
offsetof(Pkt, pkt_case),
|
||||
offsetof(Pkt, update_commit),
|
||||
&update_commit__descriptor,
|
||||
NULL,
|
||||
0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"update_revocation",
|
||||
6,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
offsetof(Pkt, pkt_case),
|
||||
offsetof(Pkt, update_revocation),
|
||||
&update_revocation__descriptor,
|
||||
NULL,
|
||||
0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"open",
|
||||
20,
|
||||
@ -2281,31 +2244,28 @@ static const ProtobufCFieldDescriptor pkt__field_descriptors[15] =
|
||||
},
|
||||
};
|
||||
static const unsigned pkt__field_indices_by_name[] = {
|
||||
14, /* field[14] = auth */
|
||||
11, /* field[11] = close_clearing */
|
||||
12, /* field[12] = close_signature */
|
||||
13, /* field[13] = error */
|
||||
7, /* field[7] = open */
|
||||
8, /* field[8] = open_anchor */
|
||||
9, /* field[9] = open_commit_sig */
|
||||
10, /* field[10] = open_complete */
|
||||
1, /* field[1] = update_accept */
|
||||
12, /* field[12] = auth */
|
||||
9, /* field[9] = close_clearing */
|
||||
10, /* field[10] = close_signature */
|
||||
11, /* field[11] = error */
|
||||
5, /* field[5] = open */
|
||||
6, /* field[6] = open_anchor */
|
||||
7, /* field[7] = open_commit_sig */
|
||||
8, /* field[8] = open_complete */
|
||||
0, /* field[0] = update_add_htlc */
|
||||
3, /* field[3] = update_complete */
|
||||
4, /* field[4] = update_decline_htlc */
|
||||
6, /* field[6] = update_fail_htlc */
|
||||
5, /* field[5] = update_fulfill_htlc */
|
||||
2, /* field[2] = update_signature */
|
||||
3, /* field[3] = update_commit */
|
||||
2, /* field[2] = update_fail_htlc */
|
||||
1, /* field[1] = update_fulfill_htlc */
|
||||
4, /* field[4] = update_revocation */
|
||||
};
|
||||
static const ProtobufCIntRange pkt__number_ranges[6 + 1] =
|
||||
static const ProtobufCIntRange pkt__number_ranges[5 + 1] =
|
||||
{
|
||||
{ 2, 0 },
|
||||
{ 9, 6 },
|
||||
{ 20, 7 },
|
||||
{ 30, 11 },
|
||||
{ 40, 13 },
|
||||
{ 50, 14 },
|
||||
{ 0, 15 }
|
||||
{ 20, 5 },
|
||||
{ 30, 9 },
|
||||
{ 40, 11 },
|
||||
{ 50, 12 },
|
||||
{ 0, 13 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor pkt__descriptor =
|
||||
{
|
||||
@ -2315,10 +2275,10 @@ const ProtobufCMessageDescriptor pkt__descriptor =
|
||||
"Pkt",
|
||||
"",
|
||||
sizeof(Pkt),
|
||||
15,
|
||||
13,
|
||||
pkt__field_descriptors,
|
||||
pkt__field_indices_by_name,
|
||||
6, pkt__number_ranges,
|
||||
5, pkt__number_ranges,
|
||||
(ProtobufCMessageInit) pkt__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
|
303
lightning.pb-c.h
303
lightning.pb-c.h
@ -25,13 +25,13 @@ typedef struct _OpenChannel OpenChannel;
|
||||
typedef struct _OpenAnchor OpenAnchor;
|
||||
typedef struct _OpenCommitSig OpenCommitSig;
|
||||
typedef struct _OpenComplete OpenComplete;
|
||||
typedef struct _Routing Routing;
|
||||
typedef struct _UpdateAddHtlc UpdateAddHtlc;
|
||||
typedef struct _UpdateDeclineHtlc UpdateDeclineHtlc;
|
||||
typedef struct _UpdateFulfillHtlc UpdateFulfillHtlc;
|
||||
typedef struct _FailReason FailReason;
|
||||
typedef struct _UpdateFailHtlc UpdateFailHtlc;
|
||||
typedef struct _UpdateAccept UpdateAccept;
|
||||
typedef struct _UpdateSignature UpdateSignature;
|
||||
typedef struct _UpdateComplete UpdateComplete;
|
||||
typedef struct _UpdateCommit UpdateCommit;
|
||||
typedef struct _UpdateRevocation UpdateRevocation;
|
||||
typedef struct _CloseClearing CloseClearing;
|
||||
typedef struct _CloseSignature CloseSignature;
|
||||
typedef struct _Error Error;
|
||||
@ -267,6 +267,19 @@ struct _OpenComplete
|
||||
, NULL }
|
||||
|
||||
|
||||
/*
|
||||
* FIXME: Routing information.
|
||||
*/
|
||||
struct _Routing
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
ProtobufCBinaryData info;
|
||||
};
|
||||
#define ROUTING__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&routing__descriptor) \
|
||||
, {0,NULL} }
|
||||
|
||||
|
||||
/*
|
||||
* Start a new commitment tx to add an HTLC me -> you.
|
||||
*/
|
||||
@ -274,9 +287,9 @@ struct _UpdateAddHtlc
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
/*
|
||||
* Hash for which I will supply preimage to revoke this commitment tx.
|
||||
* Unique identifier for this HTLC.
|
||||
*/
|
||||
Sha256Hash *revocation_hash;
|
||||
uint64_t id;
|
||||
/*
|
||||
* Amount for htlc (millisatoshi)
|
||||
*/
|
||||
@ -288,37 +301,15 @@ struct _UpdateAddHtlc
|
||||
/*
|
||||
* Time at which HTLC expires (absolute)
|
||||
*/
|
||||
/*
|
||||
* FIXME: Routing information.
|
||||
*/
|
||||
Locktime *expiry;
|
||||
/*
|
||||
* Onion-wrapped routing information.
|
||||
*/
|
||||
Routing *route;
|
||||
};
|
||||
#define UPDATE_ADD_HTLC__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&update_add_htlc__descriptor) \
|
||||
, NULL, 0, NULL, NULL }
|
||||
|
||||
|
||||
typedef enum {
|
||||
UPDATE_DECLINE_HTLC__REASON__NOT_SET = 0,
|
||||
UPDATE_DECLINE_HTLC__REASON_INSUFFICIENT_FUNDS = 1,
|
||||
UPDATE_DECLINE_HTLC__REASON_CANNOT_ROUTE = 2,
|
||||
} UpdateDeclineHtlc__ReasonCase;
|
||||
|
||||
/*
|
||||
* We can't do this HTLC, sorry (instead of update_accept)
|
||||
*/
|
||||
struct _UpdateDeclineHtlc
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
UpdateDeclineHtlc__ReasonCase reason_case;
|
||||
union {
|
||||
Funding *insufficient_funds;
|
||||
protobuf_c_boolean cannot_route;
|
||||
};
|
||||
};
|
||||
#define UPDATE_DECLINE_HTLC__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&update_decline_htlc__descriptor) \
|
||||
, UPDATE_DECLINE_HTLC__REASON__NOT_SET, {} }
|
||||
, 0, 0, NULL, NULL, NULL }
|
||||
|
||||
|
||||
/*
|
||||
@ -328,9 +319,9 @@ struct _UpdateFulfillHtlc
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
/*
|
||||
* Hash for which I will supply preimage to revoke this commitment tx.
|
||||
* Which HTLC
|
||||
*/
|
||||
Sha256Hash *revocation_hash;
|
||||
uint64_t id;
|
||||
/*
|
||||
* HTLC R value.
|
||||
*/
|
||||
@ -338,83 +329,73 @@ struct _UpdateFulfillHtlc
|
||||
};
|
||||
#define UPDATE_FULFILL_HTLC__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&update_fulfill_htlc__descriptor) \
|
||||
, NULL, NULL }
|
||||
, 0, NULL }
|
||||
|
||||
|
||||
/*
|
||||
* Remove your HTLC: routing has failed upstream, we didn't like it, or timeout.
|
||||
* FIXME: Failure information.
|
||||
*/
|
||||
struct _FailReason
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
ProtobufCBinaryData info;
|
||||
};
|
||||
#define FAIL_REASON__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&fail_reason__descriptor) \
|
||||
, {0,NULL} }
|
||||
|
||||
|
||||
struct _UpdateFailHtlc
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
/*
|
||||
* Hash for which I will supply preimage to revoke this commitment tx.
|
||||
* Which HTLC
|
||||
*/
|
||||
Sha256Hash *revocation_hash;
|
||||
uint64_t id;
|
||||
/*
|
||||
* Hash for HTLC R value.
|
||||
* Reason for failure (for relay to initial node)
|
||||
*/
|
||||
Sha256Hash *r_hash;
|
||||
FailReason *reason;
|
||||
};
|
||||
#define UPDATE_FAIL_HTLC__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&update_fail_htlc__descriptor) \
|
||||
, NULL, NULL }
|
||||
, 0, NULL }
|
||||
|
||||
|
||||
/*
|
||||
* OK, I accept that update; here's your signature.
|
||||
* Commit all the staged HTLCs.
|
||||
*/
|
||||
struct _UpdateAccept
|
||||
struct _UpdateCommit
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
/*
|
||||
* Signature for your new commitment tx.
|
||||
*/
|
||||
Signature *sig;
|
||||
/*
|
||||
* Hash for which I will supply preimage to revoke this new commit tx.
|
||||
*/
|
||||
Sha256Hash *revocation_hash;
|
||||
};
|
||||
#define UPDATE_ACCEPT__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&update_accept__descriptor) \
|
||||
, NULL, NULL }
|
||||
|
||||
|
||||
/*
|
||||
* Thanks for accepting, here's my last bit.
|
||||
*/
|
||||
struct _UpdateSignature
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
/*
|
||||
* Signature for your new commitment tx.
|
||||
*/
|
||||
Signature *sig;
|
||||
/*
|
||||
* Hash preimage which revokes old commitment tx.
|
||||
*/
|
||||
Sha256Hash *revocation_preimage;
|
||||
};
|
||||
#define UPDATE_SIGNATURE__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&update_signature__descriptor) \
|
||||
, NULL, NULL }
|
||||
#define UPDATE_COMMIT__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&update_commit__descriptor) \
|
||||
, NULL }
|
||||
|
||||
|
||||
/*
|
||||
* Complete the update.
|
||||
*/
|
||||
struct _UpdateComplete
|
||||
struct _UpdateRevocation
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
/*
|
||||
* Hash preimage which revokes old commitment tx.
|
||||
*/
|
||||
Sha256Hash *revocation_preimage;
|
||||
/*
|
||||
* Revocation hash for my next commit transaction
|
||||
*/
|
||||
Sha256Hash *next_revocation_hash;
|
||||
};
|
||||
#define UPDATE_COMPLETE__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&update_complete__descriptor) \
|
||||
, NULL }
|
||||
#define UPDATE_REVOCATION__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&update_revocation__descriptor) \
|
||||
, NULL, NULL }
|
||||
|
||||
|
||||
/*
|
||||
@ -467,12 +448,10 @@ typedef enum {
|
||||
PKT__PKT_OPEN_COMMIT_SIG = 22,
|
||||
PKT__PKT_OPEN_COMPLETE = 23,
|
||||
PKT__PKT_UPDATE_ADD_HTLC = 2,
|
||||
PKT__PKT_UPDATE_ACCEPT = 3,
|
||||
PKT__PKT_UPDATE_SIGNATURE = 4,
|
||||
PKT__PKT_UPDATE_COMPLETE = 5,
|
||||
PKT__PKT_UPDATE_DECLINE_HTLC = 6,
|
||||
PKT__PKT_UPDATE_FULFILL_HTLC = 7,
|
||||
PKT__PKT_UPDATE_FAIL_HTLC = 9,
|
||||
PKT__PKT_UPDATE_FULFILL_HTLC = 3,
|
||||
PKT__PKT_UPDATE_FAIL_HTLC = 4,
|
||||
PKT__PKT_UPDATE_COMMIT = 5,
|
||||
PKT__PKT_UPDATE_REVOCATION = 6,
|
||||
PKT__PKT_CLOSE_CLEARING = 30,
|
||||
PKT__PKT_CLOSE_SIGNATURE = 31,
|
||||
PKT__PKT_ERROR = 40,
|
||||
@ -501,12 +480,10 @@ struct _Pkt
|
||||
* Updating (most common)
|
||||
*/
|
||||
UpdateAddHtlc *update_add_htlc;
|
||||
UpdateAccept *update_accept;
|
||||
UpdateSignature *update_signature;
|
||||
UpdateComplete *update_complete;
|
||||
UpdateDeclineHtlc *update_decline_htlc;
|
||||
UpdateFulfillHtlc *update_fulfill_htlc;
|
||||
UpdateFailHtlc *update_fail_htlc;
|
||||
UpdateCommit *update_commit;
|
||||
UpdateRevocation *update_revocation;
|
||||
/*
|
||||
* Closing
|
||||
*/
|
||||
@ -713,6 +690,25 @@ OpenComplete *
|
||||
void open_complete__free_unpacked
|
||||
(OpenComplete *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* Routing methods */
|
||||
void routing__init
|
||||
(Routing *message);
|
||||
size_t routing__get_packed_size
|
||||
(const Routing *message);
|
||||
size_t routing__pack
|
||||
(const Routing *message,
|
||||
uint8_t *out);
|
||||
size_t routing__pack_to_buffer
|
||||
(const Routing *message,
|
||||
ProtobufCBuffer *buffer);
|
||||
Routing *
|
||||
routing__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data);
|
||||
void routing__free_unpacked
|
||||
(Routing *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* UpdateAddHtlc methods */
|
||||
void update_add_htlc__init
|
||||
(UpdateAddHtlc *message);
|
||||
@ -732,25 +728,6 @@ UpdateAddHtlc *
|
||||
void update_add_htlc__free_unpacked
|
||||
(UpdateAddHtlc *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* UpdateDeclineHtlc methods */
|
||||
void update_decline_htlc__init
|
||||
(UpdateDeclineHtlc *message);
|
||||
size_t update_decline_htlc__get_packed_size
|
||||
(const UpdateDeclineHtlc *message);
|
||||
size_t update_decline_htlc__pack
|
||||
(const UpdateDeclineHtlc *message,
|
||||
uint8_t *out);
|
||||
size_t update_decline_htlc__pack_to_buffer
|
||||
(const UpdateDeclineHtlc *message,
|
||||
ProtobufCBuffer *buffer);
|
||||
UpdateDeclineHtlc *
|
||||
update_decline_htlc__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data);
|
||||
void update_decline_htlc__free_unpacked
|
||||
(UpdateDeclineHtlc *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* UpdateFulfillHtlc methods */
|
||||
void update_fulfill_htlc__init
|
||||
(UpdateFulfillHtlc *message);
|
||||
@ -770,6 +747,25 @@ UpdateFulfillHtlc *
|
||||
void update_fulfill_htlc__free_unpacked
|
||||
(UpdateFulfillHtlc *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* FailReason methods */
|
||||
void fail_reason__init
|
||||
(FailReason *message);
|
||||
size_t fail_reason__get_packed_size
|
||||
(const FailReason *message);
|
||||
size_t fail_reason__pack
|
||||
(const FailReason *message,
|
||||
uint8_t *out);
|
||||
size_t fail_reason__pack_to_buffer
|
||||
(const FailReason *message,
|
||||
ProtobufCBuffer *buffer);
|
||||
FailReason *
|
||||
fail_reason__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data);
|
||||
void fail_reason__free_unpacked
|
||||
(FailReason *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* UpdateFailHtlc methods */
|
||||
void update_fail_htlc__init
|
||||
(UpdateFailHtlc *message);
|
||||
@ -789,62 +785,43 @@ UpdateFailHtlc *
|
||||
void update_fail_htlc__free_unpacked
|
||||
(UpdateFailHtlc *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* UpdateAccept methods */
|
||||
void update_accept__init
|
||||
(UpdateAccept *message);
|
||||
size_t update_accept__get_packed_size
|
||||
(const UpdateAccept *message);
|
||||
size_t update_accept__pack
|
||||
(const UpdateAccept *message,
|
||||
/* UpdateCommit methods */
|
||||
void update_commit__init
|
||||
(UpdateCommit *message);
|
||||
size_t update_commit__get_packed_size
|
||||
(const UpdateCommit *message);
|
||||
size_t update_commit__pack
|
||||
(const UpdateCommit *message,
|
||||
uint8_t *out);
|
||||
size_t update_accept__pack_to_buffer
|
||||
(const UpdateAccept *message,
|
||||
size_t update_commit__pack_to_buffer
|
||||
(const UpdateCommit *message,
|
||||
ProtobufCBuffer *buffer);
|
||||
UpdateAccept *
|
||||
update_accept__unpack
|
||||
UpdateCommit *
|
||||
update_commit__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data);
|
||||
void update_accept__free_unpacked
|
||||
(UpdateAccept *message,
|
||||
void update_commit__free_unpacked
|
||||
(UpdateCommit *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* UpdateSignature methods */
|
||||
void update_signature__init
|
||||
(UpdateSignature *message);
|
||||
size_t update_signature__get_packed_size
|
||||
(const UpdateSignature *message);
|
||||
size_t update_signature__pack
|
||||
(const UpdateSignature *message,
|
||||
/* UpdateRevocation methods */
|
||||
void update_revocation__init
|
||||
(UpdateRevocation *message);
|
||||
size_t update_revocation__get_packed_size
|
||||
(const UpdateRevocation *message);
|
||||
size_t update_revocation__pack
|
||||
(const UpdateRevocation *message,
|
||||
uint8_t *out);
|
||||
size_t update_signature__pack_to_buffer
|
||||
(const UpdateSignature *message,
|
||||
size_t update_revocation__pack_to_buffer
|
||||
(const UpdateRevocation *message,
|
||||
ProtobufCBuffer *buffer);
|
||||
UpdateSignature *
|
||||
update_signature__unpack
|
||||
UpdateRevocation *
|
||||
update_revocation__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data);
|
||||
void update_signature__free_unpacked
|
||||
(UpdateSignature *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* UpdateComplete methods */
|
||||
void update_complete__init
|
||||
(UpdateComplete *message);
|
||||
size_t update_complete__get_packed_size
|
||||
(const UpdateComplete *message);
|
||||
size_t update_complete__pack
|
||||
(const UpdateComplete *message,
|
||||
uint8_t *out);
|
||||
size_t update_complete__pack_to_buffer
|
||||
(const UpdateComplete *message,
|
||||
ProtobufCBuffer *buffer);
|
||||
UpdateComplete *
|
||||
update_complete__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data);
|
||||
void update_complete__free_unpacked
|
||||
(UpdateComplete *message,
|
||||
void update_revocation__free_unpacked
|
||||
(UpdateRevocation *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* CloseClearing methods */
|
||||
void close_clearing__init
|
||||
@ -954,26 +931,26 @@ typedef void (*OpenCommitSig_Closure)
|
||||
typedef void (*OpenComplete_Closure)
|
||||
(const OpenComplete *message,
|
||||
void *closure_data);
|
||||
typedef void (*Routing_Closure)
|
||||
(const Routing *message,
|
||||
void *closure_data);
|
||||
typedef void (*UpdateAddHtlc_Closure)
|
||||
(const UpdateAddHtlc *message,
|
||||
void *closure_data);
|
||||
typedef void (*UpdateDeclineHtlc_Closure)
|
||||
(const UpdateDeclineHtlc *message,
|
||||
void *closure_data);
|
||||
typedef void (*UpdateFulfillHtlc_Closure)
|
||||
(const UpdateFulfillHtlc *message,
|
||||
void *closure_data);
|
||||
typedef void (*FailReason_Closure)
|
||||
(const FailReason *message,
|
||||
void *closure_data);
|
||||
typedef void (*UpdateFailHtlc_Closure)
|
||||
(const UpdateFailHtlc *message,
|
||||
void *closure_data);
|
||||
typedef void (*UpdateAccept_Closure)
|
||||
(const UpdateAccept *message,
|
||||
typedef void (*UpdateCommit_Closure)
|
||||
(const UpdateCommit *message,
|
||||
void *closure_data);
|
||||
typedef void (*UpdateSignature_Closure)
|
||||
(const UpdateSignature *message,
|
||||
void *closure_data);
|
||||
typedef void (*UpdateComplete_Closure)
|
||||
(const UpdateComplete *message,
|
||||
typedef void (*UpdateRevocation_Closure)
|
||||
(const UpdateRevocation *message,
|
||||
void *closure_data);
|
||||
typedef void (*CloseClearing_Closure)
|
||||
(const CloseClearing *message,
|
||||
@ -1004,13 +981,13 @@ extern const ProtobufCEnumDescriptor open_channel__anchor_offer__descriptor;
|
||||
extern const ProtobufCMessageDescriptor open_anchor__descriptor;
|
||||
extern const ProtobufCMessageDescriptor open_commit_sig__descriptor;
|
||||
extern const ProtobufCMessageDescriptor open_complete__descriptor;
|
||||
extern const ProtobufCMessageDescriptor routing__descriptor;
|
||||
extern const ProtobufCMessageDescriptor update_add_htlc__descriptor;
|
||||
extern const ProtobufCMessageDescriptor update_decline_htlc__descriptor;
|
||||
extern const ProtobufCMessageDescriptor update_fulfill_htlc__descriptor;
|
||||
extern const ProtobufCMessageDescriptor fail_reason__descriptor;
|
||||
extern const ProtobufCMessageDescriptor update_fail_htlc__descriptor;
|
||||
extern const ProtobufCMessageDescriptor update_accept__descriptor;
|
||||
extern const ProtobufCMessageDescriptor update_signature__descriptor;
|
||||
extern const ProtobufCMessageDescriptor update_complete__descriptor;
|
||||
extern const ProtobufCMessageDescriptor update_commit__descriptor;
|
||||
extern const ProtobufCMessageDescriptor update_revocation__descriptor;
|
||||
extern const ProtobufCMessageDescriptor close_clearing__descriptor;
|
||||
extern const ProtobufCMessageDescriptor close_signature__descriptor;
|
||||
extern const ProtobufCMessageDescriptor error__descriptor;
|
||||
|
@ -112,63 +112,57 @@ message open_complete {
|
||||
// FIXME: add a merkle proof plus block headers here?
|
||||
}
|
||||
|
||||
// FIXME: Routing information.
|
||||
message routing {
|
||||
required bytes info = 1;
|
||||
}
|
||||
|
||||
// Start a new commitment tx to add an HTLC me -> you.
|
||||
message update_add_htlc {
|
||||
// Hash for which I will supply preimage to revoke this commitment tx.
|
||||
required sha256_hash revocation_hash = 1;
|
||||
// Unique identifier for this HTLC.
|
||||
required uint64 id = 1;
|
||||
// Amount for htlc (millisatoshi)
|
||||
required uint32 amount_msat = 2;
|
||||
// Hash for HTLC R value.
|
||||
required sha256_hash r_hash = 3;
|
||||
// Time at which HTLC expires (absolute)
|
||||
required locktime expiry = 4;
|
||||
// FIXME: Routing information.
|
||||
}
|
||||
|
||||
// We can't do this HTLC, sorry (instead of update_accept)
|
||||
message update_decline_htlc {
|
||||
oneof reason {
|
||||
funding insufficient_funds = 1;
|
||||
bool cannot_route = 2;
|
||||
};
|
||||
// Onion-wrapped routing information.
|
||||
required routing route = 5;
|
||||
}
|
||||
|
||||
// Complete your HTLC: I have the R value, pay me!
|
||||
message update_fulfill_htlc {
|
||||
// Hash for which I will supply preimage to revoke this commitment tx.
|
||||
required sha256_hash revocation_hash = 1;
|
||||
// Which HTLC
|
||||
required uint64 id = 1;
|
||||
// HTLC R value.
|
||||
required sha256_hash r = 2;
|
||||
}
|
||||
|
||||
// Remove your HTLC: routing has failed upstream, we didn't like it, or timeout.
|
||||
// FIXME: Failure information.
|
||||
message fail_reason {
|
||||
required bytes info = 1;
|
||||
}
|
||||
|
||||
message update_fail_htlc {
|
||||
// Hash for which I will supply preimage to revoke this commitment tx.
|
||||
required sha256_hash revocation_hash = 1;
|
||||
// Hash for HTLC R value.
|
||||
required sha256_hash r_hash = 2;
|
||||
// Which HTLC
|
||||
required uint64 id = 1;
|
||||
// Reason for failure (for relay to initial node)
|
||||
required fail_reason reason = 2;
|
||||
}
|
||||
|
||||
// OK, I accept that update; here's your signature.
|
||||
message update_accept {
|
||||
// Commit all the staged HTLCs.
|
||||
message update_commit {
|
||||
// Signature for your new commitment tx.
|
||||
required signature sig = 1;
|
||||
// Hash for which I will supply preimage to revoke this new commit tx.
|
||||
required sha256_hash revocation_hash = 2;
|
||||
}
|
||||
|
||||
// Thanks for accepting, here's my last bit.
|
||||
message update_signature {
|
||||
// Signature for your new commitment tx.
|
||||
required signature sig = 1;
|
||||
// Hash preimage which revokes old commitment tx.
|
||||
required sha256_hash revocation_preimage = 2;
|
||||
}
|
||||
|
||||
// Complete the update.
|
||||
message update_complete {
|
||||
message update_revocation {
|
||||
// Hash preimage which revokes old commitment tx.
|
||||
required sha256_hash revocation_preimage = 1;
|
||||
// Revocation hash for my next commit transaction
|
||||
required sha256_hash next_revocation_hash = 2;
|
||||
}
|
||||
|
||||
// Start clearing out the channel HTLCs so we can close it
|
||||
@ -199,12 +193,11 @@ message pkt {
|
||||
open_complete open_complete = 23;
|
||||
// Updating (most common)
|
||||
update_add_htlc update_add_htlc = 2;
|
||||
update_accept update_accept = 3;
|
||||
update_signature update_signature = 4;
|
||||
update_complete update_complete = 5;
|
||||
update_decline_htlc update_decline_htlc = 6;
|
||||
update_fulfill_htlc update_fulfill_htlc = 7;
|
||||
update_fail_htlc update_fail_htlc = 9;
|
||||
update_fulfill_htlc update_fulfill_htlc = 3;
|
||||
update_fail_htlc update_fail_htlc = 4;
|
||||
update_commit update_commit = 5;
|
||||
update_revocation update_revocation = 6;
|
||||
|
||||
// Closing
|
||||
close_clearing close_clearing = 30;
|
||||
close_signature close_signature = 31;
|
||||
|
306
state.c
306
state.c
@ -4,17 +4,6 @@
|
||||
#endif
|
||||
#include <state.h>
|
||||
|
||||
static inline bool high_priority(enum state state)
|
||||
{
|
||||
return (state & 1) == (STATE_NORMAL_HIGHPRIO & 1);
|
||||
}
|
||||
|
||||
#define prio(state, name) \
|
||||
(high_priority(state) ? name##_HIGHPRIO : name##_LOWPRIO)
|
||||
|
||||
#define toggle_prio(state, name) \
|
||||
(!high_priority(state) ? name##_HIGHPRIO : name##_LOWPRIO)
|
||||
|
||||
/* STATE_CLOSE* can be treated as a bitset offset from STATE_CLOSED */
|
||||
#define BITS_TO_STATE(bits) (STATE_CLOSED + (bits))
|
||||
#define STATE_TO_BITS(state) ((state) - STATE_CLOSED)
|
||||
@ -39,10 +28,11 @@ static enum command_status next_state(struct peer *peer,
|
||||
/*
|
||||
* Simple marker to note we don't update state.
|
||||
*
|
||||
* This happens in two cases:
|
||||
* This happens in three cases:
|
||||
* - We're ignoring packets while closing.
|
||||
* - We stop watching an on-chain HTLC: we indicate that we want
|
||||
* INPUT_NO_MORE_HTLCS when we get the last one.
|
||||
* - HTLC add/remove in STATE_NORMAL.
|
||||
*/
|
||||
static enum command_status unchanged_state(enum command_status cstatus)
|
||||
{
|
||||
@ -78,6 +68,16 @@ static void complete_cmd(struct peer *peer, enum command_status *statusp,
|
||||
*statusp = status;
|
||||
}
|
||||
|
||||
/* FIXME: We do this when a command succeeds instantly, and
|
||||
* state is unchanged. */
|
||||
static enum command_status instant_cmd_success(struct peer *peer,
|
||||
enum command_status cstatus)
|
||||
{
|
||||
assert(peer->cond == PEER_CMD_OK);
|
||||
assert(cstatus == CMD_NONE);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static void queue_tx_broadcast(const struct bitcoin_tx **broadcast,
|
||||
const struct bitcoin_tx *tx)
|
||||
{
|
||||
@ -91,7 +91,6 @@ enum command_status state(struct peer *peer,
|
||||
const union input *idata,
|
||||
const struct bitcoin_tx **broadcast)
|
||||
{
|
||||
Pkt *decline;
|
||||
const struct bitcoin_tx *tx;
|
||||
Pkt *err;
|
||||
enum command_status cstatus = CMD_NONE;
|
||||
@ -243,8 +242,7 @@ enum command_status state(struct peer *peer,
|
||||
queue_pkt_open_complete(peer);
|
||||
if (peer->state == STATE_OPEN_WAITING_OURANCHOR_THEYCOMPLETED) {
|
||||
complete_cmd(peer, &cstatus, CMD_SUCCESS);
|
||||
return next_state(peer, cstatus,
|
||||
STATE_NORMAL_HIGHPRIO);
|
||||
return next_state(peer, cstatus, STATE_NORMAL);
|
||||
}
|
||||
return next_state(peer, cstatus,
|
||||
STATE_OPEN_WAIT_FOR_COMPLETE_OURANCHOR);
|
||||
@ -315,8 +313,7 @@ enum command_status state(struct peer *peer,
|
||||
queue_pkt_open_complete(peer);
|
||||
if (peer->state == STATE_OPEN_WAITING_THEIRANCHOR_THEYCOMPLETED) {
|
||||
complete_cmd(peer, &cstatus, CMD_SUCCESS);
|
||||
return next_state(peer, cstatus,
|
||||
STATE_NORMAL_LOWPRIO);
|
||||
return next_state(peer, cstatus, STATE_NORMAL);
|
||||
}
|
||||
return next_state(peer, cstatus,
|
||||
STATE_OPEN_WAIT_FOR_COMPLETE_THEIRANCHOR);
|
||||
@ -370,12 +367,10 @@ enum command_status state(struct peer *peer,
|
||||
/* Ready for business! Anchorer goes first. */
|
||||
if (peer->state == STATE_OPEN_WAIT_FOR_COMPLETE_OURANCHOR) {
|
||||
complete_cmd(peer, &cstatus, CMD_SUCCESS);
|
||||
return next_state(peer, cstatus,
|
||||
STATE_NORMAL_HIGHPRIO);
|
||||
return next_state(peer, cstatus, STATE_NORMAL);
|
||||
} else {
|
||||
complete_cmd(peer, &cstatus, CMD_SUCCESS);
|
||||
return next_state(peer, cstatus,
|
||||
STATE_NORMAL_LOWPRIO);
|
||||
return next_state(peer, cstatus, STATE_NORMAL);
|
||||
}
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) {
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
@ -406,217 +401,78 @@ enum command_status state(struct peer *peer,
|
||||
/*
|
||||
* Channel normal operating states.
|
||||
*/
|
||||
case STATE_NORMAL_LOWPRIO:
|
||||
case STATE_NORMAL_HIGHPRIO:
|
||||
assert(peer->cond == PEER_CMD_OK);
|
||||
if (input_is(input, CMD_SEND_HTLC_ADD)) {
|
||||
/* We are to send an HTLC update. */
|
||||
queue_pkt_htlc_add(peer, idata->htlc_prog);
|
||||
case STATE_NORMAL:
|
||||
/*
|
||||
* FIXME: For simplicity, we disallow new staging requests
|
||||
* while a commit is outstanding.
|
||||
*/
|
||||
|
||||
/* You can only issue this command one at a time. */
|
||||
if (input_is(input, CMD_SEND_COMMIT)) {
|
||||
queue_pkt_commit(peer);
|
||||
change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY);
|
||||
return next_state(peer, cstatus,
|
||||
prio(peer->state, STATE_WAIT_FOR_HTLC_ACCEPT));
|
||||
return next_state(peer, cstatus, STATE_NORMAL_COMMITTING);
|
||||
} else if (input_is(input, CMD_SEND_HTLC_ADD)) {
|
||||
/* We are to send an HTLC add. */
|
||||
queue_pkt_htlc_add(peer, idata->htlc_prog);
|
||||
return instant_cmd_success(peer, cstatus);
|
||||
} else if (input_is(input, CMD_SEND_HTLC_FULFILL)) {
|
||||
/* We are to send an HTLC fulfill. */
|
||||
queue_pkt_htlc_fulfill(peer, idata->htlc_prog);
|
||||
change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY);
|
||||
return next_state(peer, cstatus,
|
||||
prio(peer->state, STATE_WAIT_FOR_UPDATE_ACCEPT));
|
||||
return instant_cmd_success(peer, cstatus);
|
||||
} else if (input_is(input, CMD_SEND_HTLC_FAIL)) {
|
||||
/* We are to send an HTLC fail. */
|
||||
queue_pkt_htlc_fail(peer, idata->htlc_prog);
|
||||
change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY);
|
||||
return next_state(peer, cstatus,
|
||||
prio(peer->state, STATE_WAIT_FOR_UPDATE_ACCEPT));
|
||||
} else if (input_is(input, CMD_CLOSE)) {
|
||||
goto start_clearing;
|
||||
} else if (input_is(input, INPUT_CONNECTION_LOST)) {
|
||||
goto start_unilateral_close;
|
||||
} else if (input_is(input, PKT_UPDATE_ADD_HTLC)) {
|
||||
change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY);
|
||||
goto accept_htlc_add;
|
||||
} else if (input_is(input, PKT_UPDATE_FULFILL_HTLC)) {
|
||||
change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY);
|
||||
goto accept_htlc_fulfill;
|
||||
} else if (input_is(input, PKT_UPDATE_FAIL_HTLC)) {
|
||||
change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY);
|
||||
goto accept_htlc_fail;
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) {
|
||||
goto them_unilateral;
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_OTHERSPEND)) {
|
||||
goto old_commit_spotted;
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) {
|
||||
goto anchor_unspent;
|
||||
} else if (input_is(input, PKT_CLOSE_CLEARING)) {
|
||||
goto accept_clearing;
|
||||
} else if (input_is_pkt(input)) {
|
||||
goto unexpected_pkt;
|
||||
return instant_cmd_success(peer, cstatus);
|
||||
}
|
||||
break;
|
||||
case STATE_WAIT_FOR_HTLC_ACCEPT_LOWPRIO:
|
||||
case STATE_WAIT_FOR_HTLC_ACCEPT_HIGHPRIO:
|
||||
/* HTLCs can also evoke a refusal. */
|
||||
if (input_is(input, PKT_UPDATE_DECLINE_HTLC)) {
|
||||
peer_htlc_declined(peer, idata->pkt);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
/* No update means no priority change. */
|
||||
return next_state(peer, cstatus,
|
||||
prio(peer->state, STATE_NORMAL));
|
||||
}
|
||||
/* Fall thru */
|
||||
case STATE_WAIT_FOR_UPDATE_ACCEPT_LOWPRIO:
|
||||
case STATE_WAIT_FOR_UPDATE_ACCEPT_HIGHPRIO:
|
||||
if (input_is(input, PKT_UPDATE_ADD_HTLC)) {
|
||||
/* If we're high priority, ignore their packet */
|
||||
if (high_priority(peer->state))
|
||||
return cstatus;
|
||||
|
||||
/* Otherwise, process their request first: defer ours */
|
||||
peer_htlc_ours_deferred(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_REQUEUE);
|
||||
/* Stay busy, since we're processing theirs. */
|
||||
change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY);
|
||||
goto accept_htlc_add;
|
||||
} else if (input_is(input, PKT_UPDATE_FULFILL_HTLC)) {
|
||||
/* If we're high priority, ignore their packet */
|
||||
if (high_priority(peer->state))
|
||||
return cstatus;
|
||||
|
||||
/* Otherwise, process their request first: defer ours */
|
||||
peer_htlc_ours_deferred(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_REQUEUE);
|
||||
/* Stay busy, since we're processing theirs. */
|
||||
change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY);
|
||||
goto accept_htlc_fulfill;
|
||||
} else if (input_is(input, PKT_UPDATE_FAIL_HTLC)) {
|
||||
/* If we're high priority, ignore their packet */
|
||||
if (high_priority(peer->state))
|
||||
return cstatus;
|
||||
|
||||
/* Otherwise, process their request first: defer ours */
|
||||
peer_htlc_ours_deferred(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_REQUEUE);
|
||||
/* Stay busy, since we're processing theirs. */
|
||||
change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY);
|
||||
goto accept_htlc_fail;
|
||||
} else if (input_is(input, PKT_UPDATE_ACCEPT)) {
|
||||
err = accept_pkt_update_accept(peer, idata->pkt);
|
||||
/* Fall through... */
|
||||
case STATE_NORMAL_COMMITTING:
|
||||
/* Only expect revocation in STATE_NORMAL_COMMITTING */
|
||||
if (peer->state == STATE_NORMAL_COMMITTING
|
||||
&& input_is(input, PKT_UPDATE_REVOCATION)) {
|
||||
err = accept_pkt_revocation(peer, idata->pkt);
|
||||
if (err) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto err_start_unilateral_close;
|
||||
}
|
||||
queue_pkt_update_signature(peer);
|
||||
/* HTLC is signed (though old tx not revoked yet!) */
|
||||
return next_state(peer, cstatus,
|
||||
prio(peer->state, STATE_WAIT_FOR_UPDATE_COMPLETE));
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto anchor_unspent;
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto them_unilateral;
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_OTHERSPEND)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto old_commit_spotted;
|
||||
} else if (input_is(input, CMD_CLOSE)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto start_clearing;
|
||||
} else if (input_is(input, INPUT_CONNECTION_LOST)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto start_unilateral_close;
|
||||
} else if (input_is(input, PKT_CLOSE_CLEARING)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto accept_clearing;
|
||||
} else if (input_is_pkt(input)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto unexpected_pkt;
|
||||
}
|
||||
break;
|
||||
case STATE_WAIT_FOR_UPDATE_COMPLETE_LOWPRIO:
|
||||
case STATE_WAIT_FOR_UPDATE_COMPLETE_HIGHPRIO:
|
||||
if (input_is(input, PKT_UPDATE_COMPLETE)) {
|
||||
err = accept_pkt_update_complete(peer, idata->pkt);
|
||||
if (err) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto err_start_unilateral_close;
|
||||
}
|
||||
peer_htlc_done(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_SUCCESS);
|
||||
return next_state(peer, cstatus,
|
||||
toggle_prio(peer->state, STATE_NORMAL));
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto anchor_unspent;
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto them_unilateral;
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_OTHERSPEND)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto old_commit_spotted;
|
||||
} else if (input_is(input, PKT_CLOSE_CLEARING)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto accept_clearing;
|
||||
} else if (input_is(input, CMD_CLOSE)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto start_clearing;
|
||||
} else if (input_is(input, INPUT_CONNECTION_LOST)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto start_unilateral_close;
|
||||
} else if (input_is_pkt(input)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto unexpected_pkt;
|
||||
return next_state(peer, cstatus, STATE_NORMAL);
|
||||
}
|
||||
break;
|
||||
case STATE_WAIT_FOR_UPDATE_SIG_LOWPRIO:
|
||||
case STATE_WAIT_FOR_UPDATE_SIG_HIGHPRIO:
|
||||
if (input_is(input, PKT_UPDATE_SIGNATURE)) {
|
||||
err = accept_pkt_update_signature(peer, idata->pkt);
|
||||
if (err) {
|
||||
peer_htlc_aborted(peer);
|
||||
|
||||
if (input_is(input, CMD_CLOSE)) {
|
||||
goto start_clearing;
|
||||
} else if (input_is(input, PKT_UPDATE_ADD_HTLC)) {
|
||||
err = accept_pkt_htlc_add(peer, idata->pkt);
|
||||
if (err)
|
||||
goto err_start_unilateral_close;
|
||||
}
|
||||
queue_pkt_update_complete(peer);
|
||||
|
||||
peer_htlc_done(peer);
|
||||
change_peer_cond(peer, PEER_BUSY, PEER_CMD_OK);
|
||||
/* Toggle between high and low priority states. */
|
||||
return next_state(peer, cstatus,
|
||||
toggle_prio(peer->state, STATE_NORMAL));
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) {
|
||||
peer_htlc_aborted(peer);
|
||||
goto anchor_unspent;
|
||||
return unchanged_state(cstatus);
|
||||
} else if (input_is(input, PKT_UPDATE_FULFILL_HTLC)) {
|
||||
err = accept_pkt_htlc_fulfill(peer, idata->pkt);
|
||||
if (err)
|
||||
goto err_start_unilateral_close;
|
||||
return unchanged_state(cstatus);
|
||||
} else if (input_is(input, PKT_UPDATE_FAIL_HTLC)) {
|
||||
err = accept_pkt_htlc_fail(peer, idata->pkt);
|
||||
if (err)
|
||||
goto err_start_unilateral_close;
|
||||
return unchanged_state(cstatus);
|
||||
} else if (input_is(input, PKT_UPDATE_COMMIT)) {
|
||||
err = accept_pkt_commit(peer, idata->pkt);
|
||||
if (err)
|
||||
goto err_start_unilateral_close;
|
||||
queue_pkt_revocation(peer);
|
||||
return unchanged_state(cstatus);
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) {
|
||||
peer_htlc_aborted(peer);
|
||||
goto them_unilateral;
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_OTHERSPEND)) {
|
||||
peer_htlc_aborted(peer);
|
||||
goto old_commit_spotted;
|
||||
} else if (input_is(input, CMD_CLOSE)) {
|
||||
peer_htlc_aborted(peer);
|
||||
goto start_clearing;
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) {
|
||||
goto anchor_unspent;
|
||||
} else if (input_is(input, INPUT_CONNECTION_LOST)) {
|
||||
peer_htlc_aborted(peer);
|
||||
goto start_unilateral_close;
|
||||
} else if (input_is(input, PKT_CLOSE_CLEARING)) {
|
||||
peer_htlc_aborted(peer);
|
||||
goto accept_clearing;
|
||||
} else if (input_is_pkt(input)) {
|
||||
peer_htlc_aborted(peer);
|
||||
goto unexpected_pkt;
|
||||
}
|
||||
break;
|
||||
@ -1017,39 +873,6 @@ them_unilateral:
|
||||
|
||||
return next_state(peer, cstatus, STATE_CLOSE_WAIT_SPENDTHEM);
|
||||
|
||||
accept_htlc_add:
|
||||
err = accept_pkt_htlc_add(peer, idata->pkt, &decline);
|
||||
if (err)
|
||||
goto err_start_unilateral_close;
|
||||
if (decline) {
|
||||
queue_pkt_err(peer, decline);
|
||||
peer_htlc_declined(peer, decline);
|
||||
/* No update means no priority change. */
|
||||
change_peer_cond(peer, PEER_BUSY, PEER_CMD_OK);
|
||||
/* We may already be in STATE_NORMAL */
|
||||
return next_state_nocheck(peer, cstatus,
|
||||
prio(peer->state, STATE_NORMAL));
|
||||
}
|
||||
queue_pkt_update_accept(peer);
|
||||
return next_state(peer, cstatus,
|
||||
prio(peer->state, STATE_WAIT_FOR_UPDATE_SIG));
|
||||
|
||||
accept_htlc_fail:
|
||||
err = accept_pkt_htlc_fail(peer, idata->pkt);
|
||||
if (err)
|
||||
goto err_start_unilateral_close;
|
||||
queue_pkt_update_accept(peer);
|
||||
return next_state(peer, cstatus,
|
||||
prio(peer->state, STATE_WAIT_FOR_UPDATE_SIG));
|
||||
|
||||
accept_htlc_fulfill:
|
||||
err = accept_pkt_htlc_fulfill(peer, idata->pkt);
|
||||
if (err)
|
||||
goto err_start_unilateral_close;
|
||||
queue_pkt_update_accept(peer);
|
||||
return next_state(peer, cstatus,
|
||||
prio(peer->state, STATE_WAIT_FOR_UPDATE_SIG));
|
||||
|
||||
start_clearing:
|
||||
/*
|
||||
* Start a mutual close: tell them we want to clear.
|
||||
@ -1095,6 +918,7 @@ instant_close:
|
||||
/* We can't have any HTLCs, since we haven't started. */
|
||||
if (committed_to_htlcs(peer))
|
||||
return next_state(peer, cstatus, STATE_ERR_INTERNAL);
|
||||
|
||||
return next_state(peer, cstatus, STATE_CLOSED);
|
||||
|
||||
old_commit_spotted:
|
||||
|
37
state.h
37
state.h
@ -65,30 +65,6 @@ struct signature;
|
||||
/* Inform peer have an unexpected packet. */
|
||||
void peer_unexpected_pkt(struct peer *peer, const Pkt *pkt);
|
||||
|
||||
/* Current HTLC management.
|
||||
* The "current" htlc is set before sending CMD_SEND_HTLC_*, or by
|
||||
* accept_pkt_htlc_*.
|
||||
*
|
||||
* After that the state machine manages the current htlc, eventually giving one
|
||||
* of the following calls (which should reset the current HTLC):
|
||||
*
|
||||
* - peer_htlc_declined: sent PKT_UPDATE_DECLINE_HTLC.
|
||||
* - peer_htlc_ours_deferred: their update was higher priority, retry later.
|
||||
* - peer_htlc_added: a new HTLC was added successfully.
|
||||
* - peer_htlc_fulfilled: an existing HTLC was fulfilled successfully.
|
||||
* - peer_htlc_fail: an existing HTLC failed to route/timedout/etc.
|
||||
* - peer_htlc_aborted: eg. comms error
|
||||
*/
|
||||
|
||||
/* Someone declined our HTLC: details in pkt (we will also get CMD_FAIL) */
|
||||
void peer_htlc_declined(struct peer *peer, const Pkt *pkt);
|
||||
/* Called when their update overrides our update cmd. */
|
||||
void peer_htlc_ours_deferred(struct peer *peer);
|
||||
/* Successfully added/fulfilled/timedout/fail an HTLC. */
|
||||
void peer_htlc_done(struct peer *peer);
|
||||
/* Someone aborted an existing HTLC. */
|
||||
void peer_htlc_aborted(struct peer *peer);
|
||||
|
||||
/* An on-chain transaction revealed an R value. */
|
||||
const struct htlc *peer_tx_revealed_r_value(struct peer *peer,
|
||||
const struct bitcoin_event *btc);
|
||||
@ -104,9 +80,8 @@ void queue_pkt_htlc_fulfill(struct peer *peer,
|
||||
const struct htlc_progress *htlc_prog);
|
||||
void queue_pkt_htlc_fail(struct peer *peer,
|
||||
const struct htlc_progress *htlc_prog);
|
||||
void queue_pkt_update_accept(struct peer *peer);
|
||||
void queue_pkt_update_signature(struct peer *peer);
|
||||
void queue_pkt_update_complete(struct peer *peer);
|
||||
void queue_pkt_commit(struct peer *peer);
|
||||
void queue_pkt_revocation(struct peer *peer);
|
||||
void queue_pkt_close_clearing(struct peer *peer);
|
||||
void queue_pkt_close_signature(struct peer *peer);
|
||||
|
||||
@ -123,8 +98,7 @@ Pkt *accept_pkt_open_commit_sig(struct peer *peer, const Pkt *pkt);
|
||||
|
||||
Pkt *accept_pkt_open_complete(struct peer *peer, const Pkt *pkt);
|
||||
|
||||
Pkt *accept_pkt_htlc_add(struct peer *peer, const Pkt *pkt,
|
||||
Pkt **decline);
|
||||
Pkt *accept_pkt_htlc_add(struct peer *peer, const Pkt *pkt);
|
||||
|
||||
Pkt *accept_pkt_htlc_fail(struct peer *peer, const Pkt *pkt);
|
||||
|
||||
@ -132,10 +106,9 @@ Pkt *accept_pkt_htlc_fulfill(struct peer *peer, const Pkt *pkt);
|
||||
|
||||
Pkt *accept_pkt_update_accept(struct peer *peer, const Pkt *pkt);
|
||||
|
||||
Pkt *accept_pkt_update_complete(struct peer *peer, const Pkt *pkt);
|
||||
|
||||
Pkt *accept_pkt_update_signature(struct peer *peer, const Pkt *pkt);
|
||||
Pkt *accept_pkt_commit(struct peer *peer, const Pkt *pkt);
|
||||
|
||||
Pkt *accept_pkt_revocation(struct peer *peer, const Pkt *pkt);
|
||||
Pkt *accept_pkt_close_clearing(struct peer *peer, const Pkt *pkt);
|
||||
Pkt *accept_pkt_close_sig(struct peer *peer, const Pkt *pkt, bool *matches);
|
||||
|
||||
|
@ -30,25 +30,11 @@ enum state {
|
||||
STATE_OPEN_WAIT_FOR_COMPLETE_THEIRANCHOR,
|
||||
|
||||
/*
|
||||
* Normal update loop.
|
||||
*
|
||||
* NOTE: High and low prios must alternate!
|
||||
* Normal state.
|
||||
*/
|
||||
STATE_NORMAL_LOWPRIO,
|
||||
STATE_NORMAL_HIGHPRIO,
|
||||
|
||||
STATE_WAIT_FOR_HTLC_ACCEPT_LOWPRIO,
|
||||
STATE_WAIT_FOR_HTLC_ACCEPT_HIGHPRIO,
|
||||
|
||||
STATE_WAIT_FOR_UPDATE_ACCEPT_LOWPRIO,
|
||||
STATE_WAIT_FOR_UPDATE_ACCEPT_HIGHPRIO,
|
||||
STATE_NORMAL,
|
||||
STATE_NORMAL_COMMITTING,
|
||||
|
||||
STATE_WAIT_FOR_UPDATE_COMPLETE_LOWPRIO,
|
||||
STATE_WAIT_FOR_UPDATE_COMPLETE_HIGHPRIO,
|
||||
|
||||
STATE_WAIT_FOR_UPDATE_SIG_LOWPRIO,
|
||||
STATE_WAIT_FOR_UPDATE_SIG_HIGHPRIO,
|
||||
|
||||
/*
|
||||
* Closing.
|
||||
*/
|
||||
@ -195,15 +181,9 @@ enum state_input {
|
||||
/* Updating the commit transaction: your HTLC failed upstream */
|
||||
PKT_UPDATE_FAIL_HTLC = PKT__PKT_UPDATE_FAIL_HTLC,
|
||||
|
||||
/* Update replies: */
|
||||
PKT_UPDATE_ACCEPT = PKT__PKT_UPDATE_ACCEPT,
|
||||
/* Only for PKT_UPDATE_ADD_HTLC. */
|
||||
PKT_UPDATE_DECLINE_HTLC = PKT__PKT_UPDATE_DECLINE_HTLC,
|
||||
|
||||
/* Reply to PKT_UPDATE_ACCEPT */
|
||||
PKT_UPDATE_SIGNATURE = PKT__PKT_UPDATE_SIGNATURE,
|
||||
/* Reply to PKT_UPDATE_SIGNATURE */
|
||||
PKT_UPDATE_COMPLETE = PKT__PKT_UPDATE_COMPLETE,
|
||||
/* Committing updates */
|
||||
PKT_UPDATE_COMMIT = PKT__PKT_UPDATE_COMMIT,
|
||||
PKT_UPDATE_REVOCATION = PKT__PKT_UPDATE_REVOCATION,
|
||||
|
||||
/* Mutual close sequence. */
|
||||
PKT_CLOSE_CLEARING = PKT__PKT_CLOSE_CLEARING,
|
||||
@ -279,6 +259,7 @@ enum state_input {
|
||||
CMD_SEND_HTLC_ADD,
|
||||
CMD_SEND_HTLC_FULFILL,
|
||||
CMD_SEND_HTLC_FAIL,
|
||||
CMD_SEND_COMMIT,
|
||||
CMD_CLOSE,
|
||||
|
||||
/* Connection lost/timedout with other node. */
|
||||
|
Loading…
Reference in New Issue
Block a user