mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-17 19:03:42 +01:00
protocol: implement close as per BOLT #2.
We don't actually implement closing when we have HTLCs (we should allow it, as that's what the clearing phase is for), since soon we'll rewrite HTLC to match the async HTLC protocol of BOLT #2. Note that this folds the close paths, using a simple check if we have a close transaction. That's a slight state layer violation, but reduces code duplication. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
afedf0e8ac
commit
b423b33236
@ -147,12 +147,21 @@ static void default_config(struct config *config)
|
||||
|
||||
static void check_config(struct lightningd_state *dstate)
|
||||
{
|
||||
/* BOLT #2:
|
||||
* The sender MUST set `close_fee` lower than or equal to the
|
||||
* fee of the final commitment transaction, and MUST set
|
||||
* `close_fee` to an even number of satoshis.
|
||||
*/
|
||||
if (dstate->config.closing_fee > dstate->config.commitment_fee)
|
||||
fatal("Closing fee %"PRIu64
|
||||
" can't exceed commitment fee %"PRIu64,
|
||||
dstate->config.closing_fee,
|
||||
dstate->config.commitment_fee);
|
||||
|
||||
if (dstate->config.closing_fee & 1)
|
||||
fatal("Closing fee %"PRIu64 "must be even.",
|
||||
dstate->config.closing_fee);
|
||||
|
||||
if (dstate->config.commitment_fee_min > dstate->config.commitment_fee)
|
||||
fatal("Minumum fee %"PRIu64
|
||||
" can't exceed commitment fee %"PRIu64,
|
||||
|
162
daemon/packets.c
162
daemon/packets.c
@ -243,35 +243,29 @@ Pkt *pkt_err(const tal_t *ctx, const char *msg, ...)
|
||||
return make_pkt(ctx, PKT__PKT_ERROR, e);
|
||||
}
|
||||
|
||||
Pkt *pkt_close(const tal_t *ctx, const struct peer *peer)
|
||||
Pkt *pkt_close_clearing(const tal_t *ctx, const struct peer *peer)
|
||||
{
|
||||
CloseChannel *c = tal(ctx, CloseChannel);
|
||||
CloseClearing *c = tal(ctx, CloseClearing);
|
||||
|
||||
close_channel__init(c);
|
||||
close_clearing__init(c);
|
||||
|
||||
c->close_fee = peer->close_tx->fee;
|
||||
c->sig = signature_to_proto(c, &peer->our_close_sig.sig);
|
||||
|
||||
return make_pkt(ctx, PKT__PKT_CLOSE, c);
|
||||
return make_pkt(ctx, PKT__PKT_CLOSE_CLEARING, c);
|
||||
}
|
||||
|
||||
Pkt *pkt_close_complete(const tal_t *ctx, const struct peer *peer)
|
||||
Pkt *pkt_close_signature(const tal_t *ctx, const struct peer *peer)
|
||||
{
|
||||
CloseChannelComplete *c = tal(ctx, CloseChannelComplete);
|
||||
CloseSignature *c = tal(ctx, CloseSignature);
|
||||
struct bitcoin_tx *close_tx;
|
||||
struct signature our_close_sig;
|
||||
|
||||
close_channel_complete__init(c);
|
||||
assert(peer->close_tx);
|
||||
c->sig = signature_to_proto(c, &peer->our_close_sig.sig);
|
||||
close_signature__init(c);
|
||||
close_tx = peer_create_close_tx(ctx, peer, peer->closing.our_fee);
|
||||
|
||||
return make_pkt(ctx, PKT__PKT_CLOSE_COMPLETE, c);
|
||||
}
|
||||
peer_sign_mutual_close(peer, close_tx, &our_close_sig);
|
||||
c->sig = signature_to_proto(c, &our_close_sig);
|
||||
c->close_fee = peer->closing.our_fee;
|
||||
|
||||
Pkt *pkt_close_ack(const tal_t *ctx, const struct peer *peer)
|
||||
{
|
||||
CloseChannelAck *a = tal(ctx, CloseChannelAck);
|
||||
|
||||
close_channel_ack__init(a);
|
||||
return make_pkt(ctx, PKT__PKT_CLOSE_ACK, a);
|
||||
return make_pkt(ctx, PKT__PKT_CLOSE_SIGNATURE, c);
|
||||
}
|
||||
|
||||
Pkt *pkt_err_unexpected(const tal_t *ctx, const Pkt *pkt)
|
||||
@ -721,68 +715,84 @@ Pkt *accept_pkt_update_signature(const tal_t *ctx,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool peer_sign_close_tx(struct peer *peer, const Signature *theirs)
|
||||
Pkt *accept_pkt_close_clearing(const tal_t *ctx, struct peer *peer, const Pkt *pkt)
|
||||
{
|
||||
/* FIXME: Reject unknown odd fields? */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Pkt *accept_pkt_close_sig(const tal_t *ctx, struct peer *peer, const Pkt *pkt,
|
||||
bool *matches)
|
||||
{
|
||||
const CloseSignature *c = pkt->close_signature;
|
||||
struct bitcoin_tx *close_tx;
|
||||
struct bitcoin_signature theirsig;
|
||||
|
||||
/* We never sign twice! */
|
||||
assert(peer->close_tx->input[0].script_length == 0);
|
||||
/* BOLT #2:
|
||||
|
||||
theirsig.stype = SIGHASH_ALL;
|
||||
if (!proto_to_signature(theirs, &theirsig.sig))
|
||||
return false;
|
||||
|
||||
/* Their sig + ours should sign the close tx. */
|
||||
if (!check_2of2_sig(peer->dstate->secpctx,
|
||||
peer->close_tx, 0,
|
||||
peer->anchor.redeemscript,
|
||||
tal_count(peer->anchor.redeemscript),
|
||||
&peer->them.commitkey, &peer->us.commitkey,
|
||||
&theirsig, &peer->our_close_sig))
|
||||
return false;
|
||||
|
||||
/* Complete the close_tx, using signatures. */
|
||||
peer->close_tx->input[0].script
|
||||
= scriptsig_p2sh_2of2(peer->close_tx,
|
||||
&theirsig, &peer->our_close_sig,
|
||||
&peer->them.commitkey,
|
||||
&peer->us.commitkey);
|
||||
peer->close_tx->input[0].script_length
|
||||
= tal_count(peer->close_tx->input[0].script);
|
||||
return true;
|
||||
}
|
||||
|
||||
Pkt *accept_pkt_close(const tal_t *ctx, struct peer *peer, const Pkt *pkt)
|
||||
{
|
||||
const CloseChannel *c = pkt->close;
|
||||
|
||||
/* FIXME: Don't accept tiny close fee! */
|
||||
if (!peer_create_close_tx(peer, c->close_fee))
|
||||
* The sender MUST set `close_fee` lower than or equal to the fee of the
|
||||
* final commitment transaction, and MUST set `close_fee` to an even
|
||||
* number of satoshis.
|
||||
*/
|
||||
if (c->close_fee & 1 || c->close_fee > peer->them.commit_fee)
|
||||
return pkt_err(ctx, "Invalid close fee");
|
||||
|
||||
if (!peer_sign_close_tx(peer, c->sig))
|
||||
/* FIXME: Don't accept tiny fee at all? */
|
||||
|
||||
/* BOLT #2:
|
||||
... otherwise it SHOULD propose a
|
||||
value strictly between the received `close_fee` and its
|
||||
previously-sent `close_fee`.
|
||||
*/
|
||||
if (peer->closing.their_sig) {
|
||||
/* We want more, they should give more. */
|
||||
if (peer->closing.our_fee > peer->closing.their_fee) {
|
||||
if (c->close_fee <= peer->closing.their_fee)
|
||||
return pkt_err(ctx, "Didn't increase close fee");
|
||||
} else {
|
||||
if (c->close_fee >= peer->closing.their_fee)
|
||||
return pkt_err(ctx, "Didn't decrease close fee");
|
||||
}
|
||||
}
|
||||
|
||||
/* BOLT #2:
|
||||
*
|
||||
* The receiver MUST check `sig` is valid for the close
|
||||
* transaction, and MUST fail the connection if it is not. */
|
||||
theirsig.stype = SIGHASH_ALL;
|
||||
if (!proto_to_signature(c->sig, &theirsig.sig))
|
||||
return pkt_err(ctx, "Invalid signature format");
|
||||
|
||||
close_tx = peer_create_close_tx(ctx, peer, c->close_fee);
|
||||
if (!check_tx_sig(peer->dstate->secpctx, close_tx, 0,
|
||||
peer->anchor.redeemscript,
|
||||
tal_count(peer->anchor.redeemscript),
|
||||
&peer->them.commitkey, &theirsig))
|
||||
return pkt_err(ctx, "Invalid signature");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Pkt *accept_pkt_close_complete(const tal_t *ctx,
|
||||
struct peer *peer, const Pkt *pkt)
|
||||
{
|
||||
const CloseChannelComplete *c = pkt->close_complete;
|
||||
if (!peer_sign_close_tx(peer, c->sig))
|
||||
return pkt_err(ctx, "Invalid signature");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Pkt *accept_pkt_simultaneous_close(const tal_t *ctx,
|
||||
struct peer *peer,
|
||||
const Pkt *pkt)
|
||||
{
|
||||
FIXME_STUB(peer);
|
||||
}
|
||||
|
||||
/* FIXME: Since this packet is empty, is it worth having? */
|
||||
Pkt *accept_pkt_close_ack(const tal_t *ctx, struct peer *peer, const Pkt *pkt)
|
||||
{
|
||||
|
||||
tal_free(peer->closing.their_sig);
|
||||
peer->closing.their_sig = tal_dup(peer,
|
||||
struct bitcoin_signature, &theirsig);
|
||||
peer->closing.their_fee = c->close_fee;
|
||||
|
||||
if (peer->closing.our_fee == peer->closing.their_fee) {
|
||||
*matches = true;
|
||||
} else {
|
||||
/* Adjust our fee to close on their fee. */
|
||||
u64 sum;
|
||||
|
||||
/* Beware overflow! */
|
||||
sum = (u64)peer->closing.our_fee + peer->closing.their_fee;
|
||||
|
||||
peer->closing.our_fee = sum / 2;
|
||||
if (peer->closing.our_fee & 1)
|
||||
peer->closing.our_fee++;
|
||||
|
||||
/* FIXME: Fees may *now* be equal, and they'll
|
||||
* consider this an ACK! */
|
||||
}
|
||||
*matches = false;
|
||||
|
||||
/* FIXME: Dynamic fee! */
|
||||
return NULL;
|
||||
}
|
||||
|
123
daemon/peer.c
123
daemon/peer.c
@ -222,6 +222,13 @@ static void state_event(struct peer *peer,
|
||||
const union input *idata)
|
||||
{
|
||||
state_single(peer, input, idata);
|
||||
|
||||
if (peer->cleared != INPUT_NONE && !committed_to_htlcs(peer)) {
|
||||
enum state_input all_done = peer->cleared;
|
||||
peer->cleared = INPUT_NONE;
|
||||
state_single(peer, all_done, NULL);
|
||||
}
|
||||
|
||||
try_command(peer);
|
||||
}
|
||||
|
||||
@ -353,11 +360,12 @@ static struct peer *new_peer(struct lightningd_state *dstate,
|
||||
list_head_init(&peer->pending_cmd);
|
||||
peer->current_htlc = NULL;
|
||||
peer->commit_tx_counter = 0;
|
||||
peer->close_tx = NULL;
|
||||
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;
|
||||
|
||||
/* If we free peer, conn should be closed, but can't be freed
|
||||
* immediately so don't make peer a parent. */
|
||||
@ -621,29 +629,35 @@ static bool txmatch(const struct bitcoin_tx *txa, const struct bitcoin_tx *txb)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool is_mutual_close(const struct bitcoin_tx *tx,
|
||||
const struct bitcoin_tx *close_tx)
|
||||
/* 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,
|
||||
const struct bitcoin_tx *tx)
|
||||
{
|
||||
varint_t i;
|
||||
const u8 *ctx, *our_p2sh, *their_p2sh;
|
||||
bool matches;
|
||||
|
||||
/* Haven't created mutual close yet? This isn't one then. */
|
||||
if (!close_tx)
|
||||
if (tx->output_count != 2)
|
||||
return false;
|
||||
|
||||
/* We know it spends anchor, but do txouts match? */
|
||||
if (tx->output_count != close_tx->output_count)
|
||||
if (!is_p2sh(tx->output[0].script, tx->output[0].script_length)
|
||||
|| !is_p2sh(tx->output[1].script, tx->output[1].script_length))
|
||||
return false;
|
||||
for (i = 0; i < tx->output_count; i++) {
|
||||
if (tx->output[i].amount != close_tx->output[i].amount)
|
||||
return false;
|
||||
if (tx->output[i].script_length
|
||||
!= close_tx->output[i].script_length)
|
||||
return false;
|
||||
if (memcmp(tx->output[i].script, close_tx->output[i].script,
|
||||
tx->output[i].script_length) != 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
/* FIXME: Cache these! */
|
||||
ctx = tal(NULL, u8);
|
||||
our_p2sh = scriptpubkey_p2sh(ctx,
|
||||
bitcoin_redeem_single(tx, &peer->us.finalkey));
|
||||
their_p2sh = scriptpubkey_p2sh(ctx,
|
||||
bitcoin_redeem_single(tx, &peer->them.finalkey));
|
||||
|
||||
matches =
|
||||
(memcmp(tx->output[0].script, our_p2sh, tal_count(our_p2sh)) == 0
|
||||
&& memcmp(tx->output[1].script, their_p2sh, tal_count(their_p2sh)) == 0)
|
||||
|| (memcmp(tx->output[0].script, their_p2sh, tal_count(their_p2sh)) == 0
|
||||
&& memcmp(tx->output[1].script, our_p2sh, tal_count(our_p2sh)) == 0);
|
||||
tal_free(ctx);
|
||||
return matches;
|
||||
}
|
||||
|
||||
static void close_depth_cb(struct peer *peer, int depth)
|
||||
@ -665,7 +679,7 @@ static void anchor_spent(struct peer *peer,
|
||||
idata.btc = (struct bitcoin_event *)tx;
|
||||
if (txmatch(tx, peer->them.commit))
|
||||
state_event(peer, w->theyspent, &idata);
|
||||
else if (is_mutual_close(tx, peer->close_tx))
|
||||
else if (is_mutual_close(peer, tx))
|
||||
add_close_tx_watch(peer, peer, tx, close_depth_cb);
|
||||
else
|
||||
state_event(peer, w->otherspent, &idata);
|
||||
@ -836,20 +850,20 @@ void peer_watch_tx(struct peer *peer,
|
||||
add_commit_tx_watch(tx, peer, &txid, spend_tx_done, int2ptr(done));
|
||||
}
|
||||
|
||||
bool peer_create_close_tx(struct peer *peer, u64 fee_satoshis)
|
||||
struct bitcoin_tx *peer_create_close_tx(const tal_t *ctx,
|
||||
const struct peer *peer, u64 fee)
|
||||
{
|
||||
struct channel_state cstate;
|
||||
|
||||
assert(!peer->close_tx);
|
||||
|
||||
/* We don't need a deep copy here, just fee levels. */
|
||||
cstate = *peer->cstate;
|
||||
if (!adjust_fee(peer->anchor.satoshis, fee_satoshis,
|
||||
if (!adjust_fee(peer->anchor.satoshis, fee,
|
||||
&cstate.a, &cstate.b))
|
||||
return false;
|
||||
return NULL;
|
||||
|
||||
log_debug(peer->log,
|
||||
"creating close-tx: to %02x%02x%02x%02x/%02x%02x%02x%02x, amounts %u/%u",
|
||||
"creating close-tx with fee %"PRIu64": to %02x%02x%02x%02x/%02x%02x%02x%02x, amounts %u/%u",
|
||||
fee,
|
||||
peer->us.finalkey.der[0], peer->us.finalkey.der[1],
|
||||
peer->us.finalkey.der[2], peer->us.finalkey.der[3],
|
||||
peer->them.finalkey.der[0], peer->them.finalkey.der[1],
|
||||
@ -857,7 +871,7 @@ bool peer_create_close_tx(struct peer *peer, u64 fee_satoshis)
|
||||
cstate.a.pay_msat / 1000,
|
||||
cstate.b.pay_msat / 1000);
|
||||
|
||||
peer->close_tx = create_close_tx(peer->dstate->secpctx, peer,
|
||||
return create_close_tx(peer->dstate->secpctx, ctx,
|
||||
&peer->us.finalkey,
|
||||
&peer->them.finalkey,
|
||||
&peer->anchor.txid,
|
||||
@ -865,10 +879,23 @@ bool peer_create_close_tx(struct peer *peer, u64 fee_satoshis)
|
||||
peer->anchor.satoshis,
|
||||
cstate.a.pay_msat / 1000,
|
||||
cstate.b.pay_msat / 1000);
|
||||
}
|
||||
|
||||
peer->our_close_sig.stype = SIGHASH_ALL;
|
||||
peer_sign_mutual_close(peer, peer->close_tx, &peer->our_close_sig.sig);
|
||||
return true;
|
||||
void peer_calculate_close_fee(struct peer *peer)
|
||||
{
|
||||
/* BOLT #2:
|
||||
* The sender MUST set `close_fee` lower than or equal to the
|
||||
* fee of the final commitment transaction, and MUST set
|
||||
* `close_fee` to an even number of satoshis.
|
||||
*/
|
||||
|
||||
/* FIXME: Dynamic fee! */
|
||||
peer->closing.our_fee = peer->dstate->config.closing_fee;
|
||||
}
|
||||
|
||||
bool peer_has_close_sig(const struct peer *peer)
|
||||
{
|
||||
return peer->closing.their_sig;
|
||||
}
|
||||
|
||||
static void send_close_timeout(struct peer *peer)
|
||||
@ -883,10 +910,6 @@ void peer_watch_close(struct peer *peer,
|
||||
/* We save some work by assuming these. */
|
||||
assert(done == BITCOIN_CLOSE_DONE);
|
||||
|
||||
/* FIXME: Dynamic closing fee! */
|
||||
if (!peer->close_tx)
|
||||
peer_create_close_tx(peer, peer->dstate->config.closing_fee);
|
||||
|
||||
/* FIXME: We can't send CLOSE, so timeout immediately */
|
||||
if (!peer->conn) {
|
||||
assert(timedout == INPUT_CLOSE_COMPLETE_TIMEOUT);
|
||||
@ -994,12 +1017,36 @@ bool committed_to_htlcs(const struct peer *peer)
|
||||
|| tal_count(peer->cstate->b.htlcs) != 0;
|
||||
}
|
||||
|
||||
/* Create a bitcoin close tx. */
|
||||
void peer_watch_htlcs_cleared(struct peer *peer,
|
||||
enum state_input all_done)
|
||||
{
|
||||
assert(peer->cleared == INPUT_NONE);
|
||||
assert(all_done != INPUT_NONE);
|
||||
peer->cleared = all_done;
|
||||
}
|
||||
|
||||
/* Create a bitcoin close tx, using last signature they sent. */
|
||||
const struct bitcoin_tx *bitcoin_close(const tal_t *ctx, struct peer *peer)
|
||||
{
|
||||
/* Must be signed! */
|
||||
assert(peer->close_tx->input[0].script_length != 0);
|
||||
return peer->close_tx;
|
||||
struct bitcoin_tx *close_tx;
|
||||
struct bitcoin_signature our_close_sig;
|
||||
|
||||
close_tx = peer_create_close_tx(ctx, peer, peer->closing.their_fee);
|
||||
|
||||
our_close_sig.stype = SIGHASH_ALL;
|
||||
peer_sign_mutual_close(peer, close_tx, &our_close_sig.sig);
|
||||
|
||||
/* Complete the close_tx, using signatures. */
|
||||
close_tx->input[0].script
|
||||
= scriptsig_p2sh_2of2(close_tx,
|
||||
peer->closing.their_sig,
|
||||
&our_close_sig,
|
||||
&peer->them.commitkey,
|
||||
&peer->us.commitkey);
|
||||
close_tx->input[0].script_length
|
||||
= tal_count(close_tx->input[0].script);
|
||||
|
||||
return close_tx;
|
||||
}
|
||||
|
||||
/* Create a bitcoin spend tx (to spend our commit's outputs) */
|
||||
|
@ -141,10 +141,17 @@ struct peer {
|
||||
/* Number of HTLC updates (== number of previous commit txs) */
|
||||
u64 commit_tx_counter;
|
||||
|
||||
/* FIXME: Group closing fields together in anon struct. */
|
||||
/* Closing tx and signature once we've generated it */
|
||||
struct bitcoin_tx *close_tx;
|
||||
struct bitcoin_signature our_close_sig;
|
||||
struct {
|
||||
/* Our last suggested closing fee. */
|
||||
u64 our_fee;
|
||||
/* If they've offered a signature, these are set: */
|
||||
struct bitcoin_signature *their_sig;
|
||||
/* If their_sig is non-NULL, this is the fee. */
|
||||
u64 their_fee;
|
||||
} closing;
|
||||
|
||||
/* If not INPUT_NONE, send this when we have no more HTLCs. */
|
||||
enum state_input cleared;
|
||||
|
||||
/* Current ongoing packetflow */
|
||||
struct io_data *io_data;
|
||||
@ -177,6 +184,7 @@ void make_commit_txs(const tal_t *ctx,
|
||||
void peer_add_htlc_expiry(struct peer *peer,
|
||||
const struct abs_locktime *expiry);
|
||||
|
||||
bool peer_create_close_tx(struct peer *peer, u64 fee_satoshis);
|
||||
struct bitcoin_tx *peer_create_close_tx(const tal_t *ctx,
|
||||
const struct peer *peer, u64 fee);
|
||||
|
||||
#endif /* LIGHTNING_DAEMON_PEER_H */
|
||||
|
292
lightning.pb-c.c
292
lightning.pb-c.c
@ -738,133 +738,90 @@ void update_complete__free_unpacked
|
||||
assert(message->base.descriptor == &update_complete__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void close_channel__init
|
||||
(CloseChannel *message)
|
||||
void close_clearing__init
|
||||
(CloseClearing *message)
|
||||
{
|
||||
static CloseChannel init_value = CLOSE_CHANNEL__INIT;
|
||||
static CloseClearing init_value = CLOSE_CLEARING__INIT;
|
||||
*message = init_value;
|
||||
}
|
||||
size_t close_channel__get_packed_size
|
||||
(const CloseChannel *message)
|
||||
size_t close_clearing__get_packed_size
|
||||
(const CloseClearing *message)
|
||||
{
|
||||
assert(message->base.descriptor == &close_channel__descriptor);
|
||||
assert(message->base.descriptor == &close_clearing__descriptor);
|
||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
||||
}
|
||||
size_t close_channel__pack
|
||||
(const CloseChannel *message,
|
||||
size_t close_clearing__pack
|
||||
(const CloseClearing *message,
|
||||
uint8_t *out)
|
||||
{
|
||||
assert(message->base.descriptor == &close_channel__descriptor);
|
||||
assert(message->base.descriptor == &close_clearing__descriptor);
|
||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
||||
}
|
||||
size_t close_channel__pack_to_buffer
|
||||
(const CloseChannel *message,
|
||||
size_t close_clearing__pack_to_buffer
|
||||
(const CloseClearing *message,
|
||||
ProtobufCBuffer *buffer)
|
||||
{
|
||||
assert(message->base.descriptor == &close_channel__descriptor);
|
||||
assert(message->base.descriptor == &close_clearing__descriptor);
|
||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
||||
}
|
||||
CloseChannel *
|
||||
close_channel__unpack
|
||||
CloseClearing *
|
||||
close_clearing__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data)
|
||||
{
|
||||
return (CloseChannel *)
|
||||
protobuf_c_message_unpack (&close_channel__descriptor,
|
||||
return (CloseClearing *)
|
||||
protobuf_c_message_unpack (&close_clearing__descriptor,
|
||||
allocator, len, data);
|
||||
}
|
||||
void close_channel__free_unpacked
|
||||
(CloseChannel *message,
|
||||
void close_clearing__free_unpacked
|
||||
(CloseClearing *message,
|
||||
ProtobufCAllocator *allocator)
|
||||
{
|
||||
assert(message->base.descriptor == &close_channel__descriptor);
|
||||
assert(message->base.descriptor == &close_clearing__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void close_channel_complete__init
|
||||
(CloseChannelComplete *message)
|
||||
void close_signature__init
|
||||
(CloseSignature *message)
|
||||
{
|
||||
static CloseChannelComplete init_value = CLOSE_CHANNEL_COMPLETE__INIT;
|
||||
static CloseSignature init_value = CLOSE_SIGNATURE__INIT;
|
||||
*message = init_value;
|
||||
}
|
||||
size_t close_channel_complete__get_packed_size
|
||||
(const CloseChannelComplete *message)
|
||||
size_t close_signature__get_packed_size
|
||||
(const CloseSignature *message)
|
||||
{
|
||||
assert(message->base.descriptor == &close_channel_complete__descriptor);
|
||||
assert(message->base.descriptor == &close_signature__descriptor);
|
||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
||||
}
|
||||
size_t close_channel_complete__pack
|
||||
(const CloseChannelComplete *message,
|
||||
size_t close_signature__pack
|
||||
(const CloseSignature *message,
|
||||
uint8_t *out)
|
||||
{
|
||||
assert(message->base.descriptor == &close_channel_complete__descriptor);
|
||||
assert(message->base.descriptor == &close_signature__descriptor);
|
||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
||||
}
|
||||
size_t close_channel_complete__pack_to_buffer
|
||||
(const CloseChannelComplete *message,
|
||||
size_t close_signature__pack_to_buffer
|
||||
(const CloseSignature *message,
|
||||
ProtobufCBuffer *buffer)
|
||||
{
|
||||
assert(message->base.descriptor == &close_channel_complete__descriptor);
|
||||
assert(message->base.descriptor == &close_signature__descriptor);
|
||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
||||
}
|
||||
CloseChannelComplete *
|
||||
close_channel_complete__unpack
|
||||
CloseSignature *
|
||||
close_signature__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data)
|
||||
{
|
||||
return (CloseChannelComplete *)
|
||||
protobuf_c_message_unpack (&close_channel_complete__descriptor,
|
||||
return (CloseSignature *)
|
||||
protobuf_c_message_unpack (&close_signature__descriptor,
|
||||
allocator, len, data);
|
||||
}
|
||||
void close_channel_complete__free_unpacked
|
||||
(CloseChannelComplete *message,
|
||||
void close_signature__free_unpacked
|
||||
(CloseSignature *message,
|
||||
ProtobufCAllocator *allocator)
|
||||
{
|
||||
assert(message->base.descriptor == &close_channel_complete__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void close_channel_ack__init
|
||||
(CloseChannelAck *message)
|
||||
{
|
||||
static CloseChannelAck init_value = CLOSE_CHANNEL_ACK__INIT;
|
||||
*message = init_value;
|
||||
}
|
||||
size_t close_channel_ack__get_packed_size
|
||||
(const CloseChannelAck *message)
|
||||
{
|
||||
assert(message->base.descriptor == &close_channel_ack__descriptor);
|
||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
||||
}
|
||||
size_t close_channel_ack__pack
|
||||
(const CloseChannelAck *message,
|
||||
uint8_t *out)
|
||||
{
|
||||
assert(message->base.descriptor == &close_channel_ack__descriptor);
|
||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
||||
}
|
||||
size_t close_channel_ack__pack_to_buffer
|
||||
(const CloseChannelAck *message,
|
||||
ProtobufCBuffer *buffer)
|
||||
{
|
||||
assert(message->base.descriptor == &close_channel_ack__descriptor);
|
||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
||||
}
|
||||
CloseChannelAck *
|
||||
close_channel_ack__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data)
|
||||
{
|
||||
return (CloseChannelAck *)
|
||||
protobuf_c_message_unpack (&close_channel_ack__descriptor,
|
||||
allocator, len, data);
|
||||
}
|
||||
void close_channel_ack__free_unpacked
|
||||
(CloseChannelAck *message,
|
||||
ProtobufCAllocator *allocator)
|
||||
{
|
||||
assert(message->base.descriptor == &close_channel_ack__descriptor);
|
||||
assert(message->base.descriptor == &close_signature__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void error__init
|
||||
@ -2033,111 +1990,73 @@ const ProtobufCMessageDescriptor update_complete__descriptor =
|
||||
(ProtobufCMessageInit) update_complete__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor close_channel__field_descriptors[2] =
|
||||
#define close_clearing__field_descriptors NULL
|
||||
#define close_clearing__field_indices_by_name NULL
|
||||
#define close_clearing__number_ranges NULL
|
||||
const ProtobufCMessageDescriptor close_clearing__descriptor =
|
||||
{
|
||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||
"close_clearing",
|
||||
"CloseClearing",
|
||||
"CloseClearing",
|
||||
"",
|
||||
sizeof(CloseClearing),
|
||||
0,
|
||||
close_clearing__field_descriptors,
|
||||
close_clearing__field_indices_by_name,
|
||||
0, close_clearing__number_ranges,
|
||||
(ProtobufCMessageInit) close_clearing__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor close_signature__field_descriptors[2] =
|
||||
{
|
||||
{
|
||||
"close_fee",
|
||||
1,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_UINT64,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(CloseSignature, close_fee),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"sig",
|
||||
1,
|
||||
2,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(CloseChannel, sig),
|
||||
offsetof(CloseSignature, sig),
|
||||
&signature__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"close_fee",
|
||||
2,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_UINT64,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(CloseChannel, close_fee),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned close_channel__field_indices_by_name[] = {
|
||||
1, /* field[1] = close_fee */
|
||||
0, /* field[0] = sig */
|
||||
static const unsigned close_signature__field_indices_by_name[] = {
|
||||
0, /* field[0] = close_fee */
|
||||
1, /* field[1] = sig */
|
||||
};
|
||||
static const ProtobufCIntRange close_channel__number_ranges[1 + 1] =
|
||||
static const ProtobufCIntRange close_signature__number_ranges[1 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 0, 2 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor close_channel__descriptor =
|
||||
const ProtobufCMessageDescriptor close_signature__descriptor =
|
||||
{
|
||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||
"close_channel",
|
||||
"CloseChannel",
|
||||
"CloseChannel",
|
||||
"close_signature",
|
||||
"CloseSignature",
|
||||
"CloseSignature",
|
||||
"",
|
||||
sizeof(CloseChannel),
|
||||
sizeof(CloseSignature),
|
||||
2,
|
||||
close_channel__field_descriptors,
|
||||
close_channel__field_indices_by_name,
|
||||
1, close_channel__number_ranges,
|
||||
(ProtobufCMessageInit) close_channel__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor close_channel_complete__field_descriptors[1] =
|
||||
{
|
||||
{
|
||||
"sig",
|
||||
1,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(CloseChannelComplete, sig),
|
||||
&signature__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned close_channel_complete__field_indices_by_name[] = {
|
||||
0, /* field[0] = sig */
|
||||
};
|
||||
static const ProtobufCIntRange close_channel_complete__number_ranges[1 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 0, 1 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor close_channel_complete__descriptor =
|
||||
{
|
||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||
"close_channel_complete",
|
||||
"CloseChannelComplete",
|
||||
"CloseChannelComplete",
|
||||
"",
|
||||
sizeof(CloseChannelComplete),
|
||||
1,
|
||||
close_channel_complete__field_descriptors,
|
||||
close_channel_complete__field_indices_by_name,
|
||||
1, close_channel_complete__number_ranges,
|
||||
(ProtobufCMessageInit) close_channel_complete__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
#define close_channel_ack__field_descriptors NULL
|
||||
#define close_channel_ack__field_indices_by_name NULL
|
||||
#define close_channel_ack__number_ranges NULL
|
||||
const ProtobufCMessageDescriptor close_channel_ack__descriptor =
|
||||
{
|
||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||
"close_channel_ack",
|
||||
"CloseChannelAck",
|
||||
"CloseChannelAck",
|
||||
"",
|
||||
sizeof(CloseChannelAck),
|
||||
0,
|
||||
close_channel_ack__field_descriptors,
|
||||
close_channel_ack__field_indices_by_name,
|
||||
0, close_channel_ack__number_ranges,
|
||||
(ProtobufCMessageInit) close_channel_ack__init,
|
||||
close_signature__field_descriptors,
|
||||
close_signature__field_indices_by_name,
|
||||
1, close_signature__number_ranges,
|
||||
(ProtobufCMessageInit) close_signature__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor error__field_descriptors[1] =
|
||||
@ -2178,7 +2097,7 @@ const ProtobufCMessageDescriptor error__descriptor =
|
||||
(ProtobufCMessageInit) error__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor pkt__field_descriptors[16] =
|
||||
static const ProtobufCFieldDescriptor pkt__field_descriptors[15] =
|
||||
{
|
||||
{
|
||||
"update_add_htlc",
|
||||
@ -2313,37 +2232,25 @@ static const ProtobufCFieldDescriptor pkt__field_descriptors[16] =
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"close",
|
||||
"close_clearing",
|
||||
30,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
offsetof(Pkt, pkt_case),
|
||||
offsetof(Pkt, close),
|
||||
&close_channel__descriptor,
|
||||
offsetof(Pkt, close_clearing),
|
||||
&close_clearing__descriptor,
|
||||
NULL,
|
||||
0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"close_complete",
|
||||
"close_signature",
|
||||
31,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
offsetof(Pkt, pkt_case),
|
||||
offsetof(Pkt, close_complete),
|
||||
&close_channel_complete__descriptor,
|
||||
NULL,
|
||||
0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"close_ack",
|
||||
32,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
offsetof(Pkt, pkt_case),
|
||||
offsetof(Pkt, close_ack),
|
||||
&close_channel_ack__descriptor,
|
||||
offsetof(Pkt, close_signature),
|
||||
&close_signature__descriptor,
|
||||
NULL,
|
||||
0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
@ -2374,11 +2281,10 @@ static const ProtobufCFieldDescriptor pkt__field_descriptors[16] =
|
||||
},
|
||||
};
|
||||
static const unsigned pkt__field_indices_by_name[] = {
|
||||
15, /* field[15] = auth */
|
||||
11, /* field[11] = close */
|
||||
13, /* field[13] = close_ack */
|
||||
12, /* field[12] = close_complete */
|
||||
14, /* field[14] = error */
|
||||
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 */
|
||||
@ -2397,9 +2303,9 @@ static const ProtobufCIntRange pkt__number_ranges[6 + 1] =
|
||||
{ 9, 6 },
|
||||
{ 20, 7 },
|
||||
{ 30, 11 },
|
||||
{ 40, 14 },
|
||||
{ 50, 15 },
|
||||
{ 0, 16 }
|
||||
{ 40, 13 },
|
||||
{ 50, 14 },
|
||||
{ 0, 15 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor pkt__descriptor =
|
||||
{
|
||||
@ -2409,7 +2315,7 @@ const ProtobufCMessageDescriptor pkt__descriptor =
|
||||
"Pkt",
|
||||
"",
|
||||
sizeof(Pkt),
|
||||
16,
|
||||
15,
|
||||
pkt__field_descriptors,
|
||||
pkt__field_indices_by_name,
|
||||
6, pkt__number_ranges,
|
||||
|
155
lightning.pb-c.h
155
lightning.pb-c.h
@ -32,9 +32,8 @@ typedef struct _UpdateFailHtlc UpdateFailHtlc;
|
||||
typedef struct _UpdateAccept UpdateAccept;
|
||||
typedef struct _UpdateSignature UpdateSignature;
|
||||
typedef struct _UpdateComplete UpdateComplete;
|
||||
typedef struct _CloseChannel CloseChannel;
|
||||
typedef struct _CloseChannelComplete CloseChannelComplete;
|
||||
typedef struct _CloseChannelAck CloseChannelAck;
|
||||
typedef struct _CloseClearing CloseClearing;
|
||||
typedef struct _CloseSignature CloseSignature;
|
||||
typedef struct _Error Error;
|
||||
typedef struct _Pkt Pkt;
|
||||
|
||||
@ -419,53 +418,32 @@ struct _UpdateComplete
|
||||
|
||||
|
||||
/*
|
||||
* Begin cooperative close of channel.
|
||||
* Start clearing out the channel HTLCs so we can close it
|
||||
*/
|
||||
struct _CloseChannel
|
||||
struct _CloseClearing
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
};
|
||||
#define CLOSE_CLEARING__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&close_clearing__descriptor) \
|
||||
}
|
||||
|
||||
|
||||
struct _CloseSignature
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
/*
|
||||
* This is our signature a new transaction which spends the anchor
|
||||
* output to my open->final and your open->final,
|
||||
* as per the last commit tx.
|
||||
*/
|
||||
Signature *sig;
|
||||
/*
|
||||
* Fee to pay for close transaction.
|
||||
* Fee in satoshis.
|
||||
*/
|
||||
uint64_t close_fee;
|
||||
};
|
||||
#define CLOSE_CHANNEL__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&close_channel__descriptor) \
|
||||
, NULL, 0 }
|
||||
|
||||
|
||||
/*
|
||||
* OK, here's my sig so you can broadcast it too. We're done.
|
||||
*/
|
||||
struct _CloseChannelComplete
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
/*
|
||||
* This is my signature for that same tx.
|
||||
* Signature on the close transaction.
|
||||
*/
|
||||
Signature *sig;
|
||||
};
|
||||
#define CLOSE_CHANNEL_COMPLETE__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&close_channel_complete__descriptor) \
|
||||
, NULL }
|
||||
|
||||
|
||||
/*
|
||||
* Received close_channel_complete, you can close now.
|
||||
*/
|
||||
struct _CloseChannelAck
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
};
|
||||
#define CLOSE_CHANNEL_ACK__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&close_channel_ack__descriptor) \
|
||||
}
|
||||
#define CLOSE_SIGNATURE__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&close_signature__descriptor) \
|
||||
, 0, NULL }
|
||||
|
||||
|
||||
/*
|
||||
@ -495,9 +473,8 @@ typedef enum {
|
||||
PKT__PKT_UPDATE_DECLINE_HTLC = 6,
|
||||
PKT__PKT_UPDATE_FULFILL_HTLC = 7,
|
||||
PKT__PKT_UPDATE_FAIL_HTLC = 9,
|
||||
PKT__PKT_CLOSE = 30,
|
||||
PKT__PKT_CLOSE_COMPLETE = 31,
|
||||
PKT__PKT_CLOSE_ACK = 32,
|
||||
PKT__PKT_CLOSE_CLEARING = 30,
|
||||
PKT__PKT_CLOSE_SIGNATURE = 31,
|
||||
PKT__PKT_ERROR = 40,
|
||||
} Pkt__PktCase;
|
||||
|
||||
@ -533,9 +510,8 @@ struct _Pkt
|
||||
/*
|
||||
* Closing
|
||||
*/
|
||||
CloseChannel *close;
|
||||
CloseChannelComplete *close_complete;
|
||||
CloseChannelAck *close_ack;
|
||||
CloseClearing *close_clearing;
|
||||
CloseSignature *close_signature;
|
||||
/*
|
||||
* Unexpected issue.
|
||||
*/
|
||||
@ -870,62 +846,43 @@ UpdateComplete *
|
||||
void update_complete__free_unpacked
|
||||
(UpdateComplete *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* CloseChannel methods */
|
||||
void close_channel__init
|
||||
(CloseChannel *message);
|
||||
size_t close_channel__get_packed_size
|
||||
(const CloseChannel *message);
|
||||
size_t close_channel__pack
|
||||
(const CloseChannel *message,
|
||||
/* CloseClearing methods */
|
||||
void close_clearing__init
|
||||
(CloseClearing *message);
|
||||
size_t close_clearing__get_packed_size
|
||||
(const CloseClearing *message);
|
||||
size_t close_clearing__pack
|
||||
(const CloseClearing *message,
|
||||
uint8_t *out);
|
||||
size_t close_channel__pack_to_buffer
|
||||
(const CloseChannel *message,
|
||||
size_t close_clearing__pack_to_buffer
|
||||
(const CloseClearing *message,
|
||||
ProtobufCBuffer *buffer);
|
||||
CloseChannel *
|
||||
close_channel__unpack
|
||||
CloseClearing *
|
||||
close_clearing__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data);
|
||||
void close_channel__free_unpacked
|
||||
(CloseChannel *message,
|
||||
void close_clearing__free_unpacked
|
||||
(CloseClearing *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* CloseChannelComplete methods */
|
||||
void close_channel_complete__init
|
||||
(CloseChannelComplete *message);
|
||||
size_t close_channel_complete__get_packed_size
|
||||
(const CloseChannelComplete *message);
|
||||
size_t close_channel_complete__pack
|
||||
(const CloseChannelComplete *message,
|
||||
/* CloseSignature methods */
|
||||
void close_signature__init
|
||||
(CloseSignature *message);
|
||||
size_t close_signature__get_packed_size
|
||||
(const CloseSignature *message);
|
||||
size_t close_signature__pack
|
||||
(const CloseSignature *message,
|
||||
uint8_t *out);
|
||||
size_t close_channel_complete__pack_to_buffer
|
||||
(const CloseChannelComplete *message,
|
||||
size_t close_signature__pack_to_buffer
|
||||
(const CloseSignature *message,
|
||||
ProtobufCBuffer *buffer);
|
||||
CloseChannelComplete *
|
||||
close_channel_complete__unpack
|
||||
CloseSignature *
|
||||
close_signature__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data);
|
||||
void close_channel_complete__free_unpacked
|
||||
(CloseChannelComplete *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* CloseChannelAck methods */
|
||||
void close_channel_ack__init
|
||||
(CloseChannelAck *message);
|
||||
size_t close_channel_ack__get_packed_size
|
||||
(const CloseChannelAck *message);
|
||||
size_t close_channel_ack__pack
|
||||
(const CloseChannelAck *message,
|
||||
uint8_t *out);
|
||||
size_t close_channel_ack__pack_to_buffer
|
||||
(const CloseChannelAck *message,
|
||||
ProtobufCBuffer *buffer);
|
||||
CloseChannelAck *
|
||||
close_channel_ack__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data);
|
||||
void close_channel_ack__free_unpacked
|
||||
(CloseChannelAck *message,
|
||||
void close_signature__free_unpacked
|
||||
(CloseSignature *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* Error methods */
|
||||
void error__init
|
||||
@ -1018,14 +975,11 @@ typedef void (*UpdateSignature_Closure)
|
||||
typedef void (*UpdateComplete_Closure)
|
||||
(const UpdateComplete *message,
|
||||
void *closure_data);
|
||||
typedef void (*CloseChannel_Closure)
|
||||
(const CloseChannel *message,
|
||||
typedef void (*CloseClearing_Closure)
|
||||
(const CloseClearing *message,
|
||||
void *closure_data);
|
||||
typedef void (*CloseChannelComplete_Closure)
|
||||
(const CloseChannelComplete *message,
|
||||
void *closure_data);
|
||||
typedef void (*CloseChannelAck_Closure)
|
||||
(const CloseChannelAck *message,
|
||||
typedef void (*CloseSignature_Closure)
|
||||
(const CloseSignature *message,
|
||||
void *closure_data);
|
||||
typedef void (*Error_Closure)
|
||||
(const Error *message,
|
||||
@ -1057,9 +1011,8 @@ 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 close_channel__descriptor;
|
||||
extern const ProtobufCMessageDescriptor close_channel_complete__descriptor;
|
||||
extern const ProtobufCMessageDescriptor close_channel_ack__descriptor;
|
||||
extern const ProtobufCMessageDescriptor close_clearing__descriptor;
|
||||
extern const ProtobufCMessageDescriptor close_signature__descriptor;
|
||||
extern const ProtobufCMessageDescriptor error__descriptor;
|
||||
extern const ProtobufCMessageDescriptor pkt__descriptor;
|
||||
|
||||
|
@ -171,24 +171,15 @@ message update_complete {
|
||||
required sha256_hash revocation_preimage = 1;
|
||||
}
|
||||
|
||||
// Begin cooperative close of channel.
|
||||
message close_channel {
|
||||
// This is our signature a new transaction which spends the anchor
|
||||
// output to my open->final and your open->final,
|
||||
// as per the last commit tx.
|
||||
required signature sig = 1;
|
||||
// Fee to pay for close transaction.
|
||||
required uint64 close_fee = 2;
|
||||
// Start clearing out the channel HTLCs so we can close it
|
||||
message close_clearing {
|
||||
}
|
||||
|
||||
// OK, here's my sig so you can broadcast it too. We're done.
|
||||
message close_channel_complete {
|
||||
// This is my signature for that same tx.
|
||||
required signature sig = 1;
|
||||
}
|
||||
|
||||
// Received close_channel_complete, you can close now.
|
||||
message close_channel_ack {
|
||||
message close_signature {
|
||||
// Fee in satoshis.
|
||||
required uint64 close_fee = 1;
|
||||
// Signature on the close transaction.
|
||||
required signature sig = 2;
|
||||
}
|
||||
|
||||
// This means we're going to hang up; it's to help diagnose only!
|
||||
@ -215,9 +206,8 @@ message pkt {
|
||||
update_fulfill_htlc update_fulfill_htlc = 7;
|
||||
update_fail_htlc update_fail_htlc = 9;
|
||||
// Closing
|
||||
close_channel close = 30;
|
||||
close_channel_complete close_complete = 31;
|
||||
close_channel_ack close_ack = 32;
|
||||
close_clearing close_clearing = 30;
|
||||
close_signature close_signature = 31;
|
||||
|
||||
// Unexpected issue.
|
||||
error error = 40;
|
||||
|
276
state.c
276
state.c
@ -276,14 +276,14 @@ enum command_status state(const tal_t *ctx,
|
||||
BITCOIN_ANCHOR_DEPTHOK,
|
||||
INPUT_NONE);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto start_closing;
|
||||
} else if (input_is(input, PKT_CLOSE)) {
|
||||
goto start_clearing;
|
||||
} else if (input_is(input, PKT_CLOSE_CLEARING)) {
|
||||
/* We no longer care about anchor depth. */
|
||||
peer_unwatch_anchor_depth(peer,
|
||||
BITCOIN_ANCHOR_DEPTHOK,
|
||||
INPUT_NONE);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto accept_closing;
|
||||
goto accept_clearing;
|
||||
} else if (input_is_pkt(input)) {
|
||||
/* We no longer care about anchor depth. */
|
||||
peer_unwatch_anchor_depth(peer,
|
||||
@ -344,14 +344,14 @@ enum command_status state(const tal_t *ctx,
|
||||
BITCOIN_ANCHOR_DEPTHOK,
|
||||
BITCOIN_ANCHOR_TIMEOUT);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto start_closing;
|
||||
} else if (input_is(input, PKT_CLOSE)) {
|
||||
goto start_clearing;
|
||||
} else if (input_is(input, PKT_CLOSE_CLEARING)) {
|
||||
/* We no longer care about anchor depth. */
|
||||
peer_unwatch_anchor_depth(peer,
|
||||
BITCOIN_ANCHOR_DEPTHOK,
|
||||
BITCOIN_ANCHOR_TIMEOUT);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto accept_closing;
|
||||
goto accept_clearing;
|
||||
} else if (input_is_pkt(input)) {
|
||||
/* We no longer care about anchor depth. */
|
||||
peer_unwatch_anchor_depth(peer,
|
||||
@ -387,10 +387,10 @@ enum command_status state(const tal_t *ctx,
|
||||
goto them_unilateral;
|
||||
} else if (input_is(input, CMD_CLOSE)) {
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto start_closing;
|
||||
} else if (input_is(input, PKT_CLOSE)) {
|
||||
goto start_clearing;
|
||||
} else if (input_is(input, PKT_CLOSE_CLEARING)) {
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto accept_closing;
|
||||
goto accept_clearing;
|
||||
} else if (input_is_pkt(input)) {
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto unexpected_pkt;
|
||||
@ -427,7 +427,7 @@ enum command_status state(const tal_t *ctx,
|
||||
return next_state(peer, cstatus,
|
||||
prio(peer->state, STATE_WAIT_FOR_UPDATE_ACCEPT));
|
||||
} else if (input_is(input, CMD_CLOSE)) {
|
||||
goto start_closing;
|
||||
goto start_clearing;
|
||||
} else if (input_is(input, PKT_UPDATE_ADD_HTLC)) {
|
||||
change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY);
|
||||
goto accept_htlc_add;
|
||||
@ -443,8 +443,8 @@ enum command_status state(const tal_t *ctx,
|
||||
goto old_commit_spotted;
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) {
|
||||
goto anchor_unspent;
|
||||
} else if (input_is(input, PKT_CLOSE)) {
|
||||
goto accept_closing;
|
||||
} else if (input_is(input, PKT_CLOSE_CLEARING)) {
|
||||
goto accept_clearing;
|
||||
} else if (input_is_pkt(input)) {
|
||||
goto unexpected_pkt;
|
||||
}
|
||||
@ -522,11 +522,11 @@ enum command_status state(const tal_t *ctx,
|
||||
} else if (input_is(input, CMD_CLOSE)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto start_closing;
|
||||
} else if (input_is(input, PKT_CLOSE)) {
|
||||
goto start_clearing;
|
||||
} else if (input_is(input, PKT_CLOSE_CLEARING)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto accept_closing;
|
||||
goto accept_clearing;
|
||||
} else if (input_is_pkt(input)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
@ -558,14 +558,14 @@ enum command_status state(const tal_t *ctx,
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto old_commit_spotted;
|
||||
} else if (input_is(input, PKT_CLOSE)) {
|
||||
} else if (input_is(input, PKT_CLOSE_CLEARING)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto accept_closing;
|
||||
goto accept_clearing;
|
||||
} else if (input_is(input, CMD_CLOSE)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto start_closing;
|
||||
goto start_clearing;
|
||||
} else if (input_is_pkt(input)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
@ -599,81 +599,81 @@ enum command_status state(const tal_t *ctx,
|
||||
goto old_commit_spotted;
|
||||
} else if (input_is(input, CMD_CLOSE)) {
|
||||
peer_htlc_aborted(peer);
|
||||
goto start_closing;
|
||||
} else if (input_is(input, PKT_CLOSE)) {
|
||||
goto start_clearing;
|
||||
} else if (input_is(input, PKT_CLOSE_CLEARING)) {
|
||||
peer_htlc_aborted(peer);
|
||||
goto accept_closing;
|
||||
goto accept_clearing;
|
||||
} else if (input_is_pkt(input)) {
|
||||
peer_htlc_aborted(peer);
|
||||
goto unexpected_pkt;
|
||||
}
|
||||
break;
|
||||
case STATE_US_CLEARING:
|
||||
/* This is their reply once they're clearing too. */
|
||||
if (input_is(input, PKT_CLOSE_CLEARING)) {
|
||||
err = accept_pkt_close_clearing(ctx, peer, idata->pkt);
|
||||
if (err)
|
||||
goto err_start_unilateral_close;
|
||||
|
||||
case STATE_WAIT_FOR_CLOSE_COMPLETE:
|
||||
if (input_is(input, PKT_CLOSE_COMPLETE)) {
|
||||
peer_unwatch_close_timeout(peer,
|
||||
INPUT_CLOSE_COMPLETE_TIMEOUT);
|
||||
err = accept_pkt_close_complete(ctx, peer, idata->pkt);
|
||||
if (err)
|
||||
goto err_start_unilateral_close_already_closing;
|
||||
queue_pkt(out,
|
||||
pkt_close_ack(ctx, peer));
|
||||
queue_tx_broadcast(broadcast, bitcoin_close(ctx, peer));
|
||||
change_peer_cond(peer, PEER_CLOSING, PEER_CLOSED);
|
||||
return next_state(peer, cstatus, STATE_CLOSE_WAIT_CLOSE);
|
||||
} else if (input_is(input, PKT_CLOSE)) {
|
||||
peer_unwatch_close_timeout(peer,
|
||||
INPUT_CLOSE_COMPLETE_TIMEOUT);
|
||||
/* We can use the sig just like CLOSE_COMPLETE */
|
||||
err = accept_pkt_simultaneous_close(ctx, peer,
|
||||
idata->pkt);
|
||||
if (err)
|
||||
goto err_start_unilateral_close_already_closing;
|
||||
queue_pkt(out,
|
||||
pkt_close_ack(ctx, peer));
|
||||
queue_tx_broadcast(broadcast, bitcoin_close(ctx, peer));
|
||||
set_peer_cond(peer, PEER_CLOSED);
|
||||
return next_state(peer, cstatus, STATE_CLOSE_WAIT_CLOSE);
|
||||
} else if (input_is(input, PKT_ERROR)) {
|
||||
peer_unwatch_close_timeout(peer,
|
||||
INPUT_CLOSE_COMPLETE_TIMEOUT);
|
||||
peer_unexpected_pkt(peer, idata->pkt);
|
||||
goto start_unilateral_close_already_closing;
|
||||
/* Notify us when there are no more htlcs in
|
||||
* either commit tx */
|
||||
peer_watch_htlcs_cleared(peer, INPUT_HTLCS_CLEARED);
|
||||
|
||||
return next_state(peer, cstatus, STATE_BOTH_CLEARING);
|
||||
/* FIXME: We must continue to allow fulfill & fail! */
|
||||
} else if (input_is(input, CMD_SEND_HTLC_FAIL)
|
||||
|| input_is(input, CMD_SEND_HTLC_FULFILL)) {
|
||||
err = pkt_err(ctx, "FIXME: cmd during clearing.");
|
||||
goto err_start_unilateral_close;
|
||||
} else if (input_is_pkt(input)) {
|
||||
/* We ignore all other packets while closing. */
|
||||
/* FIXME: We must continue to allow add, fulfill & fail packets */
|
||||
goto unexpected_pkt;
|
||||
}
|
||||
break;
|
||||
case STATE_BOTH_CLEARING:
|
||||
if (input_is(input, INPUT_HTLCS_CLEARED)) {
|
||||
goto start_closing_cleared;
|
||||
} else if (input_is(input, CMD_SEND_HTLC_FAIL)
|
||||
|| input_is(input, CMD_SEND_HTLC_FULFILL)) {
|
||||
err = pkt_err(ctx, "FIXME: cmd during clearing.");
|
||||
goto err_start_unilateral_close;
|
||||
} else if (input_is_pkt(input)) {
|
||||
/* FIXME: We must continue to allow fulfill & fail packets */
|
||||
goto unexpected_pkt;
|
||||
}
|
||||
break;
|
||||
case STATE_WAIT_FOR_CLOSE_SIG:
|
||||
if (input_is(input, PKT_CLOSE_SIGNATURE)) {
|
||||
bool matches;
|
||||
err = accept_pkt_close_sig(ctx, peer, idata->pkt,
|
||||
&matches);
|
||||
if (err)
|
||||
goto err_start_unilateral_close;
|
||||
|
||||
/* Did they offer the same fee we did? */
|
||||
if (matches) {
|
||||
peer_unwatch_close_timeout(peer,
|
||||
INPUT_CLOSE_COMPLETE_TIMEOUT);
|
||||
|
||||
/* Send close TX. */
|
||||
queue_tx_broadcast(broadcast,
|
||||
bitcoin_close(ctx, peer));
|
||||
change_peer_cond(peer,
|
||||
PEER_CLOSING, PEER_CLOSED);
|
||||
return next_state(peer, cstatus,
|
||||
STATE_CLOSE_WAIT_CLOSE);
|
||||
}
|
||||
|
||||
/* Offer the new fee. */
|
||||
queue_pkt(out, pkt_close_signature(ctx, peer));
|
||||
return unchanged_state(cstatus);
|
||||
} else if (input_is(input, INPUT_CLOSE_COMPLETE_TIMEOUT)) {
|
||||
/* They didn't respond in time. Unilateral close. */
|
||||
err = pkt_err(ctx, "Close timed out");
|
||||
goto err_start_unilateral_close_already_closing;
|
||||
}
|
||||
peer_unwatch_close_timeout(peer, INPUT_CLOSE_COMPLETE_TIMEOUT);
|
||||
goto fail_during_close;
|
||||
|
||||
case STATE_WAIT_FOR_CLOSE_ACK:
|
||||
if (input_is(input, PKT_CLOSE_ACK)) {
|
||||
err = accept_pkt_close_ack(ctx, peer, idata->pkt);
|
||||
if (err)
|
||||
queue_pkt(out, err);
|
||||
set_peer_cond(peer, PEER_CLOSED);
|
||||
/* Just wait for close to happen now. */
|
||||
return next_state(peer, cstatus, STATE_CLOSE_WAIT_CLOSE);
|
||||
goto err_start_unilateral_close;
|
||||
} else if (input_is_pkt(input)) {
|
||||
peer_unexpected_pkt(peer, idata->pkt);
|
||||
/* Don't reply to an error with an error. */
|
||||
if (!input_is(input, PKT_ERROR)) {
|
||||
queue_pkt(out,
|
||||
pkt_err_unexpected(ctx, idata->pkt));
|
||||
goto unexpected_pkt;
|
||||
}
|
||||
set_peer_cond(peer, PEER_CLOSED);
|
||||
/* Just wait for close to happen now. */
|
||||
return next_state(peer, cstatus, STATE_CLOSE_WAIT_CLOSE);
|
||||
} else if (input_is(input, BITCOIN_CLOSE_DONE)) {
|
||||
/* They didn't ack, but we're closed, so stop. */
|
||||
set_peer_cond(peer, PEER_CLOSED);
|
||||
return next_state(peer, cstatus, STATE_CLOSED);
|
||||
}
|
||||
goto fail_during_close;
|
||||
break;
|
||||
|
||||
/* Close states are regular: handle as a group. */
|
||||
case STATE_CLOSE_WAIT_HTLCS:
|
||||
@ -949,8 +949,20 @@ start_unilateral_close:
|
||||
/*
|
||||
* Close unilaterally.
|
||||
*/
|
||||
|
||||
/* No more inputs, no more commands. */
|
||||
set_peer_cond(peer, PEER_CLOSED);
|
||||
|
||||
/*
|
||||
* If they sent us a close tx, that's always cheaper than
|
||||
* broadcasting our last commit tx, and our funds are not
|
||||
* timelocked.
|
||||
*/
|
||||
if (peer_has_close_sig(peer)) {
|
||||
queue_tx_broadcast(broadcast, bitcoin_close(ctx, peer));
|
||||
return next_state(peer, cstatus, STATE_CLOSE_WAIT_CLOSE);
|
||||
}
|
||||
|
||||
tx = bitcoin_commit(ctx, peer);
|
||||
queue_tx_broadcast(broadcast, tx);
|
||||
peer_watch_delayed(peer, tx, BITCOIN_ANCHOR_OURCOMMIT_DELAYPASSED);
|
||||
@ -965,28 +977,6 @@ start_unilateral_close:
|
||||
|
||||
return next_state(peer, cstatus, STATE_CLOSE_WAIT_OURCOMMIT);
|
||||
|
||||
err_start_unilateral_close_already_closing:
|
||||
/*
|
||||
* They timed out, or were broken; we are going to close unilaterally.
|
||||
*/
|
||||
queue_pkt(out, err);
|
||||
|
||||
start_unilateral_close_already_closing:
|
||||
/*
|
||||
* Close unilaterally.
|
||||
*/
|
||||
/* No more inputs, no more commands. */
|
||||
set_peer_cond(peer, PEER_CLOSED);
|
||||
tx = bitcoin_commit(ctx, peer);
|
||||
queue_tx_broadcast(broadcast, tx);
|
||||
peer_watch_delayed(peer, tx, BITCOIN_ANCHOR_OURCOMMIT_DELAYPASSED);
|
||||
|
||||
/* We agreed to close: shouldn't have any HTLCs */
|
||||
if (committed_to_htlcs(peer))
|
||||
return next_state(peer, cstatus, STATE_ERR_INTERNAL);
|
||||
|
||||
return next_state(peer, cstatus, STATE_CLOSE_WAIT_CLOSE_OURCOMMIT);
|
||||
|
||||
them_unilateral:
|
||||
assert(input == BITCOIN_ANCHOR_THEIRSPEND);
|
||||
|
||||
@ -1045,35 +1035,39 @@ accept_htlc_fulfill:
|
||||
return next_state(peer, cstatus,
|
||||
prio(peer->state, STATE_WAIT_FOR_UPDATE_SIG));
|
||||
|
||||
start_closing:
|
||||
start_clearing:
|
||||
/*
|
||||
* Start a mutual close.
|
||||
* Start a mutual close: tell them we want to clear.
|
||||
*/
|
||||
/* Protocol doesn't (currently?) allow closing with HTLCs. */
|
||||
if (committed_to_htlcs(peer)) {
|
||||
err = pkt_err(ctx, "Close forced due to HTLCs");
|
||||
goto err_start_unilateral_close;
|
||||
}
|
||||
peer_watch_close(peer, BITCOIN_CLOSE_DONE, INPUT_CLOSE_COMPLETE_TIMEOUT);
|
||||
queue_pkt(out, pkt_close_clearing(ctx, peer));
|
||||
|
||||
/* No more commands, we're already closing. */
|
||||
set_peer_cond(peer, PEER_CLOSING);
|
||||
|
||||
/* As soon as we send packet, they could close. */
|
||||
queue_pkt(out, pkt_close(ctx, peer));
|
||||
return next_state(peer, cstatus, STATE_WAIT_FOR_CLOSE_COMPLETE);
|
||||
return next_state(peer, cstatus, STATE_US_CLEARING);
|
||||
|
||||
accept_closing:
|
||||
err = accept_pkt_close(ctx, peer, idata->pkt);
|
||||
start_closing_cleared:
|
||||
/* As soon as we send packet, they could close. */
|
||||
peer_calculate_close_fee(peer);
|
||||
peer_watch_close(peer, BITCOIN_CLOSE_DONE, INPUT_CLOSE_COMPLETE_TIMEOUT);
|
||||
queue_pkt(out, pkt_close_signature(ctx, peer));
|
||||
return next_state(peer, cstatus, STATE_WAIT_FOR_CLOSE_SIG);
|
||||
|
||||
accept_clearing:
|
||||
err = accept_pkt_close_clearing(ctx, peer, idata->pkt);
|
||||
if (err)
|
||||
goto err_start_unilateral_close;
|
||||
peer_watch_close(peer, BITCOIN_CLOSE_DONE, INPUT_NONE);
|
||||
/* Send close TX. */
|
||||
queue_tx_broadcast(broadcast, bitcoin_close(ctx, peer));
|
||||
queue_pkt(out, pkt_close_complete(ctx, peer));
|
||||
|
||||
/* Notify us when there are no more htlcs in either commit tx */
|
||||
peer_watch_htlcs_cleared(peer, INPUT_HTLCS_CLEARED);
|
||||
|
||||
/* No more commands, we're already closing. */
|
||||
set_peer_cond(peer, PEER_CLOSING);
|
||||
return next_state(peer, cstatus, STATE_WAIT_FOR_CLOSE_ACK);
|
||||
|
||||
/* Tell them we're clearing too. */
|
||||
queue_pkt(out, pkt_close_clearing(ctx, peer));
|
||||
|
||||
return next_state(peer, cstatus, STATE_BOTH_CLEARING);
|
||||
|
||||
instant_close:
|
||||
/*
|
||||
@ -1088,48 +1082,6 @@ instant_close:
|
||||
return next_state(peer, cstatus, STATE_ERR_INTERNAL);
|
||||
return next_state(peer, cstatus, STATE_CLOSED);
|
||||
|
||||
fail_during_close:
|
||||
/*
|
||||
* We've broadcast close tx; if anything goes wrong, we just close
|
||||
* connection and wait.
|
||||
*/
|
||||
set_peer_cond(peer, PEER_CLOSED);
|
||||
|
||||
/* Once close tx is deep enough, we consider it done. */
|
||||
if (input_is(input, BITCOIN_CLOSE_DONE)) {
|
||||
return next_state(peer, cstatus, STATE_CLOSED);
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) {
|
||||
/* A reorganization could make this happen. */
|
||||
tx = bitcoin_spend_theirs(ctx, peer, idata->btc);
|
||||
queue_tx_broadcast(broadcast, tx);
|
||||
peer_watch_tx(peer, tx, BITCOIN_SPEND_THEIRS_DONE);
|
||||
if (peer_watch_their_htlc_outputs(peer, idata->btc,
|
||||
BITCOIN_HTLC_TOUS_TIMEOUT,
|
||||
BITCOIN_HTLC_TOTHEM_SPENT,
|
||||
BITCOIN_HTLC_TOTHEM_TIMEOUT)) {
|
||||
/* Expect either close or spendthem to complete */
|
||||
/* FIXME: Make sure caller uses INPUT_RVAL
|
||||
* if they were in the middle of FULFILL! */
|
||||
return next_state(peer, cstatus,
|
||||
STATE_CLOSE_WAIT_SPENDTHEM_CLOSE_WITH_HTLCS);
|
||||
}
|
||||
return next_state(peer, cstatus,
|
||||
STATE_CLOSE_WAIT_SPENDTHEM_CLOSE);
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_OTHERSPEND)) {
|
||||
tx = bitcoin_steal(ctx, peer, idata->btc);
|
||||
if (!tx)
|
||||
return next_state(peer, cstatus,
|
||||
STATE_ERR_INFORMATION_LEAK);
|
||||
queue_tx_broadcast(broadcast, tx);
|
||||
peer_watch_tx(peer, tx, BITCOIN_STEAL_DONE);
|
||||
/* Expect either close or steal to complete */
|
||||
return next_state(peer, cstatus,
|
||||
STATE_CLOSE_WAIT_STEAL_CLOSE);
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) {
|
||||
return next_state(peer, cstatus, STATE_ERR_ANCHOR_LOST);
|
||||
}
|
||||
return next_state(peer, cstatus, STATE_ERR_INTERNAL);
|
||||
|
||||
old_commit_spotted:
|
||||
/*
|
||||
* bitcoind reported a broadcast of the not-latest commit tx.
|
||||
|
40
state.h
40
state.h
@ -111,9 +111,8 @@ Pkt *pkt_update_accept(const tal_t *ctx, const struct peer *peer);
|
||||
Pkt *pkt_update_signature(const tal_t *ctx, const struct peer *peer);
|
||||
Pkt *pkt_update_complete(const tal_t *ctx, const struct peer *peer);
|
||||
Pkt *pkt_err(const tal_t *ctx, const char *fmt, ...);
|
||||
Pkt *pkt_close(const tal_t *ctx, const struct peer *peer);
|
||||
Pkt *pkt_close_complete(const tal_t *ctx, const struct peer *peer);
|
||||
Pkt *pkt_close_ack(const tal_t *ctx, const struct peer *peer);
|
||||
Pkt *pkt_close_clearing(const tal_t *ctx, const struct peer *peer);
|
||||
Pkt *pkt_close_signature(const tal_t *ctx, const struct peer *peer);
|
||||
Pkt *pkt_err_unexpected(const tal_t *ctx, const Pkt *pkt);
|
||||
|
||||
/* Process various packets: return an error packet on failure. */
|
||||
@ -151,16 +150,9 @@ Pkt *accept_pkt_update_signature(const tal_t *ctx,
|
||||
struct peer *peer,
|
||||
const Pkt *pkt);
|
||||
|
||||
Pkt *accept_pkt_close(const tal_t *ctx, struct peer *peer, const Pkt *pkt);
|
||||
|
||||
Pkt *accept_pkt_close_complete(const tal_t *ctx,
|
||||
struct peer *peer, const Pkt *pkt);
|
||||
|
||||
Pkt *accept_pkt_simultaneous_close(const tal_t *ctx,
|
||||
struct peer *peer,
|
||||
const Pkt *pkt);
|
||||
|
||||
Pkt *accept_pkt_close_ack(const tal_t *ctx, struct peer *peer, const Pkt *pkt);
|
||||
Pkt *accept_pkt_close_clearing(const tal_t *ctx, struct peer *peer, const Pkt *pkt);
|
||||
Pkt *accept_pkt_close_sig(const tal_t *ctx, struct peer *peer, const Pkt *pkt,
|
||||
bool *matches);
|
||||
|
||||
/**
|
||||
* committed_to_htlcs: do we have any locked-in HTLCs?
|
||||
@ -170,6 +162,14 @@ Pkt *accept_pkt_close_ack(const tal_t *ctx, struct peer *peer, const Pkt *pkt);
|
||||
*/
|
||||
bool committed_to_htlcs(const struct peer *peer);
|
||||
|
||||
/**
|
||||
* peer_has_close_sig: do we have a valid close_sig from them?
|
||||
* @peer: the state data for this peer.
|
||||
*
|
||||
* We use any acceptable close tx, if we have one, in preference to a commit tx.
|
||||
*/
|
||||
bool peer_has_close_sig(const struct peer *peer);
|
||||
|
||||
/**
|
||||
* peer_watch_anchor: create a watch for the anchor transaction.
|
||||
* @peer: the state data for this peer.
|
||||
@ -336,6 +336,20 @@ void peer_unwatch_htlc_spend(struct peer *peer,
|
||||
const struct htlc *htlc,
|
||||
enum state_input all_done);
|
||||
|
||||
/**
|
||||
* peer_watch_htlcs_cleared: tell us when no HTLCs are in commit txs.
|
||||
* @peer: the state data for this peer.
|
||||
* @all_done: input to give when all HTLCs are done.
|
||||
*/
|
||||
void peer_watch_htlcs_cleared(struct peer *peer,
|
||||
enum state_input all_done);
|
||||
|
||||
/**
|
||||
* peer_calculate_close_fee: figure out what the fee for closing is.
|
||||
* @peer: the state data for this peer.
|
||||
*/
|
||||
void peer_calculate_close_fee(struct peer *peer);
|
||||
|
||||
/* Start creation of the bitcoin anchor tx. */
|
||||
void bitcoin_create_anchor(struct peer *peer, enum state_input done);
|
||||
|
||||
|
@ -52,10 +52,12 @@ enum state {
|
||||
/*
|
||||
* Closing.
|
||||
*/
|
||||
/* We told them to close, waiting for complete msg. */
|
||||
STATE_WAIT_FOR_CLOSE_COMPLETE,
|
||||
/* They told us to close, waiting for ack msg. */
|
||||
STATE_WAIT_FOR_CLOSE_ACK,
|
||||
/* We told them to clear. */
|
||||
STATE_US_CLEARING,
|
||||
/* They told us to clear, or acked our CLEARING. */
|
||||
STATE_BOTH_CLEARING,
|
||||
/* We're cleared, waiting for close signature / negotiation */
|
||||
STATE_WAIT_FOR_CLOSE_SIG,
|
||||
|
||||
/* All closed. */
|
||||
STATE_CLOSED,
|
||||
@ -204,9 +206,8 @@ enum state_input {
|
||||
PKT_UPDATE_COMPLETE = PKT__PKT_UPDATE_COMPLETE,
|
||||
|
||||
/* Mutual close sequence. */
|
||||
PKT_CLOSE = PKT__PKT_CLOSE,
|
||||
PKT_CLOSE_COMPLETE = PKT__PKT_CLOSE_COMPLETE,
|
||||
PKT_CLOSE_ACK = PKT__PKT_CLOSE_ACK,
|
||||
PKT_CLOSE_CLEARING = PKT__PKT_CLOSE_CLEARING,
|
||||
PKT_CLOSE_SIGNATURE = PKT__PKT_CLOSE_SIGNATURE,
|
||||
|
||||
/* Something unexpected went wrong. */
|
||||
PKT_ERROR = PKT__PKT_ERROR,
|
||||
@ -256,6 +257,9 @@ enum state_input {
|
||||
/* We are not watching any HTLCs any more. */
|
||||
INPUT_NO_MORE_HTLCS,
|
||||
|
||||
/* No more HTLCs in either commitment tx. */
|
||||
INPUT_HTLCS_CLEARED,
|
||||
|
||||
/*
|
||||
* Timeouts.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user