Tendermint ABCI 应用开发完全指南:连接状态、交易结果、验证者更新与状态同步
区块链共识算法【免费下载链接】tendermint⟁ Tendermint Core (BFT Consensus) in Go项目地址https://gitcode.com/gh_mirrors/te/tendermint点击查看免费下载本文是 Tendermint Core 中 ABCI 应用规范spec/abci/apps.md的深度解读面向希望基于 ABCIApplication Blockchain Interface构建确定性状态机的开发者。你将系统掌握四大 ABCI 连接与各自状态的管理方式、交易结果与 Gas 规则、验证者集与共识参数的更新机制、Query 与 Merkle 证明、崩溃恢复握手协议以及 State Sync 快照引导等核心内容并结合本仓库源码abci/types/application.go、consensus/replay.go 等理解其底层实现原理。阅读本文前建议先通读 ABCI 方法与类型规范spec/abci/abci.md掌握Request*/Response*消息结构本文聚焦于应用如何实现这些方法。一、连接状态Connection State四个连接与四种状态Tendermint 与 ABCI 应用之间维护四个并发的 ABCI 连接相关消息分组见 abci.md 的 Connections 一节每个连接服务于不同的职责因此典型做法是应用为每个连接维护一份独立的状态并在Commit时将这些状态同步到最新已提交状态连接承载方法建议维护的状态Consensus共识连接InitChain、BeginBlock、DeliverTx、EndBlock、CommitDeliverTxState区块执行的工作状态Mempool交易池连接CheckTxCheckTxState待定交易预检状态Info信息/查询连接Info、QueryQueryState最新已提交状态的只读视图Snapshot快照连接ListSnapshots、LoadSnapshotChunk、OfferSnapshot、ApplySnapshotChunk状态同步快照的提供与恢复这四种连接在 abci/types/application.go 的Application接口中对应地分成四组方法接口注释明确标出了Info/Query Connection、Mempool Connection、Consensus Connection、State Sync Connection四个分组。仓库同时提供了默认空实现的 BaseApplication开发者可以像 kvstore 示例 那样通过嵌入types.BaseApplication只覆写需要的方法。1.1 并发与线程安全从原理上讲四个连接彼此并发运行应用必须保证状态访问的线程安全。但在实践中默认的进程内 ABCI 客户端localClient 持有一个全局互斥锁mtx所有*Async/*Sync方法如CheckTxSync、DeliverTxSync进入时都执行app.mtx.Lock()/defer app.mtx.Unlock()默认的Go Socket ABCI 服务端SocketServer 同样通过appMtx全局锁包裹handleRequest见 socket_server.go。因此只要你的应用用 Go 编写、通过默认NewLocalClient与 Tendermint 同进程编译或通过默认SocketServer独立进程运行所有连接的 ABCI 消息都会线性化linearizable即一次只处理一条天然串行。这一全局互斥锁的存在意味着Go 应用开发者可以把所有读和写都路由经过 ABCI 系统来获得状态线程安全反之直接向 RPC 接口暴露应用状态可能不安全——除非采取显式措施否则所有查询都应经由 ABCIQuery方法。1.2 BeginBlock区块开始的钩子BeginBlock请求用于在每个区块开始时执行一些代码Tendermint 会在发送任何交易之前把当前区块的 hash 与 header传给应用RequestBeginBlock的字段定义见 types.proto。应用应当记住最近一次成功Commit时的高度和 header以便重启后通过下面的 Handshake 告知 Tendermint 从何处继续。1.3 Commit唯一允许持久化的时机应用状态只应在Commit期间持久化到磁盘。Commit的调用时机遵循严格的时序调用Commit前Tendermint锁定并刷空lock flushmempool 连接确保不再有新的 CheckTx 消息进入这为应用提供了一次性安全更新全部四个连接状态到最新已提交状态的机会Commit完成后Tendermint 解锁 mempool。⚠️ 死锁警告如果处理Commit消息的 ABCI 应用逻辑在继续之前同步调用/broadcast_tx_sync或/broadcast_tx_commit并等待响应就会死锁——因为执行这些broadcast_tx调用需要获取Commit调用期间持有的那把锁。并发发起broadcast_tx调用没有问题只是不能作为Commit函数的顺序逻辑的一部分。ResponseCommit.Data是应用的 Merkle 根哈希会作为Header.AppHash写入下一个区块头字段定义见 types.protoRetainHeight用于指示低于该高度的区块可被移除默认0表示全部保留。仓库示例 kvstore 在 Commit 实现 中展示了如何更新AppHash与Height并持久化状态同时按需返回RetainHeight。1.4 Consensus Connection维护 DeliverTxState共识连接应维护DeliverTxState——区块执行的工作状态。它由区块执行期间的BeginBlock、DeliverTx、EndBlock调用更新并在Commit时作为最新已提交状态写入磁盘。每次方法调用产生的更新必须对后续方法可见即更新是线性化的。1.5 Mempool Connection维护 CheckTxStatemempool 连接维护CheckTxState用于顺序处理 mempool 中尚未提交的待定交易并在每次Commit结束时初始化为最新已提交状态。其完整生命周期为调用Commit前Tendermint 锁定并刷空 mempool 连接等待所有既有 CheckTx 得到响应且不允许新的 CheckTx 开始CheckTxState可与DeliverTxState并发更新Consensus 与 Mempool 连接可能并发发送消息Commit后、仍持有 mempool 锁期间Tendermint 对本地 mempool 中过滤掉已入块交易后剩余的所有交易重新执行 CheckTx重新检查期间RequestCheckTx.Type会额外标识交易是新的CheckTxType_New还是重查CheckTxType_Recheck枚举定义见 types.proto重查结束后解锁 mempool 连接新交易重新开始接受 CheckTx。需要明确CheckTx 只是把无效交易挡在链外的弱过滤器。它不必检查影响交易合法性的所有内容昂贵检查可以跳过。说它弱是因为拜占庭节点根本不在乎 CheckTx——它完全可以主动提议一个装满无效交易的区块。重放保护Replay Protection为防止旧交易被重放CheckTx 必须实现重放保护。旧交易完全可能再次被发送到应用所以 CheckTx 必须有相应逻辑处理它们。1.6 QueryInfoConnection维护 QueryStateInfo 连接维护QueryState用于回答用户查询以及 Tendermint 启动时的初始化。它应始终包含与最新已提交区块关联的最新已提交状态在每次Commit末尾、完整区块处理完毕且状态写入磁盘后将QueryState设为最新的DeliverTxState除此之外绝不应被修改。Tendermint Core 目前还使用 Query 连接在建立连接时按 IP 地址或节点 ID 过滤对等节点。对以下任一查询返回非 OK 的 ABCI 响应Tendermint 将拒绝连接对应 peerp2p/filter/addr/ip addr其中ip addr是 IP 地址p2p/filter/id/id其中id是十六进制编码的节点 ID节点 p2p 公钥的哈希。注意这些查询格式可能会变化1.7 Snapshot Connection可选的状态同步通道Snapshot 连接是可选的仅用于为其他节点提供状态同步快照以及/或者为正在引导的本地节点恢复状态同步快照。详见下文状态同步章节。二、交易结果Transaction Results确定性规则与 GasResponseCheckTx与ResponseDeliverTx中结构定义见 types.protoInfo与Log是非确定性字段仅供调试/便利之用Tendermint 会忽略Data必须严格确定但内容可以是任意字节Events用于把执行过程的元数据关联到交易/区块上供索引与订阅使用Event/EventAttribute 结构见 types.proto。2.1 Gas可选的弱抽象Tendermint 借鉴了以太坊的 gas 抽象但只是可选且弱化地使用允许应用自定义执行成本的含义。ConsensusParams.Block.MaxGas 限制一个区块内可用的 gas 总量默认值为-1表示无限制、或 gas 概念无意义响应包含GasWanted发送者愿意为交易支付的最大 gas与GasUsed实际消耗的 gas。应用应强制GasUsed GasWanted——即交易执行在消耗超过请求量之前就应中止当MaxGas -1时 Tendermint 强制以下规则mempool 中所有交易的GasWanted MaxGas提议区块时(区块内 GasWanted 之和) MaxGas若MaxGas -1则不执行任何 gas 规则。⚠️ 重要限制Tendermint 目前只在 mempool 层面执行 gas 规则并不在共识层面强制——它不保证已提交区块满足这些规则应用有责任在 gas 超限时返回非零响应码。同时GasUsed被 Tendermint完全忽略但应用应强制GasUsed GasWanted单笔交易与(区块内 GasUsed 之和) MaxGas每个区块未来计划在响应中增加Priority字段用于显式地为 mempool 中的交易排序以便进入区块提案对应仓库历史 issue #1861 的讨论。2.2 CheckTx 结果语义若Code ! 0交易将被拒绝进入 mempool从而不会被广播给其他 peer也不会被纳入提议区块Data携带 CheckTx 执行结果如果有对 Tendermint 而言无语义意义Events包含执行产生的事件但交易尚未提交因此 Tendermint实际上会忽略它们。2.3 DeliverTx 结果语义DeliverTx 是区块链的主力方法Tendermint异步但有序地发送 DeliverTx 请求并依赖底层 socket 协议如 TCP保证应用按序收到交易顺序已由 Tendermint 共识在全局层面确定。若DeliverTx返回Code ! 0交易会被视为无效但仍会包含在区块中Code与Data会一起被哈希进下一个区块头的LastResultsHash对应字段定义见 types.protoEvents会被 Tendermint 用于索引交易使交易可以按执行期间发生的事件被查询。三、更新验证者集Validator Set Updates应用可以在InitChain时设置验证者集并可在EndBlock时更新它。验证者集总投票权上限为MaxTotalVotingPower MaxInt64 / 8该常量定义于 types/validator_set.go应用有责任确保更新不会导致总权超过该上限validator_set.go 的更新逻辑 会对超过上限的更新触发 panic应用必须保证单次更新中不含重复项——给定公钥在单次更新中只能出现一次若含重复区块执行将不可恢复地失败。3.1 InitChainInitChain可以返回一个验证者列表列表为空时Tendermint 使用 genesis 文件加载的验证者列表非空时Tendermint 使用其内容作为验证者集。这样应用就能为区块链设定初始验证者集。仓库在 consensus/replay.go 的 ReplayBlocks 中展示了该逻辑当appBlockHeight 0处于创世时Tendermint 把 genesis 文档中的验证者、共识参数、应用状态等封装成RequestInitChain调用应用并使用返回的AppHash。3.2 EndBlock在ResponseEndBlock中返回ValidatorUpdate对象即可更新验证者集message ValidatorUpdate { tendermint.crypto.keys.PublicKey pub_key int64 power } message PublicKey { oneof { ed25519 bytes 1; } }当前仓库中ValidatorUpdate与PublicKey的实际定义见 types.proto 与 crypto/keys.proto。pub_key目前只支持一种类型type ed25519power是验证者的新投票权规则如下power 必须非负power 为 0验证者必须已存在将从验证者集移除power 非 0验证者不存在则加入按给定 power已存在则调整到给定 power新验证者集的总权不得超过MaxTotalVotingPower。注意时效区块H返回的更新要到区块H2才生效。更细的时序见 abci.md 的 EndBlock 说明H1时NextValidatorsHash包含新值H2时ValidatorsHash更新H3时LastCommitInfo才反映变更。四、共识参数Consensus ParametersConsensusParams 用于强制执行区块链中的某些限制区块最大尺寸、区块内 gas 量、证据的最大可接受年龄等。它们可在 InitChain 设置、在 EndBlock 更新。4.1 BlockParams.MaxBytes完整 Protobuf 编码区块的最大尺寸由 Tendermint 共识强制执行。这隐含了最大交易尺寸 MaxBytes 减去 header、验证者集及区块内所含证据的预期尺寸。约束0 MaxBytes 100 MB。4.2 BlockParams.MaxGas提议区块中允许的GasWanted之和的上限。不由 Tendermint 共识强制执行留给应用自行强制即超限交易应返回非零码Tendermint 用它限制提议区块中包含的交易。约束MaxGas -1MaxGas -1表示不设限。4.3 EvidenceParams.MaxAgeDuration证据在时间维度上的最大年龄由共识强制执行。若区块包含比这更旧的证据且证据创建时间早于MaxAgeNumBlocks之前区块将被拒绝验证者不会投票。约束MaxAgeDuration 0。4.4 EvidenceParams.MaxAgeNumBlocks证据在区块数量维度上的最大年龄由共识强制执行。若区块包含比这更旧的证据且证据创建时间早于MaxAgeDuration之前区块将被拒绝。约束MaxAgeNumBlocks 0。4.5 EvidenceParams.MaxNum单个区块可提交的最大证据数量。该值与MaxEvidenceBytes的乘积不得超过区块尺寸减去开销约MaxBytes。约束MaxNum 0。4.6 更新规则应用可在 InitChain 设置 ConsensusParams、在 EndBlock 更新它们。规则为ConsensusParams 为空则被忽略每个非空字段都会被整体应用例如只更新Block.MaxBytes时也必须同时设置其他 Block 字段如Block.MaxGas即使它们不变——否则这些字段会被更新为 0。InitChainResponseInitChain包含一个ConsensusParams。若其为 nilTendermint 使用 genesis 文件中的参数非 nil 则使用它。由此应用可决定区块链的初始共识参数。EndBlockResponseEndBlock包含一个ConsensusParams。nil 则什么都不做非 nil 则使用它从而随区块推进持续更新共识参数。注意时效区块H返回的更新对区块H1立即生效。五、Query查询、Merkle 证明与 Peer 过滤Query是一个通用方法为查询应用状态提供了极大的灵活性。Tendermint 用Query按 ID 和 IP 过滤新 peer并通过 RPC 将Query暴露给用户/abci_query。注意Query 调用不跨节点复制而是查询本地节点的状态——因此可能返回过期读需要共识保证的读请使用交易。Query 最重要的用途是返回某个高度的应用状态 Merkle 证明用于高效的、应用特定的轻客户端。同时Tendermint 对Query消息正常运行没有技术要求——ABCI 应用开发者不想实现的话完全可以不实现。5.1 Query 证明Query ProofsTendermint 区块头包含多个哈希每个都是某类区块链证明的锚点ValidatorsHash快速验证验证者集DataHash快速验证区块内交易等。其中AppHash是应用特定的允许针对应用状态构造应用特定的 Merkle 证明有些应用把所有相关状态放在交易本身中如比特币的 UTXO另一些应用维护一个从交易确定性推导出来、但不直接包含在交易中的独立状态如以太坊的合约和账户。对后者AppHash为轻客户端证明提供了更高效的验证路径。ABCI 应用可按如下方式提供高效证明在ResponseCommit.Data中返回确定性应用状态的Merkle 根它将作为AppHash写入下一个区块在ResponseQuery.Proof中返回关于该应用状态的高效 Merkle 证明可用对应区块的AppHash验证。例如这允许应用的轻客户端验证应用状态中某键的缺席proof of absence而用区块哈希做这件事效率低得多。一些应用如 Ethereum、Cosmos-SDK有多层 Merkle 树一层树的叶子是另一层树的根哈希。为支持这一点以及 Merkle 证明的普遍可变性ResponseQuery.Proof采用最小结构message ProofOps { repeated ProofOp ops } message ProofOp { string type 1; bytes key 2; bytes data 3; }每个ProofOp包含单棵 Merkle 树中单个键的证明按指定type。仅通过变化typeABCI 就能支持多种 Merkle 树、编码格式和证明如存在性与缺席性证明。data是按type编码的实际证明字节。验证完整证明时前一个 ProofOp 的根哈希就是下一个 ProofOp 要验证的值列表中最后一个 ProofOp 的根哈希应与被验证的AppHash一致。仓库中对应的 Go 结构定义可参考 crypto/merkle/proof_op.go。5.2 Peer 过滤Peer FilteringTendermint 连接 peer 时会用以下路径、不带额外数据向 ABCI 应用发送两个查询/p2p/filter/addr/IP:PORT其中IP:PORT是连接的 IP 地址和端口p2p/filter/id/ID其中ID是 peer 节点 ID即 peer 公钥的pubkey.Address()。两个查询任一返回非零 ABCI 码Tendermint 就拒绝连接该 peer。5.3 路径Paths查询按路径path定向且可选择性携带额外数据data。规范期望存在若干高层路径来区分关注点如/p2p、/store、/app。目前 Tendermint 只用/p2p过滤 peer。更复杂的用法可参考 Cosmos-SDK 的 baseapp 实现如/store按 key 查询底层存储data字段应指定 key应用还应支持/accounts/...、/votes/...等类型化查询——见 abci.md 的 Query 小节。六、崩溃恢复Crash RecoveryABCI 握手与区块重放启动时Tendermint 在 Info 连接上调用Info方法获取应用的最新已提交状态。应用必须返回与其最后一次成功Commit的区块一致的信息若应用成功提交了区块 Hlast_block_height Hlast_block_app_hash 区块 H 的 Commit 返回的 hash若应用在区块 H 的 Commit 过程中失败last_block_height H-1last_block_app_hash 区块 H-1 的 Commit 返回的 hash即区块 H header 中的 hash。下面区分三个高度描述 Tendermint 如何与应用同步storeBlockHeight Tendermint 见到 commit 的最后一个区块高度 stateBlockHeight Tendermint 完成全部区块处理并把所有 ABCI 结果写入磁盘的最后一个区块高度 appBlockHeight ABCI 应用成功完成 Commit 的最后一个区块高度恒有storeBlockHeight stateBlockHeight且storeBlockHeight appBlockHeight且Tendermint 永远不会对同一高度对 ABCI 应用调用两次 Commit。6.1 握手流程对应仓库实现 consensus/replay.go 中的 HandshakerHandshake通过 Info 连接的InfoSync获取应用的LastBlockHeight与LastBlockAppHash随后调用ReplayBlocksreplay.go执行下述分支逻辑。启动条件若appBlockHeight 0调用InitChain对应 replay.go 中从 genesis 构造RequestInitChain的代码若storeBlockHeight 0完成。健全性检查storeBlockHeight appBlockHeight报错storeBlockHeight stateBlockHeightpanicstoreBlockHeight stateBlockHeight1panic。核心分支条件动作场景storeBlockHeight stateBlockHeight且appBlockHeight storeBlockHeight从appBlockHeight到storeBlockHeight完整重放所有区块完成了区块处理但应用忘了自己的高度两者相等appBlockHeight storeBlockHeight完成在恰当位置崩溃storeBlockHeight stateBlockHeight1且appBlockHeight stateBlockHeight从appBlockHeight到storeBlockHeight-1完整重放并用WAL重放storeBlockHeight处的区块开始处理区块但未完成且应用忘了最后一个已提交区块storeBlockHeight stateBlockHeight1且appBlockHeight stateBlockHeight完整重放最后一个区块storeBlockHeight在应用完成 Commit 前崩溃storeBlockHeight stateBlockHeight1且appBlockHeight storeBlockHeight用已保存的 ABCI 响应更新状态但不对真实应用运行该区块应用完成 Commit 后、Tendermint 保存状态前崩溃握手完成时Tendermint 与应用达成同步对应 replay.go 的 Completed ABCI Handshake 日志。kvstore 示例在 Info 实现 中展示了如何返回LastBlockHeight与LastBlockAppHash供握手使用。七、状态同步State Sync快照引导新节点新节点加入网络的传统方式是从创世高度加入共识并重放全部历史区块直到追平。但对大链来说这通常需要数天甚至数周。State sync提供另一种引导机制抓取指定高度的状态机快照并恢复视应用而定可比重放区块快几个数量级。注意State sync 目前不会回填历史区块因此节点拥有截断的区块历史——用户应就区块可用性与可审计性考虑其网络影响该能力未来可能会补充。具体 ABCI 调用与类型参见 方法与类型规范ListSnapshots、LoadSnapshotChunk、OfferSnapshot、ApplySnapshotChunk的请求/响应字段均定义于 types.proto 与 types.proto。7.1 制作快照Taking Snapshots想要支持状态同步的应用必须定期制作状态快照方式完全由应用决定。一个快照由元数据 一组任意格式的二进制 chunk 组成Height (uint64)快照所处高度。必须在给定高度已提交之后制作且不得包含任何更高高度的数据Format (uint32)任意快照格式标识符可用来给快照格式做版本化例如从 Protobuf 切换到 MessagePack 序列化。应用可在恢复时据此决定接受或拒绝快照Chunks (uint32)快照的 chunk 数量。每个 chunk 含任意二进制数据应小于 16 MB10 MB 是不错的起点Hash ([]byte)快照的任意哈希下载 chunk 时用来跨节点判断快照是否相同Metadata ([]byte)任意快照元数据例如用于校验的 chunk 哈希或其他必要信息。跨节点判断快照相同要求以上所有字段完全一致。快照元数据消息在网络上传输时限制为 4 MB。新节点运行 state sync 发现快照时Tendermint 会通过 ABCIListSnapshots查询既有应用的可用快照并通过LoadSnapshotChunk加载二进制 chunk。应用可自由选择实现方式与格式但必须满足以下保证一致性Consistent快照必须在单一、隔离的高度制作不受并发写入影响——可用支持 ACID 事务 快照隔离的数据存储实现异步性Asynchronous制作快照可能耗时不得阻塞链的推进——例如放到独立线程运行确定性Deterministic同一高度、同一格式制作的快照必须逐字节相同含所有元数据以保证 chunk 的良好可用性与跨节点拼接。一个很基础的实现思路是使用支持 MVCC 事务的数据存储如 RocksDB在区块提交后立即开启事务并派生一个传入事务句柄的新线程该线程导出全部数据项、用 Protobuf 等序列化、对字节流哈希、切分成 chunk、连同元数据存入文件系统——而区块链同时并行应用新区块。更进阶的做法包括对单个 chunk 相对链上 AppHash 做增量校验、并行/批量导出、压缩等。旧快照应在一段时间后删除——通常只需保留最近两个防止恢复过程中最后一个被删掉。7.2 引导节点Bootstrapping a Node空节点通过设置配置项statesync.enable true启用状态同步。节点还需要链的 genesis 文件基本链信息以及轻客户端验证恢复快照所需的配置一组 Tendermint RPC 服务器以及来自可信来源的可信 header 哈希与对应高度均在statesync配置段下。仓库中对应配置结构为 config/config.go 的 StateSyncConfig字段包括enable、temp_dir、rpc_servers、trust_period、trust_height、trust_hash、discovery_time、chunk_request_timeout、chunk_fetchers。默认值见 DefaultStateSyncConfigtrust_period默认 168 小时、discovery_time默认 15 秒、chunk_request_timeout默认 10 秒、chunk_fetchers默认 4。ValidateBasic 还强制启用时必须提供至少两个rpc_servers、trust_height 0、合法的trust_hash、chunk_request_timeout 5s等。启动后节点连接 P2P 网络并开始发现快照通过OfferSnapshot提供给本地应用一旦快照被接受Tendermint 抓取并应用快照 chunk全部 chunk 应用成功后Tendermint 用轻客户端把应用的AppHash与链比对验证然后切换节点进入正常共识运行。快照发现Snapshot Discovery空节点加入 P2P 网络后通过ListSnapshotsABCI 调用请所有 peer 报告快照每节点限 10 个。一段时间后节点挑选最合适的快照一般按高度、格式、peer 数量优先并通过OfferSnapshot提供给应用。应用可选择多种响应接受、拒绝该快照、拒绝该格式、拒绝发送者等。Tendermint 会持续发现并提供快照直到有一个被接受或应用中止。OfferSnapshot的响应枚举ACCEPT/ABORT/REJECT/REJECT_FORMAT/REJECT_SENDER定义见 types.proto。快照恢复Snapshot Restoration快照经OfferSnapshot接受后Tendermint 从任何持有相同快照元数据字段一致的 peer 下载 chunk。chunk 先在临时目录暂存然后通过ApplySnapshotChunk按顺序交给应用直到所有 chunk 被接受。恢复方法完全由应用决定。恢复期间应用可通过ApplySnapshotChunk响应指示如何继续通常是接受当前 chunk 并等待下一个但也可以要求重新抓取当前或任意数量的先前 chunk、封禁 P2P peer、拒绝/重试快照等。响应枚举ACCEPT/ABORT/RETRY/RETRY_SNAPSHOT/REJECT_SNAPSHOT及refetch_chunks、reject_senders字段见 types.proto。若 Tendermint 一段时间内无法抓取某个 chunk会拒绝该快照并尝试通过OfferSnapshot换一个——应用可自行决定支持重启恢复还是直接报错中止。快照验证Snapshot Verification所有 chunk 接受后Tendermint 发出 ABCIInfo调用获取LastBlockAppHash与链上可信 app hash由轻客户端检索并验证比对同时检查LastBlockHeight与快照高度一致。该验证保证应用在加入网络前是有效的。但快照恢复可能耗时很长应用可能希望在恢复期间就做额外校验以便尽早发现失败例如用打包的 Merkle 证明对每个 chunk 相对 app hash 做增量校验用校验和防止磁盘或网络造成的数据损坏。务必注意唯一可信的信息是 app hash其余所有快照元数据都可能被对手伪造。应用还应考虑状态同步的拒绝服务DoS向量——对手可能提供无效或有害快照阻止节点入网。应用可通过要求 Tendermint 封禁 peer 来应对作为最后手段节点运营者可用 P2P 配置选项将一组可提供有效快照的 peer 加入白名单。转入共识Transition to Consensus快照全部恢复后Tendermint 从 genesis 文件与轻客户端 RPC 服务器收集引导节点所需的额外信息链 ID、共识参数、验证者集、区块头等并从 ABCI 应用抓取记录AppVersion。状态机恢复并收集齐这些信息后节点转入 block sync若启用抓取直到链头的剩余区块然后转入常规共识运行。此时节点与任何普通节点无异唯一的区别是区块历史在恢复快照的高度处被截断。小结ABCI 应用开发的核心要点可以概括为一条铁律区块执行路径BeginBlock → [DeliverTx] → EndBlock → Commit必须严格确定响应中除Info/Log外的字段全部参与下一个区块头的哈希四个连接、四份状态在Commit中一次性同步两类更新验证者集更新延迟两个区块生效共识参数更新立即生效以及两条引导路径崩溃后的 ABCI 握手 区块重放新节点的 State Sync 快照恢复。以本仓库的 kvstore 示例应用 为最小可运行参照配合 ABCI 方法与类型规范即可在此基础上实现生产级的确定性状态机。赞分享区块链共识算法【免费下载链接】tendermint⟁ Tendermint Core (BFT Consensus) in Go项目地址https://gitcode.com/gh_mirrors/te/tendermint点击查看免费下载相关推荐Tendermint ABCIApplication BlockChain Interface详解连接区块链复制引擎与应用状态机的接口规范Tendermint ABCIApplication BlockChain Interface详解连接区块链复制引擎与应用状态机的接口规范 ABCIAp区块链共识算法SwiftyStoreKit状态管理完全指南如何实现交易状态与UI的完美同步SwiftyStoreKit是一个轻量级的iOS应用内购买框架支持iOS 8.0、tvOS 9.0和macOS 10.10平台。这个框架的核心功能之一就后端Tendermint 状态同步State SyncP2P 消息协议完全指南通道、消息类型与实现验证Tendermint 状态同步State SyncP2P 消息协议完全指南通道、消息类型与实现验证 状态同步State Sync是 Tendermin区块链共识算法上一篇Go Web 编程深入理解 Session 与 Cookie 的原理、区别与 Go 语言实践下一篇如何免费解锁Microsoft 365完整功能Ohook终极指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

GaussDB工作级开发者认证全解析:从开发、调优到迁移实战

GaussDB工作级开发者认证全解析:从开发、调优到迁移实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 2:10:12 阅读更多 →
AI语音智能体开发日记(十一)为智能设备“声”临其境——详解音频资源自动化生成流程

AI语音智能体开发日记(十一)为智能设备“声”临其境——详解音频资源自动化生成流程

相关链接: AI语音智能体开发日记(一)如何为“小智”服务器启用并调试 License 功能-CSDN博客 AI语音智能体开发日记(二)解决 Wi-Fi 配网小程序的兼容性问题-CSDN博客 AI语音智能体开发日记(三&#xff09…

2026/10/12 2:09:11 阅读更多 →
perfect-freehand 仓库现代化改造实战指南:TypeScript 5、Vitest、Rolldown 与 Lazyrepo 完整落地

perfect-freehand 仓库现代化改造实战指南:TypeScript 5、Vitest、Rolldown 与 Lazyrepo 完整落地

图形学 【免费下载链接】perfect-freehand Draw perfect pressure-sensitive freehand lines. 项目地址: https://gitcode.com/gh_mirrors/pe/perfect-freehand 点击查看 免费下载 导读:本文以 perfect-freehand 仓库根目录的 todo.md(Moder…

2026/10/12 2:09:11 阅读更多 →

最新新闻

MySQL 64学时教学大纲拆解:从E-R图到PetStore建库全链路

MySQL 64学时教学大纲拆解:从E-R图到PetStore建库全链路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 2:55:40 阅读更多 →
MySQL与PostgreSQL整数类型选型:从INT到BIGINT的避坑指南

MySQL与PostgreSQL整数类型选型:从INT到BIGINT的避坑指南

搞数据库的人,十有八九都遇到过这种场景:建表时图省事顺手写了个INT,看着挺正常,结果业务量上来之后,主键突然撞到天花板,或者磁盘空间莫名暴涨。选整数类型这件事,在 MySQL 和 PostgreSQL 里看…

2026/10/12 2:55:40 阅读更多 →
互联网医院+居家养老:医养协同闭环如何落地

互联网医院+居家养老:医养协同闭环如何落地

晚上九点多,同事给我打电话,说她父亲在老家测出血压180/110,人有点晕。她自己在外地出差,隔着几百公里,语音那头全是慌张。这种场景,做互联网医院和居家养老医养结合项目之前,基本只能干着急&am…

2026/10/12 2:55:40 阅读更多 →
消息队列如何保证数据不丢失?生产、存储、消费三端全解析

消息队列如何保证数据不丢失?生产、存储、消费三端全解析

面试题这东西,十有八九是套路,但“消息队列如何保证数据不丢失”是我见过最容易“背了配置但答不出本质”的一道。很多人上来就背:Kafka 开 acksall、副本设 3、消费者别自动提交,听起来很全,但面试官只要换个问法——…

2026/10/12 2:55:40 阅读更多 →
Git常用命令实战:从核心设计逻辑到高频操作指南

Git常用命令实战:从核心设计逻辑到高频操作指南

每个写代码的人,早晚都要面对版本管理这件事。刚开始我不太在意,直到有一次熬夜改了三天代码,因为一次误操作把整个项目覆盖,才真正体会到版本管理的分量。后来把Git当成每日必用工具,才发现真正高频的“常用命令”就二…

2026/10/12 2:55:40 阅读更多 →
PLC程序质量四层评估模型:从能运行到可维护可演进

PLC程序质量四层评估模型:从能运行到可维护可演进

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 2:54:40 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:54 阅读更多 →