在上一篇文章里|深入解读闪电网络:HTLC 的工作方式与多跳支付的实现方式

在上一篇文章里|深入解读闪电网络:HTLC 的工作方式与多跳支付的实现方式
文章图片
在上一篇文章里 , 我们详细解释了支付通道的运作 , 以及多种保证支付安全发生的方法 。 不过 , 这些功能 , 还不足以支撑一个可用的支付通道网络:即使我们很确定在每个通道内每个参与者都是诚实守信的 , 也没法保证通过多个通道来支付同样是安全的 。 这就是我们需要“HTLC(哈希-时间锁-合约)”这种智能合约的原因 。 在本文中 , 我们会讲解HTLC工作的方式 , 并使用一个例子来展示多跳支付是如何在闪电网络中实现的 。
哈希时间锁合约(HTLC)
HTLC的结构并不复杂 , 但非常高效 。 它使我们可以创建具有明确“过期时间”的支付 。 你可能也猜得到 , HTLC合约由两部分组成:哈希验证和过期验证 。
我们先从哈希值(hash)开始 。 要创建一笔带有HTLC的支付事务 , 你先要生成一个秘密数值R , 然后计算出其哈希值 。 任何词语、任何数字都可以充当这个秘密值 , 因为 , 对哈希函数来说 , 它们都是一堆数据的组合 , 没有什么分别 。
H=Hash(R)
这个哈希值H会放在事务输出的锁定脚本中 。 如此 , 只有知道H所对应的秘密值的人才能使用这个输出 。 而R就是所谓的“原像(preimage)” 。
HTLC的第二部分是过期时间的验证 。 如果秘密值没有及时地公开 , 这笔支付就用不了了 , 发送者会收回所有的资金 。
我们来考虑一个发给某人的HLTC支付事务:
#检查所提供的R是否为H的原像
HASH160EQUAL
IF
#检查公开R的人是否为事务最初的接收者
CHECKSIG
ELSE
#检查时间锁是否已终止
CHECKLOCKTIMEVERIFY
#检查请求返回资金的是不是事务最初的发送者
CHECKSIG
ENDIF
在正确的R(哈希值H的原像)公开之后 , 我们进入IF流程 , 进一步验证提供R的是不是这笔支付事务一开始的支付对象 。 在花费这个输出时 , 接收方只需提供一个非常简单的解锁脚本:
如果解锁脚本所提供的R是错的 , 我们跳转入ELSE流程 , 首先验证时间锁解锁了没有 。 如果时间锁已然解锁 , 发送者就可以收回所有的资金 。 收回资金这个操作的解锁脚本也差不多 , 唯一的区别在于 , 为了进入ELSE流程 , 需要提供一个错误的秘密值:
当然 , 这只是HTLC的一个非常基础的实现 , 代表着一个普通的时间锁支付 。 你可以在脚本中加入任意多的其它条件 , 比如说 , 在IF流程中移除公钥验证 , 这样只要知道秘密值R的人都可以使用这个输出;也可以在其中加入多签名限制 , 要求提供多个预设私钥的签名才能解锁 。
多说一句 , 在这个案例中 , 我们使用的操作码是CHECKLOCKTIMEVERIFY , 这个操作码使用绝对数值来定义时间锁 , 意思就像:“这个输出在区块#546212之前是无法动用的” 。 而在闪电网络中 , 还用上了另一种时间锁 , 更“灵活”的一种:CHECKSEQUENCEVERIFY , 它用到的是相对数值 , 意思近于:“这个输出 , 在使用它的事务上链之后的1000个区块内 , 是无法使用的”(译者注:这里的数值都是例子 , 实践中当然可以使用别的数值) 。
闪电网络案例
现在 , 我们终于讲解完所有元素了 , 可以尝试理解闪电网络运作的全景了 。
我们假设现在闪电网络有5个参与者:Alice、Bob、Carol、Diana和Eric , 他们各自有一个支付通道相连 , 而每个通道的每一边都有2btc的余额可用 。 现在 , 我们尝试让Alice通过通道链条给Eric支付 。
在上一篇文章里|深入解读闪电网络:HTLC 的工作方式与多跳支付的实现方式
文章图片
-一系列相连的双向支付通道 , 组成了闪电网络 , 可以转介Alice对Eric的支付-