Hi all, I've been working on a revision to BOLT13's proposal with the comments received over the list (h/t Rusty and Antoine), and from conversations with different people from the community at Advancing Bitcoin and over email this last weeks.
This revision includes user accounts, payment methods, and message signing, as well as improvements over the original proposal. On top of that, there are a few things I'd love to add in a future revision: - Proofs of storage for subscription renewals in s similar fashion to Dead Men's Button (h/t Joost Jager). - Recognition codes for a more private approach to subscriptions (thanks ZmnSCPxj for the extensive discussion over the last week). As the last time, there's a list discussion topics at the end, with things I'd love to hear your opinion on. Best, PS: The documents can also be found at https://github.com/sr-gi/bolt13 ---- # Watchtower protocol specification (BOLT DRAFT REV.1) ## Overview All off-chain protocols assume the user remains online and synchronised with the network. To alleviate this assumption, customers can hire a third party watching service (a.k.a Watchtower) to watch the blockchain and respond to channel breaches on their behalf. At a high level, every time there is a new transfer in the client's lightning channel, the client sends the Watchtower an encrypted penalty transaction and a transaction locator. Internally, the Watchtower maps the transaction locator to the encrypted penalty transaction. If there is a breach in the lightning channel, the Watchtower can identify it with the locator, and use the commitment transaction ID to compute the decryption key. With the decryption key, the tower decrypt the encrypted penalty transaction and broadcast it to the network. Therefore, the Watchtower does not learn any information about the client's channel unless there is a channel breach (channel-privacy). Due to replace-by-revocation Lightning channels, the client should send data to the Watchtower for every new update in the channel, otherwise the Watchtower cannot respond to all potential breaches. Finally, optional extensions can be offered by the Watchtower to provide stronger guarantees to the client, such as a signed receipt for every new job. The rationale for the receipt is to build an _accountable_ Watchtower as the customer can later use it as publicly verifiable evidence if the Watchtower fails to protect them. The scope of this document includes: - A protocol for client/server communication. - A payment protocol between the customer and Watchtower. - How to build appointments for the Watchtower, including key/locator derivation and data encryption. - A format for the signed receipt. The scope of this bolt does not include: - Watchtower server discovery. For the rest of this document we will use server/tower and client/Lightning node indistinguishably. ## Table of Contents * [Watchtower discovery](#watchtower-discovery) * [Watchtower services](#watchtower-discovery) * [Basic Service](#basic-service) * [Extensions](#extensions) * [User authentication](#user-authentication-and-subscriptions) * [The `register_top_up` message](#the-register_top_up-message) * [The `subscription_details` message](#the-subscription_details-message) * [Sending appointments to the tower](#sending-appointments-to-the-tower) * [The `add_update_appointment` message](#the-add_update_appointment-message) * [The `appointment_accepted` message](#the-appointment_accepted-message) * [The `appointment_rejected` message](#the-appointment_rejected-message) * [Deleting appointments](#deleting-appointments) * [The `delete_appointment` message](#the-delete_appointment-message) * [The `deletion_accepted` message](#the-deletion_accepted-message) * [The `deletion_rejected` message](#the-deletion_rejected-message) * [Transaction Locator and Encryption Key](#transaction-locator-and-encryption-key) * [Encryption Algorithms and Parameters](#encryption-algorithms-and-parameters) * [Payment Modes](#payment-modes) * [Data serialisation and signing](#data-serialisation-and-signing) * [No compression of penalty transaction](#no-compression-of-penalty-transaction) * [Attacks on towers](#attacks-on-towers) ## Watchtower discovery We have not defined how a client can find a list of servers to hire yet. We assume the client has found a server and the server is offering a watching service. ## Watchtower services ### Basic Service The customer can hire the Watchtower to watch for breaches on the blockchain and relay a penalty transaction on their behalf. The customer receives an acknowledgement when the Watchtower has accepted the job, but the hiring protocol does not guarantee the transaction inclusion. ### Extensions Extensions build on top of the basic service and are optionally provided by the tower. Different extensions can be offered by the tower. For now we are defining a single type of extension: `accountability`. #### `accountability` A Watchtower provides a signed receipt to the customer. This is considered reputational accountability as the customer has publicly verifiable cryptographic evidence the Watchtower was hired. The receipt can be used to prove the Watchtower did not relay the penalty transaction on their behalf and/or request a refund. ## User authentication and subscriptions Upon establishing the first connection with the tower, the client needs to register a public key. The registration aims to give the user access to the tower's services: +-------+ +-------+ | A |--(1)-- register ---->| B | | |<-(2)--- subscription_details -----| | +-------+ +-------+ - where node A is 'client' and node B is 'server' ### The `register_top_up` message The `register_top_up` message contains the information required to start the registration of a new public key with the tower, or to top up an existing one. 1. type: ? (`register_top_up`) 2. data: * [`point`:`public_key`] * [`u32`: `appointment_slots`] * [`u32`: `subscription_period`] #### Rationale We define appointment (in a lack of a better word) as how the Watchtower is hired by a client for its watching services. Every a client updates the state of one of his channels, he will send an appointment containing information related to the update. Check [Sending appointments to the tower](#sending-appointments-to-the-tower) for more on this. #### Requirements The client: - MUST set `public_key` to the public key he wants to register or top up. - MUST set `appointment_slots` to the appointment slots he is requesting. - MUST set `subscription_period` to the number of blocks he is asking the tower to watch for channel breaches. Upon receiving a `register_top_up` message, the server: - MUST reply with a `subscription_details` message. ### The `subscription_details` message The `subscription_details` message contains information regarding the subscription the tower is offering to the client, including the subscription payment request if necessary. 1. type: ? (`subscription_details`) 2. data: * [`u16`: `appointment_max_size`] * [`u32`: `amount_msat`] 3. tlvs: `wt_subscription_tlvs` 4. types: 1. type: 1 (`subscription_invoice`) 2. data: * [`tu16*byte`: `invoice`] #### Requirements The server: * MUST receive a `register_top_up` message before sending `subscription_details`. * MUST set `appointment_max_size` to the maximum size allowed for a single appointment. * MUST set `amount_msat` to the amount to be paid by the user for the service. * MAY include `subscription_invoice` if it is offering a non-altruistic service. If so: * MUST set `invoice` to a [BOLT11]( https://github.com/lightningnetwork/lightning-rfc/blob/master/11-payment-encoding.md) invoice. The user: * MUST have sent `register_top_up` before receiving a `subscription_details` message. If `subscription_invoice` is set: * MAY pay the [BOLT11]( https://github.com/lightningnetwork/lightning-rfc/blob/master/11-payment-encoding.md) `invoice`. #### Rationale User authentication with the tower is required to allow interaction with the tower beyond simply sending channel updates (like requesting, updating or deleting channel updates). Authentication is also required to account for the amount of data the client is sending to the tower, so subscriptions models can be properly defined. The mechanism used to authenticate users by the tower is based on message signing and public key recovery. During the registration phase the user will request a public key registration with the tower (`public_key`). `appointment_slots` and `subscription_period` are requested by the user to reduce the number of messages exchanged by the two parties whilst allowing for high customisation. Otherwise the tower will need to inform the user of what type of services he can apply for. `appointment_max_size` defines what is the maximum size of an appointment. The tower is effectively charging for storage over time, so if an appointment exceeds `appointment_max_size` it will be counted as `ceil(len(appointment)/appointment_max_size)`. Once the user is registered, the tower will be able to identify him by doing EC recovery on his signed requests. Message signing and EC recover is performed using the current approach followed by [lnd and c-lightning](#data-serialisation-and-signing). If a user has filled all his appointment slots, or need to keep the data in the tower for longer than the `subscription_period`, he may need to top up his subscription. For now we have only defined `subscription_invoice` as payment method. Other payment methods can be defined as tlv in the future. ## Sending appointments to the tower Once the client is registered, he can start sending appointments to the tower: +-------+ +-------+ | A |--(1)--- add_update_appointment ---->| B | | |<-(2)--- accepted/rejected -----| | +-------+ +-------+ - where node A is 'client' and node B is 'server' ### The `add_update_appointment` message This message contains all the information regarding an appointment between the client and the server. 1. type: ? (`add_update_appointment`) 2. data: * [`16*byte`:`locator`] * [`u16`: `encrypted_blob_len`] * [`encrypted_blob_len*byte`:`encrypted_blob`] * [`u16`: `signature_len`] * [`signature_len*byte`: `user_signature`] 3. tlvs: `wt_accountability_tlvs` 4. types: 1. type: 1 (`user_evidence`) 2. data: * [`u64 `:`to_self_delay`] #### Requirements The client: * MUST set `locator` as specified in [Transaction Locator and Encryption Key](#transaction-locator-and-encryption-key). * MUST set `encrypted_blob` to the encryption of the `penalty_transaction` as specified in [Transaction Locator and Encryption Key](#transaction-locator-and-encryption-key). * MUST set `encrypted_blob_len` to the length of `encrypted_blob`. * MUST set `user_signature ` to the appointment signature. * MUST set `signature_len` to the length of `user_signature`. * MAY set `to_self_delay` to the `to_self_delay` requested by the client to its peer. The server: * MUST compute `public_key` by performing EC recover. * MUST reject the appointment if the recovered `public_key` does not match with any of the registered ones. * MAY reject the appointment if `encrypted_blob` has unreasonable size. If `accountability` is being offered and `to_self_delay` can be found in `add_update_appointment`: * MUST reject the appointment if `to_self_delay` is too small. * MAY accept the appointment otherwise. If the server accepts the appointment: * MUST send an `appointment_accepted` message. If the server rejects the appointment: * MUST send an `appointment_rejected` message. #### Signing appointment requests Appointment request must be arranged as follows while serialised for signing: locator | encrypted_blob | to_self_delay `to_self_delay` will only be included if it is also included in the request. The signature must be performed following [Data serialisation and signing](#data-serialisation-and-signing). #### Rationale Users must have preregistered before they can hire the Watchtower, as discussed in [User authentication](#user-authentication-and-subscriptions). Appointments from non-registered users are therefore rejected. A client may need to update an appointment after having sent it to the tower (for instance to update the fee, change the outputs, etc). The same message can be used to add new appointments or to update existing ones. If two appointments from the same user share a `locator`, the tower should interpret that as an update and override the oldest. `locators` are `128-bit` values so unintended collisions within the same user should be negligible. The `encrypted_blob` size depends on the encrypted commitment transaction size and the block size of the chosen cipher. Arbitrarily small/big transaction are invalid, meaning that arbitrarily small/big `encrypted_blob`s will, therefore, also be invalid. The `encrypted_blob` have to be larger than (or equal to): `cipher_block_size * ceil(minimum_viable_transaction_size / cipher_block_size)` and smaller than (or equal to): `cipher_block_size * ceil(maximum_viable_transaction_size / cipher_block_size`) `minimum_viable_transaction_size` and `maximum_viable_transaction_size` refer to the minimum/maximum size required to create a valid transaction. `encrypted_blob`s outside those boundaries cannot contain valid transactions, so they should be rejected. A tower should broadcast the penalty transaction right after a breach is seen, but should be also able to bump the fee if necessary. If `to_self_delay` is smaller than expected, then it can lead the tower to fail. ### The `appointment_accepted` message This message contains information about the acceptance of an appointment by the Watchtower. 1. type: ? (`appointment_accepted `) 2. data: * [`16*byte `:`locator`] * [`u32`: `start_block`] 3. tlvs: `wt_accountability_tlvs` 4. types: 1. type: 2 (`receipt_signature`) 2. data: * [`tu16*byte`: `tower_signature`] The server: * MUST receive `add_update_appointment` before sending an `appointment_accepted` message. * MUST set the `locator` to match the one received in `add_update_appointment`. * MUST set `start_block` to the block height where the tower will start looking for breaches. If `accountability` is being offered and `add_update_appointment` contained `to_self_delay`: * MUST create a receipt of the appointment. * MUST set `tower_signature` to the signature of the receipt as defined in [Data serialisation and signing](#data-serialisation-and-signing). The client: * MUST fail the connection if `locator` does not match any of locators the previously sent to the server. #### Appointment receipt format Data must be arranged in the following order to create the receipt: locator | encrypted_blob | to_self_delay | user_signature | start_block The receipt must be signed following [Data serialisation and signing](#data-serialisation-and-signing). #### Rationale `start_block` is set by the tower so the user knows when the channel update will be covered. We assume the tower has a well-known public key and the user is aware of it. The receipt contains, mainly, the information provided by the user. The Watchtower will need to sign the receipt to provide evidence of agreement. The `user_signature` is included in the receipt to link both the client request and the server response. Otherwise, the tower could sign a receipt with different data that the one sent by the user, and the user would have no way to prove whether that's true or not. By signing the customer signature the tower creates evidence of what the user sent, since the tower cannot forge the client's signature. ### The `appointment_rejected` message This message contains information about the rejection of an appointment by the Watchtower. 1. type: ? (`appointment_rejected `) 2. data: * [`16*byte `:`locator`] * [`u16`: `rcode`] * [`u16`: `reason_len` * [`reason_len*byte`: `reason`] The server: * MUST receive `add_update_appointment` before sending an `appointment_rejected` message. * MUST set the `locator` to match the one received in `add_update_appointment`. * MUST set `rcode` to the rejection code. * MAY set an empty `reason` field. * MUST set `reason_len` to length of `reason`. #### Rationale The `appointment_rejected` message follows the approach taken by the `error` message defined in [BOLT#1]( https://github.com/lightningnetwork/lightning-rfc/blob/master/01-messaging.md#the-error-message): error codes are mandatory, whereas reasons are optional and implementation dependant. ## Deleting appointments A client may want to delete appointments from the tower after a breach, or closing a channel: +-------+ +-------+ | A |--(1)--- delete_appointment ---->| B | | |<-(2)--- accepted/rejected -----| | +-------+ +-------+ - where node A is 'client' and node B is 'server' ### The `delete_appointment` message 1. type: ? (`delete_appointment`) 2. data: * [`16*byte `:`locator`] * [`u16`: `signature_len`] * [`signature_len*byte`: `user_signature`] The user: * MUST set `locator` as specified in [Transaction Locator and Encryption Key](#transaction-locator-and-encryption-key). * MUST set `user_signature` to the signature of the deletion request. * MUST set `signature_len` to the length of `user_signature`. The server: * MUST compute `public_key` by performing EC recover. * If the recovered `public_key` has an associated appointment with locator matching `locator`: * MUST delete the appointment and send `deletion_accepted`. * Otherwise: * MUST reject the deletion request and send `deletion_rejected`. #### Signing deletion requests Deletion requests must contain a signature of the following message: "Delete appointment <locator>" where `<locator>` MUST match `locator`. The signature must be performed following [Data serialisation and signing](#data-serialisation-and-signing). #### Rationale Freeing expired appointment from the tower (after a channel clousure or breach) should be beneficial for both parties. From the tower side, it allows to reduce the load and free space, for the user side, it recovers space that was used by expired appointments, so it can be used to back up new channel updates. ### The `deletion_accepted` message This message contains information about the acceptance of an appointment deletion by the Watchtower. 1. type: ? (`deletion_accepted`) 2. data: * [`16*byte `:`locator`] 3. tlvs: `wt_accountability_tlvs` 4. types: 1. type: 2 (`receipt_signature`) 2. data: * [`tu16*byte`: `tower_signature`] The server: * MUST receive `delete_appointment` before sending an `deletion_accepted` message. * MUST set the `locator` to match the one received in `delete_appointment`. If `accountability` is being offered it was requested for the appointment appointment: * MUST set `tower_signature` to the signature of `user_signature` as specified following [Data serialisation and signing](#data-serialisation-and-signing). The client: * MUST fail the connection if `locator` does not match the `locator` from `delete_appointment`. ### The `deletion_rejected` message This message contains information about the rejection of an appointment deletion by the Watchtower. 1. type: ? (`deletion_rejected`) 2. data: * [`16*byte `:`locator`] * [`u16`: `rcode`] * [`u16`: `reason_len` * [`reason_len*byte`: `reason`] The server: * MUST receive `delete_appointment` before sending an `deletion_rejected` message. * MUST set the `locator` to match the one received in `delete_appointment`. * MUST set `rcode` to the rejection code. * MAY set and empty `reason` field. * MUST set `reason_len` to length of `reason`. #### Rationale Deletion rejection should include cases like the appointment cannot be found for the requesting user (either because it never existed, or because it was already deleted). The same approach as for `appointment_rejected` error messages is followed here. ## Transaction Locator and Encryption Key Implementations MUST compute the `locator`, `encryption_key` and `encryption_iv` from the commitment transaction as defined below: - `locator`: first half of the commitment transaction id (`commitment_txid(0,16]`) - `encryption_key `: Hash of the commitment transaction id (`SHA256(commitment_txid)`) - `encryption_iv`: A 12-byte long 0 (`'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'`) The server relies on both the encryption key and iv to decrypt the penalty transaction. Furthermore, the transaction locator helps the Watchtower identify a breach transaction on the blockchain. ## Encryption Algorithms and Parameters Users and servers MUST use [ChaCha20-Poly1305]( https://tools.ietf.org/html/rfc7539) to encrypt / decrypt blobs. Sample code (python) for the client to prepare the `encrypted_blob`: from hashlib import sha256 from binascii import hexlify from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305 def encrypt(penalty_tx, commitment_txid): # The SHA256 of the commitment txid is used as secret key, and 0 (12-byte long) as nonce. sk = sha256(commitment_txid).digest() nonce = bytearray(12) # Encrypt the data cipher = ChaCha20Poly1305(sk) encrypted_blob = cipher.encrypt(nonce=nonce, data=penalty_tx, associated_data=None) encrypted_blob = hexlify(encrypted_blob).decode("utf8") return encrypted_blob ## Payment modes The three most common ways of paying a tower are: **On-chain bounty**. An additional output is created in the penalty transaction that will reward the Watchtower. **Micropayments**. A small payment is sent to the Watchtower for every new job (e.g. over the lightning network). **Subscription**. Watchtower is periodically rewarded / paid for their service to the customer. (e.g. over the lightning network or fiat subscription). The bounty approach has the benefit of paying the tower only if the job is done, but lets the customer hire many Watchtowers and only one Watchtower will be rewarded upon collecting the bounty (O(N) storage for each tower). On top of that, the onchain bounty allows a network-wise DoS attack for free. However, it also has the benefit of allowing fee-bumping via CPFP by including an output dedicated to the tower. The micropayment approach can be achieved using the same method as the subscription approach but setting the `appointment_slots` to one. Both micropayments and subscriptions are favourable for a Watchtower. The ideal approach could be something in between. The tower is paid via a subscription to cover the storage costs and making DoS attacks having a financial cost. On top of that, the penalty transactions can include an output for the tower so the tower is encouraged to watch for beaches whilst allowing fee-bumping. ## Data serialisation and signing Request and receipts are serialised in big-endian, concatenating their values in the given order if they contain more than one value (as is the case of the appointment receipt). The signature algorithm follows the approach developed by lnd and currently implemented by both lnd and c-lightning [#specinatweet]( https://twitter.com/rusty_twit/status/1182102005914800128): Signatures are [zbase32 encoded]( https://philzimmermann.com/docs/human-oriented-base-32-encoding.txt) and are performed over the sha256d of the message prefixed by `"Lightning Signed Message:"`, that is: zbase32(SigRec(SHA256(SHA256("Lightning Signed Message:" + serialised_data)))) For example, for a deletion request of appointment identified by locator `4a5e1e4baab89f3a32518a88c3bc87f6`, the structure will be: zbase32(SigRec(SHA256(SHA256("Lightning Signed Message:Delete appointment 4a5e1e4baab89f3a32518a88c3bc87f6)))) ## No compression of penalty transaction The storage requirements for a Watchtower can be reduced (linearly) by implementing [shachain]( https://github.com/rustyrussell/ccan/blob/master/ccan/crypto/shachain/design.txt), therefore storing the parts required to build the transaction and the corresponding signing key instead of the full transaction. For now, we have decided to keep the hiring protocol simple. Storage is relatively cheap and we can revisit this standard if it becomes a problem. ## Attacks on towers There are three main factors that define how easy is, for a malicious user, to attack a tower: the `cost` of hiring the tower, the level of user `privacy` achieved by the service, and who has `access` to the tower's services. The most vulnerable Watchtower will, therefore, be a cheap, public, and completely privacy preserving tower. Privacy being our mail goal, we've defined parts of this BOLT to prevent cheap attacks, such as favouring subscriptions over single appointments. Here's an example of what subscriptions try to protect from: ### Locator reuse attack Given a locator `l`, a tower that provides a per-appointment hiring service (appointments can be bought one by one), and complete privacy (no registration), a malicious user could: * Send `n` appointments to the tower, all identified by `l` * Trigger a breach by sending a single old commitment (`txfee`) The tower will need to store all appointments, since it has no clue which of them is the valid one (if any). On the other hand, the cost for the attacker will only be `n * appointment_cost + txfee`. Upon detection a breach, the tower will need to decrypt and analyse `n` transactions and left with the decision of what of them to broadcast (if any). Using subscriptions, the tower will only store a single appointment, since all appointments with the same `l` will be seen as updates. An attacker will need `n` different subscriptions to attempt the same attack. Assuming a subscription has a minimum size of `m` appointments (`m >> 1`), the cost for the attacker will be `n * m * appointment_cost + txfee`. Check [Trustless WatchTowers?]( https://lists.linuxfoundation.org/pipermail/lightning-dev/2018-April/001203.html) for more on this. [ADD MORE ATTACKS] ## FIXMES - Define a proper tower discovery. - None of the message types have been defined (they have been left with ?). - Define errors (transient vs permanently). - Extend attacks on towers ## DISCUSS - The tower may also need to reply with `appointment_slots` during the registration phase so a minimum amount of appointments are paid for. Check [Attacks on towers](#attacks-on-towers). Therefore hiring the tower for a single appointment may be problematic. - Signature on the deletion acceptance by the server may not be necessary. - Appointment deletion can be performed in bulk, by allowing sending more than one appointment at a time. That could result in a privacy leak though, since the tower will be able to link what appointments belonged to the same channel. - Recognition codes, by ZmnSCPxj, may help here. - Separate register and top up so proofs can be used for top ups, in a similar way to [Dead Men's Button]( https://github.com/joostjager/deadmensbutton) -- Sergi.
_______________________________________________ Lightning-dev mailing list Lightning-dev@lists.linuxfoundation.org https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev