coin moves: record cheats / loss due to 'unknown' txs

Whenever we detect an 'unknown' tx is published, we should count that as
a loss, as needed.
This commit is contained in:
lisa neigut 2020-04-01 21:41:19 -05:00 committed by Rusty Russell
parent 034b2c7ee4
commit c215a00c45
1 changed files with 76 additions and 1 deletions

View File

@ -243,6 +243,27 @@ static void record_mutual_closure(const struct bitcoin_txid *txid,
send_coin_mvt(take(mvt)); send_coin_mvt(take(mvt));
} }
static void record_coin_loss(const struct bitcoin_txid *txid,
struct tracked_output *out)
{
struct chain_coin_mvt *mvt;
/* We don't for sure know that it's a 'penalty'
* but we write it as that anyway... */
mvt = new_chain_coin_mvt_sat(NULL, NULL,
txid, &out->txid,
out->outnum, NULL,
PENALTY, out->sat, false,
BTC);
if (!mvt)
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"unable to convert %s to msat",
type_to_string(tmpctx, struct amount_sat,
&out->sat));
send_coin_mvt(take(mvt));
}
static void record_channel_withdrawal_minus_fees(const struct bitcoin_txid *tx_txid, static void record_channel_withdrawal_minus_fees(const struct bitcoin_txid *tx_txid,
struct tracked_output *out, struct tracked_output *out,
struct amount_sat fees) struct amount_sat fees)
@ -274,6 +295,12 @@ static void record_channel_withdrawal_minus_fees(const struct bitcoin_txid *tx_t
} }
static void record_channel_withdrawal(const struct bitcoin_txid *tx_txid,
struct tracked_output *out)
{
record_channel_withdrawal_minus_fees(tx_txid, out, AMOUNT_SAT(0));
}
static bool is_our_htlc_tx(struct tracked_output *out) static bool is_our_htlc_tx(struct tracked_output *out)
{ {
return out->resolved && return out->resolved &&
@ -1265,6 +1292,7 @@ static void output_spent(const struct chainparams *chainparams,
case OUTPUT_TO_US: case OUTPUT_TO_US:
case DELAYED_OUTPUT_TO_US: case DELAYED_OUTPUT_TO_US:
unknown_spend(out, tx); unknown_spend(out, tx);
record_coin_loss(&txid, out);
break; break;
case THEIR_HTLC: case THEIR_HTLC:
@ -2747,6 +2775,46 @@ static void handle_their_unilateral(const struct bitcoin_tx *tx,
wait_for_resolved(tx->chainparams, outs); wait_for_resolved(tx->chainparams, outs);
} }
static void update_ledger_unknown(const struct bitcoin_txid *txid,
struct amount_sat amt_salvaged)
{
/* ideally, we'd be able to capture the loss to fees (if we funded
* the channel) here separately, but given that we don't know the htlc
* set (and thus which outputs are trimmed), this is difficult.
*
* instead, we count the difference between any recoverable output
* and our current channel balance as a loss (or gain) */
bool is_credit;
struct amount_msat diff;
struct chain_coin_mvt *mvt;
/* we do nothing if the amount withdrawn via 'salvage' is
* the same as our channel balance */
if (amount_msat_eq_sat(our_msat, amt_salvaged))
return;
/* if we've withdrawn *less* in salvage than we have on the books
* as being ours, we record the difference as a debit */
if (!amount_msat_sub_sat(&diff, our_msat, amt_salvaged)) {
is_credit = false;
if (!amount_sat_sub_msat(&diff, amt_salvaged, our_msat))
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"overflow subtracting %s from %s",
type_to_string(tmpctx, struct amount_msat,
&our_msat),
type_to_string(tmpctx, struct amount_sat,
&amt_salvaged));
} else
is_credit = true;
/* FIXME: elements txs not in BTC ?? */
mvt = new_chain_coin_mvt(NULL, NULL,
txid, NULL, 0, NULL,
JOURNAL, diff,
is_credit, BTC);
send_coin_mvt(take(mvt));
}
static void handle_unknown_commitment(const struct bitcoin_tx *tx, static void handle_unknown_commitment(const struct bitcoin_tx *tx,
u32 tx_blockheight, u32 tx_blockheight,
u64 commit_num, u64 commit_num,
@ -2759,6 +2827,7 @@ static void handle_unknown_commitment(const struct bitcoin_tx *tx,
{ {
int to_us_output = -1; int to_us_output = -1;
u8 *local_script; u8 *local_script;
struct amount_sat amt_salvaged = AMOUNT_SAT(0);
onchain_annotate_txin(txid, 0, TX_CHANNEL_UNILATERAL | TX_THEIRS); onchain_annotate_txin(txid, 0, TX_CHANNEL_UNILATERAL | TX_THEIRS);
@ -2767,8 +2836,9 @@ static void handle_unknown_commitment(const struct bitcoin_tx *tx,
/* If they don't give us a per-commitment point and we rotate keys, /* If they don't give us a per-commitment point and we rotate keys,
* we're out of luck. */ * we're out of luck. */
if (!possible_remote_per_commitment_point if (!possible_remote_per_commitment_point
&& !option_static_remotekey) && !option_static_remotekey) {
goto search_done; goto search_done;
}
if (!option_static_remotekey) { if (!option_static_remotekey) {
struct keyset *ks = tal(tmpctx, struct keyset); struct keyset *ks = tal(tmpctx, struct keyset);
@ -2822,6 +2892,7 @@ static void handle_unknown_commitment(const struct bitcoin_tx *tx,
i, amt, i, amt,
OUTPUT_TO_US, NULL, NULL, NULL); OUTPUT_TO_US, NULL, NULL, NULL);
ignore_output(out); ignore_output(out);
record_channel_withdrawal(txid, out);
tell_wallet_to_remote(tx, i, txid, tell_wallet_to_remote(tx, i, txid,
tx_blockheight, tx_blockheight,
@ -2845,6 +2916,10 @@ search_done:
init_reply("ERROR: Unknown commitment, recovering our funds!"); init_reply("ERROR: Unknown commitment, recovering our funds!");
} }
/* update our accounting notions for this channel.
* should result in a channel balance of zero */
update_ledger_unknown(txid, amt_salvaged);
/* Tell master to give up on HTLCs immediately. */ /* Tell master to give up on HTLCs immediately. */
for (size_t i = 0; i < tal_count(htlcs); i++) { for (size_t i = 0; i < tal_count(htlcs); i++) {
u8 *msg; u8 *msg;