feat: add support for proving predicates

This commit is contained in:
dan
2025-12-11 10:44:11 +02:00
parent 4fe5c1defd
commit 830d0ab0d5
14 changed files with 405 additions and 113 deletions

190
Cargo.lock generated
View File

@@ -174,9 +174,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
[[package]]
name = "alloy-consensus"
version = "1.1.2"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b6440213a22df93a87ed512d2f668e7dc1d62a05642d107f82d61edc9e12370"
checksum = "2e318e25fb719e747a7e8db1654170fc185024f3ed5b10f86c08d448a912f6e2"
dependencies = [
"alloy-eips",
"alloy-primitives",
@@ -201,9 +201,9 @@ dependencies = [
[[package]]
name = "alloy-consensus-any"
version = "1.1.2"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15d0bea09287942405c4f9d2a4f22d1e07611c2dbd9d5bf94b75366340f9e6e0"
checksum = "364380a845193a317bcb7a5398fc86cdb66c47ebe010771dde05f6869bf9e64a"
dependencies = [
"alloy-consensus",
"alloy-eips",
@@ -253,9 +253,9 @@ dependencies = [
[[package]]
name = "alloy-eips"
version = "1.1.2"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bd2c7ae05abcab4483ce821f12f285e01c0b33804e6883dd9ca1569a87ee2be"
checksum = "a4c4d7c5839d9f3a467900c625416b24328450c65702eb3d8caff8813e4d1d33"
dependencies = [
"alloy-eip2124",
"alloy-eip2930",
@@ -288,9 +288,9 @@ dependencies = [
[[package]]
name = "alloy-json-rpc"
version = "1.1.2"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "003f46c54f22854a32b9cc7972660a476968008ad505427eabab49225309ec40"
checksum = "f72cf87cda808e593381fb9f005ffa4d2475552b7a6c5ac33d087bf77d82abd0"
dependencies = [
"alloy-primitives",
"alloy-sol-types",
@@ -303,9 +303,9 @@ dependencies = [
[[package]]
name = "alloy-network"
version = "1.1.2"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f4029954d9406a40979f3a3b46950928a0fdcfe3ea8a9b0c17490d57e8aa0e3"
checksum = "12aeb37b6f2e61b93b1c3d34d01ee720207c76fe447e2a2c217e433ac75b17f5"
dependencies = [
"alloy-consensus",
"alloy-consensus-any",
@@ -329,9 +329,9 @@ dependencies = [
[[package]]
name = "alloy-network-primitives"
version = "1.1.2"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7805124ad69e57bbae7731c9c344571700b2a18d351bda9e0eba521c991d1bcb"
checksum = "abd29ace62872083e30929cd9b282d82723196d196db589f3ceda67edcc05552"
dependencies = [
"alloy-consensus",
"alloy-eips",
@@ -391,9 +391,9 @@ dependencies = [
[[package]]
name = "alloy-rpc-types-any"
version = "1.1.2"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b43c1622aac2508d528743fd4cfdac1dea92d5a8fa894038488ff7edd0af0b32"
checksum = "6a63fb40ed24e4c92505f488f9dd256e2afaed17faa1b7a221086ebba74f4122"
dependencies = [
"alloy-consensus-any",
"alloy-rpc-types-eth",
@@ -402,9 +402,9 @@ dependencies = [
[[package]]
name = "alloy-rpc-types-eth"
version = "1.1.2"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed5fafb741c19b3cca4cdd04fa215c89413491f9695a3e928dee2ae5657f607e"
checksum = "9eae0c7c40da20684548cbc8577b6b7447f7bf4ddbac363df95e3da220e41e72"
dependencies = [
"alloy-consensus",
"alloy-consensus-any",
@@ -423,9 +423,9 @@ dependencies = [
[[package]]
name = "alloy-serde"
version = "1.1.2"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6f180c399ca7c1e2fe17ea58343910cad0090878a696ff5a50241aee12fc529"
checksum = "c0df1987ed0ff2d0159d76b52e7ddfc4e4fbddacc54d2fbee765e0d14d7c01b5"
dependencies = [
"alloy-primitives",
"serde",
@@ -434,9 +434,9 @@ dependencies = [
[[package]]
name = "alloy-signer"
version = "1.1.2"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecc39ad2c0a3d2da8891f4081565780703a593f090f768f884049aa3aa929cbc"
checksum = "6ff69deedee7232d7ce5330259025b868c5e6a52fa8dffda2c861fb3a5889b24"
dependencies = [
"alloy-primitives",
"async-trait",
@@ -449,9 +449,9 @@ dependencies = [
[[package]]
name = "alloy-signer-local"
version = "1.1.2"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "930e17cb1e46446a193a593a3bfff8d0ecee4e510b802575ebe300ae2e43ef75"
checksum = "72cfe0be3ec5a8c1a46b2e5a7047ed41121d360d97f4405bb7c1c784880c86cb"
dependencies = [
"alloy-consensus",
"alloy-network",
@@ -551,9 +551,9 @@ dependencies = [
[[package]]
name = "alloy-tx-macros"
version = "1.1.2"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae109e33814b49fc0a62f2528993aa8a2dd346c26959b151f05441dc0b9da292"
checksum = "333544408503f42d7d3792bfc0f7218b643d968a03d2c0ed383ae558fb4a76d0"
dependencies = [
"darling 0.21.3",
"proc-macro2",
@@ -1783,9 +1783,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cc"
version = "1.2.48"
version = "1.2.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c481bdbf0ed3b892f6f806287d72acd515b352a4ec27a208489b8c1bc839633a"
checksum = "90583009037521a116abf44494efecd645ba48b6622457080f080b85544e2215"
dependencies = [
"find-msvc-tools",
"shlex",
@@ -2026,7 +2026,7 @@ checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"
[[package]]
name = "clmul"
version = "0.1.0-alpha.4"
source = "git+https://github.com/privacy-ethereum/mpz?rev=9c343f8#9c343f86d386bc1360d6ac0a37eb1af65f48216a"
source = "git+https://github.com/privacy-ethereum/mpz?branch=feat%2Fpredicate_on_dev#59e65304af8619ddc69b77b7dd2a9b0ca7219eec"
dependencies = [
"bytemuck",
"cfg-if",
@@ -3747,9 +3747,9 @@ checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a"
[[package]]
name = "icu_properties"
version = "2.1.1"
version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99"
checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec"
dependencies = [
"icu_collections",
"icu_locale_core",
@@ -3761,9 +3761,9 @@ dependencies = [
[[package]]
name = "icu_properties_data"
version = "2.1.1"
version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899"
checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af"
[[package]]
name = "icu_provider"
@@ -4225,7 +4225,7 @@ checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
[[package]]
name = "matrix-transpose"
version = "0.1.0-alpha.4"
source = "git+https://github.com/privacy-ethereum/mpz?rev=9c343f8#9c343f86d386bc1360d6ac0a37eb1af65f48216a"
source = "git+https://github.com/privacy-ethereum/mpz?branch=feat%2Fpredicate_on_dev#59e65304af8619ddc69b77b7dd2a9b0ca7219eec"
dependencies = [
"thiserror 1.0.69",
]
@@ -4270,9 +4270,9 @@ dependencies = [
[[package]]
name = "mio"
version = "1.1.0"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873"
checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc"
dependencies = [
"libc",
"wasi",
@@ -4282,7 +4282,7 @@ dependencies = [
[[package]]
name = "mpz-circuits"
version = "0.1.0-alpha.4"
source = "git+https://github.com/privacy-ethereum/mpz?rev=9c343f8#9c343f86d386bc1360d6ac0a37eb1af65f48216a"
source = "git+https://github.com/privacy-ethereum/mpz?branch=feat%2Fpredicate_on_dev#59e65304af8619ddc69b77b7dd2a9b0ca7219eec"
dependencies = [
"mpz-circuits-core",
"mpz-circuits-data",
@@ -4291,7 +4291,7 @@ dependencies = [
[[package]]
name = "mpz-circuits-core"
version = "0.1.0-alpha.4"
source = "git+https://github.com/privacy-ethereum/mpz?rev=9c343f8#9c343f86d386bc1360d6ac0a37eb1af65f48216a"
source = "git+https://github.com/privacy-ethereum/mpz?branch=feat%2Fpredicate_on_dev#59e65304af8619ddc69b77b7dd2a9b0ca7219eec"
dependencies = [
"bincode 1.3.3",
"itybity 0.3.1",
@@ -4306,7 +4306,7 @@ dependencies = [
[[package]]
name = "mpz-circuits-data"
version = "0.1.0-alpha.4"
source = "git+https://github.com/privacy-ethereum/mpz?rev=9c343f8#9c343f86d386bc1360d6ac0a37eb1af65f48216a"
source = "git+https://github.com/privacy-ethereum/mpz?branch=feat%2Fpredicate_on_dev#59e65304af8619ddc69b77b7dd2a9b0ca7219eec"
dependencies = [
"bincode 1.3.3",
"mpz-circuits-core",
@@ -4316,7 +4316,7 @@ dependencies = [
[[package]]
name = "mpz-cointoss"
version = "0.1.0-alpha.4"
source = "git+https://github.com/privacy-ethereum/mpz?rev=9c343f8#9c343f86d386bc1360d6ac0a37eb1af65f48216a"
source = "git+https://github.com/privacy-ethereum/mpz?branch=feat%2Fpredicate_on_dev#59e65304af8619ddc69b77b7dd2a9b0ca7219eec"
dependencies = [
"futures",
"mpz-cointoss-core",
@@ -4329,7 +4329,7 @@ dependencies = [
[[package]]
name = "mpz-cointoss-core"
version = "0.1.0-alpha.4"
source = "git+https://github.com/privacy-ethereum/mpz?rev=9c343f8#9c343f86d386bc1360d6ac0a37eb1af65f48216a"
source = "git+https://github.com/privacy-ethereum/mpz?branch=feat%2Fpredicate_on_dev#59e65304af8619ddc69b77b7dd2a9b0ca7219eec"
dependencies = [
"mpz-core",
"opaque-debug",
@@ -4340,7 +4340,7 @@ dependencies = [
[[package]]
name = "mpz-common"
version = "0.1.0-alpha.4"
source = "git+https://github.com/privacy-ethereum/mpz?rev=9c343f8#9c343f86d386bc1360d6ac0a37eb1af65f48216a"
source = "git+https://github.com/privacy-ethereum/mpz?branch=feat%2Fpredicate_on_dev#59e65304af8619ddc69b77b7dd2a9b0ca7219eec"
dependencies = [
"async-trait",
"bytes",
@@ -4360,7 +4360,7 @@ dependencies = [
[[package]]
name = "mpz-core"
version = "0.1.0-alpha.4"
source = "git+https://github.com/privacy-ethereum/mpz?rev=9c343f8#9c343f86d386bc1360d6ac0a37eb1af65f48216a"
source = "git+https://github.com/privacy-ethereum/mpz?branch=feat%2Fpredicate_on_dev#59e65304af8619ddc69b77b7dd2a9b0ca7219eec"
dependencies = [
"aes 0.9.0-rc.2",
"bcs",
@@ -4386,7 +4386,7 @@ dependencies = [
[[package]]
name = "mpz-fields"
version = "0.1.0-alpha.4"
source = "git+https://github.com/privacy-ethereum/mpz?rev=9c343f8#9c343f86d386bc1360d6ac0a37eb1af65f48216a"
source = "git+https://github.com/privacy-ethereum/mpz?branch=feat%2Fpredicate_on_dev#59e65304af8619ddc69b77b7dd2a9b0ca7219eec"
dependencies = [
"ark-ff 0.4.2",
"ark-secp256r1",
@@ -4406,7 +4406,7 @@ dependencies = [
[[package]]
name = "mpz-garble"
version = "0.1.0-alpha.4"
source = "git+https://github.com/privacy-ethereum/mpz?rev=9c343f8#9c343f86d386bc1360d6ac0a37eb1af65f48216a"
source = "git+https://github.com/privacy-ethereum/mpz?branch=feat%2Fpredicate_on_dev#59e65304af8619ddc69b77b7dd2a9b0ca7219eec"
dependencies = [
"async-trait",
"derive_builder 0.11.2",
@@ -4421,7 +4421,7 @@ dependencies = [
"mpz-vm-core",
"opaque-debug",
"rand 0.9.2",
"rangeset 0.2.0",
"rangeset",
"serde",
"serio",
"thiserror 1.0.69",
@@ -4432,7 +4432,7 @@ dependencies = [
[[package]]
name = "mpz-garble-core"
version = "0.1.0-alpha.4"
source = "git+https://github.com/privacy-ethereum/mpz?rev=9c343f8#9c343f86d386bc1360d6ac0a37eb1af65f48216a"
source = "git+https://github.com/privacy-ethereum/mpz?branch=feat%2Fpredicate_on_dev#59e65304af8619ddc69b77b7dd2a9b0ca7219eec"
dependencies = [
"aes 0.9.0-rc.2",
"bitvec",
@@ -4452,7 +4452,7 @@ dependencies = [
"rand 0.9.2",
"rand_chacha 0.9.0",
"rand_core 0.9.3",
"rangeset 0.2.0",
"rangeset",
"rayon",
"serde",
"serde_arrays",
@@ -4463,7 +4463,7 @@ dependencies = [
[[package]]
name = "mpz-hash"
version = "0.1.0-alpha.4"
source = "git+https://github.com/privacy-ethereum/mpz?rev=9c343f8#9c343f86d386bc1360d6ac0a37eb1af65f48216a"
source = "git+https://github.com/privacy-ethereum/mpz?branch=feat%2Fpredicate_on_dev#59e65304af8619ddc69b77b7dd2a9b0ca7219eec"
dependencies = [
"blake3",
"itybity 0.3.1",
@@ -4476,7 +4476,7 @@ dependencies = [
[[package]]
name = "mpz-ideal-vm"
version = "0.1.0-alpha.4"
source = "git+https://github.com/privacy-ethereum/mpz?rev=9c343f8#9c343f86d386bc1360d6ac0a37eb1af65f48216a"
source = "git+https://github.com/privacy-ethereum/mpz?branch=feat%2Fpredicate_on_dev#59e65304af8619ddc69b77b7dd2a9b0ca7219eec"
dependencies = [
"async-trait",
"futures",
@@ -4484,7 +4484,7 @@ dependencies = [
"mpz-core",
"mpz-memory-core",
"mpz-vm-core",
"rangeset 0.2.0",
"rangeset",
"serde",
"serio",
"thiserror 1.0.69",
@@ -4493,14 +4493,14 @@ dependencies = [
[[package]]
name = "mpz-memory-core"
version = "0.1.0-alpha.4"
source = "git+https://github.com/privacy-ethereum/mpz?rev=9c343f8#9c343f86d386bc1360d6ac0a37eb1af65f48216a"
source = "git+https://github.com/privacy-ethereum/mpz?branch=feat%2Fpredicate_on_dev#59e65304af8619ddc69b77b7dd2a9b0ca7219eec"
dependencies = [
"blake3",
"futures",
"itybity 0.3.1",
"mpz-core",
"rand 0.9.2",
"rangeset 0.2.0",
"rangeset",
"serde",
"thiserror 1.0.69",
]
@@ -4508,7 +4508,7 @@ dependencies = [
[[package]]
name = "mpz-ole"
version = "0.1.0-alpha.4"
source = "git+https://github.com/privacy-ethereum/mpz?rev=9c343f8#9c343f86d386bc1360d6ac0a37eb1af65f48216a"
source = "git+https://github.com/privacy-ethereum/mpz?branch=feat%2Fpredicate_on_dev#59e65304af8619ddc69b77b7dd2a9b0ca7219eec"
dependencies = [
"async-trait",
"futures",
@@ -4526,7 +4526,7 @@ dependencies = [
[[package]]
name = "mpz-ole-core"
version = "0.1.0-alpha.4"
source = "git+https://github.com/privacy-ethereum/mpz?rev=9c343f8#9c343f86d386bc1360d6ac0a37eb1af65f48216a"
source = "git+https://github.com/privacy-ethereum/mpz?branch=feat%2Fpredicate_on_dev#59e65304af8619ddc69b77b7dd2a9b0ca7219eec"
dependencies = [
"hybrid-array",
"itybity 0.3.1",
@@ -4542,7 +4542,7 @@ dependencies = [
[[package]]
name = "mpz-ot"
version = "0.1.0-alpha.4"
source = "git+https://github.com/privacy-ethereum/mpz?rev=9c343f8#9c343f86d386bc1360d6ac0a37eb1af65f48216a"
source = "git+https://github.com/privacy-ethereum/mpz?branch=feat%2Fpredicate_on_dev#59e65304af8619ddc69b77b7dd2a9b0ca7219eec"
dependencies = [
"async-trait",
"cfg-if",
@@ -4565,7 +4565,7 @@ dependencies = [
[[package]]
name = "mpz-ot-core"
version = "0.1.0-alpha.4"
source = "git+https://github.com/privacy-ethereum/mpz?rev=9c343f8#9c343f86d386bc1360d6ac0a37eb1af65f48216a"
source = "git+https://github.com/privacy-ethereum/mpz?branch=feat%2Fpredicate_on_dev#59e65304af8619ddc69b77b7dd2a9b0ca7219eec"
dependencies = [
"aes 0.9.0-rc.2",
"blake3",
@@ -4593,10 +4593,26 @@ dependencies = [
"zerocopy",
]
[[package]]
name = "mpz-predicate"
version = "0.1.0-alpha.14-pre"
source = "git+https://github.com/privacy-ethereum/mpz?branch=feat%2Fpredicate_on_dev#59e65304af8619ddc69b77b7dd2a9b0ca7219eec"
dependencies = [
"bytes",
"mpz-circuits",
"rand 0.9.2",
"rand_chacha 0.9.0",
"rand_core 0.9.3",
"rangeset",
"serde",
"serde_json",
"thiserror 1.0.69",
]
[[package]]
name = "mpz-share-conversion"
version = "0.1.0-alpha.4"
source = "git+https://github.com/privacy-ethereum/mpz?rev=9c343f8#9c343f86d386bc1360d6ac0a37eb1af65f48216a"
source = "git+https://github.com/privacy-ethereum/mpz?branch=feat%2Fpredicate_on_dev#59e65304af8619ddc69b77b7dd2a9b0ca7219eec"
dependencies = [
"async-trait",
"mpz-common",
@@ -4612,7 +4628,7 @@ dependencies = [
[[package]]
name = "mpz-share-conversion-core"
version = "0.1.0-alpha.4"
source = "git+https://github.com/privacy-ethereum/mpz?rev=9c343f8#9c343f86d386bc1360d6ac0a37eb1af65f48216a"
source = "git+https://github.com/privacy-ethereum/mpz?branch=feat%2Fpredicate_on_dev#59e65304af8619ddc69b77b7dd2a9b0ca7219eec"
dependencies = [
"mpz-common",
"mpz-core",
@@ -4626,7 +4642,7 @@ dependencies = [
[[package]]
name = "mpz-vm-core"
version = "0.1.0-alpha.4"
source = "git+https://github.com/privacy-ethereum/mpz?rev=9c343f8#9c343f86d386bc1360d6ac0a37eb1af65f48216a"
source = "git+https://github.com/privacy-ethereum/mpz?branch=feat%2Fpredicate_on_dev#59e65304af8619ddc69b77b7dd2a9b0ca7219eec"
dependencies = [
"async-trait",
"futures",
@@ -4639,7 +4655,7 @@ dependencies = [
[[package]]
name = "mpz-zk"
version = "0.1.0-alpha.4"
source = "git+https://github.com/privacy-ethereum/mpz?rev=9c343f8#9c343f86d386bc1360d6ac0a37eb1af65f48216a"
source = "git+https://github.com/privacy-ethereum/mpz?branch=feat%2Fpredicate_on_dev#59e65304af8619ddc69b77b7dd2a9b0ca7219eec"
dependencies = [
"async-trait",
"blake3",
@@ -4657,7 +4673,7 @@ dependencies = [
[[package]]
name = "mpz-zk-core"
version = "0.1.0-alpha.4"
source = "git+https://github.com/privacy-ethereum/mpz?rev=9c343f8#9c343f86d386bc1360d6ac0a37eb1af65f48216a"
source = "git+https://github.com/privacy-ethereum/mpz?branch=feat%2Fpredicate_on_dev#59e65304af8619ddc69b77b7dd2a9b0ca7219eec"
dependencies = [
"blake3",
"cfg-if",
@@ -4666,7 +4682,7 @@ dependencies = [
"mpz-core",
"mpz-memory-core",
"mpz-vm-core",
"rangeset 0.2.0",
"rangeset",
"rayon",
"serde",
"thiserror 1.0.69",
@@ -5442,7 +5458,7 @@ version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983"
dependencies = [
"toml_edit 0.23.7",
"toml_edit 0.23.9",
]
[[package]]
@@ -5759,15 +5775,6 @@ version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbbbbea733ec66275512d0b9694f34102e7d5406fdbe2ad8d21b28dce92887c"
[[package]]
name = "rangeset"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fc7af00a06ad692080d87495a904677592c662610edb82b4fc8782f4ed2f01f"
dependencies = [
"serde",
]
[[package]]
name = "rangeset"
version = "0.4.0"
@@ -5857,9 +5864,9 @@ checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
[[package]]
name = "reqwest"
version = "0.12.24"
version = "0.12.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f"
checksum = "b6eff9328d40131d43bd911d42d79eb6a47312002a4daefc9e37f17e74a7701a"
dependencies = [
"base64 0.22.1",
"bytes",
@@ -5886,7 +5893,7 @@ dependencies = [
"tokio",
"tokio-rustls",
"tower",
"tower-http 0.6.7",
"tower-http 0.6.8",
"tower-service",
"url",
"wasm-bindgen",
@@ -6744,9 +6751,9 @@ dependencies = [
[[package]]
name = "simd-adler32"
version = "0.3.7"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
[[package]]
name = "sized-chunks"
@@ -6810,9 +6817,9 @@ checksum = "bceb57dc07c92cdae60f5b27b3fa92ecaaa42fe36c55e22dbfb0b44893e0b1f7"
[[package]]
name = "sourcemap"
version = "9.2.2"
version = "9.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e22afbcb92ce02d23815b9795523c005cb9d3c214f8b7a66318541c240ea7935"
checksum = "37ccaaa78a0ca68b20f8f711eaa2522a00131c48a3de5b892ca5c36cec1ce9bb"
dependencies = [
"base64-simd",
"bitvec",
@@ -6835,7 +6842,7 @@ dependencies = [
"httparse",
"pest",
"pest_derive",
"rangeset 0.4.0",
"rangeset",
"serde",
"thiserror 1.0.69",
]
@@ -6988,9 +6995,9 @@ dependencies = [
[[package]]
name = "sys_traits"
version = "0.1.19"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1495a604cd38eeb30c408724966cd31ca1b68b5a97e3afc474c0d719bfeec5a"
checksum = "6b61f4a25d0baba25511bed00c39c199d9a19cfd8107f4472724b72a84f530b1"
dependencies = [
"sys_traits_macros",
]
@@ -7224,12 +7231,13 @@ dependencies = [
"mpz-memory-core",
"mpz-ole",
"mpz-ot",
"mpz-predicate",
"mpz-vm-core",
"mpz-zk",
"once_cell",
"opaque-debug",
"rand 0.9.2",
"rangeset 0.4.0",
"rangeset",
"rstest",
"rustls-pki-types",
"rustls-webpki 0.103.8",
@@ -7308,11 +7316,12 @@ dependencies = [
"generic-array",
"hex",
"itybity 0.2.1",
"mpz-predicate",
"opaque-debug",
"rand 0.9.2",
"rand_chacha 0.9.0",
"rand_core 0.9.3",
"rangeset 0.4.0",
"rangeset",
"rs_merkle",
"rstest",
"rustls-pki-types",
@@ -7347,7 +7356,7 @@ dependencies = [
"mpz-core",
"mpz-ideal-vm",
"mpz-vm-core",
"rangeset 0.4.0",
"rangeset",
"serde",
"serio",
"thiserror 1.0.69",
@@ -7368,12 +7377,15 @@ dependencies = [
"hyper",
"hyper-util",
"k256",
"mpz-predicate",
"noir",
"rangeset",
"serde",
"serde_json",
"spansy",
"tls-server-fixture",
"tlsn",
"tlsn-core",
"tlsn-formats",
"tlsn-server-fixture",
"tlsn-server-fixture-certs",
@@ -7590,7 +7602,7 @@ dependencies = [
"tokio",
"tokio-util",
"tower",
"tower-http 0.6.7",
"tower-http 0.6.8",
"tower-service",
"tracing",
"tracing-subscriber",
@@ -7851,9 +7863,9 @@ dependencies = [
[[package]]
name = "toml_edit"
version = "0.23.7"
version = "0.23.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d"
checksum = "5d7cbc3b4b49633d57a0509303158ca50de80ae32c265093b24c414705807832"
dependencies = [
"indexmap 2.12.1",
"toml_datetime 0.7.3",
@@ -7919,9 +7931,9 @@ dependencies = [
[[package]]
name = "tower-http"
version = "0.6.7"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cf146f99d442e8e68e585f5d798ccd3cad9a7835b917e09728880a862706456"
checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8"
dependencies = [
"bitflags",
"bytes",

View File

@@ -66,21 +66,21 @@ tlsn-harness-runner = { path = "crates/harness/runner" }
tlsn-wasm = { path = "crates/wasm" }
tlsn = { path = "crates/tlsn" }
mpz-circuits = { git = "https://github.com/privacy-ethereum/mpz", rev = "9c343f8" }
mpz-circuits-data = { git = "https://github.com/privacy-ethereum/mpz", rev = "9c343f8" }
mpz-memory-core = { git = "https://github.com/privacy-ethereum/mpz", rev = "9c343f8" }
mpz-common = { git = "https://github.com/privacy-ethereum/mpz", rev = "9c343f8" }
mpz-core = { git = "https://github.com/privacy-ethereum/mpz", rev = "9c343f8" }
mpz-vm-core = { git = "https://github.com/privacy-ethereum/mpz", rev = "9c343f8" }
mpz-garble = { git = "https://github.com/privacy-ethereum/mpz", rev = "9c343f8" }
mpz-garble-core = { git = "https://github.com/privacy-ethereum/mpz", rev = "9c343f8" }
mpz-ole = { git = "https://github.com/privacy-ethereum/mpz", rev = "9c343f8" }
mpz-ot = { git = "https://github.com/privacy-ethereum/mpz", rev = "9c343f8" }
mpz-share-conversion = { git = "https://github.com/privacy-ethereum/mpz", rev = "9c343f8" }
mpz-fields = { git = "https://github.com/privacy-ethereum/mpz", rev = "9c343f8" }
mpz-zk = { git = "https://github.com/privacy-ethereum/mpz", rev = "9c343f8" }
mpz-hash = { git = "https://github.com/privacy-ethereum/mpz", rev = "9c343f8" }
mpz-ideal-vm = { git = "https://github.com/privacy-ethereum/mpz", rev = "9c343f8" }
mpz-circuits = { git = "https://github.com/privacy-ethereum/mpz", branch = "feat/predicate_on_dev" }
mpz-common = { git = "https://github.com/privacy-ethereum/mpz", branch = "feat/predicate_on_dev" }
mpz-core = { git = "https://github.com/privacy-ethereum/mpz", branch = "feat/predicate_on_dev" }
mpz-fields = { git = "https://github.com/privacy-ethereum/mpz", branch = "feat/predicate_on_dev" }
mpz-garble = { git = "https://github.com/privacy-ethereum/mpz", branch = "feat/predicate_on_dev" }
mpz-garble-core = { git = "https://github.com/privacy-ethereum/mpz", branch = "feat/predicate_on_dev" }
mpz-hash = { git = "https://github.com/privacy-ethereum/mpz", branch = "feat/predicate_on_dev" }
mpz-ideal-vm = { git = "https://github.com/privacy-ethereum/mpz", branch = "feat/predicate_on_dev" }
mpz-memory-core = { git = "https://github.com/privacy-ethereum/mpz", branch = "feat/predicate_on_dev" }
mpz-ole = { git = "https://github.com/privacy-ethereum/mpz", branch = "feat/predicate_on_dev" }
mpz-ot = { git = "https://github.com/privacy-ethereum/mpz", branch = "feat/predicate_on_dev" }
mpz-predicate = { git = "https://github.com/privacy-ethereum/mpz", branch = "feat/predicate_on_dev" }
mpz-share-conversion = { git = "https://github.com/privacy-ethereum/mpz", branch = "feat/predicate_on_dev" }
mpz-vm-core = { git = "https://github.com/privacy-ethereum/mpz", branch = "feat/predicate_on_dev" }
mpz-zk = { git = "https://github.com/privacy-ethereum/mpz", branch = "feat/predicate_on_dev" }
rangeset = { version = "0.4" }
serio = { version = "0.2" }

View File

@@ -27,6 +27,7 @@ tlsn-data-fixtures = { workspace = true, optional = true }
tlsn-tls-core = { workspace = true, features = ["serde"] }
tlsn-utils = { workspace = true }
rangeset = { workspace = true, features = ["serde"] }
mpz-predicate = { workspace = true }
aead = { workspace = true, features = ["alloc"], optional = true }
aes-gcm = { workspace = true, optional = true }

View File

@@ -1,16 +1,119 @@
//! Proving configuration.
use mpz_predicate::Pred;
use rangeset::set::{RangeSet, ToRangeSet};
use serde::{Deserialize, Serialize};
use crate::transcript::{Direction, Transcript, TranscriptCommitConfig, TranscriptCommitRequest};
/// Configuration to prove information to the verifier.
/// Configuration for a predicate to prove over transcript data.
///
/// A predicate is a boolean constraint that operates on transcript bytes.
/// The prover proves in ZK that the predicate evaluates to true.
///
/// The predicate itself encodes which byte indices it operates on via its
/// atomic comparisons (e.g., `gte(42, threshold)` operates on byte index 42).
#[derive(Debug, Clone)]
pub struct PredicateConfig {
/// Human-readable name for the predicate (sent to verifier as sanity
/// check).
name: String,
/// Direction of transcript data the predicate operates on.
direction: Direction,
/// The predicate to prove.
predicate: Pred,
}
impl PredicateConfig {
/// Creates a new predicate configuration.
///
/// # Arguments
///
/// * `name` - Human-readable name for the predicate.
/// * `direction` - Whether the predicate operates on sent or received data.
/// * `predicate` - The predicate to prove.
pub fn new(name: impl Into<String>, direction: Direction, predicate: Pred) -> Self {
Self {
name: name.into(),
direction,
predicate,
}
}
/// Returns the predicate name.
pub fn name(&self) -> &str {
&self.name
}
/// Returns the direction of transcript data.
pub fn direction(&self) -> Direction {
self.direction
}
/// Returns the predicate.
pub fn predicate(&self) -> &Pred {
&self.predicate
}
/// Returns the transcript byte indices this predicate operates on.
pub fn indices(&self) -> Vec<usize> {
self.predicate.indices()
}
/// Converts to a request (wire format).
pub fn to_request(&self) -> PredicateRequest {
let indices: RangeSet<usize> = self
.predicate
.indices()
.into_iter()
.map(|idx| idx..idx + 1)
.collect();
PredicateRequest {
name: self.name.clone(),
direction: self.direction,
indices,
}
}
}
/// Wire format for predicate proving request.
///
/// Contains only the predicate name and indices - the verifier is expected
/// to know which predicate corresponds to the name from out-of-band agreement.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PredicateRequest {
/// Human-readable name for the predicate.
name: String,
/// Direction of transcript data the predicate operates on.
direction: Direction,
/// Transcript byte indices the predicate operates on.
indices: RangeSet<usize>,
}
impl PredicateRequest {
/// Returns the predicate name.
pub fn name(&self) -> &str {
&self.name
}
/// Returns the direction of transcript data.
pub fn direction(&self) -> Direction {
self.direction
}
/// Returns the transcript byte indices as a RangeSet.
pub fn indices(&self) -> &RangeSet<usize> {
&self.indices
}
}
/// Configuration to prove information to the verifier.
#[derive(Debug, Clone)]
pub struct ProveConfig {
server_identity: bool,
reveal: Option<(RangeSet<usize>, RangeSet<usize>)>,
transcript_commit: Option<TranscriptCommitConfig>,
predicates: Vec<PredicateConfig>,
}
impl ProveConfig {
@@ -35,6 +138,11 @@ impl ProveConfig {
self.transcript_commit.as_ref()
}
/// Returns the predicate configurations.
pub fn predicates(&self) -> &[PredicateConfig] {
&self.predicates
}
/// Returns a request.
pub fn to_request(&self) -> ProveRequest {
ProveRequest {
@@ -44,6 +152,7 @@ impl ProveConfig {
.transcript_commit
.clone()
.map(|config| config.to_request()),
predicates: self.predicates.iter().map(|p| p.to_request()).collect(),
}
}
}
@@ -55,6 +164,7 @@ pub struct ProveConfigBuilder<'a> {
server_identity: bool,
reveal: Option<(RangeSet<usize>, RangeSet<usize>)>,
transcript_commit: Option<TranscriptCommitConfig>,
predicates: Vec<PredicateConfig>,
}
impl<'a> ProveConfigBuilder<'a> {
@@ -65,6 +175,7 @@ impl<'a> ProveConfigBuilder<'a> {
server_identity: false,
reveal: None,
transcript_commit: None,
predicates: Vec::new(),
}
}
@@ -137,12 +248,52 @@ impl<'a> ProveConfigBuilder<'a> {
Ok(self)
}
/// Adds a predicate to prove over transcript data.
///
/// The predicate encodes which byte indices it operates on via its atomic
/// comparisons (e.g., `gte(42, threshold)` operates on byte index 42).
///
/// # Arguments
///
/// * `name` - Human-readable name for the predicate (sent to verifier as
/// sanity check).
/// * `direction` - Whether the predicate operates on sent or received data.
/// * `predicate` - The predicate to prove.
pub fn predicate(
&mut self,
name: impl Into<String>,
direction: Direction,
predicate: Pred,
) -> Result<&mut Self, ProveConfigError> {
let indices = predicate.indices();
// Predicate must reference at least one transcript byte.
let last_idx = *indices
.last()
.ok_or(ProveConfigError(ErrorRepr::EmptyPredicate))?;
// Since indices are sorted, only check the last one for bounds.
let transcript_len = self.transcript.len_of_direction(direction);
if last_idx >= transcript_len {
return Err(ProveConfigError(ErrorRepr::IndexOutOfBounds {
direction,
actual: last_idx,
len: transcript_len,
}));
}
self.predicates
.push(PredicateConfig::new(name, direction, predicate));
Ok(self)
}
/// Builds the configuration.
pub fn build(self) -> Result<ProveConfig, ProveConfigError> {
Ok(ProveConfig {
server_identity: self.server_identity,
reveal: self.reveal,
transcript_commit: self.transcript_commit,
predicates: self.predicates,
})
}
}
@@ -153,6 +304,7 @@ pub struct ProveRequest {
server_identity: bool,
reveal: Option<(RangeSet<usize>, RangeSet<usize>)>,
transcript_commit: Option<TranscriptCommitRequest>,
predicates: Vec<PredicateRequest>,
}
impl ProveRequest {
@@ -171,6 +323,11 @@ impl ProveRequest {
pub fn transcript_commit(&self) -> Option<&TranscriptCommitRequest> {
self.transcript_commit.as_ref()
}
/// Returns the predicate requests.
pub fn predicates(&self) -> &[PredicateRequest] {
&self.predicates
}
}
/// Error for [`ProveConfig`].
@@ -180,10 +337,12 @@ pub struct ProveConfigError(#[from] ErrorRepr);
#[derive(Debug, thiserror::Error)]
enum ErrorRepr {
#[error("range is out of bounds of the transcript ({direction}): {actual} > {len}")]
#[error("index out of bounds for {direction} transcript: {actual} >= {len}")]
IndexOutOfBounds {
direction: Direction,
actual: usize,
len: usize,
},
#[error("predicate must reference at least one transcript byte")]
EmptyPredicate,
}

View File

@@ -10,10 +10,13 @@ workspace = true
[dependencies]
tlsn = { workspace = true }
tlsn-formats = { workspace = true }
tlsn-core = { workspace = true }
tls-server-fixture = { workspace = true }
tlsn-server-fixture = { workspace = true }
tlsn-server-fixture-certs = { workspace = true }
spansy = { workspace = true }
mpz-predicate = { workspace = true }
rangeset = { workspace = true }
anyhow = { workspace = true }
bincode = { workspace = true }
@@ -61,3 +64,7 @@ path = "attestation/present.rs"
[[example]]
name = "attestation_verify"
path = "attestation/verify.rs"
[[example]]
name = "interactive_predicate"
path = "interactive_predicate/interactive_predicate.rs"

View File

@@ -5,6 +5,7 @@ This folder contains examples demonstrating how to use the TLSNotary protocol.
* [Interactive](./interactive/README.md): Interactive Prover and Verifier session without a trusted notary.
* [Attestation](./attestation/README.md): Performing a simple notarization with a trusted notary.
* [Interactive_zk](./interactive_zk/README.md): Interactive Prover and Verifier session demonstrating zero-knowledge age verification using Noir.
* [Interactive_predicate](./interactive_predicate/README.md): Interactive session demonstrating predicate proving over transcript data (e.g., proving a JSON field is a valid string without revealing it).
Refer to <https://tlsnotary.org/docs/quick_start> for a quick start guide to using TLSNotary with these examples.

View File

@@ -33,6 +33,7 @@ web-spawn = { workspace = true, optional = true }
mpz-circuits = { workspace = true, features = ["aes"] }
mpz-common = { workspace = true }
mpz-core = { workspace = true }
mpz-predicate = { workspace = true }
mpz-garble = { workspace = true }
mpz-garble-core = { workspace = true }
mpz-hash = { workspace = true }

View File

@@ -49,6 +49,13 @@ impl ProverError {
{
Self::new(ErrorKind::Commit, source)
}
pub(crate) fn predicate<E>(source: E) -> Self
where
E: Into<Box<dyn Error + Send + Sync + 'static>>,
{
Self::new(ErrorKind::Predicate, source)
}
}
#[derive(Debug)]
@@ -58,6 +65,7 @@ enum ErrorKind {
Zk,
Config,
Commit,
Predicate,
}
impl fmt::Display for ProverError {
@@ -70,6 +78,7 @@ impl fmt::Display for ProverError {
ErrorKind::Zk => f.write_str("zk error")?,
ErrorKind::Config => f.write_str("config error")?,
ErrorKind::Commit => f.write_str("commit error")?,
ErrorKind::Predicate => f.write_str("predicate error")?,
}
if let Some(source) = &self.source {

View File

@@ -20,6 +20,7 @@ use crate::{
encoding::{self, MacStore},
hash::prove_hash,
},
predicate::prove_predicates,
},
};
@@ -54,6 +55,20 @@ pub(crate) async fn prove<T: Vm<Binary> + MacStore + Send + Sync>(
});
}
// Build predicate ranges from config
let (mut predicate_sent, mut predicate_recv) = (RangeSet::default(), RangeSet::default());
for predicate in config.predicates() {
let indices: RangeSet<usize> = predicate
.indices()
.into_iter()
.map(|idx| idx..idx + 1)
.collect();
match predicate.direction() {
Direction::Sent => predicate_sent.union_mut(&indices),
Direction::Received => predicate_recv.union_mut(&indices),
}
}
let transcript_refs = TranscriptRefs {
sent: prove_plaintext(
vm,
@@ -66,6 +81,7 @@ pub(crate) async fn prove<T: Vm<Binary> + MacStore + Send + Sync>(
.filter(|record| record.typ == ContentType::ApplicationData),
&reveal_sent,
&commit_sent,
&predicate_sent,
)
.map_err(ProverError::commit)?,
recv: prove_plaintext(
@@ -79,6 +95,7 @@ pub(crate) async fn prove<T: Vm<Binary> + MacStore + Send + Sync>(
.filter(|record| record.typ == ContentType::ApplicationData),
&reveal_recv,
&commit_recv,
&predicate_recv,
)
.map_err(ProverError::commit)?,
};
@@ -100,6 +117,12 @@ pub(crate) async fn prove<T: Vm<Binary> + MacStore + Send + Sync>(
None
};
// Prove predicates over transcript data
if !config.predicates().is_empty() {
prove_predicates(vm, &transcript_refs, config.predicates())
.map_err(ProverError::predicate)?;
}
vm.execute_all(ctx).await.map_err(ProverError::zk)?;
if let Some(commit_config) = config.transcript_commit()

View File

@@ -1,5 +1,6 @@
pub(crate) mod auth;
pub(crate) mod commit;
pub(crate) mod predicate;
use mpz_memory_core::{Vector, binary::U8};

View File

@@ -25,14 +25,15 @@ pub(crate) fn prove_plaintext<'a>(
records: impl IntoIterator<Item = &'a Record>,
reveal: &RangeSet<usize>,
commit: &RangeSet<usize>,
predicate: &RangeSet<usize>,
) -> Result<ReferenceMap, PlaintextAuthError> {
let is_reveal_all = reveal == (0..plaintext.len());
let is_reveal_all = reveal == (0..plaintext.len()) && predicate.is_empty();
let alloc_ranges = if is_reveal_all {
commit.clone()
} else {
// The plaintext is only partially revealed, so we need to authenticate in ZK.
commit.union(reveal).into_set()
commit.union(reveal).union(predicate).into_set()
};
let plaintext_refs = alloc_plaintext(vm, &alloc_ranges)?;
@@ -49,7 +50,8 @@ pub(crate) fn prove_plaintext<'a>(
vm.commit(*slice).map_err(PlaintextAuthError::vm)?;
}
} else {
let private = commit.difference(reveal).into_set();
// Private ranges: committed but not revealed, plus predicate ranges
let private = commit.difference(reveal).union(predicate).into_set();
for (_, slice) in plaintext_refs
.index(&private)
.expect("all ranges are allocated")
@@ -91,14 +93,15 @@ pub(crate) fn verify_plaintext<'a>(
records: impl IntoIterator<Item = &'a Record>,
reveal: &RangeSet<usize>,
commit: &RangeSet<usize>,
predicate: &RangeSet<usize>,
) -> Result<(ReferenceMap, PlaintextProof<'a>), PlaintextAuthError> {
let is_reveal_all = reveal == (0..plaintext.len());
let is_reveal_all = reveal == (0..plaintext.len()) && predicate.is_empty();
let alloc_ranges = if is_reveal_all {
commit.clone()
} else {
// The plaintext is only partially revealed, so we need to authenticate in ZK.
commit.union(reveal).into_set()
commit.union(reveal).union(predicate).into_set()
};
let plaintext_refs = alloc_plaintext(vm, &alloc_ranges)?;
@@ -123,9 +126,10 @@ pub(crate) fn verify_plaintext<'a>(
ciphertext,
})
} else {
let private = commit.difference(reveal).into_set();
// Blind ranges: committed but not revealed, plus predicate ranges
let blind = commit.difference(reveal).union(predicate).into_set();
for (_, slice) in plaintext_refs
.index(&private)
.index(&blind)
.expect("all ranges are allocated")
.iter()
{

View File

@@ -8,6 +8,7 @@ use std::sync::Arc;
pub use error::VerifierError;
pub use tlsn_core::{VerifierOutput, webpki::ServerCertVerifier};
pub use verify::PredicateResolver;
use crate::{
Role,
@@ -323,8 +324,24 @@ impl Verifier<state::Verify> {
}
/// Accepts the proving request.
///
/// Note: If the prover requests predicate verification, use
/// [`accept_with_predicates`](Self::accept_with_predicates) instead.
pub async fn accept(
self,
) -> Result<(VerifierOutput, Verifier<state::Committed>), VerifierError> {
self.accept_with_predicates(None).await
}
/// Accepts the proving request with predicate verification support.
///
/// # Arguments
///
/// * `predicate_resolver` - A function that resolves predicate names to
/// circuits. Required if the prover requests any predicates.
pub async fn accept_with_predicates(
self,
predicate_resolver: Option<&verify::PredicateResolver>,
) -> Result<(VerifierOutput, Verifier<state::Committed>), VerifierError> {
let state::Verify {
mux_ctrl,
@@ -353,6 +370,7 @@ impl Verifier<state::Verify> {
request,
handshake,
transcript,
predicate_resolver,
))
.await?;

View File

@@ -49,6 +49,13 @@ impl VerifierError {
{
Self::new(ErrorKind::Verify, source)
}
pub(crate) fn predicate<E>(source: E) -> Self
where
E: Into<Box<dyn Error + Send + Sync + 'static>>,
{
Self::new(ErrorKind::Predicate, source)
}
}
#[derive(Debug)]
@@ -59,6 +66,7 @@ enum ErrorKind {
Zk,
Commit,
Verify,
Predicate,
}
impl fmt::Display for VerifierError {
@@ -72,6 +80,7 @@ impl fmt::Display for VerifierError {
ErrorKind::Zk => f.write_str("zk error")?,
ErrorKind::Commit => f.write_str("commit error")?,
ErrorKind::Verify => f.write_str("verification error")?,
ErrorKind::Predicate => f.write_str("predicate error")?,
}
if let Some(source) = &self.source {

View File

@@ -1,6 +1,7 @@
use mpc_tls::SessionKeys;
use mpz_common::Context;
use mpz_memory_core::binary::Binary;
use mpz_predicate::Pred;
use mpz_vm_core::Vm;
use rangeset::set::RangeSet;
use tlsn_core::{
@@ -21,10 +22,24 @@ use crate::{
encoding::{self, KeyStore},
hash::verify_hash,
},
predicate::verify_predicates,
},
verifier::VerifierError,
};
/// A function that resolves predicate names to predicates.
///
/// The verifier must provide this to look up predicates by name,
/// based on out-of-band agreement with the prover.
///
/// The function receives:
/// - The predicate name
/// - The byte indices the predicate operates on (from the prover's request)
///
/// The verifier should validate that the indices make sense for the predicate
/// and return the appropriate predicate built with those indices.
pub type PredicateResolver = dyn Fn(&str, &RangeSet<usize>) -> Option<Pred> + Send + Sync;
#[allow(clippy::too_many_arguments)]
pub(crate) async fn verify<T: Vm<Binary> + KeyStore + Send + Sync>(
ctx: &mut Context,
@@ -35,6 +50,7 @@ pub(crate) async fn verify<T: Vm<Binary> + KeyStore + Send + Sync>(
request: ProveRequest,
handshake: Option<(ServerName, HandshakeData)>,
transcript: Option<PartialTranscript>,
predicate_resolver: Option<&PredicateResolver>,
) -> Result<VerifierOutput, VerifierError> {
let ciphertext_sent = collect_ciphertext(tls_transcript.sent());
let ciphertext_recv = collect_ciphertext(tls_transcript.recv());
@@ -101,6 +117,15 @@ pub(crate) async fn verify<T: Vm<Binary> + KeyStore + Send + Sync>(
}
}
// Build predicate ranges from request
let (mut predicate_sent, mut predicate_recv) = (RangeSet::default(), RangeSet::default());
for predicate_req in request.predicates() {
match predicate_req.direction() {
Direction::Sent => predicate_sent.union_mut(predicate_req.indices()),
Direction::Received => predicate_recv.union_mut(predicate_req.indices()),
}
}
let (sent_refs, sent_proof) = verify_plaintext(
vm,
keys.client_write_key,
@@ -113,6 +138,7 @@ pub(crate) async fn verify<T: Vm<Binary> + KeyStore + Send + Sync>(
.filter(|record| record.typ == ContentType::ApplicationData),
transcript.sent_authed(),
&commit_sent,
&predicate_sent,
)
.map_err(VerifierError::zk)?;
let (recv_refs, recv_proof) = verify_plaintext(
@@ -127,6 +153,7 @@ pub(crate) async fn verify<T: Vm<Binary> + KeyStore + Send + Sync>(
.filter(|record| record.typ == ContentType::ApplicationData),
transcript.received_authed(),
&commit_recv,
&predicate_recv,
)
.map_err(VerifierError::zk)?;
@@ -146,6 +173,26 @@ pub(crate) async fn verify<T: Vm<Binary> + KeyStore + Send + Sync>(
);
}
// Verify predicates if any were requested
if !request.predicates().is_empty() {
let resolver = predicate_resolver.ok_or_else(|| {
VerifierError::predicate("predicates requested but no resolver provided")
})?;
let predicates = request
.predicates()
.iter()
.map(|req| {
let predicate = resolver(req.name(), req.indices()).ok_or_else(|| {
VerifierError::predicate(format!("unknown predicate: {}", req.name()))
})?;
Ok((req.direction(), req.indices().clone(), predicate))
})
.collect::<Result<Vec<_>, VerifierError>>()?;
verify_predicates(vm, &transcript_refs, predicates).map_err(VerifierError::predicate)?;
}
vm.execute_all(ctx).await.map_err(VerifierError::zk)?;
sent_proof.verify().map_err(VerifierError::verify)?;