In this guide I’m going to walk you through making a payment using Bitcoin’s Layer 2 Lightning Network using testnet to demonstrate. We will be using the command line as I’ve found this to be the most reliable way to use the network and doing so gives you a deeper understanding of how the network operates.

Prerequisites

You have access to a lightning node that: 1. is running bitcoind and lightningd and is synced to the testnet blockchain, 2. has blockstream’s c-lightning cli tool, lightning-cli, installed and accessible in its $PATH.

Check out my guide to setting up a lightning network node if you still need to set one up.

1. Generate Address and Fund Wallet

Layer 1 BTC transactions = 1. Wait Time = 60 mins.

Create a new address.

$ lightning-cli newaddr

Go to the testnet faucet and send yourself some bitcoin. Tip - use chrome to get that 70% bonus for using IPV6!

Click on the transaction ID link that will appear just beneath which will take you to the blockchain explorer with details of the transaction.

You need to wait for 6 confirmations - about 1 hour before the funds show up in your wallet.

$ lightning-cli listfunds
{
	"outputs": [
		{
			"txid": "d30ad72742d5c05343f65a1f78a90191f7b13341ed309cad0297a4e2fd3f0196",
			"output": 1,
			"value": 64849668,
			"status": "confirmed"
		}
	]
}

Bitcoin Explorer

2. Connect to a Peer and Create a Payment Channel

Layer 1 BTC transactions = 1. Wait Time = 60 mins.

In order to make payments on the network you first need to connect to it. How do you find another node to connect to? Head to Acinq’s lightning network explorer.

Search for a well connected peer (one with a lot of channels) and copy its URI. I timed out on a few nodes initially, just keep trying and you’ll find one that connects immediately.

$ lightning-cli connect 03e5f9d1935c67a029bf0a26af5f63109f4f4c45993a8f45177a8f2f39bcb46144 77.58.162.148 9735

$ lightning-cli list peers
		{
			"state": "GOSSIPING",
			"id": "03e5f9d1935c67a029bf0a26af5f63109f4f4c45993a8f45177a8f2f39bcb46144",
			"alias": "IslandDSP",
			"netaddr": [
				"84.246.200.122:9735"
			],
			"connected": true
		}

Now we will create a payment channel with the peer we just connected to. Opening and closing channels entails interacting with the main blockchain so we want to fund it with a decent amount (in millisatoshis) so that we can use it for several payments.

$ lightning-cli fundchannel 03e5f9d1935c67a029bf0a26af5f63109f4f4c45993a8f45177a8f2f39bcb46144 50000

$ lightning-cli listpeers
{
			"id": "03e5f9d1935c67a029bf0a26af5f63109f4f4c45993a8f45177a8f2f39bcb46144",
			"connected": true,
			"netaddr": [
				"84.246.200.122:9735"
			],
			"alias": "IslandDSP",
			"color": "68f442",
			"channels": [
				{
					"state": "CHANNELD_AWAITING_LOCKIN",
					"owner": "lightning_channeld",
					"channel_id": "958b3bd04adb40fd8ff0700a0b24e0298a2ac265273c08ed0218af38140ba678",
					"funding_txid": "78a60b1438af1802ed083c2765c22a8a29e0240b0a70f08ffd40db4ad03b8b95",
					"msatoshi_to_us": 500000000,
					"msatoshi_total": 500000000,
					"dust_limit_satoshis": 546,
					"max_htlc_value_in_flight_msat": 18446744073709552000,
					"channel_reserve_satoshis": 0,
					"htlc_minimum_msat": 0,
					"their_to_self_delay": 6,
					"our_to_self_delay": 144,
					"to_self_delay": 6,
					"max_accepted_htlcs": 483,
					"status": [
						"CHANNELD_AWAITING_LOCKIN:Funding needs more confirmations."
					],

Again, search for the txid in the bitcoin testnet explorer and wait for 3-6 confirmations before the channel is considered open. When it is you should see the status changed to CHANNELD_NORMAL.

$ lightning-cli listpeers
{
	"peers": [
		{
			"id": "03e5f9d1935c67a029bf0a26af5f63109f4f4c45993a8f45177a8f2f39bcb46144",
			"connected": true,
			"netaddr": [
				"84.246.200.122:9735"
			],
			"alias": "IslandDSP",
			"color": "3399ff",
			"channels": [
				{
					"state": "CHANNELD_NORMAL",
					"owner": "lightning_channeld",
					"short_channel_id": "1289768:416:0",
					"channel_id": "ba95c71228ce3f57e25f6ac9c4a7418a52a056435b2276dd47437c7521ebda8e",
					"funding_txid": "8edaeb21757c4347dd76225b4356a0528a41a7c4c96a5fe2573fce2812c795ba",
					"msatoshi_to_us": 100000000,
					"msatoshi_total": 100000000,
					"dust_limit_satoshis": 546,
					"max_htlc_value_in_flight_msat": 18446744073709552000,
					"channel_reserve_satoshis": 0,
					"htlc_minimum_msat": 0,
					"their_to_self_delay": 6,
					"our_to_self_delay": 144,
					"to_self_delay": 6,
					"max_accepted_htlcs": 483,
					"status": [
						"CHANNELD_NORMAL:Funding transaction locked. Channel announced."
					],
					"in_payments_offered": 0,
					"in_msatoshi_offered": 0,
					"in_payments_fulfilled": 0,
					"in_msatoshi_fulfilled": 0,
					"out_payments_offered": 0,
					"out_msatoshi_offered": 0,
					"out_payments_fulfilled": 0,
					"out_msatoshi_fulfilled": 0
				}
			]
		}
	]
}

Lightning Network Explorer

3. Generate Payment Request

Now we have a confirmed channel established we can start using the lightning network for transactions.

Go to an article on Y’alls and click on the “continue reading” button to generate a payment request. This is essentially a serialised invoice. Decode it to check that you are not being overcharged!

$ lightning-cli decodepay lntb1500n1pdvp7t9pp5k5mvp8u045pdnumnt89cdc7l90lpvff7sjzkrvawg93ju3mgg3nsdp62fjkzepqg9e8g6trd3jn5gzfyp9kummhyptksmeq2dshgmmndp5jqjtnp5cqzyskw8lzg7w4hcfyhncczcaexlpx3tdefm0vjnh9dkqev23g94tdta8jjqzp87v6r9q8xwe3mnjf0tryaa7zkxxj4gwgfcqea32j0x069qqsjyjhz
{
	"currency": "tb",
	"timestamp": 1522596197,
	"created_at": 1522596197,
	"expiry": 3600,
	"payee": "039cc950286a8fa99218283d1adc2456e0d5e81be558da77dd6e85ba9a1fff5ad3",
	"msatoshi": 150000,
	"description": "Read Article: I Know Who Satoshi Is\r",
	"min_final_cltv_expiry": 144,
	"payment_hash": "b536c09f8fad02d9f37359cb86e3df2bfe16253e848561b3ae41632e47684467",
	"signature": "3045022100b38ff123ceadf0925e78c0b1dc9be13456dca76f64a772b6c0cb151416ab6afa022079480209fccd0ca0399d98ee724bd63277be158c69550e42700cf62a93ccfd14"
}

Y'alls Payment Request

4. Make the Payment

Layer 2 BTC transactions = 1. Wait Time = milliseconds.

Now we have everything in place to make a layer 2 bitcoin transaction which should be instantly confirmed.

$ lightning-cli pay lntb1500n1pdvp7t9pp5k5mvp8u045pdnumnt89cdc7l90lpvff7sjzkrvawg93ju3mgg3nsdp62fjkzepqg9e8g6trd3jn5gzfyp9kummhyptksmeq2dshgmmndp5jqjtnp5cqzyskw8lzg7w4hcfyhncczcaexlpx3tdefm0vjnh9dkqev23g94tdta8jjqzp87v6r9q8xwe3mnjf0tryaa7zkxxj4gwgfcqea32j0x069qqsjyjhz
{
	"code": 206,
	"message": "Fee 1100 is 0.733333% of payment 150000; max fee requested is 0.500000%",
	"data": {
		"fee": 1100,
		"feepercent": 0.733333,
		"msatoshi": 150000,
		"maxfeepercent": 0.500000,
		"getroute_tries": 6,
		"sendpay_tries": 0,
		"failures": []
	}
}

Go back to Y’alls and click on the “check for payment” button to reveal the article. Unfortunately this didn’t work for me. When I checked on the command line I discovered that indeed no payments had been made.

$ lightning-cli listpayments
{
	"payments": []
}

To try to solve this issue, I attempted to create a payment channel with Y’alls directly (their address is listed as “peer” when they create you an invoice to continue reading).

$ lightning-cli connect 039cc950286a8fa99218283d1adc2456e0d5e81be558da77dd6e85ba9a1fff5ad3 34.200.252.146

$ lightning-cli fundchannel 039cc950286a8fa99218283d1adc2456e0d5e81be558da77dd6e85ba9a1fff5ad3 500000
{
	"code": -1,
	"message": "received ERROR channel 3795216ba4a257a1f36f1062af58b4513ad82dac90d298e45ca83271e67cf1d6: Unacceptable channel constraints: minimum HTLC value is too large: 0"
}

Apparently this is a known bug with lnd, which Y’alls must be using as their lightning daemon.

As a backup plan we’ll send a payment to ourselves using a web lightning wallet. Go to htlc.me and generate a wallet and then click on the “receive” tab to request a payment of 0.0001 tBTC ($0.65 tUSD). Copy the serialised invoice and check it before sending payment.

$ lightning-cli decodepay lntb100u1pdvzzc4pp5h55942ehdpy5g70sty9mnvt3k2wlvt4ucnctnellau8drhaew8lsdqqcqzyswv3n3vyzx9uua4tjl8ttcp5fp7srn80zywvg4vses6fj4q9n3v846mgkuu648u37venf93znkckadjejvddv04vyq5l2krx486z23ysqhcrxg6
{
	"currency": "tb",
	"timestamp": 1522600725,
	"created_at": 1522600725,
	"expiry": 3600,
	"payee": "03193d512b010997885b232ecd6b300917e5288de8785d6d9f619a8952728c78e8",
	"msatoshi": 10000000,
	"description": "",
	"min_final_cltv_expiry": 144,
	"payment_hash": "bd285aab3768494479f0590bb9b171b29df62ebcc4f0b9e7ffef0ed1dfb971ff",
	"signature": "30440220732338b0823179ced572f9d6bc06890fa0399de223988ab21986932a80b38b0f02205d6d16e73553f23e666692c453b62dd6cb32635ac7d584053eab0cd53e84a892"
}

This time when I attempted payment I received multiple errors.

$ lightning-cli pay lntb100u1pdvzzc4pp5h55942ehdpy5g70sty9mnvt3k2wlvt4ucnctnellau8drhaew8lsdqqcqzyswv3n3vyzx9uua4tjl8ttcp5fp7srn80zywvg4vses6fj4q9n3v846mgkuu648u37venf93znkckadjejvddv04vyq5l2krx486z23ysqhcrxg6
{
	"failures": [{
			"type": "FAIL_PAYMENT_REPLY",
			"erring_index": 1,
			"failcode": 4103...

However, when I refreshed the htlc.me web page I saw that the payment had in fact succeeded. Checking in the console confirmed that payment had been made.

$ lightning-cli listpayments
{
	"payments": [
		{
			"id": 1,
			"payment_hash": "bd285aab3768494479f0590bb9b171b29df62ebcc4f0b9e7ffef0ed1dfb971ff",
			"destination": "03193d512b010997885b232ecd6b300917e5288de8785d6d9f619a8952728c78e8",
			"msatoshi": 10000000,
			"msatoshi_sent": 10002020,
			"timestamp": 1522601027,
			"created_at": 1522601027,
			"status": "complete",
			"payment_preimage": "3e75637befbeec9e7056a4103a06d652cd3cdee9134de69799d8b39c6b1f714c"
		}
	]
}

We sent a payment and paid just 2020 millisatoshi in transaction fees ($0.00013 USD at the time of writing)!

Finally, let’s try to connect with htlc.me directly so we don’t get any console errors when making payment. Copy the payee id from the decodepay command output above and search for it in the lightning network explorer. Copy the URI then connect to it and create a channel.

$ lightning-cli connect 03193d512b010997885b232ecd6b300917e5288de8785d6d9f619a8952728c78e8 34.201.11.250 9735

$ lightning-cli fundchannel 03193d512b010997885b232ecd6b300917e5288de8785d6d9f619a8952728c78e8 500000

Unfortunately we need to wait for the transaction to confirm on the blockchain so that the channel becomes usable.

An hour later we can see the channel is established - the status is CHANNELD_NORMAL.

$ lightning-cli listpeers
	{
		"id": "03193d512b010997885b232ecd6b300917e5288de8785d6d9f619a8952728c78e8",
		"connected": true,
		"netaddr": [
			"34.201.11.250:9735"
		],
		"alias": "htlc.me",
		"color": "854cc5",
		"channels": [
			{
				"state": "CHANNELD_NORMAL",
				"owner": "lightning_channeld",
				"short_channel_id": "1289949:56:0",
				"channel_id": "20dd321c23224b2022f62f59602efc311a8ad63c4481fcd210ef8dade88e8064",
				"funding_txid": "64808ee8ad8def10d2fc81443cd68a1a31fc2e60592ff622204b22231c32dd20",
				"msatoshi_to_us": 500000000,
				"msatoshi_total": 500000000,
				"dust_limit_satoshis": 546,
				"max_htlc_value_in_flight_msat": 18446744073709552000,
				"channel_reserve_satoshis": 0,
				"htlc_minimum_msat": 0,
				"their_to_self_delay": 6,
				"our_to_self_delay": 144,
				"to_self_delay": 6,
				"max_accepted_htlcs": 483,
				"status": [
					"CHANNELD_NORMAL:Funding transaction locked."
				],
				"in_payments_offered": 0,
				"in_msatoshi_offered": 0,
				"in_payments_fulfilled": 0,
				"in_msatoshi_fulfilled": 0,
				"out_payments_offered": 0,
				"out_msatoshi_offered": 0,
				"out_payments_fulfilled": 0,
				"out_msatoshi_fulfilled": 0
			}
		]
	}

Now generate another invoice on htlc.me, this time for 0.00020000 tBTC ($1.31 tUSD).

$ lightning-cli decodepay lntb200u1pdvzvf8pp5tyjfw9ma9uj8hhrhqvmum9vzvaun45qg6mmesu3c08zkhmgl44ssdqqcqzysah4qe4zef3rssusa42cyx0gxxq6q06g50m38w7chz50en80dfh45fj7kdgpx474udehq22mv2pwxfky66kdjdrw88z34w8hjjdjdu6sq6zy2a4

Finally make the payment.

$ lightning-cli pay lntb200u1pdvzvf8pp5tyjfw9ma9uj8hhrhqvmum9vzvaun45qg6mmesu3c08zkhmgl44ssdqqcqzysah4qe4zef3rssusa42cyx0gxxq6q06g50m38w7chz50en80dfh45fj7kdgpx474udehq22mv2pwxfky66kdjdrw88z34w8hjjdjdu6sq6zy2a4
{
	"id": 2,
	"payment_hash": "592497177d2f247bdc770337cd958267793ad008d6f798723879c56bed1fad61",
	"destination": "03193d512b010997885b232ecd6b300917e5288de8785d6d9f619a8952728c78e8",
	"msatoshi": 20000000,
	"msatoshi_sent": 20000000,
	"timestamp": 1522610489,
	"created_at": 1522610489,
	"status": "complete",
	"payment_preimage": "1e2767675a227c7f8d57252bfe67d6324829c267f3df38396b4d2bb79a27dfd6",
	"getroute_tries": 1,
	"sendpay_tries": 1,
	"route": [{
		"id": "03193d512b010997885b232ecd6b300917e5288de8785d6d9f619a8952728c78e8",
		"channel": "1289949:56:0",
		"msatoshi": 20000000,
		"delay": 144
	}],
	"failures": []
}

This time no console errors. Your web wallet at htlc.me should immediately detect the payment. You should now be able to make any number of subsequent payments instantly and with similarly low fees until you deplete the funds in your channel or it expires.

HTLC.me confirmed received payment

Conclusion

As you can see, the nodes on testnet are sketchy to say the least. The three main lightning software implementations (lnd, c-lightning, eclair) are all still in the early stages of development so it’s not surprising that a few bugs exist. But this should at least give you a flavour of how cheap and fast transactions will be in the future when the network is bigger and the software running it more mature.

Join the discussion on medium.