This is our fourth post in our Lightning 101 For Exchanges series. We will investigate in detail the security schema of the Lightning Network. This post will be more technical than our previous ones and is intended for software engineers and security professionals.
Lightning for Exchanges Series
- Regulation Part 1 — Money Transmitter Rules
- Regulation Part 2 — Money Transmitter Rules
- Security Part 1 — Overview
- Security Part 2 – Backing Up Your Lightning Wallet
- Security Part 3 – Private Key Management
- User Experience – Liquidity
- Managing Fees With Lightning
- Routing Nodes
The Lightning Network has a new way for funds to be lost when compared to an exchange’s traditional hot wallet. With current blockchains, security engineers for exchanges only need to be concerned with private keys associated with their hot and cold storage wallets. If an attacker cannot access these keys, they cannot steal the exchange’s funds. In this post we will address the security concerns revolving around managing revoked states on the Lightning Network which, if managed incorrectly, can result in loss of funds.
You can think of commitment transactions as the fund “states” in your Lightning channel. Each of these “states” consists of a reference to the on-chain funding, and a set of outputs that dictate who has what. Both participants in a channel have a copy of this “state”. If we have two peers on the Lightning network, Alice and Bob, this is what a commitment transaction means to each of them.
- Both Alice and Bob have an equivalent list of (HTLC) outputs for lightning transactions that are underway but not yet completed. These are conditional outputs that basically say that the receiver can spend the money should the payment succeed, otherwise the sender can claim this money after a fixed delay.
- Alice has an output (to_remote) that allows Bob to spend his money immediately.
- Alice also has an output (to_local) that lets her access her money after she waits a certain delay (to_self_delay).
- Bob has an output (to_remote) that allows Alice to spend her money immediately.
- Bob also has an output (to_local) that lets him access his money after he waits a certain delay (to_self_delay).
It is important to recognize that commitment transactions are symmetrical. This means that Alice & Bob’s commitment transactions are mirror images of each other. This means both Alice & Bob will be subject to the same scheme of revoking old states.
Note: Both Alice & Bob would rather not have to wait for to_self_delay blocks to occur to be able to access their money. This is one incentive for both of them to cooperate in the lightning protocol.
It’s important to remember that a commitment transaction is in fact a fully signed bitcoin transaction that could be broadcasted to the blockchain at any time. They are the mechanism that Lightning uses to make payments “trustless” — because every lightning network transaction results in a fully valid bitcoin transaction that can be put on-chain.
Payments on the Lightning Network must always result in two outcomes:
- Both parties must have updated (fully signed) commitment transactions that reflect the updated balances
- Both parties must revoke their previous commitment transactions. Meaning that if they were to broadcast an old state, their counterparty must be able to penalize them, here this means take all their money in the channel; this is called the Lightning Penalty.
The first condition facilitates the transfer of value between the two parties while the second condition ensures that this transfer of value cannot be undone by either party. This second condition also introduces new complexity that doesn’t exist on a blockchain: It is the responsibility of the Lightning user to punish their counterparty if they attempt to cheat and so the user must have measures in place to secure their funds.
This is what introduces a new security concern related to losing funds, namely, revoked states.
The outputs of the commitment transactions enforce the revocation of old states by having a condition in their scripts that allows money to be spent immediately by a cheating node’s peer if the state has been revoked. Let’s take a dive into the actual scripts to see how.
There are two main outputs on a commitment transaction:
- to_local — this is the output that sends money back to you
- to_remote — this is the output that sends money back to your lightning peer
# Penalty transaction
This script has two control flow branches that say:
- If someone (namely your lightning peer) can provide a valid digital signature that corresponds to revocationpubkey they can spend that money immediately.
- After waiting to_self_delay blocks, you can spend this money by providing a digital signature for local_delayedpubkey.
The revocationpubkey is extremely important here. If you, or your peer, have the private key that corresponds to revocationpubkey, you can create a digital signature and validly spends the to_local output immediately (without the to_self_delay). Remember, commitment transactions are symmetrical. This means if you are an exchange, your peer may be able to generaterevocationprivkey and steal money from you if you broadcast a revoked state to the blockchain!
As BOLT3 states, the revocation private key can be created if you have both of these keys:
The first key, revocation_basepoint_secret, is the private key that corresponds to revocation_base_point public key in the open_channel or accept_channelmessages in the peer-to-peer protocol. You generate this secret locally and store it while you send the revocation_base_point public key to your peer (your peer must never learn this secret).
The second key is the per_commitment_secret. It is generated by your peer. Revoking a commitment transaction is simply the act of sharingper_commitment_secret since with this secret, a counterparty will have both secrets and can generate revocationprivkey.
A state is revoked (and a new state acknowledged) with the revoke_and_ack message in the Lightning p2p protocol which is sent to you when your peer has verified that all HTLC signatures passed in the commitment_signed message are valid. This message completes the state transition from the old commitment transaction to a brand new one.
Once someone has revocation_basepoint_secret and per_commitment_secretthey can generate revocationprivkey as specified in BOLT3:
revocationprivkey = revocation_basepoint_secret * SHA256(revocation_basepoint || per_commitment_point) + per_commitment_secret * SHA256(per_commitment_point || revocation_basepoint)
This allows them to provide a valid digital signature that corresponds to revocationpubkey in a peer’s to_local output.
The per_commitment_secret poisons the old state by allowing you to claim money from your peer’s to_local output, if they broadcast the revokedcommitment transaction to the blockchain, since you can now generate the revocationprivkey.
Remember, commitment transactions are symmetrical. This exact same process applies to your exchange and it’s peers on the lightning network. An exchange needs to be wary of:
- Accidentally broadcasting a revoked state
- A peer broadcasting a revoked state
If a peer broadcasts a revoked state, the exchange must claim the peers money by constructing a transaction that is signed by revocationprivkey.
We’ve now covered how the Lightning Penalty is enforced in commitment transactions:
- Each payment creates an updated and fully signed commitment transaction.
- The last commitment transaction is revoked by revealing per_commitment_secret.
So how does an exchange protect itself against this new potential way of losing funds? We will discuss techniques exchanges can use to mitigate these risks and challenges in a future post.
If you are an exchange or interested in what Lightning can do for you and your business, contact us at [email protected].
You can also reach us on the Lightning Network: 038bdb5538a4e415c42[email protected].