1. 引言
比特币闪电网络论文笔记参见:
闪电网络实际实现参见设计文档 Basis of Lightning Technology (BOLT) :
BOLT设计文档分为10个子部分:
- BOLT #1:Base Protocol
- BOLT #2:Peer Protocol for Channel Management
- BOLT #3:Bitcoin Transaction and Script Formats
- BOLT #4:Onion Routing Protocol
- BOLT #5:Recommendations for On-chain Transaction Handling
- BOLT #7:P2P Node and Channel Discovery
- BOLT #8:Encrypted and Authenticated Transport
- BOLT #9:Assigned Feature Flags
- BOLT #10:DNS Bootstrap and Assisted Node Location
- BOLT #11:Invoice Protocol for Lightning Payments
1.1 闪电网络关键技术简介
闪电网络为使用通道网络实现比特币快速支付的协议。
闪电网络中使用的核心技术有:
-
1)Channels通道
两个参与者创建闪电支付通道,往通道内存入一定数额的比特币(如0.1BTC),通道内的比特币金额会锁定在Bitcoin主网上,仅有双方签名才可消费。
最初,他们各自持有一个比特币交易,可将所有金额(如0.1BTC)全部发送回一方。
稍后,他们可签名新的比特币交易,将资金拆分,如0.09BTC给一方,0.01BTC给另一方,然后设置之前的比特币交易为无效的——即之前的比特币交易不可再消费。
– 通道创建的信息,可参看 BOLT #2:Channel Establishment。
– 创建通道时的比特币交易格式,可参看 BOLT #3:Funding Transaction Output。
– 当参与方不同意或失败时,必须消费cross-signed bitcoin transaction,详细的处理流程可参看 BOLT #5:Recommendations for On-chain Transaction Handling。 -
2)Conditional Payments 有条件支付
一个闪电通道仅支持两个参与者之间支付,但是很多通道连接成网络,将支持网络内的所有用户之间进行支付。这其中用到的技术为:有条件支付——可附加在通道上,如,“若你能在6小时内公开某个秘密,你将获得0.01BTC”。一旦接收方公开了秘密,则该笔比特币交易将被一个缺少有条件支付的交易所替代,并将相应的资金添加到接收方的output中。
– 某一方添加有条件支付交易的命令格式,详细参见 BOLT #2:Adding an HTLC,完整的比特币交易格式可参见 BOLT #3:Commitment Transaction。 -
3)Forwarding 转发
有条件支付可 以lower time limit的方式安全地转发给另一参与者,如“若你能在5小时内公开某个秘密,你将获得0.01BTC”【”5小时“ < 之前的”6小时“】。一旦接收方公开了秘密,则该笔比特币交易将被一个缺少有条件支付的交易所替代,并将相应的资金添加到接收方的output中。
– 转发支付的详情参见 BOLT #2:Forwarding HTLCs
– 如何传送支付指令参见 BOLT #4:Packet Structure -
4)Network Topology 网络拓扑
要进行支付,参与者需要知道可通过哪些通道进行发送。参与者相互告知通道和节点的创建及更新信息。
– 详细的通讯协议参见 BOLT #7:P2P Node and Channel Discovery
– 初始的网络bootstrap参见 BOLT #10:DNS Bootstrap and Assisted Node Location -
5)Payment Invoicing 支付费用清单
参与者会收到支付清单,以告知他该支付什么。
– 描述收款对象及支付目的的协议,以便付款人以后能证明支付成功,协议详情见 BOLT #11:Invoice Protocol for Lightning Payments
1.2 词汇及术语指南
- Announcement:peers之间发送的gossip message,用于发现通道或节点。
- chain_hash:目标区块链的唯一标识hash值(通常为genesis hash值)。chain_hash允许节点在多个区块链上创建和引用通道。节点将忽略来源于其未引用的chain_hash 消息。与bitcoin-cli不同,该hash值不是反向的,而是可直接使用的。
比特币主网的chain_hash值为:6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000 - Channel:在2个peers之间实现快速链下交互。为了进行资金交互,peers交换签名来创建updated commitment transaction。
channel通道支持mutual close,revoked transaction close以及unilateral close (单方关闭)。 - Closing transaction:为mutual close时生成的交易之一。Closing transaction与commitment transaction类似,但是没有pending payments。
- Commitment number:用于每个commitment transaction中,为48位递增计数器。通道内每个peer的计数器是独立的,都从0开始。
- Commitment revocation(废除) private key:每一个commitment transaction都有一个唯一的commitment revocation private-key value,另一方若拥有该key value值,则可立马花费所有outputs中的金额:通过reveal该key value值,即可废除 old commitment transaction。为了支持废除,每个commitment transaction都引用了废除该commitment对应的public key。
- Commitment transaction:为花费funding transaction的transaction。每个peer都拥有对方对该笔交易的签名,因此,各自都有一个可花费的commitment transaction。当有新的commitment transaction时,老的将被废除。
- Final node:一笔支付由初始节点发起,经由多个中间节点(hops),到达的最终接收方。同时为链路中的最终接收节点。
- Funding transaction:为不可逆的链上交易,在一个通道内向2个peers付费。只有在双方同意的情况下才能使用。
- Hop:一种节点。通常为起始节点和最终节点之间的中间节点。
- HTLC:Hashed Time Locked Contract。
为2个peers之间的有条件支付:接收方通过展示其签名和支付preimage来获得相应金额,否则付款人可在指定时间后取消该付款合约。这些以commtiment transaction outputs的方式实现。 - Invoice:A request for funds on the Lightning Network, possibly。费用清单中包含:支付类型、支付金额、过期时间以及其他信息。这是闪电网络内的支付形式,而不是使用比特币式地址。
- It’s ok to be odd:为某些数域内的规则,表示对某种feature的可选或强制支持。偶数表示2个endpoints都必须支持所讨论的feature,而奇数表示endpoint可忽略该feature。
- MSAT:为一个millisatoshi,常用作field name。
- Mutual close:对通道的合作式关闭,通过广播一个unconditional spend of the funding transaction with an ouput to each peer(除非某个output太小才可不包含在内)。
- Node:作为闪电网络一部分的计算机或其他设备。
- Origin node:为一笔支付的初始节点,经由数个hops,到达最终节点。Origin node为链路上的第一个发送peer。
- Outpoint:唯一标识unspent transaction output的transaction hash和output index。需作为输入来组成一笔新的交易。
- Payment hash:HTLC中包含了payment hash,payment hash为payment preimage的hash值。
- Payment preimage:为付款已收到的证明,由最终接收方持有。只有最终接收方知道该秘密。最终接收方为了release funds,需release该preimage。支付preimage 在HTCL中以payment hash的方式存在。
- Peers:为两个相互通讯的节点。2个peers在建立通道之前可相互gossip。2个peers可通过建立通道来相互交易。
- Penalty transaction:通过使用commitment revocation private key来消费revoked commitment transaction中所有outputs的交易。若某peer试图通过广播一个废弃的commitment transaction的方式来作弊,则另一peer可发起penalty transaction。
- Per-commitment secret:每个commitment transaction都基于a per-commitment secret来派生keys,通过该方式,所有之前commitments的一系列per-commitment secrets都可以压缩的方式存储。
- Processing node:为正在处理a packet的节点。该packet由origin node发起,路由发往final node。Processing node作为receiving peer来接收消息,作为sending peer来发送packet。
- Receiving node:为正在receiving 消息的节点。
- Revoked commitment transaction:为已废弃的old commitment transaction。因为已产生新的commitment transaction。
- Revoked transaction close:为一个无效的通道关闭,广播的是废弃的commitment transaction。由于另一peer知道该commitment revocation secret key,可发起penalty transaction。
- Route:为闪电网络中的路径,允许由初始节点发起的支付,经由一个或多个hops,到达最终节点。
- Sending node:为正在sending消息的节点。
- Sending peer:为正在给直接连接的peer发送消息的节点。
- Unilateral close:(单方关闭)为通道的不合作关闭方式。通过广播commitment transaction来实现。该交易比closing transaction更大(即更低效),commitment被广播的peer在预设时间内,无法访问其自身的outputs。
2. BOLT #1: Base Protocol
此协议假定一个底层的经过身份验证且有序的传输机制,该机制负责对单个消息进行帧处理。详细实现可参见 BOLT #8,也可替代为其他传输机制。
默认的TCP端口为9735,对应的16进制表示为0x2607,为 the Unicode code point for LIGHTNING。
除非明确指出,所有数据field都是以unsigned big-endian形式存储。(默认SHA2和比特币公钥都是以big endian的方式编码的。)
每个peer有一个单独的连接(connection),通道信息(其中包含channel ID)应可在单个连接上复用。
2.1 闪电消息格式
解密后,所有的闪电消息格式为:
- 1)type:为2字节的big-endian field,表明消息的类型。
- 2)payload:为可变长度的payload,包含了剩余message的内容,其格式与type类型匹配。
- 3)extension:为可选的 TLV(Type-Length-Value Format) stream。
不同的type类型,其解析payload的方式也不同。type类型遵循”It’s ok to be odd“规则,若不确定接收方是否理解,可发送奇数类型。(”It’s ok to be odd“规则 允许将来的可选extension扩展,而不需要协商,也不需要在客户端进行特殊编码。在可选扩展中,未来可包含额外的TLV data。注意,只有当payload长度不等于65535最大长度时,才可附加extension field。)
闪电消息类型逻辑上可分为5类,由最高有效位的值来区分:
- Setup & Control (类型值为0-31):表示建立连接、control、supported features以及error reporting相关的消息。Setup类型对应有init消息和error消息;Control类型对应有ping消息和pong消息
- Channel (类型值为31-127):用于建立和关闭微支付通道的消息。
- Commitment(类型值为128-255):用于更新当前commitment transaction的消息,包括adding、revoking、settling HTLCS以及更新费用和交换签名。
- Routing(类型值为256-511):节点和通道声明消息,以及任意的active route exploration消息。
- Custom(类型值为32768-65535):为测试和应用相关消息。
应传输层要求,message的size应为2字节的unsigned int,因此消息的最大size为65535 bytes。(可借助密码学wrapping技术来保证消息长度不超过65535字节。实际实现时,可将message数据以8字节对齐的方式存储,但是额外附加6个字节被认为是一种浪费,因此只在对message解码到buffer中时才做一个6字节的pre-padding。)
对于sending node:
- 未经事先协商,不得发送此处未列出的evenly-typed message。
- 未经事先协商,不得在extension中发送evenly-typed TLV records。
- 协商中的可选项:必须包含该可选项中注释的所有字段。
- 当定义custom messages时:为避免与其他custom type冲突,应选择随机type值;应不与此处列出的其他测试值冲突;当要求regular nodes可忽略additional data时,应选择奇数type值;当regular node可拒绝消息并关闭连接时,应选择偶数type值。
对于receiving node:
- 当接收到奇数或未知type值时,必须忽略所接收到的消息;
- 当接收到偶数或未知type值时,必须关闭连接,可fail通道。
- 当接收到已知消息,但其内容长度不够时:必须关闭连接,可fail通道。
- 当接收到的消息包含extension时:可忽略该extension;或者若该extension为invalid的,必须关闭连接,可fail通道。
2.2 TLV (Type-Length-Value Format)
当在现有消息类型中添加新的field时,为了向后兼容,可使用TLV。
tlv_record
表示一个单独的field,其编码格式为:
- [bigsize: type]:type以BigSize格式编码。为64位标识。
- [bigsize: length]:以BigSize格式编码,表示value的字节大小。
- [length: value]:根据type类型来编解码。
tlv_stream
表示0个或多个tlv_record
,直接将tlv_record
串接在一起。当用于扩展现有消息时,tlv_stream
通常位于现有所有定义fields之后。
2.3 基础类型
基础类型有:
- byte: an 8-bit byte
- u16: a 2 byte unsigned integer
- u32: a 4 byte unsigned integer
- u64: an 8 byte unsigned integer
TLV record中的类型有:
- tu16: a 0 to 2 byte unsigned integer
- tu32: a 0 to 4 byte unsigned integer
- tu64: a 0 to 8 byte unsigned integer
同时,有一些自定义类型:
- chain_hash: a 32-byte chain identifier (see BOLT #0)
- channel_id: a 32-byte channel_id (see BOLT #2)
- sha256: a 32-byte SHA2-256 hash
- signature: a 64-byte bitcoin Elliptic Curve signature
- point: a 33-byte Elliptic Curve point (compressed encoding as per SEC 1 standard)
- short_channel_id: an 8 byte value identifying a channel (see BOLT #7)
- bigsize: a variable-length, unsigned integer similar to Bitcoin’s CompactSize encoding, but * big-endian. Described in BigSize.
3. BOLT #2: Peer Protocol for Channel Management
某些消息会使用channel_id
来标识通道。channel_id
派生自funding transaction,结合了funding_txid
和 funding_output_index
,采用了big-endian异或操作(即,funding_output_index
改变了最后2个字节)。
在通道建立之前,使用的是随机nonce值 temporary_channel_id
。注意,不同节点之间可能存在相同的temporary_channel_id
值。若在创建funding transaction之前,通过channel_id来引用通道的API是不安全的,同时该API产生的交易即使确认了也是不持久的。而且除非你知道对应funding output对应的script pubkey,否则没有办法来避免channel id重复的问题。在funding_created之前,由协议提供并交换的channel标识为(source_node_id, destination_node_id, temporary_channel_id) tuple。
3.1 建立通道
在对连接进行认证(BOLT #8)和初始化(BOLT #1)之后,就可开始建立通道。
具体流程为:
- 1)funding node (funder) 发送
open_channel
消息。 - 2)另一node (fundee) 发送
accept_channel
消息。 - 3)在锁定通道参数的情况下,funder可创建funding transaction和2个版本的commitment transaction(具体见BOLT #3)。然后funder将funding output的outpoint、
funding_created
消息、签名给fundee版本的commitment transaction 发送给fundee。 - 4)一旦fundee收到了该funding output,其可生成签名给funder版本的commitment transaction,并将其
funding_signed
消息发给funder。 - 5)当funder收到
funding_signed
消息,其必须将funding transaction广播至比特币主链上。 - 6)当发送/收到
funding_signed
消息之后,双方都需等待funding transaction交易上链并达到指定的深度(区块确认数)。当双方都发出了funding_locked
消息之后,通道建立完成,即可进行normal operation了。【通道内发送的金额以msat为单位,尽管上链的金额应不低于某dust limit。】
funding_locked
消息中包含了用于构建channel authentication proof的信息。
若在以上任一环节失败,或某节点判定另一节点提供的通道条件不合适,则通道建立失败。
注意,多个通道可并行操作,所有的通道的消息要么以temporary_channel_id
(在funding transaction 创建之前)标记,要么以channel_id
(派生自funding transaction)标记。
+-------+ +-------+
| |--(1)--- open_channel ----->| |
| |<-(2)-- accept_channel -----| |
| | | |
| A |--(3)-- funding_created --->| B |
| |<-(4)-- funding_signed -----| |
| | | |
| |--(5)--- funding_locked ---->| |
| |<-(6)--- funding_locked -----| |
+-------+ +-------+
- where node A is 'funder' and node B is 'fundee'
- 1)A节点发起创建新通道的请求,在
open_channel
消息中的关键字段有:
[chain_hash:chain_hash]:通道所锚定的链,为该链的genesis hash。
[32*byte:temporary_channel_id]:为临时channel id(对该A节点来说是唯一标识的),在funding_created会替换为正式的channel_id(由funding transaction派生)。
[u64:funding_satoshis]:充入通道内的资金。单位为sat。
[u64:push_msat]:充入通道内的资金。单位为msta。为funding_satoshis*1000。
[u64:dust_limit_satoshis]:比特币链上支付的最小金额为546sat。低于该阈值的金额不会映射上链。
[u64:channel_reserve_satoshis]:为the minimum amount that the other node is to keep as a direct payment。该值应大于等于dust_limit_satoshis。
[u64:max_htlc_value_in_flight_msat]:为未偿付HTLC总价值的上限,允许节点限制其对HTLC的敞口
[u64:htlc_minimum_msat]:本节点所能接受的最小金额的HTLC。
[u16:max_accepted_htlcs]:限制其他节点可以提供的未完成HTLC的数量。
[point:funding_pubkey]、[point:revocation_basepoint]、[point:payment_basepoint]、[point:delayed_payment_basepoint]、[point:htlc_basepoint]为secp256k1公钥。【
其中:
funding_pubkey:为funding transaction output的2-of-2 multisig script中的公钥。
各种_basepoint字段:用于为每个commitment transaction派生唯一的秘钥。每个commitment transaction都使用不同唯一的localpubkey和remotepubkey。
这样可保证对于外部观察者而言,每个commitment transaction的交易ID是不可预测的。当将penalty交易外包给第三方时,该属性可保证隐私。
】
[point:first_per_commitment_point]:为第一笔commitment transaction的per-commitment point。
[byte:channel_flags]:设置为0,表示 publicly announce the channel.。用于表示通道发起方是否将该该通道向网络公开。
[u32:feerate_per_kw]:为计算commitment transaction和HTLC transaction的fee rate。通常只与发送方(支付费用的人)有关,但HTLC交易也会支付费率;因此,不合理的高费率也可能会惩罚接收者。
[u16:to_self_delay]:对方节点的to-self output必须等待的区块数,用于OP_CHECKSEQUENCEVERIFY delays。用于breakdown情况下需等待的时长,过了之后才能赎回自己的资金。
upfront_shutdown_script和shutdown_scriptpubkey:双向关闭通道时所使用的公钥脚本。
[open_channel_tlvs:tlvs]:
- 2)B节点接受A节点的通道开通请求,回应
accept_channel
消息中的关键字段有:
[32*byte:temporary_channel_id]:必须与open_channel消息中的temporary_channel_id一致。
[u64:dust_limit_satoshis]:必须小于等于open_channel消息中的channel_reserve_satoshis值。
[u64:max_htlc_value_in_flight_msat]
[u64:channel_reserve_satoshis]:必须大于等于open_channel消息中的dust_limit_satoshis值。
[u64:htlc_minimum_msat]
[u32:minimum_depth]:为防止funding transaction双花所需等待的区块数。
[u16:to_self_delay]
[u16:max_accepted_htlcs]
[point:funding_pubkey]
[point:revocation_basepoint]
[point:payment_basepoint]
[point:delayed_payment_basepoint]
[point:htlc_basepoint]
[point:first_per_commitment_point]
[accept_channel_tlvs:tlvs]
- 3)在锁定通道参数的情况下,funder可创建funding transaction和2个版本的commitment transaction(具体见BOLT #3)。然后funder将funding output的outpoint、
funding_created
消息、签名给fundee版本的commitment transaction 发送给fundee。
A节点验证完B发来的accept_channel
消息之后,A会创建初始(第一笔)commitment transaction的outpoint,并在funding_created
消息中描述该outpoint,funding_created
消息中的关键字段有:
[32*byte:temporary_channel_id]:必须与open_channel消息中的temporary_channel_id一致。
[sha256:funding_txid]:为A节点所创建的第一笔commitment transaction(为non-malleable transaction)的交易ID。不可将该交易广播上链。
[u16:funding_output_index]:为funding transaction output中的output序号。仅为2字节,不超过65535个output。
[signature:signature]:为A节点的funding_pubkey对第一笔commitment transaction的签名。
- 4)一旦fundee收到了该funding output,其可生成签名给funder版本的commitment transaction,并将其
funding_signed
消息发给funder。
B节点验证完funding_created
之后,回应funding_signed
消息中有:
[channel_id:channel_id]:生成正式的channel_id来标记该通道。派生自funding_txid和funding_output_index,对二者进行big-endian异或计算。
[signature:signature]:使用B的funding_pubkey对A发来的第一笔commitment transaction进行签名。
- 5)当funder收到
funding_signed
消息,其必须将funding transaction广播至比特币主链上。 - 当发送/收到
funding_signed
消息之后,双方都需等待funding transaction交易上链并达到指定的深度(区块确认数)。当双方都发出了funding_locked
消息之后,通道建立完成,即可进行normal operation了。
funding_locked
消息中包含了用于构建channel authentication proof的信息。
A确认其广播上链的funding transaction达到了在accept_channel
中要求的minimum_depth
时,会向B发送funding_locked
消息:
[channel_id:channel_id]
[point:next_per_commitment_point]:为下一个commitment transaction将使用的per-commitment point。
- 6)B确认A的funding transaction交易上链达到了指定的深度后,向A发送
funding_locked
消息。至此,通道创建完成。
3.2 关闭通道
节点可协商以mutual close的方式关闭连接,与unilateral close不同,mutual close支持双方以更低的手续费立刻获取各自的资金。
关闭发生在2种阶段:
- 1) 一方表示希望清理通道(因此不再接受新的HTLCs)
- 2)当所有的HTLCs都处理完毕后,可开始协商最终的通道关闭。
+-------+ +-------+
| |--(1)----- shutdown ------->| |
| |<-(2)----- shutdown --------| |
| | | |
| | <complete all pending HTLCs> | |
| A | ... | B |
| | | |
| |--(3)-- closing_signed F1--->| |
| |<-(4)-- closing_signed F2----| |
| | ... | |
| |--(?)-- closing_signed Fn--->| |
| |<-(?)-- closing_signed Fn----| |
+-------+ +-------+
mutual close关闭通道的流程为:
- Closing Initiation:
shutdown
:任一节点或2个节点发送shutdown
消息来启动关闭,shutdown
消息会附带其希望收款的scriptpubkey
。 - Closing Negotiation:
closing_signed
:一旦shutdown
完成,且通道内没有HTLCs,即the final current commitment transaction中没有HTLCs,即可开始closing fee 协商。Funder可选择一个自认为公平的费率,然后使用shutdown
消息中附带的scriptpubkey
值来对closing transaction和其自认公平的费率进行签名,并发送该签名。另一节点以类似的方式响应,使用其自认公平的费率。这种交互持续到直到双方达成相同的费率或者某一方fail the channel。
详细的消息流为:
- 1)A发起关闭请求,发送
shutdown
消息:【不再接受新的HTLCs】
[channel_id:channel_id]
[u16:len]
[len*byte:scriptpubkey]:为A希望收款的scriptpubkey。
- 2)B回应关闭请求,在
shutdown
消息中提供其收款地址。 - 3)等待通道内HTLCs都处理完毕后。最后一笔commitment transaction中将没有HTLCs。然后开始关闭费用协商。
Funder可选择一个自认为公平的费率,然后使用shutdown
消息中附带的scriptpubkey
值来对closing transaction和其自认公平的费率进行签名,并发送该签名。另一节点以类似的方式响应,使用其自认公平的费率。这种交互持续到直到双方达成相同的费率或者某一方fail the channel。
A发送closing_signed
消息:
[channel_id:channel_id]
[u64:fee_satoshis]:A认为合理的手续费区间。B需要从该区间选一个fee值。
[signature:signature]:采用shutdown消息中的scriptpubkey字段内的公钥对closing交易进行签名。
[closing_signed_tlvs:tlvs]
3.3 正常的通道操作
当节点双方交换完funding_locked
之后(也可为announcement_signatures),通道将可借助Hashed Time Locked Contracts来发起支付。
批量修改(changes are sent in batches):在commitment_signed
消息之前,发送一个或多个update_
消息,具体流程为:
+-------+ +-------+
| |--(1)---- update_add_htlc ---->| |
| |--(2)---- update_add_htlc ---->| |
| |<-(3)---- update_add_htlc -----| |
| | | |
| |--(4)--- commitment_signed --->| |
| A |<-(5)---- revoke_and_ack ------| B |
| | | |
| |<-(6)--- commitment_signed ----| |
| |--(7)---- revoke_and_ack ----->| |
| | | |
| |--(8)--- commitment_signed --->| |
| |<-(9)---- revoke_and_ack ------| |
+-------+ +-------+
与直觉相反,这些更新会先添加到给对方节点的commitment transaction中,待对方节点通过revoke_and_ack
方式确认后,才会将这些更新添加到本地节点自身的commitment transaction中。
每次更新都会遍历以下状态:
- 1)pending on the receiver
- 2)在receiver的最新commitment transaction中
- 3)废弃了receiver之前的commitment transaction,同时the update is pending on the sender
- 4)在sender最新的commitment transaction中
- 5)废弃了sender之前的commitment transaction。
由于2个节点是独立更新的,所以这2个commitment transaction可能会无限期地不同步。这没有关系,重要的是双方是否不可撤销地致力于某一特定的更新。
3.3.1 转发HTLCs
通常,节点发送HTLC的原因有2种:
- 发起其自身的支付
- 转发另一节点的支付。
在转发情况下,必须注意确保传出的HTLC不能被赎回,除非传入的HTLC可以被赎回。在下列情况下,HTLC的相应增加或删除可被视为是不可撤销committed的:
- 1)with/without commitment transaction由通道内的2个节点commit了,且任何之前的without/with commitment transaction均已废弃。或者
- 2)with/without commitment transaction已不可逆地提交上链了。
3.3.2 选择cltv_expiry_delta
一旦HTLC超时,它可以被完成或者超时;无论是提供的还是收到的HTLC,都必须注意这个过渡。
考虑下面的场景,其中A发送HTLC到B,转发给C,一旦收到付款,就立即交付货物:
- 1)C需要确认B发来的HTLC不会超时,即使B不响应。即,B在链上使该HTLC超时之前,C可在链上完成该incoming HTLC。
- 2)B必须确保C所完成的HTLC来自于B,B完成的incoming HTLC来自于A。即,B可get the preimage from C,且fulfill the incoming HTLC on-chain before A can time it out on-chain。
这其中涉及的关键设置有:
- BOLT #7 中的
cltv_expiry_delta
:为转发情况下(B)的minimum difference in HTLC CLTV timeouts. - BOLT #9 中的
min_final_cltv_expiry
:为终端情况下(C)的minimum difference between HTLC CLTV timeout and the current block height。
3.3.3 添加HTLC:update_add_htlc
通道内的任一节点都可发送update_add_htlc
来给另一方提供HTLC,通过提供payment preimage可赎回该HTLC。
支付金额以millisatoshi为单位,尽管链上执行的金额需大于dust limit(在commitment中,该金额会按BOLT #3 进行四舍五入)。
update_add_htlc
消息中:
[channel_id:channel_id]
[u64:id]:第一个HTLC的id为0,后续提供的每个HTLC该id加1。
[u64:amount_msat]:金额单位为msat。
[sha256:payment_hash]:
[u32:cltv_expiry]:HTLC超时时间。
[1366*byte:onion_routing_packet]:包含一个模糊的跳跃列表,以及路径上每个跳跃的指令。以payment_hash为关联数据,采用HMAC算法来对HTLC进行commit,可防止使用 之前的onion_routing_packet+不同的payment_hash进行重放攻击。
3.3.4 移除HTLC:update_fulfill_htlc
,update_fail_htlc
,update_fail_malformed_htlc
节点仅可移除由其它节点添加的HTLCs。
移除HTLC通常有4种原因:
- 已提供了payment preimage:对应
update_fulfill_htlc
消息:
[channel_id:channel_id]
[u64:id]
[32*byte:payment_preimage]
- HTLC已超时:对应
update_fail_htlc
消息。 - HTLC路由失败:对应
update_fail_htlc
消息:
[channel_id:channel_id]
[u64:id]
[u16:len]
[len*byte:reason]
- HTLC格式错误:对应
update_fail_malformed_htlc
消息:
[channel_id:channel_id]
[u64:id]
[sha256:sha256_of_onion]
[u16:failure_code]
3.3.5 迄今为止的Committing Updates:commitment_signed
当节点为远程的commitment完成了修改后,其可应用该远程commitment,签名the resulting transaction(根据BOLT #3中定义),并发送commitment_signed
消息。
commitment_signed
消息内容为:
[channel_id:channel_id]
[signature:signature]:A节点对发给B的resulting transaction进行签名。
[u16:num_htlcs]:该commitment中包含的htlc数量。
[num_htlcs*signature:htlc_signature]:对每个HTLC交易的签名,与commitment transaction中的顺序一致。
3.3.6 Completing the Transition to the Updated State:revoke_and_ack
一旦收到commitment_signed
,对签名进行验证并确认其为有效的新commitment transaction之后,在回复的revoke_and_ack
消息中附加the commitment preimage for the previous commitment transaction。
可将revoke_and_ack
简单理解为是对收到commitment_signed
之后的响应,因此对于commitment_signed
sender来说,其在发送消息和更新任何pending updates之间存在逻辑上的时间差。
revoke_and_ack
消息中有:
[channel_id:channel_id]
[32*byte:per_commitment_secret]:接收方发出的前一commitment transaction中对应的preimage(即前一commitment transaction中各公钥对应的私钥信息)【应根据该秘密可计算出前一commitment transaction中的`per_commitment_point`字段。】
[point:next_per_commitment_point]:为接收方下一个commitment transaction中将用到的值。
3.3.7 更新费用:update_fee
update_fee
消息由支付比特币交易费的节点发出。与其他update类似,其首先commit to the receiver’s commitment transaction,然后收到相应的acknowledgement 后commit to the sender’s。
与HTLC不同,update_fee
永不关闭,仅是简单的替换。
存在竞争的可能性,因为接收者可以在收到update_fee
之前添加新的HTLC。在这种情况下,一旦接收方最终确认了update_fee
,发送方就可能无法支付其自己的commitment transaction的费用。在这种情况下,费用将低于费率,如BOLT # 3 所述。
update_fee
消息中有:
[channel_id:channel_id]
[u32:feerate_per_kw]
3.4 消息重传:channel_reestablish
由于通讯传输是不可靠的,可能需不时地进行重连,所以传输的设计已经明确地从协议中分离出来。
具体见BOLT #7。
channel_reestablish
消息内有:
[channel_id:channel_id]
[u64:next_commitment_number]:为48位递增计数器,每个commitment transaction该值会加1。且每个节点该计数器从0开始,分别独立计数。仅用于re-establishment。
[u64:next_revocation_number]
[32*byte:your_last_per_commitment_secret]
[point:my_current_per_commitment_point]
4. BOLT #3: Bitcoin Transaction and Script Formats
transactions outputs的排序规则为:
- 首先根据transaction outputs的值(以整数satoshi为单位,注意HTLC outputs中的millisatoshi必须忽略);
- 接着是
scriptpubkey
,使用memcmp
比较common-length prefix的字典顺序,然后选择更短的script; - 最后,对于HTLC outputs,按
cltv_expiry
升序排列。
闪电网络中的大多数交易outputs都为 pay-to-witness-script-hash (P2WSH) outputs:即P2SH的Segwit版本。
为了消费这些outputs,witness stack中的最后一个元素必须为the actual script that was used to generate the P2WSH output that is being spent。
Funding Transaction Output 为P2WSH to :(其中pubkey1为词典序更小的funding_pubkey,pubkey2为词典序更大的。)
2 <pubkey1> <pubkey2> 2 OP_CHECKMULTISIG
4.1 Commitment Transaction
commitment transaction格式为:
- version: 2
- locktime:高8位为0x20,低24位为模糊的commitment number
- txin count: 1
– txin[0] outpoint: txid and output_index from funding_created message
– txin[0] sequence: upper 8 bits are 0x80, lower 24 bits are upper 24 bits of the obscured commitment number
– txin[0] script bytes: 0
– txin[0] witness:0 <signature_for_pubkey1> <signature_for_pubkey2>
The 48-bit commitment number is obscured by XOR with the lower 48 bits of:
SHA256(payment_basepoint from open_channel || payment_basepoint from accept_channel)
该值可让2节点根据index快速找到某废弃的commitment transaction。
Commitment Transaction Outputs:可支持penalty transactions,必须等待to_selft_delay
个blocks。该等待操作可通过second-stage HTLC交易来实现(HTLC-success for HTLCs accepted by the local node, HTLC-timeout for HTLCs offered by the local node)。
将HTLC output分为不同交易阶段的原因在于,HTLC要么timeout,要么在to_self_delay
期内被fulfill。否则,HTLC所需的最少timeout将随着该delay而延长,导致HTLC穿越网络的超时时间更长。
commitment transaction的每个output将四舍五入为整sat值。若该值减去HTLC的手续费,小于该commitment transaction owner设置的dust_limit_satoshis
值,则不应生成该output。
Commitment Transaction Outputs类型有:
- 1)
to_local
Output:该output将资金发回该commitment transaction owner,必须使用OP_CHECKSEQUENCEVERIFY
进行time lock。而对手方无需delay,通过提交revocation private key即可拿回其资金。该output为 version-0 P2WSH + a witness script:【己方需提供:<local_delayedsig> <> 并等待to_self_delay
才生效;对手方提供:<revocation_sig> 1 即立即生效。】
OP_IF
# Penalty transaction
<revocationpubkey>
OP_ELSE
`to_self_delay`
OP_CHECKSEQUENCEVERIFY
OP_DROP
<local_delayedpubkey>
OP_ENDIF
OP_CHECKSIG
- 2)
to_remote
Output:若在commitment transaction中使用了option_anchors
,对应为:<remote_pubkey> OP_CHECKSIGVERIFY 1 OP_CHECKSEQUENCEVERIFY,需等待一个block的csv lock,然后提供<remote_sig>即可。若未使用option_anchors
,该output就是简单的P2WPKH toremotepubkey
。 - 3)
to_local_anchor
andto_remote_anchor
Output (option_anchors): - 4)Offered HTLC Outputs:当HTLC-timeout之后,该output会将资金发送给an HTLC-timeout transaction;或者,通过使用payment preimage或revocation key,该output将资金发送给远程节点。该output是 a P2WSH + a witness script:
# To remote node with revocation key
OP_DUP OP_HASH160 <RIPEMD160(SHA256(revocationpubkey))> OP_EQUAL
OP_IF
OP_CHECKSIG //输入为<revocation_sig> <revocationpubkey>
OP_ELSE
<remote_htlcpubkey> OP_SWAP OP_SIZE 32 OP_EQUAL
OP_NOTIF
# To local node via HTLC-timeout transaction (timelocked).
OP_DROP 2 OP_SWAP <local_htlcpubkey> 2 OP_CHECKMULTISIG
OP_ELSE
# To remote node with preimage.
OP_HASH160 <RIPEMD160(payment_hash)> OP_EQUALVERIFY //输入为<remotehtlcsig> <payment_preimage>
OP_CHECKSIG
OP_ENDIF
OP_ENDIF
- 5)Received HTLC Outputs:当HTLC-timeout或使用revocation key,该output将资金发送给远程节点;或者,通过成功的payment preimage,该output将资金发送给an HTLC-success transaction。该output为 a P2WSH + a witness script:
# To remote node with revocation key
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
# To local node via HTLC-success transaction.
OP_HASH160 <RIPEMD160(payment_hash)> OP_EQUALVERIFY
2 OP_SWAP <local_htlcpubkey> 2 OP_CHECKMULTISIG
OP_ELSE
# To remote node after timeout.
OP_DROP <cltv_expiry> OP_CHECKLOCKTIMEVERIFY OP_DROP
OP_CHECKSIG
OP_ENDIF
OP_ENDIF
- 6)Trimmed Outputs:每个节点设置
dust_limit_satoshis
,不产生低于该值的outputs。这些不该产生的outputs标记为“trimmed”。a trimmed output被认为太小,不值得创建,而是添加到commitment transaction fee中。对于HTLC,需要考虑到第二阶段HTLC交易也可能低于该限额。
4.2 HTLC-Timeout and HTLC-Success Transactions
HTLC-Timeout 和 HTLC-Success 交易几乎一样,除了HTLC-Timeout交易为timelocked。
HTLC-Timeout 和 HTLC-Success 交易均可作为valid penalty transaction来花费。
version: 2
locktime: 0 for HTLC-success, cltv_expiry for HTLC-timeout
txin count: 1
txin[0] outpoint: txid of the commitment transaction and output_index of the matching HTLC output for the HTLC transaction
txin[0] sequence: 0 (set to 1 for option_anchors)
txin[0] script bytes: 0
txin[0] witness stack: 0 <remotehtlcsig> <localhtlcsig> <payment_preimage> for HTLC-success, 0 <remotehtlcsig> <localhtlcsig> <> for HTLC-timeout
txout count: 1
txout[0] amount: the HTLC amount minus fees (see Fee Calculation)
txout[0] script: version-0 P2WSH with witness script as shown below
该output的witness script为:
OP_IF
# Penalty transaction
<revocationpubkey> //该输入为<revocationsig> 1
OP_ELSE
`to_self_delay`
OP_CHECKSEQUENCEVERIFY
OP_DROP
<local_delayedpubkey> //该输入为<local_delayedsig> 0
OP_ENDIF
OP_CHECKSIG
4.3 Closing Transaction
注意每个节点有2种可能的变体:
- version: 2
- locktime: 0
- txin count: 1
– txin[0] outpoint: txid and output_index from funding_created message
– txin[0] sequence: 0xFFFFFFFF
– txin[0] script bytes: 0
– txin[0] witness:0 <signature_for_pubkey1> <signature_for_pubkey2>
- txout count: 0, 1 or 2
– txout amount: final balance to be paid to one node (minus fee_satoshis from closing_signed, if this peer funded the channel)
– txout script: as specified in that node’sscriptpubkey
in itsshutdown
message
4.4 费用
commitment transaction和HTLC transaction的费用需基于当前的feerate_per_kw
和交易expected weight来计算。
The actual and expected weights vary for several reasons:
- Bitcoin uses DER-encoded signatures, which vary in size.
- Bitcoin also uses variable-length integers, so a large number of outputs will take 3 bytes to encode rather than 1.
- The to_remote output may be below the dust limit.
- The to_local output may be below the dust limit once fees are extracted.
Thus, a simplified formula for expected weight is used, which assumes:
- Signatures are 73 bytes long (the maximum length).
- There are a small number of outputs (thus 1 byte to count them).
- There are always both a to_local output and a to_remote output.
- (if option_anchors) there are always both a to_local_anchor and to_remote_anchor output.
This yields the following expected weights:(详细可见博客比特币闪电网络中的dust limit
)
Commitment weight (no option_anchors): 724 + 172 * num-untrimmed-htlc-outputs
Commitment weight (option_anchors): 1124 + 172 * num-untrimmed-htlc-outputs
HTLC-timeout weight (no option_anchors): 663
HTLC-timeout weight (option_anchors): 666
HTLC-success weight (no option_anchors): 703
HTLC-success weight (option_anchors): 706
commitment transaction的交易金额和交易费均从funder账号扣除。
举例为:
For example, suppose there is a feerate_per_kw of 5000, a dust_limit_satoshis of 546 satoshis, and a commitment transaction with:
- two offered HTLCs of 5000000 and 1000000 millisatoshis (5000 and 1000 satoshis)
- two received HTLCs of 7000000 and 800000 millisatoshis (7000 and 800 satoshis)
The HTLC-timeout transaction weight is 663, and thus the fee is 3315 satoshis. The HTLC-success transaction weight is 703, and thus the fee is 3515 satoshis
The commitment transaction weight is calculated as follows:
- weight starts at 724.
- The offered HTLC of 5000 satoshis is above 546 + 3315 and results in:
- an output of 5000 satoshi in the commitment transaction
- an HTLC-timeout transaction of 5000 - 3315 satoshis that spends this output
- weight increases to 896
- The offered HTLC of 1000 satoshis is below 546 + 3315 so it is trimmed.
- The received HTLC of 7000 satoshis is above 546 + 3515 and results in:
- an output of 7000 satoshi in the commitment transaction
- an HTLC-success transaction of 7000 - 3515 satoshis that spends this output
- weight increases to 1068
- The received HTLC of 800 satoshis is below 546 + 3515 so it is trimmed.
The base commitment transaction fee is 5340 satoshi; the actual fee (which adds the 1000 and 800 satoshi HTLCs that would make dust outputs) is 7140 satoshi. The final fee may be even higher if the to_local
or to_remote
outputs fall below dust_limit_satoshis
.
4.5 交易中所使用key的派生规则
每个commitment transaction都使用唯一的localpubkey
和remotepubkey
。
HTLC-success和HTLC-timeout 交易使用local_delayedpubkey
和revocationpubkey
。
每个交易的这些key会根据per_commitment_point
修改。
要求每笔交易的key是变化的,是为了可外包trustless watching for revoked transaction。
考虑效率问题,这些key基于由单个种子产生的一系列per-commitment secrets来生成,使得receiver可对这些秘密进行压缩存储:
localpubkey, local_htlcpubkey, remote_htlcpubkey, local_delayedpubkey, and remote_delayedpubkey Derivation
5. BOLT #5: Recommendations for On-chain Transaction Handling
闪电网络支持2方(a local node和a remote node),通过给每一方一个cross-signed commitment transaction,用于描述通道内的当前状态(通常为当前balance)的方式,来实现链下交易。每当有新的支付时,该commitment transaction都将更新,且总是spendable的。
关闭通道的方式通常有3种:
- 最好的方式——mutual close:local node和remote node同时同意关闭通道。他们发起closing transaction(与commitment transaction类似,但是没有任何的pending payments),并将该closing transaction广播上链。
- 不好的方式——unilateral close:出了问题,可能双方都没有恶意。比如说,可能有一方崩溃了。一方公布最新承诺交易。
- 最不好的方式——revoked transaction close:某一方试图作弊,广播过期的commitment transaction。
闪电网络为trustless的,可有效处理以上3种情况。
任何unspent output 可认为是unresolved。可通过resoling transaction来花费unspent output。
当output在链上记录的深度超过100个区块,即可认为该output是resolved的。100个区块大于目前已知的比特币分叉高度,同时等于矿工激励等待的确认数。