aboutsummaryrefslogtreecommitdiff
path: root/guests
diff options
context:
space:
mode:
authorKamen Mladenov <kamen@syndamia.com>2025-02-17 18:37:08 +0200
committerKamen Mladenov <kamen@syndamia.com>2025-04-15 14:39:37 +0300
commitefdd6857ab7e9b25e6c3e173fc32ca63812ac21c (patch)
tree04d5dd673a77bc267b07775e9ef1bad577d53c54 /guests
parent32b2f8b3a630ebf04259457c5f9522b6bc71b7ff (diff)
downloadzkVMs-benchmarks-dvt-circuits-port.tar
zkVMs-benchmarks-dvt-circuits-port.tar.gz
zkVMs-benchmarks-dvt-circuits-port.zip
feat(guests): Add dvt-circuits cratedvt-circuits-port
This is a port of https://github.com/metacraft-labs/dvt-circuits Co-authored-by: Marto <martindobrev0@gmail.com>
Diffstat (limited to 'guests')
-rw-r--r--guests/dvt-circuits/Cargo.lock848
-rw-r--r--guests/dvt-circuits/Cargo.toml36
-rw-r--r--guests/dvt-circuits/bls_utils/Cargo.toml15
-rw-r--r--guests/dvt-circuits/bls_utils/src/bls.rs410
-rw-r--r--guests/dvt-circuits/bls_utils/src/lib.rs6
-rw-r--r--guests/dvt-circuits/bls_utils/src/verification.rs338
-rw-r--r--guests/dvt-circuits/default.env0
-rw-r--r--guests/dvt-circuits/default_private_input.toml64
-rw-r--r--guests/dvt-circuits/default_public_input.toml0
-rw-r--r--guests/dvt-circuits/dvt_abi/Cargo.toml11
-rw-r--r--guests/dvt-circuits/dvt_abi/src/lib.rs208
-rw-r--r--guests/dvt-circuits/src/lib.rs18
12 files changed, 1954 insertions, 0 deletions
diff --git a/guests/dvt-circuits/Cargo.lock b/guests/dvt-circuits/Cargo.lock
new file mode 100644
index 0000000..c02a82d
--- /dev/null
+++ b/guests/dvt-circuits/Cargo.lock
@@ -0,0 +1,848 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "bitvec"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
+dependencies = [
+ "funty",
+ "radium",
+ "tap",
+ "wyz",
+]
+
+[[package]]
+name = "block-buffer"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "bls12_381"
+version = "0.8.0"
+source = "git+https://github.com/sp1-patches/bls12_381#9ea427c0eb1a7e2ac16902a322aea156c496ddb0"
+dependencies = [
+ "digest",
+ "ff",
+ "group",
+ "pairing",
+ "rand_core",
+ "subtle",
+]
+
+[[package]]
+name = "bls_utils"
+version = "0.1.0"
+dependencies = [
+ "bls12_381",
+ "dvt_abi",
+ "ff",
+ "group",
+ "hex",
+ "rand",
+ "serde",
+ "sha2",
+]
+
+[[package]]
+name = "byteorder"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "cpufeatures"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
+[[package]]
+name = "darling"
+version = "0.20.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
+dependencies = [
+ "darling_core",
+ "darling_macro",
+]
+
+[[package]]
+name = "darling_core"
+version = "0.20.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
+dependencies = [
+ "fnv",
+ "ident_case",
+ "proc-macro2",
+ "quote",
+ "strsim",
+ "syn",
+]
+
+[[package]]
+name = "darling_macro"
+version = "0.20.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
+dependencies = [
+ "darling_core",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "digest"
+version = "0.10.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
+dependencies = [
+ "block-buffer",
+ "crypto-common",
+]
+
+[[package]]
+name = "displaydoc"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "dvt_abi"
+version = "0.1.0"
+dependencies = [
+ "hex",
+ "serde",
+ "serde_json",
+ "validator",
+]
+
+[[package]]
+name = "ff"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449"
+dependencies = [
+ "bitvec",
+ "rand_core",
+ "subtle",
+]
+
+[[package]]
+name = "finalization_prove"
+version = "1.1.0"
+dependencies = [
+ "bls12_381",
+ "bls_utils",
+ "dvt_abi",
+ "ff",
+ "group",
+ "guests_macro",
+ "hex",
+ "rand",
+ "serde",
+ "sha2",
+]
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "form_urlencoded"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
+name = "funty"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
+
+[[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "group"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
+dependencies = [
+ "ff",
+ "rand_core",
+ "subtle",
+]
+
+[[package]]
+name = "guests_macro"
+version = "0.1.0"
+
+[[package]]
+name = "hex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+
+[[package]]
+name = "icu_collections"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
+dependencies = [
+ "displaydoc",
+ "yoke",
+ "zerofrom",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
+dependencies = [
+ "displaydoc",
+ "litemap",
+ "tinystr",
+ "writeable",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid_transform"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
+dependencies = [
+ "displaydoc",
+ "icu_locid",
+ "icu_locid_transform_data",
+ "icu_provider",
+ "tinystr",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid_transform_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
+
+[[package]]
+name = "icu_normalizer"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
+dependencies = [
+ "displaydoc",
+ "icu_collections",
+ "icu_normalizer_data",
+ "icu_properties",
+ "icu_provider",
+ "smallvec",
+ "utf16_iter",
+ "utf8_iter",
+ "write16",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_normalizer_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
+
+[[package]]
+name = "icu_properties"
+version = "1.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5"
+dependencies = [
+ "displaydoc",
+ "icu_collections",
+ "icu_locid_transform",
+ "icu_properties_data",
+ "icu_provider",
+ "tinystr",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_properties_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
+
+[[package]]
+name = "icu_provider"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
+dependencies = [
+ "displaydoc",
+ "icu_locid",
+ "icu_provider_macros",
+ "stable_deref_trait",
+ "tinystr",
+ "writeable",
+ "yoke",
+ "zerofrom",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_provider_macros"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "ident_case"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
+
+[[package]]
+name = "idna"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
+dependencies = [
+ "idna_adapter",
+ "smallvec",
+ "utf8_iter",
+]
+
+[[package]]
+name = "idna_adapter"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71"
+dependencies = [
+ "icu_normalizer",
+ "icu_properties",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
+
+[[package]]
+name = "libc"
+version = "0.2.169"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
+
+[[package]]
+name = "litemap"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
+
+[[package]]
+name = "memchr"
+version = "2.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+
+[[package]]
+name = "once_cell"
+version = "1.20.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e"
+
+[[package]]
+name = "pairing"
+version = "0.23.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81fec4625e73cf41ef4bb6846cafa6d44736525f442ba45e407c4a000a13996f"
+dependencies = [
+ "group",
+]
+
+[[package]]
+name = "percent-encoding"
+version = "2.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
+dependencies = [
+ "zerocopy",
+]
+
+[[package]]
+name = "proc-macro-error-attr2"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+]
+
+[[package]]
+name = "proc-macro-error2"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802"
+dependencies = [
+ "proc-macro-error-attr2",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.93"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "radium"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "regex"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
+
+[[package]]
+name = "ryu"
+version = "1.0.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd"
+
+[[package]]
+name = "serde"
+version = "1.0.217"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.217"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.138"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949"
+dependencies = [
+ "itoa",
+ "memchr",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "sha2"
+version = "0.10.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd"
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+
+[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+
+[[package]]
+name = "subtle"
+version = "2.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
+
+[[package]]
+name = "syn"
+version = "2.0.98"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "synstructure"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tap"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
+
+[[package]]
+name = "tinystr"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
+dependencies = [
+ "displaydoc",
+ "zerovec",
+]
+
+[[package]]
+name = "typenum"
+version = "1.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034"
+
+[[package]]
+name = "url"
+version = "2.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "percent-encoding",
+]
+
+[[package]]
+name = "utf16_iter"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
+
+[[package]]
+name = "utf8_iter"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
+
+[[package]]
+name = "validator"
+version = "0.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0b4a29d8709210980a09379f27ee31549b73292c87ab9899beee1c0d3be6303"
+dependencies = [
+ "idna",
+ "once_cell",
+ "regex",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "url",
+ "validator_derive",
+]
+
+[[package]]
+name = "validator_derive"
+version = "0.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bac855a2ce6f843beb229757e6e570a42e837bcb15e5f449dd48d5747d41bf77"
+dependencies = [
+ "darling",
+ "once_cell",
+ "proc-macro-error2",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "version_check"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "write16"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
+
+[[package]]
+name = "writeable"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
+
+[[package]]
+name = "wyz"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
+dependencies = [
+ "tap",
+]
+
+[[package]]
+name = "yoke"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
+dependencies = [
+ "serde",
+ "stable_deref_trait",
+ "yoke-derive",
+ "zerofrom",
+]
+
+[[package]]
+name = "yoke-derive"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
+[[package]]
+name = "zerocopy"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
+dependencies = [
+ "byteorder",
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "zerofrom"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e"
+dependencies = [
+ "zerofrom-derive",
+]
+
+[[package]]
+name = "zerofrom-derive"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
+[[package]]
+name = "zerovec"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079"
+dependencies = [
+ "yoke",
+ "zerofrom",
+ "zerovec-derive",
+]
+
+[[package]]
+name = "zerovec-derive"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
diff --git a/guests/dvt-circuits/Cargo.toml b/guests/dvt-circuits/Cargo.toml
new file mode 100644
index 0000000..0f01828
--- /dev/null
+++ b/guests/dvt-circuits/Cargo.toml
@@ -0,0 +1,36 @@
+[package]
+name = "finalization_prove"
+version = "1.1.0"
+edition = "2021"
+publish = false
+
+[workspace]
+members = [
+ "bls_utils",
+ "dvt_abi",
+]
+
+[workspace.package]
+edition = "2021"
+version = "0.1.0"
+authors = ["Martin Dobrev <martindobrev0@gmail.com>", "Grigor Gachev", "Zahary Karadjov" ]
+keywords = ["nimbus", "dvt"]
+categories = ["cryptography"]
+repository = "https://github.com/metacraft-labs/dvt-circuits"
+license = "MIT OR Apache-2.0"
+
+[dependencies]
+bls12_381 = { git = "https://github.com/sp1-patches/bls12_381", features = ["experimental"] }
+ff = "0.13.0"
+rand = "0.8.5"
+group = "0.13.0"
+serde = "1.0.216"
+dvt_abi = { path = "./dvt_abi" }
+bls_utils = { path = "./bls_utils" }
+sha2 = "0.10"
+hex = "0.4"
+
+guests_macro = { version = "0.1.0", path = "../../guests_macro" }
+
+[features]
+no_std = []
diff --git a/guests/dvt-circuits/bls_utils/Cargo.toml b/guests/dvt-circuits/bls_utils/Cargo.toml
new file mode 100644
index 0000000..a6f4922
--- /dev/null
+++ b/guests/dvt-circuits/bls_utils/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+name = "bls_utils"
+version = { workspace = true }
+authors = { workspace = true }
+edition = { workspace = true }
+
+[dependencies]
+bls12_381 = { git = "https://github.com/sp1-patches/bls12_381", features = ["experimental"] }
+ff = "0.13.0"
+rand = "0.8.5"
+group = "0.13.0"
+serde = "1.0.216"
+dvt_abi = { path = "../dvt_abi" }
+sha2 = "0.10"
+hex = "0.4"
diff --git a/guests/dvt-circuits/bls_utils/src/bls.rs b/guests/dvt-circuits/bls_utils/src/bls.rs
new file mode 100644
index 0000000..3a6c7ba
--- /dev/null
+++ b/guests/dvt-circuits/bls_utils/src/bls.rs
@@ -0,0 +1,410 @@
+use bls12_381::{
+ hash_to_curve::{ExpandMsgXmd, HashToCurve},
+ pairing, G1Affine, G1Projective, G2Affine, G2Projective, Scalar,
+};
+
+use dvt_abi::{self};
+use sha2::Sha256;
+use std::fmt;
+
+// https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing
+//
+// In Shamir's secret sharing, a secret is encoded as a n-degree polynomial
+// F where the secret value is equal to F(0). Here, F(0) is provided as mask[0].
+//
+// A key share is generated by evaluating the polynomial in the `id` point.
+// Later we can use at least N of these points to recover the original secret.
+//
+// Furthermore, if we sign some message M with at least K of the secret key
+// shares we can restore from them the signature of the same message signed
+// with original secret key.
+//
+// For a more gentle introductiont to Shamir's secret sharing, see also:
+//
+// https://github.com/dashpay/dips/blob/master/dip-0006/bls_m-of-n_threshold_scheme_and_dkg.md
+// https://medium.com/toruslabs/what-distributed-key-generation-is-866adc79620
+pub fn evaluate_polynomial(cfs: Vec<G1Affine>, x: Scalar) -> G1Affine {
+ let cfst: Vec<G1Projective> = cfs.iter().map(|c| G1Projective::from(c)).collect();
+ let count = cfst.len();
+ if count == 0 {
+ return G1Affine::identity();
+ } else if count == 1 {
+ return cfs[0];
+ } else {
+ let mut y = cfst[count - 1];
+ for i in 2..(count + 1) {
+ y = y * x + cfs[count - i];
+ }
+ return G1Affine::from(y);
+ }
+}
+
+pub fn lagrange_interpolation(
+ y_vec: &Vec<G1Affine>,
+ x_vec: &Vec<Scalar>,
+) -> Result<G1Affine, Box<dyn std::error::Error>> {
+ let k = x_vec.len();
+ if k == 0 || k != y_vec.len() {
+ return Err(Box::new(std::io::Error::new(
+ std::io::ErrorKind::InvalidData,
+ "invalid inputs",
+ )));
+ }
+ if k == 1 {
+ return Ok(y_vec[0]);
+ }
+
+ // We calculate L(0) so we can simplify
+ // (X - X0) .. (X - Xj-1) * (X - Xj+1) .. (X - Xk) to just X0 * X1 .. Xk
+ // Later we can divide by Xi for each basis polynomial li(0)
+ let mut a = x_vec[0];
+ for i in 1..k {
+ a *= x_vec[i];
+ }
+ if a == Scalar::zero() {
+ return Err(Box::new(std::io::Error::new(
+ std::io::ErrorKind::InvalidData,
+ "zero secret share id",
+ )));
+ }
+ let mut r = G1Projective::identity();
+ for i in 0..k {
+ let mut b = x_vec[i];
+ for j in 0..k {
+ if j != i {
+ let v = x_vec[j] - x_vec[i];
+ if v == Scalar::zero() {
+ return Err(Box::new(std::io::Error::new(
+ std::io::ErrorKind::InvalidData,
+ "duplicate secret share id",
+ )));
+ }
+ b *= v;
+ }
+ }
+ let li0 = a * b.invert().unwrap();
+ let tmp = y_vec[i] * li0;
+ r = r + tmp;
+ }
+ Ok(G1Affine::from(r))
+}
+
+pub fn hash_message_to_g2(msg: &[u8], domain: &[u8]) -> G2Projective {
+ <G2Projective as HashToCurve<ExpandMsgXmd<Sha256>>>::hash_to_curve([msg], domain)
+}
+
+pub fn bls_verify(pubkey: &G1Affine, signature: &G2Affine, message: &[u8]) -> bool {
+ let domain = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_";
+ let pk_projective = G1Projective::from(pubkey);
+ let sig_projective = G2Projective::from(signature);
+
+ let hashed_msg = hash_message_to_g2(message, domain);
+ let left = pairing(&G1Affine::from(pk_projective), &G2Affine::from(hashed_msg));
+ let right = pairing(&G1Affine::generator(), &G2Affine::from(sig_projective));
+
+ left == right
+}
+
+pub fn bls_id_from_u32(id: u32) -> Scalar {
+ let unwrapped_le: [u8; 4] = (id as u32).to_le_bytes();
+ let mut bytes = [0u8; 32];
+ bytes[..4].copy_from_slice(&unwrapped_le);
+ Scalar::from_bytes(&bytes).unwrap()
+}
+
+#[derive(PartialEq)]
+pub struct PublicKey {
+ key: G1Affine,
+}
+
+#[derive(PartialEq)]
+pub struct SecretKey {
+ key: Scalar,
+}
+
+impl PublicKey {
+ pub fn to_hex(&self) -> String {
+ hex::encode(self.key.to_compressed())
+ }
+
+ pub fn from_bytes(bytes: &dvt_abi::BLSPubkey) -> Result<PublicKey, Box<dyn std::error::Error>> {
+ let g1 = G1Affine::from_compressed(&bytes).into_option();
+ match g1 {
+ Some(g1) => Ok(PublicKey { key: g1 }),
+ None => Err(Box::new(std::io::Error::new(
+ std::io::ErrorKind::InvalidData,
+ "Invalid public key",
+ ))),
+ }
+ }
+
+ pub fn from_g1(g1: &G1Affine) -> PublicKey {
+ PublicKey { key: *g1 }
+ }
+
+ pub fn verify_signature(&self, message: &[u8], signature: &dvt_abi::BLSSignature) -> bool {
+ bls_verify(
+ &self.key,
+ &G2Affine::from_compressed(signature).into_option().unwrap(),
+ message,
+ )
+ }
+
+ pub fn eq(&self, g1: &G1Affine) -> bool {
+ self.key == *g1
+ }
+}
+
+impl SecretKey {
+ pub fn to_public_key(&self) -> PublicKey {
+ PublicKey {
+ key: G1Affine::from(G1Affine::generator() * self.key),
+ }
+ }
+
+ pub fn from_bytes(bytes: &[u8; 32]) -> Result<SecretKey, Box<dyn std::error::Error>> {
+ let mut le_bytes = bytes.clone();
+ le_bytes.reverse();
+
+ let sk = Scalar::from_bytes(&le_bytes);
+
+ if sk.is_none().into() {
+ return Err(Box::new(std::io::Error::new(
+ std::io::ErrorKind::InvalidData,
+ "Invalid secret key",
+ )));
+ }
+
+ Ok(SecretKey { key: sk.unwrap() })
+ }
+
+ pub fn to_bytes(&self) -> [u8; 32] {
+ self.key.to_bytes()
+ }
+}
+
+impl fmt::Debug for PublicKey {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "PublicKey({})", self.to_hex())
+ }
+}
+
+impl fmt::Debug for SecretKey {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "SecretKey({})", hex::encode(self.to_bytes()))
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use dvt_abi::{BLSPubkey, BLSSignature};
+
+ use super::*;
+
+ #[test]
+ fn test_bls_id_from_u32() {
+ let mut bytes: [u8; 32] = [
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,
+ ];
+ assert_eq!(bls_id_from_u32(0), Scalar::from_bytes(&bytes).unwrap());
+ bytes[0] = 1;
+ assert_eq!(bls_id_from_u32(1), Scalar::from_bytes(&bytes).unwrap());
+ bytes[0] = 2;
+ assert_eq!(bls_id_from_u32(2), Scalar::from_bytes(&bytes).unwrap());
+ }
+
+ #[test]
+ fn test_bls_id_from_u32_to_hex() {
+ let id = bls_id_from_u32(0);
+ assert_eq!(
+ hex::encode(id.to_bytes()),
+ "0000000000000000000000000000000000000000000000000000000000000000"
+ );
+ let id = bls_id_from_u32(1);
+ assert_eq!(
+ hex::encode(id.to_bytes()),
+ "0100000000000000000000000000000000000000000000000000000000000000"
+ );
+ let id = bls_id_from_u32(2);
+ assert_eq!(
+ hex::encode(id.to_bytes()),
+ "0200000000000000000000000000000000000000000000000000000000000000"
+ );
+ }
+
+ #[test]
+ fn test_verify_signature() {
+ let data = hex::decode("2f901d5cec8722e44afd59e94d0a56bf1506a72a0a60709920aad714d1a2ece0")
+ .unwrap();
+ let pk: BLSPubkey = hex::decode("90346f9c5f3c09d96ea02acd0220daa8459f03866ed938c798e3716e42c7e033c9a7ef66a10f83af06d5c00b508c6d0f").unwrap().try_into().unwrap();
+ let sig:BLSSignature = hex::decode("a9c08eff13742f78f1e5929888f223b5b5b12b4836b5417c5a135cf24f4e2a4c66a6cdef91be3098b7e7a6a63903b61302e3cf2b8653101da245cf01a8d82b25debe7b18a3a2eb1778f8628fd2c59c8687f6e048a31250fbc2804c20043b8443").unwrap().try_into().unwrap();
+ let pk = G1Affine::from_compressed(&pk).into_option().unwrap();
+ let sig = G2Affine::from_compressed(&sig).into_option().unwrap();
+ assert!(bls_verify(&pk, &sig, &data));
+
+ let invalida_data = hex::decode("00").unwrap();
+ assert!(!bls_verify(&pk, &sig, &invalida_data));
+
+ let wrong_pk: BLSPubkey = hex::decode("98876a81fe982573ec5f986956bf9bf0bcb5349d95c3c8da0aefd05a49fea6215f59b0696f906547baed90ab245804e8").unwrap().try_into().unwrap();
+ let wrong_pk = G1Affine::from_compressed(&wrong_pk).into_option().unwrap();
+ assert!(!bls_verify(&wrong_pk, &sig, &data));
+
+ let bad_sig: BLSSignature = hex::decode("999e7b24bee2587d687e8f358ed10627ef57ec54935bd7a500bbbb18a57e7aa21b800f8b1f487a980d7c93918fdbd8020b66ce9a9e5788a4826e610ac937d8c2ce0ad9c0ee9a5732cf73052493e9a500cc5100a15bdbf9e5b79104db52dbf07c").unwrap().try_into().unwrap();
+ let bad_sig = G2Affine::from_compressed(&bad_sig).into_option().unwrap();
+ assert!(!bls_verify(&pk, &bad_sig, &data))
+ }
+
+ #[test]
+ fn test_evaluate_polynomial() {
+ let pks: Vec<G1Affine> = [
+ "92cad77a95432bc1030d81b5465cb69be672c1dd0da752230bf8112f8449b03149e7fa208a6fae460a9f0a1d5bd175e9",
+ "98876a81fe982573ec5f986956bf9bf0bcb5349d95c3c8da0aefd05a49fea6215f59b0696f906547baed90ab245804e8",
+ "ad2c4e5b631fbded449ede4dca2d040b9c7eae58d1e73b3050486c1ba22c15a92d9ff13c05c356f974447e4fca84864a"]
+ .iter().map(|pk| -> BLSPubkey {
+ hex::decode(pk).unwrap().try_into().unwrap()
+ })
+ .map(|pk| G1Affine::from_compressed(&pk).into_option().unwrap()).collect();
+
+ let target = "af8e0095ecc662f65b95ce57e5bd2f8739ff93b0621a1ad53f5616538d1323ff40e6e9ddd7132298710974fe6fc0344e";
+
+ let id = bls_id_from_u32(1);
+
+ let result = evaluate_polynomial(pks, id);
+
+ assert!(hex::encode(result.to_compressed()) == target);
+ }
+
+ #[test]
+ fn test_evaluate_polynomial_bad_base_keys() {
+ let pks: Vec<G1Affine> = [
+ "92cad77a95432bc1030d81b5465cb69be672c1dd0da752230bf8112f8449b03149e7fa208a6fae460a9f0a1d5bd175e9",
+ "92cad77a95432bc1030d81b5465cb69be672c1dd0da752230bf8112f8449b03149e7fa208a6fae460a9f0a1d5bd175e9",
+ "92cad77a95432bc1030d81b5465cb69be672c1dd0da752230bf8112f8449b03149e7fa208a6fae460a9f0a1d5bd175e9"]
+ .iter().map(|pk| -> BLSPubkey {
+ hex::decode(pk).unwrap().try_into().unwrap()
+ })
+ .map(|pk| G1Affine::from_compressed(&pk).into_option().unwrap()).collect();
+
+ let target = "af8e0095ecc662f65b95ce57e5bd2f8739ff93b0621a1ad53f5616538d1323ff40e6e9ddd7132298710974fe6fc0344e";
+
+ let id = bls_id_from_u32(1);
+
+ let result = evaluate_polynomial(pks, id);
+
+ assert!(hex::encode(result.to_compressed()) != target);
+ }
+
+ #[test]
+ fn test_lagrange_interpolation() {
+ let pks: Vec<G1Affine> = [
+ "8da434e68daef9af33e39ab727557a3cd86d7991cd6b545746bf92c8edec37012912cfa2292a21512bce9040a1c0e502",
+ "a3cd061aab6013f7561978959482d79e9ca636392bc94d4bcad9cb6f90fe2cdf52100f211052f1570db0ca690b6a9903",
+ "8cbfb6cb7af927cfe5fb17621df7036de539b7ff4aa0620cdc218d6b7fe7f2e714a96bdeddb2a0dc24867a90594427e1",
+ "9892b390d9d3000c7bf04763006fbc617b7ba9c261fff35094aec3f43599f2c254ae667d9ba135747309b77cd02f1fbc",
+ "b255c8a66fd1a13373537e8a4ba258f4990c141fc3c06daccda0711f5ebaffc092f0e5b0e4454e6344e2f97957be4017"]
+ .iter().map(|pk| -> BLSPubkey {
+ hex::decode(pk).unwrap().try_into().unwrap()
+ })
+ .map(|pk| G1Affine::from_compressed(&pk).into_option().unwrap()).collect();
+
+ let target = "a31d9a483703cd0da9873e5e76b4de5f7035d0a73d79b3be8667daa4fc7065a1bbb5bf77787fcf2a35bd327eecc4fa6b";
+
+ let ids = vec![
+ bls_id_from_u32(1),
+ bls_id_from_u32(2),
+ bls_id_from_u32(3),
+ bls_id_from_u32(4),
+ bls_id_from_u32(5),
+ ];
+
+ let result = lagrange_interpolation(&pks, &ids);
+
+ assert!(hex::encode(result.unwrap().to_compressed()) == target);
+ }
+
+ #[test]
+ fn test_lagrange_interpolation_out_of_order() {
+ let pks: Vec<G1Affine> = [
+ "b255c8a66fd1a13373537e8a4ba258f4990c141fc3c06daccda0711f5ebaffc092f0e5b0e4454e6344e2f97957be4017",
+ "8da434e68daef9af33e39ab727557a3cd86d7991cd6b545746bf92c8edec37012912cfa2292a21512bce9040a1c0e502",
+ "a3cd061aab6013f7561978959482d79e9ca636392bc94d4bcad9cb6f90fe2cdf52100f211052f1570db0ca690b6a9903",
+ "8cbfb6cb7af927cfe5fb17621df7036de539b7ff4aa0620cdc218d6b7fe7f2e714a96bdeddb2a0dc24867a90594427e1",
+ "9892b390d9d3000c7bf04763006fbc617b7ba9c261fff35094aec3f43599f2c254ae667d9ba135747309b77cd02f1fbc",
+ ]
+ .iter().map(|pk| -> BLSPubkey {
+ hex::decode(pk).unwrap().try_into().unwrap()
+ })
+ .map(|pk| G1Affine::from_compressed(&pk).into_option().unwrap()).collect();
+
+ let target = "a31d9a483703cd0da9873e5e76b4de5f7035d0a73d79b3be8667daa4fc7065a1bbb5bf77787fcf2a35bd327eecc4fa6b";
+
+ let ids = vec![
+ bls_id_from_u32(5),
+ bls_id_from_u32(1),
+ bls_id_from_u32(2),
+ bls_id_from_u32(3),
+ bls_id_from_u32(4),
+ ];
+
+ let result = lagrange_interpolation(&pks, &ids);
+
+ assert!(hex::encode(result.unwrap().to_compressed()) == target);
+ }
+
+ #[test]
+ fn test_lagrange_interpolation_wrong_order() {
+ let pks: Vec<G1Affine> = [
+ "a3cd061aab6013f7561978959482d79e9ca636392bc94d4bcad9cb6f90fe2cdf52100f211052f1570db0ca690b6a9903",
+ "8da434e68daef9af33e39ab727557a3cd86d7991cd6b545746bf92c8edec37012912cfa2292a21512bce9040a1c0e502",
+ "8cbfb6cb7af927cfe5fb17621df7036de539b7ff4aa0620cdc218d6b7fe7f2e714a96bdeddb2a0dc24867a90594427e1",
+ "9892b390d9d3000c7bf04763006fbc617b7ba9c261fff35094aec3f43599f2c254ae667d9ba135747309b77cd02f1fbc",
+ "b255c8a66fd1a13373537e8a4ba258f4990c141fc3c06daccda0711f5ebaffc092f0e5b0e4454e6344e2f97957be4017"]
+ .iter().map(|pk| -> BLSPubkey {
+ hex::decode(pk).unwrap().try_into().unwrap()
+ })
+ .map(|pk| G1Affine::from_compressed(&pk).into_option().unwrap()).collect();
+
+ let target = "a31d9a483703cd0da9873e5e76b4de5f7035d0a73d79b3be8667daa4fc7065a1bbb5bf77787fcf2a35bd327eecc4fa6b";
+
+ let ids = vec![
+ bls_id_from_u32(1),
+ bls_id_from_u32(2),
+ bls_id_from_u32(3),
+ bls_id_from_u32(4),
+ bls_id_from_u32(5),
+ ];
+
+ let result = lagrange_interpolation(&pks, &ids);
+
+ assert!(hex::encode(result.unwrap().to_compressed()) != target);
+ }
+
+ #[test]
+ fn test_lagrange_interpolation_wrong_base_keys() {
+ let pks: Vec<G1Affine> = [
+ "a3cd061aab6013f7561978959482d79e9ca636392bc94d4bcad9cb6f90fe2cdf52100f211052f1570db0ca690b6a9903",
+ "a3cd061aab6013f7561978959482d79e9ca636392bc94d4bcad9cb6f90fe2cdf52100f211052f1570db0ca690b6a9903",
+ "a3cd061aab6013f7561978959482d79e9ca636392bc94d4bcad9cb6f90fe2cdf52100f211052f1570db0ca690b6a9903",
+ "a3cd061aab6013f7561978959482d79e9ca636392bc94d4bcad9cb6f90fe2cdf52100f211052f1570db0ca690b6a9903",
+ "a3cd061aab6013f7561978959482d79e9ca636392bc94d4bcad9cb6f90fe2cdf52100f211052f1570db0ca690b6a9903"]
+ .iter().map(|pk| -> BLSPubkey {
+ hex::decode(pk).unwrap().try_into().unwrap()
+ })
+ .map(|pk| G1Affine::from_compressed(&pk).into_option().unwrap()).collect();
+
+ let target = "a31d9a483703cd0da9873e5e76b4de5f7035d0a73d79b3be8667daa4fc7065a1bbb5bf77787fcf2a35bd327eecc4fa6b";
+
+ let ids = vec![
+ bls_id_from_u32(1),
+ bls_id_from_u32(2),
+ bls_id_from_u32(3),
+ bls_id_from_u32(4),
+ bls_id_from_u32(5),
+ ];
+
+ let result = lagrange_interpolation(&pks, &ids);
+
+ assert!(hex::encode(result.unwrap().to_compressed()) != target);
+ }
+}
diff --git a/guests/dvt-circuits/bls_utils/src/lib.rs b/guests/dvt-circuits/bls_utils/src/lib.rs
new file mode 100644
index 0000000..6ae7927
--- /dev/null
+++ b/guests/dvt-circuits/bls_utils/src/lib.rs
@@ -0,0 +1,6 @@
+pub mod bls;
+pub mod verification;
+
+pub use verification::{
+ verify_generations, verify_initial_commitment_hash, verify_seed_exchange_commitment, VerificationErrors
+};
diff --git a/guests/dvt-circuits/bls_utils/src/verification.rs b/guests/dvt-circuits/bls_utils/src/verification.rs
new file mode 100644
index 0000000..ea414c5
--- /dev/null
+++ b/guests/dvt-circuits/bls_utils/src/verification.rs
@@ -0,0 +1,338 @@
+use bls12_381::{G1Affine, G1Projective, G2Affine, Scalar};
+
+use dvt_abi::{self};
+use sha2::{Digest, Sha256};
+
+use crate::bls::{
+ bls_id_from_u32, bls_verify, evaluate_polynomial, lagrange_interpolation, PublicKey, SecretKey,
+};
+
+#[derive(Debug)]
+pub enum VerificationErrors {
+ SlashableError(String),
+ UnslashableError(String),
+}
+
+impl std::fmt::Display for VerificationErrors {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ VerificationErrors::SlashableError(e) => write!(f, "{}", e),
+ VerificationErrors::UnslashableError(e) => write!(f, "{}", e),
+ }
+ }
+}
+
+impl std::error::Error for VerificationErrors {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
+ None
+ }
+}
+
+pub fn compute_seed_exchange_hash(
+ seed_exchange: &dvt_abi::AbiSeedExchangeCommitment,
+) -> dvt_abi::SHA256 {
+ let shared_secret = &seed_exchange.shared_secret;
+ let mut hasher = Sha256::new();
+
+ let sk = SecretKey::from_bytes(&shared_secret.secret).unwrap();
+
+ hasher.update(&seed_exchange.initial_commitment_hash);
+ hasher.update(&sk.to_bytes());
+ hasher.update(&shared_secret.dst_base_hash);
+ hasher.update(&shared_secret.src_id);
+ hasher.update(&shared_secret.dst_id);
+
+ hasher.finalize().to_vec().try_into().unwrap()
+}
+
+pub fn get_index_in_commitments(
+ commitments: &dvt_abi::AbiVerificationHashes,
+ destination_id: &dvt_abi::SHA256,
+) -> Result<u32, Box<dyn std::error::Error>> {
+ let mut sorted = commitments.clone();
+ sorted.sort();
+ for i in 0..sorted.len() {
+ if commitments[i] == *destination_id {
+ return Ok(i as u32);
+ }
+ }
+
+ Err(Box::new(std::io::Error::new(
+ std::io::ErrorKind::InvalidData,
+ "Could not find destination in commitments",
+ )))
+}
+
+pub fn verify_seed_exchange_commitment(
+ verification_hashes: &dvt_abi::AbiVerificationHashes,
+ seed_exchange: &dvt_abi::AbiSeedExchangeCommitment,
+ initial_commitment: &dvt_abi::AbiInitialCommitment,
+) -> Result<(), Box<dyn std::error::Error>> {
+ let commitment = &seed_exchange.commitment;
+ let shared_secret = &seed_exchange.shared_secret;
+
+ if !bls_verify(
+ &G1Affine::from_compressed(&commitment.pubkey)
+ .into_option()
+ .unwrap(),
+ &G2Affine::from_compressed(&commitment.signature)
+ .into_option()
+ .unwrap(),
+ &commitment.hash,
+ ) {
+ // Return unslashable error
+ return Err(Box::new(VerificationErrors::UnslashableError(
+ String::from(format!(
+ "Invalid field seeds_exchange_commitment.commitment.signature {}\n",
+ hex::encode(commitment.signature)
+ )),
+ )));
+ }
+
+ let sk = SecretKey::from_bytes(&shared_secret.secret);
+ if sk.is_err() {
+ return Err(Box::new(VerificationErrors::SlashableError(String::from(
+ format!(
+ "Invalid field seeds_exchange_commitment.shared_secret.secret: {} \n",
+ sk.unwrap_err()
+ ),
+ ))));
+ }
+
+ let sk = sk.unwrap();
+
+ let computed_commitment_hash = compute_seed_exchange_hash(seed_exchange);
+
+ if computed_commitment_hash.to_vec() != seed_exchange.commitment.hash {
+ return Err(Box::new(VerificationErrors::SlashableError(
+ String::from(format!(
+ "Invalid field seeds_exchange_commitment.commitment.hash. Expected: {:?}, got hash: {:?}\n",
+ hex::encode(seed_exchange.commitment.hash),
+ hex::encode(computed_commitment_hash.to_vec())
+ )),
+ )));
+ }
+
+ let dest_id = get_index_in_commitments(
+ verification_hashes,
+ &seed_exchange.shared_secret.dst_base_hash,
+ );
+
+ if dest_id.is_err() {
+ return Err(Box::new(VerificationErrors::SlashableError(String::from(
+ format!(
+ "Invalid field seeds_exchange_commitment.shared_secret.dst_id: {} \n",
+ dest_id.unwrap_err()
+ ),
+ ))));
+ }
+
+ let unwraped = dest_id.unwrap() + 1;
+ let test_id = bls_id_from_u32(unwraped);
+
+ let mut cfst: Vec<G1Affine> = Vec::new();
+ for pubkey in &initial_commitment.verification_vector.pubkeys {
+ cfst.push(G1Affine::from_compressed(pubkey).into_option().unwrap());
+ }
+
+ let le_bytes = seed_exchange.shared_secret.dst_id.clone();
+
+ let id = Scalar::from_bytes(&le_bytes).unwrap();
+
+ if id != test_id {
+ return Err(Box::new(VerificationErrors::SlashableError(String::from(
+ "Invalid field seeds_exchange_commitment.shared_secret.dst_id\n",
+ ))));
+ }
+ let eval_result = evaluate_polynomial(cfst, id);
+
+ if !sk.to_public_key().eq(&eval_result) {
+ return Err(Box::new(VerificationErrors::SlashableError(String::from(
+ format!(
+ "Bad secret field : Expected secret with public key: {:?}, got public key: {:?}\n",
+ PublicKey::from_g1(&eval_result),
+ sk.to_public_key()
+ ),
+ ))));
+ }
+
+ Ok(())
+}
+
+pub fn verify_initial_commitment_hash(commitment: &dvt_abi::AbiInitialCommitment) -> bool {
+ let mut hasher = Sha256::new();
+
+ hasher.update([commitment.settings.n]);
+ hasher.update([commitment.settings.k]);
+ hasher.update(commitment.settings.gen_id);
+ for pubkey in &commitment.verification_vector.pubkeys {
+ hasher.update(&pubkey);
+ }
+ let computed_hash = hasher.finalize().to_vec();
+ computed_hash == commitment.hash
+}
+
+fn verify_generation_sig(
+ generation: &dvt_abi::AbiGeneration,
+) -> Result<(), Box<dyn std::error::Error>> {
+ let partial_pubkey = PublicKey::from_bytes(&generation.partial_pubkey)?;
+ if !partial_pubkey
+ .verify_signature(&generation.message_cleartext, &generation.message_signature)
+ {
+ return Err(Box::new(std::io::Error::new(
+ std::io::ErrorKind::InvalidData,
+ format!(
+ "Invalid signature {}",
+ hex::encode(generation.partial_pubkey)
+ ),
+ )));
+ }
+ Ok(())
+}
+
+fn generate_initial_commitment(
+ generation: &dvt_abi::AbiGeneration,
+ settings: &dvt_abi::AbiGenerateSettings,
+) -> dvt_abi::AbiInitialCommitment {
+ dvt_abi::AbiInitialCommitment {
+ hash: generation.base_hash,
+ settings: dvt_abi::AbiGenerateSettings {
+ n: settings.n,
+ k: settings.k,
+ gen_id: settings.gen_id,
+ },
+ verification_vector: dvt_abi::AbiVerificationVector {
+ pubkeys: generation.verification_vector.clone(),
+ },
+ }
+}
+
+fn print_vec_g1_as_hex(v: &Vec<G1Affine>) {
+ for i in 0..v.len() {
+ println!("{} ", hex::encode(v[i].to_compressed()));
+ }
+}
+
+fn compute_agg_key_from_dvt(
+ verification_vectors: Vec<dvt_abi::AbiVerificationVector>,
+ ids: &Vec<Scalar>,
+) -> Result<G1Affine, Box<dyn std::error::Error>> {
+ let verification_vectors: Vec<Vec<G1Affine>> = verification_vectors
+ .iter()
+ .map(|vector| -> Vec<G1Affine> {
+ vector
+ .pubkeys
+ .iter()
+ .map(|pk: &[u8; 48]| G1Affine::from_compressed(&pk).into_option().unwrap())
+ .collect()
+ })
+ .collect();
+
+ let mut all_pts = Vec::new();
+
+ for i in 0..verification_vectors.len() {
+ let mut pts = Vec::new();
+ let share_id = ids[i];
+ for j in 0..verification_vectors.len() {
+ let pt = evaluate_polynomial(verification_vectors[j].clone(), share_id);
+ pts.push(pt);
+ }
+ all_pts.push(pts);
+ }
+ let mut final_keys = Vec::new();
+
+ for i in 0..all_pts.len() {
+ let mut key: G1Affine = all_pts[i][0];
+ for j in 1..all_pts[i].len() {
+ key = G1Affine::from(G1Projective::from(key) + G1Projective::from(all_pts[i][j]));
+ }
+ final_keys.push(key);
+ }
+
+ let agg_key = lagrange_interpolation(&final_keys, &ids)?;
+ return Ok(agg_key);
+}
+
+pub fn verify_generations(
+ generations: &[dvt_abi::AbiGeneration],
+ settings: &dvt_abi::AbiGenerateSettings,
+ agg_key: &dvt_abi::BLSPubkey,
+) -> Result<(), Box<dyn std::error::Error>> {
+
+ if generations.len() != settings.n as usize {
+ return Err(Box::new(std::io::Error::new(
+ std::io::ErrorKind::InvalidData,
+ "Invalid number of generations",
+ )));
+ }
+
+ let mut sorted = generations.to_vec();
+ sorted.sort_by(|a, b| a.base_hash.cmp(&b.base_hash));
+
+ let verification_vectors = sorted
+ .iter()
+ .map(|generation| -> dvt_abi::AbiVerificationVector {
+ dvt_abi::AbiVerificationVector {
+ pubkeys: generation.verification_vector.clone(),
+ }
+ })
+ .collect();
+
+ let ids = sorted
+ .iter()
+ .enumerate()
+ .map(|(i, _)| -> Scalar { bls_id_from_u32((i + 1) as u32) })
+ .collect();
+
+ let computed_key = compute_agg_key_from_dvt(verification_vectors, &ids)?;
+
+ let agg_key = G1Affine::from_compressed(agg_key).into_option();
+
+ if agg_key.is_none() {
+ return Err(Box::new(std::io::Error::new(
+ std::io::ErrorKind::InvalidData,
+ "Invalid aggregate public key",
+ )));
+ }
+
+ let agg_key = agg_key.unwrap();
+ if computed_key != agg_key {
+ return Err(Box::new(std::io::Error::new(
+ std::io::ErrorKind::InvalidData,
+ format!("Computed key {} does not match aggregate public key {}", hex::encode(computed_key.to_compressed()), hex::encode(agg_key.to_compressed())),
+ )));
+ }
+
+ let partial_keys = sorted
+ .iter()
+ .map(|generation| -> G1Affine {
+ G1Affine::from_compressed(&generation.partial_pubkey)
+ .into_option()
+ .unwrap()
+ })
+ .collect();
+
+ let computed_key = lagrange_interpolation(&partial_keys, &ids)?;
+
+ if computed_key != agg_key {
+ return Err(Box::new(std::io::Error::new(
+ std::io::ErrorKind::InvalidData,
+ format!("Computed key {} does not match aggregate public key {}", hex::encode(computed_key.to_compressed()), hex::encode(agg_key.to_compressed())),
+ )));
+ }
+
+ for (_, generation) in generations.iter().enumerate() {
+ verify_generation_sig(generation)?;
+ let initial_commitment = generate_initial_commitment(generation, &settings);
+ let ok = verify_initial_commitment_hash(&initial_commitment);
+ if !ok {
+ return Err(Box::new(VerificationErrors::UnslashableError(
+ String::from(format!(
+ "Invalid initial commitment hash {}\n",
+ hex::encode(initial_commitment.hash)
+ )),
+ )));
+ }
+ }
+ Ok(())
+}
diff --git a/guests/dvt-circuits/default.env b/guests/dvt-circuits/default.env
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/guests/dvt-circuits/default.env
diff --git a/guests/dvt-circuits/default_private_input.toml b/guests/dvt-circuits/default_private_input.toml
new file mode 100644
index 0000000..ef62058
--- /dev/null
+++ b/guests/dvt-circuits/default_private_input.toml
@@ -0,0 +1,64 @@
+generate_settings = [5, 3, "89f0996b33ca953e0cf9b70a5f84cb50"]
+generations = [
+ [
+ [
+ "aa772b2a290804da566759b4162de6ffc8f0a47b70908f8db932a3e8e1dff73eb04f59f7549df8a33219a333bb19659c",
+ "a19e4b16cc1d5de8c6fd87549f9fa1fa7de066c5cb566f610909e1a712780bf8c291e82e98b023121f70d980096e4af5",
+ "84496615716d84d3c1d69fb295c968ed4563acd51d0fd0cc624ccce384af1d479f7adbf0ee5cce74b80f248ff8224dee"
+ ],
+ "0bcbd9433dfde67e0dd7c501e255a2bdc31d6968e51b1290e6ef7d264911eb91",
+ "8da434e68daef9af33e39ab727557a3cd86d7991cd6b545746bf92c8edec37012912cfa2292a21512bce9040a1c0e502",
+ "test for signing",
+ "8a751bd10706178f9dae64b18ccb758abd0535d9592ca06c3ac44831715c6cb4e66eff0b0248cdae23ec0f921963ae58040feb4862929549b690e2d8073f7b937e971c1a2387feb8d11fdc107390290bb254e941700932e15cc2d63165e09d52",
+ ],
+
+ [
+ [
+ "92cad77a95432bc1030d81b5465cb69be672c1dd0da752230bf8112f8449b03149e7fa208a6fae460a9f0a1d5bd175e9",
+ "98876a81fe982573ec5f986956bf9bf0bcb5349d95c3c8da0aefd05a49fea6215f59b0696f906547baed90ab245804e8",
+ "ad2c4e5b631fbded449ede4dca2d040b9c7eae58d1e73b3050486c1ba22c15a92d9ff13c05c356f974447e4fca84864a"
+ ],
+ "13602b274436a91ffa3bd3eb16927e011d81fe9e2e9673769a0152acbafe3e33",
+ "a3cd061aab6013f7561978959482d79e9ca636392bc94d4bcad9cb6f90fe2cdf52100f211052f1570db0ca690b6a9903",
+ "test for signing",
+ "8268c0494f7228cb71472a9c8d05374336ac65b7af2b4fb52292867595d69138a75cfc9a5ff6f102de68a7e173a57f8e13a8378ef9e103adab85b9413b6455d0bb104fc176b0e4859f5c7719ac1f63955fecefbe9eca69a4fa42eadef5b27df5"
+ ],
+
+ [
+ [
+ "91283a9d9826347da8ef73ebe88a013989d2abecf0eb6368cb14e079da25fdf8e90fa2f793ad3566ac613882a93a531c",
+ "b059e3afa1f18c18eabb2be01a491b97b013b493e34bcf4fb288a7975e6a71a0e45d1d6b38d308a89726e99f09a7be85",
+ "a6d720d55aaae5b3a11758ca2dc5900ede471d508243b86d2adc715095c4a1efac82e96b6949763dfc288af555e8a9df"
+ ],
+ "1ae7975df76c5df0c301d390d82180ff536f5dbbf78942e53b4ec9e9e1497a1a",
+ "8cbfb6cb7af927cfe5fb17621df7036de539b7ff4aa0620cdc218d6b7fe7f2e714a96bdeddb2a0dc24867a90594427e1",
+ "test for signing",
+ "8b796dd8e8a35a6b97bd740388ad2da0399839f7ce83ae85e8651e23a0d58db44ccaca43e747713624344945ee7f25d803fe0919c669518e9bce2b0ba16e88f4ca05f5568b482b1a0068158468bc3ea8c9764b3dae9c7cb56002fcd5ab2ef25c"
+ ],
+
+ [
+ [
+ "ac70a68387afb0ad4912970b72afc0e1143833091414498ecab27661677f7b2a79aebee35cfbd95731d3b77985b4dc72",
+ "97bcf8fe7f75a87f5b9e4852f4b76fdad62d8af3dc8895f4db74e74d2096b10976f262e2930c89fccc484bc9edf6c0f3",
+ "a04c57e48a2ad82468f702b1d444f37af91fe4a05034d003fd1ff422958d37c30d29760d443e9374aa98bc096abf4d2d"
+ ],
+ "54effb7411607a0c6484cb68cad8a30fd03e24c0fd561c5c8a4c5baa0509f9b3",
+ "9892b390d9d3000c7bf04763006fbc617b7ba9c261fff35094aec3f43599f2c254ae667d9ba135747309b77cd02f1fbc",
+ "test for signing",
+ "999e7b24bee2587d687e8f358ed10627ef57ec54935bd7a500bbbb18a57e7aa21b800f8b1f487a980d7c93918fdbd8020b66ce9a9e5788a4826e610ac937d8c2ce0ad9c0ee9a5732cf73052493e9a500cc5100a15bdbf9e5b79104db52dbf07c"
+ ],
+
+ [
+ [
+ "a6e87e5bbed258d82a13c53e04c1c3fb5baa6649a28a0d00e4a934b6473575721a7f1f1c3787145f43a1bf15368619ee",
+ "858276460f23124923c94bf968024dd415a39a0f638d67f1d5f27ce8d8de75273d145cd70177a26bd76c07b8e784c98a",
+ "8174cc034101357048634437473371c7f6b8c39e2a305c2f95fc95c13ed03939a5c3bf2bdbbaab5351e8aa3443949038"
+ ],
+ "dbd8b546ab29bfa87aa9d568e8315037695e8802fa0e0c9ed9009fe8a0fde402",
+ "b255c8a66fd1a13373537e8a4ba258f4990c141fc3c06daccda0711f5ebaffc092f0e5b0e4454e6344e2f97957be4017",
+ "test for signing",
+ "b61e78c430eaea45f8b7974c411dd6d50eb8748fde211089838b1ca93ddefd2d9571548c4ee2eb03eec232997dc3818c1917af21083157f19966c998c35e4acf6c59e8e92bf0988692026580e425742a754eb69255e834dc75d9b729cd7ca83a"
+ ]
+]
+
+aggregate_pubkey = "a31d9a483703cd0da9873e5e76b4de5f7035d0a73d79b3be8667daa4fc7065a1bbb5bf77787fcf2a35bd327eecc4fa6b"
diff --git a/guests/dvt-circuits/default_public_input.toml b/guests/dvt-circuits/default_public_input.toml
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/guests/dvt-circuits/default_public_input.toml
diff --git a/guests/dvt-circuits/dvt_abi/Cargo.toml b/guests/dvt-circuits/dvt_abi/Cargo.toml
new file mode 100644
index 0000000..8147faf
--- /dev/null
+++ b/guests/dvt-circuits/dvt_abi/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "dvt_abi"
+version = { workspace = true }
+authors = { workspace = true }
+edition = { workspace = true }
+
+[dependencies]
+serde = { version = "1.0", features = ["derive"] }
+serde_json = "1.0"
+hex = "0.4.3"
+validator = { version = "0.19.0", features = ["derive"] } \ No newline at end of file
diff --git a/guests/dvt-circuits/dvt_abi/src/lib.rs b/guests/dvt-circuits/dvt_abi/src/lib.rs
new file mode 100644
index 0000000..ca3d946
--- /dev/null
+++ b/guests/dvt-circuits/dvt_abi/src/lib.rs
@@ -0,0 +1,208 @@
+use serde::de::DeserializeOwned;
+use serde::Deserialize;
+
+use validator::Validate;
+
+use hex::decode;
+use std::fs::File;
+use std::io::Read;
+
+use std::error::Error;
+
+pub const BLS_SIGNATURE_SIZE: usize = 96;
+pub const BLS_PUBKEY_SIZE: usize = 48;
+pub const BLS_SECRET_SIZE: usize = 32;
+pub const BLS_ID_SIZE: usize = 32;
+pub const GEN_ID_SIZE: usize = 16;
+pub const SHA256_SIZE: usize = 32;
+
+pub type BLSPubkey = [u8; BLS_PUBKEY_SIZE];
+pub type BLSSecret = [u8; BLS_SECRET_SIZE];
+pub type BLSId = [u8; BLS_ID_SIZE];
+pub type BLSSignature = [u8; BLS_SIGNATURE_SIZE];
+pub type SHA256 = [u8; SHA256_SIZE];
+
+macro_rules! decode {
+ ($str:ident) => { hex::decode($str).unwrap().try_into().unwrap() };
+}
+
+#[derive(Debug, Deserialize)]
+pub struct DvtVerificationVector {
+ #[serde(rename(deserialize = "base_pubkeys"))]
+ pub pubkeys: Vec<String>,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct DvtGenerateSettings {
+ pub n: u8,
+ pub k: u8,
+ pub gen_id: String,
+}
+
+pub type DvtVerificationHashes = Vec<String>;
+
+#[derive(Debug, Deserialize, Validate)]
+pub struct DvtInitialCommitment {
+ pub hash: String,
+ pub settings: DvtGenerateSettings,
+ #[serde(rename(deserialize = "vvector"))]
+ pub verification_vector: DvtVerificationVector,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct DvtCommitment {
+ pub hash: String,
+ pub pubkey: String,
+ pub signature: String,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct DvtShareExchangeCommitment {
+ pub initial_commitment_hash: String,
+ #[serde(rename(deserialize = "ssecret"))]
+ pub shared_secret: DvtExchangedSecret,
+ pub commitment: DvtCommitment,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct DvtExchangedSecret {
+ #[serde(rename(deserialize = "dst_share_id"))]
+ pub dst_id: String,
+ #[serde(rename(deserialize = "src_share_id"))]
+ pub src_id: String,
+ #[serde(rename(deserialize = "shared_secret"))]
+ pub secret: String,
+ #[serde(rename(deserialize = "dst_base_hash"))]
+ pub dst_base_hash: String,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct DvtShare {
+ pub id: String,
+ pub pubkey: String,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct DvtBlsSharedData {
+ #[serde(rename(deserialize = "base_hashes"))]
+ verification_hashes: DvtVerificationHashes,
+ initial_commitment: DvtInitialCommitment,
+ seeds_exchange_commitment: DvtShareExchangeCommitment,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct DvtGeneration {
+ #[serde(rename(deserialize = "base_pubkeys"))]
+ verification_vector: Vec<String>,
+ base_hash: String,
+ partial_pubkey: String,
+ message_cleartext: String,
+ message_signature: String,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct DvtFinalizationData {
+ settings: DvtGenerateSettings,
+ generations: Vec<DvtGeneration>,
+ aggregate_pubkey: String,
+}
+
+#[derive(Debug)]
+pub struct AbiVerificationVector {
+ pub pubkeys: Vec<BLSPubkey>,
+}
+
+#[derive(Debug)]
+pub struct AbiGenerateSettings {
+ pub n: u8,
+ pub k: u8,
+ pub gen_id: [u8; GEN_ID_SIZE],
+}
+
+impl AbiGenerateSettings {
+ fn new((n, k, gen_id): (u8, u8, String)) -> AbiGenerateSettings {
+ AbiGenerateSettings { n, k, gen_id: decode!(gen_id) }
+ }
+}
+
+pub type AbiVerificationHashes = Vec<SHA256>;
+
+#[derive(Debug)]
+pub struct AbiInitialCommitment {
+ pub hash: SHA256,
+ pub settings: AbiGenerateSettings,
+ pub verification_vector: AbiVerificationVector,
+}
+
+#[derive(Debug)]
+pub struct AbiExchangedSecret {
+ pub src_id: BLSId,
+ pub dst_id: BLSId,
+ pub dst_base_hash: SHA256,
+ pub secret: BLSSecret,
+}
+
+#[derive(Debug)]
+pub struct AbiCommitment {
+ pub hash: SHA256,
+ pub pubkey: BLSPubkey,
+ pub signature: BLSSignature,
+}
+
+#[derive(Debug)]
+pub struct AbiSeedExchangeCommitment {
+ pub initial_commitment_hash: SHA256,
+ pub shared_secret: AbiExchangedSecret,
+ pub commitment: AbiCommitment,
+}
+
+#[derive(Debug)]
+pub struct AbiBlsSharedData {
+ pub verification_hashes: AbiVerificationHashes,
+ pub initial_commitment: AbiInitialCommitment,
+ pub seeds_exchange_commitment: AbiSeedExchangeCommitment,
+}
+
+#[derive(Debug, Clone)]
+pub struct AbiGeneration {
+ pub verification_vector: Vec<BLSPubkey>,
+ pub base_hash: SHA256,
+ pub partial_pubkey: BLSPubkey,
+ pub message_cleartext: Vec<u8>,
+ pub message_signature: BLSSignature,
+}
+
+impl AbiGeneration {
+ fn new(
+ (vector, base_hash, partial_pubkey, cleartext, signature): (Vec<String>, String, String, String, String),
+ ) -> AbiGeneration {
+ AbiGeneration {
+ verification_vector: vector.into_iter().map(|x| decode!(x)).collect(),
+ base_hash: decode!(base_hash),
+ partial_pubkey: decode!(partial_pubkey),
+ message_cleartext: cleartext.into(),
+ message_signature: decode!(signature),
+ }
+ }
+}
+
+#[derive(Debug)]
+pub struct AbiFinalizationData {
+ pub settings: AbiGenerateSettings,
+ pub generations: Vec<AbiGeneration>,
+ pub aggregate_pubkey: BLSPubkey,
+}
+
+impl AbiFinalizationData {
+ pub fn new(
+ generate_settings: (u8, u8, String),
+ generations: Vec<(Vec<String>, String, String, String, String)>,
+ aggregate_pubkey: String,
+ ) -> AbiFinalizationData {
+ AbiFinalizationData {
+ settings: AbiGenerateSettings::new(generate_settings),
+ generations: generations.into_iter().map(|x| AbiGeneration::new(x)).collect(),
+ aggregate_pubkey: decode!(aggregate_pubkey),
+ }
+ }
+}
diff --git a/guests/dvt-circuits/src/lib.rs b/guests/dvt-circuits/src/lib.rs
new file mode 100644
index 0000000..68e3a6d
--- /dev/null
+++ b/guests/dvt-circuits/src/lib.rs
@@ -0,0 +1,18 @@
+#![no_main]
+
+use bls_utils;
+use dvt_abi::AbiFinalizationData;
+
+#[guests_macro::proving_entrypoint]
+pub fn main(
+ generate_settings: (u8, u8, String),
+ generations: Vec<(Vec<String>, String, String, String, String)>,
+ aggregate_pubkey: String,
+) {
+ let data = AbiFinalizationData::new(generate_settings, generations, aggregate_pubkey);
+ let ok =
+ bls_utils::verify_generations(&data.generations, &data.settings, &data.aggregate_pubkey);
+ if ok.is_err() {
+ panic!("{:?}", ok.unwrap_err().to_string());
+ }
+}