本文介绍了多方参与的潜水艇互换(Submarine Swaps)方案,旨在提高闪电网络中链上和链下资产互换的效率。通过将传统的两方互换扩展到多方,可以减少链上交易的足迹,提高吞吐量。文章详细讨论了链上到链下以及链下到链上两种互换场景,并提出了减少恶意行为的措施,如手续费、预存系统和忠诚债券。
作者:conduition
来源: https://conduition.io/scriptless/multi-party-submarine-swaps/
“ 潜水艇互换” 允许闪电网络上的用户免信任地将链内的 UTXO 置换成闪电通道中的余额。它基本上就是用于闪电网络的原子化互换,并且对闪电节点运营者极其有用(可用来重新平衡他们的通道,以及其他事项)。
随着潜水艇互换变得日益重要和常见,也许是时候该看看如何更好地扩大潜水艇互换的吞吐量了 —— 如今,更多的对等节点和流动性提供者可以参与互换。
传统的潜水艇互换是一种两方的原子化互换,使用两个哈希时间锁合约(HTLC):一个部署在比特币链内;另一个部署在闪电网络中。
假设 Alice 想要卖出链内的比特币,换成一笔闪电支付;而 Bob 想要使用他的闪电通道余额来购买 Alice 的链内资金。
首先,Alice 要生成一个只有她自己知道的随机秘密值 $s$ 。
Alice 和 Bob 构造一个 2-of-2 的托管地址:如果 Bob 知晓了 $s$ ,将拥有这个地址的完全花费权限,这是用一个哈希锁条件来表达的;此外,在网络达到特定的区块高度 $B$ 之后,Alice 将获得这个地址的完全花费权限。
这是一个用描述符来表达的案例:
tr(
musig(<alice_pubkey>, <bob_pubkey>),
{
and(sha256(<hash>), pk(<bob_pubkey>)),
and(after(<B>), pk(<alice_pubkey>))
}
)
Alice 把自己的钱币存入这个 2-of-2 托管合约,确信自己可以在区块高度 $B$ 之后重新拿回资金,以及,Bob 当前是无法取走其中的钱的,因为只有她自己知道 $s$ 。
然后,Alice 给 Bob 一个闪电发票,其要求支付的数额与钱币的面额一样,并使用 $SHA256(s)$ 作为支付哈希值。Bob 可以支付这个发票,同时(通过 HTLC 的时间锁)要求 Alice 最晚在区块高度 $B - \Delta$ 就要释放原像(领取支付),这里的 $\Delta$ 是合理的时间延迟。如果 Alice 领取了 Bob 的闪电支付 HTLC(不论是与自己的通道对手完成协商,在链外释放原像、领取资金;还是强制关闭通道,Alice 在链内曝光原像来领取),Bob 就会知道 Alice 的秘密值原像 $s$ ,然后他就可以转走 上述托管合约中的资金。如果 Alice 很狡猾,到最后一刻,也就是区块高度 $B - \Delta$ 才领取支付,Bob 也拥有 $\Delta$ 个区块来知晓 $s$ 并使用它来领取 Alice 在链内的 HTLC(即上述合约)。
就是这样!Bob 和 Alice 可以彼此置换链内和链外的钱币,双方都没有机会欺诈对方。为了提升隐私性和效率性,Alice 和 Bob 可以合作:一旦 Bob 支付了闪电发票,双方就使用 MuSig 来联合签名花费上述合约的交易、将资金转移给 Bob(从而外人无法看出这是一笔 HTLC/潜水艇互换 交易)。
一些潜水艇互换供应商,比如 Lightning Labs 的 Loop 服务,会批量处理他们的链内交易。在清扫他们收到的链内钱币之时,一次清扫多个合约可以更好地将大量资金归集到少量的 UTXO 中。在给潜水艇互换的托管合约地址注资时,也可以这样做,每个输出都给一个独立的潜水艇互换合约注资。
但是,这里依然有一个效率瓶颈,来自潜水艇互换协议自身的拓扑。我们有许多小节点(用户),全部都跟一个潜水艇互换服务商(比如 Loop 或 Boltz)交互。用户们完全不知道其他人的交易,所以每一笔潜水艇互换都是一个完全独立的合约,发生在一个用户和一个互换服务商之间。这就产生了浪费。
而每一个从链内钱币到链外支付的潜水艇互换,都要求用户发起一笔单独的注资交易,因为用户们不知道彼此,所以无法一起批量处理他们的主子交易。此外,每一个潜水艇互换都会创建一个独立的注资交易输出,所以,即使注资交易 得到了 批处理(就像 Loop 的链外到链内协议一样),我们依然有 $n$ 个单独的注入了资金的 HTLC 地址,可能要用 $n$ 笔额外的交易来解决。
我们可以通过将潜水艇互换从单一接单者协议转变成 $n$-吃单者协议,来提高效率。 我们不再假设在每次互换中都是一个挂单人(maker)和一个吃单人(taker),而是假设有一个挂单人 以及 $n$ 个吃单人,他们有能力进行带有身份认证的通信,不论是通过 P2P 还是一个代理(比如挂单人)。这些参与者将通过将他们的 $n$ 个潜水艇互换合约聚合成一个注资 UTXO,一起执行一次免信任的原子化互换。
这会增加协议的复杂性和碎片化,但也能极大地提高链内效率。我们来看看这是怎么做到的。
我们先来看看 $n$ 个吃单人参与从链内到链外资金置换的情形。在这种情形下,交易的两边是:
不像传统的潜水艇互换中那样,吃单人们注资 $n$ 个链内单独的链内托管地址 —— 而是一起注资到单个托管合约中,并且资金是在单笔交易中转入的 —— 这个托管合约,要么被挂单人花掉(如果合约执行顺利的话),要么退回给各位吃单人(如果合约执行不顺利的话)。
以下是一个用描述符来表示的三重哈希锁案例:
tr(
musig(
<taker1_pubkey>,
<taker2_pubkey>,
<taker3_pubkey>,
<maker_pubkey>
),
and(
hash160(<hash1>),
hash160(<hash2>),
hash160(<hash3>),
pk(<maker_pubkey>)
)
)
使用 taproot 脚本,我们可以(通过聚合公钥协议)使用 4-of-4 的内部公钥,从而,在各方都配合的情况下,将体积很大的哈希锁完全隐藏起来。我们使用 hash160 而费 SHA256 是为了节约区块空间,同时保留在闪电网络中以相同的秘密值(原像)使用 HTLC 的选择。
挂单人有三种选择。
挂单人可以使用原像 ${s_1, s_2, …, s_n }$ 在哈希锁花费路径中领取注资交易输出。这样的 申领交易 会在网络中揭晓所有原像,从而吃单人们可以用这些原像来领取各自收到的 HTLC 中的资金。
即使挂单人拖到最后一刻才发布 领取交易,吃单人们依然有 $\Delta$ 个区块的时间窗口来领取各自通道中的 HTLC 中的资金。
挂单人可以将 ${s_1, s_2, …, s_n }$ 中的每一个分别交给对应的吃单人。吃单人可以使用这些原像来领取自己通道中的 HTLC 。作为交换,吃单人们应该跟挂单人配合签名一笔交易,从而将注资交易输出中的资金释放给挂单人。
即使有人拿原像兑换 HTLC 之后拒不交出签名,挂单人依然可以在链内强制执行、取走注资交易输出中的资金。
请注意,挂单人只交出 一部分 原像(而不是全部交付)是不理性的,因为实质上,每一个原像都是从挂单人处领取一些资金的权利。只要挂单人想在链上取走资金,就必然要揭晓所有的原像,而不是一部分。
挂单人可以选择不揭晓任何原像。因此,吃单人将无法领取各自通道中的 HTLC 。当网络达到区块高度 $B$ 的时候,任何一个吃单人都可以发布 超时交易,从而让资金返还给各吃单人。再过 $\Delta$ 个区块,他们各自通道中的 HTLC 也将过时。
如果使用 $n$ 次传统的潜水艇互换,链内的足迹最少也将是:
在理想情况下,我们这里的多方互换方法可以将($n$ 次互换)链内足迹减少到:
值得指出的是,如果 $n$ 较大,一些吃单人不配合,为了在链内领取注资交易输出,挂单人可能需要在交易的见证输出中发布大量的 RMD160 哈希值和一个体积巨大的脚本。这可能会影响性能分析和 $n$ 的选择。
现在,来看看我们的方法在相反的情形中是如何工作的。
这时候,参与交易的两种角色是:
这时候,挂单人不再像传统的潜水艇互换那样生成 $n$ 个单独的链内托管地址,而是为一个托管地址注入资金,预期这个地址会在单个交易中花费 —— 要么是发送资金给各吃单人(如果互换顺利)、要么是返回给挂单人(如果互换不顺利)。
以下是一个用描述符来表示的吃单人数量为 3 的案例:
taker_joint_pubkey = musig(
<taker1_pubkey>,
<taker2_pubkey>,
<taker3_pubkey>
);
tr(
musig(
<taker1_pubkey>,
<taker2_pubkey>,
<taker3_pubkey>,
<maker_pubkey>
),
{
{
and(
hash160(<hash1>),
pk(taker_joint_pubkey)
),
and(
hash160(<hash2>),
pk(taker_joint_pubkey)
)
},
and(
hash160(<hash3>),
pk(taker_joint_pubkey)
)
}
)
注意,在这个脚本中,吃单人是 3 个不同的哈希锁花费条件的联合收款方,也就是说,<hash1>、<hash2>、<hash3> 三个原像中的任何一个,都可以被吃单人用来领取其中的资金。
任何一个吃单人 $i$,在知道原像 $s_i$ 之后,都可以发布一笔 领取交易(是早前由所有吃单人签名过的)。这笔原子化的交易会将挂单人的资金在吃单人之间公平分配。
即使挂单人希望等到其闪电通道内的 HTLC(根本上来自各位吃单人)超时之前的最后一刻才揭晓所有原像 ${s_1, s_2, …, s_n}$ ,也即最坏情况下,吃单人们也将拥有 $\Delta$ 个区块的时间窗口来发布和确认一笔 领取交易。
一旦挂单人领取了其闪电通道内所有的 HTLC,也即所有的原像 ${s_1, s_2, …, s_n}$ 都曝光了,挂单人可以跟吃单人们配合签名一笔新版本的领取交易,使用那个 4-of-4 的内部公钥。这让他们可以藏起合约中的哈希锁花费分支,提高隐私性和链内效率。
如果有人不签名这个新版本的领取交易,某一个吃单人可以退回到发布自己的 领取交易,只需在区块高度 $B$ 之前(在 超时交易 变成有效交易之前)。
如果挂单人什么也没做(不释放原像),那么来自吃单人的 HTLC 会在区块高度 $B - \Delta$ 过期,从而给吃单人返回闪电通道余额。然后,等到区块高度 $B$ ,挂单人就可以用超时交易来清扫注资交易输出。
如果吃单人在挂单人发布 注资交易 之后不再响应,挂单人什么都不需要做,只需等待区块高度 $B$ ,然后发布超时交易。
如果使用 $n$ 次传统的潜水艇互换,链内的足迹最少也将是:
在理想情况下,我们这里的多方互换方法可以将($n$ 次互换)链内足迹减少到:
在部分吃单人或挂单人不合作的情形中,吃单人需要使用其中一个哈希锁分支来领取链内资金。
尽管将潜水艇互换拓展为多方协议是显然有可能的,但这样做可以获得具体多少效率提升,是可以争议的,因为这很大程度上取决于过程中的各方是否配合。从链内到链外的互换尤其如此,只要一个吃单人不合作,就可以迫使挂单人支付额外的手续费来(发布一连串似乎毫无必要的哈希值和原像)领取资金。
同样的骚扰攻击在传统的潜水艇互换协议中也存在,但在多方参与的环境中影响更大,因为一颗老鼠屎就能弄坏一锅汤(让互换对每个人都变得更贵)。
为了遏制来自吃单人的骚人,挂单人可以实现以下技术:
(完)
- 本文转载自: btcstudy.org/2026/01/12/... , 如有侵权请联系管理员删除。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!