diff --git a/daemon/test/Makefile b/daemon/test/Makefile index ccaadce21..58e18bbd2 100644 --- a/daemon/test/Makefile +++ b/daemon/test/Makefile @@ -2,52 +2,58 @@ check: daemon-tests # We run three different bitcoinds, for different types of tests. # Provides limited paralellism. -daemon-test.sh-0-%: - NO_VALGRIND=$(NO_VALGRIND) VARIANT=0 daemon/test/test.sh --$* -daemon-test.sh-1-%: - NO_VALGRIND=$(NO_VALGRIND) VARIANT=1 daemon/test/test.sh --$* -daemon-test.sh-2-%: - NO_VALGRIND=$(NO_VALGRIND) VARIANT=2 daemon/test/test.sh --$* +daemon-test-0-%: + NO_VALGRIND=$(NO_VALGRIND) VARIANT=0 daemon/test/test-$* +daemon-test-1-%: + NO_VALGRIND=$(NO_VALGRIND) VARIANT=1 daemon/test/test-$* +daemon-test-2-%: + NO_VALGRIND=$(NO_VALGRIND) VARIANT=2 daemon/test/test-$* # These don't work in parallel, so chain the deps -daemon-test.sh-0-steal: daemon-test.sh-0-dump-onchain -daemon-test.sh-0-dump-onchain: daemon-test.sh-0-timeout-anchor -daemon-test.sh-0-timeout-anchor: daemon-test.sh-0-different-fee-rates -daemon-test.sh-0-different-fee-rates: daemon-test.sh-0-mutual-close-with-htlcs -daemon-test.sh-0-mutual-close-with-htlcs: daemon-test.sh-0-manual-commit -daemon-test.sh-0-manual-commit: daemon-test.sh-0-normal -daemon-test.sh-0-normal: daemon-test-setup-0 +daemon-test-0-steal: daemon-test-0-unilateral +daemon-test-0-unilateral: daemon-test-0-funding-timeout +daemon-test-0-funding-timeout: daemon-test-0-mutual-close-with-htlcs +daemon-test-0-mutual-close-with-htlcs: daemon-test-0-different-fees +daemon-test-0-different-fees: daemon-test-0-routing +daemon-test-0-routing: daemon-test-0-invoice +daemon-test-0-invoice: daemon-test-0-basic\ manual-commit +daemon-test-0-basic\ manual-commit: daemon-test-0-basic +daemon-test-0-basic: daemon-test-setup-0 -daemon-test.sh-1-steal\ --restart: daemon-test.sh-1-dump-onchain\ --restart -daemon-test.sh-1-dump-onchain\ --restart: daemon-test.sh-1-timeout-anchor\ --restart -daemon-test.sh-1-timeout-anchor\ --restart: daemon-test.sh-1-different-fee-rates\ --restart -daemon-test.sh-1-different-fee-rates\ --restart: daemon-test.sh-1-mutual-close-with-htlcs\ --restart -daemon-test.sh-1-mutual-close-with-htlcs\ --restart: daemon-test.sh-1-manual-commit\ --restart -daemon-test.sh-1-manual-commit\ --restart: daemon-test.sh-1-normal\ --restart -daemon-test.sh-1-normal\ --restart: daemon-test-setup-1 +daemon-test-2-steal\ --reconnect: daemon-test-2-unilateral\ --reconnect +daemon-test-2-unilateral\ --reconnect: daemon-test-2-funding-timeout\ --reconnect +daemon-test-2-funding-timeout\ --reconnect: daemon-test-2-mutual-close-with-htlcs\ --reconnect +daemon-test-2-mutual-close-with-htlcs\ --reconnect: daemon-test-2-different-fees\ --reconnect +daemon-test-2-different-fees\ --reconnect: daemon-test-2-routing\ --reconnect +daemon-test-2-routing\ --reconnect: daemon-test-2-invoice\ --reconnect +daemon-test-2-invoice\ --reconnect: daemon-test-2-basic\ manual-commit\ --reconnect +daemon-test-2-basic\ manual-commit\ --reconnect: daemon-test-2-basic\ --reconnect +daemon-test-2-basic\ --reconnect: daemon-test-setup-2 -daemon-test.sh-2-steal\ --reconnect: daemon-test.sh-2-dump-onchain\ --reconnect -daemon-test.sh-2-dump-onchain\ --reconnect: daemon-test.sh-2-timeout-anchor\ --reconnect -daemon-test.sh-2-timeout-anchor\ --reconnect: daemon-test.sh-2-different-fee-rates\ --reconnect -daemon-test.sh-2-different-fee-rates\ --reconnect: daemon-test.sh-2-mutual-close-with-htlcs\ --reconnect -daemon-test.sh-2-mutual-close-with-htlcs\ --reconnect: daemon-test.sh-2-manual-commit\ --reconnect -daemon-test.sh-2-manual-commit\ --reconnect: daemon-test.sh-2-normal\ --reconnect -daemon-test.sh-2-normal\ --reconnect: daemon-test-setup-2 +daemon-test-1-steal\ --restart: daemon-test-1-unilateral\ --restart +daemon-test-1-unilateral\ --restart: daemon-test-1-funding-timeout\ --restart +daemon-test-1-funding-timeout\ --restart: daemon-test-1-mutual-close-with-htlcs\ --restart +daemon-test-1-mutual-close-with-htlcs\ --restart: daemon-test-1-different-fees\ --restart +daemon-test-1-different-fees\ --restart: daemon-test-1-routing\ --restart +daemon-test-1-routing\ --restart: daemon-test-1-invoice\ --restart +daemon-test-1-invoice\ --restart: daemon-test-1-basic\ manual-commit\ --restart +daemon-test-1-basic\ manual-commit\ --restart: daemon-test-1-basic\ --restart +daemon-test-1-basic\ --restart: daemon-test-setup-1 # We shutdown first in case something is left over. daemon-test-setup-%: daemon-all VARIANT=$* daemon/test/scripts/shutdown.sh 2>/dev/null || true VARIANT=$* daemon/test/scripts/setup.sh -daemon-test-shutdown-0: daemon-test.sh-0-steal +daemon-test-shutdown-0: daemon-test-0-steal VARIANT=0 daemon/test/scripts/shutdown.sh -daemon-test-shutdown-1: daemon-test.sh-1-steal\ --restart +daemon-test-shutdown-1: daemon-test-1-steal\ --restart VARIANT=1 daemon/test/scripts/shutdown.sh -daemon-test-shutdown-2: daemon-test.sh-2-steal\ --reconnect +daemon-test-shutdown-2: daemon-test-2-steal\ --reconnect VARIANT=2 daemon/test/scripts/shutdown.sh # Forms long dependency chains. -daemon-all-test.sh: daemon-test-shutdown-0 daemon-test-shutdown-1 daemon-test-shutdown-2 +daemon-all-test: daemon-test-shutdown-0 daemon-test-shutdown-1 daemon-test-shutdown-2 # Note that these actually #include everything they need, except ccan/ and bitcoin/. # That allows for unit testing of statics, and special effects. @@ -82,5 +88,5 @@ VALGRIND_TEST_ARGS = --track-origins=yes --leak-check=full --show-reachable=yes daemon-unit-tests: $(DAEMON_TEST_PROGRAMS) set -e; for f in $(DAEMON_TEST_PROGRAMS); do $(VALGRIND) $(VALGRIND_TEST_ARGS) $$f; done -daemon-tests: daemon-unit-tests daemon-all-test.sh +daemon-tests: daemon-unit-tests daemon-all-test diff --git a/daemon/test/scripts/helpers.sh b/daemon/test/scripts/helpers.sh index 3061246b0..e108d5db4 100644 --- a/daemon/test/scripts/helpers.sh +++ b/daemon/test/scripts/helpers.sh @@ -148,6 +148,7 @@ start_lightningd() # If bitcoind not already running, start it. if ! $CLI getinfo >/dev/null 2>&1; then + echo Starting bitcoind... scripts/setup.sh SHUTDOWN_BITCOIN=scripts/shutdown.sh else diff --git a/daemon/test/test-basic b/daemon/test/test-basic new file mode 100755 index 000000000..8fa3bbab5 --- /dev/null +++ b/daemon/test/test-basic @@ -0,0 +1,358 @@ +#! /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/helpers.sh + +if [ x"$1" = x"manual-commit" ]; then + MANUALCOMMIT=1 + shift +fi + +parse_cmdline 2 "$@" +setup_lightning 2 + +if [ -n "$MANUALCOMMIT" ]; then + # Aka. never. + echo 'commit-time=1h' >> $DIR1/config + echo 'commit-time=1h' >> $DIR2/config +fi + +start_lightningd 2 + +# Check IDs match logs +[ `$LCLI1 getlog | sed -n 's/.*"ID: \([0-9a-f]*\)".*/\1/p'` = $ID1 ] +[ `$LCLI2 getlog | sed -n 's/.*"ID: \([0-9a-f]*\)".*/\1/p'` = $ID2 ] + +lcli1 connect localhost $PORT2 $FUND_INPUT_TX & + +# Expect them to be waiting for anchor, and ack from other side. +check_peerstate lcli1 STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE +check_peerstate lcli2 STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE + +# Enable reconnect from here. +DO_RECONNECT=$RECONNECT + +# Now make it pass anchor (should be in mempool: one block to bury it) +check_tx_spend +$CLI generate 1 + +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 + +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 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` + +if [ -n "$MANUALCOMMIT" ]; then + # They should register a staged htlc. + check_status $A_AMOUNT $A_FEE "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_HTLC } " $B_AMOUNT $B_FEE "" + + # Now commit it. + lcli1 dev-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 "{ msatoshi : $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 "{ msatoshi : $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 dev-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 "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } " $B_AMOUNT $B_FEE "" + +lcli2 dev-fulfillhtlc $ID1 $HTLCID $SECRET +[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-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 dev-commit $ID2 + +# If we're very slow, manually committed above, and we're restarting, +# we may restart *after* this and thus not see it in the log. +[ "$RECONNECT$MANUALCOMMIT" = restart1 ] || 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 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` +[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 +[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-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 "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } " $B_AMOUNT $B_FEE "" + +lcli2 dev-failhtlc $ID1 $HTLCID 695 +[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 +[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-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 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` +[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 +[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-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 "{ msatoshi : $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 "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : RCVD_REMOVE_HTLC } " $B_AMOUNT $B_FEE "" + + lcli2 dev-commit $ID1 + lcli1 dev-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 "" + +# First, give more money to node2, so it can offer HTLCs. +EXPIRY=$(( $(blockheight) + 10)) +HTLC_AMOUNT=100000000 +HTLCID=`lcli1 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` +[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 +[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 + +check_status $(($A_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE)) $(($A_FEE + $EXTRA_FEE)) "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } " $B_AMOUNT $B_FEE "" + +lcli2 dev-fulfillhtlc $ID1 $HTLCID $SECRET +[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 +[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-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 "" + +# Two failures crossover +SECRET2=1de08917a61cb2b62ed5937d38577f6a7bfe59c176781c6d8128018e8b5ccdfe +RHASH2=`lcli1 dev-rhash $SECRET2 | sed 's/.*"\([0-9a-f]*\)".*/\1/'` + +# This means B will *just* afford it (but can't cover increased fees) +HTLC_AMOUNT=$(($B_AMOUNT - $EXTRA_FEE / 2)) +HTLCID=`lcli2 dev-newhtlc $ID1 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` +# Make sure that's committed, in case lcli1 restarts. +lcli2 dev-commit $ID1 >/dev/null || true + +HTLCID2=`lcli1 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH2 | extract_id` +[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 +[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 + +# A covers the extra part of the fee. +check_status $(($A_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE - $EXTRA_FEE / 2)) $(($A_FEE + $EXTRA_FEE + $EXTRA_FEE / 2)) "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH2 , state : SENT_ADD_ACK_REVOCATION } " 0 $(($B_FEE + $EXTRA_FEE / 2)) "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : RCVD_ADD_ACK_REVOCATION } " + +# Fail both, to reset. +lcli1 dev-failhtlc $ID2 $HTLCID 830 +lcli2 dev-failhtlc $ID1 $HTLCID2 829 + +[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 +[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 +[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 + +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 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` +HTLCID2=`lcli2 dev-newhtlc $ID1 $HTLC_AMOUNT $EXPIRY $RHASH2 | extract_id` +[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 +[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 +[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 + +check_status $(($A_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE)) $(($A_FEE + $EXTRA_FEE)) "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } " $(($B_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE)) $(($B_FEE + $EXTRA_FEE)) "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH2 , state : RCVD_ADD_ACK_REVOCATION } " + +lcli1 dev-fulfillhtlc $ID2 $HTLCID2 $SECRET2 +lcli2 dev-failhtlc $ID1 $HTLCID 849 +[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 +[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 +[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-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. +DO_RECONNECT="" +lcli2 dev-output $ID1 false +HTLCID=`lcli1 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` + +# Make sure node1 sends commit (in the background, since it will block!) +[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-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)) "{ msatoshi : $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)) "{ msatoshi : $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)) "{ msatoshi : $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 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH2 | extract_id` +lcli2 dev-output $ID1 true + +[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 +[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 +[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 + +DO_RECONNECT=$RECONNECT + +# 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 : [ { msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION }, { msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH2 , state : SENT_ADD_ACK_REVOCATION } ], their_htlcs : [ ]" || lcli1 getpeers | tr -s '\012\011" ' ' ' | $FGREP "our_htlcs : [ { msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH2 , state : SENT_ADD_ACK_REVOCATION }, { msatoshi : $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 : [ { msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : RCVD_ADD_ACK_REVOCATION }, { msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH2 , state : RCVD_ADD_ACK_REVOCATION } ]" || lcli2 getpeers | tr -s '\012\011" ' ' ' | $FGREP "our_htlcs : [ ], their_htlcs : [ { msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH2 , state : RCVD_ADD_ACK_REVOCATION }, { msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : RCVD_ADD_ACK_REVOCATION } ]" + +# Just for once, reconnect/restart node 2. +case "$RECONNECT" in + reconnect) + echo RECONNECTING NODE2 + $LCLI2 dev-reconnect $ID1 >/dev/null + sleep 1 + ;; + restart) + echo RESTARTING NODE2 + $LCLI2 -- dev-restart $LIGHTNINGD2 >/dev/null 2>&1 || true + if ! check "$LCLI2 getlog 2>/dev/null | fgrep -q Hello"; then + echo "Node2 dev-restart failed!">&2 + exit 1 + fi + ;; +esac + +if ! check "$LCLI2 getpeers | tr -s '\012\011\" ' ' ' | fgrep -q 'connected : true'"; then + echo "Failed to reconnect!">&2 + exit 1 +fi + +# Node2 collects the HTLCs. +lcli2 dev-fulfillhtlc $ID1 $HTLCID $SECRET +lcli2 dev-fulfillhtlc $ID1 $HTLCID2 $SECRET2 + +[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 +[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-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 "" + +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 forever-1 blocks. +$CLI generate 8 + +# 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 diff --git a/daemon/test/test-different-fees b/daemon/test/test-different-fees new file mode 100755 index 000000000..50f9df7b9 --- /dev/null +++ b/daemon/test/test-different-fees @@ -0,0 +1,85 @@ +#! /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/helpers.sh + +parse_cmdline 2 "$@" +setup_lightning 2 + +# Simply override default fee (estimatefee fails on regtest anyway) +DEFAULT_FEE_RATE2=50000 +# We use 5x fee rate for commits, by defailt. +FEE_RATE2=$(($DEFAULT_FEE_RATE2 * 5)) +echo "default-fee-rate=$DEFAULT_FEE_RATE2" >> $DIR2/config + +start_lightningd 2 + +lcli1 connect localhost $PORT2 $FUND_INPUT_TX & + +# Now make it pass anchor (should be in mempool: one block to bury it) +check_tx_spend +$CLI generate 1 + +DO_RECONNECT=$RECONNECT + +check_peerstate lcli1 STATE_NORMAL +check_peerstate lcli2 STATE_NORMAL + +# 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)) "" + +# This is 100,000 satoshi, so covers fees. +HTLC_AMOUNT=100000000 +RHASH=`lcli2 invoice $HTLC_AMOUNT RHASH3 | sed 's/.*"\([0-9a-f]*\)".*/\1/'` +ROUTE=`lcli1 getroute $ID2 $HTLC_AMOUNT 1` +ROUTE=`echo $ROUTE | sed 's/^{ "route" : \(.*\) }$/\1/'` +lcli1 sendpay "$ROUTE" $RHASH + +# They should not split fees. +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)) "" + + # FIXME: reactivate feechanges! + # # Change fee rate on node2 to same as node1. + # lcli2 dev-feerate 40000 + # $CLI generate 1 + # [ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 + # [ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 + + # check_status $(($AMOUNT - $HTLC_AMOUNT - $NO_HTLCS_FEE / 2)) $(($NO_HTLCS_FEE / 2)) "" $(($HTLC_AMOUNT - $NO_HTLCS_FEE / 2)) $(($NO_HTLCS_FEE / 2)) "" + + # # Change back. + # lcli2 dev-feerate 50000 + # $CLI generate 1 + # [ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 + # [ ! -n "$MANUALCOMMIT" ] || lcli1 dev-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 +check_tx_spend + +# Give it 10 blocks ie "forever" +$CLI generate 10 +check_no_peers lcli1 +check_no_peers lcli2 + +lcli1 stop +lcli2 stop + +all_ok diff --git a/daemon/test/test-funding-timeout b/daemon/test/test-funding-timeout new file mode 100755 index 000000000..ee8c5b3fc --- /dev/null +++ b/daemon/test/test-funding-timeout @@ -0,0 +1,81 @@ +#! /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/helpers.sh + +parse_cmdline 2 "$@" +setup_lightning 2 +start_lightningd 2 + +# Prevent anchor broadcast +lcli1 dev-broadcast false +lcli1 connect localhost $PORT2 $FUND_INPUT_TX & + +# Expect them to be waiting for anchor, and ack from other side. +check_peerstate lcli1 STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE +check_peerstate lcli2 STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE + +# Enable reconnect from here. +DO_RECONNECT=$RECONNECT + +$CLI generate 99 + +# Still waiting. +check_peerstate lcli1 STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE +check_peerstate lcli2 STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE + +# Make sure whichever times out first doesn't tell the other. +lcli1 dev-output $ID2 false +lcli2 dev-output $ID1 false +$CLI generate 1 + +# Node1 should have gone into STATE_ERR_ANCHOR_TIMEOUT. +check "lcli1 getlog debug | $FGREP STATE_ERR_ANCHOR_TIMEOUT" + +# Don't try to reconnect any more if we are. +if [ x"$RECONNECT" = xreconnect ]; then DO_RECONNECT=""; fi + +# If we're restarting, don't expect peer. +NO_PEER2=1 + +# Now let them send errors if they're still trying. +lcli2 dev-output $ID1 true || true +lcli1 dev-output $ID2 true || true + +# Peer 2 should give up, and have forgotten all about it. +check "lcli2 getlog debug | $FGREP STATE_CLOSED" +check_no_peers lcli2 + +# Node1 should be disconnected. +check_peerconnected lcli1 false + +# Now let node1 broadcast anchor and unilateral close belatedly! +lcli1 dev-broadcast true + +# Now mine that transaction so they see it. +$CLI generate 1 +check_peerstate lcli1 STATE_CLOSE_ONCHAIN_OUR_UNILATERAL + +# Now move bitcoind 1 day, which is what node2 asked for on commit. +# Get current time from last block (works if we run this twice). +CURTIME=$($CLI getblock $($CLI getblockhash $(($BLOCKHEIGHT + 100))) | sed -n 's/ "time": \([0-9]*\),/\1/p') +$CLI setmocktime $(($CURTIME + 24 * 60 * 60)) + +# Move average so CSV moves. +$CLI generate 6 + +# Now it should have spent the commit tx. +check_tx_spend + +# 100 blocks pass +$CLI generate 100 + +# Considers it all done now. +check_no_peers lcli1 + +lcli1 stop +lcli2 stop +all_ok diff --git a/daemon/test/test-invoice b/daemon/test/test-invoice new file mode 100755 index 000000000..06e57a9e2 --- /dev/null +++ b/daemon/test/test-invoice @@ -0,0 +1,86 @@ +#! /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/helpers.sh + +parse_cmdline 2 "$@" +setup_lightning 2 +start_lightningd 2 + +lcli1 connect localhost $PORT2 $FUND_INPUT_TX & + +# Now make it pass anchor (should be in mempool: one block to bury it) +check_tx_spend +$CLI generate 1 + +DO_RECONNECT=$RECONNECT + +check_peerstate lcli1 STATE_NORMAL +check_peerstate lcli2 STATE_NORMAL + +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 "" + +# 100k satoshi should cover fees. +HTLC_AMOUNT=100000000 +EXPIRY=$(( $(blockheight) + 10)) +RHASH3=`lcli2 invoice $HTLC_AMOUNT RHASH3 | sed 's/.*"\([0-9a-f]*\)".*/\1/'` + +lcli2 listinvoice +[ "`lcli2 listinvoice | tr -s '\012\011\" ' ' '`" = "[ { label : RHASH3 , rhash : $RHASH3 , msatoshi : $HTLC_AMOUNT, complete : false } ] " ] + +HTLCID3=`lcli1 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH3 | extract_id` + +# We transferred amount from A to B, but fee now split evenly. +A_AMOUNT=$(($A_AMOUNT - $HTLC_AMOUNT + $NO_HTLCS_FEE / 2)) +B_AMOUNT=$(($B_AMOUNT + $HTLC_AMOUNT - $NO_HTLCS_FEE / 2)) +A_FEE=$(($NO_HTLCS_FEE / 2)) +B_FEE=$(($NO_HTLCS_FEE / 2)) +check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE "" + +[ "`lcli2 listinvoice | tr -s '\012\011\" ' ' '`" = "[ { label : RHASH3 , rhash : $RHASH3 , msatoshi : $HTLC_AMOUNT, complete : true } ] " ] + +# Now, failed payment (didn't pay enough) +RHASH4=`lcli2 invoice $HTLC_AMOUNT RHASH4 | sed 's/.*"\([0-9a-f]*\)".*/\1/'` + +# Shouldn't have this already. +if lcli2 getlog | $FGREP 'Short payment for'; then exit 1; fi + +# Test listinvoice with both, or subset (either order possible!) +INVOICES=`lcli2 listinvoice | tr -s '\012\011\" ' ' '` +[ "$INVOICES" = "[ { label : RHASH3 , rhash : $RHASH3 , msatoshi : $HTLC_AMOUNT, complete : true }, { label : RHASH4 , rhash : $RHASH4 , msatoshi : $HTLC_AMOUNT, complete : false } ] " ] || [ "$INVOICES" = "[ { label : RHASH4 , rhash : $RHASH4 , msatoshi : $HTLC_AMOUNT, complete : false }, { label : RHASH3 , rhash : $RHASH3 , msatoshi : $HTLC_AMOUNT, complete : true } ] " ] +[ "`lcli2 listinvoice RHASH3 | tr -s '\012\011\" ' ' '`" = "[ { label : RHASH3 , rhash : $RHASH3 , msatoshi : $HTLC_AMOUNT, complete : true } ] " ] +[ "`lcli2 listinvoice RHASH4 | tr -s '\012\011\" ' ' '`" = "[ { label : RHASH4 , rhash : $RHASH4 , msatoshi : $HTLC_AMOUNT, complete : false } ] " ] + +HTLCID4=`lcli1 dev-newhtlc $ID2 $(($HTLC_AMOUNT - 1)) $EXPIRY $RHASH4 | extract_id` + +check lcli2 "getlog | $FGREP 'Short payment for'" +check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE "" + +lcli2 delinvoice RHASH4 +if lcli2 delinvoice RHASH3 >/dev/null; then + echo "Should not be able to delete completed invoice!" >&2 + exit 1 +fi + +lcli1 close $ID2 + +# They should be negotiate the close. +check_tx_spend + +# Bury it in "forever" blocks. +$CLI generate 10 + +check_no_peers lcli1 +check_no_peers lcli2 + +lcli1 stop +lcli2 stop + +all_ok diff --git a/daemon/test/test-mutual-close-with-htlcs b/daemon/test/test-mutual-close-with-htlcs new file mode 100755 index 000000000..0fc1a3141 --- /dev/null +++ b/daemon/test/test-mutual-close-with-htlcs @@ -0,0 +1,95 @@ +#! /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/helpers.sh + +parse_cmdline 2 "$@" +setup_lightning 2 +start_lightningd 2 + +lcli1 connect localhost $PORT2 $FUND_INPUT_TX & + +# Now make it pass anchor (should be in mempool: one block to bury it) +check_tx_spend +$CLI generate 1 + +DO_RECONNECT=$RECONNECT + +check_peerstate lcli1 STATE_NORMAL +check_peerstate lcli2 STATE_NORMAL + +A_AMOUNT=$(($AMOUNT - $NO_HTLCS_FEE)) +A_FEE=$NO_HTLCS_FEE +B_AMOUNT=0 +B_FEE=0 + +# Send funds to 2 so it can offer HTLCS +HTLC_AMOUNT=100000000 +RHASH=`lcli2 invoice $HTLC_AMOUNT RHASH3 | sed 's/.*"\([0-9a-f]*\)".*/\1/'` +ROUTE=`lcli1 getroute $ID2 $HTLC_AMOUNT 1` +ROUTE=`echo $ROUTE | sed 's/^{ "route" : \(.*\) }$/\1/'` +lcli1 sendpay "$ROUTE" $RHASH + +# They pay half fees each. +A_AMOUNT=$(($A_AMOUNT - $HTLC_AMOUNT + $NO_HTLCS_FEE / 2)) +A_FEE=$(($NO_HTLCS_FEE / 2)) +B_AMOUNT=$(($B_AMOUNT + $HTLC_AMOUNT - $NO_HTLCS_FEE / 2)) +B_FEE=$(($NO_HTLCS_FEE / 2)) +check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE "" + +# For next step, make sure neither node fails HTLCs we're about to set up. +lcli1 dev-routefail false +lcli2 dev-routefail false + +# Set up HTLCs both ways. + +# 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/'` + +HTLCID1=`lcli1 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` + +# FIXME: Test with dust htlc, too. +HTLCID2=`lcli2 dev-newhtlc $ID1 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` + +check_status $(($A_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE)) $(($A_FEE + $EXTRA_FEE)) "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } " $(($B_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE)) $(($B_FEE + $EXTRA_FEE)) "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : RCVD_ADD_ACK_REVOCATION } " + +# Now begin close +lcli1 close $ID2 + +# They should be waiting for it to clear up. +check_peerstate lcli1 STATE_SHUTDOWN +check_peerstate lcli2 STATE_SHUTDOWN + +# Fail one, still waiting. +lcli2 dev-failhtlc $ID1 $HTLCID1 800 +check_peerstate lcli1 STATE_SHUTDOWN +check_peerstate lcli2 STATE_SHUTDOWN + +# Fulfill the other causes them to actually complete the close. +lcli1 dev-fulfillhtlc $ID2 $HTLCID2 $SECRET +check_peerstate lcli1 STATE_MUTUAL_CLOSING +check_peerstate lcli2 STATE_MUTUAL_CLOSING + +check_tx_spend +$CLI generate 1 + +check_peerstate lcli1 STATE_CLOSE_ONCHAIN_MUTUAL +check_peerstate lcli2 STATE_CLOSE_ONCHAIN_MUTUAL + +# Give it "forever" blocks. +$CLI generate 9 + +check_no_peers lcli1 +check_no_peers lcli2 + +lcli1 stop +lcli2 stop + +all_ok diff --git a/daemon/test/test-routing b/daemon/test/test-routing new file mode 100755 index 000000000..17e32d05b --- /dev/null +++ b/daemon/test/test-routing @@ -0,0 +1,143 @@ +#! /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/helpers.sh + +parse_cmdline 3 "$@" +setup_lightning 3 +start_lightningd 3 + +# We connect 1->2->3 +lcli1 connect localhost $PORT2 $FUND_INPUT_TX & +check_tx_spend +$CLI generate 1 + +P2SHADDR2=`$LCLI2 newaddr | sed -n 's/{ "address" : "\(.*\)" }/\1/p'` +TXID2=`$CLI sendtoaddress $P2SHADDR2 0.01` +FUND_INPUT_TX2=`$CLI getrawtransaction $TXID2` +$CLI generate 1 + +lcli2 connect localhost $PORT3 $FUND_INPUT_TX2 & +check_tx_spend +$CLI generate 1 + +DO_RECONNECT=$RECONNECT + +# Make sure all in STATE_NORMAL. +check_peerstate lcli1 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. +# Add to config in case we are restaring. +echo "add-route=$ID2/$ID3/546000/10/36/36" >> $DIR1/config +lcli1 dev-add-route $ID2 $ID3 546000 10 36 36 +RHASH=`lcli3 invoice $HTLC_AMOUNT RHASH | sed 's/.*"\([0-9a-f]*\)".*/\1/'` +BAD_RHASH=`echo $RHASH | tr '0-9a-f' 'a-f0-9'` + +# Get route. +ROUTE=`lcli1 getroute $ID3 $HTLC_AMOUNT 1` +ROUTE=`echo $ROUTE | sed 's/^{ "route" : \(.*\) }$/\1/'` + +# Try wrong hash. +if lcli1 sendpay "$ROUTE" $BAD_RHASH; then + echo Paid with wrong hash? >&2 + exit 1 +fi + +# Try underpaying. +PAID=`echo "$ROUTE" | sed -n 's/.*"msatoshi" : \([0-9]*\),.*/\1/p'` +UNDERPAY=`echo "$ROUTE" | sed "s/: $PAID,/: $(($PAID - 1)),/"` +if lcli1 sendpay "$UNDERPAY" $RHASH; then + echo Paid with too little? >&2 + exit 1 +fi + +# If restarting, make sure node3 remembers incoming payment. +if [ "$RECONNECT" = restart ]; then + $LCLI3 -- dev-restart $LIGHTNINGD3 >/dev/null 2>&1 || true + if ! check "$LCLI3 getpeers 2>/dev/null | tr -s '\012\011\" ' ' ' | fgrep -q 'connected : true'"; then + echo "Failed to reconnect!">&2 + exit 1 + fi +fi + +[ "`lcli3 listinvoice RHASH | tr -s '\012\011\" ' ' '`" = "[ { label : RHASH , rhash : $RHASH , msatoshi : $HTLC_AMOUNT, complete : false } ] " ] +# Pay correctly. +lcli1 sendpay "$ROUTE" $RHASH + +# 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))\"" + +# If restarting, make sure node3 remembers completed payment. +if [ "$RECONNECT" = restart ]; then + echo RESTARTING NODE3 + $LCLI3 -- dev-restart $LIGHTNINGD3 >/dev/null 2>&1 || true + if ! check "$LCLI3 getpeers 2>/dev/null | tr -s '\012\011\" ' ' ' | fgrep -q 'connected : true'"; then + echo "Failed to reconnect!">&2 + exit 1 + fi +fi + +[ "`lcli3 listinvoice RHASH | tr -s '\012\011\" ' ' '`" = "[ { label : RHASH , rhash : $RHASH , msatoshi : $HTLC_AMOUNT, complete : true } ] " ] + +[ "`lcli3 waitinvoice | tr -s '\012\011\" ' ' '`" = "{ label : RHASH , rhash : $RHASH , msatoshi : $HTLC_AMOUNT } " ] + +# Can't pay twice (try from node2) +ROUTE2=`lcli2 getroute $ID3 $HTLC_AMOUNT 1` +ROUTE2=`echo $ROUTE2 | sed 's/^{ "route" : \(.*\) }$/\1/'` +if lcli2 sendpay "$ROUTE2" $RHASH; then + echo "Paying twice worked?" >&2 + exit 1 +fi + +lcli3 close $ID2 +check_peerstate lcli3 STATE_MUTUAL_CLOSING + +# Re-send should be a noop (doesn't matter that node3 is down!) +lcli1 sendpay "$ROUTE" $RHASH + +# Re-send to different id or amount should complain. +SHORTROUTE=`echo "$ROUTE" | sed 's/, { "id" : .* }//' | sed 's/"msatoshi" : [0-9]*,/"msatoshi" : '$HTLC_AMOUNT,/` +lcli1 sendpay "$SHORTROUTE" $RHASH | $FGREP "already succeeded to $ID3" +lcli1 sendpay "$UNDERPAY" $RHASH | $FGREP "already succeeded with amount $HTLC_AMOUNT" + +# Now node2 should fail to route. +if lcli1 sendpay "$ROUTE" $BAD_RHASH | $FGREP "failed: error code 404 node $ID2 reason Unknown peer"; then : ; +else + echo "Pay to node3 didn't give 404" >&2 + exit 1 +fi + +# Now node1 should fail to route (route deleted) +if lcli1 getroute $ID3 $HTLC_AMOUNT 1 | $FGREP "no route found"; then : ; +else + echo "Pay to node3 didn't fail instantly second time" >&2 + exit 1 +fi + +lcli1 close $ID2 +check_peerstate lcli1 STATE_MUTUAL_CLOSING + +# Make sure both txs broadcast. +check '[ `$CLI getrawmempool | egrep -c "[a-f0-9]{32}"` = 2 ]' + +# Bury them in "forever" blocks. +$CLI generate 10 + +check_no_peers lcli1 +check_no_peers lcli2 +check_no_peers lcli3 + +lcli1 stop +lcli2 stop +lcli3 stop + +all_ok diff --git a/daemon/test/test-steal b/daemon/test/test-steal new file mode 100755 index 000000000..e5deee5d9 --- /dev/null +++ b/daemon/test/test-steal @@ -0,0 +1,90 @@ +#! /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/helpers.sh + +parse_cmdline 2 "$@" +setup_lightning 2 +start_lightningd 2 + +lcli1 connect localhost $PORT2 $FUND_INPUT_TX & + +# Now make it pass anchor (should be in mempool: one block to bury it) +check_tx_spend +$CLI generate 1 + +DO_RECONNECT=$RECONNECT + +check_peerstate lcli1 STATE_NORMAL +check_peerstate lcli2 STATE_NORMAL + +A_AMOUNT=$(($AMOUNT - $NO_HTLCS_FEE)) +A_FEE=$NO_HTLCS_FEE +B_AMOUNT=0 +B_FEE=0 + +# Send funds to 2 so it can offer HTLCS +HTLC_AMOUNT=100000000 +RHASH=`lcli2 invoice $HTLC_AMOUNT RHASH3 | sed 's/.*"\([0-9a-f]*\)".*/\1/'` +ROUTE=`lcli1 getroute $ID2 $HTLC_AMOUNT 1` +ROUTE=`echo $ROUTE | sed 's/^{ "route" : \(.*\) }$/\1/'` +lcli1 sendpay "$ROUTE" $RHASH + +# They pay half fees each noe. +A_AMOUNT=$(($A_AMOUNT - $HTLC_AMOUNT + $NO_HTLCS_FEE / 2)) +A_FEE=$(($NO_HTLCS_FEE / 2)) +B_AMOUNT=$(($B_AMOUNT + $HTLC_AMOUNT - $NO_HTLCS_FEE / 2)) +B_FEE=$(($NO_HTLCS_FEE / 2)) +check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE "" + +# For next step, make sure neither node fails HTLCs we're about to set up. +lcli1 dev-routefail false +lcli2 dev-routefail false + +# Set up HTLCs both ways. + +# 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/'` + +HTLCID1=`lcli1 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` + +# FIXME: Test with dust htlc, too. +HTLCID2=`lcli2 dev-newhtlc $ID1 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` + +check_status $(($A_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE)) $(($A_FEE + $EXTRA_FEE)) "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } " $(($B_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE)) $(($B_FEE + $EXTRA_FEE)) "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : RCVD_ADD_ACK_REVOCATION } " + +# This is the tx we're going to try to spend. +STEAL_TX=`$LCLI1 dev-signcommit $ID2 | cut -d\" -f4` + +# Fail one, succeed 2->1 payment +lcli2 dev-failhtlc $ID1 $HTLCID1 800 +lcli1 dev-fulfillhtlc $ID2 $HTLCID2 $SECRET + +A_AMOUNT=$(($A_AMOUNT + $HTLC_AMOUNT)) +B_AMOUNT=$(($B_AMOUNT - $HTLC_AMOUNT)) +check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE "" + +# 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 + +# Give it "forever" blocks. +$CLI generate 10 + +check_no_peers lcli2 + +lcli1 stop +lcli2 stop +all_ok diff --git a/daemon/test/test-unilateral b/daemon/test/test-unilateral new file mode 100755 index 000000000..4f8006a58 --- /dev/null +++ b/daemon/test/test-unilateral @@ -0,0 +1,86 @@ +#! /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/helpers.sh + +parse_cmdline 2 "$@" +setup_lightning 2 +start_lightningd 2 + +lcli1 connect localhost $PORT2 $FUND_INPUT_TX & + +# Now make it pass anchor (should be in mempool: one block to bury it) +check_tx_spend +$CLI generate 1 + +DO_RECONNECT=$RECONNECT + +check_peerstate lcli1 STATE_NORMAL +check_peerstate lcli2 STATE_NORMAL + +# Make sure node2 doesn't fail +lcli2 dev-routefail false + +A_AMOUNT=$(($AMOUNT - $NO_HTLCS_FEE)) +A_FEE=$NO_HTLCS_FEE +B_AMOUNT=0 +B_FEE=0 + +# 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 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` + +A_AMOUNT=$(($A_AMOUNT - $EXTRA_FEE - $HTLC_AMOUNT)) +A_FEE=$(($A_FEE + $EXTRA_FEE)) +B_AMOUNT=0 +B_FEE=0 + +# Wait for both to committed. +check_status $A_AMOUNT $A_FEE "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } " $B_AMOUNT $B_FEE "" + +# 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 + +# 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 "{ msatoshi : $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 +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 + +# Now, after "forever" blocks, should all be concluded. +$CLI generate 10 + +# Both consider it all done now. +check_no_peers lcli1 + +lcli1 stop +all_ok diff --git a/daemon/test/test.sh b/daemon/test/test.sh deleted file mode 100755 index 99b040955..000000000 --- a/daemon/test/test.sh +++ /dev/null @@ -1,791 +0,0 @@ -#! /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/helpers.sh - -# Bash variables for in-depth debugging. -#set -vx -#export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }' - -STYLE=${1:-normal} -shift - -parse_cmdline 3 "$@" -case x"$STYLE" in - 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") - ;; - *) - echo Unknown arg "$STYLE" >&2 - exit 1 - ;; -esac - -setup_lightning 3 - -if [ -n "$DIFFERENT_FEES" ]; then - # Simply override default fee (estimatefee fails on regtest anyway) - DEFAULT_FEE_RATE2=50000 - # We use 5x fee rate for commits, by defailt. - FEE_RATE2=$(($DEFAULT_FEE_RATE2 * 5)) - echo "default-fee-rate=$DEFAULT_FEE_RATE2" >> $DIR2/config -fi - -if [ -n "$MANUALCOMMIT" ]; then - # Aka. never. - echo 'commit-time=1h' >> $DIR1/config - echo 'commit-time=1h' >> $DIR2/config - echo 'commit-time=1h' >> $DIR3/config -fi - -start_lightningd 3 - -# Check IDs match logs -[ `$LCLI1 getlog | sed -n 's/.*"ID: \([0-9a-f]*\)".*/\1/p'` = $ID1 ] -[ `$LCLI2 getlog | sed -n 's/.*"ID: \([0-9a-f]*\)".*/\1/p'` = $ID2 ] -[ $NUM_LIGHTNINGD = 2 ] || [ `$LCLI3 getlog | sed -n 's/.*"ID: \([0-9a-f]*\)".*/\1/p'` = $ID3 ] - -# Make sure they see it (for timeout we need to know what height they were) -BLOCKHEIGHT=`$CLI getblockcount` -check '[ `get_info_field "$LCLI1" blockheight` = $BLOCKHEIGHT ]' -check '[ `get_info_field "$LCLI2" blockheight` = $BLOCKHEIGHT ]' - -# Prevent anchor broadcast if we want to test timeout. -if [ -n "$TIMEOUT_ANCHOR" ]; then - lcli1 dev-broadcast false -fi -lcli1 connect localhost $PORT2 $FUND_INPUT_TX & - -# Expect them to be waiting for anchor, and ack from other side. -check_peerstate lcli1 STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE -check_peerstate lcli2 STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE - -DO_RECONNECT=$RECONNECT - -if [ -n "$TIMEOUT_ANCHOR" ]; then - # Blocks before anchor committed (100 to hit chain, 1 to reach depth) - $CLI generate 100 - - # Still waiting. - check_peerstate lcli1 STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE - check_peerstate lcli2 STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE - - # Make sure whichever times out first doesn't tell the other. - lcli1 dev-output $ID2 false - lcli2 dev-output $ID1 false - $CLI generate 1 - - # Node1 should have gone into STATE_ERR_ANCHOR_TIMEOUT. - check "lcli1 getlog debug | $FGREP STATE_ERR_ANCHOR_TIMEOUT" - - # Don't try to reconnect any more if we are. - if [ x"$RECONNECT" = xreconnect ]; then DO_RECONNECT=""; fi - NO_PEER2=1 - - # Now let them send errors if they're still trying. - lcli2 dev-output $ID1 true || true - lcli1 dev-output $ID2 true || true - - # Peer 2 should give up, and have forgotten all about it. - check "lcli2 getlog debug | $FGREP STATE_CLOSED" - check_no_peers lcli2 - - # Node1 should be disconnected. - check_peerconnected lcli1 false - - # Now let node1 broadcast anchor and unilateral close belatedly! - lcli1 dev-broadcast true - - # Now mine that transaction so they see it. - $CLI generate 1 - - check_peerstate lcli1 STATE_CLOSE_ONCHAIN_OUR_UNILATERAL - - # Now move bitcoind 1 day, which is what node2 asked for on commit. - # Get current time from last block (works if we run this twice). - CURTIME=$($CLI getblock $($CLI getblockhash $(($BLOCKHEIGHT + 100))) | sed -n 's/ "time": \([0-9]*\),/\1/p') - $CLI setmocktime $(($CURTIME + 24 * 60 * 60)) - - # Move average so CSV moves. - $CLI generate 6 - - # Now it should have spent the commit tx. - check_tx_spend - - # 100 blocks pass - $CLI generate 100 - - # 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: one block to bury it) -check_tx_spend -$CLI generate 1 - -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 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` - [ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 - [ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 - check_status_single lcli2 0 0 "" $(($AMOUNT - $HTLC_AMOUNT - $ONE_HTLCS_FEE2)) $(($ONE_HTLCS_FEE2)) "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : RCVD_ADD_ACK_REVOCATION } " - lcli2 dev-fulfillhtlc $ID1 $HTLCID $SECRET - [ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 - [ ! -n "$MANUALCOMMIT" ] || lcli1 dev-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)) "" - - # FIXME: reactivate feechanges! - # # Change fee rate on node2 to same as node1. - # lcli2 dev-feerate 40000 - # $CLI generate 1 - # [ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 - # [ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 - - # check_status $(($AMOUNT - $HTLC_AMOUNT - $NO_HTLCS_FEE / 2)) $(($NO_HTLCS_FEE / 2)) "" $(($HTLC_AMOUNT - $NO_HTLCS_FEE / 2)) $(($NO_HTLCS_FEE / 2)) "" - - # # Change back. - # lcli2 dev-feerate 50000 - # $CLI generate 1 - # [ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 - # [ ! -n "$MANUALCOMMIT" ] || lcli1 dev-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 10 blocks ie "forever" - $CLI generate 10 - 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 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` - -if [ -n "$MANUALCOMMIT" ]; then - # They should register a staged htlc. - check_status $A_AMOUNT $A_FEE "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_HTLC } " $B_AMOUNT $B_FEE "" - - # Now commit it. - lcli1 dev-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 "{ msatoshi : $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 "{ msatoshi : $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 dev-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 "{ msatoshi : $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 - - # 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 "{ msatoshi : $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 - 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 - - # Now, after 10 blocks, should all be concluded. - $CLI generate 10 - - # Both consider it all done now. - check_no_peers lcli1 - - lcli1 stop - all_ok -fi - -lcli2 dev-fulfillhtlc $ID1 $HTLCID $SECRET -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-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 dev-commit $ID2 - -# If we're very slow, manually committed above, and we're restarting, -# we may restart *after* this and thus not see it in the log. -[ "$RECONNECT$MANUALCOMMIT" = restart1 ] || 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 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-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 "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } " $B_AMOUNT $B_FEE "" - -lcli2 dev-failhtlc $ID1 $HTLCID 695 -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-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 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-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 "{ msatoshi : $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 "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : RCVD_REMOVE_HTLC } " $B_AMOUNT $B_FEE "" - - lcli2 dev-commit $ID1 - lcli1 dev-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 - - # Give it "forever" blocks. - $CLI generate 10 - - 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 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 - -check_status $(($A_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE)) $(($A_FEE + $EXTRA_FEE)) "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } " $B_AMOUNT $B_FEE "" - -lcli2 dev-fulfillhtlc $ID1 $HTLCID $SECRET -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-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 "" - -# Two failures crossover -SECRET2=1de08917a61cb2b62ed5937d38577f6a7bfe59c176781c6d8128018e8b5ccdfe -RHASH2=`lcli1 dev-rhash $SECRET2 | sed 's/.*"\([0-9a-f]*\)".*/\1/'` - -# This means B will *just* afford it (but can't cover increased fees) -HTLC_AMOUNT=$(($B_AMOUNT - $EXTRA_FEE / 2)) -HTLCID=`lcli2 dev-newhtlc $ID1 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` -# Make sure that's committed, in case lcli1 restarts. -lcli2 dev-commit $ID1 >/dev/null || true - -HTLCID2=`lcli1 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH2 | extract_id` -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 - -# A covers the extra part of the fee. -check_status $(($A_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE - $EXTRA_FEE / 2)) $(($A_FEE + $EXTRA_FEE + $EXTRA_FEE / 2)) "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH2 , state : SENT_ADD_ACK_REVOCATION } " 0 $(($B_FEE + $EXTRA_FEE / 2)) "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : RCVD_ADD_ACK_REVOCATION } " - -# Fail both, to reset. -lcli1 dev-failhtlc $ID2 $HTLCID 830 -lcli2 dev-failhtlc $ID1 $HTLCID2 829 - -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 - -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 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` -HTLCID2=`lcli2 dev-newhtlc $ID1 $HTLC_AMOUNT $EXPIRY $RHASH2 | extract_id` -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 - -check_status $(($A_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE)) $(($A_FEE + $EXTRA_FEE)) "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } " $(($B_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE)) $(($B_FEE + $EXTRA_FEE)) "{ msatoshi : $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_SHUTDOWN - check_peerstate lcli2 STATE_SHUTDOWN - - # Fail one, still waiting. - lcli2 dev-failhtlc $ID1 $HTLCID 800 - check_peerstate lcli1 STATE_SHUTDOWN - check_peerstate lcli2 STATE_SHUTDOWN - - # Fulfill the other causes them to actually complete the close. - lcli1 dev-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 "forever" blocks. - $CLI generate 9 - - check_no_peers lcli1 - check_no_peers lcli2 - - lcli1 stop - lcli2 stop - - all_ok -fi - -lcli1 dev-fulfillhtlc $ID2 $HTLCID2 $SECRET2 -lcli2 dev-failhtlc $ID1 $HTLCID 849 -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-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. -DO_RECONNECT="" -lcli2 dev-output $ID1 false -HTLCID=`lcli1 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` - -# Make sure node1 sends commit (in the background, since it will block!) -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-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)) "{ msatoshi : $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)) "{ msatoshi : $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)) "{ msatoshi : $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 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH2 | extract_id` -lcli2 dev-output $ID1 true - -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 - -DO_RECONNECT=$RECONNECT - -# 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 : [ { msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION }, { msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH2 , state : SENT_ADD_ACK_REVOCATION } ], their_htlcs : [ ]" || lcli1 getpeers | tr -s '\012\011" ' ' ' | $FGREP "our_htlcs : [ { msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH2 , state : SENT_ADD_ACK_REVOCATION }, { msatoshi : $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 : [ { msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : RCVD_ADD_ACK_REVOCATION }, { msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH2 , state : RCVD_ADD_ACK_REVOCATION } ]" || lcli2 getpeers | tr -s '\012\011" ' ' ' | $FGREP "our_htlcs : [ ], their_htlcs : [ { msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH2 , state : RCVD_ADD_ACK_REVOCATION }, { msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : RCVD_ADD_ACK_REVOCATION } ]" - -# Just for once, reconnect/restart node 2. -case "$RECONNECT" in - reconnect) - echo RECONNECTING NODE2 - $LCLI2 dev-reconnect $ID1 >/dev/null - sleep 1 - ;; - restart) - echo RESTARTING NODE2 - $LCLI2 -- dev-restart $LIGHTNINGD2 >/dev/null 2>&1 || true - if ! check "$LCLI2 getlog 2>/dev/null | fgrep -q Hello"; then - echo "Node2 dev-restart failed!">&2 - exit 1 - fi - ;; -esac - -if ! check "$LCLI2 getpeers | tr -s '\012\011\" ' ' ' | fgrep -q 'connected : true'"; then - echo "Failed to reconnect!">&2 - exit 1 -fi - -# Node2 collects the HTLCs. -lcli2 dev-fulfillhtlc $ID1 $HTLCID $SECRET -lcli2 dev-fulfillhtlc $ID1 $HTLCID2 $SECRET2 - -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-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 invoice $HTLC_AMOUNT RHASH3 | sed 's/.*"\([0-9a-f]*\)".*/\1/'` - -lcli2 listinvoice -[ "`lcli2 listinvoice | tr -s '\012\011\" ' ' '`" = "[ { label : RHASH3 , rhash : $RHASH3 , msatoshi : $HTLC_AMOUNT, complete : false } ] " ] - -HTLCID3=`lcli1 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH3 | extract_id` -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 - -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-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 "" - -[ "`lcli2 listinvoice | tr -s '\012\011\" ' ' '`" = "[ { label : RHASH3 , rhash : $RHASH3 , msatoshi : $HTLC_AMOUNT, complete : true } ] " ] - -# Now, failed payment (didn't pay enough) -RHASH4=`lcli2 invoice $HTLC_AMOUNT RHASH4 | sed 's/.*"\([0-9a-f]*\)".*/\1/'` - -# Shouldn't have this already. -if lcli2 getlog | $FGREP 'Short payment for'; then exit 1; fi - -# Test listinvoice with both, or subset (either order possible!) -INVOICES=`lcli2 listinvoice | tr -s '\012\011\" ' ' '` -[ "$INVOICES" = "[ { label : RHASH3 , rhash : $RHASH3 , msatoshi : $HTLC_AMOUNT, complete : true }, { label : RHASH4 , rhash : $RHASH4 , msatoshi : $HTLC_AMOUNT, complete : false } ] " ] || [ "$INVOICES" = "[ { label : RHASH4 , rhash : $RHASH4 , msatoshi : $HTLC_AMOUNT, complete : false }, { label : RHASH3 , rhash : $RHASH3 , msatoshi : $HTLC_AMOUNT, complete : true } ] " ] -[ "`lcli2 listinvoice RHASH3 | tr -s '\012\011\" ' ' '`" = "[ { label : RHASH3 , rhash : $RHASH3 , msatoshi : $HTLC_AMOUNT, complete : true } ] " ] -[ "`lcli2 listinvoice RHASH4 | tr -s '\012\011\" ' ' '`" = "[ { label : RHASH4 , rhash : $RHASH4 , msatoshi : $HTLC_AMOUNT, complete : false } ] " ] - -HTLCID4=`lcli1 dev-newhtlc $ID2 $(($HTLC_AMOUNT - 1)) $EXPIRY $RHASH4 | extract_id` -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 - -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 - -check lcli2 "getlog | $FGREP 'Short payment for'" -check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE "" - -lcli2 delinvoice RHASH4 -if lcli2 delinvoice RHASH3 >/dev/null; then - echo "Should not be able to delete completed invoice!" >&2 - exit 1 -fi - -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 - $CLI generate 1 - - # 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. - # Add to config in case we are restaring. - echo "add-route=$ID2/$ID3/546000/10/36/36" >> $DIR1/config - lcli1 dev-add-route $ID2 $ID3 546000 10 36 36 - RHASH5=`lcli3 invoice $HTLC_AMOUNT RHASH5 | sed 's/.*"\([0-9a-f]*\)".*/\1/'` - - # Get route. - ROUTE=`lcli1 getroute $ID3 $HTLC_AMOUNT 1` - ROUTE=`echo $ROUTE | sed 's/^{ "route" : \(.*\) }$/\1/'` - - # Try wrong hash. - if lcli1 sendpay "$ROUTE" $RHASH4; then - echo Paid with wrong hash? >&2 - exit 1 - fi - - # Try underpaying. - PAID=`echo "$ROUTE" | sed -n 's/.*"msatoshi" : \([0-9]*\),.*/\1/p'` - UNDERPAY=`echo "$ROUTE" | sed "s/: $PAID,/: $(($PAID - 1)),/"` - if lcli1 sendpay "$UNDERPAY" $RHASH5; then - echo Paid with too little? >&2 - exit 1 - fi - - # If restarting, make sure node3 remembers incoming payment. - if [ "$RECONNECT" = restart ]; then - $LCLI3 -- dev-restart $LIGHTNINGD3 >/dev/null 2>&1 || true - if ! check "$LCLI3 getpeers 2>/dev/null | tr -s '\012\011\" ' ' ' | fgrep -q 'connected : true'"; then - echo "Failed to reconnect!">&2 - exit 1 - fi - fi - - [ "`lcli3 listinvoice RHASH5 | tr -s '\012\011\" ' ' '`" = "[ { label : RHASH5 , rhash : $RHASH5 , msatoshi : $HTLC_AMOUNT, complete : false } ] " ] - # Pay correctly. - lcli1 sendpay "$ROUTE" $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))\"" - - # If restarting, make sure node3 remembers completed payment. - if [ "$RECONNECT" = restart ]; then - echo RESTARTING NODE3 - $LCLI3 -- dev-restart $LIGHTNINGD3 >/dev/null 2>&1 || true - if ! check "$LCLI3 getpeers 2>/dev/null | tr -s '\012\011\" ' ' ' | fgrep -q 'connected : true'"; then - echo "Failed to reconnect!">&2 - exit 1 - fi - fi - - [ "`lcli3 listinvoice RHASH5 | tr -s '\012\011\" ' ' '`" = "[ { label : RHASH5 , rhash : $RHASH5 , msatoshi : $HTLC_AMOUNT, complete : true } ] " ] - - [ "`lcli3 waitinvoice | tr -s '\012\011\" ' ' '`" = "{ label : RHASH5 , rhash : $RHASH5 , msatoshi : $HTLC_AMOUNT } " ] - - # Can't pay twice (try from node2) - ROUTE2=`lcli2 getroute $ID3 $HTLC_AMOUNT 1` - ROUTE2=`echo $ROUTE2 | sed 's/^{ "route" : \(.*\) }$/\1/'` - if lcli2 sendpay "$ROUTE2" $RHASH5; then - echo "Paying twice worked?" >&2 - exit 1 - fi - - lcli3 close $ID2 - - # Re-send should be a noop (doesn't matter that node3 is down!) - lcli1 sendpay "$ROUTE" $RHASH5 - - # Re-send to different id or amount should complain. - SHORTROUTE=`echo "$ROUTE" | sed 's/, { "id" : .* }//' | sed 's/"msatoshi" : [0-9]*,/"msatoshi" : '$HTLC_AMOUNT,/` - lcli1 sendpay "$SHORTROUTE" $RHASH5 | $FGREP "already succeeded to $ID3" - lcli1 sendpay "$UNDERPAY" $RHASH5 | $FGREP "already succeeded with amount $HTLC_AMOUNT" - - # Now node2 should fail to route. - if lcli1 sendpay "$ROUTE" $RHASH4 | $FGREP "failed: error code 404 node $ID2 reason Unknown peer"; then : ; - else - echo "Pay to node3 didn't give 404" >&2 - exit 1 - fi - - # Now node1 should fail to route (route deleted) - if lcli1 getroute $ID3 $HTLC_AMOUNT 1 | $FGREP "no route found"; then : ; - else - echo "Pay to node3 didn't fail instantly second time" >&2 - exit 1 - fi -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 forever-1 blocks. -$CLI generate 8 - -# 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