Pointproofs 学习笔记3——代码解析

1. 引言

之前的系列博客有:

本博客,主要针对该论文算法的实现(基于bls12-381 curve),https://github.com/algorand/pointproofs,进行相应的梳理。

2. github.com/algorand/pointproofs 代码总体结构

  • Cargo.toml:Cargo配置文件。

  • benches:benchmark文件夹。
    - basic.rs:提供basic benchmarks,数据记录在benchmark.md文件。
    - bench_aggregation.rs:bench the cost for cross commitments aggregation和batch verification。
    - bench_mul.rs:bench the cost of sum of product vs doing it serialized。
    - extra.rs:extra benchmarks using parameters with pre-computation。
    - old_data.md:在MacOS 3.1GHz Intel Core i5的测试数据,最新的测试数据见benchmark.md
    - benchmark_extra.md:AWS Intel® Xeon® CPU E5-2686 v4 @ 2.30 GHz服务器,分别对 n = 1024 n=1024 n = 32768 n=32768 ,以及proof in G1,proof in G2进行了bench。同时指出,new commitment和new proof的主要开销在sum of n product,对有无precompute进行了性能对比,当 n < 1024 n<1024 时,有precomputation的性能提升明显。

  • src:Pointproofs算法Rust语言实现。
    - bin:内含bin执行文件。
    - pairings:pairings模块,此处为Pointproofs核心功能模块。详见第3节分析。
    - test:test测试模块。
    - lib.rs:对外暴露pairings模块,支持test测试模块。

  • c_test:Pointproofs算法对应C语言接口测试。
    - pointproofs_c.h:通过Makefile内脚本自动生成。cbindgen --config cbindgen.toml --crate pointproofs --output c_test/pointproofs_c.h
    - test.c:对封装的C语言接口的测试代码。make test

  • build.rs:采用Build script方式调用cbindgen crate来生成相应的C语言header文件pointproofs.h,默认在target/debug或target/release目录下。(language: cbindgen::Language::C

  • Makefile, cbindgen.toml:使用make方式调用cbindgen命令工具(cargo install cargo install –force cbindgen 安装)来生成相应的C语言header文件pointproofs_c.h,在c_test/目录下。(在cbindgen.toml中配置了language = "C"

  • crs.param:即common reference string。可调用https://github.com/algorand/pointproofs-paramgen来生成。

  • SPEC.md:函数接口说明。

  • benchmark.md:取 n = 1024 n=1024 ,proofs in G1,AWS Intel® Xeon® CPU E5-2686 v4 @ 2.30 GHz服务器上的bench性能数据。

3. Pointproofs核心算法实现

Pointproofs核心算法实现在src/pairings/目录下:

  • err.rs
  • commit.rs
  • c_api.rs
  • hash_to_field_pointproofs.rs
  • misc.rs
  • mod.rs
  • param.rs
  • pointproofs_groups.rs
  • prove.rs
  • serdes.rs

3.0 一些依赖库

3.0.1 ff/ff-zeroize

github.com/algorand/ff-zeroize是从github.com/zkcrypto/ff fork来的。
ff是用pure Rust写的finite field库,里面没有任何的unsafe{}代码,提供了finite field内各种运算Traits和utilities。包含的traits有:Field, PrimeField, PrimeFieldRepr, SqrtField
调用方式为:

  • 在Cargo.toml中配置:
[dependencies]
ff-zeroize = { version = "0.6.3", features = ["derive"]}
  • 采用如下方式进行宏调用。Fr会执行 FieldPrimeField,若支持SqrtField也会执行SqrtField。同时会自动执行FrRepr并derives PrimeFieldRepr for it。
#[macro_use]
extern crate ff;

#[derive(PrimeField)]
#[PrimeFieldModulus = "52435875175126190479447740508185965837690552500527637822603658699938581184513"]
#[PrimeFieldGenerator = "7"]
pub struct Fr(FrRepr);


3.0.2 zeroize

https://github.com/iqlusioninc/crates/tree/develop/zeroize zeroized:提供a portable approach to securely zeroing memory using techniques which guarantee they won’t be “optimized away” by the compiler。用于保证:

  • The zeroing operation can’t be “optimized away” by the compiler.【LLVM的volatile semantics可保证其成立。】
  • All subsequent reads to memory will see “zeroized” values.【Unsafe Code Guidelines Working Group可保证其成立。】

zeroize主要API就是Zeroize trait。
调用方式为:

  • 在Cargo.toml中配置,使用zeroize_derive feature,将自动call zeroized() on all members of a struct or tuple struct。
[dependencies]
zeroize = { version  = "1.1", features = ["zeroize_derive"]}
  • drop后将清零:
use zeroize::Zeroize;

// This struct will be zeroized on drop
#[derive(Zeroize)]
#[zeroize(drop)]
struct MyStruct([u8; 32]);

  • drop后不清零:
use zeroize::Zeroize;

// This struct will *NOT* be zeroized on drop
#[derive(Copy, Clone, Zeroize)]
struct MyStruct([u8; 32]);

3.0.3 pairing-plus

https://github.com/algorand/pairing-plus 代码库中仅对BLS12-381曲线做了实现。(可参考博客 bls12 curve生成器,可生成ZCash sapling版本中所使用的BLS12-381曲线
BLS12-381的表达为:
E : y 2 = x 3 + 4 E: y^2 = x^3 + 4
F q = 0 x 1 a 0111 e a 397 f e 69 a 4 b 1 b a 7 b 6434 b a c d 764774 b 84 f 38512 b f 6730 d 2 a 0 f 6 b 0 f 6241 e a b f f f e b 153 f f f f b 9 f e f f f f f f f f a a a b F_q= 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab
F r = 0 x 73 e d a 753299 d 7 d 483339 d 80809 a 1 d 80553 b d a 402 f f f e 5 b f e f f f f f f f f 00000001 F_r=0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001 【为E.order()的最大素数因子】
取的generator为:
x 1 = 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 x_1=3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507
g 1 = ( x 1 , y 1 ) g_1=(x_1,y_1) g_1.order()即为Fr

cd pointproofs/src/bin
cargo run

调试信息有:

zouyudi alpha_power:Fr(0x0000000000000000000000000000000000000000000000000000000000000001)
zouyudi g1_power:G1Affine { x: Fq(0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb), y: Fq(0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1), infinity: false }
zouyudi alpha_power:Fr(0x03530f615aa764a263544084485bf91a014712497bc9ba54f11114c3b3e45f08)
zouyudi g1_power:G1Affine { x: Fq(0x06b73e205fc1403b0ea47f87cd9d1752814bfcfa43f37e64e5a4267e7947890678319eebaa659bfbbb07f0b885924ac6), y: Fq(0x00956a7c3cbbfea2a46544aba6dd27989a2c8dcd6c9bed54416c158c0c3c74cbdd045171d85527226a9c854523499467), infinity: false }
zouyudi alpha_power:Fr(0x201474474cc90c279328d8f6cd5e085a575e15e60a1503b7889c2c54b53ae52f)
zouyudi g1_power:G1Affine { x: Fq(0x02102361767f5aa63ca59d03f9985352223962a9bf72a1aaf540cdb1ef89a822c7a9ab5d77cb378112c9bb0519150d89), y: Fq(0x1895ec61d5a8386f61e698c52f19991a3df095fc806fde62912822510e29688ad14a332fb3866e416b2cae3b063112cc), infinity: false }
zouyudi alpha_power:Fr(0x434e2571e93e582a486fd726085cb3dcb9674bd28d56eb5aaab07d1faab07c4c)
zouyudi g1_power:G1Affine { x: Fq(0x121addc500baa3418225e0679869bb03c15492f69f126fa0b410736e60efebc31930070069ee03ad66f89c8345ae5a95), y: Fq(0x00ec4f34faec47049ed87f265ffd4316b5fb056de39ef5eb251ce30e2361438f6c6d0487e28dedaaccbb04bba698306d), infinity: false }
zouyudi alpha_power:Fr(0x0033efb58b5d261aa71244c3388763afde5aec58d477011b9efac221370f3476)
zouyudi g1_power:G1Affine { x: Fq(0x1496012438bf82884c09ba192a60b7c6026a0f1cf10d6f3af28faf48817ccc766cb5ae8331f22745bcd4505eef44a86d), y: Fq(0x040e549bea1b95fc2879f26d3d519dea281629c7e9ec9cc3a2cb437b5102a2cb8c1ca0d9e6e5c2be05a2447f02fb957c), infinity: false }
zouyudi alpha_power:Fr(0x420473cf58dc43ee3c4eb7b0958cb16c05d730a6cec0a6b23533c12dc21e2e06)
zouyudi g1_power:G1Affine { x: Fq(0x0c7b76fd7878fa81257eed5366755d2694061444e91906f946d7547684c11de46af885c181f58e399cff2071fc572a2c), y: Fq(0x19c31696549ead61867ec7ae15c4fd3f7872a21247323e04bd6e777c6a066b875d66a700a454532b0cf7b52f2319a6f9), infinity: false }
zouyudi alpha_power:Fr(0x4b6041ce28f6a592ddbfa94ce392874bbe643d576ebf0f41136bc7c3d072d00a)
zouyudi g1_power:G1Affine { x: Fq(0x06ce08ab6142da0ee7b4f56cc6aa00ee12c56aca1c74e592a27366549d6f10a762f7600244635208de0aba94f7dc1eb8), y: Fq(0x176e53894df072b1c6af745cc069d289bd2e72116f155add8a651e92ab3bb248f64e5cbefd5489c2966392775697bd18), infinity: false }
zouyudi alpha_power:Fr(0x44fba9a63d9240738c0820c346a135345881bb851ef41aaf56e138a209099188)
zouyudi g1_power:G1Affine { x: Fq(0x03249e85f796004385721a8fb3954e8741590ad96ed8eda61c513b7ca9e569d9c4ca1455b7cf41691f460da9cbc5a1fa), y: Fq(0x0b09d3086c7e953c36fae391bae607d44f3068c80e8fd52bbd95819de3687186592cd8adabc95b6617c6af5c0854d1cd), infinity: false }
zouyudi alpha_power:Fr(0x312e7f4ce42b19172a6ca49a002068e275b22bc07a6c2159cfe267b140ff6616)
zouyudi g1_power:G1Affine { x: Fq(0x1118ea263e2942f5fb4ac0143d348c6f48d9b17c7b9c460992b50e3aad892eb4f89a23d3d05b2bcd00c781f66a2447a9), y: Fq(0x144308cf3622b856d7cefc62641baa01432fd426a354e601b8f09606a432f2bd6c26e5a6fb9b96aa31ddeae154f7123f), infinity: false }
zouyudi alpha_power:Fr(0x398edca2cc10069a98cfe724d0e4d268a7c159d767cf769ffce05e12d2d27818)
zouyudi g1_power:G1Affine { x: Fq(0x133e87a933c86c9ce06916e90439740d5f5d078bbe6af04a02eaf739bddb9af014daa212751bae28b31bda7e026f5ac7), y: Fq(0x0635dfb810a2ed0531a68e5e3c040342fd37ce201a53f588c8ca29ce23f2c354f2d58da4d56da8d308885e29aa3b58e8), infinity: false }
zouyudi alpha_power:Fr(0x34f012ea3f06227bb1631c9c96ce71f1bb9d1347b7b82392f07406a6fa0bb327)
zouyudi g1_power:G1Affine { x: Fq(0x10926badcea4c03842de90394a0912911b0dffc24e7ed4348c34dbff11bb0cc8e342bccf139f860b01cdfbf00409d691), y: Fq(0x002df711e8de4dfbb0a35025663047a24542a33ae35c97872adaa4a710088496c2ec049ad53c86b440c562ccaf982b68), infinity: false }
zouyudi alpha_power:Fr(0x68fedeffa6be5dd066539d1f88ee82e7547190222b491dbea0715780e1c44897)
zouyudi g1_power:G1Affine { x: Fq(0x12c0b2d0b58ebb4128104c6edd8a88b7968650da3a1bad968e7f32aeaad3165496928b72e5ccbba101ce1a981c2ba61c), y: Fq(0x01bdbf4ccee5ecd53b8eccfc5cae1f17aac62aeffb05d3e4e940a58ac32157f1189b41f18a19488fac260cb4168e7015), infinity: false }
zouyudi alpha_power:Fr(0x6e9941d817e53229828be6fe7feceadd360302744a597cd0b79ca2b6f3312125)
zouyudi g1_power:G1Affine { x: Fq(0x04dc13a65c4eeff8a29e0644ebae1c80a638a282a1222b8b2233a5a36983f785e600b8d911b11979a938f7f4dae691a6), y: Fq(0x1530b5c7a11a1da31685c6ad7b1dd9ab7e20333d0f3f53b840e0f1662888a0bd434c99f747ffbd7182fe14c9a4caec0a), infinity: false }
zouyudi alpha_power:Fr(0x57094e27fcf86b77398edccc4c01451af179c2bb0b3ec82a9df92d2caa3cc015)
zouyudi g1_power:G1Affine { x: Fq(0x08ac8bd7f7537d834b6169cf2e8cfa9b82c5de32648bb73603dbae5990928f2e3b6ac96029c9578ae0d150c81a8ff838), y: Fq(0x11110702c85d06e5bf49bf99f205efc4711054e0eb53f5765631e51f9028c3786f6d6529477d129ac5d849d7a81304eb), infinity: false }
zouyudi alpha_power:Fr(0x003c2abeb3b07662e5f74a425480ec30bcbcf72f0d807fd88c80bdf8055808f2)
zouyudi g1_power:G1Affine { x: Fq(0x151a8c4cc8cd1c3982e21fd9e0414f29631c7317b633c4d4536eb9f229dc8c47b48b52485b4ba58f7b5fb81887112afb), y: Fq(0x0f44c48426172d9400bdf6b5e77324ab87cc6d8838b76bba887efef1ee38ef3c8348f253b378b75e4f3f771045c1d438), infinity: false }
zouyudi alpha_power:Fr(0x29e17af9825f9f1be10e3686c2a7eed52fff948971c9f00dea6e639cb9232b92)
zouyudi g1_power:G1Affine { x: Fq(0x19d2276f826a3b8a4c9d7f2e1437f0e33c840695e6145e2c7fbc6f68058314c913df46bc4e241b02deed383d0506eb07), y: Fq(0x116178fac0d354255f0ab171dc820941714030dbb8c909ac10b357a66215910918e649248eff18465b7a90f186b2a659), infinity: false }
Commiting to the following 16 strings
this is message number 0
this is message number 1
this is message number 2
this is message number 3
this is message number 4
this is message number 5
this is message number 6
this is message number 7
this is message number 8
this is message number 9
this is message number 10
this is message number 11
this is message number 12
this is message number 13
this is message number 14
this is message number 15

Commitment:  [00, aa, c4, 32, 35, 05, c1, cc, 60, b0, 9f, 4a, 6d, 08, 05, 73, 1a, 59, de, 52, cd, 18, 4d, bf, 90, 51,93, 22, 7b, 6b, 9a, 90, 87, 07, f7, 70, a8, 54, 76, e4, d1, 2c, 69, 78, c5, 87, 3a, 9b, 23]

Old Proof 0: [00, 8a, 8b, bc, 7f, c6, b1, d5, f2, 75, ce, 08, f8, 8a, 50, 04, 7b, 5d, 14, 5e, 73, b1, d0, f7, e2, db,74, ee, 42, c9, 4e, 4c, 91, 62, 70, ca, 45, 13, 89, 2d, 84, 96, 34, c0, 5a, 2f, cb, 9f, 09]
Old Proof 1: [00, a5, e7, 5a, 2f, ce, 8f, 63, 31, 20, 05, 72, 9e, 3d, a3, b5, cf, a3, 6a, f3, 3b, 1d, bd, a2, 29, ef,3c, 88, 11, 51, ba, 60, 61, 24, b6, 39, ac, 69, 66, 7d, 5d, 8b, da, f3, 63, ad, 46, d0, 81]
Old Proof 2: [00, 80, 1e, 2a, d1, 1e, 19, 4b, f3, 3a, 02, 20, fd, e7, 3e, 41, 44, bc, 86, 2d, f2, 22, f6, df, 30, 5b,a2, e9, 93, b6, 78, 01, c9, 77, 96, e0, d3, 2c, 45, a6, 8c, ac, df, d6, 99, 14, ca, a8, 40]
Old Proof 3: [00, b7, 9a, 92, 73, 2a, ae, c9, cb, e3, 3b, 2f, d2, ba, a4, 9c, a5, cb, 69, 45, f2, 48, 0f, d5, ef, f6,0f, fb, 65, 48, ef, 8d, 1f, 4a, 91, 1d, 7f, 9f, 21, 24, f4, 41, f8, 54, b6, 79, 21, 11, ab]
Old Proof 4: [00, 8a, 10, bc, 95, 03, b9, 59, d7, 02, 67, 19, a5, 5c, 6a, 1f, 34, 82, 66, 70, 7c, 21, b3, 4c, df, 1a,fc, 0c, f9, e1, 18, 05, bd, c7, 1a, 4a, e5, c1, 6c, 5f, b9, 0f, da, cc, f8, 5b, 11, cc, 79]
Old Proof 5: [00, 8d, 11, dc, 45, ad, df, ad, 2f, 21, 70, 0d, 49, e8, 62, f0, 2a, 06, ee, 1f, 29, c7, d2, 42, 9f, ab,5e, 88, 78, 9e, 92, fa, f6, 88, 81, cb, 6a, 30, 3b, 21, 3b, 1a, a9, 60, 1a, 66, 4d, c0, 6b]
Old Proof 6: [00, 92, 60, 8b, 1a, d5, e9, 1a, 0a, 07, 0b, 4e, db, b1, 29, ca, 24, 63, c1, 93, 52, 71, 2a, dd, 68, 36,55, e9, 46, e4, 82, 06, f8, 5f, fe, 2e, 22, 91, f4, 89, 77, 60, 41, 69, 41, a5, 95, 8f, c2]
Old Proof 7: [00, ab, d6, 1d, e1, 99, 68, 6e, e5, 16, ea, a7, 92, 2e, 0e, 61, 7e, ef, ce, 06, 46, bf, 37, 80, 6b, bd,7f, 11, 4a, f5, 72, 71, b5, f4, 11, 6b, db, 7d, 85, 49, 57, a4, 68, 14, 75, 7e, e7, 0d, ec]
Old Proof 8: [00, 88, 04, 65, 88, b9, e5, 42, b5, 38, 46, da, b6, f3, 0b, 1d, e5, 69, 05, 93, 0b, 3d, e6, 27, 66, f9,91, df, a3, e4, f6, cf, 4e, 01, 4f, 28, cb, ff, 96, b1, 2a, 5a, 48, 89, 67, cd, ec, ae, 1b]
Old Proof 9: [00, b0, 7a, e2, 18, 26, ca, 6a, 26, a7, 37, 49, 9a, 0e, f9, b6, 92, 49, 18, e6, fe, dc, 90, 9f, 12, 62,60, 5e, e4, a3, 14, 26, 9c, 2f, 6f, 86, 61, 64, b0, 1a, c6, d2, 8f, d0, 2d, 47, 37, 1a, 4c]
Old Proof 10: [00, 92, ef, 66, a2, 38, e5, 1b, 95, 94, f9, 31, b4, 1d, b7, 11, 19, 85, 9c, b6, f6, ea, d7, e9, 09, 55, cb, 99, f7, 18, 61, 84, a2, a3, f0, 41, bf, 1f, 08, 86, c8, 6d, 9d, 8e, 4e, 45, 28, 9b, c0]
Old Proof 11: [00, 88, 4d, d5, 79, 6a, ca, 2d, 2b, f7, 85, 68, 03, 32, 58, f6, 97, cc, d0, 59, f4, a3, 2d, 1c, eb, 4c, 5c, a4, 63, 39, 5d, 37, b3, 24, b0, ad, a6, 99, f4, 72, bc, a7, 37, 1e, 3e, 60, ea, 09, ac]
Old Proof 12: [00, b7, 38, 05, 51, aa, a7, 6b, 42, 5a, 1b, 2e, 2c, 4c, 44, 71, b5, e5, 20, 13, 1f, 8a, a2, 64, ef, 8b, d0, 1d, b8, d7, e0, 12, e4, 00, b7, 4f, 6e, 62, db, b2, 9b, e0, d0, 7a, ff, 99, 95, c5, 13]
Old Proof 13: [00, 99, 38, 00, ce, 30, ef, 2c, ba, b2, 62, e1, 64, 49, 87, e5, 25, c5, ae, e3, 7b, 10, 27, 79, 7f, cf, 38, fa, 5c, db, 73, 43, da, 6e, cd, 38, 5a, 6c, 96, 2f, 4b, af, 86, 68, ff, c2, 6e, 4e, f2]
Old Proof 14: [00, 80, b1, 57, 6b, 75, 34, b4, 8e, 99, 89, c3, f1, e8, 2e, 94, b1, 50, 2b, 6a, 4f, 74, 81, 2a, ee, 1a, c9, 9d, fb, cf, 8e, e3, ec, 45, 30, 96, 56, d5, cb, eb, f1, 01, b0, d6, 9e, 55, b2, 56, e6]
Old Proof 15: [00, 98, 3d, 1c, ac, bd, 2f, fe, 9c, 51, 36, 82, 1c, 59, 25, 2f, f3, 71, 10, 1c, f6, ac, 85, 03, 24, 1e, 21, 55, 7c, e8, 54, 40, cf, d9, 8d, 98, 5c, 1f, 01, 56, 83, a2, 36, 67, 3a, 1e, e1, 7c, c9]

Updating string 8 to "this is new message number 8"

New Proof 0: [00, 84, 73, 04, 01, 7a, 39, 2d, fd, 18, e6, 1b, 0e, c0, f0, 09, 41, bc, 5a, 6b, 97, 27, 65, 8b, 30, 0a,26, bb, d4, 09, ef, ce, fb, 81, 71, 0b, bd, eb, 38, 6f, af, 69, 33, 48, 90, 33, 58, 57, 6e]
New Proof 1: [00, ae, ca, df, 0d, f7, 27, 62, fe, ff, 41, 41, c1, 13, 86, f6, 89, 0d, 75, 48, 85, b7, d9, 41, f0, 9b,12, a2, 70, 17, f0, e6, 1f, c5, 7e, 06, f7, c3, 50, c7, c1, c2, 18, 3d, b2, 9d, 8a, ed, 1c]
New Proof 2: [00, b1, 84, 98, e5, f2, 7e, 73, 3d, 58, ed, fc, 04, fc, 7e, 0a, 45, cd, 80, c6, 99, e0, 14, a6, d2, 17,3d, c3, 07, 4a, 6c, 53, 34, bc, 4d, 80, 64, d9, f3, 46, 12, f4, 50, 90, 83, 36, 8e, bc, 2c]
New Proof 3: [00, 86, 49, b1, 70, 4c, f2, c1, e1, 21, 7f, de, e5, 52, a0, 8a, 6c, 95, 18, 53, 44, 35, b8, 2a, 9e, f1,36, ec, a3, db, b0, 16, 05, 90, db, e7, 13, 96, 4a, 21, 09, 1b, f4, 5c, f7, 3f, 67, 82, ed]
New Proof 4: [00, a5, 91, 54, c0, 3e, 1d, 09, 57, ba, b1, 41, d7, ff, 37, f4, 09, 5c, 17, eb, 29, 00, a8, a7, 12, fd,99, d8, d7, 7a, 50, f9, a0, 0e, 9d, cb, 7e, ae, c1, 89, 88, d3, bf, 1d, 28, aa, d6, cf, 62]
New Proof 5: [00, 96, 0c, 8e, 70, ae, e6, bc, 22, f3, fd, 02, 2f, 02, 00, fa, ae, 3d, 42, 9f, 3a, 22, b6, 44, c7, 29,03, a9, bc, 48, 5e, b8, cd, a4, 2d, b0, d2, f7, 2e, 2f, b2, 1f, d0, d6, 63, ba, aa, 6e, 29]
New Proof 6: [00, a2, c5, ec, 5d, b1, 93, 12, 97, 69, fa, c1, 30, 19, da, 5f, 9e, 92, 9a, 0c, 8e, 41, 6e, f4, 3a, f2,ce, c4, fc, 3e, ff, 4b, 55, 3b, 3d, 3e, 6f, 27, 9f, 80, 6f, 0f, f4, d7, 38, c9, 4e, 67, 19]
New Proof 7: [00, 93, 10, 2d, 0b, 72, 38, 58, 50, 8a, d0, c9, 6a, fb, f7, 5e, ef, 14, 51, 86, ce, 7a, a5, 57, 48, 5a,47, 89, 08, 5a, a1, f4, 36, 60, cf, 7d, 27, bb, 20, 33, 33, b0, 9d, 43, 12, 04, bf, a4, 2b]
New Proof 8: [00, 88, 04, 65, 88, b9, e5, 42, b5, 38, 46, da, b6, f3, 0b, 1d, e5, 69, 05, 93, 0b, 3d, e6, 27, 66, f9,91, df, a3, e4, f6, cf, 4e, 01, 4f, 28, cb, ff, 96, b1, 2a, 5a, 48, 89, 67, cd, ec, ae, 1b]
New Proof 9: [00, 80, fe, 01, 3a, 7f, 58, f8, 6f, 7a, 3f, f8, e3, b8, f4, fe, 6c, 4c, 7e, e0, 45, 98, 45, 65, 10, bd,d3, a6, c4, 99, b9, 6e, 8e, de, f1, 86, 94, 28, ce, f0, 38, 30, 5c, 25, f5, 90, 38, 08, 5f]
New Proof 10: [00, 8a, 1c, fa, 02, 03, e1, aa, 1e, 96, 52, 5b, df, 1d, 40, b6, 37, 1f, 55, 6a, 22, 0e, bd, 64, ad, de, b2, bc, b0, 83, 41, a4, 3d, 1a, 71, e9, d7, 57, cf, ac, 26, 98, 96, d5, aa, 72, 01, e0, c2]
New Proof 11: [00, 92, ea, a8, c2, 33, ff, 53, f1, 2f, de, eb, 91, b8, a2, bc, 9f, 66, b0, 39, a9, d9, 5b, 63, 1f, 73, 49, 59, b9, 7d, 0b, 86, 33, 77, 0c, 5a, e2, 0e, 8a, 0f, ba, ee, 62, f8, 5c, 4d, 58, 62, 6a]
New Proof 12: [00, b3, d8, 50, 3f, f6, 65, 84, 0f, e6, 92, 2e, b4, 75, 79, ca, bf, 63, d1, 57, a6, 03, 59, bd, f5, a2, e7, 9e, 13, d0, 1e, 2b, d5, e7, 43, ca, 27, 45, ae, cd, f6, 16, d1, f4, 6f, 46, 7b, 9a, 6f]
New Proof 13: [00, 8b, 18, 66, e4, 31, e7, 82, 53, 20, 1e, a8, 6f, 5b, 45, 60, 11, ee, 7c, b8, 24, 7a, c9, c7, 6f, 73, 8e, 72, 0f, c3, 95, e5, a1, 95, 01, 12, 29, 21, 72, c7, c3, 58, 65, a6, c3, 49, c6, 07, 2d]
New Proof 14: [00, 84, bd, 3a, 13, c6, 9c, 21, db, 1e, e3, 40, 9b, 1e, 63, c9, cc, 2b, ec, 51, 4b, 10, ca, 20, c1, e2, f9, 17, cc, d7, 0d, ad, 0e, 73, a8, 46, eb, 37, 48, 40, ff, b2, bc, 27, 0c, ea, 42, 95, 83]
New Proof 15: [00, b7, c7, 54, 7f, 17, 8e, e9, 90, ba, 32, 9b, 2b, 0b, f6, 03, 5b, d0, 44, c1, 64, 55, 41, 16, b7, 74, 9f, ea, 06, 8d, 59, e7, 2e, a0, 69, dc, eb, 4f, fe, 42, 2a, c7, 77, d2, b1, 83, 00, ce, 4a]

Ni hao, Algorand

对应的Sage脚本验证为:

sage: 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffe
....: b153ffffb9feffffffffaaab
4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787
sage: 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001
52435875175126190479447740508185965837690552500527637822603658699938581184513
sage: r=0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001
sage: primitive_root(r)
7
sage: q=0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabff
....: feb153ffffb9feffffffffaaab
sage: E=EllipticCurve(GF(q),[0,4])
sage: E
Elliptic Curve defined by y^2 = x^3 + 4 over Finite Field of size 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787
sage: E.order()
4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129030796414117214202539

sage:
sage: x1=36854167537133870167810883151830777579616207957825464098945783786886075
....: 92378376318836054947676345821548104185464507
sage: y1=13395065449444764730204713799419212215849338759383496204265437364165114
....: 23956333506472724655353366534992391756441569
sage: g1=E(x1,y1)
sage: g1
(3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 : 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569 : 1)
sage: g1.order()
52435875175126190479447740508185965837690552500527637822603658699938581184513
sage: r==E.order()
False
sage: r
52435875175126190479447740508185965837690552500527637822603658699938581184513
sage: n=E.order()
sage: n
4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129030796414117214202539
sage: n/r
76329603384216526031706109802092473003
sage: factor(n)
3 * 11^2 * 10177^2 * 859267^2 * 52437899^2 * 52435875175126190479447740508185965837690552500527637822603658699938581184513
sage: alpha=0x03530f615aa764a263544084485bf91a014712497bc9ba54f11114c3b3e45f08
sage: alpha
1503693002983401415113014640808306074223599471496430042206067283810050137864
sage: alpha*g1
(1033654949785203021207026044129189331069127518790367648505266630501389934793504305044295310538037400252804790110918 : 89832893542883859029728348878945587183573275246553105705168502974169963454784039491043776459113083475851957867623 : 1)
sage: 0x06b73e205fc1403b0ea47f87cd9d1752814bfcfa43f37e64e5a4267e7947890678319eeb
....: aa659bfbbb07f0b885924ac6
1033654949785203021207026044129189331069127518790367648505266630501389934793504305044295310538037400252804790110918
sage: 0x00956a7c3cbbfea2a46544aba6dd27989a2c8dcd6c9bed54416c158c0c3c74cbdd045171
....: d85527226a9c854523499467
89832893542883859029728348878945587183573275246553105705168502974169963454784039491043776459113083475851957867623
sage: alpha^2*g1
(317530896942699193401993928133193212893828000826560927504886177222118619833512039417536313380970329724770472758665 : 3784076042772903410141691002998593408675975121295218085246014556053129360108039689761174879948682644693003357197004 : 1)
sage: 0x02102361767f5aa63ca59d03f9985352223962a9bf72a1aaf540cdb1ef89a822c7a9ab5d
....: 77cb378112c9bb0519150d89
317530896942699193401993928133193212893828000826560927504886177222118619833512039417536313380970329724770472758665
sage: 0x1895ec61d5a8386f61e698c52f19991a3df095fc806fde62912822510e29688ad14a332f
....: b3866e416b2cae3b063112cc
3784076042772903410141691002998593408675975121295218085246014556053129360108039689761174879948682644693003357197004
sage: alpha^2
2261092647221239657091752652260266674954220400406356578851084432298038859086196117355910565756002857385403067247496885268714372239001032877485406482496
sage: n
4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129030796414117214202539
sage: r
52435875175126190479447740508185965837690552500527637822603658699938581184513
sage: n*g1
(0 : 1 : 0)
sage: r*g1
(0 : 1 : 0)
sage: factor(r-1)
2^32 * 3 * 11 * 19 * 10177 * 125527 * 859267 * 906349^2 * 2508409 * 2529403 * 52437899 * 254760293^2
sage: 2^32
4294967296
sage: 2^16
65536

sage: r
52435875175126190479447740508185965837690552500527637822603658699938581184513
sage: power_mod(alpha,1,r)*g1
(1033654949785203021207026044129189331069127518790367648505266630501389934793504305044295310538037400252804790110918 : 89832893542883859029728348878945587183573275246553105705168502974169963454784039491043776459113083475851957867623 : 1)
sage: power_mod(alpha,65536,r)*g1
(2929581191141486328429440551007643252814074518455193727550712002326468324879784506948162616659764036885075131959131 : 1833309532402667846915061345496965443062083588117682951357230429927267422538646169998646858646199052204360375863032 : 1)
sage: power_mod(alpha,65537,r)*g1
(853565093434707070897210410773523905749086743143914719869029110470270375947122945706367973698433903895259486740180 : 3713832379110814907791946740505740797159596171420901812951617661121822875856088494720913309256289030430931653551227 : 1)
sage:

3.1 mod.rs

除param模块和pointproofs_groups模块外,其它模块均只对crate内public。有如下结构体定义:

  • Prove key:
/// Structure for porver parameters.
#[derive(Clone, Debug)]
pub struct ProverParams {
    pub(crate) ciphersuite: Ciphersuite,
    pub(crate) n: usize,
    generators: Vec<PointproofsG1Affine>,
    pp_len: usize,
    precomp: Vec<PointproofsG1Affine>,
}
  • Verify key:
/// Structure for verifier parameters.
#[derive(Clone, Debug)]
pub struct VerifierParams {
    pub(crate) ciphersuite: Ciphersuite,
    pub(crate) n: usize,
    generators: Vec<PointproofsG2Affine>,
    pp_len: usize,
    precomp: Vec<PointproofsG2Affine>,
    gt_elt: Fq12,
}
  • Commitment:
/// Structure to hold a commitment.
#[derive(Clone, Debug, PartialEq)]
pub struct Commitment {
    pub(crate) ciphersuite: Ciphersuite,
    pub(crate) commit: PointproofsG1,
}
  • Proof:
/// Structure to hold a proof.
#[derive(Clone, Debug, PartialEq)]
pub struct Proof {
    pub(crate) ciphersuite: Ciphersuite,
    pub(crate) proof: PointproofsG1,
}

3.2 err.rs

err.rs中主要定义的是一系列错误码,用于Pointproofs crate内部使用。pub(crate) 表示该变量在本crate内public可见,但对除本crate外的其它crates中均不可见。

//! this file is part of the pointproofs.
//! It defines a list of error messages.

pub(crate) const ERR_SEED_TOO_SHORT: &str = "The seed length is too short";
pub(crate) const ERR_CIPHERSUITE: &str = "Invalid ciphersuite ID";
pub(crate) const ERR_COMPRESS: &str = "Only support compress=true mode";
pub(crate) const ERR_INVALID_VALUE: &str = "Invalid number of values";
pub(crate) const ERR_INVALID_INDEX: &str = "Invalid index";
pub(crate) const ERR_DUPLICATED_INDEX: &str = "Duplicated index";
pub(crate) const ERR_INDEX_PROOF_NOT_MATCH: &str = "Length of index and proof sets do not match";
pub(crate) const ERR_X_COM_SIZE: &str =
    "Invalid sizes for commit, proof, or values for cross commit";
pub(crate) const ERR_MAX_N: &str = "N is too large";
pub(crate) const ERR_PARAM: &str = "The input parameter is not correct";
pub(crate) const ERR_INDEX_VALUE_NOT_MATCH: &str = "Length of index and value sets do not match";

3.3 hash_to_field_pointproofs.rs

hash_to_field_pointproofs.rs中,定义了一系列hash_to_*函数。其中的hash_to_field_*函数执行效率要高于https://github.com/algorand/pairing-plus中的bls::hash_to_field函数。详细的接口说明可参见SPEC.md
主要的接口函数有:

  • hash_to_field_pointproofs:用于将输入的string通过SHA512后转换为非零的field element。
// hash_to_field_pointproofs use SHA 512 to hash a blob into a non-zero field element
pub fn hash_to_field_pointproofs<Blob: AsRef<[u8]>>(input: Blob) -> Fr

该函数具体的实现步骤为:
a.hash input into 64 bytes array data
b.convert data into a 512 bits integer a = os2ip(data)
c.t = a mod r where r is the group order
d.if t == 0 return 1, else return t

  • hash_to_tj_fr :计算的是AggregateAcross中的 t j = H ( j , { C j , S j , m j [ S j ] } j [ l ] ) t_j’=H’(j,\{C_j,S_j,\vec{m}_j[S_j]\}_{j\in[l]})
pub(crate) fn hash_to_tj_fr<Blob: AsRef<[u8]>>(
    commits: &[Commitment],
    set: &[Vec<usize>],
    value_sub_vector: &[Vec<Blob>],
    n: usize,
) -> Result<Vec<Fr>, String>

基本的思路为:当aggregate的commitment数为1时(即 l = 1 |l|=1 时),设置 t j = 1 t_j’=1
Input: a list of k commitments
Input: a list of k * x indices, for which we need to generate t_j
Input: Value: a list of k * x messages that is committed to
Output: a list of k field elements
Error: ciphersuite id not supported
Error: lengths do no match
Steps:
a.tmp = {C | S | m[S]} for i \in [0 .. commit.len-1]
b.digest = SHA512(tmp)
c.for 0 <= i < commits.len(), res[i] = hash_to_field_pointproofs(i, digest)
注意:this procedure is a bit different from the paper, where no intermediate digest is generated. We pre-hash the data into a digest to improve efficiency.

  • hash_to_ti_fr:计算的是AggregateAcross中的 t j , i = H ( i , C j , S j , m j [ S j ] ) t_{j,i}=H(i,C_j,S_j,\vec{m}_j[S_j]) 或者same-commitment aggregte中的 t i = H ( i , C , S , m [ S ] ) t_i=H(i,C,S,\vec{m}[S])
pub(crate) fn hash_to_ti_fr<Blob: AsRef<[u8]>>(
    commit: &Commitment,
    set: &[usize],
    value_sub_vector: &[Blob],
    n: usize,
) -> Result<Vec<Fr>, String>

总体的思路为:当aggregate后open的总位置数为1(即 S = 1 |S|=1 )时,设置 t i = 1 t_i=1 t j , i = 1 t_{j,i}=1
Input: the commitment
Input: a list of indices, for which we need to generate t_i
Input: Value: the messages that is committed to
Output: a list of field elements
Error: ciphersuite id not supported
Error: lengths do no match
Steps:
a.digest = SHA512(C | S | m[S])
b.for 0 <= i < set.len(), res[i] = hash_to_field_pointproofs(i, digest)
注意:this procedure is a bit different from the paper, where no intermediate digest is generated. We pre-hash the data into a digest to improve efficiency.

3.4 param.rs

param.rs中,pub函数有:

  • check_ciphersuite:目前仅支持csid=0u8
const VALID_CIPHERSUITE: [u8; 1] = [0u8];
/// Ciphersuite ID is a wrapper of u8.
pub type Ciphersuite = u8;

/// Checks if csid is supported. Currently only support csid = 0.
pub fn check_ciphersuite(csid: Ciphersuite) -> bool {
    VALID_CIPHERSUITE.contains(&csid)
}
  • paramgen_from_seed:根据seed和csid生成public parameters——Prove key和Verify key。(该函数仅在测试环境下调用。实际生产部署时,应使用单独的https://github.com/algorand/pointproofs-paramgen crate 来生成Prove key和Verify key,以保证public parameters的安全性。)
    1)要求seed长度不低于32,否则报错ERR_SEED_TOO_SHORT
    2)会check_ciphersuite,否则报错ERR_CIPHERSUITE
    3) 0 < n < = 65536 0<n<=65536 ,否则报错ERR_MAX_N
    4)将seed通过hash_to_field_pointproofs映射为 α \alpha 值。
    5)计算Prove key: g 1 α , , g 1 α N , g 1 α N + 2 , , g 1 α 2 N g_1^{\alpha},\cdots,g_1^{\alpha^N},g_1^{\alpha^{N+2}},\cdots,g_1^{\alpha^{2N}} ;计算Verify key: g 2 α , , g 2 α N ; g T α N + 1 g_2^{\alpha},\cdots,g_2^{\alpha^N};g_T^{\alpha^{N+1}}

  • precomp_256:预计算,对于Prove和Verify都有,当 n < = 1024 n<=1024 时,可明显提升性能。

/// pre-process the public parameters with precomputation value set to 256
    pub fn precomp_256(&mut self) {
        let twice_n = self.generators.len();
        self.precomp = vec![PointproofsG1Affine::zero(); 256 * twice_n];
        for i in 0..twice_n {
            self.generators[i].precomp_256(&mut self.precomp[i * 256..(i + 1) * 256]);
        }
        self.pp_len = self.n * 512;
    }

// pre[i] becomes (\sum_{b such that bth bit of i is 1} 2^{32i}) * self for i in 0..25
            fn precomp_256(&self, pre: &mut [Self]) {
                // TODO: check if pre has the right length?
                // TODO: possible optimization: convert 256 points into affine jointly by doing a single inversion, rather than separately
                // In fact, this function gets called multiple times, and the conversions to affine could be cheaper if done together

                pre[0] = Self::zero();
                let mut piece_length = 1;
                let mut power_of_2_times_self = self.into_projective(); // power_of_2_times_self = 2^{32*piece_length} * self
                while piece_length <= 128 {
                    // operate in pieces of length 1, 2, 4, 8, 16, 32, 64, 128
                    pre[piece_length] = power_of_2_times_self.into_affine();
                    for i in 1..piece_length {
                        pre[i + piece_length] = pre[i];
                        let mut temp = pre[i].into_projective();
                        temp.add_assign_mixed(&pre[piece_length]);
                        pre[i + piece_length] = temp.into_affine();
                    }
                    if piece_length < 128 {
                        for _ in 0..32 {
                            power_of_2_times_self.double();
                        }
                    }
                    piece_length *= 2;
                }
            }

3.5 commit.rs

  • new:对vector $\vec{m}$ 生成commitment $C$,基本思路为:
    $\vec{m}$中的每一个值都通过hash_to_field_repr_pointproofs经Sha512再映射为scalar field值,计算 C = i = 1 n p p [ i ] m i C=\prod_{i=1}^{n}pp[i]^{m_i} (通过pp_sum_of_prod_helper计算)。

  • update:更新单个位置的commitment。

pub fn update<Blob: AsRef<[u8]>>(
      &mut self,
      prover_params: &ProverParams,
      changed_index: usize,
      value_before: Blob,
      value_after: Blob,
  ) -> Result<(), String>
Input: self, a Commitment
Input: a ProverParam
Input: the index to be updated
Input: the original value
Input: the value updated to
Output: mutate self to the updated commit
Error: ciphersuite is not supported
Error: self.ciphersuite does not match prover_params.ciphersuite
Error: index out of range
Steps:
a.hash value_before into old_scalar
b.hash value_after into new_scalar
c.commit = commit * prover_params,generators[changed_index]^(new_scalar-old_scalar)
  • batch_update:更新多个位置的commitment。
pub fn batch_update<Blob: AsRef<[u8]>>(
    &mut self,
    prover_params: &ProverParams,
    changed_index: &[usize],
    value_before: &[Blob],
    value_after: &[Blob],
) -> Result<(), String>
Input: self, a Commitment
Input: a ProverParam
Input: a list of indices to be updated
Input: a list of original values
Input: a list of values updated to
Output: mutate self to the updated commit
Error: ciphersuite is not supported
Error: self.ciphersuite does not match prover_params.ciphersuite
Error: index out of range
Error: # of changed_index, value_before or value_after do not match
Steps:
a.for i in indices
b.hash value_before[i]s into old_scalar[i]
c.hash value_after[i]s into new_scalar[i]
d.commit = commit * \prod prover_params.generators[i]^(new_scalar[i]-old_scalar[i]) for i in indices

3.6 misc.rs

  • pp_sum_of_prod_helper:用于计算 C = i = 1 n p p [ i ] m i C=\prod_{i=1}^{n}pp[i]^{m_i}
/// This helper computes the sum of product:
///     \sum_{i=start}^{end-1}
///         param.generator[i]^scarlar_u64[i]
/// It tries to use pre-computed data when possible.
/// It assumes end - start = n; and the lengths matches.
/// It doesnot perform any sanity checks of those conditions.
pub(crate) fn pp_sum_of_prod_helper(
    prover_params: &ProverParams,
    scalars_u64: &[&[u64; 4]],
    start: usize,
    end: usize,
) -> PointproofsG1 {
    // the second condition `n <= 1024` comes from benchmarking
    // pre-computation is faster only when the #basis is <1024
    if prover_params.precomp.len() == 512 * prover_params.n && prover_params.n <= 1024 {
        PointproofsG1Affine::sum_of_products_precomp_256(
            &prover_params.generators[start..end],
            &scalars_u64,
            &prover_params.precomp[start * 256..end * 256],
        )
    } else {
        PointproofsG1Affine::sum_of_products(&prover_params.generators[start..end], &scalars_u64)
    }
}

sum_of_products中使用了pippenger算法。
sum_of_products_precomp_256中使用了public parameter中precompute的信息。(// pre[i] becomes (\sum_{b such that bth bit of i is 1} 2^{32i}) * self for i in 0…25)

fn sum_of_products(points: &[Self], scalars: &[&[u64; 4]]) -> $projective {
                // TODO: figure out what to do if the lengths of the two input slices don't match
                // For now, take the minimum
                let num_components = if points.len() < scalars.len() {
                    points.len()
                } else {
                    scalars.len()
                };
                Self::sum_of_products_pippinger(
                    points,
                    scalars,
                    Self::find_pippinger_window(num_components),
                )
            }


// Expects pre[j*256+i] = (\sum_{b such that bth bit of i is 1} 2^{32i}) * self[j] for i in 0..256 and for each j
            // pre can be obtained by calling precomp_256
            fn sum_of_products_precomp_256(
                points: &[Self],
                scalars: &[&[u64; 4]],
                pre: &[Self],
            ) -> $projective {
                // TODO: we may decide we should clear memory, such as the old self
                // and the precomp array.
                // For now, none of the other functions do that, either.
                // TODO: figure out what to do if the lengths of the two input slices don't match
                // For now, take the minimum
                let mut res = Self::Projective::zero();
                let num_components = if points.len() < scalars.len() {
                    points.len()
                } else {
                    scalars.len()
                };

                // Interleaved window technique: deal with each of the 8 32-bit chunks words of each scalar in parallel

                // TODO: understand how this large table will affect performance due to caching

                for i in (0..32).rev() {
                    res.double();
                    for j in 0..num_components {
                        let mut byte = (scalars[j][3] >> (i + 25)) & 128;
                        byte |= ((scalars[j][3] >> i) << 6) & 64; // can't shift by i-6 because it can be negative
                        byte |= (scalars[j][2] >> (i + 27)) & 32;
                        byte |= ((scalars[j][2] >> i) << 4) & 16;
                        byte |= (scalars[j][1] >> (i + 29)) & 8;
                        byte |= ((scalars[j][1] >> i) << 2) & 4;
                        byte |= (scalars[j][0] >> (i + 31)) & 2;
                        byte |= (scalars[j][0] >> i) & 1;
                        res.add_assign_mixed(&pre[(j << 8) + byte as usize]);
                    }
                }
                res
            }
        }

3.7 serdes.rs

  • serializedeserialize 用于对Commitment/Proof/ProverParams/VerifierParams进行序列化和反序列化。会调用pairing-plus crate中的serdes.rs内相关接口。
fn serialize<W: Write>(&self, writer: &mut W, compressed: bool) -> Result<()>

Input: a Commitment
Input: a writable buffer
Input: a flag whether to compress the group point or not; must be true
Output: none
Error: compression is false
Error: ciphersuite is not supported
Error: serialization fails
Steps: convert | ciphersuite | commit | to bytes

fn deserialize<R: Read>(reader: &mut R, compressed: bool) -> Result<Self>

Input: a readeble buffer
Input: a flag whether the group elements are expected to be compressed or not; must be true
Output: a Commitment
Error: compression is false
Error: ciphersuite is not supported
Error: encoded buffer has a different compressness than specified
Error: deserialization fails
Steps: convert bytes to | ciphersuite | commit |

3.8 pointproofs_groups.rs

主要定义了部分类型的重命名。

3.9 prove.rs

  • new:生成单个位置index的proof。
/// generate a new proof
pub fn new<Blob: AsRef<[u8]>>(
    prover_params: &ProverParams,
    values: &[Blob],
    index: usize,
) -> Result<Self, String>

Input: a ProverParams
Input: a list of values to commit
Input: the index for which the proof is generated
Output: a new proof
Error: ciphersuite is not supported
Error: index out of range
Error: values.length does not match n
Steps:
a.hash the values into scarlars
b.proof = \prod prover_params.generators[n - index + i]^scalar[i] for i in range(n) except index (in implementation we implement it as for i in range(n) without exception, since the corresponding generator was already set to 0)

  • verify:验证单个位置的proof。
/// Verify the proof
pub fn verify<Blob: AsRef<[u8]>>(
    &self,
    verifier_params: &VerifierParams,
    com: &Commitment,
    value: Blob,
    index: usize,
) -> bool

Input: self, the proof to be verified
Input: a VerifierParams
Input: the commitment
Input: the value that proof is generated
Input: index of the value in the value vector
Output: if the proof is valid w.r.t. commit/values/index or not
Steps:
a.Compute t = hash_to_field_pointproofs(value)
b.return e(com^{1/t}, veririer_params.generators[n-index-1]) * e(proof^{-1/t}, generator_of_g2) == gt_elt

  • update:更新单个位置的proof。
/// For updating your proof when someone else's value changes
/// Not for updating your own proof when your value changes -- because then the proof does not change!
pub fn update<Blob: AsRef<[u8]>>(
    &mut self,
    prover_params: &ProverParams,
    proof_index: usize,
    changed_index: usize,
    value_before: Blob,
    value_after: Blob,
) -> Result<(), String>

Input: self, the proof to be updated
Input: a ProverParams
Input: proof_index, the index for which the proof is generated
Input: changed_index, the index for which the proof will be updated
Output: mutate self to a new proof
Error: ciphersuite is not supported
Error: index out of range
Note: This function is used for updating your proof when someone else’s value changes. It is not for updating your own proof when your value changes – because then the proof does not change!
Steps:
a.hash value_before into old_scalar
b.hash value_after into new_scalar
c.proof = proof * prover_params.generators[changed_index + n - proof_index]^(new_scalar-old_scalar)

  • batch_new:同时生成多个位置的proof,不再逐个生成。
/// generate a list of new proofs
pub fn batch_new<Blob: AsRef<[u8]>>(
    prover_params: &ProverParams,
    values: &[Blob],
    indices: &[usize],
) -> Result<Vec<Self>, String>

Input: a ProverParam
Input: a list of values to commit
Input: a list of indices for which the proofs are generated
Output: a list of proofs, each corresponding to an index
Error: ciphersuite is not supported
Error: index out of range
Error: values.length does not match n
Error: indices.length = 0 or indices.length > n
Steps:
a.hash the values into scarlars
b.for j in 0…indices.len():
b.a.proof[j] = \prod prover_params[n - indices[j] + i]^scalar[i] for i in range(n) except index
(in implementation we implement it as for i in range(n) without exception, since the corresponding generator was already set to 1)

3.10 c_api.rs

c_api.rs 中实现的是rust接口函数的C语言封装。

猜你喜欢

转载自blog.csdn.net/mutourend/article/details/106531700