Browse Source

onchaind: fulfill HTLCs onchain.

When we see an offered HTLC onchain, we need to use the preimage if we
know it.  So we dump all the known HTLC preimages at startup, and send
new ones as we discover them.

This doesn't cover preimages we know because we're the final
recipient; that can happen if an HTLC hasn't been irrevocably
committed yet.  We'll do that in a followup patch.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 7 years ago
parent
commit
a76a53a933
  1. 24
      lightningd/peer_control.c
  2. 20
      lightningd/peer_htlcs.c
  3. 286
      onchaind/onchain.c
  4. 4
      onchaind/onchain_types.h
  5. 88
      tests/test_lightningd.py
  6. 7
      tests/utils.py

24
lightningd/peer_control.c

@ -1045,6 +1045,27 @@ static void peer_onchain_finished(struct subd *subd, int status)
tal_free(subd->peer);
}
/* We dump all the known preimages when onchaind starts up. */
static void onchaind_tell_fulfill(struct peer *peer)
{
struct htlc_in_map_iter ini;
struct htlc_in *hin;
u8 *msg;
for (hin = htlc_in_map_first(&peer->ld->htlcs_in, &ini);
hin;
hin = htlc_in_map_next(&peer->ld->htlcs_in, &ini)) {
if (hin->key.peer != peer)
continue;
if (!hin->preimage)
continue;
msg = towire_onchain_known_preimage(peer, hin->preimage);
subd_send_msg(peer->owner, take(msg));
}
}
static int handle_onchain_init_reply(struct peer *peer, const u8 *msg)
{
u8 state;
@ -1062,6 +1083,9 @@ static int handle_onchain_init_reply(struct peer *peer, const u8 *msg)
/* We could come from almost any state. */
peer_set_condition(peer, peer->state, state);
/* Tell it about any preimages we know. */
onchaind_tell_fulfill(peer);
return 0;
}

20
lightningd/peer_htlcs.c

@ -18,6 +18,7 @@
#include <lightningd/peer_control.h>
#include <lightningd/peer_htlcs.h>
#include <lightningd/subd.h>
#include <onchaind/gen_onchain_wire.h>
#include <onchaind/onchain_wire.h>
#include <wire/gen_onion_wire.h>
@ -284,10 +285,21 @@ static void fulfill_htlc(struct htlc_in *hin, const struct preimage *preimage)
/* We update state now to signal it's in progress, for persistence. */
htlc_in_update_state(hin->key.peer, hin, SENT_REMOVE_HTLC);
/* FIXME: fail the peer if it doesn't tell us that htlc fulfill is
* committed before deadline.
*/
msg = towire_channel_fulfill_htlc(hin->key.peer, hin->key.id, preimage);
/* No owner? We'll either send to channeld in peer_htlcs, or
* onchaind in onchaind_tell_fulfill. */
if (!hin->key.peer->owner) {
log_debug(hin->key.peer->log, "HTLC fulfilled, but no owner.");
return;
}
if (peer_state_on_chain(hin->key.peer->state)) {
msg = towire_onchain_known_preimage(hin, preimage);
} else {
/* FIXME: fail the peer if it doesn't tell us that htlc
* fulfill is committed before deadline.
*/
msg = towire_channel_fulfill_htlc(hin, hin->key.id, preimage);
}
subd_send_msg(hin->key.peer->owner, take(msg));
}

286
onchaind/onchain.c

@ -69,6 +69,13 @@ struct tracked_output {
u64 satoshi;
enum output_type output_type;
/* If it is an HTLC, these are non-NULL */
const struct htlc_stub *htlc;
const u8 *wscript;
/* If it's an HTLC off our unilateral, this is their sig for htlc_tx */
const secp256k1_ecdsa_signature *remote_htlc_sig;
/* Our proposed solution (if any) */
struct proposed_resolution *proposal;
@ -185,6 +192,55 @@ static const char *output_type_name(enum output_type output_type)
return "unknown";
}
/*
* This covers:
* 1. to-us output spend (`<local_delayedsig> 0`)
* 2. the their-commitment, our HTLC timeout case (`<remotesig> 0`),
* 3. the their-commitment, our HTLC redeem case (`<remotesig> <payment_preimage>`)
*/
static struct bitcoin_tx *tx_to_us(const tal_t *ctx,
struct tracked_output *out,
u32 to_self_delay,
u32 locktime,
const void *elem, size_t elemsize,
const u8 *wscript,
const struct privkey *privkey,
const struct pubkey *pubkey)
{
struct bitcoin_tx *tx;
u64 fee;
secp256k1_ecdsa_signature sig;
tx = bitcoin_tx(ctx, 1, 1);
tx->lock_time = locktime;
tx->input[0].sequence_number = to_self_delay;
tx->input[0].txid = out->txid;
tx->input[0].index = out->outnum;
tx->input[0].amount = tal_dup(tx->input, u64, &out->satoshi);
tx->output[0].amount = out->satoshi;
tx->output[0].script = scriptpubkey_p2wpkh(tx->output,
&our_wallet_pubkey);
/* Worst-case sig is 73 bytes */
fee = feerate_per_kw * (measure_tx_cost(tx)
+ 1 + 3 + 73 + 0 + tal_len(wscript))
/ 1000;
/* Result is trivial? Just eliminate output. */
if (tx->output[0].amount < dust_limit_satoshis + fee)
tal_resize(&tx->output, 0);
else
tx->output[0].amount -= fee;
sign_tx_input(tx, 0, NULL, wscript, privkey, pubkey, &sig);
tx->input[0].witness = bitcoin_witness_sig_and_element(tx->input,
&sig,
elem, elemsize,
wscript);
return tx;
}
static struct tracked_output *
new_tracked_output(struct tracked_output ***outs,
const struct sha256_double *txid,
@ -192,7 +248,10 @@ static struct tracked_output *
enum tx_type tx_type,
u32 outnum,
u64 satoshi,
enum output_type output_type)
enum output_type output_type,
const struct htlc_stub *htlc,
const u8 *wscript,
const secp256k1_ecdsa_signature *remote_htlc_sig)
{
size_t n = tal_count(*outs);
struct tracked_output *out = tal(*outs, struct tracked_output);
@ -211,6 +270,9 @@ static struct tracked_output *
out->output_type = output_type;
out->proposal = NULL;
out->resolved = NULL;
out->htlc = htlc;
out->wscript = wscript;
out->remote_htlc_sig = remote_htlc_sig;
tal_resize(outs, n+1);
(*outs)[n] = out;
@ -434,7 +496,7 @@ static void unwatch_tx(const struct bitcoin_tx *tx)
wire_sync_write(REQ_FD, take(msg));
}
static void handle_their_htlc_fulfill(struct tracked_output *out,
static void handle_htlc_onchain_fulfill(struct tracked_output *out,
const struct bitcoin_tx *tx)
{
status_failed(STATUS_FAIL_INTERNAL_ERROR, "FIXME: %s", __func__);
@ -476,7 +538,7 @@ static void output_spent(struct tracked_output **outs,
case OUR_HTLC:
/* The only way they can spend this: fulfill */
handle_their_htlc_fulfill(outs[i], tx);
handle_htlc_onchain_fulfill(outs[i], tx);
break;
case FUNDING_OUTPUT:
@ -531,10 +593,90 @@ static void tx_new_depth(struct tracked_output **outs,
}
}
/* BOLT #5:
*
* If the node receives (or already knows) a payment preimage for an
* unresolved HTLC output it was offered, it MUST *resolve* the output by
* spending it.
*/
static void handle_preimage(struct tracked_output **outs,
const struct preimage *preimage)
{
status_failed(STATUS_FAIL_INTERNAL_ERROR, "FIXME: %s", __func__);
size_t i;
struct sha256 sha;
struct ripemd160 ripemd;
sha256(&sha, preimage, sizeof(*preimage));
ripemd160(&ripemd, &sha, sizeof(sha));
for (i = 0; i < tal_count(outs); i++) {
struct bitcoin_tx *tx;
secp256k1_ecdsa_signature sig;
if (outs[i]->output_type != THEIR_HTLC)
continue;
if (!structeq(&outs[i]->htlc->ripemd, &ripemd))
continue;
/* Too late? */
if (outs[i]->resolved) {
/* FIXME: We need a better warning method! */
status_trace("WARNING: HTLC already resolved by %s"
" when we found preimage",
tx_type_name(outs[i]->resolved->tx_type));
return;
}
/* Discard any previous resolution. Could be a timeout,
* could be due to multiple identical rhashes in tx. */
outs[i]->proposal = tal_free(outs[i]->proposal);
/* BOLT #5:
*
* If the transaction is the nodes' own commitment
* transaction, then the it MUST use the HTLC-success
* transaction, and the HTLC-success transaction output MUST
* be *resolved* as described in "On-chain HTLC Transaction
* Handling".
*/
if (outs[i]->remote_htlc_sig) {
tx = htlc_success_tx(outs[i], &outs[i]->txid,
outs[i]->outnum,
outs[i]->satoshi * 1000,
to_self_delay[LOCAL],
feerate_per_kw,
keyset);
sign_tx_input(tx, 0, NULL, outs[i]->wscript,
&payment_privkey,
&keyset->self_payment_key,
&sig);
tx->input[0].witness
= bitcoin_witness_htlc_success_tx(tx->input,
&sig,
outs[i]->remote_htlc_sig,
preimage,
outs[i]->wscript);
propose_resolution(outs[i], tx, 0, OUR_HTLC_SUCCESS_TX);
} else {
/* BOLT #5:
*
* Otherwise, it MUST *resolve* the output by spending
* it to a convenient address.
*/
tx = tx_to_us(outs[i], outs[i], 0, 0,
preimage, sizeof(*preimage),
outs[i]->wscript,
&payment_privkey,
&keyset->other_payment_key);
propose_resolution(outs[i], tx, 0,
THEIR_HTLC_FULFILL_TO_US);
}
/* Broadcast immediately. */
proposal_meets_depth(outs[i]);
break;
}
}
/* BOLT #5:
@ -620,56 +762,7 @@ static u8 **derive_htlc_scripts(const struct htlc_stub *htlcs, enum side side)
return htlc_scripts;
}
/*
* This covers both the to-us output spend (`<local_delayedsig> 0`)
* and the their-commitment, our HTLC timeout case (`<remotesig> 0`).
*/
static struct bitcoin_tx *tx_to_us(const tal_t *ctx,
struct tracked_output *out,
u32 to_self_delay,
u32 locktime,
const u8 *wscript,
const struct privkey *privkey,
const struct pubkey *pubkey)
{
struct bitcoin_tx *tx;
u64 fee;
secp256k1_ecdsa_signature sig;
tx = bitcoin_tx(ctx, 1, 1);
tx->lock_time = locktime;
tx->input[0].sequence_number = to_self_delay;
tx->input[0].txid = out->txid;
tx->input[0].index = out->outnum;
tx->input[0].amount = tal_dup(tx->input, u64, &out->satoshi);
tx->output[0].amount = out->satoshi;
tx->output[0].script = scriptpubkey_p2wpkh(tx->output,
&our_wallet_pubkey);
/* Worst-case sig is 73 bytes */
fee = feerate_per_kw * (measure_tx_cost(tx)
+ 1 + 3 + 73 + 0 + tal_len(wscript))
/ 1000;
/* Result is trivial? Just eliminate output. */
if (tx->output[0].amount < dust_limit_satoshis + fee)
tal_resize(&tx->output, 0);
else
tx->output[0].amount -= fee;
sign_tx_input(tx, 0, NULL, wscript, privkey, pubkey, &sig);
tx->input[0].witness = bitcoin_witness_sig_and_element(tx->input,
&sig,
NULL, 0,
wscript);
return tx;
}
static void resolve_our_htlc_ourcommit(struct tracked_output *out,
const u8 *wscript,
const struct htlc_stub *htlc,
const secp256k1_ecdsa_signature *remotesig)
static void resolve_our_htlc_ourcommit(struct tracked_output *out)
{
struct bitcoin_tx *tx;
secp256k1_ecdsa_signature localsig;
@ -687,13 +780,8 @@ static void resolve_our_htlc_ourcommit(struct tracked_output *out,
* "On-chain HTLC Transaction Handling".
*/
tx = htlc_timeout_tx(out, &out->txid, out->outnum, out->satoshi * 1000,
htlc->cltv_expiry, to_self_delay[LOCAL], 0, keyset);
wscript = bitcoin_wscript_htlc_offer_ripemd160(tx,
&keyset->self_payment_key,
&keyset->other_payment_key,
&htlc->ripemd,
&keyset->self_revocation_key);
out->htlc->cltv_expiry,
to_self_delay[LOCAL], 0, keyset);
/* BOLT #3:
*
@ -703,29 +791,26 @@ static void resolve_our_htlc_ourcommit(struct tracked_output *out,
* 1. Multiply `feerate_per_kw` by 663 and divide by 1000 (rounding
* down).
*/
if (!grind_feerate(tx, remotesig, wscript, 663))
if (!grind_feerate(tx, out->remote_htlc_sig, out->wscript, 663))
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Could not find feerate for signature on"
" HTLC timeout between %u and %u",
feerate_range.min, feerate_range.max);
sign_tx_input(tx, 0, NULL, wscript, &payment_privkey,
sign_tx_input(tx, 0, NULL, out->wscript, &payment_privkey,
&keyset->self_payment_key, &localsig);
tx->input[0].witness
= bitcoin_witness_htlc_timeout_tx(tx->input,
&localsig,
remotesig,
wscript);
out->remote_htlc_sig,
out->wscript);
propose_resolution_at_block(out, tx, htlc->cltv_expiry,
propose_resolution_at_block(out, tx, out->htlc->cltv_expiry,
OUR_HTLC_TIMEOUT_TO_US);
tal_free(wscript);
}
static void resolve_our_htlc_theircommit(struct tracked_output *out,
const u8 *wscript,
const struct htlc_stub *htlc)
static void resolve_our_htlc_theircommit(struct tracked_output *out)
{
struct bitcoin_tx *tx;
@ -739,17 +824,16 @@ static void resolve_our_htlc_theircommit(struct tracked_output *out,
* own commitment transaction, .... Otherwise it MUST resolve the
* output by spending it to a convenient address.
*/
tx = tx_to_us(out, out, 0, htlc->cltv_expiry,
wscript,
tx = tx_to_us(out, out, 0, out->htlc->cltv_expiry, NULL, 0,
out->wscript,
&payment_privkey,
&keyset->other_payment_key);
propose_resolution_at_block(out, tx, htlc->cltv_expiry,
propose_resolution_at_block(out, tx, out->htlc->cltv_expiry,
OUR_HTLC_TIMEOUT_TO_US);
}
static void resolve_their_htlc(struct tracked_output *out,
const struct htlc_stub *htlc)
static void resolve_their_htlc(struct tracked_output *out)
{
/* BOLT #5:
*
@ -771,7 +855,7 @@ static void resolve_their_htlc(struct tracked_output *out,
* *irrevocably resolved*.
*/
/* If we hit timeout depth, resolve by ignoring. */
propose_resolution_at_block(out, NULL, htlc->cltv_expiry,
propose_resolution_at_block(out, NULL, out->htlc->cltv_expiry,
THEIR_HTLC_TIMEOUT_TO_THEM);
}
@ -808,7 +892,7 @@ static void handle_our_unilateral(const struct bitcoin_tx *tx,
const struct pubkey *local_delayed_payment_basepoint,
u64 commit_num,
const struct htlc_stub *htlcs,
const secp256k1_ecdsa_signature *htlc_sigs,
const secp256k1_ecdsa_signature *remote_htlc_sigs,
struct tracked_output **outs)
{
const tal_t *tmpctx = tal_tmpctx(NULL);
@ -928,7 +1012,8 @@ static void handle_our_unilateral(const struct bitcoin_tx *tx,
out = new_tracked_output(&outs, txid, tx_blockheight,
OUR_UNILATERAL, i,
tx->output[i].amount,
DELAYED_OUTPUT_TO_US);
DELAYED_OUTPUT_TO_US,
NULL, NULL, NULL);
/* BOLT #3:
*
* It is spent by a transaction with `nSequence` field
@ -938,6 +1023,7 @@ static void handle_our_unilateral(const struct bitcoin_tx *tx,
* <local_delayedsig> 0
*/
to_us = tx_to_us(out, out, to_self_delay[LOCAL], 0,
NULL, 0,
local_wscript,
&delayed_payment_privkey,
&keyset->self_delayed_payment_key);
@ -962,7 +1048,8 @@ static void handle_our_unilateral(const struct bitcoin_tx *tx,
out = new_tracked_output(&outs, txid, tx_blockheight,
OUR_UNILATERAL, i,
tx->output[i].amount,
OUTPUT_TO_THEM);
OUTPUT_TO_THEM,
NULL, NULL, NULL);
ignore_output(out);
script[REMOTE] = NULL;
continue;
@ -984,24 +1071,28 @@ static void handle_our_unilateral(const struct bitcoin_tx *tx,
tx_blockheight,
OUR_UNILATERAL, i,
tx->output[i].amount,
OUR_HTLC);
resolve_our_htlc_ourcommit(out, htlc_scripts[j],
&htlcs[j],
htlc_sigs);
/* Each of these consumes one HTLC signature */
htlc_sigs++;
OUR_HTLC,
&htlcs[j], htlc_scripts[j],
remote_htlc_sigs);
resolve_our_htlc_ourcommit(out);
} else {
out = new_tracked_output(&outs, txid,
tx_blockheight,
OUR_UNILATERAL, i,
tx->output[i].amount,
THEIR_HTLC);
THEIR_HTLC,
&htlcs[j],
htlc_scripts[j],
remote_htlc_sigs);
/* BOLT #5:
*
* 4. _B's offered HTLCs_: See "On-chain HTLC
* Output Handling: Their Offers" below. */
resolve_their_htlc(out, &htlcs[j]);
resolve_their_htlc(out);
}
/* Each of these consumes one HTLC signature */
remote_htlc_sigs++;
/* We've matched this HTLC, can't do again. */
htlc_scripts[j] = NULL;
}
@ -1154,7 +1245,7 @@ static void handle_their_unilateral(const struct bitcoin_tx *tx,
out = new_tracked_output(&outs, txid, tx_blockheight,
THEIR_UNILATERAL,
i, tx->output[i].amount,
OUTPUT_TO_US);
OUTPUT_TO_US, NULL, NULL, NULL);
ignore_output(out);
script[LOCAL] = NULL;
continue;
@ -1169,7 +1260,8 @@ static void handle_their_unilateral(const struct bitcoin_tx *tx,
out = new_tracked_output(&outs, txid, tx_blockheight,
THEIR_UNILATERAL, i,
tx->output[i].amount,
DELAYED_OUTPUT_TO_THEM);
DELAYED_OUTPUT_TO_THEM,
NULL, NULL, NULL);
ignore_output(out);
continue;
}
@ -1188,21 +1280,23 @@ static void handle_their_unilateral(const struct bitcoin_tx *tx,
tx_blockheight,
THEIR_UNILATERAL, i,
tx->output[i].amount,
OUR_HTLC);
resolve_our_htlc_theircommit(out,
htlc_scripts[j],
&htlcs[i]);
OUR_HTLC,
&htlcs[j], htlc_scripts[j],
NULL);
resolve_our_htlc_theircommit(out);
} else {
out = new_tracked_output(&outs, txid,
tx_blockheight,
THEIR_UNILATERAL, i,
tx->output[i].amount,
THEIR_HTLC);
THEIR_HTLC,
&htlcs[j], htlc_scripts[j],
NULL);
/* BOLT #5:
*
* 4. _B's offered HTLCs_: See "On-chain HTLC Output
* Handling: Their Offers" below. */
resolve_their_htlc(out, &htlcs[j]);
resolve_their_htlc(out);
}
htlc_scripts[j] = NULL;
}
@ -1292,7 +1386,7 @@ int main(int argc, char *argv[])
FUNDING_TRANSACTION,
tx->input[0].index,
funding_amount_satoshi,
FUNDING_OUTPUT);
FUNDING_OUTPUT, NULL, NULL, NULL);
status_trace("Remote per-commit point: %s",
type_to_string(trc, struct pubkey,

4
onchaind/onchain_types.h

@ -22,6 +22,10 @@ enum tx_type {
OUR_HTLC_TIMEOUT_TO_US,
OUR_HTLC_FULFILL_TO_THEM,
/* Delayed variants */
OUR_HTLC_TIMEOUT_TX,
OUR_HTLC_SUCCESS_TX,
/* When we spend the to-us output (after cltv_expiry) */
OUR_UNILATERAL_TO_US_RETURN_TO_WALLET,

88
tests/test_lightningd.py

@ -153,6 +153,8 @@ class BaseLightningDTests(unittest.TestCase):
return 1 if errors else 0
def getCrashLog(self, node):
if node.known_fail:
return None, None
try:
crashlog = os.path.join(node.daemon.lightning_dir, 'crash.log')
with open(crashlog, 'r') as f:
@ -444,6 +446,66 @@ class LightningDTests(BaseLightningDTests):
bitcoind.rpc.generate(100)
l2.daemon.wait_for_log('onchaind complete, forgetting peer')
def test_onchain_middleman(self):
# HTLC 1->2->3, 1->2 goes down after 2 gets preimage from 3.
disconnects = ['-WIRE_UPDATE_FULFILL_HTLC', 'permfail']
l1 = self.node_factory.get_node()
l2 = self.node_factory.get_node(disconnect=disconnects)
l3 = self.node_factory.get_node()
# l2 connects to both, so l1 can't reconnect and thus l2 drops to chain
l2.rpc.connect('localhost', l1.info['port'], l1.info['id'])
l2.rpc.connect('localhost', l3.info['port'], l3.info['id'])
self.fund_channel(l2, l1, 10**6)
self.fund_channel(l2, l3, 10**6)
# Give l1 some money to play with.
self.pay(l2, l1, 2 * 10**8)
# Must be bigger than dust!
rhash = l3.rpc.invoice(10**8, 'middleman')['rhash']
# Wait for route propagation.
l1.bitcoin.rpc.generate(5)
l1.daemon.wait_for_log('Received node_announcement for node {}'
.format(l3.info['id']))
route = l1.rpc.getroute(l3.info['id'], 10**8, 1)["route"]
assert len(route) == 2
def try_pay():
l1.rpc.sendpay(to_json(route), rhash, async=False)
t = threading.Thread(target=try_pay)
t.daemon = True
t.start()
# l2 will drop to chain.
l2.daemon.wait_for_log('sendrawtx exit 0')
l1.bitcoin.rpc.generate(1)
l2.daemon.wait_for_log('-> ONCHAIND_OUR_UNILATERAL')
l1.daemon.wait_for_log('-> ONCHAIND_THEIR_UNILATERAL')
l2.daemon.wait_for_log('OUR_UNILATERAL/THEIR_HTLC')
# l2 should fulfill HTLC onchain
l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/THEIR_HTLC by OUR_HTLC_SUCCESS_TX .* in 0 blocks')
l2.daemon.wait_for_log('sendrawtx exit 0')
l1.bitcoin.rpc.generate(1)
# FIXME: l1 should get preimage off the chain!
l1.daemon.wait_for_log('FIXME: handle_htlc_onchain_fulfill')
l1.has_failed()
# After 5 more blocks, l2 can spend to-us
l1.bitcoin.rpc.generate(5)
l2.daemon.wait_for_log('Broadcasting OUR_UNILATERAL_TO_US_RETURN_TO_WALLET')
l2.daemon.wait_for_log('sendrawtx exit 0')
# 100 blocks after last spend, l2 should be done.
l1.bitcoin.rpc.generate(100)
l2.daemon.wait_for_log('onchaind complete, forgetting peer')
# FIXME: kill thread?
def test_permfail_new_commit(self):
# Test case where we have two possible commits: it will use new one.
disconnects = ['-WIRE_REVOKE_AND_ACK', 'permfail']
@ -504,14 +566,15 @@ class LightningDTests(BaseLightningDTests):
l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/THEIR_HTLC by THEIR_HTLC_TIMEOUT_TO_THEM \\(IGNORING\\) in 5 blocks')
l1.daemon.wait_for_log('Propose handling THEIR_UNILATERAL/OUR_HTLC by OUR_HTLC_TIMEOUT_TO_US (.*) in 5 blocks')
# FIXME: Implement FULFILL!
# OK, time out HTLC.
bitcoind.rpc.generate(5)
l1.daemon.wait_for_log('sendrawtx exit 0')
l1.daemon.wait_for_log('FIXME: handle_htlc_onchain_fulfill')
l1.has_failed()
# l1.daemon.wait_for_log('sendrawtx exit 0')
bitcoind.rpc.generate(1)
l1.daemon.wait_for_log('Resolved THEIR_UNILATERAL/OUR_HTLC by our proposal OUR_HTLC_TIMEOUT_TO_US')
l2.daemon.wait_for_log('Ignoring output.*: OUR_UNILATERAL/THEIR_HTLC')
# l1.daemon.wait_for_log('Resolved THEIR_UNILATERAL/OUR_HTLC by our proposal OUR_HTLC_TIMEOUT_TO_US')
l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/THEIR_HTLC by OUR_HTLC_SUCCESS_TX .* in 0 blocks')
# FIXME: This doesn't work :(
# FIXME: sendpay command should time out!
@ -519,7 +582,7 @@ class LightningDTests(BaseLightningDTests):
# Now, 100 blocks it should be done.
bitcoind.rpc.generate(100)
l1.daemon.wait_for_log('onchaind complete, forgetting peer')
# l1.daemon.wait_for_log('onchaind complete, forgetting peer')
l2.daemon.wait_for_log('onchaind complete, forgetting peer')
def test_permfail_htlc_out(self):
@ -543,14 +606,15 @@ class LightningDTests(BaseLightningDTests):
l2.daemon.wait_for_log('Propose handling OUR_UNILATERAL/OUR_HTLC by OUR_HTLC_TIMEOUT_TO_US \\(.*\\) in 5 blocks')
l1.daemon.wait_for_log('Propose handling THEIR_UNILATERAL/THEIR_HTLC by THEIR_HTLC_TIMEOUT_TO_THEM \\(IGNORING\\) in 5 blocks')
# FIXME: Implement FULFILL!
# OK, time out HTLC.
bitcoind.rpc.generate(5)
l2.daemon.wait_for_log('sendrawtx exit 0')
l2.daemon.wait_for_log('FIXME: handle_htlc_onchain_fulfill')
l2.has_failed()
bitcoind.rpc.generate(1)
l1.daemon.wait_for_log('Ignoring output.*: THEIR_UNILATERAL/THEIR_HTLC')
l2.daemon.wait_for_log('Resolved OUR_UNILATERAL/OUR_HTLC by our proposal OUR_HTLC_TIMEOUT_TO_US')
l1.daemon.wait_for_log('Propose handling THEIR_UNILATERAL/THEIR_HTLC by THEIR_HTLC_FULFILL_TO_US .* in 0 blocks')
# l2.daemon.wait_for_log('Resolved OUR_UNILATERAL/OUR_HTLC by our proposal OUR_HTLC_TIMEOUT_TO_US')
# FIXME: This doesn't work :(
# FIXME: sendpay command should time out!
@ -559,7 +623,7 @@ class LightningDTests(BaseLightningDTests):
# Now, 100 blocks it should be done.
bitcoind.rpc.generate(100)
l1.daemon.wait_for_log('onchaind complete, forgetting peer')
l2.daemon.wait_for_log('onchaind complete, forgetting peer')
# l2.daemon.wait_for_log('onchaind complete, forgetting peer')
def test_gossip_jsonrpc(self):
l1,l2 = self.connect()

7
tests/utils.py

@ -243,6 +243,7 @@ class LightningNode(object):
self.daemon = daemon
self.bitcoin = btc
self.executor = executor
self.known_fail = False
# Use batch if you're doing more than one async.
def connect(self, remote_node, capacity, async=False):
@ -307,3 +308,9 @@ class LightningNode(object):
c.close()
db.close()
return result
def has_failed(self):
"""Note that a daemon has (deliberately) crashed, so we don't fail
on cleanup"""
self.known_fail = True

Loading…
Cancel
Save