From d1f8509060ea5b733a98f23702226f1edb64d20d Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Thu, 7 May 2020 10:24:26 +0930 Subject: [PATCH] watchtower: Call the commitment_revoked hook every time we update Changelog-Added: plugin: Added a new `commitment_revocation` hook that provides the plugin with penalty transactions for all revoked transactions. --- channeld/channel_wire.csv | 1 + channeld/channeld.c | 13 +++++++++- lightningd/peer_htlcs.c | 51 ++++++++++++++++++++++++++++++++++++++- wallet/test/run-wallet.c | 2 +- 4 files changed, 64 insertions(+), 3 deletions(-) diff --git a/channeld/channel_wire.csv b/channeld/channel_wire.csv index bb8460c75..9a25cc5e0 100644 --- a/channeld/channel_wire.csv +++ b/channeld/channel_wire.csv @@ -154,6 +154,7 @@ msgdata,channel_got_revoke,fee_states,fee_states, msgdata,channel_got_revoke,num_changed,u16, msgdata,channel_got_revoke,changed,changed_htlc,num_changed msgdata,channel_got_revoke,pbase,?penalty_base, +msgdata,channel_got_revoke,penalty_tx,?bitcoin_tx, # Wait for reply, to make sure it's on disk before we continue # (eg. if we sent another commitment_signed, that would implicitly ack). msgtype,channel_got_revoke_reply,1122 diff --git a/channeld/channeld.c b/channeld/channeld.c index 8ae295044..873dde7f1 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -1394,6 +1395,7 @@ static u8 *got_revoke_msg(struct peer *peer, u64 revoke_num, u8 *msg; struct penalty_base *pbase; struct changed_htlc *changed = tal_arr(tmpctx, struct changed_htlc, 0); + const struct bitcoin_tx *ptx = NULL; for (size_t i = 0; i < tal_count(changed_htlcs); i++) { struct changed_htlc c; @@ -1409,9 +1411,18 @@ static u8 *got_revoke_msg(struct peer *peer, u64 revoke_num, } pbase = penalty_base_by_commitnum(tmpctx, peer, revoke_num); + + if (pbase) { + ptx = penalty_tx_create( + NULL, peer->channel, peer->feerate_penalty, + peer->final_scriptpubkey, per_commitment_secret, + &pbase->txid, pbase->outnum, pbase->amount); + } + msg = towire_channel_got_revoke(peer, revoke_num, per_commitment_secret, next_per_commit_point, fee_states, - changed, pbase); + changed, pbase, ptx); + tal_free(ptx); return msg; } diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index ac1093d5b..fdd69b71e 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -1971,6 +1971,41 @@ void update_per_commit_point(struct channel *channel, ci->remote_per_commit = *per_commitment_point; } +struct commitment_revocation_payload { + struct bitcoin_txid commitment_txid; + const struct bitcoin_tx *penalty_tx; + struct wallet *wallet; + u64 channel_id; + u64 commitnum; +}; + +static void commitment_revocation_hook_serialize( + struct commitment_revocation_payload *payload, struct json_stream *stream) +{ + json_add_txid(stream, "commitment_txid", &payload->commitment_txid); + json_add_tx(stream, "penalty_tx", payload->penalty_tx); +} + +static void +commitment_revocation_hook_cb(struct commitment_revocation_payload *p STEALS){ + wallet_penalty_base_delete(p->wallet, p->channel_id, p->commitnum); +} + +static bool +commitment_revocation_hook_deserialize(struct commitment_revocation_payload *p, + const char *buffer, + const jsmntok_t *toks) +{ + return true; +} + + +REGISTER_PLUGIN_HOOK(commitment_revocation, + commitment_revocation_hook_deserialize, + commitment_revocation_hook_cb, + commitment_revocation_hook_serialize, + struct commitment_revocation_payload *); + void peer_got_revoke(struct channel *channel, const u8 *msg) { u64 revokenum; @@ -1983,13 +2018,16 @@ void peer_got_revoke(struct channel *channel, const u8 *msg) struct lightningd *ld = channel->peer->ld; struct fee_states *fee_states; struct penalty_base *pbase; + struct commitment_revocation_payload *payload; + struct bitcoin_tx *penalty_tx; if (!fromwire_channel_got_revoke(msg, msg, &revokenum, &per_commitment_secret, &next_per_commitment_point, &fee_states, &changed, - &pbase) + &pbase, + &penalty_tx) || !fee_states_valid(fee_states, channel->opener)) { channel_internal_error(channel, "bad fromwire_channel_got_revoke %s", tal_hex(channel, msg)); @@ -2082,6 +2120,17 @@ void peer_got_revoke(struct channel *channel, const u8 *msg) : fromwire_peektype(failmsgs[i])); } wallet_channel_save(ld->wallet, channel); + + if (penalty_tx == NULL) + return; + + payload = tal(tmpctx, struct commitment_revocation_payload); + payload->commitment_txid = pbase->txid; + payload->penalty_tx = tal_steal(payload, penalty_tx); + payload->wallet = ld->wallet; + payload->channel_id = channel->dbid; + payload->commitnum = pbase->commitment_num; + plugin_hook_call_commitment_revocation(ld, payload); } diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 1044d9032..6ae1fe4b3 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -116,7 +116,7 @@ bool fromwire_channel_dev_memleak_reply(const void *p UNNEEDED, bool *leak UNNEE bool fromwire_channel_got_commitsig(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *commitnum UNNEEDED, struct fee_states **fee_states UNNEEDED, struct bitcoin_signature *signature UNNEEDED, secp256k1_ecdsa_signature **htlc_signature UNNEEDED, struct added_htlc **added UNNEEDED, struct fulfilled_htlc **fulfilled UNNEEDED, struct failed_htlc ***failed UNNEEDED, struct changed_htlc **changed UNNEEDED, struct bitcoin_tx **tx UNNEEDED) { fprintf(stderr, "fromwire_channel_got_commitsig called!\n"); abort(); } /* Generated stub for fromwire_channel_got_revoke */ -bool fromwire_channel_got_revoke(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *revokenum UNNEEDED, struct secret *per_commitment_secret UNNEEDED, struct pubkey *next_per_commit_point UNNEEDED, struct fee_states **fee_states UNNEEDED, struct changed_htlc **changed UNNEEDED, struct penalty_base **pbase UNNEEDED) +bool fromwire_channel_got_revoke(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *revokenum UNNEEDED, struct secret *per_commitment_secret UNNEEDED, struct pubkey *next_per_commit_point UNNEEDED, struct fee_states **fee_states UNNEEDED, struct changed_htlc **changed UNNEEDED, struct penalty_base **pbase UNNEEDED, struct bitcoin_tx **penalty_tx UNNEEDED) { fprintf(stderr, "fromwire_channel_got_revoke called!\n"); abort(); } /* Generated stub for fromwire_channel_offer_htlc_reply */ bool fromwire_channel_offer_htlc_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *id UNNEEDED, u8 **failuremsg UNNEEDED, wirestring **failurestr UNNEEDED)