diff --git a/Cargo.lock b/Cargo.lock index 3ef97fa355e0b..955aa6a1dc1af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -202,23 +202,24 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.5" +version = "0.6.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" +checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56" [[package]] name = "anstyle-parse" @@ -240,12 +241,12 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -317,7 +318,7 @@ dependencies = [ "bcs 0.1.4", "bollard", "chrono", - "clap 4.4.14", + "clap 4.5.20", "clap_complete", "colored", "dashmap", @@ -601,7 +602,7 @@ dependencies = [ "async-trait", "bcs 0.1.4", "bytes", - "clap 4.4.14", + "clap 4.5.20", "csv", "futures", "itertools 0.13.0", @@ -720,7 +721,7 @@ dependencies = [ "aptos-metrics-core", "aptos-types", "bcs 0.1.4", - "clap 4.4.14", + "clap 4.5.20", "criterion", "dashmap", "itertools 0.13.0", @@ -770,7 +771,7 @@ dependencies = [ "anyhow", "camino", "chrono", - "clap 4.4.14", + "clap 4.5.20", "clap-verbosity-flag", "determinator", "env_logger", @@ -797,7 +798,7 @@ name = "aptos-cli-common" version = "1.0.0" dependencies = [ "anstyle", - "clap 4.4.14", + "clap 4.5.20", "clap_complete", ] @@ -817,7 +818,7 @@ dependencies = [ "aptos-validator-interface", "aptos-vm", "bcs 0.1.4", - "clap 4.4.14", + "clap 4.5.20", "futures", "itertools 0.13.0", "move-binary-format", @@ -929,7 +930,7 @@ dependencies = [ "bytes", "chrono", "claims", - "clap 4.4.14", + "clap 4.5.20", "dashmap", "enum_dispatch", "fail", @@ -1188,7 +1189,7 @@ dependencies = [ "bcs 0.1.4", "byteorder", "claims", - "clap 4.4.14", + "clap 4.5.20", "crossbeam-channel", "dashmap", "either", @@ -1269,7 +1270,7 @@ dependencies = [ "aptos-types", "aptos-vm", "bcs 0.1.4", - "clap 4.4.14", + "clap 4.5.20", "itertools 0.13.0", "rayon", "serde_json", @@ -1286,7 +1287,7 @@ dependencies = [ "aptos-logger", "aptos-move-debugger", "aptos-push-metrics", - "clap 4.4.14", + "clap 4.5.20", "jemallocator", "tokio", ] @@ -1518,7 +1519,7 @@ dependencies = [ "async-trait", "bcs 0.1.4", "chrono", - "clap 4.4.14", + "clap 4.5.20", "derivative", "indicatif 0.15.0", "itertools 0.13.0", @@ -1551,7 +1552,7 @@ dependencies = [ "aptos-types", "aptos-vm", "bcs 0.1.4", - "clap 4.4.14", + "clap 4.5.20", "crossbeam-channel", "ctrlc", "dashmap", @@ -1687,7 +1688,7 @@ dependencies = [ "aptos-faucet-core", "aptos-logger", "aptos-sdk", - "clap 4.4.14", + "clap 4.5.20", "tokio", ] @@ -1703,7 +1704,7 @@ dependencies = [ "aptos-sdk", "async-trait", "captcha", - "clap 4.4.14", + "clap 4.5.20", "deadpool-redis", "enum_dispatch", "futures", @@ -1743,7 +1744,7 @@ dependencies = [ "anyhow", "aptos-faucet-core", "aptos-logger", - "clap 4.4.14", + "clap 4.5.20", "tokio", ] @@ -1755,7 +1756,7 @@ dependencies = [ "aptos-logger", "aptos-node-checker", "aptos-sdk", - "clap 4.4.14", + "clap 4.5.20", "env_logger", "futures", "gcp-bigquery-client", @@ -1792,7 +1793,7 @@ dependencies = [ "aptos-transaction-generator-lib", "async-trait", "chrono", - "clap 4.4.14", + "clap 4.5.20", "either", "futures", "hex", @@ -1836,7 +1837,7 @@ dependencies = [ "aptos-testcases", "async-trait", "chrono", - "clap 4.4.14", + "clap 4.5.20", "futures", "jemallocator", "once_cell", @@ -1878,7 +1879,7 @@ dependencies = [ "bulletproofs", "byteorder", "claims", - "clap 4.4.14", + "clap 4.5.20", "codespan-reporting", "curve25519-dalek-ng", "either", @@ -1943,7 +1944,7 @@ dependencies = [ "aptos-language-e2e-tests", "aptos-types", "bcs 0.1.4", - "clap 4.4.14", + "clap 4.5.20", "float-cmp", "move-binary-format", "move-core-types", @@ -2007,7 +2008,7 @@ dependencies = [ "aptos-package-builder", "aptos-types", "bcs 0.1.4", - "clap 4.4.14", + "clap 4.5.20", "move-core-types", "move-model", "tempfile", @@ -2101,7 +2102,7 @@ dependencies = [ "aptos-moving-average 0.1.0 (git+https://github.com/aptos-labs/aptos-indexer-processors.git?rev=4801acae7aea30d7e96bbfbe5ec5b04056dfa4cf)", "aptos-protos 1.3.1", "async-trait", - "clap 4.4.14", + "clap 4.5.20", "futures", "futures-core", "jemallocator", @@ -2129,7 +2130,7 @@ dependencies = [ "aptos-protos 1.3.1", "aptos-transaction-filter", "async-trait", - "clap 4.4.14", + "clap 4.5.20", "futures", "jemallocator", "once_cell", @@ -2154,7 +2155,7 @@ dependencies = [ "aptos-indexer-grpc-utils", "aptos-metrics-core", "async-trait", - "clap 4.4.14", + "clap 4.5.20", "cloud-storage", "jemallocator", "once_cell", @@ -2174,7 +2175,7 @@ dependencies = [ "aptos-metrics-core", "aptos-moving-average 0.1.0 (git+https://github.com/aptos-labs/aptos-indexer-processors.git?rev=4801acae7aea30d7e96bbfbe5ec5b04056dfa4cf)", "async-trait", - "clap 4.4.14", + "clap 4.5.20", "futures", "jemallocator", "once_cell", @@ -2193,7 +2194,7 @@ dependencies = [ "aptos-indexer-grpc-utils", "aptos-protos 1.3.1", "async-trait", - "clap 4.4.14", + "clap 4.5.20", "futures", "jemallocator", "serde", @@ -2284,7 +2285,7 @@ dependencies = [ "aptos-system-utils 0.1.0", "async-trait", "backtrace", - "clap 4.4.14", + "clap 4.5.20", "prometheus", "serde", "serde_yaml 0.8.26", @@ -2408,7 +2409,7 @@ dependencies = [ "aptos-faucet-core", "aptos-indexer-grpc-utils", "aptos-protos 1.3.1", - "clap 4.4.14", + "clap 4.5.20", "futures", "itertools 0.13.0", "rand 0.7.3", @@ -2842,7 +2843,7 @@ dependencies = [ "aptos-vm-logging", "aptos-vm-types", "bcs 0.1.4", - "clap 4.4.14", + "clap 4.5.20", "itertools 0.13.0", "regex", "reqwest 0.11.23", @@ -2870,7 +2871,7 @@ dependencies = [ "aptos-gas-schedule", "aptos-types", "aptos-vm", - "clap 4.4.14", + "clap 4.5.20", "move-cli", "move-model", "move-package", @@ -3080,7 +3081,7 @@ dependencies = [ "aptos-logger", "aptos-network", "aptos-types", - "clap 4.4.14", + "clap 4.5.20", "futures", "serde", "tokio", @@ -3126,7 +3127,7 @@ dependencies = [ "backoff", "bytes", "chrono", - "clap 4.4.14", + "clap 4.5.20", "diesel", "diesel_migrations", "enum_dispatch", @@ -3203,7 +3204,7 @@ dependencies = [ "aptos-vm", "aptos-vm-environment", "bcs 0.1.4", - "clap 4.4.14", + "clap 4.5.20", "either", "fail", "futures", @@ -3233,7 +3234,7 @@ dependencies = [ "aptos-sdk", "aptos-transaction-emitter-lib", "async-trait", - "clap 4.4.14", + "clap 4.5.20", "futures", "once_cell", "poem", @@ -3303,7 +3304,7 @@ dependencies = [ "aptos-mempool", "aptos-storage-interface", "aptos-types", - "clap 4.4.14", + "clap 4.5.20", ] [[package]] @@ -3501,7 +3502,7 @@ dependencies = [ "aptos-vm-logging", "aptos-vm-types", "bcs 0.1.4", - "clap 4.4.14", + "clap 4.5.20", "futures", "git2 0.16.1", "handlebars", @@ -3573,7 +3574,7 @@ dependencies = [ "aptos-types", "bcs 0.1.4", "bytes", - "clap 4.4.14", + "clap 4.5.20", "hex", "move-core-types", "reqwest 0.11.23", @@ -3617,7 +3618,7 @@ dependencies = [ "aptos-types", "aptos-warp-webserver", "bcs 0.1.4", - "clap 4.4.14", + "clap 4.5.20", "futures", "hex", "itertools 0.13.0", @@ -3640,7 +3641,7 @@ dependencies = [ "aptos-logger", "aptos-rosetta", "aptos-types", - "clap 4.4.14", + "clap 4.5.20", "serde", "serde_json", "tokio", @@ -3759,7 +3760,7 @@ dependencies = [ "aptos-framework", "aptos-types", "bcs 0.1.4", - "clap 4.4.14", + "clap 4.5.20", "heck 0.4.1", "move-core-types", "once_cell", @@ -4100,7 +4101,7 @@ dependencies = [ "bcs 0.1.4", "chrono", "claims", - "clap 4.4.14", + "clap 4.5.20", "debug-ignore", "flate2", "futures", @@ -4192,7 +4193,7 @@ dependencies = [ "aptos-types", "aptos-vm", "aptos-vm-logging", - "clap 4.4.14", + "clap 4.5.20", "criterion", "criterion-cpu-time", "num_cpus", @@ -4208,7 +4209,7 @@ dependencies = [ "aptos-logger", "aptos-sdk", "aptos-transaction-emitter-lib", - "clap 4.4.14", + "clap 4.5.20", "futures", "rand 0.7.3", "tokio", @@ -4231,7 +4232,7 @@ dependencies = [ "aptos-types", "async-trait", "base64 0.13.1", - "clap 4.4.14", + "clap 4.5.20", "futures", "hex", "itertools 0.13.0", @@ -4270,7 +4271,7 @@ dependencies = [ "aptos-logger", "aptos-sdk", "async-trait", - "clap 4.4.14", + "clap 4.5.20", "move-binary-format", "once_cell", "rand 0.7.3", @@ -4296,7 +4297,7 @@ dependencies = [ "aptos-vm-environment", "aptos-vm-genesis", "bcs 0.1.4", - "clap 4.4.14", + "clap 4.5.20", "codespan-reporting", "datatest-stable", "hex", @@ -4508,7 +4509,7 @@ dependencies = [ "aptos-language-e2e-tests", "aptos-types", "bcs 0.1.4", - "clap 4.4.14", + "clap 4.5.20", "move-binary-format", "move-core-types", ] @@ -4590,7 +4591,7 @@ dependencies = [ "aptos-types", "aptos-vm", "bcs 0.1.4", - "clap 4.4.14", + "clap 4.5.20", "glob", "move-binary-format", "move-core-types", @@ -5419,9 +5420,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.6" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c79fed4cdb43e993fcdadc7e58a09fd0e3e649c4436fa11da71c9f1f3ee7feb9" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64" @@ -5777,7 +5778,7 @@ version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f03db470b3c0213c47e978da93200259a1eb4dae2e5512cba9955e2b540a6fc6" dependencies = [ - "base64 0.21.6", + "base64 0.21.7", "bollard-stubs", "bytes", "futures-core", @@ -5952,7 +5953,7 @@ name = "calc-dep-sizes" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.4.14", + "clap 4.5.20", "futures", "move-binary-format", "move-core-types", @@ -6103,7 +6104,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.0", + "windows-targets 0.52.6", ] [[package]] @@ -6225,12 +6226,12 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.14" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e92c5c1a78c62968ec57dbc2440366a2d6e5a23faf829970ff1585dc6b18e2" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", - "clap_derive 4.4.7", + "clap_derive 4.5.18", ] [[package]] @@ -6239,20 +6240,20 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c90e95e5bd4e8ac34fa6f37c774b0c6f8ed06ea90c79931fd448fcf941a9767" dependencies = [ - "clap 4.4.14", + "clap 4.5.20", "log", ] [[package]] name = "clap_builder" -version = "4.4.14" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4323769dc8a61e2c39ad7dc26f6f2800524691a44d74fe3d1071a5c24db6370" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", - "clap_lex 0.6.0", - "strsim 0.10.0", + "clap_lex 0.7.2", + "strsim 0.11.1", "terminal_size", ] @@ -6262,7 +6263,7 @@ version = "4.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97aeaa95557bd02f23fbb662f981670c3d20c5a26e69f7354b28f57092437fcd" dependencies = [ - "clap 4.4.14", + "clap 4.5.20", ] [[package]] @@ -6280,11 +6281,11 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "proc-macro2", "quote", "syn 2.0.48", @@ -6301,9 +6302,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "clear_on_drop" @@ -6400,7 +6401,7 @@ name = "compute-module-expansion-size" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.4.14", + "clap 4.5.20", "futures", "move-binary-format", "move-core-types", @@ -7133,6 +7134,15 @@ dependencies = [ "tokio", ] +[[package]] +name = "dearbitrary" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "708ee6091d6965eb85c69f7a707303dcc48cc55fd937fb30e531909a10b314d4" +dependencies = [ + "derive_dearbitrary", +] + [[package]] name = "debug-ignore" version = "1.0.5" @@ -7253,6 +7263,17 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "derive_dearbitrary" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afdf9e6fb6c8a925c6b19b78ec3a80152e7a46dc7811be5f1fa64568e7c7b6c0" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -8008,7 +8029,7 @@ version = "0.1.0" dependencies = [ "anyhow", "atty", - "clap 4.4.14", + "clap 4.5.20", "codespan-reporting", "move-to-yul", "serde_json", @@ -8476,6 +8497,20 @@ dependencies = [ [[package]] name = "fuzzer" version = "0.1.0" +dependencies = [ + "aptos-framework", + "aptos-types", + "arbitrary", + "base64 0.21.7", + "bcs 0.1.4", + "clap 4.5.20", + "csv", + "dearbitrary", + "hex", + "move-binary-format", + "move-core-types", + "sha2 0.9.9", +] [[package]] name = "fuzzer-fuzz" @@ -8488,6 +8523,7 @@ dependencies = [ "aptos-types", "aptos-vm", "arbitrary", + "base64 0.13.1", "bcs 0.1.4", "libfuzzer-sys", "move-binary-format", @@ -8496,6 +8532,7 @@ dependencies = [ "move-vm-types", "once_cell", "rayon", + "ring 0.16.20", "serde", "serde_json", ] @@ -8579,7 +8616,7 @@ dependencies = [ "aptos-network", "aptos-types", "bcs 0.1.4", - "clap 4.4.14", + "clap 4.5.20", "move-core-types", "rand 0.7.3", "serde", @@ -8783,7 +8820,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "931bedb2264cb00f914b0a6a5c304e34865c34306632d3932e0951a073e4a67d" dependencies = [ "async-trait", - "base64 0.21.6", + "base64 0.21.7", "google-cloud-metadata", "google-cloud-token", "home", @@ -8862,7 +8899,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22c57ca1d971d7c6f852c02eda4e87e88b1247b6ed8be9fa5b2768c68b0f2ca5" dependencies = [ "async-stream", - "base64 0.21.6", + "base64 0.21.7", "bytes", "futures-util", "google-cloud-auth", @@ -9081,7 +9118,7 @@ version = "7.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "765c9198f173dd59ce26ff9f95ef0aafd0a0fe01fb9d72841bc5066a4c06511d" dependencies = [ - "base64 0.21.6", + "base64 0.21.7", "byteorder", "flate2", "nom", @@ -9094,7 +9131,7 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" dependencies = [ - "base64 0.21.6", + "base64 0.21.7", "bytes", "headers-core 0.2.0", "http 0.2.11", @@ -9109,7 +9146,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "322106e6bd0cba2d5ead589ddb8150a13d7c4217cf80d7c4f682ca994ccc6aa9" dependencies = [ - "base64 0.21.6", + "base64 0.21.7", "bytes", "headers-core 0.3.0", "http 1.1.0", @@ -9367,7 +9404,7 @@ dependencies = [ "assert-json-diff", "async-object-pool", "async-trait", - "base64 0.21.6", + "base64 0.21.7", "basic-cookies", "crossbeam-utils", "form_urlencoded", @@ -9815,7 +9852,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "321f0f839cd44a4686e9504b0a62b4d69a50b62072144c71c68f5873c167b8d9" dependencies = [ "ahash 0.8.11", - "clap 4.4.14", + "clap 4.5.20", "crossbeam-channel", "crossbeam-utils", "dashmap", @@ -9936,6 +9973,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06d198e9919d9822d5f7083ba8530e04de87841eaf21ead9af8f2304efd57c89" +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "isahc" version = "1.7.2" @@ -10094,7 +10137,7 @@ version = "8.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" dependencies = [ - "base64 0.21.6", + "base64 0.21.7", "pem 1.1.1", "ring 0.16.20", "serde", @@ -10108,7 +10151,7 @@ version = "9.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9ae10193d25051e74945f1ea2d0b42e03cc3b890f7e4cc5faa44997d808193f" dependencies = [ - "base64 0.21.6", + "base64 0.21.7", "js-sys", "pem 3.0.4", "ring 0.17.7", @@ -10902,7 +10945,7 @@ dependencies = [ "anyhow", "aptos-framework", "bcs 0.1.4", - "clap 4.4.14", + "clap 4.5.20", "move-binary-format", ] @@ -10954,6 +10997,7 @@ dependencies = [ "anyhow", "arbitrary", "backtrace", + "dearbitrary", "indexmap 1.9.3", "move-bytecode-spec", "move-core-types", @@ -11023,7 +11067,7 @@ name = "move-bytecode-viewer" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.4.14", + "clap 4.5.20", "crossterm 0.26.1", "move-binary-format", "move-bytecode-source-map", @@ -11037,7 +11081,7 @@ name = "move-cli" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.4.14", + "clap 4.5.20", "codespan-reporting", "colored", "datatest-stable", @@ -11085,7 +11129,7 @@ version = "0.0.1" dependencies = [ "anyhow", "bcs 0.1.4", - "clap 4.4.14", + "clap 4.5.20", "codespan-reporting", "datatest-stable", "hex", @@ -11121,7 +11165,7 @@ dependencies = [ "abstract-domain-derive", "anyhow", "bcs 0.1.4", - "clap 4.4.14", + "clap 4.5.20", "codespan-reporting", "datatest-stable", "ethnum", @@ -11171,6 +11215,7 @@ dependencies = [ "arbitrary", "bcs 0.1.4", "bytes", + "dearbitrary", "ethnum", "hashbrown 0.14.3", "hex", @@ -11195,7 +11240,7 @@ version = "0.1.0" dependencies = [ "anyhow", "bcs 0.1.4", - "clap 4.4.14", + "clap 4.5.20", "codespan", "colored", "move-binary-format", @@ -11213,7 +11258,7 @@ version = "0.1.0" dependencies = [ "anyhow", "bcs 0.1.4", - "clap 4.4.14", + "clap 4.5.20", "codespan", "codespan-reporting", "datatest-stable", @@ -11232,7 +11277,7 @@ name = "move-disassembler" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.4.14", + "clap 4.5.20", "colored", "move-binary-format", "move-bytecode-source-map", @@ -11248,7 +11293,7 @@ name = "move-docgen" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.4.14", + "clap 4.5.20", "codespan", "codespan-reporting", "datatest-stable", @@ -11301,7 +11346,7 @@ name = "move-explain" version = "0.1.0" dependencies = [ "bcs 0.1.4", - "clap 4.4.14", + "clap 4.5.20", "move-command-line-common", "move-core-types", ] @@ -11312,7 +11357,7 @@ version = "0.1.0" dependencies = [ "anyhow", "bcs 0.1.4", - "clap 4.4.14", + "clap 4.5.20", "move-binary-format", "move-bytecode-source-map", "move-bytecode-verifier", @@ -11417,7 +11462,7 @@ name = "move-package" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.4.14", + "clap 4.5.20", "colored", "datatest-stable", "evm-exec-utils", @@ -11456,7 +11501,7 @@ version = "0.1.0" dependencies = [ "anyhow", "atty", - "clap 4.4.14", + "clap 4.5.20", "codespan-reporting", "datatest-stable", "itertools 0.13.0", @@ -11652,7 +11697,7 @@ version = "0.1.0" dependencies = [ "anyhow", "atty", - "clap 4.4.14", + "clap 4.5.20", "codespan", "codespan-reporting", "datatest-stable", @@ -11683,7 +11728,7 @@ name = "move-transactional-test-runner" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.4.14", + "clap 4.5.20", "datatest-stable", "difference", "move-binary-format", @@ -11715,7 +11760,7 @@ version = "0.1.0" dependencies = [ "anyhow", "better_any", - "clap 4.4.14", + "clap 4.5.20", "codespan-reporting", "colored", "datatest-stable", @@ -13271,7 +13316,7 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49b6c5ef183cd3ab4ba005f1ca64c21e8bd97ce4699cfea9e8d9a2c4958ca520" dependencies = [ - "base64 0.21.6", + "base64 0.21.7", "byteorder", "bytes", "fallible-iterator", @@ -13557,7 +13602,7 @@ dependencies = [ "bitflags 2.6.0", "canonical_json", "chrono", - "clap 4.4.14", + "clap 4.5.20", "diesel", "diesel-async", "diesel_migrations", @@ -13842,7 +13887,7 @@ version = "0.1.0" dependencies = [ "anyhow", "chrono", - "clap 4.4.14", + "clap 4.5.20", "codespan-reporting", "itertools 0.13.0", "log", @@ -14321,7 +14366,7 @@ version = "0.11.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" dependencies = [ - "base64 0.21.6", + "base64 0.21.7", "bytes", "cookie 0.16.2", "cookie_store", @@ -14826,7 +14871,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.6", + "base64 0.21.7", ] [[package]] @@ -14835,7 +14880,7 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f48172685e6ff52a556baa527774f61fcaa884f59daf3375c62a3f1cd2549dab" dependencies = [ - "base64 0.21.6", + "base64 0.21.7", "rustls-pki-types", ] @@ -15309,7 +15354,7 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23" dependencies = [ - "base64 0.21.6", + "base64 0.21.7", "chrono", "hex", "indexmap 1.9.3", @@ -15386,7 +15431,7 @@ dependencies = [ "aptos-system-utils 0.1.0 (git+https://github.com/aptos-labs/aptos-core.git?rev=202bdccff2b2d333a385ae86a4fcf23e89da9f62)", "async-trait", "backtrace", - "clap 4.4.14", + "clap 4.5.20", "prometheus", "serde", "serde_yaml 0.8.26", @@ -16279,12 +16324,12 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" +checksum = "4f599bd7ca042cfdf8f4512b277c02ba102247820f9d9d4a9f521f496751a6ef" dependencies = [ "rustix 0.38.28", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -16330,7 +16375,7 @@ dependencies = [ name = "test-generation" version = "0.1.0" dependencies = [ - "clap 4.4.14", + "clap 4.5.20", "crossbeam-channel", "getrandom 0.2.11", "hex", @@ -16355,7 +16400,7 @@ name = "testdiff" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.4.14", + "clap 4.5.20", "once_cell", "regex", "walkdir", @@ -16822,7 +16867,7 @@ dependencies = [ "async-stream", "async-trait", "axum 0.6.20", - "base64 0.21.6", + "base64 0.21.7", "bytes", "flate2", "futures-core", @@ -17947,7 +17992,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.6", ] [[package]] @@ -17974,7 +18019,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -18009,17 +18063,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -18036,9 +18091,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -18054,9 +18109,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -18072,9 +18127,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -18090,9 +18151,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -18108,9 +18169,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -18126,9 +18187,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -18144,9 +18205,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" @@ -18242,7 +18303,7 @@ checksum = "b61da40aeb0907a65f7fb5c1de83c5a224d6a9ebb83bf918588a2bb744d636b8" dependencies = [ "anyhow", "async-trait", - "base64 0.21.6", + "base64 0.21.7", "futures", "http 0.2.11", "hyper 0.14.28", diff --git a/Cargo.toml b/Cargo.toml index 64384fd8c1c8f..57eb07ee62bbf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -589,6 +589,7 @@ ethnum = "1.5.0" event-listener = "2.5.3" evm = { version = "0.33.1", features = ["tracing"] } evm-runtime = { version = "0.33.0", features = ["tracing"] } +dearbitrary = { version = "1.0.4", features = ["derive"] } fail = "0.5.0" ff = { version = "0.13", features = ["derive"] } field_count = "0.1.1" diff --git a/testsuite/fuzzer/Cargo.toml b/testsuite/fuzzer/Cargo.toml index 1afea076541cd..4d8b3d26f2e78 100644 --- a/testsuite/fuzzer/Cargo.toml +++ b/testsuite/fuzzer/Cargo.toml @@ -5,3 +5,15 @@ edition = "2021" license = { workspace = true } [dependencies] +aptos-framework = { workspace = true } +aptos-types = { workspace = true } +arbitrary = { workspace = true } +base64 = "0.21.7" +bcs = { workspace = true } +clap = "4.5.20" +csv = "1.3.0" +dearbitrary = { workspace = true } +hex = "0.4.3" +move-binary-format = { workspace = true, features = ["fuzzing"] } +move-core-types = { workspace = true, features = ["fuzzing"] } +sha2 = { workspace = true } diff --git a/testsuite/fuzzer/README.md b/testsuite/fuzzer/README.md index c33bc198058b2..d948c5cc611a0 100644 --- a/testsuite/fuzzer/README.md +++ b/testsuite/fuzzer/README.md @@ -12,7 +12,10 @@ The script includes several functions to manage and execute fuzz tests: ```bash ./fuzz.sh add ``` - +- `block-builder`: Run rust utility to build fuzzers. + ```bash + ./fuzz.sh block-builder [args] + ``` - `build`: Build specified fuzz targets or all targets. ```bash ./fuzz.sh build [target_dir] @@ -22,7 +25,22 @@ The script includes several functions to manage and execute fuzz tests: ```bash ./fuzz.sh build-oss-fuzz ``` - +- `coverage`: Generates coverage report in HTML format + ```bash + ./fuzz.sh coverage + ``` +- `coverage-cleanup`: + ```bash + ./fuzz.sh clean-coverage + ``` +- `degub`: Run fuzzer with GDB and pass test_case as input + ```bash + ./fuzz.sh debug + ``` +- `flamegraph`: Generates flamegraph report (might requires addition setups on the os) + ``` + ./fuzz.sh flamegraph + ``` - `list`: List all existing fuzz targets. ```bash ./fuzz.sh list @@ -97,6 +115,15 @@ When building in the OSS-Fuzz environment, `fuzz.sh` will place the corpus archi - **Error Handling:** Implement robust error handling to intercept crashes or unwanted/unexpected behavior. - **Performance Optimization:** Optimize for performance to enable more iterations and deeper fuzzing. +## Generate Corpora +Some fuzzers operate better if a good initial corpus is provided. In order to generate the corpus, utilities are available via `./fuzz.sh block-builder`. Once a corpus is obtained, to feed it to fuzzers running on OSS-Fuzz, building a ZIP archive with a specific name is required: `$FUZZERNAME_seed_corpus.zip`. Upload it to a publicly accessible cloud, e.g., GCP Bucket or S3; avoid GDrive. Obtain a public link and add it to the `CORPUS_ZIPS` array in `fuzz.sh`. It will automatically be downloaded and used inside Google's infrastructure. +### Aptos-VM Publish & Run +`./fuzz.sh block-builder generate_runnable_state /tmp/modules.csv /tmp/Modules` +The CSV file is structured as follows: +- Column 1: Module name +- Column 2: Module address +- Column 3: Base64-encoded bytecode of the module + ## References - [Rust Fuzz Book](https://rust-fuzz.github.io/book/) - [Google OSS-Fuzz](https://google.github.io/oss-fuzz/) diff --git a/testsuite/fuzzer/data/.gitignore b/testsuite/fuzzer/data/.gitignore new file mode 100644 index 0000000000000..45ed3d72d55d8 --- /dev/null +++ b/testsuite/fuzzer/data/.gitignore @@ -0,0 +1 @@ +*/build \ No newline at end of file diff --git a/testsuite/fuzzer/data/install-federated-jwks/Move.toml b/testsuite/fuzzer/data/install-federated-jwks/Move.toml new file mode 100644 index 0000000000000..d1533a9f87304 --- /dev/null +++ b/testsuite/fuzzer/data/install-federated-jwks/Move.toml @@ -0,0 +1,16 @@ +[package] +name = "install-federated-jwks" +version = "1.0.0" +authors = [] + +[addresses] +named_addr = "0xFED" + +[dev-addresses] + +[dependencies.AptosFramework] +git = "https://github.com/aptos-labs/aptos-core.git" +rev = "mainnet" +subdir = "aptos-move/framework/aptos-framework" + +[dev-dependencies] diff --git a/testsuite/fuzzer/data/install-federated-jwks/sources/install_federated_jwks.move b/testsuite/fuzzer/data/install-federated-jwks/sources/install_federated_jwks.move new file mode 100644 index 0000000000000..623e8adc63815 --- /dev/null +++ b/testsuite/fuzzer/data/install-federated-jwks/sources/install_federated_jwks.move @@ -0,0 +1,19 @@ +script { + use aptos_framework::jwks; + use std::string::utf8; + fun main(account: &signer) {{ + let iss = b"test.oidc.provider"; + let kid = utf8(b"RSA"); + let alg = utf8(b"RS256"); + let e = utf8(b"AQAB"); + let n = utf8(b"6S7asUuzq5Q_3U9rbs-PkDVIdjgmtgWreG5qWPsC9xXZKiMV1AiV9LXyqQsAYpCqEDM3XbfmZqGb48yLhb_XqZaKgSYaC_h2DjM7lgrIQAp9902Rr8fUmLN2ivr5tnLxUUOnMOc2SQtr9dgzTONYW5Zu3PwyvAWk5D6ueIUhLtYzpcB-etoNdL3Ir2746KIy_VUsDwAM7dhrqSK8U2xFCGlau4ikOTtvzDownAMHMrfE7q1B6WZQDAQlBmxRQsyKln5DIsKv6xauNsHRgBAKctUxZG8M4QJIx3S6Aughd3RZC4Ca5Ae9fd8L8mlNYBCrQhOZ7dS0f4at4arlLcajtw"); + jwks::update_federated_jwk_set( + account, + iss, + vector[kid], + vector[alg], + vector[e], + vector[n] + ); + }} +} diff --git a/testsuite/fuzzer/fuzz.sh b/testsuite/fuzzer/fuzz.sh index 057a13d816349..b0171f5c1370a 100755 --- a/testsuite/fuzzer/fuzz.sh +++ b/testsuite/fuzzer/fuzz.sh @@ -2,6 +2,9 @@ export RUSTFLAGS="${RUSTFLAGS} --cfg tokio_unstable" export EXTRAFLAGS="-Ztarget-applies-to-host -Zhost-config" +# Nightly version control +# Pin nightly-2024-02-12 because of https://github.com/google/oss-fuzz/issues/11626 +NIGHTLY_VERSION="nightly-2024-02-12" # GDRIVE format https://docs.google.com/uc?export=download&id=DOCID CORPUS_ZIPS=("https://storage.googleapis.com/aptos-core-corpora/move_aptosvm_publish_and_run_seed_corpus.zip" "https://storage.googleapis.com/aptos-core-corpora/move_aptosvm_publish_seed_corpus.zip") @@ -16,9 +19,6 @@ function error() { } function cargo_fuzz() { - # Nightly version control - # Pin nightly-2024-02-12 because of https://github.com/google/oss-fuzz/issues/11626 - NIGHTLY_VERSION="nightly-2024-02-12" rustup install $NIGHTLY_VERSION if [ -z "$1" ]; then error "error using cargo()" @@ -28,11 +28,25 @@ function cargo_fuzz() { $cargo_fuzz_cmd $EXTRAFLAGS $@ } +function cargo_local() { + rustup install $NIGHTLY_VERSION + if [ -z "$1" ]; then + error "error using cargo()" + fi + cargo_cmd="cargo "+$NIGHTLY_VERSION" $1" + shift + $cargo_cmd $EXTRAFLAGS $@ +} + function usage() { case "$1" in "add") echo "Usage: $0 add " ;; + "block-builder") + #echo "Usage: $0 block-builder [argumetns]" + cargo_local run --quiet -- --help + ;; "build") echo "Usage: $0 build [target_dir]" ;; @@ -61,8 +75,9 @@ function usage() { echo "Usage: $0 test" ;; *) - echo "Usage: $0 " + echo "Usage: $0 " echo " add adds a new fuzz target" + echo " block-builder runs rust tool to hel build fuzzers" echo " build builds fuzz targets" echo " build-oss-fuzz builds fuzz targets for oss-fuzz" echo " coverage generates coverage for a fuzz target" @@ -77,6 +92,16 @@ function usage() { exit 1 } +function block-builder() { + if [ -z "$1" ]; then + usage block-builder + fi + command=$1 + shift + cargo_local run --quiet -- $command $@ + exit 0 +} + function build() { if [ -z "$1" ]; then usage build @@ -217,14 +242,9 @@ function flamegraph() { error "$testcase does not exist" fi info "Generating flamegraph for $fuzz_target with $testcase" - # find the binary - binary=$(find ./target -name $fuzz_target -type f -perm /111) - if [ -z "$binary" ]; then - error "Could not find binary for $fuzz_target. Run `./fuzz.sh build $fuzz_target` first" - fi # run the binary with cargo-flamegraph time=$(date +%s) - cargo flamegraph -o "${fuzz_target}_${time}.svg" --bin "$binary" "$testcase -- -runs=1" + cargo flamegraph -o "${fuzz_target}_${time}.svg" --root -p="fuzzer-fuzz" --bin="$fuzz_target" -- "$testcase" "-- -runs=1" } function run() { @@ -298,6 +318,10 @@ case "$1" in shift add "$@" ;; + "block-builder") + shift + block-builder "$@" + ;; "build") shift build "$@" diff --git a/testsuite/fuzzer/fuzz/Cargo.toml b/testsuite/fuzzer/fuzz/Cargo.toml index 30776b12c1acc..1edbf019c14b9 100644 --- a/testsuite/fuzzer/fuzz/Cargo.toml +++ b/testsuite/fuzzer/fuzz/Cargo.toml @@ -15,6 +15,7 @@ aptos-language-e2e-tests = { workspace = true, features = ["fuzzing"] } aptos-types = { workspace = true, features = ["fuzzing"] } aptos-vm = { workspace = true } arbitrary = { workspace = true, features = ["derive"] } +base64 = { workspace = true } bcs = { workspace = true } libfuzzer-sys = "0.4" move-binary-format = { workspace = true, features = ["fuzzing"] } @@ -23,12 +24,10 @@ move-core-types = { workspace = true, features = ["fuzzing"] } move-vm-types = { workspace = true, features = ["fuzzing"] } once_cell = { workspace = true } rayon = { workspace = true } +ring = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } -[features] -disabled = [] - [[bin]] name = "move_bytecode_verifier_code_unit" path = "fuzz_targets/move/bytecode_verifier_code_unit.rs" @@ -41,6 +40,30 @@ path = "fuzz_targets/move/bytecode_verifier_mixed.rs" test = false doc = false +[[bin]] +name = "move_value_deserialize" +path = "fuzz_targets/move/value_deserialize.rs" +test = false +doc = false + +[[bin]] +name = "move_move_value_deserialize" +path = "fuzz_targets/move/move_value_deserialize.rs" +test = false +doc = false + +[[bin]] +name = "move_move_value_decorate" +path = "fuzz_targets/move/move_value_decorate.rs" +test = false +doc = false + +[[bin]] +name = "signed_transaction_deserialize" +path = "fuzz_targets/signed_transaction_deserialize.rs" +test = false +doc = false + [[bin]] name = "move_aptosvm_publish_and_run" path = "fuzz_targets/move/aptosvm_publish_and_run.rs" @@ -58,30 +81,3 @@ name = "move_aptosvm_authenticators" path = "fuzz_targets/move/aptosvm_authenticators.rs" test = false doc = false - -#[[bin]]#name = "move_value_deserialize" -#path = "fuzz_targets/move/value_deserialize.rs" -#test = false -#doc = false -#required-features = ["disabled"] - -#[[bin]] -#name = "move_move_value_deserialize" -#path = "fuzz_targets/move/move_value_deserialize.rs" -#test = false -#doc = false -#required-features = ["disabled"] - -#[[bin]] -#name = "move_move_value_decorate" -#path = "fuzz_targets/move/move_value_decorate.rs" -#test = false -#doc = false -#required-features = ["disabled"] - -#[[bin]] -#name = "signed_transaction_deserialize" -#path = "fuzz_targets/signed_transaction_deserialize.rs" -#test = false -#doc = false -#required-features = ["disabled"] diff --git a/testsuite/fuzzer/fuzz/fuzz_targets/move/aptosvm_authenticators.rs b/testsuite/fuzzer/fuzz/fuzz_targets/move/aptosvm_authenticators.rs index a406d991a800c..759c55c6be2d2 100644 --- a/testsuite/fuzzer/fuzz/fuzz_targets/move/aptosvm_authenticators.rs +++ b/testsuite/fuzzer/fuzz/fuzz_targets/move/aptosvm_authenticators.rs @@ -1,7 +1,7 @@ -#![no_main] - // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 +#![no_main] +#![allow(unused_imports)] use aptos_cached_packages::aptos_stdlib; use aptos_crypto::{ @@ -13,7 +13,14 @@ use aptos_language_e2e_tests::{ }; use aptos_types::{ chain_id::ChainId, - keyless::{AnyKeylessPublicKey, KeylessSignature, TransactionAndProof}, + jwks::{secure_test_rsa_jwk, AllProvidersJWKs, PatchedJWKs, ProviderJWKs}, + keyless::{ + test_utils::get_sample_iss, AnyKeylessPublicKey, Configuration, EphemeralCertificate, + Groth16Proof, Groth16ProofAndStatement, IdCommitment, KeylessPublicKey, KeylessSignature, + OpenIdSig, TransactionAndProof, ZeroKnowledgeSig, ZKP, + }, + on_chain_config::OnChainConfig, + state_store::state_key::StateKey, transaction::{ authenticator::{ AccountAuthenticator, AnyPublicKey, AnySignature, EphemeralPublicKey, @@ -25,12 +32,21 @@ use aptos_types::{ }; use aptos_vm::AptosVM; use libfuzzer_sys::{fuzz_target, Corpus}; -use move_core_types::vm_status::{StatusCode, StatusType}; +use move_core_types::{ + account_address::AccountAddress, + vm_status::{StatusCode, StatusType}, +}; use once_cell::sync::Lazy; +use ring::signature; use std::sync::Arc; mod utils; use utils::{ - check_for_invariant_violation, FuzzerTransactionAuthenticator, Style, TransactionState, + authenticator::{ + miscellaneous::{SampleJwtPayload, SAMPLE_EPK_BLINDER, SAMPLE_JWK_SK, SAMPLE_PEPPER}, + FuzzerTransactionAuthenticator, Style, TransactionState, + }, + helpers::base64url_encode_str, + vm::check_for_invariant_violation, }; // genesis write set generated once for each fuzzing session @@ -146,67 +162,170 @@ fn run_case(input: TransactionState) -> Result<(), Corpus> { // Construct the SignedTransaction SignedTransaction::new_signed_transaction(raw_tx, authenticator) }, + // Style::MatchJWT => { + + // // Generate a keypair for ephemeral keys + // let private_key = Ed25519PrivateKey::generate_for_testing(); + // let public_key: Ed25519PublicKey = private_key.public_key(); + + // // Create a TransactionAndProof to be signed + // let txn_and_proof = TransactionAndProof { + // message: raw_tx.clone(), + // proof: None, + // }; + + // let ks_sig: KeylessSignature; + // let any_public_key: AnyPublicKey; + + // // Sign the transaction + // let signature = private_key.sign(&txn_and_proof).map_err(|_| Corpus::Keep)?; + + // // Setup storage or chain state + // match any_keyless_public_key { + // AnyKeylessPublicKey::Normal(_) => { + // // Push JWKs via write_state_value to make them available to fetch_config + // let state_key = StateKey::resource(&AccountAddress::ONE, &PatchedJWKs::struct_tag()).unwrap(); + // let iss = get_sample_iss(); + // let patched_jwks = PatchedJWKs { + // jwks: AllProvidersJWKs { + // entries: vec![ProviderJWKs { + // issuer: iss.into_bytes(), + // version: 0, + // jwks: vec![secure_test_rsa_jwk().into()], + // }], + // }, + // }; + // let data_blob = bcs::to_bytes(&patched_jwks).unwrap(); + // vm.write_state_value(state_key, data_blob); + + // let config = Configuration::new_for_devnet(); + + // // TODO: check if I need to move this to the top + // let epk = EphemeralPublicKey::ed25519(public_key); + + // // Build JSON Web Token + // let mut jwt_json = ::default(); + // jwt_json.aud = "aud".to_string(); + // jwt_json.sub = "sub".to_string(); + // jwt_json.iss = get_sample_iss(); // this is contained also in JWKs issuer, need to match + // jwt_json.exp = keyless_signature.exp_date_secs(); + // jwt_json.iat = keyless_signature.exp_date_secs()-10; // need to be less than exp, I should generate it to test for overflow + // jwt_json.nonce = OpenIdSig::reconstruct_oauth_nonce(SAMPLE_EPK_BLINDER.clone().as_slice(), keyless_signature.exp_date_secs(), &epk, &config).unwrap(); + + // let jwt_header_b64 = base64url_encode_str(&input.tx_auth_type.get_jwt_header_json().unwrap()); //SAMPLE_JWT_HEADER_B64.to_string(); + // let jwt_payload_b64 = base64url_encode_str(&serde_json::to_string(&jwt_json).unwrap()); + // let msg = jwt_header_b64.clone() + "." + jwt_payload_b64.as_str(); + // let rng = ring::rand::SystemRandom::new(); //TODO: use a fixed seed + // let sk = *SAMPLE_JWK_SK; + // let mut jwt_sig = vec![0u8; sk.public_modulus_len()]; + + // sk.sign( + // &signature::RSA_PKCS1_SHA256, + // &rng, + // msg.as_bytes(), + // jwt_sig.as_mut_slice(), + // ) + // .unwrap(); + + // // Build OpenIdSig + // let openid_sig = OpenIdSig { + // jwt_sig, + // jwt_payload_json: serde_json::to_string(&jwt_json).unwrap(), + // uid_key: "aud".to_string(), + // epk_blinder: SAMPLE_EPK_BLINDER.clone(), + // pepper: SAMPLE_PEPPER.clone(), + // idc_aud_val: None, + // }; + + // // Build KeylessSignature + // ks_sig = KeylessSignature { + // cert: EphemeralCertificate::OpenIdSig(openid_sig.clone()), // TODO: this should be ZeroKnowledgeSig not OpenIdSig + // jwt_header_json: input.tx_auth_type.get_jwt_header_json().unwrap(), //SAMPLE_JWT_HEADER_JSON.to_string(), + // exp_date_secs: keyless_signature.exp_date_secs(), + // ephemeral_pubkey: epk, + // ephemeral_signature: EphemeralSignature::ed25519(signature), + // }; + + // // Build AnyPublicKey::Keyless + // any_public_key = AnyPublicKey::Keyless { + // public_key: KeylessPublicKey { + // iss_val: get_sample_iss().to_string(), + // // idc here is matched against OpenIdSig::pepper, idc_aud_val, uid_key, uid_val + // idc: IdCommitment::new_from_preimage( + // &SAMPLE_PEPPER.clone(), + // &jwt_json.aud, + // "aud", + // &jwt_json.sub, + // ) + // .map_err(|_| Corpus::Keep)?, + // }, + // }; + + // }, + // AnyKeylessPublicKey::Federated(_) => { + // // TODO: deploy Federated JWK at some address to be available for get_federated_jwks_onchain + // let acc = Account::new(); + // let tx = acc + // .transaction() + // .gas_unit_price(100) + // .sequence_number(0) + // .payload(bcs::from_bytes(&[0, 132, 5, 161, 28, 235, 11, 6, 0, 0, 0, 7, 1, 0, 4, 2, 4, 4, 3, 8, 10, 5, 18, 36, 7, 54, 49, 8, 103, 32, 6, 135, 1, 138, 3, 0, 0, 0, 1, 1, 2, 7, 0, 1, 3, 3, 4, 0, 0, 4, 5, 2, 0, 1, 6, 12, 4, 8, 0, 8, 0, 8, 0, 8, 0, 0, 1, 10, 2, 1, 8, 0, 6, 6, 12, 10, 2, 10, 8, 0, 10, 8, 0, 10, 8, 0, 10, 8, 0, 4, 106, 119, 107, 115, 6, 115, 116, 114, 105, 110, 103, 6, 83, 116, 114, 105, 110, 103, 4, 117, 116, 102, 56, 24, 117, 112, 100, 97, 116, 101, 95, 102, 101, 100, 101, 114, 97, 116, 101, 100, 95, 106, 119, 107, 95, 115, 101, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 10, 2, 4, 3, 82, 83, 65, 10, 2, 6, 5, 82, 83, 50, 53, 54, 10, 2, 5, 4, 65, 81, 65, 66, 10, 2, 216, 2, 214, 2, 54, 83, 55, 97, 115, 85, 117, 122, 113, 53, 81, 95, 51, 85, 57, 114, 98, 115, 45, 80, 107, 68, 86, 73, 100, 106, 103, 109, 116, 103, 87, 114, 101, 71, 53, 113, 87, 80, 115, 67, 57, 120, 88, 90, 75, 105, 77, 86, 49, 65, 105, 86, 57, 76, 88, 121, 113, 81, 115, 65, 89, 112, 67, 113, 69, 68, 77, 51, 88, 98, 102, 109, 90, 113, 71, 98, 52, 56, 121, 76, 104, 98, 95, 88, 113, 90, 97, 75, 103, 83, 89, 97, 67, 95, 104, 50, 68, 106, 77, 55, 108, 103, 114, 73, 81, 65, 112, 57, 57, 48, 50, 82, 114, 56, 102, 85, 109, 76, 78, 50, 105, 118, 114, 53, 116, 110, 76, 120, 85, 85, 79, 110, 77, 79, 99, 50, 83, 81, 116, 114, 57, 100, 103, 122, 84, 79, 78, 89, 87, 53, 90, 117, 51, 80, 119, 121, 118, 65, 87, 107, 53, 68, 54, 117, 101, 73, 85, 104, 76, 116, 89, 122, 112, 99, 66, 45, 101, 116, 111, 78, 100, 76, 51, 73, 114, 50, 55, 52, 54, 75, 73, 121, 95, 86, 85, 115, 68, 119, 65, 77, 55, 100, 104, 114, 113, 83, 75, 56, 85, 50, 120, 70, 67, 71, 108, 97, 117, 52, 105, 107, 79, 84, 116, 118, 122, 68, 111, 119, 110, 65, 77, 72, 77, 114, 102, 69, 55, 113, 49, 66, 54, 87, 90, 81, 68, 65, 81, 108, 66, 109, 120, 82, 81, 115, 121, 75, 108, 110, 53, 68, 73, 115, 75, 118, 54, 120, 97, 117, 78, 115, 72, 82, 103, 66, 65, 75, 99, 116, 85, 120, 90, 71, 56, 77, 52, 81, 74, 73, 120, 51, 83, 54, 65, 117, 103, 104, 100, 51, 82, 90, 67, 52, 67, 97, 53, 65, 101, 57, 102, 100, 56, 76, 56, 109, 108, 78, 89, 66, 67, 114, 81, 104, 79, 90, 55, 100, 83, 48, 102, 52, 97, 116, 52, 97, 114, 108, 76, 99, 97, 106, 116, 119, 10, 2, 19, 18, 116, 101, 115, 116, 46, 111, 105, 100, 99, 46, 112, 114, 111, 118, 105, 100, 101, 114, 0, 0, 1, 24, 7, 0, 17, 0, 12, 3, 7, 1, 17, 0, 12, 1, 7, 2, 17, 0, 12, 2, 7, 3, 17, 0, 12, 4, 11, 0, 7, 4, 11, 3, 64, 4, 1, 0, 0, 0, 0, 0, 0, 0, 11, 1, 64, 4, 1, 0, 0, 0, 0, 0, 0, 0, 11, 2, 64, 4, 1, 0, 0, 0, 0, 0, 0, 0, 11, 4, 64, 4, 1, 0, 0, 0, 0, 0, 0, 0, 17, 1, 2, 0, 0]).unwrap()) + // .sign(); + + // vm.execute_and_apply(tx.clone()); + + // let public_inputs_hash = fr_to_bytes_le(&get_public_inputs_hash(&sig, pk, jwk, config).unwrap()); + + // // Build ZKP + // let proof = ZKP::Groth16( + // Groth16Proof { + // a: sig.a, + // b: sig.b, + // c: sig.c, + // } + // ); + + // // Build ZeroKnowledgeSig + // let zk_sig = ZeroKnowledgeSig { + // proof, + // exp_horizon_secs: 0, + // extra_field: None, + // override_aud_val: None, + // training_wheels_signature: None, + // }; + + // // Build KeylessSignature + // ks_sig = KeylessSignature { + // cert: EphemeralCertificate::ZeroKnowledgeSig(zk_sig.clone()), + // jwt_header_json: input.tx_auth_type.get_jwt_header_json().unwrap(), //SAMPLE_JWT_HEADER_JSON.to_string(), + // exp_date_secs: keyless_signature.exp_date_secs(), + // ephemeral_pubkey: epk, + // ephemeral_signature: EphemeralSignature::ed25519(signature), + // }; + + // let fed_pk = FederatedKeylessPublicKey { + // acc, + // pk: SAMPLE_PK.clone(), + // }; + // }, + // }; + + // // Build AnySignature::Keyless + // let any_signature = AnySignature::Keyless { + // signature: ks_sig, + // }; + + // // Build an authenticator + // let authenticator = TransactionAuthenticator::SingleSender { + // sender: AccountAuthenticator::SingleKey { + // authenticator: SingleKeyAuthenticator::new(any_public_key, any_signature), + // }, + // }; + + // // Construct the SignedTransaction + // SignedTransaction::new_signed_transaction(raw_tx, authenticator) + // }, /* - Style::MatchJWT => { - // Generate a keypair for ephemeral keys - let private_key = Ed25519PrivateKey::generate_for_testing(); - let public_key: Ed25519PublicKey = private_key.public_key(); - - // Create a TransactionAndProof to be signed - let txn_and_proof = TransactionAndProof { - message: raw_tx.clone(), - proof: None, - }; - - // Sign the transaction - let signature = private_key.sign(&txn_and_proof).map_err(|_| Corpus::Keep)?; - - // Build AnyPublicKey::Keyless - let any_public_key = AnyPublicKey::Keyless { - public_key: KeylessPublicKey { - iss_val: "test.oidc.provider".to_string(), - idc: IdCommitment::new_from_preimage( - &Pepper::from_number(0x5678), - "aud", - "uid_key", - "uid_val", - ) - .map_err(|_| Corpus::Keep)?, - }, - }; - - /* - EphemeralCertificate::OpenIdSig(OpenIdSig { - jwt_sig: vec![], - jwt_payload_json: "jwt_payload_json".to_string(), - uid_key: "uid_key".to_string(), - epk_blinder: b"epk_blinder".to_vec(), - pepper: Pepper::from_number(0x1234), - idc_aud_val: None, - }) - */ - - // Build AnySignature::Keyless - let any_signature = AnySignature::Keyless { - signature: KeylessSignature { - cert: keyless_signature.cert().clone(), - jwt_header_json: input.tx_auth_type.get_jwt_header_json().unwrap(), - exp_date_secs: keyless_signature.exp_date_secs(), - ephemeral_pubkey: EphemeralPublicKey::ed25519(public_key), - ephemeral_signature: EphemeralSignature::ed25519(signature), - }, - }; - - // Build an authenticator - let authenticator = TransactionAuthenticator::SingleSender { - sender: AccountAuthenticator::SingleKey { - authenticator: SingleKeyAuthenticator::new(any_public_key, any_signature), - }, - }; - - // Construct the SignedTransaction - SignedTransaction::new_signed_transaction(raw_tx, authenticator) - }, Style::MatchKeys => { // Generate a keypair for ephemeral keys let private_key = Ed25519PrivateKey::generate_for_testing(); @@ -267,7 +386,7 @@ fn run_case(input: TransactionState) -> Result<(), Corpus> { // Construct the SignedTransaction SignedTransaction::new_signed_transaction(raw_tx, authenticator) } - */ + */ } }, FuzzerTransactionAuthenticator::MultiAgent { diff --git a/testsuite/fuzzer/fuzz/fuzz_targets/move/aptosvm_publish.rs b/testsuite/fuzzer/fuzz/fuzz_targets/move/aptosvm_publish.rs index ca532a4f11258..8eef77817a664 100644 --- a/testsuite/fuzzer/fuzz/fuzz_targets/move/aptosvm_publish.rs +++ b/testsuite/fuzzer/fuzz/fuzz_targets/move/aptosvm_publish.rs @@ -18,7 +18,7 @@ use std::{ collections::{BTreeMap, HashSet}, sync::Arc, }; -use utils::{publish_group, sort_by_deps, ExecVariant, RunnableState}; +use utils::vm::{publish_group, sort_by_deps, ExecVariant, RunnableState}; // genesis write set generated once for each fuzzing session static VM: Lazy = Lazy::new(|| GENESIS_CHANGE_SET_HEAD.write_set().clone()); diff --git a/testsuite/fuzzer/fuzz/fuzz_targets/move/aptosvm_publish_and_run.rs b/testsuite/fuzzer/fuzz/fuzz_targets/move/aptosvm_publish_and_run.rs index 5f6a50e42f547..745498ecc81d8 100644 --- a/testsuite/fuzzer/fuzz/fuzz_targets/move/aptosvm_publish_and_run.rs +++ b/testsuite/fuzzer/fuzz/fuzz_targets/move/aptosvm_publish_and_run.rs @@ -31,7 +31,7 @@ use std::{ time::Instant, }; mod utils; -use utils::{ +use utils::vm::{ check_for_invariant_violation, publish_group, sort_by_deps, ExecVariant, FuzzerRunnableAuthenticator, RunnableState, }; @@ -51,7 +51,7 @@ static TP: Lazy> = Lazy::new(|| { const MAX_TYPE_PARAMETER_VALUE: u16 = 64 / 4 * 16; // third_party/move/move-bytecode-verifier/src/signature_v2.rs#L1306-L1312 -const EXECUTION_TIME_GAS_RATIO: u8 = 35; +const EXECUTION_TIME_GAS_RATIO: u8 = 50; fn check_for_invariant_violation_vmerror(e: VMError) { if e.status_type() == StatusType::InvariantViolation @@ -94,7 +94,7 @@ fn run_case(mut input: RunnableState) -> Result<(), Corpus> { filter_modules(&input)?; let verifier_config = VerifierConfig::production(); - let deserializer_config = DeserializerConfig::default(); + let deserializer_config = DeserializerConfig::new(8, 255); for m in input.dep_modules.iter_mut() { // m.metadata = vec![]; // we could optimize metadata to only contain aptos metadata diff --git a/testsuite/fuzzer/fuzz/fuzz_targets/move/bytecode_verifier_code_unit.rs b/testsuite/fuzzer/fuzz/fuzz_targets/move/bytecode_verifier_code_unit.rs index 8a674fadcb8b2..2a06bb0ef8be7 100644 --- a/testsuite/fuzzer/fuzz/fuzz_targets/move/bytecode_verifier_code_unit.rs +++ b/testsuite/fuzzer/fuzz/fuzz_targets/move/bytecode_verifier_code_unit.rs @@ -13,6 +13,7 @@ use move_binary_format::file_format::{ Visibility, }; use move_core_types::{account_address::AccountAddress, ident_str}; +use utils::helpers::compiled_module_serde; mod utils; fuzz_target!(|code_unit: CodeUnit| { @@ -80,7 +81,7 @@ fuzz_target!(|code_unit: CodeUnit| { }; module.function_defs.push(fun_def); - if utils::compiled_module_serde(&module).is_ok() { + if compiled_module_serde(&module).is_ok() { let _ = move_bytecode_verifier::verify_module(&module); } }); diff --git a/testsuite/fuzzer/fuzz/fuzz_targets/move/bytecode_verifier_mixed.rs b/testsuite/fuzzer/fuzz/fuzz_targets/move/bytecode_verifier_mixed.rs index 2026dc8a0d897..1cd96135e4586 100644 --- a/testsuite/fuzzer/fuzz/fuzz_targets/move/bytecode_verifier_mixed.rs +++ b/testsuite/fuzzer/fuzz/fuzz_targets/move/bytecode_verifier_mixed.rs @@ -14,6 +14,7 @@ use move_binary_format::file_format::{ Visibility, }; use move_core_types::{account_address::AccountAddress, ident_str}; +use utils::helpers::compiled_module_serde; mod utils; #[derive(Arbitrary, Debug)] @@ -94,7 +95,7 @@ fuzz_target!(|mix: Mixed| { }; module.function_defs.push(fun_def); - if utils::compiled_module_serde(&module).is_ok() { + if compiled_module_serde(&module).is_ok() { let _ = move_bytecode_verifier::verify_module(&module); } }); diff --git a/testsuite/fuzzer/fuzz/fuzz_targets/move/move_value_decorate.rs b/testsuite/fuzzer/fuzz/fuzz_targets/move/move_value_decorate.rs index b91192b28cf3d..3638e39bb6838 100644 --- a/testsuite/fuzzer/fuzz/fuzz_targets/move/move_value_decorate.rs +++ b/testsuite/fuzzer/fuzz/fuzz_targets/move/move_value_decorate.rs @@ -5,8 +5,8 @@ use arbitrary::Arbitrary; use libfuzzer_sys::fuzz_target; use move_core_types::value::{MoveTypeLayout, MoveValue}; - mod utils; +use utils::helpers::is_valid_layout; #[derive(Arbitrary, Debug)] struct FuzzData { @@ -15,7 +15,7 @@ struct FuzzData { } fuzz_target!(|fuzz_data: FuzzData| { - if !utils::is_valid_layout(&fuzz_data.layout) { + if !is_valid_layout(&fuzz_data.layout) { return; } diff --git a/testsuite/fuzzer/fuzz/fuzz_targets/move/move_value_deserialize.rs b/testsuite/fuzzer/fuzz/fuzz_targets/move/move_value_deserialize.rs index 3c130d708e3bd..450c53fb7f716 100644 --- a/testsuite/fuzzer/fuzz/fuzz_targets/move/move_value_deserialize.rs +++ b/testsuite/fuzzer/fuzz/fuzz_targets/move/move_value_deserialize.rs @@ -7,6 +7,7 @@ use libfuzzer_sys::fuzz_target; use move_core_types::value::{MoveTypeLayout, MoveValue}; mod utils; +use utils::helpers::is_valid_layout; #[derive(Arbitrary, Debug)] struct FuzzData { @@ -15,7 +16,7 @@ struct FuzzData { } fuzz_target!(|fuzz_data: FuzzData| { - if fuzz_data.data.is_empty() || !utils::is_valid_layout(&fuzz_data.layout) { + if fuzz_data.data.is_empty() || !is_valid_layout(&fuzz_data.layout) { return; } let _ = MoveValue::simple_deserialize(&fuzz_data.data, &fuzz_data.layout); diff --git a/testsuite/fuzzer/fuzz/fuzz_targets/move/utils/authenticator.rs b/testsuite/fuzzer/fuzz/fuzz_targets/move/utils/authenticator.rs new file mode 100644 index 0000000000000..1dc04685b9223 --- /dev/null +++ b/testsuite/fuzzer/fuzz/fuzz_targets/move/utils/authenticator.rs @@ -0,0 +1,226 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +#![allow(dead_code)] + +use super::helpers::UserAccount; +use aptos_types::keyless::{AnyKeylessPublicKey, EphemeralCertificate}; +use arbitrary::Arbitrary; +use serde::{Deserialize, Serialize}; +use serde_json; + +#[derive(Debug, Arbitrary, Eq, PartialEq, Clone, Serialize, Deserialize)] +pub struct JwtHeader { + pub alg: String, + pub typ: Option, + pub kid: Option, + // Add other JWT header fields as needed +} + +#[derive(Debug, Arbitrary, Eq, PartialEq, Clone, Serialize, Deserialize)] +pub struct FuzzingKeylessSignature { + exp_date_secs: u64, + jwt_header: JwtHeader, + cert: EphemeralCertificate, + //ephemeral_pubkey: EphemeralPublicKey, + //ephemeral_signature: EphemeralSignature, +} + +impl FuzzingKeylessSignature { + pub fn exp_date_secs(&self) -> u64 { + self.exp_date_secs + } + + pub fn jwt_header(&self) -> &JwtHeader { + &self.jwt_header + } + + pub fn cert(&self) -> &EphemeralCertificate { + &self.cert + } + + /* + pub fn ephemeral_pubkey(&self) -> &EphemeralPublicKey { + &self.ephemeral_pubkey + } + + pub fn ephemeral_signature(&self) -> &EphemeralSignature { + &self.ephemeral_signature + } + */ +} + +#[derive(Debug, Arbitrary, Eq, PartialEq, Clone)] +pub enum Style { + Break, + //MatchJWT, + //MatchKeys, +} + +//TODO: reorganize this type excluding not usefull fields. Do it after implementing JWK and Federated Keyless. +// Used to fuzz the transaction authenticator +#[derive(Debug, Arbitrary, Eq, PartialEq, Clone)] +pub enum FuzzerTransactionAuthenticator { + Ed25519 { + sender: UserAccount, + }, + Keyless { + sender: UserAccount, + style: Style, + any_keyless_public_key: AnyKeylessPublicKey, + keyless_signature: FuzzingKeylessSignature, + }, + MultiAgent { + sender: UserAccount, + secondary_signers: Vec, + }, + FeePayer { + sender: UserAccount, + secondary_signers: Vec, + fee_payer: UserAccount, + }, +} + +impl FuzzerTransactionAuthenticator { + pub fn sender(&self) -> UserAccount { + match self { + FuzzerTransactionAuthenticator::Ed25519 { sender } => *sender, + FuzzerTransactionAuthenticator::Keyless { + sender, + style: _, + any_keyless_public_key: _, + keyless_signature: _, + } => *sender, + FuzzerTransactionAuthenticator::MultiAgent { + sender, + secondary_signers: _, + } => *sender, + FuzzerTransactionAuthenticator::FeePayer { + sender, + secondary_signers: _, + fee_payer: _, + } => *sender, + } + } + + pub fn get_jwt_header_json(&self) -> Option { + if let FuzzerTransactionAuthenticator::Keyless { + keyless_signature, .. + } = self + { + serde_json::to_string(&keyless_signature.jwt_header).ok() + } else { + None + } + } +} + +#[derive(Debug, Arbitrary, Eq, PartialEq, Clone)] +pub struct TransactionState { + pub tx_auth_type: FuzzerTransactionAuthenticator, +} + +pub(crate) mod miscellaneous { + use aptos_crypto::{ed25519::ed25519_keys::Ed25519PrivateKey, PrivateKey, Uniform}; + use aptos_types::{ + jwks::rsa::INSECURE_TEST_RSA_KEY_PAIR, + keyless::{Configuration, OpenIdSig, Pepper}, + transaction::authenticator::EphemeralPublicKey, + }; + use once_cell::sync::Lazy; + use ring::signature::RsaKeyPair; + use serde::{Deserialize, Serialize}; + use std::collections::HashMap; + + pub(crate) const SAMPLE_UID_KEY: &str = "sub"; + + /// This is the SK from https://token.dev/. + /// To convert it into a JSON, you can use https://irrte.ch/jwt-js-decode/pem2jwk.html + pub(crate) static SAMPLE_JWK_SK: Lazy<&RsaKeyPair> = Lazy::new(|| &*INSECURE_TEST_RSA_KEY_PAIR); + + pub(crate) static SAMPLE_PEPPER: Lazy = Lazy::new(|| Pepper::from_number(76)); + + pub(crate) static SAMPLE_ESK: Lazy = + Lazy::new(Ed25519PrivateKey::generate_for_testing); + + pub(crate) static SAMPLE_EPK: Lazy = + Lazy::new(|| EphemeralPublicKey::ed25519(SAMPLE_ESK.public_key())); + + pub(crate) static SAMPLE_EPK_BLINDER: Lazy> = Lazy::new(|| { + let mut byte_vector = vec![0; 31]; + byte_vector[0] = 42; + byte_vector + }); + + /// The nonce-committed expiration date (not the JWT `exp`), 12/21/5490 + pub(crate) const SAMPLE_EXP_DATE: u64 = 111_111_111_111; + + /// Consistent with what is in `SAMPLE_JWT_PAYLOAD_JSON` + pub(crate) const SAMPLE_JWT_EXTRA_FIELD_KEY: &str = "family_name"; + + /// Consistent with what is in `SAMPLE_JWT_PAYLOAD_JSON` + pub(crate) static SAMPLE_JWT_EXTRA_FIELD: Lazy = + Lazy::new(|| format!(r#""{}":"Straka","#, SAMPLE_JWT_EXTRA_FIELD_KEY)); + + static SAMPLE_NONCE: Lazy = Lazy::new(|| { + let config = Configuration::new_for_testing(); + OpenIdSig::reconstruct_oauth_nonce( + SAMPLE_EPK_BLINDER.as_slice(), + SAMPLE_EXP_DATE, + &SAMPLE_EPK, + &config, + ) + .unwrap() + }); + + pub(crate) const SAMPLE_TEST_ISS_VALUE: &str = "test.oidc.provider"; + + #[derive(Serialize, Deserialize, Debug)] + pub struct SampleJwtPayload { + pub iss: String, + pub azp: String, + pub aud: String, + pub sub: String, + pub hd: String, + pub email: String, + pub email_verified: bool, + pub at_hash: String, + pub name: String, + pub picture: String, + pub given_name: String, + #[serde(flatten)] + pub extra_fields: HashMap, + pub locale: String, + pub iat: u64, + pub nonce: String, + pub exp: u64, + } + + impl Default for SampleJwtPayload { + fn default() -> Self { + // Parse the extra fields from the SAMPLE_JWT_EXTRA_FIELD string + let extra_fields_json = format!("{{{}}}", SAMPLE_JWT_EXTRA_FIELD.as_str()); + let extra_fields: HashMap = + serde_json::from_str(&extra_fields_json).unwrap_or_default(); + + SampleJwtPayload { + iss: SAMPLE_TEST_ISS_VALUE.to_string(), + azp: "407408718192.apps.googleusercontent.com".to_string(), + aud: "407408718192.apps.googleusercontent.com".to_string(), + sub: "113990307082899718775".to_string(), + hd: "aptoslabs.com".to_string(), + email: "michael@aptoslabs.com".to_string(), + email_verified: true, + at_hash: "bxIESuI59IoZb5alCASqBg".to_string(), + name: "Michael Straka".to_string(), + picture: "https://lh3.googleusercontent.com/a/ACg8ocJvY4kVUBRtLxe1IqKWL5i7tBDJzFp9YuWVXMzwPpbs=s96-c".to_string(), + given_name: "Michael".to_string(), + extra_fields, + locale: "en".to_string(), + iat: 1700255944, + nonce: SAMPLE_NONCE.as_str().to_string(), + exp: 2700259544, + } + } + } +} diff --git a/testsuite/fuzzer/fuzz/fuzz_targets/move/utils/helpers.rs b/testsuite/fuzzer/fuzz/fuzz_targets/move/utils/helpers.rs new file mode 100644 index 0000000000000..15960f5f920aa --- /dev/null +++ b/testsuite/fuzzer/fuzz/fuzz_targets/move/utils/helpers.rs @@ -0,0 +1,101 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +#![allow(dead_code)] + +use aptos_language_e2e_tests::{account::Account, executor::FakeExecutor}; +use arbitrary::Arbitrary; +use move_binary_format::file_format::CompiledModule; +use move_core_types::value::{MoveStructLayout, MoveTypeLayout}; + +#[macro_export] +macro_rules! tdbg { + () => { + () + }; + ($val:expr $(,)?) => { + { + if std::env::var("DEBUG").is_ok() { + dbg!($val) + } else { + $val + } + } + }; + ($($val:expr),+ $(,)?) => { + { + if std::env::var("DEBUG").is_ok() { + dbg!($($val),+) + } else { + ($($val),+) + } + } + }; +} + +#[derive(Debug, Arbitrary, Eq, PartialEq, Clone, Copy)] +pub enum FundAmount { + Zero, + Poor, + Rich, +} + +#[derive(Debug, Arbitrary, Eq, PartialEq, Clone, Copy)] +pub struct UserAccount { + is_inited_and_funded: bool, + fund: FundAmount, +} + +impl UserAccount { + pub fn fund_amount(&self) -> u64 { + match self.fund { + FundAmount::Zero => 0, + FundAmount::Poor => 1_000, + FundAmount::Rich => 1_000_000_000_000_000, + } + } + + pub fn convert_account(&self, vm: &mut FakeExecutor) -> Account { + if self.is_inited_and_funded { + vm.create_accounts(1, self.fund_amount(), 0).remove(0) + } else { + Account::new() + } + } +} + +pub(crate) fn is_valid_layout(layout: &MoveTypeLayout) -> bool { + use MoveTypeLayout as L; + + match layout { + L::Bool | L::U8 | L::U16 | L::U32 | L::U64 | L::U128 | L::U256 | L::Address | L::Signer => { + true + }, + + L::Vector(layout) | L::Native(_, layout) => is_valid_layout(layout), + L::Struct(MoveStructLayout::RuntimeVariants(variants)) => { + variants.iter().all(|v| v.iter().all(is_valid_layout)) + }, + L::Struct(MoveStructLayout::Runtime(fields)) => { + if fields.is_empty() { + return false; + } + fields.iter().all(is_valid_layout) + }, + L::Struct(_) => { + // decorated layouts not supported + false + }, + } +} + +pub(crate) fn compiled_module_serde(module: &CompiledModule) -> Result<(), ()> { + let mut blob = vec![]; + module.serialize(&mut blob).map_err(|_| ())?; + CompiledModule::deserialize(&blob).map_err(|_| ())?; + Ok(()) +} + +pub(crate) fn base64url_encode_str(data: &str) -> String { + base64::encode_config(data.as_bytes(), base64::URL_SAFE_NO_PAD) +} diff --git a/testsuite/fuzzer/fuzz/fuzz_targets/move/utils/mod.rs b/testsuite/fuzzer/fuzz/fuzz_targets/move/utils/mod.rs new file mode 100644 index 0000000000000..9183877fc57b0 --- /dev/null +++ b/testsuite/fuzzer/fuzz/fuzz_targets/move/utils/mod.rs @@ -0,0 +1,6 @@ +// Copyright (c) Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +pub mod authenticator; +pub mod helpers; +pub mod vm; diff --git a/testsuite/fuzzer/fuzz/fuzz_targets/move/utils.rs b/testsuite/fuzzer/fuzz/fuzz_targets/move/utils/vm.rs similarity index 54% rename from testsuite/fuzzer/fuzz/fuzz_targets/move/utils.rs rename to testsuite/fuzzer/fuzz/fuzz_targets/move/utils/vm.rs index 9a95cdd257361..b87e657d13484 100644 --- a/testsuite/fuzzer/fuzz/fuzz_targets/move/utils.rs +++ b/testsuite/fuzzer/fuzz/fuzz_targets/move/utils/vm.rs @@ -3,15 +3,14 @@ #![allow(dead_code)] +use super::helpers::UserAccount; +use crate::tdbg; use aptos_cached_packages::aptos_stdlib::code_publish_package_txn; use aptos_framework::natives::code::{ ModuleMetadata, MoveOption, PackageDep, PackageMetadata, UpgradePolicy, }; use aptos_language_e2e_tests::{account::Account, executor::FakeExecutor}; -use aptos_types::{ - keyless::{AnyKeylessPublicKey, EphemeralCertificate}, - transaction::{ExecutionStatus, TransactionPayload, TransactionStatus}, -}; +use aptos_types::transaction::{ExecutionStatus, TransactionPayload, TransactionStatus}; use arbitrary::Arbitrary; use libfuzzer_sys::Corpus; use move_binary_format::{ @@ -20,68 +19,11 @@ use move_binary_format::{ }; use move_core_types::{ language_storage::{ModuleId, TypeTag}, - value::{MoveStructLayout, MoveTypeLayout, MoveValue}, + value::MoveValue, vm_status::{StatusType, VMStatus}, }; -use serde::{Deserialize, Serialize}; use std::collections::{BTreeMap, BTreeSet, HashSet}; -#[macro_export] -macro_rules! tdbg { - () => { - () - }; - ($val:expr $(,)?) => { - { - if std::env::var("DEBUG").is_ok() { - dbg!($val) - } else { - $val - } - } - }; - ($($val:expr),+ $(,)?) => { - { - if std::env::var("DEBUG").is_ok() { - dbg!($($val),+) - } else { - ($($val),+) - } - } - }; -} - -#[derive(Debug, Arbitrary, Eq, PartialEq, Clone, Copy)] -pub enum FundAmount { - Zero, - Poor, - Rich, -} - -#[derive(Debug, Arbitrary, Eq, PartialEq, Clone, Copy)] -pub struct UserAccount { - is_inited_and_funded: bool, - fund: FundAmount, -} - -impl UserAccount { - pub fn fund_amount(&self) -> u64 { - match self.fund { - FundAmount::Zero => 0, - FundAmount::Poor => 1_000, - FundAmount::Rich => 1_000_000_000_000_000, - } - } - - pub fn convert_account(&self, vm: &mut FakeExecutor) -> Account { - if self.is_inited_and_funded { - vm.create_accounts(1, self.fund_amount(), 0).remove(0) - } else { - Account::new() - } - } -} - // Used to fuzz the MoveVM #[derive(Debug, Arbitrary, Eq, PartialEq, Clone)] pub enum FuzzerRunnableAuthenticator { @@ -138,117 +80,6 @@ pub struct RunnableState { pub tx_auth_type: FuzzerRunnableAuthenticator, } -#[derive(Debug, Arbitrary, Eq, PartialEq, Clone, Serialize, Deserialize)] -pub struct JwtHeader { - pub alg: String, - pub typ: Option, - pub kid: Option, - // Add other JWT header fields as needed -} - -#[derive(Debug, Arbitrary, Eq, PartialEq, Clone, Serialize, Deserialize)] -pub struct FuzzingKeylessSignature { - exp_date_secs: u64, - jwt_header: JwtHeader, - cert: EphemeralCertificate, - //ephemeral_pubkey: EphemeralPublicKey, - //ephemeral_signature: EphemeralSignature, -} - -impl FuzzingKeylessSignature { - pub fn exp_date_secs(&self) -> u64 { - self.exp_date_secs - } - - pub fn jwt_header(&self) -> &JwtHeader { - &self.jwt_header - } - - pub fn cert(&self) -> &EphemeralCertificate { - &self.cert - } - - /* - pub fn ephemeral_pubkey(&self) -> &EphemeralPublicKey { - &self.ephemeral_pubkey - } - - pub fn ephemeral_signature(&self) -> &EphemeralSignature { - &self.ephemeral_signature - } - */ -} - -#[derive(Debug, Arbitrary, Eq, PartialEq, Clone)] -pub enum Style { - Break, - //MatchJWT, - //MatchKeys, -} - -//TODO: reorganize this type excluding not usefull fields. Do it after implementing JWK and Federated Keyless. -// Used to fuzz the transaction authenticator -#[derive(Debug, Arbitrary, Eq, PartialEq, Clone)] -pub enum FuzzerTransactionAuthenticator { - Ed25519 { - sender: UserAccount, - }, - Keyless { - sender: UserAccount, - style: Style, - any_keyless_public_key: AnyKeylessPublicKey, - keyless_signature: FuzzingKeylessSignature, - }, - MultiAgent { - sender: UserAccount, - secondary_signers: Vec, - }, - FeePayer { - sender: UserAccount, - secondary_signers: Vec, - fee_payer: UserAccount, - }, -} - -impl FuzzerTransactionAuthenticator { - pub fn sender(&self) -> UserAccount { - match self { - FuzzerTransactionAuthenticator::Ed25519 { sender } => *sender, - FuzzerTransactionAuthenticator::Keyless { - sender, - style: _, - any_keyless_public_key: _, - keyless_signature: _, - } => *sender, - FuzzerTransactionAuthenticator::MultiAgent { - sender, - secondary_signers: _, - } => *sender, - FuzzerTransactionAuthenticator::FeePayer { - sender, - secondary_signers: _, - fee_payer: _, - } => *sender, - } - } - - pub fn get_jwt_header_json(&self) -> Option { - if let FuzzerTransactionAuthenticator::Keyless { - keyless_signature, .. - } = self - { - serde_json::to_string(&keyless_signature.jwt_header).ok() - } else { - None - } - } -} - -#[derive(Debug, Arbitrary, Eq, PartialEq, Clone)] -pub struct TransactionState { - pub tx_auth_type: FuzzerTransactionAuthenticator, -} - // used for ordering modules topologically pub(crate) fn sort_by_deps( map: &BTreeMap, @@ -381,35 +212,3 @@ pub(crate) fn publish_group( _ => Err(Corpus::Keep), } } - -pub(crate) fn is_valid_layout(layout: &MoveTypeLayout) -> bool { - use MoveTypeLayout as L; - - match layout { - L::Bool | L::U8 | L::U16 | L::U32 | L::U64 | L::U128 | L::U256 | L::Address | L::Signer => { - true - }, - - L::Vector(layout) | L::Native(_, layout) => is_valid_layout(layout), - L::Struct(MoveStructLayout::RuntimeVariants(variants)) => { - variants.iter().all(|v| v.iter().all(is_valid_layout)) - }, - L::Struct(MoveStructLayout::Runtime(fields)) => { - if fields.is_empty() { - return false; - } - fields.iter().all(is_valid_layout) - }, - L::Struct(_) => { - // decorated layouts not supported - false - }, - } -} - -pub(crate) fn compiled_module_serde(module: &CompiledModule) -> Result<(), ()> { - let mut blob = vec![]; - module.serialize(&mut blob).map_err(|_| ())?; - CompiledModule::deserialize(&blob).map_err(|_| ())?; - Ok(()) -} diff --git a/testsuite/fuzzer/fuzz/fuzz_targets/move/value_deserialize.rs b/testsuite/fuzzer/fuzz/fuzz_targets/move/value_deserialize.rs index adf71d8435fe3..3cca926099b3b 100644 --- a/testsuite/fuzzer/fuzz/fuzz_targets/move/value_deserialize.rs +++ b/testsuite/fuzzer/fuzz/fuzz_targets/move/value_deserialize.rs @@ -6,8 +6,8 @@ use arbitrary::Arbitrary; use libfuzzer_sys::fuzz_target; use move_core_types::value::MoveTypeLayout; use move_vm_types::values::Value; - mod utils; +use utils::helpers::is_valid_layout; #[derive(Arbitrary, Debug)] struct FuzzData { @@ -16,7 +16,7 @@ struct FuzzData { } fuzz_target!(|fuzz_data: FuzzData| { - if fuzz_data.data.is_empty() || !utils::is_valid_layout(&fuzz_data.layout) { + if fuzz_data.data.is_empty() || !is_valid_layout(&fuzz_data.layout) { return; } let _ = Value::simple_deserialize(&fuzz_data.data, &fuzz_data.layout); diff --git a/testsuite/fuzzer/src/main.rs b/testsuite/fuzzer/src/main.rs index 57733e1cbdb62..a5b9fbb0611cd 100644 --- a/testsuite/fuzzer/src/main.rs +++ b/testsuite/fuzzer/src/main.rs @@ -1,6 +1,70 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 +mod utils; +use clap::{Arg, Command}; + fn main() { - println!("Hello, world!"); + let matches = Command::new("Fuzz CLI") + .version("0.1") + .author("Security Team @ Aptos Labs") + .about("This CLI is used to help craft and maintain fuzz targets for the Core components of the Aptos Blockchain.") + .subcommand( + Command::new("compile_federated_jwk") + .about("Compiles a module from source and dumps serialized metadata and code to be used as static initializers in fuzz targets.") + .arg( + Arg::new("module_path") + .help("Path to the module source") + .required(true) + .index(1), + ) + ) + .subcommand( + Command::new("generate_runnable_state") + .about("Generates a runnable state from a Move module and its metadata.") + .arg( + Arg::new("csv_path") + .help("Path to a csv containing b64 encode modules in third coulmn") + .required(true) + .index(1), + ) + .arg( + Arg::new("destination_path") + .help("Path to write the runnable state to") + .required(true) + .index(2), + ) + ) + // Add more subcommands or arguments here + .get_matches(); + + match matches.subcommand() { + Some(("compile_federated_jwk", sub_m)) => { + let module_path = sub_m.get_one::("module_path").unwrap(); + + // Call the function with the provided arguments + if let Err(e) = utils::cli::compile_federated_jwk(module_path) { + eprintln!("Error compiling module: {}", e); + std::process::exit(1); + } else { + println!("Module compiled successfully."); + } + }, + Some(("generate_runnable_state", sub_m)) => { + let csv_path = sub_m.get_one::("csv_path").unwrap(); + let destination_path = sub_m.get_one::("destination_path").unwrap(); + + // Call the function with the provided arguments + if let Err(e) = utils::cli::generate_runnable_state(csv_path, destination_path) { + eprintln!("Error generating runnable state: {}", e); + std::process::exit(1); + } else { + println!("Runnable state generated successfully."); + } + }, + // Handle other subcommands or default behavior + _ => { + println!("No valid subcommand was used. Use --help for more information."); + }, + } } diff --git a/testsuite/fuzzer/src/utils.rs b/testsuite/fuzzer/src/utils.rs new file mode 100644 index 0000000000000..cefc8366450ec --- /dev/null +++ b/testsuite/fuzzer/src/utils.rs @@ -0,0 +1,274 @@ +// Copyright (c) Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +#[allow(dead_code)] +#[allow(unused_variables)] +pub(crate) mod cli { + use aptos_framework::{BuildOptions, BuiltPackage}; + use aptos_types::{ + account_address::AccountAddress, + transaction::{EntryFunction, Script, TransactionPayload}, + }; + use arbitrary::Arbitrary; + use base64::{engine::general_purpose::STANDARD, Engine as _}; + use dearbitrary::Dearbitrary; + use move_binary_format::file_format::{ + CompiledModule, CompiledScript, FunctionDefinitionIndex, + }; + use move_core_types::{ + ident_str, + identifier::Identifier, + language_storage::{ModuleId, TypeTag}, + value::MoveValue, + }; + use sha2::{Digest, Sha256}; + use std::{collections::HashMap, fs::File, io::Write, path::PathBuf}; + + /// Compiles a Move module from source code. + /// The compiled module and its metadata are returned serialized. + /// Those can be used to publish the module on-chain via code_publish_package_txn(). + pub(crate) fn compile_federated_jwk(module_path: &str) -> Result<(), String> { + let package = BuiltPackage::build(PathBuf::from(module_path), BuildOptions::default()) + .map_err(|e| e.to_string())?; + + let transaction_payload = generate_script_payload_jwk(&package); + let code_snippet = format!( + r#" + let tx = acc + .transaction() + .gas_unit_price(100) + .sequence_number(sequence_number) + .payload(bcs::from_bytes(&{:?}).unwrap()) + .sign(); + "#, + bcs::to_bytes(&transaction_payload).unwrap() + ); + println!("{}", code_snippet); + + Ok(()) + } + + /// Generate a TransactionPayload for modules + /// + /// ### Arguments + /// + /// * `package` - Built Move package + fn generate_module_payload(package: &BuiltPackage) -> TransactionPayload { + // extract package data + let code = package.extract_code(); + let metadata = package + .extract_metadata() + .expect("extracting package metadata must succeed"); + + // publish package similar to create_publish_package in harness.rs + code_publish_package_txn( + bcs::to_bytes(&metadata).expect("PackageMetadata has BCS"), + code, + ) + } + + /// Generate a TransactionPayload for scripts + /// + /// ### Arguments + /// + /// * `package` - Built Move package + fn generate_script_payload_jwk(package: &BuiltPackage) -> TransactionPayload { + // extract package data + let code = package.extract_script_code().into_iter().next().unwrap(); + let ty_args = vec![]; + let args = vec![]; + + TransactionPayload::Script(Script::new(code, ty_args, args)) + } + + /// Same as `publish_package` but as an entry function which can be called as a transaction. Because + /// of current restrictions for txn parameters, the metadata needs to be passed in serialized form. + pub fn code_publish_package_txn( + metadata_serialized: Vec, + code: Vec>, + ) -> TransactionPayload { + TransactionPayload::EntryFunction(EntryFunction::new( + ModuleId::new( + AccountAddress::new([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, + ]), + ident_str!("code").to_owned(), + ), + ident_str!("publish_package_txn").to_owned(), + vec![], + vec![ + bcs::to_bytes(&metadata_serialized).unwrap(), + bcs::to_bytes(&code).unwrap(), + ], + )) + } + + /// Data types for generate VM fuzzer corpora + #[derive(Debug, Eq, PartialEq, arbitrary::Arbitrary, dearbitrary::Dearbitrary)] + pub enum ExecVariant { + Script { + script: CompiledScript, + type_args: Vec, + args: Vec, + }, + CallFunction { + module: ModuleId, + function: FunctionDefinitionIndex, + type_args: Vec, + args: Vec>, + }, + } + + #[derive(Debug, Arbitrary, Dearbitrary, Eq, PartialEq, Clone)] + pub enum FundAmount { + Zero, + Poor, + Rich, + } + + #[derive(Debug, Arbitrary, Dearbitrary, Eq, PartialEq, Clone)] + pub struct UserAccount { + pub is_inited_and_funded: bool, + pub fund: FundAmount, + } + + #[derive(Debug, Arbitrary, Dearbitrary, Eq, PartialEq, Clone)] + pub enum Authenticator { + Ed25519 { + sender: UserAccount, + }, + MultiAgent { + sender: UserAccount, + secondary_signers: Vec, + }, + FeePayer { + sender: UserAccount, + secondary_signers: Vec, + fee_payer: UserAccount, + }, + } + #[derive(Debug, Eq, arbitrary::Arbitrary, dearbitrary::Dearbitrary, PartialEq)] + pub struct RunnableState { + pub dep_modules: Vec, + pub exec_variant: ExecVariant, + pub tx_auth_type: Authenticator, + } + + /// Convert module to RunnableState data structure + /// This is used to run the module in the VM + pub(crate) fn generate_runnable_state( + csv_path: &str, + destination_path: &str, + ) -> Result<(), String> { + std::fs::create_dir_all(destination_path).map_err(|e| e.to_string())?; + let runnable_states = to_runnablestate(&read_csv(csv_path)); + let mut cnt: usize = 0; + println!("Number of runnable states: {} \n", runnable_states.len()); + for runnable_state in runnable_states { + let d = runnable_state.0.dearbitrary_first(); + let bytes = d.finish(); + + let u = arbitrary::Unstructured::new(&bytes); + let runnable_state_generated = + RunnableState::arbitrary_take_rest(u).map_err(|e| e.to_string())?; + if runnable_state.0 != runnable_state_generated { + println!( + "Failed : {:#?}", + runnable_state.0.dep_modules[0] + ); + println!("Failed : {:#?} \n", runnable_state.1); + cnt += 1; + } + let mut hasher = Sha256::new(); + hasher.update(&bytes); + let hash = hasher.finalize(); + let filename = format!("{}/{}.bytes", destination_path, hex::encode(hash)); + let mut file = File::create(&filename).map_err(|e| e.to_string())?; + file.write_all(&bytes).map_err(|e| e.to_string())?; + } + println!("Number of different states: {}", cnt); + + Ok(()) + } + + // function that read a CSV files and get the third element of each row and return a vector of bytes + fn read_csv(path: &str) -> HashMap { + let mut reader = csv::Reader::from_path(path).unwrap(); + + let mut v = HashMap::new(); + + for result in reader.records() { + let record = result.unwrap(); + + let module_name = record.get(0).unwrap(); + let address = record.get(1).unwrap(); + let bytecode = match STANDARD.decode(record.get(2).unwrap()) { + Ok(bytecode) => bytecode, + Err(err) => panic!( + "Error decoding {:?} B64 Decoding error: {:?}, Base64 string: {:?}", + address, + err, + record.get(2).unwrap() + ), + }; + /* + let bytecode: Vec = match hex::decode(decoded_bytecode.clone()) { + Ok(bytecode) => bytecode, + Err(err) => panic!("Error decoding {:?}, Decoded Error: {:?}, bytecode: {:?}", address, err, decoded_bytecode), + }; + */ + let serialized = record.get(2).unwrap(); + + let account_address = match AccountAddress::from_hex_literal(address) { + Ok(addr) => addr, + Err(err) => { + eprintln!("Invalid address {}: {:?}", address, err); + continue; + }, + }; + let identifier = match Identifier::new(module_name) { + Ok(id) => id, + Err(err) => { + eprintln!("Invalid module name {}: {:?}", module_name, err); + continue; + }, + }; + let key = ModuleId::new(account_address, identifier); + let compiled_module = match CompiledModule::deserialize(&bytecode) { + Ok(module) => module, + Err(err) => { + eprintln!("Error deserializing module: {:?}", err); + continue; // Skip to the next iteration of the loop + }, + }; + v.insert(key, (compiled_module, serialized.to_string())); + } + v + } + + fn to_runnablestate( + map: &HashMap, + ) -> Vec<(RunnableState, String)> { + map.iter() + .map(|(module_id, tuple)| { + let runnable_state = RunnableState { + dep_modules: vec![tuple.0.to_owned()], + exec_variant: ExecVariant::CallFunction { + module: module_id.to_owned(), + function: FunctionDefinitionIndex::new(0), + type_args: vec![], + args: vec![], + }, + tx_auth_type: Authenticator::Ed25519 { + sender: UserAccount { + is_inited_and_funded: true, + fund: FundAmount::Rich, + }, + }, + }; + (runnable_state, tuple.1.to_owned()) + }) + .collect() + } +} diff --git a/third_party/move/move-binary-format/Cargo.toml b/third_party/move/move-binary-format/Cargo.toml index eac71298e6626..18024c2d91669 100644 --- a/third_party/move/move-binary-format/Cargo.toml +++ b/third_party/move/move-binary-format/Cargo.toml @@ -13,6 +13,7 @@ edition = "2021" anyhow = { workspace = true } arbitrary = { workspace = true, optional = true, features = ["derive"] } backtrace = { workspace = true } +dearbitrary = { workspace = true, optional = true, features = ["derive"] } indexmap = { workspace = true } move-bytecode-spec = { workspace = true } move-core-types = { path = "../move-core/types" } @@ -30,5 +31,5 @@ serde_json = { workspace = true } [features] default = [] -fuzzing = ["proptest", "proptest-derive", "arbitrary", "move-core-types/fuzzing"] +fuzzing = ["proptest", "proptest-derive", "arbitrary", "dearbitrary", "move-core-types/fuzzing"] testing = [] diff --git a/third_party/move/move-binary-format/src/file_format.rs b/third_party/move/move-binary-format/src/file_format.rs index 538a588439c54..3037cec1eaea5 100644 --- a/third_party/move/move-binary-format/src/file_format.rs +++ b/third_party/move/move-binary-format/src/file_format.rs @@ -66,7 +66,7 @@ macro_rules! define_index { #[derive(Clone, Copy, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] #[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] - #[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] + #[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary))] #[doc=$comment] pub struct $name(pub TableIndex); @@ -247,7 +247,10 @@ pub const NO_TYPE_ARGUMENTS: SignatureIndex = SignatureIndex(0); #[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] #[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct ModuleHandle { /// Index into the `AddressIdentifierIndex`. Identifies module-holding account's address. pub address: AddressIdentifierIndex, @@ -271,7 +274,10 @@ pub struct ModuleHandle { #[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] #[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct StructHandle { /// The module that defines the type. pub module: ModuleHandleIndex, @@ -295,7 +301,10 @@ impl StructHandle { #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct StructTypeParameter { /// The type parameter constraints. pub constraints: AbilitySet, @@ -313,7 +322,10 @@ pub struct StructTypeParameter { #[derive(Clone, Debug, Eq, Hash, PartialEq)] #[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(params = "usize"))] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct FunctionHandle { /// The module that defines the function. pub module: ModuleHandleIndex, @@ -340,7 +352,10 @@ pub struct FunctionHandle { #[derive(Clone, Debug, Eq, Hash, PartialEq)] #[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct FieldHandle { pub owner: StructDefinitionIndex, pub field: MemberCount, @@ -350,7 +365,10 @@ pub struct FieldHandle { #[derive(Clone, Debug, Eq, Hash, PartialEq)] #[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct VariantFieldHandle { /// The structure which defines the variant. pub struct_index: StructDefinitionIndex, @@ -365,7 +383,10 @@ pub struct VariantFieldHandle { #[derive(Clone, Debug, Eq, Hash, PartialEq)] #[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct StructVariantHandle { pub struct_index: StructDefinitionIndex, pub variant: VariantIndex, @@ -378,7 +399,10 @@ pub struct StructVariantHandle { #[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub enum StructFieldInformation { Native, Declared(Vec), @@ -452,7 +476,10 @@ impl StructFieldInformation { #[derive(Clone, Debug, Eq, Hash, PartialEq)] #[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct StructDefInstantiation { pub def: StructDefinitionIndex, pub type_parameters: SignatureIndex, @@ -462,7 +489,10 @@ pub struct StructDefInstantiation { #[derive(Clone, Debug, Eq, Hash, PartialEq)] #[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct StructVariantInstantiation { pub handle: StructVariantHandleIndex, pub type_parameters: SignatureIndex, @@ -472,7 +502,10 @@ pub struct StructVariantInstantiation { #[derive(Clone, Debug, Eq, Hash, PartialEq)] #[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct FunctionInstantiation { pub handle: FunctionHandleIndex, pub type_parameters: SignatureIndex, @@ -487,7 +520,10 @@ pub struct FunctionInstantiation { #[derive(Clone, Debug, Eq, Hash, PartialEq)] #[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct FieldInstantiation { pub handle: FieldHandleIndex, pub type_parameters: SignatureIndex, @@ -497,7 +533,10 @@ pub struct FieldInstantiation { #[derive(Clone, Debug, Eq, Hash, PartialEq)] #[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct VariantFieldInstantiation { pub handle: VariantFieldHandleIndex, pub type_parameters: SignatureIndex, @@ -508,7 +547,10 @@ pub struct VariantFieldInstantiation { #[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct StructDefinition { /// The `StructHandle` for this `StructDefinition`. This has the name and the abilities /// for the type. @@ -523,7 +565,10 @@ pub struct StructDefinition { #[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct FieldDefinition { /// The name of the field. pub name: IdentifierIndex, @@ -534,7 +579,10 @@ pub struct FieldDefinition { #[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct VariantDefinition { pub name: IdentifierIndex, pub fields: Vec, @@ -545,7 +593,10 @@ pub struct VariantDefinition { #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] #[repr(u8)] pub enum Visibility { /// Accessible within its defining module only. @@ -589,7 +640,10 @@ impl std::convert::TryFrom for Visibility { #[derive(Clone, Debug, Default, Eq, PartialEq)] #[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(params = "usize"))] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct FunctionDefinition { /// The prototype of the function (module, name, signature). pub function: FunctionHandleIndex, @@ -640,7 +694,10 @@ impl FunctionDefinition { #[derive(Clone, Debug, Eq, Hash, PartialEq)] #[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct TypeSignature(pub SignatureToken); // TODO: remove at some point or move it in the front end (language/move-ir-compiler) @@ -674,7 +731,10 @@ pub struct FunctionSignature { #[derive(Clone, Debug, Default, Eq, Hash, PartialEq, Ord, PartialOrd)] #[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(params = "usize"))] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct Signature( #[cfg_attr( any(test, feature = "fuzzing"), @@ -774,7 +834,10 @@ impl fmt::Display for Ability { /// A set of `Ability`s #[derive(Clone, Eq, Copy, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize)] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct AbilitySet(u8); impl AbilitySet { @@ -1039,7 +1102,10 @@ impl Arbitrary for AbilitySet { /// ``` #[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd, Debug)] #[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] -#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] +#[cfg_attr( + any(test, feature = "fuzzing"), + derive(proptest_derive::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct AccessSpecifier { /// The kind of access: read, write, or both. pub kind: AccessKind, @@ -1065,7 +1131,10 @@ impl AccessSpecifier { /// The kind of specified access. #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd, Debug)] #[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] -#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] +#[cfg_attr( + any(test, feature = "fuzzing"), + derive(proptest_derive::Arbitrary, dearbitrary::Dearbitrary) +)] pub enum AccessKind { Reads, Writes, @@ -1108,7 +1177,10 @@ impl fmt::Display for AccessKind { /// The specification of a resource in an access specifier. #[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd, Debug)] #[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] -#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] +#[cfg_attr( + any(test, feature = "fuzzing"), + derive(proptest_derive::Arbitrary, dearbitrary::Dearbitrary) +)] pub enum ResourceSpecifier { /// Any resource Any, @@ -1125,7 +1197,10 @@ pub enum ResourceSpecifier { /// The specification of an address in an access specifier. #[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd, Debug)] #[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] -#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] +#[cfg_attr( + any(test, feature = "fuzzing"), + derive(proptest_derive::Arbitrary, dearbitrary::Dearbitrary) +)] pub enum AddressSpecifier { /// Resource can be stored at any address. Any, @@ -1152,7 +1227,10 @@ pub enum AddressSpecifier { /// A SignatureToken can express more types than the VM can handle safely, and correctness is /// enforced by the verifier. #[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub enum SignatureToken { /// Boolean, `true` or `false`. Bool, @@ -1433,7 +1511,10 @@ impl SignatureToken { /// A `Constant` is a serialized value along with its type. That type will be deserialized by the /// loader/evaluator #[derive(Clone, Debug, Eq, PartialEq, Hash)] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct Constant { pub type_: SignatureToken, pub data: Vec, @@ -1443,7 +1524,10 @@ pub struct Constant { #[derive(Clone, Debug, Default, Eq, PartialEq)] #[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(params = "usize"))] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct CodeUnit { /// List of locals type. All locals are typed. pub locals: SignatureIndex, @@ -1476,7 +1560,10 @@ pub struct CodeUnit { #[derive(Clone, Hash, Eq, VariantCount, PartialEq)] #[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub enum Bytecode { #[group = "stack_and_local"] #[description = "Pop and discard the value at the top of the stack. The value on the stack must be an copyable type."] @@ -3077,7 +3164,10 @@ impl Bytecode { /// A CompiledScript defines the constant pools (string, address, signatures, etc.), the handle /// tables (external code references) and it has a `main` definition. #[derive(Clone, Default, Eq, PartialEq, Debug)] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct CompiledScript { /// Version number found during deserialization pub version: u32, @@ -3128,7 +3218,10 @@ impl CompiledScript { /// /// A module is published as a single entry and it is retrieved as a single blob. #[derive(Clone, Debug, Default, Eq, PartialEq)] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct CompiledModule { /// Version number found during deserialization pub version: u32, diff --git a/third_party/move/move-core/types/Cargo.toml b/third_party/move/move-core/types/Cargo.toml index 591721a90796a..c76b390c88786 100644 --- a/third_party/move/move-core/types/Cargo.toml +++ b/third_party/move/move-core/types/Cargo.toml @@ -14,6 +14,7 @@ anyhow = { workspace = true } arbitrary = { workspace = true, features = ["derive_arbitrary"], optional = true } bcs = { workspace = true } bytes = { workspace = true } +dearbitrary = { workspace = true, optional = true, features = ["derive"] } ethnum = { workspace = true } hashbrown = { workspace = true } hex = { workspace = true } @@ -40,4 +41,4 @@ serde_json = { workspace = true } [features] default = [] -fuzzing = ["proptest", "proptest-derive", "arbitrary"] +fuzzing = ["proptest", "proptest-derive", "arbitrary", "dearbitrary"] diff --git a/third_party/move/move-core/types/src/account_address.rs b/third_party/move/move-core/types/src/account_address.rs index 3858f80162f19..83737b2d029f5 100644 --- a/third_party/move/move-core/types/src/account_address.rs +++ b/third_party/move/move-core/types/src/account_address.rs @@ -11,7 +11,10 @@ use std::{convert::TryFrom, fmt, str::FromStr}; /// A struct that represents an account address. #[derive(Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)] #[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] -#[cfg_attr(any(test, feature = "fuzzing"), derive(arbitrary::Arbitrary))] +#[cfg_attr( + any(test, feature = "fuzzing"), + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct AccountAddress([u8; AccountAddress::LENGTH]); impl AccountAddress { diff --git a/third_party/move/move-core/types/src/identifier.rs b/third_party/move/move-core/types/src/identifier.rs index 786729b9dde94..3fdf0ed944a2e 100644 --- a/third_party/move/move-core/types/src/identifier.rs +++ b/third_party/move/move-core/types/src/identifier.rs @@ -105,7 +105,10 @@ pub(crate) static ALLOWED_NO_SELF_IDENTIFIERS: &str = /// /// For more details, see the module level documentation. #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize)] -#[cfg_attr(any(test, feature = "fuzzing"), derive(arbitrary::Arbitrary))] +#[cfg_attr( + any(test, feature = "fuzzing"), + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct Identifier(Box); // An identifier cannot be mutated so use Box instead of String -- it is 1 word smaller. diff --git a/third_party/move/move-core/types/src/language_storage.rs b/third_party/move/move-core/types/src/language_storage.rs index 398caa38ab9ee..3a6daaaddee7a 100644 --- a/third_party/move/move-core/types/src/language_storage.rs +++ b/third_party/move/move-core/types/src/language_storage.rs @@ -23,7 +23,10 @@ pub const RESOURCE_TAG: u8 = 1; pub const CORE_CODE_ADDRESS: AccountAddress = AccountAddress::ONE; #[derive(Serialize, Deserialize, Debug, PartialEq, Hash, Eq, Clone, PartialOrd, Ord)] -#[cfg_attr(any(test, feature = "fuzzing"), derive(arbitrary::Arbitrary))] +#[cfg_attr( + any(test, feature = "fuzzing"), + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub enum TypeTag { // alias for compatibility with old json serialized data. #[serde(rename = "bool", alias = "Bool")] @@ -102,7 +105,10 @@ impl FromStr for TypeTag { } #[derive(Serialize, Deserialize, Debug, PartialEq, Hash, Eq, Clone, PartialOrd, Ord)] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] #[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] pub struct StructTag { @@ -212,7 +218,10 @@ impl ResourceKey { /// Represents the initial key into global storage where we first index by the address, and then /// the struct tag. The struct fields are public to support pattern matching. #[derive(Serialize, Deserialize, Debug, PartialEq, Hash, Eq, Clone, PartialOrd, Ord)] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] #[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] pub struct ModuleId { diff --git a/third_party/move/move-core/types/src/metadata.rs b/third_party/move/move-core/types/src/metadata.rs index 9191615d9c39d..2b00773262da1 100644 --- a/third_party/move/move-core/types/src/metadata.rs +++ b/third_party/move/move-core/types/src/metadata.rs @@ -3,7 +3,10 @@ /// Representation of metadata, #[derive(Clone, PartialEq, Eq, Debug)] -#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "fuzzing", + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub struct Metadata { /// The key identifying the type of metadata. pub key: Vec, diff --git a/third_party/move/move-core/types/src/u256.rs b/third_party/move/move-core/types/src/u256.rs index b73647ea06fe8..40a47e050c06c 100644 --- a/third_party/move/move-core/types/src/u256.rs +++ b/third_party/move/move-core/types/src/u256.rs @@ -705,6 +705,13 @@ impl<'a> arbitrary::Arbitrary<'a> for U256 { } } +#[cfg(any(test, feature = "fuzzing"))] +impl dearbitrary::Dearbitrary for U256 { + fn dearbitrary(&self, dearbitrator: &mut dearbitrary::Dearbitrator) { + dearbitrator.push_bytes(U256::to_le_bytes(self.to_owned()).as_ref()); + } +} + #[test] fn wrapping_add() { // a + b overflows U256::MAX by 100 diff --git a/third_party/move/move-core/types/src/value.rs b/third_party/move/move-core/types/src/value.rs index 49a4d4eada8df..de4ef817e4832 100644 --- a/third_party/move/move-core/types/src/value.rs +++ b/third_party/move/move-core/types/src/value.rs @@ -76,7 +76,10 @@ pub fn variant_name_placeholder(len: usize) -> &'static [&'static str] { } #[derive(Debug, PartialEq, Eq, Clone)] -#[cfg_attr(any(test, feature = "fuzzing"), derive(arbitrary::Arbitrary))] +#[cfg_attr( + any(test, feature = "fuzzing"), + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub enum MoveStruct { /// The representation used by the MoveVM Runtime(Vec), @@ -86,15 +89,18 @@ pub enum MoveStruct { WithFields(Vec<(Identifier, MoveValue)>), /// An even more decorated representation with both types and human-readable field names WithTypes { - type_: StructTag, - fields: Vec<(Identifier, MoveValue)>, + _type_: StructTag, + _fields: Vec<(Identifier, MoveValue)>, }, /// A decorated representation of a variant, with the variant name, tag value, and field values. WithVariantFields(Identifier, u16, Vec<(Identifier, MoveValue)>), } #[derive(Debug, PartialEq, Eq, Clone)] -#[cfg_attr(any(test, feature = "fuzzing"), derive(arbitrary::Arbitrary))] +#[cfg_attr( + any(test, feature = "fuzzing"), + derive(arbitrary::Arbitrary, dearbitrary::Dearbitrary) +)] pub enum MoveValue { U8(u8), U64(u64), @@ -282,7 +288,10 @@ impl MoveStruct { } pub fn with_types(type_: StructTag, fields: Vec<(Identifier, MoveValue)>) -> Self { - Self::WithTypes { type_, fields } + Self::WithTypes { + _type_: type_, + _fields: fields, + } } pub fn simple_deserialize(blob: &[u8], ty: &MoveStructLayout) -> AResult { @@ -301,8 +310,8 @@ impl MoveStruct { }, (MoveStruct::Runtime(vals), MoveStructLayout::WithTypes { type_, fields }) => { MoveStruct::WithTypes { - type_: type_.clone(), - fields: vals + _type_: type_.clone(), + _fields: vals .into_iter() .zip(fields) .map(|(v, l)| (l.name.clone(), v.decorate(&l.layout))) @@ -324,8 +333,8 @@ impl MoveStruct { }, (MoveStruct::WithFields(vals), MoveStructLayout::WithTypes { type_, fields }) => { MoveStruct::WithTypes { - type_: type_.clone(), - fields: vals + _type_: type_.clone(), + _fields: vals .into_iter() .zip(fields) .map(|((fld, v), l)| (fld, v.decorate(&l.layout))) @@ -354,9 +363,10 @@ impl MoveStruct { match self { Self::Runtime(vals) => (None, vals), Self::RuntimeVariant(tag, vals) => (Some(tag), vals), - Self::WithFields(fields) | Self::WithTypes { fields, .. } => { - (None, fields.into_iter().map(|(_, f)| f).collect()) - }, + Self::WithFields(fields) + | Self::WithTypes { + _fields: fields, .. + } => (None, fields.into_iter().map(|(_, f)| f).collect()), Self::WithVariantFields(_, tag, fields) => { (Some(tag), fields.into_iter().map(|(_, f)| f).collect()) }, @@ -365,7 +375,10 @@ impl MoveStruct { pub fn undecorate(self) -> Self { match self { - MoveStruct::WithFields(fields) | MoveStruct::WithTypes { fields, .. } => Self::Runtime( + MoveStruct::WithFields(fields) + | MoveStruct::WithTypes { + _fields: fields, .. + } => Self::Runtime( fields .into_iter() .map(|(_, v)| MoveValue::undecorate(v)) @@ -641,8 +654,8 @@ impl<'d> serde::de::DeserializeSeed<'d> for &MoveStructLayout { let fields = deserializer .deserialize_tuple(layout.len(), DecoratedStructFieldVisitor(layout))?; Ok(MoveStruct::WithTypes { - type_: type_.clone(), - fields, + _type_: type_.clone(), + _fields: fields, }) }, MoveStructLayout::WithVariants(decorated_variants) => { @@ -742,7 +755,10 @@ impl serde::Serialize for MoveStruct { } }, Self::WithFields(fields) => MoveFields(fields).serialize(serializer), - Self::WithTypes { type_, fields } => { + Self::WithTypes { + _type_: type_, + _fields: fields, + } => { // Serialize a Move struct as Serde struct type named `struct `with two fields named `type` and `fields`. // `fields` will get serialized as a Serde map. // Unfortunately, we can't serialize this in the logical way: as a Serde struct named `type` with a field for @@ -902,7 +918,10 @@ impl fmt::Display for MoveStruct { MoveStruct::WithFields(fields) => { fmt_list(f, "{", fields.iter().map(DisplayFieldBinding), "}") }, - MoveStruct::WithTypes { type_, fields } => { + MoveStruct::WithTypes { + _type_: type_, + _fields: fields, + } => { fmt::Display::fmt(type_, f)?; fmt_list(f, " {", fields.iter().map(DisplayFieldBinding), "}") }, diff --git a/third_party/move/move-stdlib/src/natives/debug.rs b/third_party/move/move-stdlib/src/natives/debug.rs index e9cdb47764fcb..38876b7685fdb 100644 --- a/third_party/move/move-stdlib/src/natives/debug.rs +++ b/third_party/move/move-stdlib/src/natives/debug.rs @@ -461,7 +461,10 @@ mod testing { } }, MoveValue::Struct(move_struct) => match move_struct { - MoveStruct::WithTypes { type_, mut fields } => { + MoveStruct::WithTypes { + _type_: type_, + _fields: mut fields, + } => { let type_tag = TypeTag::from(type_.clone()); // Check if struct is an std::string::String diff --git a/third_party/move/tools/move-resource-viewer/src/lib.rs b/third_party/move/tools/move-resource-viewer/src/lib.rs index 54ffa7f3c65ab..4f06ccc18ce22 100644 --- a/third_party/move/tools/move-resource-viewer/src/lib.rs +++ b/third_party/move/tools/move-resource-viewer/src/lib.rs @@ -263,7 +263,10 @@ impl MoveValueAnnotator { field_names.into_iter().zip(values).collect(), ) }, - MoveStruct::WithFields(fields) | MoveStruct::WithTypes { fields, .. } => (None, fields), + MoveStruct::WithFields(fields) + | MoveStruct::WithTypes { + _fields: fields, .. + } => (None, fields), MoveStruct::WithVariantFields(name, _, fields) => (Some(name), fields), }) }