mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
test_state_coverage: test all accept_pkt failure paths.
Reveals a number of places where we don't handle errors correctly. Note: this takes about 14.5 GB to test on my x86-64 box. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
82e25a31cb
commit
1ac08e3b11
62
state.c
62
state.c
@ -450,6 +450,7 @@ enum state state(const enum state state, const struct state_data *sdata,
|
||||
idata->pkt, &sig);
|
||||
if (err) {
|
||||
fail_cmd(effect, CMD_SEND_UPDATE_ANY, NULL);
|
||||
set_effect(effect, htlc_abandon, true);
|
||||
goto err_start_unilateral_close;
|
||||
}
|
||||
set_effect(effect, update_theirsig, sig);
|
||||
@ -485,8 +486,10 @@ enum state state(const enum state state, const struct state_data *sdata,
|
||||
if (input_is(input, PKT_UPDATE_COMPLETE)) {
|
||||
err = accept_pkt_update_complete(effect, sdata,
|
||||
idata->pkt);
|
||||
if (err)
|
||||
if (err) {
|
||||
fail_cmd(effect, CMD_SEND_UPDATE_ANY, NULL);
|
||||
goto err_start_unilateral_close;
|
||||
}
|
||||
complete_cmd(effect, CMD_SEND_UPDATE_ANY);
|
||||
return toggle_prio(state, STATE_NORMAL);
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) {
|
||||
@ -515,8 +518,10 @@ enum state state(const enum state state, const struct state_data *sdata,
|
||||
struct signature *sig;
|
||||
err = accept_pkt_update_signature(effect, sdata,
|
||||
idata->pkt, &sig);
|
||||
if (err)
|
||||
if (err) {
|
||||
set_effect(effect, htlc_abandon, true);
|
||||
goto err_start_unilateral_close;
|
||||
}
|
||||
set_effect(effect, update_theirsig, sig);
|
||||
set_effect(effect, send,
|
||||
pkt_update_complete(effect, sdata));
|
||||
@ -552,7 +557,7 @@ enum state state(const enum state state, const struct state_data *sdata,
|
||||
err = accept_pkt_close_complete(effect, sdata,
|
||||
idata->pkt);
|
||||
if (err)
|
||||
goto err_start_unilateral_close;
|
||||
goto err_start_unilateral_close_already_closing;
|
||||
set_effect(effect, close_status, CMD_STATUS_SUCCESS);
|
||||
set_effect(effect, send, pkt_close_ack(effect, sdata));
|
||||
set_effect(effect, broadcast,
|
||||
@ -565,7 +570,7 @@ enum state state(const enum state state, const struct state_data *sdata,
|
||||
err = accept_pkt_simultaneous_close(effect, sdata,
|
||||
idata->pkt);
|
||||
if (err)
|
||||
goto err_start_unilateral_close;
|
||||
goto err_start_unilateral_close_already_closing;
|
||||
set_effect(effect, close_status, CMD_STATUS_SUCCESS);
|
||||
set_effect(effect, send, pkt_close_ack(effect, sdata));
|
||||
set_effect(effect, broadcast,
|
||||
@ -573,28 +578,17 @@ enum state state(const enum state state, const struct state_data *sdata,
|
||||
set_effect(effect, stop_commands, true);
|
||||
set_effect(effect, stop_packets, true);
|
||||
return STATE_CLOSE_WAIT_CLOSE;
|
||||
} else if (input_is(input, PKT_ERROR)) {
|
||||
set_effect(effect, in_error,
|
||||
set_errpkt(effect, idata->pkt));
|
||||
goto start_unilateral_close_already_closing;
|
||||
} else if (input_is_pkt(input)) {
|
||||
/* We ignore all other packets while closing. */
|
||||
return STATE_WAIT_FOR_CLOSE_COMPLETE;
|
||||
} else if (input_is(input, INPUT_CLOSE_COMPLETE_TIMEOUT)) {
|
||||
/* They didn't respond in time. Unilateral close. */
|
||||
set_effect(effect, send,
|
||||
pkt_err(effect, "Close timed out"));
|
||||
set_effect(effect, close_status, CMD_STATUS_FAILED);
|
||||
set_effect(effect, stop_commands, true);
|
||||
set_effect(effect, stop_packets, true);
|
||||
set_effect(effect, broadcast,
|
||||
bitcoin_commit(effect, sdata));
|
||||
set_effect(effect, watch,
|
||||
bitcoin_watch_delayed(effect,
|
||||
effect->broadcast,
|
||||
BITCOIN_ANCHOR_OURCOMMIT_DELAYPASSED));
|
||||
|
||||
/* We agreed to close: shouldn't have any HTLCs */
|
||||
if (committed_to_htlcs(sdata))
|
||||
return STATE_ERR_INTERNAL;
|
||||
|
||||
return STATE_CLOSE_WAIT_CLOSE_OURCOMMIT;
|
||||
err = pkt_err(effect, "Close timed out");
|
||||
goto err_start_unilateral_close_already_closing;
|
||||
}
|
||||
set_effect(effect, close_status, CMD_STATUS_FAILED);
|
||||
set_effect(effect, stop_commands, true);
|
||||
@ -943,6 +937,32 @@ start_unilateral_close:
|
||||
}
|
||||
return STATE_CLOSE_WAIT_OURCOMMIT;
|
||||
|
||||
err_start_unilateral_close_already_closing:
|
||||
/*
|
||||
* They timed out, or were broken; we are going to close unilaterally.
|
||||
*/
|
||||
set_effect(effect, send, err);
|
||||
|
||||
start_unilateral_close_already_closing:
|
||||
set_effect(effect, close_status, CMD_STATUS_FAILED);
|
||||
|
||||
/*
|
||||
* Close unilaterally.
|
||||
*/
|
||||
/* No more inputs, no more commands. */
|
||||
set_effect(effect, stop_packets, true);
|
||||
set_effect(effect, stop_commands, true);
|
||||
set_effect(effect, broadcast, bitcoin_commit(effect, sdata));
|
||||
set_effect(effect, watch,
|
||||
bitcoin_watch_delayed(effect, effect->broadcast,
|
||||
BITCOIN_ANCHOR_OURCOMMIT_DELAYPASSED));
|
||||
|
||||
/* We agreed to close: shouldn't have any HTLCs */
|
||||
if (committed_to_htlcs(sdata))
|
||||
return STATE_ERR_INTERNAL;
|
||||
|
||||
return STATE_CLOSE_WAIT_CLOSE_OURCOMMIT;
|
||||
|
||||
them_unilateral:
|
||||
assert(input == BITCOIN_ANCHOR_THEIRSPEND);
|
||||
|
||||
|
@ -30,6 +30,21 @@ static enum state_input *mapping_inputs;
|
||||
enum failure {
|
||||
FAIL_NONE,
|
||||
FAIL_DECLINE_HTLC,
|
||||
FAIL_STEAL,
|
||||
FAIL_ACCEPT_OPEN,
|
||||
FAIL_ACCEPT_ANCHOR,
|
||||
FAIL_ACCEPT_OPEN_COMMIT_SIG,
|
||||
FAIL_ACCEPT_HTLC_UPDATE,
|
||||
FAIL_ACCEPT_HTLC_ROUTEFAIL,
|
||||
FAIL_ACCEPT_HTLC_TIMEDOUT,
|
||||
FAIL_ACCEPT_HTLC_FULFILL,
|
||||
FAIL_ACCEPT_UPDATE_ACCEPT,
|
||||
FAIL_ACCEPT_UPDATE_COMPLETE,
|
||||
FAIL_ACCEPT_UPDATE_SIGNATURE,
|
||||
FAIL_ACCEPT_CLOSE,
|
||||
FAIL_ACCEPT_CLOSE_COMPLETE,
|
||||
FAIL_ACCEPT_CLOSE_ACK,
|
||||
FAIL_ACCEPT_SIMULTANEOUS_CLOSE
|
||||
};
|
||||
|
||||
struct htlc {
|
||||
@ -635,16 +650,22 @@ Pkt *unexpected_pkt(const tal_t *ctx, enum state_input input)
|
||||
|
||||
Pkt *accept_pkt_open(struct state_effect *effect, const struct state_data *sdata, const Pkt *pkt)
|
||||
{
|
||||
if (fail(sdata, FAIL_ACCEPT_OPEN))
|
||||
return pkt_err(effect, "Error inject");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Pkt *accept_pkt_anchor(struct state_effect *effect, const struct state_data *sdata, const Pkt *pkt)
|
||||
{
|
||||
if (fail(sdata, FAIL_ACCEPT_ANCHOR))
|
||||
return pkt_err(effect, "Error inject");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Pkt *accept_pkt_open_commit_sig(struct state_effect *effect, const struct state_data *sdata, const Pkt *pkt)
|
||||
{
|
||||
if (fail(sdata, FAIL_ACCEPT_OPEN_COMMIT_SIG))
|
||||
return pkt_err(effect, "Error inject");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -653,6 +674,9 @@ Pkt *accept_pkt_htlc_update(struct state_effect *effect,
|
||||
Pkt **decline,
|
||||
struct htlc_progress **htlcprog)
|
||||
{
|
||||
if (fail(sdata, FAIL_ACCEPT_HTLC_UPDATE))
|
||||
return pkt_err(effect, "Error inject");
|
||||
|
||||
if (fail(sdata, FAIL_DECLINE_HTLC))
|
||||
*decline = new_pkt(effect, PKT_UPDATE_DECLINE_HTLC);
|
||||
else {
|
||||
@ -673,6 +697,9 @@ Pkt *accept_pkt_htlc_routefail(struct state_effect *effect,
|
||||
unsigned int id = htlc_id_from_pkt(pkt);
|
||||
const struct htlc *h = find_htlc(sdata, id);
|
||||
|
||||
if (fail(sdata, FAIL_ACCEPT_HTLC_ROUTEFAIL))
|
||||
return pkt_err(effect, "Error inject");
|
||||
|
||||
/* The shouldn't fail unless it's to them */
|
||||
assert(h->to_them);
|
||||
|
||||
@ -689,6 +716,9 @@ Pkt *accept_pkt_htlc_timedout(struct state_effect *effect,
|
||||
unsigned int id = htlc_id_from_pkt(pkt);
|
||||
const struct htlc *h = find_htlc(sdata, id);
|
||||
|
||||
if (fail(sdata, FAIL_ACCEPT_HTLC_TIMEDOUT))
|
||||
return pkt_err(effect, "Error inject");
|
||||
|
||||
/* The shouldn't timeout unless it's to us */
|
||||
assert(!h->to_them);
|
||||
|
||||
@ -705,6 +735,9 @@ Pkt *accept_pkt_htlc_fulfill(struct state_effect *effect,
|
||||
unsigned int id = htlc_id_from_pkt(pkt);
|
||||
const struct htlc *h = find_htlc(sdata, id);
|
||||
|
||||
if (fail(sdata, FAIL_ACCEPT_HTLC_FULFILL))
|
||||
return pkt_err(effect, "Error inject");
|
||||
|
||||
/* The shouldn't complete unless it's to them */
|
||||
assert(h->to_them);
|
||||
|
||||
@ -716,12 +749,17 @@ Pkt *accept_pkt_htlc_fulfill(struct state_effect *effect,
|
||||
|
||||
Pkt *accept_pkt_update_accept(struct state_effect *effect, const struct state_data *sdata, const Pkt *pkt, struct signature **sig)
|
||||
{
|
||||
if (fail(sdata, FAIL_ACCEPT_UPDATE_ACCEPT))
|
||||
return pkt_err(effect, "Error inject");
|
||||
|
||||
*sig = (struct signature *)tal_strdup(effect, "from PKT_UPDATE_ACCEPT");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Pkt *accept_pkt_update_complete(struct state_effect *effect, const struct state_data *sdata, const Pkt *pkt)
|
||||
{
|
||||
if (fail(sdata, FAIL_ACCEPT_UPDATE_COMPLETE))
|
||||
return pkt_err(effect, "Error inject");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -729,27 +767,37 @@ Pkt *accept_pkt_update_signature(struct state_effect *effect,
|
||||
const struct state_data *sdata, const Pkt *pkt,
|
||||
struct signature **sig)
|
||||
{
|
||||
if (fail(sdata, FAIL_ACCEPT_UPDATE_SIGNATURE))
|
||||
return pkt_err(effect, "Error inject");
|
||||
*sig = (struct signature *)tal_strdup(effect, "from PKT_UPDATE_SIGNATURE");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Pkt *accept_pkt_close(struct state_effect *effect, const struct state_data *sdata, const Pkt *pkt)
|
||||
{
|
||||
if (fail(sdata, FAIL_ACCEPT_CLOSE))
|
||||
return pkt_err(effect, "Error inject");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Pkt *accept_pkt_close_complete(struct state_effect *effect, const struct state_data *sdata, const Pkt *pkt)
|
||||
{
|
||||
if (fail(sdata, FAIL_ACCEPT_CLOSE_COMPLETE))
|
||||
return pkt_err(effect, "Error inject");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Pkt *accept_pkt_simultaneous_close(struct state_effect *effect, const struct state_data *sdata, const Pkt *pkt)
|
||||
{
|
||||
if (fail(sdata, FAIL_ACCEPT_SIMULTANEOUS_CLOSE))
|
||||
return pkt_err(effect, "Error inject");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Pkt *accept_pkt_close_ack(struct state_effect *effect, const struct state_data *sdata, const Pkt *pkt)
|
||||
{
|
||||
if (fail(sdata, FAIL_ACCEPT_CLOSE_ACK))
|
||||
return pkt_err(effect, "Error inject");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -920,7 +968,8 @@ struct bitcoin_tx *bitcoin_steal(const tal_t *ctx,
|
||||
const struct state_data *sdata,
|
||||
struct bitcoin_event *btc)
|
||||
{
|
||||
/* FIXME: Test this failing! */
|
||||
if (fail(sdata, FAIL_STEAL))
|
||||
return NULL;
|
||||
return bitcoin_tx("steal");
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user