In this article, I will go over the process of opening a Lightning Network
channel as it works today (pre taproot channels). I will start with the
channel_open
message and will talk in detail about it and all the messages
involved in “opening” the channel ending with the channel_announcement
message.
My goal for this article is to recap today’s channel open flow so that we can later focus only on the changes required for opening a taproot channel1.
This article replaces my previous short article on channel opens. It includes more detail and more diagrams (yay diagrams!). I will assume that the reader understands the structure of a commitment transaction and understands why they are asymmetric. If you feel a bit rusty in this area, please check out my articles explaining these concepts in detail.
The end goal
Before we dig into the first step, I think it is useful to illustrate the goal we are trying to reach. I will once again use our trusty peers, Alice and Bob, to tell the story.
Alice and Bob are both Lightning Network nodes. Alice’s node ID (ie, the public
key used to identify her node) is alice_node_id
and Bob’s node ID is
bob_node_id
. Their main two goals are:
- They want to open a channel between themselves in a trustless way.
- They want to be able to advertise their new channel so that the rest of the network can use it for routing.
Opening the channel
A channel is opened once both parties have the ability to fully sign their respective commitment transactions and once the funding transaction is on chain. Throughout this explanation, I will use diagrams and colours to illustrate the process. In the diagrams, a white background means that the field of the transaction is not yet known. A coloured-in field indicates that the field value is known. Any green fields are used to highlight any of Alice’s public keys or signatures and any blue fields are used to show Bob’s.
There are three transactions in play for the opening of a channel. The first is the funding transaction which will need to go on chain. The other two are the first commitment transactions held by Alice and Bob describing the initial state of the channel.
Here are the diagrams used to describe the three transactions. Note that at the moment we still don’t know anything about the parameters of the channel and so all fields still have a white background. Remember that our end goal is to have all these fields coloured in.
The open_channel
message
The first step of the process is Alice deciding that she wants to open a channel
with Bob. In doing so, she also becomes the funder of the channel. Let’s say
that Alice decides that she wants to open a 1 BTC channel and wants to
immediately give Bob half of the channel’s capacity (0.5 BTC). Alice will now
put together an open_channel
message that she will send to Bob. Let’s take a
look at the relevant open_channel
parameters (I am leaving out any parameters
that don’t have anything to do with the channel-open phase). You can skip this
table if you want. It is just a reference for incase you want to check what the
meaning of a field is.
Let’s now fill in Alice’s values for these fields:
Alice sends this message over to Bob.
Since Alice has decided on the type of channel she wants to open (default channel type as opposed to an anchors, taproot etc) as well as the channel capacity, she can already piece together quite a large part of the funding transaction:
Since she knows the capacity of the channel she wants to open, she can choose some of her UTXOs to be inputs to the funding transaction. Since Alice does not yet know which pub key Bob would want to use for the channel, she cannot yet finalise the channel funding output and hence can also not yet produce signatures for the inputs.
Since Alice has decided on the channel type (and hence the commitment
transaction structure), she can also start putting together the pieces of the
commitment transactions. If we assume that Bob is delighted by this
channel-opening proposal from Alice, then from this open_channel
message, he
can also start putting together the pieces. Remember that both parties will need
to construct both commitment transactions since they will both need to be able
to sign their peer’s transactions. Let’s take a look at what pieces they are now
both able to fill in:
Alice’s commitment transaction has filled in quite nicely. It has the structure
of a default, non-anchor channel transaction and all her public keys have been
filled in (alice_local_delayed_pk_1
is derived using her
delayed_payment_basepoint
and her first_commitment_point
). Since she hasn’t
received any messages from Bob yet, she has not yet been able to fill in any of
his pub keys and since the funding transaction is still incomplete, she also
can’t yet know the TXID to point the input of this commitment transaction to.
Bob’s commitment transaction (from his perspective) is looking a bit more complete:
Like Alice, he also cannot yet fill in the funding transaction’s TXID, but he can fill in a few other things:
- The
alice_pubkey_1
,alice_to_self_delay
,push_amt
andlocal_amt
values are taken as is from theopen_channel
message alice_payment_key_1
is derived using Alice’spayment_basepoint
andfirst_commitment_point
revoke_pubkey_1b
is derived using Alice’srevocation_basepoint
and Bob’sfirst_per_commitment
point (at this point Alice cannot derive this point yet since she has not received hisfirst_per_commitment_point
)
Ok cool! Time for Bob to indicate to Alice his acceptance of the request by
sending the next message: accept_channel
The accept_channel
message
The message shares many of the fields from open_channel
. Here is the message
that Bob will put together:
When Alice gets this message from Bob, she can now complete the funding transaction’s output and can create the signatures for the inputs. Since everything is filled in, the TXID for the funding tx is now also known.
Alice can now also further fill in her own commitment transaction:
- she is now able to use the values sent by Bob to fill in
bob_pubkey_1
,bob_payment_key_1
,bob_to_self_delay
andrevoke_pubkey_1a
- since the TXID for the funding tx is now known, she can complete the input too.
She now knows everything she needs to know in order to sign this transaction herself but she is still missing Bob’s signature for this transaction.
Bob’s view of his commitment transaction is still the same as before since he
learned no new info after sending the accept_channel
message.
Now that Alice knows the txid for the funding transaction, she is also able to
complete her view of Bob’s commitment transaction and so she can produce her
signature for his transaction. This is where the next message comes in:
funding_created
.
The funding_created
message
Alice will now use the funding_created
message to tell Bob the TXID and index
of the funding transaction along with her signature for Bob’s commitment
transaction. Note that he still wont be able to broadcast his transaction since
Alice has not yet broadcast the funding transaction.
Once the funding message has been received, Bob can fill in the rest of his commitment transaction:
Alice won’t broadcast the funding transaction until she has a valid signature
from Bob for her commitment transaction. Enter funding_signed
:
Notice that this is the first message to use the real channel ID instead of the temporary one.
This was the last piece of the puzzle for Alice. She now has all the info she needs to be able to sign her commitment transaction if ever needed.
Alice can now safely broadcast the funding transaction. Both she and Bob will
watch the chain for the confirmation of the funding transaction. Once it has
reached the minimum_depth
specified by Bob in accept_channel
, both sides
will exchange the channel_ready
message (previously named funding_locked
).
This message serves as both a signal to the peer to indicate to them that the
channel is ready for use (and that the channel announcement process can now
start if the peers decided on an announced channel) and also to send across each
peer’s second_per_commitment_point
that they should use in their second
commitment transaction.
Ok cool! We have completed our first goal: Alice and Bob have opened a channel between themselves in a trust-less way. Now we move on to step 2: announcing this channel to the network!
Announcing the channel
This part is fairly painless. Basically there is just one message,
channel_announcement
, that Alice and Bob need to construct together and once
it is complete, then they can broadcast it to the network. Other nodes will use
this message to prove a few things:
- That the channel funding tx is actually an existing, unspent UTXO with an acceptable number of confirmations.
- That the funding transaction output actually looks like a lightning channel funding transaction
- That the channel is actually owned by the keys that Alice and Bob say they used to construct the channel.
- That Alice and Bob both agree on the message being broadcast.
An incomplete version of the channel_announcement
message looks as follows:
h
is the hash of all the data that will be covered by the signatures. In order
to complete the message, Alice and Bob both compute a signature over h
using
the private keys associated with their node IDs and the pubkeys they used in the
funding transaction. They then both exchange the announcement_signatures
message in order to communicate these signatures to each other:
Now both nodes can put together the complete channel_announcement
message:
Let’s go over the steps that a node (Charlie) receiving this message will go through in order to verify the new channel that Alice and Bob claimed to have opened.
- First, Charlie will use the
short_channel_id
included in the message to make sure that the channel’s funding transaction actually exists on-chain, that it has a sufficient number of confirmations and that it is in fact unspent. - Then, Charlie will also check that the unspent output actually does look like a
Lightning channel owned by
alice_pubkey_1
andbob_pubkey_1
. He will do this by using the advertised pubkeys to reconstruct the P2WSH and ensure that it is the same as the one found on-chain. - Now, Charlie will want to confirm that the nodes owning the pubkeys found in the
channel funding output do in fact belong to the nodes owning the node ID
pubkeys. This is done by verifying the
alice_pubkey_1_sig
andbob_pubkey_1_sig
signatures. If these signatures are valid, then it is clear that the owners ofalice_pubkey_1
andbob_pubkey_1
agree to being associated withalice_node_ID
andbob_node_ID
since the message signed includes these nodes IDs. - Finally, Charlie will also want to ensure that owners of the node ID pubkeys
agree to being associated with the new channel. This is done by verifying the
alice_node_ID_sig
andbob_node_ID_sig
signatures. If these signatures are valid, then it is clear that the owners ofalice_node_ID_sig
andbob_node_ID_sig
agree to being associated withalice_pubkey_1
andbob_pubkey_1
since the message signed includes these pubkeys.
Alice and Bob are done! Their channel is open and other nodes in the network, like Charlie, will happily use the new channel.
In the next post, I will dive into how the above process will change with taproot channels (given the current proposal). The main thing that will need to change is how signatures are dealt with. In all the above cases, Alice and Bob didn’t really need to do anything special when they were generating their signatures since they each would need to provide their own signature to sign for the 2-of-2 funding transaction. But with taproot, the funding output will use Musig2 to combine the pubkeys of Alice and Bob and so any signatures will need to involve the Musig2 signing protocol… But let’s leave the details of that for next time :)