mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-22 06:41:44 +01:00
peer: save/load results in database.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
71b8a07c56
commit
5f368f1c95
8 changed files with 441 additions and 109 deletions
|
@ -443,12 +443,19 @@ static void get_init_blockhash(struct lightningd_state *dstate, u32 blockcount,
|
|||
void *unused)
|
||||
{
|
||||
u32 start;
|
||||
struct peer *peer;
|
||||
|
||||
if (blockcount < 100)
|
||||
start = 0;
|
||||
else
|
||||
start = blockcount - 100;
|
||||
|
||||
/* If loaded from database, go back to earliest possible peer anchor. */
|
||||
list_for_each(&dstate->peers, peer, list) {
|
||||
if (peer->anchor.min_depth && peer->anchor.min_depth < start)
|
||||
start = peer->anchor.min_depth;
|
||||
}
|
||||
|
||||
/* Start topology from 100 blocks back. */
|
||||
bitcoind_getblockhash(dstate, start, get_init_block, int2ptr(start));
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include "db.h"
|
||||
#include "htlc.h"
|
||||
#include "log.h"
|
||||
#include "peer.h"
|
||||
|
@ -150,9 +151,10 @@ int htlc_state_flags(enum htlc_state state)
|
|||
return per_state_bits[state];
|
||||
}
|
||||
|
||||
void htlc_changestate(struct htlc *h,
|
||||
bool htlc_changestate(struct htlc *h,
|
||||
enum htlc_state oldstate,
|
||||
enum htlc_state newstate)
|
||||
enum htlc_state newstate,
|
||||
bool db_commit)
|
||||
{
|
||||
log_debug(h->peer->log, "htlc %"PRIu64": %s->%s", h->id,
|
||||
htlc_state_name(h->state), htlc_state_name(newstate));
|
||||
|
@ -166,6 +168,18 @@ void htlc_changestate(struct htlc *h,
|
|||
== (htlc_state_flags(newstate)&(HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER)));
|
||||
|
||||
h->state = newstate;
|
||||
|
||||
if (db_commit) {
|
||||
if (newstate == RCVD_ADD_COMMIT || newstate == SENT_ADD_COMMIT)
|
||||
return db_new_htlc(h->peer, h);
|
||||
/* These never hit the database. */
|
||||
if (oldstate == RCVD_REMOVE_HTLC)
|
||||
oldstate = SENT_ADD_ACK_REVOCATION;
|
||||
else if (oldstate == SENT_REMOVE_HTLC)
|
||||
oldstate = RCVD_ADD_ACK_REVOCATION;
|
||||
return db_update_htlc_state(h->peer, h, oldstate);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void htlc_undostate(struct htlc *h,
|
||||
|
|
|
@ -73,9 +73,10 @@ struct htlc {
|
|||
|
||||
const char *htlc_state_name(enum htlc_state s);
|
||||
enum htlc_state htlc_state_from_name(const char *name);
|
||||
void htlc_changestate(struct htlc *h,
|
||||
bool htlc_changestate(struct htlc *h,
|
||||
enum htlc_state oldstate,
|
||||
enum htlc_state newstate);
|
||||
enum htlc_state newstate,
|
||||
bool db_commit);
|
||||
int htlc_state_flags(enum htlc_state state);
|
||||
|
||||
static inline bool htlc_has(const struct htlc *h, int flag)
|
||||
|
|
436
daemon/peer.c
436
daemon/peer.c
|
@ -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));
|
||||
|
|
|
@ -243,7 +243,7 @@ void set_htlc_rval(struct peer *peer,
|
|||
bool setup_first_commit(struct peer *peer);
|
||||
|
||||
/* Whenever we send a signature, remember the txid -> commit_num mapping */
|
||||
void peer_add_their_commit(struct peer *peer,
|
||||
bool peer_add_their_commit(struct peer *peer,
|
||||
const struct sha256_double *txid, u64 commit_num);
|
||||
|
||||
/* Allocate a new commit_info struct. */
|
||||
|
@ -273,6 +273,8 @@ void peer_open_complete(struct peer *peer, const char *problem);
|
|||
|
||||
struct bitcoin_tx *peer_create_close_tx(struct peer *peer, u64 fee);
|
||||
|
||||
void debug_dump_peers(struct lightningd_state *dstate);
|
||||
|
||||
void reconnect_peers(struct lightningd_state *dstate);
|
||||
void cleanup_peers(struct lightningd_state *dstate);
|
||||
#endif /* LIGHTNING_DAEMON_PEER_H */
|
||||
|
|
|
@ -125,6 +125,7 @@ get_or_make_connection(struct lightningd_state *dstate,
|
|||
nc = tal(dstate, struct node_connection);
|
||||
nc->src = from;
|
||||
nc->dst = to;
|
||||
log_add(dstate->base_log, " = %p (%p->%p)", nc, from, to);
|
||||
|
||||
/* Hook it into in/out arrays. */
|
||||
i = tal_count(to->in);
|
||||
|
@ -226,6 +227,7 @@ struct peer *find_route(struct lightningd_state *dstate,
|
|||
src->bfg[0].total = msatoshi;
|
||||
|
||||
for (runs = 0; runs < ROUTING_MAX_HOPS; runs++) {
|
||||
log_debug(dstate->base_log, "Run %i", runs);
|
||||
/* Run through every edge. */
|
||||
for (n = node_map_first(dstate->nodes, &it);
|
||||
n;
|
||||
|
@ -233,6 +235,16 @@ struct peer *find_route(struct lightningd_state *dstate,
|
|||
size_t num_edges = tal_count(n->in);
|
||||
for (i = 0; i < num_edges; i++) {
|
||||
bfg_one_edge(n, i);
|
||||
log_debug(dstate->base_log, "We seek %p->%p, this is %p -> %p",
|
||||
dst, src, n->in[i]->src, n->in[i]->dst);
|
||||
log_debug_struct(dstate->base_log,
|
||||
"Checking from %s",
|
||||
struct pubkey,
|
||||
&n->in[i]->src->id);
|
||||
log_add_struct(dstate->base_log,
|
||||
" to %s",
|
||||
struct pubkey,
|
||||
&n->in[i]->dst->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "bitcoin/script.h"
|
||||
#include "bitcoin/signature.h"
|
||||
#include "bitcoin/tx.h"
|
||||
#include "db.h"
|
||||
#include "jsonrpc.h"
|
||||
#include "lightningd.h"
|
||||
#include "log.h"
|
||||
|
@ -108,6 +109,7 @@ static void json_newaddr(struct command *cmd,
|
|||
ripemd160(&w->p2sh, h.u.u8, sizeof(h));
|
||||
|
||||
list_add_tail(&cmd->dstate->wallet, &w->list);
|
||||
db_add_wallet_privkey(cmd->dstate, &w->privkey);
|
||||
|
||||
json_object_start(response, NULL);
|
||||
json_add_string(response, "address",
|
||||
|
|
66
state.c
66
state.c
|
@ -1,4 +1,5 @@
|
|||
#include <ccan/build_assert/build_assert.h>
|
||||
#include <daemon/db.h>
|
||||
#include <daemon/lightningd.h>
|
||||
#include <daemon/log.h>
|
||||
#include <daemon/packets.h>
|
||||
|
@ -44,7 +45,10 @@ static Pkt *init_from_pkt_open(struct peer *peer, const Pkt *pkt)
|
|||
&peer->remote.next_revocation_hash);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
||||
if (!db_set_visible_state(peer))
|
||||
return pkt_err(peer, "Database error");
|
||||
|
||||
/* Set up their commit info now: rest gets done in setup_first_commit
|
||||
* once anchor is established. */
|
||||
peer->remote.commit = ci;
|
||||
|
@ -147,10 +151,39 @@ enum state state(struct peer *peer,
|
|||
peer->remote.commit->sig->stype = SIGHASH_ALL;
|
||||
peer_sign_theircommit(peer, peer->remote.commit->tx,
|
||||
&peer->remote.commit->sig->sig);
|
||||
peer_add_their_commit(peer, &peer->remote.commit->txid,
|
||||
peer->remote.commit->commit_num);
|
||||
|
||||
peer->remote.commit->order = peer->order_counter++;
|
||||
if (!db_start_transaction(peer)) {
|
||||
err = pkt_err(peer, "database error");
|
||||
peer_open_complete(peer, err->error->problem);
|
||||
goto err_breakdown;
|
||||
}
|
||||
if (!db_set_anchor(peer)) {
|
||||
err = pkt_err(peer, "database error");
|
||||
peer_open_complete(peer, err->error->problem);
|
||||
db_abort_transaction(peer);
|
||||
goto err_breakdown;
|
||||
}
|
||||
if (!db_new_commit_info(peer, THEIRS, NULL)) {
|
||||
err = pkt_err(peer, "database error");
|
||||
peer_open_complete(peer, err->error->problem);
|
||||
db_abort_transaction(peer);
|
||||
goto err_breakdown;
|
||||
}
|
||||
if (!peer_add_their_commit(peer,
|
||||
&peer->remote.commit->txid,
|
||||
peer->remote.commit->commit_num)) {
|
||||
err = pkt_err(peer, "database error");
|
||||
peer_open_complete(peer, err->error->problem);
|
||||
db_abort_transaction(peer);
|
||||
goto err_breakdown;
|
||||
}
|
||||
if (!db_commit_transaction(peer)) {
|
||||
err = pkt_err(peer, "database error");
|
||||
peer_open_complete(peer, err->error->problem);
|
||||
goto err_breakdown;
|
||||
}
|
||||
|
||||
queue_pkt_open_commit_sig(peer);
|
||||
peer_watch_anchor(peer,
|
||||
peer->local.mindepth,
|
||||
|
@ -183,6 +216,33 @@ enum state state(struct peer *peer,
|
|||
goto err_breakdown;
|
||||
}
|
||||
peer->their_commitsigs++;
|
||||
|
||||
if (!db_start_transaction(peer)) {
|
||||
bitcoin_release_anchor(peer, INPUT_NONE);
|
||||
err = pkt_err(peer, "database error");
|
||||
peer_open_complete(peer, err->error->problem);
|
||||
goto err_breakdown;
|
||||
}
|
||||
if (!db_set_anchor(peer)) {
|
||||
bitcoin_release_anchor(peer, INPUT_NONE);
|
||||
err = pkt_err(peer, "database error");
|
||||
peer_open_complete(peer, err->error->problem);
|
||||
db_abort_transaction(peer);
|
||||
goto err_breakdown;
|
||||
}
|
||||
if (!db_new_commit_info(peer, OURS, NULL)) {
|
||||
bitcoin_release_anchor(peer, INPUT_NONE);
|
||||
err = pkt_err(peer, "database error");
|
||||
peer_open_complete(peer, err->error->problem);
|
||||
db_abort_transaction(peer);
|
||||
goto err_breakdown;
|
||||
}
|
||||
if (!db_commit_transaction(peer)) {
|
||||
bitcoin_release_anchor(peer, INPUT_NONE);
|
||||
err = pkt_err(peer, "database error");
|
||||
peer_open_complete(peer, err->error->problem);
|
||||
goto err_breakdown;
|
||||
}
|
||||
queue_tx_broadcast(broadcast, bitcoin_anchor(peer));
|
||||
peer_watch_anchor(peer,
|
||||
peer->local.mindepth,
|
||||
|
|
Loading…
Add table
Reference in a new issue