mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
closingd: send the tx to master as we negotiate.
We can derive fees from this, and also broadcast at any time without having to reconstruct it. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
253b3e679e
commit
c389215a35
@ -355,6 +355,7 @@ int main(int argc, char *argv[])
|
||||
trimmed)
|
||||
: "NONE");
|
||||
}
|
||||
tx = trimmed;
|
||||
}
|
||||
|
||||
status_trace("Received fee offer %"PRIu64, received_fee);
|
||||
@ -377,8 +378,7 @@ int main(int argc, char *argv[])
|
||||
} else {
|
||||
status_trace("Fee accepted.");
|
||||
msg = towire_closing_received_signature(tmpctx,
|
||||
received_fee,
|
||||
&sig);
|
||||
&sig, tx);
|
||||
if (!wire_sync_write(REQ_FD, take(msg)))
|
||||
status_failed(WIRE_CLOSING_INTERNAL_ERROR,
|
||||
"Writing received to master: %s",
|
||||
|
@ -42,8 +42,8 @@ closing_init,,revocations_received,u64
|
||||
|
||||
# We received an offer, save signature.
|
||||
closing_received_signature,2
|
||||
closing_received_signature,,fee_satoshi,u64
|
||||
closing_received_signature,,signature,secp256k1_ecdsa_signature
|
||||
closing_received_signature,,tx,struct bitcoin_tx
|
||||
|
||||
closing_received_signature_reply,102
|
||||
|
||||
|
|
@ -97,7 +97,44 @@ static void peer_reconnect(struct peer *peer)
|
||||
|
||||
static void drop_to_chain(struct peer *peer)
|
||||
{
|
||||
const tal_t *tmpctx = tal_tmpctx(peer);
|
||||
u8 *funding_wscript;
|
||||
struct pubkey local_funding_pubkey;
|
||||
struct secrets secrets;
|
||||
secp256k1_ecdsa_signature sig;
|
||||
|
||||
/* FIXME: Implement. */
|
||||
if (peer->state != CLOSINGD_SIGEXCHANGE) {
|
||||
tal_free(tmpctx);
|
||||
return;
|
||||
}
|
||||
|
||||
derive_basepoints(peer->seed, &local_funding_pubkey, NULL, &secrets,
|
||||
NULL);
|
||||
|
||||
funding_wscript = bitcoin_redeem_2of2(tmpctx,
|
||||
&local_funding_pubkey,
|
||||
&peer->channel_info->remote_fundingkey);
|
||||
/* Need input amount for signing */
|
||||
peer->last_tx->input[0].amount = tal_dup(peer->last_tx->input, u64,
|
||||
&peer->funding_satoshi);
|
||||
sign_tx_input(peer->last_tx, 0, NULL, funding_wscript,
|
||||
&secrets.funding_privkey,
|
||||
&local_funding_pubkey,
|
||||
&sig);
|
||||
|
||||
peer->last_tx->input[0].witness
|
||||
= bitcoin_witness_2of2(peer->last_tx->input,
|
||||
peer->last_sig,
|
||||
&sig,
|
||||
&peer->channel_info->remote_fundingkey,
|
||||
&local_funding_pubkey);
|
||||
|
||||
/* Keep broadcasting until we say stop (can fail due to dup,
|
||||
* if they beat us to the broadcast). */
|
||||
broadcast_tx(peer->ld->topology, peer, peer->last_tx, NULL);
|
||||
|
||||
tal_free(tmpctx);
|
||||
}
|
||||
|
||||
void peer_fail_permanent(struct peer *peer, const u8 *msg)
|
||||
@ -500,7 +537,6 @@ void add_peer(struct lightningd *ld, u64 unique_id,
|
||||
= peer->num_revocations_received = 0;
|
||||
peer->next_htlc_id = 0;
|
||||
wallet_shachain_init(ld->wallet, &peer->their_shachain);
|
||||
peer->closing_sig_received = NULL;
|
||||
|
||||
idname = type_to_string(peer, struct pubkey, id);
|
||||
|
||||
@ -1240,39 +1276,57 @@ static int closingd_got_negotiation_error(struct peer *peer, const u8 *msg)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static bool better_closing_fee(struct peer *peer, u64 fee_satoshi)
|
||||
void peer_last_tx(struct peer *peer, struct bitcoin_tx *tx,
|
||||
const secp256k1_ecdsa_signature *sig)
|
||||
{
|
||||
/* FIXME: Use estimatefee 24 or something? */
|
||||
u64 min_feerate = get_feerate(peer->ld->topology) / 2;
|
||||
/* FIXME: Real fee, using real tx, and estimatefee 6 */
|
||||
u64 ideal_fee = commit_tx_base_fee(get_feerate(peer->ld->topology), 0);
|
||||
s64 old_diff, new_diff;
|
||||
/* FIXME: save to db. */
|
||||
|
||||
/* FIXME: Use real tx here! (+ 74 for sig). */
|
||||
if (fee_satoshi < commit_tx_base_fee(min_feerate, 0))
|
||||
tal_free(peer->last_sig);
|
||||
peer->last_sig = tal_dup(peer, secp256k1_ecdsa_signature, sig);
|
||||
tal_free(peer->last_tx);
|
||||
peer->last_tx = tal_steal(peer, tx);
|
||||
}
|
||||
|
||||
/* Is this better than the last tx we were holding? */
|
||||
static bool better_closing_fee(struct peer *peer, const struct bitcoin_tx *tx)
|
||||
{
|
||||
u64 weight, fee, last_fee, ideal_fee, min_fee;
|
||||
s64 old_diff, new_diff;
|
||||
size_t i;
|
||||
|
||||
/* Calculate actual fee. */
|
||||
fee = peer->funding_satoshi;
|
||||
for (i = 0; i < tal_count(tx->output); i++)
|
||||
fee -= tx->output[i].amount;
|
||||
|
||||
last_fee = peer->funding_satoshi;
|
||||
for (i = 0; i < tal_count(peer->last_tx); i++)
|
||||
last_fee -= peer->last_tx->output[i].amount;
|
||||
|
||||
/* Weight once we add in sigs. */
|
||||
weight = measure_tx_cost(tx) + 74 * 2;
|
||||
|
||||
/* FIXME: Use estimatefee 24 or something? */
|
||||
min_fee = get_feerate(peer->ld->topology) / 5 * weight / 1000;
|
||||
if (fee < min_fee)
|
||||
return false;
|
||||
|
||||
/* FIXME: Derive old fee from last tx, which would work even
|
||||
* for the case where we're using the final commitment tx. */
|
||||
if (!peer->closing_sig_received)
|
||||
return true;
|
||||
|
||||
/* FIXME: Real fee, using real tx, and estimatefee 6 */
|
||||
/* FIXME: Use estimatefee 6 */
|
||||
ideal_fee = get_feerate(peer->ld->topology) / 2 * weight / 1000;
|
||||
|
||||
/* We prefer fee which is closest to our ideal. */
|
||||
old_diff = imaxabs((s64)ideal_fee - (s64)peer->closing_fee_received);
|
||||
new_diff = imaxabs((s64)ideal_fee - (s64)fee_satoshi);
|
||||
old_diff = imaxabs((s64)ideal_fee - (s64)last_fee);
|
||||
new_diff = imaxabs((s64)ideal_fee - (s64)fee);
|
||||
|
||||
return (new_diff < old_diff);
|
||||
}
|
||||
|
||||
static int peer_received_closing_signature(struct peer *peer, const u8 *msg)
|
||||
{
|
||||
u64 fee_satoshi;
|
||||
secp256k1_ecdsa_signature sig;
|
||||
struct bitcoin_tx *tx = tal(msg, struct bitcoin_tx);
|
||||
|
||||
if (!fromwire_closing_received_signature(msg, NULL,
|
||||
&fee_satoshi, &sig)) {
|
||||
if (!fromwire_closing_received_signature(msg, NULL, &sig, tx)) {
|
||||
peer_internal_error(peer, "Bad closing_received_signature %s",
|
||||
tal_hex(peer, msg));
|
||||
return -1;
|
||||
@ -1280,14 +1334,8 @@ static int peer_received_closing_signature(struct peer *peer, const u8 *msg)
|
||||
|
||||
/* FIXME: Make sure signature is correct! */
|
||||
|
||||
if (better_closing_fee(peer, fee_satoshi)) {
|
||||
/* FIXME: save to db. */
|
||||
|
||||
peer->closing_fee_received = fee_satoshi;
|
||||
tal_free(peer->closing_sig_received);
|
||||
peer->closing_sig_received
|
||||
= tal_dup(peer, secp256k1_ecdsa_signature, &sig);
|
||||
}
|
||||
if (better_closing_fee(peer, tx))
|
||||
peer_last_tx(peer, tx, &sig);
|
||||
|
||||
/* OK, you can continue now. */
|
||||
subd_send_msg(peer->owner,
|
||||
@ -1297,13 +1345,6 @@ static int peer_received_closing_signature(struct peer *peer, const u8 *msg)
|
||||
|
||||
static int peer_closing_complete(struct peer *peer, const u8 *msg)
|
||||
{
|
||||
struct bitcoin_tx *tx;
|
||||
u8 *local_scriptpubkey, *funding_wscript;
|
||||
u64 out_amounts[NUM_SIDES];
|
||||
struct pubkey local_funding_pubkey;
|
||||
struct secrets secrets;
|
||||
secp256k1_ecdsa_signature sig;
|
||||
|
||||
if (!fromwire_closing_complete(msg, NULL)) {
|
||||
peer_internal_error(peer, "Bad closing_complete %s",
|
||||
tal_hex(peer, msg));
|
||||
@ -1314,60 +1355,7 @@ static int peer_closing_complete(struct peer *peer, const u8 *msg)
|
||||
if (peer->state == CLOSINGD_COMPLETE)
|
||||
return -1;
|
||||
|
||||
if (!peer->closing_sig_received) {
|
||||
peer_internal_error(peer,
|
||||
"closing_complete without sending sig!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
local_scriptpubkey = p2wpkh_for_keyidx(msg, peer->ld,
|
||||
peer->local_shutdown_idx);
|
||||
if (!local_scriptpubkey) {
|
||||
peer_internal_error(peer,
|
||||
"Can't generate local shutdown scriptpubkey");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* BOLT #3:
|
||||
*
|
||||
* The amounts for each output MUST BE rounded down to whole satoshis.
|
||||
*/
|
||||
out_amounts[LOCAL] = *peer->our_msatoshi / 1000;
|
||||
out_amounts[REMOTE] = peer->funding_satoshi
|
||||
- (*peer->our_msatoshi / 1000);
|
||||
out_amounts[peer->funder] -= peer->closing_fee_received;
|
||||
|
||||
derive_basepoints(peer->seed, &local_funding_pubkey, NULL, &secrets,
|
||||
NULL);
|
||||
|
||||
tx = create_close_tx(msg, local_scriptpubkey,
|
||||
peer->remote_shutdown_scriptpubkey,
|
||||
peer->funding_txid,
|
||||
peer->funding_outnum,
|
||||
peer->funding_satoshi,
|
||||
out_amounts[LOCAL],
|
||||
out_amounts[REMOTE],
|
||||
peer->our_config.dust_limit_satoshis);
|
||||
|
||||
funding_wscript = bitcoin_redeem_2of2(msg,
|
||||
&local_funding_pubkey,
|
||||
&peer->channel_info->remote_fundingkey);
|
||||
sign_tx_input(tx, 0, NULL, funding_wscript,
|
||||
&secrets.funding_privkey,
|
||||
&local_funding_pubkey,
|
||||
&sig);
|
||||
|
||||
tx->input[0].witness
|
||||
= bitcoin_witness_2of2(tx->input,
|
||||
peer->closing_sig_received,
|
||||
&sig,
|
||||
&peer->channel_info->remote_fundingkey,
|
||||
&local_funding_pubkey);
|
||||
|
||||
/* Keep broadcasting until we say stop (can fail due to dup,
|
||||
* if they beat us to the broadcast). */
|
||||
broadcast_tx(peer->ld->topology, peer, tx, NULL);
|
||||
|
||||
drop_to_chain(peer);
|
||||
peer_set_condition(peer, CLOSINGD_SIGEXCHANGE, CLOSINGD_COMPLETE);
|
||||
return -1;
|
||||
}
|
||||
|
@ -91,10 +91,6 @@ struct peer {
|
||||
/* Our key for shutdown (-1 if not chosen yet) */
|
||||
s64 local_shutdown_idx;
|
||||
|
||||
/* Closing stuff. */
|
||||
u64 closing_fee_received;
|
||||
secp256k1_ecdsa_signature *closing_sig_received;
|
||||
|
||||
/* Reestablishment stuff: last sent commit and revocation details. */
|
||||
bool last_was_revoke;
|
||||
struct changed_htlc *last_sent_commit;
|
||||
@ -142,6 +138,9 @@ struct peer *peer_from_json(struct lightningd *ld,
|
||||
const char *buffer,
|
||||
jsmntok_t *peeridtok);
|
||||
|
||||
void peer_last_tx(struct peer *peer, struct bitcoin_tx *tx,
|
||||
const secp256k1_ecdsa_signature *sig);
|
||||
|
||||
void peer_fundee_open(struct peer *peer, const u8 *msg,
|
||||
const struct crypto_state *cs,
|
||||
int peer_fd, int gossip_fd);
|
||||
|
@ -525,16 +525,7 @@ static bool wallet_stmt2channel(struct wallet *w, sqlite3_stmt *stmt,
|
||||
col += 2;
|
||||
}
|
||||
|
||||
chan->peer->closing_fee_received = sqlite3_column_int64(stmt, col++);
|
||||
if (sqlite3_column_type(stmt, col) != SQLITE_NULL) {
|
||||
if (!chan->peer->closing_sig_received) {
|
||||
chan->peer->closing_sig_received = tal(chan->peer, secp256k1_ecdsa_signature);
|
||||
}
|
||||
ok &= sqlite3_column_sig(stmt, col++, chan->peer->closing_sig_received);
|
||||
} else {
|
||||
col++;
|
||||
}
|
||||
assert(col == 36);
|
||||
assert(col == 34);
|
||||
|
||||
return ok;
|
||||
}
|
||||
@ -559,8 +550,8 @@ bool wallet_channel_load(struct wallet *w, const u64 id,
|
||||
"old_per_commit_remote, feerate_per_kw, shachain_remote_id, "
|
||||
"shutdown_scriptpubkey_remote, shutdown_keyidx_local, "
|
||||
"last_sent_commit_state, last_sent_commit_id, "
|
||||
"last_tx, last_sig, "
|
||||
"closing_fee_received, closing_sig_received FROM channels WHERE "
|
||||
"last_tx, last_sig "
|
||||
"FROM channels WHERE "
|
||||
"id=%" PRIu64 ";";
|
||||
|
||||
sqlite3_stmt *stmt = db_query(__func__, w->db, channel_query, id);
|
||||
@ -702,9 +693,7 @@ bool wallet_channel_save(struct wallet *w, struct wallet_channel *chan){
|
||||
" shutdown_scriptpubkey_remote='%s',"
|
||||
" shutdown_keyidx_local=%"PRIu64","
|
||||
" channel_config_local=%"PRIu64","
|
||||
" last_tx=%s, last_sig=%s, "
|
||||
" closing_fee_received=%"PRIu64","
|
||||
" closing_sig_received=%s"
|
||||
" last_tx=%s, last_sig=%s"
|
||||
" WHERE id=%"PRIu64,
|
||||
p->their_shachain.id,
|
||||
p->scid?tal_fmt(tmpctx,"'%s'", short_channel_id_to_str(tmpctx, p->scid)):"null",
|
||||
@ -727,8 +716,6 @@ bool wallet_channel_save(struct wallet *w, struct wallet_channel *chan){
|
||||
p->our_config.id,
|
||||
db_serialize_tx(tmpctx, p->last_tx),
|
||||
db_serialize_signature(tmpctx, p->last_sig),
|
||||
p->closing_fee_received,
|
||||
db_serialize_signature(tmpctx, p->closing_sig_received),
|
||||
chan->id);
|
||||
|
||||
if (chan->peer->channel_info) {
|
||||
|
@ -176,14 +176,6 @@ static bool channelseq(struct wallet_channel *c1, struct wallet_channel *c2)
|
||||
p2->last_sig, sizeof(*p2->last_sig)));
|
||||
}
|
||||
|
||||
CHECK((p1->closing_sig_received != NULL) == (p2->closing_sig_received != NULL));
|
||||
if(p1->closing_sig_received) {
|
||||
CHECK(memeq(p1->closing_sig_received,
|
||||
sizeof(secp256k1_ecdsa_signature),
|
||||
p2->closing_sig_received,
|
||||
sizeof(secp256k1_ecdsa_signature)));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -275,12 +267,6 @@ static bool test_channel_crud(const tal_t *ctx)
|
||||
CHECK_MSG(wallet_channel_load(w, c1.id, c2), tal_fmt(w, "Load from DB: %s", w->db->err));
|
||||
CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v7)");
|
||||
|
||||
/* Variant 8: update with closing_sig */
|
||||
p.closing_sig_received = sig;
|
||||
CHECK_MSG(wallet_channel_save(w, &c1), tal_fmt(w, "Insert into DB: %s", w->db->err));
|
||||
CHECK_MSG(wallet_channel_load(w, c1.id, c2), tal_fmt(w, "Load from DB: %s", w->db->err));
|
||||
CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v8)");
|
||||
|
||||
tal_free(w);
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user