mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 07:04:22 +01:00
onchaind: use lightningd to sign and broadcast htlc spending txs.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -557,6 +557,11 @@ struct onchain_signing_info {
|
|||||||
struct bitcoin_signature remote_htlc_sig;
|
struct bitcoin_signature remote_htlc_sig;
|
||||||
struct preimage preimage;
|
struct preimage preimage;
|
||||||
} htlc_success;
|
} htlc_success;
|
||||||
|
/* WIRE_ONCHAIND_SPEND_FULFILL */
|
||||||
|
struct {
|
||||||
|
struct pubkey remote_per_commitment_point;
|
||||||
|
struct preimage preimage;
|
||||||
|
} fulfill;
|
||||||
} u;
|
} u;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -618,6 +623,22 @@ static u8 *sign_htlc_success(const tal_t *ctx,
|
|||||||
info->channel->dbid);
|
info->channel->dbid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u8 *sign_fulfill(const tal_t *ctx,
|
||||||
|
const struct bitcoin_tx *tx,
|
||||||
|
const struct onchain_signing_info *info)
|
||||||
|
{
|
||||||
|
const bool anchor_outputs = channel_has(info->channel, OPT_ANCHOR_OUTPUTS);
|
||||||
|
|
||||||
|
assert(info->msgtype == WIRE_ONCHAIND_SPEND_FULFILL);
|
||||||
|
return towire_hsmd_sign_any_remote_htlc_to_us(ctx,
|
||||||
|
&info->u.fulfill.remote_per_commitment_point,
|
||||||
|
tx, info->wscript,
|
||||||
|
anchor_outputs,
|
||||||
|
0,
|
||||||
|
&info->channel->peer->id,
|
||||||
|
info->channel->dbid);
|
||||||
|
}
|
||||||
|
|
||||||
/* Matches bitcoin_witness_sig_and_element! */
|
/* Matches bitcoin_witness_sig_and_element! */
|
||||||
static const struct onchain_witness_element **
|
static const struct onchain_witness_element **
|
||||||
onchain_witness_sig_and_element(const tal_t *ctx, u8 **witness)
|
onchain_witness_sig_and_element(const tal_t *ctx, u8 **witness)
|
||||||
@@ -913,6 +934,51 @@ static void handle_onchaind_spend_penalty(struct channel *channel,
|
|||||||
__func__);
|
__func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void handle_onchaind_spend_fulfill(struct channel *channel,
|
||||||
|
const u8 *msg)
|
||||||
|
{
|
||||||
|
struct lightningd *ld = channel->peer->ld;
|
||||||
|
struct onchain_signing_info *info;
|
||||||
|
struct bitcoin_outpoint out;
|
||||||
|
struct amount_sat out_sats;
|
||||||
|
struct preimage preimage;
|
||||||
|
u32 initial_feerate;
|
||||||
|
u64 htlc_id;
|
||||||
|
const bool anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS);
|
||||||
|
|
||||||
|
info = new_signing_info(msg, channel, WIRE_ONCHAIND_SPEND_FULFILL);
|
||||||
|
info->minblock = 0;
|
||||||
|
|
||||||
|
if (!fromwire_onchaind_spend_fulfill(info, msg,
|
||||||
|
&out, &out_sats,
|
||||||
|
&htlc_id,
|
||||||
|
&info->u.fulfill.remote_per_commitment_point,
|
||||||
|
&preimage,
|
||||||
|
&info->wscript)) {
|
||||||
|
channel_internal_error(channel, "Invalid onchaind_spend_fulfill %s",
|
||||||
|
tal_hex(tmpctx, msg));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
info->stack_elem = tal_dup(info, struct preimage, &preimage);
|
||||||
|
|
||||||
|
/* FIXME: Be more sophisticated! */
|
||||||
|
initial_feerate = htlc_resolution_feerate(ld->topology);
|
||||||
|
if (!initial_feerate)
|
||||||
|
initial_feerate = tx_feerate(channel->last_tx);
|
||||||
|
|
||||||
|
info->deadline_block = htlc_incoming_deadline(channel, htlc_id);
|
||||||
|
/* BOLT #3:
|
||||||
|
*
|
||||||
|
* Note that if `option_anchors` applies, the nSequence field of
|
||||||
|
* the spending input must be `1`.
|
||||||
|
*/
|
||||||
|
create_onchain_tx(channel, &out, out_sats,
|
||||||
|
anchor_outputs ? 1 : 0,
|
||||||
|
0,
|
||||||
|
initial_feerate, sign_fulfill, info,
|
||||||
|
__func__);
|
||||||
|
}
|
||||||
|
|
||||||
static void handle_onchaind_spend_htlc_success(struct channel *channel,
|
static void handle_onchaind_spend_htlc_success(struct channel *channel,
|
||||||
const u8 *msg)
|
const u8 *msg)
|
||||||
{
|
{
|
||||||
@@ -1048,6 +1114,10 @@ static unsigned int onchain_msg(struct subd *sd, const u8 *msg, const int *fds U
|
|||||||
handle_onchaind_spend_htlc_success(sd->channel, msg);
|
handle_onchaind_spend_htlc_success(sd->channel, msg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case WIRE_ONCHAIND_SPEND_FULFILL:
|
||||||
|
handle_onchaind_spend_fulfill(sd->channel, msg);
|
||||||
|
break;
|
||||||
|
|
||||||
/* We send these, not receive them */
|
/* We send these, not receive them */
|
||||||
case WIRE_ONCHAIND_INIT:
|
case WIRE_ONCHAIND_INIT:
|
||||||
case WIRE_ONCHAIND_SPENT:
|
case WIRE_ONCHAIND_SPENT:
|
||||||
|
|||||||
@@ -1742,7 +1742,7 @@ static void handle_preimage(struct tracked_output **outs,
|
|||||||
ripemd160(&ripemd, &sha, sizeof(sha));
|
ripemd160(&ripemd, &sha, sizeof(sha));
|
||||||
|
|
||||||
for (i = 0; i < tal_count(outs); i++) {
|
for (i = 0; i < tal_count(outs); i++) {
|
||||||
struct bitcoin_tx *tx;
|
const u8 *msg;
|
||||||
|
|
||||||
if (outs[i]->output_type != THEIR_HTLC)
|
if (outs[i]->output_type != THEIR_HTLC)
|
||||||
continue;
|
continue;
|
||||||
@@ -1779,7 +1779,6 @@ static void handle_preimage(struct tracked_output **outs,
|
|||||||
*/
|
*/
|
||||||
if (outs[i]->remote_htlc_sig) {
|
if (outs[i]->remote_htlc_sig) {
|
||||||
struct amount_sat fee;
|
struct amount_sat fee;
|
||||||
const u8 *msg;
|
|
||||||
const u8 *htlc_wscript;
|
const u8 *htlc_wscript;
|
||||||
|
|
||||||
/* FIXME: lightningd could derive this itself? */
|
/* FIXME: lightningd could derive this itself? */
|
||||||
@@ -1802,8 +1801,6 @@ static void handle_preimage(struct tracked_output **outs,
|
|||||||
propose_immediate_resolution(outs[i], take(msg),
|
propose_immediate_resolution(outs[i], take(msg),
|
||||||
OUR_HTLC_SUCCESS_TX);
|
OUR_HTLC_SUCCESS_TX);
|
||||||
} else {
|
} else {
|
||||||
enum tx_type tx_type = THEIR_HTLC_FULFILL_TO_US;
|
|
||||||
|
|
||||||
/* BOLT #5:
|
/* BOLT #5:
|
||||||
*
|
*
|
||||||
* ## HTLC Output Handling: Remote Commitment, Remote
|
* ## HTLC Output Handling: Remote Commitment, Remote
|
||||||
@@ -1817,13 +1814,16 @@ static void handle_preimage(struct tracked_output **outs,
|
|||||||
* - MUST *resolve* the output by spending it to a
|
* - MUST *resolve* the output by spending it to a
|
||||||
* convenient address.
|
* convenient address.
|
||||||
*/
|
*/
|
||||||
tx = tx_to_us(outs[i], remote_htlc_to_us, outs[i],
|
msg = towire_onchaind_spend_fulfill(NULL,
|
||||||
option_anchor_outputs ? 1 : 0,
|
&outs[i]->outpoint,
|
||||||
0, preimage, sizeof(*preimage),
|
outs[i]->sat,
|
||||||
outs[i]->wscript, &tx_type,
|
outs[i]->htlc.id,
|
||||||
htlc_feerate);
|
remote_per_commitment_point,
|
||||||
propose_resolution(outs[i], tx, 0, tx_type);
|
preimage,
|
||||||
|
outs[i]->wscript);
|
||||||
|
|
||||||
|
propose_immediate_resolution(outs[i], take(msg),
|
||||||
|
THEIR_HTLC_FULFILL_TO_US);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1960,6 +1960,7 @@ static void wait_for_resolved(struct tracked_output **outs)
|
|||||||
case WIRE_ONCHAIND_SPEND_TO_US:
|
case WIRE_ONCHAIND_SPEND_TO_US:
|
||||||
case WIRE_ONCHAIND_SPEND_PENALTY:
|
case WIRE_ONCHAIND_SPEND_PENALTY:
|
||||||
case WIRE_ONCHAIND_SPEND_HTLC_SUCCESS:
|
case WIRE_ONCHAIND_SPEND_HTLC_SUCCESS:
|
||||||
|
case WIRE_ONCHAIND_SPEND_FULFILL:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
master_badmsg(-1, msg);
|
master_badmsg(-1, msg);
|
||||||
|
|||||||
@@ -173,6 +173,16 @@ msgdata,onchaind_spend_htlc_success,wscript,u8,wscript_len
|
|||||||
msgdata,onchaind_spend_htlc_success,htlc_wscript_len,u32,
|
msgdata,onchaind_spend_htlc_success,htlc_wscript_len,u32,
|
||||||
msgdata,onchaind_spend_htlc_success,htlc_wscript,u8,htlc_wscript_len
|
msgdata,onchaind_spend_htlc_success,htlc_wscript,u8,htlc_wscript_len
|
||||||
|
|
||||||
|
# We tell lightningd to create, sign and broadcast this HTLC redepmtion:
|
||||||
|
msgtype,onchaind_spend_fulfill,5043
|
||||||
|
msgdata,onchaind_spend_fulfill,outpoint,bitcoin_outpoint,
|
||||||
|
msgdata,onchaind_spend_fulfill,outpoint_amount,amount_sat,
|
||||||
|
msgdata,onchaind_spend_fulfill,htlc_id,u64,
|
||||||
|
msgdata,onchaind_spend_fulfill,remote_per_commitment_point,pubkey,
|
||||||
|
msgdata,onchaind_spend_fulfill,preimage,preimage,
|
||||||
|
msgdata,onchaind_spend_fulfill,wscript_len,u32,
|
||||||
|
msgdata,onchaind_spend_fulfill,wscript,u8,wscript_len
|
||||||
|
|
||||||
subtype,onchain_witness_element
|
subtype,onchain_witness_element
|
||||||
subtypedata,onchain_witness_element,is_signature,bool,
|
subtypedata,onchain_witness_element,is_signature,bool,
|
||||||
subtypedata,onchain_witness_element,len,u32,
|
subtypedata,onchain_witness_element,len,u32,
|
||||||
|
|||||||
|
@@ -282,6 +282,9 @@ u8 *towire_onchaind_missing_htlc_output(const tal_t *ctx UNNEEDED, const struct
|
|||||||
/* Generated stub for towire_onchaind_notify_coin_mvt */
|
/* Generated stub for towire_onchaind_notify_coin_mvt */
|
||||||
u8 *towire_onchaind_notify_coin_mvt(const tal_t *ctx UNNEEDED, const struct chain_coin_mvt *mvt UNNEEDED)
|
u8 *towire_onchaind_notify_coin_mvt(const tal_t *ctx UNNEEDED, const struct chain_coin_mvt *mvt UNNEEDED)
|
||||||
{ fprintf(stderr, "towire_onchaind_notify_coin_mvt called!\n"); abort(); }
|
{ fprintf(stderr, "towire_onchaind_notify_coin_mvt called!\n"); abort(); }
|
||||||
|
/* Generated stub for towire_onchaind_spend_fulfill */
|
||||||
|
u8 *towire_onchaind_spend_fulfill(const tal_t *ctx UNNEEDED, const struct bitcoin_outpoint *outpoint UNNEEDED, struct amount_sat outpoint_amount UNNEEDED, u64 htlc_id UNNEEDED, const struct pubkey *remote_per_commitment_point UNNEEDED, const struct preimage *preimage UNNEEDED, const u8 *wscript UNNEEDED)
|
||||||
|
{ fprintf(stderr, "towire_onchaind_spend_fulfill called!\n"); abort(); }
|
||||||
/* Generated stub for towire_onchaind_spend_htlc_success */
|
/* Generated stub for towire_onchaind_spend_htlc_success */
|
||||||
u8 *towire_onchaind_spend_htlc_success(const tal_t *ctx UNNEEDED, const struct bitcoin_outpoint *outpoint UNNEEDED, struct amount_sat outpoint_amount UNNEEDED, struct amount_sat fee UNNEEDED, u64 htlc_id UNNEEDED, u64 commit_num UNNEEDED, const struct bitcoin_signature *remote_htlc_sig UNNEEDED, const struct preimage *preimage UNNEEDED, const u8 *wscript UNNEEDED, const u8 *htlc_wscript UNNEEDED)
|
u8 *towire_onchaind_spend_htlc_success(const tal_t *ctx UNNEEDED, const struct bitcoin_outpoint *outpoint UNNEEDED, struct amount_sat outpoint_amount UNNEEDED, struct amount_sat fee UNNEEDED, u64 htlc_id UNNEEDED, u64 commit_num UNNEEDED, const struct bitcoin_signature *remote_htlc_sig UNNEEDED, const struct preimage *preimage UNNEEDED, const u8 *wscript UNNEEDED, const u8 *htlc_wscript UNNEEDED)
|
||||||
{ fprintf(stderr, "towire_onchaind_spend_htlc_success called!\n"); abort(); }
|
{ fprintf(stderr, "towire_onchaind_spend_htlc_success called!\n"); abort(); }
|
||||||
|
|||||||
@@ -314,6 +314,9 @@ u8 *towire_onchaind_missing_htlc_output(const tal_t *ctx UNNEEDED, const struct
|
|||||||
/* Generated stub for towire_onchaind_notify_coin_mvt */
|
/* Generated stub for towire_onchaind_notify_coin_mvt */
|
||||||
u8 *towire_onchaind_notify_coin_mvt(const tal_t *ctx UNNEEDED, const struct chain_coin_mvt *mvt UNNEEDED)
|
u8 *towire_onchaind_notify_coin_mvt(const tal_t *ctx UNNEEDED, const struct chain_coin_mvt *mvt UNNEEDED)
|
||||||
{ fprintf(stderr, "towire_onchaind_notify_coin_mvt called!\n"); abort(); }
|
{ fprintf(stderr, "towire_onchaind_notify_coin_mvt called!\n"); abort(); }
|
||||||
|
/* Generated stub for towire_onchaind_spend_fulfill */
|
||||||
|
u8 *towire_onchaind_spend_fulfill(const tal_t *ctx UNNEEDED, const struct bitcoin_outpoint *outpoint UNNEEDED, struct amount_sat outpoint_amount UNNEEDED, u64 htlc_id UNNEEDED, const struct pubkey *remote_per_commitment_point UNNEEDED, const struct preimage *preimage UNNEEDED, const u8 *wscript UNNEEDED)
|
||||||
|
{ fprintf(stderr, "towire_onchaind_spend_fulfill called!\n"); abort(); }
|
||||||
/* Generated stub for towire_onchaind_spend_htlc_success */
|
/* Generated stub for towire_onchaind_spend_htlc_success */
|
||||||
u8 *towire_onchaind_spend_htlc_success(const tal_t *ctx UNNEEDED, const struct bitcoin_outpoint *outpoint UNNEEDED, struct amount_sat outpoint_amount UNNEEDED, struct amount_sat fee UNNEEDED, u64 htlc_id UNNEEDED, u64 commit_num UNNEEDED, const struct bitcoin_signature *remote_htlc_sig UNNEEDED, const struct preimage *preimage UNNEEDED, const u8 *wscript UNNEEDED, const u8 *htlc_wscript UNNEEDED)
|
u8 *towire_onchaind_spend_htlc_success(const tal_t *ctx UNNEEDED, const struct bitcoin_outpoint *outpoint UNNEEDED, struct amount_sat outpoint_amount UNNEEDED, struct amount_sat fee UNNEEDED, u64 htlc_id UNNEEDED, u64 commit_num UNNEEDED, const struct bitcoin_signature *remote_htlc_sig UNNEEDED, const struct preimage *preimage UNNEEDED, const u8 *wscript UNNEEDED, const u8 *htlc_wscript UNNEEDED)
|
||||||
{ fprintf(stderr, "towire_onchaind_spend_htlc_success called!\n"); abort(); }
|
{ fprintf(stderr, "towire_onchaind_spend_htlc_success called!\n"); abort(); }
|
||||||
|
|||||||
@@ -2382,15 +2382,16 @@ def test_onchain_middleman_their_unilateral_in(node_factory, bitcoind):
|
|||||||
l2.daemon.wait_for_log('THEIR_UNILATERAL/THEIR_HTLC')
|
l2.daemon.wait_for_log('THEIR_UNILATERAL/THEIR_HTLC')
|
||||||
|
|
||||||
# l2 should fulfill HTLC onchain, immediately
|
# l2 should fulfill HTLC onchain, immediately
|
||||||
l2.wait_for_onchaind_broadcast('THEIR_HTLC_FULFILL_TO_US',
|
((_, txid2, blocks),) = l2.wait_for_onchaind_tx('THEIR_HTLC_FULFILL_TO_US',
|
||||||
'THEIR_UNILATERAL/THEIR_HTLC')
|
'THEIR_UNILATERAL/THEIR_HTLC')
|
||||||
|
assert blocks == 0
|
||||||
|
|
||||||
((_, txid, blocks),) = l1.wait_for_onchaind_tx('OUR_DELAYED_RETURN_TO_WALLET',
|
((_, txid, blocks),) = l1.wait_for_onchaind_tx('OUR_DELAYED_RETURN_TO_WALLET',
|
||||||
'OUR_UNILATERAL/DELAYED_OUTPUT_TO_US')
|
'OUR_UNILATERAL/DELAYED_OUTPUT_TO_US')
|
||||||
assert blocks == 4
|
assert blocks == 4
|
||||||
|
|
||||||
# Payment should succeed.
|
# Payment should succeed.
|
||||||
l1.bitcoin.generate_block(1)
|
l1.bitcoin.generate_block(1, wait_for_mempool=txid2)
|
||||||
l1.daemon.wait_for_log('OUR_UNILATERAL/OUR_HTLC gave us preimage')
|
l1.daemon.wait_for_log('OUR_UNILATERAL/OUR_HTLC gave us preimage')
|
||||||
err = q.get(timeout=10)
|
err = q.get(timeout=10)
|
||||||
if err:
|
if err:
|
||||||
@@ -3164,17 +3165,17 @@ def test_permfail_htlc_out(node_factory, bitcoind, executor):
|
|||||||
l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/OUR_HTLC by OUR_HTLC_TIMEOUT_TX \\(.*\\) after 6 blocks')
|
l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/OUR_HTLC by OUR_HTLC_TIMEOUT_TX \\(.*\\) after 6 blocks')
|
||||||
|
|
||||||
l2.daemon.logsearch_start = needle
|
l2.daemon.logsearch_start = needle
|
||||||
((_, txid, blocks),) = l2.wait_for_onchaind_tx('OUR_DELAYED_RETURN_TO_WALLET',
|
((_, txid2, blocks),) = l2.wait_for_onchaind_tx('OUR_DELAYED_RETURN_TO_WALLET',
|
||||||
'OUR_UNILATERAL/DELAYED_OUTPUT_TO_US')
|
'OUR_UNILATERAL/DELAYED_OUTPUT_TO_US')
|
||||||
assert blocks == 4
|
assert blocks == 4
|
||||||
|
|
||||||
l1.daemon.wait_for_log('Propose handling THEIR_UNILATERAL/THEIR_HTLC by THEIR_HTLC_TIMEOUT_TO_THEM \\(IGNORING\\) after 6 blocks')
|
l1.daemon.wait_for_log('Propose handling THEIR_UNILATERAL/THEIR_HTLC by THEIR_HTLC_TIMEOUT_TO_THEM \\(IGNORING\\) after 6 blocks')
|
||||||
# l1 then gets preimage, uses it instead of ignoring
|
# l1 then gets preimage, uses it instead of ignoring
|
||||||
l1.wait_for_onchaind_broadcast('THEIR_HTLC_FULFILL_TO_US',
|
((_, txid1, blocks),) = l1.wait_for_onchaind_tx('THEIR_HTLC_FULFILL_TO_US',
|
||||||
'THEIR_UNILATERAL/THEIR_HTLC')
|
'THEIR_UNILATERAL/THEIR_HTLC')
|
||||||
|
assert blocks == 0
|
||||||
# l2 sees l1 fulfill tx.
|
# l2 sees l1 fulfill tx.
|
||||||
bitcoind.generate_block(1)
|
bitcoind.generate_block(1, wait_for_mempool=txid1)
|
||||||
|
|
||||||
l2.daemon.wait_for_log('OUR_UNILATERAL/OUR_HTLC gave us preimage')
|
l2.daemon.wait_for_log('OUR_UNILATERAL/OUR_HTLC gave us preimage')
|
||||||
t.cancel()
|
t.cancel()
|
||||||
@@ -3183,7 +3184,7 @@ def test_permfail_htlc_out(node_factory, bitcoind, executor):
|
|||||||
bitcoind.generate_block(3)
|
bitcoind.generate_block(3)
|
||||||
|
|
||||||
# Now, 100 blocks they should be done.
|
# Now, 100 blocks they should be done.
|
||||||
bitcoind.generate_block(95, txid)
|
bitcoind.generate_block(95, txid2)
|
||||||
sync_blockheight(bitcoind, [l1, l2])
|
sync_blockheight(bitcoind, [l1, l2])
|
||||||
assert not l1.daemon.is_in_log('onchaind complete, forgetting peer')
|
assert not l1.daemon.is_in_log('onchaind complete, forgetting peer')
|
||||||
assert not l2.daemon.is_in_log('onchaind complete, forgetting peer')
|
assert not l2.daemon.is_in_log('onchaind complete, forgetting peer')
|
||||||
|
|||||||
Reference in New Issue
Block a user