:BFT 时间机制的算法级重构)
区块链共识算法【免费下载链接】tendermint⟁ Tendermint Core (BFT Consensus) in Go项目地址https://gitcode.com/gh_mirrors/te/tendermint点击查看免费下载导读本文聚焦 Tendermint 共识中区块时间的产生方式系统讲解一份以提议者时间戳Proposer-Based Time简称 PBT替代传统中位数 BFT 时间bfttime的算法级重构方案。原文来自本仓库 spec/consensus/proposer-based-timestamp 目录下的三篇配套规范主文档 pbts_001_draft.md、系统模型 pbts-sysmodel_001_draft.md 与算法草案 pbts-algorithm_001_draft.md并辅以仓库内 TLA 形式化规范 与 Go 共识实现源码进行印证。读完本文你将掌握PBT 协议如何将时间从投票携带改为提议携带、PRECISION/MSGDELAY/ACCURACY三个系统参数如何支撑安全性与活性、共识算法伪代码逐条改写为带时间的版本以及这套方案在现实实现如 consensus/state.go 的 propose 步骤与 config/config.go 的超时配置中对应的形态。背景为什么需要重构 BFT 时间现有 bfttime 的工作方式在 spec/consensus/bft-time.md 中记录了当前 Tendermint 的时间机制以下称旧方案 bfttime验证者在PRECOMMIT消息中携带自己的本地时间提议者收集到2f1个PRECOMMIT后以按投票权加权的投票时间中位数作为下一个区块头Time字段的值。仓库中的实现佐证了这一机制加权中位数由 types/time/time.go 的WeightedTime与WeightedMedian计算median : totalVotingPower / 2再按时间排序、按权重累减定位中位数而PRECOMMIT投票的时间则通过max(lockedBlock/Proposal.Timestamp 1ms, time.Now())之类的规则确定见 spec/consensus/bft-time.md。时间字段是int64类型的 Unix 毫秒时间戳。旧方案满足两个核心性质时间单调性相邻高度H1.Time H2.Time与时间有效性区块时间只由正确进程的PRECOMMIT时间界定恶意进程无法任意抬高时间。旧方案的六项分析结论主文档 对 bfttime 给出了六点剖析容错性只要故障验证者的投票权少于 1/3计算出的中位数时间必然落在正确验证者发送时间的区间内因此是拜占庭容错的。故障验证者的影响力当故障方掌握超过 1/2即介于 1/3 与 2/3 之间的投票权时时间完全被故障方掌控这对轻客户端安全尤其不利。提议者对区块时间的影响力提议者计算中位数时可从2f1票中任意挑选子集、可任意选择用于计算的轮次因此对bfttime有相当的自由度。活性协议活性不依赖时钟同步但依赖有界的消息延迟。与真实时间的关系没有时钟同步意味着计算出的区块时间与真实时间没有任何保证的关联。聚合签名PRECOMMIT消息携带各不相同的时间字段阻碍了聚合签名的使用。提议者时间戳方案PBT的改进PBT 的核心思路是把时间从投票移到提议不再是每个验证者在PRECOMMIT里各报一个时间而是提议者在PROPOSE消息中携带自己的时间now_p验证者用本地时钟校验这个时间是否及时timely。新旧方案逐项对比见下表摘自 主文档维度bfttime旧PBT新容错性保持保持故障方对时间的控制投票权 1/2 即可完全控制仅当故障方 2/3 时才能破坏极端情况才可能提议者对时间自由度可任意挑选子集/轮次在1/3故障假设下第一类自由度被消除轮次选择仍存在活性不依赖时钟同步依赖新增的时钟同步假设仍依赖消息延迟不可避免与真实时间的关系无保证形式化时钟同步后区块时间与真实时间有明确定义的关系聚合签名被时间字段阻碍PRECOMMIT不再携带时间允许聚合签名需要说明PBT 引入了验证者时钟同步这一额外假设下文PRECISION/ACCURACY这是它与旧方案最本质的系统模型差异。此外 主文档 还记录了一个与实现更贴近的语义调整接收步骤不再丢弃超时的 PROPOSE 消息而是保留全部消息、只对及时者打上timely标记。系统模型三个时间参数与安全性质Part I 系统模型文档 为算法改写给出了精确的形式化基础。时钟与消息延迟假设[PBTS-CLOCK-NEWTON.0]存在一个牛顿参考真实时间tUTC。[PBTS-CLOCK-PRECISION.0]存在系统参数PRECISION使得任意两个正确验证者V、W在同一真实时刻的本地时钟差满足|C_V(t) - C_W(t)| PRECISION。[PBTS-MSG-D.0] / [PBTS-MSG-FAIR.0]存在以本地时钟时间计量的系统参数MSGDELAY正确提议者到正确验证者的PROPOSE消息端到端延迟小于MSGDELAY。注意文档特别指出该假设同时约束了消息延迟与时钟[PBTS-MSG-D.0] 的备注。[PBTS-CLOCK-GROW.0]一次共识实例期间本地时钟不会被回拨即每个正确验证者在高度k上满足beginConsensus(V,k) endConsensus(V,k)。文档强调见 pbts_001_draft.mdPRECISION与MSGDELAY会出现在代码层面而ACCURACY不必在代码层面可见甚至可以看作随时间变化的量——它在一次共识实例中越小区块时间就越贴近真实时间。决策相关的不变量[PBTS-PROPOSE.0]提议者提议一对值(v, t)。[PBTS-INV-AGREEMENT.0]Agreement没有两个正确验证者会就不同的值v达成决策。[PBTS-INV-TIME-VAL.0]Time-Validity即使多达2f个验证者故障正确验证者决定的时间t也是OK的。[PBTS-INV-TIME-AGR.0]Time-Agreement同一轮中决策的两个正确验证者必然决定相同的t。[PBTS-DECISION-ROUND.0]由于验证者可能在不同轮次决策下一区块的提议者会选择某一轮的 commit至少2f1个PRECOMMIT作为canonic决策轮从而隐式地在决策轮对应的时间中做选择——这与旧方案中基于中位数的选择在本质上是相同的自由度文档指出由于 Cosmos hub 上大多数共识实例单轮即终止这一自由度在实践中几乎观察不到。共识层安全Consensus-Time-Validity[PBTS-CONSENSUS-TIME-VALID.0]给出了区块时间与共识起止时刻的界设beginConsensus(k)为所有正确验证者进入高度k的最小本地时刻、endConsensus(k)为最大离开时刻则被有效 commit 签名、且包含至少一个正确验证者PRECOMMIT的区块时间b.time满足beginConsensus(k) - PRECISION b.time endConsensus(k) PRECISION MSGDELAY该性质的分析场景是提议者故障不计入上述区间并估计正确验证者收到并接受提议消息的时刻当提议者正确时可进一步得到[PBTS-CONSENSUS-SAFE-VALID-CORR.PROP.0]beginConsensus_k b.time last-beginConsensus_k即区块时间落在正确验证者进入该高度的本地时间区间内。这两条性质成立的前提是第 1 轮提议者正确、[TMBC-FM-2THIRDS.0]多于 2/3 正确成立、[PBTS-MSG-FAIR.0]、[PBTS-CLOCK-PRECISION.0] 与 [PBTS-CLOCK-GROW.0] 成立文档对后者标注了 TODO是否充分待确认。真实时间安全Real-Time Safety要建立区块时间与真实时间的关系需要引入[PBTS-CLOCKSYNC-EXTERNAL.0]存在系统参数ACCURACY使所有真实时刻t、所有正确验证者V满足|C_V(t) - t| ACCURACY。在此基础上[PBTS-CONSENSUS-REALTIME-VALID.0]提议者可能故障设propRecvTime(m)为首个正确验证者收到触发PRECOMMIT的提议消息m的真实时刻则propRecvTime(m) - ACCURACY - PRECISION b.time propRecvTime(m) ACCURACY PRECISION MSGDELAY[PBTS-CONSENSUS-REALTIME-VALID-CORR.0]提议者正确设proposalTime(m)为提议者真实发送m的时刻则proposalTime(m) - ACCURACY b.time proposalTime(m) ACCURACY因算法在发送时刻令m.time - now_p。活性Liveness当 [TMBC-FM-2THIRDS.0]、[PBTS-MSG-FAIR.0]、[PBTS-CLOCK.0]、[PBTS-CLOCK-GROW.0]同样标注 TODO成立时最终会存在高度k的有效 commit更进一步[PBTS-CONSENSUS-LIVE-VALID-CORR.PROP.0]指出若第 1 轮提议者正确所有正确验证者将在有界时间内于第 1 轮完成决策。这些性质在仓库的 TLA 规范 中被逐一实现为不变量AgreementOnValue、AgreementOnTime、ConsensusTimeValid、ConsensusSafeValidCorrProp、ConsensusRealTimeValid、ConsensusRealTimeValidCorr、BoundedDelay以及活性条件ConsensusTimeLive。该 TLA 模块将PRECISION、ACCURACY、Delay等声明为常量并将Proposal(v, t)、Decision(v, t, r)建模为时间与值的元组。算法改写从 arXiv 伪代码到带时间的规则Part II 算法文档 的总体策略是显式区分消息接收步骤与处理步骤原 arXiv 论文只隐式地评估收到的消息规则并保持 arXiv 论文中除下述规则外的一切不变。PROPOSE消息的proposal字段被扩展为对(v, time)即提议的共识值v与提议时间time。接收步骤及时性判定[PBTS-RECEPTION-STEP.0]进程p在本地时刻now_p收到消息m时若m为PROPOSE类型且满足now_p - PRECISION m.time now_p PRECISION MSGDELAY则标记为timely否则标记为untimely。注意这是双边界判定时间既不能太旧低于now_p - PRECISION也不能太新超过now_p PRECISION MSGDELAY多出的MSGDELAY是给在途提议的传输预算。在 TLA 中对应ReceiveProposal(p)动作其判定条件localClock[p] - Precision t ∧ t localClock[p] Precision Delay与文档逐字对应见 TendermintPBT_001_draft.tla 中标注[PBTS-RECEPTION-STEP.0]的注释。新的 StartRound单调时间等待 时间上链[PBTS-ALG-STARTROUND.0]对原StartRound有两处新增若提议者本地时间不大于上一个区块时间则等待直到now_p blockTime保证区块时间严格单调递增提议者将其当前时间now_p作为提议的一部分发出。function StartRound(round) { blockTime ← block time of block h_p - 1 waitingTime ← blockTime 2 * ACCURACY MSGDELAY - now_p round_p ← round step_p ← propose if proposer(h_p, round_p) p { wait until now_p blockTime // new wait condition if validValue_p ! nil { proposal ← (validValue_p, now_p) // added now_p } else { proposal ← (getValue(), now_p) // added now_p } broadcast ⟨PROPOSAL, h_p, round_p, proposal, validRound_p⟩ } else { schedule OnTimeoutPropose(h_p,round_p) to be executed after max(timeoutPropose(round_p), waitingTime) } }同时文档给出了PROPOSE步骤超时上界更新的推导链正确的提议者最迟在真实时间blockTime ACCURACY发出此时其本地时钟必然已超过blockTime接收者在blockTime ACCURACY MSGDELAY前收到PROPOSE接收者本地时钟此时 blockTime 2 * ACCURACY MSGDELAY因此接收者p进入该轮时可把等待时间设为waitingTime blockTime 2 * ACCURACY MSGDELAY - now_p。最终该轮超时应取max(timeoutPropose(round_p), waitingTime)。文档还预留了未来演进若引入区块延迟参数BLOCKDELAY提议者应等待now_p blockTime BLOCKDELAY再发PROPOSE且waitingTime中也要加上BLOCKDELAY。这一等待 超时放大的语义与仓库实现结构可相互印证Go 实现中enterPropose通过cs.scheduleTimeout(cs.config.Propose(round), ...)调度timeoutProposeconsensus/state.go而超时值由 config/config.go 的ConsensusConfig.Propose(round)计算TimeoutPropose TimeoutProposeDelta * round默认timeout_propose 3000ms、timeout_propose_delta 500ms见 config/config.go 与 Propose 方法。PBT 方案中的waitingTime相当于在既有超时之上叠加与blockTime、时钟精度相关的分量——当前仓库实现尚未引入该叠加这是规范草案相对实现的超前设计。规则改写一第 22-27 行首次收到及时提议 → 预投票原规则是对值v预投票新规则变为对值v和时间t预投票upon timely(⟨PROPOSAL, h_p, round_p, (v,t), −1⟩) from proposer(h_p, round_p) while step_p propose do { if valid(v) ∧ (lockedRound_p −1 ∨ lockedValue_p v) { broadcast ⟨PREVOTE, h_p, round_p, id(v,t)⟩ } else { broadcast ⟨PREVOTE, h_p, round_p, nil⟩ } step_p ← prevote }关键变化在于PREVOTE的投票对象由id(v)变为id(v,t)即把提议时间纳入投票哈希。TLA 中对应UponProposalInPropose(p)其中mid : IF IsValid(v) ∧ (lockedRound[p] NilRound ∨ lockedValue[p] v) THEN Id(Proposal(v, t)) ELSE NilProposal。规则改写二第 28-33 行旧轮次预投票 新提议当第 1 轮未达成共识时后续轮次的提议者可能提议相同的值但不同的时间因此旧PREVOTE中的时间tvote不必与当前PROPOSAL的时间tprop一致。[PBTS-ALG-OLD-PREVOTE.0]规定只要值v匹配验证者就可以为当前轮次发PREVOTEupon timely(⟨PROPOSAL, h_p, round_p, (v, tprop), vr⟩) from proposer(h_p, round_p) AND 2f 1 ⟨PREVOTE, h_p, vr, id((v, tvote)⟩ while step_p propose ∧ (vr ≥ 0 ∧ vr round_p) do { if valid(v) ∧ (lockedRound_p ≤ vr ∨ lockedValue_p v) { broadcast ⟨PREVOTE, h_p, roundp, id(v, tprop)⟩ } else { broadcast ⟨PREVOTE, hp, roundp, nil⟩ } step_p ← prevote }这里需要消化新旧时间错位tvote属于历史轮次vr而新PREVOTE投票用id(v, tprop)。TLA 中UponProposalInProposeAndPrevote(p)将msgsPrevote[vr]中id Id(Proposal(v, t2))的消息计数并对照THRESHOLD2 2*T1随后广播Id(Proposal(v, t1))。规则改写三第 36-43 行新轮次预投票达成 2/3[PBTS-ALG-NEW-PREVOTE.0]当及时提议(v,t)与当前轮2f1个id(v,t)预投票同时满足时第一次进入此状态的处理如下upon timely(⟨PROPOSAL, h_p, round_p, (v,t), ∗⟩) from proposer(h_p, round_p) AND 2f 1 ⟨PREVOTE, h_p, round_p, id(v,t)⟩ while valid(v) ∧ step_p ≥ prevote for the first time do { if step_p prevote { lockedValue_p ← v lockedRound_p ← round_p broadcast ⟨PRECOMMIT, h_p, round_p, id(v,t))⟩ step_p ← precommit } validValue_p ← v validRound_p ← round_p }注意lockedValue/validValue等存储值不含时间时间只存在于消息与决策中——这是本规则与 [PBTS-ALG-UPON-PROP.0] 共同的要点。TLA 中UponProposalInPrevoteOrCommitAndPrevote(p)要求step[p] ∈ {PREVOTE,PRECOMMIT}并对照Cardinality(PV) THRESHOLD2。规则改写四第 49-54 行决策[PBTS-ALG-DECIDE.0]决策同时针对值v与提议消息中的时间t且不要求提议是 timely 的upon ⟨PROPOSAL, h_p, r, (v,t), ∗⟩ from proposer(h_p, r) AND 2f 1 ⟨PRECOMMIT, h_p, r, id(v,t)⟩ while decisionp[h_p] nil do { if valid(v) { decision_p [h_p] (v,t) // decide on time too h_p ← h_p 1 reset lockedRound_p , lockedValue_p, validRound_p and validValue_p to initial values and empty message log StartRound(0) } }文档特别强调了一个场景当提议者对某个正确验证者不及时untimely时需要确保若其他人都决策该验证者也必须决策——这正是决策规则不要求timely标记的原因。TLA 中UponProposalInPrecommitNoDecision(p)用p ∈ inspectedProposal[r]收到过该轮提议即可替代timely要求并把决策建模为Decision(v, t, round[p])同时记录endConsensus与step DECIDED。其余规则超时、nil 投票、round catch-up 等保持不变。与仓库实现、形式化验证的对照Go 实现侧时间如何进入区块当前仓库 Go 实现仍是 bfttime 形态PBT 规范属于草案演进方向但两处关键结构可供对照加权中位数实现types/time/time.go 定义WeightedTime{Time, Weight}与WeightedMedianmedian : totalVotingPower / 2后按Time.UnixNano()升序、按权重累减定位即为按投票权加权的中位数的落地实现Propose 步骤与超时consensus/state.go 的enterPropose通过scheduleTimeout(cs.config.Propose(round), ...)安排timeoutPropose并在defaultDecideProposal中经createProposalBlock生成包含区块时间的提案config/config.go 定义timeout_propose系列配置及其随轮次增长的Propose(round)公式。PBT 草案中的waitingTime blockTime 2*ACCURACY MSGDELAY - now_p与max(timeoutPropose, waitingTime)即是对这一超时机制的改造方向。TLA 形式化验证侧不变量与动作全覆盖spec/consensus/proposer-based-timestamp/tla/TendermintPBT_001_draft.tla 是本方案的机器可检验形态常量Precision、Accuracy、Delay、ClockDrift分别对应规范中的三个系统参数与时钟漂移开关动作InsertProposal[PBTS-PROPOSE.0]提议(validValue[p] 或 v, localClock[p])、ReceiveProposal[PBTS-RECEPTION-STEP.0]、UponProposalInPropose[PBTS-ALG-UPON-PROP.0]、UponProposalInProposeAndPrevote[PBTS-ALG-OLD-PREVOTE.0]、UponProposalInPrevoteOrCommitAndPrevote[PBTS-ALG-NEW-PREVOTE.0]、UponProposalInPrecommitNoDecision[PBTS-ALG-DECIDE.0]与文档规则一一对应且注释中直接标注了文档编号收尾的Inv不变量集合把 Part I 中的性质翻译为可模型检验的公式例如ConsensusRealTimeValid精确复刻了proposalReceivedTime[r] - Accuracy - Precision t proposalReceivedTime[r] Accuracy Precision Delay。这也解释了规范的三段式组织README主文档问题与对比→ Part I 系统模型与性质 → Part II 协议规范 → TLA 规范形成需求 → 假设 → 算法 → 验证的完整链条。结语PBT 方案的价值与边界从仓库规范与源码可以得出以下结论安全与活性的收益PBT 在保持 Tendermint 原有容错性的同时将故障方控制区块时间的门槛从 1/2 提升到 2/3并通过 [PBTS-CLOCKSYNC-EXTERNAL.0] 让区块时间与真实时间之间有了可量化的边界ACCURACY越小越贴近真实时间工程收益PRECOMMIT不再携带时间为聚合签名扫清了障碍同时明确了接收步骤的timely过滤语义为共识实现提供了可直接编码的判定规则now_p - PRECISION m.time now_p PRECISION MSGDELAY代价与边界PBT 引入了对时钟同步PRECISION、ACCURACY的依赖且waitingTime需要叠加进PROPOSE超时对应实现中timeout_propose的改造当前仓库 Go 实现仍以 bfttime 为主PBT 以草案 TLA的形态沉淀于 spec/consensus/proposer-based-timestamp适用于需要形式化验证支撑的协议演进讨论。赞分享区块链共识算法【免费下载链接】tendermint⟁ Tendermint Core (BFT Consensus) in Go项目地址https://gitcode.com/gh_mirrors/te/tendermint点击查看免费下载相关推荐Podman 日志时间戳选项 --timestamps / -t 深度解析用法、时间格式与源码实现Podman 日志时间戳选项 timestamps / t 深度解析用法、时间格式与源码实现 导读 timestamps 短选项 t 是 Podman 中容器运行时云原生CLIDelta Lake In-Commit Timestamps 协议详解让 TIMESTAMP AS OF 时间旅行摆脱文件系统时间戳的不可靠性Delta Lake In Commit Timestamps 协议详解让 TIMESTAMP AS OF 时间旅行摆脱文件系统时间戳的不可靠性 导读 本文围湖仓一体数据工程数据湖NautilusTrader时间序列处理纳秒级时间戳精度保障机制NautilusTrader时间序列处理纳秒级时间戳精度保障机制 引言高频交易中的时间精度挑战 在算法交易领域时间精度是决定策略成败的关键因素之一。当交易金融科技后端上一篇DS4Windows为你的PC游戏体验注入新活力下一篇Winpilot安全终极指南这款Windows优化工具是否值得信赖创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考