Skip to main content

承诺

承诺度量旨在为客户提供一个衡量特定区块上的网络确认和利益水平的标准。 然后,客户可以使用这些信息来推导出自己的承诺度量。

计算远程调用#

客户端可以通过get_block_commitment(s: Signature) -> BlockCommitment,使用远程调用向验证节点请求签名s的承诺指标。 BlockCommitment结构包含一个u64[u64,MAX_CONFIRMATIONS]的数组。 这个数组表示验证节点投票的最后一个区块M时,包含签名s的特定区块N的承诺度量。

BlockCommitment数组中索引i处的条目s意味着验证节点观察到s在某一区块M中观察到的集群中的总质押达到i个确认的区块N。 这个数组中会有MAX_CONFIRMATIONS元素,代表从1到MAX_CONFIRMATIONS的所有可能的确认数。

承诺度量的计算#

建立这个BlockCommitment结构利用了为建立共识而进行的计算。 consensus.rs中的collect_vote_lockouts函数建立了一个HashMap,其中每个条目的形式是(b, s),其中s是银行b的质押数量。

对可投票候选银行b的计算如下。

let output: HashMap<b, Stake> = HashMap::new();
for vote_account in b.vote_accounts {
for v in vote_account.vote_stack {
for a in ancestors(v) {
f(*output.get_mut(a), vote_account, v);
}
}
}

其中f是一些累积函数,它用一些可从投票vvote_account派生的数据(stake、lockout等) 来修改插槽astake条目。 这里注意,这里的ancestors只包括当前状态缓存中存在的插槽。 比状态缓存中存在的更早的银行的签名无论如何也查询不到,所以这里的承诺计算中不包括这些银行。

现在,我们自然可以通过以下方法来增强上述计算,为每一个银行b也建立一个BlockCommitment数组。

  1. 增加一个ForkCommitmentCache来收集BlockCommitment结构
  2. f代替f',使上述计算也为每一个银行b建立这个BlockCommitment

由于1) 是不是很重要,所以我们将继续讨论2) 的细节。

在继续之前,值得注意的是,对于某个验证节点的投票账户a,该验证节点在插槽s上的本地确认数为v.num_confirmations,其中v是投票堆栈a.vails中最小的一票,这样v.slot >= s(即不需要查看任何大于v的投票>,因为确认数会更低)。

现在更具体的说,我们把上面的计算增强为。

let output: HashMap<b, Stake> = HashMap::new();
let fork_commitment_cache = ForkCommitmentCache::default();
for vote_account in b.vote_accounts {
// vote stack is sorted from oldest vote to newest vote
for (v1, v2) in vote_account.vote_stack.windows(2) {
for a in ancestors(v1).difference(ancestors(v2)) {
f'(*output.get_mut(a), *fork_commitment_cache.get_mut(a), vote_account, v);
}
}
}

其中f'被定义为:

fn f`(
stake: &mut Stake,
some_ancestor: &mut BlockCommitment,
vote_account: VoteAccount,
v: Vote, total_stake: u64
){
f(stake, vote_account, v);
*some_ancestor.commitment[v.num_confirmations] += vote_account.stake;
}