新闻详情

新闻详情

首页 / 资讯中心 / 详情

Substrate Statement Store 深度解析:链下签名数据存储、传播与访问机制

发布时间:2026/9/26 10:14:38来源:尧图网络
Substrate Statement Store 深度解析:链下签名数据存储、传播与访问机制
区块链开发框架后端【免费下载链接】substrateSubstrate: The platform for blockchain innovators项目地址https://gitcode.com/gh_mirrors/su/substrate点击查看免费下载Statement Store语句存储是 Substrate 提供的一种链下off-chain数据存储用于保存携带真实性证明签名的语句statement并可通过 RPC 与 OCW链下工作者访问。本文以 primitives/statement-store/README.md 为核心结合仓库中的类型定义、客户端实现、网络传播层与 RPC 接口源码系统讲解 Statement Store 的数据模型、签名与编码约定、运行时集成方式、存储约束管理以及完整的数据流帮助你理解并能在自己的 Substrate 链上使用这一机制。一、Statement Store 是什么Statement Store 是 Substrate 中一个面向带签名声明的链下数据仓库。节点会保存一定数量的语句每个语句附带一个归属账户 ID 的真实性证明proof of authenticity。语句的写入通道有三种OCW链下工作者可以在数据仓库中放入语句需要有效签名只要它们控制对应账户的密钥RPC用户可以通过 RPC 提交预先签名好的语句链上事件链上逻辑可以通过一个运行时事件把语句提交到仓库。为了让任何链上账户都能声明我想为仓库制作一条语句运行时新增了一个系统事件NewStatement。在节点存储与广播时该语句会附带事件所在区块的哈希以及事件在区块内的索引这两者实质上取代了真实签名用于证明语句确实来自某个链上账户。frame/statement/src/lib.rs 中可以看到该事件的定义#[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum EventT: Config where T as frame_system::Config::AccountId: Fromsp_statement_store::AccountId, { /// A new statement is submitted NewStatement { account: T::AccountId, statement: Statement }, }语句由可选的真伪证明例如签名和一组**字段field组成。对于没有证明的语句节点会以带速率限制器rate-limiter**的随机方式在网络上 gossip以最大限度降低被恶意节点淹没的风险这类语句通常会被节点忽略除非它由多个不同的对等节点转发或对等节点以某种方式为此付费例如转发了一条有价值的内容。二、语句的字段模型Field 枚举每条语句的每个字段本质上都是一个键/值对。字段必须排序且同一字段类型不能重复出现。客户端可以根据出现哪些键key对消息建立索引便于检索。形式上Statement等价于VecField而Field是如下的 SCALE 编码枚举见 primitives/statement-store/src/lib.rs判别值变体类型/说明0AuthenticityProof(Proof)消息的签名。对于无法从签名 消息数据推导出公钥的密码学体系还需包含签名者的公钥1DecryptionKey([u8; 32])解密语句数据所用的密钥标识符若缺失此字段Data应视为未加密2Priority(u32)优先级说明。同一发送者的多条语句在竞争持久化或传输时高优先级语句应优先保留节点在考虑无签名语句时应忽略此字段3Channel([u8; 32])频道标识符。同一频道在任意时刻只应保留一条消息保留优先级最高的那条节点在考虑无签名语句时应忽略此字段4Topic1([u8; 32])第一个主题标识符5Topic2([u8; 32])第二个主题标识符6Topic3([u8; 32])第三个主题标识符7Topic4([u8; 32])第四个主题标识符8Data(Vecu8)通用数据段无特殊含义主题数量上限由常量MAX_TOPICS: usize 4限制primitives/statement-store/src/lib.rs。从源码结构看Topic、DecryptionKey、Hash、BlockHash、AccountId、Channel全部是[u8; 32]类型别名primitives/statement-store/src/lib.rs。字段顺序与去重的解码校验Statement的Decode实现会严格校验字段顺序后续字段的判别值必须严格大于前一个字段否则解码失败返回Invalid field order or duplicate fields这正是 README 中字段必须排序且同一类型不得重复的实现保证primitives/statement-store/src/lib.rslet num_fields: codec::Compactu32 Decode::decode(input)?; let mut tag 0; let mut statement Statement::new(); for i in 0..num_fields.into() { let field: Field Decode::decode(input)?; if i 0 field.discriminant() tag { return Err(Invalid field order or duplicate fields.into()) } tag field.discriminant(); ... }对应的单元测试decode_checks_fields验证了重复字段与乱序字段都会导致解码失败primitives/statement-store/src/lib.rs。三、Proof证明枚举与签名机制Proof是另一个 SCALE 编码枚举表示语句真伪证明的具体形态primitives/statement-store/src/lib.rs判别值变体组成0Sr25519signature: [u8; 64]signer: [u8; 32]1Ed25519signature: [u8; 64]signer: [u8; 32]2Secp256k1Ecdsasignature: [u8; 65]signer: [u8; 33]3OnChainwho: [u8; 32]block_hash: [u8; 32]event_index: u64对于Proof::OnChainwho是与事件关联的账户标识block_hash是包含该事件的区块哈希event_index是事件在事件列表中的索引。Proof::account_id()方法可以返回证明创建者的账户 ID——注意Secp256k1Ecdsa的 signer 是 33 字节压缩公钥因此该方法会对其做BlakeTwo256哈希后再转为AccountIdprimitives/statement-store/src/lib.rs。签名数据signature material的特殊约定README 特别强调了一个关键细节签名所覆盖的消息数据是所有字段除签名本身外按顺序拼接的结果且不含Vec通常会带有的长度前缀length prefix。这样做的目的是签名可以在无需重新编码整条语句的情况下被推导出来。这一约定在Statement::encoded(for_signing)中实现当for_signing为真时编码会省略长度前缀与AuthenticityProof字段本身primitives/statement-store/src/lib.rsfn encoded(self, for_signing: bool) - Vecu8 { // 正常编码完整语句时Compact 长度前缀 各字段 if !for_signing { let compact_len codec::Compact::u32(num_fields); compact_len.encode_to(mut output); if let Some(proof) self.proof { 0u8.encode_to(mut output); proof.encode_to(mut output); } } // 签名数据从 DecryptionKey 开始按字段顺序拼接无长度前缀、无 proof ... }signature_material()调用encoded(true)生成待签名数据primitives/statement-store/src/lib.rs。三种签名算法的签名与验证Statement提供三套签名接口分别对应三种曲线sign_sr25519_public/sign_sr25519_private通过 keystore 中的公钥或直接给定私钥对签名sign_ed25519_public/sign_ed25519_privatesign_ecdsa_public/sign_ecdsa_private。其中*_public系列方法只能从运行时runtime调用因为 keystore 位于节点侧primitives/statement-store/src/lib.rs。verify_signature()返回SignatureVerificationResult枚举为Valid(AccountId)、Invalid、NoSignature无 proof 或Proof::OnChain三种primitives/statement-store/src/lib.rs。测试用例sign_and_verify用//Alice账户分别验证了三种算法的签名、无效签名与移除 proof 后的行为primitives/statement-store/src/lib.rs。四、链上集成Statement Pallet 与 Offchain Workerframe/statement/src/lib.rs 是支撑 Statement Store 的 FRAME pallet负责创建语句与校验语句。它通过runtime_api::ValidateStatement暴露校验接口。校验逻辑余额驱动的限额pallet 的校验函数validate_statement会根据语句作者的账户余额计算两个值max_count该账户签名者允许的最大语句条数max_size该账户允许的语句数据总大小上限。计算方式与账户余额挂钩max_count balance / StatementCostmax_size balance / ByteCost并各自clamp在MinAllowedStatements..MaxAllowedStatements与MinAllowedBytes..MaxAllowedBytes范围内frame/statement/src/lib.rs。相关配置常量定义在 pallet 的Configtrait 中StatementCost、ByteCost、MinAllowedStatements、MaxAllowedStatements、MinAllowedBytes、MaxAllowedBytesframe/statement/src/lib.rs。对于Proof::OnChain类型的语句校验不是验签而是验证block_hash必须等于当前区块的parent_hashevent_index必须指向一个真实的NewStatement事件事件中的account与statement必须与所提交语句完全一致。这一系列检查都在 frame/statement/src/lib.rs 中完成任何一项不匹配都会返回InvalidStatement::BadProof。Offchain Worker把链上事件变成网络语句pallet 的offchain_worker钩子会调用collect_statements()遍历本区块产生的所有事件找出NewStatement事件如果语句没有 proof则构造Proof::OnChain { who: account, block_hash: parent_hash, event_index }并附加到语句上然后通过 host 函数statement_store::submit_statement(statement)提交到节点本地的 Statement Storeframe/statement/src/lib.rs。这样链上账户无需持有私钥即可声明一条语句真实性由区块哈希与事件索引背书。运行时侧还提供了sp_statement_store::runtime_api::StatementStorehost 接口primitives/statement-store/src/runtime_api.rs包括submit_statement、statements、broadcasts、posted、posted_clear、removeOCW 正是通过这些 host 函数访问节点本地存储。StatementSource枚举Chain/Network/Local标记语句来源其中Chain与Local来源允许重新提交延长过期时间而Network来源不允许primitives/statement-store/src/runtime_api.rs。五、节点侧实现磁盘存储与约束管理client/statement-store/src/lib.rs 是基于parity_db的磁盘存储实现Store实现sp_statement_store::StatementStoretrait。README 中提到节点持有一定数量的语句而Store中通过如下默认配置约束总量const DEFAULT_PURGE_AFTER_SEC: u64 2 * 24 * 60 * 60; // 48 小时 const DEFAULT_MAX_TOTAL_STATEMENTS: usize 8192; const DEFAULT_MAX_TOTAL_SIZE: usize 64 * 1024 * 1024; // 64 MiBclient/statement-store/src/lib.rs。Options结构体提供max_total_statements、max_total_size、purge_after_sec三个可配置项client/statement-store/src/lib.rs。约束管理Constraint Management每条新语句插入前先经运行时校验函数得到max_count与max_size随后检查两类约束见 client/statement-store/src/lib.rs账户级约束对给定账户 ID最多允许max_count条语句、max_size总数据大小。为满足约束会从最低优先级开始删除该账户的旧语句全局约束全库语句数不超过MAX_TOTAL_STATEMENTS、总大小不超过MAX_TOTAL_SIZE。同样从最低global_priority开始驱逐。如果新语句本身就无法满足约束例如它比被驱逐的语句优先级还低、或数据量过大则不会删除任何语句直接返回Ignored。同一优先级下删除顺序不保证。另外同一(account, channel)组合只保留一条消息同频道出现更高优先级语句时旧语句被替换client/statement-store/src/lib.rs。单元测试constraints对账户级与全局级约束、频道替换、越界忽略等场景做了完整覆盖client/statement-store/src/lib.rs。过期与清理Statement Expiration每当语句被移出存储无论被高优先级语句驱逐还是通过remove显式删除都会标记为expired。过期语句在purge_after_sec秒内不能重新入库防止旧语句在网络中反复传播client/statement-store/src/lib.rs。Store::new_shared会启动一个周期为 30 秒的维护任务MAINTENANCE_PERIOD定期调用maintain()清除已过期的过期标记client/statement-store/src/lib.rs。测试expired_statements_are_purged验证了删除后经过DEFAULT_PURGE_AFTER_SEC 1秒再maintain()后过期记录被彻底清空client/statement-store/src/lib.rs。索引与检索Index在内存中维护按主题by_topic、解密密钥by_dec_key、账户accounts等维度的索引client/statement-store/src/lib.rs。iterate_with实现匹配所有给定主题的集合求交检索先从最小的集合开始迭代以提高效率client/statement-store/src/lib.rs。Store启动时会populate()从磁盘加载历史语句并重建内存索引client/statement-store/src/lib.rs。六、网络传播statement gossipclient/network/statement/src/lib.rs 实现了 statement gossip 层用于在网络中对等节点之间传播语句。协议与会话管理StatementHandlerPrototype::new(genesis_hash, fork_id)生成协议名/{genesis_hash_hex}/statement/1有 fork_id 时为/{genesis_hash_hex}/{fork_id}/statement/1并返回NonDefaultSetConfig供网络服务挂载client/network/statement/src/lib.rs。相关常量client/network/statement/src/config.rs常量值含义MAX_STATEMENT_SIZE256 KiB单条通知的最大尺寸MAX_KNOWN_STATEMENTS10240每个对等节点 LRU 已知语句集合上限MAX_PENDING_STATEMENTS8192待验证语句队列上限PROPAGATE_TIMEOUT1000 ms周期性广播间隔声誉Reputation机制收到对等节点的语句后节点会依据验证结果调整该对等节点的声誉分数client/network/statement/src/lib.rs收到任意语句先扣分ANY_STATEMENT迫使节点验证它验证通过后退还ANY_STATEMENT_REFUND高优先级新语句奖励EXCELLENT_STATEMENT普通新语句奖励GOOD_STATEMENT无效语句重罚BAD_STATEMENT重复语句罚DUPLICATE_STATEMENT。广播与同步状态StatementHandler在不处于 major syncing时才接受和广播语句client/network/statement/src/lib.rs并且绝不向轻节点Light广播client/network/statement/src/lib.rs。propagate_statements每PROPAGATE_TIMEOUT1 秒触发一次向每个对等节点发送其未知的语句通过 per-peer 的known_statementsLRU 集合去重并统计substrate_sync_propagated_statements指标client/network/statement/src/lib.rs。七、RPC 访问查询与提交预签名语句用户可通过 RPC 查询与提交语句。RPC 接口定义在 client/rpc-api/src/statement/mod.rs实现位于 client/rpc/src/statement/mod.rs。六个方法如下方法名参数说明statement_dump无返回全部语句SCALE 编码的Statement列表statement_broadcastsmatch_all_topics: Vec[u8;32]返回所有包含全部给定主题、且无DecryptionKey字段的语句的Datastatement_postedmatch_all_topics、dest: [u8;32]返回解密密钥标识为dest的语句的Data密文statement_postedClearmatch_all_topics、dest: [u8;32]返回解密密钥标识为dest、且客户端持有私钥可解密的明文Datastatement_submitencoded: Bytes提交一条预编码的语句StatementSource::Localstatement_removestatement_hash: [u8;32]按哈希从存储中移除语句其中statement_dump是 unsafe 方法需要节点允许--rpc-expose-unsafe或通过安全访问策略才能调用DenyUnsafe检查见 client/rpc/src/statement/mod.rs。statement_submit返回New/Known时视为成功Ignored存储已满、Bad校验失败等情况返回 RPC 错误client/rpc/src/statement/mod.rs。StatementStoretraitprimitives/statement-store/src/store_api.rs是所有这些能力的统一抽象RPC、gossip、OCW host 函数都通过它访问同一个节点本地存储实例。八、数据加密可选的端到端加密README 中DecryptionKey字段的说明暗示语句数据可以加密。Statement提供了基于ECIES的加密/解密方法encrypt/decrypt_privateprimitives/statement-store/src/lib.rs实现位于 primitives/statement-store/src/ecies.rs密钥交换x25519由x25519-dalek提供生成临时密钥对KDFHKDF-SHA256 从共享秘密推导 AES-256 密钥AEADAES-256-GCM 加密nonce 12 字节密文布局临时公钥(32B) || nonce(12B) || ciphertext。encrypt_ed25519会把 ed25519 公钥转换为 Montgomery 形式后执行 x25519 加密decrypt_ed25519则通过 SHA-512 从 ed25519 私钥派生出 x25519 私钥primitives/statement-store/src/ecies.rs。posted_clearRPC 正是依赖节点 keystore 中持有的 ed25519 密钥对才能返回明文client/statement-store/src/lib.rs。对应测试覆盖了 x25519/ed25519 加解密往返与坏数据拒绝primitives/statement-store/src/ecies.rs。九、典型应用场景README 列举了 Statement Store 的多种潜在用途结合前面的机制可以更好地理解其适用性环签名聚合ring-signature aggregation多参与者先链下交换签名材料再统一上链消息传递messaging结合Channel与Topic字段实现定向或主题化消息状态通道state-channels链下交换带签名的状态更新仅在争议时上链裁决多方交易广告阶段的延迟先链下公布交易意图待各方就绪后再正式上链预言机数据preimage发布发布哈希已上链引用的 preimage 数据手续费转移由第二方代为支付费用的有效途径先链下签好声明链上验证。这些场景共同的特点是需要可信地证明某账户曾声明过某内容但不必立刻写入链上状态——Statement Store 以链下存储 签名/事件背书 网络 gossip RPC 检索的组合恰好提供了这一能力。十、快速上手要点启用组件链上集成需要引入frame/statementpallet 并在 runtime 中实现ValidateStatementruntime APImock 示例见 client/statement-store/src/lib.rs节点侧需要client/statement-storeStore::new_shared创建唯一实例见 client/statement-store/src/lib.rs与client/network/statement的StatementHandler配合。提交语句链下工作者通过 host 函数submit_statement提交来源Chain用户通过statement_submitRPC 提交预签名语句来源Local链上账户通过pallet_statement::Pallet::submit_statement存款NewStatement事件由 OCW 拾取并转为Proof::OnChain。查询语句无加密广播内容用statement_broadcasts加密内容用statement_posted/statement_postedClear后者要求节点 keystore 有对应 ed25519 私钥。约束与清理默认每账户限额由运行时按余额计算全局默认最多 8192 条语句、64 MiB 数据被驱逐或删除的语句在 48 小时内禁止重新入库。相关核心文件索引语句原语定义、存储 trait、运行时 host 接口、ECIES 加密、pallet 实现、磁盘存储实现、网络 gossip 层、RPC 接口、RPC 实现。声明本模块基于 Apache-2.0 许可原语 crate客户端实现采用 GPL-3.0-or-later WITH Classpath-exception-2.0 许可。赞分享区块链开发框架后端【免费下载链接】substrateSubstrate: The platform for blockchain innovators项目地址https://gitcode.com/gh_mirrors/su/substrate点击查看免费下载相关推荐WordPress Gutenberg 核心数据存储锁Store Locks机制深度解析WordPress Gutenberg 核心数据存储锁Store Locks机制深度解析 GutenbergWordPress 块编辑器的 core d后端前端Substrate Transaction Storage Pallet 实战指南链上数据存储、存储证明与 IPFS 访问Substrate Transaction Storage Pallet 实战指南链上数据存储、存储证明与 IPFS 访问 导读 pallet transac区块链开发框架后端Obsidian笔记美化终极指南如何用CSS布局技巧打造个性化知识库Obsidian笔记美化终极指南如何用CSS布局技巧打造个性化知识库 你是否厌倦了Obsidian默认的单列布局想让你的知识库拥有杂志般的排版效果吗前端上一篇终极NGA论坛优化指南5个技巧让你的浏览效率提升300%下一篇DXVK实用指南让Linux玩转DirectX游戏的黑科技创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

the USB CDC-ACM descriptor layout 2026/9/26 11:09:31

the USB CDC-ACM descriptor layout

For a USB CDC-ACM (Virtual COM Port) device, the descriptor hierarchy typically looks like this: Device Descriptor │ └── Configuration Descriptor│├── Interface 0 (Communication Class Interface, CIC)│ ├── Header Functional Descriptor│ ├─…

阅读更多 →
BunnyScholar文献综述实操:搭建文献对比矩阵避免流水账 2026/9/26 11:09:31

BunnyScholar文献综述实操:搭建文献对比矩阵避免流水账

“综述写成文献流水账,毫无批判性思考!”被导师痛骂后,用BunnyScholar 5分钟搭建顶刊对比矩阵“今天下午组会汇报文献综述,导师翻了两页我的开题报告初稿,脸色铁青地打断我:‘你这写的叫文献综述吗&#xf…

阅读更多 →
BunnyScholar开题报告实操:创新点与技术路线如何对应 2026/9/26 11:09:31

BunnyScholar开题报告实操:创新点与技术路线如何对应

“创新点写了三条,导师批注全是‘伪创新’!”用BunnyScholar从边际贡献到技术路线全面翻盘“开题报告被导师当场毙掉了,退回来的 Word 文档批注红得触目惊心!我在‘研究创新点’里认认真真写了三条:第一条,…

阅读更多 →
《基于微信小程序的自助搭配花束购买管理系统》 2026/9/26 11:09:31

《基于微信小程序的自助搭配花束购买管理系统》

一、前言传统线上花店大多只能直接购买成品花束,用户很难按自己的喜好自由搭配花材;线下花店又受营业时间和地理位置限制,选购不够方便。针对这些问题,本系统基于微信小程序开发,分为管理员和用户两端,搭建…

阅读更多 →
BunnyScholar文献综述实操:连接经典文献与近三年前沿研究 2026/9/26 11:09:31

BunnyScholar文献综述实操:连接经典文献与近三年前沿研究

经典文献与近三年顶刊严重脱节?手把手教你用BunnyScholar搭起“理论渊源到前沿突破”传承链“开题答辩现场,评委专家翻了翻我的第二章国内外研究现状,冷笑一声提问:‘同学,你的选题是生成式人工智能赋能智慧医疗&#…

阅读更多 →
知网标红微服务与Redis分布式锁说明:助研君按字修改方法 2026/9/26 11:09:24

知网标红微服务与Redis分布式锁说明:助研君按字修改方法

微服务架构与Redis分布式锁设计被知网标红?助研君按字定点爆改:保留全部代码注解与参数“计算机毕设代码写了上万行,Spring Cloud 微服务、Redis 缓存和分布式事务调通调得头发掉光。结果第三章‘系统设计与技术实现’一查知网,整…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉