mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-09-11 13:56:58 +03:00
Merge pull request #27967 from ProvableHQ/feat/generic-cli
[Feature] Support `--network` selection in CLI.
This commit is contained in:
commit
6ef5b3623f
347
Cargo.lock
generated
347
Cargo.lock
generated
@ -36,17 +36,6 @@ version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "aes"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cipher",
|
||||
"cpufeatures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.11"
|
||||
@ -207,15 +196,6 @@ version = "1.0.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
|
||||
|
||||
[[package]]
|
||||
name = "arbitrary"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110"
|
||||
dependencies = [
|
||||
"derive_arbitrary",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.7"
|
||||
@ -251,7 +231,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.36",
|
||||
"syn 2.0.63",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -262,9 +242,15 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.36",
|
||||
"syn 2.0.63",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atomic-waker"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.3.0"
|
||||
@ -416,7 +402,7 @@ dependencies = [
|
||||
"regex",
|
||||
"rustc-hash",
|
||||
"shlex",
|
||||
"syn 2.0.63",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -498,16 +484,6 @@ version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
|
||||
|
||||
[[package]]
|
||||
name = "bzip2"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8"
|
||||
dependencies = [
|
||||
"bzip2-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bzip2-sys"
|
||||
version = "0.1.11+1.0.8"
|
||||
@ -533,9 +509,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.97"
|
||||
version = "1.0.98"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4"
|
||||
checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
"libc",
|
||||
@ -593,21 +569,11 @@ dependencies = [
|
||||
"half",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cipher"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"inout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "1.7.0"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1"
|
||||
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"libc",
|
||||
@ -645,7 +611,7 @@ dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
"quote 1.0.36",
|
||||
"syn 2.0.63",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -730,21 +696,6 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc"
|
||||
version = "3.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636"
|
||||
dependencies = [
|
||||
"crc-catalog",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc-catalog"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.4.2"
|
||||
@ -911,7 +862,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.36",
|
||||
"syn 2.0.63",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -927,12 +878,6 @@ dependencies = [
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deflate64"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83ace6c86376be0b6cdcf3fb41882e81d94b31587573d1cfa9d01cd06bba210d"
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.7.9"
|
||||
@ -963,17 +908,6 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_arbitrary"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.36",
|
||||
"syn 2.0.63",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "difflib"
|
||||
version = "0.4.0"
|
||||
@ -1032,17 +966,6 @@ dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "displaydoc"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.36",
|
||||
"syn 2.0.63",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "doc-comment"
|
||||
version = "0.3.3"
|
||||
@ -1082,9 +1005,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.11.0"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2"
|
||||
checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b"
|
||||
|
||||
[[package]]
|
||||
name = "encode_unicode"
|
||||
@ -1277,7 +1200,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.36",
|
||||
"syn 2.0.63",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1410,15 +1333,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "816ec7294445779408f36fe57bc5b7fc1cf59664059096c65f905c1c61f58069"
|
||||
checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab"
|
||||
dependencies = [
|
||||
"atomic-waker",
|
||||
"bytes",
|
||||
"fnv",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"futures-util",
|
||||
"http 1.1.0",
|
||||
"indexmap 2.2.6",
|
||||
"slab",
|
||||
@ -1501,15 +1424,6 @@ version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "hmac"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
|
||||
dependencies = [
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "0.2.12"
|
||||
@ -1611,7 +1525,7 @@ dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
"futures-util",
|
||||
"h2 0.4.4",
|
||||
"h2 0.4.5",
|
||||
"http 1.1.0",
|
||||
"http-body 1.0.0",
|
||||
"httparse",
|
||||
@ -1654,9 +1568,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hyper-util"
|
||||
version = "0.1.3"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa"
|
||||
checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
@ -1724,20 +1638,11 @@ version = "2.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5"
|
||||
|
||||
[[package]]
|
||||
name = "inout"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||
checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
@ -1888,6 +1793,7 @@ dependencies = [
|
||||
"leo-package",
|
||||
"leo-parser",
|
||||
"leo-passes",
|
||||
"leo-retriever",
|
||||
"leo-span",
|
||||
"leo-test-framework",
|
||||
"rand",
|
||||
@ -1967,7 +1873,6 @@ dependencies = [
|
||||
"tracing-subscriber",
|
||||
"ureq",
|
||||
"walkdir",
|
||||
"zip 2.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2075,9 +1980,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.154"
|
||||
version = "0.2.155"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
|
||||
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
@ -2116,9 +2021,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libz-sys"
|
||||
version = "1.1.16"
|
||||
version = "1.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e143b5e666b2695d28f6bca6497720813f699c9602dd7f5cac91008b8ada7f9"
|
||||
checksum = "c15da26e5af7e25c90b37a2d75cdbf940cf4a55316de9d84c679c9b8bfabf82e"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
@ -2134,9 +2039,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.13"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
|
||||
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
@ -2148,12 +2053,6 @@ dependencies = [
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lockfree-object-pool"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.21"
|
||||
@ -2179,16 +2078,6 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lzma-rs"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"crc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matchers"
|
||||
version = "0.1.0"
|
||||
@ -2287,9 +2176,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.7.2"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
|
||||
checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
@ -2308,11 +2197,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "native-tls"
|
||||
version = "0.2.11"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e"
|
||||
checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"log",
|
||||
"openssl",
|
||||
@ -2405,7 +2293,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.36",
|
||||
"syn 2.0.63",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2499,7 +2387,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.36",
|
||||
"syn 2.0.63",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2534,9 +2422,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.2"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb"
|
||||
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
@ -2561,16 +2449,6 @@ version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
||||
|
||||
[[package]]
|
||||
name = "pbkdf2"
|
||||
version = "0.12.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
|
||||
dependencies = [
|
||||
"digest",
|
||||
"hmac",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "peeking_take_while"
|
||||
version = "0.1.2"
|
||||
@ -2610,7 +2488,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.36",
|
||||
"syn 2.0.63",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2649,9 +2527,9 @@ checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7"
|
||||
|
||||
[[package]]
|
||||
name = "plotters"
|
||||
version = "0.3.5"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45"
|
||||
checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"plotters-backend",
|
||||
@ -2662,15 +2540,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "plotters-backend"
|
||||
version = "0.3.5"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609"
|
||||
checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7"
|
||||
|
||||
[[package]]
|
||||
name = "plotters-svg"
|
||||
version = "0.3.5"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab"
|
||||
checksum = "81b30686a7d9c3e010b84284bdd26a29f2138574f52f5eb6f794fc0ad924e705"
|
||||
dependencies = [
|
||||
"plotters-backend",
|
||||
]
|
||||
@ -2727,14 +2605,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"syn 2.0.63",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.82"
|
||||
version = "1.0.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b"
|
||||
checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@ -2981,7 +2859,7 @@ dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2 0.4.4",
|
||||
"h2 0.4.5",
|
||||
"http 1.1.0",
|
||||
"http-body 1.0.0",
|
||||
"http-body-util",
|
||||
@ -3134,9 +3012,9 @@ checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d"
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.102.3"
|
||||
version = "0.102.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3bce581c0dd41bce533ce695a1437fa16a7ab5ac3ccfa99fe1a620a7885eabf"
|
||||
checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e"
|
||||
dependencies = [
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
@ -3301,7 +3179,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
"urlencoding",
|
||||
"zip 0.6.6",
|
||||
"zip",
|
||||
"zipsign-api",
|
||||
]
|
||||
|
||||
@ -3328,7 +3206,7 @@ checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.36",
|
||||
"syn 2.0.63",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3408,7 +3286,7 @@ checksum = "82fe9db325bcef1fbcde82e078a5cc4efdf787e96b3b9cf45b50b529f2083d67"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.36",
|
||||
"syn 2.0.63",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3488,12 +3366,6 @@ dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simd-adler32"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
|
||||
|
||||
[[package]]
|
||||
name = "simple_asn1"
|
||||
version = "0.6.2"
|
||||
@ -4748,7 +4620,7 @@ source = "git+https://github.com/AleoNet/snarkVM.git?rev=140ff26#140ff26f87697c2
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.36",
|
||||
"syn 2.0.63",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4821,7 +4693,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.36",
|
||||
"rustversion",
|
||||
"syn 2.0.63",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4854,9 +4726,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.63"
|
||||
version = "2.0.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704"
|
||||
checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.36",
|
||||
@ -4968,7 +4840,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.36",
|
||||
"syn 2.0.63",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5048,9 +4920,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.37.0"
|
||||
version = "1.38.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787"
|
||||
checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
@ -5067,13 +4939,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "2.2.0"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
|
||||
checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.36",
|
||||
"syn 2.0.63",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5234,7 +5106,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.36",
|
||||
"syn 2.0.63",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5457,7 +5329,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote 1.0.36",
|
||||
"syn 2.0.63",
|
||||
"syn 2.0.66",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@ -5491,7 +5363,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.36",
|
||||
"syn 2.0.63",
|
||||
"syn 2.0.66",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@ -5693,9 +5565,9 @@ checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.6.8"
|
||||
version = "0.6.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d"
|
||||
checksum = "86c949fede1d13936a99f14fafd3e76fd642b556dd2ce96287fbe2e0151bfac6"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
@ -5746,7 +5618,7 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.36",
|
||||
"syn 2.0.63",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5766,7 +5638,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.36",
|
||||
"syn 2.0.63",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5781,35 +5653,6 @@ dependencies = [
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zip"
|
||||
version = "2.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "775a2b471036342aa69bc5a602bc889cb0a06cda00477d0c69566757d5553d39"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"arbitrary",
|
||||
"bzip2",
|
||||
"constant_time_eq",
|
||||
"crc32fast",
|
||||
"crossbeam-utils",
|
||||
"deflate64",
|
||||
"displaydoc",
|
||||
"flate2",
|
||||
"hmac",
|
||||
"indexmap 2.2.6",
|
||||
"lzma-rs",
|
||||
"memchr",
|
||||
"pbkdf2",
|
||||
"rand",
|
||||
"sha1",
|
||||
"thiserror",
|
||||
"time",
|
||||
"zeroize",
|
||||
"zopfli",
|
||||
"zstd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zipsign-api"
|
||||
version = "0.1.1"
|
||||
@ -5819,45 +5662,3 @@ dependencies = [
|
||||
"ed25519-dalek",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zopfli"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5019f391bac5cf252e93bbcc53d039ffd62c7bfb7c150414d61369afe57e946"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"crc32fast",
|
||||
"lockfree-object-pool",
|
||||
"log",
|
||||
"once_cell",
|
||||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a"
|
||||
dependencies = [
|
||||
"zstd-safe",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd-safe"
|
||||
version = "7.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a"
|
||||
dependencies = [
|
||||
"zstd-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd-sys"
|
||||
version = "2.0.10+zstd.1.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
@ -176,9 +176,6 @@ version = "0.1"
|
||||
version = "0.3.18"
|
||||
features = [ "fmt" ]
|
||||
|
||||
[dependencies.zip]
|
||||
version = "^2.1"
|
||||
|
||||
[dependencies.crossterm]
|
||||
version = "0.27.0"
|
||||
|
||||
|
@ -51,12 +51,15 @@ features = [ ]
|
||||
[dev-dependencies.leo-disassembler]
|
||||
path = "../../utils/disassembler"
|
||||
|
||||
[dev-dependencies.leo-test-framework]
|
||||
path = "../../tests/test-framework"
|
||||
|
||||
[dev-dependencies.leo-package]
|
||||
path = "../../leo/package"
|
||||
|
||||
[dev-dependencies.leo-retriever]
|
||||
path = "../../utils/retriever"
|
||||
|
||||
[dev-dependencies.leo-test-framework]
|
||||
path = "../../tests/test-framework"
|
||||
|
||||
[dev-dependencies.aleo-std-storage]
|
||||
version = "0.1.7"
|
||||
default-features = false
|
||||
|
@ -26,8 +26,6 @@ use std::{
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
type CurrentNetwork = snarkvm::prelude::MainnetV0;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
#[clap(name = "leo parser", about = "Parse Leo AST and store it as a JSON")]
|
||||
struct Opt {
|
||||
@ -40,6 +38,10 @@ struct Opt {
|
||||
/// Whether to print result to STDOUT.
|
||||
#[clap(short, long)]
|
||||
print_stdout: bool,
|
||||
|
||||
/// The network to use. Defaults to mainnet.
|
||||
#[clap(long, default_value = "mainnet")]
|
||||
pub(crate) network: String,
|
||||
}
|
||||
|
||||
fn main() -> Result<(), String> {
|
||||
@ -50,7 +52,15 @@ fn main() -> Result<(), String> {
|
||||
|
||||
Handler::with(|h| {
|
||||
let node_builder = NodeBuilder::default();
|
||||
let ast = leo_parser::parse_ast::<CurrentNetwork>(h, &node_builder, &code.src, code.start_pos)?;
|
||||
let ast = match opt.network.as_str() {
|
||||
"mainnet" => {
|
||||
leo_parser::parse_ast::<snarkvm::prelude::MainnetV0>(h, &node_builder, &code.src, code.start_pos)
|
||||
}
|
||||
"testnet" => {
|
||||
leo_parser::parse_ast::<snarkvm::prelude::TestnetV0>(h, &node_builder, &code.src, code.start_pos)
|
||||
}
|
||||
_ => panic!("Invalid network"),
|
||||
}?;
|
||||
let json = Ast::to_json_string(&ast)?;
|
||||
println!("{json}");
|
||||
Ok(json)
|
||||
|
@ -93,7 +93,7 @@ create_messages!(
|
||||
@backtraced
|
||||
failed_to_load_instructions {
|
||||
args: (error: impl Display),
|
||||
msg: format!("Failed to load compiled Aleo instructions into an Aleo file.\nSnarkVM Error: {error}"),
|
||||
msg: format!("Failed to load compiled Aleo instructions into an Aleo file.\nError: {error}"),
|
||||
help: Some("Generated Aleo instructions have been left in `main.aleo`".to_string()),
|
||||
}
|
||||
|
||||
@ -107,84 +107,84 @@ create_messages!(
|
||||
@backtraced
|
||||
failed_to_execute_build {
|
||||
args: (error: impl Display),
|
||||
msg: format!("Failed to execute the `build` command.\nSnarkVM Error: {error}"),
|
||||
msg: format!("Failed to execute the `build` command.\nError: {error}"),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@backtraced
|
||||
failed_to_execute_new {
|
||||
args: (error: impl Display),
|
||||
msg: format!("Failed to execute the `new` command.\nSnarkVM Error: {error}"),
|
||||
msg: format!("Failed to execute the `new` command.\nError: {error}"),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@backtraced
|
||||
failed_to_execute_run {
|
||||
args: (error: impl Display),
|
||||
msg: format!("Failed to execute the `run` command.\nSnarkVM Error: {error}"),
|
||||
msg: format!("Failed to execute the `run` command.\nError: {error}"),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@backtraced
|
||||
failed_to_execute_node {
|
||||
args: (error: impl Display),
|
||||
msg: format!("Failed to execute the `node` command.\nSnarkVM Error: {error}"),
|
||||
msg: format!("Failed to execute the `node` command.\nError: {error}"),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@backtraced
|
||||
failed_to_execute_deploy {
|
||||
args: (error: impl Display),
|
||||
msg: format!("Failed to execute the `deploy` command.\nSnarkVM Error: {error}"),
|
||||
msg: format!("Failed to execute the `deploy` command.\nError: {error}"),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@backtraced
|
||||
failed_to_parse_new {
|
||||
args: (error: impl Display),
|
||||
msg: format!("Failed to parse the `new` command.\nSnarkVM Error: {error}"),
|
||||
msg: format!("Failed to parse the `new` command.\nError: {error}"),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@backtraced
|
||||
failed_to_parse_run {
|
||||
args: (error: impl Display),
|
||||
msg: format!("Failed to parse the `run` command.\nSnarkVM Error: {error}"),
|
||||
msg: format!("Failed to parse the `run` command.\nError: {error}"),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@backtraced
|
||||
failed_to_parse_node {
|
||||
args: (error: impl Display),
|
||||
msg: format!("Failed to parse the `node` command.\nSnarkVM Error: {error}"),
|
||||
msg: format!("Failed to parse the `node` command.\nError: {error}"),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@backtraced
|
||||
failed_to_parse_deploy {
|
||||
args: (error: impl Display),
|
||||
msg: format!("Failed to parse the `deploy` command.\nSnarkVM Error: {error}"),
|
||||
msg: format!("Failed to parse the `deploy` command.\nError: {error}"),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@backtraced
|
||||
failed_to_parse_execute {
|
||||
args: (error: impl Display),
|
||||
msg: format!("Failed to parse the `execute` command.\nSnarkVM Error: {error}"),
|
||||
msg: format!("Failed to parse the `execute` command.\nError: {error}"),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@backtraced
|
||||
failed_to_execute_execute {
|
||||
args: (error: impl Display),
|
||||
msg: format!("Failed to execute the `execute` command.\nSnarkVM Error: {error}"),
|
||||
msg: format!("Failed to execute the `execute` command.\nError: {error}"),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@backtraced
|
||||
failed_to_parse_seed {
|
||||
args: (error: impl Display),
|
||||
msg: format!("Failed to parse the seed string for account.\nSnarkVM Error: {error}"),
|
||||
msg: format!("Failed to parse the seed string for account.\nError: {error}"),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@ -198,14 +198,14 @@ create_messages!(
|
||||
@backtraced
|
||||
failed_to_parse_private_key {
|
||||
args: (error: impl Display),
|
||||
msg: format!("Failed to parse private key.\nSnarkVM Error: {error}"),
|
||||
msg: format!("Failed to parse private key.\nError: {error}"),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@backtraced
|
||||
failed_to_execute_account {
|
||||
args: (error: impl Display),
|
||||
msg: format!("Failed to execute the `account` command.\nSnarkVM Error: {error}"),
|
||||
msg: format!("Failed to execute the `account` command.\nError: {error}"),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@ -222,4 +222,25 @@ create_messages!(
|
||||
msg: "Cannot combine recursive deploy with private fee.".to_string(),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@backtraced
|
||||
invalid_network_name {
|
||||
args: (network: impl Display),
|
||||
msg: format!("Invalid network name: {network}"),
|
||||
help: Some("Valid network names are `testnet` and `mainnet`.".to_string()),
|
||||
}
|
||||
|
||||
@backtraced
|
||||
invalid_example {
|
||||
args: (example: impl Display),
|
||||
msg: format!("Invalid Leo example: {example}"),
|
||||
help: Some("Valid Leo examples are `lottery`, `tictactoe`, and `token`.".to_string()),
|
||||
}
|
||||
|
||||
@backtraced
|
||||
build_error {
|
||||
args: (error: impl Display),
|
||||
msg: format!("Failed to build program: {error}"),
|
||||
help: None,
|
||||
}
|
||||
);
|
||||
|
@ -198,8 +198,8 @@ create_messages!(
|
||||
/// For when the package failed to initialize.
|
||||
@backtraced
|
||||
failed_to_initialize_package {
|
||||
args: (package: impl Display, path: impl Debug),
|
||||
msg: format!("failed to initialize package {package} {path:?}"),
|
||||
args: (package: impl Display, path: impl Debug, error: impl Display),
|
||||
msg: format!("Failed to initialize package {package} at {path:?}. Error: {error}"),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@ -207,7 +207,7 @@ create_messages!(
|
||||
@backtraced
|
||||
invalid_package_name {
|
||||
args: (package: impl Display),
|
||||
msg: format!("invalid project name {package}"),
|
||||
msg: format!("Invalid project name {package}"),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@ -397,4 +397,11 @@ create_messages!(
|
||||
msg: "The name of the program to execute on-chain is missing.".to_string(),
|
||||
help: Some("Either set `--local` to execute the local program on chain, or set `--program <PROGRAM>`.".to_string()),
|
||||
}
|
||||
|
||||
@backtraced
|
||||
failed_to_read_manifest_file {
|
||||
args: (path: impl Display, error: impl ErrorArg),
|
||||
msg: format!("Failed to read manifest file from the provided file path {path} - {error}"),
|
||||
help: None,
|
||||
}
|
||||
);
|
||||
|
@ -1,20 +0,0 @@
|
||||
[[package]]
|
||||
name = "board.aleo"
|
||||
location = "local"
|
||||
path = "board"
|
||||
checksum = "da94274230d0c0c3deb96d80e07ad9db8bbf53264286c14cc3231b7a8b7ef380"
|
||||
dependencies = []
|
||||
|
||||
[[package]]
|
||||
name = "move.aleo"
|
||||
location = "local"
|
||||
path = "move"
|
||||
checksum = "7d9fef5fe083eb24376e63935855e4ec709c17fb5ee46a0bb4594b0f9ef8eb08"
|
||||
dependencies = []
|
||||
|
||||
[[package]]
|
||||
name = "verify.aleo"
|
||||
location = "local"
|
||||
path = "verify"
|
||||
checksum = "2c2035ebd70500b7e5a9a6198bed1a1163cd1ddfd09128db8f4c16cf23ad2c62"
|
||||
dependencies = []
|
@ -54,7 +54,7 @@ enum Commands {
|
||||
},
|
||||
#[clap(about = "Create a new Leo example package in a new directory")]
|
||||
Example {
|
||||
#[clap(subcommand)]
|
||||
#[clap(flatten)]
|
||||
command: Example,
|
||||
},
|
||||
#[clap(about = "Run a program with input variables")]
|
||||
@ -314,6 +314,8 @@ mod test_helpers {
|
||||
use leo_span::symbol::create_session_if_not_set_then;
|
||||
use std::path::Path;
|
||||
|
||||
const NETWORK: &str = "mainnet";
|
||||
|
||||
pub(crate) fn sample_nested_package(temp_dir: &Path) {
|
||||
let name = "nested";
|
||||
|
||||
@ -327,7 +329,7 @@ mod test_helpers {
|
||||
let new = CLI {
|
||||
debug: false,
|
||||
quiet: false,
|
||||
command: Commands::New { command: New { name: name.to_string() } },
|
||||
command: Commands::New { command: New { name: name.to_string(), network: NETWORK.to_string() } },
|
||||
path: Some(project_directory.clone()),
|
||||
home: None,
|
||||
};
|
||||
@ -395,7 +397,7 @@ function external_nested_function:
|
||||
command: Add {
|
||||
name: "nested_example_layer_0".to_string(),
|
||||
local: None,
|
||||
network: "mainnet".to_string(),
|
||||
network: NETWORK.to_string(),
|
||||
clear: false,
|
||||
},
|
||||
},
|
||||
@ -428,7 +430,7 @@ function external_nested_function:
|
||||
let create_grandparent_project = CLI {
|
||||
debug: false,
|
||||
quiet: false,
|
||||
command: Commands::New { command: New { name: "grandparent".to_string() } },
|
||||
command: Commands::New { command: New { name: "grandparent".to_string(), network: NETWORK.to_string() } },
|
||||
path: Some(grandparent_directory.clone()),
|
||||
home: None,
|
||||
};
|
||||
@ -436,7 +438,7 @@ function external_nested_function:
|
||||
let create_parent_project = CLI {
|
||||
debug: false,
|
||||
quiet: false,
|
||||
command: Commands::New { command: New { name: "parent".to_string() } },
|
||||
command: Commands::New { command: New { name: "parent".to_string(), network: NETWORK.to_string() } },
|
||||
path: Some(parent_directory.clone()),
|
||||
home: None,
|
||||
};
|
||||
@ -444,7 +446,7 @@ function external_nested_function:
|
||||
let create_child_project = CLI {
|
||||
debug: false,
|
||||
quiet: false,
|
||||
command: Commands::New { command: New { name: "child".to_string() } },
|
||||
command: Commands::New { command: New { name: "child".to_string(), network: NETWORK.to_string() } },
|
||||
path: Some(child_directory.clone()),
|
||||
home: None,
|
||||
};
|
||||
@ -489,7 +491,7 @@ program child.aleo {
|
||||
command: Add {
|
||||
name: "parent".to_string(),
|
||||
local: Some(parent_directory.clone()),
|
||||
network: "mainnet".to_string(),
|
||||
network: NETWORK.to_string(),
|
||||
clear: false,
|
||||
},
|
||||
},
|
||||
@ -504,7 +506,7 @@ program child.aleo {
|
||||
command: Add {
|
||||
name: "child".to_string(),
|
||||
local: Some(child_directory.clone()),
|
||||
network: "mainnet".to_string(),
|
||||
network: NETWORK.to_string(),
|
||||
clear: false,
|
||||
},
|
||||
},
|
||||
@ -519,7 +521,7 @@ program child.aleo {
|
||||
command: Add {
|
||||
name: "child".to_string(),
|
||||
local: Some(child_directory.clone()),
|
||||
network: "mainnet".to_string(),
|
||||
network: NETWORK.to_string(),
|
||||
clear: false,
|
||||
},
|
||||
},
|
||||
@ -559,7 +561,7 @@ program child.aleo {
|
||||
let create_outer_project = CLI {
|
||||
debug: false,
|
||||
quiet: false,
|
||||
command: Commands::New { command: New { name: "outer".to_string() } },
|
||||
command: Commands::New { command: New { name: "outer".to_string(), network: NETWORK.to_string() } },
|
||||
path: Some(outer_directory.clone()),
|
||||
home: None,
|
||||
};
|
||||
@ -567,7 +569,7 @@ program child.aleo {
|
||||
let create_inner_1_project = CLI {
|
||||
debug: false,
|
||||
quiet: false,
|
||||
command: Commands::New { command: New { name: "inner_1".to_string() } },
|
||||
command: Commands::New { command: New { name: "inner_1".to_string(), network: NETWORK.to_string() } },
|
||||
path: Some(inner_1_directory.clone()),
|
||||
home: None,
|
||||
};
|
||||
@ -575,7 +577,7 @@ program child.aleo {
|
||||
let create_inner_2_project = CLI {
|
||||
debug: false,
|
||||
quiet: false,
|
||||
command: Commands::New { command: New { name: "inner_2".to_string() } },
|
||||
command: Commands::New { command: New { name: "inner_2".to_string(), network: NETWORK.to_string() } },
|
||||
path: Some(inner_2_directory.clone()),
|
||||
home: None,
|
||||
};
|
||||
@ -643,7 +645,7 @@ program outer.aleo {
|
||||
command: Add {
|
||||
name: "inner_1".to_string(),
|
||||
local: Some(inner_1_directory.clone()),
|
||||
network: "mainnet".to_string(),
|
||||
network: NETWORK.to_string(),
|
||||
clear: false,
|
||||
},
|
||||
},
|
||||
@ -658,7 +660,7 @@ program outer.aleo {
|
||||
command: Add {
|
||||
name: "inner_2".to_string(),
|
||||
local: Some(inner_2_directory.clone()),
|
||||
network: "mainnet".to_string(),
|
||||
network: NETWORK.to_string(),
|
||||
clear: false,
|
||||
},
|
||||
},
|
||||
@ -697,7 +699,7 @@ program outer.aleo {
|
||||
let create_outer_project = CLI {
|
||||
debug: false,
|
||||
quiet: false,
|
||||
command: Commands::New { command: New { name: "outer_2".to_string() } },
|
||||
command: Commands::New { command: New { name: "outer_2".to_string(), network: NETWORK.to_string() } },
|
||||
path: Some(outer_directory.clone()),
|
||||
home: None,
|
||||
};
|
||||
@ -705,7 +707,7 @@ program outer.aleo {
|
||||
let create_inner_1_project = CLI {
|
||||
debug: false,
|
||||
quiet: false,
|
||||
command: Commands::New { command: New { name: "inner_1".to_string() } },
|
||||
command: Commands::New { command: New { name: "inner_1".to_string(), network: NETWORK.to_string() } },
|
||||
path: Some(inner_1_directory.clone()),
|
||||
home: None,
|
||||
};
|
||||
@ -713,7 +715,7 @@ program outer.aleo {
|
||||
let create_inner_2_project = CLI {
|
||||
debug: false,
|
||||
quiet: false,
|
||||
command: Commands::New { command: New { name: "inner_2".to_string() } },
|
||||
command: Commands::New { command: New { name: "inner_2".to_string(), network: NETWORK.to_string() } },
|
||||
path: Some(inner_2_directory.clone()),
|
||||
home: None,
|
||||
};
|
||||
@ -812,7 +814,7 @@ program outer_2.aleo {
|
||||
command: Add {
|
||||
name: "inner_1".to_string(),
|
||||
local: Some(inner_1_directory.clone()),
|
||||
network: "mainnet".to_string(),
|
||||
network: NETWORK.to_string(),
|
||||
clear: false,
|
||||
},
|
||||
},
|
||||
@ -827,7 +829,7 @@ program outer_2.aleo {
|
||||
command: Add {
|
||||
name: "inner_2".to_string(),
|
||||
local: Some(inner_2_directory.clone()),
|
||||
network: "mainnet".to_string(),
|
||||
network: NETWORK.to_string(),
|
||||
clear: false,
|
||||
},
|
||||
},
|
||||
|
@ -18,14 +18,15 @@ use super::*;
|
||||
use leo_errors::UtilError;
|
||||
use leo_package::root::Env;
|
||||
use snarkvm::{
|
||||
cli::dotenv_private_key,
|
||||
console::program::{Signature, ToFields, Value},
|
||||
prelude::{Address, PrivateKey, ViewKey},
|
||||
};
|
||||
|
||||
use crossterm::ExecutableCommand;
|
||||
use leo_retriever::NetworkName;
|
||||
use rand::SeedableRng;
|
||||
use rand_chacha::ChaChaRng;
|
||||
use snarkvm::prelude::{MainnetV0, Network, TestnetV0};
|
||||
use std::{
|
||||
io::{self, Read, Write},
|
||||
path::PathBuf,
|
||||
@ -46,23 +47,27 @@ pub enum Account {
|
||||
/// Print sensitive information (such as private key) discreetly to an alternate screen
|
||||
#[clap(long)]
|
||||
discreet: bool,
|
||||
#[clap(short = 'n', long, help = "Name of the network to use", default_value = "mainnet")]
|
||||
network: String,
|
||||
},
|
||||
/// Derive an Aleo account from a private key.
|
||||
Import {
|
||||
/// Private key plaintext
|
||||
private_key: Option<PrivateKey<CurrentNetwork>>,
|
||||
private_key: Option<String>,
|
||||
/// Write the private key to the .env file.
|
||||
#[clap(short = 'w', long)]
|
||||
write: bool,
|
||||
/// Print sensitive information (such as private key) discreetly to an alternate screen
|
||||
#[clap(long)]
|
||||
discreet: bool,
|
||||
#[clap(short = 'n', long, help = "Name of the network to use", default_value = "mainnet")]
|
||||
network: String,
|
||||
},
|
||||
/// Sign a message using your Aleo private key.
|
||||
Sign {
|
||||
/// Specify the account private key of the node
|
||||
#[clap(long = "private-key")]
|
||||
private_key: Option<PrivateKey<CurrentNetwork>>,
|
||||
private_key: Option<String>,
|
||||
/// Specify the path to a file containing the account private key of the node
|
||||
#[clap(long = "private-key-file")]
|
||||
private_key_file: Option<String>,
|
||||
@ -75,12 +80,14 @@ pub enum Account {
|
||||
/// When enabled, parses the message as bytes instead of Aleo literals
|
||||
#[clap(short = 'r', long)]
|
||||
raw: bool,
|
||||
#[clap(short = 'n', long, help = "Name of the network to use", default_value = "mainnet")]
|
||||
network: String,
|
||||
},
|
||||
/// Verify a message from an Aleo address.
|
||||
Verify {
|
||||
/// Address to use for verification
|
||||
#[clap(short = 'a', long)]
|
||||
address: Address<CurrentNetwork>,
|
||||
address: String,
|
||||
/// Signature to verify
|
||||
#[clap(short = 's', long)]
|
||||
signature: String,
|
||||
@ -90,6 +97,8 @@ pub enum Account {
|
||||
/// When enabled, parses the message as bytes instead of Aleo literals
|
||||
#[clap(short = 'r', long)]
|
||||
raw: bool,
|
||||
#[clap(short = 'n', long, help = "Name of the network to use", default_value = "mainnet")]
|
||||
network: String,
|
||||
},
|
||||
}
|
||||
|
||||
@ -109,79 +118,43 @@ impl Command for Account {
|
||||
Self: Sized,
|
||||
{
|
||||
match self {
|
||||
Account::New { seed, write, discreet } => {
|
||||
// Sample a new Aleo account.
|
||||
let private_key = match seed {
|
||||
// Recover the field element deterministically.
|
||||
Some(seed) => PrivateKey::new(&mut ChaChaRng::seed_from_u64(seed)),
|
||||
// Sample a random field element.
|
||||
None => PrivateKey::new(&mut ChaChaRng::from_entropy()),
|
||||
}
|
||||
.map_err(CliError::failed_to_parse_seed)?;
|
||||
|
||||
// Derive the view key and address and print to stdout.
|
||||
print_keys(private_key, discreet)?;
|
||||
|
||||
// Save key data to .env file.
|
||||
if write {
|
||||
write_to_env_file(private_key, &ctx)?;
|
||||
}
|
||||
Account::New { seed, write, discreet, network } => {
|
||||
// Parse the network.
|
||||
let network = NetworkName::try_from(network.as_str())?;
|
||||
match network {
|
||||
NetworkName::MainnetV0 => generate_new_account::<MainnetV0>(seed, write, discreet, &ctx),
|
||||
NetworkName::TestnetV0 => generate_new_account::<TestnetV0>(seed, write, discreet, &ctx),
|
||||
}?
|
||||
}
|
||||
Account::Import { private_key, write, discreet } => {
|
||||
let priv_key = match discreet {
|
||||
true => {
|
||||
let private_key_input = rpassword::prompt_password("Please enter your private key: ").unwrap();
|
||||
snarkvm::prelude::FromStr::from_str(&private_key_input)
|
||||
.map_err(CliError::failed_to_parse_private_key)?
|
||||
}
|
||||
false => match private_key {
|
||||
Some(private_key) => private_key,
|
||||
None => {
|
||||
return Err(CliError::failed_to_execute_account(
|
||||
"PRIVATE_KEY shouldn't be empty when --discreet is false",
|
||||
)
|
||||
.into());
|
||||
}
|
||||
},
|
||||
};
|
||||
// Derive the view key and address and print to stdout.
|
||||
print_keys(priv_key, discreet)?;
|
||||
|
||||
// Save key data to .env file.
|
||||
if write {
|
||||
write_to_env_file(priv_key, &ctx)?;
|
||||
}
|
||||
Account::Import { private_key, write, discreet, network } => {
|
||||
// Parse the network.
|
||||
let network = NetworkName::try_from(network.as_str())?;
|
||||
match network {
|
||||
NetworkName::MainnetV0 => import_account::<MainnetV0>(private_key, write, discreet, &ctx),
|
||||
NetworkName::TestnetV0 => import_account::<TestnetV0>(private_key, write, discreet, &ctx),
|
||||
}?
|
||||
}
|
||||
Self::Sign { message, seed, raw, private_key, private_key_file } => {
|
||||
let key = match (private_key, private_key_file) {
|
||||
(Some(private_key), None) => private_key,
|
||||
(None, Some(private_key_file)) => {
|
||||
let path = private_key_file
|
||||
.parse::<PathBuf>()
|
||||
.map_err(|e| CliError::cli_invalid_input(format!("invalid path - {e}")))?;
|
||||
let key_str = std::fs::read_to_string(path).map_err(UtilError::failed_to_read_file)?;
|
||||
PrivateKey::<CurrentNetwork>::from_str(key_str.trim())
|
||||
.map_err(|e| CliError::cli_invalid_input(format!("could not parse private key: {e}")))?
|
||||
Self::Sign { message, seed, raw, private_key, private_key_file, network } => {
|
||||
// Parse the network.
|
||||
let network = NetworkName::try_from(network.as_str())?;
|
||||
let result = match network {
|
||||
NetworkName::MainnetV0 => {
|
||||
sign_message::<MainnetV0>(message, seed, raw, private_key, private_key_file)
|
||||
}
|
||||
(None, None) => {
|
||||
// Attempt to pull private key from env, then .env file
|
||||
match dotenvy::var("PRIVATE_KEY")
|
||||
.map_or_else(|_| dotenv_private_key(), |key| PrivateKey::<CurrentNetwork>::from_str(&key))
|
||||
{
|
||||
Ok(key) => key,
|
||||
Err(_) => Err(CliError::cli_invalid_input(
|
||||
"missing the '--private-key', '--private-key-file', PRIVATE_KEY env, or .env",
|
||||
))?,
|
||||
}
|
||||
NetworkName::TestnetV0 => {
|
||||
sign_message::<TestnetV0>(message, seed, raw, private_key, private_key_file)
|
||||
}
|
||||
(Some(_), Some(_)) => Err(CliError::cli_invalid_input(
|
||||
"cannot specify both the '--private-key' and '--private-key-file' flags",
|
||||
))?,
|
||||
};
|
||||
println!("{}", sign_message(key, message, seed, raw)?);
|
||||
}?;
|
||||
println!("{result}")
|
||||
}
|
||||
Self::Verify { address, signature, message, raw } => {
|
||||
println!("{}", verify_message(address, signature, message, raw)?)
|
||||
Self::Verify { address, signature, message, raw, network } => {
|
||||
// Parse the network.
|
||||
let network = NetworkName::try_from(network.as_str())?;
|
||||
let result = match network {
|
||||
NetworkName::MainnetV0 => verify_message::<MainnetV0>(address, signature, message, raw),
|
||||
NetworkName::TestnetV0 => verify_message::<TestnetV0>(address, signature, message, raw),
|
||||
}?;
|
||||
println!("{result}")
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@ -190,10 +163,60 @@ impl Command for Account {
|
||||
|
||||
// Helper functions
|
||||
|
||||
// Generate a new account.
|
||||
fn generate_new_account<N: Network>(seed: Option<u64>, write: bool, discreet: bool, ctx: &Context) -> Result<()> {
|
||||
// Sample a new Aleo account.
|
||||
let private_key = match seed {
|
||||
// Recover the field element deterministically.
|
||||
Some(seed) => PrivateKey::<N>::new(&mut ChaChaRng::seed_from_u64(seed)),
|
||||
// Sample a random field element.
|
||||
None => PrivateKey::new(&mut ChaChaRng::from_entropy()),
|
||||
}
|
||||
.map_err(CliError::failed_to_parse_seed)?;
|
||||
|
||||
// Derive the view key and address and print to stdout.
|
||||
print_keys(private_key, discreet)?;
|
||||
|
||||
// Save key data to .env file.
|
||||
if write {
|
||||
write_to_env_file(private_key, ctx)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Import an account.
|
||||
fn import_account<N: Network>(private_key: Option<String>, write: bool, discreet: bool, ctx: &Context) -> Result<()> {
|
||||
let priv_key = match discreet {
|
||||
true => {
|
||||
let private_key_input = rpassword::prompt_password("Please enter your private key: ").unwrap();
|
||||
FromStr::from_str(&private_key_input).map_err(CliError::failed_to_parse_private_key)?
|
||||
}
|
||||
false => match private_key {
|
||||
Some(private_key) => FromStr::from_str(&private_key).map_err(CliError::failed_to_parse_private_key)?,
|
||||
None => {
|
||||
return Err(CliError::failed_to_execute_account(
|
||||
"PRIVATE_KEY shouldn't be empty when --discreet is false",
|
||||
)
|
||||
.into());
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Derive the view key and address and print to stdout.
|
||||
print_keys::<N>(priv_key, discreet)?;
|
||||
|
||||
// Save key data to .env file.
|
||||
if write {
|
||||
write_to_env_file::<N>(priv_key, ctx)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Print keys as a formatted string without log level.
|
||||
fn print_keys(private_key: PrivateKey<CurrentNetwork>, discreet: bool) -> Result<()> {
|
||||
fn print_keys<N: Network>(private_key: PrivateKey<N>, discreet: bool) -> Result<()> {
|
||||
let view_key = ViewKey::try_from(&private_key)?;
|
||||
let address = Address::<CurrentNetwork>::try_from(&view_key)?;
|
||||
let address = Address::<N>::try_from(&view_key)?;
|
||||
|
||||
if !discreet {
|
||||
println!(
|
||||
@ -209,14 +232,100 @@ fn print_keys(private_key: PrivateKey<CurrentNetwork>, discreet: bool) -> Result
|
||||
"### Do not share or lose this private key! Press any key to complete. ###",
|
||||
)?;
|
||||
println!("\n {:>12} {view_key}\n {:>12} {address}\n", "View Key".cyan().bold(), "Address".cyan().bold(),);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Sign a message with an Aleo private key
|
||||
pub(crate) fn sign_message<N: Network>(
|
||||
message: String,
|
||||
seed: Option<u64>,
|
||||
raw: bool,
|
||||
private_key: Option<String>,
|
||||
private_key_file: Option<String>,
|
||||
) -> Result<String> {
|
||||
let private_key = match (private_key, private_key_file) {
|
||||
(Some(private_key), None) => PrivateKey::<N>::from_str(private_key.trim())
|
||||
.map_err(|e| CliError::cli_invalid_input(format!("could not parse private key: {e}")))?,
|
||||
(None, Some(private_key_file)) => {
|
||||
let path = private_key_file
|
||||
.parse::<PathBuf>()
|
||||
.map_err(|e| CliError::cli_invalid_input(format!("invalid path - {e}")))?;
|
||||
let key_str = std::fs::read_to_string(path).map_err(UtilError::failed_to_read_file)?;
|
||||
PrivateKey::<N>::from_str(key_str.trim())
|
||||
.map_err(|e| CliError::cli_invalid_input(format!("could not parse private key: {e}")))?
|
||||
}
|
||||
(None, None) => {
|
||||
// Attempt to pull private key from env, then .env file
|
||||
match dotenvy::var("PRIVATE_KEY") {
|
||||
Ok(key) => PrivateKey::<N>::from_str(key.trim())
|
||||
.map_err(|e| CliError::cli_invalid_input(format!("could not parse private key: {e}")))?,
|
||||
Err(_) => Err(CliError::cli_invalid_input(
|
||||
"missing the '--private-key', '--private-key-file', PRIVATE_KEY env, or .env",
|
||||
))?,
|
||||
}
|
||||
}
|
||||
(Some(_), Some(_)) => {
|
||||
Err(CliError::cli_invalid_input("cannot specify both the '--private-key' and '--private-key-file' flags"))?
|
||||
}
|
||||
};
|
||||
// Recover the seed.
|
||||
let mut rng = match seed {
|
||||
// Recover the field element deterministically.
|
||||
Some(seed) => ChaChaRng::seed_from_u64(seed),
|
||||
// Sample a random field element.
|
||||
None => ChaChaRng::from_entropy(),
|
||||
};
|
||||
|
||||
// Sign the message
|
||||
let signature = if raw {
|
||||
private_key.sign_bytes(message.as_bytes(), &mut rng)
|
||||
} else {
|
||||
let fields = Value::<N>::from_str(&message)?
|
||||
.to_fields()
|
||||
.map_err(|_| CliError::cli_invalid_input("Failed to parse a valid Aleo value"))?;
|
||||
private_key.sign(&fields, &mut rng)
|
||||
}
|
||||
.map_err(|_| CliError::cli_runtime_error("Failed to sign the message"))?
|
||||
.to_string();
|
||||
// Return the signature as a string
|
||||
Ok(signature)
|
||||
}
|
||||
|
||||
// Verify a signature with an Aleo address
|
||||
pub(crate) fn verify_message<N: Network>(
|
||||
address: String,
|
||||
signature: String,
|
||||
message: String,
|
||||
raw: bool,
|
||||
) -> Result<String> {
|
||||
// Parse the address.
|
||||
let address = Address::<N>::from_str(&address)?;
|
||||
|
||||
let signature = Signature::<N>::from_str(&signature)
|
||||
.map_err(|e| CliError::cli_invalid_input(format!("Failed to parse a valid signature: {e}")))?;
|
||||
|
||||
// Verify the signature
|
||||
let verified = if raw {
|
||||
signature.verify_bytes(&address, message.as_bytes())
|
||||
} else {
|
||||
let fields = Value::<N>::from_str(&message)?
|
||||
.to_fields()
|
||||
.map_err(|_| CliError::cli_invalid_input("Failed to parse a valid Aleo value"))?;
|
||||
signature.verify(&address, &fields)
|
||||
};
|
||||
|
||||
// Return the verification result
|
||||
match verified {
|
||||
true => Ok("✅ The signature is valid".to_string()),
|
||||
false => Err(CliError::cli_runtime_error("❌ The signature is invalid"))?,
|
||||
}
|
||||
}
|
||||
|
||||
// Write the network and private key to the .env file in project directory.
|
||||
fn write_to_env_file(private_key: PrivateKey<CurrentNetwork>, ctx: &Context) -> Result<()> {
|
||||
let data = format!("NETWORK=mainnet\nPRIVATE_KEY={private_key}\n");
|
||||
fn write_to_env_file<N: Network>(private_key: PrivateKey<N>, ctx: &Context) -> Result<()> {
|
||||
let program_dir = ctx.dir()?;
|
||||
Env::<CurrentNetwork>::from(data).write_to(&program_dir)?;
|
||||
Env::<N>::from(private_key).write_to(&program_dir)?;
|
||||
tracing::info!("✅ Private Key written to {}", program_dir.join(".env").display());
|
||||
Ok(())
|
||||
}
|
||||
@ -242,155 +351,100 @@ fn wait_for_keypress() {
|
||||
std::io::stdin().read_exact(&mut single_key).unwrap();
|
||||
}
|
||||
|
||||
// Sign a message with an Aleo private key
|
||||
pub(crate) fn sign_message(
|
||||
private_key: PrivateKey<CurrentNetwork>,
|
||||
message: String,
|
||||
seed: Option<u64>,
|
||||
raw: bool,
|
||||
) -> Result<String> {
|
||||
// Recover the seed.
|
||||
let mut rng = match seed {
|
||||
// Recover the field element deterministically.
|
||||
Some(seed) => ChaChaRng::seed_from_u64(seed),
|
||||
// Sample a random field element.
|
||||
None => ChaChaRng::from_entropy(),
|
||||
};
|
||||
|
||||
// Sign the message
|
||||
let signature = if raw {
|
||||
private_key.sign_bytes(message.as_bytes(), &mut rng)
|
||||
} else {
|
||||
let fields = Value::<CurrentNetwork>::from_str(&message)?
|
||||
.to_fields()
|
||||
.map_err(|_| CliError::cli_invalid_input("Failed to parse a valid Aleo value"))?;
|
||||
private_key.sign(&fields, &mut rng)
|
||||
}
|
||||
.map_err(|_| CliError::cli_runtime_error("Failed to sign the message"))?
|
||||
.to_string();
|
||||
// Return the signature as a string
|
||||
Ok(signature)
|
||||
}
|
||||
|
||||
// Verify a signature with an Aleo address
|
||||
pub(crate) fn verify_message(
|
||||
address: Address<CurrentNetwork>,
|
||||
signature: String,
|
||||
message: String,
|
||||
raw: bool,
|
||||
) -> Result<String> {
|
||||
let signature = Signature::<CurrentNetwork>::from_str(&signature)
|
||||
.map_err(|e| CliError::cli_invalid_input(format!("Failed to parse a valid signature: {e}")))?;
|
||||
|
||||
// Verify the signature
|
||||
let verified = if raw {
|
||||
signature.verify_bytes(&address, message.as_bytes())
|
||||
} else {
|
||||
let fields = Value::<CurrentNetwork>::from_str(&message)?
|
||||
.to_fields()
|
||||
.map_err(|_| CliError::cli_invalid_input("Failed to parse a valid Aleo value"))?;
|
||||
signature.verify(&address, &fields)
|
||||
};
|
||||
|
||||
// Return the verification result
|
||||
match verified {
|
||||
true => Ok("✅ The signature is valid".to_string()),
|
||||
false => Err(CliError::cli_runtime_error("❌ The signature is invalid"))?,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{sign_message, verify_message};
|
||||
|
||||
type CurrentNetwork = snarkvm::prelude::MainnetV0;
|
||||
|
||||
#[test]
|
||||
fn test_signature_raw() {
|
||||
let key = "APrivateKey1zkp61PAYmrYEKLtRWeWhUoDpFnGLNuHrCciSqN49T86dw3p".parse().unwrap();
|
||||
let key = "APrivateKey1zkp61PAYmrYEKLtRWeWhUoDpFnGLNuHrCciSqN49T86dw3p".to_string();
|
||||
let message = "Hello, world!".to_string();
|
||||
assert!(sign_message(key, message, None, true).is_ok());
|
||||
assert!(sign_message::<CurrentNetwork>(message, None, true, Some(key), None).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_signature() {
|
||||
let key = "APrivateKey1zkp61PAYmrYEKLtRWeWhUoDpFnGLNuHrCciSqN49T86dw3p".parse().unwrap();
|
||||
let key = "APrivateKey1zkp61PAYmrYEKLtRWeWhUoDpFnGLNuHrCciSqN49T86dw3p".to_string();
|
||||
let message = "5field".to_string();
|
||||
assert!(sign_message(key, message, None, false).is_ok());
|
||||
assert!(sign_message::<CurrentNetwork>(message, None, false, Some(key), None).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_signature_fail() {
|
||||
let key = "APrivateKey1zkp61PAYmrYEKLtRWeWhUoDpFnGLNuHrCciSqN49T86dw3p".parse().unwrap();
|
||||
let key = "APrivateKey1zkp61PAYmrYEKLtRWeWhUoDpFnGLNuHrCciSqN49T86dw3p".to_string();
|
||||
let message = "not a literal value".to_string();
|
||||
assert!(sign_message(key, message, None, false).is_err());
|
||||
assert!(sign_message::<CurrentNetwork>(message, None, false, Some(key), None).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_seeded_signature_raw() {
|
||||
let seed = Some(38868010450269069);
|
||||
let key = "APrivateKey1zkp61PAYmrYEKLtRWeWhUoDpFnGLNuHrCciSqN49T86dw3p".parse().unwrap();
|
||||
let key = "APrivateKey1zkp61PAYmrYEKLtRWeWhUoDpFnGLNuHrCciSqN49T86dw3p".to_string();
|
||||
let message = "Hello, world!".to_string();
|
||||
let expected = "sign175pmqldmkqw2nwp7wz7tfmpyqdnvzaq06mh8t2g22frsmrdtuvpf843p0wzazg27rwrjft8863vwn5a5cqgr97ldw69cyq53l0zlwqhesm5elrqqunzqzmac7kzutl6zk7mqht3c0m9kg4hklv7h2js0qmxavwnpuwyl4lzldl6prs4qeqy9wxyp8y44nnydg3h8sg6ue99qkevd26g";
|
||||
let actual = sign_message(key, message, seed, true).unwrap();
|
||||
let actual = sign_message::<CurrentNetwork>(message, seed, true, Some(key), None).unwrap();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_seeded_signature() {
|
||||
let seed = Some(38868010450269069);
|
||||
let key = "APrivateKey1zkp61PAYmrYEKLtRWeWhUoDpFnGLNuHrCciSqN49T86dw3p".parse().unwrap();
|
||||
let key = "APrivateKey1zkp61PAYmrYEKLtRWeWhUoDpFnGLNuHrCciSqN49T86dw3p".to_string();
|
||||
let message = "5field".to_string();
|
||||
let expected = "sign1ad29myqy8gv6xve2r6tuly39m63l2mpfpyvqkwdl2umxqek6q5qxmy63zmhjx75x90sqxq69u5ntzp25kp59e0hp4hj8l8085sg7vqlesm5elrqqunzqzmac7kzutl6zk7mqht3c0m9kg4hklv7h2js0qmxavwnpuwyl4lzldl6prs4qeqy9wxyp8y44nnydg3h8sg6ue99qk7v46re";
|
||||
let actual = sign_message(key, message, seed, false).unwrap();
|
||||
let actual = sign_message::<CurrentNetwork>(message, seed, false, Some(key), None).unwrap();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_verify_raw() {
|
||||
// test signature of "Hello, world!"
|
||||
let address = "aleo1zecnqchckrzw7dlsyf65g6z5le2rmys403ecwmcafrag0e030yxqrnlg8j".parse().unwrap();
|
||||
let address = "aleo1zecnqchckrzw7dlsyf65g6z5le2rmys403ecwmcafrag0e030yxqrnlg8j".to_string();
|
||||
let signature = "sign1nnvrjlksrkxdpwsrw8kztjukzhmuhe5zf3srk38h7g32u4kqtqpxn3j5a6k8zrqcfx580a96956nsjvluzt64cqf54pdka9mgksfqp8esm5elrqqunzqzmac7kzutl6zk7mqht3c0m9kg4hklv7h2js0qmxavwnpuwyl4lzldl6prs4qeqy9wxyp8y44nnydg3h8sg6ue99qkwsnaqq".to_string();
|
||||
let message = "Hello, world!".to_string();
|
||||
assert!(verify_message(address, signature, message, true).is_ok());
|
||||
assert!(verify_message::<CurrentNetwork>(address.clone(), signature, message, true).is_ok());
|
||||
|
||||
// test signature of "Hello, world!" against the message "Different Message"
|
||||
let signature = "sign1nnvrjlksrkxdpwsrw8kztjukzhmuhe5zf3srk38h7g32u4kqtqpxn3j5a6k8zrqcfx580a96956nsjvluzt64cqf54pdka9mgksfqp8esm5elrqqunzqzmac7kzutl6zk7mqht3c0m9kg4hklv7h2js0qmxavwnpuwyl4lzldl6prs4qeqy9wxyp8y44nnydg3h8sg6ue99qkwsnaqq".to_string();
|
||||
let message = "Different Message".to_string();
|
||||
assert!(verify_message(address, signature, message, true).is_err());
|
||||
assert!(verify_message::<CurrentNetwork>(address.clone(), signature, message, true).is_err());
|
||||
|
||||
// test signature of "Hello, world!" against the wrong address
|
||||
let signature = "sign1nnvrjlksrkxdpwsrw8kztjukzhmuhe5zf3srk38h7g32u4kqtqpxn3j5a6k8zrqcfx580a96956nsjvluzt64cqf54pdka9mgksfqp8esm5elrqqunzqzmac7kzutl6zk7mqht3c0m9kg4hklv7h2js0qmxavwnpuwyl4lzldl6prs4qeqy9wxyp8y44nnydg3h8sg6ue99qkwsnaqq".to_string();
|
||||
let message = "Hello, world!".to_string();
|
||||
let wrong_address = "aleo1uxl69laseuv3876ksh8k0nd7tvpgjt6ccrgccedpjk9qwyfensxst9ftg5".parse().unwrap();
|
||||
assert!(verify_message(wrong_address, signature, message, true).is_err());
|
||||
let wrong_address = "aleo1uxl69laseuv3876ksh8k0nd7tvpgjt6ccrgccedpjk9qwyfensxst9ftg5".to_string();
|
||||
assert!(verify_message::<CurrentNetwork>(wrong_address, signature, message, true).is_err());
|
||||
|
||||
// test a valid signature of "Different Message"
|
||||
let signature = "sign1424ztyt9hcm77nq450gvdszrvtg9kvhc4qadg4nzy9y0ah7wdqq7t36cxal42p9jj8e8pjpmc06lfev9nvffcpqv0cxwyr0a2j2tjqlesm5elrqqunzqzmac7kzutl6zk7mqht3c0m9kg4hklv7h2js0qmxavwnpuwyl4lzldl6prs4qeqy9wxyp8y44nnydg3h8sg6ue99qk3yrr50".to_string();
|
||||
let message = "Different Message".to_string();
|
||||
assert!(verify_message(address, signature, message, true).is_ok());
|
||||
assert!(verify_message::<CurrentNetwork>(address, signature, message, true).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_verify() {
|
||||
// test signature of 5u8
|
||||
let address = "aleo1zecnqchckrzw7dlsyf65g6z5le2rmys403ecwmcafrag0e030yxqrnlg8j".parse().unwrap();
|
||||
let address = "aleo1zecnqchckrzw7dlsyf65g6z5le2rmys403ecwmcafrag0e030yxqrnlg8j".to_string();
|
||||
let signature = "sign1j7swjfnyujt2vme3ulu88wdyh2ddj85arh64qh6c6khvrx8wvsp8z9wtzde0sahqj2qwz8rgzt803c0ceega53l4hks2mf5sfsv36qhesm5elrqqunzqzmac7kzutl6zk7mqht3c0m9kg4hklv7h2js0qmxavwnpuwyl4lzldl6prs4qeqy9wxyp8y44nnydg3h8sg6ue99qkdetews".to_string();
|
||||
let message = "5field".to_string();
|
||||
assert!(verify_message(address, signature, message, false).is_ok());
|
||||
assert!(verify_message::<CurrentNetwork>(address.clone(), signature, message, false).is_ok());
|
||||
|
||||
// test signature of 5u8 against the message 10u8
|
||||
let signature = "sign1j7swjfnyujt2vme3ulu88wdyh2ddj85arh64qh6c6khvrx8wvsp8z9wtzde0sahqj2qwz8rgzt803c0ceega53l4hks2mf5sfsv36qhesm5elrqqunzqzmac7kzutl6zk7mqht3c0m9kg4hklv7h2js0qmxavwnpuwyl4lzldl6prs4qeqy9wxyp8y44nnydg3h8sg6ue99qkdetews".to_string();
|
||||
let message = "10field".to_string();
|
||||
assert!(verify_message(address, signature, message, false).is_err());
|
||||
assert!(verify_message::<CurrentNetwork>(address.clone(), signature, message, false).is_err());
|
||||
|
||||
// test signature of 5u8 against the wrong address
|
||||
let signature = "sign1j7swjfnyujt2vme3ulu88wdyh2ddj85arh64qh6c6khvrx8wvsp8z9wtzde0sahqj2qwz8rgzt803c0ceega53l4hks2mf5sfsv36qhesm5elrqqunzqzmac7kzutl6zk7mqht3c0m9kg4hklv7h2js0qmxavwnpuwyl4lzldl6prs4qeqy9wxyp8y44nnydg3h8sg6ue99qkdetews".to_string();
|
||||
let message = "5field".to_string();
|
||||
let wrong_address = "aleo1uxl69laseuv3876ksh8k0nd7tvpgjt6ccrgccedpjk9qwyfensxst9ftg5".parse().unwrap();
|
||||
assert!(verify_message(wrong_address, signature, message, false).is_err());
|
||||
let wrong_address = "aleo1uxl69laseuv3876ksh8k0nd7tvpgjt6ccrgccedpjk9qwyfensxst9ftg5".to_string();
|
||||
assert!(verify_message::<CurrentNetwork>(wrong_address, signature, message, false).is_err());
|
||||
|
||||
// test a valid signature of 10u8
|
||||
let signature = "sign1t9v2t5tljk8pr5t6vkcqgkus0a3v69vryxmfrtwrwg0xtj7yv5qj2nz59e5zcyl50w23lhntxvt6vzeqfyu6dt56698zvfj2l6lz6q0esm5elrqqunzqzmac7kzutl6zk7mqht3c0m9kg4hklv7h2js0qmxavwnpuwyl4lzldl6prs4qeqy9wxyp8y44nnydg3h8sg6ue99qk8rh9kt".to_string();
|
||||
let message = "10field".to_string();
|
||||
assert!(verify_message(address, signature, message, false).is_ok());
|
||||
assert!(verify_message::<CurrentNetwork>(address, signature, message, false).is_ok());
|
||||
}
|
||||
}
|
||||
|
@ -59,12 +59,10 @@ impl Command for Add {
|
||||
// Make sure the program name is valid.
|
||||
// Allow both `credits.aleo` and `credits` syntax.
|
||||
let name: String = match &self.name {
|
||||
name if name.ends_with(".aleo")
|
||||
&& Package::<CurrentNetwork>::is_aleo_name_valid(&name[0..self.name.len() - 5]) =>
|
||||
{
|
||||
name if name.ends_with(".aleo") && Package::is_aleo_name_valid(&name[0..self.name.len() - 5]) => {
|
||||
name.clone()
|
||||
}
|
||||
name if Package::<CurrentNetwork>::is_aleo_name_valid(name) => format!("{name}.aleo"),
|
||||
name if Package::is_aleo_name_valid(name) => format!("{name}.aleo"),
|
||||
name => return Err(PackageError::invalid_file_name_dependency(name).into()),
|
||||
};
|
||||
|
||||
@ -113,7 +111,7 @@ impl Command for Add {
|
||||
}
|
||||
None => {
|
||||
tracing::info!("✅ Added network dependency to program `{name}` from network `{}`.", self.network);
|
||||
Dependency::new(name, Location::Network, Some(NetworkName::from(&self.network)), None)
|
||||
Dependency::new(name, Location::Network, Some(NetworkName::try_from(self.network.as_str())?), None)
|
||||
}
|
||||
});
|
||||
|
||||
@ -125,9 +123,7 @@ impl Command for Add {
|
||||
manifest.license(),
|
||||
Some(dependencies),
|
||||
);
|
||||
let new_manifest_data = serde_json::to_string_pretty(&new_manifest)
|
||||
.map_err(|err| PackageError::failed_to_serialize_manifest_file(path.to_str().unwrap(), err))?;
|
||||
std::fs::write(path.join("program.json"), new_manifest_data).map_err(PackageError::failed_to_write_manifest)?;
|
||||
new_manifest.write_to_dir(&path)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -18,17 +18,21 @@ use super::*;
|
||||
|
||||
use leo_ast::Stub;
|
||||
use leo_compiler::{Compiler, CompilerOptions, OutputOptions};
|
||||
use leo_errors::UtilError;
|
||||
use leo_errors::{CliError, UtilError};
|
||||
use leo_package::{build::BuildDirectory, outputs::OutputsDirectory, source::SourceDirectory};
|
||||
use leo_retriever::Retriever;
|
||||
use leo_retriever::{Manifest, NetworkName, Retriever};
|
||||
use leo_span::Symbol;
|
||||
|
||||
use snarkvm::{package::Package, prelude::ProgramID};
|
||||
use snarkvm::{
|
||||
package::Package,
|
||||
prelude::{MainnetV0, Network, ProgramID, TestnetV0},
|
||||
};
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use std::{
|
||||
io::Write,
|
||||
path::{Path, PathBuf},
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
impl From<BuildOptions> for CompilerOptions {
|
||||
@ -88,101 +92,96 @@ impl Command for Build {
|
||||
}
|
||||
|
||||
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||
// Get the package path.
|
||||
let package_path = context.dir()?;
|
||||
let home_path = context.home()?;
|
||||
// Parse the network.
|
||||
let network = NetworkName::try_from(self.options.network.as_str())?;
|
||||
match network {
|
||||
NetworkName::MainnetV0 => handle_build::<MainnetV0>(&self, context),
|
||||
NetworkName::TestnetV0 => handle_build::<TestnetV0>(&self, context),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Open the build directory.
|
||||
let build_directory = BuildDirectory::create(&package_path)?;
|
||||
// A helper function to handle the build command.
|
||||
fn handle_build<N: Network>(command: &Build, context: Context) -> Result<<Build as Command>::Output> {
|
||||
// Get the package path.
|
||||
let package_path = context.dir()?;
|
||||
let home_path = context.home()?;
|
||||
|
||||
// Get the program id.
|
||||
let manifest = context.open_manifest()?;
|
||||
let program_id = manifest.program_id();
|
||||
// Get the program id.
|
||||
let manifest = Manifest::read_from_dir(&package_path)?;
|
||||
let program_id = ProgramID::<N>::from_str(manifest.program())?;
|
||||
|
||||
// Initialize error handler
|
||||
let handler = Handler::default();
|
||||
// Clear and recreate the build directory.
|
||||
let build_directory = package_path.join("build");
|
||||
if build_directory.exists() {
|
||||
std::fs::remove_dir_all(&build_directory).map_err(CliError::build_error)?;
|
||||
}
|
||||
Package::create(&build_directory, &program_id).map_err(CliError::build_error)?;
|
||||
|
||||
// Retrieve all local dependencies in post order
|
||||
let main_sym = Symbol::intern(&program_id.name().to_string());
|
||||
let mut retriever =
|
||||
Retriever::<CurrentNetwork>::new(main_sym, &package_path, &home_path, self.options.endpoint.clone())
|
||||
.map_err(|err| UtilError::failed_to_retrieve_dependencies(err, Default::default()))?;
|
||||
let mut local_dependencies =
|
||||
retriever.retrieve().map_err(|err| UtilError::failed_to_retrieve_dependencies(err, Default::default()))?;
|
||||
// Initialize error handler
|
||||
let handler = Handler::default();
|
||||
|
||||
// Push the main program at the end of the list to be compiled after all of its dependencies have been processed
|
||||
local_dependencies.push(main_sym);
|
||||
// Retrieve all local dependencies in post order
|
||||
let main_sym = Symbol::intern(&program_id.name().to_string());
|
||||
let mut retriever = Retriever::<N>::new(main_sym, &package_path, &home_path, command.options.endpoint.clone())
|
||||
.map_err(|err| UtilError::failed_to_retrieve_dependencies(err, Default::default()))?;
|
||||
let mut local_dependencies =
|
||||
retriever.retrieve().map_err(|err| UtilError::failed_to_retrieve_dependencies(err, Default::default()))?;
|
||||
|
||||
// Recursive build will recursively compile all local dependencies. Can disable to save compile time.
|
||||
let recursive_build = !self.options.non_recursive;
|
||||
// Push the main program at the end of the list to be compiled after all of its dependencies have been processed
|
||||
local_dependencies.push(main_sym);
|
||||
|
||||
// Loop through all local dependencies and compile them in order
|
||||
for dependency in local_dependencies.into_iter() {
|
||||
if recursive_build || dependency == main_sym {
|
||||
// Get path to the local project
|
||||
let (local_path, stubs) = retriever.prepare_local(dependency)?;
|
||||
// Recursive build will recursively compile all local dependencies. Can disable to save compile time.
|
||||
let recursive_build = !command.options.non_recursive;
|
||||
|
||||
// Create the outputs directory.
|
||||
let local_outputs_directory = OutputsDirectory::create(&local_path)?;
|
||||
// Loop through all local dependencies and compile them in order
|
||||
for dependency in local_dependencies.into_iter() {
|
||||
if recursive_build || dependency == main_sym {
|
||||
// Get path to the local project
|
||||
let (local_path, stubs) = retriever.prepare_local(dependency)?;
|
||||
|
||||
// Open the build directory.
|
||||
let local_build_directory = BuildDirectory::create(&local_path)?;
|
||||
// Create the outputs directory.
|
||||
let local_outputs_directory = OutputsDirectory::create(&local_path)?;
|
||||
|
||||
// Fetch paths to all .leo files in the source directory.
|
||||
let local_source_files = SourceDirectory::files(&local_path)?;
|
||||
// Open the build directory.
|
||||
let local_build_directory = BuildDirectory::create(&local_path)?;
|
||||
|
||||
// Check the source files.
|
||||
SourceDirectory::check_files(&local_source_files)?;
|
||||
// Fetch paths to all .leo files in the source directory.
|
||||
let local_source_files = SourceDirectory::files(&local_path)?;
|
||||
|
||||
// Compile all .leo files into .aleo files.
|
||||
for file_path in local_source_files {
|
||||
compile_leo_file(
|
||||
file_path,
|
||||
&ProgramID::<CurrentNetwork>::try_from(format!("{}.aleo", dependency))
|
||||
.map_err(|_| UtilError::snarkvm_error_building_program_id(Default::default()))?,
|
||||
&local_outputs_directory,
|
||||
&local_build_directory,
|
||||
&handler,
|
||||
self.options.clone(),
|
||||
stubs.clone(),
|
||||
)?;
|
||||
}
|
||||
// Check the source files.
|
||||
SourceDirectory::check_files(&local_source_files)?;
|
||||
|
||||
// Compile all .leo files into .aleo files.
|
||||
for file_path in local_source_files {
|
||||
compile_leo_file(
|
||||
file_path,
|
||||
&ProgramID::<N>::try_from(format!("{}.aleo", dependency))
|
||||
.map_err(|_| UtilError::snarkvm_error_building_program_id(Default::default()))?,
|
||||
&local_outputs_directory,
|
||||
&local_build_directory,
|
||||
&handler,
|
||||
command.options.clone(),
|
||||
stubs.clone(),
|
||||
)?;
|
||||
}
|
||||
|
||||
// Writes `leo.lock` as well as caches objects (when target is an intermediate dependency)
|
||||
retriever.process_local(dependency, recursive_build)?;
|
||||
}
|
||||
|
||||
// `Package::open` checks that the build directory and that `main.aleo` and all imported files are well-formed.
|
||||
Package::<CurrentNetwork>::open(&build_directory).map_err(CliError::failed_to_execute_build)?;
|
||||
|
||||
// // Unset the Leo panic hook.
|
||||
// let _ = std::panic::take_hook();
|
||||
//
|
||||
// // Change the cwd to the build directory to compile aleo files.
|
||||
// std::env::set_current_dir(&build_directory)
|
||||
// .map_err(|err| PackageError::failed_to_set_cwd(build_directory.display(), err))?;
|
||||
//
|
||||
// // Call the `build` command.
|
||||
// let mut args = vec![SNARKVM_COMMAND];
|
||||
// if self.options.offline {
|
||||
// args.push("--offline");
|
||||
// }
|
||||
// let command = AleoBuild::try_parse_from(&args).map_err(CliError::failed_to_execute_aleo_build)?;
|
||||
// let result = command.parse().map_err(CliError::failed_to_execute_aleo_build)?;
|
||||
//
|
||||
// // Log the result of the build
|
||||
// tracing::info!("{}", result);
|
||||
|
||||
Ok(())
|
||||
// Writes `leo.lock` as well as caches objects (when target is an intermediate dependency)
|
||||
retriever.process_local(dependency, recursive_build)?;
|
||||
}
|
||||
|
||||
// `Package::open` checks that the build directory and that `main.aleo` and all imported files are well-formed.
|
||||
Package::<N>::open(&build_directory).map_err(CliError::failed_to_execute_build)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Compiles a Leo file in the `src/` directory.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn compile_leo_file(
|
||||
fn compile_leo_file<N: Network>(
|
||||
file_path: PathBuf,
|
||||
program_id: &ProgramID<CurrentNetwork>,
|
||||
program_id: &ProgramID<N>,
|
||||
outputs: &Path,
|
||||
build: &Path,
|
||||
handler: &Handler,
|
||||
@ -197,7 +196,7 @@ fn compile_leo_file(
|
||||
aleo_file_path.push(format!("main.{}", program_id.network()));
|
||||
|
||||
// Create a new instance of the Leo compiler.
|
||||
let mut compiler = Compiler::<CurrentNetwork>::new(
|
||||
let mut compiler = Compiler::<N>::new(
|
||||
program_name.clone(),
|
||||
program_id.network().to_string(),
|
||||
handler,
|
||||
|
@ -15,8 +15,12 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
use leo_retriever::NetworkName;
|
||||
use snarkos_cli::commands::{Deploy as SnarkOSDeploy, Developer};
|
||||
use snarkvm::cli::helpers::dotenv_private_key;
|
||||
use snarkvm::{
|
||||
cli::helpers::dotenv_private_key,
|
||||
prelude::{MainnetV0, TestnetV0},
|
||||
};
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// Deploys an Aleo program.
|
||||
@ -54,8 +58,13 @@ impl Command for Deploy {
|
||||
}
|
||||
|
||||
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||
// Parse the network.
|
||||
let network = NetworkName::try_from(self.compiler_options.network.as_str())?;
|
||||
// Get the program name.
|
||||
let project_name = context.open_manifest()?.program_id().to_string();
|
||||
let project_name = match network {
|
||||
NetworkName::MainnetV0 => context.open_manifest::<MainnetV0>()?.program_id().to_string(),
|
||||
NetworkName::TestnetV0 => context.open_manifest::<TestnetV0>()?.program_id().to_string(),
|
||||
};
|
||||
|
||||
// Get the private key.
|
||||
let mut private_key = self.fee_options.private_key;
|
||||
@ -88,10 +97,12 @@ impl Command for Deploy {
|
||||
self.compiler_options.endpoint.clone(),
|
||||
"--priority-fee".to_string(),
|
||||
self.fee_options.priority_fee.to_string(),
|
||||
"--network".to_string(),
|
||||
network.id().to_string(),
|
||||
"--path".to_string(),
|
||||
path.to_str().unwrap().parse().unwrap(),
|
||||
"--broadcast".to_string(),
|
||||
format!("{}/{}/transaction/broadcast", self.compiler_options.endpoint, self.fee_options.network)
|
||||
format!("{}/{}/transaction/broadcast", self.compiler_options.endpoint, self.compiler_options.network)
|
||||
.to_string(),
|
||||
name.clone(),
|
||||
];
|
||||
|
@ -18,15 +18,13 @@ use super::*;
|
||||
|
||||
use std::fs;
|
||||
|
||||
/// The example programs that can be generated.
|
||||
/// Initialize a new Leo example.
|
||||
#[derive(Parser, Debug)]
|
||||
pub enum Example {
|
||||
#[clap(name = "lottery", about = "A public lottery program")]
|
||||
Lottery,
|
||||
#[clap(name = "tictactoe", about = "A standard tic-tac-toe game program")]
|
||||
TicTacToe,
|
||||
#[clap(name = "token", about = "A transparent & shielded custom token program")]
|
||||
Token,
|
||||
pub struct Example {
|
||||
#[clap(name = "NAME", help = "The example to initialize.")]
|
||||
pub(crate) name: String,
|
||||
#[clap(short = 'n', long, help = "Name of the network to use", default_value = "mainnet")]
|
||||
pub(crate) network: String,
|
||||
}
|
||||
|
||||
impl Command for Example {
|
||||
@ -34,8 +32,8 @@ impl Command for Example {
|
||||
type Output = ();
|
||||
|
||||
fn prelude(&self, context: Context) -> Result<Self::Input> {
|
||||
// Run leo new EXAMPLE_NAME
|
||||
(New { name: self.name() }).execute(context)
|
||||
// Run leo new <name> --network <network>
|
||||
(New { name: self.name.clone(), network: self.network.clone() }).execute(context)
|
||||
}
|
||||
|
||||
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output>
|
||||
@ -44,22 +42,26 @@ impl Command for Example {
|
||||
{
|
||||
let package_dir = context.dir()?;
|
||||
|
||||
// Parse the example variant.
|
||||
let example_variant =
|
||||
ExampleVariant::try_from(self.name.as_str()).map_err(|_| CliError::invalid_example(self.name.as_str()))?;
|
||||
|
||||
// Write the main file.
|
||||
let main_file_path = package_dir.join("src").join("main.leo");
|
||||
fs::write(main_file_path, self.main_file_string()).map_err(CliError::failed_to_write_file)?;
|
||||
fs::write(main_file_path, example_variant.main_file_string()).map_err(CliError::failed_to_write_file)?;
|
||||
|
||||
// Write the README file.
|
||||
let readme_file_path = package_dir.join("README.md");
|
||||
let readme_file_path_string = readme_file_path.display().to_string();
|
||||
fs::write(readme_file_path, self.readme_file_string()).map_err(CliError::failed_to_write_file)?;
|
||||
fs::write(readme_file_path, example_variant.readme_file_string()).map_err(CliError::failed_to_write_file)?;
|
||||
|
||||
// Write the run.sh file.
|
||||
let run_file_path = package_dir.join("run.sh");
|
||||
fs::write(run_file_path, self.run_file_string()).map_err(CliError::failed_to_write_file)?;
|
||||
fs::write(run_file_path, example_variant.run_file_string()).map_err(CliError::failed_to_write_file)?;
|
||||
|
||||
tracing::info!(
|
||||
"🚀 To run the '{}' program follow the instructions at {}",
|
||||
self.name().bold(),
|
||||
example_variant.name().bold(),
|
||||
readme_file_path_string
|
||||
);
|
||||
|
||||
@ -67,12 +69,23 @@ impl Command for Example {
|
||||
}
|
||||
}
|
||||
|
||||
impl Example {
|
||||
/// The example programs that can be generated.
|
||||
#[derive(Parser, Debug, Copy, Clone)]
|
||||
pub enum ExampleVariant {
|
||||
#[clap(name = "lottery", about = "A public lottery program")]
|
||||
Lottery,
|
||||
#[clap(name = "tictactoe", about = "A standard tic-tac-toe game program")]
|
||||
TicTacToe,
|
||||
#[clap(name = "token", about = "A transparent & shielded custom token program")]
|
||||
Token,
|
||||
}
|
||||
|
||||
impl ExampleVariant {
|
||||
fn name(&self) -> String {
|
||||
match self {
|
||||
Example::Lottery => "lottery".to_string(),
|
||||
Example::TicTacToe => "tictactoe".to_string(),
|
||||
Example::Token => "token".to_string(),
|
||||
Self::Lottery => "lottery".to_string(),
|
||||
Self::TicTacToe => "tictactoe".to_string(),
|
||||
Self::Token => "token".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,3 +125,16 @@ impl Example {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for ExampleVariant {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
|
||||
match value {
|
||||
"lottery" => Ok(Self::Lottery),
|
||||
"tictactoe" => Ok(Self::TicTacToe),
|
||||
"token" => Ok(Self::Token),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,10 +16,11 @@
|
||||
|
||||
use super::*;
|
||||
use clap::Parser;
|
||||
use leo_retriever::NetworkName;
|
||||
use snarkos_cli::commands::{Developer, Execute as SnarkOSExecute};
|
||||
use snarkvm::{
|
||||
cli::{helpers::dotenv_private_key, Execute as SnarkVMExecute},
|
||||
prelude::Parser as SnarkVMParser,
|
||||
prelude::{MainnetV0, Network, Parser as SnarkVMParser, TestnetV0},
|
||||
};
|
||||
|
||||
/// Build, Prove and Run Leo program with inputs
|
||||
@ -60,132 +61,144 @@ impl Command for Execute {
|
||||
}
|
||||
|
||||
fn apply(self, context: Context, _input: Self::Input) -> Result<Self::Output> {
|
||||
// If the `broadcast` flag is set, then broadcast the transaction.
|
||||
if self.broadcast {
|
||||
// Get the program name.
|
||||
let program_name = match (self.program, self.local) {
|
||||
(Some(name), true) => {
|
||||
let local = context.open_manifest()?.program_id().to_string();
|
||||
// Throw error if local name doesn't match the specified name.
|
||||
if name == local {
|
||||
local
|
||||
} else {
|
||||
return Err(PackageError::conflicting_on_chain_program_name(local, name).into());
|
||||
}
|
||||
}
|
||||
(Some(name), false) => name,
|
||||
(None, true) => context.open_manifest()?.program_id().to_string(),
|
||||
(None, false) => return Err(PackageError::missing_on_chain_program_name().into()),
|
||||
};
|
||||
|
||||
// Get the private key.
|
||||
let private_key = match self.fee_options.private_key {
|
||||
Some(private_key) => private_key,
|
||||
None => dotenv_private_key().map_err(CliError::failed_to_read_environment_private_key)?.to_string(),
|
||||
};
|
||||
|
||||
// Set deploy arguments.
|
||||
let mut fee_args = vec![
|
||||
"snarkos".to_string(),
|
||||
"--private-key".to_string(),
|
||||
private_key.clone(),
|
||||
"--query".to_string(),
|
||||
self.compiler_options.endpoint.clone(),
|
||||
"--priority-fee".to_string(),
|
||||
self.fee_options.priority_fee.to_string(),
|
||||
"--broadcast".to_string(),
|
||||
format!("{}/{}/transaction/broadcast", self.compiler_options.endpoint, self.fee_options.network)
|
||||
.to_string(),
|
||||
];
|
||||
|
||||
// Use record as payment option if it is provided.
|
||||
if let Some(record) = self.fee_options.record.clone() {
|
||||
fee_args.push("--record".to_string());
|
||||
fee_args.push(record);
|
||||
};
|
||||
|
||||
// Execute program.
|
||||
Developer::Execute(
|
||||
SnarkOSExecute::try_parse_from(
|
||||
[
|
||||
// The arguments for determining fee.
|
||||
fee_args,
|
||||
// The program ID and function name.
|
||||
vec![program_name, self.name],
|
||||
// The function inputs.
|
||||
self.inputs,
|
||||
]
|
||||
.concat(),
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
.parse()
|
||||
.map_err(CliError::failed_to_execute_deploy)?;
|
||||
|
||||
return Ok(());
|
||||
// Parse the network.
|
||||
let network = NetworkName::try_from(self.compiler_options.network.as_str())?;
|
||||
match network {
|
||||
NetworkName::MainnetV0 => handle_execute::<MainnetV0>(self, context),
|
||||
NetworkName::TestnetV0 => handle_execute::<TestnetV0>(self, context),
|
||||
}
|
||||
|
||||
// If input values are provided, then run the program with those inputs.
|
||||
// Otherwise, use the input file.
|
||||
let mut inputs = self.inputs;
|
||||
|
||||
// Compose the `execute` command.
|
||||
let mut arguments = vec![SNARKVM_COMMAND.to_string(), self.name];
|
||||
|
||||
// Add the inputs to the arguments.
|
||||
match self.file {
|
||||
Some(file) => {
|
||||
// Get the contents from the file.
|
||||
let path = context.dir()?.join(file);
|
||||
let raw_content = std::fs::read_to_string(&path)
|
||||
.map_err(|err| PackageError::failed_to_read_file(path.display(), err))?;
|
||||
// Parse the values from the file.
|
||||
let mut content = raw_content.as_str();
|
||||
let mut values = vec![];
|
||||
while let Ok((remaining, value)) = snarkvm::prelude::Value::<CurrentNetwork>::parse(content) {
|
||||
content = remaining;
|
||||
values.push(value);
|
||||
}
|
||||
// Check that the remaining content is empty.
|
||||
if !content.trim().is_empty() {
|
||||
return Err(PackageError::failed_to_read_input_file(path.display()).into());
|
||||
}
|
||||
// Convert the values to strings.
|
||||
let mut inputs_from_file = values.into_iter().map(|value| value.to_string()).collect::<Vec<String>>();
|
||||
// Add the inputs from the file to the arguments.
|
||||
arguments.append(&mut inputs_from_file);
|
||||
}
|
||||
None => arguments.append(&mut inputs),
|
||||
}
|
||||
|
||||
// Add the compiler options to the arguments.
|
||||
if self.compiler_options.offline {
|
||||
arguments.push(String::from("--offline"));
|
||||
}
|
||||
|
||||
// Add the endpoint to the arguments.
|
||||
arguments.push(String::from("--endpoint"));
|
||||
arguments.push(self.compiler_options.endpoint.clone());
|
||||
|
||||
// Open the Leo build/ directory.
|
||||
let path = context.dir()?;
|
||||
let build_directory = BuildDirectory::open(&path)?;
|
||||
|
||||
// Change the cwd to the Leo build/ directory to compile aleo files.
|
||||
std::env::set_current_dir(&build_directory)
|
||||
.map_err(|err| PackageError::failed_to_set_cwd(build_directory.display(), err))?;
|
||||
|
||||
// Unset the Leo panic hook.
|
||||
let _ = std::panic::take_hook();
|
||||
|
||||
// Call the `execute` command.
|
||||
println!();
|
||||
let command = SnarkVMExecute::try_parse_from(&arguments).map_err(CliError::failed_to_parse_execute)?;
|
||||
let res = command.parse().map_err(CliError::failed_to_execute_execute)?;
|
||||
|
||||
// Log the output of the `execute` command.
|
||||
tracing::info!("{}", res);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// A helper function to handle the `execute` command.
|
||||
fn handle_execute<N: Network>(command: Execute, context: Context) -> Result<<Execute as Command>::Output> {
|
||||
// If the `broadcast` flag is set, then broadcast the transaction.
|
||||
if command.broadcast {
|
||||
// Get the program name.
|
||||
let program_name = match (command.program, command.local) {
|
||||
(Some(name), true) => {
|
||||
let local = context.open_manifest::<N>()?.program_id().to_string();
|
||||
// Throw error if local name doesn't match the specified name.
|
||||
if name == local {
|
||||
local
|
||||
} else {
|
||||
return Err(PackageError::conflicting_on_chain_program_name(local, name).into());
|
||||
}
|
||||
}
|
||||
(Some(name), false) => name,
|
||||
(None, true) => context.open_manifest::<N>()?.program_id().to_string(),
|
||||
(None, false) => return Err(PackageError::missing_on_chain_program_name().into()),
|
||||
};
|
||||
|
||||
// Get the private key.
|
||||
let private_key = match command.fee_options.private_key {
|
||||
Some(private_key) => private_key,
|
||||
None => dotenv_private_key().map_err(CliError::failed_to_read_environment_private_key)?.to_string(),
|
||||
};
|
||||
|
||||
// Set deploy arguments.
|
||||
let mut fee_args = vec![
|
||||
"snarkos".to_string(),
|
||||
"--private-key".to_string(),
|
||||
private_key.clone(),
|
||||
"--query".to_string(),
|
||||
command.compiler_options.endpoint.clone(),
|
||||
"--priority-fee".to_string(),
|
||||
command.fee_options.priority_fee.to_string(),
|
||||
"--network".to_string(),
|
||||
N::ID.to_string(),
|
||||
"--broadcast".to_string(),
|
||||
format!("{}/{}/transaction/broadcast", command.compiler_options.endpoint, command.compiler_options.network)
|
||||
.to_string(),
|
||||
];
|
||||
|
||||
// Use record as payment option if it is provided.
|
||||
if let Some(record) = command.fee_options.record.clone() {
|
||||
fee_args.push("--record".to_string());
|
||||
fee_args.push(record);
|
||||
};
|
||||
|
||||
// Execute program.
|
||||
Developer::Execute(
|
||||
SnarkOSExecute::try_parse_from(
|
||||
[
|
||||
// The arguments for determining fee.
|
||||
fee_args,
|
||||
// The program ID and function name.
|
||||
vec![program_name, command.name],
|
||||
// The function inputs.
|
||||
command.inputs,
|
||||
]
|
||||
.concat(),
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
.parse()
|
||||
.map_err(CliError::failed_to_execute_deploy)?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// If input values are provided, then run the program with those inputs.
|
||||
// Otherwise, use the input file.
|
||||
let mut inputs = command.inputs;
|
||||
|
||||
// Compose the `execute` command.
|
||||
let mut arguments = vec![SNARKVM_COMMAND.to_string(), command.name];
|
||||
|
||||
// Add the inputs to the arguments.
|
||||
match command.file {
|
||||
Some(file) => {
|
||||
// Get the contents from the file.
|
||||
let path = context.dir()?.join(file);
|
||||
let raw_content =
|
||||
std::fs::read_to_string(&path).map_err(|err| PackageError::failed_to_read_file(path.display(), err))?;
|
||||
// Parse the values from the file.
|
||||
let mut content = raw_content.as_str();
|
||||
let mut values = vec![];
|
||||
while let Ok((remaining, value)) = snarkvm::prelude::Value::<N>::parse(content) {
|
||||
content = remaining;
|
||||
values.push(value);
|
||||
}
|
||||
// Check that the remaining content is empty.
|
||||
if !content.trim().is_empty() {
|
||||
return Err(PackageError::failed_to_read_input_file(path.display()).into());
|
||||
}
|
||||
// Convert the values to strings.
|
||||
let mut inputs_from_file = values.into_iter().map(|value| value.to_string()).collect::<Vec<String>>();
|
||||
// Add the inputs from the file to the arguments.
|
||||
arguments.append(&mut inputs_from_file);
|
||||
}
|
||||
None => arguments.append(&mut inputs),
|
||||
}
|
||||
|
||||
// Add the compiler options to the arguments.
|
||||
if command.compiler_options.offline {
|
||||
arguments.push(String::from("--offline"));
|
||||
}
|
||||
|
||||
// Add the endpoint to the arguments.
|
||||
arguments.push(String::from("--endpoint"));
|
||||
arguments.push(command.compiler_options.endpoint.clone());
|
||||
|
||||
// Open the Leo build/ directory.
|
||||
let path = context.dir()?;
|
||||
let build_directory = BuildDirectory::open(&path)?;
|
||||
|
||||
// Change the cwd to the Leo build/ directory to compile aleo files.
|
||||
std::env::set_current_dir(&build_directory)
|
||||
.map_err(|err| PackageError::failed_to_set_cwd(build_directory.display(), err))?;
|
||||
|
||||
// Unset the Leo panic hook.
|
||||
let _ = std::panic::take_hook();
|
||||
|
||||
// Call the `execute` command.
|
||||
println!();
|
||||
let command = SnarkVMExecute::try_parse_from(&arguments).map_err(CliError::failed_to_parse_execute)?;
|
||||
let res = command.parse().map_err(CliError::failed_to_execute_execute)?;
|
||||
|
||||
// Log the output of the `execute` command.
|
||||
tracing::info!("{}", res);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -126,10 +126,12 @@ pub trait Command {
|
||||
|
||||
/// Compiler Options wrapper for Build command. Also used by other commands which
|
||||
/// require Build command output as their input.
|
||||
#[derive(Parser, Clone, Debug, Default)]
|
||||
#[derive(Parser, Clone, Debug)]
|
||||
pub struct BuildOptions {
|
||||
#[clap(long, help = "Endpoint to retrieve network state from.", default_value = "http://api.explorer.aleo.org/v1")]
|
||||
pub endpoint: String,
|
||||
#[clap(long, help = "Network to broadcast to. Defaults to mainnet.", default_value = "mainnet")]
|
||||
pub(crate) network: String,
|
||||
#[clap(long, help = "Does not recursively compile dependencies.")]
|
||||
pub non_recursive: bool,
|
||||
#[clap(long, help = "Enables offline mode.")]
|
||||
@ -168,14 +170,39 @@ pub struct BuildOptions {
|
||||
pub disable_conditional_branch_type_checking: bool,
|
||||
}
|
||||
|
||||
impl Default for BuildOptions {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
endpoint: "http://api.explorer.aleo.org/v1".to_string(),
|
||||
network: "mainnet".to_string(),
|
||||
non_recursive: false,
|
||||
offline: false,
|
||||
enable_symbol_table_spans: false,
|
||||
enable_initial_symbol_table_snapshot: false,
|
||||
enable_type_checked_symbol_table_snapshot: false,
|
||||
enable_unrolled_symbol_table_snapshot: false,
|
||||
enable_ast_spans: false,
|
||||
enable_dce: false,
|
||||
enable_all_ast_snapshots: false,
|
||||
enable_initial_ast_snapshot: false,
|
||||
enable_unrolled_ast_snapshot: false,
|
||||
enable_ssa_ast_snapshot: false,
|
||||
enable_flattened_ast_snapshot: false,
|
||||
enable_destructured_ast_snapshot: false,
|
||||
enable_inlined_ast_snapshot: false,
|
||||
enable_dce_ast_snapshot: false,
|
||||
conditional_block_max_depth: 10,
|
||||
disable_conditional_branch_type_checking: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// On Chain Execution Options to set preferences for keys, fees and networks.
|
||||
/// Used by Execute and Deploy commands.
|
||||
#[derive(Parser, Clone, Debug, Default)]
|
||||
#[derive(Parser, Clone, Debug)]
|
||||
pub struct FeeOptions {
|
||||
#[clap(long, help = "Priority fee in microcredits. Defaults to 0.", default_value = "0")]
|
||||
pub(crate) priority_fee: String,
|
||||
#[clap(long, help = "Network to broadcast to. Defaults to mainnet.", default_value = "mainnet")]
|
||||
pub(crate) network: String,
|
||||
#[clap(long, help = "Private key to authorize fee expenditure.")]
|
||||
pub(crate) private_key: Option<String>,
|
||||
#[clap(
|
||||
@ -185,3 +212,9 @@ pub struct FeeOptions {
|
||||
)]
|
||||
record: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for FeeOptions {
|
||||
fn default() -> Self {
|
||||
Self { priority_fee: "0".to_string(), private_key: None, record: None }
|
||||
}
|
||||
}
|
||||
|
@ -15,14 +15,17 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
use snarkvm::prelude::{MainnetV0, TestnetV0};
|
||||
|
||||
use snarkvm::{cli::New as SnarkVMNew, file::AleoFile};
|
||||
use leo_retriever::NetworkName;
|
||||
|
||||
/// Create new Leo project
|
||||
#[derive(Parser, Debug)]
|
||||
pub struct New {
|
||||
#[clap(name = "NAME", help = "Set package name")]
|
||||
pub(crate) name: String,
|
||||
#[clap(short = 'n', long, help = "Name of the network to use", default_value = "mainnet")]
|
||||
pub(crate) network: String,
|
||||
}
|
||||
|
||||
impl Command for New {
|
||||
@ -38,55 +41,21 @@ impl Command for New {
|
||||
}
|
||||
|
||||
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||
// Parse the network.
|
||||
let network = NetworkName::try_from(self.network.as_str())?;
|
||||
|
||||
// Derive the location of the parent directory to the project.
|
||||
let mut package_path = context.parent_dir()?;
|
||||
let package_path = context.parent_dir()?;
|
||||
|
||||
// Change the cwd to the Leo package directory to initialize all files.
|
||||
std::env::set_current_dir(&package_path)
|
||||
.map_err(|err| PackageError::failed_to_set_cwd(package_path.display(), err))?;
|
||||
|
||||
// Call the `aleo new` command from the Aleo SDK.
|
||||
let command =
|
||||
SnarkVMNew::try_parse_from([SNARKVM_COMMAND, &self.name]).map_err(CliError::failed_to_parse_new)?;
|
||||
let result = command.parse().map_err(CliError::failed_to_execute_new)?;
|
||||
|
||||
// Log the output of the `aleo new` command.
|
||||
tracing::info!("{}", result);
|
||||
|
||||
// Initialize the Leo package in the directory created by `aleo new`.
|
||||
package_path.push(&self.name);
|
||||
std::env::set_current_dir(&package_path)
|
||||
.map_err(|err| PackageError::failed_to_set_cwd(package_path.display(), err))?;
|
||||
Package::<CurrentNetwork>::initialize(&self.name, &package_path)?;
|
||||
|
||||
// Open the program manifest.
|
||||
let manifest = context.open_manifest()?;
|
||||
|
||||
// Create a path to the build directory.
|
||||
let mut build_directory = package_path.clone();
|
||||
build_directory.push(BUILD_DIRECTORY_NAME);
|
||||
|
||||
// Write the Aleo file into the build directory.
|
||||
AleoFile::create(&build_directory, manifest.program_id(), true)
|
||||
.map_err(PackageError::failed_to_create_aleo_file)?;
|
||||
|
||||
// build_aleo_file.push(AleoFile::<Network>::main_file_name());
|
||||
//
|
||||
// println!("{}", build_aleo_file.display());
|
||||
//
|
||||
//
|
||||
// std::fs::File::create(build_aleo_file).map_err()
|
||||
// aleo_file.write_to(&build_aleo_file).map_err(PackageError::failed_to_write_aleo_file)?;
|
||||
|
||||
// Open the `main.aleo` file path.
|
||||
let aleo_file = AleoFile::open(&package_path, manifest.program_id(), true)
|
||||
.map_err(PackageError::failed_to_open_aleo_file)?;
|
||||
|
||||
let mut aleo_file_path = package_path.clone();
|
||||
aleo_file_path.push(AleoFile::<CurrentNetwork>::main_file_name());
|
||||
|
||||
// Remove the Aleo file from the package directory.
|
||||
aleo_file.remove(&aleo_file_path).map_err(PackageError::failed_to_remove_aleo_file)?;
|
||||
// Initialize the package.
|
||||
match network {
|
||||
NetworkName::MainnetV0 => Package::initialize::<MainnetV0>(&self.name, &package_path),
|
||||
NetworkName::TestnetV0 => Package::initialize::<TestnetV0>(&self.name, &package_path),
|
||||
}?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ impl Command for Program {
|
||||
// Build custom url to fetch from based on the flags and user's input.
|
||||
let url = if let Some(mapping_info) = self.mapping_value {
|
||||
// Check that the mapping name is valid.
|
||||
Package::<CurrentNetwork>::is_aleo_name_valid(&mapping_info[0]);
|
||||
Package::is_aleo_name_valid(&mapping_info[0]);
|
||||
format!("program/{}/mapping/{}/{}", program, mapping_info[0], mapping_info[1])
|
||||
} else if self.mappings {
|
||||
format!("program/{}/mappings", program)
|
||||
|
@ -14,10 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
|
||||
use leo_errors::{LeoError, Result, UtilError};
|
||||
|
||||
use leo_package::package::Package;
|
||||
|
||||
// A valid hash is 61 characters long, with preface "ab1" and all characters lowercase or numbers.
|
||||
@ -85,10 +82,10 @@ pub fn is_valid_field(field: &str) -> Result<String, LeoError> {
|
||||
// Checks if the string is a valid program name in Aleo.
|
||||
pub fn check_valid_program_name(name: String) -> String {
|
||||
if name.ends_with(".aleo") {
|
||||
Package::<CurrentNetwork>::is_aleo_name_valid(&name[0..name.len() - 5]);
|
||||
Package::is_aleo_name_valid(&name[0..name.len() - 5]);
|
||||
name
|
||||
} else {
|
||||
Package::<CurrentNetwork>::is_aleo_name_valid(&name);
|
||||
Package::is_aleo_name_valid(&name);
|
||||
format!("{}.aleo", name)
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
use super::*;
|
||||
use leo_retriever::{Dependency, Manifest};
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// Remove a dependency from the current package.
|
||||
#[derive(Parser, Debug)]
|
||||
@ -29,12 +28,6 @@ pub struct Remove {
|
||||
)]
|
||||
pub(crate) name: Option<String>,
|
||||
|
||||
#[clap(short = 'l', long, help = "Path to local dependency")]
|
||||
pub(crate) local: Option<PathBuf>,
|
||||
|
||||
#[clap(short = 'n', long, help = "Name of the network to use", default_value = "testnet3")]
|
||||
pub(crate) network: String,
|
||||
|
||||
#[clap(long, help = "Clear all previous dependencies.", default_value = "false")]
|
||||
pub(crate) all: bool,
|
||||
}
|
||||
@ -62,18 +55,8 @@ impl Command for Remove {
|
||||
.map_err(|err| PackageError::failed_to_deserialize_manifest_file(path.to_str().unwrap(), err))?;
|
||||
|
||||
let dependencies: Vec<Dependency> = if !self.all {
|
||||
// Make sure the program name is valid.
|
||||
// Allow both `credits.aleo` and `credits` syntax.
|
||||
let name: String = match &self.name {
|
||||
Some(name)
|
||||
if name.ends_with(".aleo")
|
||||
&& Package::<CurrentNetwork>::is_aleo_name_valid(&name[0..name.len() - 5]) =>
|
||||
{
|
||||
name.clone()
|
||||
}
|
||||
Some(name) if Package::<CurrentNetwork>::is_aleo_name_valid(name) => format!("{name}.aleo"),
|
||||
name => return Err(PackageError::invalid_file_name_dependency(name.clone().unwrap()).into()),
|
||||
};
|
||||
// Note that this unwrap is safe since `name` is required if `all` is `false`.
|
||||
let name: String = self.name.unwrap().clone();
|
||||
|
||||
let mut found_match = false;
|
||||
let dep = match manifest.dependencies() {
|
||||
@ -121,9 +104,7 @@ impl Command for Remove {
|
||||
manifest.license(),
|
||||
Some(dependencies),
|
||||
);
|
||||
let new_manifest_data = serde_json::to_string_pretty(&new_manifest)
|
||||
.map_err(|err| PackageError::failed_to_serialize_manifest_file(path.to_str().unwrap(), err))?;
|
||||
std::fs::write(path.join("program.json"), new_manifest_data).map_err(PackageError::failed_to_write_manifest)?;
|
||||
new_manifest.write_to_dir(&path)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -16,7 +16,11 @@
|
||||
|
||||
use super::*;
|
||||
|
||||
use snarkvm::{cli::Run as SnarkVMRun, prelude::Parser as SnarkVMParser};
|
||||
use leo_retriever::NetworkName;
|
||||
use snarkvm::{
|
||||
cli::Run as SnarkVMRun,
|
||||
prelude::{MainnetV0, Network, Parser as SnarkVMParser, TestnetV0},
|
||||
};
|
||||
|
||||
/// Build, Prove and Run Leo program with inputs
|
||||
#[derive(Parser, Debug)]
|
||||
@ -47,56 +51,66 @@ impl Command for Run {
|
||||
}
|
||||
|
||||
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||
let mut inputs = self.inputs;
|
||||
|
||||
// Compose the `run` command.
|
||||
let mut arguments = vec![SNARKVM_COMMAND.to_string(), self.name];
|
||||
|
||||
// Add the inputs to the arguments.
|
||||
match self.file {
|
||||
Some(file) => {
|
||||
// Get the contents from the file.
|
||||
let path = context.dir()?.join(file);
|
||||
let raw_content = std::fs::read_to_string(&path)
|
||||
.map_err(|err| PackageError::failed_to_read_file(path.display(), err))?;
|
||||
// Parse the values from the file.
|
||||
let mut content = raw_content.as_str();
|
||||
let mut values = vec![];
|
||||
while let Ok((remaining, value)) = snarkvm::prelude::Value::<CurrentNetwork>::parse(content) {
|
||||
content = remaining;
|
||||
values.push(value);
|
||||
}
|
||||
// Check that the remaining content is empty.
|
||||
if !content.trim().is_empty() {
|
||||
return Err(PackageError::failed_to_read_input_file(path.display()).into());
|
||||
}
|
||||
// Convert the values to strings.
|
||||
let mut inputs_from_file = values.into_iter().map(|value| value.to_string()).collect::<Vec<String>>();
|
||||
// Add the inputs from the file to the arguments.
|
||||
arguments.append(&mut inputs_from_file);
|
||||
}
|
||||
None => arguments.append(&mut inputs),
|
||||
// Parse the network.
|
||||
let network = NetworkName::try_from(self.compiler_options.network.as_str())?;
|
||||
match network {
|
||||
NetworkName::MainnetV0 => handle_run::<MainnetV0>(self, context),
|
||||
NetworkName::TestnetV0 => handle_run::<TestnetV0>(self, context),
|
||||
}
|
||||
|
||||
// Open the Leo build/ directory
|
||||
let path = context.dir()?;
|
||||
let build_directory = BuildDirectory::open(&path)?;
|
||||
|
||||
// Change the cwd to the Leo build/ directory to compile aleo files.
|
||||
std::env::set_current_dir(&build_directory)
|
||||
.map_err(|err| PackageError::failed_to_set_cwd(build_directory.display(), err))?;
|
||||
|
||||
// Unset the Leo panic hook
|
||||
let _ = std::panic::take_hook();
|
||||
|
||||
// Call the `run` command.
|
||||
println!();
|
||||
let command = SnarkVMRun::try_parse_from(&arguments).map_err(CliError::failed_to_parse_run)?;
|
||||
let res = command.parse().map_err(CliError::failed_to_execute_run)?;
|
||||
|
||||
// Log the output of the `run` command.
|
||||
tracing::info!("{}", res);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// A helper function to handle the run command.
|
||||
fn handle_run<N: Network>(command: Run, context: Context) -> Result<<Run as Command>::Output> {
|
||||
let mut inputs = command.inputs;
|
||||
|
||||
// Compose the `run` command.
|
||||
let mut arguments = vec![SNARKVM_COMMAND.to_string(), command.name];
|
||||
|
||||
// Add the inputs to the arguments.
|
||||
match command.file {
|
||||
Some(file) => {
|
||||
// Get the contents from the file.
|
||||
let path = context.dir()?.join(file);
|
||||
let raw_content =
|
||||
std::fs::read_to_string(&path).map_err(|err| PackageError::failed_to_read_file(path.display(), err))?;
|
||||
// Parse the values from the file.
|
||||
let mut content = raw_content.as_str();
|
||||
let mut values = vec![];
|
||||
while let Ok((remaining, value)) = snarkvm::prelude::Value::<N>::parse(content) {
|
||||
content = remaining;
|
||||
values.push(value);
|
||||
}
|
||||
// Check that the remaining content is empty.
|
||||
if !content.trim().is_empty() {
|
||||
return Err(PackageError::failed_to_read_input_file(path.display()).into());
|
||||
}
|
||||
// Convert the values to strings.
|
||||
let mut inputs_from_file = values.into_iter().map(|value| value.to_string()).collect::<Vec<String>>();
|
||||
// Add the inputs from the file to the arguments.
|
||||
arguments.append(&mut inputs_from_file);
|
||||
}
|
||||
None => arguments.append(&mut inputs),
|
||||
}
|
||||
|
||||
// Open the Leo build/ directory
|
||||
let path = context.dir()?;
|
||||
let build_directory = BuildDirectory::open(&path)?;
|
||||
|
||||
// Change the cwd to the Leo build/ directory to compile aleo files.
|
||||
std::env::set_current_dir(&build_directory)
|
||||
.map_err(|err| PackageError::failed_to_set_cwd(build_directory.display(), err))?;
|
||||
|
||||
// Unset the Leo panic hook
|
||||
let _ = std::panic::take_hook();
|
||||
|
||||
// Call the `run` command.
|
||||
println!();
|
||||
let command = SnarkVMRun::try_parse_from(&arguments).map_err(CliError::failed_to_parse_run)?;
|
||||
let res = command.parse().map_err(CliError::failed_to_execute_run)?;
|
||||
|
||||
// Log the output of the `run` command.
|
||||
tracing::info!("{}", res);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -14,7 +14,6 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
use aleo_std;
|
||||
use leo_errors::{CliError, PackageError, Result};
|
||||
use leo_package::build::{BuildDirectory, BUILD_DIRECTORY_NAME};
|
||||
@ -24,6 +23,7 @@ use snarkvm::file::Manifest;
|
||||
|
||||
use aleo_std::aleo_dir;
|
||||
use indexmap::IndexMap;
|
||||
use snarkvm::prelude::Network;
|
||||
use std::{
|
||||
env::current_dir,
|
||||
fs::File,
|
||||
@ -76,10 +76,10 @@ impl Context {
|
||||
|
||||
/// Returns the package name as a String.
|
||||
/// Opens the manifest file `program.json` and creates the build directory if it doesn't exist.
|
||||
pub fn open_manifest(&self) -> Result<Manifest<CurrentNetwork>> {
|
||||
pub fn open_manifest<N: Network>(&self) -> Result<Manifest<N>> {
|
||||
// Open the manifest file.
|
||||
let path = self.dir()?;
|
||||
let manifest = Manifest::<CurrentNetwork>::open(&path).map_err(PackageError::failed_to_open_manifest)?;
|
||||
let manifest = Manifest::<N>::open(&path).map_err(PackageError::failed_to_open_manifest)?;
|
||||
|
||||
// Lookup the program id.
|
||||
// let program_id = manifest.program_id();
|
||||
@ -97,7 +97,7 @@ impl Context {
|
||||
std::fs::read_to_string(manifest.path()).map_err(PackageError::failed_to_read_manifest)?;
|
||||
|
||||
// Construct the file path.
|
||||
let build_manifest_path = build_path.join(Manifest::<CurrentNetwork>::file_name());
|
||||
let build_manifest_path = build_path.join(Manifest::<N>::file_name());
|
||||
|
||||
// Write the file.
|
||||
File::create(build_manifest_path)
|
||||
|
@ -14,8 +14,6 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
pub use super::*;
|
||||
|
||||
pub mod context;
|
||||
pub mod logger;
|
||||
pub mod updater;
|
||||
|
@ -23,7 +23,6 @@ pub use commands::*;
|
||||
mod helpers;
|
||||
pub use helpers::*;
|
||||
|
||||
pub(crate) type CurrentNetwork = snarkvm::prelude::MainnetV0;
|
||||
pub(crate) const SNARKVM_COMMAND: &str = "snarkvm";
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -15,28 +15,27 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{
|
||||
build::BuildDirectory,
|
||||
inputs::InputsDirectory,
|
||||
root::{Env, Gitignore},
|
||||
source::{MainFile, SourceDirectory},
|
||||
};
|
||||
use leo_errors::{PackageError, Result};
|
||||
use snarkvm::console::prelude::Network;
|
||||
|
||||
use leo_retriever::{Manifest, NetworkName};
|
||||
use serde::Deserialize;
|
||||
use std::{marker::PhantomData, path::Path};
|
||||
use snarkvm::prelude::Network;
|
||||
use std::path::Path;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Package<N: Network> {
|
||||
pub struct Package {
|
||||
pub name: String,
|
||||
pub version: String,
|
||||
pub description: Option<String>,
|
||||
pub license: Option<String>,
|
||||
_phantom: PhantomData<N>,
|
||||
pub network: NetworkName,
|
||||
}
|
||||
|
||||
impl<N: Network> Package<N> {
|
||||
pub fn new(package_name: &str) -> Result<Self> {
|
||||
impl Package {
|
||||
pub fn new(package_name: &str, network: NetworkName) -> Result<Self> {
|
||||
// Check that the package name is a valid Aleo program name.
|
||||
if !Self::is_aleo_name_valid(package_name) {
|
||||
return Err(PackageError::invalid_package_name(package_name).into());
|
||||
@ -47,7 +46,7 @@ impl<N: Network> Package<N> {
|
||||
version: "0.1.0".to_owned(),
|
||||
description: None,
|
||||
license: None,
|
||||
_phantom: PhantomData,
|
||||
network,
|
||||
})
|
||||
}
|
||||
|
||||
@ -126,72 +125,79 @@ impl<N: Network> Package<N> {
|
||||
}
|
||||
|
||||
/// Creates a Leo package at the given path
|
||||
pub fn initialize(package_name: &str, path: &Path) -> Result<()> {
|
||||
// Verify that the .gitignore file does not exist.
|
||||
if !Gitignore::exists_at(path) {
|
||||
// Create the .gitignore file.
|
||||
Gitignore::new().write_to(path)?;
|
||||
pub fn initialize<N: Network>(package_name: &str, path: &Path) -> Result<()> {
|
||||
// Construct the path to the package directory.
|
||||
let path = path.join(package_name);
|
||||
|
||||
// Verify that there is no existing directory at the path.
|
||||
if path.exists() {
|
||||
return Err(
|
||||
PackageError::failed_to_initialize_package(package_name, &path, "Directory already exists").into()
|
||||
);
|
||||
}
|
||||
|
||||
// Verify that the .env file does not exist.
|
||||
if !Env::<N>::exists_at(path) {
|
||||
// Create the .env file.
|
||||
Env::<N>::new()?.write_to(path)?;
|
||||
}
|
||||
// Create the package directory.
|
||||
std::fs::create_dir(&path).map_err(|e| PackageError::failed_to_initialize_package(package_name, &path, e))?;
|
||||
|
||||
// Change the current working directory to the package directory.
|
||||
std::env::set_current_dir(&path)
|
||||
.map_err(|e| PackageError::failed_to_initialize_package(package_name, &path, e))?;
|
||||
|
||||
// Create the .gitignore file.
|
||||
Gitignore::new().write_to(&path)?;
|
||||
|
||||
// Create the .env file.
|
||||
Env::<N>::new()?.write_to(&path)?;
|
||||
|
||||
// Create a manifest.
|
||||
let manifest = Manifest::default(package_name);
|
||||
manifest.write_to_dir(&path)?;
|
||||
|
||||
// Create the source directory.
|
||||
SourceDirectory::create(path)?;
|
||||
|
||||
// Create the inputs directory.
|
||||
InputsDirectory::create(path)?;
|
||||
|
||||
// Create the Leo build/ directory
|
||||
BuildDirectory::create(path)?;
|
||||
SourceDirectory::create(&path)?;
|
||||
|
||||
// Create the main file in the source directory.
|
||||
MainFile::new(package_name).write_to(path)?;
|
||||
MainFile::new(package_name).write_to(&path)?;
|
||||
|
||||
// Next, verify that a valid Leo package has been initialized in this directory
|
||||
if !Self::is_initialized(package_name, path) {
|
||||
return Err(PackageError::failed_to_initialize_package(package_name, path.as_os_str()).into());
|
||||
if !Self::is_initialized(package_name, &path) {
|
||||
return Err(PackageError::failed_to_initialize_package(
|
||||
package_name,
|
||||
&path,
|
||||
"Failed to correctly initialize package",
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
//
|
||||
// /// Removes the package at the given path
|
||||
// pub fn remove_imported_package(package_name: &str, path: &Path) -> Result<()> {
|
||||
// ImportsDirectory::remove_import(path, package_name)
|
||||
// }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
type CurrentNetwork = snarkvm::prelude::MainnetV0;
|
||||
|
||||
#[test]
|
||||
fn test_is_package_name_valid() {
|
||||
assert!(Package::<CurrentNetwork>::is_aleo_name_valid("foo"));
|
||||
assert!(Package::<CurrentNetwork>::is_aleo_name_valid("foo_bar"));
|
||||
assert!(Package::<CurrentNetwork>::is_aleo_name_valid("foo1"));
|
||||
assert!(Package::<CurrentNetwork>::is_aleo_name_valid("foo_bar___baz_"));
|
||||
assert!(Package::is_aleo_name_valid("foo"));
|
||||
assert!(Package::is_aleo_name_valid("foo_bar"));
|
||||
assert!(Package::is_aleo_name_valid("foo1"));
|
||||
assert!(Package::is_aleo_name_valid("foo_bar___baz_"));
|
||||
|
||||
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("foo-bar"));
|
||||
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("foo-bar-baz"));
|
||||
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("foo-1"));
|
||||
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid(""));
|
||||
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("-"));
|
||||
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("-foo"));
|
||||
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("-foo-"));
|
||||
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("_foo"));
|
||||
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("foo--bar"));
|
||||
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("foo---bar"));
|
||||
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("foo--bar--baz"));
|
||||
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("foo---bar---baz"));
|
||||
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("foo*bar"));
|
||||
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("foo,bar"));
|
||||
assert!(!Package::<CurrentNetwork>::is_aleo_name_valid("1-foo"));
|
||||
assert!(!Package::is_aleo_name_valid("foo-bar"));
|
||||
assert!(!Package::is_aleo_name_valid("foo-bar-baz"));
|
||||
assert!(!Package::is_aleo_name_valid("foo-1"));
|
||||
assert!(!Package::is_aleo_name_valid(""));
|
||||
assert!(!Package::is_aleo_name_valid("-"));
|
||||
assert!(!Package::is_aleo_name_valid("-foo"));
|
||||
assert!(!Package::is_aleo_name_valid("-foo-"));
|
||||
assert!(!Package::is_aleo_name_valid("_foo"));
|
||||
assert!(!Package::is_aleo_name_valid("foo--bar"));
|
||||
assert!(!Package::is_aleo_name_valid("foo---bar"));
|
||||
assert!(!Package::is_aleo_name_valid("foo--bar--baz"));
|
||||
assert!(!Package::is_aleo_name_valid("foo---bar---baz"));
|
||||
assert!(!Package::is_aleo_name_valid("foo*bar"));
|
||||
assert!(!Package::is_aleo_name_valid("foo,bar"));
|
||||
assert!(!Package::is_aleo_name_valid("1-foo"));
|
||||
}
|
||||
}
|
||||
|
@ -16,26 +16,31 @@
|
||||
|
||||
//! The `.env` file.
|
||||
use leo_errors::{PackageError, Result};
|
||||
use snarkvm::console::{account::PrivateKey, prelude::Network};
|
||||
use leo_retriever::NetworkName;
|
||||
use snarkvm::console::account::PrivateKey;
|
||||
|
||||
use snarkvm::prelude::{MainnetV0, Network, TestnetV0};
|
||||
|
||||
use serde::Deserialize;
|
||||
use std::{borrow::Cow, fs::File, io::Write, marker::PhantomData, path::Path};
|
||||
use std::{borrow::Cow, fs::File, io::Write, path::Path};
|
||||
|
||||
pub static ENV_FILENAME: &str = ".env";
|
||||
|
||||
#[derive(Deserialize, Default)]
|
||||
#[derive(Deserialize)]
|
||||
pub struct Env<N: Network> {
|
||||
data: String,
|
||||
_phantom: PhantomData<N>,
|
||||
#[serde(bound(deserialize = ""))]
|
||||
private_key: PrivateKey<N>,
|
||||
}
|
||||
|
||||
impl<N: Network> Env<N> {
|
||||
pub fn new() -> Result<Self> {
|
||||
Ok(Self { data: Self::template()?, _phantom: PhantomData })
|
||||
}
|
||||
// Initialize an RNG.
|
||||
let rng = &mut rand::thread_rng();
|
||||
|
||||
pub fn from(data: String) -> Self {
|
||||
Self { data, _phantom: PhantomData }
|
||||
// Generate a development private key.
|
||||
let private_key = PrivateKey::<N>::new(rng)?;
|
||||
|
||||
Ok(Self { private_key })
|
||||
}
|
||||
|
||||
pub fn exists_at(path: &Path) -> bool {
|
||||
@ -53,17 +58,26 @@ impl<N: Network> Env<N> {
|
||||
}
|
||||
|
||||
let mut file = File::create(&path).map_err(PackageError::io_error_env_file)?;
|
||||
file.write_all(self.data.as_bytes()).map_err(PackageError::io_error_env_file)?;
|
||||
file.write_all(self.to_string().as_bytes()).map_err(PackageError::io_error_env_file)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn template() -> Result<String> {
|
||||
// Initialize an RNG.
|
||||
let rng = &mut rand::thread_rng();
|
||||
|
||||
// Initialize a new development private key.
|
||||
let private_key = PrivateKey::<N>::new(rng)?;
|
||||
|
||||
Ok(format!("NETWORK=mainnet\nPRIVATE_KEY={private_key}\n"))
|
||||
impl<N: Network> From<PrivateKey<N>> for Env<N> {
|
||||
fn from(private_key: PrivateKey<N>) -> Self {
|
||||
Self { private_key }
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Network> ToString for Env<N> {
|
||||
fn to_string(&self) -> String {
|
||||
// Get the network name.
|
||||
let network = match N::ID {
|
||||
MainnetV0::ID => NetworkName::MainnetV0,
|
||||
TestnetV0::ID => NetworkName::TestnetV0,
|
||||
_ => unimplemented!("Unsupported network"),
|
||||
};
|
||||
// Return the formatted string.
|
||||
format!("NETWORK={network}\nPRIVATE_KEY={}\n", self.private_key)
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,9 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::Dependency;
|
||||
use leo_errors::PackageError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::Path;
|
||||
|
||||
// Struct representation of program's `program.json` specification
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
@ -44,6 +46,16 @@ impl Manifest {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn default(program: &str) -> Self {
|
||||
Self {
|
||||
program: format!("{program}.aleo"),
|
||||
version: "0.1.0".to_owned(),
|
||||
description: "".to_owned(),
|
||||
license: "MIT".to_owned(),
|
||||
dependencies: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn program(&self) -> &String {
|
||||
&self.program
|
||||
}
|
||||
@ -63,4 +75,21 @@ impl Manifest {
|
||||
pub fn dependencies(&self) -> &Option<Vec<Dependency>> {
|
||||
&self.dependencies
|
||||
}
|
||||
|
||||
pub fn write_to_dir(&self, path: &Path) -> Result<(), PackageError> {
|
||||
// Serialize the manifest to a JSON string.
|
||||
let contents = serde_json::to_string_pretty(&self)
|
||||
.map_err(|err| PackageError::failed_to_serialize_manifest_file(path.to_str().unwrap(), err))?;
|
||||
// Write the manifest to the file.
|
||||
std::fs::write(path.join("program.json"), contents).map_err(PackageError::failed_to_write_manifest)
|
||||
}
|
||||
|
||||
pub fn read_from_dir(path: &Path) -> Result<Self, PackageError> {
|
||||
// Read the manifest file.
|
||||
let contents = std::fs::read_to_string(path.join("program.json"))
|
||||
.map_err(|err| PackageError::failed_to_read_file(path.to_str().unwrap(), err))?;
|
||||
// Deserialize the manifest.
|
||||
serde_json::from_str(&contents)
|
||||
.map_err(|err| PackageError::failed_to_deserialize_manifest_file(path.to_str().unwrap(), err))
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,9 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use leo_errors::{CliError, LeoError};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use snarkvm::prelude::{MainnetV0, Network, TestnetV0};
|
||||
use std::fmt;
|
||||
|
||||
// Retrievable networks for an external program
|
||||
@ -26,12 +28,23 @@ pub enum NetworkName {
|
||||
MainnetV0,
|
||||
}
|
||||
|
||||
impl From<&String> for NetworkName {
|
||||
fn from(network: &String) -> Self {
|
||||
match network.to_ascii_lowercase().as_str() {
|
||||
"testnet" => NetworkName::TestnetV0,
|
||||
"mainnet" => NetworkName::MainnetV0,
|
||||
_ => panic!("Invalid network"),
|
||||
impl NetworkName {
|
||||
pub fn id(&self) -> u16 {
|
||||
match self {
|
||||
NetworkName::TestnetV0 => TestnetV0::ID,
|
||||
NetworkName::MainnetV0 => MainnetV0::ID,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for NetworkName {
|
||||
type Error = LeoError;
|
||||
|
||||
fn try_from(network: &str) -> Result<Self, LeoError> {
|
||||
match network {
|
||||
"testnet" => Ok(NetworkName::TestnetV0),
|
||||
"mainnet" => Ok(NetworkName::MainnetV0),
|
||||
_ => Err(LeoError::CliError(CliError::invalid_network_name(network))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user