ARTICLE DETAIL

资讯详情

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

Polkadot PVF Host 与 Workers 深入解析:确定性保障与安全加固设计

Polkadot PVF Host 与 Workers 深入解析:确定性保障与安全加固设计 区块链【免费下载链接】polkadotPolkadot Node Implementation项目地址https://gitcode.com/gh_mirrors/po/polkadot点击查看免费下载本文聚焦 Polkadot 节点实现中负责处理 PVFParallalized Validation Function平行链验证函数代码 blob 的PVF Host 与 Workers 子系统。PVF Host 负责接收准备prepare即编译与执行execute两类请求并将实际工作交给运行在独立子进程中的 PVF Worker 完成。整篇文章围绕该子系统在设计上的两大核心目标——确定性determinism与安全性security展开读者将掌握为什么执行失败需要重试、准备超时为何在执行阶段比预检查pre-checking阶段更宽松、为何用 CPU 时钟而非墙钟计时、以及针对恶意 PVF 的完整威胁模型与沙箱加固手段Landlock 文件系统隔离 环境变量清理。PVF Host 与 Workers 概述PVF 是平行链运行时的验证函数以 WebAssembly 形式存在于链上。任何验证者节点在确认候选区块candidate block时都必须对候选的 PVF 进行准备编译为可执行的 artifact 并缓存到磁盘和执行在给定参数下运行并得到验证结果。在 Polkadot 中这一职责由node/core/pvfcrate 承担其整体结构如下node/core/pvf/src/host.rsPVF Host 主体运行一个事件循环event-loop对外暴露ValidationHost句柄node/core/pvf/src/prepare/准备队列queue与准备 worker 池pool的编排node/core/pvf/src/execute/执行队列queue与执行 worker 接口node/core/pvf/src/artifacts.rs已编译 artifact 的状态机准备中 / 已准备 / 处理失败与磁盘缓存管理node/core/pvf/common/Host 与 Worker 共享的协议、错误类型与安全模块security.rsnode/core/pvf/prepare-worker/与node/core/pvf/execute-worker/两个独立的 Worker 二进制入口。Host 与 Worker 通过Unix 域套接字通信Host 先创建一个临时 socket 路径随后以polkadot-prepare-worker/polkadot-execute-worker程序路径 spawn 子进程对应源码中的PREPARE_BINARY_NAME与EXECUTE_BINARY_NAME常量子进程通过--socket-path参数连接回 Host握手完成后即可接收任务见 worker_intf.rs 中的spawn_with_program_path。Host 侧在等待子进程连回 socket 时使用 spawn 超时默认 3 秒见 host.rs 中Config::new超时即返回SpawnErr::AcceptTimeout。从 host.rs 的start函数可以看出Host 事件循环由以下几个异步组件拼装而成prepare::start_pool准备 worker 池prepare::start_queue准备队列execute::start执行队列sweeper_task专门负责删除到期 artifact 文件的清理任务run_host核心事件循环处理来自ValidationHost句柄的三类请求。ValidationHost句柄对外暴露三个方法见 host.rsprecheck_pvf预检查请求验证 PVF 能在合理时间内编译通过execute_pvf执行请求包含执行超时、参数与优先级heads_up向 Host 通报当前活跃的 PVF 集合用于刷新 artifact 的最后使用时间last_time_needed从而影响缓存的裁剪策略。确定性Determinism尽力减少争议PVF Host 系统的首要目标是让 PVF 处理过程尽可能确定从而降低争议disputes的发生率。争议可能源于同一份工作在一台机器上超时、在另一台机器上却没有超时这类环境差异。虽然 Polkadot 目前无法做到完全确定性但在代码中已经内置了多个争议缓解机制下文逐一拆解。执行请求的重试机制当**准备preparation**阶段失败时Host 会判断错误是否可能是瞬时的transient。如果准备错误属于瞬时类型例如 panic 或超时则会安排重试。重试有两个约束条件见 host.rs 中PREPARE_FAILURE_COOLDOWN与NUM_PREPARE_RETRIES常量以及can_retry_prepare_after_failure函数冷却时间仅当新的请求在失败 15 分钟PREPARE_FAILURE_COOLDOWN Duration::from_secs(15 * 60)之后再次到来时才重试以保证潜在的瞬时条件有足够时间被消除最大次数最多重试 5 次NUM_PREPARE_RETRIES 5。测试模式下冷却时间被缩短为 200 毫秒便于单元测试快速验证重试逻辑。当**执行execution**阶段失败时若错误可能为瞬时错误则只重试一次且延迟更短1 秒而不是准备阶段的 15 分钟因为一次成功的执行必须在一个很短的时间窗口内完成。两种重试策略的对比可总结如下阶段重试次数重试间隔/条件原因准备prepare最多 5 次失败后冷却 15 分钟等待新的请求触发给瞬时条件充分的解决时间执行execute1 次约 1 秒成功执行必须在短时间内完成目前已知会导致执行请求被重试的具体情形有三种OOM内存耗尽机器可能因同一台机器上其他进程的运行而暂时内存不足。注意如果重试仍然不成功该候选将被投反对票并可能引发争议。Artifact 丢失已准备好的 artifact 可能因操作员失误或系统 bug 被删除。这一场景在 host.rs 的handle_execute_pvf中有专门处理当 artifact 状态为Prepared但文件元数据检查std::fs::metadata失败时会打日志 Re-queuing PVF preparation for prepared artifact with missing file将状态重置为Preparing并重新入队。Panicworker 线程因某种不确定原因 panic可能与候选或 PVF 本身无关也可能相关。准备超时Preparation timeouts预检查 vs 执行准备和执行任务都有各自的超时限制以约束它们可消耗的时间。由于任务耗时随机器配置和负载而变化这可能引发争议某些验证者成功执行了 PVF而另一些没有。一个重要的争议缓解手段是执行期间的准备超时比预检查期间更宽松lenient。其理由在于PVF 已经通过了预检查我们知道它应该是有效的因此允许它花费比预期更长的时间是合理的——这更可能是机器的问题而不是 PVF 的问题。对应到源码host.rs 的handle_execute_pvf文档注释明确指出执行时的准备使用更宽松的LENIENT_PREPARATION_TIMEOUT预检查使用 common/src/execute.rs 中更严格的超时。CPU 时钟超时CPU 时间而非墙钟时间另一项与超时相关的缓解措施是用 CPU 时间而非墙钟时间来度量任务耗时。原因在于进程的 CPU 时间在不同系统负载条件下波动更小——当系统整体负载很重时任务的墙钟时间受影响的幅度远大于 CPU 时间。这一机制在 common/src/worker/mod.rs 中实现为cpu_time_monitor_loopworker 在独立的 CPU 时间监控线程中用cpu_time::ProcessTime记录开始时间循环检查已消耗的 CPU 时间是否超过超时上限每次睡眠间隔为剩余 CPU 时间 JOB_TIMEOUT_OVERHEAD50 毫秒以弥补开销。如果 CPU 时间耗尽则返回Some通知 Host 发送TimedOut错误如果任务先完成则返回None。此外在 worker_intf.rs 中还有一道配套的墙钟兜底Host 侧等待执行响应时的墙钟超时是执行超时的4 倍JOB_TIMEOUT_WALL_CLOCK_FACTOR 4用于防止子进程彻底停滞stalled而 Host 永远等不到响应。也就是说子进程内部用 CPU 时间判定超时精确且受负载影响小Host 侧用宽松的墙钟时间兜底防止子进程挂死。内部错误Internal errors的处理原则对于不会引发争议的错误处理上必须极其谨慎。只有满足以下任一条件把某个错误归类为内部错误才是稳妥的该错误已在预检查阶段被排除。如果某件事在预检查中没有被检查即使它与候选和 PVF 无关也必须引发争议。100% 确定是硬件/本地问题例如文件损坏等。原因有两层否则攻击者可以注册一个候选无法被检查、却不会引发争议的 PVF从而无人受到惩罚其次系统会陷入一个无法自行解除的最终性停滞finality stall。源码层面错误分类逻辑位于 error.rsPrepareError::is_deterministic()见 common/src/error.rs将错误划分为确定性与非确定性两类确定性错误可复现不重试Prevalidation预验证失败、Preparation编译失败、Panicpanic——但注意Panic在准备错误分类中被视为确定性而在执行阶段另有InvalidCandidate::Panic的处理逻辑非确定性错误可能是瞬时资源问题可重试TimedOut、IoErr、CreateTmpFileErr、RenameTmpFileErr、RuntimeConstruction。PrepareError转ValidationError时见 error.rs确定性错误归类为InvalidCandidate::PrepareError投票反对非确定性错误归类为InternalValidationError::NonDeterministicPrepareError内部错误。存在一些无法确定候选是否真的无效、还是发生了内部故障的错误条件典型的就是panic。每当不确定时绝不能把错误当作内部错误处理因为那将导致弃权投票abstain from voting。正确路径是先重试该候选如果问题持续存在则被迫投无效票vote invalid。这一点在InvalidCandidate::Panic的文档注释中有明确说明同时InvalidCandidate::AmbiguousWorkerDeathworker 在验证候选期间死亡也遵循同样的归因于无效候选原则——无论是瞬时故障还是 PVF 故意耗尽资源导致进程被杀都无法程序化区分一律按无效候选处理以保护共识安全。安全性Security加固 PVF 处理随着按需平行链on-demand parachains的引入向链上提交 PVF 以进行准备和执行变得容易得多。这同时让**错误的争议与罚没slashing**更容易发生——无论是有意为之恶意攻击者还是无意为之bug 或操作员错误。因此PVF Host 的另一个目标就是围绕 PVF 全面加固安全以保护验证者的经济利益并提升整个系统的信心。威胁模型可能的攻击方式WebAssembly 本身是沙箱化的但历史上已有多个可导致远程代码执行的 CVE 被披露例如 2023 年 3 月与 2022 年 7 月针对 wasmtime 的安全公告。因此设计者真正担心的是以下几类攻击共识故障Consensus faults如果攻击者能获取某种随机性来源就可以以 50% 的概率投反对票制造无法解决的争议。定向罚没Targeted slashes攻击者可以针对特定验证者例如运行在易受攻击硬件上的验证者诱使其对有效候选投无效票从而使其被罚没。大规模罚没Mass slashes借助某种随机性来源进行无差别攻击——攻击者以 1/3 的概率投反对票即可造成显著的经济损失甚至无需窃取密钥或完全替换二进制。窃取密钥Stealing keys后果非常严重。理论上不应在沙箱化下发生至少不应允许文件系统访问或网络访问。控制验证者节点Taking control over the validator例如把polkadot二进制替换成polkadot-evil。在沙箱化到位后这同样不应可能。拦截并篡改软件包Intercepting and manipulating packages效果与上一条类似且很难在不先实现 4 或 5 的情况下完成。限制文件系统访问Landlock 沙箱一项基础安全机制是确保任何直接与不受信任代码交互的线程都无法访问文件系统从而防止攻击者读取敏感数据或修改宿主机上的数据。具体实现位于 common/src/worker/security.rsWorker 使用 Linux 内核自 5.13 起提供的Landlock安全特性在真正执行不受信任的代码之前对当前线程施加所有全局文件系统访问的访问控制Ruleset::new().handle_access(AccessFs::from_all(LANDLOCK_ABI))...restrict_self()。设计中值得注意的两个决策ABI 版本固定为 V1代码注释解释了原因——Polkadot 的参考内核版本是 5.16V15.13 引入已包含对文件读取的完整限制V25.19新增的改名限制并未使用。更关键的是确定性考量如果一半验证者运行在 V2、一半在 V1它们对某些 PVF 可能产生不同的语义恶意 PVF 便可以利用这种 ABI 之间的不确定行展开新的攻击向量。因此只有在参考内核版本支持或引入对安全有实质收益的新特性时才会升级 ABI。Host 启动时检查 Landlock 状态在 host.rs 的warn_if_no_landlock中每次 Host 启动都会检查 Landlock 是否完全启用status_is_fully_enabled若未完全启用则打印警告Running validation of malicious PVF code has a higher risk of compromising this machine非 Linux 平台则提示考虑迁移到支持 Landlock 的 Linux 以获得最大安全性。security.rs中还附带了一个测试restricted_thread_cannot_access_fs在应用 Landlock 之后同一线程对临时文件的读写都会以PermissionDenied失败验证沙箱确实生效。清理环境变量Clearing env vars在开始处理不受信任的代码之前Worker 会清除全部环境变量。理由有二一是没必要把潜在敏感数据白白交给攻击者二是即使其他一切都已锁定环境变量仍可能成为随机性来源对应威胁模型第 1 点共识故障——例如RUST_LOG的值或其存在性本身就可能被恶意代码当作随机种子。实现见 common/src/worker/mod.rs 的remove_env_vars遍历std::env::vars_os()逐一删除唯一例外是保留RUST_LOG便于日志调试代码注释中留有 TODO未来可将其一并移除并在 Host 侧记录日志。同时该函数对键为空、键含、键/值含空字符等会导致remove_varpanic 的畸形环境变量做了防御性处理先记录警告再尝试删除。版本一致性防护Node 与 Worker 版本不匹配作为安全兜底Worker 在启动时会校验自身版本与节点Host版本是否一致common/src/worker/mod.rs 的worker_event_loop。如果发现版本不匹配例如原地升级导致会立即向父节点进程发送SIGTERMkill_parent_node_in_emergency强制节点关闭重启——这是为了防止用旧二进制验证新格式候选而错误地引发争议。同时由于父进程退出会关闭所有已打开的 Unix socket其余 Worker 也会随之收到错误并退出且准备任务写入的是临时文件、由节点侧在成功后才重命名为正式 artifact因此不会留下残留产物。内部流水线从请求到结果综合 host.rs 的事件循环一次典型的execute_pvf请求完整走一遍内部流水线调用方如候选验证子系统参见 candidate-validation.md通过ValidationHost::execute_pvf提交请求Host 将其转换为ToHost::ExecutePvf消息Host 用 PVF 数据计算ArtifactId基于 validation code hash查询 artifacts.rs 中的 artifact 状态已准备直接向执行队列发送execute::ToQueue::Enqueue准备中把执行请求挂到AwaitingPrepare映射表等准备完成后再派发处理失败若满足can_retry_prepare_after_failure非确定性错误 冷却期已过 重试次数未超上限重置为Preparing重新入准备队列否则直接把PrepareError转成ValidationError返回未知注册为Preparing并同时入准备队列。准备队列prepare/queue.rs按Priority::Normal/Priority::Critical双队列调度交给准备 worker 池编译hard_capacity与soft_capacity允许在出现关键任务时临时扩容到硬上限准备完成后handle_prepare_done把结果分发给所有等待中的 result sender随后将仍在等待的AwaitingPrepare执行请求派发到执行队列执行队列execute/queue.rs维护一组执行 worker默认上限execute_workers_max_num 2同一executor_params_hash的 worker 可复用若队列中没有兼容 worker任务最多等待MAX_KEEP_WAITING 4秒之后会杀掉首个空闲 worker 以重新 spawn 匹配的 worker 立即执行执行结果经Outcome枚举返回成功返回验证结果描述符候选无效返回InvalidCandidate此时 worker 可复用内部错误/超时/panic/I/O 错误则终止 worker 并由 Host 依据重试策略处理。此外Host 会以cleanup_pulse_interval默认 1 小时为周期对 artifact 缓存做prune裁剪artifact_ttl默认为 24 小时裁剪出的过期文件路径经sweeper_task异步删除见 host.rs 的handle_cleanup_pulse与sweeper_task。heads_up请求会刷新活跃 PVF 的last_time_needed使活跃 artifact 免于被过早清理。配置项一览Host 的Config见 host.rs可配置项及其默认值如下配置项默认值说明cache_path由节点指定artifact 缓存的根目录node_version由节点指定节点版本传None可跳过版本校验仅测试用prepare_worker_program_path由节点指定用于 spawn 准备 worker 的程序路径prepare_worker_spawn_timeout3 秒准备 worker 启动并连回 Host 的时限prepare_workers_soft_max_num1低于 critical 优先级任务可使用的准备 worker 软上限prepare_workers_hard_max_num1准备 worker 池的绝对硬上限execute_worker_program_path由节点指定用于 spawn 执行 worker 的程序路径execute_worker_spawn_timeout3 秒执行 worker 启动并连回 Host 的时限execute_workers_max_num2可同时运行的最大执行 worker 数核心重试/超时参数则作为常量固化在代码中准备失败冷却PREPARE_FAILURE_COOLDOWN 15 分钟、准备最大重试次数NUM_PREPARE_RETRIES 5、执行墙钟兜底系数JOB_TIMEOUT_WALL_CLOCK_FACTOR 4、CPU 时间监控开销补偿JOB_TIMEOUT_OVERHEAD 50ms、执行队列无兼容 worker 的最大等待MAX_KEEP_WAITING 4 秒、artifact 清理周期 1 小时与 TTL 24 小时。小结PVF Host 与 Workers 子系统通过独立子进程 Unix socket 通信 Landlock 沙箱 环境变量清理 版本一致性自检构筑了针对恶意或错误 PVF 的纵深防御同时借助准备重试冷却与次数上限、执行单次快速重试、CPU 时间超时、预检查与执行差异化超时、确定性错误分类等机制在无法做到完全确定性的现实约束下尽可能把争议和罚没风险降到最低。这些设计集中体现在 node/core/pvf 目录下的源码中读者可结合 host.rs、error.rs、security.rs 及 prepare/queue.rs、execute/queue.rs 继续深入研读。赞分享区块链【免费下载链接】polkadotPolkadot Node Implementation项目地址https://gitcode.com/gh_mirrors/po/polkadot点击查看免费下载相关推荐YouTube.js 解析器节点解析ThumbnailOverlayTitleView 类的工作原理与实战使用YouTube.js 解析器节点解析ThumbnailOverlayTitleView 类的工作原理与实战使用 导读 本文围绕 YouTube.jsInne区块链Sapiens系统稳定性保障深度解析故障恢复与可靠性设计Sapiens系统稳定性保障深度解析故障恢复与可靠性设计 Sapiens作为基于3亿张真实世界人类图像预训练的高分辨率视觉模型在姿态估计、语义分割、深度估计人工智能基础模型计算机视觉预训练深度学习终极Pipenv安全指南哈希验证与确定性构建如何保障Python项目安全终极Pipenv安全指南哈希验证与确定性构建如何保障Python项目安全 Pipenv是Python开发工作流的一站式解决方案它将pip、virtualen开发工具CLI包管理器上一篇Windows任务栏透明美化神器3分钟解锁TranslucentTB的完整指南下一篇终极GTA5线上小助手完全免费的洛圣都游戏体验增强工具完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表