longfellow 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/LICENSE.txt +21 -0
- data/README.md +152 -0
- data/ext/longfellow/CMakeLists.txt +76 -0
- data/ext/longfellow/extconf.rb +77 -0
- data/lib/longfellow/attribute.rb +65 -0
- data/lib/longfellow/c.rb +105 -0
- data/lib/longfellow/errors.rb +78 -0
- data/lib/longfellow/version.rb +5 -0
- data/lib/longfellow/zk_spec.rb +40 -0
- data/lib/longfellow.rb +162 -0
- data/sig/longfellow.rbs +74 -0
- data/vendor/longfellow-zk/LICENSE +203 -0
- data/vendor/longfellow-zk/lib/algebra/blas.h +121 -0
- data/vendor/longfellow-zk/lib/algebra/bogorng.h +68 -0
- data/vendor/longfellow-zk/lib/algebra/compare.h +40 -0
- data/vendor/longfellow-zk/lib/algebra/convolution.h +219 -0
- data/vendor/longfellow-zk/lib/algebra/crt.cc +42 -0
- data/vendor/longfellow-zk/lib/algebra/crt.h +299 -0
- data/vendor/longfellow-zk/lib/algebra/crt_convolution.h +114 -0
- data/vendor/longfellow-zk/lib/algebra/crt_test.cc +371 -0
- data/vendor/longfellow-zk/lib/algebra/fft.h +104 -0
- data/vendor/longfellow-zk/lib/algebra/fft_interpolation.h +304 -0
- data/vendor/longfellow-zk/lib/algebra/fft_interpolation_test.cc +168 -0
- data/vendor/longfellow-zk/lib/algebra/fft_test.cc +257 -0
- data/vendor/longfellow-zk/lib/algebra/fp.h +59 -0
- data/vendor/longfellow-zk/lib/algebra/fp2.h +240 -0
- data/vendor/longfellow-zk/lib/algebra/fp24.h +342 -0
- data/vendor/longfellow-zk/lib/algebra/fp24_6.h +305 -0
- data/vendor/longfellow-zk/lib/algebra/fp24_6_test.cc +197 -0
- data/vendor/longfellow-zk/lib/algebra/fp2_test.cc +280 -0
- data/vendor/longfellow-zk/lib/algebra/fp_generic.h +533 -0
- data/vendor/longfellow-zk/lib/algebra/fp_p128.h +91 -0
- data/vendor/longfellow-zk/lib/algebra/fp_p256.h +68 -0
- data/vendor/longfellow-zk/lib/algebra/fp_p256k1.h +123 -0
- data/vendor/longfellow-zk/lib/algebra/fp_p384.h +65 -0
- data/vendor/longfellow-zk/lib/algebra/fp_p521.h +62 -0
- data/vendor/longfellow-zk/lib/algebra/fp_test.cc +522 -0
- data/vendor/longfellow-zk/lib/algebra/hash.h +39 -0
- data/vendor/longfellow-zk/lib/algebra/interpolation.h +117 -0
- data/vendor/longfellow-zk/lib/algebra/interpolation_test.cc +74 -0
- data/vendor/longfellow-zk/lib/algebra/limb.h +153 -0
- data/vendor/longfellow-zk/lib/algebra/limb_test.cc +75 -0
- data/vendor/longfellow-zk/lib/algebra/nat.cc +32 -0
- data/vendor/longfellow-zk/lib/algebra/nat.h +212 -0
- data/vendor/longfellow-zk/lib/algebra/nat_test.cc +183 -0
- data/vendor/longfellow-zk/lib/algebra/nussbaumer.h +400 -0
- data/vendor/longfellow-zk/lib/algebra/nussbaumer_test.cc +138 -0
- data/vendor/longfellow-zk/lib/algebra/nussbaumerfp2_test.cc +139 -0
- data/vendor/longfellow-zk/lib/algebra/permutations.h +79 -0
- data/vendor/longfellow-zk/lib/algebra/poly.h +240 -0
- data/vendor/longfellow-zk/lib/algebra/poly_test.cc +123 -0
- data/vendor/longfellow-zk/lib/algebra/reed_solomon.h +150 -0
- data/vendor/longfellow-zk/lib/algebra/reed_solomon_extension.h +108 -0
- data/vendor/longfellow-zk/lib/algebra/reed_solomon_extension_test.cc +76 -0
- data/vendor/longfellow-zk/lib/algebra/reed_solomon_test.cc +473 -0
- data/vendor/longfellow-zk/lib/algebra/rfft.h +400 -0
- data/vendor/longfellow-zk/lib/algebra/rfft_test.cc +102 -0
- data/vendor/longfellow-zk/lib/algebra/static_string.h +29 -0
- data/vendor/longfellow-zk/lib/algebra/sysdep.h +495 -0
- data/vendor/longfellow-zk/lib/algebra/sysdep_test.cc +41 -0
- data/vendor/longfellow-zk/lib/algebra/twiddle.h +59 -0
- data/vendor/longfellow-zk/lib/algebra/utility.h +86 -0
- data/vendor/longfellow-zk/lib/algebra/utility_test.cc +86 -0
- data/vendor/longfellow-zk/lib/arrays/affine.h +56 -0
- data/vendor/longfellow-zk/lib/arrays/affine_test.cc +220 -0
- data/vendor/longfellow-zk/lib/arrays/dense.h +210 -0
- data/vendor/longfellow-zk/lib/arrays/eq.h +75 -0
- data/vendor/longfellow-zk/lib/arrays/eqs.h +137 -0
- data/vendor/longfellow-zk/lib/arrays/eqs_test.cc +151 -0
- data/vendor/longfellow-zk/lib/arrays/sparse.h +192 -0
- data/vendor/longfellow-zk/lib/cbor/host_decoder.h +323 -0
- data/vendor/longfellow-zk/lib/cbor/host_decoder_test.cc +541 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor.h +594 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_byte_decoder.h +150 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_byte_decoder_test.cc +147 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_constants.h +27 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_pluck.h +110 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_pluck_test.cc +55 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_test.cc +174 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_testing.h +98 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_witness.h +312 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/mso2_test.cc +662 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/mso_test.cc +485 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/scan.h +104 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/scan_test.cc +137 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor.h +640 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor_byte_decoder.h +150 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor_byte_decoder_test.cc +147 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor_constants.h +27 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor_testing.h +99 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor_witness.h +319 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/lexer_test.cc +120 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/mdoc_examples_test.cc +89 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/parser_circuit_test.cc +506 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/parser_size_test.cc +79 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/parser_test.cc +473 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/canonicalization_test.cc +185 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/circuit_dump.h +65 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/compiler.h +471 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/compiler_test.cc +110 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/node.h +176 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/pdqhash.h +127 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/schedule.h +435 -0
- data/vendor/longfellow-zk/lib/circuits/ecdsa/verify_circuit.h +371 -0
- data/vendor/longfellow-zk/lib/circuits/ecdsa/verify_external_test.cc +246 -0
- data/vendor/longfellow-zk/lib/circuits/ecdsa/verify_test.cc +587 -0
- data/vendor/longfellow-zk/lib/circuits/ecdsa/verify_witness.h +201 -0
- data/vendor/longfellow-zk/lib/circuits/logic/bit_adder.h +140 -0
- data/vendor/longfellow-zk/lib/circuits/logic/bit_adder_test.cc +64 -0
- data/vendor/longfellow-zk/lib/circuits/logic/bit_plucker.h +247 -0
- data/vendor/longfellow-zk/lib/circuits/logic/bit_plucker_constants.h +35 -0
- data/vendor/longfellow-zk/lib/circuits/logic/bit_plucker_encoder.h +72 -0
- data/vendor/longfellow-zk/lib/circuits/logic/bit_plucker_test.cc +183 -0
- data/vendor/longfellow-zk/lib/circuits/logic/compiler_backend.h +62 -0
- data/vendor/longfellow-zk/lib/circuits/logic/counter.h +171 -0
- data/vendor/longfellow-zk/lib/circuits/logic/counter_test.cc +102 -0
- data/vendor/longfellow-zk/lib/circuits/logic/evaluation_backend.h +94 -0
- data/vendor/longfellow-zk/lib/circuits/logic/logic.h +1232 -0
- data/vendor/longfellow-zk/lib/circuits/logic/logic_circuit_test.cc +310 -0
- data/vendor/longfellow-zk/lib/circuits/logic/logic_test.cc +521 -0
- data/vendor/longfellow-zk/lib/circuits/logic/memcmp.h +68 -0
- data/vendor/longfellow-zk/lib/circuits/logic/memcmp_test.cc +148 -0
- data/vendor/longfellow-zk/lib/circuits/logic/polynomial.h +94 -0
- data/vendor/longfellow-zk/lib/circuits/logic/polynomial_test.cc +62 -0
- data/vendor/longfellow-zk/lib/circuits/logic/routing.h +445 -0
- data/vendor/longfellow-zk/lib/circuits/logic/routing_test.cc +241 -0
- data/vendor/longfellow-zk/lib/circuits/logic/unary.h +55 -0
- data/vendor/longfellow-zk/lib/circuits/logic/unary_plucker.h +77 -0
- data/vendor/longfellow-zk/lib/circuits/logic/unary_plucker_constants.h +37 -0
- data/vendor/longfellow-zk/lib/circuits/logic/unary_plucker_test.cc +53 -0
- data/vendor/longfellow-zk/lib/circuits/logic/unary_size_test.cc +69 -0
- data/vendor/longfellow-zk/lib/circuits/logic/unary_test.cc +62 -0
- data/vendor/longfellow-zk/lib/circuits/mac/mac_circuit.h +193 -0
- data/vendor/longfellow-zk/lib/circuits/mac/mac_circuit_test.cc +223 -0
- data/vendor/longfellow-zk/lib/circuits/mac/mac_reference.h +72 -0
- data/vendor/longfellow-zk/lib/circuits/mac/mac_witness.h +94 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/circuit_maker.cc +242 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_attribute_ids.h +311 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_attribute_test.cc +64 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_circuit_id.cc +85 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_constants.h +85 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_decompress.cc +41 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_decompress.h +27 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_examples.h +5232 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_generate_circuit.cc +199 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_hash.h +554 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_signature.h +143 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_signature_test.cc +444 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_test_attributes.h +157 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_witness.h +863 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_zk.cc +693 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_zk.h +216 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_zk_test.cc +724 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/zk_spec.cc +100 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/zk_spec_test.cc +155 -0
- data/vendor/longfellow-zk/lib/circuits/sha/flatsha256_circuit.h +330 -0
- data/vendor/longfellow-zk/lib/circuits/sha/flatsha256_circuit_test.cc +607 -0
- data/vendor/longfellow-zk/lib/circuits/sha/flatsha256_io.h +26 -0
- data/vendor/longfellow-zk/lib/circuits/sha/flatsha256_witness.cc +163 -0
- data/vendor/longfellow-zk/lib/circuits/sha/flatsha256_witness.h +47 -0
- data/vendor/longfellow-zk/lib/circuits/sha/sha256_constants.cc +34 -0
- data/vendor/longfellow-zk/lib/circuits/sha/sha256_constants.h +27 -0
- data/vendor/longfellow-zk/lib/circuits/sha/sha256_test_values.h +389 -0
- data/vendor/longfellow-zk/lib/circuits/tests/anoncred/ptrcred.h +171 -0
- data/vendor/longfellow-zk/lib/circuits/tests/anoncred/small.h +218 -0
- data/vendor/longfellow-zk/lib/circuits/tests/anoncred/small_examples.h +118 -0
- data/vendor/longfellow-zk/lib/circuits/tests/anoncred/small_io.h +25 -0
- data/vendor/longfellow-zk/lib/circuits/tests/anoncred/small_test.cc +208 -0
- data/vendor/longfellow-zk/lib/circuits/tests/anoncred/small_witness.h +130 -0
- data/vendor/longfellow-zk/lib/circuits/tests/base64/decode.h +508 -0
- data/vendor/longfellow-zk/lib/circuits/tests/base64/decode_circuit_test.cc +95 -0
- data/vendor/longfellow-zk/lib/circuits/tests/base64/decode_test.cc +119 -0
- data/vendor/longfellow-zk/lib/circuits/tests/base64/decode_util.cc +47 -0
- data/vendor/longfellow-zk/lib/circuits/tests/base64/decode_util.h +29 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ec/pk_circuit.h +231 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ec/pk_circuit_test.cc +428 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ec/pk_witness.h +102 -0
- data/vendor/longfellow-zk/lib/circuits/tests/jwt/jwt.h +190 -0
- data/vendor/longfellow-zk/lib/circuits/tests/jwt/jwt_constants.h +26 -0
- data/vendor/longfellow-zk/lib/circuits/tests/jwt/jwt_test.cc +559 -0
- data/vendor/longfellow-zk/lib/circuits/tests/jwt/jwt_witness.h +315 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_1f.h +411 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_1f_io.h +32 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_1f_test.cc +364 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_1f_witness.h +278 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_revocation.h +146 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_revocation_constants.h +25 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_revocation_test.cc +315 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_revocation_witness.h +136 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/bitaddr/bitaddr.h +250 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/bitaddr/bitaddr_test.cc +333 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/bitaddr/bitaddr_witness.h +152 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44.h +903 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_circuit_test.cc +274 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_eval_test.cc +440 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_examples.cc +8851 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_examples.h +93 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_types.cc +24 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_types.h +118 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_witness.h +453 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_witness_test.cc +49 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref.cc +458 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref.h +150 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref_test.cc +398 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref_test_vectors.inc +3618 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref_test_vectors_pkdecode.inc +689 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref_test_vectors_sigdecode.inc +1501 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/sigdecode_test_vectors.inc +540 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ripemd/ripemd_circuit.h +394 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ripemd/ripemd_circuit_test.cc +577 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ripemd/ripemd_constants.h +90 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ripemd/ripemd_witness.cc +174 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ripemd/ripemd_witness.h +140 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_circuit.h +351 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_circuit_test.cc +466 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_reference.cc +207 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_reference.h +59 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_reference_test.cc +153 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_round_constants.cc +39 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_round_constants.h +29 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_slicing.h +31 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_witness.cc +83 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_witness.h +72 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/shake_test_vectors.h +477 -0
- data/vendor/longfellow-zk/lib/ec/elliptic_curve.h +596 -0
- data/vendor/longfellow-zk/lib/ec/elliptic_curve_test.cc +548 -0
- data/vendor/longfellow-zk/lib/ec/p256.cc +36 -0
- data/vendor/longfellow-zk/lib/ec/p256.h +60 -0
- data/vendor/longfellow-zk/lib/ec/p256k1.cc +34 -0
- data/vendor/longfellow-zk/lib/ec/p256k1.h +60 -0
- data/vendor/longfellow-zk/lib/gf2k/gf2_128.h +503 -0
- data/vendor/longfellow-zk/lib/gf2k/gf2_128_bench.cc +48 -0
- data/vendor/longfellow-zk/lib/gf2k/gf2_128_test.cc +416 -0
- data/vendor/longfellow-zk/lib/gf2k/gf2poly.h +74 -0
- data/vendor/longfellow-zk/lib/gf2k/lch14.h +242 -0
- data/vendor/longfellow-zk/lib/gf2k/lch14_bench.cc +75 -0
- data/vendor/longfellow-zk/lib/gf2k/lch14_reed_solomon.h +127 -0
- data/vendor/longfellow-zk/lib/gf2k/lch14_reed_solomon_test.cc +110 -0
- data/vendor/longfellow-zk/lib/gf2k/lch14_test.cc +246 -0
- data/vendor/longfellow-zk/lib/gf2k/sysdep.h +329 -0
- data/vendor/longfellow-zk/lib/ligero/ligero_param.h +449 -0
- data/vendor/longfellow-zk/lib/ligero/ligero_prover.h +354 -0
- data/vendor/longfellow-zk/lib/ligero/ligero_test.cc +136 -0
- data/vendor/longfellow-zk/lib/ligero/ligero_transcript.h +67 -0
- data/vendor/longfellow-zk/lib/ligero/ligero_verifier.h +272 -0
- data/vendor/longfellow-zk/lib/merkle/merkle_commitment.h +104 -0
- data/vendor/longfellow-zk/lib/merkle/merkle_tree.h +216 -0
- data/vendor/longfellow-zk/lib/merkle/merkle_tree_test.cc +240 -0
- data/vendor/longfellow-zk/lib/proto/circuit.h +354 -0
- data/vendor/longfellow-zk/lib/proto/circuit_test.cc +202 -0
- data/vendor/longfellow-zk/lib/random/random.h +119 -0
- data/vendor/longfellow-zk/lib/random/random_test.cc +189 -0
- data/vendor/longfellow-zk/lib/random/secure_random_engine.h +37 -0
- data/vendor/longfellow-zk/lib/random/transcript.h +193 -0
- data/vendor/longfellow-zk/lib/random/transcript_test.cc +344 -0
- data/vendor/longfellow-zk/lib/sumcheck/circuit.h +148 -0
- data/vendor/longfellow-zk/lib/sumcheck/circuit_id.h +71 -0
- data/vendor/longfellow-zk/lib/sumcheck/equad.h +126 -0
- data/vendor/longfellow-zk/lib/sumcheck/hquad.h +115 -0
- data/vendor/longfellow-zk/lib/sumcheck/prover.h +59 -0
- data/vendor/longfellow-zk/lib/sumcheck/prover_layers.h +362 -0
- data/vendor/longfellow-zk/lib/sumcheck/quad.h +227 -0
- data/vendor/longfellow-zk/lib/sumcheck/quad_builder.h +211 -0
- data/vendor/longfellow-zk/lib/sumcheck/quad_test.cc +169 -0
- data/vendor/longfellow-zk/lib/sumcheck/sumcheck_test.cc +324 -0
- data/vendor/longfellow-zk/lib/sumcheck/testing.h +69 -0
- data/vendor/longfellow-zk/lib/sumcheck/transcript_sumcheck.h +85 -0
- data/vendor/longfellow-zk/lib/sumcheck/verifier.h +84 -0
- data/vendor/longfellow-zk/lib/sumcheck/verifier_layers.h +221 -0
- data/vendor/longfellow-zk/lib/testing/test_main.cc +50 -0
- data/vendor/longfellow-zk/lib/util/ceildiv.h +164 -0
- data/vendor/longfellow-zk/lib/util/ceildiv_test.cc +152 -0
- data/vendor/longfellow-zk/lib/util/crc64.h +45 -0
- data/vendor/longfellow-zk/lib/util/crypto.cc +39 -0
- data/vendor/longfellow-zk/lib/util/crypto.h +108 -0
- data/vendor/longfellow-zk/lib/util/log.cc +110 -0
- data/vendor/longfellow-zk/lib/util/log.h +33 -0
- data/vendor/longfellow-zk/lib/util/panic.h +40 -0
- data/vendor/longfellow-zk/lib/util/readbuffer.h +67 -0
- data/vendor/longfellow-zk/lib/util/serialization.h +54 -0
- data/vendor/longfellow-zk/lib/zk/zk_common.h +455 -0
- data/vendor/longfellow-zk/lib/zk/zk_proof.h +378 -0
- data/vendor/longfellow-zk/lib/zk/zk_prover.h +202 -0
- data/vendor/longfellow-zk/lib/zk/zk_test.cc +340 -0
- data/vendor/longfellow-zk/lib/zk/zk_testing.h +154 -0
- data/vendor/longfellow-zk/lib/zk/zk_verifier.h +109 -0
- metadata +347 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
// Copyright 2026 Google LLC.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
|
|
15
|
+
#include "merkle/merkle_tree.h"
|
|
16
|
+
|
|
17
|
+
#include <stddef.h>
|
|
18
|
+
#include <stdint.h>
|
|
19
|
+
#include <stdio.h>
|
|
20
|
+
|
|
21
|
+
#include <algorithm>
|
|
22
|
+
#include <vector>
|
|
23
|
+
|
|
24
|
+
#include "benchmark/benchmark.h"
|
|
25
|
+
#include "gtest/gtest.h"
|
|
26
|
+
|
|
27
|
+
namespace proofs {
|
|
28
|
+
namespace {
|
|
29
|
+
|
|
30
|
+
TEST(MerkleTree, BuildTree) {
|
|
31
|
+
MerkleTree mt(4);
|
|
32
|
+
Digest leaves[4] = {Digest{100}, Digest{101}, Digest{102}, Digest{103}};
|
|
33
|
+
for (size_t i = 0; i < 4; i++) {
|
|
34
|
+
mt.set_leaf(i, leaves[i]);
|
|
35
|
+
}
|
|
36
|
+
Digest root = mt.build_tree();
|
|
37
|
+
EXPECT_EQ(mt.layers_[4], leaves[0]);
|
|
38
|
+
EXPECT_EQ(mt.layers_[2], Digest::hash2(leaves[0], leaves[1]));
|
|
39
|
+
EXPECT_EQ(mt.layers_[3], Digest::hash2(leaves[2], leaves[3]));
|
|
40
|
+
EXPECT_EQ(mt.layers_[1], Digest::hash2(Digest::hash2(leaves[0], leaves[1]),
|
|
41
|
+
Digest::hash2(leaves[2], leaves[3])));
|
|
42
|
+
EXPECT_EQ(root, Digest::hash2(Digest::hash2(leaves[0], leaves[1]),
|
|
43
|
+
Digest::hash2(leaves[2], leaves[3])));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
MerkleTree setupBatch(size_t n, size_t batch_size, std::vector<Digest>& leaves,
|
|
48
|
+
std::vector<size_t>& idx) {
|
|
49
|
+
MerkleTree prover(n);
|
|
50
|
+
uint8_t data = 1;
|
|
51
|
+
for (size_t i = 0; i < n; i++) {
|
|
52
|
+
prover.set_leaf(i, Digest{data});
|
|
53
|
+
data += 1;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Pick a random set of leaf indices with no repeats.
|
|
57
|
+
for (size_t i = 0; i < batch_size; ++i) {
|
|
58
|
+
size_t j = random() % n;
|
|
59
|
+
// Rejection sampling is OK for small batch sizes.
|
|
60
|
+
while (std::find(idx.begin(), idx.end(), j) != idx.end()) {
|
|
61
|
+
j = random() % n;
|
|
62
|
+
}
|
|
63
|
+
idx.push_back(j);
|
|
64
|
+
leaves.push_back(prover.layers_[j + n]);
|
|
65
|
+
}
|
|
66
|
+
return prover;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
TEST(MerkleTree, VerifyCompressedProof) {
|
|
70
|
+
std::vector<size_t> sizes{1, 10, 80};
|
|
71
|
+
for (size_t testSize : sizes) {
|
|
72
|
+
for (size_t n = 200; n <= 300; ++n) {
|
|
73
|
+
std::vector<size_t> idx;
|
|
74
|
+
std::vector<Digest> leaves;
|
|
75
|
+
MerkleTree prover = setupBatch(n, testSize, leaves, idx);
|
|
76
|
+
Digest root = prover.build_tree();
|
|
77
|
+
std::vector<Digest> proof;
|
|
78
|
+
size_t len = prover.generate_compressed_proof(proof, &idx[0], testSize);
|
|
79
|
+
|
|
80
|
+
MerkleTreeVerifier verifier(n, root);
|
|
81
|
+
EXPECT_TRUE(verifier.verify_compressed_proof(
|
|
82
|
+
proof.data(), len, leaves.data(), idx.data(), idx.size()));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
TEST(MerkleTree, VerifyCompressedProofFailure) {
|
|
88
|
+
const size_t kTestSize = 80;
|
|
89
|
+
for (size_t n = 200; n <= 300; ++n) {
|
|
90
|
+
std::vector<size_t> idx;
|
|
91
|
+
std::vector<Digest> leaves;
|
|
92
|
+
MerkleTree prover = setupBatch(n, kTestSize, leaves, idx);
|
|
93
|
+
Digest root = prover.build_tree();
|
|
94
|
+
|
|
95
|
+
std::vector<Digest> proof;
|
|
96
|
+
size_t len = prover.generate_compressed_proof(proof, &idx[0], kTestSize);
|
|
97
|
+
MerkleTreeVerifier verifier(n, root);
|
|
98
|
+
|
|
99
|
+
// Check that any bit flip fails the verification.
|
|
100
|
+
for (size_t ei = 0; ei < proof.size(); ++ei) {
|
|
101
|
+
proof[ei].data[0] ^= 1;
|
|
102
|
+
EXPECT_FALSE(verifier.verify_compressed_proof(&proof[0], len, &leaves[0],
|
|
103
|
+
&idx[0], idx.size()));
|
|
104
|
+
proof[ei].data[0] ^= 1;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
TEST(MerkleTree, ZeroLengthProof) {
|
|
110
|
+
Digest leaves[4] = {Digest{100}, Digest{101}, Digest{102}, Digest{103}};
|
|
111
|
+
MerkleTree mt(4);
|
|
112
|
+
for (size_t i = 0; i < 4; i++) {
|
|
113
|
+
mt.set_leaf(i, leaves[i]);
|
|
114
|
+
}
|
|
115
|
+
Digest root = mt.build_tree();
|
|
116
|
+
|
|
117
|
+
size_t ids[] = {0, 1, 2, 3};
|
|
118
|
+
std::vector<Digest> empty_leaves;
|
|
119
|
+
MerkleTreeVerifier verifier(4, root);
|
|
120
|
+
std::vector<Digest> empty_proof;
|
|
121
|
+
|
|
122
|
+
// Empty proof should fail.
|
|
123
|
+
EXPECT_FALSE(
|
|
124
|
+
verifier.verify_compressed_proof(empty_proof.data(), 0, leaves, ids, 1));
|
|
125
|
+
|
|
126
|
+
// The valid case for a zero-length proof is when all the leaves are given.
|
|
127
|
+
EXPECT_TRUE(
|
|
128
|
+
verifier.verify_compressed_proof(empty_proof.data(), 0, leaves, ids, 4));
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
TEST(MerkleTree, UniqueLeaves) {
|
|
132
|
+
Digest leaves[4] = {Digest{100}, Digest{101}, Digest{102}, Digest{103}};
|
|
133
|
+
MerkleTree mt(4);
|
|
134
|
+
for (size_t i = 0; i < 4; i++) {
|
|
135
|
+
mt.set_leaf(i, leaves[i]);
|
|
136
|
+
}
|
|
137
|
+
Digest root = mt.build_tree();
|
|
138
|
+
size_t ids[] = {1, 1};
|
|
139
|
+
std::vector<Digest> ll = {leaves[1], leaves[1]};
|
|
140
|
+
MerkleTreeVerifier verifier(4, root);
|
|
141
|
+
std::vector<Digest> proof = {Digest::hash2(leaves[1], leaves[1])};
|
|
142
|
+
|
|
143
|
+
EXPECT_DEATH(
|
|
144
|
+
verifier.verify_compressed_proof(proof.data(), 1, leaves, ids, 2),
|
|
145
|
+
"duplicate position in merkle tree requested");
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
TEST(MerkleTree, BatchVerifyProofTooShort) {
|
|
149
|
+
std::vector<size_t> idx;
|
|
150
|
+
std::vector<Digest> leaves;
|
|
151
|
+
MerkleTree prover = setupBatch(300, 20, leaves, idx);
|
|
152
|
+
Digest root = prover.build_tree();
|
|
153
|
+
std::vector<Digest> proof;
|
|
154
|
+
size_t len = prover.generate_compressed_proof(proof, &idx[0], 20);
|
|
155
|
+
MerkleTreeVerifier verifier(300, root);
|
|
156
|
+
|
|
157
|
+
EXPECT_FALSE(verifier.verify_compressed_proof(&proof[0], len - 1, &leaves[0],
|
|
158
|
+
&idx[0], idx.size()));
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
void print_digest(const Digest& d) {
|
|
162
|
+
for (size_t i = 0; i < Digest::kLength; ++i) {
|
|
163
|
+
printf("%02x", d.data[i]);
|
|
164
|
+
}
|
|
165
|
+
printf("\n");
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Generates the test vectors for the RFC.
|
|
169
|
+
TEST(MerkleTree, TestVectors) {
|
|
170
|
+
MerkleTree mt(5);
|
|
171
|
+
Digest leaves[5] =
|
|
172
|
+
{
|
|
173
|
+
Digest{0x4b, 0xf5, 0x12, 0x2f, 0x34, 0x45, 0x54, 0xc5,
|
|
174
|
+
0x3b, 0xde, 0x2e, 0xbb, 0x8c, 0xd2, 0xb7, 0xe3,
|
|
175
|
+
0xd1, 0x60, 0x0a, 0xd6, 0x31, 0xc3, 0x85, 0xa5,
|
|
176
|
+
0xd7, 0xcc, 0xe2, 0x3c, 0x77, 0x85, 0x45, 0x9a}, // hash(01)
|
|
177
|
+
Digest{0xdb, 0xc1, 0xb4, 0xc9, 0x00, 0xff, 0xe4, 0x8d,
|
|
178
|
+
0x57, 0x5b, 0x5d, 0xa5, 0xc6, 0x38, 0x04, 0x01,
|
|
179
|
+
0x25, 0xf6, 0x5d, 0xb0, 0xfe, 0x3e, 0x24, 0x49,
|
|
180
|
+
0x4b, 0x76, 0xea, 0x98, 0x64, 0x57, 0xd9, 0x86}, // hash(02)
|
|
181
|
+
Digest{0x08, 0x4f, 0xed, 0x08, 0xb9, 0x78, 0xaf, 0x4d,
|
|
182
|
+
0x7d, 0x19, 0x6a, 0x74, 0x46, 0xa8, 0x6b, 0x58,
|
|
183
|
+
0x00, 0x9e, 0x63, 0x6b, 0x61, 0x1d, 0xb1, 0x62,
|
|
184
|
+
0x11, 0xb6, 0x5a, 0x9a, 0xad, 0xff, 0x29, 0xc5}, // hash(03)
|
|
185
|
+
Digest{0xe5, 0x2d, 0x9c, 0x50, 0x8c, 0x50, 0x23, 0x47,
|
|
186
|
+
0x34, 0x4d, 0x8c, 0x07, 0xad, 0x91, 0xcb, 0xd6,
|
|
187
|
+
0x06, 0x8a, 0xfc, 0x75, 0xff, 0x62, 0x92, 0xf0,
|
|
188
|
+
0x62, 0xa0, 0x9c, 0xa3, 0x81, 0xc8, 0x9e, 0x71}, // hash(04)
|
|
189
|
+
Digest{0xe7, 0x7b, 0x9a, 0x9a, 0xe9, 0xe3, 0x0b, 0x0d,
|
|
190
|
+
0xbd, 0xb6, 0xf5, 0x10, 0xa2, 0x64, 0xef, 0x9d,
|
|
191
|
+
0xe7, 0x81, 0x50, 0x1d, 0x7b, 0x6b, 0x92, 0xae,
|
|
192
|
+
0x89, 0xeb, 0x05, 0x9c, 0x5a, 0xb7, 0x43, 0xdb} // hash(05)
|
|
193
|
+
};
|
|
194
|
+
for (size_t i = 0; i < 5; i++) {
|
|
195
|
+
mt.set_leaf(i, leaves[i]);
|
|
196
|
+
}
|
|
197
|
+
Digest root = mt.build_tree();
|
|
198
|
+
print_digest(root);
|
|
199
|
+
|
|
200
|
+
std::vector<size_t> idx;
|
|
201
|
+
std::vector<Digest> proof;
|
|
202
|
+
idx.push_back(0);
|
|
203
|
+
idx.push_back(1);
|
|
204
|
+
size_t len = mt.generate_compressed_proof(proof, &idx[0], 2);
|
|
205
|
+
printf("len = %zu\n", len);
|
|
206
|
+
for (size_t i = 0; i < len; ++i) {
|
|
207
|
+
print_digest(proof[i]);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Example requires 3 elements in the proof.
|
|
211
|
+
idx[0] = 1;
|
|
212
|
+
idx[1] = 3;
|
|
213
|
+
std::vector<Digest> proof2;
|
|
214
|
+
len = mt.generate_compressed_proof(proof2, &idx[0], 2);
|
|
215
|
+
printf("len = %zu\n", len);
|
|
216
|
+
for (size_t i = 0; i < len; ++i) {
|
|
217
|
+
print_digest(proof2[i]);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// ============================= Benchmarks ===================================
|
|
222
|
+
|
|
223
|
+
void BM_MerkleTree_BuildTree(benchmark::State& state) {
|
|
224
|
+
const size_t size = state.range(0);
|
|
225
|
+
|
|
226
|
+
MerkleTree mt(size);
|
|
227
|
+
std::vector<Digest> leaves(size);
|
|
228
|
+
for (size_t i = 0; i < size; i++) {
|
|
229
|
+
leaves[i] = Digest{static_cast<uint8_t>(i)};
|
|
230
|
+
mt.set_leaf(i, leaves[i]);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
for (auto s : state) {
|
|
234
|
+
mt.build_tree();
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
BENCHMARK(BM_MerkleTree_BuildTree)->RangeMultiplier(4)->Range(1024, 1 << 20);
|
|
238
|
+
|
|
239
|
+
} // namespace
|
|
240
|
+
} // namespace proofs
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
// Copyright 2026 Google LLC.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
|
|
15
|
+
#ifndef PRIVACY_PROOFS_ZK_LIB_PROTO_CIRCUIT_H_
|
|
16
|
+
#define PRIVACY_PROOFS_ZK_LIB_PROTO_CIRCUIT_H_
|
|
17
|
+
|
|
18
|
+
#include <cstddef>
|
|
19
|
+
#include <cstdint>
|
|
20
|
+
#include <cstring>
|
|
21
|
+
#include <memory>
|
|
22
|
+
#include <optional>
|
|
23
|
+
#include <vector>
|
|
24
|
+
|
|
25
|
+
#include "sumcheck/circuit.h"
|
|
26
|
+
#include "sumcheck/circuit_id.h"
|
|
27
|
+
#include "sumcheck/quad.h"
|
|
28
|
+
#include "sumcheck/quad_builder.h"
|
|
29
|
+
#include "util/ceildiv.h"
|
|
30
|
+
#include "util/panic.h"
|
|
31
|
+
#include "util/readbuffer.h"
|
|
32
|
+
|
|
33
|
+
namespace proofs {
|
|
34
|
+
|
|
35
|
+
// CircuitRep class handles custom circuit serialization.
|
|
36
|
+
//
|
|
37
|
+
// We expect circuits to be created and stored locally by the prover and
|
|
38
|
+
// verifier respectively. The byte representations are thus assumed to be
|
|
39
|
+
// trusted. As a result, the methods below perform only basic sanity checking.
|
|
40
|
+
//
|
|
41
|
+
// An earlier experiment implemented the IO methods using protobuf parsing.
|
|
42
|
+
// Despite applying techniques like arena allocation, those methods required
|
|
43
|
+
// several seconds to deserialize the circuit. In contrast, these methods take
|
|
44
|
+
// 100s of ms.
|
|
45
|
+
//
|
|
46
|
+
// This class implements an optimization by which internal indices for
|
|
47
|
+
// wire and gate labels and circuit size statistics are stored in a configurable
|
|
48
|
+
// number of bytes (kBytesPerSizeT) which we set to 3 instead of 8 to save
|
|
49
|
+
// space. If this value is set to >4, there is a possibility of failure on
|
|
50
|
+
// 32b platforms, which currently stops execution. Thus, all circuits must be
|
|
51
|
+
// tested on 32b platforms to ensure they are small enough to work.
|
|
52
|
+
enum FieldID {
|
|
53
|
+
NONE = 0,
|
|
54
|
+
P256_ID = 1,
|
|
55
|
+
P384_ID = 2,
|
|
56
|
+
P521_ID = 3,
|
|
57
|
+
GF2_128_ID = 4,
|
|
58
|
+
GF2_16_ID = 5,
|
|
59
|
+
FP128_ID = 6,
|
|
60
|
+
FP64_ID = 7,
|
|
61
|
+
GOLDI_ID = 8,
|
|
62
|
+
FP64_2_ID = 9,
|
|
63
|
+
SECP_ID = 10,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
template <class Field>
|
|
67
|
+
class CircuitRep {
|
|
68
|
+
using Elt = typename Field::Elt;
|
|
69
|
+
using QuadCorner = typename Quad<Field>::quad_corner_t;
|
|
70
|
+
constexpr static size_t kMaxLayers = 10000; /* deep circuits are errors */
|
|
71
|
+
|
|
72
|
+
public:
|
|
73
|
+
// Serialize kBytesPerSizeT bytes of a size or index used in the circuit to
|
|
74
|
+
// save space.
|
|
75
|
+
static constexpr size_t kBytesPerSizeT = 3;
|
|
76
|
+
static constexpr size_t kIdSize = 32;
|
|
77
|
+
|
|
78
|
+
explicit CircuitRep(const Field& f, FieldID field_id)
|
|
79
|
+
: f_(f), field_id_(field_id) {}
|
|
80
|
+
|
|
81
|
+
void to_bytes(const Circuit<Field>& sc_c, std::vector<uint8_t>& bytes) {
|
|
82
|
+
KvecBuilder<Field> kb(f_);
|
|
83
|
+
// Collect constants
|
|
84
|
+
for (const auto& layer : sc_c.l) {
|
|
85
|
+
for (const auto& ec : *layer.quad) {
|
|
86
|
+
kb.kstore(ec.v);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Write header
|
|
91
|
+
bytes.push_back(0x1); // version
|
|
92
|
+
serialize_field_id(bytes, field_id_);
|
|
93
|
+
serialize_size(bytes, sc_c.nv);
|
|
94
|
+
serialize_size(bytes, sc_c.nc);
|
|
95
|
+
serialize_size(bytes, sc_c.npub_in);
|
|
96
|
+
serialize_size(bytes, sc_c.subfield_boundary);
|
|
97
|
+
serialize_size(bytes, sc_c.ninputs);
|
|
98
|
+
serialize_size(bytes, sc_c.l.size());
|
|
99
|
+
|
|
100
|
+
// Write kvec
|
|
101
|
+
auto kvec = kb.kvec();
|
|
102
|
+
serialize_size(bytes, kvec->size());
|
|
103
|
+
for (const auto& v : *kvec) {
|
|
104
|
+
serialize_elt(bytes, v, f_);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Serialize layers and quads
|
|
108
|
+
for (const auto& layer : sc_c.l) {
|
|
109
|
+
serialize_size(bytes, layer.logw);
|
|
110
|
+
serialize_size(bytes, layer.nw);
|
|
111
|
+
serialize_size(bytes, layer.quad->size());
|
|
112
|
+
|
|
113
|
+
QuadCorner prevg(0), prevh0(0), prevh1(0);
|
|
114
|
+
for (const auto& ec : *layer.quad) {
|
|
115
|
+
serialize_index(bytes, ec.g, prevg);
|
|
116
|
+
serialize_index(bytes, ec.h[0], prevh0);
|
|
117
|
+
serialize_index(bytes, ec.h[1], prevh1);
|
|
118
|
+
serialize_num(bytes, kb.kload(ec.v));
|
|
119
|
+
prevg = ec.g;
|
|
120
|
+
prevh0 = ec.h[0];
|
|
121
|
+
prevh1 = ec.h[1];
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Write circuit ID
|
|
126
|
+
bytes.insert(bytes.end(), sc_c.id, sc_c.id + kIdSize);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Returns a unique_ptr<Circuit> or nullptr if there is an error in
|
|
130
|
+
// deserializing the circuit.
|
|
131
|
+
//
|
|
132
|
+
// If ENFORCE_CIRCUIT_ID is TRUE, check that the circuit id in
|
|
133
|
+
// the serialization matches the id stored in the circuit.
|
|
134
|
+
std::unique_ptr<Circuit<Field>> from_bytes(ReadBuffer& buf,
|
|
135
|
+
bool enforce_circuit_id) {
|
|
136
|
+
if (!buf.have(8 * kBytesPerSizeT + 1)) {
|
|
137
|
+
return nullptr;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
uint8_t version = *buf.next(1);
|
|
141
|
+
if (version != 1) {
|
|
142
|
+
return nullptr;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
size_t fid_as_size_t = read_field_id(buf);
|
|
146
|
+
size_t nv = read_size(buf);
|
|
147
|
+
size_t nc = read_size(buf);
|
|
148
|
+
size_t npub_in = read_size(buf);
|
|
149
|
+
size_t subfield_boundary = read_size(buf);
|
|
150
|
+
size_t ninputs = read_size(buf);
|
|
151
|
+
size_t nl = read_size(buf);
|
|
152
|
+
size_t numconst = read_size(buf);
|
|
153
|
+
|
|
154
|
+
// Basic sanity checks.
|
|
155
|
+
if (fid_as_size_t != static_cast<size_t>(field_id_) || npub_in > ninputs ||
|
|
156
|
+
subfield_boundary > ninputs || nl > kMaxLayers) {
|
|
157
|
+
return nullptr;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Ensure there are enough input bytes for the quad constants.
|
|
161
|
+
auto need = checked_mul(numconst, Field::kBytes);
|
|
162
|
+
if (!need || !buf.have(need.value())) {
|
|
163
|
+
return nullptr;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
auto constants = std::make_shared<std::vector<Elt>>(numconst);
|
|
167
|
+
for (size_t i = 0; i < numconst; ++i) {
|
|
168
|
+
// Fail if Elt cannot be parsed.
|
|
169
|
+
auto vv = f_.of_bytes_field(buf.next(Field::kBytes));
|
|
170
|
+
if (!vv.has_value()) {
|
|
171
|
+
return nullptr;
|
|
172
|
+
}
|
|
173
|
+
(*constants)[i] = vv.value();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
auto c = std::make_unique<Circuit<Field>>();
|
|
177
|
+
*c = Circuit<Field>{
|
|
178
|
+
.nv = nv,
|
|
179
|
+
.logv = lg(nv),
|
|
180
|
+
.nc = nc,
|
|
181
|
+
.logc = lg(nc),
|
|
182
|
+
.nl = nl,
|
|
183
|
+
.ninputs = ninputs,
|
|
184
|
+
.npub_in = npub_in,
|
|
185
|
+
.subfield_boundary = subfield_boundary,
|
|
186
|
+
};
|
|
187
|
+
c->l.reserve(nl);
|
|
188
|
+
|
|
189
|
+
size_t max_g = nv; // a starting bound on quad number
|
|
190
|
+
|
|
191
|
+
// Use an approximate delta table builder, preferring quick lookup at the
|
|
192
|
+
// cost of missing some deduplications.
|
|
193
|
+
ApproximateDeltaTableBuilder<Field> db(/*prime*/ 8209);
|
|
194
|
+
|
|
195
|
+
for (size_t ly = 0; ly < nl; ++ly) {
|
|
196
|
+
// Ensure there are enough input bytes for the layer, 3 values.
|
|
197
|
+
if (!buf.have(3 * kBytesPerSizeT)) {
|
|
198
|
+
return nullptr;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
size_t lw = read_size(buf);
|
|
202
|
+
size_t nw = read_size(buf);
|
|
203
|
+
size_t nq = read_size(buf);
|
|
204
|
+
|
|
205
|
+
// Each quad takes 4 values, check for overflow.
|
|
206
|
+
need = checked_mul(4 * kBytesPerSizeT, nq);
|
|
207
|
+
if (!need || !buf.have(need.value())) {
|
|
208
|
+
return nullptr;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
auto qq = std::make_unique<Quad<Field>>(nq, constants, db.delta_table());
|
|
212
|
+
size_t prevg = 0, prevhl = 0, prevhr = 0;
|
|
213
|
+
for (size_t i = 0; i < nq; ++i) {
|
|
214
|
+
size_t g = read_index(buf, prevg);
|
|
215
|
+
if (g > max_g) { // index of quad must be < wires in the layer
|
|
216
|
+
return nullptr;
|
|
217
|
+
}
|
|
218
|
+
size_t hl = read_index(buf, prevhl);
|
|
219
|
+
size_t hr = read_index(buf, prevhr);
|
|
220
|
+
if (hl > nw || hr > nw) {
|
|
221
|
+
return nullptr;
|
|
222
|
+
}
|
|
223
|
+
size_t vi = read_num(buf);
|
|
224
|
+
if (vi >= numconst) {
|
|
225
|
+
return nullptr;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
qq->assign(
|
|
229
|
+
i, db.dedup(QuadCorner(g - prevg), QuadCorner(hl - prevhl),
|
|
230
|
+
QuadCorner(hr - prevhr), static_cast<uint32_t>(vi)));
|
|
231
|
+
prevg = g;
|
|
232
|
+
prevhl = hl;
|
|
233
|
+
prevhr = hr;
|
|
234
|
+
}
|
|
235
|
+
c->l.push_back(Layer<Field>{
|
|
236
|
+
.nw = nw,
|
|
237
|
+
.logw = lw,
|
|
238
|
+
.quad = std::unique_ptr<const Quad<Field>>(std::move(qq))});
|
|
239
|
+
max_g = nw;
|
|
240
|
+
}
|
|
241
|
+
// Read the circuit name from the serialization.
|
|
242
|
+
if (!buf.have(kIdSize)) {
|
|
243
|
+
return nullptr;
|
|
244
|
+
}
|
|
245
|
+
buf.next(kIdSize, c->id);
|
|
246
|
+
|
|
247
|
+
if (enforce_circuit_id) {
|
|
248
|
+
uint8_t idtmp[kIdSize];
|
|
249
|
+
circuit_id(idtmp, *c, f_);
|
|
250
|
+
if (memcmp(idtmp, c->id, kIdSize) != 0) {
|
|
251
|
+
return nullptr;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return c;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
private:
|
|
258
|
+
static constexpr uint64_t kMaxValue = (1ULL << (kBytesPerSizeT * 8)) - 1;
|
|
259
|
+
|
|
260
|
+
// Multiplies arguments and checks for overflow.
|
|
261
|
+
template <typename T>
|
|
262
|
+
std::optional<T> checked_mul(T a, T b) {
|
|
263
|
+
T ab = a * b;
|
|
264
|
+
if (a == 0 || ab / a == b) return ab;
|
|
265
|
+
return std::nullopt;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
static void serialize_elt(std::vector<uint8_t>& bytes, const Elt& v,
|
|
269
|
+
const Field& f) {
|
|
270
|
+
uint8_t buf[Field::kBytes];
|
|
271
|
+
f.to_bytes_field(buf, v);
|
|
272
|
+
bytes.insert(bytes.end(), buf, buf + Field::kBytes);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
static void serialize_field_id(std::vector<uint8_t>& bytes, FieldID id) {
|
|
276
|
+
serialize_num(bytes, static_cast<size_t>(id));
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
static void serialize_size(std::vector<uint8_t>& bytes, size_t sz) {
|
|
280
|
+
serialize_num(bytes, sz);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// We write indices as differences from the previous index. This
|
|
284
|
+
// encoding appears to produce byte streams that compress better
|
|
285
|
+
// under both gzip and xz compression. For example, xz compresses
|
|
286
|
+
// a 35MB test circuit to 2MB without delta encoding, and to 100KB
|
|
287
|
+
// with delta encoding. We have no real theory to explain this
|
|
288
|
+
// phenomenon, but at least part of the reason is that the deltas
|
|
289
|
+
// are usually smaller than the indices.
|
|
290
|
+
//
|
|
291
|
+
static void serialize_index(std::vector<uint8_t>& bytes, QuadCorner index,
|
|
292
|
+
QuadCorner prev_index) {
|
|
293
|
+
size_t ind = static_cast<size_t>(index);
|
|
294
|
+
size_t prev_ind = static_cast<size_t>(prev_index);
|
|
295
|
+
|
|
296
|
+
// Encode the delta IND - PREV_IND. Since the delta can be
|
|
297
|
+
// negative, and the rest of the code is unsigned only,
|
|
298
|
+
// use the LSB as sign bit.
|
|
299
|
+
if (ind >= prev_ind) {
|
|
300
|
+
serialize_num(bytes, 2u * (ind - prev_ind));
|
|
301
|
+
} else {
|
|
302
|
+
serialize_num(bytes, 2u * (prev_ind - ind) + 1u);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
static void serialize_num(std::vector<uint8_t>& bytes, size_t g) {
|
|
307
|
+
check(g < kMaxValue, "Violating small wire-label assumption");
|
|
308
|
+
uint8_t tmp[kBytesPerSizeT];
|
|
309
|
+
for (size_t i = 0; i < kBytesPerSizeT; ++i) {
|
|
310
|
+
tmp[i] = static_cast<uint8_t>(g & 0xff);
|
|
311
|
+
g >>= 8;
|
|
312
|
+
}
|
|
313
|
+
bytes.insert(bytes.end(), tmp, tmp + kBytesPerSizeT);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// These routine reads bytes written by serialize_* methods, and thus
|
|
317
|
+
// only needs to handle values expressed in kBytesPerSizeT.
|
|
318
|
+
// On 32b platforms, some large circuits may fail; this method
|
|
319
|
+
// causes a failure in that case.
|
|
320
|
+
|
|
321
|
+
// Do not cast to FieldID, since the input is untrusted and the
|
|
322
|
+
// cast may fail.
|
|
323
|
+
static size_t read_field_id(ReadBuffer& buf) { return read_num(buf); }
|
|
324
|
+
|
|
325
|
+
static size_t read_size(ReadBuffer& buf) { return read_num(buf); }
|
|
326
|
+
|
|
327
|
+
static size_t read_index(ReadBuffer& buf, size_t prev_ind) {
|
|
328
|
+
size_t delta = read_num(buf);
|
|
329
|
+
if (delta & 1) {
|
|
330
|
+
return prev_ind - (delta >> 1);
|
|
331
|
+
} else {
|
|
332
|
+
return prev_ind + (delta >> 1);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
static size_t read_num(ReadBuffer& buf) {
|
|
337
|
+
uint64_t r = 0;
|
|
338
|
+
const uint8_t* p = buf.next(kBytesPerSizeT);
|
|
339
|
+
for (size_t i = 0; i < kBytesPerSizeT; ++i) {
|
|
340
|
+
r |= (static_cast<uint64_t>(p[i]) << (i * 8));
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// SIZE_MAX is system defined as max value for size_t.
|
|
344
|
+
// This check fails if a large circuit is loaded on a 32b machine.
|
|
345
|
+
check(r < SIZE_MAX, "Violating small wire-label assumption");
|
|
346
|
+
return static_cast<size_t>(r);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const Field& f_;
|
|
350
|
+
FieldID field_id_;
|
|
351
|
+
};
|
|
352
|
+
} // namespace proofs
|
|
353
|
+
|
|
354
|
+
#endif // PRIVACY_PROOFS_ZK_LIB_PROTO_CIRCUIT_H_
|