Christian Decker
5 years ago
committed by
Rusty Russell
5 changed files with 146 additions and 3 deletions
@ -0,0 +1,120 @@ |
|||
#include "watchtower.h" |
|||
|
|||
#include <bitcoin/feerate.h> |
|||
#include <bitcoin/script.h> |
|||
#include <bitcoin/signature.h> |
|||
#include <bitcoin/tx.h> |
|||
#include <common/htlc_tx.h> |
|||
#include <common/key_derive.h> |
|||
#include <common/keyset.h> |
|||
#include <common/status.h> |
|||
#include <common/type_to_string.h> |
|||
#include <hsmd/gen_hsm_wire.h> |
|||
#include <wire/wire_sync.h> |
|||
|
|||
static const u8 ONE = 0x1; |
|||
#define HSM_FD 6 |
|||
|
|||
const struct bitcoin_tx * |
|||
penalty_tx_create(const tal_t *ctx, |
|||
const struct channel *channel, |
|||
u32 penalty_feerate, |
|||
u8 *final_scriptpubkey, |
|||
const struct secret *revocation_preimage, |
|||
const struct bitcoin_txid *commitment_txid, |
|||
s16 to_them_outnum, struct amount_sat to_them_sats) |
|||
{ |
|||
u8 *wscript; |
|||
struct bitcoin_tx *tx; |
|||
struct keyset keyset; |
|||
size_t weight; |
|||
u8 *msg; |
|||
struct amount_sat fee, min_out, amt; |
|||
struct bitcoin_signature sig; |
|||
u32 locktime = 0; |
|||
bool option_static_remotekey = channel->option_static_remotekey; |
|||
u8 **witness; |
|||
u32 remote_to_self_delay = channel->config[REMOTE].to_self_delay; |
|||
const struct amount_sat dust_limit = channel->config[LOCAL].dust_limit; |
|||
BUILD_ASSERT(sizeof(struct secret) == sizeof(*revocation_preimage)); |
|||
const struct secret remote_per_commitment_secret = *revocation_preimage; |
|||
struct pubkey remote_per_commitment_point; |
|||
const struct basepoints *basepoints = channel->basepoints; |
|||
|
|||
if (to_them_outnum == -1 || |
|||
amount_sat_less_eq(to_them_sats, dust_limit)) { |
|||
status_unusual( |
|||
"Cannot create penalty transaction because there " |
|||
"is no non-dust to_them output in the commitment."); |
|||
return NULL; |
|||
} |
|||
|
|||
if (!pubkey_from_secret(&remote_per_commitment_secret, &remote_per_commitment_point)) |
|||
status_broken("Failed derive from per_commitment_secret %s", |
|||
type_to_string(tmpctx, struct secret, |
|||
&remote_per_commitment_secret)); |
|||
|
|||
if (!derive_keyset(&remote_per_commitment_point, |
|||
&basepoints[REMOTE], |
|||
&basepoints[LOCAL], |
|||
option_static_remotekey, |
|||
&keyset)) |
|||
abort(); /* TODO(cdecker) Handle a bit more gracefully */ |
|||
|
|||
wscript = bitcoin_wscript_to_local(tmpctx, remote_to_self_delay, |
|||
&keyset.self_revocation_key, |
|||
&keyset.self_delayed_payment_key); |
|||
|
|||
tx = bitcoin_tx(ctx, chainparams, 1, 1, locktime); |
|||
bitcoin_tx_add_input(tx, commitment_txid, to_them_outnum, 0xFFFFFFFF, |
|||
to_them_sats, NULL); |
|||
|
|||
bitcoin_tx_add_output(tx, final_scriptpubkey, to_them_sats); |
|||
|
|||
/* Worst-case sig is 73 bytes */ |
|||
weight = bitcoin_tx_weight(tx) + 1 + 3 + 73 + 0 + tal_count(wscript); |
|||
weight = elements_add_overhead(weight, 1, 1); |
|||
fee = amount_tx_fee(penalty_feerate, weight); |
|||
|
|||
if (!amount_sat_add(&min_out, dust_limit, fee)) |
|||
status_broken( |
|||
"Cannot add dust_limit %s and fee %s", |
|||
type_to_string(tmpctx, struct amount_sat, &dust_limit), |
|||
type_to_string(tmpctx, struct amount_sat, &fee)); |
|||
|
|||
if (amount_sat_less(to_them_sats, min_out)) { |
|||
/* FIXME: We should use SIGHASH_NONE so others can take it */ |
|||
fee = amount_tx_fee(feerate_floor(), weight); |
|||
} |
|||
|
|||
/* This can only happen if feerate_floor() is still too high; shouldn't
|
|||
* happen! */ |
|||
if (!amount_sat_sub(&amt, to_them_sats, fee)) { |
|||
amt = dust_limit; |
|||
status_broken( |
|||
"TX can't afford minimal feerate" |
|||
"; setting output to %s", |
|||
type_to_string(tmpctx, struct amount_sat, &amt)); |
|||
} |
|||
bitcoin_tx_output_set_amount(tx, 0, amt); |
|||
bitcoin_tx_finalize(tx); |
|||
|
|||
u8 *hsm_sign_msg = |
|||
towire_hsm_sign_penalty_to_us(ctx, &remote_per_commitment_secret, tx, |
|||
wscript, *tx->input_amounts[0]); |
|||
|
|||
if (!wire_sync_write(HSM_FD, take(hsm_sign_msg))) |
|||
status_broken("Writing sign request to hsm"); |
|||
|
|||
msg = wire_sync_read(tmpctx, HSM_FD); |
|||
if (!msg || !fromwire_hsm_sign_tx_reply(msg, &sig)) { |
|||
status_broken("Reading sign_tx_reply: %s", tal_hex(tmpctx, msg)); |
|||
abort(); |
|||
} |
|||
|
|||
witness = bitcoin_witness_sig_and_element(tx, &sig, &ONE, sizeof(ONE), |
|||
wscript); |
|||
|
|||
bitcoin_tx_input_set_witness(tx, 0, take(witness)); |
|||
return tx; |
|||
} |
@ -0,0 +1,18 @@ |
|||
#ifndef LIGHTNING_CHANNELD_WATCHTOWER_H |
|||
#define LIGHTNING_CHANNELD_WATCHTOWER_H |
|||
#include "config.h" |
|||
#include <ccan/short_types/short_types.h> |
|||
#include <ccan/tal/tal.h> |
|||
#include <common/derive_basepoints.h> |
|||
#include <common/initial_channel.h> |
|||
|
|||
const struct bitcoin_tx * |
|||
penalty_tx_create(const tal_t *ctx, |
|||
const struct channel *channel, |
|||
u32 penalty_feerate, |
|||
u8 *final_scriptpubkey, |
|||
const struct secret *revocation_preimage, |
|||
const struct bitcoin_txid *commitment_txid, |
|||
s16 to_them_outnum, struct amount_sat to_them_sats); |
|||
|
|||
#endif /* LIGHTNING_CHANNELD_WATCHTOWER_H */ |
Loading…
Reference in new issue