You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lnbook/09_channel_operation.asciidoc

359 lines
26 KiB
Plaintext

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

[[channel_operation]]
== Channel Operation and pass:[<span class="keep-together">Payment Forwarding</span>]
((("payment channel","operation", id="ix_09_channel_operation-asciidoc0", range="startofrange")))In this chapter we will bring together payment channels and hash time-locked contracts (HTLCs). In <<payment_channels>>, we explained the way Alice and Bob construct a payment channel between their two nodes. We also looked at the commitment and penalty mechanisms that secure the payment channel. In <<routing>>, we looked at HTLCs and how these can be used to route a payment across a path made of multiple payment channels. In this chapter we bring the two concepts together by looking at how HTLCs are managed on each payment channel, how the HTLCs are committed to the channel state, and how they are settled to update the channel balances.
Specifically, we will be discussing "Adding, settling, failing HTLCs" and the "Channel state machine" that form the overlap between the peer-to-peer layer and the routing layer, as highlighted by an outline in <<LN_protocol_channelops_highlight>>.
[[LN_protocol_channelops_highlight]]
.Channel operation and payment forwarding in the Lightning protocol suite
image::images/mtln_0901.png["Channel operation and payment forwarding in the Lightning protocol suite"]
=== Local (Single Channel) Versus Routed (Multiple Channels)
((("payment channel","local channel versus routed channels")))Even though it is possible to send payments across a payment channel simply by updating the channel balances and creating new commitment transactions, the Lightning protocol uses HTLCs even for "local" payments across a payment channel. The reason for this is to maintain the same protocol design regardless of whether a payment is only one hop (across a single payment channel) or several hops (routed across multiple payment channels).
By maintaining the same abstraction for both local and remote, we not only simplify the protocol design but also improve privacy. For the recipient of a payment there is no discernible difference between a payment made directly by their channel partner and a payment forwarded by their channel partner on behalf of someone else.
=== Forwarding Payments and Updating Commitments pass:[<span class="keep-together">with HTLCs</span>]
((("commitment transactions","updating commitments with HTLCs", id="ix_09_channel_operation-asciidoc1", range="startofrange")))((("hash time-locked contracts (HTLCs)","updating commitments with", id="ix_09_channel_operation-asciidoc2", range="startofrange")))((("payment channel","updating commitments with HTLCs", id="ix_09_channel_operation-asciidoc3", range="startofrange")))We will revisit our example from <<routing>> to demonstrate how the HTLCs from Alice to Dina get committed to each payment channel. As you recall in our example, Alice is paying Dina 50,000 satoshis by routing an HTLC via Bob and Chan. The network is shown in <<alice_dina_htlc_2>>.
[[alice_dina_htlc_2]]
.Alice pays Dina with an HTLC routed via Bob and Chan
image::images/mtln_0809.png["Alice pays Dina with an HTLC routed via Bob and Chan"]
We will focus on the payment channel between Alice and Bob and review the messages and transactions that they use to process this HTLC.
==== HTLC and Commitment Message Flow
((("hash time-locked contracts (HTLCs)","commitment message flow")))The message flow between Alice and Bob (and also between any pair of channel partners) is shown in <<HTLC_commitment_message_flow>>.
[[HTLC_commitment_message_flow]]
.The message flow for HTLC commitment between channel partners
image::images/mtln_0903.png["The message flow for HTLC commitment between channel partners"]
[role="pagebreak-before"]
We've already seen the +commitment_signed+ and +revoke_and_ack+ in <<payment_channels>>. Now we will see how HTLCs fit into the commitment scheme. The two new messages are +update_add_htlc+, which Alice uses to ask Bob to add an HTLC, and +update_fulfill_htlc+, which Bob uses to redeem the HTLC once he has received the payment secret (Dina's secret).(((range="endofrange", startref="ix_09_channel_operation-asciidoc3")))(((range="endofrange", startref="ix_09_channel_operation-asciidoc2")))(((range="endofrange", startref="ix_09_channel_operation-asciidoc1")))
=== Forwarding Payments with HTLCs
((("hash time-locked contracts (HTLCs)","forwarding payments with", id="ix_09_channel_operation-asciidoc4", range="startofrange")))((("payment forwarding","with HTLCs", id="ix_09_channel_operation-asciidoc5", range="startofrange")))Alice and Bob start with a payment channel that has a 70,000 satoshi balance on each side.
As we saw in <<payment_channels>>, this means that Alice and Bob have negotiated and each hold commitment transactions. These commitment transactions are asymmetric, delayed, and revocable, and look like the example in <<alice_bob_commitment_txs_1>>.
[[alice_bob_commitment_txs_1]]
.Alice and Bob's initial commitment transactions
image::images/mtln_0904.png["Alice and Bob's initial commitment transactions"]
==== Adding an HTLC
((("hash time-locked contracts (HTLCs)","adding an HTLC")))Alice wants Bob to accept an HTLC worth 50,200 satoshis to forward to Dina. To do so, Alice must send the details of this HTLC, including the payment hash and amount, to Bob. Bob will also need to know where to forward it, which is something we discuss in detail in <<onion_routing>>.
To add the HTLC, Alice starts the flow we saw in <<HTLC_commitment_message_flow>> by sending the +update_add_htlc+ message to Bob.
[[update_add_htlc]]
==== The update_add_HTLC Message
((("hash time-locked contracts (HTLCs)","update_add_HTLC message")))((("update_add_HTLC message")))Alice sends the `update_add_HTLC` Lightning message to Bob. This message is defined in https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md#adding-an-htlc-update_add_htlc[BOLT #2: Peer Protocol, `update_add_HTLC`], and is shown in Example 9-1.
[[update_add_HTLC_message_fields]]
.The `update_add_HTLC` message
====
----
[channel_id:channel_id]
[u64:id]
[u64:amount_msat]
[sha256:payment_hash]
[u32:cltv_expiry]
[1366*byte:onion_routing_packet]
----
====
+channel_id+:: This is the channel that Alice has with Bob where she wants to add the HTLC. Remember that Alice and Bob may have multiple channels with each other.
+id+:: This is an HTLC counter and starts at +0+ for the first HTLC offered to Bob by Alice and is incremented for each subsequent offered HTLC.
+amount_msat+:: This is the amount (value) of the HTLC in millisatoshis. In our example this is 50,200,000 millisatoshis (i.e., 50,200 satoshis).
+payment_hash+:: This is the payment hash calculated from Dina's invoice. It is _H_ = RIPEMD160(SHA-256(_R_)), where _R_ is Dina's secret that is known only by Dina and will be revealed if Dina is paid.
+cltv_expiry+:: This is the expiry time for this HTLC, which will be encoded as a time-locked refund in case the HTLC fails to reach Dina in this time.
+onion_routing_packet+:: This is an onion-encrypted route that tells Bob where to forward this HTLC next (to Chan). Onion routing is covered in detail in <<onion_routing>>.
[TIP]
====
As a reminder, accounting within the Lightning Network is in units of millisatoshis (thousandths of a satoshi), whereas Bitcoin accounting is in satoshis. Any amounts in HTLCs are millisatoshis, which are then rounded to the nearest satoshi in the Bitcoin commitment transactions.
====
==== HTLC in Commitment Transactions
((("commitment transactions","HTLC in")))((("hash time-locked contracts (HTLCs)","commitment transactions and")))The received information is enough for Bob to create a new commitment transaction. The new commitment transaction has the same two outputs +to_self+ and +to_remote+ for Alice and Bob's balance, and a _new_ output representing the HTLC offered by Alice.
We've already seen the basic structure of an HTLC in <<routing>>. The complete script of an offered HTLC is defined in https://github.com/lightningnetwork/lightning-rfc/blob/master/03-transactions.md#offered-htlc-outputs[BOLT #3: Transactions, Offered HTLC Output] and is shown in <<offered_htlc_output_script>>.
[[offered_htlc_output_script]]
.Offered HTLC output script
====
[source,text,linenums]
----
# Revocation <1>
OP_DUP OP_HASH160 <RIPEMD160(SHA256(revocationpubkey))> OP_EQUAL
OP_IF
OP_CHECKSIG
OP_ELSE
<remote_HTLCpubkey> OP_SWAP OP_SIZE 32 OP_EQUAL
OP_IF
# Redemption <2>
OP_HASH160 <RIPEMD160(payment_hash)> OP_EQUALVERIFY
2 OP_SWAP <local_HTLCpubkey> 2 OP_CHECKMULTISIG
OP_ELSE
# Refund <3>
OP_DROP <cltv_expiry> OP_CHECKLOCKTIMEVERIFY OP_DROP
OP_CHECKSIG
OP_ENDIF
OP_ENDIF
----
<1> The first clause of the `OP_IF` conditional is redeemable by Alice with a revocation key. If this commitment is later revoked, Alice will have a revocation key to claim this output in a penalty transaction, taking the whole channel balance.
<2> The second clause is redeemable by the preimage (payment secret, or in our example, Dina's secret) if it is revealed. This allows Bob to claim this output if he has the secret from Dina, meaning he has successfully delivered the payment to Dina.
<3> The third and final clause is a refund of the HTLC to Alice if the HTLC expires without reaching Dina. It is time-locked with the expiration +cltv_expiry+. This ensures that Alice's balance is not "stuck" in an HTLC that can't be routed to Dina.
====
There are three ways to claim this output. Try to read the script and see if you can figure it out (remember, it is a stack-based language, so things appear "backward").
==== New Commitment with HTLC Output
((("commitment transactions","new commitment with HTLC output", id="ix_09_channel_operation-asciidoc6", range="startofrange")))((("hash time-locked contracts (HTLCs)","new commitment with HTLC output", id="ix_09_channel_operation-asciidoc7", range="startofrange")))Bob now has the necessary information to add this HTLC script as an additional output and create a new commitment transaction. Bob's new commitment will have 50,200 satoshis in the HTLC output. That amount will come from Alice's channel balance, so Alice's new balance will be 19,800 satoshis (70,000 50,200 = 19,800). Bob constructs this commitment as a tentative "Commitment #3," shown in <<add_commitment_3b>>.
[[add_commitment_3b]]
.Bob's new commitment with an HTLC output
image::images/mtln_0905.png["Bob's new commitment with an HTLC output"]
[role="pagebreak-before less_space"]
==== Alice Commits
Shortly after sending the +update_add_htlc+ message, she will commit to the new state of the channel, so that the HTLC can be safely added by Bob. Bob has the HTLC information and has constructed a new commitment but does not yet have this new commitment signed by Alice.
Alice sends +commitment_signed+ to Bob, with the signature for the new commitment and for the HTLC within. We saw the +commitment_signed+ message in <<payment_channels>>, but now we can understand the rest of the fields. As a reminder, it is shown in <<ops_commitment_signed_message>>.
[[ops_commitment_signed_message]]
.The `commitment_signed` message
====
----
[channel_id:channel_id]
[signature:signature]
[u16:num_htlcs]
[num_htlcs*signature:htlc_signature]
----
====
The fields +num_htlcs+ and +htlc_signature+ now make more sense:
+num_htlcs+:: This is the number of HTLCs that are outstanding in the commitment transaction. In our example, just one HTLC, the one Alice offered.
+htlc_signature+:: This is an array of signatures (+num_htlcs+ in length), containing signatures for the HTLC outputs.
Alice can send these signatures without hesitation: she can always get a refund if the HTLC expires without being routed to Dina.
Now, Bob has a new signed commitment transaction, as shown in <<signed_commitment_3b>>.
[[signed_commitment_3b]]
.Bob has a new signed commitment
image::images/mtln_0906.png[Bob has a new signed commitment]
==== Bob Acknowledges New Commitment and Revokes Old One
((("hash time-locked contracts (HTLCs)","acknowledging new commitment/revoking old commitment")))Now that Bob has a new signed commitment, he needs to acknowledge it and revoke the old commitment. ((("revoke_and_ack message", id="ix_09_channel_operation-asciidoc8", range="startofrange")))He does so by sending the +revoke_and_ack+ message, as we saw in <<payment_channels>> previously. As a reminder, that message is shown in <<revoke_and_ack_message_2>>.
[[revoke_and_ack_message_2]]
.The +revoke_and_ack+ message
====
----
[channel_id:channel_id]
[32*byte:per_commitment_secret]
[point:next_per_commitment_point]
----
====
Bob sends the +per_commitment_secret+ that allows Alice to construct a revocation key to build a penalty transaction spending Bob's old commitment. Once Bob has sent this, he can never publish "Commitment #2" without risking a penalty transaction and losing all his money. So, the old commitment is effectively revoked.
Bob has effectively moved the channel state forward, as shown in <<revoked_commitment_2b>>.
[[revoked_commitment_2b]]
.Bob has revoked the old commitment
image::images/mtln_0907.png[Bob has revoked the old commitment]
Despite the fact that Bob has a new (signed) commitment transaction and an HTLC output inside, he cannot consider his HTLC as being set up successfully.
He first needs to have Alice revoke her old commitment, because otherwise, Alice can roll back her balance to 70,000 satoshis. Bob needs to make sure that Alice also has a commitment transaction containing the HTLC and has revoked the old commitment.
That is why, if Bob is not the final recipient of the HTLC funds, he should not forward the HTLC yet by offering an HTLC on the next channel with Chan.
Alice has constructed a mirror-image new commitment transaction containing the new HTLC, but it is yet to be signed by Bob. We can see it in <<add_commitment_3a>>.
[[add_commitment_3a]]
.Alice's new commitment with an HTLC output
image::images/mtln_0908.png["Alice's new commitment with an HTLC output"]
As we described in <<payment_channels>>, Alice's commitment is the mirror image of Bob's, as it contains the asymmetric, delayed, revocable construct for revocation and penalty enforcement of old commitments. Alice's 19,800 satoshi balance (after deducting the HTLC value), is delayed and revocable. Bob's 70,000 satoshi balance is immediately redeemable.
Next, the message flow for +commitment_signed+ and +revoke_and_ack+ is now repeated, but in the opposite direction. Bob sends +commitment_signed+ to sign Alice's new commitment, and Alice responds by revoking her old commitment.(((range="endofrange", startref="ix_09_channel_operation-asciidoc8")))
For completeness sake, let's quickly review the commitment transactions as this round of commitment/revocation happens.
[role="pagebreak-before less_space"]
==== Bob Commits
Bob now sends a +commitment_signed+ back to Alice, with his signatures for Alice's new commitment transaction, including the HTLC output she has added.
Now Alice has the signature for the new commitment transaction. The state of the channel is shown in <<signed_commitment_3a>>.
[[signed_commitment_3a]]
.Alice has a new signed commitment
image::images/mtln_0909.png[Alice has a new signed commitment]
Alice can now acknowledge the new commitment by revoking the old one. Alice sends the +revoke_and_ack+ message containing the necessary +per_commitment_point+ that will allow Bob to construct a revocation key and penalty transaction. Thus, Alice revokes her old commitment.
The channel state is shown in <<revoked_commitment_2a>>.(((range="endofrange", startref="ix_09_channel_operation-asciidoc7")))(((range="endofrange", startref="ix_09_channel_operation-asciidoc6"))) (((range="endofrange", startref="ix_09_channel_operation-asciidoc5")))(((range="endofrange", startref="ix_09_channel_operation-asciidoc4")))
[[revoked_commitment_2a]]
.Alice has revoked the old commitment
image::images/mtln_0910.png[Alice has revoked the old commitment]
=== Multiple HTLCs
((("hash time-locked contracts (HTLCs)","multiple contracts")))At any point in time, Alice and Bob may have dozens or even hundreds of HTLCs across a single channel. Each HTLC is offered and added to the commitment transaction as an additional output. A commitment transaction therefore always has two outputs for the channel partner balances and any number of HTLC outputs, one per HTLC.
As we saw in the +commitment_signed+ message, there is an array for HTLC signatures so that multiple HTLC commitments can be transmitted at the same time.
The current maximum number of HTLCs allowed on a channel is 483 HTLCs to account for the maximum Bitcoin transaction size and ensure that the commitment transactions continue to be valid Bitcoin transactions.
As we will see in the next section, the maximum is only for _pending_ HTLCs because, once an HTLC is fulfilled (or fails due to timeout/error), it is removed from the commitment transaction.
=== HTLC Fulfillment
((("hash time-locked contracts (HTLCs)","fulfillment", id="ix_09_channel_operation-asciidoc9", range="startofrange")))((("payment forwarding","HTLC fulfillment", id="ix_09_channel_operation-asciidoc10", range="startofrange")))Now Bob and Alice both have a new commitment transaction with an additional HTLC output, and we have achieved a major step toward updating a payment pass:[<span class="keep-together">channel</span>].
The new balance of Alice and Bob does not reflect yet that Alice has successfully sent 50,200 satoshis to Bob.
However, the HTLCs are now set up in a way that secure settlement in exchange for the proof of payment will be possible.
==== HTLC Propagation
((("hash time-locked contracts (HTLCs)","propagation", id="ix_09_channel_operation-asciidoc11", range="startofrange")))((("payment forwarding","HTLC propagation", id="ix_09_channel_operation-asciidoc12", range="startofrange")))Let's assume that Bob continues the chain and sets up an HTLC with Chan for 50,100 satoshis. The process will be exactly the same as we just saw between Alice and Bob. Bob will send +update_add_htlc+ to Chan, then they will exchange +commitment_signed+ and +revoke_and_ack+ messages in two rounds, progressing their channel to the next state.
Next, Chan will do the same with Dina: offer a 50,000 satoshi HTLC, commit, and revoke, etc. However, Dina is the final recipient of the HTLC. Dina is the only one that knows the payment secret (the preimage of the payment hash). Therefore, Dina can fulfill the HTLC with Chan immediately!
==== Dina Fulfills the HTLC with Chan
Dina can settle the HTLC by sending an +update_ful&#x2060;fill_&#x200b;htlc+ message to Chan. The +update_fulfill_htlc+ message is defined in https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md#removing-an-htlc-update_fulfill_htlc-update_fail_htlc-and-update_fail_malformed_htlc[BOLT #2: Peer Protocol, `update_fulfill_htlc`] and is shown here:
[[update_fulfill_htlc_message]]
.The +update_fulfill_htlc+ message
----
[channel_id:channel_id]
[u64:id]
[32*byte:payment_preimage]
----
It's a really simple message:
+channel_id+:: The channel ID on which the HTLC is committed.
+id+:: The ID of the HTLC (we started with 0 and incremented for each HTLC on the channel).
+payment_preimage+:: The secret that proves payment was made and redeems the HTLC. This is the +R+ value that was hashed by Dina to produce the payment hash in the invoice to Alice.
When Chan receives this message, he will immediately check if the `payment_preimage` (let's call it _R_) produces the payment hash (let's call it _H_) in the HTLC that he offered to Dina. He hashes it like this:
++++
<ul class="simplelist">
<li><em>H</em> = RIPEMD160(SHA-256 (<em>R</em>))</li>
</ul>
++++
If the result _H_ matches the payment hash in the HTLC, Chan can do a little dance of celebration. This long-awaited secret can be used to redeem the HTLC, and will be passed back along the chain of payment channels all the way to Alice, resolving every HTLC that was part of this payment to Dina.
Let's go back to Alice and Bob's channel and watch them unwind the HTLC. To get there, let's assume Dina sent the +update_fulfill_htlc+ to Chan, Chan sent +update_fulfill_htlc+ to Bob, and Bob sent +update_fulfill_htlc+ to Alice. The payment preimage has propagated all the way back to Alice.
==== Bob Settles the HTLC with Alice
When Bob sends the +update_fulfill_htlc+ to Alice, it will contain the same +payment_preimage+ that Dina selected for her invoice. That +payment_preimage+ has traveled backward along the payment path. At each step, the +channel_id+ will be different and +id+ (HTLC ID) may be different. But the preimage is the same!
Alice will also validate the +payment_preimage+ received from Bob. She will compare its hash to the HTLC payment hash in the HTLC she offered Bob. She will also find this preimage matches the hash in Dina's invoice. This is proof that Dina was paid.
The message flow between Alice and Bob is shown in <<htlc_fulfillment_message_flow>>.
[[htlc_fulfillment_message_flow]]
.The HTLC fulfillment message flow
image::images/mtln_0911.png[The HTLC fulfillment message flow]
Both Alice and Bob can now remove the HTLC from the commitment transactions and update their channel balances.
They create new commitments (Commitment #4), as shown in <<htlc_fulfillment_commitments_added>>.
[[htlc_fulfillment_commitments_added]]
.The HTLC is removed and balances are updated in new commitments
image::images/mtln_0912.png[The HTLC is removed and balances are updated in new commitments]
[role="pagebreak-before"]
Next, they complete two rounds of commitment and revocation. First, Alice sends +commitment_signed+ to sign Bob's new commitment transaction. Bob responds with +revoke_and_ack+ to revoke his old commitment. Once Bob has moved the state of the channel forward, the commitments look like we see in <<htlc_fulfillment_commitments_bob_commit>>.
[[htlc_fulfillment_commitments_bob_commit]]
.Alice signs Bob's new commitment and Bob revoked the old one
image::images/mtln_0913.png[Alice signs Bob's new commitment and Bob revoked the old one]
[role="pagebreak-before"]
Finally, Bob signs Alice's commitment by sending Alice a +commitment_signed+ message. Then Alice acknowledges and revokes her old commitment by sending +revoke_and_ack+ to Bob. The end result is that both Alice and Bob have moved their channel state to Commitment #4, have removed the HTLC, and have updated their balances. Their current channel state is represented by the commitment transactions that are shown in <<alice_bob_htlc_fulfilled>>(((range="endofrange", startref="ix_09_channel_operation-asciidoc12")))(((range="endofrange", startref="ix_09_channel_operation-asciidoc11"))). (((range="endofrange", startref="ix_09_channel_operation-asciidoc10")))(((range="endofrange", startref="ix_09_channel_operation-asciidoc9")))
[[alice_bob_htlc_fulfilled]]
.Alice and Bob settle the HTLC and update balances
image::images/mtln_0914.png[Alice and Bob settle the HTLC and update balances]
[role="pagebreak-before less_space"]
=== Removing an HTLC Due to Error or Expiry
((("hash time-locked contracts (HTLCs)","removing due to error/expiry")))((("payment forwarding","removing an HTLC due to error/expiry")))If an HTLC cannot be fulfilled, it can be removed from the channel commitment using the same process of commitment and revocation.
Instead of +update_fulfill_htlc+, Bob would send an +update_fail_htlc+ or +update_fail_malformed_htlc+. These two messages are defined in https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md#removing-an-htlc-update_fulfill_htlc-update_fail_htlc-and-update_fail_malformed_htlc[BOLT #2: Peer Protocol, Removing an HTLC].
The +update_fail_htlc+ message is shown in the following:
[[update_fail_htlc_message]]
.The +update_fail_htlc+ message
----
[channel_id:channel_id]
[u64:id]
[u16:len]
[len*byte:reason]
----
It's pretty self-explanatory. The multibyte +reason+ field is defined in https://github.com/lightningnetwork/lightning-rfc/blob/master/04-onion-routing.md#failure-messages[BOLT #4: Onion Routing], which we will describe in <<onion_routing>>.
If Alice received an +update_fail_htlc+ from Bob, the process would unfold in much the same way: the two channel partners would remove the HTLC, create updated commitment transactions, and go through two rounds of commitment/revocation to move the channel state forward to the next commitment. The only difference: the end balances would revert back to what they were without the HTLC, essentially refunding Alice for the HTLC value.
=== Making a Local Payment
((("hash time-locked contracts (HTLCs)","local payment with")))((("local payments")))((("payment forwarding","local payments")))At this point, you will easily understand why HTLCs are used for both remote and local payments. When Alice pays Bob for a coffee, she doesn't just update the channel balance and commit to a new state. Instead, the payment is made with an HTLC, in the same way Alice paid Dina. The fact that there's only one channel hop makes no difference. It would work like this:
[start=1]
. Alice orders a coffee from Bob's shop page.
. Bob's shop sends an invoice with a payment hash.
. Alice constructs an HTLC from that payment hash.
. Alice offers the HTLC to Bob with +update_add_htlc+.
. Alice and Bob exchange commitments and revocations adding the HTLC to their commitment transactions.
. Bob sends +update_fulfill_htlc+ to Alice with the payment preimage.
. Alice and Bob exchange commitments and revocations removing the HTLC and updating the channel balances.
Whether an HTLC is forwarded across many channels or just fulfilled in a single channel "hop," the process is exactly the same
=== Conclusion
In this chapter we saw how commitment transactions (from <<payment_channels>>) and HTLCs (from <<routing>>) work together. We saw how an HTLC is added to a commitment transaction, and how it is fulfilled. We saw how the asymmetric, delayed, revocable system for enforcing channel state is extended to HTLCs.
We also saw how a local payment and a multihop routed payment are handled identically: using HTLCs.(((range="endofrange", startref="ix_09_channel_operation-asciidoc0")))
In the next chapter we will look at the encrypted message routing system called _onion routing_.