Read on for my experience. Want to test yourself? Follow my detailed guide! On testnet, losing coins is free, go ahead and play! I’m writing this fairly beginner friendly, and not assume too much familiarity with LND. I encourage anyone not experienced with LND to read the logs, which can be found in ~/.lnd-*/logs/bitcoin/testnet/ – lnd.log is the last one, and there’s automatic log rotation.
Setup
Everything was done with the same user on a Linux machine, to keep it simple. This particularly simplifies the bitcoind configuration.
Bitcoind
Bitcoind compiled with ZMQ was configured to run on testnet with the following configuration in ~/.bitcoin/bitcoin.conf:
testnet=1 txindex=1 server=1 daemon=1 zmqpubrawblock=tcp://127.0.0.1:18501 zmqpubrawtx=tcp://127.0.0.1:18502
LND node 1
I compiled a fresh, 0.8.0-beta, LND.
I configured a node VegardNodeA by creating a .lnd-a directory in my home directory, copying sample-lnd.conf from the LND source directory to lnd.conf in this directory, with the following changes:
[Application Options] listen=0.0.0.0:9735 rpclisten=localhost:10009 restlisten=localhost:8080 alias=VegardNodeA [Bitcoin] bitcoin.active=1 bitcoin.testnet=1 bitcoin.node=bitcoind [wtclient] wtclient.active=1
LND node 2
Then, I configured a second node, VegardNodeB, in a .lnd-b directory, with lnd.conf:
[Application Options]
listen=0.0.0.0:9745 rpclisten=localhost:10019 restlisten=localhost:8085 alias=VegardNodeB [Bitcoin] bitcoin.active=1 bitcoin.testnet=1 bitcoin.node=bitcoind
Watchtower LND
[Application Options] listen=0.0.0.0:9755 rpclisten=localhost:10029 restlisten=localhost:8090 alias=VegardWatchtower [Bitcoin] bitcoin.active=1 bitcoin.testnet=1 [watchtower] watchtower.active=1
Running the instances
Finally, you need to start and initalize all the nodes. Fire up three different terminals to run lnd’s in, and one to control them all
lnd --lnddir ~/.lnd-a lnd --lnddir ~/.lnd-b lnd --lnddir ~/.lnd-wt lncli --network=testnet --lnddir ~/.lnd-a --rpcserver localhost:10009 create lncli --network=testnet --lnddir ~/.lnd-b --rpcserver localhost:10019 create lncli --network=testnet --lnddir ~/.lnd-wt --rpcserver localhost:10029 create
It might be a good idea for minimizing typing (and I will use this in rest of the tutorial)
alias lnclia="lncli --network=testnet --lnddir ~/.lnd-a --rpcserver localhost:10009"
alias lnclib="lncli --network=testnet --lnddir ~/.lnd-b --rpcserver localhost:10019"
alias lncliwt="lncli --network=testnet --lnddir ~/.lnd-wt --rpcserver localhost:10029"
and then use the aliases like this:
lnclia create lnclib create lncliwt create
For all lncli create’s, create passwords and write down seeds as you would for any wallet creation.
Now, familiarize yourself with your setup by running lncli getinfo and other queries against nodes A, B and the watchtower, and finally
lncliwt tower info
This should reveal the URI for the tower, which is different than the regular URI for the tower node. Now, you need to add this watchtower to node A (replace URI with your own URI, of course)
lnclia wtclient add 03471c0a89d51f189c899dcbc0c623cdb8c632686a4b7d6bc9b4f2cba2a84a6528@127.0.0.1:9911
This should give you only the following output:
{ }
Funding a wallet
Having set up it all, get some testnet coins. Go to https://coinfaucet.eu/en/btc-testnet/ and paste the resulting address from
lncli newaddress np2wkh
Now, you need to wait for a confirmation. You can check status with
lnclia walletbalance
When the transactions confirmed, the wallet balance moves to confirmed balance.
Creating a channel
lnclia connect 03523083824e7c9a3c01ac804ebabedf36d4cc216d62e1b365dc4d0aea1344de95@88.95.208.194:9745 lnclia openchannel 03523083824e7c9a3c01ac804ebabedf36d4cc216d62e1b365dc4d0aea1344de95 300000 --sat_per_byte 10
You will of course need to use the URI of node B instead of my example URI. Now, you again need to wait a few confirmations. Check back after a while if your channel appears when you do
lnclia listchannels
This would probably be a good place to go grab a coffee, or in my case – walk the dog. Or, read the logfiles, ~/.lnd-<node>/logs/bitcoin/testnet/lnd.log to see what things happens.
Do some payments
For our tests to work, there has to happen some transactions. So, we’ll go on send some bitcoin back and forth between node A and B. You can of course not cut and paste all this, but need
lnclib addinvoice 100000 { "r_hash": "85a0e3033bcbcc6067e095fc952947739e514466ed8671ef5c6ce8c76a4e4563", "pay_req": "lntb1m1pw6j3jlpp5skswxqeme0xxqelqjh7f2228ww09z3rxakr8rm6udn5vw6jwg43sdqqcqzpgvl7ja8n88rp6sgt7ydrggfzsw78mdc4qzcqfh2urpwrf8aa769ks2k4rd6n8mx2sz37l5ezpzqhd27hhmjx6evn2d3ma0hfr2gqadhcpntcj5d", "add_index": 2 } lnclia payinvoice lntb1m1pw6j3jlpp5skswxqeme0xxqelqjh7f2228ww09z3rxakr8rm6udn5vw6jwg43sdqqcqzpgvl7ja8n88rp6sgt7ydrggfzsw78mdc4qzcqfh2urpwrf8aa769ks2k4rd6n8mx2sz37l5ezpzqhd27hhmjx6evn2d3ma0hfr2gqadhcpntcj5d Description: Amount (in satoshis): 100000 Destination: 03523083824e7c9a3c01ac804ebabedf36d4cc216d62e1b365dc4d0aea1344de95 Confirm payment (yes/no): yes { "payment_error": "", "payment_preimage": "1e7162123cc48125f4bbf770f060383906e0a8a899999d457d7cd17c6c99e72c", "payment_route": { "total_time_lock": 1583287, "total_amt": 100000, "hops": [ { "chan_id": 1740763301772722176, "chan_capacity": 300000, "amt_to_forward": 100000, "expiry": 1583287, "amt_to_forward_msat": 100000000, "pub_key": "03523083824e7c9a3c01ac804ebabedf36d4cc216d62e1b365dc4d0aea1344de95", "tlv_payload": true } ], "total_amt_msat": 100000000 } } lnclia addinvoice 50000 { "r_hash": "91c58b341de687d12a58a97e8f374c6c9a61cc4a4056db13bd1c041fe54dde51", "pay_req": "lntb500u1pw6j34fpp5j8zckdqau6raz2jc49lg7d6vdjdxrnz2gptdkyaarszple2dmegsdqqcqzpgzcp3x4w883jpdan6uzqvmgcw5ef763hknpcq9ch4xs460wklslqn5pch6sv967k44jfdmk2qr22htxyscgduu97ehty7mu6sl24ex3cqse5t0x", "add_index": 1 } lnclib payinvoice lntb500u1pw6j34fpp5j8zckdqau6raz2jc49lg7d6vdjdxrnz2gptdkyaarszple2dmegsdqqcqzpgzcp3x4w883jpdan6uzqvmgcw5ef763hknpcq9ch4xs460wklslqn5pch6sv967k44jfdmk2qr22htxyscgduu97ehty7mu6sl24ex3cqse5t0x Description: Amount (in satoshis): 50000 Destination: 0292f889e38b479731676c4fd307e0126672b06d76d9bb4815602cc4bbd19a1d11 Confirm payment (yes/no): yes { "payment_error": "", "payment_preimage": "65b8e81e7928a0b6c70197a83a20b5d75350a299d8466476a96ab237c8e1075f", "payment_route": { "total_time_lock": 1583287, "total_amt": 50000, "hops": [ { "chan_id": 1740763301772722176, "chan_capacity": 300000, "amt_to_forward": 50000, "expiry": 1583287, "amt_to_forward_msat": 50000000, "pub_key": "0292f889e38b479731676c4fd307e0126672b06d76d9bb4815602cc4bbd19a1d11", "tlv_payload": true } ], "total_amt_msat": 50000000 } }
Setting up for a fraud….
You now need to copy channel.db of node B to a safe place. Ideally while node B is down, to make sure it’s consistent and usable.
lnclib stop cp ~/.lnd-b/data/graph/testnet/channel.db ~/.lnd-b/data/graph/testnet/channel.db.copy
Now, restart lnd B in another terminal
lnd --lnddir=~/.lnd-b
And unlock it in your terminal with your aliases.
lnclib unlock Input wallet password: lnd successfully unlocked!
Now, we need to give node B something to steal…
lnclia addinvoice 10000 { "r_hash": "924cad77f3dbcc4e7cc19d0c1f1554843214f17da6bdf0ddbe99be883419c583", "pay_req": "lntb100u1pw6jjmgpp5jfx26alnm0xyulxpn5xp7925ssepfuta567lphd7nxlgsdqeckpsdqqcqzpgfegtwge95z5x7ppnrkdcdmw6yr5f5kls94xc09u7gms9g6fvvrpz9xs0pfuszqh9zpg7sl2xj67fvlyexg5kmjg2mkv80gkvvrkhyjgpf89rw6", "add_index": 2 } lnclib payinvoice lntb100u1pw6jjmgpp5jfx26alnm0xyulxpn5xp7925ssepfuta567lphd7nxlgsdqeckpsdqqcqzpgfegtwge95z5x7ppnrkdcdmw6yr5f5kls94xc09u7gms9g6fvvrpz9xs0pfuszqh9zpg7sl2xj67fvlyexg5kmjg2mkv80gkvvrkhyjgpf89rw6 Description: Amount (in satoshis): 10000 Destination: 0292f889e38b479731676c4fd307e0126672b06d76d9bb4815602cc4bbd19a1d11 Confirm payment (yes/no): yes { "payment_error": "", "payment_preimage": "0b710f14ebaa6245672e4bdd04ba7309ca1d0159009da57f4427a3d13b9e63f5", "payment_route": { "total_time_lock": 1583289, "total_amt": 10000, "hops": [ { "chan_id": 1740763301772722176, "chan_capacity": 300000, "amt_to_forward": 10000, "expiry": 1583289, "amt_to_forward_msat": 10000000, "pub_key": "0292f889e38b479731676c4fd307e0126672b06d76d9bb4815602cc4bbd19a1d11", "tlv_payload": true } ], "total_amt_msat": 10000000 } }
The fraud
For this to work, node A need to be down, so stop it.
lnclia stop
Now, upon seeing that node A is gone, node B is guessing that he will not be back before the timelocks built into the channel is over. Let’s do some fraud! Stop node B, put back in place the backup, and restart it
lnclib stop cp ~/.lnd-b/data/graph/testnet/channel.db.copy ~/.lnd-b/data/graph/testnet/channel.db lnd --lnddir=~/.lnd-b (in another window) lnclib unlock
Verify that it indeed thinks it has 50000 (the result after the first payment of 50000), and not 40000 (after paying 10000 more), and find the channel point.
lnclib listchannels { "channels": [ { "active": false, "remote_pubkey": "0292f889e38b479731676c4fd307e0126672b06d76d9bb4815602cc4bbd19a1d11", "channel_point": "108b9d9b1202d23307d7272530ea74c7473d5c3d8e250384cb672b602e7239f7:0", "chan_id": "1740763301772722176", "capacity": "300000", "local_balance": "50000", "remote_balance": "249817", "commit_fee": "183", "commit_weight": "724", "fee_per_kw": "253", "unsettled_balance": "0", "total_satoshis_sent": "50000", "total_satoshis_received": "100000", "num_updates": "4", "pending_htlcs": [ ], "csv_delay": 144, "private": false, "initiator": false, "chan_status_flags": "ChanStatusDefault", "local_chan_reserve_sat": "3000", "remote_chan_reserve_sat": "3000", "static_remote_key": true } ] }
Now, force close it!
lnclib closechannel 108b9d9b1202d23307d7272530ea74c7473d5c3d8e250384cb672b602e7239f7 0 --force { "closing_txid": "827732758fb9973f3b99b677ccb460460fb54712e3ec1639ce019e33d87d06f0" }
Now, a watchtower acts on confirmed transactions, so we’ll need to wait a block. Follow ~/.lnd-wt/logs/bitcoin/testnet/lnd.log, until you see it gets a new block and magic starts happen!
019-10-18 07:43:44.651 [INF] NTFN: New block: height=1583249, sha=0000000000088208f755f57ec65814fcba2a4b2385826cf9e2103484002601c8 2019-10-18 07:43:44.651 [INF] UTXN: Attempting to graduate height=1583249: num_kids=0, num_babies=0 2019-10-18 07:43:44.692 [INF] WTWR: Found 1 breach in (height=1583249, hash=0000000000088208f755f57ec65814fcba2a4b2385826cf9e2103484002601c8) 2019-10-18 07:43:44.692 [INF] WTWR: Dispatching punisher for client 0395b404e198d07a2ae5542cd7c691c030587ea9df12647cb3032c54edee52bc59, breach-txid=827732758fb9973f3b99b677ccb460460fb54712e3ec1639ce019e33d87d06f0 2019-10-18 07:43:44.694 [INF] WTWR: Publishing justice transaction for client=0395b404e198d07a2ae5542cd7c691c030587ea9df12647cb3032c54edee52bc59 with txid=079082649b11986377a1717ba04bb90097a774977a0f44d3b6424d90e81418cf 2019-10-18 07:43:44.694 [INF] LNWL: Inserting unconfirmed transaction 079082649b11986377a1717ba04bb90097a774977a0f44d3b6424d90e81418cf 2019-10-18 07:43:44.700 [INF] WTWR: Punishment for client 0395b404e198d07a2ae5542cd7c691c030587ea9df12647cb3032c54edee52bc59 with breach-txid=827732758fb9973f3b99b677ccb460460fb54712e3ec1639ce019e33d87d06f0 dispatched
Now, let’s restart node A and see what happens
lnd --lnddir ~/.lnd-a/ (in another window) lnclia unlock
And check the balance
lnclia walletbalance { "total_balance": "2682098", "confirmed_balance": "2682098", "unconfirmed_balance": "0" }
Read ~/.lnd-a/logs/bitcoin/testnet/lnd.log and you should see something like this
2019-10-18 07:48:50.463 [ERR] BRAR: Unable to broadcast justice tx: Transaction rejected: output already spent 019-10-18 07:48:50.464 [INF] BRAR: Waiting for a spend event before attempting to craft new justice tx. 2019-10-18 07:48:50.464 [INF] BRAR: Checking spend from CommitmentNoDelayTweakless(827732758fb9973f3b99b677ccb460460fb54712e3ec1639ce019e33d87d06f0:1) for ChannelPoint(108b9d9b1202d23307d7272530ea74c7473d5c3d8e250384cb672b602e7239f7:0) 2019-10-18 07:48:50.464 [INF] NTFN: New spend subscription: spend_id=2, outpoint=827732758fb9973f3b99b677ccb460460fb54712e3ec1639ce019e33d87d06f0:1, height _hint=1583249 2019-10-18 07:48:50.466 [INF] BRAR: Checking spend from CommitmentRevoke(827732758fb9973f3b99b677ccb460460fb54712e3ec1639ce019e33d87d06f0:0) for ChannelPoi nt(108b9d9b1202d23307d7272530ea74c7473d5c3d8e250384cb672b602e7239f7:0) 2019-10-18 07:48:50.466 [INF] NTFN: New spend subscription: spend_id=3, outpoint=827732758fb9973f3b99b677ccb460460fb54712e3ec1639ce019e33d87d06f0:0, height _hint=1583249
This is node A trying to serve justice to node B itself, but noticing that the transaction is already spent – by the watchtower! Now, let’s wait for the next block, and we see…
2019-10-18 08:03:53.362 [INF] LNWL: Inserting unconfirmed transaction 079082649b11986377a1717ba04bb90097a774977a0f44d3b6424d90e81418cf 2019-10-18 08:03:53.382 [INF] LNWL: Marking unconfirmed transaction 079082649b11986377a1717ba04bb90097a774977a0f44d3b6424d90e81418cf mined in block 1583250 2019-10-18 08:03:53.489 [INF] CRTR: Pruning channel graph using block 0000000044cfde0667c22eec017b059f7ab47a9626221a7d47cb5a78d3fa0eb9 (height=1583250) 2019-10-18 08:03:53.507 [INF] CRTR: Block 0000000044cfde0667c22eec017b059f7ab47a9626221a7d47cb5a78d3fa0eb9 (height=1583250) closed 0 channels 2019-10-18 08:03:53.591 [INF] NTFN: New block: height=1583250, sha=0000000044cfde0667c22eec017b059f7ab47a9626221a7d47cb5a78d3fa0eb9 2019-10-18 08:03:53.591 [INF] NTFN: Dispatching confirmed spend notification for outpoint=827732758fb9973f3b99b677ccb460460fb54712e3ec1639ce019e33d87d06f0:0 at height=1583250 2019-10-18 08:03:53.591 [INF] NTFN: Dispatching confirmed spend notification for outpoint=827732758fb9973f3b99b677ccb460460fb54712e3ec1639ce019e33d87d06f0:1 at height=1583250 2019-10-18 08:03:53.591 [INF] BRAR: Detected spend on CommitmentNoDelayTweakless(827732758fb9973f3b99b677ccb460460fb54712e3ec1639ce019e33d87d06f0:1) by txid(079082649b11986377a1717ba04bb90097a774977a0f44d3b6424d90e81418cf) for ChannelPoint(108b9d9b1202d23307d7272530ea74c7473d5c3d8e250384cb672b602e7239f7:0) 2019-10-18 08:03:53.591 [INF] UTXN: Attempting to graduate height=1583250: num_kids=0, num_babies=0 2019-10-18 08:03:53.591 [INF] BRAR: Detected spend on CommitmentRevoke(827732758fb9973f3b99b677ccb460460fb54712e3ec1639ce019e33d87d06f0:0) by txid(079082649b11986377a1717ba04bb90097a774977a0f44d3b6424d90e81418cf) for ChannelPoint(108b9d9b1202d23307d7272530ea74c7473d5c3d8e250384cb672b602e7239f7:0) 2019-10-18 08:03:53.591 [INF] BRAR: Spend on CommitmentNoDelayTweakless(827732758fb9973f3b99b677ccb460460fb54712e3ec1639ce019e33d87d06f0:1) for ChannelPoint(108b9d9b1202d23307d7272530ea74c7473d5c3d8e250384cb672b602e7239f7:0) transitions output to terminal state, removing input from justice transaction 2019-10-18 08:03:53.591 [INF] BRAR: Spend on CommitmentRevoke(827732758fb9973f3b99b677ccb460460fb54712e3ec1639ce019e33d87d06f0:0) for ChannelPoint(108b9d9b1202d23307d7272530ea74c7473d5c3d8e250384cb672b602e7239f7:0) transitions output to terminal state, removing input from justice transaction
And
vegard@vegardlaptop:~$ lnclia walletbalance
{
“total_balance”: “2730201”,
“confirmed_balance”: “2730201”,
“unconfirmed_balance”: “0”
}
We have got back the 50k. Now, let’s check our whole onchain history.
lnclia listchaintxns { "transactions": [ { "tx_hash": "22a9fca598c63f98f9192699c91d37774fdf97fc5f800a80d96412ee6e54e254", "amount": "2734038", "num_confirmations": 37, "block_hash": "000000002afed444dfcc5990d1ecee289f81353934e25354e1c11f8a87cf1f01", "block_height": 1583214, "time_stamp": "1571343204", "total_fees": "0", "dest_addresses": [ "2MszP1ucze7pVQvT4t2puSG6uocFMSqK5QT", "2N3dmvz4yZ6Deax3uPMueaSMGBoWy8vzTcX" ], "raw_tx_hex": "02000000000101dad2d5004a6dc6d1c2406e2d17fe026b2da61f42e370fd67de108f7ce3d49a310000000017160014d923e6eff6605fc9c779fdc0c706e7307a3bae38feffffff02228d29060000000017a91408296c2c771644f2a2ac66d9932fa092927d224787d6b729000000000017a91471f512e28098d4f9f7783fa3e6409697d5270c3d8702473044022059a73c2f586a8a20653694a87b56f41a8fa843f0656ad46e51d324cef2a7a4b60220356447f366fe0828df78d8bdf2ea96c108e4ab26f285e272857dda7d17878f530121033337a82f3823ccf16d6a8cce7bb3923438bde4001303bbddfeeb1e7547f8f4f26d281800" }, { "tx_hash": "108b9d9b1202d23307d7272530ea74c7473d5c3d8e250384cb672b602e7239f7", "amount": "-301757", "num_confirmations": 36, "block_hash": "00000000756a9068b87636f6e2da22d17230037743262b1b9385c699a369b18e", "block_height": 1583215, "time_stamp": "1571344408", "total_fees": "1757", "dest_addresses": [ "tb1qres4wzattp4cpn4c7egpg57v8m77x3q0z2hkma43fga9pus655ys0uhkx7", "tb1qkf380ljsjefv83q6748jd2t2srnqfea72tukku" ], "raw_tx_hex": "0100000000010154e2546eee1264d9800a805ffc97df4f77371dc9992619f9983fc698a5fca92201000000171600147654d9bf658e6cf5db44d0d75382beb8ba496608ffffffff02e0930400000000002200201e61570bab586b80ceb8f6501453cc3efde3440f12af6df6b14a3a50f21aa509191d250000000000160014b26277fe509652c3c41af54f26a96a80e604e7be0247304402207309e076a8e3e1db9a8f0514b1905ea427314edd855abf03b5f0fff93e40bfbe02205f04e50d0e4e52240610733230e3f9ab9738c00df4b592ba62ddd726e6e725af0121023413d20fe826a6587f3e6dc46d7a6337f65641aba2b672acdd129e196acefa4d00000000" }, { "tx_hash": "827732758fb9973f3b99b677ccb460460fb54712e3ec1639ce019e33d87d06f0", "amount": "249817", "num_confirmations": 2, "block_hash": "0000000000088208f755f57ec65814fcba2a4b2385826cf9e2103484002601c8", "block_height": 1583249, "time_stamp": "1571377425", "total_fees": "0", "dest_addresses": [ "tb1qq0tprf2rtc7yleq6zl5qrcsuk65u655ceyskpq8ngl9vmmejkzzsjc2k64", "tb1qfdfqsm04epnnnv4k2qwzywggwgequ4rmtk2qcl" ], "raw_tx_hex": "02000000000101f739722e602b67cb8403258e3d5c3d47c774ea302527d70733d202129b9d8b100000000000d3692c800250c300000000000022002003d611a5435e3c4fe41a17e801e21cb6a9cd5298c9216080f347cacdef32b085d9cf0300000000001600144b52086df5c86739b2b6501c22390872320e547b040047304402205b100144524d510dd9df6a5245fda54985c8f40ed379fe96cbba2fd163c3966c022073d7ad1e5afccee53134a5f65284ecc3ffe480e8862760037dcbdb65736617fc01483045022100b7ae8870c7e9efb5d88a7fe0b012c14f4eb1c2ff30319b2fc924240d4351e2ce0220057cf5514996283d5b2a0129cc52f03e721de95995eb2ae70b5d77f3224f797401475221030b495346e543601fef83cfd8af1072e406bc7b04105ee2a070ea4def6d36216e2103ca54f236bf4218c80f3435d373a7e57ce0efed86bb6d02c6465f3917c508fb6c52ae1a45b820" }, { "tx_hash": "079082649b11986377a1717ba04bb90097a774977a0f44d3b6424d90e81418cf", "amount": "48103", "num_confirmations": 1, "block_hash": "0000000044cfde0667c22eec017b059f7ab47a9626221a7d47cb5a78d3fa0eb9", "block_height": 1583250, "time_stamp": "1571378631", "total_fees": "0", "dest_addresses": [ "tb1qage5aacsvql758v6z8ufulzn083pst6ukzwzw8" ], "raw_tx_hex": "02000000000102f0067dd8339e01ce3916ece31247b50f4660b4cc77b6993b3f97b98f75327782000000000000000000f0067dd8339e01ce3916ece31247b50f4660b4cc77b6993b3f97b98f7532778201000000000000000001c08b040000000000160014ea334ef710603fea1d9a11f89e7c5379e2182f5c03473044022011b42b74cbed2ff7a4303547e3f4c34dbc8b32c6684dbc9982119c851c3604a302206e5345806ce5a463a22e858d703b94eb469c239e7bde3bfc21b81737a650c5950101014d632103ecf2f02402d7477f06b4581e7fe09d556c902b8a18c8f02a1b7f371f4bd49ed367029000b2752103ef235e503884117ab07d79ae38017ed343a37dd5de4977e0ad9966f4762c90c568ac024730440220094166b2fd72c98dd69f78a2572e8bd392df705daf6c2821f94d65a3cee85d0702202201e6667d5d3a07d820c8860565f3fb56937fa7ee82644eacf34dd7421d7d9201210376f06e006287a7ffdea318d008e997535a144f4bef6b44138ec127f372e6a1c300000000" } ] }
We can see 4 transactions. The first transaction, node A gets 2734038 satoshi from the faucet. In the second transaction, node A spends 301757 satoshi to set up a channel with 300k capacity. Then, node A got the (approximately, fee subtracted) 250k that node B had to give him in the fraudulent transaction. Note that he can not even attempt to steal everything, he can attempt to steal only what node A at some time has allowed him to spend. The fourth, and last, transaction, is the 50k (minus some fees) from the watchtower that caught the fraud, and sent back not only the 10k he tried to take, but the full balance he had. Justice is served! Note also that in this version of watchtowers, the watchtower gets nothing at all, so it’s not as trustless as it will eventually be – there’s no self-interest for a watchtower to publish a penalty transaction. This means we’re not likely to see a bunch of public watchtowers at this stage. However, you could still set up a watchtower for yourself – perhaps in the cloud (remember, it doesn’t actually hold any funds), or you could partner with some friends or business partners to run watchtower services for each others.
Another thing to note is that in LND version 0.8.0-beta, the address that a force close transaction sent to now is controlled by the on-chain wallet, while earlier it would be a temporary address. This means that if you totally lose the node, and have no backup at all, everything should end up in addressess recoverable by your seed if your partner force close the channel. If you want to signal to your channel partners to do that, you will still need the static channel backup that LND generates.
This new commitment format, “safu commitment format”, also leads to less on-chain transactions. Earlier, force-closed transactions ended up in a temporary address that your node would then have to move to the on-chain wallet, in a new transaction. This should now slowly be gone, for new channels.
So, does watchtowers work? I’ll have to say yes! But they will improve in the future.
I’ve test it but my case. Tower not do their job. After node A down. Seem like tower no longer receive and action anything until node A back online. Watch tower seem to get some info from node A. Also once node A online then it send punishment as you say. But another test, if I let node A down past the time of justice or 1 day. Then cheat success. Meaning watch tower don’t do it’s job. I don’t sure why? Is it because it local networking?
Hard to say, been a while since I played with this. There might also have been changes in how you set it up.
But all the nodes of course need to be getting new blocks from the blockchain. First thing would be to check if the nodes are healthy and get new blocks.
I’ve try again, open channel, close channel. For more than 5th time. Result still similar. I also send you email. Can you help me some? Maybe I can send what I’ve done trough email more easy. And I sure I get new block, it testnet and I got Bitcoin tow test around 2million Satoshi. I also can send and receive Satoshi trough node.b follow by your article. Also node wt seem to get info quite well. Node a log seem to connect to watch tower as well. That log output from node a. But node wt seem to quite shy, little activity I mean.
And 2 scenario I test:
Cheating success if I let node.a offline for more than 1 day. Node.b will get what it cheating for. Verify by wallet balance.
Cheating protected if node.a online before finish 1 day then it node.a publish justice transaction then punished node.b those also verify by wallet balance after force close channels.
That said but I still not sure why watchtower not publish the cheating transaction thing . Only node.a done when it online within 1 day after force close channel.
Do you see anything in logs of the watchtower?
My bad! It work already. Look carefully again in log file in watch tower node with grep. I can see it log breach detect around 5-10 minute. later or my 2-times test case. Thank for help. I like your article. It simple to follow and explanation.
The watchtower would need to wait until the cheat is confirmed onchain, of course. I don’t know either if it will wait a couple of confirmation, which might be sensible because then it allows you to catch the cheater yourself, witch might save you some fees.
Been a while since I looked at this, so my info here would probably even be outdated if I knew it at that point.