mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-12-26 11:45:00 +03:00
Merge branch 'master' of github.com:AleoHQ/leo into fix/synthesis-error-stack-overflow
This commit is contained in:
commit
6631da0c7e
342
Cargo.lock
generated
342
Cargo.lock
generated
@ -92,6 +92,30 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.53.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c72a978d268b1d70b0e963217e60fdabd9523a941457a6c42a7315d15c7e89e5"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cexpr",
|
||||
"cfg-if",
|
||||
"clang-sys",
|
||||
"clap",
|
||||
"env_logger",
|
||||
"lazy_static",
|
||||
"lazycell",
|
||||
"log",
|
||||
"peeking_take_while",
|
||||
"proc-macro2 1.0.19",
|
||||
"quote 1.0.7",
|
||||
"regex",
|
||||
"rustc-hash",
|
||||
"shlex",
|
||||
"which",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
@ -128,7 +152,7 @@ version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
|
||||
dependencies = [
|
||||
"generic-array 0.14.3",
|
||||
"generic-array 0.14.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -211,6 +235,18 @@ name = "cc"
|
||||
version = "1.0.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9a06fb2e53271d7c279ec1efea6ab691c35a2ae67ec0d91d7acec0caf13b518"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cexpr"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
@ -220,9 +256,9 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.13"
|
||||
version = "0.4.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c74d84029116787153e02106bf53e66828452a4b325cc8652b788b5967c0a0b6"
|
||||
checksum = "942f72db697d8767c22d46a598e01f2d3b475501ea43d0db4f16d90259182d0b"
|
||||
dependencies = [
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
@ -239,6 +275,17 @@ dependencies = [
|
||||
"envmnt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "0.29.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe6837df1d5cba2397b835c8530f51723267e16abbf83892e9e5af4f0e5dd10a"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"libc",
|
||||
"libloading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.33.3"
|
||||
@ -254,6 +301,15 @@ dependencies = [
|
||||
"vec_map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cloudabi"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colored"
|
||||
version = "2.0.0"
|
||||
@ -412,6 +468,36 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "curl"
|
||||
version = "0.4.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9447ad28eee2a5cfb031c329d46bef77487244fff6a724b378885b8691a35f78"
|
||||
dependencies = [
|
||||
"curl-sys",
|
||||
"libc",
|
||||
"openssl-probe",
|
||||
"openssl-sys",
|
||||
"schannel",
|
||||
"socket2",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "curl-sys"
|
||||
version = "0.4.34+curl-7.71.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad4eff0be6985b7e709f64b5a541f700e9ad1407190a29f4884319eb663ed1d6"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"libz-sys",
|
||||
"openssl-sys",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derivative"
|
||||
version = "2.1.1"
|
||||
@ -420,7 +506,7 @@ checksum = "cb582b60359da160a9477ee80f15c8d784c477e69c217ef2cdd4169c24ea380f"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.19",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.36",
|
||||
"syn 1.0.38",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -438,7 +524,7 @@ version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
|
||||
dependencies = [
|
||||
"generic-array 0.14.3",
|
||||
"generic-array 0.14.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -449,9 +535,9 @@ checksum = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.5.3"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
|
||||
checksum = "cd56b59865bce947ac5958779cfa508f6c3b9497cc762b7e24a12d11ccde2c4f"
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
@ -503,7 +589,7 @@ checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.19",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.36",
|
||||
"syn 1.0.38",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@ -677,9 +763,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.3"
|
||||
version = "0.14.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60fb4bb6bba52f78a471264d9a3b7d026cc0af47b22cd2cffbc0b787ca003e63"
|
||||
checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
@ -711,6 +797,12 @@ version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724"
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.2.6"
|
||||
@ -738,9 +830,9 @@ checksum = "d36fab90f82edc3c747f9d438e06cf0a491055896f2a279638bb5beed6c40177"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34f595585f103464d8d2f6e9864682d74c1601fed5e07d62b1c9058dba8246fb"
|
||||
checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
@ -846,9 +938,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.5.0"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b88cd59ee5f71fea89a62248fc8f387d44400cefe05ef548466d61ced9029a7"
|
||||
checksum = "86b45e59b16c76b11bf9738fd5d38879d3bd28ad292d7b313608becb17ae2df9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
@ -874,6 +966,12 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b141fdc7836c525d4d594027d318c84161ca17aaf8113ab1f81ab93ae897485"
|
||||
|
||||
[[package]]
|
||||
name = "iovec"
|
||||
version = "0.1.4"
|
||||
@ -913,6 +1011,15 @@ version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.44"
|
||||
@ -970,6 +1077,7 @@ dependencies = [
|
||||
"leo-gadgets",
|
||||
"leo-input",
|
||||
"leo-package",
|
||||
"leo-state",
|
||||
"log",
|
||||
"notify",
|
||||
"num-bigint",
|
||||
@ -1014,6 +1122,8 @@ dependencies = [
|
||||
"leo-ast",
|
||||
"leo-gadgets",
|
||||
"leo-input",
|
||||
"leo-package",
|
||||
"leo-state",
|
||||
"leo-typed",
|
||||
"log",
|
||||
"num-bigint",
|
||||
@ -1077,6 +1187,25 @@ dependencies = [
|
||||
"zip",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "leo-state"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"leo-input",
|
||||
"leo-typed",
|
||||
"rand",
|
||||
"rand_xorshift",
|
||||
"snarkos-algorithms",
|
||||
"snarkos-curves",
|
||||
"snarkos-dpc",
|
||||
"snarkos-errors",
|
||||
"snarkos-models",
|
||||
"snarkos-objects",
|
||||
"snarkos-storage",
|
||||
"snarkos-utilities",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "leo-typed"
|
||||
version = "0.1.0"
|
||||
@ -1097,6 +1226,49 @@ version = "0.2.74"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2f02823cf78b754822df5f7f268fb59822e7296276d3e069d8e8cb26a14bd10"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "librocksdb-sys"
|
||||
version = "6.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "883213ae3d09bfc3d104aefe94b25ebb183b6f4d3a515b23b14817e1f4854005"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"cc",
|
||||
"glob",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libz-sys"
|
||||
version = "1.0.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ca8894883d250240341478bf987467332fbdd5da5c42426c69a8f93dbc302f2"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28247cc5a5be2f05fbcd76dd0cf2c7d3b5400cb978a28042abcd4fa0b3f8261c"
|
||||
dependencies = [
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.11"
|
||||
@ -1242,6 +1414,16 @@ version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab250442c86f1850815b5d268639dff018c0627022bc1940eb2d642ca1ce12f0"
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "5.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "notify"
|
||||
version = "4.0.15"
|
||||
@ -1363,6 +1545,38 @@ dependencies = [
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733"
|
||||
dependencies = [
|
||||
"instant",
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cloudabi",
|
||||
"instant",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "peeking_take_while"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.1.0"
|
||||
@ -1411,7 +1625,7 @@ dependencies = [
|
||||
"pest_meta",
|
||||
"proc-macro2 1.0.19",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.36",
|
||||
"syn 1.0.38",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1442,7 +1656,7 @@ checksum = "2c0e815c3ee9a031fdf5af21c10aa17c573c9c6a566328d99e3936c34e36461f"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.19",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.36",
|
||||
"syn 1.0.38",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1682,12 +1896,28 @@ dependencies = [
|
||||
"winreg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rocksdb"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12069b106981c6103d3eab7dd1c86751482d0779a520b7c14954c8b586c1e643"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"librocksdb-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
@ -1805,7 +2035,7 @@ checksum = "609feed1d0a73cc36a0182a840a9b37b4a82f0b1150369f0536a9e3f2a31dc48"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.19",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.36",
|
||||
"syn 1.0.38",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1856,6 +2086,12 @@ dependencies = [
|
||||
"opaque-debug 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
|
||||
|
||||
[[package]]
|
||||
name = "single"
|
||||
version = "1.0.0"
|
||||
@ -1873,14 +2109,14 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.4.1"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3757cb9d89161a2f24e1cf78efa0c1fcff485d18e3f55e0aa3480824ddaa0f3f"
|
||||
checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252"
|
||||
|
||||
[[package]]
|
||||
name = "snarkos-algorithms"
|
||||
version = "0.8.0"
|
||||
source = "git+ssh://git@github.com/AleoHQ/snarkOS.git#a0d7afb4398abc9b2eb7980811b8b9b808df4019"
|
||||
source = "git+ssh://git@github.com/AleoHQ/snarkOS.git#57fef6a27035419e0b22fee5b72ca6639e15e1ac"
|
||||
dependencies = [
|
||||
"blake2",
|
||||
"derivative",
|
||||
@ -1900,7 +2136,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "snarkos-curves"
|
||||
version = "0.8.0"
|
||||
source = "git+ssh://git@github.com/AleoHQ/snarkOS.git#a0d7afb4398abc9b2eb7980811b8b9b808df4019"
|
||||
source = "git+ssh://git@github.com/AleoHQ/snarkOS.git#57fef6a27035419e0b22fee5b72ca6639e15e1ac"
|
||||
dependencies = [
|
||||
"derivative",
|
||||
"rand",
|
||||
@ -1915,17 +2151,17 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "snarkos-derives"
|
||||
version = "0.1.0"
|
||||
source = "git+ssh://git@github.com/AleoHQ/snarkOS.git#a0d7afb4398abc9b2eb7980811b8b9b808df4019"
|
||||
source = "git+ssh://git@github.com/AleoHQ/snarkOS.git#57fef6a27035419e0b22fee5b72ca6639e15e1ac"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.19",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.36",
|
||||
"syn 1.0.38",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "snarkos-dpc"
|
||||
version = "0.8.0"
|
||||
source = "git+ssh://git@github.com/AleoHQ/snarkOS.git#a0d7afb4398abc9b2eb7980811b8b9b808df4019"
|
||||
source = "git+ssh://git@github.com/AleoHQ/snarkOS.git#57fef6a27035419e0b22fee5b72ca6639e15e1ac"
|
||||
dependencies = [
|
||||
"blake2",
|
||||
"derivative",
|
||||
@ -1946,20 +2182,23 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "snarkos-errors"
|
||||
version = "0.8.0"
|
||||
source = "git+ssh://git@github.com/AleoHQ/snarkOS.git#a0d7afb4398abc9b2eb7980811b8b9b808df4019"
|
||||
source = "git+ssh://git@github.com/AleoHQ/snarkOS.git#57fef6a27035419e0b22fee5b72ca6639e15e1ac"
|
||||
dependencies = [
|
||||
"base58",
|
||||
"bech32",
|
||||
"bincode",
|
||||
"curl",
|
||||
"hex",
|
||||
"jsonrpc-core",
|
||||
"rocksdb",
|
||||
"thiserror",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "snarkos-gadgets"
|
||||
version = "0.8.0"
|
||||
source = "git+ssh://git@github.com/AleoHQ/snarkOS.git#a0d7afb4398abc9b2eb7980811b8b9b808df4019"
|
||||
source = "git+ssh://git@github.com/AleoHQ/snarkOS.git#57fef6a27035419e0b22fee5b72ca6639e15e1ac"
|
||||
dependencies = [
|
||||
"derivative",
|
||||
"digest 0.8.1",
|
||||
@ -1974,7 +2213,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "snarkos-models"
|
||||
version = "0.8.0"
|
||||
source = "git+ssh://git@github.com/AleoHQ/snarkOS.git#a0d7afb4398abc9b2eb7980811b8b9b808df4019"
|
||||
source = "git+ssh://git@github.com/AleoHQ/snarkOS.git#57fef6a27035419e0b22fee5b72ca6639e15e1ac"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"derivative",
|
||||
@ -1990,7 +2229,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "snarkos-objects"
|
||||
version = "0.8.0"
|
||||
source = "git+ssh://git@github.com/AleoHQ/snarkOS.git#a0d7afb4398abc9b2eb7980811b8b9b808df4019"
|
||||
source = "git+ssh://git@github.com/AleoHQ/snarkOS.git#57fef6a27035419e0b22fee5b72ca6639e15e1ac"
|
||||
dependencies = [
|
||||
"base58",
|
||||
"bech32",
|
||||
@ -2011,8 +2250,9 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "snarkos-parameters"
|
||||
version = "0.8.0"
|
||||
source = "git+ssh://git@github.com/AleoHQ/snarkOS.git#a0d7afb4398abc9b2eb7980811b8b9b808df4019"
|
||||
source = "git+ssh://git@github.com/AleoHQ/snarkOS.git#57fef6a27035419e0b22fee5b72ca6639e15e1ac"
|
||||
dependencies = [
|
||||
"curl",
|
||||
"hex",
|
||||
"snarkos-algorithms",
|
||||
"snarkos-errors",
|
||||
@ -2023,12 +2263,31 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "snarkos-profiler"
|
||||
version = "0.8.0"
|
||||
source = "git+ssh://git@github.com/AleoHQ/snarkOS.git#a0d7afb4398abc9b2eb7980811b8b9b808df4019"
|
||||
source = "git+ssh://git@github.com/AleoHQ/snarkOS.git#57fef6a27035419e0b22fee5b72ca6639e15e1ac"
|
||||
|
||||
[[package]]
|
||||
name = "snarkos-storage"
|
||||
version = "0.8.0"
|
||||
source = "git+ssh://git@github.com/AleoHQ/snarkOS.git#57fef6a27035419e0b22fee5b72ca6639e15e1ac"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"hex",
|
||||
"parking_lot",
|
||||
"rand",
|
||||
"rocksdb",
|
||||
"serde",
|
||||
"snarkos-algorithms",
|
||||
"snarkos-errors",
|
||||
"snarkos-models",
|
||||
"snarkos-objects",
|
||||
"snarkos-parameters",
|
||||
"snarkos-utilities",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "snarkos-utilities"
|
||||
version = "0.8.0"
|
||||
source = "git+ssh://git@github.com/AleoHQ/snarkOS.git#a0d7afb4398abc9b2eb7980811b8b9b808df4019"
|
||||
source = "git+ssh://git@github.com/AleoHQ/snarkOS.git#57fef6a27035419e0b22fee5b72ca6639e15e1ac"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"rand",
|
||||
@ -2073,9 +2332,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.36"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cdb98bcb1f9d81d07b536179c269ea15999b5d14ea958196413869445bb5250"
|
||||
checksum = "e69abc24912995b3038597a7a593be5053eb0fb44f3cc5beec0deb421790c1f4"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.19",
|
||||
"quote 1.0.7",
|
||||
@ -2090,7 +2349,7 @@ checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.19",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.36",
|
||||
"syn 1.0.38",
|
||||
"unicode-xid 0.2.1",
|
||||
]
|
||||
|
||||
@ -2143,7 +2402,7 @@ checksum = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.19",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.36",
|
||||
"syn 1.0.38",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2406,7 +2665,7 @@ dependencies = [
|
||||
"log",
|
||||
"proc-macro2 1.0.19",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.36",
|
||||
"syn 1.0.38",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@ -2440,7 +2699,7 @@ checksum = "841a6d1c35c6f596ccea1f82504a192a60378f64b3bb0261904ad8f2f5657556"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.19",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.36",
|
||||
"syn 1.0.38",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@ -2461,6 +2720,15 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "3.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.2.8"
|
||||
|
@ -13,13 +13,14 @@ name = "leo"
|
||||
path = "leo/main.rs"
|
||||
|
||||
[workspace]
|
||||
members = [ "ast", "compiler", "gadgets", "input", "linter", "package", "typed" ]
|
||||
members = [ "ast", "compiler", "gadgets", "input", "linter", "package", "typed", "state"]
|
||||
|
||||
[dependencies]
|
||||
leo-compiler = { path = "compiler", version = "0.1.0" }
|
||||
leo-gadgets = { path = "gadgets", version = "0.1.0" }
|
||||
leo-input = { path = "input", version = "0.1.0" }
|
||||
leo-package = { path = "package", version = "0.1.0" }
|
||||
leo-state = { path = "state", version = "0.1.0" }
|
||||
|
||||
snarkos-algorithms = { git = "ssh://git@github.com/AleoHQ/snarkOS.git", package = "snarkos-algorithms", default-features = false }
|
||||
snarkos-curves = { git = "ssh://git@github.com/AleoHQ/snarkOS.git", package = "snarkos-curves", default-features = false }
|
||||
|
27
ast/src/annotations/annotation_arguments.rs
Normal file
27
ast/src/annotations/annotation_arguments.rs
Normal file
@ -0,0 +1,27 @@
|
||||
use crate::{
|
||||
ast::{span_into_string, Rule},
|
||||
SpanDef,
|
||||
};
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::annotation_arguments))]
|
||||
pub struct AnnotationArguments<'ast> {
|
||||
pub arguments: Vec<AnnotationArgument<'ast>>,
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::annotation_argument))]
|
||||
pub struct AnnotationArgument<'ast> {
|
||||
#[pest_ast(outer(with(span_into_string)))]
|
||||
pub value: String,
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
}
|
19
ast/src/annotations/annotation_name.rs
Normal file
19
ast/src/annotations/annotation_name.rs
Normal file
@ -0,0 +1,19 @@
|
||||
use crate::{ast::Rule, SpanDef};
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::annotation_name))]
|
||||
pub enum AnnotationName<'ast> {
|
||||
Context(Context<'ast>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::context))]
|
||||
pub struct Context<'ast> {
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
}
|
13
ast/src/annotations/annotation_symbol.rs
Normal file
13
ast/src/annotations/annotation_symbol.rs
Normal file
@ -0,0 +1,13 @@
|
||||
use crate::{ast::Rule, SpanDef};
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::annotation_symbol))]
|
||||
pub struct AnnotationSymbol<'ast> {
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
}
|
20
ast/src/annotations/annotations.rs
Normal file
20
ast/src/annotations/annotations.rs
Normal file
@ -0,0 +1,20 @@
|
||||
use crate::{
|
||||
annotations::{AnnotationArguments, AnnotationName, AnnotationSymbol},
|
||||
ast::Rule,
|
||||
SpanDef,
|
||||
};
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::annotation))]
|
||||
pub struct Annotation<'ast> {
|
||||
pub symbol: AnnotationSymbol<'ast>,
|
||||
pub name: AnnotationName<'ast>,
|
||||
pub arguments: AnnotationArguments<'ast>,
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
}
|
11
ast/src/annotations/mod.rs
Normal file
11
ast/src/annotations/mod.rs
Normal file
@ -0,0 +1,11 @@
|
||||
pub mod annotations;
|
||||
pub use annotations::*;
|
||||
|
||||
pub mod annotation_symbol;
|
||||
pub use annotation_symbol::*;
|
||||
|
||||
pub mod annotation_name;
|
||||
pub use annotation_name::*;
|
||||
|
||||
pub mod annotation_arguments;
|
||||
pub use annotation_arguments::*;
|
15
ast/src/definitions/annotated_definition.rs
Normal file
15
ast/src/definitions/annotated_definition.rs
Normal file
@ -0,0 +1,15 @@
|
||||
use crate::{annotations::Annotation, ast::Rule, definitions::Definition, SpanDef};
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::definition_annotated))]
|
||||
pub struct AnnotatedDefinition<'ast> {
|
||||
pub annotation: Annotation<'ast>,
|
||||
pub definition: Box<Definition<'ast>>,
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
use crate::{
|
||||
ast::Rule,
|
||||
circuits::Circuit,
|
||||
definitions::AnnotatedDefinition,
|
||||
functions::{Function, TestFunction},
|
||||
imports::Import,
|
||||
};
|
||||
@ -11,6 +12,7 @@ use serde::Serialize;
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::definition))]
|
||||
pub enum Definition<'ast> {
|
||||
Annotated(AnnotatedDefinition<'ast>),
|
||||
Import(Import<'ast>),
|
||||
Circuit(Circuit<'ast>),
|
||||
Function(Function<'ast>),
|
||||
|
@ -1,2 +1,5 @@
|
||||
pub mod annotated_definition;
|
||||
pub use annotated_definition::*;
|
||||
|
||||
pub mod definition;
|
||||
pub use definition::*;
|
||||
|
@ -8,12 +8,16 @@ file = { SOI ~ NEWLINE* ~ definition* ~ NEWLINE* ~ EOI }
|
||||
|
||||
// Declared in definitions/definition.rs
|
||||
definition = {
|
||||
import
|
||||
definition_annotated
|
||||
| import
|
||||
| circuit
|
||||
| function
|
||||
| test_function
|
||||
}
|
||||
|
||||
// Declared in definitions/annotated_definition.rs
|
||||
definition_annotated = { annotation ~ NEWLINE* ~ definition}
|
||||
|
||||
// Declared in common/identifier.rs
|
||||
identifier = @{ ((!protected_name ~ ASCII_ALPHA) | (protected_name ~ (ASCII_ALPHANUMERIC | "_"))) ~ (ASCII_ALPHANUMERIC | "_")* }
|
||||
protected_name = {
|
||||
@ -230,9 +234,20 @@ value_boolean = { "true" | "false" }
|
||||
value_field = ${ value_number ~ type_field }
|
||||
|
||||
// Declared in values/group_value.rs
|
||||
value_group = ${ group_single_or_tuple ~ type_group }
|
||||
group_tuple = !{"(" ~ value_number ~ "," ~ value_number ~ ")"}
|
||||
group_single_or_tuple = {value_number | group_tuple}
|
||||
value_group = ${ group_tuple ~ type_group }
|
||||
group_tuple = !{"(" ~ group_coordinate ~ "," ~ group_coordinate ~ ")"}
|
||||
|
||||
// Declared in values/group_coordinate.rs
|
||||
group_coordinate = {
|
||||
value_number
|
||||
| sign_high
|
||||
| sign_low
|
||||
| inferred
|
||||
}
|
||||
|
||||
sign_high = @{"+"}
|
||||
sign_low = @{"-"}
|
||||
inferred = @{"_"}
|
||||
|
||||
// Declared in values/address.rs
|
||||
address = @{ "aleo1" ~ (LOWERCASE_LETTER | ASCII_DIGIT){58} }
|
||||
@ -457,3 +472,23 @@ debug = {"debug"}
|
||||
// Declared in macros/error.rs
|
||||
error = {"error"}
|
||||
|
||||
/// Annotations
|
||||
|
||||
// Declared in annotations/annotation.rs
|
||||
annotation = ${annotation_symbol ~ annotation_name ~ annotation_arguments}
|
||||
|
||||
// Declared in annotations/annotation_symbol.rs
|
||||
annotation_symbol = ${"@"}
|
||||
|
||||
// Declared in annotations/annotation_name.rs
|
||||
annotation_name = {
|
||||
context
|
||||
}
|
||||
|
||||
// Declared in annotations/context.rs
|
||||
context = {"context"}
|
||||
|
||||
// Declared in annotations/annotation_argument.rs
|
||||
annotation_arguments = !{"(" ~ NEWLINE* ~ annotation_argument ~ ("," ~ NEWLINE* ~ annotation_argument)* ~ ","? ~ NEWLINE* ~ ")"}
|
||||
|
||||
annotation_argument = @{ (ASCII_ALPHANUMERIC | "_")+ }
|
||||
|
@ -8,6 +8,7 @@ extern crate thiserror;
|
||||
mod ast;
|
||||
|
||||
pub mod access;
|
||||
pub mod annotations;
|
||||
pub mod circuits;
|
||||
pub mod common;
|
||||
pub mod definitions;
|
||||
|
61
ast/src/values/group_coordinate.rs
Normal file
61
ast/src/values/group_coordinate.rs
Normal file
@ -0,0 +1,61 @@
|
||||
use crate::{ast::Rule, values::NumberValue, SpanDef};
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::group_coordinate))]
|
||||
pub enum GroupCoordinate<'ast> {
|
||||
Number(NumberValue<'ast>),
|
||||
SignHigh(SignHigh<'ast>),
|
||||
SignLow(SignLow<'ast>),
|
||||
Inferred(Inferred<'ast>),
|
||||
}
|
||||
|
||||
impl<'ast> GroupCoordinate<'ast> {
|
||||
pub fn span(&self) -> &Span<'ast> {
|
||||
match self {
|
||||
GroupCoordinate::Number(number) => &number.span(),
|
||||
GroupCoordinate::SignHigh(sign_high) => &sign_high.span,
|
||||
GroupCoordinate::SignLow(sign_low) => &sign_low.span,
|
||||
GroupCoordinate::Inferred(inferred) => &inferred.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> fmt::Display for GroupCoordinate<'ast> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
GroupCoordinate::Number(number) => write!(f, "{}", number),
|
||||
GroupCoordinate::SignHigh(_) => write!(f, "+"),
|
||||
GroupCoordinate::SignLow(_) => write!(f, "-"),
|
||||
GroupCoordinate::Inferred(_) => write!(f, "_"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::sign_high))]
|
||||
pub struct SignHigh<'ast> {
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::sign_low))]
|
||||
pub struct SignLow<'ast> {
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::inferred))]
|
||||
pub struct Inferred<'ast> {
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
use crate::{ast::Rule, types::GroupType, values::NumberValue, SpanDef};
|
||||
use crate::{ast::Rule, types::GroupType, values::GroupCoordinate, SpanDef};
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
@ -8,8 +8,8 @@ use std::fmt;
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::value_group))]
|
||||
pub struct GroupValue<'ast> {
|
||||
pub value: GroupRepresentation<'ast>,
|
||||
pub _type: GroupType,
|
||||
pub value: GroupTuple<'ast>,
|
||||
pub type_: GroupType,
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
@ -21,27 +21,11 @@ impl<'ast> fmt::Display for GroupValue<'ast> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::group_single_or_tuple))]
|
||||
pub enum GroupRepresentation<'ast> {
|
||||
Single(NumberValue<'ast>),
|
||||
Tuple(GroupTuple<'ast>),
|
||||
}
|
||||
|
||||
impl<'ast> fmt::Display for GroupRepresentation<'ast> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
GroupRepresentation::Single(number) => write!(f, "{}", number),
|
||||
GroupRepresentation::Tuple(tuple) => write!(f, "{}", tuple),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::group_tuple))]
|
||||
pub struct GroupTuple<'ast> {
|
||||
pub x: NumberValue<'ast>,
|
||||
pub y: NumberValue<'ast>,
|
||||
pub x: GroupCoordinate<'ast>,
|
||||
pub y: GroupCoordinate<'ast>,
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
|
@ -10,6 +10,9 @@ pub use boolean_value::*;
|
||||
pub mod field_value;
|
||||
pub use field_value::*;
|
||||
|
||||
pub mod group_coordinate;
|
||||
pub use group_coordinate::*;
|
||||
|
||||
pub mod group_value;
|
||||
pub use group_value::*;
|
||||
|
||||
|
@ -8,7 +8,9 @@ edition = "2018"
|
||||
leo-ast = { path = "../ast", version = "0.1.0" }
|
||||
leo-gadgets = { path = "../gadgets", version = "0.1.0" }
|
||||
leo-input = { path = "../input", version = "0.1.0" }
|
||||
leo-package = { path = "../package", version = "0.1.0"}
|
||||
leo-typed = { path = "../typed", version = "0.1.0" }
|
||||
leo-state = { path = "../state", version = "0.1.0" }
|
||||
|
||||
snarkos-curves = { git = "ssh://git@github.com/AleoHQ/snarkOS.git", package = "snarkos-curves", default-features = false }
|
||||
snarkos-dpc = { git = "ssh://git@github.com/AleoHQ/snarkOS.git", package = "snarkos-dpc", default-features = false }
|
||||
|
@ -10,8 +10,11 @@ use crate::{
|
||||
};
|
||||
use leo_ast::LeoAst;
|
||||
use leo_input::LeoInputParser;
|
||||
use leo_package::inputs::InputPairs;
|
||||
use leo_state::verify_local_data_commitment;
|
||||
use leo_typed::{Input, LeoTypedAst, MainInput, Program};
|
||||
|
||||
use snarkos_dpc::{base_dpc::instantiated::Components, SystemParameters};
|
||||
use snarkos_errors::gadgets::SynthesisError;
|
||||
use snarkos_models::{
|
||||
curves::{Field, PrimeField},
|
||||
@ -124,6 +127,16 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
self.program_input.set_main_input(input);
|
||||
}
|
||||
|
||||
/// Verifies the input to the program
|
||||
pub fn verify_local_data_commitment(
|
||||
&self,
|
||||
system_parameters: &SystemParameters<Components>,
|
||||
) -> Result<bool, CompilerError> {
|
||||
let result = verify_local_data_commitment(system_parameters, &self.program_input)?;
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn checksum(&self) -> Result<String, CompilerError> {
|
||||
// Read in the main file as string
|
||||
let unparsed_file = fs::read_to_string(&self.main_file_path)
|
||||
@ -151,8 +164,13 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
}
|
||||
|
||||
/// Synthesizes the circuit for test functions with program input.
|
||||
pub fn compile_test_constraints(self) -> Result<(), CompilerError> {
|
||||
generate_test_constraints::<F, G>(self.program, self.program_input, &self.imported_programs)
|
||||
pub fn compile_test_constraints(self, input_pairs: InputPairs) -> Result<(), CompilerError> {
|
||||
generate_test_constraints::<F, G>(
|
||||
self.program,
|
||||
input_pairs,
|
||||
&self.imported_programs,
|
||||
&self.output_directory,
|
||||
)
|
||||
}
|
||||
|
||||
/// Calls the internal generate_constraints method with arguments
|
||||
@ -204,6 +222,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstraintSynthesizer<F> for Compil
|
||||
|
||||
// Write results to file
|
||||
let output_file = OutputFile::new(&package_name);
|
||||
|
||||
log::info!("Writing to output registers...");
|
||||
|
||||
output_file.write(&output_directory, result.bytes()).unwrap();
|
||||
|
||||
Ok(())
|
||||
|
@ -8,13 +8,17 @@ use crate::{
|
||||
GroupType,
|
||||
ImportParser,
|
||||
OutputBytes,
|
||||
OutputFile,
|
||||
};
|
||||
use leo_typed::{Input, Program};
|
||||
|
||||
use leo_input::LeoInputParser;
|
||||
use leo_package::inputs::InputPairs;
|
||||
use snarkos_models::{
|
||||
curves::{Field, PrimeField},
|
||||
gadgets::r1cs::{ConstraintSystem, TestConstraintSystem},
|
||||
};
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub fn generate_constraints<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
|
||||
cs: &mut CS,
|
||||
@ -43,27 +47,61 @@ pub fn generate_constraints<F: Field + PrimeField, G: GroupType<F>, CS: Constrai
|
||||
|
||||
pub fn generate_test_constraints<F: Field + PrimeField, G: GroupType<F>>(
|
||||
program: Program,
|
||||
input: Input,
|
||||
input: InputPairs,
|
||||
imported_programs: &ImportParser,
|
||||
output_directory: &PathBuf,
|
||||
) -> Result<(), CompilerError> {
|
||||
let mut resolved_program = ConstrainedProgram::<F, G>::new();
|
||||
let program_name = program.get_name();
|
||||
|
||||
let tests = program.tests.clone();
|
||||
|
||||
// Store definitions
|
||||
resolved_program.store_definitions(program, imported_programs)?;
|
||||
|
||||
// Get default input
|
||||
let default = input.pairs.get(&program_name);
|
||||
|
||||
log::info!("Running {} tests", tests.len());
|
||||
|
||||
for (test_name, test_function) in tests.into_iter() {
|
||||
for (test_name, test) in tests.into_iter() {
|
||||
let cs = &mut TestConstraintSystem::<F>::new();
|
||||
let full_test_name = format!("{}::{}", program_name.clone(), test_name.to_string());
|
||||
let mut output_file_name = program_name.clone();
|
||||
|
||||
let result = resolved_program.enforce_main_function(
|
||||
// get input file name from annotation or use test_name
|
||||
let input_pair = match test.input_file {
|
||||
Some(file_id) => {
|
||||
let file_name = file_id.name;
|
||||
|
||||
output_file_name = file_name.clone();
|
||||
|
||||
match input.pairs.get(&file_name) {
|
||||
Some(pair) => pair.to_owned(),
|
||||
None => return Err(CompilerError::InvalidTestContext(file_name)),
|
||||
}
|
||||
}
|
||||
None => default.ok_or(CompilerError::NoTestInput)?,
|
||||
};
|
||||
|
||||
// parse input files to abstract syntax trees
|
||||
let input_file = &input_pair.input_file;
|
||||
let state_file = &input_pair.state_file;
|
||||
|
||||
let input_ast = LeoInputParser::parse_file(input_file)?;
|
||||
let state_ast = LeoInputParser::parse_file(state_file)?;
|
||||
|
||||
// parse input files into input struct
|
||||
let mut input = Input::new();
|
||||
input.parse_input(input_ast)?;
|
||||
input.parse_state(state_ast)?;
|
||||
|
||||
// run test function on new program with input
|
||||
let result = resolved_program.clone().enforce_main_function(
|
||||
cs,
|
||||
program_name.clone(),
|
||||
test_function.0,
|
||||
input.clone(), // pass program input into every test
|
||||
test.function,
|
||||
input, // pass program input into every test
|
||||
);
|
||||
|
||||
if result.is_ok() {
|
||||
@ -72,6 +110,14 @@ pub fn generate_test_constraints<F: Field + PrimeField, G: GroupType<F>>(
|
||||
full_test_name,
|
||||
cs.is_satisfied()
|
||||
);
|
||||
|
||||
// write result to file
|
||||
let output = result?;
|
||||
let output_file = OutputFile::new(&output_file_name);
|
||||
|
||||
log::info!("\tWriting output to registers in `{}.out` ...", output_file_name);
|
||||
|
||||
output_file.write(output_directory, output.bytes()).unwrap();
|
||||
} else {
|
||||
log::error!("test {} errored: {}", full_test_name, result.unwrap_err());
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::errors::{FunctionError, ImportError, OutputBytesError, OutputFileError};
|
||||
use leo_ast::ParserError;
|
||||
use leo_input::InputParserError;
|
||||
use leo_state::LocalDataVerificationError;
|
||||
|
||||
use bincode::Error as SerdeError;
|
||||
use std::path::PathBuf;
|
||||
@ -13,18 +14,27 @@ pub enum CompilerError {
|
||||
#[error("{}", _0)]
|
||||
InputParserError(#[from] InputParserError),
|
||||
|
||||
#[error("Cannot find input files with context name `{}`", _0)]
|
||||
InvalidTestContext(String),
|
||||
|
||||
#[error("{}", _0)]
|
||||
FunctionError(#[from] FunctionError),
|
||||
|
||||
#[error("Cannot read from the provided file path - {:?}", _0)]
|
||||
FileReadError(PathBuf),
|
||||
|
||||
#[error("{}", _0)]
|
||||
LocalDataVerificationError(#[from] LocalDataVerificationError),
|
||||
|
||||
#[error("`main` function not found")]
|
||||
NoMain,
|
||||
|
||||
#[error("`main` must be a function")]
|
||||
NoMainFunction,
|
||||
|
||||
#[error("Failed to find input files for the current test")]
|
||||
NoTestInput,
|
||||
|
||||
#[error("{}", _0)]
|
||||
OutputError(#[from] OutputFileError),
|
||||
|
||||
|
@ -52,4 +52,34 @@ impl GroupError {
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn x_invalid(x: String, span: Span) -> Self {
|
||||
let message = format!("invalid x coordinate `{}`", x);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn y_invalid(y: String, span: Span) -> Self {
|
||||
let message = format!("invalid y coordinate `{}`", y);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn not_on_curve(element: String, span: Span) -> Self {
|
||||
let message = format!("group element `{}` is not on the supported curve", element);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn x_recover(span: Span) -> Self {
|
||||
let message = format!("could not recover group element from x coordinate");
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn y_recover(span: Span) -> Self {
|
||||
let message = format!("could not recover group element from y coordinate");
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
}
|
||||
|
@ -45,4 +45,10 @@ impl ValueError {
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn implicit_group(span: Span) -> Self {
|
||||
let message = format!("group coordinates should be in (x, y)group format");
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
Expression::Address(address, span) => Ok(ConstrainedValue::Address(Address::new(address, span)?)),
|
||||
Expression::Boolean(boolean, span) => Ok(ConstrainedValue::Boolean(new_bool_constant(boolean, span)?)),
|
||||
Expression::Field(field, span) => Ok(ConstrainedValue::Field(FieldType::constant(field, span)?)),
|
||||
Expression::Group(group_affine, span) => Ok(ConstrainedValue::Group(G::constant(group_affine, span)?)),
|
||||
Expression::Group(group_affine) => Ok(ConstrainedValue::Group(G::constant(group_affine)?)),
|
||||
Expression::Implicit(value, span) => Ok(enforce_number_implicit(expected_type, value, span)?),
|
||||
Expression::Integer(type_, integer, span) => {
|
||||
Ok(ConstrainedValue::Integer(Integer::new_constant(&type_, integer, span)?))
|
||||
|
@ -40,7 +40,6 @@ impl OutputFile {
|
||||
// create output file
|
||||
let path = self.setup_file_path(path);
|
||||
let mut file = File::create(&path)?;
|
||||
log::info!("Writing to output registers...");
|
||||
|
||||
Ok(file.write_all(bytes)?)
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ use snarkos_models::curves::{Field, PrimeField};
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ConstrainedProgram<F: Field + PrimeField, G: GroupType<F>> {
|
||||
pub identifiers: HashMap<String, ConstrainedValue<F, G>>,
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! A data type that represents members in the group formed by the set of affine points on a curve.
|
||||
|
||||
use crate::errors::GroupError;
|
||||
use leo_typed::Span;
|
||||
use leo_typed::{GroupValue, Span};
|
||||
|
||||
use snarkos_models::{
|
||||
curves::{Field, One},
|
||||
@ -27,12 +27,12 @@ pub trait GroupType<F: Field>:
|
||||
+ EvaluateEqGadget<F>
|
||||
+ EqGadget<F>
|
||||
+ ConditionalEqGadget<F>
|
||||
+ AllocGadget<String, F>
|
||||
+ AllocGadget<GroupValue, F>
|
||||
+ CondSelectGadget<F>
|
||||
+ ToBitsGadget<F>
|
||||
+ ToBytesGadget<F>
|
||||
{
|
||||
fn constant(string: String, span: Span) -> Result<Self, GroupError>;
|
||||
fn constant(value: GroupValue) -> Result<Self, GroupError>;
|
||||
|
||||
fn to_allocated<CS: ConstraintSystem<F>>(&self, cs: CS, span: Span) -> Result<Self, GroupError>;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! Methods to enforce constraints on input group values in a Leo program.
|
||||
|
||||
use crate::{errors::GroupError, ConstrainedValue, GroupType};
|
||||
use leo_typed::{InputValue, Span};
|
||||
use leo_typed::{GroupValue, InputValue, Span};
|
||||
|
||||
use snarkos_errors::gadgets::SynthesisError;
|
||||
use snarkos_models::{
|
||||
@ -12,7 +12,7 @@ use snarkos_models::{
|
||||
pub(crate) fn allocate_group<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
|
||||
cs: &mut CS,
|
||||
name: String,
|
||||
option: Option<String>,
|
||||
option: Option<GroupValue>,
|
||||
span: Span,
|
||||
) -> Result<G, GroupError> {
|
||||
let group_name = format!("{}: group", name);
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::{errors::GroupError, GroupType};
|
||||
use leo_typed::Span;
|
||||
use leo_typed::{GroupCoordinate, GroupValue, Span};
|
||||
|
||||
use snarkos_curves::{
|
||||
edwards_bls12::{EdwardsAffine, EdwardsParameters, Fq},
|
||||
@ -36,14 +36,8 @@ pub enum EdwardsGroupType {
|
||||
}
|
||||
|
||||
impl GroupType<Fq> for EdwardsGroupType {
|
||||
fn constant(string: String, span: Span) -> Result<Self, GroupError> {
|
||||
// 1group = generator
|
||||
if string.eq("1") {
|
||||
return Ok(Self::one());
|
||||
}
|
||||
|
||||
let value =
|
||||
Self::edwards_affine_from_str(string.clone()).map_err(|_| GroupError::invalid_group(string, span))?;
|
||||
fn constant(group: GroupValue) -> Result<Self, GroupError> {
|
||||
let value = Self::edwards_affine_from_value(group)?;
|
||||
|
||||
Ok(EdwardsGroupType::Constant(value))
|
||||
}
|
||||
@ -124,10 +118,57 @@ impl GroupType<Fq> for EdwardsGroupType {
|
||||
}
|
||||
|
||||
impl EdwardsGroupType {
|
||||
pub fn edwards_affine_from_str(string: String) -> Result<EdwardsAffine, SynthesisError> {
|
||||
// x or (x, y)
|
||||
match Fq::from_str(&string).ok() {
|
||||
Some(x) => {
|
||||
pub fn edwards_affine_from_value(group: GroupValue) -> Result<EdwardsAffine, GroupError> {
|
||||
let span = group.span;
|
||||
let x = group.x;
|
||||
let y = group.y;
|
||||
|
||||
match (x, y) {
|
||||
// (x, y)
|
||||
(GroupCoordinate::Number(x_string, x_span), GroupCoordinate::Number(y_string, y_span)) => {
|
||||
Self::edwards_affine_from_pair(x_string, y_string, x_span, y_span, span)
|
||||
}
|
||||
// (x, +)
|
||||
(GroupCoordinate::Number(x_string, x_span), GroupCoordinate::SignHigh) => {
|
||||
Self::edwards_affine_from_x_str(x_string, x_span, Some(true), span)
|
||||
}
|
||||
// (x, -)
|
||||
(GroupCoordinate::Number(x_string, x_span), GroupCoordinate::SignLow) => {
|
||||
Self::edwards_affine_from_x_str(x_string, x_span, Some(false), span)
|
||||
}
|
||||
// (x, _)
|
||||
(GroupCoordinate::Number(x_string, x_span), GroupCoordinate::Inferred) => {
|
||||
Self::edwards_affine_from_x_str(x_string, x_span, None, span)
|
||||
}
|
||||
// (+, y)
|
||||
(GroupCoordinate::SignHigh, GroupCoordinate::Number(y_string, y_span)) => {
|
||||
Self::edwards_affine_from_y_str(y_string, y_span, Some(true), span)
|
||||
}
|
||||
// (-, y)
|
||||
(GroupCoordinate::SignLow, GroupCoordinate::Number(y_string, y_span)) => {
|
||||
Self::edwards_affine_from_y_str(y_string, y_span, Some(false), span)
|
||||
}
|
||||
// (_, y)
|
||||
(GroupCoordinate::Inferred, GroupCoordinate::Number(y_string, y_span)) => {
|
||||
Self::edwards_affine_from_y_str(y_string, y_span, None, span)
|
||||
}
|
||||
// Invalid
|
||||
(x, y) => Err(GroupError::invalid_group(format!("({}, {})", x, y), span)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn edwards_affine_from_x_str(
|
||||
x_string: String,
|
||||
x_span: Span,
|
||||
greatest: Option<bool>,
|
||||
element_span: Span,
|
||||
) -> Result<EdwardsAffine, GroupError> {
|
||||
let x = Fq::from_str(&x_string).map_err(|_| GroupError::x_invalid(x_string, x_span))?;
|
||||
match greatest {
|
||||
// Sign provided
|
||||
Some(greatest) => EdwardsAffine::from_x_coordinate(x, greatest).ok_or(GroupError::x_recover(element_span)),
|
||||
// Sign inferred
|
||||
None => {
|
||||
// Attempt to recover with a sign_low bit.
|
||||
if let Some(element) = EdwardsAffine::from_x_coordinate(x.clone(), false) {
|
||||
return Ok(element);
|
||||
@ -139,29 +180,71 @@ impl EdwardsGroupType {
|
||||
}
|
||||
|
||||
// Otherwise return error.
|
||||
Err(SynthesisError::AssignmentMissing)
|
||||
Err(GroupError::x_recover(element_span))
|
||||
}
|
||||
None => EdwardsAffine::from_str(&string).map_err(|_| SynthesisError::AssignmentMissing),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_x_helper<Fn: FnOnce() -> Result<T, SynthesisError>, T: Borrow<String>>(
|
||||
pub fn edwards_affine_from_y_str(
|
||||
y_string: String,
|
||||
y_span: Span,
|
||||
greatest: Option<bool>,
|
||||
element_span: Span,
|
||||
) -> Result<EdwardsAffine, GroupError> {
|
||||
let y = Fq::from_str(&y_string).map_err(|_| GroupError::y_invalid(y_string, y_span))?;
|
||||
|
||||
match greatest {
|
||||
// Sign provided
|
||||
Some(greatest) => EdwardsAffine::from_y_coordinate(y, greatest).ok_or(GroupError::y_recover(element_span)),
|
||||
// Sign inferred
|
||||
None => {
|
||||
// Attempt to recover with a sign_low bit.
|
||||
if let Some(element) = EdwardsAffine::from_y_coordinate(y.clone(), false) {
|
||||
return Ok(element);
|
||||
}
|
||||
|
||||
// Attempt to recover with a sign_high bit.
|
||||
if let Some(element) = EdwardsAffine::from_y_coordinate(y, true) {
|
||||
return Ok(element);
|
||||
}
|
||||
|
||||
// Otherwise return error.
|
||||
Err(GroupError::y_recover(element_span))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn edwards_affine_from_pair(
|
||||
x_string: String,
|
||||
y_string: String,
|
||||
x_span: Span,
|
||||
y_span: Span,
|
||||
element_span: Span,
|
||||
) -> Result<EdwardsAffine, GroupError> {
|
||||
let x = Fq::from_str(&x_string).map_err(|_| GroupError::x_invalid(x_string, x_span))?;
|
||||
let y = Fq::from_str(&y_string).map_err(|_| GroupError::y_invalid(y_string, y_span))?;
|
||||
|
||||
let element = EdwardsAffine::new(x, y);
|
||||
|
||||
if element.is_on_curve() {
|
||||
Ok(element)
|
||||
} else {
|
||||
Err(GroupError::not_on_curve(format!("{}", element), element_span))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_helper<Fn: FnOnce() -> Result<T, SynthesisError>, T: Borrow<GroupValue>>(
|
||||
value_gen: Fn,
|
||||
) -> Result<EdwardsAffine, SynthesisError> {
|
||||
let affine_string = match value_gen() {
|
||||
let group_value = match value_gen() {
|
||||
Ok(value) => {
|
||||
let string_value = value.borrow().clone();
|
||||
Ok(string_value)
|
||||
let group_value = value.borrow().clone();
|
||||
Ok(group_value)
|
||||
}
|
||||
_ => Err(SynthesisError::AssignmentMissing),
|
||||
}?;
|
||||
|
||||
// 1group = generator
|
||||
if affine_string.eq("1") {
|
||||
Ok(edwards_affine_one())
|
||||
} else {
|
||||
Self::edwards_affine_from_str(affine_string)
|
||||
}
|
||||
Self::edwards_affine_from_value(group_value).map_err(|_| SynthesisError::AssignmentMissing)
|
||||
}
|
||||
|
||||
pub fn allocated<CS: ConstraintSystem<Fq>>(&self, mut cs: CS) -> Result<EdwardsBlsGadget, SynthesisError> {
|
||||
@ -189,24 +272,24 @@ impl EdwardsGroupType {
|
||||
}
|
||||
}
|
||||
|
||||
impl AllocGadget<String, Fq> for EdwardsGroupType {
|
||||
fn alloc<Fn: FnOnce() -> Result<T, SynthesisError>, T: Borrow<String>, CS: ConstraintSystem<Fq>>(
|
||||
impl AllocGadget<GroupValue, Fq> for EdwardsGroupType {
|
||||
fn alloc<Fn: FnOnce() -> Result<T, SynthesisError>, T: Borrow<GroupValue>, CS: ConstraintSystem<Fq>>(
|
||||
cs: CS,
|
||||
value_gen: Fn,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
let value = <EdwardsBlsGadget as AllocGadget<GroupAffine<EdwardsParameters>, Fq>>::alloc(cs, || {
|
||||
Self::alloc_x_helper(value_gen)
|
||||
Self::alloc_helper(value_gen)
|
||||
})?;
|
||||
|
||||
Ok(EdwardsGroupType::Allocated(value))
|
||||
}
|
||||
|
||||
fn alloc_input<Fn: FnOnce() -> Result<T, SynthesisError>, T: Borrow<String>, CS: ConstraintSystem<Fq>>(
|
||||
fn alloc_input<Fn: FnOnce() -> Result<T, SynthesisError>, T: Borrow<GroupValue>, CS: ConstraintSystem<Fq>>(
|
||||
cs: CS,
|
||||
value_gen: Fn,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
let value = <EdwardsBlsGadget as AllocGadget<GroupAffine<EdwardsParameters>, Fq>>::alloc_input(cs, || {
|
||||
Self::alloc_x_helper(value_gen)
|
||||
Self::alloc_helper(value_gen)
|
||||
})?;
|
||||
|
||||
Ok(EdwardsGroupType::Allocated(value))
|
||||
|
@ -69,7 +69,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
||||
Type::Address => Ok(ConstrainedValue::Address(Address::new(value, span)?)),
|
||||
Type::Boolean => Ok(ConstrainedValue::Boolean(new_bool_constant(value, span)?)),
|
||||
Type::Field => Ok(ConstrainedValue::Field(FieldType::constant(value, span)?)),
|
||||
Type::Group => Ok(ConstrainedValue::Group(G::constant(value, span)?)),
|
||||
Type::Group => Err(ValueError::implicit_group(span)),
|
||||
Type::IntegerType(integer_type) => Ok(ConstrainedValue::Integer(Integer::new_constant(
|
||||
integer_type,
|
||||
value,
|
||||
|
3
compiler/tests/group/double_high.leo
Normal file
3
compiler/tests/group/double_high.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() {
|
||||
let element = (+, +)group;
|
||||
}
|
3
compiler/tests/group/double_inferred.leo
Normal file
3
compiler/tests/group/double_inferred.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() {
|
||||
let element = (_, _)group;
|
||||
}
|
3
compiler/tests/group/double_low.leo
Normal file
3
compiler/tests/group/double_low.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() {
|
||||
let element = (-, -)group;
|
||||
}
|
3
compiler/tests/group/input/invalid.in
Normal file
3
compiler/tests/group/input/invalid.in
Normal file
@ -0,0 +1,3 @@
|
||||
[main]
|
||||
a: group = (1, 0)group;
|
||||
b: group = (+, +)group;
|
@ -1,3 +0,0 @@
|
||||
[main]
|
||||
a: group = 1;
|
||||
b: group = 1;
|
@ -1,3 +0,0 @@
|
||||
[main]
|
||||
a: group = 1;
|
||||
b: group = 0;
|
3
compiler/tests/group/input/valid.in
Normal file
3
compiler/tests/group/input/valid.in
Normal file
@ -0,0 +1,3 @@
|
||||
[main]
|
||||
a: group = (0, -)group;
|
||||
b: group = (0, _)group;
|
@ -1,39 +1,37 @@
|
||||
use crate::{
|
||||
assert_satisfied,
|
||||
expect_compiler_error,
|
||||
expect_synthesis_error,
|
||||
field::field_to_decimal_string,
|
||||
generate_main_input,
|
||||
parse_program,
|
||||
parse_program_with_input,
|
||||
};
|
||||
use leo_typed::InputValue;
|
||||
use leo_typed::{GroupCoordinate, GroupValue, InputValue, Span};
|
||||
|
||||
use snarkos_curves::edwards_bls12::EdwardsAffine;
|
||||
|
||||
use rand::{Rng, SeedableRng};
|
||||
use rand_xorshift::XorShiftRng;
|
||||
|
||||
pub fn group_to_decimal_string(g: EdwardsAffine) -> String {
|
||||
pub fn group_element_to_input_value(g: EdwardsAffine) -> GroupValue {
|
||||
let x = field_to_decimal_string(g.x);
|
||||
let y = field_to_decimal_string(g.y);
|
||||
|
||||
format!("({}, {})", x, y)
|
||||
}
|
||||
format!("({}, {})", x, y);
|
||||
|
||||
#[test]
|
||||
fn test_zero() {
|
||||
let bytes = include_bytes!("zero.leo");
|
||||
let program = parse_program(bytes).unwrap();
|
||||
let fake_span = Span {
|
||||
text: "".to_string(),
|
||||
line: 0,
|
||||
start: 0,
|
||||
end: 0,
|
||||
};
|
||||
|
||||
assert_satisfied(program);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_one() {
|
||||
let bytes = include_bytes!("one.leo");
|
||||
let program = parse_program(bytes).unwrap();
|
||||
|
||||
assert_satisfied(program)
|
||||
GroupValue {
|
||||
x: GroupCoordinate::Number(x, fake_span.clone()),
|
||||
y: GroupCoordinate::Number(y, fake_span.clone()),
|
||||
span: fake_span,
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -44,6 +42,81 @@ fn test_point() {
|
||||
assert_satisfied(program);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_x_sign_high() {
|
||||
let bytes = include_bytes!("x_sign_high.leo");
|
||||
let program = parse_program(bytes).unwrap();
|
||||
|
||||
assert_satisfied(program);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_x_sign_low() {
|
||||
let bytes = include_bytes!("x_sign_low.leo");
|
||||
let program = parse_program(bytes).unwrap();
|
||||
|
||||
assert_satisfied(program);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_x_sign_inferred() {
|
||||
let bytes = include_bytes!("x_sign_inferred.leo");
|
||||
let program = parse_program(bytes).unwrap();
|
||||
|
||||
assert_satisfied(program);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_y_sign_high() {
|
||||
let bytes = include_bytes!("y_sign_high.leo");
|
||||
let program = parse_program(bytes).unwrap();
|
||||
|
||||
assert_satisfied(program);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_y_sign_low() {
|
||||
let bytes = include_bytes!("y_sign_low.leo");
|
||||
let program = parse_program(bytes).unwrap();
|
||||
|
||||
assert_satisfied(program);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_y_sign_inferred() {
|
||||
let bytes = include_bytes!("y_sign_inferred.leo");
|
||||
let program = parse_program(bytes).unwrap();
|
||||
|
||||
assert_satisfied(program);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_double_high() {
|
||||
let bytes = include_bytes!("double_high.leo");
|
||||
|
||||
let program = parse_program(bytes).unwrap();
|
||||
|
||||
expect_compiler_error(program);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_double_low() {
|
||||
let bytes = include_bytes!("double_low.leo");
|
||||
|
||||
let program = parse_program(bytes).unwrap();
|
||||
|
||||
expect_compiler_error(program);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_double_inferred() {
|
||||
let bytes = include_bytes!("double_inferred.leo");
|
||||
|
||||
let program = parse_program(bytes).unwrap();
|
||||
|
||||
expect_compiler_error(program);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_point_input() {
|
||||
let program_bytes = include_bytes!("point_input.leo");
|
||||
@ -57,8 +130,8 @@ fn test_point_input() {
|
||||
#[test]
|
||||
fn test_input() {
|
||||
let program_bytes = include_bytes!("input.leo");
|
||||
let input_bytes_pass = include_bytes!("input/one_one.in");
|
||||
let input_bytes_fail = include_bytes!("input/one_zero.in");
|
||||
let input_bytes_pass = include_bytes!("input/valid.in");
|
||||
let input_bytes_fail = include_bytes!("input/invalid.in");
|
||||
|
||||
let program = parse_program_with_input(program_bytes, input_bytes_pass).unwrap();
|
||||
|
||||
@ -66,7 +139,7 @@ fn test_input() {
|
||||
|
||||
let program = parse_program_with_input(program_bytes, input_bytes_fail).unwrap();
|
||||
|
||||
expect_synthesis_error(program);
|
||||
expect_compiler_error(program);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -79,15 +152,15 @@ fn test_negate() {
|
||||
let a: EdwardsAffine = rng.gen();
|
||||
let b = a.neg();
|
||||
|
||||
let a_string = group_to_decimal_string(a);
|
||||
let b_string = group_to_decimal_string(b);
|
||||
let a_element = group_element_to_input_value(a);
|
||||
let b_element = group_element_to_input_value(b);
|
||||
|
||||
let bytes = include_bytes!("negate.leo");
|
||||
let mut program = parse_program(bytes).unwrap();
|
||||
|
||||
let main_input = generate_main_input(vec![
|
||||
("a", Some(InputValue::Group(a_string))),
|
||||
("b", Some(InputValue::Group(b_string))),
|
||||
("a", Some(InputValue::Group(a_element))),
|
||||
("b", Some(InputValue::Group(b_element))),
|
||||
]);
|
||||
program.set_main_input(main_input);
|
||||
|
||||
@ -106,17 +179,17 @@ fn test_add() {
|
||||
let b: EdwardsAffine = rng.gen();
|
||||
let c = a.add(&b);
|
||||
|
||||
let a_string = group_to_decimal_string(a);
|
||||
let b_string = group_to_decimal_string(b);
|
||||
let c_string = group_to_decimal_string(c);
|
||||
let a_element = group_element_to_input_value(a);
|
||||
let b_element = group_element_to_input_value(b);
|
||||
let c_element = group_element_to_input_value(c);
|
||||
|
||||
let bytes = include_bytes!("add.leo");
|
||||
let mut program = parse_program(bytes).unwrap();
|
||||
|
||||
let main_input = generate_main_input(vec![
|
||||
("a", Some(InputValue::Group(a_string))),
|
||||
("b", Some(InputValue::Group(b_string))),
|
||||
("c", Some(InputValue::Group(c_string))),
|
||||
("a", Some(InputValue::Group(a_element))),
|
||||
("b", Some(InputValue::Group(b_element))),
|
||||
("c", Some(InputValue::Group(c_element))),
|
||||
]);
|
||||
program.set_main_input(main_input);
|
||||
|
||||
@ -135,17 +208,17 @@ fn test_sub() {
|
||||
let b: EdwardsAffine = rng.gen();
|
||||
let c = a.sub(&b);
|
||||
|
||||
let a_string = group_to_decimal_string(a);
|
||||
let b_string = group_to_decimal_string(b);
|
||||
let c_string = group_to_decimal_string(c);
|
||||
let a_element = group_element_to_input_value(a);
|
||||
let b_element = group_element_to_input_value(b);
|
||||
let c_element = group_element_to_input_value(c);
|
||||
|
||||
let bytes = include_bytes!("sub.leo");
|
||||
let mut program = parse_program(bytes).unwrap();
|
||||
|
||||
let main_input = generate_main_input(vec![
|
||||
("a", Some(InputValue::Group(a_string))),
|
||||
("b", Some(InputValue::Group(b_string))),
|
||||
("c", Some(InputValue::Group(c_string))),
|
||||
("a", Some(InputValue::Group(a_element))),
|
||||
("b", Some(InputValue::Group(b_element))),
|
||||
("c", Some(InputValue::Group(c_element))),
|
||||
]);
|
||||
program.set_main_input(main_input);
|
||||
|
||||
@ -160,14 +233,14 @@ fn test_assert_eq_pass() {
|
||||
for _ in 0..10 {
|
||||
let a: EdwardsAffine = rng.gen();
|
||||
|
||||
let a_string = group_to_decimal_string(a);
|
||||
let a_element = group_element_to_input_value(a);
|
||||
|
||||
let bytes = include_bytes!("assert_eq.leo");
|
||||
let mut program = parse_program(bytes).unwrap();
|
||||
|
||||
let main_input = generate_main_input(vec![
|
||||
("a", Some(InputValue::Group(a_string.clone()))),
|
||||
("b", Some(InputValue::Group(a_string))),
|
||||
("a", Some(InputValue::Group(a_element.clone()))),
|
||||
("b", Some(InputValue::Group(a_element))),
|
||||
]);
|
||||
|
||||
program.set_main_input(main_input);
|
||||
@ -188,15 +261,15 @@ fn test_assert_eq_fail() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let a_string = group_to_decimal_string(a);
|
||||
let b_string = group_to_decimal_string(b);
|
||||
let a_element = group_element_to_input_value(a);
|
||||
let b_element = group_element_to_input_value(b);
|
||||
|
||||
let bytes = include_bytes!("assert_eq.leo");
|
||||
let mut program = parse_program(bytes).unwrap();
|
||||
|
||||
let main_input = generate_main_input(vec![
|
||||
("a", Some(InputValue::Group(a_string))),
|
||||
("b", Some(InputValue::Group(b_string))),
|
||||
("a", Some(InputValue::Group(a_element))),
|
||||
("b", Some(InputValue::Group(b_element))),
|
||||
]);
|
||||
|
||||
program.set_main_input(main_input);
|
||||
@ -214,8 +287,8 @@ fn test_eq() {
|
||||
let a: EdwardsAffine = rng.gen();
|
||||
let b: EdwardsAffine = rng.gen();
|
||||
|
||||
let a_string = group_to_decimal_string(a);
|
||||
let b_string = group_to_decimal_string(b);
|
||||
let a_element = group_element_to_input_value(a);
|
||||
let b_element = group_element_to_input_value(b);
|
||||
|
||||
// test equal
|
||||
|
||||
@ -223,8 +296,8 @@ fn test_eq() {
|
||||
let mut program = parse_program(bytes).unwrap();
|
||||
|
||||
let main_input = generate_main_input(vec![
|
||||
("a", Some(InputValue::Group(a_string.clone()))),
|
||||
("b", Some(InputValue::Group(a_string.clone()))),
|
||||
("a", Some(InputValue::Group(a_element.clone()))),
|
||||
("b", Some(InputValue::Group(a_element.clone()))),
|
||||
("c", Some(InputValue::Boolean(true))),
|
||||
]);
|
||||
|
||||
@ -239,8 +312,8 @@ fn test_eq() {
|
||||
let mut program = parse_program(bytes).unwrap();
|
||||
|
||||
let main_input = generate_main_input(vec![
|
||||
("a", Some(InputValue::Group(a_string))),
|
||||
("b", Some(InputValue::Group(b_string))),
|
||||
("a", Some(InputValue::Group(a_element))),
|
||||
("b", Some(InputValue::Group(b_element))),
|
||||
("c", Some(InputValue::Boolean(c))),
|
||||
]);
|
||||
|
||||
@ -257,8 +330,8 @@ fn test_ternary() {
|
||||
let a: EdwardsAffine = rng.gen();
|
||||
let b: EdwardsAffine = rng.gen();
|
||||
|
||||
let a_string = group_to_decimal_string(a);
|
||||
let b_string = group_to_decimal_string(b);
|
||||
let a_element = group_element_to_input_value(a);
|
||||
let b_element = group_element_to_input_value(b);
|
||||
|
||||
let bytes = include_bytes!("ternary.leo");
|
||||
let mut program = parse_program(bytes).unwrap();
|
||||
@ -266,9 +339,9 @@ fn test_ternary() {
|
||||
// true -> field a
|
||||
let main_input = generate_main_input(vec![
|
||||
("s", Some(InputValue::Boolean(true))),
|
||||
("a", Some(InputValue::Group(a_string.clone()))),
|
||||
("b", Some(InputValue::Group(b_string.clone()))),
|
||||
("c", Some(InputValue::Group(a_string.clone()))),
|
||||
("a", Some(InputValue::Group(a_element.clone()))),
|
||||
("b", Some(InputValue::Group(b_element.clone()))),
|
||||
("c", Some(InputValue::Group(a_element.clone()))),
|
||||
]);
|
||||
|
||||
program.set_main_input(main_input);
|
||||
@ -280,9 +353,9 @@ fn test_ternary() {
|
||||
// false -> field b
|
||||
let main_input = generate_main_input(vec![
|
||||
("s", Some(InputValue::Boolean(false))),
|
||||
("a", Some(InputValue::Group(a_string))),
|
||||
("b", Some(InputValue::Group(b_string.clone()))),
|
||||
("c", Some(InputValue::Group(b_string))),
|
||||
("a", Some(InputValue::Group(a_element))),
|
||||
("b", Some(InputValue::Group(b_element.clone()))),
|
||||
("c", Some(InputValue::Group(b_element))),
|
||||
]);
|
||||
|
||||
program.set_main_input(main_input);
|
||||
|
@ -1,3 +0,0 @@
|
||||
function main() {
|
||||
let a = 1group;
|
||||
}
|
3
compiler/tests/group/x_and_y.leo
Normal file
3
compiler/tests/group/x_and_y.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(element: group) {
|
||||
let b = element;
|
||||
}
|
3
compiler/tests/group/x_sign_high.leo
Normal file
3
compiler/tests/group/x_sign_high.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() {
|
||||
let element = (0, +)group;
|
||||
}
|
3
compiler/tests/group/x_sign_inferred.leo
Normal file
3
compiler/tests/group/x_sign_inferred.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() {
|
||||
let element = (0, _)group;
|
||||
}
|
3
compiler/tests/group/x_sign_low.leo
Normal file
3
compiler/tests/group/x_sign_low.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() {
|
||||
let element = (0, -)group;
|
||||
}
|
3
compiler/tests/group/y_sign_high.leo
Normal file
3
compiler/tests/group/y_sign_high.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() {
|
||||
let element = (+, 1)group;
|
||||
}
|
3
compiler/tests/group/y_sign_inferred.leo
Normal file
3
compiler/tests/group/y_sign_inferred.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() {
|
||||
let element = (_, 1)group;
|
||||
}
|
3
compiler/tests/group/y_sign_low.leo
Normal file
3
compiler/tests/group/y_sign_low.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() {
|
||||
let element = (-, 1)group;
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
function main() {
|
||||
let a = 0group;
|
||||
}
|
@ -48,6 +48,12 @@ impl InputParserError {
|
||||
Self::new_from_span(message, implicit.span().clone())
|
||||
}
|
||||
|
||||
pub fn implicit_group(number: NumberValue) -> Self {
|
||||
let message = format!("group coordinates should be in (x, y)group format, found `{}`", number);
|
||||
|
||||
Self::new_from_span(message, number.span().clone())
|
||||
}
|
||||
|
||||
pub fn data_type_mismatch(data_type: DataType, value: Value) -> Self {
|
||||
let message = format!("expected `{}`, found `{}`", data_type.to_string(), value.to_string());
|
||||
let span = value.span().to_owned();
|
||||
|
@ -131,9 +131,20 @@ value_boolean = { "true" | "false" }
|
||||
value_field = ${ value_number ~ type_field }
|
||||
|
||||
// Declared in values/group_value.rs
|
||||
value_group = ${ group_single_or_tuple ~ type_group }
|
||||
group_tuple = !{"(" ~ value_number ~ "," ~ value_number ~ ")"}
|
||||
group_single_or_tuple = {value_number | group_tuple}
|
||||
value_group = ${ group_tuple ~ type_group }
|
||||
group_tuple = !{"(" ~ group_coordinate ~ "," ~ group_coordinate ~ ")"}
|
||||
|
||||
// Declared in values/group_coordinate.rs
|
||||
group_coordinate = {
|
||||
value_number
|
||||
| sign_high
|
||||
| sign_low
|
||||
| inferred
|
||||
}
|
||||
|
||||
sign_high = @{"+"}
|
||||
sign_low = @{"-"}
|
||||
inferred = @{"_"}
|
||||
|
||||
// Declared in values/address.rs
|
||||
address = @{ "aleo" ~ ASCII_DIGIT ~ (LOWERCASE_LETTER | ASCII_DIGIT){58} }
|
||||
|
57
input/src/values/group_coordinate.rs
Normal file
57
input/src/values/group_coordinate.rs
Normal file
@ -0,0 +1,57 @@
|
||||
use crate::{ast::Rule, values::NumberValue};
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
|
||||
#[pest_ast(rule(Rule::group_coordinate))]
|
||||
pub enum GroupCoordinate<'ast> {
|
||||
Number(NumberValue<'ast>),
|
||||
SignHigh(SignHigh<'ast>),
|
||||
SignLow(SignLow<'ast>),
|
||||
Inferred(Inferred<'ast>),
|
||||
}
|
||||
|
||||
impl<'ast> GroupCoordinate<'ast> {
|
||||
pub fn span(&self) -> &Span<'ast> {
|
||||
match self {
|
||||
GroupCoordinate::Number(number) => &number.span(),
|
||||
GroupCoordinate::SignHigh(sign_high) => &sign_high.span,
|
||||
GroupCoordinate::SignLow(sign_low) => &sign_low.span,
|
||||
GroupCoordinate::Inferred(inferred) => &inferred.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> fmt::Display for GroupCoordinate<'ast> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
GroupCoordinate::Number(number) => write!(f, "{}", number),
|
||||
GroupCoordinate::SignHigh(_) => write!(f, "+"),
|
||||
GroupCoordinate::SignLow(_) => write!(f, "-"),
|
||||
GroupCoordinate::Inferred(_) => write!(f, "_"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
|
||||
#[pest_ast(rule(Rule::sign_high))]
|
||||
pub struct SignHigh<'ast> {
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
|
||||
#[pest_ast(rule(Rule::sign_low))]
|
||||
pub struct SignLow<'ast> {
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
|
||||
#[pest_ast(rule(Rule::inferred))]
|
||||
pub struct Inferred<'ast> {
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
use crate::{ast::Rule, types::GroupType, values::NumberValue};
|
||||
use crate::{ast::Rule, types::GroupType, values::GroupCoordinate};
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
@ -7,7 +7,7 @@ use std::fmt;
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
|
||||
#[pest_ast(rule(Rule::value_group))]
|
||||
pub struct GroupValue<'ast> {
|
||||
pub value: GroupRepresentation<'ast>,
|
||||
pub value: GroupTuple<'ast>,
|
||||
pub type_: GroupType,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
@ -19,27 +19,11 @@ impl<'ast> fmt::Display for GroupValue<'ast> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
|
||||
#[pest_ast(rule(Rule::group_single_or_tuple))]
|
||||
pub enum GroupRepresentation<'ast> {
|
||||
Single(NumberValue<'ast>),
|
||||
Tuple(GroupTuple<'ast>),
|
||||
}
|
||||
|
||||
impl<'ast> fmt::Display for GroupRepresentation<'ast> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
GroupRepresentation::Single(number) => write!(f, "{}", number),
|
||||
GroupRepresentation::Tuple(tuple) => write!(f, "{}", tuple),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
|
||||
#[pest_ast(rule(Rule::group_tuple))]
|
||||
pub struct GroupTuple<'ast> {
|
||||
pub x: NumberValue<'ast>,
|
||||
pub y: NumberValue<'ast>,
|
||||
pub x: GroupCoordinate<'ast>,
|
||||
pub y: GroupCoordinate<'ast>,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
|
@ -13,6 +13,9 @@ pub use boolean_value::*;
|
||||
pub mod field_value;
|
||||
pub use field_value::*;
|
||||
|
||||
pub mod group_coordinate;
|
||||
pub use group_coordinate::*;
|
||||
|
||||
pub mod group_value;
|
||||
pub use group_value::*;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
cli::*,
|
||||
cli_types::*,
|
||||
commands::{BuildCommand, LoginCommand},
|
||||
commands::LoginCommand,
|
||||
errors::{
|
||||
commands::PublishError::{ConnectionUnavalaible, PackageNotPublished},
|
||||
CLIError,
|
||||
|
@ -6,7 +6,7 @@ use crate::{
|
||||
use leo_compiler::{compiler::Compiler, group::targets::edwards_bls12::EdwardsGroupType};
|
||||
use leo_package::{
|
||||
inputs::*,
|
||||
outputs::OUTPUTS_DIRECTORY_NAME,
|
||||
outputs::{OutputsDirectory, OUTPUTS_DIRECTORY_NAME},
|
||||
root::Manifest,
|
||||
source::{MainFile, MAIN_FILE_NAME, SOURCE_DIRECTORY_NAME},
|
||||
};
|
||||
@ -63,27 +63,23 @@ impl CLI for TestCommand {
|
||||
let mut output_directory = package_path.clone();
|
||||
output_directory.push(OUTPUTS_DIRECTORY_NAME);
|
||||
|
||||
// Load the input file at `package_name`
|
||||
let input_string = InputFile::new(&package_name).read_from(&path)?;
|
||||
// Create the output directory
|
||||
OutputsDirectory::create(&package_path)?;
|
||||
|
||||
// Load the state file at `package_name.in`
|
||||
let state_string = StateFile::new(&package_name).read_from(&path)?;
|
||||
|
||||
// Compute the current program checksum
|
||||
let program = Compiler::<Fq, EdwardsGroupType>::parse_program_with_input(
|
||||
// Parse the current main program file
|
||||
let program = Compiler::<Fq, EdwardsGroupType>::parse_program_without_input(
|
||||
package_name.clone(),
|
||||
main_file_path.clone(),
|
||||
output_directory,
|
||||
&input_string,
|
||||
&state_string,
|
||||
)?;
|
||||
|
||||
// Generate the program on the constraint system and verify correctness
|
||||
{
|
||||
let temporary_program = program.clone();
|
||||
let output = temporary_program.compile_test_constraints()?;
|
||||
log::debug!("Compiled constraints - {:#?}", output);
|
||||
}
|
||||
// Parse all inputs as input pairs
|
||||
let pairs = InputPairs::try_from(&package_path)?;
|
||||
|
||||
// Run tests
|
||||
let temporary_program = program.clone();
|
||||
let output = temporary_program.compile_test_constraints(pairs)?;
|
||||
log::debug!("Compiled constraints - {:#?}", output);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
use crate::{InputFileError, StateFileError};
|
||||
|
||||
use std::{ffi::OsString, fs::FileType, io};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
@ -11,15 +13,24 @@ pub enum InputsDirectoryError {
|
||||
#[error("file {:?} extension getting", _0)]
|
||||
GettingFileExtension(OsString),
|
||||
|
||||
#[error("file {:?} name getting", _0)]
|
||||
GettingFileName(OsString),
|
||||
|
||||
#[error("file {:?} type getting: {}", _0, _1)]
|
||||
GettingFileType(OsString, io::Error),
|
||||
|
||||
#[error("{}", _0)]
|
||||
InputFileError(#[from] InputFileError),
|
||||
|
||||
#[error("invalid file {:?} extension: {:?}", _0, _1)]
|
||||
InvalidFileExtension(OsString, OsString),
|
||||
InvalidFileExtension(String, OsString),
|
||||
|
||||
#[error("invalid file {:?} type: {:?}", _0, _1)]
|
||||
InvalidFileType(OsString, FileType),
|
||||
|
||||
#[error("reading: {}", _0)]
|
||||
Reading(io::Error),
|
||||
|
||||
#[error("{}", _0)]
|
||||
StateFileError(#[from] StateFileError),
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::{errors::InputsDirectoryError, inputs::INPUT_FILE_EXTENSION};
|
||||
use crate::errors::InputsDirectoryError;
|
||||
|
||||
use std::{fs, path::PathBuf};
|
||||
use std::{fs, fs::ReadDir, path::PathBuf};
|
||||
|
||||
pub static INPUTS_DIRECTORY_NAME: &str = "inputs/";
|
||||
|
||||
@ -17,42 +17,42 @@ impl InputsDirectory {
|
||||
fs::create_dir_all(&path).map_err(InputsDirectoryError::Creating)
|
||||
}
|
||||
|
||||
/// Returns a list of files in the source directory.
|
||||
/// Returns a list of files in the input directory.
|
||||
pub fn files(path: &PathBuf) -> Result<Vec<PathBuf>, InputsDirectoryError> {
|
||||
let mut path = path.to_owned();
|
||||
path.push(PathBuf::from(INPUTS_DIRECTORY_NAME));
|
||||
let directory = fs::read_dir(&path).map_err(InputsDirectoryError::Reading)?;
|
||||
|
||||
let mut file_paths = Vec::new();
|
||||
for file_entry in directory.into_iter() {
|
||||
let file_entry = file_entry.map_err(InputsDirectoryError::GettingFileEntry)?;
|
||||
let file_path = file_entry.path();
|
||||
|
||||
// Verify that the entry is structured as a valid file
|
||||
let file_type = file_entry
|
||||
.file_type()
|
||||
.map_err(|error| InputsDirectoryError::GettingFileType(file_path.as_os_str().to_owned(), error))?;
|
||||
if !file_type.is_file() {
|
||||
return Err(InputsDirectoryError::InvalidFileType(
|
||||
file_path.as_os_str().to_owned(),
|
||||
file_type,
|
||||
));
|
||||
}
|
||||
|
||||
// Verify that the file has the default file extension
|
||||
let file_extension = file_path
|
||||
.extension()
|
||||
.ok_or_else(|| InputsDirectoryError::GettingFileExtension(file_path.as_os_str().to_owned()))?;
|
||||
if file_extension != INPUT_FILE_EXTENSION {
|
||||
return Err(InputsDirectoryError::InvalidFileExtension(
|
||||
file_path.as_os_str().to_owned(),
|
||||
file_extension.to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
file_paths.push(file_path);
|
||||
}
|
||||
parse_file_paths(directory, &mut file_paths)?;
|
||||
|
||||
Ok(file_paths)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_file_paths(directory: ReadDir, file_paths: &mut Vec<PathBuf>) -> Result<(), InputsDirectoryError> {
|
||||
for file_entry in directory.into_iter() {
|
||||
let file_entry = file_entry.map_err(InputsDirectoryError::GettingFileEntry)?;
|
||||
let file_path = file_entry.path();
|
||||
|
||||
// Verify that the entry is structured as a valid file or directory
|
||||
let file_type = file_entry
|
||||
.file_type()
|
||||
.map_err(|error| InputsDirectoryError::GettingFileType(file_path.as_os_str().to_owned(), error))?;
|
||||
if file_type.is_dir() {
|
||||
let directory = fs::read_dir(&file_path).map_err(InputsDirectoryError::Reading)?;
|
||||
|
||||
parse_file_paths(directory, file_paths)?;
|
||||
continue;
|
||||
} else if !file_type.is_file() {
|
||||
return Err(InputsDirectoryError::InvalidFileType(
|
||||
file_path.as_os_str().to_owned(),
|
||||
file_type,
|
||||
));
|
||||
}
|
||||
|
||||
file_paths.push(file_path);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -4,5 +4,8 @@ pub use directory::*;
|
||||
pub mod input;
|
||||
pub use input::*;
|
||||
|
||||
pub mod pairs;
|
||||
pub use pairs::*;
|
||||
|
||||
pub mod state;
|
||||
pub use state::*;
|
||||
|
79
package/src/inputs/pairs.rs
Normal file
79
package/src/inputs/pairs.rs
Normal file
@ -0,0 +1,79 @@
|
||||
use crate::{
|
||||
inputs::{InputFile, InputsDirectory, StateFile, INPUT_FILE_EXTENSION, STATE_FILE_EXTENSION},
|
||||
InputsDirectoryError,
|
||||
};
|
||||
|
||||
use std::{collections::HashMap, convert::TryFrom, path::PathBuf};
|
||||
|
||||
pub struct InputPairs {
|
||||
/// Maps file names to input file pairs
|
||||
pub pairs: HashMap<String, InputPair>,
|
||||
}
|
||||
|
||||
pub struct InputPair {
|
||||
pub input_file: String,
|
||||
pub state_file: String,
|
||||
}
|
||||
|
||||
impl InputPairs {
|
||||
pub fn new() -> Self {
|
||||
Self { pairs: HashMap::new() }
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&PathBuf> for InputPairs {
|
||||
type Error = InputsDirectoryError;
|
||||
|
||||
fn try_from(directory: &PathBuf) -> Result<Self, Self::Error> {
|
||||
let files = InputsDirectory::files(directory)?;
|
||||
|
||||
let mut pairs = HashMap::<String, InputPair>::new();
|
||||
|
||||
for file in files {
|
||||
let file_extension = file
|
||||
.extension()
|
||||
.ok_or_else(|| InputsDirectoryError::GettingFileExtension(file.as_os_str().to_owned()))?;
|
||||
|
||||
let file_name = file
|
||||
.file_stem()
|
||||
.ok_or(InputsDirectoryError::GettingFileName(file.as_os_str().to_owned()))?
|
||||
.to_str()
|
||||
.ok_or(InputsDirectoryError::GettingFileName(file.as_os_str().to_owned()))?;
|
||||
|
||||
if file_extension == INPUT_FILE_EXTENSION.trim_start_matches(".") {
|
||||
let input_file = InputFile::new(file_name).read_from(&file)?;
|
||||
|
||||
if pairs.contains_key(file_name) {
|
||||
let pair = pairs.get_mut(file_name).unwrap();
|
||||
pair.input_file = input_file;
|
||||
} else {
|
||||
let pair = InputPair {
|
||||
input_file,
|
||||
state_file: "".to_owned(),
|
||||
};
|
||||
pairs.insert(file_name.to_owned(), pair);
|
||||
}
|
||||
} else if file_extension == STATE_FILE_EXTENSION.trim_start_matches(".") {
|
||||
let state_file = StateFile::new(file_name).read_from(&file)?;
|
||||
|
||||
if pairs.contains_key(file_name) {
|
||||
let pair = pairs.get_mut(file_name).unwrap();
|
||||
pair.state_file = state_file;
|
||||
} else {
|
||||
let pair = InputPair {
|
||||
input_file: "".to_owned(),
|
||||
state_file,
|
||||
};
|
||||
pairs.insert(file_name.to_owned(), pair);
|
||||
}
|
||||
} else {
|
||||
return Err(InputsDirectoryError::InvalidFileExtension(
|
||||
file_name.to_owned(),
|
||||
file_extension.to_owned(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(InputPairs { pairs })
|
||||
}
|
||||
}
|
27
state/Cargo.toml
Normal file
27
state/Cargo.toml
Normal file
@ -0,0 +1,27 @@
|
||||
[package]
|
||||
name = "leo-state"
|
||||
version = "0.1.0"
|
||||
authors = ["The Aleo Team <hello@aleo.org>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
leo-input = { path = "../input", version = "0.1.0" }
|
||||
leo-typed = { path = "../typed", version = "0.1.0" }
|
||||
|
||||
snarkos-algorithms = { git = "ssh://git@github.com/AleoHQ/snarkOS.git", package = "snarkos-algorithms", default-features = false }
|
||||
snarkos-curves = { git = "ssh://git@github.com/AleoHQ/snarkOS.git", package = "snarkos-curves", default-features = false }
|
||||
snarkos-dpc = { git = "ssh://git@github.com/AleoHQ/snarkOS.git", package = "snarkos-dpc", default-features = false }
|
||||
snarkos-errors = { git = "ssh://git@github.com/AleoHQ/snarkOS.git", package = "snarkos-errors", default-features = false }
|
||||
snarkos-models = { git = "ssh://git@github.com/AleoHQ/snarkOS.git", package = "snarkos-models", default-features = false }
|
||||
snarkos-objects = { git = "ssh://git@github.com/AleoHQ/snarkOS.git", package = "snarkos-objects" }
|
||||
snarkos-utilities = { git = "ssh://git@github.com/AleoHQ/snarkOS.git", package = "snarkos-utilities" }
|
||||
|
||||
|
||||
rand = { version = "0.7" }
|
||||
rand_xorshift = { version = "0.2" }
|
||||
thiserror = { version = "1.0" }
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
snarkos-storage = { git = "ssh://git@github.com/AleoHQ/snarkOS.git", package = "snarkos-storage" }
|
||||
|
20
state/src/errors/dpc_record_values.rs
Normal file
20
state/src/errors/dpc_record_values.rs
Normal file
@ -0,0 +1,20 @@
|
||||
use crate::InputValueError;
|
||||
|
||||
use snarkos_errors::objects::account::AccountError;
|
||||
|
||||
use std::{num::ParseIntError, str::ParseBoolError};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum DPCRecordValuesError {
|
||||
#[error("{}", _0)]
|
||||
AccountError(#[from] AccountError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
InputValueError(#[from] InputValueError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
ParseBoolError(#[from] ParseBoolError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
ParseIntError(#[from] ParseIntError),
|
||||
}
|
16
state/src/errors/input_value.rs
Normal file
16
state/src/errors/input_value.rs
Normal file
@ -0,0 +1,16 @@
|
||||
use std::num::ParseIntError;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum InputValueError {
|
||||
#[error("expected parameter array of u8 bytes, found `{}`", _0)]
|
||||
ExpectedBytes(String),
|
||||
|
||||
#[error("expected integer parameter, found `{}`", _0)]
|
||||
ExpectedInteger(String),
|
||||
|
||||
#[error("input parameter `{}` not found in state file", _0)]
|
||||
MissingParameter(String),
|
||||
|
||||
#[error("{}", _0)]
|
||||
ParseIntError(#[from] ParseIntError),
|
||||
}
|
26
state/src/errors/local_data_commitment.rs
Normal file
26
state/src/errors/local_data_commitment.rs
Normal file
@ -0,0 +1,26 @@
|
||||
use crate::{RecordVerificationError, StateLeafValuesError, StateValuesError};
|
||||
|
||||
use snarkos_errors::algorithms::{CommitmentError, MerkleError};
|
||||
|
||||
use std::io::Error as IOError;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum LocalDataVerificationError {
|
||||
#[error("{}", _0)]
|
||||
CommitmentError(#[from] CommitmentError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
MerkleError(#[from] MerkleError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
IOError(#[from] IOError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
RecordVerificationError(#[from] RecordVerificationError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
StateLeafValuesError(#[from] StateLeafValuesError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
StateValuesError(#[from] StateValuesError),
|
||||
}
|
17
state/src/errors/mod.rs
Normal file
17
state/src/errors/mod.rs
Normal file
@ -0,0 +1,17 @@
|
||||
pub mod dpc_record_values;
|
||||
pub use self::dpc_record_values::*;
|
||||
|
||||
pub mod input_value;
|
||||
pub use self::input_value::*;
|
||||
|
||||
pub mod state_leaf_values;
|
||||
pub use self::state_leaf_values::*;
|
||||
|
||||
pub mod state_values;
|
||||
pub use self::state_values::*;
|
||||
|
||||
pub mod local_data_commitment;
|
||||
pub use self::local_data_commitment::*;
|
||||
|
||||
pub mod record_commitment;
|
||||
pub use self::record_commitment::*;
|
20
state/src/errors/record_commitment.rs
Normal file
20
state/src/errors/record_commitment.rs
Normal file
@ -0,0 +1,20 @@
|
||||
use crate::DPCRecordValuesError;
|
||||
|
||||
use snarkos_errors::algorithms::CommitmentError;
|
||||
|
||||
use std::io::Error as IOError;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum RecordVerificationError {
|
||||
#[error("record commitment does not match record data")]
|
||||
CommitmentsDoNotMatch,
|
||||
|
||||
#[error("{}", _0)]
|
||||
CommitmentError(#[from] CommitmentError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
DPCRecordValuesError(#[from] DPCRecordValuesError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
IOError(#[from] IOError),
|
||||
}
|
15
state/src/errors/state_leaf_values.rs
Normal file
15
state/src/errors/state_leaf_values.rs
Normal file
@ -0,0 +1,15 @@
|
||||
use crate::InputValueError;
|
||||
|
||||
use std::{num::ParseIntError, str::ParseBoolError};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum StateLeafValuesError {
|
||||
#[error("{}", _0)]
|
||||
InputValueError(#[from] InputValueError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
ParseBoolError(#[from] ParseBoolError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
ParseIntError(#[from] ParseIntError),
|
||||
}
|
15
state/src/errors/state_values.rs
Normal file
15
state/src/errors/state_values.rs
Normal file
@ -0,0 +1,15 @@
|
||||
use crate::InputValueError;
|
||||
|
||||
use std::{num::ParseIntError, str::ParseBoolError};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum StateValuesError {
|
||||
#[error("{}", _0)]
|
||||
InputValueError(#[from] InputValueError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
ParseBoolError(#[from] ParseBoolError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
ParseIntError(#[from] ParseIntError),
|
||||
}
|
14
state/src/lib.rs
Normal file
14
state/src/lib.rs
Normal file
@ -0,0 +1,14 @@
|
||||
#[macro_use]
|
||||
extern crate thiserror;
|
||||
|
||||
pub mod errors;
|
||||
pub use self::errors::*;
|
||||
|
||||
pub mod local_data_commitment;
|
||||
pub use self::local_data_commitment::*;
|
||||
|
||||
pub mod record_commitment;
|
||||
pub use self::record_commitment::*;
|
||||
|
||||
pub mod utilities;
|
||||
pub use self::utilities::*;
|
69
state/src/local_data_commitment/local_data_commitment.rs
Normal file
69
state/src/local_data_commitment/local_data_commitment.rs
Normal file
@ -0,0 +1,69 @@
|
||||
use crate::{verify_record_commitment, LocalDataVerificationError, StateLeafValues, StateValues};
|
||||
use leo_typed::Input as TypedInput;
|
||||
|
||||
use snarkos_algorithms::commitment_tree::CommitmentMerklePath;
|
||||
use snarkos_dpc::base_dpc::{
|
||||
instantiated::{Components, LocalDataCRH, LocalDataCommitment},
|
||||
parameters::SystemParameters,
|
||||
};
|
||||
use snarkos_models::{
|
||||
algorithms::{CommitmentScheme, CRH},
|
||||
dpc::DPCComponents,
|
||||
};
|
||||
use snarkos_utilities::{bytes::ToBytes, to_bytes, FromBytes};
|
||||
|
||||
use std::convert::TryFrom;
|
||||
|
||||
pub fn verify_local_data_commitment(
|
||||
system_parameters: &SystemParameters<Components>,
|
||||
typed_input: &TypedInput,
|
||||
) -> Result<bool, LocalDataVerificationError> {
|
||||
// verify record commitment
|
||||
let typed_record = typed_input.get_record();
|
||||
let dpc_record_values = verify_record_commitment(system_parameters, typed_record)?;
|
||||
let record_commitment: Vec<u8> = dpc_record_values.commitment;
|
||||
let record_serial_number: Vec<u8> = dpc_record_values.serial_number;
|
||||
|
||||
// parse typed state values
|
||||
let typed_state = typed_input.get_state();
|
||||
let state_values = StateValues::try_from(typed_state)?;
|
||||
let leaf_index: u32 = state_values.leaf_index;
|
||||
let root: Vec<u8> = state_values.root;
|
||||
|
||||
// parse typed state leaf values
|
||||
let typed_state_leaf = typed_input.get_state_leaf();
|
||||
let state_leaf_values = StateLeafValues::try_from(typed_state_leaf)?;
|
||||
let path: Vec<u8> = state_leaf_values.path;
|
||||
let memo: Vec<u8> = state_leaf_values.memo;
|
||||
let network_id: u8 = state_leaf_values.network_id;
|
||||
let leaf_randomness: Vec<u8> = state_leaf_values.leaf_randomness;
|
||||
|
||||
// Select local data commitment input bytes
|
||||
let is_death = leaf_index < (Components::NUM_INPUT_RECORDS as u32);
|
||||
let input_bytes = if is_death {
|
||||
to_bytes![record_serial_number, record_commitment, memo, network_id]?
|
||||
} else {
|
||||
to_bytes![record_commitment, memo, network_id]?
|
||||
};
|
||||
|
||||
// Construct local data commitment leaf
|
||||
let local_data_leaf_randomness = <LocalDataCommitment as CommitmentScheme>::Randomness::read(&leaf_randomness[..])?;
|
||||
let local_data_commitment_leaf = LocalDataCommitment::commit(
|
||||
&system_parameters.local_data_commitment,
|
||||
&input_bytes,
|
||||
&local_data_leaf_randomness,
|
||||
)?;
|
||||
|
||||
// Construct record commitment merkle path
|
||||
let local_data_merkle_path = CommitmentMerklePath::<LocalDataCommitment, LocalDataCRH>::read(&path[..])?;
|
||||
|
||||
// Check record commitment merkle path is valid for the given local data commitment root
|
||||
let local_data_commitment_root = <LocalDataCRH as CRH>::Output::read(&root[..])?;
|
||||
let result = local_data_merkle_path.verify(
|
||||
&system_parameters.local_data_crh,
|
||||
&local_data_commitment_root,
|
||||
&local_data_commitment_leaf,
|
||||
)?;
|
||||
|
||||
Ok(result)
|
||||
}
|
8
state/src/local_data_commitment/mod.rs
Normal file
8
state/src/local_data_commitment/mod.rs
Normal file
@ -0,0 +1,8 @@
|
||||
pub mod state_values;
|
||||
pub use self::state_values::*;
|
||||
|
||||
pub mod state_leaf_values;
|
||||
pub use self::state_leaf_values::*;
|
||||
|
||||
pub mod local_data_commitment;
|
||||
pub use self::local_data_commitment::*;
|
47
state/src/local_data_commitment/state_leaf_values.rs
Normal file
47
state/src/local_data_commitment/state_leaf_values.rs
Normal file
@ -0,0 +1,47 @@
|
||||
use crate::{find_input, input_to_integer_string, input_to_u8_vec, StateLeafValuesError};
|
||||
use leo_typed::StateLeaf as TypedStateLeaf;
|
||||
|
||||
use std::convert::TryFrom;
|
||||
|
||||
static PATH_PARAMETER_STRING: &str = "path";
|
||||
static MEMO_PARAMETER_STRING: &str = "memo";
|
||||
static NETWORK_ID_PARAMETER_STRING: &str = "network_id";
|
||||
static LEAF_RANDOMNESS_PARAMETER_STRING: &str = "leaf_randomness";
|
||||
|
||||
pub struct StateLeafValues {
|
||||
pub path: Vec<u8>,
|
||||
pub memo: Vec<u8>,
|
||||
pub network_id: u8,
|
||||
pub leaf_randomness: Vec<u8>,
|
||||
}
|
||||
|
||||
impl TryFrom<&TypedStateLeaf> for StateLeafValues {
|
||||
type Error = StateLeafValuesError;
|
||||
|
||||
fn try_from(state_leaf: &TypedStateLeaf) -> Result<Self, Self::Error> {
|
||||
let parameters = state_leaf.values();
|
||||
|
||||
// Lookup path
|
||||
let path_value = find_input(PATH_PARAMETER_STRING.to_owned(), ¶meters)?;
|
||||
let path = input_to_u8_vec(path_value)?;
|
||||
|
||||
// Lookup memo
|
||||
let memo_value = find_input(MEMO_PARAMETER_STRING.to_owned(), ¶meters)?;
|
||||
let memo = input_to_u8_vec(memo_value)?;
|
||||
|
||||
// Lookup network id
|
||||
let network_id_value = find_input(NETWORK_ID_PARAMETER_STRING.to_owned(), ¶meters)?;
|
||||
let network_id = input_to_integer_string(network_id_value)?.parse::<u8>()?;
|
||||
|
||||
// Lookup leaf randomness
|
||||
let leaf_randomness_value = find_input(LEAF_RANDOMNESS_PARAMETER_STRING.to_owned(), ¶meters)?;
|
||||
let leaf_randomness = input_to_u8_vec(leaf_randomness_value)?;
|
||||
|
||||
Ok(Self {
|
||||
path,
|
||||
memo,
|
||||
network_id,
|
||||
leaf_randomness,
|
||||
})
|
||||
}
|
||||
}
|
30
state/src/local_data_commitment/state_values.rs
Normal file
30
state/src/local_data_commitment/state_values.rs
Normal file
@ -0,0 +1,30 @@
|
||||
use crate::{find_input, input_to_integer_string, input_to_u8_vec, StateValuesError};
|
||||
use leo_typed::State as TypedState;
|
||||
|
||||
use std::convert::TryFrom;
|
||||
|
||||
static LEAF_INDEX_PARAMETER_STRING: &str = "leaf_index";
|
||||
static ROOT_PARAMETER_STRING: &str = "root";
|
||||
|
||||
pub struct StateValues {
|
||||
pub leaf_index: u32,
|
||||
pub root: Vec<u8>,
|
||||
}
|
||||
|
||||
impl TryFrom<&TypedState> for StateValues {
|
||||
type Error = StateValuesError;
|
||||
|
||||
fn try_from(state: &TypedState) -> Result<Self, Self::Error> {
|
||||
let parameters = state.values();
|
||||
|
||||
// Lookup leaf index
|
||||
let leaf_index_value = find_input(LEAF_INDEX_PARAMETER_STRING.to_owned(), ¶meters)?;
|
||||
let leaf_index = input_to_integer_string(leaf_index_value)?.parse::<u32>()?;
|
||||
|
||||
// Lookup root
|
||||
let root_value = find_input(ROOT_PARAMETER_STRING.to_owned(), ¶meters)?;
|
||||
let root = input_to_u8_vec(root_value)?;
|
||||
|
||||
Ok(Self { leaf_index, root })
|
||||
}
|
||||
}
|
92
state/src/record_commitment/dpc_record_values.rs
Normal file
92
state/src/record_commitment/dpc_record_values.rs
Normal file
@ -0,0 +1,92 @@
|
||||
use crate::{utilities::*, DPCRecordValuesError};
|
||||
use leo_typed::Record as TypedRecord;
|
||||
|
||||
use snarkos_dpc::base_dpc::instantiated::Components;
|
||||
use snarkos_objects::AccountAddress;
|
||||
|
||||
use std::{convert::TryFrom, str::FromStr};
|
||||
|
||||
static SERIAL_NUMBER_PARAMETER_STRING: &str = "serial_number";
|
||||
static OWNER_PARAMETER_STRING: &str = "owner";
|
||||
static IS_DUMMY_PARAMETER_STRING: &str = "is_dummy";
|
||||
static VALUE_PARAMETER_STRING: &str = "value";
|
||||
static PAYLOAD_PARAMETER_STRING: &str = "payload";
|
||||
static BIRTH_PROGRAM_ID_PARAMETER_STRING: &str = "birth_program_id";
|
||||
static DEATH_PROGRAM_ID_PARAMETER_STRING: &str = "death_program_id";
|
||||
static SERIAL_NUMBER_NONCE_PARAMETER_STRING: &str = "serial_number_nonce";
|
||||
static COMMITMENT_PARAMETER_STRING: &str = "commitment";
|
||||
static COMMITMENT_RANDOMNESS_PARAMETER_STRING: &str = "commitment_randomness";
|
||||
|
||||
pub struct DPCRecordValues {
|
||||
pub serial_number: Vec<u8>,
|
||||
pub owner: AccountAddress<Components>,
|
||||
pub is_dummy: bool,
|
||||
pub value: u64,
|
||||
pub payload: Vec<u8>,
|
||||
pub birth_program_id: Vec<u8>,
|
||||
pub death_program_id: Vec<u8>,
|
||||
pub serial_number_nonce: Vec<u8>,
|
||||
pub commitment: Vec<u8>,
|
||||
pub commitment_randomness: Vec<u8>,
|
||||
}
|
||||
|
||||
impl TryFrom<&TypedRecord> for DPCRecordValues {
|
||||
type Error = DPCRecordValuesError;
|
||||
|
||||
fn try_from(record: &TypedRecord) -> Result<Self, Self::Error> {
|
||||
let parameters = record.values();
|
||||
|
||||
// Lookup serial number
|
||||
let serial_number_value = find_input(SERIAL_NUMBER_PARAMETER_STRING.to_owned(), ¶meters)?;
|
||||
let serial_number = input_to_u8_vec(serial_number_value)?;
|
||||
|
||||
// Lookup record owner
|
||||
let owner_value = find_input(OWNER_PARAMETER_STRING.to_owned(), ¶meters)?;
|
||||
let owner = AccountAddress::<Components>::from_str(&format!("{}", owner_value))?;
|
||||
|
||||
// Lookup record is_dummy
|
||||
let is_dummy_value = find_input(IS_DUMMY_PARAMETER_STRING.to_owned(), ¶meters)?;
|
||||
let is_dummy = is_dummy_value.to_string().parse::<bool>()?;
|
||||
|
||||
// Lookup record value
|
||||
let value_value = find_input(VALUE_PARAMETER_STRING.to_owned(), ¶meters)?;
|
||||
let value = input_to_integer_string(value_value)?.parse::<u64>()?;
|
||||
|
||||
// Lookup record payload
|
||||
let payload_value = find_input(PAYLOAD_PARAMETER_STRING.to_owned(), ¶meters)?;
|
||||
let payload = input_to_u8_vec(payload_value)?;
|
||||
|
||||
// Lookup record birth program id
|
||||
let birth_program_id_value = find_input(BIRTH_PROGRAM_ID_PARAMETER_STRING.to_owned(), ¶meters)?;
|
||||
let birth_program_id = input_to_u8_vec(birth_program_id_value)?;
|
||||
|
||||
// Lookup record death program id
|
||||
let death_program_id_value = find_input(DEATH_PROGRAM_ID_PARAMETER_STRING.to_owned(), ¶meters)?;
|
||||
let death_program_id = input_to_u8_vec(death_program_id_value)?;
|
||||
|
||||
// Lookup record serial number nonce
|
||||
let serial_number_nonce_value = find_input(SERIAL_NUMBER_NONCE_PARAMETER_STRING.to_owned(), ¶meters)?;
|
||||
let serial_number_nonce = input_to_u8_vec(serial_number_nonce_value)?;
|
||||
|
||||
// Lookup record commitment
|
||||
let commitment_value = find_input(COMMITMENT_PARAMETER_STRING.to_owned(), ¶meters)?;
|
||||
let commitment = input_to_u8_vec(commitment_value)?;
|
||||
|
||||
// Lookup record commitment randomness
|
||||
let commitment_randomness_value = find_input(COMMITMENT_RANDOMNESS_PARAMETER_STRING.to_owned(), ¶meters)?;
|
||||
let commitment_randomness = input_to_u8_vec(commitment_randomness_value)?;
|
||||
|
||||
Ok(Self {
|
||||
serial_number,
|
||||
owner,
|
||||
is_dummy,
|
||||
value,
|
||||
payload,
|
||||
birth_program_id,
|
||||
death_program_id,
|
||||
serial_number_nonce,
|
||||
commitment,
|
||||
commitment_randomness,
|
||||
})
|
||||
}
|
||||
}
|
5
state/src/record_commitment/mod.rs
Normal file
5
state/src/record_commitment/mod.rs
Normal file
@ -0,0 +1,5 @@
|
||||
pub mod dpc_record_values;
|
||||
pub use self::dpc_record_values::*;
|
||||
|
||||
pub mod record_commitment;
|
||||
pub use self::record_commitment::*;
|
46
state/src/record_commitment/record_commitment.rs
Normal file
46
state/src/record_commitment/record_commitment.rs
Normal file
@ -0,0 +1,46 @@
|
||||
use crate::{DPCRecordValues, RecordVerificationError};
|
||||
use leo_typed::Record as TypedRecord;
|
||||
|
||||
use snarkos_dpc::base_dpc::{
|
||||
instantiated::{Components, RecordCommitment},
|
||||
parameters::SystemParameters,
|
||||
};
|
||||
use snarkos_models::algorithms::CommitmentScheme;
|
||||
use snarkos_utilities::{bytes::ToBytes, to_bytes, FromBytes};
|
||||
|
||||
use std::convert::TryFrom;
|
||||
|
||||
pub fn verify_record_commitment(
|
||||
system_parameters: &SystemParameters<Components>,
|
||||
typed_record: &TypedRecord,
|
||||
) -> Result<DPCRecordValues, RecordVerificationError> {
|
||||
// generate a dpc record from the typed record
|
||||
let record = DPCRecordValues::try_from(typed_record)?;
|
||||
|
||||
// verify record commitment
|
||||
let record_commitment_input = to_bytes![
|
||||
record.owner,
|
||||
record.is_dummy,
|
||||
record.value,
|
||||
record.payload,
|
||||
record.birth_program_id,
|
||||
record.death_program_id,
|
||||
record.serial_number_nonce
|
||||
]?;
|
||||
|
||||
let commitment = <RecordCommitment as CommitmentScheme>::Output::read(&record.commitment[..])?;
|
||||
let commitment_randomness =
|
||||
<RecordCommitment as CommitmentScheme>::Randomness::read(&record.commitment_randomness[..])?;
|
||||
|
||||
let record_commitment = RecordCommitment::commit(
|
||||
&system_parameters.record_commitment,
|
||||
&record_commitment_input,
|
||||
&commitment_randomness,
|
||||
)?;
|
||||
|
||||
if record_commitment == commitment {
|
||||
Ok(record)
|
||||
} else {
|
||||
Err(RecordVerificationError::CommitmentsDoNotMatch)
|
||||
}
|
||||
}
|
63
state/src/utilities/input_value.rs
Normal file
63
state/src/utilities/input_value.rs
Normal file
@ -0,0 +1,63 @@
|
||||
use crate::InputValueError;
|
||||
use leo_typed::{InputValue, Parameter};
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub fn find_input(
|
||||
name: String,
|
||||
parameters: &HashMap<Parameter, Option<InputValue>>,
|
||||
) -> Result<InputValue, InputValueError> {
|
||||
let matched_parameter = parameters
|
||||
.iter()
|
||||
.find(|(parameter, _value)| parameter.variable.name == name);
|
||||
|
||||
match matched_parameter {
|
||||
Some((_parameter, value_option)) => match value_option {
|
||||
Some(value) => Ok(value.clone()),
|
||||
None => Err(InputValueError::MissingParameter(name)),
|
||||
},
|
||||
None => Err(InputValueError::MissingParameter(name)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn input_to_integer_string(input: InputValue) -> Result<String, InputValueError> {
|
||||
match input {
|
||||
InputValue::Integer(_type, string) => Ok(string),
|
||||
value => Err(InputValueError::ExpectedInteger(value.to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn input_to_u8_vec(input: InputValue) -> Result<Vec<u8>, InputValueError> {
|
||||
let input_array = match input {
|
||||
InputValue::Array(values) => values,
|
||||
value => return Err(InputValueError::ExpectedBytes(value.to_string())),
|
||||
};
|
||||
|
||||
let mut result_vec = vec![];
|
||||
|
||||
for input in input_array {
|
||||
let integer_string = input_to_integer_string(input)?;
|
||||
let byte = integer_string.parse::<u8>()?;
|
||||
|
||||
result_vec.push(byte);
|
||||
}
|
||||
|
||||
Ok(result_vec)
|
||||
}
|
||||
|
||||
pub fn input_to_nested_u8_vec(input: InputValue) -> Result<Vec<Vec<u8>>, InputValueError> {
|
||||
let inner_arrays = match input {
|
||||
InputValue::Array(arrays) => arrays,
|
||||
value => return Err(InputValueError::ExpectedBytes(value.to_string())),
|
||||
};
|
||||
|
||||
let mut result_vec = vec![];
|
||||
|
||||
for input_array in inner_arrays {
|
||||
let array = input_to_u8_vec(input_array)?;
|
||||
|
||||
result_vec.push(array);
|
||||
}
|
||||
|
||||
Ok(result_vec)
|
||||
}
|
2
state/src/utilities/mod.rs
Normal file
2
state/src/utilities/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod input_value;
|
||||
pub use self::input_value::*;
|
23
state/tests/inputs/test_record.state
Normal file
23
state/tests/inputs/test_record.state
Normal file
@ -0,0 +1,23 @@
|
||||
[[public]]
|
||||
[state]
|
||||
leaf_index: u32 = 0;
|
||||
root: u8[32] = [0u8; 32];
|
||||
|
||||
[[private]]
|
||||
[record]
|
||||
serial_number: u8[32] = [0u8; 32];
|
||||
commitment: u8[32] = [24, 156, 6, 189, 180, 191, 65, 243, 196, 227, 127, 239, 207, 46, 119, 151, 6, 98, 159, 197, 6, 239, 1, 149, 94, 119, 37, 190, 168, 146, 198, 6];
|
||||
owner: address = aleo1daxej63vwrmn2zhl4dymygagh89k5d2vaw6rjauueme7le6k2q8sjn0ng9;
|
||||
is_dummy: bool = false;
|
||||
value: u64 = 13895627391323573723;
|
||||
payload: u8[32] = [235, 120, 28, 41, 42, 46, 237, 32, 50, 70, 185, 70, 180, 174, 198, 169, 149, 118, 227, 124, 192, 36, 43, 2, 239, 2, 207, 166, 142, 240, 246, 39];
|
||||
birth_program_id: u8[48] = [89, 70, 116, 103, 190, 86, 194, 133, 37, 77, 113, 166, 160, 156, 98, 252, 16, 219, 94, 12, 214, 12, 151, 139, 239, 1, 79, 79, 86, 235, 209, 168, 240, 156, 224, 86, 35, 63, 185, 196, 0, 10, 148, 56, 92, 199, 45, 0];
|
||||
death_program_id: u8[48] = [89, 70, 116, 103, 190, 86, 194, 133, 37, 77, 113, 166, 160, 156, 98, 252, 16, 219, 94, 12, 214, 12, 151, 139, 239, 1, 79, 79, 86, 235, 209, 168, 240, 156, 224, 86, 35, 63, 185, 196, 0, 10, 148, 56, 92, 199, 45, 0];
|
||||
serial_number_nonce: u8[32] = [13, 163, 44, 146, 30, 254, 39, 255, 41, 20, 154, 181, 69, 34, 205, 82, 37, 173, 21, 57, 100, 180, 40, 7, 57, 209, 107, 89, 142, 91, 122, 16];
|
||||
commitment_randomness: u8[32] = [55, 189, 0, 182, 148, 137, 120, 223, 121, 7, 140, 240, 100, 202, 196, 41, 236, 128, 38, 189, 60, 59, 23, 210, 25, 102, 65, 117, 38, 140, 136, 1];
|
||||
|
||||
[state_leaf]
|
||||
path: u8[128] = [0u8; 128];
|
||||
memo: u8[32] = [0u8; 32];
|
||||
network_id: u8 = 0;
|
||||
leaf_randomness: u8[32] = [0u8; 32];
|
23
state/tests/inputs/test_state.state
Normal file
23
state/tests/inputs/test_state.state
Normal file
@ -0,0 +1,23 @@
|
||||
[[public]]
|
||||
[state]
|
||||
leaf_index: u32 = 0;
|
||||
root: u8[32] = [70, 27, 231, 101, 102, 20, 37, 118, 77, 38, 56, 106, 49, 17, 135, 81, 134, 61, 255, 147, 230, 94, 218, 157, 98, 31, 132, 10, 116, 201, 78, 15];
|
||||
|
||||
[[private]]
|
||||
[record]
|
||||
serial_number: u8[64] = [98, 228, 41, 139, 42, 245, 63, 73, 45, 255, 134, 169, 18, 86, 90, 209, 31, 207, 161, 83, 183, 126, 53, 86, 142, 64, 59, 29, 185, 204, 179, 8, 43, 199, 156, 127, 124, 7, 91, 56, 27, 101, 57, 52, 166, 145, 153, 137, 17, 1, 140, 42, 205, 91, 32, 99, 22, 119, 141, 253, 235, 213, 112, 14];
|
||||
commitment: u8[32] = [233, 180, 207, 91, 31, 4, 177, 7, 21, 177, 170, 63, 134, 227, 249, 217, 193, 113, 220, 188, 97, 228, 70, 43, 160, 112, 228, 151, 110, 58, 85, 7];
|
||||
owner: address = aleo1daxej63vwrmn2zhl4dymygagh89k5d2vaw6rjauueme7le6k2q8sjn0ng9;
|
||||
is_dummy: bool = false;
|
||||
value: u64 = 18186969098991041491;
|
||||
payload: u8[32] = [192, 118, 4, 191, 56, 79, 165, 142, 20, 92, 140, 207, 81, 125, 226, 247, 184, 40, 101, 235, 205, 174, 175, 180, 18, 104, 251, 132, 117, 163, 219, 125];
|
||||
birth_program_id: u8[48] = [89, 70, 116, 103, 190, 86, 194, 133, 37, 77, 113, 166, 160, 156, 98, 252, 16, 219, 94, 12, 214, 12, 151, 139, 239, 1, 79, 79, 86, 235, 209, 168, 240, 156, 224, 86, 35, 63, 185, 196, 0, 10, 148, 56, 92, 199, 45, 0];
|
||||
death_program_id: u8[48] = [89, 70, 116, 103, 190, 86, 194, 133, 37, 77, 113, 166, 160, 156, 98, 252, 16, 219, 94, 12, 214, 12, 151, 139, 239, 1, 79, 79, 86, 235, 209, 168, 240, 156, 224, 86, 35, 63, 185, 196, 0, 10, 148, 56, 92, 199, 45, 0];
|
||||
serial_number_nonce: u8[32] = [74, 128, 103, 188, 105, 165, 185, 183, 83, 178, 164, 202, 65, 224, 154, 216, 132, 146, 103, 158, 153, 229, 73, 162, 0, 182, 176, 162, 17, 201, 27, 6];
|
||||
commitment_randomness: u8[32] = [129, 174, 175, 20, 1, 168, 248, 69, 51, 186, 30, 34, 82, 6, 148, 174, 128, 163, 156, 197, 94, 129, 117, 226, 240, 95, 203, 196, 65, 222, 96, 4];
|
||||
|
||||
[state_leaf]
|
||||
path: u8[128] = [144, 36, 140, 16, 110, 109, 215, 172, 251, 234, 246, 145, 192, 60, 79, 255, 58, 199, 52, 107, 224, 235, 152, 27, 232, 42, 96, 225, 170, 62, 118, 12, 8, 205, 94, 96, 200, 133, 229, 122, 179, 198, 124, 104, 197, 86, 67, 1, 52, 61, 168, 92, 201, 240, 61, 116, 221, 76, 172, 83, 174, 194, 118, 5, 221, 106, 153, 186, 50, 200, 155, 245, 255, 253, 169, 40, 236, 88, 58, 147, 46, 160, 55, 132, 157, 0, 134, 15, 40, 223, 53, 175, 220, 13, 222, 15, 143, 179, 79, 184, 75, 238, 87, 199, 102, 168, 167, 60, 232, 62, 64, 107, 12, 182, 200, 155, 107, 138, 224, 193, 233, 221, 54, 96, 206, 191, 83, 9];
|
||||
memo: u8[32] = [0u8; 32];
|
||||
network_id: u8 = 0;
|
||||
leaf_randomness: u8[32] = [102, 202, 135, 202, 235, 133, 143, 160, 137, 212, 216, 158, 17, 44, 104, 126, 157, 109, 93, 213, 174, 57, 194, 113, 75, 184, 26, 204, 143, 131, 95, 1];
|
3
state/tests/mod.rs
Normal file
3
state/tests/mod.rs
Normal file
@ -0,0 +1,3 @@
|
||||
mod test_verify_local_data_commitment;
|
||||
|
||||
mod test_verify_record_commitment;
|
200
state/tests/test_verify_local_data_commitment.rs
Normal file
200
state/tests/test_verify_local_data_commitment.rs
Normal file
@ -0,0 +1,200 @@
|
||||
use leo_input::LeoInputParser;
|
||||
use leo_state::verify_local_data_commitment;
|
||||
use leo_typed::Input;
|
||||
|
||||
use snarkos_dpc::base_dpc::{instantiated::*, record_payload::RecordPayload, DPC};
|
||||
use snarkos_models::{
|
||||
algorithms::{CommitmentScheme, CRH},
|
||||
dpc::Record,
|
||||
objects::AccountScheme,
|
||||
};
|
||||
use snarkos_objects::Account;
|
||||
use snarkos_utilities::{bytes::ToBytes, to_bytes};
|
||||
|
||||
use rand::{Rng, SeedableRng};
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use snarkos_models::dpc::DPCScheme;
|
||||
use snarkos_storage::Ledger;
|
||||
|
||||
#[test]
|
||||
fn test_verify_local_data_commitment_from_file() {
|
||||
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
|
||||
|
||||
// Generate parameters for the record commitment scheme
|
||||
let system_parameters = InstantiatedDPC::generate_system_parameters(&mut rng).unwrap();
|
||||
|
||||
// Load test record state file from `inputs/test.state`
|
||||
let file_bytes = include_bytes!("inputs/test_state.state");
|
||||
let file_string = String::from_utf8_lossy(file_bytes);
|
||||
let file = LeoInputParser::parse_file(&file_string).unwrap();
|
||||
|
||||
let mut program_input = Input::new();
|
||||
program_input.parse_state(file).unwrap();
|
||||
|
||||
// check record state is correct by verifying commitment
|
||||
let result = verify_local_data_commitment(&system_parameters, &program_input).unwrap();
|
||||
|
||||
assert!(result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_generate_values_from_dpc() {
|
||||
type L = Ledger<Tx, CommitmentMerkleParameters>;
|
||||
|
||||
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
|
||||
|
||||
// Specify network_id
|
||||
let network_id: u8 = 0;
|
||||
|
||||
// Generate parameters for the ledger, commitment schemes, CRH, and the
|
||||
// "always-accept" program.
|
||||
let system_parameters = InstantiatedDPC::generate_system_parameters(&mut rng).unwrap();
|
||||
let noop_program_snark_pp =
|
||||
InstantiatedDPC::generate_noop_program_snark_parameters(&system_parameters, &mut rng).unwrap();
|
||||
|
||||
let noop_program_id = to_bytes![
|
||||
ProgramVerificationKeyHash::hash(
|
||||
&system_parameters.program_verification_key_hash,
|
||||
&to_bytes![noop_program_snark_pp.verification_key].unwrap()
|
||||
)
|
||||
.unwrap()
|
||||
]
|
||||
.unwrap();
|
||||
|
||||
let signature_parameters = &system_parameters.account_signature;
|
||||
let commitment_parameters = &system_parameters.account_commitment;
|
||||
let encryption_parameters = &system_parameters.account_encryption;
|
||||
|
||||
// Generate metadata and an account for a dummy initial record.
|
||||
let dummy_account = Account::new(
|
||||
signature_parameters,
|
||||
commitment_parameters,
|
||||
encryption_parameters,
|
||||
&mut rng,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let sn_nonce = SerialNumberNonce::hash(&system_parameters.serial_number_nonce, &[0u8; 1]).unwrap();
|
||||
let value = rng.gen();
|
||||
let payload: [u8; 32] = rng.gen();
|
||||
|
||||
let old_record = DPC::generate_record(
|
||||
&system_parameters,
|
||||
&sn_nonce,
|
||||
&dummy_account.address,
|
||||
false,
|
||||
value,
|
||||
&RecordPayload::from_bytes(&payload),
|
||||
&noop_program_id,
|
||||
&noop_program_id,
|
||||
&mut rng,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Set the input records for our transaction to be the initial dummy records.
|
||||
let old_records = vec![old_record.clone(); NUM_INPUT_RECORDS];
|
||||
let old_account_private_keys = vec![dummy_account.private_key.clone(); NUM_INPUT_RECORDS];
|
||||
|
||||
// Construct new records.
|
||||
|
||||
// Create an account for an actual new record.
|
||||
|
||||
let new_account = Account::new(
|
||||
signature_parameters,
|
||||
commitment_parameters,
|
||||
encryption_parameters,
|
||||
&mut rng,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Set the new record's program to be the "always-accept" program.
|
||||
|
||||
let new_record_owners = vec![new_account.address.clone(); NUM_OUTPUT_RECORDS];
|
||||
let new_is_dummy_flags = vec![false; NUM_OUTPUT_RECORDS];
|
||||
let new_values = vec![10; NUM_OUTPUT_RECORDS];
|
||||
let new_payloads = vec![RecordPayload::default(); NUM_OUTPUT_RECORDS];
|
||||
let new_birth_program_ids = vec![noop_program_id.clone(); NUM_OUTPUT_RECORDS];
|
||||
let new_death_program_ids = vec![noop_program_id.clone(); NUM_OUTPUT_RECORDS];
|
||||
let memo = [0u8; 32];
|
||||
|
||||
let context = <InstantiatedDPC as DPCScheme<L>>::execute_offline(
|
||||
&system_parameters,
|
||||
&old_records,
|
||||
&old_account_private_keys,
|
||||
&new_record_owners,
|
||||
&new_is_dummy_flags,
|
||||
&new_values,
|
||||
&new_payloads,
|
||||
&new_birth_program_ids,
|
||||
&new_death_program_ids,
|
||||
&memo,
|
||||
network_id,
|
||||
&mut rng,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let local_data = context.into_local_data();
|
||||
let leaf_index = 0;
|
||||
let record = &local_data.old_records[leaf_index];
|
||||
|
||||
let root = local_data.local_data_merkle_tree.root();
|
||||
|
||||
let serial_number = local_data.old_serial_numbers[0].clone();
|
||||
let serial_number_bytes = to_bytes![serial_number].unwrap();
|
||||
|
||||
let memorandum = local_data.memorandum;
|
||||
let network_id = local_data.network_id;
|
||||
let input_bytes = to_bytes![serial_number, record.commitment(), memorandum, network_id].unwrap();
|
||||
let leaf_randomness = local_data.local_data_commitment_randomizers[0].clone();
|
||||
|
||||
let old_record_leaf = <LocalDataCommitment as CommitmentScheme>::commit(
|
||||
&system_parameters.local_data_commitment,
|
||||
&input_bytes,
|
||||
&leaf_randomness,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// generate the path
|
||||
|
||||
let path = local_data
|
||||
.local_data_merkle_tree
|
||||
.generate_proof(&old_record_leaf)
|
||||
.unwrap();
|
||||
|
||||
println!("////////////////////////////////////////////////////");
|
||||
println!();
|
||||
println!("[state]");
|
||||
println!("leaf index {}", leaf_index);
|
||||
println!("root {:?}", to_bytes![root].unwrap());
|
||||
println!();
|
||||
println!("[record]");
|
||||
println!(
|
||||
"serial number {:?} len {}",
|
||||
serial_number_bytes,
|
||||
serial_number_bytes.len()
|
||||
);
|
||||
println!("commitment {:?}", to_bytes![record.commitment()].unwrap());
|
||||
println!("owner {}", record.owner());
|
||||
println!("is_dummy {:?}", record.is_dummy());
|
||||
println!("value {:?}", record.value());
|
||||
println!("payload {:?}", record.payload());
|
||||
println!("birth_program_id {:?}", record.birth_program_id());
|
||||
println!("death_program_id {:?}", record.death_program_id());
|
||||
println!(
|
||||
"serial number nonce {:?}",
|
||||
to_bytes![record.serial_number_nonce()].unwrap()
|
||||
);
|
||||
println!(
|
||||
"commitment randomness {:?}",
|
||||
to_bytes![record.commitment_randomness()].unwrap()
|
||||
);
|
||||
println!();
|
||||
println!("[state_leaf]");
|
||||
println!("path {:?}", to_bytes![path].unwrap());
|
||||
println!("memo {:?}", memorandum);
|
||||
println!("network id {:?}", network_id);
|
||||
println!("leaf randomness {:?}", to_bytes![leaf_randomness].unwrap());
|
||||
println!();
|
||||
println!("////////////////////////////////////////////////////");
|
||||
}
|
29
state/tests/test_verify_record_commitment.rs
Normal file
29
state/tests/test_verify_record_commitment.rs
Normal file
@ -0,0 +1,29 @@
|
||||
use leo_input::LeoInputParser;
|
||||
use leo_state::verify_record_commitment;
|
||||
use leo_typed::Input;
|
||||
|
||||
use snarkos_dpc::base_dpc::instantiated::*;
|
||||
|
||||
use rand::SeedableRng;
|
||||
use rand_xorshift::XorShiftRng;
|
||||
|
||||
#[test]
|
||||
fn test_verify_record_from_file() {
|
||||
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
|
||||
|
||||
// Generate parameters for the record commitment scheme
|
||||
let system_parameters = InstantiatedDPC::generate_system_parameters(&mut rng).unwrap();
|
||||
|
||||
// Load test record state file from `inputs/test.state`
|
||||
let file_bytes = include_bytes!("inputs/test_record.state");
|
||||
let file_string = String::from_utf8_lossy(file_bytes);
|
||||
let file = LeoInputParser::parse_file(&file_string).unwrap();
|
||||
|
||||
let mut program_input = Input::new();
|
||||
program_input.parse_state(file).unwrap();
|
||||
|
||||
let typed_record = program_input.get_record();
|
||||
|
||||
// check record state is correct by verifying commitment
|
||||
let _values = verify_record_commitment(&system_parameters, typed_record).unwrap();
|
||||
}
|
58
typed/src/annotation.rs
Normal file
58
typed/src/annotation.rs
Normal file
@ -0,0 +1,58 @@
|
||||
use crate::{Circuit, Function, Identifier, Import, InputVariable, TestFunction};
|
||||
use leo_ast::{
|
||||
annotations::{Annotation, AnnotationArguments, AnnotationName},
|
||||
definitions::{AnnotatedDefinition, Definition},
|
||||
};
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub fn load_annotation(
|
||||
annotated_definition: AnnotatedDefinition,
|
||||
_imports: &mut Vec<Import>,
|
||||
_circuits: &mut HashMap<Identifier, Circuit>,
|
||||
_functions: &mut HashMap<Identifier, Function>,
|
||||
tests: &mut HashMap<Identifier, TestFunction>,
|
||||
_expected: &mut Vec<InputVariable>,
|
||||
) {
|
||||
let ast_annotation = annotated_definition.annotation;
|
||||
let ast_definition = *annotated_definition.definition;
|
||||
|
||||
match ast_definition {
|
||||
Definition::Import(_) => unimplemented!("annotated imports are not supported yet"),
|
||||
Definition::Circuit(_) => unimplemented!("annotated circuits are not supported yet"),
|
||||
Definition::Function(_) => unimplemented!("annotated functions are not supported yet"),
|
||||
Definition::TestFunction(ast_test) => {
|
||||
let test = TestFunction::from(ast_test);
|
||||
load_annotated_test(test, ast_annotation, tests)
|
||||
}
|
||||
Definition::Annotated(_) => unimplemented!("nested annotations are not supported yet"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_annotated_test(test: TestFunction, annotation: Annotation, tests: &mut HashMap<Identifier, TestFunction>) {
|
||||
let name = annotation.name;
|
||||
let ast_arguments = annotation.arguments;
|
||||
|
||||
match name {
|
||||
AnnotationName::Context(_) => load_annotated_test_context(test, ast_arguments, tests),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_annotated_test_context(
|
||||
mut test: TestFunction,
|
||||
ast_arguments: AnnotationArguments,
|
||||
tests: &mut HashMap<Identifier, TestFunction>,
|
||||
) {
|
||||
let arguments = ast_arguments.arguments;
|
||||
|
||||
if arguments.len() != 1 {
|
||||
panic!("text context annotation must have one argument identifier")
|
||||
}
|
||||
|
||||
let ast_input_file = arguments[0].to_owned();
|
||||
let input_file = Identifier::from(ast_input_file);
|
||||
|
||||
test.input_file = Some(input_file);
|
||||
|
||||
tests.insert(test.function.identifier.clone(), test);
|
||||
}
|
@ -1,5 +1,9 @@
|
||||
use crate::Span;
|
||||
use leo_ast::{common::Identifier as AstIdentifier, imports::PackageName as AstPackageName};
|
||||
use leo_ast::{
|
||||
annotations::AnnotationArgument,
|
||||
common::Identifier as AstIdentifier,
|
||||
imports::PackageName as AstPackageName,
|
||||
};
|
||||
use leo_input::common::Identifier as InputAstIdentifier;
|
||||
|
||||
use serde::{
|
||||
@ -55,6 +59,15 @@ impl<'ast> From<InputAstIdentifier<'ast>> for Identifier {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<AnnotationArgument<'ast>> for Identifier {
|
||||
fn from(argument: AnnotationArgument<'ast>) -> Self {
|
||||
Self {
|
||||
name: argument.value,
|
||||
span: Span::from(argument.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Identifier {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.name)
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::{CircuitFieldDefinition, Identifier, IntegerType, RangeOrExpression, Span, SpreadOrExpression};
|
||||
use crate::{CircuitFieldDefinition, GroupValue, Identifier, IntegerType, RangeOrExpression, Span, SpreadOrExpression};
|
||||
use leo_ast::{
|
||||
access::{Access, AssigneeAccess},
|
||||
common::{Assignee, Identifier as AstIdentifier},
|
||||
@ -17,7 +17,7 @@ use leo_ast::{
|
||||
AddressValue,
|
||||
BooleanValue,
|
||||
FieldValue,
|
||||
GroupValue,
|
||||
GroupValue as AstGroupValue,
|
||||
IntegerValue,
|
||||
NumberValue as AstNumber,
|
||||
PositiveNumber as AstPositiveNumber,
|
||||
@ -40,7 +40,7 @@ pub enum Expression {
|
||||
Address(String, Span),
|
||||
Boolean(String, Span),
|
||||
Field(String, Span),
|
||||
Group(String, Span),
|
||||
Group(GroupValue),
|
||||
Implicit(String, Span),
|
||||
Integer(IntegerType, String, Span),
|
||||
|
||||
@ -86,7 +86,7 @@ impl Expression {
|
||||
pub fn set_span(&mut self, new_span: &Span) {
|
||||
match self {
|
||||
Expression::Field(_, old_span) => *old_span = new_span.clone(),
|
||||
Expression::Group(_, old_span) => *old_span = new_span.clone(),
|
||||
Expression::Group(value) => value.span = new_span.clone(),
|
||||
|
||||
Expression::Add(_, _, old_span) => *old_span = new_span.clone(),
|
||||
Expression::Sub(_, _, old_span) => *old_span = new_span.clone(),
|
||||
@ -146,7 +146,7 @@ impl<'ast> fmt::Display for Expression {
|
||||
Expression::Address(ref address, ref _span) => write!(f, "{}", address),
|
||||
Expression::Boolean(ref bool, ref _span) => write!(f, "{}", bool),
|
||||
Expression::Field(ref field, ref _span) => write!(f, "{}", field),
|
||||
Expression::Group(ref group, ref _span) => write!(f, "{}", group),
|
||||
Expression::Group(ref group) => write!(f, "{}", group),
|
||||
Expression::Implicit(ref value, ref _span) => write!(f, "{}", value),
|
||||
Expression::Integer(ref type_, ref integer, ref _span) => write!(f, "{}{}", integer, type_),
|
||||
|
||||
@ -509,9 +509,9 @@ impl<'ast> From<FieldValue<'ast>> for Expression {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GroupValue<'ast>> for Expression {
|
||||
fn from(group: GroupValue<'ast>) -> Self {
|
||||
Expression::Group(group.to_string(), Span::from(group.span))
|
||||
impl<'ast> From<AstGroupValue<'ast>> for Expression {
|
||||
fn from(ast_group: AstGroupValue<'ast>) -> Self {
|
||||
Expression::Group(GroupValue::from(ast_group))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,19 @@
|
||||
use crate::Function;
|
||||
use crate::{Function, Identifier};
|
||||
use leo_ast::functions::TestFunction as AstTestFunction;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct TestFunction(pub Function);
|
||||
pub struct TestFunction {
|
||||
pub function: Function,
|
||||
pub input_file: Option<Identifier>,
|
||||
}
|
||||
|
||||
impl<'ast> From<AstTestFunction<'ast>> for TestFunction {
|
||||
fn from(test: AstTestFunction) -> Self {
|
||||
TestFunction(Function::from(test.function))
|
||||
TestFunction {
|
||||
function: Function::from(test.function),
|
||||
input_file: None, // pass custom input file with `@context` annotation
|
||||
}
|
||||
}
|
||||
}
|
||||
|
113
typed/src/groups/group_coordinate.rs
Normal file
113
typed/src/groups/group_coordinate.rs
Normal file
@ -0,0 +1,113 @@
|
||||
use crate::common::span::Span;
|
||||
use leo_ast::values::{
|
||||
GroupCoordinate as AstGroupCoordinate,
|
||||
Inferred as AstInferred,
|
||||
NumberValue as AstNumberValue,
|
||||
SignHigh as AstSignHigh,
|
||||
SignLow as AstSignLow,
|
||||
};
|
||||
use leo_input::values::{
|
||||
GroupCoordinate as InputGroupCoordinate,
|
||||
Inferred as InputInferred,
|
||||
NumberValue as InputNumberValue,
|
||||
SignHigh as InputSignHigh,
|
||||
SignLow as InputSignLow,
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum GroupCoordinate {
|
||||
Number(String, Span),
|
||||
SignHigh,
|
||||
SignLow,
|
||||
Inferred,
|
||||
}
|
||||
|
||||
impl<'ast> From<AstGroupCoordinate<'ast>> for GroupCoordinate {
|
||||
fn from(coordinate: AstGroupCoordinate<'ast>) -> Self {
|
||||
match coordinate {
|
||||
AstGroupCoordinate::Number(number) => GroupCoordinate::from(number),
|
||||
AstGroupCoordinate::SignHigh(sign_high) => GroupCoordinate::from(sign_high),
|
||||
AstGroupCoordinate::SignLow(sign_low) => GroupCoordinate::from(sign_low),
|
||||
AstGroupCoordinate::Inferred(inferred) => GroupCoordinate::from(inferred),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<InputGroupCoordinate<'ast>> for GroupCoordinate {
|
||||
fn from(coordinate: InputGroupCoordinate<'ast>) -> Self {
|
||||
match coordinate {
|
||||
InputGroupCoordinate::Number(number) => GroupCoordinate::from(number),
|
||||
InputGroupCoordinate::SignHigh(sign_high) => GroupCoordinate::from(sign_high),
|
||||
InputGroupCoordinate::SignLow(sign_low) => GroupCoordinate::from(sign_low),
|
||||
InputGroupCoordinate::Inferred(inferred) => GroupCoordinate::from(inferred),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for GroupCoordinate {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
GroupCoordinate::Number(number, _) => write!(f, "{}", number),
|
||||
GroupCoordinate::SignHigh => write!(f, "+"),
|
||||
GroupCoordinate::SignLow => write!(f, "-"),
|
||||
GroupCoordinate::Inferred => write!(f, "_"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<AstNumberValue<'ast>> for GroupCoordinate {
|
||||
fn from(number: AstNumberValue<'ast>) -> Self {
|
||||
let value = number.to_string();
|
||||
let span = Span::from(number.span().clone());
|
||||
|
||||
GroupCoordinate::Number(value, span)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<AstSignHigh<'ast>> for GroupCoordinate {
|
||||
fn from(_sign: AstSignHigh<'ast>) -> Self {
|
||||
GroupCoordinate::SignHigh
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<AstSignLow<'ast>> for GroupCoordinate {
|
||||
fn from(_sign: AstSignLow<'ast>) -> Self {
|
||||
GroupCoordinate::SignLow
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<AstInferred<'ast>> for GroupCoordinate {
|
||||
fn from(_sign: AstInferred<'ast>) -> Self {
|
||||
GroupCoordinate::Inferred
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<InputNumberValue<'ast>> for GroupCoordinate {
|
||||
fn from(number: InputNumberValue<'ast>) -> Self {
|
||||
let value = number.to_string();
|
||||
let span = Span::from(number.span().clone());
|
||||
|
||||
GroupCoordinate::Number(value, span)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<InputSignHigh<'ast>> for GroupCoordinate {
|
||||
fn from(_sign: InputSignHigh<'ast>) -> Self {
|
||||
GroupCoordinate::SignHigh
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<InputSignLow<'ast>> for GroupCoordinate {
|
||||
fn from(_sign: InputSignLow<'ast>) -> Self {
|
||||
GroupCoordinate::SignLow
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<InputInferred<'ast>> for GroupCoordinate {
|
||||
fn from(_sign: InputInferred<'ast>) -> Self {
|
||||
GroupCoordinate::Inferred
|
||||
}
|
||||
}
|
45
typed/src/groups/group_value.rs
Normal file
45
typed/src/groups/group_value.rs
Normal file
@ -0,0 +1,45 @@
|
||||
use crate::{common::span::Span, groups::GroupCoordinate};
|
||||
use leo_ast::values::GroupValue as AstGroupValue;
|
||||
use leo_input::values::GroupValue as InputGroupValue;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct GroupValue {
|
||||
pub x: GroupCoordinate,
|
||||
pub y: GroupCoordinate,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'ast> From<AstGroupValue<'ast>> for GroupValue {
|
||||
fn from(ast_group: AstGroupValue<'ast>) -> Self {
|
||||
let ast_x = ast_group.value.x;
|
||||
let ast_y = ast_group.value.y;
|
||||
|
||||
Self {
|
||||
x: GroupCoordinate::from(ast_x),
|
||||
y: GroupCoordinate::from(ast_y),
|
||||
span: Span::from(ast_group.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<InputGroupValue<'ast>> for GroupValue {
|
||||
fn from(ast_group: InputGroupValue<'ast>) -> Self {
|
||||
let ast_x = ast_group.value.x;
|
||||
let ast_y = ast_group.value.y;
|
||||
|
||||
Self {
|
||||
x: GroupCoordinate::from(ast_x),
|
||||
y: GroupCoordinate::from(ast_y),
|
||||
span: Span::from(ast_group.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for GroupValue {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "({}, {})", self.x, self.y)
|
||||
}
|
||||
}
|
5
typed/src/groups/mod.rs
Normal file
5
typed/src/groups/mod.rs
Normal file
@ -0,0 +1,5 @@
|
||||
pub mod group_coordinate;
|
||||
pub use self::group_coordinate::*;
|
||||
|
||||
pub mod group_value;
|
||||
pub use self::group_value::*;
|
@ -6,6 +6,7 @@ use leo_input::{
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct Input {
|
||||
name: String,
|
||||
program_input: ProgramInput,
|
||||
program_state: ProgramState,
|
||||
}
|
||||
@ -13,6 +14,7 @@ pub struct Input {
|
||||
impl Input {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
name: "default".to_owned(),
|
||||
program_input: ProgramInput::new(),
|
||||
program_state: ProgramState::new(),
|
||||
}
|
||||
@ -25,6 +27,7 @@ impl Input {
|
||||
let state = self.program_state.empty();
|
||||
|
||||
Self {
|
||||
name: self.name.clone(),
|
||||
program_input: input,
|
||||
program_state: state,
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
use crate::GroupValue;
|
||||
use leo_input::{
|
||||
errors::InputParserError,
|
||||
expressions::{ArrayInitializerExpression, ArrayInlineExpression, Expression},
|
||||
types::{ArrayType, DataType, IntegerType, Type},
|
||||
values::{BooleanValue, FieldValue, GroupValue, NumberValue, Value},
|
||||
values::{BooleanValue, FieldValue, GroupValue as InputGroupValue, NumberValue, Value},
|
||||
};
|
||||
|
||||
use leo_input::{
|
||||
@ -17,7 +18,7 @@ pub enum InputValue {
|
||||
Address(String),
|
||||
Boolean(bool),
|
||||
Field(String),
|
||||
Group(String),
|
||||
Group(GroupValue),
|
||||
Integer(IntegerType, String),
|
||||
Array(Vec<InputValue>),
|
||||
Tuple(Vec<InputValue>),
|
||||
@ -44,8 +45,8 @@ impl InputValue {
|
||||
Ok(InputValue::Integer(integer_type, number))
|
||||
}
|
||||
|
||||
fn from_group(group: GroupValue) -> Self {
|
||||
InputValue::Group(group.to_string())
|
||||
fn from_group(group: InputGroupValue) -> Self {
|
||||
InputValue::Group(GroupValue::from(group))
|
||||
}
|
||||
|
||||
fn from_field(field: FieldValue) -> Self {
|
||||
@ -57,7 +58,7 @@ impl InputValue {
|
||||
DataType::Address(_) => Err(InputParserError::implicit_type(data_type, implicit)),
|
||||
DataType::Boolean(_) => Err(InputParserError::implicit_type(data_type, implicit)),
|
||||
DataType::Integer(integer_type) => InputValue::from_number(integer_type, implicit.to_string()),
|
||||
DataType::Group(_) => Ok(InputValue::Group(implicit.to_string())),
|
||||
DataType::Group(_) => Err(InputParserError::implicit_group(implicit)),
|
||||
DataType::Field(_) => Ok(InputValue::Field(implicit.to_string())),
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
//! A typed syntax tree is represented as a `Program` and consists of import, circuit, and function definitions.
|
||||
//! Each defined type consists of typed statements and expressions.
|
||||
|
||||
pub mod annotation;
|
||||
pub use self::annotation::*;
|
||||
|
||||
pub mod circuits;
|
||||
pub use self::circuits::*;
|
||||
|
||||
@ -16,6 +19,9 @@ pub use self::expression::*;
|
||||
pub mod functions;
|
||||
pub use self::functions::*;
|
||||
|
||||
pub mod groups;
|
||||
pub use self::groups::*;
|
||||
|
||||
pub mod imports;
|
||||
pub use self::imports::*;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! A typed Leo program consists of import, circuit, and function definitions.
|
||||
//! Each defined type consists of typed statements and expressions.
|
||||
|
||||
use crate::{Circuit, Function, Identifier, Import, InputVariable, TestFunction};
|
||||
use crate::{load_annotation, Circuit, Function, Identifier, Import, InputVariable, TestFunction};
|
||||
use leo_ast::{definitions::Definition, files::File};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -47,7 +47,17 @@ impl<'ast> Program {
|
||||
}
|
||||
Definition::TestFunction(test_def) => {
|
||||
let test = TestFunction::from(test_def);
|
||||
tests.insert(test.0.identifier.clone(), test);
|
||||
tests.insert(test.function.identifier.clone(), test);
|
||||
}
|
||||
Definition::Annotated(annotated_definition) => {
|
||||
load_annotation(
|
||||
annotated_definition,
|
||||
&mut imports,
|
||||
&mut circuits,
|
||||
&mut functions,
|
||||
&mut tests,
|
||||
&mut expected_input,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user