ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Diem Execution Correctness(LEC)规范解析:受信计算基中的安全交易执行服务

Diem Execution Correctness(LEC)规范解析:受信计算基中的安全交易执行服务 区块链金融科技【免费下载链接】diemDiem’s mission is to build a trusted and innovative financial network that empowers people and businesses around the world.项目地址https://gitcode.com/gh_mirrors/di/diem点击查看免费下载导读本文基于 Diem Execution Correctness Specification 编写深入讲解 Diem 区块链中一个关键的安全组件 —— LECLibra/Diem Execution Correctness服务一个受信计算基TCB内、专门负责正确执行交易的独立服务它运行 Move VM 并将执行结果提供给共识Consensus模块使用。读完本文你将掌握 LEC 在整个 Diem 节点中的定位、它与 Storage / VM / LSR 的协作流程、StateComputeResult等核心数据结构、execute_block/commit_blocks等关键接口的内部实现步骤以及 Local / Thread / Process 三种运行时安全模式的区别与配置方法。一、LEC 在 Diem TCB 中的定位Diem 每个验证者validator节点的受信计算基TCB由四个组件构成见 Trusted Computing Base 总览Safety RulesLSR保证验证者按安全规则参与共识Execution CorrectnessLEC保证每笔交易在验证者上被正确执行Key Manager管理与轮换安全关键的密码学密钥Secure Storage为敏感数据如密钥提供安全存储。其中 LEC 是本文的主角。从源码结构看LEC 作为独立 crate 位于 execution/execution-correctness其入口 lib.rs 对外导出ExecutionCorrectnesstrait、ExecutionCorrectnessManager与Process。若对 TCB 的整体架构尚不熟悉建议先阅读 TCB 架构文档。二、概览与架构LEC 如何支撑复制状态机2.1 从复制状态机到区块树Diem 区块链可视为一个复制状态机从创世状态 S₀ 开始每笔交易 Tᵢ 通过既定函数 F 把上一状态 Sᵢ₋₁ 更新为 SᵢF(Sᵢ₋₁, Tᵢ) Sᵢ每个 Sᵢ 是从账户地址32 字节到账户数据的映射。T₀ 是硬编码的创世交易其 write set 产出创世状态对应仓库中的 Move 适配器规范见 specifications/move_adapter/README.md从 T₁ 起是客户端提交的交易。由于共识协议保证所有诚实节点看到相同的有序交易序列 T₀, T₁, …, Tₙ 及执行结果所有非拜占庭节点将收敛到相同状态序列 S₀, S₁, …, Sₙ。LEC 的职责接收全序化的交易把每笔交易应用到上一状态并把交易与状态持久化到 Storage。执行系统与共识算法协作帮助其对一组提议的交易及其执行结果达成一致这样一组交易称为一个区块block。与其他区块链不同Diem 中区块没有特殊意义只是交易的批处理 —— 每笔交易通过其版本号在账本中的位置唯一标识。每个共识参与者维护一棵区块树对区块树有两种操作向树中添加区块以给定父块为父节点延伸某条链例如以 F 为父块添加 G。延伸时新区块应包含仿佛所有祖先都已按序提交的正确执行结果。所有未提交区块及其执行结果存放在临时位置当前以内存为主外部客户端不可见。提交区块共识收集到足够多的区块投票后按特定规则提交该区块及其所有祖先此时把所有相关区块写入永久存储同时丢弃所有冲突区块。例如上图中 A 已提交系统即将提交 E由于 B 与 E 冲突B 及其全部后代不再有效将被一并丢弃。2.2 LEC 与 Executor 的分工为保证执行正确性即状态变更规则被严格执行需要一个经过安全审计的执行服务 —— 在 Diem Core 中就是 LEC它构建在Executor库之上。Executor承担两项职责执行execution基于特定状态 Merkle 树接受交易执行根据 VM 处理交易产生的 changeset 生成一棵新的推测性speculative树提交commitExecutor 是 Diem Core 中唯一对 Storage 具有写权限的模块。一旦新状态在仲裁quorum中达成共识由 Executor 将达成一致的状态提交到 Storage。2.3 LEC 与各服务的完整协作流程下图展示了 LEC 相关的 Diem Core 子系统架构及编号交互步骤原图见 execution_correctness.svg从启动到提交区块的完整流程共 10 步编号 0–9启动前置条件验证者节点启动前必须确保 SSBSecure Storage Backend已被初始化其中包含execution_keypair和consensus_keypair—— 前者用于 LEC 对执行结果签名、LSR 验证该签名后者用于 LSR 对投票签名以验证节点身份。LEC 读取私钥LEC 启动时是唯一能访问 SSB 中execution_private_key的组件它读取私钥并保存在本地。LSR 读取密钥与步骤 1 类似LSR 启动时从 SSB 读取execution_public_key和consensus_private_key并保存在本地。共识发起执行请求Consensus 通过 RPC 调用向 LEC 发送区块执行请求。LEC 执行并返回LEC 执行区块返回结果状态计算结果及对应区块的签名。共识生成投票Consensus 为该区块生成投票交给 LSR 签名。LSR 校验并签名LSR 验证投票有效性用consensus_private_key签名。LSR 返回签名投票签名后的投票返回给 Consensus。共识请求提交稍后 Consensus 对投票达成一致向 LEC 请求提交区块。LEC 落盘LEC 携带必要数据向 Storage 发送提交命令将变更持久化到 Diem 区块链。从源码可以印证该流程的密钥与签名链路execution_correctness_manager.rs 中的extract_execution_prikey从config.execution.backend初始化的 Storage 中导入并导出EXECUTION_KEYdiem_global_constants::EXECUTION_KEY且仅当sign_vote_proposal为 true 时才导出私钥用于签名而 local.rs 中execute_block在拿到执行结果后用私钥对VoteProposal签名并写回结果 —— 这正是流程中 LEC 生成区块签名的落点。三、核心数据结构本节介绍 LEC 专用或主要由其使用的数据结构。其余依赖的数据结构见 common data structures 文档。3.1 公共数据结构StateComputeResultStateComputeResult汇总一个区块执行的结果供共识达成一致使用同时包含投票生成、状态上报等用途所需的元数据。LEC 负责生成新状态的 id即对父区块结果应用本区块执行结果后推测性交易累加器transaction accumulator的根哈希。该结构的实际实现位于 execution/executor-types/src/lib.rspub struct StateComputeResult { /// transaction accumulator root hash is identified as state_id in Consensus. root_hash: HashValue, /// Represents the roots of all the full subtrees from left to right in this accumulator /// after the execution. For details, please see InMemoryAccumulator. frozen_subtree_roots: VecHashValue, /// The frozen subtrees roots of the parent block, parent_frozen_subtree_roots: VecHashValue, /// The number of leaves of the transaction accumulator after executing a proposed block. /// This state must be persisted to ensure that on restart that the version is calculated correctly. num_leaves: u64, /// The number of leaves after executing the parent block, parent_num_leaves: u64, /// If set, this is the new epoch state that should be changed to if this block is committed. epoch_state: OptionEpochState, /// Not every transaction in the payload succeeds: the returned vector keeps the boolean status /// of success / failure of the transactions. /// The compute status (success/failure) of the given payload. The specific details are opaque /// for StateMachineReplication, which is merely passing it between StateComputer and /// TxnManager. compute_status: VecTransactionStatus, /// The transaction info hashes of all success txns. transaction_info_hashes: VecHashValue, /// The signature of the VoteProposal corresponding to this block. signature: OptionEd25519Signature, }字段含义速览字段含义root_hash交易累加器根哈希共识中视为state_idfrozen_subtree_roots执行后累加器从左到右所有完整子树的根parent_frozen_subtree_roots父区块的 frozen 子树根num_leaves/parent_num_leaves执行后 / 父区块的交易累加器叶子数须持久化保证重启后版本计算正确epoch_state若设置表示该区块提交后应切换到的全新 epoch 状态compute_status每个交易成功/失败的布尔状态向量transaction_info_hashes所有成功交易的 transaction info 哈希signature对应区块VoteProposal的 Ed25519 签名值得注意的是源码中的实际结构还多出一个reconfig_events: VecContractEvent字段executor-types/src/lib.rs用于携带重配置事件 —— 这印证了规范中还包括投票生成与统计上报所需元数据的表述也从源码结构看StateComputeResult由ProcessedVMOutput派生而来。3.2 私有数据结构以下结构对 LEC 内部实现至关重要。ExecutedTreesExecutedTrees将内存中的状态稀疏 Merkle 树与交易累加器打包共同代表某个区块链状态。通常它代表执行完一个区块后的状态特殊情况下在StateSync中它可代表两棵树在交易之间而非区块之间的状态。实际定义见 execution/executor/src/types.rspub struct ExecutedTrees { /// The in-memory Sparse Merkle Tree representing a specific state after execution. If this /// tree is presenting the latest committed state, it will have a single Subtree node (or /// Empty node) whose hash equals the root hash of the newest Sparse Merkle Tree in /// storage. state_tree: ArcSparseMerkleTree, /// The in-memory Merkle Accumulator representing a blockchain state consistent with the /// state_tree. transaction_accumulator: ArcInMemoryAccumulatorTransactionAccumulatorHasher, }TransactionDataTransactionData是 LEC 缓存中某个已执行但未提交区块的推测性结果里与单笔交易关联的必要数据集。除 VM 输出write sets 与事件外还包含内存树。pub struct TransactionData { /// Each entry in this map represents the new blob value of an account touched by this /// transaction. The blob is obtained by deserializing the previous blob into a BTreeMap, /// applying relevant portion of write set on the map and serializing the updated map into a /// new blob. account_blobs: HashMapAccountAddress, AccountStateBlob, /// The list of events emitted during this transaction. events: VecContractEvent, /// The execution status set by the VM. status: TransactionStatus, /// The in-memory Sparse Merkle Tree after the write set is applied. This is Arc because the /// tree has uncommitted state and sometimes StateVersionView needs to have a pointer to the /// tree so VM can read it. state_tree: ArcSparseMerkleTree, /// The in-memory Merkle Accumulator that has all events emitted by this transaction. event_tree: ArcInMemoryAccumulatorEventAccumulatorHasher, /// The amount of gas used. gas_used: u64, /// The transaction info hash if the VM status output was keep, None otherwise. txn_info_hash: OptionHashValue, }ProcessedVMOutputProcessedVMOutput是把一系列交易的 VM 输出处理到父区块内存状态树与累加器之后的完整数据。每个实例对应一个区块并以区块 id 为键缓存在 LEC 的区块树中StateComputeResult可从ProcessedVMOutput生成。pub struct ProcessedVMOutput { /// The entire set of data associated with each transaction. transaction_data: VecTransactionData, /// The in-memory Merkle Accumulator and state Sparse Merkle Tree after appending all the /// transactions in this set. executed_trees: ExecutedTrees, /// If set, this is the new epoch state that should be changed to if this block is committed. epoch_state: OptionEpochState, }3.3 抽象的外部模块LEC 依赖的外部组件以接口形式抽象。VMExecutorLEC 内部调用 VM 的执行接口VMExecutor把人类可读的交易翻译为存储友好的 write set 以修改区块链状态pub trait VMExecutor: Send { /// Executes a block of transactions and returns output for each one of them. fn execute_block( transactions: VecTransaction, state_view: dyn StateView, ) - ResultVecTransactionOutput, VMStatus; }StorageDiem Core 的 Storage 实现为DiemDB一个基于 RocksDB、为 Diem 深度定制的存储系统保存构成 Diem 区块链的全部数据。执行区块后LEC 将推测性执行结果保存在自身缓存中待共识命令到达后再提交提交使执行效果在链上生效并对外可见。LEC 依赖存储接口暴露的两个 traitDbReaderLEC 将其 trait object 直接传给 VMExecutor 所需的StateView和DbWriter只有一个方法/// Only methods required by LEC are listed. Trait DbReader { // Please refer to StateView for more details. ... } /// Trait that is implemented by a DB that supports certain public (to client) write APIs /// expected of a Diem DB. This adds write APIs to DbReader. pub trait DbWriter: Send Sync { /// Persist transactions. Called by the executor module when either syncing nodes or committing /// blocks during normal operation. fn save_transactions( self, txns_to_commit: [TransactionToCommit], first_version: Version, ledger_info_with_sigs: OptionLedgerInfoWithSignatures, ) - Result(); }StateView 与 VerifiedStateViewStateView是定义状态 Merkle 树全局状态只读快照的抽象 trait被传给 VM 用于交易执行保证 VM 在给定状态下可读到任何数据。在此基础上实现的VerifiedStateView增加了一个关键特性保证从存储读出的状态可对照当前状态树根哈希进行验证。每当VerifiedStateView从存储读取账户数据它同时要求存储提供 Merkle 证明证明返回数据与最新持久化状态树根哈希一致。这样任何经VerifiedStateView获取的账户数据损坏都会在读取瞬间被检测到避免更严重的错误。其内部结构见 execution/executor/src/state_view.rs 附近的实现如下/// VerifiedStateView is like a snapshot of the global state comprised of state view at two /// levels, persistent storage and memory. pub struct VerifiedStateViewa { /// A gateway implementing persistent storage interface, which can be a RPC client or direct /// accessor. reader: Arcdyn DbReader, /// The most recent version in persistent storage. latest_persistent_version: OptionVersion, /// The most recent state root hash in persistent storage. latest_persistent_state_root: HashValue, /// The in-momery version of sparse Merkle tree of which the states havent been committed. speculative_state: a SparseMerkleTree, /// The cache of verified account states from reader and speculative_state_view, /// represented by a hashmap with an account address as key and a pair of an ordered /// account state map and an an optional account state proof as value. ... }account_to_state_cache: RefCellHashMapAccountAddress, AccountState, account_to_proof_cache: RefCellHashMapHashValue, SparseMerkleProof,VerifiedStateView的数据流可概括为VM 查询某个account_address/path时先命中缓存未命中则按顺序从 scratchpad推测状态或持久化存储加载账户状态为反序列化有序 map 并缓存缓存中的证明供 ScratchPad 在 VM 执行后构造内存稀疏 Merkle 树使用。3.4 指定模块SpeculativeCache区块树缓存LEC 作为独立服务执行区块并把推测性结果存到本地缓存。SpeculativeCache实现了记录区块间父子关系及每个区块对应推测执行结果的区块树结构必要时可剪枝丢弃的分支并以新提交链的 tip 区块更新区块树。树的形状与第二节的区块树完全一致。其实际定义位于 execution/executor/src/speculation_cache/mod.rs/// SpeculationCache implements the block tree structrue. The tree is reprensented by a root block id, /// all the children of root and a global block map. Each block is an ArcMutxSpeculationBlock /// with ref_count 1. For the chidren of the root, the sole owner is heads. For the rest, the sole /// owner is their parent block. So when a block is dropped, all its descendants will be dropped /// recursively. In the meanwhile, wheir entries in the block map will be removed by each blocks drop(). pub(crate) struct SpeculationCache { synced_trees: ExecutedTrees, committed_trees: ExecutedTrees, // The id of root block. committed_block_id: HashValue, // The chidren of root block. heads: VecArcMutexSpeculationBlock, // A pointer to the global block map keyed by id to achieve O(1) lookup time complexity. // It is optional but an optimization. block_map: ArcMutexHashMapHashValue, WeakMutexSpeculationBlock, }设计要点每个区块是ArcMutexSpeculationBlock引用计数为 1根区块的子块唯一属主是heads其余块唯一属主是其父块。因此当一个块被 drop其所有后代被递归 drop同时block_map中的条目由每个块的drop()移除 —— 这是一种内存安全的自动剪枝机制。以规范中图示为例若决定提交 B7则 B5、B6、B7 提交到存储而 B5、B6、B7含分叉 B7全部从树中剪除新的区块树只有一个根节点 B7 且无子节点代表最新已提交状态。LEC 对外接口ExecutionCorrectness traitLEC 通过ExecutionCorrectnesstrait 对外暴露服务。源码实现见 execution/execution-correctness/src/execution_correctness.rspub trait ExecutionCorrectness: Send { fn committed_block_id(self) - ResultHashValue, Error; fn reset(self) - Result(), Error; /// Executes a block. fn execute_block( self, block: Block, parent_block_id: HashValue, ) - ResultStateComputeResult, Error; fn commit_blocks( self, block_ids: VecHashValue, ledger_info_with_sigs: LedgerInfoWithSignatures, ) - Result(), Error; }各方法职责committed_block_id返回当前区块树根区块最新已提交区块的 idreset将执行器状态重置为以最新已提交区块为根的空树execute_block执行区块并返回执行结果commit_blocks按区块 id 列表将区块提交到存储。源码中 trait 的注释明确指出它基本与BlockExecutor相同区别在于部分接口返回带签名signature的结果。Executor 接口ChunkExecutor 与 BlockExecutorExecutor提供两个公共 traitChunkExecutor与BlockExecutor。ChunkExecutor供StateSync在全节点FN同步模式下执行并提交任意长度的连续交易BlockExecutor被 LEC 包装以提供区块级执行与提交 APIpub trait ChunkExecutor: Send { /// Verifies the transactions based on the provided proofs and ledger info. If the transactions /// are valid, executes them and commits immediately if execution results match the proofs. /// Returns a vector of reconfiguration events in the chunk fn execute_and_commit_chunk( mut self, txn_list_with_proof: TransactionListWithProof, // Target LI that has been verified independently: the proofs are relative to this version. verified_target_li: LedgerInfoWithSignatures, // An optional end of epoch LedgerInfo. We do not allow chunks that end epoch without // carrying any epoch change LI. epoch_change_li: OptionLedgerInfoWithSignatures, ) - ResultVecContractEvent; } pub trait BlockExecutor: Send { /// Get the latest committed block id fn committed_block_id(mut self) - ResultHashValue, Error; /// Reset the internal state including cache with newly fetched latest committed block from storage. fn reset(mut self) - Result(), Error; /// Executes a block. fn execute_block( mut self, block: (HashValue, VecTransaction), parent_block_id: HashValue, ) - ResultStateComputeResult, Error; /// Saves eligible blocks to persistent storage. /// If we have multiple blocks and not all of them have validator signatures, we may send them to storage /// in a few batches. For example, if we have /// text /// A - B - C - D - E /// /// and only C and E have signatures, we will send A, B and C in the first batch, /// then D and E later in the another batch. /// Commits a block and all its ancestors in a batch manner. /// /// Returns Ok(ResultVecTransaction, VecContractEvents) if successful, /// where VecTransaction is a vector of transactions that were kept from the submitted blocks, and /// VecContractEvents is a vector of reconfiguration events in the submitted blocks fn commit_blocks( mut self, block_ids: VecHashValue, ledger_info_with_sigs: LedgerInfoWithSignatures, ) - Result(VecTransaction, VecContractEvent), Error; }注意BlockExecutor与ExecutionCorrectness高度相似唯一区别是execute_block的参数集不同Executor 除区块 id 和交易列表外不需要知道区块的任何元数据。四、实现细节三个核心流程LEC 是对实现BlockExecutor的 trait object 的包装并负责对结果签名因此重点看execute_block与commit_blocks。4.1 execute_block该方法的核心功能是给定区块链状态把一个区块转换为新状态。规范中定义的执行步骤检查待执行区块是否为未提交重配置区块的后代。若是遵循重配置规则返回与其父区块相同的执行结果否则进入步骤 2。从缓存中取出父区块的推测性结果含ExecutedTrees由此生成VerifiedStateView。把父区块的VerifiedStateView与当前区块的交易一起送入 VM 执行得到 VM 输出。处理 VM 输出生成ProcessedVMOutput利用父区块的VerifiedStateView创建当前区块的ExecutedTrees。把该区块的执行输出放入缓存。从ProcessedVMOutput中提取 Consensus 与 LSR 所需数据组装为StateComputeResult并返回。为什么执行完不直接落盘规范给出了两个原因其一区块未必最终落在正确链上并被提交不能提前写存储其二稍后执行以当前区块为父块的新区块时当前区块的结果状态树必须对新区块可见。负责管理这些临时结果的组件名为ScratchPad。4.2 commit_blocks共识决定提交一个或多个区块时通常已收集到针对根哈希的签名客户端将用这些签名判断根哈希是否可信。这些签名作为commit_block请求的一部分发给 LEC再转交给存储。提交步骤从缓存取出待提交区块内所有交易的执行结果过滤掉失败交易。比对ledger_info版本与最后一个区块的推测性结果确保二者匹配。必要时跳过若干已被 StateSync 同步过的前导交易得到最终提交交易列表。将最终列表的执行结果写入 Storage。BlockExecutor::commit_blocks的批量语义在注释中有清晰说明当一条链A - B - C - D - E中只有 C 和 E 带验证者签名时第一批先发送 A、B、C第二批再发送 D、E。4.3 execute_and_commit_chunkChunkExecutor::execute_and_commit_chunk由StateSync调用用于把一段连续交易执行并提交到存储。区块是共识特有的概念Storage 与 StateSync 并不知道区块这里的Chunk指任意长度的连续交易。当 Executor 从其他节点同步交易时可用此方法在不提交 ledger info 的情况下同步交易。步骤重置推测区块进入同步模式。验证transaction_list_with_proof是针对给定目标ledger_info的有效交易列表并确定列表中应跳过的前导交易数可能已被提交。验证无分叉发生所提供的证明与已提交的区块链状态一致。从sync_trees最新已同步状态创建VerifiedStateView。基于该状态视图执行交易列表与execute_block类似。验证执行结果与证明中的 transaction_info 一致。判断是否需随此批次提交 ledger info。提交到 Storage 并更新sync_trees。五、安全考虑5.1 两方安全模型把 Storage 移出 TCB执行交易时LEC 采用两方安全模型two-party security model对从 Storage 读取的一切进行认证从而把 Storage 排除在 TCB 之外。只要 LEC 与 VM 工作正常存储系统的任何问题都会在影响整个系统正确性之前被检测出来。概念上对每笔交易 Tᵢ执行经VerifiedStateView分四步完成Executor 已持有上一状态根哈希Hᵢ₋₁ root_digest(Sᵢ₋₁)。Executor 调用 VM 执行交易。VM 输出读集RS与写集WSRS 是地址到带 Merkle 证明的账户 blob 值的映射WS 是地址到新 blob 值的映射。对每个从存储读取的值Executor 用证明与根哈希 Hᵢ₋₁ 验证其正确性。Executor 结合证明与新值计算 Hᵢ。由于创世状态根哈希对 Executor 可用上述过程可对 T₁, T₂, … 重复进行。下图上半部分展示 Executor 的工作下半部分展示 Storage 的工作双方独立计算 S₆ 根哈希但应得到相同值值得注意的实现差异Executor/LEC 在内存中使用二叉树表示稀疏 Merkle 树而存储系统使用 Jellyfish Merkle Tree 作为物理表示。主要考量是LEC 属于 TCB因此采用更简单的数据结构Storage 不属于 TCB可以使用更复杂的数据结构以换取更好的 IO 效率。5.2 LEC 与 LSR 之间的认证链路依据 LSR 设计文档LEC 位于 zone 2负责验证存储完整性、忠实执行交易而 LSR 位于 zone 1安全级别更高。当前系统设计中LSR 与 LEC 的通信需经过 Consensus执行结果先由 LEC 传给 Consensus再提交给 LSR。由于 Consensus 的安全级别低于两者为保证执行结果的完整性必须在 LEC 与 LSR 之间建立一条认证链路使 LSR 能信任经 Consensus 转交的执行结果。具体做法LEC 利用 Secure Storage Backend 中名为 execution 的非对称密钥对 —— 只有 LEC 能拿到私钥对结果签名LSR 可获取公钥进行验证。这与本文 2.3 节流程步骤 0–2、以及extract_execution_prikey的源码实现一一对应。5.3 运行时安全模式LEC 可在三种模式本地源码中实际还有第四种下运行安全含义各不相同Local本地LEC 服务与主线程运行在同一个线程。实现见 execution/execution-correctness/src/local.rsLocalService直接包装BlockExecutorLocalClient对调用方完全透明调用方无法区分其与真正的 client/server 进程。最简单直观但漏洞面最大。Thread线程LEC 服务与主线程分离运行但仍在同一进程内。实现见 thread.rsThreadService通过thread::spawn启动一个子线程在线程内以轻量 RPCremote_service::execute监听本机随机可用端口与主线程共享堆但不共享栈是 Local 与 Process 之间的折中。Process进程LEC 服务运行在独立进程中。实现见 process.rs 与 main.rsUsage: ./executor-service node.config即通过diem-node之外的独立二进制启动。规范明确指出终极目标是让 LEC 服务运行在独立进程、更隔离的容器中只通过 RPC 暴露 API。这能彻底将 LEC 变成独立服务抵御各类内存攻击、更少的代码大幅降低缺陷概率同时在可升级性和攻击面方面比与其他系统模块同进程运行更具灵活性。当前生产中主要使用Thread模式Local多用于测试下一步是向Process模式演进。额外的第四种模式从源码 config/src/config/execution_config.rs 看ExecutionCorrectnessService枚举实际定义了四种取值Local、Process(RemoteExecutionService)、Serializer、Thread。其中Serializer模式与主线程同进程但数据通过轻量 RPC序列化器传递用于测试 ExecutionCorrectness 与 SafetyRules 之间通信层的正确性对应实现见 serializer.rs其请求/响应使用bcs序列化消息类型为ExecutionCorrectnessInputCommittedBlockId/Reset/ExecuteBlock/CommitBlocks。六、配置与部署ExecutionConfig 详解LEC 的运行方式由节点配置中的execution段控制。源码 config/src/config/execution_config.rs 定义了ExecutionConfig各字段及默认值如下字段默认值说明genesisNone序列化时跳过创世交易由genesis_file_location指向的 BCS 文件加载genesis_file_location空PathBuf创世交易文件路径经RootPath解析为完整路径空则不加载sign_vote_proposaltrue是否用EXECUTION_KEY私钥对VoteProposal签名为false时 LEC 不导出私钥、结果不带签名serviceExecutionCorrectnessService::Thread服务运行模式Local / Process / Serializer / ThreadbackendSecureBackend::InMemoryStorage安全存储后端用于存放execution_keypair等密钥network_timeout_ms30_00030 秒与存储 / 远程服务通信的网络超时ExecutionConfig::load会按root_dir拼接genesis_file_location并读取、反序列化为Transaction::GenesisTransactionBCS 格式。ExecutionCorrectnessManager::newexecution_correctness_manager.rs会根据config.execution.service分发Process模式直接以远程服务地址与超时构建ProcessService不再本地读取私钥其他模式先经extract_execution_prikey从config.execution.backend初始化的 Storage 中可选地导出执行私钥再分别构建LocalService/SerializerService/ThreadService最终统一暴露为Boxdyn ExecutionCorrectness Send Sync客户端。在Process模式下独立二进制以./executor-service node.config启动见 main.rs接收配置文件中service类型为Process时RemoteExecutionService.server_address指定的监听地址并将执行请求经remote_service::execute转发给存储地址。七、总结LEC 是 Diem 验证者 TCB 中负责正确执行交易的安全服务它以Executor库为基础通过VerifiedStateView对存储读取做 Merkle 证明认证从而把 Storage 移出 TCB通过SpeculativeCache管理未提交区块的推测性执行结果通过ExecutionCorrectnesstrait 向共识提供execute_block/commit_blocks接口并以 execution 密钥对结果签名、供 LSR 验证构建 LEC↔LSR 的认证链路。从Local到Thread再到ProcessLEC 的运行时模式演进路线清晰展现了更隔离、更安全、更易升级的设计目标。相关源码与测试可进一步查阅 execution/execution-correctness/src服务实现与模式分发、execution/executor/srcExecutor 与 SpeculationCache、execution/executor-types/src/lib.rsStateComputeResult以及 config/src/config/execution_config.rs配置项。赞分享区块链金融科技【免费下载链接】diemDiem’s mission is to build a trusted and innovative financial network that empowers people and businesses around the world.项目地址https://gitcode.com/gh_mirrors/di/diem点击查看免费下载相关推荐Authelia 集成 EspoCRM基于 OpenID Connect 1.0 实现单点登录SSO完整配置指南Authelia 集成 EspoCRM基于 OpenID Connect 1.0 实现单点登录SSO完整配置指南 本指南讲解如何将 EspoCRM 配置为区块链金融科技Diem Safety RulesLSR技术解析基于可信计算基的共识安全组件规范Diem Safety RulesLSR技术解析基于可信计算基的共识安全组件规范 Diem Safety RulesLSR是 Diem 区块链中负责保区块链金融科技飞书 CLI 执行计划体裁契约Execution Plan全解析从交付物到验收的写作规范飞书 CLI 执行计划体裁契约Execution Plan全解析从交付物到验收的写作规范 导读 execution plan.md 是飞书 CLIlarCLIAI 技能创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表