Reproducible rust bindings (#243)
* modify directory structure to isolate the generated bindings * add a lib.rs file * move deref impls to the extension file * remove unused types from generated bindings * cleanup new lines to reduce diff noise * reorder definitions to reduce diff noise * move sync and send impls to the extension file * generate bindings * blacklist used bindings; create snapshots dir to ensure freshness in the future * fix typo. Ty @pawanjay176 * run cargo build after merge * custom impl for KZGCommitment and KZGProof * final touches
This commit is contained in:
parent
88924c8aa7
commit
f384175810
|
@ -1,2 +1,2 @@
|
|||
src/consts.rs
|
||||
src/bindings/generated.rs
|
||||
target/
|
||||
|
|
|
@ -25,6 +25,27 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.64.0"
|
||||
source = "git+https://github.com/rust-lang/rust-bindgen?rev=0de11f0a521611ac8738b7b01d19dddaf3899e66#0de11f0a521611ac8738b7b01d19dddaf3899e66"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"lazy_static",
|
||||
"lazycell",
|
||||
"log",
|
||||
"peeking_take_while",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"rustc-hash",
|
||||
"shlex",
|
||||
"syn 2.0.8",
|
||||
"which",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
|
@ -33,14 +54,15 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.11.1"
|
||||
version = "3.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
|
||||
checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
|
||||
|
||||
[[package]]
|
||||
name = "c-kzg"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"criterion",
|
||||
"glob",
|
||||
"hex",
|
||||
|
@ -56,6 +78,15 @@ version = "0.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
|
||||
|
||||
[[package]]
|
||||
name = "cexpr"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
|
@ -89,6 +120,17 @@ dependencies = [
|
|||
"half",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77ed9a53e5d4d9c573ae844bfac6872b159cb1d1585a83b29e7a64b7eef7332a"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"libc",
|
||||
"libloading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.2.23"
|
||||
|
@ -148,9 +190,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.6"
|
||||
version = "0.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
|
||||
checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
|
@ -158,9 +200,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.2"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
|
||||
checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-epoch",
|
||||
|
@ -169,9 +211,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.13"
|
||||
version = "0.9.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
|
||||
checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
|
@ -182,18 +224,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.14"
|
||||
version = "0.8.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
|
||||
checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.8.0"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
|
||||
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
|
@ -269,15 +311,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.4"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
|
||||
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.60"
|
||||
version = "0.3.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
|
||||
checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
@ -289,10 +331,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.137"
|
||||
name = "lazycell"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
|
||||
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.140"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
|
@ -304,14 +362,36 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.7.1"
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.15"
|
||||
|
@ -333,9 +413,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.17.0"
|
||||
version = "1.17.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
|
||||
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
|
||||
|
||||
[[package]]
|
||||
name = "oorandom"
|
||||
|
@ -345,9 +425,15 @@ checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
|
|||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "6.4.1"
|
||||
version = "6.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
|
||||
checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267"
|
||||
|
||||
[[package]]
|
||||
name = "peeking_take_while"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
|
||||
|
||||
[[package]]
|
||||
name = "plotters"
|
||||
|
@ -385,18 +471,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.49"
|
||||
version = "1.0.53"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
|
||||
checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.23"
|
||||
version = "1.0.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
@ -433,9 +519,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.6.1"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7"
|
||||
checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
|
@ -443,9 +529,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.10.1"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3"
|
||||
checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"crossbeam-deque",
|
||||
|
@ -455,24 +541,30 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.7.0"
|
||||
version = "1.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
|
||||
checksum = "cce168fea28d3e05f158bda4576cf0c844d5045bc2cc3620fa0292ed5bb5814c"
|
||||
dependencies = [
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.28"
|
||||
version = "0.6.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
||||
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.11"
|
||||
version = "1.0.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
|
||||
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
|
@ -491,29 +583,29 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.150"
|
||||
version = "1.0.158"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e326c9ec8042f1b5da33252c8a37e9ffbd2c9bef0155215b6e6c80c790e05f91"
|
||||
checksum = "771d4d9c4163ee138805e12c710dd365e4f44be8be0503cb1bb9eb989425d9c9"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.150"
|
||||
version = "1.0.158"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42a3df25b0713732468deadad63ab9da1f1fd75a48a15024b50363f128db627e"
|
||||
checksum = "e801c1712f48475582b7696ac71e0ca34ebb30e09338425384269d9717c62cad"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.89"
|
||||
version = "1.0.94"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db"
|
||||
checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
|
@ -522,9 +614,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.9.17"
|
||||
version = "0.9.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fb06d4b6cdaef0e0c51fa881acb721bed3c924cfaa71d9c94a3b771dfdf6567"
|
||||
checksum = "f82e6c8c047aa50a7328632d067bcae6ef38772a79e28daf32f735e0e4f3dd10"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"itoa",
|
||||
|
@ -534,10 +626,27 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.107"
|
||||
name = "shlex"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
|
||||
checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -562,24 +671,23 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.6"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
|
||||
|
||||
[[package]]
|
||||
name = "unsafe-libyaml"
|
||||
version = "0.2.5"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc7ed8ba44ca06be78ea1ad2c3682a43349126c8818054231ee6f4748012aed2"
|
||||
checksum = "ad2024452afd3874bf539695e04af6732ba06517424dbf958fdb16a01f3bef6c"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.3.2"
|
||||
version = "2.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
|
||||
checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
|
@ -591,9 +699,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.83"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
|
||||
checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
|
@ -601,24 +709,24 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.83"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
|
||||
checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.109",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.83"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
|
||||
checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
|
@ -626,33 +734,44 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.83"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
|
||||
checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.109",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.83"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
|
||||
checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.60"
|
||||
version = "0.3.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
|
||||
checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "4.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
|
||||
dependencies = [
|
||||
"either",
|
||||
"libc",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
|
|
@ -21,6 +21,9 @@ glob = "0.3.1"
|
|||
rand = "0.8.5"
|
||||
serde_yaml = "0.9.17"
|
||||
|
||||
[build-dependencies]
|
||||
bindgen = { git = "https://github.com/rust-lang/rust-bindgen" , rev = "0de11f0a521611ac8738b7b01d19dddaf3899e66" }
|
||||
|
||||
[[bench]]
|
||||
name = "kzg_benches"
|
||||
harness = false
|
||||
harness = false
|
||||
|
|
|
@ -14,7 +14,8 @@ fn move_file(src: &Path, dst: &Path) -> Result<(), String> {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
let root_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()).join("../../");
|
||||
let cargo_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
|
||||
let root_dir = cargo_dir.join("../../");
|
||||
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||
|
||||
// Ensure libblst exists in `OUT_DIR`
|
||||
|
@ -72,16 +73,17 @@ fn main() {
|
|||
println!("cargo:rustc-link-lib=static=ckzg");
|
||||
println!("cargo:rustc-link-lib=static=blst");
|
||||
|
||||
// Write the compile time variable to a consts.rs file to be imported to the bindings module.
|
||||
let const_file = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()).join("src/consts.rs");
|
||||
std::fs::write(
|
||||
const_file,
|
||||
format!(
|
||||
"pub const FIELD_ELEMENTS_PER_BLOB: usize = {};",
|
||||
field_elements_per_blob
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
let bindings_out_path = cargo_dir.join("src/bindings/generated.rs");
|
||||
let build_target = env::var("TARGET").unwrap();
|
||||
let snapshot_path = cargo_dir.join("snapshots").join(format!(
|
||||
"bindings_{build_target}_{field_elements_per_blob}.rs"
|
||||
));
|
||||
make_bindings(
|
||||
field_elements_per_blob,
|
||||
&root_dir,
|
||||
bindings_out_path,
|
||||
snapshot_path,
|
||||
);
|
||||
|
||||
// Cleanup
|
||||
let obj_file = root_dir.join("src/c_kzg_4844.o");
|
||||
|
@ -89,3 +91,103 @@ fn main() {
|
|||
std::fs::remove_file(obj_file).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn make_bindings<P>(
|
||||
field_elements_per_blob: usize,
|
||||
root_dir: &Path,
|
||||
bindings_out_path: P,
|
||||
snapshot_path: P,
|
||||
) where
|
||||
P: AsRef<std::path::Path>,
|
||||
{
|
||||
use bindgen::Builder;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Callbacks;
|
||||
impl bindgen::callbacks::ParseCallbacks for Callbacks {
|
||||
fn int_macro(&self, name: &str, _value: i64) -> Option<bindgen::callbacks::IntKind> {
|
||||
match name {
|
||||
"FIELD_ELEMENTS_PER_BLOB"
|
||||
| "BYTES_PER_COMMITMENT"
|
||||
| "BYTES_PER_PROOF"
|
||||
| "BYTES_PER_FIELD_ELEMENT"
|
||||
| "BYTES_PER_BLOB" => Some(bindgen::callbacks::IntKind::Custom {
|
||||
name: "usize",
|
||||
is_signed: false,
|
||||
}),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let header_file_path = root_dir.join("src/c_kzg_4844.h");
|
||||
let header_file = header_file_path.to_str().expect("valid header file");
|
||||
|
||||
let inc_dir_path = root_dir.join("inc");
|
||||
let inc_dir = inc_dir_path.to_str().expect("valid inc dir");
|
||||
|
||||
let bindings = Builder::default()
|
||||
/*
|
||||
* Header definitions.
|
||||
*/
|
||||
// Inject the constant as C code so that the C compiler can use it.
|
||||
// -D is not supported by bindgen https://github.com/rust-lang/rust-bindgen/issues/2394
|
||||
.header_contents(
|
||||
"consts",
|
||||
&format!("#define FIELD_ELEMENTS_PER_BLOB {field_elements_per_blob}"),
|
||||
)
|
||||
.header(header_file)
|
||||
.clang_args([format!("-I{inc_dir}")])
|
||||
// Since this is not part of the header file, needs to be allowed explicitly.
|
||||
.allowlist_var("FIELD_ELEMENTS_PER_BLOB")
|
||||
// Get bindings only for the header file.
|
||||
.allowlist_file(".*/c_kzg_4844.h")
|
||||
/*
|
||||
* Cleanup instructions.
|
||||
*/
|
||||
// Remove stdio definitions related to FILE.
|
||||
.opaque_type("FILE")
|
||||
// Remove the definition of FILE to use the libc one, which is more convenient.
|
||||
.blocklist_type("FILE")
|
||||
// Inject rust code using libc's FILE
|
||||
.raw_line("use libc::FILE;")
|
||||
// Do no generate layout tests.
|
||||
.layout_tests(false)
|
||||
// Extern functions do not need individual extern blocks.
|
||||
.merge_extern_blocks(true)
|
||||
// We implement Drop for this type. Copy is not allowed for types with destructors.
|
||||
.no_copy("KZGSettings")
|
||||
/*
|
||||
* API improvements.
|
||||
*/
|
||||
// Do not create individual constants for enum variants.
|
||||
.rustified_enum("C_KZG_RET")
|
||||
// Make constants used as sizes `usize`.
|
||||
.parse_callbacks(Box::new(Callbacks))
|
||||
// Add PartialEq and Eq impls to types.
|
||||
.derive_eq(true)
|
||||
// Blobs are big, we don't want rust to liberally copy them around.
|
||||
.no_copy("Blob")
|
||||
// Do not make fields public. If we want to modify them we can create setters/mutable
|
||||
// getters when necessary.
|
||||
.default_visibility(bindgen::FieldVisibilityKind::Private)
|
||||
// Blocklist this type alias to use a custom implementation. If this stops being a type
|
||||
// alias this line needs to be removed.
|
||||
.blocklist_type("KZGCommitment")
|
||||
// Blocklist this type alias to use a custom implementation. If this stops being a type
|
||||
// alias this line needs to be removed.
|
||||
.blocklist_type("KZGProof")
|
||||
/*
|
||||
* Re-build instructions
|
||||
*/
|
||||
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
|
||||
.generate()
|
||||
.unwrap();
|
||||
|
||||
bindings
|
||||
.write_to_file(bindings_out_path)
|
||||
.expect("Failed to write bindings");
|
||||
bindings
|
||||
.write_to_file(snapshot_path)
|
||||
.expect("Failed to write snapshot");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
/* automatically generated by rust-bindgen 0.64.0 */
|
||||
|
||||
use libc::FILE;
|
||||
|
||||
pub const FIELD_ELEMENTS_PER_BLOB: usize = 4096;
|
||||
pub const BYTES_PER_COMMITMENT: usize = 48;
|
||||
pub const BYTES_PER_PROOF: usize = 48;
|
||||
pub const BYTES_PER_FIELD_ELEMENT: usize = 32;
|
||||
pub const BYTES_PER_BLOB: usize = 131072;
|
||||
pub type limb_t = u64;
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct blst_fr {
|
||||
l: [limb_t; 4usize],
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct blst_fp {
|
||||
l: [limb_t; 6usize],
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct blst_fp2 {
|
||||
fp: [blst_fp; 2usize],
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct blst_p1 {
|
||||
x: blst_fp,
|
||||
y: blst_fp,
|
||||
z: blst_fp,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct blst_p2 {
|
||||
x: blst_fp2,
|
||||
y: blst_fp2,
|
||||
z: blst_fp2,
|
||||
}
|
||||
pub type g1_t = blst_p1;
|
||||
pub type g2_t = blst_p2;
|
||||
pub type fr_t = blst_fr;
|
||||
#[doc = " An array of 32 bytes. Represents an untrusted\n (potentially invalid) field element."]
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct Bytes32 {
|
||||
bytes: [u8; 32usize],
|
||||
}
|
||||
#[doc = " An array of 48 bytes. Represents an untrusted\n (potentially invalid) commitment/proof."]
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct Bytes48 {
|
||||
bytes: [u8; 48usize],
|
||||
}
|
||||
#[doc = " A basic blob data."]
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct Blob {
|
||||
bytes: [u8; 131072usize],
|
||||
}
|
||||
#[repr(u32)]
|
||||
#[doc = " The common return type for all routines in which something can go wrong."]
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
pub enum C_KZG_RET {
|
||||
#[doc = "< Success!"]
|
||||
C_KZG_OK = 0,
|
||||
#[doc = "< The supplied data is invalid in some way."]
|
||||
C_KZG_BADARGS = 1,
|
||||
#[doc = "< Internal error - this should never occur."]
|
||||
C_KZG_ERROR = 2,
|
||||
#[doc = "< Could not allocate memory."]
|
||||
C_KZG_MALLOC = 3,
|
||||
}
|
||||
#[doc = " Stores the setup and parameters needed for performing FFTs."]
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct FFTSettings {
|
||||
#[doc = " The maximum size of FFT these settings support, a power of 2."]
|
||||
max_width: u64,
|
||||
#[doc = " Ascending powers of the root of unity, length `max_width + 1`."]
|
||||
expanded_roots_of_unity: *mut fr_t,
|
||||
#[doc = " Descending powers of the root of unity, length `max_width + 1`."]
|
||||
reverse_roots_of_unity: *mut fr_t,
|
||||
#[doc = " Powers of the root of unity in bit-reversal permutation order, length\n `max_width`."]
|
||||
roots_of_unity: *mut fr_t,
|
||||
}
|
||||
#[doc = " Stores the setup and parameters needed for computing KZG proofs."]
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct KZGSettings {
|
||||
#[doc = " The corresponding settings for performing FFTs."]
|
||||
fs: *mut FFTSettings,
|
||||
#[doc = " G1 group elements from the trusted setup,\n in Lagrange form bit-reversal permutation."]
|
||||
g1_values: *mut g1_t,
|
||||
#[doc = " G2 group elements from the trusted setup;\n both arrays have `FIELD_ELEMENTS_PER_BLOB` elements."]
|
||||
g2_values: *mut g2_t,
|
||||
}
|
||||
extern "C" {
|
||||
pub fn load_trusted_setup(
|
||||
out: *mut KZGSettings,
|
||||
g1_bytes: *const u8,
|
||||
n1: usize,
|
||||
g2_bytes: *const u8,
|
||||
n2: usize,
|
||||
) -> C_KZG_RET;
|
||||
pub fn load_trusted_setup_file(out: *mut KZGSettings, in_: *mut FILE) -> C_KZG_RET;
|
||||
pub fn free_trusted_setup(s: *mut KZGSettings);
|
||||
pub fn blob_to_kzg_commitment(
|
||||
out: *mut KZGCommitment,
|
||||
blob: *const Blob,
|
||||
s: *const KZGSettings,
|
||||
) -> C_KZG_RET;
|
||||
pub fn compute_kzg_proof(
|
||||
proof_out: *mut KZGProof,
|
||||
y_out: *mut Bytes32,
|
||||
blob: *const Blob,
|
||||
z_bytes: *const Bytes32,
|
||||
s: *const KZGSettings,
|
||||
) -> C_KZG_RET;
|
||||
pub fn compute_blob_kzg_proof(
|
||||
out: *mut KZGProof,
|
||||
blob: *const Blob,
|
||||
commitment_bytes: *const Bytes48,
|
||||
s: *const KZGSettings,
|
||||
) -> C_KZG_RET;
|
||||
pub fn verify_kzg_proof(
|
||||
ok: *mut bool,
|
||||
commitment_bytes: *const Bytes48,
|
||||
z_bytes: *const Bytes32,
|
||||
y_bytes: *const Bytes32,
|
||||
proof_bytes: *const Bytes48,
|
||||
s: *const KZGSettings,
|
||||
) -> C_KZG_RET;
|
||||
pub fn verify_blob_kzg_proof(
|
||||
ok: *mut bool,
|
||||
blob: *const Blob,
|
||||
commitment_bytes: *const Bytes48,
|
||||
proof_bytes: *const Bytes48,
|
||||
s: *const KZGSettings,
|
||||
) -> C_KZG_RET;
|
||||
pub fn verify_blob_kzg_proof_batch(
|
||||
ok: *mut bool,
|
||||
blobs: *const Blob,
|
||||
commitments_bytes: *const Bytes48,
|
||||
proofs_bytes: *const Bytes48,
|
||||
n: usize,
|
||||
s: *const KZGSettings,
|
||||
) -> C_KZG_RET;
|
||||
}
|
|
@ -1,262 +0,0 @@
|
|||
/* automatically generated by rust-bindgen 0.61.0 */
|
||||
|
||||
include!("./consts.rs");
|
||||
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use libc::FILE;
|
||||
|
||||
pub const BYTES_PER_COMMITMENT: usize = 48;
|
||||
pub const BYTES_PER_PROOF: usize = 48;
|
||||
pub const BYTES_PER_FIELD_ELEMENT: usize = 32;
|
||||
pub const BYTES_PER_BLOB: usize = FIELD_ELEMENTS_PER_BLOB * BYTES_PER_FIELD_ELEMENT;
|
||||
|
||||
type byte = u8;
|
||||
type limb_t = u64;
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
struct blst_scalar {
|
||||
b: [byte; 32usize],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
struct blst_fr {
|
||||
l: [limb_t; 4usize],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
struct blst_fp {
|
||||
l: [limb_t; 6usize],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
struct blst_fp2 {
|
||||
fp: [blst_fp; 2usize],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
struct blst_fp6 {
|
||||
fp2: [blst_fp2; 3usize],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
struct blst_fp12 {
|
||||
fp6: [blst_fp6; 2usize],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
struct blst_p1 {
|
||||
x: blst_fp,
|
||||
y: blst_fp,
|
||||
z: blst_fp,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
struct blst_p1_affine {
|
||||
x: blst_fp,
|
||||
y: blst_fp,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
struct blst_p2 {
|
||||
x: blst_fp2,
|
||||
y: blst_fp2,
|
||||
z: blst_fp2,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
struct blst_p2_affine {
|
||||
x: blst_fp2,
|
||||
y: blst_fp2,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Bytes32 {
|
||||
bytes: [u8; 32],
|
||||
}
|
||||
|
||||
impl Deref for Bytes32 {
|
||||
type Target = [u8; 32];
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Bytes48 {
|
||||
bytes: [u8; 48],
|
||||
}
|
||||
|
||||
impl Deref for Bytes48 {
|
||||
type Target = [u8; 48];
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Blob {
|
||||
bytes: [u8; BYTES_PER_BLOB],
|
||||
}
|
||||
|
||||
impl Deref for Blob {
|
||||
type Target = [u8; BYTES_PER_BLOB];
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Blob {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct KZGProof {
|
||||
bytes: [u8; BYTES_PER_PROOF],
|
||||
}
|
||||
|
||||
impl Deref for KZGProof {
|
||||
type Target = [u8; BYTES_PER_PROOF];
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
type g1_t = blst_p1;
|
||||
type g2_t = blst_p2;
|
||||
type fr_t = blst_fr;
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct KZGCommitment {
|
||||
bytes: [u8; BYTES_PER_COMMITMENT],
|
||||
}
|
||||
|
||||
impl Deref for KZGCommitment {
|
||||
type Target = [u8; BYTES_PER_COMMITMENT];
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
#[repr(u32)]
|
||||
#[doc = " The common return type for all routines in which something can go wrong."]
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
pub enum C_KZG_RET {
|
||||
#[doc = "< Success!"]
|
||||
C_KZG_OK = 0,
|
||||
#[doc = "< The supplied data is invalid in some way."]
|
||||
C_KZG_BADARGS = 1,
|
||||
#[doc = "< Internal error - this should never occur and may indicate a bug in the library."]
|
||||
C_KZG_ERROR = 2,
|
||||
#[doc = "< Could not allocate memory."]
|
||||
C_KZG_MALLOC = 3,
|
||||
}
|
||||
#[doc = " Stores the setup and parameters needed for performing FFTs."]
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct FFTSettings {
|
||||
#[doc = "< The maximum size of FFT these settings support, a power of 2."]
|
||||
max_width: u64,
|
||||
#[doc = "< Ascending powers of the root of unity, size `width + 1`."]
|
||||
expanded_roots_of_unity: *const fr_t,
|
||||
#[doc = "< Descending powers of the root of unity, size `width + 1`."]
|
||||
reverse_roots_of_unity: *const fr_t,
|
||||
#[doc = "< Powers of the root of unity in bit-reversal permutation, size `width`."]
|
||||
roots_of_unity: *const fr_t,
|
||||
}
|
||||
|
||||
#[doc = " Stores the setup and parameters needed for computing KZG proofs."]
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct KZGSettings {
|
||||
#[doc = "< The corresponding settings for performing FFTs."]
|
||||
fs: *const FFTSettings,
|
||||
#[doc = "< G1 group elements from the trusted setup, in Lagrange form bit-reversal permutation."]
|
||||
g1_values: *const g1_t,
|
||||
#[doc = "< G2 group elements from the trusted setup; both arrays have FIELD_ELEMENTS_PER_BLOB elements."]
|
||||
g2_values: *const g2_t,
|
||||
}
|
||||
|
||||
/// Safety: FFTSettings is initialized once on calling `load_trusted_setup`. After
|
||||
/// that, the struct is never modified. The memory for the arrays within `FFTSettings` and
|
||||
/// `g1_values` and `g2_values` are only freed on calling `free_trusted_setup` which only happens
|
||||
/// when we drop the struct.
|
||||
unsafe impl Sync for KZGSettings {}
|
||||
unsafe impl Send for KZGSettings {}
|
||||
|
||||
extern "C" {
|
||||
pub fn load_trusted_setup(
|
||||
out: *mut KZGSettings,
|
||||
g1_bytes: *const u8, /* n1 * 48 bytes */
|
||||
n1: usize,
|
||||
g2_bytes: *const u8, /* n2 * 96 bytes */
|
||||
n2: usize,
|
||||
) -> C_KZG_RET;
|
||||
|
||||
pub fn load_trusted_setup_file(out: *mut KZGSettings, in_: *mut FILE) -> C_KZG_RET;
|
||||
|
||||
pub fn free_trusted_setup(s: *mut KZGSettings);
|
||||
|
||||
pub fn blob_to_kzg_commitment(
|
||||
out: *mut KZGCommitment,
|
||||
blob: *const Blob,
|
||||
s: *const KZGSettings,
|
||||
) -> C_KZG_RET;
|
||||
|
||||
pub fn compute_kzg_proof(
|
||||
proof_out: *mut KZGProof,
|
||||
y_out: *mut Bytes32,
|
||||
blob: *const Blob,
|
||||
z_bytes: *const Bytes32,
|
||||
s: *const KZGSettings,
|
||||
) -> C_KZG_RET;
|
||||
|
||||
pub fn compute_blob_kzg_proof(
|
||||
out: *mut KZGProof,
|
||||
blob: *const Blob,
|
||||
commitment_bytes: *const Bytes48,
|
||||
s: *const KZGSettings,
|
||||
) -> C_KZG_RET;
|
||||
|
||||
pub fn verify_kzg_proof(
|
||||
out: *mut bool,
|
||||
commitment_bytes: *const Bytes48,
|
||||
z_bytes: *const Bytes32,
|
||||
y_bytes: *const Bytes32,
|
||||
proof_bytes: *const Bytes48,
|
||||
s: *const KZGSettings,
|
||||
) -> C_KZG_RET;
|
||||
|
||||
pub fn verify_blob_kzg_proof(
|
||||
out: *mut bool,
|
||||
blob: *const Blob,
|
||||
commitment_bytes: *const Bytes48,
|
||||
proof_bytes: *const Bytes48,
|
||||
s: *const KZGSettings,
|
||||
) -> C_KZG_RET;
|
||||
|
||||
pub fn verify_blob_kzg_proof_batch(
|
||||
out: *mut bool,
|
||||
blobs: *const Blob,
|
||||
commitments_bytes: *const Bytes48,
|
||||
proofs_bytes: *const Bytes48,
|
||||
count: usize,
|
||||
s: *const KZGSettings,
|
||||
) -> C_KZG_RET;
|
||||
}
|
|
@ -0,0 +1,745 @@
|
|||
#![allow(non_upper_case_globals)]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
mod test_formats;
|
||||
|
||||
include!("generated.rs");
|
||||
|
||||
use libc::fopen;
|
||||
use std::ffi::CString;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::os::unix::prelude::OsStrExt;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub const BYTES_PER_G1_POINT: usize = 48;
|
||||
pub const BYTES_PER_G2_POINT: usize = 96;
|
||||
|
||||
/// Number of G2 points required for the kzg trusted setup.
|
||||
/// 65 is fixed and is used for providing multiproofs up to 64 field elements.
|
||||
const NUM_G2_POINTS: usize = 65;
|
||||
|
||||
/// A trusted (valid) KZG commitment.
|
||||
// NOTE: this is a type alias to the struct Bytes48, same as [`KZGProof`] in the C header files. To
|
||||
// facilitate type safety: proofs and commitments should not be interchangeable, we use a
|
||||
// custom implementation.
|
||||
#[repr(C)]
|
||||
pub struct KZGCommitment {
|
||||
bytes: [u8; BYTES_PER_COMMITMENT],
|
||||
}
|
||||
|
||||
/// A trusted (valid) KZG proof.
|
||||
// NOTE: this is a type alias to the struct Bytes48, same as [`KZGCommitment`] in the C header
|
||||
// files. To facilitate type safety: proofs and commitments should not be interchangeable, we
|
||||
// use a custom implementation.
|
||||
#[repr(C)]
|
||||
pub struct KZGProof {
|
||||
bytes: [u8; BYTES_PER_PROOF],
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
/// Wrong number of bytes.
|
||||
InvalidBytesLength(String),
|
||||
/// The KZG proof is invalid.
|
||||
InvalidKzgProof(String),
|
||||
/// The KZG commitment is invalid.
|
||||
InvalidKzgCommitment(String),
|
||||
/// The provided trusted setup is invalid.
|
||||
InvalidTrustedSetup(String),
|
||||
/// Paired arguments have different lengths.
|
||||
MismatchLength(String),
|
||||
/// The underlying c-kzg library returned an error.
|
||||
CError(C_KZG_RET),
|
||||
}
|
||||
|
||||
/// Holds the parameters of a kzg trusted setup ceremony.
|
||||
impl KZGSettings {
|
||||
/// Initializes a trusted setup from `FIELD_ELEMENTS_PER_BLOB` g1 points
|
||||
/// and 65 g2 points in byte format.
|
||||
pub fn load_trusted_setup(
|
||||
g1_bytes: Vec<[u8; BYTES_PER_G1_POINT]>,
|
||||
g2_bytes: Vec<[u8; BYTES_PER_G2_POINT]>,
|
||||
) -> Result<Self, Error> {
|
||||
if g1_bytes.len() != FIELD_ELEMENTS_PER_BLOB {
|
||||
return Err(Error::InvalidTrustedSetup(format!(
|
||||
"Invalid number of g1 points in trusted setup. Expected {} got {}",
|
||||
FIELD_ELEMENTS_PER_BLOB,
|
||||
g1_bytes.len()
|
||||
)));
|
||||
}
|
||||
if g2_bytes.len() != NUM_G2_POINTS {
|
||||
return Err(Error::InvalidTrustedSetup(format!(
|
||||
"Invalid number of g2 points in trusted setup. Expected {} got {}",
|
||||
NUM_G2_POINTS,
|
||||
g2_bytes.len()
|
||||
)));
|
||||
}
|
||||
let mut kzg_settings = MaybeUninit::<KZGSettings>::uninit();
|
||||
unsafe {
|
||||
let res = load_trusted_setup(
|
||||
kzg_settings.as_mut_ptr(),
|
||||
g1_bytes.as_ptr() as *const u8,
|
||||
g1_bytes.len(),
|
||||
g2_bytes.as_ptr() as *const u8,
|
||||
g2_bytes.len(),
|
||||
);
|
||||
if let C_KZG_RET::C_KZG_OK = res {
|
||||
Ok(kzg_settings.assume_init())
|
||||
} else {
|
||||
Err(Error::InvalidTrustedSetup(format!(
|
||||
"Invalid trusted setup: {:?}",
|
||||
res
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Loads the trusted setup parameters from a file. The file format is as follows:
|
||||
///
|
||||
/// FIELD_ELEMENTS_PER_BLOB
|
||||
/// 65 # This is fixed and is used for providing multiproofs up to 64 field elements.
|
||||
/// FIELD_ELEMENT_PER_BLOB g1 byte values
|
||||
/// 65 g2 byte values
|
||||
pub fn load_trusted_setup_file(file_path: PathBuf) -> Result<Self, Error> {
|
||||
let file_path = CString::new(file_path.as_os_str().as_bytes()).map_err(|e| {
|
||||
Error::InvalidTrustedSetup(format!("Invalid trusted setup file: {:?}", e))
|
||||
})?;
|
||||
let mut kzg_settings = MaybeUninit::<KZGSettings>::uninit();
|
||||
unsafe {
|
||||
let file_ptr = fopen(file_path.as_ptr(), &('r' as libc::c_char));
|
||||
let res = load_trusted_setup_file(kzg_settings.as_mut_ptr(), file_ptr);
|
||||
if let C_KZG_RET::C_KZG_OK = res {
|
||||
Ok(kzg_settings.assume_init())
|
||||
} else {
|
||||
Err(Error::InvalidTrustedSetup(format!(
|
||||
"Invalid trusted setup: {:?}",
|
||||
res
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for KZGSettings {
|
||||
fn drop(&mut self) {
|
||||
unsafe { free_trusted_setup(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Blob {
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
|
||||
if bytes.len() != BYTES_PER_BLOB {
|
||||
return Err(Error::InvalidBytesLength(format!(
|
||||
"Invalid byte length. Expected {} got {}",
|
||||
BYTES_PER_BLOB,
|
||||
bytes.len(),
|
||||
)));
|
||||
}
|
||||
let mut new_bytes = [0; BYTES_PER_BLOB];
|
||||
new_bytes.copy_from_slice(bytes);
|
||||
Ok(Self { bytes: new_bytes })
|
||||
}
|
||||
|
||||
pub fn from_hex(hex_str: &str) -> Result<Self, Error> {
|
||||
Self::from_bytes(&hex::decode(&hex_str[2..]).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl Bytes32 {
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
|
||||
if bytes.len() != 32 {
|
||||
return Err(Error::InvalidBytesLength(format!(
|
||||
"Invalid byte length. Expected {} got {}",
|
||||
32,
|
||||
bytes.len(),
|
||||
)));
|
||||
}
|
||||
let mut new_bytes = [0; 32];
|
||||
new_bytes.copy_from_slice(bytes);
|
||||
Ok(Self { bytes: new_bytes })
|
||||
}
|
||||
|
||||
pub fn from_hex(hex_str: &str) -> Result<Self, Error> {
|
||||
Self::from_bytes(&hex::decode(&hex_str[2..]).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl Bytes48 {
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
|
||||
if bytes.len() != 48 {
|
||||
return Err(Error::InvalidBytesLength(format!(
|
||||
"Invalid byte length. Expected {} got {}",
|
||||
48,
|
||||
bytes.len(),
|
||||
)));
|
||||
}
|
||||
let mut new_bytes = [0; 48];
|
||||
new_bytes.copy_from_slice(bytes);
|
||||
Ok(Self { bytes: new_bytes })
|
||||
}
|
||||
|
||||
pub fn from_hex(hex_str: &str) -> Result<Self, Error> {
|
||||
Self::from_bytes(&hex::decode(&hex_str[2..]).unwrap())
|
||||
}
|
||||
|
||||
pub fn into_inner(self) -> [u8; 48] {
|
||||
self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
impl KZGProof {
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
|
||||
if bytes.len() != BYTES_PER_PROOF {
|
||||
return Err(Error::InvalidKzgProof(format!(
|
||||
"Invalid byte length. Expected {} got {}",
|
||||
BYTES_PER_PROOF,
|
||||
bytes.len(),
|
||||
)));
|
||||
}
|
||||
let mut proof_bytes = [0; BYTES_PER_PROOF];
|
||||
proof_bytes.copy_from_slice(bytes);
|
||||
Ok(Self { bytes: proof_bytes })
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Bytes48 {
|
||||
Bytes48 { bytes: self.bytes }
|
||||
}
|
||||
|
||||
pub fn as_hex_string(&self) -> String {
|
||||
hex::encode(self.bytes)
|
||||
}
|
||||
|
||||
pub fn compute_kzg_proof(
|
||||
blob: Blob,
|
||||
z_bytes: Bytes32,
|
||||
kzg_settings: &KZGSettings,
|
||||
) -> Result<(Self, Bytes32), Error> {
|
||||
let mut kzg_proof = MaybeUninit::<KZGProof>::uninit();
|
||||
let mut y_out = MaybeUninit::<Bytes32>::uninit();
|
||||
unsafe {
|
||||
let res = compute_kzg_proof(
|
||||
kzg_proof.as_mut_ptr(),
|
||||
y_out.as_mut_ptr(),
|
||||
&blob,
|
||||
&z_bytes,
|
||||
kzg_settings,
|
||||
);
|
||||
if let C_KZG_RET::C_KZG_OK = res {
|
||||
Ok((kzg_proof.assume_init(), y_out.assume_init()))
|
||||
} else {
|
||||
Err(Error::CError(res))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compute_blob_kzg_proof(
|
||||
blob: Blob,
|
||||
commitment_bytes: Bytes48,
|
||||
kzg_settings: &KZGSettings,
|
||||
) -> Result<Self, Error> {
|
||||
let mut kzg_proof = MaybeUninit::<KZGProof>::uninit();
|
||||
unsafe {
|
||||
let res = compute_blob_kzg_proof(
|
||||
kzg_proof.as_mut_ptr(),
|
||||
&blob,
|
||||
&commitment_bytes,
|
||||
kzg_settings,
|
||||
);
|
||||
if let C_KZG_RET::C_KZG_OK = res {
|
||||
Ok(kzg_proof.assume_init())
|
||||
} else {
|
||||
Err(Error::CError(res))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn verify_kzg_proof(
|
||||
commitment_bytes: Bytes48,
|
||||
z_bytes: Bytes32,
|
||||
y_bytes: Bytes32,
|
||||
proof_bytes: Bytes48,
|
||||
kzg_settings: &KZGSettings,
|
||||
) -> Result<bool, Error> {
|
||||
let mut verified: MaybeUninit<bool> = MaybeUninit::uninit();
|
||||
unsafe {
|
||||
let res = verify_kzg_proof(
|
||||
verified.as_mut_ptr(),
|
||||
&commitment_bytes,
|
||||
&z_bytes,
|
||||
&y_bytes,
|
||||
&proof_bytes,
|
||||
kzg_settings,
|
||||
);
|
||||
if let C_KZG_RET::C_KZG_OK = res {
|
||||
Ok(verified.assume_init())
|
||||
} else {
|
||||
Err(Error::CError(res))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn verify_blob_kzg_proof(
|
||||
blob: Blob,
|
||||
commitment_bytes: Bytes48,
|
||||
proof_bytes: Bytes48,
|
||||
kzg_settings: &KZGSettings,
|
||||
) -> Result<bool, Error> {
|
||||
let mut verified: MaybeUninit<bool> = MaybeUninit::uninit();
|
||||
unsafe {
|
||||
let res = verify_blob_kzg_proof(
|
||||
verified.as_mut_ptr(),
|
||||
&blob,
|
||||
&commitment_bytes,
|
||||
&proof_bytes,
|
||||
kzg_settings,
|
||||
);
|
||||
if let C_KZG_RET::C_KZG_OK = res {
|
||||
Ok(verified.assume_init())
|
||||
} else {
|
||||
Err(Error::CError(res))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn verify_blob_kzg_proof_batch(
|
||||
blobs: &[Blob],
|
||||
commitments_bytes: &[Bytes48],
|
||||
proofs_bytes: &[Bytes48],
|
||||
kzg_settings: &KZGSettings,
|
||||
) -> Result<bool, Error> {
|
||||
if blobs.len() != commitments_bytes.len() {
|
||||
return Err(Error::MismatchLength(format!(
|
||||
"There are {} blobs and {} commitments",
|
||||
blobs.len(),
|
||||
commitments_bytes.len()
|
||||
)));
|
||||
}
|
||||
if blobs.len() != proofs_bytes.len() {
|
||||
return Err(Error::MismatchLength(format!(
|
||||
"There are {} blobs and {} proofs",
|
||||
blobs.len(),
|
||||
proofs_bytes.len()
|
||||
)));
|
||||
}
|
||||
let mut verified: MaybeUninit<bool> = MaybeUninit::uninit();
|
||||
unsafe {
|
||||
let res = verify_blob_kzg_proof_batch(
|
||||
verified.as_mut_ptr(),
|
||||
blobs.as_ptr(),
|
||||
commitments_bytes.as_ptr(),
|
||||
proofs_bytes.as_ptr(),
|
||||
blobs.len(),
|
||||
kzg_settings,
|
||||
);
|
||||
if let C_KZG_RET::C_KZG_OK = res {
|
||||
Ok(verified.assume_init())
|
||||
} else {
|
||||
Err(Error::CError(res))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl KZGCommitment {
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
|
||||
if bytes.len() != BYTES_PER_COMMITMENT {
|
||||
return Err(Error::InvalidKzgCommitment(format!(
|
||||
"Invalid byte length. Expected {} got {}",
|
||||
BYTES_PER_PROOF,
|
||||
bytes.len(),
|
||||
)));
|
||||
}
|
||||
let mut commitment = [0; BYTES_PER_COMMITMENT];
|
||||
commitment.copy_from_slice(bytes);
|
||||
Ok(Self { bytes: commitment })
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Bytes48 {
|
||||
Bytes48 { bytes: self.bytes }
|
||||
}
|
||||
|
||||
pub fn as_hex_string(&self) -> String {
|
||||
hex::encode(self.bytes)
|
||||
}
|
||||
|
||||
pub fn blob_to_kzg_commitment(blob: Blob, kzg_settings: &KZGSettings) -> Result<Self, Error> {
|
||||
let mut kzg_commitment: MaybeUninit<KZGCommitment> = MaybeUninit::uninit();
|
||||
unsafe {
|
||||
let res = blob_to_kzg_commitment(
|
||||
kzg_commitment.as_mut_ptr(),
|
||||
blob.as_ptr() as *const Blob,
|
||||
kzg_settings,
|
||||
);
|
||||
if let C_KZG_RET::C_KZG_OK = res {
|
||||
Ok(kzg_commitment.assume_init())
|
||||
} else {
|
||||
Err(Error::CError(res))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; BYTES_PER_COMMITMENT]> for KZGCommitment {
|
||||
fn from(value: [u8; BYTES_PER_COMMITMENT]) -> Self {
|
||||
Self { bytes: value }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; BYTES_PER_PROOF]> for KZGProof {
|
||||
fn from(value: [u8; BYTES_PER_PROOF]) -> Self {
|
||||
Self { bytes: value }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; BYTES_PER_BLOB]> for Blob {
|
||||
fn from(value: [u8; BYTES_PER_BLOB]) -> Self {
|
||||
Self { bytes: value }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; 32]> for Bytes32 {
|
||||
fn from(value: [u8; 32]) -> Self {
|
||||
Self { bytes: value }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; 48]> for Bytes48 {
|
||||
fn from(value: [u8; 48]) -> Self {
|
||||
Self { bytes: value }
|
||||
}
|
||||
}
|
||||
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
impl Deref for Bytes32 {
|
||||
type Target = [u8; 32];
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Bytes48 {
|
||||
type Target = [u8; 48];
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Blob {
|
||||
type Target = [u8; BYTES_PER_BLOB];
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Blob {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Blob {
|
||||
fn clone(&self) -> Self {
|
||||
Blob { bytes: self.bytes }
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for KZGProof {
|
||||
type Target = [u8; BYTES_PER_PROOF];
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for KZGCommitment {
|
||||
type Target = [u8; BYTES_PER_COMMITMENT];
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
/// Safety: FFTSettings is initialized once on calling `load_trusted_setup`. After
|
||||
/// that, the struct is never modified. The memory for the arrays within `FFTSettings` and
|
||||
/// `g1_values` and `g2_values` are only freed on calling `free_trusted_setup` which only happens
|
||||
/// when we drop the struct.
|
||||
unsafe impl Sync for KZGSettings {}
|
||||
unsafe impl Send for KZGSettings {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use rand::{rngs::ThreadRng, Rng};
|
||||
use std::fs;
|
||||
|
||||
use test_formats::{
|
||||
blob_to_kzg_commitment_test, compute_blob_kzg_proof, compute_kzg_proof,
|
||||
verify_blob_kzg_proof, verify_blob_kzg_proof_batch, verify_kzg_proof,
|
||||
};
|
||||
|
||||
fn generate_random_blob(rng: &mut ThreadRng) -> Blob {
|
||||
let mut arr = [0u8; BYTES_PER_BLOB];
|
||||
rng.fill(&mut arr[..]);
|
||||
// Ensure that the blob is canonical by ensuring that
|
||||
// each field element contained in the blob is < BLS_MODULUS
|
||||
for i in 0..FIELD_ELEMENTS_PER_BLOB {
|
||||
arr[i * BYTES_PER_FIELD_ELEMENT + BYTES_PER_FIELD_ELEMENT - 1] = 0;
|
||||
}
|
||||
arr.into()
|
||||
}
|
||||
|
||||
fn test_simple(trusted_setup_file: PathBuf) {
|
||||
let mut rng = rand::thread_rng();
|
||||
assert!(trusted_setup_file.exists());
|
||||
let kzg_settings = KZGSettings::load_trusted_setup_file(trusted_setup_file).unwrap();
|
||||
|
||||
let num_blobs: usize = rng.gen_range(1..16);
|
||||
let mut blobs: Vec<Blob> = (0..num_blobs)
|
||||
.map(|_| generate_random_blob(&mut rng))
|
||||
.collect();
|
||||
|
||||
let commitments: Vec<Bytes48> = blobs
|
||||
.iter()
|
||||
.map(|blob| KZGCommitment::blob_to_kzg_commitment(blob.clone(), &kzg_settings).unwrap())
|
||||
.map(|commitment| commitment.to_bytes())
|
||||
.collect();
|
||||
|
||||
let proofs: Vec<Bytes48> = blobs
|
||||
.iter()
|
||||
.zip(commitments.iter())
|
||||
.map(|(blob, commitment)| {
|
||||
KZGProof::compute_blob_kzg_proof(blob.clone(), *commitment, &kzg_settings).unwrap()
|
||||
})
|
||||
.map(|proof| proof.to_bytes())
|
||||
.collect();
|
||||
|
||||
assert!(KZGProof::verify_blob_kzg_proof_batch(
|
||||
&blobs,
|
||||
&commitments,
|
||||
&proofs,
|
||||
&kzg_settings
|
||||
)
|
||||
.unwrap());
|
||||
|
||||
blobs.pop();
|
||||
|
||||
let error =
|
||||
KZGProof::verify_blob_kzg_proof_batch(&blobs, &commitments, &proofs, &kzg_settings)
|
||||
.unwrap_err();
|
||||
assert!(matches!(error, Error::MismatchLength(_)));
|
||||
|
||||
let incorrect_blob = generate_random_blob(&mut rng);
|
||||
blobs.push(incorrect_blob);
|
||||
|
||||
assert!(!KZGProof::verify_blob_kzg_proof_batch(
|
||||
&blobs,
|
||||
&commitments,
|
||||
&proofs,
|
||||
&kzg_settings
|
||||
)
|
||||
.unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_end_to_end() {
|
||||
let trusted_setup_file = if cfg!(feature = "minimal-spec") {
|
||||
PathBuf::from("../../src/trusted_setup_4.txt")
|
||||
} else {
|
||||
PathBuf::from("../../src/trusted_setup.txt")
|
||||
};
|
||||
test_simple(trusted_setup_file);
|
||||
}
|
||||
|
||||
const BLOB_TO_KZG_COMMITMENT_TESTS: &str = "../../tests/blob_to_kzg_commitment/*/*/*";
|
||||
const COMPUTE_KZG_PROOF_TESTS: &str = "../../tests/compute_kzg_proof/*/*/*";
|
||||
const COMPUTE_BLOB_KZG_PROOF_TESTS: &str = "../../tests/compute_blob_kzg_proof/*/*/*";
|
||||
const VERIFY_KZG_PROOF_TESTS: &str = "../../tests/verify_kzg_proof/*/*/*";
|
||||
const VERIFY_BLOB_KZG_PROOF_TESTS: &str = "../../tests/verify_blob_kzg_proof/*/*/*";
|
||||
const VERIFY_BLOB_KZG_PROOF_BATCH_TESTS: &str = "../../tests/verify_blob_kzg_proof_batch/*/*/*";
|
||||
|
||||
#[cfg(not(feature = "minimal-spec"))]
|
||||
#[test]
|
||||
fn test_blob_to_kzg_commitment() {
|
||||
let trusted_setup_file = PathBuf::from("../../src/trusted_setup.txt");
|
||||
assert!(trusted_setup_file.exists());
|
||||
let kzg_settings = KZGSettings::load_trusted_setup_file(trusted_setup_file).unwrap();
|
||||
let test_files: Vec<PathBuf> = glob::glob(BLOB_TO_KZG_COMMITMENT_TESTS)
|
||||
.unwrap()
|
||||
.map(Result::unwrap)
|
||||
.collect();
|
||||
assert!(!test_files.is_empty());
|
||||
|
||||
for test_file in test_files {
|
||||
let yaml_data = fs::read_to_string(test_file).unwrap();
|
||||
let test: blob_to_kzg_commitment_test::Test = serde_yaml::from_str(&yaml_data).unwrap();
|
||||
let Ok(blob) = test.input.get_blob() else {
|
||||
assert!(test.get_output().is_none());
|
||||
continue;
|
||||
};
|
||||
|
||||
match KZGCommitment::blob_to_kzg_commitment(blob, &kzg_settings) {
|
||||
Ok(res) => assert_eq!(res.bytes, test.get_output().unwrap().bytes),
|
||||
_ => assert!(test.get_output().is_none()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "minimal-spec"))]
|
||||
#[test]
|
||||
fn test_compute_kzg_proof() {
|
||||
let trusted_setup_file = PathBuf::from("../../src/trusted_setup.txt");
|
||||
assert!(trusted_setup_file.exists());
|
||||
let kzg_settings = KZGSettings::load_trusted_setup_file(trusted_setup_file).unwrap();
|
||||
let test_files: Vec<PathBuf> = glob::glob(COMPUTE_KZG_PROOF_TESTS)
|
||||
.unwrap()
|
||||
.map(Result::unwrap)
|
||||
.collect();
|
||||
assert!(!test_files.is_empty());
|
||||
|
||||
for test_file in test_files {
|
||||
let yaml_data = fs::read_to_string(test_file).unwrap();
|
||||
let test: compute_kzg_proof::Test = serde_yaml::from_str(&yaml_data).unwrap();
|
||||
let (Ok(blob), Ok(z)) = (test.input.get_blob(), test.input.get_z()) else {
|
||||
assert!(test.get_output().is_none());
|
||||
continue;
|
||||
};
|
||||
|
||||
match KZGProof::compute_kzg_proof(blob, z, &kzg_settings) {
|
||||
Ok((proof, y)) => {
|
||||
assert_eq!(proof.bytes, test.get_output().unwrap().0.bytes);
|
||||
assert_eq!(y.bytes, test.get_output().unwrap().1.bytes);
|
||||
}
|
||||
_ => assert!(test.get_output().is_none()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "minimal-spec"))]
|
||||
#[test]
|
||||
fn test_compute_blob_kzg_proof() {
|
||||
let trusted_setup_file = PathBuf::from("../../src/trusted_setup.txt");
|
||||
assert!(trusted_setup_file.exists());
|
||||
let kzg_settings = KZGSettings::load_trusted_setup_file(trusted_setup_file).unwrap();
|
||||
let test_files: Vec<PathBuf> = glob::glob(COMPUTE_BLOB_KZG_PROOF_TESTS)
|
||||
.unwrap()
|
||||
.map(Result::unwrap)
|
||||
.collect();
|
||||
assert!(!test_files.is_empty());
|
||||
|
||||
for test_file in test_files {
|
||||
let yaml_data = fs::read_to_string(test_file).unwrap();
|
||||
let test: compute_blob_kzg_proof::Test = serde_yaml::from_str(&yaml_data).unwrap();
|
||||
let (Ok(blob), Ok(commitment)) = (
|
||||
test.input.get_blob(),
|
||||
test.input.get_commitment()
|
||||
) else {
|
||||
assert!(test.get_output().is_none());
|
||||
continue;
|
||||
};
|
||||
|
||||
match KZGProof::compute_blob_kzg_proof(blob, commitment, &kzg_settings) {
|
||||
Ok(res) => assert_eq!(res.bytes, test.get_output().unwrap().bytes),
|
||||
_ => assert!(test.get_output().is_none()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "minimal-spec"))]
|
||||
#[test]
|
||||
fn test_verify_kzg_proof() {
|
||||
let trusted_setup_file = PathBuf::from("../../src/trusted_setup.txt");
|
||||
assert!(trusted_setup_file.exists());
|
||||
let kzg_settings = KZGSettings::load_trusted_setup_file(trusted_setup_file).unwrap();
|
||||
let test_files: Vec<PathBuf> = glob::glob(VERIFY_KZG_PROOF_TESTS)
|
||||
.unwrap()
|
||||
.map(Result::unwrap)
|
||||
.collect();
|
||||
assert!(!test_files.is_empty());
|
||||
|
||||
for test_file in test_files {
|
||||
let yaml_data = fs::read_to_string(test_file).unwrap();
|
||||
let test: verify_kzg_proof::Test = serde_yaml::from_str(&yaml_data).unwrap();
|
||||
let (Ok(commitment), Ok(z), Ok(y), Ok(proof)) = (
|
||||
test.input.get_commitment(),
|
||||
test.input.get_z(),
|
||||
test.input.get_y(),
|
||||
test.input.get_proof()
|
||||
) else {
|
||||
assert!(test.get_output().is_none());
|
||||
continue;
|
||||
};
|
||||
|
||||
match KZGProof::verify_kzg_proof(commitment, z, y, proof, &kzg_settings) {
|
||||
Ok(res) => assert_eq!(res, test.get_output().unwrap()),
|
||||
_ => assert!(test.get_output().is_none()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "minimal-spec"))]
|
||||
#[test]
|
||||
fn test_verify_blob_kzg_proof() {
|
||||
let trusted_setup_file = PathBuf::from("../../src/trusted_setup.txt");
|
||||
assert!(trusted_setup_file.exists());
|
||||
let kzg_settings = KZGSettings::load_trusted_setup_file(trusted_setup_file).unwrap();
|
||||
let test_files: Vec<PathBuf> = glob::glob(VERIFY_BLOB_KZG_PROOF_TESTS)
|
||||
.unwrap()
|
||||
.map(Result::unwrap)
|
||||
.collect();
|
||||
assert!(!test_files.is_empty());
|
||||
|
||||
for test_file in test_files {
|
||||
let yaml_data = fs::read_to_string(test_file).unwrap();
|
||||
let test: verify_blob_kzg_proof::Test = serde_yaml::from_str(&yaml_data).unwrap();
|
||||
let (Ok(blob), Ok(commitment), Ok(proof)) = (
|
||||
test.input.get_blob(),
|
||||
test.input.get_commitment(),
|
||||
test.input.get_proof()
|
||||
) else {
|
||||
assert!(test.get_output().is_none());
|
||||
continue;
|
||||
};
|
||||
|
||||
match KZGProof::verify_blob_kzg_proof(blob, commitment, proof, &kzg_settings) {
|
||||
Ok(res) => assert_eq!(res, test.get_output().unwrap()),
|
||||
_ => assert!(test.get_output().is_none()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "minimal-spec"))]
|
||||
#[test]
|
||||
fn test_verify_blob_kzg_proof_batch() {
|
||||
let trusted_setup_file = PathBuf::from("../../src/trusted_setup.txt");
|
||||
assert!(trusted_setup_file.exists());
|
||||
let kzg_settings = KZGSettings::load_trusted_setup_file(trusted_setup_file).unwrap();
|
||||
let test_files: Vec<PathBuf> = glob::glob(VERIFY_BLOB_KZG_PROOF_BATCH_TESTS)
|
||||
.unwrap()
|
||||
.map(Result::unwrap)
|
||||
.collect();
|
||||
assert!(!test_files.is_empty());
|
||||
|
||||
for test_file in test_files {
|
||||
let yaml_data = fs::read_to_string(test_file).unwrap();
|
||||
let test: verify_blob_kzg_proof_batch::Test = serde_yaml::from_str(&yaml_data).unwrap();
|
||||
let (Ok(blobs), Ok(commitments), Ok(proofs)) = (
|
||||
test.input.get_blobs(),
|
||||
test.input.get_commitments(),
|
||||
test.input.get_proofs()
|
||||
) else {
|
||||
assert!(test.get_output().is_none());
|
||||
continue;
|
||||
};
|
||||
|
||||
match KZGProof::verify_blob_kzg_proof_batch(
|
||||
&blobs,
|
||||
&commitments,
|
||||
&proofs,
|
||||
&kzg_settings,
|
||||
) {
|
||||
Ok(res) => assert_eq!(res, test.get_output().unwrap()),
|
||||
_ => assert!(test.get_output().is_none()),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,675 +1,14 @@
|
|||
#![allow(non_upper_case_globals)]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
mod test_formats;
|
||||
|
||||
include!("bindings.rs");
|
||||
|
||||
use libc::fopen;
|
||||
use std::ffi::CString;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::os::unix::prelude::OsStrExt;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub const BYTES_PER_G1_POINT: usize = 48;
|
||||
pub const BYTES_PER_G2_POINT: usize = 96;
|
||||
|
||||
/// Number of G2 points required for the kzg trusted setup.
|
||||
/// 65 is fixed and is used for providing multiproofs up to 64 field elements.
|
||||
const NUM_G2_POINTS: usize = 65;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
/// Wrong number of bytes.
|
||||
InvalidBytesLength(String),
|
||||
/// The KZG proof is invalid.
|
||||
InvalidKzgProof(String),
|
||||
/// The KZG commitment is invalid.
|
||||
InvalidKzgCommitment(String),
|
||||
/// The provided trusted setup is invalid.
|
||||
InvalidTrustedSetup(String),
|
||||
/// Paired arguments have different lengths.
|
||||
MismatchLength(String),
|
||||
/// The underlying c-kzg library returned an error.
|
||||
CError(C_KZG_RET),
|
||||
}
|
||||
|
||||
/// Holds the parameters of a kzg trusted setup ceremony.
|
||||
impl KZGSettings {
|
||||
/// Initializes a trusted setup from `FIELD_ELEMENTS_PER_BLOB` g1 points
|
||||
/// and 65 g2 points in byte format.
|
||||
pub fn load_trusted_setup(
|
||||
g1_bytes: Vec<[u8; BYTES_PER_G1_POINT]>,
|
||||
g2_bytes: Vec<[u8; BYTES_PER_G2_POINT]>,
|
||||
) -> Result<Self, Error> {
|
||||
if g1_bytes.len() != FIELD_ELEMENTS_PER_BLOB {
|
||||
return Err(Error::InvalidTrustedSetup(format!(
|
||||
"Invalid number of g1 points in trusted setup. Expected {} got {}",
|
||||
FIELD_ELEMENTS_PER_BLOB,
|
||||
g1_bytes.len()
|
||||
)));
|
||||
}
|
||||
if g2_bytes.len() != NUM_G2_POINTS {
|
||||
return Err(Error::InvalidTrustedSetup(format!(
|
||||
"Invalid number of g2 points in trusted setup. Expected {} got {}",
|
||||
NUM_G2_POINTS,
|
||||
g2_bytes.len()
|
||||
)));
|
||||
}
|
||||
let mut kzg_settings = MaybeUninit::<KZGSettings>::uninit();
|
||||
unsafe {
|
||||
let res = load_trusted_setup(
|
||||
kzg_settings.as_mut_ptr(),
|
||||
g1_bytes.as_ptr() as *const u8,
|
||||
g1_bytes.len(),
|
||||
g2_bytes.as_ptr() as *const u8,
|
||||
g2_bytes.len(),
|
||||
);
|
||||
if let C_KZG_RET::C_KZG_OK = res {
|
||||
Ok(kzg_settings.assume_init())
|
||||
} else {
|
||||
Err(Error::InvalidTrustedSetup(format!(
|
||||
"Invalid trusted setup: {:?}",
|
||||
res
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Loads the trusted setup parameters from a file. The file format is as follows:
|
||||
///
|
||||
/// FIELD_ELEMENTS_PER_BLOB
|
||||
/// 65 # This is fixed and is used for providing multiproofs up to 64 field elements.
|
||||
/// FIELD_ELEMENT_PER_BLOB g1 byte values
|
||||
/// 65 g2 byte values
|
||||
pub fn load_trusted_setup_file(file_path: PathBuf) -> Result<Self, Error> {
|
||||
let file_path = CString::new(file_path.as_os_str().as_bytes()).map_err(|e| {
|
||||
Error::InvalidTrustedSetup(format!("Invalid trusted setup file: {:?}", e))
|
||||
})?;
|
||||
let mut kzg_settings = MaybeUninit::<KZGSettings>::uninit();
|
||||
unsafe {
|
||||
let file_ptr = fopen(file_path.as_ptr(), &('r' as libc::c_char));
|
||||
let res = load_trusted_setup_file(kzg_settings.as_mut_ptr(), file_ptr);
|
||||
if let C_KZG_RET::C_KZG_OK = res {
|
||||
Ok(kzg_settings.assume_init())
|
||||
} else {
|
||||
Err(Error::InvalidTrustedSetup(format!(
|
||||
"Invalid trusted setup: {:?}",
|
||||
res
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for KZGSettings {
|
||||
fn drop(&mut self) {
|
||||
unsafe { free_trusted_setup(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Blob {
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
|
||||
if bytes.len() != BYTES_PER_BLOB {
|
||||
return Err(Error::InvalidBytesLength(format!(
|
||||
"Invalid byte length. Expected {} got {}",
|
||||
BYTES_PER_BLOB,
|
||||
bytes.len(),
|
||||
)));
|
||||
}
|
||||
let mut new_bytes = [0; BYTES_PER_BLOB];
|
||||
new_bytes.copy_from_slice(bytes);
|
||||
Ok(Self { bytes: new_bytes })
|
||||
}
|
||||
|
||||
pub fn from_hex(hex_str: &str) -> Result<Self, Error> {
|
||||
Self::from_bytes(&hex::decode(&hex_str[2..]).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl Bytes32 {
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
|
||||
if bytes.len() != 32 {
|
||||
return Err(Error::InvalidBytesLength(format!(
|
||||
"Invalid byte length. Expected {} got {}",
|
||||
32,
|
||||
bytes.len(),
|
||||
)));
|
||||
}
|
||||
let mut new_bytes = [0; 32];
|
||||
new_bytes.copy_from_slice(bytes);
|
||||
Ok(Self { bytes: new_bytes })
|
||||
}
|
||||
|
||||
pub fn from_hex(hex_str: &str) -> Result<Self, Error> {
|
||||
Self::from_bytes(&hex::decode(&hex_str[2..]).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl Bytes48 {
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
|
||||
if bytes.len() != 48 {
|
||||
return Err(Error::InvalidBytesLength(format!(
|
||||
"Invalid byte length. Expected {} got {}",
|
||||
48,
|
||||
bytes.len(),
|
||||
)));
|
||||
}
|
||||
let mut new_bytes = [0; 48];
|
||||
new_bytes.copy_from_slice(bytes);
|
||||
Ok(Self { bytes: new_bytes })
|
||||
}
|
||||
|
||||
pub fn from_hex(hex_str: &str) -> Result<Self, Error> {
|
||||
Self::from_bytes(&hex::decode(&hex_str[2..]).unwrap())
|
||||
}
|
||||
|
||||
pub fn into_inner(self) -> [u8; 48] {
|
||||
self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
impl KZGProof {
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
|
||||
if bytes.len() != BYTES_PER_PROOF {
|
||||
return Err(Error::InvalidKzgProof(format!(
|
||||
"Invalid byte length. Expected {} got {}",
|
||||
BYTES_PER_PROOF,
|
||||
bytes.len(),
|
||||
)));
|
||||
}
|
||||
let mut proof_bytes = [0; BYTES_PER_PROOF];
|
||||
proof_bytes.copy_from_slice(bytes);
|
||||
Ok(Self { bytes: proof_bytes })
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Bytes48 {
|
||||
let mut bytes = [0; 48];
|
||||
bytes.copy_from_slice(&self.bytes);
|
||||
Bytes48 { bytes }
|
||||
}
|
||||
|
||||
pub fn as_hex_string(&self) -> String {
|
||||
hex::encode(self.bytes)
|
||||
}
|
||||
|
||||
pub fn compute_kzg_proof(
|
||||
blob: Blob,
|
||||
z_bytes: Bytes32,
|
||||
kzg_settings: &KZGSettings,
|
||||
) -> Result<(Self, Bytes32), Error> {
|
||||
let mut kzg_proof = MaybeUninit::<KZGProof>::uninit();
|
||||
let mut y_out = MaybeUninit::<Bytes32>::uninit();
|
||||
unsafe {
|
||||
let res = compute_kzg_proof(
|
||||
kzg_proof.as_mut_ptr(),
|
||||
y_out.as_mut_ptr(),
|
||||
&blob,
|
||||
&z_bytes,
|
||||
kzg_settings,
|
||||
);
|
||||
if let C_KZG_RET::C_KZG_OK = res {
|
||||
Ok((kzg_proof.assume_init(), y_out.assume_init()))
|
||||
} else {
|
||||
Err(Error::CError(res))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compute_blob_kzg_proof(
|
||||
blob: Blob,
|
||||
commitment_bytes: Bytes48,
|
||||
kzg_settings: &KZGSettings,
|
||||
) -> Result<Self, Error> {
|
||||
let mut kzg_proof = MaybeUninit::<KZGProof>::uninit();
|
||||
unsafe {
|
||||
let res = compute_blob_kzg_proof(
|
||||
kzg_proof.as_mut_ptr(),
|
||||
&blob,
|
||||
&commitment_bytes,
|
||||
kzg_settings,
|
||||
);
|
||||
if let C_KZG_RET::C_KZG_OK = res {
|
||||
Ok(kzg_proof.assume_init())
|
||||
} else {
|
||||
Err(Error::CError(res))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn verify_kzg_proof(
|
||||
commitment_bytes: Bytes48,
|
||||
z_bytes: Bytes32,
|
||||
y_bytes: Bytes32,
|
||||
proof_bytes: Bytes48,
|
||||
kzg_settings: &KZGSettings,
|
||||
) -> Result<bool, Error> {
|
||||
let mut verified: MaybeUninit<bool> = MaybeUninit::uninit();
|
||||
unsafe {
|
||||
let res = verify_kzg_proof(
|
||||
verified.as_mut_ptr(),
|
||||
&commitment_bytes,
|
||||
&z_bytes,
|
||||
&y_bytes,
|
||||
&proof_bytes,
|
||||
kzg_settings,
|
||||
);
|
||||
if let C_KZG_RET::C_KZG_OK = res {
|
||||
Ok(verified.assume_init())
|
||||
} else {
|
||||
Err(Error::CError(res))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn verify_blob_kzg_proof(
|
||||
blob: Blob,
|
||||
commitment_bytes: Bytes48,
|
||||
proof_bytes: Bytes48,
|
||||
kzg_settings: &KZGSettings,
|
||||
) -> Result<bool, Error> {
|
||||
let mut verified: MaybeUninit<bool> = MaybeUninit::uninit();
|
||||
unsafe {
|
||||
let res = verify_blob_kzg_proof(
|
||||
verified.as_mut_ptr(),
|
||||
&blob,
|
||||
&commitment_bytes,
|
||||
&proof_bytes,
|
||||
kzg_settings,
|
||||
);
|
||||
if let C_KZG_RET::C_KZG_OK = res {
|
||||
Ok(verified.assume_init())
|
||||
} else {
|
||||
Err(Error::CError(res))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn verify_blob_kzg_proof_batch(
|
||||
blobs: &[Blob],
|
||||
commitments_bytes: &[Bytes48],
|
||||
proofs_bytes: &[Bytes48],
|
||||
kzg_settings: &KZGSettings,
|
||||
) -> Result<bool, Error> {
|
||||
if blobs.len() != commitments_bytes.len() {
|
||||
return Err(Error::MismatchLength(format!(
|
||||
"There are {} blobs and {} commitments",
|
||||
blobs.len(),
|
||||
commitments_bytes.len()
|
||||
)));
|
||||
}
|
||||
if blobs.len() != proofs_bytes.len() {
|
||||
return Err(Error::MismatchLength(format!(
|
||||
"There are {} blobs and {} proofs",
|
||||
blobs.len(),
|
||||
proofs_bytes.len()
|
||||
)));
|
||||
}
|
||||
let mut verified: MaybeUninit<bool> = MaybeUninit::uninit();
|
||||
unsafe {
|
||||
let res = verify_blob_kzg_proof_batch(
|
||||
verified.as_mut_ptr(),
|
||||
blobs.as_ptr(),
|
||||
commitments_bytes.as_ptr(),
|
||||
proofs_bytes.as_ptr(),
|
||||
blobs.len(),
|
||||
kzg_settings,
|
||||
);
|
||||
if let C_KZG_RET::C_KZG_OK = res {
|
||||
Ok(verified.assume_init())
|
||||
} else {
|
||||
Err(Error::CError(res))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl KZGCommitment {
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
|
||||
if bytes.len() != BYTES_PER_COMMITMENT {
|
||||
return Err(Error::InvalidKzgCommitment(format!(
|
||||
"Invalid byte length. Expected {} got {}",
|
||||
BYTES_PER_PROOF,
|
||||
bytes.len(),
|
||||
)));
|
||||
}
|
||||
let mut commitment = [0; BYTES_PER_COMMITMENT];
|
||||
commitment.copy_from_slice(bytes);
|
||||
Ok(Self { bytes: commitment })
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Bytes48 {
|
||||
let mut bytes = [0; 48];
|
||||
bytes.copy_from_slice(&self.bytes);
|
||||
Bytes48 { bytes }
|
||||
}
|
||||
|
||||
pub fn as_hex_string(&self) -> String {
|
||||
hex::encode(self.bytes)
|
||||
}
|
||||
|
||||
pub fn blob_to_kzg_commitment(blob: Blob, kzg_settings: &KZGSettings) -> Result<Self, Error> {
|
||||
let mut kzg_commitment: MaybeUninit<KZGCommitment> = MaybeUninit::uninit();
|
||||
unsafe {
|
||||
let res = blob_to_kzg_commitment(
|
||||
kzg_commitment.as_mut_ptr(),
|
||||
blob.as_ptr() as *const Blob,
|
||||
kzg_settings,
|
||||
);
|
||||
if let C_KZG_RET::C_KZG_OK = res {
|
||||
Ok(kzg_commitment.assume_init())
|
||||
} else {
|
||||
Err(Error::CError(res))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; BYTES_PER_COMMITMENT]> for KZGCommitment {
|
||||
fn from(value: [u8; BYTES_PER_COMMITMENT]) -> Self {
|
||||
Self { bytes: value }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; BYTES_PER_PROOF]> for KZGProof {
|
||||
fn from(value: [u8; BYTES_PER_PROOF]) -> Self {
|
||||
Self { bytes: value }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; BYTES_PER_BLOB]> for Blob {
|
||||
fn from(value: [u8; BYTES_PER_BLOB]) -> Self {
|
||||
Self { bytes: value }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; 32]> for Bytes32 {
|
||||
fn from(value: [u8; 32]) -> Self {
|
||||
Self { bytes: value }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; 48]> for Bytes48 {
|
||||
fn from(value: [u8; 48]) -> Self {
|
||||
Self { bytes: value }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use rand::{rngs::ThreadRng, Rng};
|
||||
use std::fs;
|
||||
|
||||
use crate::test_formats::{
|
||||
blob_to_kzg_commitment_test, compute_blob_kzg_proof, compute_kzg_proof,
|
||||
verify_blob_kzg_proof, verify_blob_kzg_proof_batch, verify_kzg_proof,
|
||||
};
|
||||
|
||||
fn generate_random_blob(rng: &mut ThreadRng) -> Blob {
|
||||
let mut arr = [0u8; BYTES_PER_BLOB];
|
||||
rng.fill(&mut arr[..]);
|
||||
// Ensure that the blob is canonical by ensuring that
|
||||
// each field element contained in the blob is < BLS_MODULUS
|
||||
for i in 0..FIELD_ELEMENTS_PER_BLOB {
|
||||
arr[i * BYTES_PER_FIELD_ELEMENT + BYTES_PER_FIELD_ELEMENT - 1] = 0;
|
||||
}
|
||||
arr.into()
|
||||
}
|
||||
|
||||
fn test_simple(trusted_setup_file: PathBuf) {
|
||||
let mut rng = rand::thread_rng();
|
||||
assert!(trusted_setup_file.exists());
|
||||
let kzg_settings = KZGSettings::load_trusted_setup_file(trusted_setup_file).unwrap();
|
||||
|
||||
let num_blobs: usize = rng.gen_range(1..16);
|
||||
let mut blobs: Vec<Blob> = (0..num_blobs)
|
||||
.map(|_| generate_random_blob(&mut rng))
|
||||
.collect();
|
||||
|
||||
let commitments: Vec<Bytes48> = blobs
|
||||
.iter()
|
||||
.map(|blob| KZGCommitment::blob_to_kzg_commitment(*blob, &kzg_settings).unwrap())
|
||||
.map(|commitment| commitment.to_bytes())
|
||||
.collect();
|
||||
|
||||
let proofs: Vec<Bytes48> = blobs
|
||||
.iter()
|
||||
.zip(commitments.iter())
|
||||
.map(|(blob, commitment)| {
|
||||
KZGProof::compute_blob_kzg_proof(*blob, *commitment, &kzg_settings).unwrap()
|
||||
})
|
||||
.map(|proof| proof.to_bytes())
|
||||
.collect();
|
||||
|
||||
assert!(KZGProof::verify_blob_kzg_proof_batch(
|
||||
&blobs,
|
||||
&commitments,
|
||||
&proofs,
|
||||
&kzg_settings
|
||||
)
|
||||
.unwrap());
|
||||
|
||||
blobs.pop();
|
||||
|
||||
let error =
|
||||
KZGProof::verify_blob_kzg_proof_batch(&blobs, &commitments, &proofs, &kzg_settings)
|
||||
.unwrap_err();
|
||||
assert!(matches!(error, Error::MismatchLength(_)));
|
||||
|
||||
let incorrect_blob = generate_random_blob(&mut rng);
|
||||
blobs.push(incorrect_blob);
|
||||
|
||||
assert!(!KZGProof::verify_blob_kzg_proof_batch(
|
||||
&blobs,
|
||||
&commitments,
|
||||
&proofs,
|
||||
&kzg_settings
|
||||
)
|
||||
.unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_end_to_end() {
|
||||
let trusted_setup_file = if cfg!(feature = "minimal-spec") {
|
||||
PathBuf::from("../../src/trusted_setup_4.txt")
|
||||
} else {
|
||||
PathBuf::from("../../src/trusted_setup.txt")
|
||||
};
|
||||
test_simple(trusted_setup_file);
|
||||
}
|
||||
|
||||
const BLOB_TO_KZG_COMMITMENT_TESTS: &str = "../../tests/blob_to_kzg_commitment/*/*/*";
|
||||
const COMPUTE_KZG_PROOF_TESTS: &str = "../../tests/compute_kzg_proof/*/*/*";
|
||||
const COMPUTE_BLOB_KZG_PROOF_TESTS: &str = "../../tests/compute_blob_kzg_proof/*/*/*";
|
||||
const VERIFY_KZG_PROOF_TESTS: &str = "../../tests/verify_kzg_proof/*/*/*";
|
||||
const VERIFY_BLOB_KZG_PROOF_TESTS: &str = "../../tests/verify_blob_kzg_proof/*/*/*";
|
||||
const VERIFY_BLOB_KZG_PROOF_BATCH_TESTS: &str = "../../tests/verify_blob_kzg_proof_batch/*/*/*";
|
||||
|
||||
#[cfg(not(feature = "minimal-spec"))]
|
||||
#[test]
|
||||
fn test_blob_to_kzg_commitment() {
|
||||
let trusted_setup_file = PathBuf::from("../../src/trusted_setup.txt");
|
||||
assert!(trusted_setup_file.exists());
|
||||
let kzg_settings = KZGSettings::load_trusted_setup_file(trusted_setup_file).unwrap();
|
||||
let test_files: Vec<PathBuf> = glob::glob(BLOB_TO_KZG_COMMITMENT_TESTS)
|
||||
.unwrap()
|
||||
.map(Result::unwrap)
|
||||
.collect();
|
||||
assert!(!test_files.is_empty());
|
||||
|
||||
for test_file in test_files {
|
||||
let yaml_data = fs::read_to_string(test_file).unwrap();
|
||||
let test: blob_to_kzg_commitment_test::Test = serde_yaml::from_str(&yaml_data).unwrap();
|
||||
let Ok(blob) = test.input.get_blob() else {
|
||||
assert!(test.get_output().is_none());
|
||||
continue;
|
||||
};
|
||||
|
||||
match KZGCommitment::blob_to_kzg_commitment(blob, &kzg_settings) {
|
||||
Ok(res) => assert_eq!(res.bytes, test.get_output().unwrap().bytes),
|
||||
_ => assert!(test.get_output().is_none()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "minimal-spec"))]
|
||||
#[test]
|
||||
fn test_compute_kzg_proof() {
|
||||
let trusted_setup_file = PathBuf::from("../../src/trusted_setup.txt");
|
||||
assert!(trusted_setup_file.exists());
|
||||
let kzg_settings = KZGSettings::load_trusted_setup_file(trusted_setup_file).unwrap();
|
||||
let test_files: Vec<PathBuf> = glob::glob(COMPUTE_KZG_PROOF_TESTS)
|
||||
.unwrap()
|
||||
.map(Result::unwrap)
|
||||
.collect();
|
||||
assert!(!test_files.is_empty());
|
||||
|
||||
for test_file in test_files {
|
||||
let yaml_data = fs::read_to_string(test_file).unwrap();
|
||||
let test: compute_kzg_proof::Test = serde_yaml::from_str(&yaml_data).unwrap();
|
||||
let (Ok(blob), Ok(z)) = (test.input.get_blob(), test.input.get_z()) else {
|
||||
assert!(test.get_output().is_none());
|
||||
continue;
|
||||
};
|
||||
|
||||
match KZGProof::compute_kzg_proof(blob, z, &kzg_settings) {
|
||||
Ok((proof, y)) => {
|
||||
assert_eq!(proof.bytes, test.get_output().unwrap().0.bytes);
|
||||
assert_eq!(y.bytes, test.get_output().unwrap().1.bytes);
|
||||
}
|
||||
_ => assert!(test.get_output().is_none()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "minimal-spec"))]
|
||||
#[test]
|
||||
fn test_compute_blob_kzg_proof() {
|
||||
let trusted_setup_file = PathBuf::from("../../src/trusted_setup.txt");
|
||||
assert!(trusted_setup_file.exists());
|
||||
let kzg_settings = KZGSettings::load_trusted_setup_file(trusted_setup_file).unwrap();
|
||||
let test_files: Vec<PathBuf> = glob::glob(COMPUTE_BLOB_KZG_PROOF_TESTS)
|
||||
.unwrap()
|
||||
.map(Result::unwrap)
|
||||
.collect();
|
||||
assert!(!test_files.is_empty());
|
||||
|
||||
for test_file in test_files {
|
||||
let yaml_data = fs::read_to_string(test_file).unwrap();
|
||||
let test: compute_blob_kzg_proof::Test = serde_yaml::from_str(&yaml_data).unwrap();
|
||||
let (Ok(blob), Ok(commitment)) = (
|
||||
test.input.get_blob(),
|
||||
test.input.get_commitment()
|
||||
) else {
|
||||
assert!(test.get_output().is_none());
|
||||
continue;
|
||||
};
|
||||
|
||||
match KZGProof::compute_blob_kzg_proof(blob, commitment, &kzg_settings) {
|
||||
Ok(res) => assert_eq!(res.bytes, test.get_output().unwrap().bytes),
|
||||
_ => assert!(test.get_output().is_none()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "minimal-spec"))]
|
||||
#[test]
|
||||
fn test_verify_kzg_proof() {
|
||||
let trusted_setup_file = PathBuf::from("../../src/trusted_setup.txt");
|
||||
assert!(trusted_setup_file.exists());
|
||||
let kzg_settings = KZGSettings::load_trusted_setup_file(trusted_setup_file).unwrap();
|
||||
let test_files: Vec<PathBuf> = glob::glob(VERIFY_KZG_PROOF_TESTS)
|
||||
.unwrap()
|
||||
.map(Result::unwrap)
|
||||
.collect();
|
||||
assert!(!test_files.is_empty());
|
||||
|
||||
for test_file in test_files {
|
||||
let yaml_data = fs::read_to_string(test_file).unwrap();
|
||||
let test: verify_kzg_proof::Test = serde_yaml::from_str(&yaml_data).unwrap();
|
||||
let (Ok(commitment), Ok(z), Ok(y), Ok(proof)) = (
|
||||
test.input.get_commitment(),
|
||||
test.input.get_z(),
|
||||
test.input.get_y(),
|
||||
test.input.get_proof()
|
||||
) else {
|
||||
assert!(test.get_output().is_none());
|
||||
continue;
|
||||
};
|
||||
|
||||
match KZGProof::verify_kzg_proof(commitment, z, y, proof, &kzg_settings) {
|
||||
Ok(res) => assert_eq!(res, test.get_output().unwrap()),
|
||||
_ => assert!(test.get_output().is_none()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "minimal-spec"))]
|
||||
#[test]
|
||||
fn test_verify_blob_kzg_proof() {
|
||||
let trusted_setup_file = PathBuf::from("../../src/trusted_setup.txt");
|
||||
assert!(trusted_setup_file.exists());
|
||||
let kzg_settings = KZGSettings::load_trusted_setup_file(trusted_setup_file).unwrap();
|
||||
let test_files: Vec<PathBuf> = glob::glob(VERIFY_BLOB_KZG_PROOF_TESTS)
|
||||
.unwrap()
|
||||
.map(Result::unwrap)
|
||||
.collect();
|
||||
assert!(!test_files.is_empty());
|
||||
|
||||
for test_file in test_files {
|
||||
let yaml_data = fs::read_to_string(test_file).unwrap();
|
||||
let test: verify_blob_kzg_proof::Test = serde_yaml::from_str(&yaml_data).unwrap();
|
||||
let (Ok(blob), Ok(commitment), Ok(proof)) = (
|
||||
test.input.get_blob(),
|
||||
test.input.get_commitment(),
|
||||
test.input.get_proof()
|
||||
) else {
|
||||
assert!(test.get_output().is_none());
|
||||
continue;
|
||||
};
|
||||
|
||||
match KZGProof::verify_blob_kzg_proof(blob, commitment, proof, &kzg_settings) {
|
||||
Ok(res) => assert_eq!(res, test.get_output().unwrap()),
|
||||
_ => assert!(test.get_output().is_none()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "minimal-spec"))]
|
||||
#[test]
|
||||
fn test_verify_blob_kzg_proof_batch() {
|
||||
let trusted_setup_file = PathBuf::from("../../src/trusted_setup.txt");
|
||||
assert!(trusted_setup_file.exists());
|
||||
let kzg_settings = KZGSettings::load_trusted_setup_file(trusted_setup_file).unwrap();
|
||||
let test_files: Vec<PathBuf> = glob::glob(VERIFY_BLOB_KZG_PROOF_BATCH_TESTS)
|
||||
.unwrap()
|
||||
.map(Result::unwrap)
|
||||
.collect();
|
||||
assert!(!test_files.is_empty());
|
||||
|
||||
for test_file in test_files {
|
||||
let yaml_data = fs::read_to_string(test_file).unwrap();
|
||||
let test: verify_blob_kzg_proof_batch::Test = serde_yaml::from_str(&yaml_data).unwrap();
|
||||
let (Ok(blobs), Ok(commitments), Ok(proofs)) = (
|
||||
test.input.get_blobs(),
|
||||
test.input.get_commitments(),
|
||||
test.input.get_proofs()
|
||||
) else {
|
||||
assert!(test.get_output().is_none());
|
||||
continue;
|
||||
};
|
||||
|
||||
match KZGProof::verify_blob_kzg_proof_batch(
|
||||
&blobs,
|
||||
&commitments,
|
||||
&proofs,
|
||||
&kzg_settings,
|
||||
) {
|
||||
Ok(res) => assert_eq!(res, test.get_output().unwrap()),
|
||||
_ => assert!(test.get_output().is_none()),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mod bindings;
|
||||
|
||||
// Expose relevant types with idiomatic names.
|
||||
pub use bindings::{
|
||||
KZGCommitment as KzgCommitment, KZGProof as KzgProof, KZGSettings as KzgSettings,
|
||||
C_KZG_RET as CkzgError,
|
||||
};
|
||||
// Expose the constants.
|
||||
pub use bindings::{
|
||||
BYTES_PER_BLOB, BYTES_PER_COMMITMENT, BYTES_PER_FIELD_ELEMENT, BYTES_PER_PROOF,
|
||||
FIELD_ELEMENTS_PER_BLOB,
|
||||
};
|
||||
// Expose the remaining relevant types.
|
||||
pub use bindings::{Blob, Bytes32, Bytes48, Error, FFTSettings};
|
||||
|
|
Loading…
Reference in New Issue