Browse Source

daemon: don't ever use timeouts in seconds, always blocks,

The protocol still supports both, but we now only support blocks.

It's hard to do risk management with timeouts in seconds, given block
variance.  This is also signficantly simpler, as HTLC timeouts are
always fired in response to blocks, not wall-clock times.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 9 years ago
parent
commit
a3375516e5
  1. 5
      daemon/chaintopology.c
  2. 3
      daemon/chaintopology.h
  3. 36
      daemon/lightningd.c
  4. 14
      daemon/lightningd.h
  5. 21
      daemon/packets.c
  6. 132
      daemon/peer.c
  7. 5
      daemon/peer.h
  8. 66
      daemon/test/test.sh

5
daemon/chaintopology.c

@ -452,6 +452,11 @@ u32 get_tip_mediantime(struct lightningd_state *dstate)
return dstate->topology->tip->mediantime;
}
u32 get_block_height(struct lightningd_state *dstate)
{
return dstate->topology->tip->height;
}
void setup_topology(struct lightningd_state *dstate)
{
dstate->topology = tal(dstate, struct topology);

3
daemon/chaintopology.h

@ -18,6 +18,9 @@ u32 get_tx_mediantime(struct lightningd_state *dstate,
/* Get mediantime of the tip; if more than one, pick greatest time. */
u32 get_tip_mediantime(struct lightningd_state *dstate);
/* Get highest block number. */
u32 get_block_height(struct lightningd_state *dstate);
/* Broadcast a single tx, and rebroadcast as reqd (takes ownership of tx) */
void broadcast_tx(struct peer *peer, const struct bitcoin_tx *tx);

36
daemon/lightningd.c

@ -70,11 +70,11 @@ static void opt_show_u32(char buf[OPT_SHOW_LEN], const u32 *u)
static void config_register_opts(struct lightningd_state *dstate)
{
opt_register_arg("--locktime", opt_set_u32, opt_show_u32,
&dstate->config.rel_locktime,
"Seconds before peer can unilaterally spend funds");
opt_register_arg("--max-locktime", opt_set_u32, opt_show_u32,
&dstate->config.rel_locktime_max,
opt_register_arg("--locktime-blocks", opt_set_u32, opt_show_u32,
&dstate->config.locktime_blocks,
"Blocks before peer can unilaterally spend funds");
opt_register_arg("--max-locktime-blocks", opt_set_u32, opt_show_u32,
&dstate->config.locktime_max,
"Maximum seconds peer can lock up our funds");
opt_register_arg("--anchor-confirms", opt_set_u32, opt_show_u32,
&dstate->config.anchor_confirms,
@ -94,12 +94,12 @@ static void config_register_opts(struct lightningd_state *dstate)
opt_register_arg("--closing-fee-rate", opt_set_u64, opt_show_u64,
&dstate->config.closing_fee_rate,
"Satoshis to use for mutual close transaction fee (per kb)");
opt_register_arg("--min-expiry", opt_set_u32, opt_show_u32,
&dstate->config.min_expiry,
"Minimum number of seconds to accept an HTLC before expiry");
opt_register_arg("--max-expiry", opt_set_u32, opt_show_u32,
&dstate->config.max_expiry,
"Maximum number of seconds to accept an HTLC before expiry");
opt_register_arg("--min-htlc-expiry", opt_set_u32, opt_show_u32,
&dstate->config.min_htlc_expiry,
"Minimum number of blocks to accept an HTLC before expiry");
opt_register_arg("--max-htlc-expiry", opt_set_u32, opt_show_u32,
&dstate->config.max_htlc_expiry,
"Maximum number of blocks to accept an HTLC before expiry");
opt_register_arg("--bitcoind-poll", opt_set_time, opt_show_time,
&dstate->config.poll_time,
"Time between polling for new transactions");
@ -108,20 +108,16 @@ static void config_register_opts(struct lightningd_state *dstate)
"Time after changes before sending out COMMIT");
}
#define MINUTES 60
#define HOURS (60 * MINUTES)
#define DAYS (24 * HOURS)
static void default_config(struct config *config)
{
/* aka. "Dude, where's my coins?" */
config->testnet = true;
/* One day to catch cheating attempts. */
config->rel_locktime = 1 * DAYS;
/* ~one day to catch cheating attempts. */
config->locktime_blocks = 6 * 24;
/* They can have up to 3 days. */
config->rel_locktime_max = 2 * DAYS;
config->locktime_max = 3 * 6 * 24;
/* We're fairly trusting, under normal circumstances. */
config->anchor_confirms = 3;
@ -152,9 +148,9 @@ static void default_config(struct config *config)
config->closing_fee_rate = 20000;
/* Don't bother me unless I have 6 hours to collect. */
config->min_expiry = 6 * HOURS;
config->min_htlc_expiry = 6 * 6;
/* Don't lock up channel for more than 5 days. */
config->max_expiry = 5 * DAYS;
config->max_htlc_expiry = 5 * 6 * 24;
config->poll_time = time_from_sec(30);

14
daemon/lightningd.h

@ -14,11 +14,11 @@ struct config {
/* Are we on testnet? */
bool testnet;
/* How long do we want them to lock up their funds? (seconds) */
u32 rel_locktime;
/* How long do we want them to lock up their funds? (blocks) */
u32 locktime_blocks;
/* How long do we let them lock up our funds? (seconds) */
u32 rel_locktime_max;
/* How long do we let them lock up our funds? (blocks) */
u32 locktime_max;
/* How many confirms until we consider an anchor "settled". */
u32 anchor_confirms;
@ -38,13 +38,13 @@ struct config {
/* What fee we use for the closing transaction (satoshis/kb) */
u64 closing_fee_rate;
/* Minimum/maximum time for an expiring HTLC (seconds). */
u32 min_expiry, max_expiry;
/* Minimum/maximum time for an expiring HTLC (blocks). */
u32 min_htlc_expiry, max_htlc_expiry;
/* How long between polling bitcoind. */
struct timerel poll_time;
/* How long between changing commit and sending COMMIT message.. */
/* How long between changing commit and sending COMMIT message. */
struct timerel commit_time;
};

21
daemon/packets.c

@ -106,8 +106,8 @@ void queue_pkt_open(struct peer *peer, OpenChannel__AnchorOffer anchor)
o->final_key = pubkey_to_proto(o, &peer->local.finalkey);
o->delay = tal(o, Locktime);
locktime__init(o->delay);
o->delay->locktime_case = LOCKTIME__LOCKTIME_SECONDS;
o->delay->seconds = rel_locktime_to_seconds(&peer->local.locktime);
o->delay->locktime_case = LOCKTIME__LOCKTIME_BLOCKS;
o->delay->blocks = rel_locktime_to_blocks(&peer->local.locktime);
o->initial_fee_rate = peer->local.commit_fee_rate;
if (anchor == OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR)
assert(peer->local.offer_anchor == CMD_OPEN_WITH_ANCHOR);
@ -201,8 +201,6 @@ void queue_pkt_htlc_add(struct peer *peer, const struct channel_htlc *htlc)
remote_changes_pending(peer);
peer_add_htlc_expiry(peer, &htlc->expiry);
queue_pkt(peer, PKT__PKT_UPDATE_ADD_HTLC, u);
}
@ -488,10 +486,9 @@ Pkt *accept_pkt_open(struct peer *peer, const Pkt *pkt)
if (!proto_to_rel_locktime(o->delay, &locktime))
return pkt_err(peer, "Invalid delay");
/* FIXME: handle blocks in locktime */
if (o->delay->locktime_case != LOCKTIME__LOCKTIME_SECONDS)
return pkt_err(peer, "Delay in blocks not accepted");
if (o->delay->seconds > peer->dstate->config.rel_locktime_max)
if (o->delay->locktime_case != LOCKTIME__LOCKTIME_BLOCKS)
return pkt_err(peer, "Delay in seconds not accepted");
if (o->delay->blocks > peer->dstate->config.locktime_max)
return pkt_err(peer, "Delay too great");
if (o->min_depth > peer->dstate->config.anchor_confirms_max)
return pkt_err(peer, "min_depth too great");
@ -616,9 +613,8 @@ Pkt *accept_pkt_htlc_add(struct peer *peer, const Pkt *pkt)
if (!proto_to_abs_locktime(u->expiry, &expiry))
return pkt_err(peer, "Invalid HTLC expiry");
/* FIXME: Handle block-based expiry! */
if (!abs_locktime_is_seconds(&expiry))
return pkt_err(peer, "HTLC expiry in blocks not supported!");
if (abs_locktime_is_seconds(&expiry))
return pkt_err(peer, "HTLC expiry in seconds not supported!");
/* BOLT #2:
*
@ -674,9 +670,6 @@ Pkt *accept_pkt_htlc_add(struct peer *peer, const Pkt *pkt)
stage.add.htlc = *htlc;
add_unacked(&peer->local, &stage);
peer_add_htlc_expiry(peer, &expiry);
/* FIXME: Fees must be sufficient. */
return NULL;
}

132
daemon/peer.c

@ -753,10 +753,9 @@ static struct peer *new_peer(struct lightningd_state *dstate,
io_set_finish(conn, peer_disconnect, peer);
peer->local.offer_anchor = offer_anchor;
if (!seconds_to_rel_locktime(dstate->config.rel_locktime,
&peer->local.locktime))
fatal("Invalid locktime configuration %u",
dstate->config.rel_locktime);
if (!blocks_to_rel_locktime(dstate->config.locktime_blocks,
&peer->local.locktime))
fatal("Could not convert locktime_blocks");
peer->local.mindepth = dstate->config.anchor_confirms;
peer->local.commit_fee_rate = dstate->config.commitment_fee_rate;
@ -975,6 +974,35 @@ const struct json_command connect_command = {
"Returns an empty result on success"
};
/* FIXME: Keep a timeout for each peer, in case they're unresponsive. */
/* FIXME: Make sure no HTLCs in any unrevoked commit tx are live. */
static void check_htlc_expiry(struct peer *peer)
{
size_t i;
u32 height = get_block_height(peer->dstate);
again:
/* Check their currently still-existing htlcs for expiry:
* We eliminate them from staging as we go. */
for (i = 0; i < tal_count(peer->remote.staging_cstate->side[THEIRS].htlcs); i++) {
struct channel_htlc *htlc = &peer->remote.staging_cstate->side[THEIRS].htlcs[i];
assert(!abs_locktime_is_seconds(&htlc->expiry));
/* We give it an extra block, to avoid the worst of the
* inter-node timing issues. */
if (height <= abs_locktime_to_blocks(&htlc->expiry))
continue;
/* This can fail only if we're in an error state. */
if (!command_htlc_fail(peer, htlc->id))
return;
goto again;
}
}
struct anchor_watch {
struct peer *peer;
enum state_input depthok;
@ -1002,6 +1030,9 @@ static void anchor_depthchange(struct peer *peer, unsigned int depth,
} else if (depth == 0)
/* FIXME: Report losses! */
fatal("Funding transaction was unspent!");
/* Since this gets called on every new block, check HTLCs here. */
check_htlc_expiry(peer);
}
/* Yay, segwit! We can just compare txids, even though we don't have both
@ -1365,14 +1396,14 @@ static void our_htlc_depth(struct peer *peer,
bool our_commit,
size_t i)
{
u32 mediantime;
struct channel_htlc *h;
u32 height;
/* Must be in a block. */
if (depth == 0)
return;
mediantime = get_tip_mediantime(peer->dstate);
height = get_block_height(peer->dstate);
h = htlc_by_index(peer->closing_onchain.ci, i);
/* BOLT #onchain:
@ -1384,18 +1415,11 @@ static void our_htlc_depth(struct peer *peer,
* `OP_CHECKSEQUENCEVERIFY` delay has passed.
*/
/* FIXME: Handle expiry in blocks. */
if (mediantime < abs_locktime_to_seconds(&h->expiry))
if (height < abs_locktime_to_blocks(&h->expiry))
return;
if (our_commit) {
u32 csv_timeout;
/* FIXME: Handle CSV in blocks. */
csv_timeout = get_tx_mediantime(peer->dstate, txid)
+ rel_locktime_to_seconds(&peer->remote.locktime);
if (mediantime <= csv_timeout)
if (depth < rel_locktime_to_blocks(&peer->remote.locktime))
return;
}
@ -1480,7 +1504,7 @@ static void their_htlc_depth(struct peer *peer,
const struct sha256_double *txid,
ptrint_t *pi)
{
u32 mediantime;
u32 height;
struct channel_htlc *h;
size_t i = ptr2int(pi);
@ -1488,7 +1512,7 @@ static void their_htlc_depth(struct peer *peer,
if (depth == 0)
return;
mediantime = get_tip_mediantime(peer->dstate);
height = get_block_height(peer->dstate);
h = htlc_by_index(peer->closing_onchain.ci, i);
/* BOLT #onchain:
@ -1497,8 +1521,7 @@ static void their_htlc_depth(struct peer *peer,
* *irrevocably resolved*.
*/
/* FIXME: Handle expiry in blocks. */
if (mediantime < abs_locktime_to_seconds(&h->expiry))
if (height < abs_locktime_to_blocks(&h->expiry))
return;
peer->closing_onchain.resolved[i] = irrevocably_resolved(peer);
@ -1528,19 +1551,8 @@ static void our_main_output_depth(struct peer *peer,
const struct sha256_double *txid,
void *unused)
{
u32 mediantime, csv_timeout;
/* Not in block any more? */
if (depth == 0)
return;
mediantime = get_tip_mediantime(peer->dstate);
/* FIXME: Handle CSV in blocks. */
csv_timeout = get_tx_mediantime(peer->dstate, txid)
+ rel_locktime_to_seconds(&peer->remote.locktime);
if (mediantime <= csv_timeout)
/* Not past CSV timeout? */
if (depth < rel_locktime_to_blocks(&peer->remote.locktime))
return;
/* Already done? (FIXME: Delete after first time) */
@ -2408,48 +2420,6 @@ const struct json_command getpeers_command = {
"Returns a 'peers' array"
};
/* FIXME: Keep a timeout for each peer, in case they're unresponsive. */
/* FIXME: Make sure no HTLCs in any unrevoked commit tx are live. */
static void check_htlc_expiry(struct peer *peer)
{
size_t i;
log_debug(peer->log, "Expiry timedout!");
/* Check their currently still-existing htlcs for expiry:
* We eliminate them from staging as we go. */
for (i = 0; i < tal_count(peer->remote.staging_cstate->side[THEIRS].htlcs); i++) {
struct channel_htlc *htlc = &peer->remote.staging_cstate->side[THEIRS].htlcs[i];
/* Not a seconds-based expiry? */
if (!abs_locktime_is_seconds(&htlc->expiry))
continue;
/* Not well-expired? */
if (controlled_time().ts.tv_sec - 30
< abs_locktime_to_seconds(&htlc->expiry))
continue;
/* This can fail only if we're in an error state. */
command_htlc_fail(peer, htlc->id);
return;
}
}
void peer_add_htlc_expiry(struct peer *peer,
const struct abs_locktime *expiry)
{
struct timeabs absexpiry;
/* Add 30 seconds to be sure peers agree on timeout. */
absexpiry.ts.tv_sec = abs_locktime_to_seconds(expiry) + 30;
absexpiry.ts.tv_nsec = 0;
new_abstimer(peer->dstate, peer, absexpiry, check_htlc_expiry, peer);
}
static void do_newhtlc(struct peer *peer,
struct channel_htlc *htlc,
struct command *jsoncmd)
@ -2553,21 +2523,21 @@ static void json_newhtlc(struct command *cmd,
return;
}
if (!seconds_to_abs_locktime(expiry, &htlc.expiry)) {
command_fail(cmd, "'%.*s' is not a valid number",
if (!blocks_to_abs_locktime(expiry, &htlc.expiry)) {
command_fail(cmd, "'%.*s' is not a valid number block number",
(int)(expirytok->end - expirytok->start),
buffer + expirytok->start);
return;
}
if (abs_locktime_to_seconds(&htlc.expiry) <
controlled_time().ts.tv_sec + peer->dstate->config.min_expiry) {
if (abs_locktime_to_blocks(&htlc.expiry) <
get_block_height(peer->dstate) + peer->dstate->config.min_htlc_expiry) {
command_fail(cmd, "HTLC expiry too soon!");
return;
}
if (abs_locktime_to_seconds(&htlc.expiry) >
controlled_time().ts.tv_sec + peer->dstate->config.max_expiry) {
if (abs_locktime_to_blocks(&htlc.expiry) >
get_block_height(peer->dstate) + peer->dstate->config.max_htlc_expiry) {
command_fail(cmd, "HTLC expiry too far!");
return;
}
@ -2589,7 +2559,7 @@ static void json_newhtlc(struct command *cmd,
const struct json_command newhtlc_command = {
"newhtlc",
json_newhtlc,
"Offer {peerid} an HTLC worth {msatoshis} in {expiry} (in seconds since Jan 1 1970) with {rhash}",
"Offer {peerid} an HTLC worth {msatoshis} in {expiry} (block number) with {rhash}",
"Returns an empty result on success"
};

5
daemon/peer.h

@ -82,7 +82,7 @@ struct peer_visible_state {
enum state_input offer_anchor;
/* Key for commitment tx inputs, then key for commitment tx outputs */
struct pubkey commitkey, finalkey;
/* How long to they want the other's outputs locked (seconds) */
/* How long to they want the other's outputs locked (blocks) */
struct rel_locktime locktime;
/* Minimum depth of anchor before channel usable. */
unsigned int mindepth;
@ -244,9 +244,6 @@ void peer_update_complete(struct peer *peer);
/* Peer has completed open, or problem (if non-NULL). */
void peer_open_complete(struct peer *peer, const char *problem);
void peer_add_htlc_expiry(struct peer *peer,
const struct abs_locktime *expiry);
struct bitcoin_tx *peer_create_close_tx(struct peer *peer, u64 fee);
uint64_t commit_tx_fee(const struct bitcoin_tx *commit,

66
daemon/test/test.sh

@ -105,6 +105,11 @@ lcli2()
$LCLI2 "$@"
}
blockheight()
{
$CLI getblockcount
}
# Usage: <cmd to test>...
check()
{
@ -235,18 +240,18 @@ fi
cat > $DIR1/config <<EOF
log-level=debug
bitcoind-poll=1s
min-expiry=900
min-htlc-expiry=6
bitcoin-datadir=$DATADIR
locktime=600
locktime-blocks=6
commit-time=$COMMIT_TIME
EOF
cat > $DIR2/config <<EOF
log-level=debug
bitcoind-poll=1s
min-expiry=900
min-htlc-expiry=6
bitcoin-datadir=$DATADIR
locktime=600
locktime-blocks=6
commit-time=$COMMIT_TIME
EOF
@ -371,13 +376,13 @@ if [ -n "$DIFFERENT_FEES" ]; then
check_status_single lcli1 $A_AMOUNT1 $A_FEE1 "" $B_AMOUNT $B_FEE ""
check_status_single lcli2 $B_AMOUNT $B_FEE "" $(($A_AMOUNT2)) $(($A_FEE2)) ""
EXPIRY=$(( $(date +%s) + 1000))
EXPIRY=$(( $(blockheight) + 10))
SECRET=1de08917a61cb2b62ed5937d38577f6a7bfe59c176781c6d8128018e8b5ccdfd
RHASH=`lcli1 dev-rhash $SECRET | sed 's/.*"\([0-9a-f]*\)".*/\1/'`
lcli1 newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH
[ ! -n "$MANUALCOMMIT" ] || lcli1 commit $ID2
[ ! -n "$MANUALCOMMIT" ] || lcli2 commit $ID1
check_status_single lcli2 0 0 "" $(($AMOUNT - $HTLC_AMOUNT - $ONE_HTLCS_FEE2)) $(($ONE_HTLCS_FEE2)) '{ "msatoshis" : '$HTLC_AMOUNT', "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH'" } '
check_status_single lcli2 0 0 "" $(($AMOUNT - $HTLC_AMOUNT - $ONE_HTLCS_FEE2)) $(($ONE_HTLCS_FEE2)) '{ "msatoshis" : '$HTLC_AMOUNT', "expiry" : { "block" : '$EXPIRY' }, "rhash" : "'$RHASH'" } '
lcli2 fulfillhtlc $ID1 $SECRET
[ ! -n "$MANUALCOMMIT" ] || lcli2 commit $ID1
[ ! -n "$MANUALCOMMIT" ] || lcli1 commit $ID2
@ -412,7 +417,7 @@ check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE ""
# This is 10,000 satoshi, so not dust!
HTLC_AMOUNT=10000000
EXPIRY=$(( $(date +%s) + 1000))
EXPIRY=$(( $(blockheight) + 10))
SECRET=1de08917a61cb2b62ed5937d38577f6a7bfe59c176781c6d8128018e8b5ccdfd
RHASH=`lcli1 dev-rhash $SECRET | sed 's/.*"\([0-9a-f]*\)".*/\1/'`
@ -438,7 +443,7 @@ if [ -n "$MANUALCOMMIT" ]; then
A_FEE=$(($A_FEE + $EXTRA_FEE))
# Node 2 has it committed.
check_status_single lcli2 $B_AMOUNT $B_FEE "" $A_AMOUNT $A_FEE '{ "msatoshis" : '$HTLC_AMOUNT', "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH'" } '
check_status_single lcli2 $B_AMOUNT $B_FEE "" $A_AMOUNT $A_FEE '{ "msatoshis" : '$HTLC_AMOUNT', "expiry" : { "block" : '$EXPIRY' }, "rhash" : "'$RHASH'" } '
# There should be no "both committed" here yet
if lcli1 getlog debug | $FGREP "Both committed"; then
@ -462,7 +467,7 @@ else
fi
# Both should have committed tx.
check_status $A_AMOUNT $A_FEE '{ "msatoshis" : '$HTLC_AMOUNT', "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH'" } ' $B_AMOUNT $B_FEE ""
check_status $A_AMOUNT $A_FEE '{ "msatoshis" : '$HTLC_AMOUNT', "expiry" : { "block" : '$EXPIRY' }, "rhash" : "'$RHASH'" } ' $B_AMOUNT $B_FEE ""
if [ -n "$STEAL" ]; then
$LCLI1 dev-signcommit $ID2 >&2
@ -484,19 +489,18 @@ if [ -n "$DUMP_ONCHAIN" ]; then
check_peerstate lcli2 STATE_CLOSE_ONCHAIN_THEIR_UNILATERAL
# both still know about htlc
check_status $A_AMOUNT $A_FEE '{ "msatoshis" : '$HTLC_AMOUNT', "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH'" } ' $B_AMOUNT $B_FEE ""
check_status $A_AMOUNT $A_FEE '{ "msatoshis" : '$HTLC_AMOUNT', "expiry" : { "block" : '$EXPIRY' }, "rhash" : "'$RHASH'" } ' $B_AMOUNT $B_FEE ""
# Move bitcoind's time so CSV timeout has expired.
$CLI setmocktime $((`date +%s` + 600))
# Generate 6 blocks so CSV timeout has expired.
$CLI generate 6
# Now, lcli1 should spend its own output.
check_tx_spend lcli1
check_peerstate lcli1 STATE_CLOSE_ONCHAIN_OUR_UNILATERAL
# Move bitcoind's time so HTLC has expired.
$CLI setmocktime $(($EXPIRY + 1))
$CLI generate 6
while [ $(blockheight) != $EXPIRY ]; do
$CLI generate 1
done
# lcli1 should have gotten HTLC back.
check_tx_spend lcli1
@ -549,7 +553,7 @@ lcli1 newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH
# Check channel status
A_AMOUNT=$(($A_AMOUNT - $EXTRA_FEE - $HTLC_AMOUNT))
A_FEE=$(($A_FEE + $EXTRA_FEE))
check_status $A_AMOUNT $A_FEE '{ "msatoshis" : '$HTLC_AMOUNT', "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH'" } ' $B_AMOUNT $B_FEE ""
check_status $A_AMOUNT $A_FEE '{ "msatoshis" : '$HTLC_AMOUNT', "expiry" : { "block" : '$EXPIRY' }, "rhash" : "'$RHASH'" } ' $B_AMOUNT $B_FEE ""
lcli2 failhtlc $ID1 $RHASH
[ ! -n "$MANUALCOMMIT" ] || lcli2 commit $ID1
@ -569,17 +573,23 @@ lcli1 newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH
# Check channel status
A_AMOUNT=$(($A_AMOUNT - $EXTRA_FEE - $HTLC_AMOUNT))
A_FEE=$(($A_FEE + $EXTRA_FEE))
check_status $A_AMOUNT $A_FEE '{ "msatoshis" : '$HTLC_AMOUNT', "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH'" } ' $B_AMOUNT $B_FEE ""
check_status $A_AMOUNT $A_FEE '{ "msatoshis" : '$HTLC_AMOUNT', "expiry" : { "block" : '$EXPIRY' }, "rhash" : "'$RHASH'" } ' $B_AMOUNT $B_FEE ""
# Make sure node1 accepts the expiry packet.
MOCKTIME=$(($EXPIRY))
lcli1 dev-mocktime $MOCKTIME
while [ $(blockheight) != $EXPIRY ]; do
$CLI generate 1
done
# This should make node2 send it.
MOCKTIME=$(($MOCKTIME + 31))
lcli2 dev-mocktime $MOCKTIME
[ ! -n "$MANUALCOMMIT" ] || lcli2 commit $ID1
[ ! -n "$MANUALCOMMIT" ] || lcli1 commit $ID2
$CLI generate 1
if [ -n "$MANUALCOMMIT" ]; then
# Don't commit until it's noticed the new block
check_staged lcli2 remote 1
lcli2 commit $ID1
lcli1 commit $ID2
fi
# Back to how we were before.
A_AMOUNT=$(($A_AMOUNT + $EXTRA_FEE + $HTLC_AMOUNT))
@ -608,13 +618,13 @@ if [ -n "$STEAL" ]; then
fi
# First, give more money to node2, so it can offer HTLCs.
EXPIRY=$(($MOCKTIME + 1000))
EXPIRY=$(( $(blockheight) + 10))
HTLC_AMOUNT=100000000
lcli1 newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH
[ ! -n "$MANUALCOMMIT" ] || lcli1 commit $ID2
[ ! -n "$MANUALCOMMIT" ] || lcli2 commit $ID1
check_status $(($A_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE)) $(($A_FEE + $EXTRA_FEE)) '{ "msatoshis" : '$HTLC_AMOUNT', "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH'" } ' $B_AMOUNT $B_FEE ""
check_status $(($A_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE)) $(($A_FEE + $EXTRA_FEE)) '{ "msatoshis" : '$HTLC_AMOUNT', "expiry" : { "block" : '$EXPIRY' }, "rhash" : "'$RHASH'" } ' $B_AMOUNT $B_FEE ""
lcli2 fulfillhtlc $ID1 $SECRET
[ ! -n "$MANUALCOMMIT" ] || lcli2 commit $ID1
@ -640,7 +650,7 @@ lcli2 newhtlc $ID1 $HTLC_AMOUNT $EXPIRY $RHASH2
[ ! -n "$MANUALCOMMIT" ] || lcli2 commit $ID1
[ ! -n "$MANUALCOMMIT" ] || lcli1 commit $ID2
check_status $(($A_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE)) $(($A_FEE + $EXTRA_FEE)) '{ "msatoshis" : '$HTLC_AMOUNT', "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH'" } ' $(($B_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE)) $(($B_FEE + $EXTRA_FEE)) '{ "msatoshis" : '$HTLC_AMOUNT', "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH2'" } '
check_status $(($A_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE)) $(($A_FEE + $EXTRA_FEE)) '{ "msatoshis" : '$HTLC_AMOUNT', "expiry" : { "block" : '$EXPIRY' }, "rhash" : "'$RHASH'" } ' $(($B_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE)) $(($B_FEE + $EXTRA_FEE)) '{ "msatoshis" : '$HTLC_AMOUNT', "expiry" : { "block" : '$EXPIRY' }, "rhash" : "'$RHASH2'" } '
if [ -n "$CLOSE_WITH_HTLCS" ]; then
# Now begin close
@ -695,7 +705,7 @@ lcli1 newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH
# Make sure node1 sends commit (in the background, since it will block!)
[ ! -n "$MANUALCOMMIT" ] || lcli1 commit $ID2 &
# node2 will consider this committed.
check_status_single lcli2 $(($B_AMOUNT - $EXTRA_FEE/2)) $(($B_FEE + $EXTRA_FEE/2)) "" $(($A_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE/2)) $(($A_FEE + $EXTRA_FEE/2)) '{ "msatoshis" : '$HTLC_AMOUNT', "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH'" } '
check_status_single lcli2 $(($B_AMOUNT - $EXTRA_FEE/2)) $(($B_FEE + $EXTRA_FEE/2)) "" $(($A_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE/2)) $(($A_FEE + $EXTRA_FEE/2)) '{ "msatoshis" : '$HTLC_AMOUNT', "expiry" : { "block" : '$EXPIRY' }, "rhash" : "'$RHASH'" } '
# Now send another offer, and enable node2 output.
lcli1 newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH2
@ -706,7 +716,7 @@ lcli2 dev-output $ID1 true
[ ! -n "$MANUALCOMMIT" ] || lcli2 commit $ID1
# Both sides should be committed to htlcs
check_status $(($A_AMOUNT - $HTLC_AMOUNT*2 - $EXTRA_FEE)) $(($A_FEE + $EXTRA_FEE)) '{ "msatoshis" : '$HTLC_AMOUNT', "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH'" }, { "msatoshis" : '$HTLC_AMOUNT', "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH2'" } ' $(($B_AMOUNT - $EXTRA_FEE)) $(($B_FEE + $EXTRA_FEE)) ""
check_status $(($A_AMOUNT - $HTLC_AMOUNT*2 - $EXTRA_FEE)) $(($A_FEE + $EXTRA_FEE)) '{ "msatoshis" : '$HTLC_AMOUNT', "expiry" : { "block" : '$EXPIRY' }, "rhash" : "'$RHASH'" }, { "msatoshis" : '$HTLC_AMOUNT', "expiry" : { "block" : '$EXPIRY' }, "rhash" : "'$RHASH2'" } ' $(($B_AMOUNT - $EXTRA_FEE)) $(($B_FEE + $EXTRA_FEE)) ""
# Node2 collects the HTLCs.
lcli2 fulfillhtlc $ID1 $SECRET

Loading…
Cancel
Save