
Proof of SQL Hello World 实战用 Space and Time 仓库跑通 SQL 零知识证明全流程【免费下载链接】sxt-proof-of-sqlSpace and Time | Proof of SQL项目地址: https://gitcode.com/GitHub_Trending/sx/sxt-proof-of-sql导读本文以 hello_world 示例 为入口带你从零跑通 Space and Time 的 Proof of SQL 完整流程构造一张含数据的表、解析一条SELECT b FROM table WHERE a 2查询、为查询结果生成零知识证明再通过验证器确认证明有效并还原可读结果。读完本文你将掌握仓库中示例程序的运行方式、CPU 与 GPU 两种运行模式的区别以及从 SQL 解析、查询规划、证明生成到验证的完整调用链。示例要解决什么问题Proof of SQL 的核心场景是证明者Prover掌握数据库验证者Verifier只持有数据的承诺Commitment证明者需要向验证者证明某条 SQL 查询在真实数据上执行后得到的查询结果确实是正确的整个过程不泄露底层数据。hello_world 是这一流程的最小化落地。它演示的查询是SELECT b FROM table WHERE a 2针对的数据表为ab1hi2hello3there2world从表中可以看到a 2命中两行因此查询应返回b列的两个值hello和world。这正是示例最终输出中验证成功的查询结果。该示例同时验证了过滤条件WHERE a 2和投影SELECT b这两类最基本的 SQL 操作在 Proof of SQL 中的正确性。运行示例标准运行默认启用 blitzar / GPU 加速在仓库根目录执行cargo run --example hello_world默认 feature 配置为arrow与perf见 crates/proof-of-sql/Cargo.toml其中perf [blitzar, cpu-perf]会同时启用 blitzarGPU 承诺引擎与 CPU 并行优化。运行时若检测到可用 GPU会先执行一次预热。纯 CPU 运行禁用 blitzar如果不希望依赖 GPU 环境可以关闭默认 feature 并显式启用test与cpu-perfcargo run --example hello_world --no-default-features --featurestest cpu-perf这条命令是 README 中特别强调的注意项--no-default-features会关闭arrow与perf而cpu-perf对应 crates/proof-of-sql/Cargo.toml 中的cpu-perf [rayon, ark-ec/parallel, ark-poly/parallel, ark-ff/asm, halo2curves/asm]会开启 Rayon 并行计算与 arkworks 的汇编级加速使纯 CPU 也能获得较好的性能。需要留意的是hello_world 示例本身声明了required-features [proof-of-sql/test]见 crates/proof-of-sql-planner/Cargo.toml因此上述两种运行方式都必须保证testfeature 被激活。示例输出解读以仓库文档给出的输出为例Warming up GPU... 520.959485ms Loading data... 3.229767ms Parsing Query... 1.870256ms Generating Proof... 467.45371ms Verifying Proof... 7.106864ms Valid proof! Query result: OwnedTable { table: {Ident { value: b, quote_style: None }: VarChar([hello, world])} }各阶段含义如下阶段输出示例含义预热Warming up GPU... 520.959485ms初始化并预热 GPU 后端仅在启用 blitzar 时出现加载数据Loading data... 3.229767ms构建公共参数、Prover/Verifier 设置并注册表数据解析查询Parsing Query... 1.870256ms将 SQL 解析并转换为 Proof of SQL 查询计划生成证明Generating Proof... 467.45371ms对查询求值并生成零知识证明耗时最长验证证明Verifying Proof... 7.106864ms验证者用承诺验证证明并还原最终结果结果Valid proof!Query result: ...证明有效输出b列命中值[hello, world]注意上述耗时数据来自示例 README 的一次实际运行记录在不同硬件与 feature 组合下会显著不同尤其是不带 GPU 时Generating Proof的耗时通常更长不要将其视为性能基准。输出中的Query result以内部OwnedTable形式打印VarChar([hello, world])即b列命中两行而示例代码在验证通过后还会把它转换为 ArrowRecordBatch并调用pretty_format_batches打印成表格形式见下文代码分析。从源码看完整调用链hello_world 的核心逻辑全部位于 crates/proof-of-sql-planner/examples/hello_world/main.rs其主流程可拆解为以下五步与上文输出的阶段一一对应。第 1 步生成公共参数与设置Loading datalet mut rng StdRng::from_seed([0u8; 32]); let public_parameters PublicParameters::rand(5, mut rng); let prover_setup ProverSetup::from(public_parameters); let verifier_setup VerifierSetup::from(public_parameters); let mut accessor OwnedTableTestAccessor::DynamicDoryEvaluationProof::new_empty_with_setup(prover_setup); accessor.add_table( TableRef::from_names(None, tab), owned_table([ bigint(a, [1, 2, 3, 2]), varchar(b, [hi, hello, there, world]), ]), 0, );几个关键点固定随机种子StdRng::from_seed([0u8; 32])保证运行结果可复现PublicParameters::rand(5, mut rng)5是 Dory 协议的max_nu最大对数规模公共参数会生成2^max_nu个 G1/G2 群元素见 crates/proof-of-sql/src/proof_primitive/dory/public_parameters.rs 中rand_impl的iter::repeat_with(...).take(1 max_nu)。示例中表只有 4 行规模很小max_nu 5已足够若表规模超过设置上限Dory 会抛出SmallSetup错误见 dynamic_dory_commitment_evaluation_proof.rs 中的DoryError::SmallSetupOwnedTableTestAccessor这是仓库为测试与示例提供的统一访问器同时实现了元数据、Schema、承诺与数据访问接口见 crates/proof-of-sql/src/base/database/test_accessor.rs 中TestAccessortrait 的约束add_table的第三个参数0是表的偏移量table offsetDory 承诺依赖生成元偏移示例固定为 0当前实现也仅支持偏移 0owned_table构造器bigint(...)与varchar(...)来自 crates/proof-of-sql/src/base/database/owned_table_utility.rs用于便捷构造OwnedTable除这两种类型外该工具模块还支持uint8、tinyint、smallint、int、int128、boolean、scalar、varbinary、decimal75、timestamptz等列类型方便你扩展自己的实验表。第 2 步SQL 解析与查询规划Parsing Querylet sql SELECT b FROM tab WHERE a 2; let config ConfigOptions::default(); let statements Parser::parse_sql(GenericDialect {}, sql).unwrap(); let query_plan sql_to_proof_plans(statements, accessor, config).unwrap()[0];这里调用了proof_of_sql_plannercrate 的sql_to_proof_plans入口。其内部处理管线在 crates/proof-of-sql-planner/src/conversion.rs 的sql_to_posql_plans中有清晰注释共五步用sqlparser将 SQL 解析为 AST用 DataFusion 的SqlToRel将 AST 转换为LogicalPlan解析选项来自ConfigOptions如parse_float_as_decimal、enable_ident_normalization用Analyzer对逻辑计划做分析用Optimizer优化仓库对 DataFusion 38 做了定制临时移除了common_sub_expression_eliminate规则详见同文件optimizer()函数将优化后的LogicalPlan通过logical_plan_to_proof_plan转换为 Proof of SQL 的DynProofPlan。也就是说一条 SQL 被翻译成了可证明的查询计划这也是 Proof of SQL 中 planner 一词的来源。sql_to_proof_plans返回的是计划列表示例取第 0 个元素。第 3 步证明生成Generating Prooflet verifiable_result VerifiableQueryResult::DynamicDoryEvaluationProof::new( query_plan, accessor, prover_setup, [], ) .unwrap();VerifiableQueryResult::new同时完成两件事计算查询结果并生成该结果有效的证明见 crates/proof-of-sql/src/sql/proof/verifiable_query_result.rs 的文档注释结果以中间形式保存以处理溢出等边界情况。它的类型参数DynamicDoryEvaluationProof是 Dory 承诺方案对应的证明类型见 crates/proof-of-sql/src/proof_primitive/dory/dynamic_dory_commitment_evaluation_proof.rs[]是占位符参数Placeholder 字面量列表本查询未使用。第 4 步证明验证与结果还原Verifying Prooflet result: RecordBatch verifiable_result .verify(query_plan, accessor, verifier_setup, []) .unwrap() .table .try_into() .unwrap();verify是VerifiableQueryResult的验证接口验证者使用列承诺这里示例简化直接复用同一 accessor 模拟承诺访问器检查证明验证通过后返回QueryData其中table被强制转换为查询目标列类型再通过try_into()转成 ArrowRecordBatch。随后示例打印println!(Valid proof!); println!({}, pretty_format_batches([result]).unwrap());在真实场景中证明者与验证者是分离的验证者只有数据库列的承诺将查询发给不可信的证明者收到VerifiableQueryResult后用自己持有的承诺验证这一交互模型在 verifiable_query_result.rs 顶部的伪代码中有完整描述。如果证明者篡改结果或数据库版本不一致验证会失败并返回DoryError::VerificationError之类的错误。第 5 步阶段计时示例通过start_timer/end_timer两个辅助函数打印各阶段耗时即 README 输出中... xxx.xxxms的来源细节fn start_timer(message: str) - Instant { print!({message}...); stdout().flush().unwrap(); Instant::now() } fn end_timer(instant: Instant) { println!( {:?}, instant.elapsed()); }更深一步这是如何做到的整个 hello_world 背后是 Proof of SQL 的两大支柱Dory 承诺方案PCSPublicParameters、ProverSetup、VerifierSetup、DynamicDoryEvaluationProof均来自proof_primitive::dory模块。Dory 是一种基于配对群的承诺方案其公开参数由 G1/G2 群元素构成见 public_parameters.rs。仓库同时实现了 CPU 版与 GPU 版dory_commitment_helper_cpu.rs/dory_commitment_helper_gpu.rsGPU 路径即 blitzar 的职责Sumcheck 协议与查询证明SQL 的每个算子过滤、投影、聚合、连接等在 crates/proof-of-sql/src/sql/proof_plans 中都有对应的证明执行器如filter_exec.rs、projection_exec.rs它们把查询的逐行求值编码为多项式通过 sumcheck 协议证明多项式恒等从而证明查询结果与底层数据一致。示例中的WHERE a 2会被编译为 FilterExecSELECT b编译为 ProjectionExec二者共同组成一个可证明的查询计划最终验证b hello与b world确实是数据表中a 2两行的取值而证明者无需向验证者泄露整张表。下一步探索跑通 hello_world 后可以从以下路径继续深入更多数据示例仓库在 crates/proof-of-sql-planner/examples 下提供了二十多个基于真实 CSV 数据的示例如books、census、stocks、dinosaurs、avocado-prices等每个示例都用 CSV 加载数据并生成证明其中posql_db示例演示了使用commit_accessor/csv_accessor/record_batch_accessor三种方式接入数据读取数据表的方式hello_world 直接以内存构造OwnedTable而生产场景更常见的是通过OwnedTableTestAccessor或commit_accessor将数据先提交为承诺再执行证明与验证流程见 crates/proof-of-sql-planner/examples/posql_db端到端测试仓库的 crates/proof-of-sql-planner/tests/e2e_tests.rs 对多种 SQL 特性聚合、连接、分组等做了端到端证明验证可以作为理解 Proof of SQL 能力边界的参考。小结hello_world 是理解 Space and Time Proof of SQL 的最佳起点它用最小代码量串起了「构造数据 → 解析 SQL → 生成证明 → 验证证明 → 得到结果」的完整链路并通过逐阶段计时让开发者直观看到每个环节的成本分布。掌握本文内容后你可以基于 main.rs 自由修改表结构与 SQL实测 Proof of SQL 对各种查询类型的支持情况。【免费下载链接】sxt-proof-of-sqlSpace and Time | Proof of SQL项目地址: https://gitcode.com/GitHub_Trending/sx/sxt-proof-of-sql创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考