mirror of
https://github.com/fluencelabs/lazy-snark
synced 2025-06-09 13:01:25 +00:00
pull from master, conflict fix
This commit is contained in:
commit
1f8fe13a0d
469
backend_fluence/Cargo.lock
generated
Normal file
469
backend_fluence/Cargo.lock
generated
Normal file
@ -0,0 +1,469 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "arrayvec"
|
||||||
|
version = "0.4.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bellman_ce"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"crossbeam 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"pairing_ce 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bit-vec"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-channel"
|
||||||
|
version = "0.3.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-queue"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.6.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ff_ce"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"ff_derive_ce 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ff_derive_ce"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fluence"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"fluence-sdk-macro 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"fluence-sdk-main 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fluence-sdk-macro"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"fluence-sdk-main 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fluence-sdk-main"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fuchsia-cprng"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures"
|
||||||
|
version = "0.1.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-cpupool"
|
||||||
|
version = "0.1.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hex"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.58"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linked-hash-map"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memoffset"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nodrop"
|
||||||
|
version = "0.1.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-bigint"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.41"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_cpus"
|
||||||
|
version = "1.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pairing_ce"
|
||||||
|
version = "0.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"ff_ce 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "0.4.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proof"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"bellman_ce 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"fluence 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "0.6.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rdrand"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ryu"
|
||||||
|
version = "0.2.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.88"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.88"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.38"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "0.6.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "0.14.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "0.15.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-xid"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[metadata]
|
||||||
|
"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71"
|
||||||
|
"checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf"
|
||||||
|
"checksum bellman_ce 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "642cd8f539e838802c6a0d1756f5bf3985385a7d538fc7950589b676586537fe"
|
||||||
|
"checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f"
|
||||||
|
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
|
||||||
|
"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
|
||||||
|
"checksum crossbeam 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b14492071ca110999a20bf90e3833406d5d66bfd93b4e52ec9539025ff43fe0d"
|
||||||
|
"checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b"
|
||||||
|
"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71"
|
||||||
|
"checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4"
|
||||||
|
"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b"
|
||||||
|
"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c"
|
||||||
|
"checksum ff_ce 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f6edceb5dc64db5e46acb519af5d994b004bc150230498527c3f9e55c94c842"
|
||||||
|
"checksum ff_derive_ce 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "189b37f93ec30f72d7420f1e6f2f07031ed0245073ab46c02b57fba696f4365a"
|
||||||
|
"checksum fluence 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "60cb68f8345b46e3bab0f9cb5a041dad4e0ad944a27d4a89b312db8d5f01cadd"
|
||||||
|
"checksum fluence-sdk-macro 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d25c41f9afe101ca24ebc41a58ca9e1c7a9627cf5249211776881fdf954b14ed"
|
||||||
|
"checksum fluence-sdk-main 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a2e09744c4895d07bafdc275d2da9c3a61edae9790f00283aa1fd48661d12506"
|
||||||
|
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
||||||
|
"checksum futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)" = "a2037ec1c6c1c4f79557762eab1f7eae1f64f6cb418ace90fae88f0942b60139"
|
||||||
|
"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4"
|
||||||
|
"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
|
||||||
|
"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
|
||||||
|
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
|
||||||
|
"checksum libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "6281b86796ba5e4366000be6e9e18bf35580adf9e63fbe2294aadb587613a319"
|
||||||
|
"checksum linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70fb39025bc7cdd76305867c4eccf2f2dcf6e9a57f5b21a93e1c2d86cd03ec9e"
|
||||||
|
"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
|
||||||
|
"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
|
||||||
|
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
|
||||||
|
"checksum num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "57450397855d951f1a41305e54851b1a7b8f5d2e349543a02a2effe25459f718"
|
||||||
|
"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"
|
||||||
|
"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32"
|
||||||
|
"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273"
|
||||||
|
"checksum pairing_ce 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cce626fb8f97e304423451d63e29b7f5882de5cfe79925ffc4a32cf4c243f40f"
|
||||||
|
"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915"
|
||||||
|
"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1"
|
||||||
|
"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
|
||||||
|
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
||||||
|
"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0"
|
||||||
|
"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
|
||||||
|
"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
|
||||||
|
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
|
||||||
|
"checksum serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "9f301d728f2b94c9a7691c90f07b0b4e8a4517181d9461be94c04bddeb4bd850"
|
||||||
|
"checksum serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "beed18e6f5175aef3ba670e57c60ef3b1b74d250d962a26604bff4c80e970dd4"
|
||||||
|
"checksum serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "27dce848e7467aa0e2fcaf0a413641499c0b745452aaca1194d24dedde9e13c9"
|
||||||
|
"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7"
|
||||||
|
"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741"
|
||||||
|
"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9"
|
||||||
|
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||||
|
"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770"
|
||||||
|
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
27
backend_fluence/Cargo.toml
Normal file
27
backend_fluence/Cargo.toml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
[package]
|
||||||
|
name = "proof"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Fluence Labs"]
|
||||||
|
publish = false
|
||||||
|
description = "Trustless off-chain zk-proof verification"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "proof"
|
||||||
|
path = "src/lib.rs"
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
debug = false
|
||||||
|
lto = true
|
||||||
|
opt-level = "z"
|
||||||
|
panic = "abort"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
serde_json = "1.0.38"
|
||||||
|
linked-hash-map = "0.5.1"
|
||||||
|
fluence = { version = "0.1.5", features = ["wasm_logger"] }
|
||||||
|
|
||||||
|
bellman_ce = "0.3.0"
|
||||||
|
|
1
backend_fluence/rust-toolchain
Normal file
1
backend_fluence/rust-toolchain
Normal file
@ -0,0 +1 @@
|
|||||||
|
nightly
|
3
backend_fluence/src/error_type.rs
Normal file
3
backend_fluence/src/error_type.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
use std::error::Error;
|
||||||
|
|
||||||
|
pub type AppResult<T> = ::std::result::Result<T, Box<Error>>;
|
46
backend_fluence/src/lib.rs
Normal file
46
backend_fluence/src/lib.rs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
mod error_type;
|
||||||
|
mod proof_manager;
|
||||||
|
mod request_response;
|
||||||
|
|
||||||
|
use crate::error_type::AppResult;
|
||||||
|
use crate::proof_manager::ProofManager;
|
||||||
|
use crate::request_response::{Request, Response};
|
||||||
|
|
||||||
|
use fluence::sdk::*;
|
||||||
|
use serde_json::Value;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
|
thread_local! {
|
||||||
|
static PROOF_MANAGER: RefCell<ProofManager> = RefCell::new(ProofManager::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_request(req: String) -> AppResult<Value> {
|
||||||
|
let request: Request = serde_json::from_str(req.as_str())?;
|
||||||
|
|
||||||
|
match request {
|
||||||
|
|
||||||
|
Request::Verify {
|
||||||
|
proof_id,
|
||||||
|
public_par,
|
||||||
|
proof,
|
||||||
|
} => PROOF_MANAGER.with(|gm| gm.borrow_mut().verify(proof_id, public_par, proof)),
|
||||||
|
|
||||||
|
Request::Check {
|
||||||
|
proof_id,
|
||||||
|
} => PROOF_MANAGER.with(|gm| gm.borrow_mut().check(proof_id))
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[invocation_handler]
|
||||||
|
fn main(req: String) -> String {
|
||||||
|
match do_request(req) {
|
||||||
|
Ok(res) => res.to_string(),
|
||||||
|
Err(err) => {
|
||||||
|
let response = Response::Error {
|
||||||
|
message: err.to_string(),
|
||||||
|
};
|
||||||
|
serde_json::to_string(&response).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
141
backend_fluence/src/proof_manager.rs
Normal file
141
backend_fluence/src/proof_manager.rs
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
use crate::error_type::AppResult;
|
||||||
|
use crate::request_response::Response;
|
||||||
|
use std::io::{Cursor, Read, Seek, SeekFrom, Write};
|
||||||
|
|
||||||
|
use bellman_ce::groth16::*;
|
||||||
|
|
||||||
|
use linked_hash_map::LinkedHashMap;
|
||||||
|
use serde_json::Value;
|
||||||
|
|
||||||
|
pub struct ProofManager {
|
||||||
|
// map from job id to verify status
|
||||||
|
proofs: LinkedHashMap<u64, u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProofManager {
|
||||||
|
|
||||||
|
pub fn new() -> Self {
|
||||||
|
ProofManager {
|
||||||
|
proofs: LinkedHashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn verify(&mut self, proof_id: u64, public_par: [f64; 5], proof: [f64; 8]) -> AppResult<Value> {
|
||||||
|
|
||||||
|
// verify mock
|
||||||
|
let mut result: u8 = 1;
|
||||||
|
if proof[0] != 8.51065254754666e75 {
|
||||||
|
result = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
let tt = "99999";
|
||||||
|
|
||||||
|
let mut c = Cursor::new(Vec::new());
|
||||||
|
|
||||||
|
// Write into the "file" and seek to the beginning
|
||||||
|
c.write_all(tt.as_bytes()).unwrap();
|
||||||
|
c.seek(SeekFrom::Start(0)).unwrap();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let pvk = {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
let proof = {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
let pub_input = {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
result_bool = verify_proof(
|
||||||
|
&pvk,
|
||||||
|
&proof,
|
||||||
|
&[Fr::one()]
|
||||||
|
).unwrap();*/
|
||||||
|
|
||||||
|
// update proof status
|
||||||
|
self.proofs.insert(proof_id, result);
|
||||||
|
|
||||||
|
let response = Response::Verify {
|
||||||
|
result : result,
|
||||||
|
};
|
||||||
|
|
||||||
|
serde_json::to_value(response).map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*pub fn read<R: Read>(
|
||||||
|
mut reader: R
|
||||||
|
) -> io::Result<Self>
|
||||||
|
{
|
||||||
|
let mut g1_repr = <E::G1Affine as CurveAffine>::Uncompressed::empty();
|
||||||
|
let mut g2_repr = <E::G2Affine as CurveAffine>::Uncompressed::empty();
|
||||||
|
|
||||||
|
reader.read_exact(g1_repr.as_mut())?;
|
||||||
|
let alpha_g1 = g1_repr.into_affine().map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||||
|
|
||||||
|
reader.read_exact(g1_repr.as_mut())?;
|
||||||
|
let beta_g1 = g1_repr.into_affine().map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||||
|
|
||||||
|
reader.read_exact(g2_repr.as_mut())?;
|
||||||
|
let beta_g2 = g2_repr.into_affine().map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||||
|
|
||||||
|
reader.read_exact(g2_repr.as_mut())?;
|
||||||
|
let gamma_g2 = g2_repr.into_affine().map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||||
|
|
||||||
|
reader.read_exact(g1_repr.as_mut())?;
|
||||||
|
let delta_g1 = g1_repr.into_affine().map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||||
|
|
||||||
|
reader.read_exact(g2_repr.as_mut())?;
|
||||||
|
let delta_g2 = g2_repr.into_affine().map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||||
|
|
||||||
|
let ic_len = reader.read_u32::<BigEndian>()? as usize;
|
||||||
|
|
||||||
|
let mut ic = vec![];
|
||||||
|
|
||||||
|
for _ in 0..ic_len {
|
||||||
|
reader.read_exact(g1_repr.as_mut())?;
|
||||||
|
let g1 = g1_repr
|
||||||
|
.into_affine()
|
||||||
|
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
|
||||||
|
.and_then(|e| if e.is_zero() {
|
||||||
|
Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity"))
|
||||||
|
} else {
|
||||||
|
Ok(e)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
ic.push(g1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(VerifyingKey {
|
||||||
|
alpha_g1: alpha_g1,
|
||||||
|
beta_g1: beta_g1,
|
||||||
|
beta_g2: beta_g2,
|
||||||
|
gamma_g2: gamma_g2,
|
||||||
|
delta_g1: delta_g1,
|
||||||
|
delta_g2: delta_g2,
|
||||||
|
ic: ic
|
||||||
|
})
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
|
pub fn check(&self, proof_id: u64) -> AppResult<Value> {
|
||||||
|
let status = self.proof_status(proof_id)?;
|
||||||
|
let response = Response::Check { verified: status };
|
||||||
|
|
||||||
|
serde_json::to_value(response).map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn proof_status(&self, proof_id: u64) -> AppResult<u8> {
|
||||||
|
let status = self
|
||||||
|
.proofs
|
||||||
|
.get(&proof_id)
|
||||||
|
.ok_or_else(|| format!("Proof with id {} wasn't found", proof_id))?;
|
||||||
|
|
||||||
|
Ok(*status)
|
||||||
|
}
|
||||||
|
}
|
23
backend_fluence/src/request_response.rs
Normal file
23
backend_fluence/src/request_response.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[serde(tag = "action")]
|
||||||
|
pub enum Request {
|
||||||
|
Verify {
|
||||||
|
proof_id: u64,
|
||||||
|
public_par: [f64; 5],
|
||||||
|
proof: [f64; 8],
|
||||||
|
},
|
||||||
|
Check {
|
||||||
|
proof_id: u64,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum Response {
|
||||||
|
Verify { result: u8 },
|
||||||
|
Check { verified: u8 },
|
||||||
|
Error { message: String },
|
||||||
|
}
|
130
backend_fluence/src/tests.rs
Normal file
130
backend_fluence/src/tests.rs
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 Fluence Labs Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
use crate::request_response::{Request, Response};
|
||||||
|
use crate::main;
|
||||||
|
|
||||||
|
// TODO: add more tests
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn correct_bets() {
|
||||||
|
let response = Response::Join { player_id: 0 };
|
||||||
|
assert_eq!(
|
||||||
|
main(create_join_request()),
|
||||||
|
serde_json::to_string(&response).unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let response = Response::Join { player_id: 1 };
|
||||||
|
assert_eq!(
|
||||||
|
main(create_join_request()),
|
||||||
|
serde_json::to_string(&response).unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let response = Response::Bet {
|
||||||
|
outcome: 6,
|
||||||
|
player_balance: 85,
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
main(create_bet_json(0, 1, 15)),
|
||||||
|
serde_json::to_string(&response).unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let response = Response::Bet {
|
||||||
|
outcome: 4,
|
||||||
|
player_balance: 85,
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
main(create_bet_json(1, 1, 15)),
|
||||||
|
serde_json::to_string(&response).unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let response = Response::Bet {
|
||||||
|
outcome: 6,
|
||||||
|
player_balance: 510,
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
main(create_bet_json(0, 6, 85)),
|
||||||
|
serde_json::to_string(&response).unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let response = Response::Bet {
|
||||||
|
outcome: 2,
|
||||||
|
player_balance: 0,
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
main(create_bet_json(1, 1, 85)),
|
||||||
|
serde_json::to_string(&response).unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let response = Response::GetBalance {
|
||||||
|
player_balance: 510,
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
main(create_get_balance_json(0)),
|
||||||
|
serde_json::to_string(&response).unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn incorrect_bets() {
|
||||||
|
let response = Response::Join { player_id: 0 };
|
||||||
|
assert_eq!(
|
||||||
|
main(create_join_request()),
|
||||||
|
serde_json::to_string(&response).unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let response = Response::Error {
|
||||||
|
message: "Incorrect placement, please choose number from 1 to 6".to_string(),
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
main(create_bet_json(0, 7, 15)),
|
||||||
|
serde_json::to_string(&response).unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let response = Response::Error {
|
||||||
|
message: "Player with id 1 wasn\'t found".to_string(),
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
main(create_bet_json(1, 1, 0)),
|
||||||
|
serde_json::to_string(&response).unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let response = Response::Error {
|
||||||
|
message: "Player hasn\'t enough money: player\'s current balance is 100 while the bet is 4294967295".to_string()
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
main(create_bet_json(0, 6, std::u32::MAX)),
|
||||||
|
serde_json::to_string(&response).unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_join_request() -> String {
|
||||||
|
let request = Request::Join;
|
||||||
|
serde_json::to_value(request).unwrap().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_bet_json(player_id: u64, placement: u8, bet_amount: u32) -> String {
|
||||||
|
let request = Request::Bet {
|
||||||
|
player_id,
|
||||||
|
placement,
|
||||||
|
bet_amount,
|
||||||
|
};
|
||||||
|
serde_json::to_value(request).unwrap().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_get_balance_json(player_id: u64) -> String {
|
||||||
|
let request = Request::GetBalance { player_id };
|
||||||
|
serde_json::to_value(request).unwrap().to_string()
|
||||||
|
}
|
BIN
backend_zk/out
Normal file
BIN
backend_zk/out
Normal file
Binary file not shown.
113984
backend_zk/out.code
Normal file
113984
backend_zk/out.code
Normal file
File diff suppressed because one or more lines are too long
8
backend_zk/proof.json
Normal file
8
backend_zk/proof.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"proof": {
|
||||||
|
"a": ["0x12d0dbcfc1da3ea29bc017288fceea3929401f4f12dbd0bba73781420d31aa2d", "0x2811c1eaa63f4a804951bd7f994cbb6bea9df64591793b8392400e8756d1bca7"],
|
||||||
|
"b": [["0x04c33f68e1bd55be0928b086c647debcdf7aa0e3c3efc6a8efbc2596a77a0e67", "0x17e7392e0e3ec2b5701e675e6e0569330d03ffffe476fc8d63cfeaa0ba1c8a97"], ["0x2fc402693a54cd1b176abeed209674f2f12ced1496c6ce27ba8cf16903daa4cc", "0x2c47efba3f4f260da643bb6427d08b551bb3446537d6ac4857d611be2355a446"]],
|
||||||
|
"c": ["0x04d40f14694092d0f70890a20492b2b68e7eaabdcee744e519678d687c9c3ed0", "0x28de140e393154b0e70b3ef12806af963a4a33b45c24e7864391093b6028fa2b"]
|
||||||
|
},
|
||||||
|
"inputs": ["0x00000000000000000000000000000000c6481e22c5ff4164af680b8cfaa5e8ed", "0x000000000000000000000000000000003120eeff89c4f307c4a6faaae059ce10", "0x000000000000000000000000000000005b6d7d198c48c17c9540d29275a04662", "0x00000000000000000000000000000000f7a9aa434629a33c84eec3e16e196f27", "0x0000000000000000000000000000000000000000000000000000000000000001"]
|
||||||
|
}
|
BIN
backend_zk/proving.key
Normal file
BIN
backend_zk/proving.key
Normal file
Binary file not shown.
18
backend_zk/root.code
Normal file
18
backend_zk/root.code
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import "hashes/sha256/512bitPacked.code" as sha256packed
|
||||||
|
|
||||||
|
def main(private field[4] n_old, private field[4] n_new, field[2] hash_old, field[2] hash_new) -> (field):
|
||||||
|
|
||||||
|
//check sum
|
||||||
|
n_old[0] + n_old[1] + n_old[2] + n_old[3] == n_new[0] + n_new[1] + n_new[2] + n_new[3]
|
||||||
|
|
||||||
|
// check old hash
|
||||||
|
h_old = sha256packed([n_old[0], n_old[1], n_old[2], n_old[3]])
|
||||||
|
h_old[0] == hash_old[0]
|
||||||
|
h_old[1] == hash_old[1]
|
||||||
|
|
||||||
|
// check new hash
|
||||||
|
h_new = sha256packed([n_new[0], n_new[1], n_new[2], n_new[3]])
|
||||||
|
h_new[0] == hash_new[0]
|
||||||
|
h_new[1] == hash_new[1]
|
||||||
|
|
||||||
|
return 1
|
11
backend_zk/verification.key
Normal file
11
backend_zk/verification.key
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
vk.alpha = 0x2c2cb1812fb05d4f31791c66ff995d756b73162f3bb016a5c114befe5cd7903e, 0x0abc1f8a5d49cb2dbda15b5a8b7cd81bec0a581e7c2e16f79446af2d2f5340c0
|
||||||
|
vk.beta = [0x071644533641f7e3acb8606328c591853b2bc27253f29bc11d008a67996fc07f, 0x26ca2720c073a085d8452aef541aac280879971c09b199a6e0f21bf36745e1d8], [0x0b17104896ed701b6d52279992c1f20d558bc0de8284087645633bf3ca1a0c98, 0x2c10eb5b6c0ca42ede8cdcf60642c6dca040abe9abb8294948f4aa0be59a0d42]
|
||||||
|
vk.gamma = [0x0afbadec2ecafdd62278c7021095660f5786f445c040e628e4ed1a410454b582, 0x038aa6f04ee254a97e2b75ea1f30e36785b6cde4dfd3a2371e058ce089b9ad51], [0x077720bb216fb0051c5e153c1bd9aa36a678173b9c13e8d3a83cb5a75ca36948, 0x1f9b58e9abde296abc3c3bab8fb0be2a4f497d8e5d9d463997d316e9cc558a7d]
|
||||||
|
vk.delta = [0x16526b9b519fa544d3f9ce35a5f4afa7aac0aa4dd54421c4864b3fe8d2415f41, 0x24e24f35699cca59416a7f43c0e93e148b2353440978994df8f81603a46f8839], [0x299f9f09280310aedf63055c5ce76feb16557ed7ff11ba35adad718102b5651a, 0x0c4a2fc4db77ef6c19511b2ffb369981cebbffcb5337a671e1ad678b460ac5e9]
|
||||||
|
vk.gammaABC.len() = 6
|
||||||
|
vk.gammaABC[0] = 0x2f910078bf5092a7ea9d3ce750b7b5399b101509adb8017a6e12fa1a4c638d5b, 0x0b76454d4300571c8d86714b4e5ef095688b51080e674425e8e5edb201f64128
|
||||||
|
vk.gammaABC[1] = 0x2922a307d415f70c8df6f14b664c46df12a89cd3a89cf7960663907bf9483b68, 0x1bc30a719ddc0099f557cca61a0687766e6275fc98b185baa77735b93bf2a0ef
|
||||||
|
vk.gammaABC[2] = 0x0201dc8c8faa3dc5b8eec85f029d2482bf11a6b46d5f8e4d9f17d41ac3e4c9c1, 0x0a1d62c1142c92dff75b53d5a572fd7a013708118acf10f718c61fb6226160f5
|
||||||
|
vk.gammaABC[3] = 0x02276f5896610ec573cd6cdc6e47c69e756362d2b1b1c51c5ab90ac838d1a898, 0x13fa6cc7987f4f3118f6ee3ab85dcd708df17050636d487914077348e0af05b1
|
||||||
|
vk.gammaABC[4] = 0x0778ae3718fd7f48564bc33b60ec4f39a238e97cb4cc0bbd4ff37119942ff7d4, 0x0282e96481744ee21524d802b3e524bf0596bb37bb63e5ed37c77fc1a5c8e89d
|
||||||
|
vk.gammaABC[5] = 0x1ce40e230695bdab7d2ff7ebcf6e6fedb68d1a320238fc98845b151ae4ee3b54, 0x0feac76664d37b57a4ea5a774252bb82355294e55635a8aeb7a1327405d27128
|
604
backend_zk/verifier.sol
Normal file
604
backend_zk/verifier.sol
Normal file
@ -0,0 +1,604 @@
|
|||||||
|
// This file is LGPL3 Licensed
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title Elliptic curve operations on twist points for alt_bn128
|
||||||
|
* @author Mustafa Al-Bassam (mus@musalbas.com)
|
||||||
|
*/
|
||||||
|
library BN256G2 {
|
||||||
|
uint256 internal constant FIELD_MODULUS = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47;
|
||||||
|
uint256 internal constant TWISTBX = 0x2b149d40ceb8aaae81be18991be06ac3b5b4c5e559dbefa33267e6dc24a138e5;
|
||||||
|
uint256 internal constant TWISTBY = 0x9713b03af0fed4cd2cafadeed8fdf4a74fa084e52d1852e4a2bd0685c315d2;
|
||||||
|
uint internal constant PTXX = 0;
|
||||||
|
uint internal constant PTXY = 1;
|
||||||
|
uint internal constant PTYX = 2;
|
||||||
|
uint internal constant PTYY = 3;
|
||||||
|
uint internal constant PTZX = 4;
|
||||||
|
uint internal constant PTZY = 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @notice Add two twist points
|
||||||
|
* @param pt1xx Coefficient 1 of x on point 1
|
||||||
|
* @param pt1xy Coefficient 2 of x on point 1
|
||||||
|
* @param pt1yx Coefficient 1 of y on point 1
|
||||||
|
* @param pt1yy Coefficient 2 of y on point 1
|
||||||
|
* @param pt2xx Coefficient 1 of x on point 2
|
||||||
|
* @param pt2xy Coefficient 2 of x on point 2
|
||||||
|
* @param pt2yx Coefficient 1 of y on point 2
|
||||||
|
* @param pt2yy Coefficient 2 of y on point 2
|
||||||
|
* @return (pt3xx, pt3xy, pt3yx, pt3yy)
|
||||||
|
*/
|
||||||
|
function ECTwistAdd(
|
||||||
|
uint256 pt1xx, uint256 pt1xy,
|
||||||
|
uint256 pt1yx, uint256 pt1yy,
|
||||||
|
uint256 pt2xx, uint256 pt2xy,
|
||||||
|
uint256 pt2yx, uint256 pt2yy
|
||||||
|
) public pure returns (
|
||||||
|
uint256, uint256,
|
||||||
|
uint256, uint256
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
pt1xx == 0 && pt1xy == 0 &&
|
||||||
|
pt1yx == 0 && pt1yy == 0
|
||||||
|
) {
|
||||||
|
if (!(
|
||||||
|
pt2xx == 0 && pt2xy == 0 &&
|
||||||
|
pt2yx == 0 && pt2yy == 0
|
||||||
|
)) {
|
||||||
|
assert(_isOnCurve(
|
||||||
|
pt2xx, pt2xy,
|
||||||
|
pt2yx, pt2yy
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
pt2xx, pt2xy,
|
||||||
|
pt2yx, pt2yy
|
||||||
|
);
|
||||||
|
} else if (
|
||||||
|
pt2xx == 0 && pt2xy == 0 &&
|
||||||
|
pt2yx == 0 && pt2yy == 0
|
||||||
|
) {
|
||||||
|
assert(_isOnCurve(
|
||||||
|
pt1xx, pt1xy,
|
||||||
|
pt1yx, pt1yy
|
||||||
|
));
|
||||||
|
return (
|
||||||
|
pt1xx, pt1xy,
|
||||||
|
pt1yx, pt1yy
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(_isOnCurve(
|
||||||
|
pt1xx, pt1xy,
|
||||||
|
pt1yx, pt1yy
|
||||||
|
));
|
||||||
|
assert(_isOnCurve(
|
||||||
|
pt2xx, pt2xy,
|
||||||
|
pt2yx, pt2yy
|
||||||
|
));
|
||||||
|
|
||||||
|
uint256[6] memory pt3 = _ECTwistAddJacobian(
|
||||||
|
pt1xx, pt1xy,
|
||||||
|
pt1yx, pt1yy,
|
||||||
|
1, 0,
|
||||||
|
pt2xx, pt2xy,
|
||||||
|
pt2yx, pt2yy,
|
||||||
|
1, 0
|
||||||
|
);
|
||||||
|
|
||||||
|
return _fromJacobian(
|
||||||
|
pt3[PTXX], pt3[PTXY],
|
||||||
|
pt3[PTYX], pt3[PTYY],
|
||||||
|
pt3[PTZX], pt3[PTZY]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @notice Multiply a twist point by a scalar
|
||||||
|
* @param s Scalar to multiply by
|
||||||
|
* @param pt1xx Coefficient 1 of x
|
||||||
|
* @param pt1xy Coefficient 2 of x
|
||||||
|
* @param pt1yx Coefficient 1 of y
|
||||||
|
* @param pt1yy Coefficient 2 of y
|
||||||
|
* @return (pt2xx, pt2xy, pt2yx, pt2yy)
|
||||||
|
*/
|
||||||
|
function ECTwistMul(
|
||||||
|
uint256 s,
|
||||||
|
uint256 pt1xx, uint256 pt1xy,
|
||||||
|
uint256 pt1yx, uint256 pt1yy
|
||||||
|
) public pure returns (
|
||||||
|
uint256, uint256,
|
||||||
|
uint256, uint256
|
||||||
|
) {
|
||||||
|
uint256 pt1zx = 1;
|
||||||
|
if (
|
||||||
|
pt1xx == 0 && pt1xy == 0 &&
|
||||||
|
pt1yx == 0 && pt1yy == 0
|
||||||
|
) {
|
||||||
|
pt1xx = 1;
|
||||||
|
pt1yx = 1;
|
||||||
|
pt1zx = 0;
|
||||||
|
} else {
|
||||||
|
assert(_isOnCurve(
|
||||||
|
pt1xx, pt1xy,
|
||||||
|
pt1yx, pt1yy
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint256[6] memory pt2 = _ECTwistMulJacobian(
|
||||||
|
s,
|
||||||
|
pt1xx, pt1xy,
|
||||||
|
pt1yx, pt1yy,
|
||||||
|
pt1zx, 0
|
||||||
|
);
|
||||||
|
|
||||||
|
return _fromJacobian(
|
||||||
|
pt2[PTXX], pt2[PTXY],
|
||||||
|
pt2[PTYX], pt2[PTYY],
|
||||||
|
pt2[PTZX], pt2[PTZY]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @notice Get the field modulus
|
||||||
|
* @return The field modulus
|
||||||
|
*/
|
||||||
|
function GetFieldModulus() public pure returns (uint256) {
|
||||||
|
return FIELD_MODULUS;
|
||||||
|
}
|
||||||
|
|
||||||
|
function submod(uint256 a, uint256 b, uint256 n) internal pure returns (uint256) {
|
||||||
|
return addmod(a, n - b, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _FQ2Mul(
|
||||||
|
uint256 xx, uint256 xy,
|
||||||
|
uint256 yx, uint256 yy
|
||||||
|
) internal pure returns(uint256, uint256) {
|
||||||
|
return (
|
||||||
|
submod(mulmod(xx, yx, FIELD_MODULUS), mulmod(xy, yy, FIELD_MODULUS), FIELD_MODULUS),
|
||||||
|
addmod(mulmod(xx, yy, FIELD_MODULUS), mulmod(xy, yx, FIELD_MODULUS), FIELD_MODULUS)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _FQ2Muc(
|
||||||
|
uint256 xx, uint256 xy,
|
||||||
|
uint256 c
|
||||||
|
) internal pure returns(uint256, uint256) {
|
||||||
|
return (
|
||||||
|
mulmod(xx, c, FIELD_MODULUS),
|
||||||
|
mulmod(xy, c, FIELD_MODULUS)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _FQ2Add(
|
||||||
|
uint256 xx, uint256 xy,
|
||||||
|
uint256 yx, uint256 yy
|
||||||
|
) internal pure returns(uint256, uint256) {
|
||||||
|
return (
|
||||||
|
addmod(xx, yx, FIELD_MODULUS),
|
||||||
|
addmod(xy, yy, FIELD_MODULUS)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _FQ2Sub(
|
||||||
|
uint256 xx, uint256 xy,
|
||||||
|
uint256 yx, uint256 yy
|
||||||
|
) internal pure returns(uint256 rx, uint256 ry) {
|
||||||
|
return (
|
||||||
|
submod(xx, yx, FIELD_MODULUS),
|
||||||
|
submod(xy, yy, FIELD_MODULUS)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _FQ2Div(
|
||||||
|
uint256 xx, uint256 xy,
|
||||||
|
uint256 yx, uint256 yy
|
||||||
|
) internal pure returns(uint256, uint256) {
|
||||||
|
(yx, yy) = _FQ2Inv(yx, yy);
|
||||||
|
return _FQ2Mul(xx, xy, yx, yy);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _FQ2Inv(uint256 x, uint256 y) internal pure returns(uint256, uint256) {
|
||||||
|
uint256 inv = _modInv(addmod(mulmod(y, y, FIELD_MODULUS), mulmod(x, x, FIELD_MODULUS), FIELD_MODULUS), FIELD_MODULUS);
|
||||||
|
return (
|
||||||
|
mulmod(x, inv, FIELD_MODULUS),
|
||||||
|
FIELD_MODULUS - mulmod(y, inv, FIELD_MODULUS)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _isOnCurve(
|
||||||
|
uint256 xx, uint256 xy,
|
||||||
|
uint256 yx, uint256 yy
|
||||||
|
) internal pure returns (bool) {
|
||||||
|
uint256 yyx;
|
||||||
|
uint256 yyy;
|
||||||
|
uint256 xxxx;
|
||||||
|
uint256 xxxy;
|
||||||
|
(yyx, yyy) = _FQ2Mul(yx, yy, yx, yy);
|
||||||
|
(xxxx, xxxy) = _FQ2Mul(xx, xy, xx, xy);
|
||||||
|
(xxxx, xxxy) = _FQ2Mul(xxxx, xxxy, xx, xy);
|
||||||
|
(yyx, yyy) = _FQ2Sub(yyx, yyy, xxxx, xxxy);
|
||||||
|
(yyx, yyy) = _FQ2Sub(yyx, yyy, TWISTBX, TWISTBY);
|
||||||
|
return yyx == 0 && yyy == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _modInv(uint256 a, uint256 n) internal pure returns(uint256 t) {
|
||||||
|
t = 0;
|
||||||
|
uint256 newT = 1;
|
||||||
|
uint256 r = n;
|
||||||
|
uint256 newR = a;
|
||||||
|
uint256 q;
|
||||||
|
while (newR != 0) {
|
||||||
|
q = r / newR;
|
||||||
|
(t, newT) = (newT, submod(t, mulmod(q, newT, n), n));
|
||||||
|
(r, newR) = (newR, r - q * newR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _fromJacobian(
|
||||||
|
uint256 pt1xx, uint256 pt1xy,
|
||||||
|
uint256 pt1yx, uint256 pt1yy,
|
||||||
|
uint256 pt1zx, uint256 pt1zy
|
||||||
|
) internal pure returns (
|
||||||
|
uint256 pt2xx, uint256 pt2xy,
|
||||||
|
uint256 pt2yx, uint256 pt2yy
|
||||||
|
) {
|
||||||
|
uint256 invzx;
|
||||||
|
uint256 invzy;
|
||||||
|
(invzx, invzy) = _FQ2Inv(pt1zx, pt1zy);
|
||||||
|
(pt2xx, pt2xy) = _FQ2Mul(pt1xx, pt1xy, invzx, invzy);
|
||||||
|
(pt2yx, pt2yy) = _FQ2Mul(pt1yx, pt1yy, invzx, invzy);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _ECTwistAddJacobian(
|
||||||
|
uint256 pt1xx, uint256 pt1xy,
|
||||||
|
uint256 pt1yx, uint256 pt1yy,
|
||||||
|
uint256 pt1zx, uint256 pt1zy,
|
||||||
|
uint256 pt2xx, uint256 pt2xy,
|
||||||
|
uint256 pt2yx, uint256 pt2yy,
|
||||||
|
uint256 pt2zx, uint256 pt2zy) internal pure returns (uint256[6] memory pt3) {
|
||||||
|
if (pt1zx == 0 && pt1zy == 0) {
|
||||||
|
(
|
||||||
|
pt3[PTXX], pt3[PTXY],
|
||||||
|
pt3[PTYX], pt3[PTYY],
|
||||||
|
pt3[PTZX], pt3[PTZY]
|
||||||
|
) = (
|
||||||
|
pt2xx, pt2xy,
|
||||||
|
pt2yx, pt2yy,
|
||||||
|
pt2zx, pt2zy
|
||||||
|
);
|
||||||
|
return pt3;
|
||||||
|
} else if (pt2zx == 0 && pt2zy == 0) {
|
||||||
|
(
|
||||||
|
pt3[PTXX], pt3[PTXY],
|
||||||
|
pt3[PTYX], pt3[PTYY],
|
||||||
|
pt3[PTZX], pt3[PTZY]
|
||||||
|
) = (
|
||||||
|
pt1xx, pt1xy,
|
||||||
|
pt1yx, pt1yy,
|
||||||
|
pt1zx, pt1zy
|
||||||
|
);
|
||||||
|
return pt3;
|
||||||
|
}
|
||||||
|
|
||||||
|
(pt2yx, pt2yy) = _FQ2Mul(pt2yx, pt2yy, pt1zx, pt1zy); // U1 = y2 * z1
|
||||||
|
(pt3[PTYX], pt3[PTYY]) = _FQ2Mul(pt1yx, pt1yy, pt2zx, pt2zy); // U2 = y1 * z2
|
||||||
|
(pt2xx, pt2xy) = _FQ2Mul(pt2xx, pt2xy, pt1zx, pt1zy); // V1 = x2 * z1
|
||||||
|
(pt3[PTZX], pt3[PTZY]) = _FQ2Mul(pt1xx, pt1xy, pt2zx, pt2zy); // V2 = x1 * z2
|
||||||
|
|
||||||
|
if (pt2xx == pt3[PTZX] && pt2xy == pt3[PTZY]) {
|
||||||
|
if (pt2yx == pt3[PTYX] && pt2yy == pt3[PTYY]) {
|
||||||
|
(
|
||||||
|
pt3[PTXX], pt3[PTXY],
|
||||||
|
pt3[PTYX], pt3[PTYY],
|
||||||
|
pt3[PTZX], pt3[PTZY]
|
||||||
|
) = _ECTwistDoubleJacobian(pt1xx, pt1xy, pt1yx, pt1yy, pt1zx, pt1zy);
|
||||||
|
return pt3;
|
||||||
|
}
|
||||||
|
(
|
||||||
|
pt3[PTXX], pt3[PTXY],
|
||||||
|
pt3[PTYX], pt3[PTYY],
|
||||||
|
pt3[PTZX], pt3[PTZY]
|
||||||
|
) = (
|
||||||
|
1, 0,
|
||||||
|
1, 0,
|
||||||
|
0, 0
|
||||||
|
);
|
||||||
|
return pt3;
|
||||||
|
}
|
||||||
|
|
||||||
|
(pt2zx, pt2zy) = _FQ2Mul(pt1zx, pt1zy, pt2zx, pt2zy); // W = z1 * z2
|
||||||
|
(pt1xx, pt1xy) = _FQ2Sub(pt2yx, pt2yy, pt3[PTYX], pt3[PTYY]); // U = U1 - U2
|
||||||
|
(pt1yx, pt1yy) = _FQ2Sub(pt2xx, pt2xy, pt3[PTZX], pt3[PTZY]); // V = V1 - V2
|
||||||
|
(pt1zx, pt1zy) = _FQ2Mul(pt1yx, pt1yy, pt1yx, pt1yy); // V_squared = V * V
|
||||||
|
(pt2yx, pt2yy) = _FQ2Mul(pt1zx, pt1zy, pt3[PTZX], pt3[PTZY]); // V_squared_times_V2 = V_squared * V2
|
||||||
|
(pt1zx, pt1zy) = _FQ2Mul(pt1zx, pt1zy, pt1yx, pt1yy); // V_cubed = V * V_squared
|
||||||
|
(pt3[PTZX], pt3[PTZY]) = _FQ2Mul(pt1zx, pt1zy, pt2zx, pt2zy); // newz = V_cubed * W
|
||||||
|
(pt2xx, pt2xy) = _FQ2Mul(pt1xx, pt1xy, pt1xx, pt1xy); // U * U
|
||||||
|
(pt2xx, pt2xy) = _FQ2Mul(pt2xx, pt2xy, pt2zx, pt2zy); // U * U * W
|
||||||
|
(pt2xx, pt2xy) = _FQ2Sub(pt2xx, pt2xy, pt1zx, pt1zy); // U * U * W - V_cubed
|
||||||
|
(pt2zx, pt2zy) = _FQ2Muc(pt2yx, pt2yy, 2); // 2 * V_squared_times_V2
|
||||||
|
(pt2xx, pt2xy) = _FQ2Sub(pt2xx, pt2xy, pt2zx, pt2zy); // A = U * U * W - V_cubed - 2 * V_squared_times_V2
|
||||||
|
(pt3[PTXX], pt3[PTXY]) = _FQ2Mul(pt1yx, pt1yy, pt2xx, pt2xy); // newx = V * A
|
||||||
|
(pt1yx, pt1yy) = _FQ2Sub(pt2yx, pt2yy, pt2xx, pt2xy); // V_squared_times_V2 - A
|
||||||
|
(pt1yx, pt1yy) = _FQ2Mul(pt1xx, pt1xy, pt1yx, pt1yy); // U * (V_squared_times_V2 - A)
|
||||||
|
(pt1xx, pt1xy) = _FQ2Mul(pt1zx, pt1zy, pt3[PTYX], pt3[PTYY]); // V_cubed * U2
|
||||||
|
(pt3[PTYX], pt3[PTYY]) = _FQ2Sub(pt1yx, pt1yy, pt1xx, pt1xy); // newy = U * (V_squared_times_V2 - A) - V_cubed * U2
|
||||||
|
}
|
||||||
|
|
||||||
|
function _ECTwistDoubleJacobian(
|
||||||
|
uint256 pt1xx, uint256 pt1xy,
|
||||||
|
uint256 pt1yx, uint256 pt1yy,
|
||||||
|
uint256 pt1zx, uint256 pt1zy
|
||||||
|
) internal pure returns(
|
||||||
|
uint256 pt2xx, uint256 pt2xy,
|
||||||
|
uint256 pt2yx, uint256 pt2yy,
|
||||||
|
uint256 pt2zx, uint256 pt2zy
|
||||||
|
) {
|
||||||
|
(pt2xx, pt2xy) = _FQ2Muc(pt1xx, pt1xy, 3); // 3 * x
|
||||||
|
(pt2xx, pt2xy) = _FQ2Mul(pt2xx, pt2xy, pt1xx, pt1xy); // W = 3 * x * x
|
||||||
|
(pt1zx, pt1zy) = _FQ2Mul(pt1yx, pt1yy, pt1zx, pt1zy); // S = y * z
|
||||||
|
(pt2yx, pt2yy) = _FQ2Mul(pt1xx, pt1xy, pt1yx, pt1yy); // x * y
|
||||||
|
(pt2yx, pt2yy) = _FQ2Mul(pt2yx, pt2yy, pt1zx, pt1zy); // B = x * y * S
|
||||||
|
(pt1xx, pt1xy) = _FQ2Mul(pt2xx, pt2xy, pt2xx, pt2xy); // W * W
|
||||||
|
(pt2zx, pt2zy) = _FQ2Muc(pt2yx, pt2yy, 8); // 8 * B
|
||||||
|
(pt1xx, pt1xy) = _FQ2Sub(pt1xx, pt1xy, pt2zx, pt2zy); // H = W * W - 8 * B
|
||||||
|
(pt2zx, pt2zy) = _FQ2Mul(pt1zx, pt1zy, pt1zx, pt1zy); // S_squared = S * S
|
||||||
|
(pt2yx, pt2yy) = _FQ2Muc(pt2yx, pt2yy, 4); // 4 * B
|
||||||
|
(pt2yx, pt2yy) = _FQ2Sub(pt2yx, pt2yy, pt1xx, pt1xy); // 4 * B - H
|
||||||
|
(pt2yx, pt2yy) = _FQ2Mul(pt2yx, pt2yy, pt2xx, pt2xy); // W * (4 * B - H)
|
||||||
|
(pt2xx, pt2xy) = _FQ2Muc(pt1yx, pt1yy, 8); // 8 * y
|
||||||
|
(pt2xx, pt2xy) = _FQ2Mul(pt2xx, pt2xy, pt1yx, pt1yy); // 8 * y * y
|
||||||
|
(pt2xx, pt2xy) = _FQ2Mul(pt2xx, pt2xy, pt2zx, pt2zy); // 8 * y * y * S_squared
|
||||||
|
(pt2yx, pt2yy) = _FQ2Sub(pt2yx, pt2yy, pt2xx, pt2xy); // newy = W * (4 * B - H) - 8 * y * y * S_squared
|
||||||
|
(pt2xx, pt2xy) = _FQ2Muc(pt1xx, pt1xy, 2); // 2 * H
|
||||||
|
(pt2xx, pt2xy) = _FQ2Mul(pt2xx, pt2xy, pt1zx, pt1zy); // newx = 2 * H * S
|
||||||
|
(pt2zx, pt2zy) = _FQ2Mul(pt1zx, pt1zy, pt2zx, pt2zy); // S * S_squared
|
||||||
|
(pt2zx, pt2zy) = _FQ2Muc(pt2zx, pt2zy, 8); // newz = 8 * S * S_squared
|
||||||
|
}
|
||||||
|
|
||||||
|
function _ECTwistMulJacobian(
|
||||||
|
uint256 d,
|
||||||
|
uint256 pt1xx, uint256 pt1xy,
|
||||||
|
uint256 pt1yx, uint256 pt1yy,
|
||||||
|
uint256 pt1zx, uint256 pt1zy
|
||||||
|
) internal pure returns(uint256[6] memory pt2) {
|
||||||
|
while (d != 0) {
|
||||||
|
if ((d & 1) != 0) {
|
||||||
|
pt2 = _ECTwistAddJacobian(
|
||||||
|
pt2[PTXX], pt2[PTXY],
|
||||||
|
pt2[PTYX], pt2[PTYY],
|
||||||
|
pt2[PTZX], pt2[PTZY],
|
||||||
|
pt1xx, pt1xy,
|
||||||
|
pt1yx, pt1yy,
|
||||||
|
pt1zx, pt1zy);
|
||||||
|
}
|
||||||
|
(
|
||||||
|
pt1xx, pt1xy,
|
||||||
|
pt1yx, pt1yy,
|
||||||
|
pt1zx, pt1zy
|
||||||
|
) = _ECTwistDoubleJacobian(
|
||||||
|
pt1xx, pt1xy,
|
||||||
|
pt1yx, pt1yy,
|
||||||
|
pt1zx, pt1zy
|
||||||
|
);
|
||||||
|
|
||||||
|
d = d / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This file is MIT Licensed.
|
||||||
|
//
|
||||||
|
// Copyright 2017 Christian Reitwiessner
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
pragma solidity ^0.5.0;
|
||||||
|
library Pairing {
|
||||||
|
struct G1Point {
|
||||||
|
uint X;
|
||||||
|
uint Y;
|
||||||
|
}
|
||||||
|
// Encoding of field elements is: X[0] * z + X[1]
|
||||||
|
struct G2Point {
|
||||||
|
uint[2] X;
|
||||||
|
uint[2] Y;
|
||||||
|
}
|
||||||
|
/// @return the generator of G1
|
||||||
|
function P1() pure internal returns (G1Point memory) {
|
||||||
|
return G1Point(1, 2);
|
||||||
|
}
|
||||||
|
/// @return the generator of G2
|
||||||
|
function P2() pure internal returns (G2Point memory) {
|
||||||
|
return G2Point(
|
||||||
|
[11559732032986387107991004021392285783925812861821192530917403151452391805634,
|
||||||
|
10857046999023057135944570762232829481370756359578518086990519993285655852781],
|
||||||
|
[4082367875863433681332203403145435568316851327593401208105741076214120093531,
|
||||||
|
8495653923123431417604973247489272438418190587263600148770280649306958101930]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/// @return the negation of p, i.e. p.addition(p.negate()) should be zero.
|
||||||
|
function negate(G1Point memory p) pure internal returns (G1Point memory) {
|
||||||
|
// The prime q in the base field F_q for G1
|
||||||
|
uint q = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
|
||||||
|
if (p.X == 0 && p.Y == 0)
|
||||||
|
return G1Point(0, 0);
|
||||||
|
return G1Point(p.X, q - (p.Y % q));
|
||||||
|
}
|
||||||
|
/// @return the sum of two points of G1
|
||||||
|
function addition(G1Point memory p1, G1Point memory p2) internal returns (G1Point memory r) {
|
||||||
|
uint[4] memory input;
|
||||||
|
input[0] = p1.X;
|
||||||
|
input[1] = p1.Y;
|
||||||
|
input[2] = p2.X;
|
||||||
|
input[3] = p2.Y;
|
||||||
|
bool success;
|
||||||
|
assembly {
|
||||||
|
success := call(sub(gas, 2000), 6, 0, input, 0xc0, r, 0x60)
|
||||||
|
// Use "invalid" to make gas estimation work
|
||||||
|
switch success case 0 { invalid() }
|
||||||
|
}
|
||||||
|
require(success);
|
||||||
|
}
|
||||||
|
/// @return the sum of two points of G2
|
||||||
|
function addition(G2Point memory p1, G2Point memory p2) internal pure returns (G2Point memory r) {
|
||||||
|
(r.X[1], r.X[0], r.Y[1], r.Y[0]) = BN256G2.ECTwistAdd(p1.X[1],p1.X[0],p1.Y[1],p1.Y[0],p2.X[1],p2.X[0],p2.Y[1],p2.Y[0]);
|
||||||
|
}
|
||||||
|
/// @return the product of a point on G1 and a scalar, i.e.
|
||||||
|
/// p == p.scalar_mul(1) and p.addition(p) == p.scalar_mul(2) for all points p.
|
||||||
|
function scalar_mul(G1Point memory p, uint s) internal returns (G1Point memory r) {
|
||||||
|
uint[3] memory input;
|
||||||
|
input[0] = p.X;
|
||||||
|
input[1] = p.Y;
|
||||||
|
input[2] = s;
|
||||||
|
bool success;
|
||||||
|
assembly {
|
||||||
|
success := call(sub(gas, 2000), 7, 0, input, 0x80, r, 0x60)
|
||||||
|
// Use "invalid" to make gas estimation work
|
||||||
|
switch success case 0 { invalid() }
|
||||||
|
}
|
||||||
|
require (success);
|
||||||
|
}
|
||||||
|
/// @return the result of computing the pairing check
|
||||||
|
/// e(p1[0], p2[0]) * .... * e(p1[n], p2[n]) == 1
|
||||||
|
/// For example pairing([P1(), P1().negate()], [P2(), P2()]) should
|
||||||
|
/// return true.
|
||||||
|
function pairing(G1Point[] memory p1, G2Point[] memory p2) internal returns (bool) {
|
||||||
|
require(p1.length == p2.length);
|
||||||
|
uint elements = p1.length;
|
||||||
|
uint inputSize = elements * 6;
|
||||||
|
uint[] memory input = new uint[](inputSize);
|
||||||
|
for (uint i = 0; i < elements; i++)
|
||||||
|
{
|
||||||
|
input[i * 6 + 0] = p1[i].X;
|
||||||
|
input[i * 6 + 1] = p1[i].Y;
|
||||||
|
input[i * 6 + 2] = p2[i].X[0];
|
||||||
|
input[i * 6 + 3] = p2[i].X[1];
|
||||||
|
input[i * 6 + 4] = p2[i].Y[0];
|
||||||
|
input[i * 6 + 5] = p2[i].Y[1];
|
||||||
|
}
|
||||||
|
uint[1] memory out;
|
||||||
|
bool success;
|
||||||
|
assembly {
|
||||||
|
success := call(sub(gas, 2000), 8, 0, add(input, 0x20), mul(inputSize, 0x20), out, 0x20)
|
||||||
|
// Use "invalid" to make gas estimation work
|
||||||
|
switch success case 0 { invalid() }
|
||||||
|
}
|
||||||
|
require(success);
|
||||||
|
return out[0] != 0;
|
||||||
|
}
|
||||||
|
/// Convenience method for a pairing check for two pairs.
|
||||||
|
function pairingProd2(G1Point memory a1, G2Point memory a2, G1Point memory b1, G2Point memory b2) internal returns (bool) {
|
||||||
|
G1Point[] memory p1 = new G1Point[](2);
|
||||||
|
G2Point[] memory p2 = new G2Point[](2);
|
||||||
|
p1[0] = a1;
|
||||||
|
p1[1] = b1;
|
||||||
|
p2[0] = a2;
|
||||||
|
p2[1] = b2;
|
||||||
|
return pairing(p1, p2);
|
||||||
|
}
|
||||||
|
/// Convenience method for a pairing check for three pairs.
|
||||||
|
function pairingProd3(
|
||||||
|
G1Point memory a1, G2Point memory a2,
|
||||||
|
G1Point memory b1, G2Point memory b2,
|
||||||
|
G1Point memory c1, G2Point memory c2
|
||||||
|
) internal returns (bool) {
|
||||||
|
G1Point[] memory p1 = new G1Point[](3);
|
||||||
|
G2Point[] memory p2 = new G2Point[](3);
|
||||||
|
p1[0] = a1;
|
||||||
|
p1[1] = b1;
|
||||||
|
p1[2] = c1;
|
||||||
|
p2[0] = a2;
|
||||||
|
p2[1] = b2;
|
||||||
|
p2[2] = c2;
|
||||||
|
return pairing(p1, p2);
|
||||||
|
}
|
||||||
|
/// Convenience method for a pairing check for four pairs.
|
||||||
|
function pairingProd4(
|
||||||
|
G1Point memory a1, G2Point memory a2,
|
||||||
|
G1Point memory b1, G2Point memory b2,
|
||||||
|
G1Point memory c1, G2Point memory c2,
|
||||||
|
G1Point memory d1, G2Point memory d2
|
||||||
|
) internal returns (bool) {
|
||||||
|
G1Point[] memory p1 = new G1Point[](4);
|
||||||
|
G2Point[] memory p2 = new G2Point[](4);
|
||||||
|
p1[0] = a1;
|
||||||
|
p1[1] = b1;
|
||||||
|
p1[2] = c1;
|
||||||
|
p1[3] = d1;
|
||||||
|
p2[0] = a2;
|
||||||
|
p2[1] = b2;
|
||||||
|
p2[2] = c2;
|
||||||
|
p2[3] = d2;
|
||||||
|
return pairing(p1, p2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract Verifier {
|
||||||
|
using Pairing for *;
|
||||||
|
struct VerifyingKey {
|
||||||
|
Pairing.G1Point a;
|
||||||
|
Pairing.G2Point b;
|
||||||
|
Pairing.G2Point gamma;
|
||||||
|
Pairing.G2Point delta;
|
||||||
|
Pairing.G1Point[] gammaABC;
|
||||||
|
}
|
||||||
|
struct Proof {
|
||||||
|
Pairing.G1Point A;
|
||||||
|
Pairing.G2Point B;
|
||||||
|
Pairing.G1Point C;
|
||||||
|
}
|
||||||
|
function verifyingKey() pure internal returns (VerifyingKey memory vk) {
|
||||||
|
vk.a = Pairing.G1Point(uint256(0x2c2cb1812fb05d4f31791c66ff995d756b73162f3bb016a5c114befe5cd7903e), uint256(0x0abc1f8a5d49cb2dbda15b5a8b7cd81bec0a581e7c2e16f79446af2d2f5340c0));
|
||||||
|
vk.b = Pairing.G2Point([uint256(0x071644533641f7e3acb8606328c591853b2bc27253f29bc11d008a67996fc07f), uint256(0x26ca2720c073a085d8452aef541aac280879971c09b199a6e0f21bf36745e1d8)], [uint256(0x0b17104896ed701b6d52279992c1f20d558bc0de8284087645633bf3ca1a0c98), uint256(0x2c10eb5b6c0ca42ede8cdcf60642c6dca040abe9abb8294948f4aa0be59a0d42)]);
|
||||||
|
vk.gamma = Pairing.G2Point([uint256(0x0afbadec2ecafdd62278c7021095660f5786f445c040e628e4ed1a410454b582), uint256(0x038aa6f04ee254a97e2b75ea1f30e36785b6cde4dfd3a2371e058ce089b9ad51)], [uint256(0x077720bb216fb0051c5e153c1bd9aa36a678173b9c13e8d3a83cb5a75ca36948), uint256(0x1f9b58e9abde296abc3c3bab8fb0be2a4f497d8e5d9d463997d316e9cc558a7d)]);
|
||||||
|
vk.delta = Pairing.G2Point([uint256(0x16526b9b519fa544d3f9ce35a5f4afa7aac0aa4dd54421c4864b3fe8d2415f41), uint256(0x24e24f35699cca59416a7f43c0e93e148b2353440978994df8f81603a46f8839)], [uint256(0x299f9f09280310aedf63055c5ce76feb16557ed7ff11ba35adad718102b5651a), uint256(0x0c4a2fc4db77ef6c19511b2ffb369981cebbffcb5337a671e1ad678b460ac5e9)]);
|
||||||
|
vk.gammaABC = new Pairing.G1Point[](6);
|
||||||
|
vk.gammaABC[0] = Pairing.G1Point(uint256(0x2f910078bf5092a7ea9d3ce750b7b5399b101509adb8017a6e12fa1a4c638d5b), uint256(0x0b76454d4300571c8d86714b4e5ef095688b51080e674425e8e5edb201f64128));
|
||||||
|
vk.gammaABC[1] = Pairing.G1Point(uint256(0x2922a307d415f70c8df6f14b664c46df12a89cd3a89cf7960663907bf9483b68), uint256(0x1bc30a719ddc0099f557cca61a0687766e6275fc98b185baa77735b93bf2a0ef));
|
||||||
|
vk.gammaABC[2] = Pairing.G1Point(uint256(0x0201dc8c8faa3dc5b8eec85f029d2482bf11a6b46d5f8e4d9f17d41ac3e4c9c1), uint256(0x0a1d62c1142c92dff75b53d5a572fd7a013708118acf10f718c61fb6226160f5));
|
||||||
|
vk.gammaABC[3] = Pairing.G1Point(uint256(0x02276f5896610ec573cd6cdc6e47c69e756362d2b1b1c51c5ab90ac838d1a898), uint256(0x13fa6cc7987f4f3118f6ee3ab85dcd708df17050636d487914077348e0af05b1));
|
||||||
|
vk.gammaABC[4] = Pairing.G1Point(uint256(0x0778ae3718fd7f48564bc33b60ec4f39a238e97cb4cc0bbd4ff37119942ff7d4), uint256(0x0282e96481744ee21524d802b3e524bf0596bb37bb63e5ed37c77fc1a5c8e89d));
|
||||||
|
vk.gammaABC[5] = Pairing.G1Point(uint256(0x1ce40e230695bdab7d2ff7ebcf6e6fedb68d1a320238fc98845b151ae4ee3b54), uint256(0x0feac76664d37b57a4ea5a774252bb82355294e55635a8aeb7a1327405d27128));
|
||||||
|
}
|
||||||
|
function verify(uint[] memory input, Proof memory proof) internal returns (uint) {
|
||||||
|
VerifyingKey memory vk = verifyingKey();
|
||||||
|
require(input.length + 1 == vk.gammaABC.length);
|
||||||
|
// Compute the linear combination vk_x
|
||||||
|
Pairing.G1Point memory vk_x = Pairing.G1Point(0, 0);
|
||||||
|
for (uint i = 0; i < input.length; i++)
|
||||||
|
vk_x = Pairing.addition(vk_x, Pairing.scalar_mul(vk.gammaABC[i + 1], input[i]));
|
||||||
|
vk_x = Pairing.addition(vk_x, vk.gammaABC[0]);
|
||||||
|
if(!Pairing.pairingProd4(
|
||||||
|
proof.A, proof.B,
|
||||||
|
Pairing.negate(vk_x), vk.gamma,
|
||||||
|
Pairing.negate(proof.C), vk.delta,
|
||||||
|
Pairing.negate(vk.a), vk.b)) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
event Verified(string s);
|
||||||
|
function verifyTx(
|
||||||
|
uint[2] memory a,
|
||||||
|
uint[2][2] memory b,
|
||||||
|
uint[2] memory c,
|
||||||
|
uint[5] memory input
|
||||||
|
) public returns (bool r) {
|
||||||
|
Proof memory proof;
|
||||||
|
proof.A = Pairing.G1Point(a[0], a[1]);
|
||||||
|
proof.B = Pairing.G2Point([b[0][0], b[0][1]], [b[1][0], b[1][1]]);
|
||||||
|
proof.C = Pairing.G1Point(c[0], c[1]);
|
||||||
|
uint[] memory inputValues = new uint[](input.length);
|
||||||
|
for(uint i = 0; i < input.length; i++){
|
||||||
|
inputValues[i] = input[i];
|
||||||
|
}
|
||||||
|
if (verify(inputValues, proof) == 0) {
|
||||||
|
emit Verified("Transaction successfully verified.");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
109786
backend_zk/witness
Normal file
109786
backend_zk/witness
Normal file
File diff suppressed because it is too large
Load Diff
6
frontend/README.md
Normal file
6
frontend/README.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# Usage
|
||||||
|
|
||||||
|
0. set the `appId` (Fluence) and `lazyAddress` (Eth contract) in `index.js`
|
||||||
|
1. run `npm i`
|
||||||
|
2. run `npm run build`
|
||||||
|
3. run `npm run start`
|
95
frontend/index.html
Normal file
95
frontend/index.html
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<!-- Required meta tags -->
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Lazy snark dashboard</title>
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
|
||||||
|
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<p> </p>
|
||||||
|
<h3>
|
||||||
|
Lazy snark dashboard
|
||||||
|
</h3>
|
||||||
|
<p> </p>
|
||||||
|
</div>
|
||||||
|
<div class="row 0">
|
||||||
|
<div class="col-sm-7">
|
||||||
|
<label id="state-id">State ID's</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2">
|
||||||
|
<label id="state-status-fluence">Fluence status</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<label id="challenge">Challenge?</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row 1">
|
||||||
|
<div class="col-sm-7">
|
||||||
|
<label id="state-id-0">None</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2">
|
||||||
|
<label id="state-status-fluence-0">None</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<button type="button" class="btn btn-primary" id="challenge-0">Challenge on Fluence!</button>
|
||||||
|
<p><a id = "link-0" target="_blank"></a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row 2">
|
||||||
|
<div class="col-sm-7">
|
||||||
|
<label id="state-id-1">None</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2">
|
||||||
|
<label id="state-status-fluence-1">None</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<button type="button" class="btn btn-primary" id="challenge-1">Challenge on Fluence!</button>
|
||||||
|
<p><a id = "link-1" target="_blank"></a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row 3">
|
||||||
|
<div class="col-sm-7">
|
||||||
|
<label id="state-id-2">None</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2">
|
||||||
|
<label id="state-status-fluence-2">None</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<button type="button" class="btn btn-primary" id="challenge-2">Challenge on Fluence!</button>
|
||||||
|
<p><a id = "link-2" target="_blank"></a></p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row 4">
|
||||||
|
<div class="col-sm-7">
|
||||||
|
<label id="state-id-3">None</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2">
|
||||||
|
<label id="state-status-fluence-3">None</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<button type="button" class="btn btn-primary" id="challenge-3">Challenge on Fluence!</button>
|
||||||
|
<p><a id = "link-3" target="_blank"></a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row 5">
|
||||||
|
<div class="col-sm-7">
|
||||||
|
<label id="state-id-4">None</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2">
|
||||||
|
<label id="state-status-fluence-4">None</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<button type="button" class="btn btn-primary" id="challenge-4">Challenge on Fluence!</button>
|
||||||
|
<p><a id = "link-4" target="_blank"></a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
<script src="bundle.js"></script>
|
||||||
|
</html>
|
437
frontend/index.js
Normal file
437
frontend/index.js
Normal file
@ -0,0 +1,437 @@
|
|||||||
|
//CONNECT FLUENCE
|
||||||
|
import * as fluence from "fluence";
|
||||||
|
|
||||||
|
|
||||||
|
window.getResultAsString = function (result) {
|
||||||
|
return result.result().then((r) => r.asString())
|
||||||
|
};
|
||||||
|
|
||||||
|
var contractInstance;
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
let contractAddress = "0xeFF91455de6D4CF57C141bD8bF819E5f873c1A01";
|
||||||
|
|
||||||
|
// set ethUrl to `undefined` to use MetaMask instead of Ethereum node
|
||||||
|
let ethUrl = "http://rinkeby.fluence.one:8545/";
|
||||||
|
|
||||||
|
// application to interact with that stored in Fluence contract
|
||||||
|
let appId = "264";
|
||||||
|
|
||||||
|
// create a session between client and backend application, and then join the game
|
||||||
|
fluence.connect(contractAddress, appId, ethUrl).then((s) => {
|
||||||
|
console.log("Session created");
|
||||||
|
window.session = s;
|
||||||
|
});
|
||||||
|
|
||||||
|
var lazyAddress = '0x1cca1f0be338c747b11a16aba8d0905251628bdf';
|
||||||
|
let ControllerAbi = [
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "verifier",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "stake",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "tasks",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"name": "input",
|
||||||
|
"type": "uint256[5]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "data",
|
||||||
|
"type": "tuple"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"name": "a",
|
||||||
|
"type": "uint256[2]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "b",
|
||||||
|
"type": "uint256[2][2]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "c",
|
||||||
|
"type": "uint256[2]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "proof",
|
||||||
|
"type": "tuple"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "submitter",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "timestamp",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "status",
|
||||||
|
"type": "uint8"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": true,
|
||||||
|
"name": "sender",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "index",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"name": "input",
|
||||||
|
"type": "uint256[5]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "data",
|
||||||
|
"type": "tuple"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"name": "a",
|
||||||
|
"type": "uint256[2]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "b",
|
||||||
|
"type": "uint256[2][2]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "c",
|
||||||
|
"type": "uint256[2]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "proof",
|
||||||
|
"type": "tuple"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "submitter",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "timestamp",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "status",
|
||||||
|
"type": "uint8"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"indexed": false,
|
||||||
|
"name": "task",
|
||||||
|
"type": "tuple"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "Submitted",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": true,
|
||||||
|
"name": "challenger",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "index",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "Challenged",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "tasksNum",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"name": "input",
|
||||||
|
"type": "uint256[5]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "data",
|
||||||
|
"type": "tuple"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"name": "a",
|
||||||
|
"type": "uint256[2]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "b",
|
||||||
|
"type": "uint256[2][2]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "c",
|
||||||
|
"type": "uint256[2]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "proof",
|
||||||
|
"type": "tuple"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "submit",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": true,
|
||||||
|
"stateMutability": "payable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "challenge",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "finzalize",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "taskDataById",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "data",
|
||||||
|
"type": "uint256[13]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "last5Timestamps",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "result",
|
||||||
|
"type": "uint256[5]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "getDataById",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"name": "input",
|
||||||
|
"type": "uint256[5]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "data",
|
||||||
|
"type": "tuple"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"name": "a",
|
||||||
|
"type": "uint256[2]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "b",
|
||||||
|
"type": "uint256[2][2]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "c",
|
||||||
|
"type": "uint256[2]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "proof",
|
||||||
|
"type": "tuple"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "submitter",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "timestamp",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "status",
|
||||||
|
"type": "uint8"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "task",
|
||||||
|
"type": "tuple"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
let ControllerContract = web3.eth.contract(ControllerAbi);
|
||||||
|
contractInstance = ControllerContract.at(lazyAddress);
|
||||||
|
window.ethereum.enable();
|
||||||
|
|
||||||
|
contractInstance.tasksNum(function (err, result) {
|
||||||
|
let maxLen = Math.min(result, 5);
|
||||||
|
for (let i = 0; i < maxLen; i++) {
|
||||||
|
let data = result - 1 - i;
|
||||||
|
$('#state-id-' + i).text(data);
|
||||||
|
let fluenceResponse_check = session.request(`{"action": "Check", "proof_id": ${data}}`);
|
||||||
|
getResultAsString(fluenceResponse_check).then(function (str) {
|
||||||
|
let fluenceResponse = JSON.parse(str);
|
||||||
|
console.log(fluenceResponse);
|
||||||
|
if (fluenceResponse.hasOwnProperty('verifed')) {
|
||||||
|
if (fluenceResponse.verifed) {
|
||||||
|
// все хорошо - мы проверили в флюенсе
|
||||||
|
$('#state-status-fluence-' + i).text('TRUE by Fluence.');
|
||||||
|
$('#challenge-' + i).prop('disabled', true);
|
||||||
|
} else {
|
||||||
|
// мы проверили, пруф неправильный
|
||||||
|
$('#state-status-fluence-' + i).text('FALSE by Fluence.');
|
||||||
|
$('#challenge-' + i).text('Challenge on Ethereum!')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('Task N ' + data + ' is not checked on Fluence!')
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$('button').click(function () {
|
||||||
|
let id = $(this)[0].id.slice(-1);
|
||||||
|
let data = $('#state-id-' + id)[0].textContent;
|
||||||
|
|
||||||
|
if ($(this)[0].textContent === 'Challenge on Fluence!') {
|
||||||
|
contractInstance.taskDataById(data, function (err, result) {
|
||||||
|
let public_par = result.slice(0, 5);
|
||||||
|
let proof = result.slice(5, 13);
|
||||||
|
|
||||||
|
let fluenceResponse_ver = session.request(`{"action": "Verify", "proof_id": ${data}, "public_par": [${public_par}], "proof": [${proof}]}`);
|
||||||
|
getResultAsString(fluenceResponse_ver).then(function (str) {
|
||||||
|
let fluenceResponse = JSON.parse(str);
|
||||||
|
let success = fluenceResponse.result === 1;
|
||||||
|
console.log(fluenceResponse);
|
||||||
|
if (success) {
|
||||||
|
// все хорошо - мы проверили в флюенсе
|
||||||
|
$('#state-status-fluence-' + id).text('TRUE by Fluence.');
|
||||||
|
$('#challenge-' + id).prop('disabled', true);
|
||||||
|
} else {
|
||||||
|
// мы проверили, пруф неправильный
|
||||||
|
$('#state-status-fluence-' + id).text('FALSE by Fluence.');
|
||||||
|
$('#challenge-' + id).text('Challenge on Ethereum!')
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else if ($(this)[0].textContent === 'Challenge on Ethereum!') {
|
||||||
|
challengeEthereum(id, data);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function challengeEthereum(id, data) {
|
||||||
|
console.log('Challenging task N ' + data + ' on Ethereum!');
|
||||||
|
contractInstance.challenge.sendTransaction(data, function (err, txHash) {
|
||||||
|
$('#challenge-' + id).remove();
|
||||||
|
$('#link-' + id).text('See tx on Etherscan!').attr("href", "https://rinkeby.etherscan.io/tx/" + txHash);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
31
frontend/package.json
Normal file
31
frontend/package.json
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"name": "frontend-challenger",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"start": "webpack-dev-server",
|
||||||
|
"build": "webpack"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"index.html"
|
||||||
|
],
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"devDependencies": {
|
||||||
|
"copy-webpack-plugin": "^5.0.2",
|
||||||
|
"css-loader": "^2.1.1",
|
||||||
|
"html-webpack-plugin": "^3.2.0",
|
||||||
|
"style-loader": "0.23.1",
|
||||||
|
"webpack": "^4.29.6",
|
||||||
|
"webpack-cli": "^3.3.0",
|
||||||
|
"webpack-dev-server": "^3.2.1",
|
||||||
|
"web3": "1.0.0-beta.55"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"Package": "0.0.1",
|
||||||
|
"fluence": "0.1.26"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
35
frontend/webpack.config.js
Normal file
35
frontend/webpack.config.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
const path = require('path');
|
||||||
|
const webpack = require('webpack');
|
||||||
|
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
// use index.js as entrypoint
|
||||||
|
entry: {
|
||||||
|
app: ['./index.js']
|
||||||
|
},
|
||||||
|
devServer: {
|
||||||
|
contentBase: './bundle',
|
||||||
|
hot: true
|
||||||
|
},
|
||||||
|
mode: "production",
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.css$/,
|
||||||
|
use: ['style-loader', 'css-loader']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
// build all code in `bundle.js` in `bundle` directory
|
||||||
|
output: {
|
||||||
|
filename: 'bundle.js',
|
||||||
|
path: path.resolve(__dirname, 'bundle')
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
// create `index.html` with imported `bundle.js`
|
||||||
|
new CopyWebpackPlugin([{
|
||||||
|
from: './*.html'
|
||||||
|
}]),
|
||||||
|
new webpack.HotModuleReplacementPlugin()
|
||||||
|
]
|
||||||
|
};
|
@ -19,17 +19,24 @@ contract Lazy is Structs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Task[] public tasks;
|
Task[] public tasks;
|
||||||
|
function tasksNum() external view returns(uint) {
|
||||||
|
return tasks.length;
|
||||||
|
}
|
||||||
|
|
||||||
uint256 public stake;
|
uint256 public stake;
|
||||||
IVerifier public verifier;
|
IVerifier public verifier;
|
||||||
|
|
||||||
|
constructor(IVerifier _verifier) public {
|
||||||
|
verifier = _verifier;
|
||||||
|
}
|
||||||
|
|
||||||
/// @dev This function submits data.
|
/// @dev This function submits data.
|
||||||
/// @param data - public inptut for zkp
|
/// @param data - public inptut for zkp
|
||||||
/// @param proof - proof that verifies input
|
/// @param proof - proof that verifies input
|
||||||
function submit(Data calldata data, Proof calldata proof) external payable {
|
function submit(Data calldata data, Proof calldata proof) external payable {
|
||||||
require(msg.value == stake);
|
require(msg.value == stake);
|
||||||
|
|
||||||
Task memory task = Task(data, proof, msg.sender, uint96(now), Status.UNCHECKED);
|
Task memory task = Task(data, proof, msg.sender, now, Status.UNCHECKED);
|
||||||
uint index = tasks.push(task);
|
uint index = tasks.push(task);
|
||||||
|
|
||||||
emit Submitted(msg.sender, index, task);
|
emit Submitted(msg.sender, index, task);
|
||||||
@ -65,19 +72,27 @@ contract Lazy is Structs {
|
|||||||
msg.sender.transfer(stake);
|
msg.sender.transfer(stake);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function taskDataById(uint id) external view returns(
|
||||||
|
uint[13] memory data
|
||||||
function last5Timestamps() view external returns (uint256[5] memory result) {
|
) {
|
||||||
uint256 length = tasks.length;
|
Task memory task = tasks[id];
|
||||||
for (uint256 i = 1; i <= 5; i++) {
|
|
||||||
result[i - 1] = tasks[length - i].timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
data[0] = task.data.input[0];
|
||||||
}
|
data[1] = task.data.input[1];
|
||||||
|
data[2] = task.data.input[2];
|
||||||
function getDataById(uint256 id) view external returns (Task memory task) {
|
data[3] = task.data.input[3];
|
||||||
task = tasks[tasks.length - 1 - id];
|
data[4] = task.data.input[4];
|
||||||
|
|
||||||
|
data[5] = task.proof.a[0];
|
||||||
|
data[6] = task.proof.a[1];
|
||||||
|
|
||||||
|
data[7] = task.proof.b[0][0];
|
||||||
|
data[8] = task.proof.b[0][1];
|
||||||
|
data[9] = task.proof.b[1][0];
|
||||||
|
data[10] = task.proof.b[1][1];
|
||||||
|
|
||||||
|
data[11] = task.proof.c[0];
|
||||||
|
data[12] = task.proof.c[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,11 +2,12 @@ pragma solidity ^0.5.4;
|
|||||||
|
|
||||||
interface Structs {
|
interface Structs {
|
||||||
struct Data {
|
struct Data {
|
||||||
uint x;
|
uint[5] input;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Proof {
|
struct Proof {
|
||||||
uint x;
|
uint[2] a;
|
||||||
|
uint[2][2] b;
|
||||||
|
uint[2] c;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
604
truffle/contracts/Verifier.sol
Normal file
604
truffle/contracts/Verifier.sol
Normal file
@ -0,0 +1,604 @@
|
|||||||
|
// This file is LGPL3 Licensed
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title Elliptic curve operations on twist points for alt_bn128
|
||||||
|
* @author Mustafa Al-Bassam (mus@musalbas.com)
|
||||||
|
*/
|
||||||
|
library BN256G2 {
|
||||||
|
uint256 internal constant FIELD_MODULUS = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47;
|
||||||
|
uint256 internal constant TWISTBX = 0x2b149d40ceb8aaae81be18991be06ac3b5b4c5e559dbefa33267e6dc24a138e5;
|
||||||
|
uint256 internal constant TWISTBY = 0x9713b03af0fed4cd2cafadeed8fdf4a74fa084e52d1852e4a2bd0685c315d2;
|
||||||
|
uint internal constant PTXX = 0;
|
||||||
|
uint internal constant PTXY = 1;
|
||||||
|
uint internal constant PTYX = 2;
|
||||||
|
uint internal constant PTYY = 3;
|
||||||
|
uint internal constant PTZX = 4;
|
||||||
|
uint internal constant PTZY = 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @notice Add two twist points
|
||||||
|
* @param pt1xx Coefficient 1 of x on point 1
|
||||||
|
* @param pt1xy Coefficient 2 of x on point 1
|
||||||
|
* @param pt1yx Coefficient 1 of y on point 1
|
||||||
|
* @param pt1yy Coefficient 2 of y on point 1
|
||||||
|
* @param pt2xx Coefficient 1 of x on point 2
|
||||||
|
* @param pt2xy Coefficient 2 of x on point 2
|
||||||
|
* @param pt2yx Coefficient 1 of y on point 2
|
||||||
|
* @param pt2yy Coefficient 2 of y on point 2
|
||||||
|
* @return (pt3xx, pt3xy, pt3yx, pt3yy)
|
||||||
|
*/
|
||||||
|
function ECTwistAdd(
|
||||||
|
uint256 pt1xx, uint256 pt1xy,
|
||||||
|
uint256 pt1yx, uint256 pt1yy,
|
||||||
|
uint256 pt2xx, uint256 pt2xy,
|
||||||
|
uint256 pt2yx, uint256 pt2yy
|
||||||
|
) public pure returns (
|
||||||
|
uint256, uint256,
|
||||||
|
uint256, uint256
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
pt1xx == 0 && pt1xy == 0 &&
|
||||||
|
pt1yx == 0 && pt1yy == 0
|
||||||
|
) {
|
||||||
|
if (!(
|
||||||
|
pt2xx == 0 && pt2xy == 0 &&
|
||||||
|
pt2yx == 0 && pt2yy == 0
|
||||||
|
)) {
|
||||||
|
assert(_isOnCurve(
|
||||||
|
pt2xx, pt2xy,
|
||||||
|
pt2yx, pt2yy
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
pt2xx, pt2xy,
|
||||||
|
pt2yx, pt2yy
|
||||||
|
);
|
||||||
|
} else if (
|
||||||
|
pt2xx == 0 && pt2xy == 0 &&
|
||||||
|
pt2yx == 0 && pt2yy == 0
|
||||||
|
) {
|
||||||
|
assert(_isOnCurve(
|
||||||
|
pt1xx, pt1xy,
|
||||||
|
pt1yx, pt1yy
|
||||||
|
));
|
||||||
|
return (
|
||||||
|
pt1xx, pt1xy,
|
||||||
|
pt1yx, pt1yy
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(_isOnCurve(
|
||||||
|
pt1xx, pt1xy,
|
||||||
|
pt1yx, pt1yy
|
||||||
|
));
|
||||||
|
assert(_isOnCurve(
|
||||||
|
pt2xx, pt2xy,
|
||||||
|
pt2yx, pt2yy
|
||||||
|
));
|
||||||
|
|
||||||
|
uint256[6] memory pt3 = _ECTwistAddJacobian(
|
||||||
|
pt1xx, pt1xy,
|
||||||
|
pt1yx, pt1yy,
|
||||||
|
1, 0,
|
||||||
|
pt2xx, pt2xy,
|
||||||
|
pt2yx, pt2yy,
|
||||||
|
1, 0
|
||||||
|
);
|
||||||
|
|
||||||
|
return _fromJacobian(
|
||||||
|
pt3[PTXX], pt3[PTXY],
|
||||||
|
pt3[PTYX], pt3[PTYY],
|
||||||
|
pt3[PTZX], pt3[PTZY]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @notice Multiply a twist point by a scalar
|
||||||
|
* @param s Scalar to multiply by
|
||||||
|
* @param pt1xx Coefficient 1 of x
|
||||||
|
* @param pt1xy Coefficient 2 of x
|
||||||
|
* @param pt1yx Coefficient 1 of y
|
||||||
|
* @param pt1yy Coefficient 2 of y
|
||||||
|
* @return (pt2xx, pt2xy, pt2yx, pt2yy)
|
||||||
|
*/
|
||||||
|
function ECTwistMul(
|
||||||
|
uint256 s,
|
||||||
|
uint256 pt1xx, uint256 pt1xy,
|
||||||
|
uint256 pt1yx, uint256 pt1yy
|
||||||
|
) public pure returns (
|
||||||
|
uint256, uint256,
|
||||||
|
uint256, uint256
|
||||||
|
) {
|
||||||
|
uint256 pt1zx = 1;
|
||||||
|
if (
|
||||||
|
pt1xx == 0 && pt1xy == 0 &&
|
||||||
|
pt1yx == 0 && pt1yy == 0
|
||||||
|
) {
|
||||||
|
pt1xx = 1;
|
||||||
|
pt1yx = 1;
|
||||||
|
pt1zx = 0;
|
||||||
|
} else {
|
||||||
|
assert(_isOnCurve(
|
||||||
|
pt1xx, pt1xy,
|
||||||
|
pt1yx, pt1yy
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint256[6] memory pt2 = _ECTwistMulJacobian(
|
||||||
|
s,
|
||||||
|
pt1xx, pt1xy,
|
||||||
|
pt1yx, pt1yy,
|
||||||
|
pt1zx, 0
|
||||||
|
);
|
||||||
|
|
||||||
|
return _fromJacobian(
|
||||||
|
pt2[PTXX], pt2[PTXY],
|
||||||
|
pt2[PTYX], pt2[PTYY],
|
||||||
|
pt2[PTZX], pt2[PTZY]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @notice Get the field modulus
|
||||||
|
* @return The field modulus
|
||||||
|
*/
|
||||||
|
function GetFieldModulus() public pure returns (uint256) {
|
||||||
|
return FIELD_MODULUS;
|
||||||
|
}
|
||||||
|
|
||||||
|
function submod(uint256 a, uint256 b, uint256 n) internal pure returns (uint256) {
|
||||||
|
return addmod(a, n - b, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _FQ2Mul(
|
||||||
|
uint256 xx, uint256 xy,
|
||||||
|
uint256 yx, uint256 yy
|
||||||
|
) internal pure returns(uint256, uint256) {
|
||||||
|
return (
|
||||||
|
submod(mulmod(xx, yx, FIELD_MODULUS), mulmod(xy, yy, FIELD_MODULUS), FIELD_MODULUS),
|
||||||
|
addmod(mulmod(xx, yy, FIELD_MODULUS), mulmod(xy, yx, FIELD_MODULUS), FIELD_MODULUS)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _FQ2Muc(
|
||||||
|
uint256 xx, uint256 xy,
|
||||||
|
uint256 c
|
||||||
|
) internal pure returns(uint256, uint256) {
|
||||||
|
return (
|
||||||
|
mulmod(xx, c, FIELD_MODULUS),
|
||||||
|
mulmod(xy, c, FIELD_MODULUS)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _FQ2Add(
|
||||||
|
uint256 xx, uint256 xy,
|
||||||
|
uint256 yx, uint256 yy
|
||||||
|
) internal pure returns(uint256, uint256) {
|
||||||
|
return (
|
||||||
|
addmod(xx, yx, FIELD_MODULUS),
|
||||||
|
addmod(xy, yy, FIELD_MODULUS)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _FQ2Sub(
|
||||||
|
uint256 xx, uint256 xy,
|
||||||
|
uint256 yx, uint256 yy
|
||||||
|
) internal pure returns(uint256 rx, uint256 ry) {
|
||||||
|
return (
|
||||||
|
submod(xx, yx, FIELD_MODULUS),
|
||||||
|
submod(xy, yy, FIELD_MODULUS)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _FQ2Div(
|
||||||
|
uint256 xx, uint256 xy,
|
||||||
|
uint256 yx, uint256 yy
|
||||||
|
) internal pure returns(uint256, uint256) {
|
||||||
|
(yx, yy) = _FQ2Inv(yx, yy);
|
||||||
|
return _FQ2Mul(xx, xy, yx, yy);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _FQ2Inv(uint256 x, uint256 y) internal pure returns(uint256, uint256) {
|
||||||
|
uint256 inv = _modInv(addmod(mulmod(y, y, FIELD_MODULUS), mulmod(x, x, FIELD_MODULUS), FIELD_MODULUS), FIELD_MODULUS);
|
||||||
|
return (
|
||||||
|
mulmod(x, inv, FIELD_MODULUS),
|
||||||
|
FIELD_MODULUS - mulmod(y, inv, FIELD_MODULUS)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _isOnCurve(
|
||||||
|
uint256 xx, uint256 xy,
|
||||||
|
uint256 yx, uint256 yy
|
||||||
|
) internal pure returns (bool) {
|
||||||
|
uint256 yyx;
|
||||||
|
uint256 yyy;
|
||||||
|
uint256 xxxx;
|
||||||
|
uint256 xxxy;
|
||||||
|
(yyx, yyy) = _FQ2Mul(yx, yy, yx, yy);
|
||||||
|
(xxxx, xxxy) = _FQ2Mul(xx, xy, xx, xy);
|
||||||
|
(xxxx, xxxy) = _FQ2Mul(xxxx, xxxy, xx, xy);
|
||||||
|
(yyx, yyy) = _FQ2Sub(yyx, yyy, xxxx, xxxy);
|
||||||
|
(yyx, yyy) = _FQ2Sub(yyx, yyy, TWISTBX, TWISTBY);
|
||||||
|
return yyx == 0 && yyy == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _modInv(uint256 a, uint256 n) internal pure returns(uint256 t) {
|
||||||
|
t = 0;
|
||||||
|
uint256 newT = 1;
|
||||||
|
uint256 r = n;
|
||||||
|
uint256 newR = a;
|
||||||
|
uint256 q;
|
||||||
|
while (newR != 0) {
|
||||||
|
q = r / newR;
|
||||||
|
(t, newT) = (newT, submod(t, mulmod(q, newT, n), n));
|
||||||
|
(r, newR) = (newR, r - q * newR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _fromJacobian(
|
||||||
|
uint256 pt1xx, uint256 pt1xy,
|
||||||
|
uint256 pt1yx, uint256 pt1yy,
|
||||||
|
uint256 pt1zx, uint256 pt1zy
|
||||||
|
) internal pure returns (
|
||||||
|
uint256 pt2xx, uint256 pt2xy,
|
||||||
|
uint256 pt2yx, uint256 pt2yy
|
||||||
|
) {
|
||||||
|
uint256 invzx;
|
||||||
|
uint256 invzy;
|
||||||
|
(invzx, invzy) = _FQ2Inv(pt1zx, pt1zy);
|
||||||
|
(pt2xx, pt2xy) = _FQ2Mul(pt1xx, pt1xy, invzx, invzy);
|
||||||
|
(pt2yx, pt2yy) = _FQ2Mul(pt1yx, pt1yy, invzx, invzy);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _ECTwistAddJacobian(
|
||||||
|
uint256 pt1xx, uint256 pt1xy,
|
||||||
|
uint256 pt1yx, uint256 pt1yy,
|
||||||
|
uint256 pt1zx, uint256 pt1zy,
|
||||||
|
uint256 pt2xx, uint256 pt2xy,
|
||||||
|
uint256 pt2yx, uint256 pt2yy,
|
||||||
|
uint256 pt2zx, uint256 pt2zy) internal pure returns (uint256[6] memory pt3) {
|
||||||
|
if (pt1zx == 0 && pt1zy == 0) {
|
||||||
|
(
|
||||||
|
pt3[PTXX], pt3[PTXY],
|
||||||
|
pt3[PTYX], pt3[PTYY],
|
||||||
|
pt3[PTZX], pt3[PTZY]
|
||||||
|
) = (
|
||||||
|
pt2xx, pt2xy,
|
||||||
|
pt2yx, pt2yy,
|
||||||
|
pt2zx, pt2zy
|
||||||
|
);
|
||||||
|
return pt3;
|
||||||
|
} else if (pt2zx == 0 && pt2zy == 0) {
|
||||||
|
(
|
||||||
|
pt3[PTXX], pt3[PTXY],
|
||||||
|
pt3[PTYX], pt3[PTYY],
|
||||||
|
pt3[PTZX], pt3[PTZY]
|
||||||
|
) = (
|
||||||
|
pt1xx, pt1xy,
|
||||||
|
pt1yx, pt1yy,
|
||||||
|
pt1zx, pt1zy
|
||||||
|
);
|
||||||
|
return pt3;
|
||||||
|
}
|
||||||
|
|
||||||
|
(pt2yx, pt2yy) = _FQ2Mul(pt2yx, pt2yy, pt1zx, pt1zy); // U1 = y2 * z1
|
||||||
|
(pt3[PTYX], pt3[PTYY]) = _FQ2Mul(pt1yx, pt1yy, pt2zx, pt2zy); // U2 = y1 * z2
|
||||||
|
(pt2xx, pt2xy) = _FQ2Mul(pt2xx, pt2xy, pt1zx, pt1zy); // V1 = x2 * z1
|
||||||
|
(pt3[PTZX], pt3[PTZY]) = _FQ2Mul(pt1xx, pt1xy, pt2zx, pt2zy); // V2 = x1 * z2
|
||||||
|
|
||||||
|
if (pt2xx == pt3[PTZX] && pt2xy == pt3[PTZY]) {
|
||||||
|
if (pt2yx == pt3[PTYX] && pt2yy == pt3[PTYY]) {
|
||||||
|
(
|
||||||
|
pt3[PTXX], pt3[PTXY],
|
||||||
|
pt3[PTYX], pt3[PTYY],
|
||||||
|
pt3[PTZX], pt3[PTZY]
|
||||||
|
) = _ECTwistDoubleJacobian(pt1xx, pt1xy, pt1yx, pt1yy, pt1zx, pt1zy);
|
||||||
|
return pt3;
|
||||||
|
}
|
||||||
|
(
|
||||||
|
pt3[PTXX], pt3[PTXY],
|
||||||
|
pt3[PTYX], pt3[PTYY],
|
||||||
|
pt3[PTZX], pt3[PTZY]
|
||||||
|
) = (
|
||||||
|
1, 0,
|
||||||
|
1, 0,
|
||||||
|
0, 0
|
||||||
|
);
|
||||||
|
return pt3;
|
||||||
|
}
|
||||||
|
|
||||||
|
(pt2zx, pt2zy) = _FQ2Mul(pt1zx, pt1zy, pt2zx, pt2zy); // W = z1 * z2
|
||||||
|
(pt1xx, pt1xy) = _FQ2Sub(pt2yx, pt2yy, pt3[PTYX], pt3[PTYY]); // U = U1 - U2
|
||||||
|
(pt1yx, pt1yy) = _FQ2Sub(pt2xx, pt2xy, pt3[PTZX], pt3[PTZY]); // V = V1 - V2
|
||||||
|
(pt1zx, pt1zy) = _FQ2Mul(pt1yx, pt1yy, pt1yx, pt1yy); // V_squared = V * V
|
||||||
|
(pt2yx, pt2yy) = _FQ2Mul(pt1zx, pt1zy, pt3[PTZX], pt3[PTZY]); // V_squared_times_V2 = V_squared * V2
|
||||||
|
(pt1zx, pt1zy) = _FQ2Mul(pt1zx, pt1zy, pt1yx, pt1yy); // V_cubed = V * V_squared
|
||||||
|
(pt3[PTZX], pt3[PTZY]) = _FQ2Mul(pt1zx, pt1zy, pt2zx, pt2zy); // newz = V_cubed * W
|
||||||
|
(pt2xx, pt2xy) = _FQ2Mul(pt1xx, pt1xy, pt1xx, pt1xy); // U * U
|
||||||
|
(pt2xx, pt2xy) = _FQ2Mul(pt2xx, pt2xy, pt2zx, pt2zy); // U * U * W
|
||||||
|
(pt2xx, pt2xy) = _FQ2Sub(pt2xx, pt2xy, pt1zx, pt1zy); // U * U * W - V_cubed
|
||||||
|
(pt2zx, pt2zy) = _FQ2Muc(pt2yx, pt2yy, 2); // 2 * V_squared_times_V2
|
||||||
|
(pt2xx, pt2xy) = _FQ2Sub(pt2xx, pt2xy, pt2zx, pt2zy); // A = U * U * W - V_cubed - 2 * V_squared_times_V2
|
||||||
|
(pt3[PTXX], pt3[PTXY]) = _FQ2Mul(pt1yx, pt1yy, pt2xx, pt2xy); // newx = V * A
|
||||||
|
(pt1yx, pt1yy) = _FQ2Sub(pt2yx, pt2yy, pt2xx, pt2xy); // V_squared_times_V2 - A
|
||||||
|
(pt1yx, pt1yy) = _FQ2Mul(pt1xx, pt1xy, pt1yx, pt1yy); // U * (V_squared_times_V2 - A)
|
||||||
|
(pt1xx, pt1xy) = _FQ2Mul(pt1zx, pt1zy, pt3[PTYX], pt3[PTYY]); // V_cubed * U2
|
||||||
|
(pt3[PTYX], pt3[PTYY]) = _FQ2Sub(pt1yx, pt1yy, pt1xx, pt1xy); // newy = U * (V_squared_times_V2 - A) - V_cubed * U2
|
||||||
|
}
|
||||||
|
|
||||||
|
function _ECTwistDoubleJacobian(
|
||||||
|
uint256 pt1xx, uint256 pt1xy,
|
||||||
|
uint256 pt1yx, uint256 pt1yy,
|
||||||
|
uint256 pt1zx, uint256 pt1zy
|
||||||
|
) internal pure returns(
|
||||||
|
uint256 pt2xx, uint256 pt2xy,
|
||||||
|
uint256 pt2yx, uint256 pt2yy,
|
||||||
|
uint256 pt2zx, uint256 pt2zy
|
||||||
|
) {
|
||||||
|
(pt2xx, pt2xy) = _FQ2Muc(pt1xx, pt1xy, 3); // 3 * x
|
||||||
|
(pt2xx, pt2xy) = _FQ2Mul(pt2xx, pt2xy, pt1xx, pt1xy); // W = 3 * x * x
|
||||||
|
(pt1zx, pt1zy) = _FQ2Mul(pt1yx, pt1yy, pt1zx, pt1zy); // S = y * z
|
||||||
|
(pt2yx, pt2yy) = _FQ2Mul(pt1xx, pt1xy, pt1yx, pt1yy); // x * y
|
||||||
|
(pt2yx, pt2yy) = _FQ2Mul(pt2yx, pt2yy, pt1zx, pt1zy); // B = x * y * S
|
||||||
|
(pt1xx, pt1xy) = _FQ2Mul(pt2xx, pt2xy, pt2xx, pt2xy); // W * W
|
||||||
|
(pt2zx, pt2zy) = _FQ2Muc(pt2yx, pt2yy, 8); // 8 * B
|
||||||
|
(pt1xx, pt1xy) = _FQ2Sub(pt1xx, pt1xy, pt2zx, pt2zy); // H = W * W - 8 * B
|
||||||
|
(pt2zx, pt2zy) = _FQ2Mul(pt1zx, pt1zy, pt1zx, pt1zy); // S_squared = S * S
|
||||||
|
(pt2yx, pt2yy) = _FQ2Muc(pt2yx, pt2yy, 4); // 4 * B
|
||||||
|
(pt2yx, pt2yy) = _FQ2Sub(pt2yx, pt2yy, pt1xx, pt1xy); // 4 * B - H
|
||||||
|
(pt2yx, pt2yy) = _FQ2Mul(pt2yx, pt2yy, pt2xx, pt2xy); // W * (4 * B - H)
|
||||||
|
(pt2xx, pt2xy) = _FQ2Muc(pt1yx, pt1yy, 8); // 8 * y
|
||||||
|
(pt2xx, pt2xy) = _FQ2Mul(pt2xx, pt2xy, pt1yx, pt1yy); // 8 * y * y
|
||||||
|
(pt2xx, pt2xy) = _FQ2Mul(pt2xx, pt2xy, pt2zx, pt2zy); // 8 * y * y * S_squared
|
||||||
|
(pt2yx, pt2yy) = _FQ2Sub(pt2yx, pt2yy, pt2xx, pt2xy); // newy = W * (4 * B - H) - 8 * y * y * S_squared
|
||||||
|
(pt2xx, pt2xy) = _FQ2Muc(pt1xx, pt1xy, 2); // 2 * H
|
||||||
|
(pt2xx, pt2xy) = _FQ2Mul(pt2xx, pt2xy, pt1zx, pt1zy); // newx = 2 * H * S
|
||||||
|
(pt2zx, pt2zy) = _FQ2Mul(pt1zx, pt1zy, pt2zx, pt2zy); // S * S_squared
|
||||||
|
(pt2zx, pt2zy) = _FQ2Muc(pt2zx, pt2zy, 8); // newz = 8 * S * S_squared
|
||||||
|
}
|
||||||
|
|
||||||
|
function _ECTwistMulJacobian(
|
||||||
|
uint256 d,
|
||||||
|
uint256 pt1xx, uint256 pt1xy,
|
||||||
|
uint256 pt1yx, uint256 pt1yy,
|
||||||
|
uint256 pt1zx, uint256 pt1zy
|
||||||
|
) internal pure returns(uint256[6] memory pt2) {
|
||||||
|
while (d != 0) {
|
||||||
|
if ((d & 1) != 0) {
|
||||||
|
pt2 = _ECTwistAddJacobian(
|
||||||
|
pt2[PTXX], pt2[PTXY],
|
||||||
|
pt2[PTYX], pt2[PTYY],
|
||||||
|
pt2[PTZX], pt2[PTZY],
|
||||||
|
pt1xx, pt1xy,
|
||||||
|
pt1yx, pt1yy,
|
||||||
|
pt1zx, pt1zy);
|
||||||
|
}
|
||||||
|
(
|
||||||
|
pt1xx, pt1xy,
|
||||||
|
pt1yx, pt1yy,
|
||||||
|
pt1zx, pt1zy
|
||||||
|
) = _ECTwistDoubleJacobian(
|
||||||
|
pt1xx, pt1xy,
|
||||||
|
pt1yx, pt1yy,
|
||||||
|
pt1zx, pt1zy
|
||||||
|
);
|
||||||
|
|
||||||
|
d = d / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This file is MIT Licensed.
|
||||||
|
//
|
||||||
|
// Copyright 2017 Christian Reitwiessner
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
pragma solidity ^0.5.0;
|
||||||
|
library Pairing {
|
||||||
|
struct G1Point {
|
||||||
|
uint X;
|
||||||
|
uint Y;
|
||||||
|
}
|
||||||
|
// Encoding of field elements is: X[0] * z + X[1]
|
||||||
|
struct G2Point {
|
||||||
|
uint[2] X;
|
||||||
|
uint[2] Y;
|
||||||
|
}
|
||||||
|
/// @return the generator of G1
|
||||||
|
function P1() pure internal returns (G1Point memory) {
|
||||||
|
return G1Point(1, 2);
|
||||||
|
}
|
||||||
|
/// @return the generator of G2
|
||||||
|
function P2() pure internal returns (G2Point memory) {
|
||||||
|
return G2Point(
|
||||||
|
[11559732032986387107991004021392285783925812861821192530917403151452391805634,
|
||||||
|
10857046999023057135944570762232829481370756359578518086990519993285655852781],
|
||||||
|
[4082367875863433681332203403145435568316851327593401208105741076214120093531,
|
||||||
|
8495653923123431417604973247489272438418190587263600148770280649306958101930]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/// @return the negation of p, i.e. p.addition(p.negate()) should be zero.
|
||||||
|
function negate(G1Point memory p) pure internal returns (G1Point memory) {
|
||||||
|
// The prime q in the base field F_q for G1
|
||||||
|
uint q = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
|
||||||
|
if (p.X == 0 && p.Y == 0)
|
||||||
|
return G1Point(0, 0);
|
||||||
|
return G1Point(p.X, q - (p.Y % q));
|
||||||
|
}
|
||||||
|
/// @return the sum of two points of G1
|
||||||
|
function addition(G1Point memory p1, G1Point memory p2) internal returns (G1Point memory r) {
|
||||||
|
uint[4] memory input;
|
||||||
|
input[0] = p1.X;
|
||||||
|
input[1] = p1.Y;
|
||||||
|
input[2] = p2.X;
|
||||||
|
input[3] = p2.Y;
|
||||||
|
bool success;
|
||||||
|
assembly {
|
||||||
|
success := call(sub(gas, 2000), 6, 0, input, 0xc0, r, 0x60)
|
||||||
|
// Use "invalid" to make gas estimation work
|
||||||
|
switch success case 0 { invalid() }
|
||||||
|
}
|
||||||
|
require(success);
|
||||||
|
}
|
||||||
|
/// @return the sum of two points of G2
|
||||||
|
function addition(G2Point memory p1, G2Point memory p2) internal pure returns (G2Point memory r) {
|
||||||
|
(r.X[1], r.X[0], r.Y[1], r.Y[0]) = BN256G2.ECTwistAdd(p1.X[1],p1.X[0],p1.Y[1],p1.Y[0],p2.X[1],p2.X[0],p2.Y[1],p2.Y[0]);
|
||||||
|
}
|
||||||
|
/// @return the product of a point on G1 and a scalar, i.e.
|
||||||
|
/// p == p.scalar_mul(1) and p.addition(p) == p.scalar_mul(2) for all points p.
|
||||||
|
function scalar_mul(G1Point memory p, uint s) internal returns (G1Point memory r) {
|
||||||
|
uint[3] memory input;
|
||||||
|
input[0] = p.X;
|
||||||
|
input[1] = p.Y;
|
||||||
|
input[2] = s;
|
||||||
|
bool success;
|
||||||
|
assembly {
|
||||||
|
success := call(sub(gas, 2000), 7, 0, input, 0x80, r, 0x60)
|
||||||
|
// Use "invalid" to make gas estimation work
|
||||||
|
switch success case 0 { invalid() }
|
||||||
|
}
|
||||||
|
require (success);
|
||||||
|
}
|
||||||
|
/// @return the result of computing the pairing check
|
||||||
|
/// e(p1[0], p2[0]) * .... * e(p1[n], p2[n]) == 1
|
||||||
|
/// For example pairing([P1(), P1().negate()], [P2(), P2()]) should
|
||||||
|
/// return true.
|
||||||
|
function pairing(G1Point[] memory p1, G2Point[] memory p2) internal returns (bool) {
|
||||||
|
require(p1.length == p2.length);
|
||||||
|
uint elements = p1.length;
|
||||||
|
uint inputSize = elements * 6;
|
||||||
|
uint[] memory input = new uint[](inputSize);
|
||||||
|
for (uint i = 0; i < elements; i++)
|
||||||
|
{
|
||||||
|
input[i * 6 + 0] = p1[i].X;
|
||||||
|
input[i * 6 + 1] = p1[i].Y;
|
||||||
|
input[i * 6 + 2] = p2[i].X[0];
|
||||||
|
input[i * 6 + 3] = p2[i].X[1];
|
||||||
|
input[i * 6 + 4] = p2[i].Y[0];
|
||||||
|
input[i * 6 + 5] = p2[i].Y[1];
|
||||||
|
}
|
||||||
|
uint[1] memory out;
|
||||||
|
bool success;
|
||||||
|
assembly {
|
||||||
|
success := call(sub(gas, 2000), 8, 0, add(input, 0x20), mul(inputSize, 0x20), out, 0x20)
|
||||||
|
// Use "invalid" to make gas estimation work
|
||||||
|
switch success case 0 { invalid() }
|
||||||
|
}
|
||||||
|
require(success);
|
||||||
|
return out[0] != 0;
|
||||||
|
}
|
||||||
|
/// Convenience method for a pairing check for two pairs.
|
||||||
|
function pairingProd2(G1Point memory a1, G2Point memory a2, G1Point memory b1, G2Point memory b2) internal returns (bool) {
|
||||||
|
G1Point[] memory p1 = new G1Point[](2);
|
||||||
|
G2Point[] memory p2 = new G2Point[](2);
|
||||||
|
p1[0] = a1;
|
||||||
|
p1[1] = b1;
|
||||||
|
p2[0] = a2;
|
||||||
|
p2[1] = b2;
|
||||||
|
return pairing(p1, p2);
|
||||||
|
}
|
||||||
|
/// Convenience method for a pairing check for three pairs.
|
||||||
|
function pairingProd3(
|
||||||
|
G1Point memory a1, G2Point memory a2,
|
||||||
|
G1Point memory b1, G2Point memory b2,
|
||||||
|
G1Point memory c1, G2Point memory c2
|
||||||
|
) internal returns (bool) {
|
||||||
|
G1Point[] memory p1 = new G1Point[](3);
|
||||||
|
G2Point[] memory p2 = new G2Point[](3);
|
||||||
|
p1[0] = a1;
|
||||||
|
p1[1] = b1;
|
||||||
|
p1[2] = c1;
|
||||||
|
p2[0] = a2;
|
||||||
|
p2[1] = b2;
|
||||||
|
p2[2] = c2;
|
||||||
|
return pairing(p1, p2);
|
||||||
|
}
|
||||||
|
/// Convenience method for a pairing check for four pairs.
|
||||||
|
function pairingProd4(
|
||||||
|
G1Point memory a1, G2Point memory a2,
|
||||||
|
G1Point memory b1, G2Point memory b2,
|
||||||
|
G1Point memory c1, G2Point memory c2,
|
||||||
|
G1Point memory d1, G2Point memory d2
|
||||||
|
) internal returns (bool) {
|
||||||
|
G1Point[] memory p1 = new G1Point[](4);
|
||||||
|
G2Point[] memory p2 = new G2Point[](4);
|
||||||
|
p1[0] = a1;
|
||||||
|
p1[1] = b1;
|
||||||
|
p1[2] = c1;
|
||||||
|
p1[3] = d1;
|
||||||
|
p2[0] = a2;
|
||||||
|
p2[1] = b2;
|
||||||
|
p2[2] = c2;
|
||||||
|
p2[3] = d2;
|
||||||
|
return pairing(p1, p2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract Verifier {
|
||||||
|
using Pairing for *;
|
||||||
|
struct VerifyingKey {
|
||||||
|
Pairing.G1Point a;
|
||||||
|
Pairing.G2Point b;
|
||||||
|
Pairing.G2Point gamma;
|
||||||
|
Pairing.G2Point delta;
|
||||||
|
Pairing.G1Point[] gammaABC;
|
||||||
|
}
|
||||||
|
struct Proof {
|
||||||
|
Pairing.G1Point A;
|
||||||
|
Pairing.G2Point B;
|
||||||
|
Pairing.G1Point C;
|
||||||
|
}
|
||||||
|
function verifyingKey() pure internal returns (VerifyingKey memory vk) {
|
||||||
|
vk.a = Pairing.G1Point(uint256(0x2c2cb1812fb05d4f31791c66ff995d756b73162f3bb016a5c114befe5cd7903e), uint256(0x0abc1f8a5d49cb2dbda15b5a8b7cd81bec0a581e7c2e16f79446af2d2f5340c0));
|
||||||
|
vk.b = Pairing.G2Point([uint256(0x071644533641f7e3acb8606328c591853b2bc27253f29bc11d008a67996fc07f), uint256(0x26ca2720c073a085d8452aef541aac280879971c09b199a6e0f21bf36745e1d8)], [uint256(0x0b17104896ed701b6d52279992c1f20d558bc0de8284087645633bf3ca1a0c98), uint256(0x2c10eb5b6c0ca42ede8cdcf60642c6dca040abe9abb8294948f4aa0be59a0d42)]);
|
||||||
|
vk.gamma = Pairing.G2Point([uint256(0x0afbadec2ecafdd62278c7021095660f5786f445c040e628e4ed1a410454b582), uint256(0x038aa6f04ee254a97e2b75ea1f30e36785b6cde4dfd3a2371e058ce089b9ad51)], [uint256(0x077720bb216fb0051c5e153c1bd9aa36a678173b9c13e8d3a83cb5a75ca36948), uint256(0x1f9b58e9abde296abc3c3bab8fb0be2a4f497d8e5d9d463997d316e9cc558a7d)]);
|
||||||
|
vk.delta = Pairing.G2Point([uint256(0x16526b9b519fa544d3f9ce35a5f4afa7aac0aa4dd54421c4864b3fe8d2415f41), uint256(0x24e24f35699cca59416a7f43c0e93e148b2353440978994df8f81603a46f8839)], [uint256(0x299f9f09280310aedf63055c5ce76feb16557ed7ff11ba35adad718102b5651a), uint256(0x0c4a2fc4db77ef6c19511b2ffb369981cebbffcb5337a671e1ad678b460ac5e9)]);
|
||||||
|
vk.gammaABC = new Pairing.G1Point[](6);
|
||||||
|
vk.gammaABC[0] = Pairing.G1Point(uint256(0x2f910078bf5092a7ea9d3ce750b7b5399b101509adb8017a6e12fa1a4c638d5b), uint256(0x0b76454d4300571c8d86714b4e5ef095688b51080e674425e8e5edb201f64128));
|
||||||
|
vk.gammaABC[1] = Pairing.G1Point(uint256(0x2922a307d415f70c8df6f14b664c46df12a89cd3a89cf7960663907bf9483b68), uint256(0x1bc30a719ddc0099f557cca61a0687766e6275fc98b185baa77735b93bf2a0ef));
|
||||||
|
vk.gammaABC[2] = Pairing.G1Point(uint256(0x0201dc8c8faa3dc5b8eec85f029d2482bf11a6b46d5f8e4d9f17d41ac3e4c9c1), uint256(0x0a1d62c1142c92dff75b53d5a572fd7a013708118acf10f718c61fb6226160f5));
|
||||||
|
vk.gammaABC[3] = Pairing.G1Point(uint256(0x02276f5896610ec573cd6cdc6e47c69e756362d2b1b1c51c5ab90ac838d1a898), uint256(0x13fa6cc7987f4f3118f6ee3ab85dcd708df17050636d487914077348e0af05b1));
|
||||||
|
vk.gammaABC[4] = Pairing.G1Point(uint256(0x0778ae3718fd7f48564bc33b60ec4f39a238e97cb4cc0bbd4ff37119942ff7d4), uint256(0x0282e96481744ee21524d802b3e524bf0596bb37bb63e5ed37c77fc1a5c8e89d));
|
||||||
|
vk.gammaABC[5] = Pairing.G1Point(uint256(0x1ce40e230695bdab7d2ff7ebcf6e6fedb68d1a320238fc98845b151ae4ee3b54), uint256(0x0feac76664d37b57a4ea5a774252bb82355294e55635a8aeb7a1327405d27128));
|
||||||
|
}
|
||||||
|
function verify(uint[] memory input, Proof memory proof) internal returns (uint) {
|
||||||
|
VerifyingKey memory vk = verifyingKey();
|
||||||
|
require(input.length + 1 == vk.gammaABC.length);
|
||||||
|
// Compute the linear combination vk_x
|
||||||
|
Pairing.G1Point memory vk_x = Pairing.G1Point(0, 0);
|
||||||
|
for (uint i = 0; i < input.length; i++)
|
||||||
|
vk_x = Pairing.addition(vk_x, Pairing.scalar_mul(vk.gammaABC[i + 1], input[i]));
|
||||||
|
vk_x = Pairing.addition(vk_x, vk.gammaABC[0]);
|
||||||
|
if(!Pairing.pairingProd4(
|
||||||
|
proof.A, proof.B,
|
||||||
|
Pairing.negate(vk_x), vk.gamma,
|
||||||
|
Pairing.negate(proof.C), vk.delta,
|
||||||
|
Pairing.negate(vk.a), vk.b)) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
event Verified(string s);
|
||||||
|
function verifyTx(
|
||||||
|
uint[2] memory a,
|
||||||
|
uint[2][2] memory b,
|
||||||
|
uint[2] memory c,
|
||||||
|
uint[5] memory input
|
||||||
|
) public returns (bool r) {
|
||||||
|
Proof memory proof;
|
||||||
|
proof.A = Pairing.G1Point(a[0], a[1]);
|
||||||
|
proof.B = Pairing.G2Point([b[0][0], b[0][1]], [b[1][0], b[1][1]]);
|
||||||
|
proof.C = Pairing.G1Point(c[0], c[1]);
|
||||||
|
uint[] memory inputValues = new uint[](input.length);
|
||||||
|
for(uint i = 0; i < input.length; i++){
|
||||||
|
inputValues[i] = input[i];
|
||||||
|
}
|
||||||
|
if (verify(inputValues, proof) == 0) {
|
||||||
|
emit Verified("Transaction successfully verified.");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
truffle/contracts/VerifierProxy.sol
Normal file
23
truffle/contracts/VerifierProxy.sol
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
pragma solidity ^0.5.4;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "./IVerifier.sol";
|
||||||
|
import "./Verifier.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract VerifierProxy is IVerifier {
|
||||||
|
Verifier internal verifier;
|
||||||
|
|
||||||
|
constructor(Verifier ver) public {
|
||||||
|
verifier = ver;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Truffle gives `UnimplementedFeatureError: Encoding struct from calldata is not yet supported.`
|
||||||
|
// that's why function is public and uses memory location modifier
|
||||||
|
function isValid(Data memory data, Proof memory proof) public returns (bool) {
|
||||||
|
bytes memory payload = abi.encodeWithSelector(verifier.verifyTx.selector, proof, data);
|
||||||
|
(bool success, bytes memory r) = address(verifier).call(payload);
|
||||||
|
require(success);
|
||||||
|
return abi.decode(r, (bool));
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,16 @@
|
|||||||
|
var Verifier = artifacts.require('Verifier');
|
||||||
|
var VerifierProxy = artifacts.require('VerifierProxy');
|
||||||
var Lazy = artifacts.require('Lazy');
|
var Lazy = artifacts.require('Lazy');
|
||||||
|
|
||||||
module.exports = function(deployer) {
|
const proof1 = [["0x12d0dbcfc1da3ea29bc017288fceea3929401f4f12dbd0bba73781420d31aa2d","0x2811c1eaa63f4a804951bd7f994cbb6bea9df64591793b8392400e8756d1bca7"],[["0x04c33f68e1bd55be0928b086c647debcdf7aa0e3c3efc6a8efbc2596a77a0e67","0x17e7392e0e3ec2b5701e675e6e0569330d03ffffe476fc8d63cfeaa0ba1c8a97"],["0x2fc402693a54cd1b176abeed209674f2f12ced1496c6ce27ba8cf16903daa4cc","0x2c47efba3f4f260da643bb6427d08b551bb3446537d6ac4857d611be2355a446"]],["0x04d40f14694092d0f70890a20492b2b68e7eaabdcee744e519678d687c9c3ed0","0x28de140e393154b0e70b3ef12806af963a4a33b45c24e7864391093b6028fa2b"]]
|
||||||
deployer.deploy(Lazy);
|
const input1 = [["0x00000000000000000000000000000000c6481e22c5ff4164af680b8cfaa5e8ed","0x000000000000000000000000000000003120eeff89c4f307c4a6faaae059ce10","0x000000000000000000000000000000005b6d7d198c48c17c9540d29275a04662","0x00000000000000000000000000000000f7a9aa434629a33c84eec3e16e196f27","0x0000000000000000000000000000000000000000000000000000000000000001"]]
|
||||||
}
|
module.exports = async function(deployer, network, accounts) {
|
||||||
|
deployer.then(async() => {
|
||||||
|
await deployer.deploy(Verifier)
|
||||||
|
await deployer.deploy(VerifierProxy, Verifier.address)
|
||||||
|
var contract = await deployer.deploy(Lazy, VerifierProxy.address)
|
||||||
|
await contract.submit([[1,2,3,4,5]],[[1,2],[[3,4],[5,6]],[7,8]])
|
||||||
|
await contract.submit(input1,proof1)
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user