Time 字段定义。
它满足以下性质:
- 时间单调性:时间是单调递增的,也就是说,给定高度为
h1的头H1和高度为h2 = h1 + 1的头H2,有H1.Time < H2.Time。 - 时间有效性:给定一组构成
block.LastCommit字段的 Commit 投票,区块头中Time字段的有效取值范围仅由正确进程发送的 Precommit 消息(来自LastCommit字段)决定,也就是说,故障进程不能任意增大Time的值。
- Commit 的中位数,等于
Vote消息中Vote.Time字段的中位数,其中Vote.Time的取值会按进程投票权重进行重复计数。由于投票权并不是均匀分布的(不是一进程一票),一个投票消息实际上等价于聚合了若干张相同的票,其数量等于发送该投票消息的进程所拥有的投票权。
- 我们有四个进程 p1、p2、p3 和 p4,它们的投票权分布如下:
(p1, 23)、(p2, 27)、(p3, 10) 和 (p4, 10)。总投票权为 70(
N = 3f+1,其中N是总投票权,f是故障进程的最大投票权),因此我们假设故障进程最多拥有 23 的投票权。 此外,在某个LastCommit字段中我们有如下投票消息(忽略除Time字段之外的所有字段):- (p1, 100)、(p2, 98)、(p3, 1000)、(p4, 500)。我们假设 p3 和 p4 是故障进程。再假设
block.LastCommit消息包含了进程 p2、p3 和 p4 的投票。此时中位数的选取方式如下: 值 98 计数 27 次,值 1000 计数 10 次,值 500 也计数 10 次。 因此,中位数将是 98。无论我们选择哪一组总投票权至少为2f+1的消息,中位数都一定会落在正确进程发送的值之间。
- (p1, 100)、(p2, 98)、(p3, 1000)、(p4, 500)。我们假设 p3 和 p4 是故障进程。再假设
-
设
rs表示某个进程的RoundState(共识内部状态)。那么rs.ProposalBlock.Header.Time == median(rs.LastCommit) && rs.Proposal.Timestamp == rs.ProposalBlock.Header.Time。 -
此外,在创建
vote消息时,用于确定vote.Time字段的规则应满足以下要求:-
如果定义了
rs.LockedBlock,则vote.Time = max(rs.LockedBlock.Timestamp + time.Millisecond, time.Now()),其中time.Now()表示本地 Unix 时间(毫秒) -
否则,如果定义了
rs.Proposal,则vote.Time = max(rs.Proposal.Timestamp + time.Millisecond, time.Now()) -
否则,
vote.Time = time.Now()。在这种情况下,vote 是针对nil的,因此不会被纳入下一个区块时间戳的计算。
-
如果定义了
CometBFT provides a deterministic, Byzantine fault-tolerant, source of time. Time in CometBFT is defined with the Time field of the block header. It satisfies the following properties:
- Time Monotonicity: Time is monotonically increasing, i.e., given
a header H1 for height h1 and a header H2 for height
h2 = h1 + 1,H1.Time < H2.Time. - Time Validity: Given a set of Commit votes that forms the
block.LastCommitfield, a range of valid values for the Time field of the block header is defined only by
Precommit messages (from the LastCommit field) sent by correct processes, i.e., a faulty process cannot arbitrarily increase the Time value.
- median of a Commit is equal to the median of
Vote.Timefields of theVotemessages, where the value ofVote.Timeis counted number of times proportional to the process voting power. As the voting power is not uniform (one process one vote), a vote message is actually an aggregator of the same votes whose number is equal to the voting power of the process that has casted the corresponding votes message.
- we have four processes p1, p2, p3 and p4, with the following voting power distribution (p1, 23), (p2, 27), (p3, 10)
and (p4, 10). The total voting power is 70 (
N = 3f+1, whereNis the total voting power, andfis the maximum voting power of the faulty processes), so we assume that the faulty processes have at most 23 of voting power. Furthermore, we have the following vote messages in some LastCommit field (we ignore all fields except Time field):- (p1, 100), (p2, 98), (p3, 1000), (p4, 500). We assume that p3 and p4 are faulty processes. Let’s assume that the
block.LastCommitmessage contains votes of processes p2, p3 and p4. Median is then chosen the following way: the value 98 is counted 27 times, the value 1000 is counted 10 times and the value 500 is counted also 10 times. So the median value will be the value 98. No matter what set of messages with at least2f+1voting power we choose, the median value will always be between the values sent by correct processes.
- (p1, 100), (p2, 98), (p3, 1000), (p4, 500). We assume that p3 and p4 are faulty processes. Let’s assume that the
-
let rs denotes
RoundState(consensus internal state) of some process. Thenrs.ProposalBlock.Header.Time == median(rs.LastCommit) && rs.Proposal.Timestamp == rs.ProposalBlock.Header.Time. -
Furthermore, when creating the
votemessage, the following rules for determiningvote.Timefield should hold:-
if
rs.LockedBlockis defined thenvote.Time = max(rs.LockedBlock.Timestamp + time.Millisecond, time.Now()), wheretime.Now()denotes local Unix time in milliseconds -
else if
rs.Proposalis defined thenvote.Time = max(rs.Proposal.Timestamp + time.Millisecond,, time.Now()), -
otherwise,
vote.Time = time.Now()). In this case vote is fornilso it is not taken into account for the timestamp of the next block.
-
if