|
|
@ -4,12 +4,14 @@ |
|
|
|
#include "commit_tx.h" |
|
|
|
#include "controlled_time.h" |
|
|
|
#include "cryptopkt.h" |
|
|
|
#include "db.h" |
|
|
|
#include "dns.h" |
|
|
|
#include "find_p2sh_out.h" |
|
|
|
#include "jsonrpc.h" |
|
|
|
#include "lightningd.h" |
|
|
|
#include "log.h" |
|
|
|
#include "names.h" |
|
|
|
#include "netaddr.h" |
|
|
|
#include "onion.h" |
|
|
|
#include "output_to_htlc.h" |
|
|
|
#include "packets.h" |
|
|
@ -59,13 +61,15 @@ static bool command_htlc_fail(struct peer *peer, struct htlc *htlc); |
|
|
|
static bool command_htlc_fulfill(struct peer *peer, struct htlc *htlc); |
|
|
|
static void try_commit(struct peer *peer); |
|
|
|
|
|
|
|
void peer_add_their_commit(struct peer *peer, |
|
|
|
bool peer_add_their_commit(struct peer *peer, |
|
|
|
const struct sha256_double *txid, u64 commit_num) |
|
|
|
{ |
|
|
|
struct their_commit *tc = tal(peer, struct their_commit); |
|
|
|
tc->txid = *txid; |
|
|
|
tc->commit_num = commit_num; |
|
|
|
list_add_tail(&peer->their_commits, &tc->list); |
|
|
|
|
|
|
|
return db_add_commit_map(peer, txid, commit_num); |
|
|
|
} |
|
|
|
|
|
|
|
/* Create a bitcoin close tx, using last signature they sent. */ |
|
|
@ -193,6 +197,33 @@ struct peer *find_peer(struct lightningd_state *dstate, const struct pubkey *id) |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
void debug_dump_peers(struct lightningd_state *dstate) |
|
|
|
{ |
|
|
|
struct peer *peer; |
|
|
|
|
|
|
|
list_for_each(&dstate->peers, peer, list) { |
|
|
|
if (!peer->local.commit |
|
|
|
|| !peer->remote.commit) |
|
|
|
continue; |
|
|
|
log_debug(peer->log, |
|
|
|
"Local cstate: pay %u/%u fee %u/%u htlcs %u/%u", |
|
|
|
peer->local.commit->cstate->side[OURS].pay_msat, |
|
|
|
peer->local.commit->cstate->side[THEIRS].pay_msat, |
|
|
|
peer->local.commit->cstate->side[OURS].fee_msat, |
|
|
|
peer->local.commit->cstate->side[THEIRS].fee_msat, |
|
|
|
peer->local.commit->cstate->side[OURS].num_htlcs, |
|
|
|
peer->local.commit->cstate->side[THEIRS].num_htlcs); |
|
|
|
log_debug(peer->log, |
|
|
|
"Remote cstate: pay %u/%u fee %u/%u htlcs %u/%u", |
|
|
|
peer->remote.commit->cstate->side[OURS].pay_msat, |
|
|
|
peer->remote.commit->cstate->side[THEIRS].pay_msat, |
|
|
|
peer->remote.commit->cstate->side[OURS].fee_msat, |
|
|
|
peer->remote.commit->cstate->side[THEIRS].fee_msat, |
|
|
|
peer->remote.commit->cstate->side[OURS].num_htlcs, |
|
|
|
peer->remote.commit->cstate->side[THEIRS].num_htlcs); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static struct peer *find_peer_json(struct lightningd_state *dstate, |
|
|
|
const char *buffer, |
|
|
|
jsmntok_t *peeridtok) |
|
|
@ -256,8 +287,8 @@ void peer_open_complete(struct peer *peer, const char *problem) |
|
|
|
log_debug(peer->log, "peer open complete"); |
|
|
|
} |
|
|
|
|
|
|
|
static void set_peer_state(struct peer *peer, enum state newstate, |
|
|
|
const char *caller) |
|
|
|
static bool set_peer_state(struct peer *peer, enum state newstate, |
|
|
|
const char *caller, bool db_commit) |
|
|
|
{ |
|
|
|
log_debug(peer->log, "%s: %s => %s", caller, |
|
|
|
state_name(peer->state), state_name(newstate)); |
|
|
@ -266,6 +297,10 @@ static void set_peer_state(struct peer *peer, enum state newstate, |
|
|
|
/* We can only route in normal state. */ |
|
|
|
if (!state_is_normal(peer->state)) |
|
|
|
peer->nc = tal_free(peer->nc); |
|
|
|
|
|
|
|
if (db_commit) |
|
|
|
return db_update_state(peer); |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
static void peer_breakdown(struct peer *peer) |
|
|
@ -281,13 +316,14 @@ static void peer_breakdown(struct peer *peer) |
|
|
|
broadcast_tx(peer, bitcoin_close(peer)); |
|
|
|
/* If we have a signed commit tx (maybe not if we just offered
|
|
|
|
* anchor, or they supplied anchor, or no outputs to us). */ |
|
|
|
} else if (peer->local.commit->sig) { |
|
|
|
} else if (peer->local.commit && peer->local.commit->sig) { |
|
|
|
log_unusual(peer->log, "Peer breakdown: sending commit tx"); |
|
|
|
broadcast_tx(peer, bitcoin_commit(peer)); |
|
|
|
} else { |
|
|
|
log_info(peer->log, "Peer breakdown: nothing to do"); |
|
|
|
/* We close immediately. */ |
|
|
|
set_peer_state(peer, STATE_CLOSED, __func__); |
|
|
|
set_peer_state(peer, STATE_CLOSED, __func__, false); |
|
|
|
db_forget_peer(peer); |
|
|
|
io_wake(peer); |
|
|
|
} |
|
|
|
} |
|
|
@ -322,7 +358,8 @@ static bool peer_comms_err(struct peer *peer, Pkt *err) |
|
|
|
if (err) |
|
|
|
queue_pkt_err(peer, err); |
|
|
|
|
|
|
|
set_peer_state(peer, STATE_ERR_BREAKDOWN, __func__); |
|
|
|
/* FIXME: Save state here? */ |
|
|
|
set_peer_state(peer, STATE_ERR_BREAKDOWN, __func__, false); |
|
|
|
peer_breakdown(peer); |
|
|
|
return false; |
|
|
|
} |
|
|
@ -365,6 +402,7 @@ void set_htlc_rval(struct peer *peer, |
|
|
|
{ |
|
|
|
assert(!htlc->r); |
|
|
|
htlc->r = tal_dup(htlc, struct rval, rval); |
|
|
|
db_htlc_fulfilled(peer, htlc); |
|
|
|
} |
|
|
|
|
|
|
|
static void route_htlc_onwards(struct peer *peer, |
|
|
@ -623,8 +661,9 @@ struct state_table { |
|
|
|
enum htlc_state from, to; |
|
|
|
}; |
|
|
|
|
|
|
|
static bool htlcs_changestate(struct peer *peer, |
|
|
|
const struct state_table *table, size_t n) |
|
|
|
static const char *htlcs_changestate(struct peer *peer, |
|
|
|
const struct state_table *table, size_t n, |
|
|
|
bool db_commit) |
|
|
|
{ |
|
|
|
struct htlc_map_iter it; |
|
|
|
struct htlc *h; |
|
|
@ -638,13 +677,22 @@ static bool htlcs_changestate(struct peer *peer, |
|
|
|
if (h->state == table[i].from) { |
|
|
|
adjust_cstates(peer, h, |
|
|
|
table[i].from, table[i].to); |
|
|
|
htlc_changestate(h, table[i].from, table[i].to); |
|
|
|
if (!htlc_changestate(h, table[i].from, |
|
|
|
table[i].to, db_commit)) |
|
|
|
return "database error"; |
|
|
|
check_both_committed(peer, h); |
|
|
|
changed = true; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return changed; |
|
|
|
/* BOLT #2:
|
|
|
|
* |
|
|
|
* A node MUST NOT send an `update_commit` message which does |
|
|
|
* not include any updates. |
|
|
|
*/ |
|
|
|
if (!changed) |
|
|
|
return "no changes made"; |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
/* This is the io loop while we're negotiating closing tx. */ |
|
|
@ -718,6 +766,11 @@ static bool closing_pkt_in(struct peer *peer, const Pkt *pkt) |
|
|
|
peer->closing.their_fee = c->close_fee; |
|
|
|
peer->closing.sigs_in++; |
|
|
|
|
|
|
|
if (!db_update_their_closing(peer)) { |
|
|
|
return peer_comms_err(peer, |
|
|
|
pkt_err(peer, "Database error")); |
|
|
|
} |
|
|
|
|
|
|
|
if (peer->closing.our_fee != peer->closing.their_fee) { |
|
|
|
/* BOLT #2:
|
|
|
|
* |
|
|
@ -741,6 +794,11 @@ static bool closing_pkt_in(struct peer *peer, const Pkt *pkt) |
|
|
|
peer->closing.our_fee); |
|
|
|
|
|
|
|
peer->closing.closing_order = peer->order_counter++; |
|
|
|
|
|
|
|
if (!db_update_our_closing(peer)) { |
|
|
|
return peer_comms_err(peer, |
|
|
|
pkt_err(peer, "Database error")); |
|
|
|
} |
|
|
|
queue_pkt_close_signature(peer); |
|
|
|
} |
|
|
|
|
|
|
@ -764,6 +822,7 @@ static bool closing_pkt_in(struct peer *peer, const Pkt *pkt) |
|
|
|
static Pkt *handle_pkt_commit(struct peer *peer, const Pkt *pkt) |
|
|
|
{ |
|
|
|
Pkt *err; |
|
|
|
const char *errmsg; |
|
|
|
struct sha256 preimage; |
|
|
|
struct commit_info *ci; |
|
|
|
bool to_them_only; |
|
|
@ -783,13 +842,21 @@ static Pkt *handle_pkt_commit(struct peer *peer, const Pkt *pkt) |
|
|
|
|
|
|
|
ci = new_commit_info(peer, peer->local.commit->commit_num + 1); |
|
|
|
|
|
|
|
if (!db_start_transaction(peer)) |
|
|
|
return pkt_err(peer, "database error"); |
|
|
|
|
|
|
|
/* BOLT #2:
|
|
|
|
* |
|
|
|
* A node MUST NOT send an `update_commit` message which does |
|
|
|
* not include any updates. |
|
|
|
*/ |
|
|
|
if (!htlcs_changestate(peer, commit_changes, ARRAY_SIZE(commit_changes))) |
|
|
|
return pkt_err(peer, "Empty commit"); |
|
|
|
errmsg = htlcs_changestate(peer, |
|
|
|
commit_changes, ARRAY_SIZE(commit_changes), |
|
|
|
true); |
|
|
|
if (errmsg) { |
|
|
|
db_abort_transaction(peer); |
|
|
|
return pkt_err(peer, "%s", errmsg); |
|
|
|
} |
|
|
|
|
|
|
|
/* Create new commit info for this commit tx. */ |
|
|
|
ci->revocation_hash = peer->local.next_revocation_hash; |
|
|
@ -805,6 +872,15 @@ static Pkt *handle_pkt_commit(struct peer *peer, const Pkt *pkt) |
|
|
|
ci->cstate, LOCAL, &to_them_only); |
|
|
|
bitcoin_txid(ci->tx, &ci->txid); |
|
|
|
|
|
|
|
log_debug(peer->log, "Check tx %"PRIu64" sig for %u/%u msatoshis, %u/%u htlcs (%u non-dust)", |
|
|
|
ci->commit_num, |
|
|
|
ci->cstate->side[THEIRS].pay_msat, |
|
|
|
ci->cstate->side[OURS].pay_msat, |
|
|
|
ci->cstate->side[THEIRS].num_htlcs, |
|
|
|
ci->cstate->side[OURS].num_htlcs, |
|
|
|
ci->cstate->num_nondust); |
|
|
|
log_add_struct(peer->log, " (txid %s)", struct sha256_double, &ci->txid); |
|
|
|
|
|
|
|
/* BOLT #2:
|
|
|
|
* |
|
|
|
* If the commitment transaction has only a single output which pays |
|
|
@ -830,12 +906,20 @@ static Pkt *handle_pkt_commit(struct peer *peer, const Pkt *pkt) |
|
|
|
NULL, 0, |
|
|
|
peer->anchor.witnessscript, |
|
|
|
&peer->remote.commitkey, |
|
|
|
ci->sig)) |
|
|
|
ci->sig)) { |
|
|
|
db_abort_transaction(peer); |
|
|
|
return pkt_err(peer, "Bad signature"); |
|
|
|
} |
|
|
|
|
|
|
|
/* Switch to the new commitment. */ |
|
|
|
tal_free(peer->local.commit); |
|
|
|
peer->local.commit = ci; |
|
|
|
peer->local.commit->order = peer->order_counter++; |
|
|
|
|
|
|
|
if (!db_new_commit_info(peer, OURS, NULL)) { |
|
|
|
db_abort_transaction(peer); |
|
|
|
return pkt_err(peer, "Database error"); |
|
|
|
} |
|
|
|
peer_get_revocation_hash(peer, ci->commit_num + 1, |
|
|
|
&peer->local.next_revocation_hash); |
|
|
|
peer->their_commitsigs++; |
|
|
@ -846,9 +930,13 @@ static Pkt *handle_pkt_commit(struct peer *peer, const Pkt *pkt) |
|
|
|
assert(to_them_only || peer->local.commit->sig); |
|
|
|
assert(peer->local.commit->commit_num > 0); |
|
|
|
|
|
|
|
if (!htlcs_changestate(peer, revocation_changes, |
|
|
|
ARRAY_SIZE(revocation_changes))) |
|
|
|
fatal("sent revoke with no changes"); |
|
|
|
errmsg = htlcs_changestate(peer, revocation_changes, |
|
|
|
ARRAY_SIZE(revocation_changes), true); |
|
|
|
if (errmsg) { |
|
|
|
log_broken(peer->log, "queue_pkt_revocation: %s", errmsg); |
|
|
|
/* FIXME: Return error. */ |
|
|
|
fatal("revocation_changes: %s", errmsg); |
|
|
|
} |
|
|
|
|
|
|
|
peer_get_revocation_preimage(peer, peer->local.commit->commit_num - 1, |
|
|
|
&preimage); |
|
|
@ -857,7 +945,9 @@ static Pkt *handle_pkt_commit(struct peer *peer, const Pkt *pkt) |
|
|
|
if (peer_uncommitted_changes(peer)) |
|
|
|
remote_changes_pending(peer); |
|
|
|
|
|
|
|
peer->local.commit->order = peer->order_counter++; |
|
|
|
if (!db_commit_transaction(peer)) |
|
|
|
return pkt_err(peer, "Database error"); |
|
|
|
|
|
|
|
queue_pkt_revocation(peer, &preimage, &peer->local.next_revocation_hash); |
|
|
|
return NULL; |
|
|
|
} |
|
|
@ -904,7 +994,7 @@ static Pkt *handle_pkt_htlc_fail(struct peer *peer, const Pkt *pkt) |
|
|
|
* ... and the receiving node MUST add the HTLC fulfill/fail |
|
|
|
* to the unacked changeset for its local commitment. |
|
|
|
*/ |
|
|
|
htlc_changestate(htlc, SENT_ADD_ACK_REVOCATION, RCVD_REMOVE_HTLC); |
|
|
|
htlc_changestate(htlc, SENT_ADD_ACK_REVOCATION, RCVD_REMOVE_HTLC, false); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
@ -929,13 +1019,15 @@ static Pkt *handle_pkt_htlc_fulfill(struct peer *peer, const Pkt *pkt) |
|
|
|
* to the unacked changeset for its local commitment. |
|
|
|
*/ |
|
|
|
cstate_fulfill_htlc(peer->local.staging_cstate, htlc); |
|
|
|
htlc_changestate(htlc, SENT_ADD_ACK_REVOCATION, RCVD_REMOVE_HTLC); |
|
|
|
htlc_changestate(htlc, SENT_ADD_ACK_REVOCATION, RCVD_REMOVE_HTLC, false); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
static Pkt *handle_pkt_revocation(struct peer *peer, const Pkt *pkt) |
|
|
|
static Pkt *handle_pkt_revocation(struct peer *peer, const Pkt *pkt, |
|
|
|
enum state next_state) |
|
|
|
{ |
|
|
|
Pkt *err; |
|
|
|
const char *errmsg; |
|
|
|
static const struct state_table changes[] = { |
|
|
|
{ SENT_ADD_COMMIT, RCVD_ADD_REVOCATION }, |
|
|
|
{ SENT_REMOVE_ACK_COMMIT, RCVD_REMOVE_ACK_REVOCATION }, |
|
|
@ -952,8 +1044,33 @@ static Pkt *handle_pkt_revocation(struct peer *peer, const Pkt *pkt) |
|
|
|
* The receiver of `update_revocation`... MUST add the remote |
|
|
|
* unacked changes to the set of local acked changes. |
|
|
|
*/ |
|
|
|
if (!htlcs_changestate(peer, changes, ARRAY_SIZE(changes))) |
|
|
|
fatal("Revocation received but we made empty commitment?"); |
|
|
|
if (!db_start_transaction(peer)) |
|
|
|
return pkt_err(peer, "database error"); |
|
|
|
errmsg = htlcs_changestate(peer, changes, ARRAY_SIZE(changes), true); |
|
|
|
if (errmsg) { |
|
|
|
log_broken(peer->log, "accept_pkt_revocation: %s", errmsg); |
|
|
|
db_abort_transaction(peer); |
|
|
|
return pkt_err(peer, "failure accepting update_revocation: %s", |
|
|
|
errmsg); |
|
|
|
} |
|
|
|
if (!db_save_shachain(peer)) { |
|
|
|
db_abort_transaction(peer); |
|
|
|
return pkt_err(peer, "database error"); |
|
|
|
} |
|
|
|
if (!db_update_next_revocation_hash(peer)) { |
|
|
|
db_abort_transaction(peer); |
|
|
|
return pkt_err(peer, "database error"); |
|
|
|
} |
|
|
|
if (!set_peer_state(peer, next_state, __func__, true)) { |
|
|
|
db_abort_transaction(peer); |
|
|
|
return pkt_err(peer, "database error"); |
|
|
|
} |
|
|
|
if (!db_remove_their_prev_revocation_hash(peer)) { |
|
|
|
db_abort_transaction(peer); |
|
|
|
return pkt_err(peer, "database error"); |
|
|
|
} |
|
|
|
if (!db_commit_transaction(peer)) |
|
|
|
return pkt_err(peer, "database error"); |
|
|
|
|
|
|
|
return NULL; |
|
|
|
} |
|
|
@ -988,7 +1105,40 @@ static void peer_calculate_close_fee(struct peer *peer) |
|
|
|
assert(!(peer->closing.our_fee & 1)); |
|
|
|
} |
|
|
|
|
|
|
|
/* This is the io loop while we're shutdown. */ |
|
|
|
static bool start_closing_in_transaction(struct peer *peer) |
|
|
|
{ |
|
|
|
assert(!committed_to_htlcs(peer)); |
|
|
|
|
|
|
|
if (!set_peer_state(peer, STATE_MUTUAL_CLOSING, __func__, true)) |
|
|
|
return false; |
|
|
|
|
|
|
|
peer_calculate_close_fee(peer); |
|
|
|
peer->closing.closing_order = peer->order_counter++; |
|
|
|
if (!db_update_our_closing(peer)) |
|
|
|
return false; |
|
|
|
queue_pkt_close_signature(peer); |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
static Pkt *start_closing(struct peer *peer) |
|
|
|
{ |
|
|
|
if (!db_start_transaction(peer)) |
|
|
|
goto fail; |
|
|
|
|
|
|
|
if (!start_closing_in_transaction(peer)) { |
|
|
|
db_abort_transaction(peer); |
|
|
|
goto fail; |
|
|
|
} |
|
|
|
|
|
|
|
if (!db_commit_transaction(peer)) |
|
|
|
goto fail; |
|
|
|
return NULL; |
|
|
|
|
|
|
|
fail: |
|
|
|
return pkt_err(peer, "database error"); |
|
|
|
} |
|
|
|
|
|
|
|
/* This is the io loop while we're doing shutdown. */ |
|
|
|
static bool shutdown_pkt_in(struct peer *peer, const Pkt *pkt) |
|
|
|
{ |
|
|
|
Pkt *err = NULL; |
|
|
@ -1001,11 +1151,9 @@ static bool shutdown_pkt_in(struct peer *peer, const Pkt *pkt) |
|
|
|
if (peer->state == STATE_SHUTDOWN) |
|
|
|
err = pkt_err_unexpected(peer, pkt); |
|
|
|
else { |
|
|
|
err = handle_pkt_revocation(peer, pkt); |
|
|
|
if (!err) { |
|
|
|
set_peer_state(peer, STATE_SHUTDOWN, __func__); |
|
|
|
err = handle_pkt_revocation(peer, pkt, STATE_SHUTDOWN); |
|
|
|
if (!err) |
|
|
|
peer_update_complete(peer); |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
@ -1026,8 +1174,13 @@ static bool shutdown_pkt_in(struct peer *peer, const Pkt *pkt) |
|
|
|
* A node... MUST NOT send more than one `close_shutdown`. */ |
|
|
|
if (peer->closing.their_script) |
|
|
|
err = pkt_err_unexpected(peer, pkt); |
|
|
|
else |
|
|
|
else { |
|
|
|
err = accept_pkt_close_shutdown(peer, pkt); |
|
|
|
if (!err) { |
|
|
|
if (!db_set_their_closing_script(peer)) |
|
|
|
err = pkt_err(peer, "database error"); |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case PKT__PKT_UPDATE_FULFILL_HTLC: |
|
|
@ -1055,49 +1208,70 @@ static bool shutdown_pkt_in(struct peer *peer, const Pkt *pkt) |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
if (!err && !committed_to_htlcs(peer)) |
|
|
|
err = start_closing(peer); |
|
|
|
|
|
|
|
if (err) |
|
|
|
return peer_comms_err(peer, err); |
|
|
|
|
|
|
|
if (!committed_to_htlcs(peer)) { |
|
|
|
set_peer_state(peer, STATE_MUTUAL_CLOSING, __func__); |
|
|
|
peer_calculate_close_fee(peer); |
|
|
|
peer->closing.closing_order = peer->order_counter++; |
|
|
|
queue_pkt_close_signature(peer); |
|
|
|
} |
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
static void peer_start_shutdown(struct peer *peer) |
|
|
|
static bool peer_start_shutdown(struct peer *peer) |
|
|
|
{ |
|
|
|
assert(peer->state == STATE_SHUTDOWN |
|
|
|
|| peer->state == STATE_SHUTDOWN_COMMITTING); |
|
|
|
enum state newstate; |
|
|
|
u8 *redeemscript; |
|
|
|
|
|
|
|
if (!db_start_transaction(peer)) |
|
|
|
return false; |
|
|
|
|
|
|
|
if (!db_begin_shutdown(peer)) { |
|
|
|
db_abort_transaction(peer); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
/* If they started close, we might not have sent ours. */ |
|
|
|
if (!peer->closing.our_script) { |
|
|
|
u8 *redeemscript = bitcoin_redeem_single(peer, |
|
|
|
peer->dstate->secpctx, |
|
|
|
&peer->local.finalkey); |
|
|
|
assert(!peer->closing.our_script); |
|
|
|
|
|
|
|
peer->closing.our_script = scriptpubkey_p2sh(peer, redeemscript); |
|
|
|
tal_free(redeemscript); |
|
|
|
/* BOLT #2:
|
|
|
|
* |
|
|
|
* A node SHOULD send a `close_shutdown` (if it has |
|
|
|
* not already) after receiving `close_shutdown`. |
|
|
|
*/ |
|
|
|
peer->closing.shutdown_order = peer->order_counter++; |
|
|
|
queue_pkt_close_shutdown(peer); |
|
|
|
redeemscript = bitcoin_redeem_single(peer, |
|
|
|
peer->dstate->secpctx, |
|
|
|
&peer->local.finalkey); |
|
|
|
|
|
|
|
peer->closing.our_script = scriptpubkey_p2sh(peer, redeemscript); |
|
|
|
tal_free(redeemscript); |
|
|
|
|
|
|
|
/* BOLT #2:
|
|
|
|
* |
|
|
|
* A node SHOULD send a `close_shutdown` (if it has |
|
|
|
* not already) after receiving `close_shutdown`. |
|
|
|
*/ |
|
|
|
peer->closing.shutdown_order = peer->order_counter++; |
|
|
|
if (!db_set_our_closing_script(peer)) { |
|
|
|
db_abort_transaction(peer); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
queue_pkt_close_shutdown(peer); |
|
|
|
|
|
|
|
if (peer->state == STATE_NORMAL_COMMITTING) |
|
|
|
newstate = STATE_SHUTDOWN_COMMITTING; |
|
|
|
else { |
|
|
|
assert(peer->state == STATE_NORMAL); |
|
|
|
newstate = STATE_SHUTDOWN; |
|
|
|
} |
|
|
|
if (!set_peer_state(peer, newstate, __func__, true)) { |
|
|
|
db_abort_transaction(peer); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
/* Catch case where we've exchanged and had no HTLCs anyway. */ |
|
|
|
if (peer->closing.our_script && peer->closing.their_script |
|
|
|
&& !committed_to_htlcs(peer)) { |
|
|
|
set_peer_state(peer, STATE_MUTUAL_CLOSING, __func__); |
|
|
|
peer_calculate_close_fee(peer); |
|
|
|
peer->closing.closing_order = peer->order_counter++; |
|
|
|
queue_pkt_close_signature(peer); |
|
|
|
if (peer->closing.their_script && !committed_to_htlcs(peer)) { |
|
|
|
if (!start_closing_in_transaction(peer)) { |
|
|
|
db_abort_transaction(peer); |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
return db_commit_transaction(peer); |
|
|
|
} |
|
|
|
|
|
|
|
/* This is the io loop while we're in normal mode. */ |
|
|
@ -1129,24 +1303,17 @@ static bool normal_pkt_in(struct peer *peer, const Pkt *pkt) |
|
|
|
err = accept_pkt_close_shutdown(peer, pkt); |
|
|
|
if (err) |
|
|
|
break; |
|
|
|
if (peer->state == STATE_NORMAL) |
|
|
|
set_peer_state(peer, STATE_SHUTDOWN, __func__); |
|
|
|
else { |
|
|
|
assert(peer->state == STATE_NORMAL_COMMITTING); |
|
|
|
set_peer_state(peer, STATE_SHUTDOWN_COMMITTING, |
|
|
|
__func__); |
|
|
|
if (!peer_start_shutdown(peer)) { |
|
|
|
err = pkt_err(peer, "database error"); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
peer_start_shutdown(peer); |
|
|
|
return true; |
|
|
|
|
|
|
|
case PKT_UPDATE_REVOCATION: |
|
|
|
if (peer->state == STATE_NORMAL_COMMITTING) { |
|
|
|
err = handle_pkt_revocation(peer, pkt); |
|
|
|
if (!err) { |
|
|
|
err = handle_pkt_revocation(peer, pkt, STATE_NORMAL); |
|
|
|
if (!err) |
|
|
|
peer_update_complete(peer); |
|
|
|
set_peer_state(peer, STATE_NORMAL, __func__); |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
/* Fall thru. */ |
|
|
@ -1170,7 +1337,7 @@ static void state_single(struct peer *peer, |
|
|
|
size_t old_outpkts = tal_count(peer->outpkt); |
|
|
|
|
|
|
|
newstate = state(peer, input, pkt, &broadcast); |
|
|
|
set_peer_state(peer, newstate, input_name(input)); |
|
|
|
set_peer_state(peer, newstate, input_name(input), false); |
|
|
|
|
|
|
|
/* We never come here again once we leave opening states. */ |
|
|
|
if (state_is_normal(peer->state)) { |
|
|
@ -1203,6 +1370,19 @@ static void state_single(struct peer *peer, |
|
|
|
|
|
|
|
/* Start output if not running already; it will close conn. */ |
|
|
|
io_wake(peer); |
|
|
|
} else if (!state_is_opening(peer->state)) { |
|
|
|
/* Now in STATE_NORMAL, so save. */ |
|
|
|
if (!db_start_transaction(peer) |
|
|
|
|| !db_update_state(peer) |
|
|
|
|| !db_commit_transaction(peer)) { |
|
|
|
set_peer_state(peer, STATE_ERR_BREAKDOWN, __func__, |
|
|
|
false); |
|
|
|
peer_breakdown(peer); |
|
|
|
|
|
|
|
/* Start output if not running already; it will close conn. */ |
|
|
|
io_wake(peer); |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -1287,7 +1467,7 @@ static bool command_htlc_fail(struct peer *peer, struct htlc *htlc) |
|
|
|
*/ |
|
|
|
cstate_fail_htlc(peer->remote.staging_cstate, htlc); |
|
|
|
|
|
|
|
htlc_changestate(htlc, RCVD_ADD_ACK_REVOCATION, SENT_REMOVE_HTLC); |
|
|
|
htlc_changestate(htlc, RCVD_ADD_ACK_REVOCATION, SENT_REMOVE_HTLC, false); |
|
|
|
|
|
|
|
remote_changes_pending(peer); |
|
|
|
|
|
|
@ -1336,7 +1516,7 @@ static bool command_htlc_fulfill(struct peer *peer, struct htlc *htlc) |
|
|
|
*/ |
|
|
|
cstate_fulfill_htlc(peer->remote.staging_cstate, htlc); |
|
|
|
|
|
|
|
htlc_changestate(htlc, RCVD_ADD_ACK_REVOCATION, SENT_REMOVE_HTLC); |
|
|
|
htlc_changestate(htlc, RCVD_ADD_ACK_REVOCATION, SENT_REMOVE_HTLC, false); |
|
|
|
|
|
|
|
remote_changes_pending(peer); |
|
|
|
|
|
|
@ -1705,6 +1885,12 @@ static void retransmit_pkts(struct peer *peer, s64 ack) |
|
|
|
assert(commit_num < peer->local.commit->commit_num); |
|
|
|
peer_get_revocation_preimage(peer, commit_num,&preimage); |
|
|
|
peer_get_revocation_hash(peer, commit_num + 2, &next); |
|
|
|
log_debug(peer->log, "Re-sending revocation hash %"PRIu64, |
|
|
|
commit_num + 2); |
|
|
|
log_add_struct(peer->log, "value %s", struct sha256, |
|
|
|
&next); |
|
|
|
log_add_struct(peer->log, "local.next=%s", struct sha256, |
|
|
|
&peer->local.next_revocation_hash); |
|
|
|
log_debug(peer->log, "Re-sending revocation %"PRIu64, |
|
|
|
commit_num); |
|
|
|
queue_pkt_revocation(peer, &preimage, &next); |
|
|
@ -1741,6 +1927,9 @@ static struct io_plan *peer_crypto_on(struct io_conn *conn, struct peer *peer) |
|
|
|
|
|
|
|
assert(peer->state == STATE_INIT); |
|
|
|
|
|
|
|
if (!db_create_peer(peer)) |
|
|
|
fatal("Database error in %s", __func__); |
|
|
|
|
|
|
|
state_event(peer, peer->local.offer_anchor, NULL); |
|
|
|
|
|
|
|
assert(!peer->connected); |
|
|
@ -1789,6 +1978,7 @@ static void peer_disconnect(struct io_conn *conn, struct peer *peer) |
|
|
|
static void do_commit(struct peer *peer, struct command *jsoncmd) |
|
|
|
{ |
|
|
|
struct commit_info *ci; |
|
|
|
const char *errmsg; |
|
|
|
static const struct state_table changes[] = { |
|
|
|
{ SENT_ADD_HTLC, SENT_ADD_COMMIT }, |
|
|
|
{ SENT_REMOVE_REVOCATION, SENT_REMOVE_ACK_COMMIT }, |
|
|
@ -1819,13 +2009,17 @@ static void do_commit(struct peer *peer, struct command *jsoncmd) |
|
|
|
= tal_dup(peer, struct sha256, |
|
|
|
&peer->remote.commit->revocation_hash); |
|
|
|
|
|
|
|
/* BOLT #2:
|
|
|
|
* |
|
|
|
* A node MUST NOT send an `update_commit` message which does |
|
|
|
* not include any updates. |
|
|
|
*/ |
|
|
|
if (!htlcs_changestate(peer, changes, ARRAY_SIZE(changes))) |
|
|
|
fatal("sent commit with no changes"); |
|
|
|
if (!db_start_transaction(peer)) { |
|
|
|
/* FIXME: Return error. */ |
|
|
|
fatal("queue_pkt_commit: db fail"); |
|
|
|
} |
|
|
|
|
|
|
|
errmsg = htlcs_changestate(peer, changes, ARRAY_SIZE(changes), true); |
|
|
|
if (errmsg) { |
|
|
|
log_broken(peer->log, "queue_pkt_commit: %s", errmsg); |
|
|
|
/* FIXME: Return error. */ |
|
|
|
fatal("queue_pkt_commit: %s", errmsg); |
|
|
|
} |
|
|
|
|
|
|
|
/* Create new commit info for this commit tx. */ |
|
|
|
ci->revocation_hash = peer->remote.next_revocation_hash; |
|
|
@ -1840,7 +2034,8 @@ static void do_commit(struct peer *peer, struct command *jsoncmd) |
|
|
|
bitcoin_txid(ci->tx, &ci->txid); |
|
|
|
|
|
|
|
if (!to_us_only) { |
|
|
|
log_debug(peer->log, "Signing tx for %u/%u msatoshis, %u/%u htlcs (%u non-dust)", |
|
|
|
log_debug(peer->log, "Signing tx %"PRIu64" for %u/%u msatoshis, %u/%u htlcs (%u non-dust)", |
|
|
|
ci->commit_num, |
|
|
|
ci->cstate->side[OURS].pay_msat, |
|
|
|
ci->cstate->side[THEIRS].pay_msat, |
|
|
|
ci->cstate->side[OURS].num_htlcs, |
|
|
@ -1856,19 +2051,29 @@ static void do_commit(struct peer *peer, struct command *jsoncmd) |
|
|
|
/* Switch to the new commitment. */ |
|
|
|
tal_free(peer->remote.commit); |
|
|
|
peer->remote.commit = ci; |
|
|
|
|
|
|
|
peer_add_their_commit(peer, &ci->txid, ci->commit_num); |
|
|
|
|
|
|
|
peer->remote.commit->order = peer->order_counter++; |
|
|
|
queue_pkt_commit(peer, ci->sig); |
|
|
|
if (!db_new_commit_info(peer, THEIRS, peer->their_prev_revocation_hash)){ |
|
|
|
/* FIXME: Return error. */ |
|
|
|
fatal("queue_pkt_commit: database error"); |
|
|
|
} |
|
|
|
/* We don't need to remember their commit if we don't give sig. */ |
|
|
|
if (ci->sig && !peer_add_their_commit(peer, &ci->txid, ci->commit_num)) |
|
|
|
/* FIXME: Return error. */ |
|
|
|
fatal("queue_pkt_commit: database error"); |
|
|
|
|
|
|
|
if (peer->state == STATE_SHUTDOWN) { |
|
|
|
set_peer_state(peer, STATE_SHUTDOWN_COMMITTING, __func__); |
|
|
|
set_peer_state(peer, STATE_SHUTDOWN_COMMITTING, __func__, true); |
|
|
|
} else { |
|
|
|
assert(peer->state == STATE_NORMAL); |
|
|
|
set_peer_state(peer, STATE_NORMAL_COMMITTING, __func__); |
|
|
|
set_peer_state(peer, STATE_NORMAL_COMMITTING, __func__, true); |
|
|
|
} |
|
|
|
if (!db_commit_transaction(peer)) |
|
|
|
/* FIXME: Return error. */ |
|
|
|
fatal("queue_pkt_commit: database error"); |
|
|
|
queue_pkt_commit(peer, ci->sig); |
|
|
|
} |
|
|
|
|
|
|
|
/* FIXME: don't spin on this timer if we're not connected! */ |
|
|
|
static void try_commit(struct peer *peer) |
|
|
|
{ |
|
|
|
peer->commit_timer = NULL; |
|
|
@ -2119,6 +2324,13 @@ static struct io_plan *reconnect_pkt_in(struct io_conn *conn, struct peer *peer) |
|
|
|
/* Queue prompted us to reconnect, but we need to eliminate it now. */ |
|
|
|
clear_output_queue(peer); |
|
|
|
|
|
|
|
/* They might have missed the error, tell them before hanging up */ |
|
|
|
if (state_is_error(peer->state)) { |
|
|
|
queue_pkt_err(peer, pkt_err(peer, "In error state %s", |
|
|
|
state_name(peer->state))); |
|
|
|
return pkt_out(conn, peer); |
|
|
|
} |
|
|
|
|
|
|
|
/* Send any packets they missed. */ |
|
|
|
retransmit_pkts(peer, peer->inpkt->reconnect->ack); |
|
|
|
|
|
|
@ -2127,7 +2339,13 @@ static struct io_plan *reconnect_pkt_in(struct io_conn *conn, struct peer *peer) |
|
|
|
if (!state_can_io(peer->state)) { |
|
|
|
log_debug(peer->log, "State %s, closing immediately", |
|
|
|
state_name(peer->state)); |
|
|
|
return io_close(conn); |
|
|
|
return pkt_out(conn, peer); |
|
|
|
} |
|
|
|
|
|
|
|
/* We could have commitments pending from before. */ |
|
|
|
if (peer_uncommitted_changes(peer)) { |
|
|
|
log_debug(peer->log, "reconnect_pkt_in: changes pending."); |
|
|
|
remote_changes_pending(peer); |
|
|
|
} |
|
|
|
|
|
|
|
/* Back into normal mode. */ |
|
|
@ -2521,7 +2739,7 @@ static void check_htlc_expiry(struct peer *peer) |
|
|
|
return; |
|
|
|
|
|
|
|
if (any_deadline_past(peer)) { |
|
|
|
set_peer_state(peer, STATE_ERR_BREAKDOWN, __func__); |
|
|
|
set_peer_state(peer, STATE_ERR_BREAKDOWN, __func__, false); |
|
|
|
peer_breakdown(peer); |
|
|
|
} |
|
|
|
} |
|
|
@ -3133,7 +3351,8 @@ static enum watch_result check_for_resolution(struct peer *peer, |
|
|
|
* output which is not *irrevocably resolved* until all outputs are |
|
|
|
* *irrevocably resolved*. |
|
|
|
*/ |
|
|
|
set_peer_state(peer, STATE_CLOSED, "check_for_resolution"); |
|
|
|
set_peer_state(peer, STATE_CLOSED, "check_for_resolution", false); |
|
|
|
db_forget_peer(peer); |
|
|
|
|
|
|
|
/* It's theoretically possible that peer is still writing output */ |
|
|
|
if (!peer->conn) |
|
|
@ -3378,7 +3597,8 @@ static enum watch_result anchor_spent(struct peer *peer, |
|
|
|
if (err && state_can_io(peer->state)) |
|
|
|
queue_pkt_err(peer, err); |
|
|
|
|
|
|
|
set_peer_state(peer, newstate, "anchor_spent"); |
|
|
|
/* Don't need to save to DB: it will be replayed if we crash. */ |
|
|
|
set_peer_state(peer, newstate, "anchor_spent", false); |
|
|
|
|
|
|
|
/* If we've just closed connection, make output close it. */ |
|
|
|
io_wake(peer); |
|
|
@ -3405,7 +3625,8 @@ unknown_spend: |
|
|
|
* cheating attempt). Such a transaction implies its |
|
|
|
* private key has leaked, and funds may be lost. |
|
|
|
*/ |
|
|
|
set_peer_state(peer, STATE_ERR_INFORMATION_LEAK, "anchor_spent"); |
|
|
|
/* FIXME: Save to db. */ |
|
|
|
set_peer_state(peer, STATE_ERR_INFORMATION_LEAK, "anchor_spent", false); |
|
|
|
return DELETE_WATCH; |
|
|
|
} |
|
|
|
|
|
|
@ -3640,12 +3861,20 @@ static struct io_plan *init_conn(struct io_conn *conn, struct peer *peer) |
|
|
|
static void try_reconnect(struct peer *peer) |
|
|
|
{ |
|
|
|
struct io_conn *conn; |
|
|
|
int fd = socket(peer->addr.saddr.s.sa_family, peer->addr.type, |
|
|
|
peer->addr.protocol); |
|
|
|
int fd; |
|
|
|
|
|
|
|
/* Already reconnected? */ |
|
|
|
if (peer->conn) { |
|
|
|
log_debug(peer->log, "try_reconnect: already connected"); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
fd = socket(peer->addr.saddr.s.sa_family, peer->addr.type, |
|
|
|
peer->addr.protocol); |
|
|
|
if (fd < 0) { |
|
|
|
log_broken(peer->log, "do_reconnect: failed to create socket: %s", |
|
|
|
strerror(errno)); |
|
|
|
set_peer_state(peer, STATE_ERR_BREAKDOWN, "do_reconnect"); |
|
|
|
set_peer_state(peer, STATE_ERR_BREAKDOWN, "do_reconnect", false); |
|
|
|
peer_breakdown(peer); |
|
|
|
return; |
|
|
|
} |
|
|
@ -3842,12 +4071,14 @@ static void json_newhtlc(struct command *cmd, |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
log_debug(peer->log, "JSON command to add new HTLC"); |
|
|
|
htlc = command_htlc_add(peer, msatoshis, expiry, &rhash, NULL, |
|
|
|
dummy_single_route(cmd, peer, msatoshis)); |
|
|
|
if (!htlc) { |
|
|
|
command_fail(cmd, "could not add htlc"); |
|
|
|
return; |
|
|
|
} |
|
|
|
log_debug(peer->log, "JSON new HTLC is %"PRIu64, htlc->id); |
|
|
|
|
|
|
|
json_object_start(response, NULL); |
|
|
|
json_add_u64(response, "id", htlc->id); |
|
|
@ -3927,7 +4158,11 @@ static void json_fulfillhtlc(struct command *cmd, |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
set_htlc_rval(peer, htlc, &r); |
|
|
|
/* This can happen if we're disconnected, and thus haven't sent
|
|
|
|
* fulfill yet; we stored r in database immediately. */ |
|
|
|
if (!htlc->r) |
|
|
|
set_htlc_rval(peer, htlc, &r); |
|
|
|
|
|
|
|
if (command_htlc_fulfill(peer, htlc)) |
|
|
|
command_success(cmd, null_response(cmd)); |
|
|
|
else |
|
|
@ -4068,11 +4303,10 @@ static void json_close(struct command *cmd, |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (peer->state == STATE_NORMAL_COMMITTING) |
|
|
|
set_peer_state(peer, STATE_SHUTDOWN_COMMITTING, __func__); |
|
|
|
else |
|
|
|
set_peer_state(peer, STATE_SHUTDOWN, __func__); |
|
|
|
peer_start_shutdown(peer); |
|
|
|
if (!peer_start_shutdown(peer)) { |
|
|
|
command_fail(cmd, "Database error"); |
|
|
|
return; |
|
|
|
} |
|
|
|
command_success(cmd, null_response(cmd)); |
|
|
|
} |
|
|
|
|
|
|
@ -4111,7 +4345,7 @@ static void json_disconnect(struct command *cmd, |
|
|
|
* one side to freak out. We just ensure we ignore it. */ |
|
|
|
log_debug(peer->log, "Pretending connection is closed"); |
|
|
|
peer->fake_close = true; |
|
|
|
set_peer_state(peer, STATE_ERR_BREAKDOWN, "json_disconnect"); |
|
|
|
set_peer_state(peer, STATE_ERR_BREAKDOWN, "json_disconnect", false); |
|
|
|
peer_breakdown(peer); |
|
|
|
|
|
|
|
command_success(cmd, null_response(cmd)); |
|
|
|