core-lightning/daemon/test/test.sh
Rusty Russell 02cb7abd9d bitcoind: keep running fee estimate.
This avoids us having to query it when we create anchor transaction, and
lets us always use dynamic fee information.

The config options for max and min are now percentages, rather than absolute.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2016-08-18 14:23:46 +09:30

895 lines
27 KiB
Bash
Executable File

#! /bin/sh -e
# Wherever we are, we want to be in daemon/test dir.
cd `git rev-parse --show-toplevel`/daemon/test
. scripts/vars.sh
scripts/setup.sh
DIR1=/tmp/lightning.$$.1
DIR2=/tmp/lightning.$$.2
DIR3=/tmp/lightning.$$.3
REDIR1="$DIR1/output"
REDIR2="$DIR2/output"
REDIRERR1="$DIR1/errors"
REDIRERR2="$DIR2/errors"
FGREP="fgrep -q"
# We inject 0.01 bitcoin, but then fees (estimatefee fails and we use a
# fee rate as per the default).
AMOUNT=991880000
# Default fee rate per kb.
FEE_RATE=200000
# Fee in millisatoshi if we have no htlcs (note rounding to make it even)
NO_HTLCS_FEE=$((338 * $FEE_RATE / 2000 * 2000))
ONE_HTLCS_FEE=$(( (338 + 32) * $FEE_RATE / 2000 * 2000))
EXTRA_FEE=$(($ONE_HTLCS_FEE - $NO_HTLCS_FEE))
# Always use valgrind if available.
[ -n "$NO_VALGRIND" ] || PREFIX="valgrind -q --error-exitcode=7"
while [ $# != 0 ]; do
case x"$1" in
x"--valgrind-vgdb")
[ -n "$NO_VALGRIND" ] || PREFIX="valgrind --vgdb-error=1"
REDIR1="/dev/tty"
REDIRERR1="/dev/tty"
REDIR2="/dev/tty"
REDIRERR2="/dev/tty"
;;
x"--gdb1")
GDB1=1
;;
x"--gdb2")
GDB2=1
;;
x"--timeout-anchor")
TIMEOUT_ANCHOR=1
;;
x"--dump-onchain")
DUMP_ONCHAIN=1
;;
x"--steal")
STEAL=1
;;
x"--manual-commit")
MANUALCOMMIT=1
;;
x"--mutual-close-with-htlcs")
CLOSE_WITH_HTLCS=1
;;
x"--different-fee-rates")
DIFFERENT_FEES=1
;;
x"--normal")
;;
x"--crash")
CRASH_ON_FAIL=1
;;
x"--verbose")
VERBOSE=1
;;
*)
echo Unknown arg "$1" >&2
exit 1
esac
shift
done
LCLI1="../lightning-cli --lightning-dir=$DIR1"
LCLI2="../lightning-cli --lightning-dir=$DIR2"
LCLI3="../lightning-cli --lightning-dir=$DIR3"
if [ -n "$VERBOSE" ]; then
FGREP="fgrep"
else
# Suppress command output.
exec >/dev/null
fi
lcli1()
{
if [ -n "$VERBOSE" ]; then
echo $LCLI1 "$@" >&2
fi
$LCLI1 "$@"
}
lcli2()
{
if [ -n "$VERBOSE" ]; then
echo $LCLI2 "$@" >&2
fi
$LCLI2 "$@"
}
lcli3()
{
if [ -n "$VERBOSE" ]; then
echo $LCLI3 "$@" >&2
fi
$LCLI3 "$@"
}
blockheight()
{
$CLI getblockcount
}
# Usage: <cmd to test>...
check()
{
local i=0
while ! eval "$@"; do
# Try making time pass for the nodes (if on mocktime), then sleeping.
if [ -n "$MOCKTIME" ]; then
MOCKTIME=$(($MOCKTIME + 1))
lcli1 dev-mocktime $MOCKTIME
lcli2 dev-mocktime $MOCKTIME
fi
sleep 1
i=$(($i + 1))
if [ $i = 20 ]; then
return 1
fi
done
}
check_balance_single()
{
lcli="$1"
us_pay=$2
us_fee=$3
them_pay=$4
them_fee=$5
if check "$lcli getpeers | tr -s '\012\011\" ' ' ' | $FGREP \"our_amount : $us_pay, our_fee : $us_fee, their_amount : $them_pay, their_fee : $them_fee,\""; then :; else
echo Cannot find $lcli output: "our_amount : $us_pay, our_fee : $us_fee, their_amount : $them_pay, their_fee : $them_fee," >&2
$lcli getpeers | tr -s '\012\011" ' ' ' >&2
return 1
fi
}
check_status_single()
{
lcli="$1"
us_pay=$2
us_fee=$3
us_htlcs="$4"
them_pay=$5
them_fee=$6
them_htlcs="$7"
check_balance_single "$lcli" $us_pay $us_fee $them_pay $them_fee
if check "$lcli getpeers | tr -s '\012\011\" ' ' ' | $FGREP \"our_htlcs : [ $us_htlcs], their_htlcs : [ $them_htlcs]\""; then :; else
echo Cannot find $lcli output: "our_htlcs : [ $us_htlcs], their_htlcs : [ $them_htlcs]" >&2
$lcli getpeers | tr -s '\012\011" ' ' ' >&2
return 1
fi
}
# SEND_ -> RCVD_ and RCVD_ -> SEND_
swap_status()
{
echo "$@" | sed -e 's/state : RCVD_/@@/g' -e 's/state : SENT_/state : RCVD_/g' -e 's/@@/state : SENT_/g'
}
check_status()
{
us_pay=$1
us_fee=$2
us_htlcs="$3"
them_pay=$4
them_fee=$5
them_htlcs="$6"
check_status_single lcli1 "$us_pay" "$us_fee" "$us_htlcs" "$them_pay" "$them_fee" "$them_htlcs"
check_status_single lcli2 "$them_pay" "$them_fee" "`swap_status \"$them_htlcs\"`" "$us_pay" "$us_fee" "`swap_status \"$us_htlcs\"`"
}
check_tx_spend()
{
if check "$CLI getrawmempool | $FGREP '\"'"; then :;
else
echo "No tx in mempool:" >&2
$CLI getrawmempool >&2
exit 1
fi
}
check_peerstate()
{
if check "$1 getpeers | $FGREP -w $2"; then :
else
echo "$1" not in state "$2": >&2
$1 getpeers >&2
exit 1
fi
}
check_peerconnected()
{
if check "$1 getpeers | tr -s '\012\011\" ' ' ' | $FGREP -w 'connected : '$2"; then :
else
echo "$1" not connected "$2": >&2
$1 getpeers >&2
exit 1
fi
}
check_no_peers()
{
if check "$1 getpeers | tr -s '\012\011\" ' ' ' | $FGREP 'peers : [ ]'"; then :
else
echo "$1" still has peers: >&2
$1 getpeers >&2
exit 1
fi
}
extract_id()
{
XID=`tr -s '\012\011\" ' ' ' | sed -n 's/{ id : \([0-9]*\) }/\1/p'`
case "$XID" in
[0-9]*)
echo $XID;;
*)
return 1;;
esac
}
all_ok()
{
# Look for valgrind errors.
if grep ^== $DIR1/errors; then exit 1; fi
if grep ^== $DIR2/errors; then exit 1; fi
if grep ^== $DIR3/errors; then exit 1; fi
scripts/shutdown.sh
trap "rm -rf $DIR1 $DIR2 $DIR3" EXIT
exit 0
}
if [ -n "$CRASH_ON_FAIL" ]; then
trap "$LCLI1 dev-crash 2>/dev/null || true; $LCLI2 dev-crash 2>/dev/null || true; echo Crash results in $DIR1 and $DIR2 >&2; cat $DIR1/errors $DIR2/errors >&2" EXIT
else
trap "echo Results in $DIR1 and $DIR2 >&2; cat $DIR1/errors $DIR2/errors >&2" EXIT
fi
mkdir $DIR1 $DIR2 $DIR3
if [ -n "$MANUALCOMMIT" ]; then
# Aka. never.
COMMIT_TIME=1h
else
COMMIT_TIME=10ms
fi
cat > $DIR1/config <<EOF
log-level=debug
bitcoind-poll=1s
deadline-blocks=5
min-htlc-expiry=6
bitcoin-datadir=$DATADIR
locktime-blocks=6
commit-time=$COMMIT_TIME
EOF
cat > $DIR2/config <<EOF
log-level=debug
bitcoind-poll=1s
deadline-blocks=5
min-htlc-expiry=6
bitcoin-datadir=$DATADIR
locktime-blocks=6
commit-time=$COMMIT_TIME
EOF
cp $DIR2/config $DIR3/config
if [ -n "$DIFFERENT_FEES" ]; then
# Simply override default fee (estimatefee fails on regtest anyway)
CLOSE_FEE_RATE2=50000
# We use 5x fee rate for commits, by defailt.
FEE_RATE2=$(($CLOSE_FEE_RATE2 * 5))
echo "default-fee-rate=$CLOSE_FEE_RATE2" >> $DIR2/config
fi
if [ -n "$GDB1" ]; then
echo Press return once you run: gdb --args daemon/lightningd --lightning-dir=$DIR1 >&2
read REPLY
else
$PREFIX ../lightningd --lightning-dir=$DIR1 > $REDIR1 2> $REDIRERR1 &
fi
if [ -n "$GDB2" ]; then
echo Press return once you run: gdb --args daemon/lightningd --lightning-dir=$DIR2 >&2
read REPLY
else
$PREFIX ../lightningd --lightning-dir=$DIR2 > $REDIR2 2> $REDIRERR2 &
fi
$PREFIX ../lightningd --lightning-dir=$DIR3 > $DIR3/output 2> $DIR3/errors &
if ! check "$LCLI1 getlog 2>/dev/null | $FGREP Hello"; then
echo Failed to start daemon 1 >&2
exit 1
fi
if ! check "$LCLI2 getlog 2>/dev/null | $FGREP Hello"; then
echo Failed to start daemon 2 >&2
exit 1
fi
if ! check "$LCLI3 getlog 2>/dev/null | $FGREP Hello"; then
echo Failed to start daemon 3 >&2
exit 1
fi
ID1=`$LCLI1 getlog | sed -n 's/.*"ID: \([0-9a-f]*\)".*/\1/p'`
ID2=`$LCLI2 getlog | sed -n 's/.*"ID: \([0-9a-f]*\)".*/\1/p'`
ID3=`$LCLI3 getlog | sed -n 's/.*"ID: \([0-9a-f]*\)".*/\1/p'`
PORT2=`$LCLI2 getlog | sed -n 's/.*on port \([0-9]*\).*/\1/p'`
PORT3=`$LCLI3 getlog | sed -n 's/.*on port \([0-9]*\).*/\1/p'`
# Make a payment into a P2SH for anchor.
P2SHADDR=`$LCLI1 newaddr | sed -n 's/{ "address" : "\(.*\)" }/\1/p'`
TXID=`$CLI sendtoaddress $P2SHADDR 0.01`
TX=`$CLI getrawtransaction $TXID`
$CLI generate 1
lcli1 connect localhost $PORT2 $TX
# Expect them to be waiting for anchor.
check_peerstate lcli1 STATE_OPEN_WAITING_OURANCHOR
check_peerstate lcli2 STATE_OPEN_WAITING_THEIRANCHOR
if [ -n "$TIMEOUT_ANCHOR" ]; then
# Check anchor emitted, not mined deep enough.
check_tx_spend lcli1
$CLI generate 2
# Timeout before anchor committed.
MOCKTIME=$((`date +%s` + 7200 + 3 * 1200 + 1))
lcli1 dev-mocktime $MOCKTIME
lcli2 dev-mocktime $MOCKTIME
# Node2 should have gone via STATE_ERR_ANCHOR_TIMEOUT, then closed.
lcli2 getlog | grep STATE_ERR_ANCHOR_TIMEOUT
check_no_peers lcli2
# Node1 should be disconnected.
check_peerconnected lcli1 false
# Node1 should send out commit tx; mine it.
check_tx_spend lcli1
$CLI generate 1
check_peerstate lcli1 STATE_CLOSE_ONCHAIN_OUR_UNILATERAL
# Now "wait" for 1 day, which is what node2 asked for on commit.
MOCKTIME=$(($MOCKTIME + 24 * 60 * 60 - 1))
lcli1 dev-mocktime $MOCKTIME
# Move bitcoind median time as well, so CSV moves.
$CLI setmocktime $MOCKTIME
$CLI generate 6
# Now it should have spent the commit tx.
check_tx_spend lcli1
# 100 blocks pass...
$CLI generate 100
MOCKTIME=$(($MOCKTIME + 1))
lcli1 dev-mocktime $MOCKTIME
# Considers it all done now.
check_no_peers lcli1
lcli1 stop
lcli2 stop
all_ok
fi
# Now make it pass anchor (should be in mempool: three blocks bury it)
check_tx_spend lcli1
$CLI generate 3
check_peerstate lcli1 STATE_NORMAL
check_peerstate lcli2 STATE_NORMAL
# We turn off routing failure for the moment.
lcli1 dev-routefail false
lcli2 dev-routefail false
if [ -n "$DIFFERENT_FEES" ]; then
# This is 100,000 satoshi, so covers fees.
HTLC_AMOUNT=100000000
# Asymmetry, since fee rates different.
NO_HTLCS_FEE2=$((338 * $FEE_RATE2 / 2000 * 2000))
ONE_HTLCS_FEE2=$(( (338 + 32) * $FEE_RATE2 / 2000 * 2000))
A_AMOUNT1=$(($AMOUNT - $NO_HTLCS_FEE))
A_FEE1=$NO_HTLCS_FEE
A_AMOUNT2=$(($AMOUNT - $NO_HTLCS_FEE2))
A_FEE2=$NO_HTLCS_FEE2
B_AMOUNT=0
B_FEE=0
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=$(( $(blockheight) + 10))
SECRET=1de08917a61cb2b62ed5937d38577f6a7bfe59c176781c6d8128018e8b5ccdfd
RHASH=`lcli1 dev-rhash $SECRET | sed 's/.*"\([0-9a-f]*\)".*/\1/'`
HTLCID=`lcli1 newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id`
[ ! -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 : { block : $EXPIRY }, rhash : $RHASH , state : RCVD_ADD_ACK_REVOCATION } "
lcli2 fulfillhtlc $ID1 $HTLCID $SECRET
[ ! -n "$MANUALCOMMIT" ] || lcli2 commit $ID1
[ ! -n "$MANUALCOMMIT" ] || lcli1 commit $ID2
check_status_single lcli1 $(($AMOUNT - $HTLC_AMOUNT - $NO_HTLCS_FEE / 2)) $(($NO_HTLCS_FEE / 2)) "" $(($HTLC_AMOUNT - $NO_HTLCS_FEE / 2)) $(($NO_HTLCS_FEE / 2)) ""
check_status_single lcli2 $(($HTLC_AMOUNT - $NO_HTLCS_FEE2 / 2)) $(($NO_HTLCS_FEE2 / 2)) "" $(($AMOUNT - $HTLC_AMOUNT - $NO_HTLCS_FEE2 / 2)) $(($NO_HTLCS_FEE2 / 2)) ""
lcli1 close $ID2
# Make sure they notice it.
check_peerstate lcli1 STATE_MUTUAL_CLOSING
check_peerstate lcli2 STATE_MUTUAL_CLOSING
$CLI generate 1
check_peerstate lcli1 STATE_CLOSE_ONCHAIN_MUTUAL
check_peerstate lcli2 STATE_CLOSE_ONCHAIN_MUTUAL
# Give it 100 blocks.
$CLI generate 100
check_no_peers lcli1
check_no_peers lcli2
lcli1 stop
lcli2 stop
all_ok
fi
A_AMOUNT=$(($AMOUNT - $NO_HTLCS_FEE))
A_FEE=$NO_HTLCS_FEE
B_AMOUNT=0
B_FEE=0
check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE ""
# This is 10,000 satoshi, so not dust!
HTLC_AMOUNT=10000000
EXPIRY=$(( $(blockheight) + 10))
SECRET=1de08917a61cb2b62ed5937d38577f6a7bfe59c176781c6d8128018e8b5ccdfd
RHASH=`lcli1 dev-rhash $SECRET | sed 's/.*"\([0-9a-f]*\)".*/\1/'`
HTLCID=`lcli1 newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id`
if [ -n "$MANUALCOMMIT" ]; then
# They should register a staged htlc.
check_status $A_AMOUNT $A_FEE "{ msatoshis : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_HTLC } " $B_AMOUNT $B_FEE ""
# Now commit it.
lcli1 commit $ID2
# Node 1 hasn't got it committed, but node2 should have told it to stage.
check_status_single lcli1 $A_AMOUNT $A_FEE "{ msatoshis : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : RCVD_ADD_REVOCATION } " $B_AMOUNT $B_FEE ""
# Check channel status
A_AMOUNT=$(($A_AMOUNT - $EXTRA_FEE - $HTLC_AMOUNT))
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 : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_REVOCATION } "
# There should be no "both committed" here yet
if lcli1 getlog debug | $FGREP "Both committed"; then
echo "Node1 thinks they are both committed";
exit 1
fi
if lcli2 getlog debug | $FGREP "Both committed"; then
echo "Node2 thinks they are both committed";
exit 1
fi
# Now node2 gives commitment to node1.
lcli2 commit $ID1
# After revocation, they should know they're both committed.
check lcli1 "getlog debug | $FGREP 'Both committed to ADD of our HTLC'"
check lcli2 "getlog debug | $FGREP 'Both committed to ADD of their HTLC'"
else
A_AMOUNT=$(($A_AMOUNT - $EXTRA_FEE - $HTLC_AMOUNT))
A_FEE=$(($A_FEE + $EXTRA_FEE))
fi
# Both should have committed tx.
check_status $A_AMOUNT $A_FEE "{ msatoshis : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } " $B_AMOUNT $B_FEE ""
if [ -n "$STEAL" ]; then
STEAL_TX=`$LCLI1 dev-signcommit $ID2 | cut -d\" -f4`
fi
if [ -n "$DUMP_ONCHAIN" ]; then
# make node1 disconnect with node2.
lcli1 dev-disconnect $ID2
check_peerconnected lcli1 false
# lcli1 should have sent out commitment tx
check_peerstate lcli1 STATE_ERR_BREAKDOWN
check_tx_spend lcli1
# Mine it.
$CLI generate 1
check_peerstate lcli1 STATE_CLOSE_ONCHAIN_OUR_UNILATERAL
check_peerstate lcli2 STATE_CLOSE_ONCHAIN_THEIR_UNILATERAL
# both still know about htlc
check_status $A_AMOUNT $A_FEE "{ msatoshis : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } " $B_AMOUNT $B_FEE ""
# 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
while [ $(blockheight) != $EXPIRY ]; do
$CLI generate 1
done
# lcli1 should have gotten HTLC back.
check_tx_spend lcli1
# Now, after 100 blocks, should all be concluded.
$CLI generate 100
# Both consider it all done now.
check_no_peers lcli1
lcli1 stop
all_ok
fi
lcli2 fulfillhtlc $ID1 $HTLCID $SECRET
[ ! -n "$MANUALCOMMIT" ] || lcli2 commit $ID1
# Without manual commit, this check is racy.
if [ -n "$MANUALCOMMIT" ]; then
if lcli1 getlog debug | $FGREP 'Both committed to FULFILL'; then
echo "Node1 thinks they are both committed";
exit 1
fi
if lcli2 getlog debug | $FGREP 'Both committed to FULFILL'; then
echo "Node2 thinks they are both committed";
exit 1
fi
fi
[ ! -n "$MANUALCOMMIT" ] || lcli1 commit $ID2
check lcli1 "getlog debug | $FGREP 'Both committed to FULFILL of our HTLC'"
check lcli2 "getlog debug | $FGREP 'Both committed to FULFILL of their HTLC'"
# We've transferred the HTLC amount to 2, who now has to pay fees,
# so no net change for A who saves on fees.
B_FEE=$HTLC_AMOUNT
# With no HTLCs, extra fee no longer required.
A_FEE=$(($A_FEE - $EXTRA_FEE - $B_FEE))
A_AMOUNT=$(($A_AMOUNT + $EXTRA_FEE + $HTLC_AMOUNT))
check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE ""
# A new one, at 10x the amount.
HTLC_AMOUNT=100000000
HTLCID=`lcli1 newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id`
[ ! -n "$MANUALCOMMIT" ] || lcli1 commit $ID2
[ ! -n "$MANUALCOMMIT" ] || lcli2 commit $ID1
# 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 : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } " $B_AMOUNT $B_FEE ""
lcli2 failhtlc $ID1 $HTLCID
[ ! -n "$MANUALCOMMIT" ] || lcli2 commit $ID1
[ ! -n "$MANUALCOMMIT" ] || lcli1 commit $ID2
# Back to how we were before.
A_AMOUNT=$(($A_AMOUNT + $EXTRA_FEE + $HTLC_AMOUNT))
A_FEE=$(($A_FEE - $EXTRA_FEE))
check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE ""
# Same again, but this time it expires.
HTLC_AMOUNT=10000001
HTLCID=`lcli1 newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id`
[ ! -n "$MANUALCOMMIT" ] || lcli1 commit $ID2
[ ! -n "$MANUALCOMMIT" ] || lcli2 commit $ID1
# 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 : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } " $B_AMOUNT $B_FEE ""
# Make sure node1 accepts the expiry packet.
while [ $(blockheight) != $EXPIRY ]; do
$CLI generate 1
done
# This should make node2 send it.
$CLI generate 1
if [ -n "$MANUALCOMMIT" ]; then
check_status $A_AMOUNT $A_FEE "{ msatoshis : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : RCVD_REMOVE_HTLC } " $B_AMOUNT $B_FEE ""
lcli2 commit $ID1
lcli1 commit $ID2
fi
# Back to how we were before.
A_AMOUNT=$(($A_AMOUNT + $EXTRA_FEE + $HTLC_AMOUNT))
A_FEE=$(($A_FEE - $EXTRA_FEE))
check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE ""
if [ -n "$STEAL" ]; then
# Send out old commit tx from peer 1.
$CLI sendrawtransaction $STEAL_TX
$CLI generate 1
# Node1 should get really upset; node2 should steal the transaction.
check_peerstate lcli1 STATE_ERR_INFORMATION_LEAK
check_peerstate lcli2 STATE_CLOSE_ONCHAIN_CHEATED
check_tx_spend lcli2
# Give it 100 blocks.
$CLI generate 100
check_no_peers lcli2
lcli1 stop
lcli2 stop
all_ok
fi
# First, give more money to node2, so it can offer HTLCs.
EXPIRY=$(( $(blockheight) + 10))
HTLC_AMOUNT=100000000
HTLCID=`lcli1 newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id`
[ ! -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 : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } " $B_AMOUNT $B_FEE ""
lcli2 fulfillhtlc $ID1 $HTLCID $SECRET
[ ! -n "$MANUALCOMMIT" ] || lcli2 commit $ID1
[ ! -n "$MANUALCOMMIT" ] || lcli1 commit $ID2
# Both now pay equal fees.
A_FEE=$(($NO_HTLCS_FEE / 2))
B_FEE=$(($NO_HTLCS_FEE / 2))
# We transferred 10000000 before, and $HTLC_AMOUNT now.
A_AMOUNT=$(($AMOUNT - 10000000 - $HTLC_AMOUNT - $A_FEE))
B_AMOUNT=$((10000000 + $HTLC_AMOUNT - $B_FEE))
check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE ""
# Now, two HTLCs at once, one from each direction.
# Both sides can afford this.
HTLC_AMOUNT=1000000
HTLCID=`lcli1 newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id`
SECRET2=1de08917a61cb2b62ed5937d38577f6a7bfe59c176781c6d8128018e8b5ccdfe
RHASH2=`lcli1 dev-rhash $SECRET2 | sed 's/.*"\([0-9a-f]*\)".*/\1/'`
HTLCID2=`lcli2 newhtlc $ID1 $HTLC_AMOUNT $EXPIRY $RHASH2 | extract_id`
[ ! -n "$MANUALCOMMIT" ] || lcli1 commit $ID2
[ ! -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 : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } " $(($B_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE)) $(($B_FEE + $EXTRA_FEE)) "{ msatoshis : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH2 , state : RCVD_ADD_ACK_REVOCATION } "
if [ -n "$CLOSE_WITH_HTLCS" ]; then
# Now begin close
lcli1 close $ID2
# They should be waiting for it to clear up.
check_peerstate lcli1 STATE_CLEARING
check_peerstate lcli2 STATE_CLEARING
# Fail one, still waiting.
lcli2 failhtlc $ID1 $HTLCID
check_peerstate lcli1 STATE_CLEARING
check_peerstate lcli2 STATE_CLEARING
# Fulfill the other causes them to actually complete the close.
lcli1 fulfillhtlc $ID2 $HTLCID2 $SECRET2
check_peerstate lcli1 STATE_MUTUAL_CLOSING
check_peerstate lcli2 STATE_MUTUAL_CLOSING
$CLI generate 1
check_peerstate lcli1 STATE_CLOSE_ONCHAIN_MUTUAL
check_peerstate lcli2 STATE_CLOSE_ONCHAIN_MUTUAL
# Give it 100 blocks.
$CLI generate 99
check_no_peers lcli1
check_no_peers lcli2
lcli1 stop
lcli2 stop
all_ok
fi
lcli2 failhtlc $ID1 $HTLCID
lcli1 fulfillhtlc $ID2 $HTLCID2 $SECRET2
[ ! -n "$MANUALCOMMIT" ] || lcli2 commit $ID1
[ ! -n "$MANUALCOMMIT" ] || lcli1 commit $ID2
[ ! -n "$MANUALCOMMIT" ] || lcli2 commit $ID1
# We transferred amount from B to A.
A_AMOUNT=$(($A_AMOUNT + $HTLC_AMOUNT))
B_AMOUNT=$(($B_AMOUNT - $HTLC_AMOUNT))
check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE ""
# Now, test making more changes before receiving commit reply.
lcli2 dev-output $ID1 false
HTLCID=`lcli1 newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id`
# Make sure node1 sends commit (in the background, since it will block!)
[ ! -n "$MANUALCOMMIT" ] || lcli1 commit $ID2 &
if [ -n "$MANUALCOMMIT" ]; then
# 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 : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_REVOCATION } "
else
# It will start committing by itself
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 , state : SENT_ADD_ACK_COMMIT } "
fi
# node1 will still be awaiting node2's revocation reply.
check_status_single lcli1 $(($A_AMOUNT)) $(($A_FEE)) "{ msatoshis : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_COMMIT } " $B_AMOUNT $B_FEE ""
# Now send another offer, and enable node2 output.
HTLCID2=`lcli1 newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH2 | extract_id`
lcli2 dev-output $ID1 true
[ ! -n "$MANUALCOMMIT" ] || lcli2 commit $ID1
[ ! -n "$MANUALCOMMIT" ] || lcli1 commit $ID2
[ ! -n "$MANUALCOMMIT" ] || lcli2 commit $ID1
# Both sides should be committed to htlcs
# We open-code check_status here: HTLCs could be in either order.
check_balance_single lcli1 $(($A_AMOUNT - $HTLC_AMOUNT*2 - $EXTRA_FEE)) $(($A_FEE + $EXTRA_FEE)) $(($B_AMOUNT - $EXTRA_FEE)) $(($B_FEE + $EXTRA_FEE))
check_balance_single lcli2 $(($B_AMOUNT - $EXTRA_FEE)) $(($B_FEE + $EXTRA_FEE)) $(($A_AMOUNT - $HTLC_AMOUNT*2 - $EXTRA_FEE)) $(($A_FEE + $EXTRA_FEE))
# Once both balances are correct, this should be right.
lcli1 getpeers | tr -s '\012\011" ' ' ' | $FGREP "our_htlcs : [ { msatoshis : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION }, { msatoshis : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH2 , state : SENT_ADD_ACK_REVOCATION } ], their_htlcs : [ ]" || lcli1 getpeers | tr -s '\012\011" ' ' ' | $FGREP "our_htlcs : [ { msatoshis : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH2 , state : SENT_ADD_ACK_REVOCATION }, { msatoshis : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } ], their_htlcs : [ ]"
lcli2 getpeers | tr -s '\012\011" ' ' ' | $FGREP "our_htlcs : [ ], their_htlcs : [ { msatoshis : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : RCVD_ADD_ACK_REVOCATION }, { msatoshis : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH2 , state : RCVD_ADD_ACK_REVOCATION } ]" || lcli2 getpeers | tr -s '\012\011" ' ' ' | $FGREP "our_htlcs : [ ], their_htlcs : [ { msatoshis : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH2 , state : RCVD_ADD_ACK_REVOCATION }, { msatoshis : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : RCVD_ADD_ACK_REVOCATION } ]"
# Node2 collects the HTLCs.
lcli2 fulfillhtlc $ID1 $HTLCID $SECRET
lcli2 fulfillhtlc $ID1 $HTLCID2 $SECRET2
[ ! -n "$MANUALCOMMIT" ] || lcli2 commit $ID1
[ ! -n "$MANUALCOMMIT" ] || lcli1 commit $ID2
# We transferred 2 * amount from A to B.
A_AMOUNT=$(($A_AMOUNT - $HTLC_AMOUNT * 2))
B_AMOUNT=$(($B_AMOUNT + $HTLC_AMOUNT * 2))
check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE ""
# Now, use automatic payment redemption
lcli1 dev-routefail true
lcli2 dev-routefail true
RHASH3=`lcli2 accept-payment $HTLC_AMOUNT | sed 's/.*"\([0-9a-f]*\)".*/\1/'`
HTLCID3=`lcli1 newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH3 | extract_id`
[ ! -n "$MANUALCOMMIT" ] || lcli1 commit $ID2
[ ! -n "$MANUALCOMMIT" ] || lcli2 commit $ID1
[ ! -n "$MANUALCOMMIT" ] || lcli2 commit $ID1
[ ! -n "$MANUALCOMMIT" ] || lcli1 commit $ID2
# We transferred amount from A to B.
A_AMOUNT=$(($A_AMOUNT - $HTLC_AMOUNT))
B_AMOUNT=$(($B_AMOUNT + $HTLC_AMOUNT))
check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE ""
# Now, failed payment (didn't pay enough)
RHASH4=`lcli2 accept-payment $HTLC_AMOUNT | sed 's/.*"\([0-9a-f]*\)".*/\1/'`
# Shouldn't have this already.
if lcli2 getlog | $FGREP 'Short payment for HTLC'; then exit 1; fi
HTLCID4=`lcli1 newhtlc $ID2 $(($HTLC_AMOUNT - 1)) $EXPIRY $RHASH4 | extract_id`
[ ! -n "$MANUALCOMMIT" ] || lcli1 commit $ID2
[ ! -n "$MANUALCOMMIT" ] || lcli2 commit $ID1
[ ! -n "$MANUALCOMMIT" ] || lcli2 commit $ID1
[ ! -n "$MANUALCOMMIT" ] || lcli1 commit $ID2
check lcli2 "getlog | $FGREP 'Short payment for HTLC'"
check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE ""
if [ ! -n "$MANUALCOMMIT" ]; then
# Test routing to a third node.
P2SHADDR2=`$LCLI2 newaddr | sed -n 's/{ "address" : "\(.*\)" }/\1/p'`
TXID2=`$CLI sendtoaddress $P2SHADDR2 0.01`
TX2=`$CLI getrawtransaction $TXID2`
$CLI generate 1
lcli2 connect localhost $PORT3 $TX2
check_tx_spend lcli2
$CLI generate 3
# Make sure it's STATE_NORMAL.
check_peerstate lcli3 STATE_NORMAL
# More than enough to cover commit fees.
HTLC_AMOUNT=100000000
# Tell node 1 about the 2->3 route.
lcli1 add-route $ID2 $ID3 546000 10 36 36
RHASH5=`lcli3 accept-payment $HTLC_AMOUNT | sed 's/.*"\([0-9a-f]*\)".*/\1/'`
# Try wrong hash.
if lcli1 pay $ID3 $HTLC_AMOUNT $RHASH4; then
echo Paid with wrong hash? >&2
exit 1
fi
# Try underpaying.
if lcli1 pay $ID3 $(($HTLC_AMOUNT-1)) $RHASH5; then
echo Paid with too little? >&2
exit 1
fi
# Pay correctly.
lcli1 pay $ID3 $HTLC_AMOUNT $RHASH5
# Node 3 should end up with that amount (minus 1/2 tx fee)
# Note that it is delayed a little, since node2 fulfils as soon as fulfill
# starts.
check lcli3 "getpeers | $FGREP \"\\\"our_amount\\\" : $(($HTLC_AMOUNT - $NO_HTLCS_FEE / 2))\""
lcli3 close $ID2
fi
lcli1 close $ID2
# They should be negotiating the close.
check_peerstate lcli1 STATE_MUTUAL_CLOSING
check_peerstate lcli2 STATE_MUTUAL_CLOSING
$CLI generate 1
check_peerstate lcli1 STATE_CLOSE_ONCHAIN_MUTUAL
check_peerstate lcli2 STATE_CLOSE_ONCHAIN_MUTUAL
# Give it 99 blocks.
$CLI generate 98
# Make sure they saw it!
check_peerstate lcli1 STATE_CLOSE_ONCHAIN_MUTUAL
check_peerstate lcli2 STATE_CLOSE_ONCHAIN_MUTUAL
# Now the final one.
$CLI generate 1
check_no_peers lcli1
check_no_peers lcli2
lcli1 stop
lcli2 stop
all_ok