---
title: 银行时间戳更正
---

每家银行都有一个时间戳，存放在时钟sysvar中，用来评估基于时间的质押账户锁定情况。 然而，自创世纪以来，这个值一直是基于理论上的每秒插槽数而不是现实，所以它是相当不准确的。 这给锁仓带来了问题，因为在锁仓设定到期的日期(或临近的任何时候)，账户都不会登记为无锁仓。

块时间已经被估计缓存在Blockstore和长期存储中，使用[验证者时间戳预言机](validator-timestamp-oracle.md)；这个数据提供了一个机会，使银行时间戳与现实世界的时间更接近。

所提出的实施方案的总体轮廓如下。

- 插槽使用验证者提供的时间戳来修正每个银行时间戳。
- 插槽更新验证者提供的时间戳计算，使用质押加权中值，而不是质押加权平均值。
- 插槽对时间戳校正进行约束，使其不能偏离预期的理论估计值太远。

## 时间戳更正

在每一个新的银行上，使用验证者时间戳预言机数据实时计算一个现实的时间戳估计值。 如果银行的时间戳大于或等于前一个银行的时间戳，那么银行的时间戳就会被修正到这个值。 也就是说，时间不应该倒退，所以被锁住的账户可能会因为修正而被释放，但一旦被释放，账户永远不能因为时间修正而被重新锁住。

### 计算质押加权中值时间戳。

为了计算特定银行的估计时间戳，运行时首先需要从活动验证者集中获取最近的投票时间戳。 `Bank::vote_accounts()`方法提供了投票账户的状态，这些账户可以被过滤到所有账户，其最近的时间戳是在上一个epoch内提供的。

从每个投票时间戳中，使用epoch的目标ns_per_slot计算出当前银行的估计值，用于银行插槽和时间戳插槽之间的任何差 。每个时间戳估计值都与委托给该投票账户的质押相关联，所有时间戳都被收集起来，以创建一个质押加权的时间戳分布。

从这组时间戳中，选择质押加权中值时间戳--即50%的质押人估计时间戳较大或相等，50%的质押人估计时间戳较小或相等的时间戳--作为潜在的更正时间戳。

这种质押加权的中值时间戳比质押加权的平均值更可取，因为在平均值计算中，质押乘以提议的时间戳，使得质押很小的节点仍然可以通过提议一个很大或很小的时间戳对结果的时间戳有很大的影响。 例如，使用之前的`calculate_stake_weighted_timestamp()`方法，一个拥有0.00003%质押的节点提出一个`i64::MAX`的时间戳，就可以将时间戳前移97000年!

### 边界时间戳

除了防止时间倒退，我们还可以通过将修正后的时间戳与理论上的预期时间的偏差限制在一个可接受的水平上来防止恶意活动。

这个提议建议，允许每个时间戳从纪元开始后与预期时间的偏差最多为25%。

为了计算时间戳的偏差，每个银行需要在时钟sysvar中记录`epoch_start_timestamp`。 这个值被设置为每个epoch的第一个插槽的`Clock::unix_timestamp`。

然后，运行时根据修正后的时间戳，比较自纪元开始以来的预期经过时间和建议的经过时间。 如果修正后的经过时间在预期的+/插槽25%以内，则接受修正后的时间戳。 否则，它将被限制在可接受的偏差范围内。
