mirror of
https://github.com/lnbook/lnbook
synced 2024-11-18 21:28:03 +00:00
Merge pull request #740 from Roasbeef/pay-channel-edits
ch-07: technical edits to payment channels chapter
This commit is contained in:
commit
ea333901cc
@ -68,7 +68,7 @@ Let's assume that Alice wants to construct a payment channel allowing her to con
|
|||||||
Every node on the Lightning Network is identified by a _node public key_. The public key uniquely identifies the specific node and is usually presented as a hexadecimal encoding. For example, Rene Pickhardt currently runs a Lightning Node (+ln.rene-pickhardt.de+) that is identified by the following node public key:
|
Every node on the Lightning Network is identified by a _node public key_. The public key uniquely identifies the specific node and is usually presented as a hexadecimal encoding. For example, Rene Pickhardt currently runs a Lightning Node (+ln.rene-pickhardt.de+) that is identified by the following node public key:
|
||||||
|
|
||||||
----
|
----
|
||||||
03efccf2c383d7bf340da9a3f02e2c23104a0e4fe8ac1a880c8e2dc92fbdacd9df
|
02a1cebfacb2674143b5ad0df3c22c609e935f7bc0ebe801f37b8e9023d45ea7b8
|
||||||
----
|
----
|
||||||
|
|
||||||
Each node generates a root private key when first initialized. The private key is kept private at all times (never shared) and securely stored in the node's wallet. From that private key, the node derives a public key which is the node identifier and shared with the network. Since the key space is enormous, as long as each node generates the private key randomly, it will have a unique public key, which can therefore uniquely identify it on the network.
|
Each node generates a root private key when first initialized. The private key is kept private at all times (never shared) and securely stored in the node's wallet. From that private key, the node derives a public key which is the node identifier and shared with the network. Since the key space is enormous, as long as each node generates the private key randomly, it will have a unique public key, which can therefore uniquely identify it on the network.
|
||||||
@ -83,10 +83,10 @@ TCP/Tor:: A Tor "onion" address and TCP port number
|
|||||||
|
|
||||||
The network address identifier is written as +Address:Port+, which is consistent with international standards for network identifiers, as used for example on the web.
|
The network address identifier is written as +Address:Port+, which is consistent with international standards for network identifiers, as used for example on the web.
|
||||||
|
|
||||||
For example, Rene's node with node public key +03efcc...acd9df+ currently advertises it's network address as the TCP/IP address:
|
For example, Rene's node with node public key +02a1ceb...45ea7b8+ currently advertises it's network address as the TCP/IP address:
|
||||||
|
|
||||||
----
|
----
|
||||||
144.76.235.20:9735
|
172.16.235.20:9735
|
||||||
----
|
----
|
||||||
|
|
||||||
[TIP]
|
[TIP]
|
||||||
@ -101,7 +101,7 @@ Together the node public key and network address are written in the following fo
|
|||||||
So the full identifier for Rene's node would be:
|
So the full identifier for Rene's node would be:
|
||||||
|
|
||||||
----
|
----
|
||||||
03efccf2c383d7bf340da9a3f02e2c23104a0e4fe8ac1a880c8e2dc92fbdacd9df@144.76.235.20:9735
|
02a1cebfacb2674143b5ad0df3c22c609e935f7bc0ebe801f37b8e9023d45ea7b8@172.16.235.20:9735
|
||||||
----
|
----
|
||||||
|
|
||||||
[TIP]
|
[TIP]
|
||||||
@ -150,14 +150,14 @@ In "<<funding_message_flow>>" Alice and Bob's nodes are represented by the verti
|
|||||||
|
|
||||||
The channel establishment involves three parts. First, the two peers communicate their capabilities and expectations, with Alice initiating a request through +open_channel+ and Bob accepting the channel request through +accept_channel+.
|
The channel establishment involves three parts. First, the two peers communicate their capabilities and expectations, with Alice initiating a request through +open_channel+ and Bob accepting the channel request through +accept_channel+.
|
||||||
|
|
||||||
Second, Alice constructs the funding and refund transactions (as we will see later in this section) and sends +funding_created+ to Bob. Bob responds by sending back the necessary signatures with +funding_signed+. This interaction is the basis for the _cryptographic protocol_ to secure the channel and prevent theft. Alice will now broadcast the funding transaction (on-chain), to establish and anchor the payment channel. The transaction will need to be confirmed on the Bitcoin blockchain.
|
Second, Alice constructs the funding and refund transactions (as we will see later in this section) and sends +funding_created+ to Bob. Another name for the "refund" transaction is a "commitment" transaction, as it commits to the current distribution of balances in the channel. Bob responds by sending back the necessary signatures with +funding_signed+. This interaction is the basis for the _cryptographic protocol_ to secure the channel and prevent theft. Alice will now broadcast the funding transaction (on-chain), to establish and anchor the payment channel. The transaction will need to be confirmed on the Bitcoin blockchain.
|
||||||
|
|
||||||
[TIP]
|
[TIP]
|
||||||
====
|
====
|
||||||
The name of the +funding_signed+ message can be a bit confusing. This message does not contain a signature for the funding transaction but it rather contains Bob's signature for the refund transaction that allows Alice to claim her bitcoin back from the multisig.
|
The name of the +funding_signed+ message can be a bit confusing. This message does not contain a signature for the funding transaction but it rather contains Bob's signature for the refund transaction that allows Alice to claim her bitcoin back from the multisig.
|
||||||
====
|
====
|
||||||
|
|
||||||
Once the transaction has sufficient confirmations, Alice and Bob exchange a +funding_locked+ messages and the channel enters normal operating mode.
|
Once the transaction has sufficient confirmations (as defined my the `minimum_depth` field in the `accept_channel` message), Alice and Bob exchange a +funding_locked+ messages and the channel enters normal operating mode.
|
||||||
|
|
||||||
===== The open_channel message
|
===== The open_channel message
|
||||||
|
|
||||||
@ -197,9 +197,9 @@ chain_hash:: This identifies which blockchain (e.g. Bitcoin mainnet) will be use
|
|||||||
|
|
||||||
funding_satoshis:: The amount Alice will use to fund the channel, which is the total channel capacity.
|
funding_satoshis:: The amount Alice will use to fund the channel, which is the total channel capacity.
|
||||||
|
|
||||||
push_msat:: An optional amount that Alice will immediately "push" to Bob as a payment upon channel funding. **Setting this value to anything but 0 means effectively gifting money to your channel partner and should be down with caution.**
|
push_msat:: An optional amount that Alice will immediately "push" to Bob as a payment upon channel funding. **Setting this value to anything but 0 means effectively gifting money to your channel partner and should be used with caution.**
|
||||||
|
|
||||||
to_self_delay:: A very important security parameter for the protocol. If Alice at any time unilaterally closes the channel against the will of Bob she commits to not accessing her own funds for the delay defined here. The higher this value the more security Bob has but the longer Alice might have to have her funds locked.
|
to_self_delay:: A very important security parameter for the protocol. The value in the `open_channel` message is used in the responder's commitment transaction, and the `accept_channel` the initiator's. This asymmetry exists to allow each side to express how long the other side needs to wait to unilaterally claim the funds in a commitment transaction. If Bob at any time unilaterally closes the channel against the will of Alice he commits to not accessing his own funds for the delay defined here. The higher this value the more security Alice has but the longer Bob might have to have his funds locked.
|
||||||
|
|
||||||
funding_pubkey:: The public key Alice will contribute to the 2-of-2 multisig that anchors this channel.
|
funding_pubkey:: The public key Alice will contribute to the 2-of-2 multisig that anchors this channel.
|
||||||
|
|
||||||
@ -259,6 +259,9 @@ Alice's node constructs a multisignature script as shown in <<A_B_multisig>> bel
|
|||||||
2 <Alice_funding_pubkey> <Bob_funding_pubkey> 2 CHECKMULTISIG
|
2 <Alice_funding_pubkey> <Bob_funding_pubkey> 2 CHECKMULTISIG
|
||||||
----
|
----
|
||||||
|
|
||||||
|
Note that in practice, the funding keys are deterministically _sorted_ (using lexicographical order of the serialized compressed form of the public keys) before being placed in the witness script (. By agreeing to this sorted order ahead of time, we ensure both parties will construct an identical funding transaction output, which is signed by the commitment transaction signature exchanged.
|
||||||
|
|
||||||
|
|
||||||
This script is encoded as a Pay-to-Witness-Script-Hash Bitcoin address, that looks something like this:
|
This script is encoded as a Pay-to-Witness-Script-Hash Bitcoin address, that looks something like this:
|
||||||
|
|
||||||
----
|
----
|
||||||
@ -328,7 +331,7 @@ The introduction of SegWit made unconfirmed transaction IDs immutable, meaning t
|
|||||||
|
|
||||||
[TIP]
|
[TIP]
|
||||||
====
|
====
|
||||||
You might have wondered how Bob would be able to alter (malleate) a transaction created and signed by Alice. Bob certainly does not have Alice's private keys. However ECDSA signatures for a message are not unique. Knowing a signature (which is included in a valid transaction) allows one to produce many different looking signatures that are still valid. Before SegWit made this impossible, Bob could replace the signature with and equivalent valid signature that produced a different transaction ID, breaking the chain between the funding transaction and the refund transaction.
|
You might have wondered how Bob would be able to alter (malleate) a transaction created and signed by Alice. Bob certainly does not have Alice's private keys. However ECDSA signatures for a message are not unique. Knowing a signature (which is included in a valid transaction) allows one to produce many different looking signatures that are still valid. Before SegWit removed signatures from the transaction digest algorithm, Bob could replace the signature with an equivalent valid signature that produced a different transaction ID, breaking the chain between the funding transaction and the refund transaction.
|
||||||
====
|
====
|
||||||
|
|
||||||
===== The funding_created message
|
===== The funding_created message
|
||||||
@ -366,6 +369,8 @@ After receiving the +funding_created+ message from Alice, Bob now knows the fun
|
|||||||
channel_id = funding_txid XOR funding_output_index
|
channel_id = funding_txid XOR funding_output_index
|
||||||
----
|
----
|
||||||
|
|
||||||
|
More precisely, a `channel_id`, which is the 32 byte representation of a funding UTXO, is generated by XOR'ing the lower 2-bytes of the funding TXID with the index of the funding output.
|
||||||
|
|
||||||
Bob will also need to send Alice his signature for the refund transaction, based on Bob's funding_pubkey which formed the 2-of-2 multisig. While Bob already has his local refund transaction this will allow Alice to complete the refund transaction with all necessary signatures and be sure her money is refundable in case something goes wrong.
|
Bob will also need to send Alice his signature for the refund transaction, based on Bob's funding_pubkey which formed the 2-of-2 multisig. While Bob already has his local refund transaction this will allow Alice to complete the refund transaction with all necessary signatures and be sure her money is refundable in case something goes wrong.
|
||||||
|
|
||||||
Bob constructs a +funding_signed+ message and sends it to Alice. In <<funding_signed_message>> below, we see the contents of this message:
|
Bob constructs a +funding_signed+ message and sends it to Alice. In <<funding_signed_message>> below, we see the contents of this message:
|
||||||
@ -480,7 +485,7 @@ Bob holds the mirror-image of that transaction, where the first output is 80,000
|
|||||||
|
|
||||||
==== Delayed (timelocked) spending to_self
|
==== Delayed (timelocked) spending to_self
|
||||||
|
|
||||||
The purpose of holding asymmetric transactions is so that the _to_local_ output is always timelocked and can't be spent immediately, whereas the _to_remote_ output is not timelocked and can be spent immediately.
|
Using asymmetric transactions allows the protocol to easily ascribe _blame_ to the cheating party. An invariant that the _broadcasting_ party must always wait ensures that the "honest" party has time to refute the claim, and revoke their funds. This aymmetry is manifested in the form of differing outputs for each side: the _to_local_ output is always timelocked and can't be spent immediately, whereas the _to_remote_ output is not timelocked and can be spent immediately.
|
||||||
|
|
||||||
In the commitment transaction held by Alice, for example, the _to_local_ output that pays her is timelocked for 432 blocks, whereas the _to_remote_ output that pays Bob can be spent immediately. Bob's commitment transaction for Commitment #2 is the mirror image: his own (_to_local_) output is timelocked and Alice's _to_remote_ output can be spent immediately.
|
In the commitment transaction held by Alice, for example, the _to_local_ output that pays her is timelocked for 432 blocks, whereas the _to_remote_ output that pays Bob can be spent immediately. Bob's commitment transaction for Commitment #2 is the mirror image: his own (_to_local_) output is timelocked and Alice's _to_remote_ output can be spent immediately.
|
||||||
|
|
||||||
@ -610,6 +615,10 @@ Once Alice has received the +revoke_and_ack+ from Bob she can be sure that Bob c
|
|||||||
|
|
||||||
In practice, both Alice and Bob have to monitor for "cheating". They are monitoring the Bitcoin blockchain for any commitment transactions related to any of the channels they are operating. If they see a commitment transaction confirmed on-chain they will check to see if it is the most recent commitment. If it is an "old" commitment, they must immediately construct and broadcast a penalty transaction. The penalty transaction spends *both* the +to_local+ and +to_remote+ outputs, closing the channel and sending both balances to the "cheated" channel partner.
|
In practice, both Alice and Bob have to monitor for "cheating". They are monitoring the Bitcoin blockchain for any commitment transactions related to any of the channels they are operating. If they see a commitment transaction confirmed on-chain they will check to see if it is the most recent commitment. If it is an "old" commitment, they must immediately construct and broadcast a penalty transaction. The penalty transaction spends *both* the +to_local+ and +to_remote+ outputs, closing the channel and sending both balances to the "cheated" channel partner.
|
||||||
|
|
||||||
|
In order to more easily allow both sides to keep track of the commitment numbers of the passed revoke commitments, each commitment actually _encodes_ the number of the commitment within the lock time and sequence fields in a transition. Within the protocol, this special encoding are referred to as "state hints". Assuming a party knows the current commitment number, they're able to use the state hints to easily recognize if a broadcasted commitment was a revoked one, and if so, which commitment number was breached, as that number is used to easily look up which revocation secret should be used in the revocation secret tree (shachain).
|
||||||
|
|
||||||
|
Rather than encode the state hint in plain site, as _obfuscated_ state hint is used in its place. This obfuscation is achieved by first XOR'ing the current commitment number with a set of random bytes generated deterministically using the funding public keys of both sides of the channel. A total of 6 bytes across the lock time and sequence (24 bits of the locktime and 24 bits of the sequence) are used to encode the state hint within the commitment transaction, so 6 random bytes are needed to use for XOR'ing. To obtain these 6 bytes, both sides obtain the SHA-256 hash of the initiator's funding key concatenated to the responder's funding key. Before encoding the current commitment height, the integer is XOR'd with this state hint obfuscater, and then encoded in the lower 24 bits of the locktime, and the upper 64 bits of the sequence.
|
||||||
|
|
||||||
Let's review our channel between Alice and Bob and show a specific example of a penalty transaction. In <<competing_commitments_2>> we see the four commitments on Alice and Bob's channel. Alice has made three payments to Bob:
|
Let's review our channel between Alice and Bob and show a specific example of a penalty transaction. In <<competing_commitments_2>> we see the four commitments on Alice and Bob's channel. Alice has made three payments to Bob:
|
||||||
|
|
||||||
* 70,000 satoshis paid and committed to Bob with Commitment #1
|
* 70,000 satoshis paid and committed to Bob with Commitment #1
|
||||||
@ -706,6 +715,8 @@ Once Alice receives a +closing_signed+ message with the same fee as the one she
|
|||||||
|
|
||||||
The cooperative close transaction looks similar to the last commitment transaction that Alice and Bob had agreed on. However, unlike the last commitment transaction, it does not have timelocks or penalty revocation keys in the outputs. Since both parties cooperate to produce this transaction and they won't be making any further commitments, there is no need for the asymmetric, delayed and revocable elements in this transaction.
|
The cooperative close transaction looks similar to the last commitment transaction that Alice and Bob had agreed on. However, unlike the last commitment transaction, it does not have timelocks or penalty revocation keys in the outputs. Since both parties cooperate to produce this transaction and they won't be making any further commitments, there is no need for the asymmetric, delayed and revocable elements in this transaction.
|
||||||
|
|
||||||
|
Typically the addresses used in this cooperative close transaction are generated freshly for each channel being closed. However, it's also possible for both sides to _lock in_ a "delivery" address to be used to send their cooperatively settled funds to. Within the TLV namespace of both the `open_channel` and `accept_channel` messages, both sides are free to specify an "upfront shutdown script". Commonly, this address is derived from keys that reside in cold storage. This practice serves to increase the securtiy of channels, as if a party is somehow hacked, then they hacker isn't able to cooperatively close the channel to an address they confirm. Instead, the non-hacked honest party will refuse to execute a cooperative channel closure if the specified upfront shutdown address isn't used. This feature effectively creates a "closed loop", restricting the flow of funds out of a given channel.
|
||||||
|
|
||||||
Alice broadcasts a transaction shown in <<closing_transaction>> below to close the channel:
|
Alice broadcasts a transaction shown in <<closing_transaction>> below to close the channel:
|
||||||
|
|
||||||
[[closing_transaction]]
|
[[closing_transaction]]
|
||||||
|
Loading…
Reference in New Issue
Block a user