Skip to content

时间锁

概述

在本节中,我们将介绍如何创建一个智能合约,该合约具有一个公共方法,该方法只能在特定时间点之后解锁。

什么是时间锁?

在智能合约的上下文中,时间锁是一种功能,它限制特定比特币的支出,直到达到指定的未来时间或块高度。sCrypt 提供了在智能合约中实现这些类型的时间锁的机制,提供了一种机制,确保交易不会在达到特定时间点或块高度之前包含在区块链中。换句话说,智能合约的方法不能在特定时间点之后成功调用。

例如,这种机制可以用于向智能合约添加提款方法。在其他各方不合作的情况下,个人可以在一定时间后从智能合约中提取其锁定资金。这种方法在跨链原子交换中得到了应用。

Image Credit: bcoin

实现

在 sCrypt 中,可以通过限制脚本执行上下文locktimesequence 值来实施时间锁。这个上下文与交易的执行有关,包括对智能合约公共方法的调用。因此,如果对值进行了限制 - 例如,locktime 需要大于 1690236000(一个 Unix 时间戳) - 那么这个交易在达到该时间点之前就无法被包含到区块链中。

注意,locktime 的值可以是 Unix 时间戳或块高度。为了实施这个值,sequence 也需要设置为小于 0xffffffff 的值。

sCrypt 提供了一个方便的内置函数 timeLock 来实施这个约束。

ts
// 公共方法可以被调用的时间。
@prop()
readonly matureTime: bigint // 可以是时间戳或块高度。

// ...

@method()
public unlock() {
    // 以下断言确保在 `matureTime` 通过之前,`unlock` 方法不能成功调用。
    assert(this.timeLock(this.matureTime), 'time lock not yet expired')
}

重要的是要注意,这种机制只能用于确保在特定时间点之后调用方法。相反,它不能用于确保在特定时间点之前调用方法。

调用

在调用上面定义的 unlock 方法时,我们需要设置将调用公共方法的事务的 locktime 值。我们可以通过简单地设置 MethodCallOptionslocktime 参数来实现这一点。

ts
timeLock.methods.unlock(
    {
        lockTime: 1673523720
    } as MethodCallOptions<TimeLock>
)

内部,这还将输入的 sequence 设置为小于 0xffffffff 的值。我们也可以显式地设置这个值。

ts
timeLock.methods.unlock(
    {
        lockTime: 1673523720,
        sequence: 0
    } as MethodCallOptions<TimeLock>
)

最后,如果我们使用的是 自定义交易构建器,我们需要为我们在那里构建的未签名事务设置这些值。

ts
instance.bindTxBuilder('unlock',
  async (
    current: TimeLock,
    options: MethodCallOptions<TimeLock>
  ) => {

    // ...

    if (options.lockTime) {
      unsignedTx.setLockTime(options.lockTime)
    }
    unsignedTx.setInputSequence(0, 0)
    
    // ...
  }
)

它是如何工作的?

在底层,timeLock 函数断言我们的调用事务的 sequence 值小于 UINT_MAX。这确保了比特币网络将强制执行 locktime 值。

接下来,它检查我们的目标时间锁值是否表示块高度或 Unix 时间戳。如果它使用的是块高度,即时间锁值小于 500,000,000,方法还确保调用事务的 locktime 值对应于块高度。

最后,方法验证 locktime 的值大于或等于我们作为参数传递的时间锁。

有关 locktimesequence 值如何工作的更多信息,请阅读 BSV wiki 页面