5 changed files with 132 additions and 324 deletions
@ -1,208 +0,0 @@ |
|||
#include <ccan/build_assert/build_assert.h> |
|||
#include <daemon/db.h> |
|||
#include <daemon/lightningd.h> |
|||
#include <daemon/log.h> |
|||
#include <daemon/packets.h> |
|||
#include <daemon/peer.h> |
|||
#include <daemon/secrets.h> |
|||
#include <names.h> |
|||
#include <state.h> |
|||
|
|||
static enum state next_state(struct peer *peer, const enum state state) |
|||
{ |
|||
assert(peer->state != state); |
|||
return state; |
|||
} |
|||
|
|||
static Pkt *init_from_pkt_open(struct peer *peer, const Pkt *pkt) |
|||
{ |
|||
struct commit_info *ci = new_commit_info(peer, 0); |
|||
Pkt *err; |
|||
|
|||
err = accept_pkt_open(peer, pkt, &ci->revocation_hash, |
|||
&peer->remote.next_revocation_hash); |
|||
if (err) |
|||
return err; |
|||
|
|||
db_start_transaction(peer); |
|||
db_set_visible_state(peer); |
|||
if (db_commit_transaction(peer) != NULL) |
|||
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; |
|||
|
|||
/* Witness script for anchor. */ |
|||
peer->anchor.witnessscript |
|||
= bitcoin_redeem_2of2(peer, peer->dstate->secpctx, |
|||
&peer->local.commitkey, |
|||
&peer->remote.commitkey); |
|||
return NULL; |
|||
} |
|||
|
|||
enum state state(struct peer *peer, |
|||
const enum state_input input, |
|||
const Pkt *pkt, |
|||
const struct bitcoin_tx **broadcast) |
|||
{ |
|||
Pkt *err; |
|||
|
|||
*broadcast = NULL; |
|||
|
|||
switch (peer->state) { |
|||
/*
|
|||
* Initial channel opening states. |
|||
*/ |
|||
case STATE_OPEN_WAIT_FOR_OPEN_NOANCHOR: |
|||
if (input_is(input, PKT_OPEN)) { |
|||
err = init_from_pkt_open(peer, pkt); |
|||
if (err) { |
|||
peer_open_complete(peer, err->error->problem); |
|||
goto err_breakdown; |
|||
} |
|||
return next_state(peer, STATE_OPEN_WAIT_FOR_ANCHOR); |
|||
} else if (input_is_pkt(input)) { |
|||
peer_open_complete(peer, "unexpected packet"); |
|||
goto unexpected_pkt; |
|||
} |
|||
break; |
|||
case STATE_OPEN_WAIT_FOR_ANCHOR: |
|||
if (input_is(input, PKT_OPEN_ANCHOR)) { |
|||
const char *db_err; |
|||
|
|||
err = accept_pkt_anchor(peer, pkt); |
|||
if (err) { |
|||
peer_open_complete(peer, err->error->problem); |
|||
goto err_breakdown; |
|||
} |
|||
|
|||
peer->anchor.ours = false; |
|||
if (!setup_first_commit(peer)) { |
|||
err = pkt_err(peer, "Insufficient funds for fee"); |
|||
peer_open_complete(peer, err->error->problem); |
|||
goto err_breakdown; |
|||
} |
|||
|
|||
log_debug_struct(peer->log, "Creating sig for %s", |
|||
struct bitcoin_tx, |
|||
peer->remote.commit->tx); |
|||
log_add_struct(peer->log, " using key %s", |
|||
struct pubkey, &peer->local.commitkey); |
|||
|
|||
peer->remote.commit->sig = tal(peer->remote.commit, |
|||
struct bitcoin_signature); |
|||
peer->remote.commit->sig->stype = SIGHASH_ALL; |
|||
peer_sign_theircommit(peer, peer->remote.commit->tx, |
|||
&peer->remote.commit->sig->sig); |
|||
|
|||
peer->remote.commit->order = peer->order_counter++; |
|||
db_start_transaction(peer); |
|||
db_set_anchor(peer); |
|||
db_new_commit_info(peer, REMOTE, NULL); |
|||
peer_add_their_commit(peer, |
|||
&peer->remote.commit->txid, |
|||
peer->remote.commit->commit_num); |
|||
db_err = db_commit_transaction(peer); |
|||
if (db_err) { |
|||
err = pkt_err(peer, "database error"); |
|||
peer_open_complete(peer, db_err); |
|||
goto err_breakdown; |
|||
} |
|||
|
|||
queue_pkt_open_commit_sig(peer); |
|||
peer_watch_anchor(peer, peer->local.mindepth); |
|||
|
|||
return next_state(peer, STATE_OPEN_WAITING_THEIRANCHOR); |
|||
} else if (input_is_pkt(input)) { |
|||
peer_open_complete(peer, "unexpected packet"); |
|||
goto unexpected_pkt; |
|||
} |
|||
break; |
|||
case STATE_OPEN_WAITING_THEIRANCHOR: |
|||
if (input_is(input, PKT_OPEN_COMPLETE)) { |
|||
err = accept_pkt_open_complete(peer, pkt); |
|||
if (err) { |
|||
peer_open_complete(peer, err->error->problem); |
|||
goto err_breakdown; |
|||
} |
|||
return next_state(peer, |
|||
STATE_OPEN_WAITING_THEIRANCHOR_THEYCOMPLETED); |
|||
} |
|||
/* Fall thru */ |
|||
case STATE_OPEN_WAITING_THEIRANCHOR_THEYCOMPLETED: |
|||
if (input_is(input, PKT_CLOSE_SHUTDOWN)) { |
|||
peer_open_complete(peer, "Received PKT_CLOSE_SHUTDOWN"); |
|||
goto accept_shutdown; |
|||
} else if (input_is_pkt(input)) { |
|||
peer_open_complete(peer, "unexpected packet"); |
|||
goto unexpected_pkt; |
|||
} |
|||
break; |
|||
case STATE_OPEN_WAIT_FOR_COMPLETE_OURANCHOR: |
|||
case STATE_OPEN_WAIT_FOR_COMPLETE_THEIRANCHOR: |
|||
if (input_is(input, PKT_OPEN_COMPLETE)) { |
|||
/* Ready for business! */ |
|||
peer_open_complete(peer, NULL); |
|||
return next_state(peer, STATE_NORMAL); |
|||
} else if (input_is(input, PKT_CLOSE_SHUTDOWN)) { |
|||
peer_open_complete(peer, "Received PKT_CLOSE_SHUTDOWN"); |
|||
goto accept_shutdown; |
|||
} else if (input_is_pkt(input)) { |
|||
peer_open_complete(peer, "unexpected packet"); |
|||
goto unexpected_pkt; |
|||
} |
|||
break; |
|||
|
|||
/* Should never happen. */ |
|||
case STATE_INIT: |
|||
case STATE_OPEN_WAIT_FOR_COMMIT_SIG: |
|||
case STATE_OPEN_WAITING_OURANCHOR: |
|||
case STATE_OPEN_WAITING_OURANCHOR_THEYCOMPLETED: |
|||
case STATE_OPEN_WAIT_FOR_OPEN_WITHANCHOR: |
|||
case STATE_NORMAL: |
|||
case STATE_NORMAL_COMMITTING: |
|||
case STATE_ERR_INTERNAL: |
|||
case STATE_ERR_ANCHOR_TIMEOUT: |
|||
case STATE_ERR_INFORMATION_LEAK: |
|||
case STATE_ERR_BREAKDOWN: |
|||
case STATE_CLOSED: |
|||
case STATE_MAX: |
|||
case STATE_SHUTDOWN: |
|||
case STATE_SHUTDOWN_COMMITTING: |
|||
case STATE_MUTUAL_CLOSING: |
|||
case STATE_CLOSE_ONCHAIN_CHEATED: |
|||
case STATE_CLOSE_ONCHAIN_THEIR_UNILATERAL: |
|||
case STATE_CLOSE_ONCHAIN_OUR_UNILATERAL: |
|||
case STATE_CLOSE_ONCHAIN_MUTUAL: |
|||
return next_state(peer, STATE_ERR_INTERNAL); |
|||
} |
|||
|
|||
/* State machine should handle all possible states. */ |
|||
return next_state(peer, STATE_ERR_INTERNAL); |
|||
|
|||
unexpected_pkt: |
|||
peer_unexpected_pkt(peer, pkt, __func__); |
|||
|
|||
/* Don't reply to an error with an error. */ |
|||
if (!input_is(input, PKT_ERROR)) { |
|||
goto breakdown; |
|||
} |
|||
err = pkt_err_unexpected(peer, pkt); |
|||
goto err_breakdown; |
|||
|
|||
err_breakdown: |
|||
queue_pkt_err(peer, err); |
|||
breakdown: |
|||
return next_state(peer, STATE_ERR_BREAKDOWN); |
|||
|
|||
accept_shutdown: |
|||
err = accept_pkt_close_shutdown(peer, pkt); |
|||
if (err) |
|||
goto err_breakdown; |
|||
|
|||
/* If we've sent commit, we're still waiting for it when shutdown. */ |
|||
if (peer->state == STATE_NORMAL_COMMITTING) |
|||
return next_state(peer, STATE_SHUTDOWN_COMMITTING); |
|||
return next_state(peer, STATE_SHUTDOWN); |
|||
} |
Loading…
Reference in new issue