Browse Source

test_lightning.py: add test for onchain with different feerates.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 7 years ago
parent
commit
5f1c77d249
  1. 4
      lightningd/peer_control.c
  2. 5
      lightningd/peer_control.h
  3. 45
      lightningd/peer_htlcs.c
  4. 3
      onchaind/onchain.c
  5. 51
      tests/test_lightningd.py

4
lightningd/peer_control.c

@ -84,6 +84,10 @@ struct peer *new_peer(struct lightningd *ld, u64 dbid,
list_head_init(&peer->channels);
peer->direction = get_channel_direction(&peer->ld->id, &peer->id);
#if DEVELOPER
peer->ignore_htlcs = false;
#endif
/* Max 128k per peer. */
peer->log_book = new_log_book(128*1024, get_log_level(ld->log_book));
set_log_outfn(peer->log_book, copy_to_parent_log, ld->log);

5
lightningd/peer_control.h

@ -45,6 +45,11 @@ struct peer {
/* If we open a channel our direction will be this */
u8 direction;
#if DEVELOPER
/* Swallow incoming HTLCs (for testing) */
bool ignore_htlcs;
#endif
};
struct peer *find_peer_by_dbid(struct lightningd *ld, u64 dbid);

45
lightningd/peer_htlcs.c

@ -10,6 +10,7 @@
#include <gossipd/gen_gossip_wire.h>
#include <lightningd/chaintopology.h>
#include <lightningd/htlc_end.h>
#include <lightningd/jsonrpc.h>
#include <lightningd/lightningd.h>
#include <lightningd/log.h>
#include <lightningd/pay.h>
@ -576,6 +577,13 @@ static bool peer_accepted_htlc(struct channel *channel,
if (!htlc_in_update_state(channel, hin, RCVD_ADD_ACK_REVOCATION))
return false;
#if DEVELOPER
if (channel->peer->ignore_htlcs) {
log_debug(channel->log, "their htlc %"PRIu64" dev_ignore_htlcs",
id);
return true;
}
#endif
/* BOLT #2:
*
* A sending node SHOULD fail to route any HTLC added after it
@ -1618,3 +1626,40 @@ void notify_feerate_change(struct lightningd *ld)
subd_send_msg(channel->owner, take(msg));
}
}
#if DEVELOPER
static void json_dev_ignore_htlcs(struct command *cmd, const char *buffer,
const jsmntok_t *params)
{
jsmntok_t *nodeidtok, *ignoretok;
struct peer *peer;
if (!json_get_params(cmd, buffer, params,
"id", &nodeidtok,
"ignore", &ignoretok,
NULL)) {
return;
}
peer = peer_from_json(cmd->ld, buffer, nodeidtok);
if (!peer) {
command_fail(cmd, "Could not find channel with that peer");
return;
}
if (!json_tok_bool(buffer, ignoretok, &peer->ignore_htlcs)) {
command_fail(cmd, "Invalid boolean '%.*s'",
ignoretok->end - ignoretok->start,
buffer + ignoretok->start);
return;
}
command_success(cmd, null_response(cmd));
}
static const struct json_command dev_ignore_htlcs = {
"dev-ignore-htlcs", json_dev_ignore_htlcs,
"Set ignoring incoming HTLCs for peer {id} to {ignore}", false,
"Set/unset ignoring of all incoming HTLCs. For testing only."
};
AUTODATA(json_command, &dev_ignore_htlcs);
#endif /* DEVELOPER */

3
onchaind/onchain.c

@ -129,9 +129,10 @@ static u64 grind_htlc_tx_fee(struct bitcoin_tx *tx,
}
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"grind_fee failed from %u - %u"
" for tx %s, signature %s, wscript %s, multiplier %"PRIu64,
" for tx %s, inputamount %"PRIu64", signature %s, wscript %s, multiplier %"PRIu64,
min_possible_feerate, max_possible_feerate,
type_to_string(tmpctx, struct bitcoin_tx, tx),
input_amount,
type_to_string(tmpctx, secp256k1_ecdsa_signature, remotesig),
tal_hex(tmpctx, wscript),
multiplier);

51
tests/test_lightningd.py

@ -1939,6 +1939,57 @@ class LightningDTests(BaseLightningDTests):
bitcoind.generate_block(1)
l1.daemon.wait_for_log('onchaind complete, forgetting peer')
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1 for dev_fail")
def test_onchain_different_fees(self):
"""Onchain handling when we've had a range of fees"""
l1, l2 = self.connect()
self.fund_channel(l1, l2, 10**7)
l2.rpc.dev_ignore_htlcs(id=l1.info['id'], ignore=True)
p1 = self.pay(l1, l2, 1000000000, async=True)
l1.daemon.wait_for_log('htlc 0: RCVD_ADD_ACK_COMMIT->SENT_ADD_ACK_REVOCATION')
l1.rpc.dev_setfees('14000')
p2 = self.pay(l1, l2, 900000000, async=True)
l1.daemon.wait_for_log('htlc 1: RCVD_ADD_ACK_COMMIT->SENT_ADD_ACK_REVOCATION')
l1.rpc.dev_setfees('5000')
p3 = self.pay(l1, l2, 800000000, async=True)
l1.daemon.wait_for_log('htlc 2: RCVD_ADD_ACK_COMMIT->SENT_ADD_ACK_REVOCATION')
# Drop to chain
l1.rpc.dev_fail(l2.info['id'])
l1.daemon.wait_for_log('sendrawtx exit 0')
bitcoind.generate_block(1)
l1.daemon.wait_for_log(' to ONCHAIN')
l2.daemon.wait_for_log(' to ONCHAIN')
# Both sides should have correct feerate
assert l1.db_query('SELECT min_possible_feerate, max_possible_feerate FROM channels;') == [{'min_possible_feerate': 5000, 'max_possible_feerate': 14000}]
assert l2.db_query('SELECT min_possible_feerate, max_possible_feerate FROM channels;') == [{'min_possible_feerate': 5000, 'max_possible_feerate': 14000}]
bitcoind.generate_block(5)
# Three HTLCs, and one for the to-us output.
l1.daemon.wait_for_logs(['sendrawtx exit 0'] * 4)
# We use 3 blocks for "reasonable depth"
bitcoind.generate_block(3)
self.assertRaises(TimeoutError, p1.result, 10)
self.assertRaises(TimeoutError, p2.result, 10)
self.assertRaises(TimeoutError, p3.result, 10)
# Two more for HTLC timeout tx to be spent.
bitcoind.generate_block(2)
l1.daemon.wait_for_logs(['sendrawtx exit 0'] * 3)
# Now, 100 blocks it should be done.
bitcoind.generate_block(100)
wait_forget_channels(l1)
wait_forget_channels(l2)
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
def test_permfail_new_commit(self):
# Test case where we have two possible commits: it will use new one.

Loading…
Cancel
Save