{"id":20424934,"url":"https://github.com/stackzoo/lightning-network-the-hard-way","last_synced_at":"2025-04-12T18:53:34.776Z","repository":{"id":212089447,"uuid":"730683831","full_name":"stackzoo/lightning-network-the-hard-way","owner":"stackzoo","description":"Get started with the Bitcoin Lightning⚡ Network the \"hard\" way 💪","archived":false,"fork":false,"pushed_at":"2024-01-02T18:25:23.000Z","size":1398,"stargazers_count":17,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-03-26T13:11:17.140Z","etag":null,"topics":["bitcoin","blockchain","demo","lightning","lightning-network","lnd","tutorial"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stackzoo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-12-12T13:02:09.000Z","updated_at":"2024-02-04T16:43:06.000Z","dependencies_parsed_at":"2023-12-12T14:29:14.780Z","dependency_job_id":"f9bb386f-199c-44f3-99c5-53f14a5aea99","html_url":"https://github.com/stackzoo/lightning-network-the-hard-way","commit_stats":null,"previous_names":["stackzoo/lightning-network-the-hard-way"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackzoo%2Flightning-network-the-hard-way","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackzoo%2Flightning-network-the-hard-way/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackzoo%2Flightning-network-the-hard-way/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackzoo%2Flightning-network-the-hard-way/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stackzoo","download_url":"https://codeload.github.com/stackzoo/lightning-network-the-hard-way/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248618260,"owners_count":21134200,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bitcoin","blockchain","demo","lightning","lightning-network","lnd","tutorial"],"created_at":"2024-11-15T07:11:33.050Z","updated_at":"2025-04-12T18:53:34.747Z","avatar_url":"https://github.com/stackzoo.png","language":null,"readme":"# LIGHTNING NETWORK⚡ THE \"HARD\" WAY\nThe following is a reproducible proof of concept to get started with the *Bitcoin Lightning Network*.  \nIn order to follow this you dont need bitcoins on the main blockchain as we will use the *testnet*.  \n\n\u003e [!WARNING]  \n\u003e This is intended as a local lab to learn the basics of lightning node operations, don't follow this to deploy a node in production!  \n\u003e Also Keep in mind that the utilized Bitcoins hold no intrinsic value, as they pertain to the test blockchain.  \n\n## Abstract\nThe **Lightning Network** is a decentralized, off-chain scaling solution for blockchain-based cryptocurrencies, most notably designed for **Bitcoin**.  \nIntroduced to address the *scalability* limitations of traditional blockchain networks, the Lightning Network enables faster and cheaper transactions by creating a secondary layer atop the primary blockchain.  \nThis layer facilitates rapid and low-cost microtransactions through the establishment of **bi-directional payment channels** between users.  \n**Nodes**, integral components of the Lightning Network, act as participants that facilitate these off-chain transactions.  \nBy conducting most transactions off-chain and only settling the final result on the main blockchain, the Lightning Network enhances the overall efficiency, privacy, scalability, and cost-effectiveness of cryptocurrency transactions, making it a promising solution for widespread adoption and improved usability of Bitcoin.  \n\n\u003cbr/\u003e\n\nAs is customary in Bitcoin, there exists a tradeoff between user-friendliness and control:  \nnumerous custodial services are available, yet the more management is entrusted to the service provider, the less control we exert over our funds.  \n**Freedom and responsibility are directly proportional**.  \nOptimal control is achieved by running one's own Bitcoin + Lightning node and retaining possession of our private keys.  \nThis tutorial provides a foundational understanding of running a Lightning node to actively participate in the network and facilitate payment transactions.  \n\n\n\n\n## Prerequisites\n- docker\n- desire to learn about ₿itcoin \u0026 lightning⚡\n\n## Getting started\n\nFor this tutorial we will use [LND](https://github.com/lightningnetwork/lnd).  \n*LND* is one of the most popular implementations of a lightning node, written in the *Go* programming language.  \nPull a specific version of *LND container image* from *dockerhub*:  \n```console\ndocker pull lightninglabs/lnd:v0.17.3-beta\n```  \n\nNow run the container in *testnet* mode and with [neutrino](https://github.com/lightninglabs/neutrino) as a backend:  \n\n```console\ndocker run --name lnd-testnet -v /Users/rago/.lnd/:/root/.lnd  lightninglabs/lnd:v0.17.3-beta --bitcoin.active --bitcoin.testnet --bitcoin.node=neutrino neutrino.addpeer=btcd-testnet.lightning.computer neutrino.feeurl=https://nodes.lightning.computer/fees/v1/btctestnet-fee-estimates.json\n```  \n\u003e [!NOTE]  \n\u003e *Neutrino* is a lightweight client-side technology designed to enhance the privacy and efficiency of wallet applications.  \n\u003e Neutrino is an improvement upon traditional SPV, which allows users to verify the inclusion of transactions in the Bitcoin blockchain without downloading the entire blockchain.  \n\nThe previous command also maps a local volume path (my user home directory) to the `.lnd` data directory inside our container.  \nIn this way we ensure persistency of our Lightning node and wallet data even when our container stops.  \n\n\nExec inside the running container and launch the command to create a new wallet via `lncli`:  \n```console\ndocker exec -it lnd-testnet lncli create  \n```  \n\nFollow the instructions on the screen to generate a new wallet seed.  \n\nNow we need to wait some time as *neutrino* is starting to sync blocks headers for the Bitcoin testnet chain, this may take up to 1 hour with the current blockchain state.  \nYou can chek che progress by inspecting the container's logs:  \n```console\ndocker logs lnd-testnet -f\n```  \n\nOr by checking the size of the `.lnd` folder mounted on our local machine:  \n```console\ncd  ~/.lnd \u0026\u0026 watch du -sh *\n```  \nAt the current state of the blockchain (December 2023) the size of the data directory needs to reach almos *700 MB* before synchronization is completed.  \n\n\n\u003e [!NOTE]  \n\u003e All the following lncli commands will specify a macaroon to use in order to authenticate with our node.  \n\u003e A [macaroon](https://en.wikipedia.org/wiki/Macaroons_(computer_science)) is a type of token used for authentication and authorization.  \n\u003e In the realm of distributed systems, macaroons are often used to provide secure access to decentralised APIs or services.  \n\nExport an environment variable with the admin macaroon path inside our node's container:  \n```console\nexport MACAROON_PATH=/root/.lnd/data/chain/bitcoin/testnet/admin.macaroon\n```  \n\n\n\nGenerate a testnet Address via *lncli*:  \n```console\ndocker exec -it lnd-testnet lncli --macaroonpath=\"$MACAROON_PATH\" newaddress p2wkh\n```  \n\nSample output:\n```json\n{\n    \"address\": \"tb1q2usfv065frackdpzn9grar0cag8mdg5wyd7q4h\"\n}\n```  \n  \n\nNow we need to obtain some Bitcoin on the testnet.  \n\nSend some testnet bitcoin by leveraging faucet services like [coinfaucet](https://coinfaucet.eu/en/btc-testnet/), by inserting the previously generated address as the payment recipient.  \nwait for the stransaction to be validated on the testnet, you can check the progress on [mempool](https://mempool.space/testnet):  \n![transaction](images/tx.png)  \n\n\u003cbr/\u003e\n\nNow check your lightning wallet balance:  \n```console\ndocker exec -it lnd-testnet lncli --macaroonpath=\"$MACAROON_PATH\" walletbalance\n```  \nSample output:  \n```json\n{\n    \"total_balance\": \"1245885\",\n    \"confirmed_balance\": \"1245885\",\n    \"unconfirmed_balance\": \"0\",\n    \"locked_balance\": \"0\",\n    \"reserved_balance_anchor_chan\": \"0\",\n    \"account_balance\": {\n        \"default\": {\n            \"confirmed_balance\": \"1245885\",\n            \"unconfirmed_balance\": \"0\"\n        }\n    }\n}\n```  \n\n\nAs we can see we now have a total balance of *1245885* satoshis!  \nNow we need to open an outbound channel on the testnet, in order to do so choose a node from [1ml](https://1ml.com/testnet/), retrieve it's data and then request channel opening via lncli with these commands:  \n```console\nlncli connect \u003cpeer_pubkey\u003e@\u003cpeer_address\u003e\nlncli openchannel --node_key=\u003cpeer_pubkey\u003e --local_amt=\u003camount_in_satoshis\u003e\n```   \n\n\nso in our specific case, if we choose [this](https://1ml.com/testnet/node/02312627fdf07fbdd7e5ddb136611bdde9b00d26821d14d94891395452f67af248) node, the commands will be:  \n```console\ndocker exec -it lnd-testnet lncli --macaroonpath=\"$MACAROON_PATH\" connect 02312627fdf07fbdd7e5ddb136611bdde9b00d26821d14d94891395452f67af248@23.237.77.12:9735\n```   \n\nand  \n\n```console\ndocker exec -it lnd-testnet lncli --macaroonpath=\"$MACAROON_PATH\" openchannel --node_key=02312627fdf07fbdd7e5ddb136611bdde9b00d26821d14d94891395452f67af248 --local_amt=50000\n```   \n\n\n\nSample output:\n```json\n{\n        \"funding_txid\": \"bfbf2b1096d76e78cb81dc4318d0403ef63efef2b783a4ff8cad85ee39c97a33\"\n}\n```  \n\n\nNow let's list our channels:  \n```console\ndocker exec -it lnd-testnet lncli --macaroonpath=\"$MACAROON_PATH\" listchannels\n\n{\n    \"channels\": []\n}\n```  \n\n\nThis may seems strange...we have 0 channels opened.  \nIn reality this is perfectly normal as our channel funding transaction on the blockchain need to wait 3 block confirmations before it is considered settled.  \nWait some minutes and retry:  \n```json\n{\n    \"channels\": [\n        {\n            \"active\": true,\n            \"remote_pubkey\": \"02312627fdf07fbdd7e5ddb136611bdde9b00d26821d14d94891395452f67af248\",\n            \"channel_point\": \"bfbf2b1096d76e78cb81dc4318d0403ef63efef2b783a4ff8cad85ee39c97a33:0\",\n            \"chan_id\": \"2795546796528500736\",\n            \"capacity\": \"50000\",\n            \"local_balance\": \"46530\",\n            \"remote_balance\": \"0\",\n            \"commit_fee\": \"3140\",\n            \"commit_weight\": \"772\",\n            \"fee_per_kw\": \"2500\",\n            \"unsettled_balance\": \"0\",\n            \"total_satoshis_sent\": \"0\",\n            \"total_satoshis_received\": \"0\",\n            \"num_updates\": \"0\",\n            \"pending_htlcs\": [],\n            \"csv_delay\": 144,\n            \"private\": false,\n            \"initiator\": true,\n            \"chan_status_flags\": \"ChanStatusDefault\",\n            \"local_chan_reserve_sat\": \"500\",\n            \"remote_chan_reserve_sat\": \"500\",\n            \"static_remote_key\": false,\n            \"commitment_type\": \"ANCHORS\",\n            \"lifetime\": \"40\",\n            \"uptime\": \"40\",\n            \"close_address\": \"\",\n            \"push_amount_sat\": \"0\",\n            \"thaw_height\": 0,\n            \"local_constraints\": {\n                \"csv_delay\": 144,\n                \"chan_reserve_sat\": \"500\",\n                \"dust_limit_sat\": \"354\",\n                \"max_pending_amt_msat\": \"49500000\",\n                \"min_htlc_msat\": \"1\",\n                \"max_accepted_htlcs\": 483\n            },\n            \"remote_constraints\": {\n                \"csv_delay\": 144,\n                \"chan_reserve_sat\": \"500\",\n                \"dust_limit_sat\": \"354\",\n                \"max_pending_amt_msat\": \"49500000\",\n                \"min_htlc_msat\": \"1\",\n                \"max_accepted_htlcs\": 483\n            },\n            \"alias_scids\": [],\n            \"zero_conf\": false,\n            \"zero_conf_confirmed_scid\": \"0\",\n            \"peer_alias\": \"1ML.com node ALPHA\",\n            \"peer_scid_alias\": \"0\",\n            \"memo\": \"\"\n        }\n    ]\n}\n```  \n\nNow our outbound channel is open and we have sufficient funds to make some transactions!  \nGo to [this](https://starblocks.acinq.co/) e-commerce website, select the product you want, add it to cart and then click \"checkout\".  \n![shop](images/e-shop.png)  \n\nYou will be presented with an invoice similar to this:  \n![invoice](images/invoice.png)  \n\u003cbr/\u003e\n\nCopy the invoice and pay it via your lightning wallet!  \n```console\ndocker exec -it lnd-testnet lncli --macaroonpath=\"$MACAROON_PATH\" payinvoice lntb15u1pjhs4xspp5vjxce36ldeecntev4eqhusm99py89zwmjv42alraxkaj39ws5v2sdpzxysy2umswfjhxum0yppk76twypgxzmnwvyxqrrsscqp79qy9qsqsp59uwdjgu9nlkyh0e99kgpx3uflsnxrrhwrw0kmcjymmf3esrphflqge0x0eme35wcxtqgr05kx84ay0rl9j7qk9jgvl6fw987t4jxulrsqnu4mjl7dnhase7c39l4cxa5g8gsqtvwhry3psdp4zuzl7ghhuqp9qvzyh\n```   \n\nOutput Sample:  \n```console\nPayment hash: 648d8cc75f6e7389af2cae417e436528487289db932aaefc7d35bb2895d0a315\nDescription: 1 Espresso Coin Panna\nAmount (in satoshis): 1500\nFee limit (in satoshis): 75\nDestination: 0348cc1a9479697cd52db445ea74149ad40bb01bb2045a3e8acba21b70f94ab7cf\nConfirm payment (yes/no): yes\n\n+-------------------------------------+--------------+--------------+--------------+-------+----------+---------------------+-------------------------------------------------------------+\n| HTLC_STATE                          | ATTEMPT_TIME | RESOLVE_TIME | RECEIVER_AMT | FEE   | TIMELOCK | CHAN_OUT            | ROUTE                                                       |\n+-------------------------------------+--------------+--------------+--------------+-------+----------+---------------------+-------------------------------------------------------------+\n| TEMPORARY_CHANNEL_FAILURE @ 1st hop |        0.029 |        0.804 | 1500         | 1.749 |  2542794 | 2795546796528500736 | 1ML.com node ALPHA-\u003e24hr Drive Thru-\u003eendurance-\u003eeclair      |\n| TEMPORARY_CHANNEL_FAILURE @ 1st hop |        0.827 |        1.641 | 1500         | 1.764 |  2542834 | 2795546796528500736 | 1ML.com node ALPHA-\u003eTowiz_testnet-\u003eendurance-\u003eeclair        |\n| SUCCEEDED                           |        1.665 |        3.258 | 1500         | 1.85  |  2542794 | 2795546796528500736 | 1ML.com node ALPHA-\u003e02eb311fca318454d00e-\u003eendurance-\u003eeclair |\n+-------------------------------------+--------------+--------------+--------------+-------+----------+---------------------+-------------------------------------------------------------+\nAmount + fee:   1500 + 1.85 sat\nPayment hash:   648d8cc75f6e7389af2cae417e436528487289db932aaefc7d35bb2895d0a315\nPayment status: SUCCEEDED, preimage: fc510042f72e4dde9ff0566907f52b11473652351b8c591713c8b6bd47e3fc93\n```  \n\nWe succesfully completed the first payment from our own lightning node and it was hyperfast!  \n\nThe website also confirm the payment:  \n![confirmation](images/confirmed.png)  \n\u003cbr/\u003e\n\nNow list your payment via lncli:  \n```console\ndocker exec -it lnd-testnet lncli --macaroonpath=\"$MACAROON_PATH\" listpayments\n```  \nOutput sample:  \n```json\n{\n    \"payments\": [\n        {\n            \"payment_hash\": \"648d8cc75f6e7389af2cae417e436528487289db932aaefc7d35bb2895d0a315\",\n            \"value\": \"1500\",\n            \"creation_date\": \"1702385051\",\n            \"fee\": \"1\",\n            \"payment_preimage\": \"fc510042f72e4dde9ff0566907f52b11473652351b8c591713c8b6bd47e3fc93\",\n            \"value_sat\": \"1500\",\n            \"value_msat\": \"1500000\",\n            \"payment_request\": \"lntb15u1pjhs4xspp5vjxce36ldeecntev4eqhusm99py89zwmjv42alraxkaj39ws5v2sdpzxysy2umswfjhxum0yppk76twypgxzmnwvyxqrrsscqp79qy9qsqsp59uwdjgu9nlkyh0e99kgpx3uflsnxrrhwrw0kmcjymmf3esrphflqge0x0eme35wcxtqgr05kx84ay0rl9j7qk9jgvl6fw987t4jxulrsqnu4mjl7dnhase7c39l4cxa5g8gsqtvwhry3psdp4zuzl7ghhuqp9qvzyh\",\n            \"status\": \"SUCCEEDED\",\n            \"fee_sat\": \"1\",\n            \"fee_msat\": \"1850\",\n            \"creation_time_ns\": \"1702385051584619534\",\n            \"htlcs\": [\n                {\n                    \"attempt_id\": \"3\",\n                    \"status\": \"SUCCEEDED\",\n                    \"route\": {\n                        \"total_time_lock\": 2542794,\n                        \"total_fees\": \"1\",\n                        \"total_amt\": \"1501\",\n                        \"hops\": [\n                            {\n                                \"chan_id\": \"2795546796528500736\",\n                                \"chan_capacity\": \"50000\",\n                                \"amt_to_forward\": \"1500\",\n                                \"fee\": \"1\",\n                                \"expiry\": 2542754,\n                                \"amt_to_forward_msat\": \"1500849\",\n                                \"fee_msat\": \"1001\",\n                                \"pub_key\": \"02312627fdf07fbdd7e5ddb136611bdde9b00d26821d14d94891395452f67af248\",\n                                \"tlv_payload\": true,\n                                \"mpp_record\": null,\n                                \"amp_record\": null,\n                                \"custom_records\": {},\n                                \"metadata\": \"\"\n                            },\n                            {\n                                \"chan_id\": \"2479405317705302016\",\n                                \"chan_capacity\": \"0\",\n                                \"amt_to_forward\": \"1500\",\n                                \"fee\": \"0\",\n                                \"expiry\": 2542714,\n                                \"amt_to_forward_msat\": \"1500748\",\n                                \"fee_msat\": \"101\",\n                                \"pub_key\": \"02eb311fca318454d00ed19fee12b5fe3bb6058034a1cb0f1e094d2c075ff93ee7\",\n                                \"tlv_payload\": true,\n                                \"mpp_record\": null,\n                                \"amp_record\": null,\n                                \"custom_records\": {},\n                                \"metadata\": \"\"\n                            },\n                            {\n                                \"chan_id\": \"2467607557938741248\",\n                                \"chan_capacity\": \"0\",\n                                \"amt_to_forward\": \"1500\",\n                                \"fee\": \"0\",\n                                \"expiry\": 2542570,\n                                \"amt_to_forward_msat\": \"1500000\",\n                                \"fee_msat\": \"748\",\n                                \"pub_key\": \"03933884aaf1d6b108397e5efe5c86bcf2d8ca8d2f700eda99db9214fc2712b134\",\n                                \"tlv_payload\": true,\n                                \"mpp_record\": null,\n                                \"amp_record\": null,\n                                \"custom_records\": {},\n                                \"metadata\": \"\"\n                            },\n                            {\n                                \"chan_id\": \"2656582820430282753\",\n                                \"chan_capacity\": \"0\",\n                                \"amt_to_forward\": \"1500\",\n                                \"fee\": \"0\",\n                                \"expiry\": 2542570,\n                                \"amt_to_forward_msat\": \"1500000\",\n                                \"fee_msat\": \"0\",\n                                \"pub_key\": \"0348cc1a9479697cd52db445ea74149ad40bb01bb2045a3e8acba21b70f94ab7cf\",\n                                \"tlv_payload\": true,\n                                \"mpp_record\": {\n                                    \"payment_addr\": \"2f1cd923859fec4bbf252d90134789fc26618eee1b9f6de244ded31cc061ba7e\",\n                                    \"total_amt_msat\": \"1500000\"\n                                },\n                                \"amp_record\": null,\n                                \"custom_records\": {},\n                                \"metadata\": \"\"\n                            }\n                        ],\n                        \"total_fees_msat\": \"1850\",\n                        \"total_amt_msat\": \"1501850\"\n                    },\n                    \"attempt_time_ns\": \"1702385053250075643\",\n                    \"resolve_time_ns\": \"1702385054843316633\",\n                    \"failure\": null,\n                    \"preimage\": \"fc510042f72e4dde9ff0566907f52b11473652351b8c591713c8b6bd47e3fc93\"\n                }\n            ],\n            \"payment_index\": \"1\",\n            \"failure_reason\": \"FAILURE_REASON_NONE\"\n        }\n    ],\n    \"first_index_offset\": \"1\",\n    \"last_index_offset\": \"1\",\n    \"total_num_payments\": \"0\"\n}\n```  \n\n\n\n\n\n\n\n\n## Conclusions\nIn this tutorial we saw the following:\n\n- spin up our own lightning node (*LND*)\n- create a new wallet\n- get some btc on the testnet\n- open a new outbound channel\n- use the channel to buy a product from a website\n\nIf you also want to be able to receive payment you need an inbound channel.  \nThe procedure for this is similar in the sense that there are some services that will open channels with you, in exchange for a small fee.  \n\nUsually you need to specify your node key in order for other nodes to be able to open channels with you.  \nYou can determine your node pubkey with the following command:\n\n```console\ndocker exec -it lnd-testnet lncli --macaroonpath=\"$MACAROON_PATH\" getinfo | grep identity_pubkey\n```\n\nOutput sample:  \n```json\n\"identity_pubkey\": \"0314751865d1456b5f091d79cd21e647a6ebf445d38b5aac77eb8d902bbbfa8642\"\n```  \n\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstackzoo%2Flightning-network-the-hard-way","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstackzoo%2Flightning-network-the-hard-way","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstackzoo%2Flightning-network-the-hard-way/lists"}