From 71f247f705fd2867382ca6a689cba9ad39c45862 Mon Sep 17 00:00:00 2001 From: TannrA Date: Tue, 7 Feb 2023 17:57:09 -0500 Subject: [PATCH 01/28] add storage structure and parser --- Cargo.lock | 522 ++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 8 +- src/instruction/mod.rs | 4 +- src/lib.rs | 12 + src/machine.rs | 18 +- src/memory.rs | 20 +- src/parser.rs | 45 ++++ src/smt/bitvec/mod.rs | 69 ++++-- src/storage.rs | 83 +++++++ 9 files changed, 744 insertions(+), 37 deletions(-) create mode 100644 src/parser.rs create mode 100644 src/storage.rs diff --git a/Cargo.lock b/Cargo.lock index 5398a74..4f75e8a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,17 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "ahash" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "0.7.20" @@ -20,6 +31,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + [[package]] name = "arrayvec" version = "0.7.2" @@ -37,12 +54,30 @@ dependencies = [ "winapi", ] +[[package]] +name = "auto_impl" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a8c1df849285fbacd587de7818cc7d13be6cd2cbcd47a04fb1801b0e2706e33" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + [[package]] name = "bindgen" version = "0.58.1" @@ -84,6 +119,15 @@ dependencies = [ "wyz", ] +[[package]] +name = "block-buffer" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +dependencies = [ + "generic-array", +] + [[package]] name = "byte-slice-cast" version = "1.2.2" @@ -96,6 +140,12 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" + [[package]] name = "cc" version = "1.0.79" @@ -152,18 +202,64 @@ dependencies = [ "cc", ] +[[package]] +name = "const-oid" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cec318a675afcb6a1ea1d4340e2d377e56e47c266f28043ceccbf4412ddfdd3b" + [[package]] name = "convert_case" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "cpufeatures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +dependencies = [ + "libc", +] + [[package]] name = "crunchy" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-bigint" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "der" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +dependencies = [ + "const-oid", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -177,6 +273,48 @@ dependencies = [ "syn", ] +[[package]] +name = "digest" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "ecdsa" +version = "0.14.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +dependencies = [ + "der", + "elliptic-curve", + "rfc6979", + "signature", +] + +[[package]] +name = "elliptic-curve" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +dependencies = [ + "base16ct", + "crypto-bigint", + "der", + "digest", + "ff", + "generic-array", + "group", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "env_logger" version = "0.8.4" @@ -190,6 +328,16 @@ dependencies = [ "termcolor", ] +[[package]] +name = "ff" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +dependencies = [ + "rand_core", + "subtle", +] + [[package]] name = "fixed-hash" version = "0.8.0" @@ -208,6 +356,16 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +[[package]] +name = "generic-array" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.8" @@ -225,12 +383,33 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "group" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + [[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", + "serde", +] + [[package]] name = "hermit-abi" version = "0.1.19" @@ -245,6 +424,18 @@ name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] [[package]] name = "humantime" @@ -261,6 +452,24 @@ dependencies = [ "parity-scale-codec", ] +[[package]] +name = "impl-rlp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +dependencies = [ + "rlp", +] + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + [[package]] name = "impl-trait-for-tuples" version = "0.2.2" @@ -279,7 +488,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", +] + +[[package]] +name = "k256" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "sha2", + "sha3", +] + +[[package]] +name = "keccak" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768" +dependencies = [ + "cpufeatures", ] [[package]] @@ -287,6 +518,9 @@ name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin", +] [[package]] name = "lazycell" @@ -344,6 +578,103 @@ dependencies = [ "memchr", ] +[[package]] +name = "num" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_enum" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d829733185c1ca374f17e52b762f24f535ec625d2cc1f070e34c8a9068f341b" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2be1598bf1c313dcdd12092e3f1920f463462525a21b7b4e11b4168353d0123e" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "once_cell" version = "1.17.0" @@ -396,6 +727,8 @@ checksum = "9f3486ccba82358b11a77516035647c34ba167dfa53312630de83b12bd4f3d66" dependencies = [ "fixed-hash", "impl-codec", + "impl-rlp", + "impl-serde", "uint", ] @@ -409,6 +742,30 @@ dependencies = [ "toml_edit", ] +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro2" version = "1.0.50" @@ -480,6 +837,73 @@ version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +[[package]] +name = "revm" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73d84c8f9836efb0f5f5f8de4700a953c4e1f3119e5cfcb0aad8e5be73daf991" +dependencies = [ + "arrayref", + "auto_impl", + "bytes", + "hashbrown 0.13.2", + "hex", + "num_enum", + "primitive-types", + "revm_precompiles", + "rlp", + "serde", + "sha3", +] + +[[package]] +name = "revm_precompiles" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0353d456ef3e989dc9190f42c6020f09bc2025930c37895826029304413204b5" +dependencies = [ + "bytes", + "hashbrown 0.13.2", + "k256", + "num", + "once_cell", + "primitive-types", + "ripemd", + "sha2", + "sha3", + "substrate-bn", +] + +[[package]] +name = "rfc6979" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +dependencies = [ + "crypto-bigint", + "hmac", + "zeroize", +] + +[[package]] +name = "ripemd" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" +dependencies = [ + "digest", +] + +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes", + "rustc-hex", +] + [[package]] name = "ruint" version = "1.7.0" @@ -520,6 +944,19 @@ dependencies = [ "semver", ] +[[package]] +name = "sec1" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +dependencies = [ + "base16ct", + "der", + "generic-array", + "subtle", + "zeroize", +] + [[package]] name = "semver" version = "1.0.16" @@ -533,6 +970,7 @@ dependencies = [ "hex", "once_cell", "rand", + "revm", "ruint", "smallvec", "uuid", @@ -544,6 +982,41 @@ name = "serde" version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sha2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha3" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdf0c33fae925bdc080598b84bc15c55e7b9a4a43b3c704da051f977469691c9" +dependencies = [ + "digest", + "keccak", +] [[package]] name = "shlex" @@ -551,12 +1024,28 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +dependencies = [ + "digest", + "rand_core", +] + [[package]] name = "smallvec" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + [[package]] name = "static_assertions" version = "1.1.0" @@ -569,6 +1058,25 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +[[package]] +name = "substrate-bn" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b5bbfa79abbae15dd642ea8176a21a635ff3c00059961d1ea27ad04e5b441c" +dependencies = [ + "byteorder", + "crunchy", + "lazy_static", + "rand", + "rustc-hex", +] + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + [[package]] name = "syn" version = "1.0.107" @@ -641,6 +1149,12 @@ dependencies = [ "toml_datetime", ] +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + [[package]] name = "uint" version = "0.9.5" @@ -761,3 +1275,9 @@ dependencies = [ "bindgen", "cmake", ] + +[[package]] +name = "zeroize" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" diff --git a/Cargo.toml b/Cargo.toml index cf8b92c..d7291b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,13 @@ uuid = { version = "1.2.2", features = ["v4"] } hex = "0.4.3" smallvec = "1.10.0" rand = "0.8.5" - +revm = { version = "2.3", default-features = false, features = [ + "std", + "k256", + "with-serde", + "memory_limit", + "optional_eip3607" +] } [target.'cfg(any(target_os = "windows", target_os = "macos"))'.dependencies] diff --git a/src/instruction/mod.rs b/src/instruction/mod.rs index 3366859..e6e3e03 100644 --- a/src/instruction/mod.rs +++ b/src/instruction/mod.rs @@ -33,11 +33,12 @@ pub enum Instruction { Sub, Div, SDiv, - SMod, Mod, + SMod, AddMod, MulMod, Exp, + SignExtend, Lt, Gt, Slt, @@ -1366,6 +1367,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { Instruction::Revert => todo!(), Instruction::Invalid => todo!(), Instruction::SelfDestruct => todo!(), + Instruction::SignExtend => todo!(), Instruction::Push(bv) => { let stack_change = StackChange { pop_qty: 0, diff --git a/src/lib.rs b/src/lib.rs index 12b2183..427f5de 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,6 +9,8 @@ pub mod smt; pub mod stack; pub mod state; pub mod traits; +pub mod storage; +pub mod parser; use instruction::*; use smt::*; use stack::*; @@ -23,3 +25,13 @@ pub fn bvi(val: impl Into) -> BitVec { pub fn bvc(val: impl AsRef) -> BitVec<32> { BitVec::new_const(val) } + + +#[cfg(test)] +mod test { + /* + + + */ + const counter_with_storage_mapping: &str = r#"608060405234801561001057600080fd5b5060056000806001815260200190815260200160002081905550610197806100396000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063846719e01461003b578063d78233d61461006b575b600080fd5b6100556004803603810190610050919061010a565b61009b565b6040516100629190610146565b60405180910390f35b6100856004803603810190610080919061010a565b6100b7565b6040516100929190610146565b60405180910390f35b6000806000838152602001908152602001600020549050919050565b60006020528060005260406000206000915090505481565b600080fd5b6000819050919050565b6100e7816100d4565b81146100f257600080fd5b50565b600081359050610104816100de565b92915050565b6000602082840312156101205761011f6100cf565b5b600061012e848285016100f5565b91505092915050565b610140816100d4565b82525050565b600060208201905061015b6000830184610137565b9291505056fea2646970667358fe122066b287fef10118cba238fe38953bfefe938afefefefefe94fefe3682fefefefe64736f6c63430008110033"#; +} \ No newline at end of file diff --git a/src/machine.rs b/src/machine.rs index 12c3d20..2bd4597 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -52,7 +52,16 @@ impl ExecutionSummary { } } + + pub type ExecBranch<'ctx> = (EvmState, Vec>); + +pub struct TransactionContext { + calldata: Option>, + output: Option>, + storage: HashMap + +} #[derive(Clone)] pub struct Evm<'ctx> { pgm: Vec, @@ -324,10 +333,10 @@ fn test_mem_store_mem_load() { Instruction::MStore, push32(bvi(2)), Instruction::MLoad, - push32(bvi(5)), - Instruction::MStore8, - push32(bvi(5)), - Instruction::MLoad, + // push32(bvi(5)), + // Instruction::MStore8, + // push32(bvi(5)), + // Instruction::MLoad, ]; /** stack memory @@ -355,6 +364,7 @@ fn test_mem_store_mem_load() { .peek() .cloned() .unwrap(); + eprintln!("Stack top size: {:#?}", top.as_ref().get_size()); assert_eq!(top, bvi(3)); } eprintln!("STATES > {:#?}", evm.states); diff --git a/src/memory.rs b/src/memory.rs index fe8d16b..29c1dad 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -54,7 +54,7 @@ impl Memory { } pub fn write(&mut self, idx: Index, val: BitVec<1>) { - let idx = idx.as_ref().as_u64().unwrap() as usize; + let idx = idx.into(); self.inner.insert(idx, val); // Pad rest with zero for i in 0..30 { @@ -62,13 +62,13 @@ impl Memory { } } pub fn read(&self, idx: Index) -> BitVec<1> { - let idx = idx.as_ref().as_u64().unwrap() as usize; + let idx: usize = idx.into(); let val = self.inner.get(idx).unwrap().clone(); val } pub fn read_word(&self, idx: Index) -> BitVec<32> { let mut i = 0; - let idx = idx.as_ref().as_u64().unwrap() as usize; + let idx: usize = idx.into(); let mut bytes = vec![]; let mut mem = self.inner.clone(); while i < 32 { @@ -79,8 +79,14 @@ impl Memory { } let mut new_bv: BitVec<1> = BitVec::default(); let mut new_bv_inner = new_bv.as_ref().clone(); - bytes.into_iter().for_each(|b| { - new_bv_inner = new_bv_inner.concat(&b); + bytes.into_iter().enumerate().for_each(|(i, b)| { + if i == 0 { + new_bv = BitVec::with_bv(b); + new_bv_inner = new_bv.as_ref().clone(); + } else { + new_bv_inner = new_bv_inner.concat(&b); + } + }); BitVec { inner: BVType::Z3(new_bv_inner), @@ -89,7 +95,7 @@ impl Memory { } pub fn write_word(&mut self, idx: Index, word: BitVec<32>) { - let idx = idx.as_ref().as_u64().unwrap() as usize; + let idx = idx.into(); if idx > self.size() { for i in 0..idx - self.size() { self.inner.push(BitVec::default()); @@ -98,7 +104,7 @@ impl Memory { //eprintln!("WORD: {word:#?}"); for i in 0..32 { let ii = 32 - i - 1; - let bv = word.as_ref().extract(ii * 8 + 7, ii * 8); + let bv = word.as_ref().extract(ii * 8 + 7, ii * 8).simplify(); // eprintln!("Extracted: {:#?}", bv); let bv: BitVec<1> = bv.into(); diff --git a/src/parser.rs b/src/parser.rs new file mode 100644 index 0000000..1ceffce --- /dev/null +++ b/src/parser.rs @@ -0,0 +1,45 @@ +use crate::instruction::Instruction; +use revm::{ + opcode::OpCode +}; +pub struct Parser<'a> { + pgm: &'a str +} + +impl<'a> Parser<'a> { + + pub fn with_pgm(pgm: &'a str) -> Self { + Self { + pgm + } + } + + pub fn mnemonic(&self) -> Vec { + let bytes = self.pgm.as_bytes(); + let mut opcodes: Vec = vec![]; + + for b in bytes { + let b = OpCode::try_from_u8(*b); + if let Some(op) = b { + + } + + } + + todo!() + } + + +} + + +impl From<&[u8]> for Instruction { + fn from(value: &[u8]) -> Self { + let first_byte = *value.first().unwrap(); + + let opcode = OpCode::try_from_u8(first_byte).unwrap(); + if opcode.is + + todo!() + } +} \ No newline at end of file diff --git a/src/smt/bitvec/mod.rs b/src/smt/bitvec/mod.rs index ae2f4bf..43f9074 100644 --- a/src/smt/bitvec/mod.rs +++ b/src/smt/bitvec/mod.rs @@ -1,21 +1,39 @@ pub mod z3; + +use std::hash::{Hash, Hasher}; pub use self::z3::*; use super::{ctx, SolverType}; use z3_ext::ast::{Ast, BV}; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum BVType { Z3(BV<'static>), } pub type SymByte = BitVec<8>; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Eq)] pub struct BitVec { pub inner: BVType, pub(crate) typ: super::SolverType, } + +// impl PartialEq for BitVec { +// fn eq(&self, other: &Self) -> bool { +// let BVType::Z3(a) = &self.inner; +// let BVType::Z3(b) = &other.inner; +// +// a == b +// } +// } + +impl Hash for BitVec { + fn hash(&self, state: &mut H) { + self.as_ref().hash(state); + state.finish(); + } +} impl BitVec { pub fn with_bv(bv: BV<'static>) -> Self { Self { @@ -40,26 +58,31 @@ impl Default for BitVec { impl PartialEq for BitVec { fn eq(&self, other: &Self) -> bool { - match &self.inner { - BVType::Z3(bv) => { - //eprintln!("LHS BV EQ: {:#?}", bv); - match &other.inner { - BVType::Z3(bvo) => { - //eprintln!("RHS BV EQ: {:#?}", bvo); - if let Some(bv1) = bv.as_u64() { - if let Some(bv2) = bvo.as_u64() { - bv1 == bv2 - } else { - false - } - } else { - false - } - } - _ => false, - } - } - _ => false, - } + + let a = self.as_ref(); + let b = other.as_ref(); + + a.eq(b) + // match &self.inner { + // BVType::Z3(bv) => { + // //eprintln!("LHS BV EQ: {:#?}", bv); + // match &other.inner { + // BVType::Z3(bvo) => { + // //eprintln!("RHS BV EQ: {:#?}", bvo); + // if let Some(bv1) = bv.as_u64() { + // if let Some(bv2) = bvo.as_u64() { + // bv1 == bv2 + // } else { + // false + // } + // } else { + // false + // } + // } + // _ => false, + // } + // } + // _ => false, + // } } } diff --git a/src/storage.rs b/src/storage.rs new file mode 100644 index 0000000..d3bf7cd --- /dev/null +++ b/src/storage.rs @@ -0,0 +1,83 @@ +use std::collections::HashMap; +use crate::traits::{MachineComponent}; +use z3_ext::{ + ast::{ + BV, Ast, Array + } +}; +use crate::{bvc, bvi}; +use crate::smt::{BitVec, ctx}; + +fn make_storage_arr() { + +} +#[derive(Debug, Clone, Default)] +pub struct AccountStorage { + inner: HashMap, StorageValue> +} +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum StorageValue { + Array(Array<'static>), + BV(BitVec<32>) +} + +impl Default for StorageValue { + fn default() -> Self { + Self::BV(Default::default()) + } +} + +impl AccountStorage { + pub fn sstore(&mut self, index: BitVec<32>, val: StorageValue) { + self.inner.insert(index, val); + } + + pub fn sload(&self, index: &BitVec<32>) -> StorageValue { + if let Some(val) = self.inner.get(index) { + val.clone() + } else { + Default::default() + } + } +} + + +pub type Address = BitVec<20>; + +#[derive(Debug, Clone, Default)] +pub struct GlobalStorage { + inner: HashMap +} + +impl GlobalStorage { + pub fn init_with_addrs(addrs: Vec
) -> Self { + let mut store = Self::default(); + addrs.into_iter().for_each(|addr| { + store.inner.insert(addr, Default::default()); + }); + store + } + + pub fn get(&self, addr: &Address) -> AccountStorage { + self.inner.get(addr).cloned().unwrap_or_default() + } +} + +#[test] +fn test_basic_lookup_works_in_acc_storage() { + let addr = Address::new_const("Address1"); + let mut acc_store = AccountStorage::default(); + acc_store.sstore(bvi(5), StorageValue::BV(bvc("val_at_idx_5"))); + + + assert_eq!(acc_store.sload(&bvi(5)), StorageValue::BV(bvc("val_at_idx_5"))); +} + +#[test] +fn test_basic_lookup_global_storage() { + let addr = Address::new_const("Address1"); + let addr2 = Address::new_const("Address2"); + let mut global = GlobalStorage::init_with_addrs(vec![addr, addr2]); + + +} \ No newline at end of file From b01376437d508d0688784f4387c6602fd2e617c6 Mon Sep 17 00:00:00 2001 From: tannr Date: Wed, 8 Feb 2023 15:46:34 -0500 Subject: [PATCH 02/28] u8 to instruction --- src/parser.rs | 175 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 164 insertions(+), 11 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index 1ceffce..5c2af74 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,6 +1,6 @@ use crate::instruction::Instruction; use revm::{ - opcode::OpCode + opcode::OpCode, OPCODE_JUMPMAP }; pub struct Parser<'a> { pgm: &'a str @@ -18,28 +18,181 @@ impl<'a> Parser<'a> { let bytes = self.pgm.as_bytes(); let mut opcodes: Vec = vec![]; + let mut pgm = vec![]; for b in bytes { - let b = OpCode::try_from_u8(*b); - if let Some(op) = b { - - } + + let inst = Instruction::from(*b); + + pgm.push(inst); } + pgm - todo!() + } + + + +} + +fn is_push(b: u8) -> bool { + 0x60 <= b && 0x7f >= b +} +fn push_size(b: u8) -> u8 { + b - 0x60 } -impl From<&[u8]> for Instruction { - fn from(value: &[u8]) -> Self { - let first_byte = *value.first().unwrap(); - let opcode = OpCode::try_from_u8(first_byte).unwrap(); - if opcode.is +impl From for Instruction { + fn from(value: u8) -> Self { + match value { + 0x00 => Instruction::Stop, + 0x01 => Instruction::Add, + 0x02 => Instruction::Mul, + 0x03 => Instruction::Sub, + 0x04 => Instruction::Div, + 0x05 => Instruction::SDiv, + 0x06 => Instruction::Mod, + 0x07 => Instruction::SMod, + 0x08 => Instruction::AddMod, + 0x09 => Instruction::MulMod, + 0x0a => Instruction::Exp, + 0x0b => Instruction::SignExtend, + 0x10 => Instruction::Lt, + 0x11 => Instruction::Gt, + 0x12 => Instruction::Slt, + 0x13 => Instruction::Sgt, + 0x14 => Instruction::Eq, + 0x15 => Instruction::And, + 0x16 => Instruction::Or, + 0x17 => Instruction::Xor, + 0x18 => Instruction::Not, + 0x19 => Instruction::Byte, + 0x1a => Instruction::Shl, + 0x1b => Instruction::Shr, + 0x20 => Instruction::Sha3, + 0x30 => Instruction::Address, + 0x31 => Instruction::Balance, + 0x32 => Instruction::Origin, + 0x33 => Instruction::Caller, + 0x34 => Instruction::CallValue, + 0x35 => Instruction::CallDataLoad, + 0x36 => Instruction::CallDataSize, + 0x37 => Instruction::CallDataCopy, + 0x38 => Instruction::CodeSize, + 0x39 => Instruction::CodeCopy, + 0x3a => Instruction::GasPrice, + 0x3b => Instruction::ExtCodeSize, + 0x3c => Instruction::ExtCodeCopy, + 0x3d => Instruction::ReturnDataSize, + 0x3e => Instruction::ReturnDataCopy, + 0x3f => Instruction::ExtCodeHash, + 0x40 => Instruction::BlockHash, + 0x41 => Instruction::Coinbase, + 0x42 => Instruction::Timestamp, + 0x43 => Instruction::Number, + 0x44 => Instruction::Difficulty, + 0x45 => Instruction::GasLimit, + 0x46 => Instruction::ChainId, + 0x47 => Instruction::SelfBalance, + 0x50 => Instruction::Pop, + 0x51 => Instruction::MLoad, + 0x52 => Instruction::MStore, + 0x53 => Instruction::MStore8, + 0x54 => Instruction::SLoad, + 0x55 => Instruction::SStore, + 0x56 => Instruction::Jump, + 0x57 => Instruction::JumpI, + 0x58 => Instruction::Pc, + 0x59 => Instruction::MSize, + 0x5a => Instruction::Gas, + 0x5b => Instruction::JumpDest, + 0x60 => Instruction::Push1(Default::default()), + 0x61 => Instruction::Push2(Default::default()), + 0x62 => Instruction::Push3(Default::default()), + 0x63 => Instruction::Push4(Default::default()), + 0x64 => Instruction::Push5(Default::default()), + 0x65 => Instruction::Push6(Default::default()), + 0x66 => Instruction::Push7(Default::default()), + 0x67 => Instruction::Push8(Default::default()), + 0x68 => Instruction::Push9(Default::default()), + 0x69 => Instruction::Push10(Default::default()), + 0x6a => Instruction::Push11(Default::default()), + 0x6b => Instruction::Push12(Default::default()), + 0x6c => Instruction::Push13(Default::default()), + 0x6d => Instruction::Push14(Default::default()), + 0x6e => Instruction::Push15(Default::default()), + 0x6f => Instruction::Push16(Default::default()), + 0x70 => Instruction::Push17(Default::default()), + 0x71 => Instruction::Push18(Default::default()), + 0x72 => Instruction::Push19(Default::default()), + 0x73 => Instruction::Push20(Default::default()), + 0x74 => Instruction::Push21(Default::default()), + 0x75 => Instruction::Push22(Default::default()), + 0x76 => Instruction::Push23(Default::default()), + 0x77 => Instruction::Push24(Default::default()), + 0x78 => Instruction::Push25(Default::default()), + 0x79 => Instruction::Push26(Default::default()), + 0x7a => Instruction::Push27(Default::default()), + 0x7b => Instruction::Push28(Default::default()), + 0x7c => Instruction::Push29(Default::default()), + 0x7d => Instruction::Push30(Default::default()), + 0x7e => Instruction::Push31(Default::default()), + 0x7f => Instruction::Push32(Default::default()), + 0x80 => Instruction::Dup1, + 0x81 => Instruction::Dup2, + 0x82 => Instruction::Dup3, + 0x83 => Instruction::Dup4, + 0x84 => Instruction::Dup5, + 0x85 => Instruction::Dup6, + 0x86 => Instruction::Dup7, + 0x87 => Instruction::Dup8, + 0x88 => Instruction::Dup9, + 0x89 => Instruction::Dup10, + 0x8a => Instruction::Dup11, + 0x8b => Instruction::Dup12, + 0x8c => Instruction::Dup13, + 0x8d => Instruction::Dup14, + 0x8e => Instruction::Dup15, + 0x8f => Instruction::Dup16, + 0x90 => Instruction::Swap1, + 0x91 => Instruction::Swap2, + 0x92 => Instruction::Swap3, + 0x93 => Instruction::Swap4, + 0x94 => Instruction::Swap5, + 0x95 => Instruction::Swap6, + 0x96 => Instruction::Swap7, + 0x97 => Instruction::Swap8, + 0x98 => Instruction::Swap9, + 0x99 => Instruction::Swap10, + 0x9a => Instruction::Swap11, + 0x9b => Instruction::Swap12, + 0x9c => Instruction::Swap13, + 0x9d => Instruction::Swap14, + 0x9e => Instruction::Swap15, + 0x9f => Instruction::Swap16, + 0xa0 => Instruction::Log0, + 0xa1 => Instruction::Log1, + 0xa2 => Instruction::Log2, + 0xa3 => Instruction::Log3, + 0xa4 => Instruction::Log4, + 0xf0 => Instruction::Create, + 0xf1 => Instruction::Call, + 0xf2 => Instruction::CallCode, + 0xf3 => Instruction::Return, + 0xf4 => Instruction::DelegateCall, + 0xf5 => Instruction::Create2, + 0xfa => Instruction::StaticCall, + 0xfd => Instruction::Revert, + 0xfe => Instruction::Invalid, + 0xff => Instruction::SelfDestruct, + _ => Instruction::Invalid, + }; + todo!() } } \ No newline at end of file From 3bc884a6f81967952c93770dabb0285352463389 Mon Sep 17 00:00:00 2001 From: TannrA Date: Wed, 8 Mar 2023 20:37:34 -0500 Subject: [PATCH 03/28] fix push size calc --- src/lib.rs | 2 ++ src/parser.rs | 35 ++++++++++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 427f5de..55da6c5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,6 +11,8 @@ pub mod state; pub mod traits; pub mod storage; pub mod parser; + + use instruction::*; use smt::*; use stack::*; diff --git a/src/parser.rs b/src/parser.rs index 5c2af74..ab12aad 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -41,11 +41,26 @@ fn is_push(b: u8) -> bool { } fn push_size(b: u8) -> u8 { - b - 0x60 + if b > 0x60 { + b - 0x60 + 1 + } else { + 0 + } + } +impl Instruction { + pub fn from_byte(value: u8) -> Self { + value.into() + + } + // Has to handle when it's a push or dup, otherwise easy 1-1 conversion + pub fn from_slice(bytes: &[u8]) -> Vec { + todo!() + } +} impl From for Instruction { fn from(value: u8) -> Self { @@ -191,8 +206,22 @@ impl From for Instruction { 0xfe => Instruction::Invalid, 0xff => Instruction::SelfDestruct, _ => Instruction::Invalid, - }; + } - todo!() + } +} + +#[test] +fn is_push_works() { + for b in (0x60_u8..0x7f) { + assert!(is_push(b)); + } + + for b in (0x00_u8 .. 0x5f) { + assert!(!is_push(b)); + } + + for b in (0x80..0xff_u8) { + assert!(!is_push(b)); } } \ No newline at end of file From 2c6063457f4e3ac830c412eed6231c64cba9afe6 Mon Sep 17 00:00:00 2001 From: tannr Date: Sat, 8 Apr 2023 02:57:38 -0400 Subject: [PATCH 04/28] add parser; add test-contracts with foundry; add convenience methods to parser --- .gitmodules | 3 + Cargo.lock | 2812 ++++++++++++++++++++++++--- Cargo.toml | 2 +- src/lib.rs | 3 +- src/parser.rs | 32 +- src/storage.rs | 7 +- test-contracts/.gitignore | 14 + test-contracts/foundry.toml | 6 + test-contracts/lib/forge-std | 1 + test-contracts/script/Counter.s.sol | 12 + test-contracts/src/Counter.sol | 14 + test-contracts/src/Storage.sol | 42 + test-contracts/test/Counter.t.sol | 24 + 13 files changed, 2657 insertions(+), 315 deletions(-) create mode 100644 .gitmodules create mode 100644 test-contracts/.gitignore create mode 100644 test-contracts/foundry.toml create mode 160000 test-contracts/lib/forge-std create mode 100644 test-contracts/script/Counter.s.sol create mode 100644 test-contracts/src/Counter.sol create mode 100644 test-contracts/src/Storage.sol create mode 100644 test-contracts/test/Counter.t.sol diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..518bb94 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "test-contracts/lib/forge-std"] + path = test-contracts/lib/forge-std + url = https://github.com/foundry-rs/forge-std diff --git a/Cargo.lock b/Cargo.lock index 4f75e8a..182976c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,24 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aes" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", + "opaque-debug", +] + [[package]] name = "ahash" version = "0.8.3" @@ -31,6 +49,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "anyhow" +version = "1.0.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" + [[package]] name = "arrayref" version = "0.3.6" @@ -43,13 +67,22 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +[[package]] +name = "ascii-canvas" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" +dependencies = [ + "term", +] + [[package]] name = "atty" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] @@ -63,7 +96,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] @@ -78,6 +111,24 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "bindgen" version = "0.58.1" @@ -87,7 +138,7 @@ dependencies = [ "bitflags", "cexpr", "clang-sys", - "clap", + "clap 2.34.0", "env_logger", "lazy_static", "lazycell", @@ -101,6 +152,21 @@ dependencies = [ "which", ] +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bitflags" version = "1.3.2" @@ -119,6 +185,15 @@ dependencies = [ "wyz", ] +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + [[package]] name = "block-buffer" version = "0.10.3" @@ -128,6 +203,18 @@ dependencies = [ "generic-array", ] +[[package]] +name = "build_const" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ae4235e6dac0694637c763029ecea1a2ec9e4e06ec2729bd21ba4d9c863eb7" + +[[package]] +name = "bumpalo" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" + [[package]] name = "byte-slice-cast" version = "1.2.2" @@ -145,12 +232,39 @@ name = "bytes" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +dependencies = [ + "serde", +] + +[[package]] +name = "bzip2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] [[package]] name = "cc" version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +dependencies = [ + "jobserver", +] [[package]] name = "cexpr" @@ -167,6 +281,25 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array", +] + [[package]] name = "clang-sys" version = "1.4.0" @@ -187,12 +320,51 @@ dependencies = [ "ansi_term", "atty", "bitflags", - "strsim", - "textwrap", + "strsim 0.8.0", + "textwrap 0.11.0", "unicode-width", "vec_map", ] +[[package]] +name = "clap" +version = "3.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" +dependencies = [ + "atty", + "bitflags", + "clap_derive", + "clap_lex", + "indexmap", + "once_cell", + "strsim 0.10.0", + "termcolor", + "textwrap 0.16.0", +] + +[[package]] +name = "clap_derive" +version = "3.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.107", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "cmake" version = "0.1.49" @@ -202,11 +374,44 @@ dependencies = [ "cc", ] +[[package]] +name = "console" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3993e6445baa160675931ec041a5e03ca84b9c6e32a056150d3aa2bdda0a1f45" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "regex", + "terminal_size", + "unicode-width", + "winapi", +] + +[[package]] +name = "console" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d79fbe8970a77e3e34151cc13d3b3e248aa0faaecb9f6091fa07ebefe5ad60" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "windows-sys 0.42.0", +] + [[package]] name = "const-oid" -version = "0.9.1" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913" + +[[package]] +name = "constant_time_eq" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cec318a675afcb6a1ea1d4340e2d377e56e47c266f28043ceccbf4412ddfdd3b" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "convert_case" @@ -223,6 +428,58 @@ dependencies = [ "libc", ] +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +dependencies = [ + "cfg-if", +] + [[package]] name = "crunchy" version = "0.2.2" @@ -241,6 +498,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "crypto-bigint" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c2538c4e68e52548bacb3e83ac549f903d44f011ac9d5abb5e132e67d0808f7" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -260,6 +529,16 @@ dependencies = [ "const-oid", ] +[[package]] +name = "der" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19c5cb402c5c958281c7c0702edea7b780d03b86b606497ca3a10fcd3fc393ac" +dependencies = [ + "const-oid", + "zeroize", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -270,448 +549,1360 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn", + "syn 1.0.107", ] [[package]] -name = "digest" -version = "0.10.6" +name = "dialoguer" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "c9dd058f8b65922819fabb4a41e7d1964e56344042c26efbccd465202c23fa0c" dependencies = [ - "block-buffer", - "crypto-common", - "subtle", + "console 0.14.1", + "lazy_static", + "tempfile", + "zeroize", ] [[package]] -name = "ecdsa" -version = "0.14.8" +name = "diff" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" -dependencies = [ - "der", - "elliptic-curve", - "rfc6979", - "signature", -] +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] -name = "elliptic-curve" -version = "0.12.3" +name = "digest" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "base16ct", - "crypto-bigint", - "der", - "digest", - "ff", "generic-array", - "group", - "rand_core", - "sec1", - "subtle", - "zeroize", ] [[package]] -name = "env_logger" -version = "0.8.4" +name = "digest" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", + "block-buffer 0.10.3", + "const-oid", + "crypto-common", + "subtle", ] [[package]] -name = "ff" -version = "0.12.1" +name = "dirs-next" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" dependencies = [ - "rand_core", - "subtle", + "cfg-if", + "dirs-sys-next", ] [[package]] -name = "fixed-hash" -version = "0.8.0" +name = "dirs-sys-next" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ - "byteorder", - "rand", - "rustc-hex", - "static_assertions", + "libc", + "redox_users", + "winapi", ] [[package]] -name = "funty" -version = "2.0.0" +name = "dunce" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +checksum = "0bd4b30a6560bbd9b4620f4de34c3f14f60848e58a9b7216801afcb4c7b31c3c" [[package]] -name = "generic-array" -version = "0.14.6" +name = "ecdsa" +version = "0.14.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" dependencies = [ - "typenum", - "version_check", + "der 0.6.1", + "elliptic-curve 0.12.3", + "rfc6979 0.3.1", + "signature 1.6.4", ] [[package]] -name = "getrandom" -version = "0.2.8" +name = "ecdsa" +version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "106401dadc137d05cb0d4ab4d42be089746aefdfe8992df4d0edcf351c16ddca" dependencies = [ - "cfg-if", - "libc", - "wasi", + "der 0.7.2", + "digest 0.10.6", + "elliptic-curve 0.13.3", + "rfc6979 0.4.0", + "signature 2.1.0", ] [[package]] -name = "glob" -version = "0.3.1" +name = "either" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] -name = "group" -version = "0.12.1" +name = "elliptic-curve" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" dependencies = [ - "ff", + "base16ct 0.1.1", + "crypto-bigint 0.4.9", + "der 0.6.1", + "digest 0.10.6", + "ff 0.12.1", + "generic-array", + "group 0.12.1", "rand_core", + "sec1 0.3.0", "subtle", + "zeroize", ] [[package]] -name = "hashbrown" -version = "0.12.3" +name = "elliptic-curve" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "22cdacd4d6ed3f9b98680b679c0e52a823b8a2c7a97358d508fe247f2180c282" +dependencies = [ + "base16ct 0.2.0", + "crypto-bigint 0.5.1", + "digest 0.10.6", + "ff 0.13.0", + "generic-array", + "group 0.13.0", + "pkcs8", + "rand_core", + "sec1 0.7.1", + "subtle", + "zeroize", +] [[package]] -name = "hashbrown" -version = "0.13.2" +name = "ena" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1" dependencies = [ - "ahash", - "serde", + "log", ] [[package]] -name = "hermit-abi" -version = "0.1.19" +name = "encode_unicode" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + +[[package]] +name = "encoding_rs" +version = "0.8.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "env_logger" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "errno" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0" dependencies = [ + "errno-dragonfly", "libc", + "windows-sys 0.45.0", ] [[package]] -name = "hex" -version = "0.4.3" +name = "errno-dragonfly" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "ethabi" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" +dependencies = [ + "ethereum-types", + "hex", + "once_cell", + "regex", + "serde", + "serde_json", + "sha3", + "thiserror", + "uint", +] + +[[package]] +name = "ethbloom" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" +dependencies = [ + "crunchy", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "scale-info", + "tiny-keccak", +] + +[[package]] +name = "ethereum-types" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" +dependencies = [ + "ethbloom", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "primitive-types", + "scale-info", + "uint", +] + +[[package]] +name = "ethers-core" +version = "2.0.2" +source = "git+https://github.com/gakonst/ethers-rs#1dd35458695e2b967d4c2ff278cc8d0eaadcc9fb" +dependencies = [ + "arrayvec", + "bytes", + "chrono", + "elliptic-curve 0.13.3", + "ethabi", + "generic-array", + "getrandom", + "hex", + "k256 0.13.0", + "num_enum", + "open-fastrlp", + "rand", + "rlp", + "serde", + "serde_json", + "strum", + "tempfile", + "thiserror", + "tiny-keccak", + "unicode-xid", +] + +[[package]] +name = "ethers-solc" +version = "2.0.2" +source = "git+https://github.com/gakonst/ethers-rs#1dd35458695e2b967d4c2ff278cc8d0eaadcc9fb" dependencies = [ + "cfg-if", + "dunce", + "ethers-core", + "futures-util", + "getrandom", + "glob", + "hex", + "home", + "md-5", + "num_cpus", + "once_cell", + "path-slash", + "rayon", + "regex", + "semver", "serde", + "serde_json", + "sha2 0.10.6", + "solang-parser", + "svm-rs", + "svm-rs-builds", + "thiserror", + "tiny-keccak", + "tokio", + "tracing", + "walkdir", + "yansi", ] [[package]] -name = "hmac" +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] +name = "ff" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" dependencies = [ - "digest", + "rand_core", + "subtle", ] [[package]] -name = "humantime" -version = "2.1.0" +name = "ff" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core", + "subtle", +] [[package]] -name = "impl-codec" -version = "0.6.0" +name = "fixed-hash" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" dependencies = [ - "parity-scale-codec", + "byteorder", + "rand", + "rustc-hex", + "static_assertions", ] [[package]] -name = "impl-rlp" -version = "0.3.0" +name = "fixedbitset" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "flate2" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" dependencies = [ - "rlp", + "crc32fast", + "miniz_oxide", ] [[package]] -name = "impl-serde" -version = "0.4.0" +name = "fnv" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ - "serde", + "percent-encoding", ] [[package]] -name = "impl-trait-for-tuples" -version = "0.2.2" +name = "fs2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures-channel" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" + +[[package]] +name = "futures-io" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" + +[[package]] +name = "futures-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.13", ] [[package]] -name = "indexmap" -version = "1.9.2" +name = "futures-sink" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + +[[package]] +name = "futures-task" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" + +[[package]] +name = "futures-util" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ - "autocfg", - "hashbrown 0.12.3", + "futures-core", + "futures-io", + "futures-macro", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", ] [[package]] -name = "k256" -version = "0.11.6" +name = "generic-array" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ - "cfg-if", - "ecdsa", - "elliptic-curve", - "sha2", - "sha3", + "typenum", + "version_check", + "zeroize", ] [[package]] -name = "keccak" -version = "0.1.3" +name = "getrandom" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ - "cpufeatures", + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", ] [[package]] -name = "lazy_static" -version = "1.4.0" +name = "glob" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "group" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" dependencies = [ - "spin", + "ff 0.12.1", + "rand_core", + "subtle", ] [[package]] -name = "lazycell" -version = "1.3.0" +name = "group" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff 0.13.0", + "rand_core", + "subtle", +] [[package]] -name = "libc" -version = "0.2.139" +name = "h2" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] [[package]] -name = "libloading" -version = "0.7.4" +name = "hashbrown" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" -dependencies = [ +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", + "serde", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.6", +] + +[[package]] +name = "home" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "747309b4b440c06d57b0b25f2aee03ee9b5e5397d288c60e21fc709bb98a7408" +dependencies = [ + "winapi", +] + +[[package]] +name = "http" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyper" +version = "0.14.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" +dependencies = [ + "http", + "hyper", + "rustls", + "tokio", + "tokio-rustls", +] + +[[package]] +name = "idna" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-rlp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +dependencies = [ + "rlp", +] + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.107", +] + +[[package]] +name = "indexmap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indicatif" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d207dc617c7a380ab07ff572a6e52fa202a2a8f355860ac9c38e23f8196be1b" +dependencies = [ + "console 0.15.5", + "lazy_static", + "number_prefix", + "regex", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" +dependencies = [ + "hermit-abi 0.3.1", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "ipnet" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" + +[[package]] +name = "is-terminal" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" +dependencies = [ + "hermit-abi 0.3.1", + "io-lifetimes", + "rustix", + "windows-sys 0.48.0", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" + +[[package]] +name = "jobserver" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "k256" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" +dependencies = [ + "cfg-if", + "ecdsa 0.14.8", + "elliptic-curve 0.12.3", + "sha2 0.10.6", + "sha3", +] + +[[package]] +name = "k256" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955890845095ccf31ef83ad41a05aabb4d8cc23dc3cac5a9f5c89cf26dd0da75" +dependencies = [ + "cfg-if", + "ecdsa 0.16.4", + "elliptic-curve 0.13.3", + "once_cell", + "sha2 0.10.6", +] + +[[package]] +name = "keccak" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lalrpop" +version = "0.19.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f34313ec00c2eb5c3c87ca6732ea02dcf3af99c3ff7a8fb622ffb99c9d860a87" +dependencies = [ + "ascii-canvas", + "bit-set", + "diff", + "ena", + "is-terminal", + "itertools", + "lalrpop-util", + "petgraph", + "pico-args", + "regex", + "regex-syntax", + "string_cache", + "term", + "tiny-keccak", + "unicode-xid", +] + +[[package]] +name = "lalrpop-util" +version = "0.19.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5c1f7869c94d214466c5fd432dfed12c379fd87786768d36455892d46b18edd" +dependencies = [ + "regex", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin", +] + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.139" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ "cfg-if", "winapi", ] [[package]] -name = "log" -version = "0.4.17" +name = "linux-raw-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "md-5" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" +dependencies = [ + "digest 0.10.6", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "memoffset" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.45.0", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" + +[[package]] +name = "nom" +version = "5.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" +dependencies = [ + "memchr", + "version_check", +] + +[[package]] +name = "nom8" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" +dependencies = [ + "memchr", +] + +[[package]] +name = "num" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi 0.2.6", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d829733185c1ca374f17e52b762f24f535ec625d2cc1f070e34c8a9068f341b" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2be1598bf1c313dcdd12092e3f1920f463462525a21b7b4e11b4168353d0123e" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.107", +] + +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + +[[package]] +name = "once_cell" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "open-fastrlp" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", + "ethereum-types", + "open-fastrlp-derive", +] + +[[package]] +name = "open-fastrlp-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c" +dependencies = [ + "bytes", + "proc-macro2", + "quote", + "syn 1.0.107", +] + +[[package]] +name = "os_str_bytes" +version = "6.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267" + +[[package]] +name = "parity-scale-codec" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3840933452adf7b3b9145e27086a5a3376c619dca1a21b1e5a5af0d54979bed" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b26a931f824dd4eca30b3e43bb4f31cd5f0d3a403c5f5ff27106b805bfde7b" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.107", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" dependencies = [ "cfg-if", + "libc", + "redox_syscall 0.2.16", + "smallvec", + "windows-sys 0.45.0", ] [[package]] -name = "memchr" -version = "2.5.0" +name = "password-hash" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" +dependencies = [ + "base64ct", + "rand_core", + "subtle", +] [[package]] -name = "nom" -version = "5.1.2" +name = "path-slash" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" -dependencies = [ - "memchr", - "version_check", -] +checksum = "1e91099d4268b0e11973f036e885d652fb0b21fedcf69738c627f94db6a44f42" [[package]] -name = "nom8" -version = "0.2.0" +name = "pbkdf2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "memchr", + "digest 0.10.6", + "hmac", + "password-hash", + "sha2 0.10.6", ] [[package]] -name = "num" -version = "0.4.0" +name = "peeking_take_while" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] -name = "num-bigint" -version = "0.4.3" +name = "percent-encoding" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] -name = "num-complex" -version = "0.4.3" +name = "petgraph" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d" +checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" dependencies = [ - "num-traits", + "fixedbitset", + "indexmap", ] [[package]] -name = "num-integer" -version = "0.1.45" +name = "phf" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c" dependencies = [ - "autocfg", - "num-traits", + "phf_macros", + "phf_shared 0.11.1", ] [[package]] -name = "num-iter" -version = "0.1.43" +name = "phf_generator" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf" dependencies = [ - "autocfg", - "num-integer", - "num-traits", + "phf_shared 0.11.1", + "rand", ] [[package]] -name = "num-rational" -version = "0.4.1" +name = "phf_macros" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "92aacdc5f16768709a569e913f7451034034178b05bdc8acda226659a3dccc66" dependencies = [ - "autocfg", - "num-bigint", - "num-integer", - "num-traits", + "phf_generator", + "phf_shared 0.11.1", + "proc-macro2", + "quote", + "syn 1.0.107", ] [[package]] -name = "num-traits" -version = "0.2.15" +name = "phf_shared" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" dependencies = [ - "autocfg", + "siphasher", ] [[package]] -name = "num_enum" -version = "0.5.9" +name = "phf_shared" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d829733185c1ca374f17e52b762f24f535ec625d2cc1f070e34c8a9068f341b" +checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676" dependencies = [ - "num_enum_derive", + "siphasher", ] [[package]] -name = "num_enum_derive" -version = "0.5.9" +name = "pico-args" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2be1598bf1c313dcdd12092e3f1920f463462525a21b7b4e11b4168353d0123e" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] +checksum = "db8bcd96cb740d03149cbad5518db9fd87126a10ab519c011893b1754134c468" [[package]] -name = "once_cell" -version = "1.17.0" +name = "pin-project-lite" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] -name = "parity-scale-codec" -version = "3.3.0" +name = "pin-utils" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3840933452adf7b3b9145e27086a5a3376c619dca1a21b1e5a5af0d54979bed" -dependencies = [ - "arrayvec", - "bitvec", - "byte-slice-cast", - "impl-trait-for-tuples", - "parity-scale-codec-derive", - "serde", -] +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] -name = "parity-scale-codec-derive" -version = "3.1.4" +name = "pkcs8" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b26a931f824dd4eca30b3e43bb4f31cd5f0d3a403c5f5ff27106b805bfde7b" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", + "der 0.7.2", + "spki", ] [[package]] -name = "peeking_take_while" -version = "0.1.2" +name = "pkg-config" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "ppv-lite86" @@ -719,6 +1910,12 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + [[package]] name = "primitive-types" version = "0.12.1" @@ -729,6 +1926,7 @@ dependencies = [ "impl-codec", "impl-rlp", "impl-serde", + "scale-info", "uint", ] @@ -751,7 +1949,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn", + "syn 1.0.107", "version_check", ] @@ -768,18 +1966,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.50" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" +checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.23" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" dependencies = [ "proc-macro2", ] @@ -820,6 +2018,57 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rayon" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall 0.2.16", + "thiserror", +] + [[package]] name = "regex" version = "1.7.1" @@ -837,6 +2086,45 @@ version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +[[package]] +name = "reqwest" +version = "0.11.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-rustls", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-rustls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", + "winreg", +] + [[package]] name = "revm" version = "2.3.1" @@ -864,12 +2152,12 @@ checksum = "0353d456ef3e989dc9190f42c6020f09bc2025930c37895826029304413204b5" dependencies = [ "bytes", "hashbrown 0.13.2", - "k256", + "k256 0.11.6", "num", "once_cell", "primitive-types", "ripemd", - "sha2", + "sha2 0.10.6", "sha3", "substrate-bn", ] @@ -880,18 +2168,43 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" dependencies = [ - "crypto-bigint", + "crypto-bigint 0.4.9", "hmac", "zeroize", ] +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + [[package]] name = "ripemd" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" dependencies = [ - "digest", + "digest 0.10.6", ] [[package]] @@ -901,58 +2214,180 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" dependencies = [ "bytes", + "rlp-derive", "rustc-hex", ] [[package]] -name = "ruint" -version = "1.7.0" +name = "rlp-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.107", +] + +[[package]] +name = "ruint" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad3a104dc8c3867f653b0fec89c65e00b0ceb752718ad282177a7e0f33257ac" +dependencies = [ + "derive_more", + "primitive-types", + "ruint-macro", + "rustc_version", + "thiserror", +] + +[[package]] +name = "ruint-macro" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62cc5760263ea229d367e7dff3c0cbf09e4797a125bd87059a6c095804f3b2d1" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b24138615de35e32031d041a09032ef3487a616d901ca4db224e7d557efae2" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.45.0", +] + +[[package]] +name = "rustls" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" +dependencies = [ + "log", + "ring", + "sct", + "webpki", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +dependencies = [ + "base64", +] + +[[package]] +name = "rustversion" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" + +[[package]] +name = "ryu" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scale-info" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad3a104dc8c3867f653b0fec89c65e00b0ceb752718ad282177a7e0f33257ac" +checksum = "0cfdffd972d76b22f3d7f81c8be34b2296afd3a25e0a547bd9abe340a4dbbe97" dependencies = [ + "cfg-if", "derive_more", - "primitive-types", - "ruint-macro", - "rustc_version", - "thiserror", + "parity-scale-codec", + "scale-info-derive", ] [[package]] -name = "ruint-macro" -version = "1.0.2" +name = "scale-info-derive" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62cc5760263ea229d367e7dff3c0cbf09e4797a125bd87059a6c095804f3b2d1" +checksum = "61fa974aea2d63dd18a4ec3a49d59af9f34178c73a4f56d2f18205628d00681e" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.107", +] [[package]] -name = "rustc-hash" +name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] -name = "rustc-hex" -version = "2.1.0" +name = "sct" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] [[package]] -name = "rustc_version" -version = "0.4.0" +name = "sec1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" dependencies = [ - "semver", + "base16ct 0.1.1", + "der 0.6.1", + "generic-array", + "subtle", + "zeroize", ] [[package]] name = "sec1" -version = "0.3.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +checksum = "48518a2b5775ba8ca5b46596aae011caa431e6ce7e4a67ead66d92f08884220e" dependencies = [ - "base16ct", - "der", + "base16ct 0.2.0", + "der 0.7.2", "generic-array", + "pkcs8", "subtle", "zeroize", ] @@ -962,11 +2397,15 @@ name = "semver" version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" +dependencies = [ + "serde", +] [[package]] name = "ser" version = "0.1.0" dependencies = [ + "ethers-solc", "hex", "once_cell", "rand", @@ -994,7 +2433,54 @@ checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.107", +] + +[[package]] +name = "serde_json" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.6", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", ] [[package]] @@ -1005,7 +2491,7 @@ checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if", "cpufeatures", - "digest", + "digest 0.10.6", ] [[package]] @@ -1014,7 +2500,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bdf0c33fae925bdc080598b84bc15c55e7b9a4a43b3c704da051f977469691c9" dependencies = [ - "digest", + "digest 0.10.6", "keccak", ] @@ -1024,40 +2510,148 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + [[package]] name = "signature" version = "1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" dependencies = [ - "digest", + "digest 0.10.6", + "rand_core", +] + +[[package]] +name = "signature" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +dependencies = [ + "digest 0.10.6", "rand_core", ] +[[package]] +name = "siphasher" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" + +[[package]] +name = "slab" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +dependencies = [ + "autocfg", +] + [[package]] name = "smallvec" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "solang-parser" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff87dae6cdccacdbf3b19e99b271083556e808de0f59c74a01482f64fdbc61fc" +dependencies = [ + "itertools", + "lalrpop", + "lalrpop-util", + "phf", + "unicode-xid", +] + [[package]] name = "spin" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spki" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37a5be806ab6f127c3da44b7378837ebf01dadca8510a0e572460216b228bd0e" +dependencies = [ + "base64ct", + "der 0.7.2", +] + [[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", +] + [[package]] name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "strum" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 1.0.107", +] + [[package]] name = "substrate-bn" version = "0.6.0" @@ -1072,64 +2666,255 @@ dependencies = [ ] [[package]] -name = "subtle" -version = "2.4.1" +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "svm-rs" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01afefe60c02f4a2271fb15d1965c37856712cebb338330b06649d12afec42df" +dependencies = [ + "anyhow", + "cfg-if", + "clap 3.2.23", + "console 0.14.1", + "dialoguer", + "fs2", + "hex", + "home", + "indicatif", + "itertools", + "once_cell", + "rand", + "reqwest", + "semver", + "serde", + "serde_json", + "sha2 0.9.9", + "tempfile", + "thiserror", + "tokio", + "tracing", + "url", + "zip", +] + +[[package]] +name = "svm-rs-builds" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e69c19996b709c881de264a6ce64609ff305ef0bf59fc45243ac5a67291afd1" +dependencies = [ + "build_const", + "hex", + "semver", + "serde_json", + "svm-rs", +] + +[[package]] +name = "syn" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall 0.3.5", + "rustix", + "windows-sys 0.45.0", +] + +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "terminal_size" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "textwrap" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" + +[[package]] +name = "thiserror" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.107", +] + +[[package]] +name = "time" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" +dependencies = [ + "serde", + "time-core", +] + +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + +[[package]] +name = "tiny-keccak" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] [[package]] -name = "syn" -version = "1.0.107" +name = "tinyvec" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "tinyvec_macros", ] [[package]] -name = "tap" -version = "1.0.1" +name = "tinyvec_macros" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] -name = "termcolor" -version = "1.2.0" +name = "tokio" +version = "1.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64" dependencies = [ - "winapi-util", + "autocfg", + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.45.0", ] [[package]] -name = "textwrap" -version = "0.11.0" +name = "tokio-macros" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" dependencies = [ - "unicode-width", + "proc-macro2", + "quote", + "syn 1.0.107", ] [[package]] -name = "thiserror" -version = "1.0.38" +name = "tokio-rustls" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" dependencies = [ - "thiserror-impl", + "rustls", + "tokio", + "webpki", ] [[package]] -name = "thiserror-impl" -version = "1.0.38" +name = "tokio-util" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" dependencies = [ - "proc-macro2", - "quote", - "syn", + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", ] [[package]] @@ -1149,6 +2934,50 @@ dependencies = [ "toml_datetime", ] +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.107", +] + +[[package]] +name = "tracing-core" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" + [[package]] name = "typenum" version = "1.16.0" @@ -1167,18 +2996,56 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + [[package]] name = "unicode-ident" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + [[package]] name = "unicode-width" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "url" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + [[package]] name = "uuid" version = "1.2.2" @@ -1200,12 +3067,127 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "walkdir" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 1.0.107", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.107", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" + +[[package]] +name = "web-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" +dependencies = [ + "webpki", +] + [[package]] name = "which" version = "3.1.1" @@ -1246,6 +3228,162 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.0", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] + [[package]] name = "wyz" version = "0.5.1" @@ -1255,6 +3393,12 @@ dependencies = [ "tap", ] +[[package]] +name = "yansi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" + [[package]] name = "z3" version = "0.11.2" @@ -1281,3 +3425,53 @@ name = "zeroize" version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" + +[[package]] +name = "zip" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0445d0fbc924bb93539b4316c11afb121ea39296f99a3c4c9edad09e3658cdef" +dependencies = [ + "aes", + "byteorder", + "bzip2", + "constant_time_eq", + "crc32fast", + "crossbeam-utils", + "flate2", + "hmac", + "pbkdf2", + "sha1", + "time", + "zstd", +] + +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.8+zstd.1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c" +dependencies = [ + "cc", + "libc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml index d7291b0..9b114af 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ revm = { version = "2.3", default-features = false, features = [ "memory_limit", "optional_eip3607" ] } - +ethers-solc = { git = "https://github.com/gakonst/ethers-rs", features = ["full"]} [target.'cfg(any(target_os = "windows", target_os = "macos"))'.dependencies] z3 = {version = "0.11.2", features = ["static-link-z3"]} diff --git a/src/lib.rs b/src/lib.rs index 55da6c5..1aafc2e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,7 +12,6 @@ pub mod traits; pub mod storage; pub mod parser; - use instruction::*; use smt::*; use stack::*; @@ -35,5 +34,5 @@ mod test { */ - const counter_with_storage_mapping: &str = r#"608060405234801561001057600080fd5b5060056000806001815260200190815260200160002081905550610197806100396000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063846719e01461003b578063d78233d61461006b575b600080fd5b6100556004803603810190610050919061010a565b61009b565b6040516100629190610146565b60405180910390f35b6100856004803603810190610080919061010a565b6100b7565b6040516100929190610146565b60405180910390f35b6000806000838152602001908152602001600020549050919050565b60006020528060005260406000206000915090505481565b600080fd5b6000819050919050565b6100e7816100d4565b81146100f257600080fd5b50565b600081359050610104816100de565b92915050565b6000602082840312156101205761011f6100cf565b5b600061012e848285016100f5565b91505092915050565b610140816100d4565b82525050565b600060208201905061015b6000830184610137565b9291505056fea2646970667358fe122066b287fef10118cba238fe38953bfefe938afefefefefe94fefe3682fefefefe64736f6c63430008110033"#; + const COUNTER_WITH_STORAGE_MAPPING: &str = r#"608060405234801561001057600080fd5b5060056000806001815260200190815260200160002081905550610197806100396000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063846719e01461003b578063d78233d61461006b575b600080fd5b6100556004803603810190610050919061010a565b61009b565b6040516100629190610146565b60405180910390f35b6100856004803603810190610080919061010a565b6100b7565b6040516100929190610146565b60405180910390f35b6000806000838152602001908152602001600020549050919050565b60006020528060005260406000206000915090505481565b600080fd5b6000819050919050565b6100e7816100d4565b81146100f257600080fd5b50565b600081359050610104816100de565b92915050565b6000602082840312156101205761011f6100cf565b5b600061012e848285016100f5565b91505092915050565b610140816100d4565b82525050565b600060208201905061015b6000830184610137565b9291505056fea2646970667358fe122066b287fef10118cba238fe38953bfefe938afefefefefe94fefe3682fefefefe64736f6c63430008110033"#; } \ No newline at end of file diff --git a/src/parser.rs b/src/parser.rs index ab12aad..9636ee3 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -34,14 +34,29 @@ impl<'a> Parser<'a> { +} + +fn is_dup(b: u8) -> bool { + 0x80 <= b && 0x8f >= b +} + +fn is_swap(b: u8) -> bool { + 0x90 <= b && 0x9f >= b } fn is_push(b: u8) -> bool { 0x60 <= b && 0x7f >= b } +fn dup_size(b: u8) -> u8 { + if b >= 0x80 { + b - 0x80 + 1 + } else { + 0 + } +} fn push_size(b: u8) -> u8 { - if b > 0x60 { + if b >= 0x60 { b - 0x60 + 1 } else { 0 @@ -58,7 +73,20 @@ impl Instruction { // Has to handle when it's a push or dup, otherwise easy 1-1 conversion pub fn from_slice(bytes: &[u8]) -> Vec { - todo!() + let instruction_byte = *bytes.first().unwrap(); + let mut instrs = vec![]; + if is_push(instruction_byte) { + let push_size = push_size(instruction_byte); + + } else if is_dup(instruction_byte) { + + } else if is_swap(instruction_byte) { + + } else { + + } + + instrs } } impl From for Instruction { diff --git a/src/storage.rs b/src/storage.rs index d3bf7cd..44ce68e 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -77,7 +77,12 @@ fn test_basic_lookup_works_in_acc_storage() { fn test_basic_lookup_global_storage() { let addr = Address::new_const("Address1"); let addr2 = Address::new_const("Address2"); - let mut global = GlobalStorage::init_with_addrs(vec![addr, addr2]); + let mut global = GlobalStorage::init_with_addrs(vec![addr, addr2.clone()]); + let mut addr_2_storage = global.get(&addr2); + addr_2_storage.sstore(bvi(3), StorageValue::BV(bvc("storage_val_at_idx_3"))); + global.inner.insert(addr2.clone(), addr_2_storage); + + assert_eq!(global.get(&addr2).sload(&bvi(3)), StorageValue::BV(bvc("storage_val_at_idx_3"))); } \ No newline at end of file diff --git a/test-contracts/.gitignore b/test-contracts/.gitignore new file mode 100644 index 0000000..85198aa --- /dev/null +++ b/test-contracts/.gitignore @@ -0,0 +1,14 @@ +# Compiler files +cache/ +out/ + +# Ignores development broadcast logs +!/broadcast +/broadcast/*/31337/ +/broadcast/**/dry-run/ + +# Docs +docs/ + +# Dotenv file +.env diff --git a/test-contracts/foundry.toml b/test-contracts/foundry.toml new file mode 100644 index 0000000..4ff40c4 --- /dev/null +++ b/test-contracts/foundry.toml @@ -0,0 +1,6 @@ +[profile.default] +src = "src" +out = "out" +libs = ["lib"] + +# See more config options https://github.com/foundry-rs/foundry/tree/master/config \ No newline at end of file diff --git a/test-contracts/lib/forge-std b/test-contracts/lib/forge-std new file mode 160000 index 0000000..fc560fa --- /dev/null +++ b/test-contracts/lib/forge-std @@ -0,0 +1 @@ +Subproject commit fc560fa34fa12a335a50c35d92e55a6628ca467c diff --git a/test-contracts/script/Counter.s.sol b/test-contracts/script/Counter.s.sol new file mode 100644 index 0000000..0e546ab --- /dev/null +++ b/test-contracts/script/Counter.s.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import "forge-std/Script.sol"; + +contract CounterScript is Script { + function setUp() public {} + + function run() public { + vm.broadcast(); + } +} diff --git a/test-contracts/src/Counter.sol b/test-contracts/src/Counter.sol new file mode 100644 index 0000000..aded799 --- /dev/null +++ b/test-contracts/src/Counter.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +contract Counter { + uint256 public number; + + function setNumber(uint256 newNumber) public { + number = newNumber; + } + + function increment() public { + number++; + } +} diff --git a/test-contracts/src/Storage.sol b/test-contracts/src/Storage.sol new file mode 100644 index 0000000..debba3c --- /dev/null +++ b/test-contracts/src/Storage.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: AGPL-3.0 +// From https://github.com/a16z/halmos/blob/main/tests/src/Storage.sol +pragma solidity >=0.8.0 <0.9.0; + +contract Storage { + uint public num; + + mapping (uint => uint) public map1; + mapping (uint => mapping (uint => uint)) public map2; + mapping (uint => mapping (uint => mapping (uint => uint))) public map3; + + uint[] public arr1; + uint[][] public arr2; + + mapping (uint => uint[]) public map1Arr1; + + constructor () { } + + function setMap1(uint k, uint v) public { + map1[k] = v; + } + + function setMap2(uint k1, uint k2, uint v) public { + map2[k1][k2] = v; + } + + function setMap3(uint k1, uint k2, uint k3, uint v) public { + map3[k1][k2][k3] = v; + } + + function addArr1(uint v) public { + arr1.push(v); + } + + function addArr2(uint i, uint v) public { + arr2[i].push(v); + } + + function addMap1Arr1(uint k, uint v) public { + map1Arr1[k].push(v); + } +} diff --git a/test-contracts/test/Counter.t.sol b/test-contracts/test/Counter.t.sol new file mode 100644 index 0000000..30235e8 --- /dev/null +++ b/test-contracts/test/Counter.t.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import "forge-std/Test.sol"; +import "../src/Counter.sol"; + +contract CounterTest is Test { + Counter public counter; + + function setUp() public { + counter = new Counter(); + counter.setNumber(0); + } + + function testIncrement() public { + counter.increment(); + assertEq(counter.number(), 1); + } + + function testSetNumber(uint256 x) public { + counter.setNumber(x); + assertEq(counter.number(), x); + } +} From 33de0b400ddc2fafad3e20f25f40c6db750a9c75 Mon Sep 17 00:00:00 2001 From: tannr Date: Thu, 18 May 2023 23:16:47 -0400 Subject: [PATCH 05/28] add more parsing and convenience methods; storage & tests with concrete index --- .gitignore | 4 +- Cargo.lock | 7 ++ Cargo.toml | 1 + src/instruction/mod.rs | 6 + src/lib.rs | 3 +- src/machine.rs | 2 +- src/parser.rs | 181 +++++++++++++++++++++++++++--- src/storage.rs | 11 +- test-contracts/test/Storage.t.sol | 45 ++++++++ 9 files changed, 239 insertions(+), 21 deletions(-) create mode 100644 test-contracts/test/Storage.t.sol diff --git a/.gitignore b/.gitignore index 145fd3e..5d0be3f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ /target .z3-trace *.txt.log* -.idea/* \ No newline at end of file +.idea/* +*.hex +*.evm \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 182976c..1f20c70 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1779,6 +1779,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "paste" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" + [[package]] name = "path-slash" version = "0.2.1" @@ -2408,6 +2414,7 @@ dependencies = [ "ethers-solc", "hex", "once_cell", + "paste", "rand", "revm", "ruint", diff --git a/Cargo.toml b/Cargo.toml index 9b114af..26fd6ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ revm = { version = "2.3", default-features = false, features = [ "optional_eip3607" ] } ethers-solc = { git = "https://github.com/gakonst/ethers-rs", features = ["full"]} +paste = "1.0.12" [target.'cfg(any(target_os = "windows", target_os = "macos"))'.dependencies] z3 = {version = "0.11.2", features = ["static-link-z3"]} diff --git a/src/instruction/mod.rs b/src/instruction/mod.rs index 56b56be..f585b25 100644 --- a/src/instruction/mod.rs +++ b/src/instruction/mod.rs @@ -1435,6 +1435,12 @@ pub fn dup14() -> Instruction { pub fn dup15() -> Instruction { Instruction::Dup15 } +pub fn dup16() -> Instruction { + Instruction::Dup16 +} +// pub fn push(size: usize, val: BitVec<>) -> Instruction { +// Instruction::Push5(BitVec::default()) +// } pub fn push1(v: BitVec<1>) -> Instruction { Instruction::Push1(v) diff --git a/src/lib.rs b/src/lib.rs index 1aafc2e..be27804 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,7 +11,7 @@ pub mod state; pub mod traits; pub mod storage; pub mod parser; - +use paste::{expr, item, paste}; use instruction::*; use smt::*; use stack::*; @@ -27,7 +27,6 @@ pub fn bvc(val: impl AsRef) -> BitVec<32> { BitVec::new_const(val) } - #[cfg(test)] mod test { /* diff --git a/src/machine.rs b/src/machine.rs index 2bd4597..f85fdb7 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -298,7 +298,7 @@ fn machine_returns_one_exec_for_non_branching_pgm() { add(), push32(bvi(7)), Instruction::JumpI, - Instruction::Push(bvi(100)), + Instruction::Push32(bvi(100)), push32(bvi(50)), ]; diff --git a/src/parser.rs b/src/parser.rs index 9636ee3..cc4e6ed 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,4 +1,4 @@ -use crate::instruction::Instruction; +use crate::{instruction::*, smt::BitVec, bvi}; use revm::{ opcode::OpCode, OPCODE_JUMPMAP }; @@ -20,20 +20,32 @@ impl<'a> Parser<'a> { let mut pgm = vec![]; for b in bytes { - - let inst = Instruction::from(*b); - - pgm.push(inst); - + if is_push(*b) { + let (inst, new_bytes) = parse_push(bytes); + } else if is_dup(*b) { + todo!() + } else if is_swap(*b) { + todo!() + } else { + let inst = Instruction::from(*b); + pgm.push(inst); + } + } pgm } - +} +// Returns instruction + any left over bytes in the slice after extracting the opcode & opcode args +fn parse_push(bytes: &[u8]) -> (Instruction, &[u8]) { + let instruction_byte = *bytes.first().unwrap(); + let push_size = push_size(instruction_byte); + let push_val = &bytes[1..push_size as usize]; + (push_op(push_size, push_val), &bytes[(push_size + 1) as usize..bytes.len()]) } fn is_dup(b: u8) -> bool { @@ -55,40 +67,139 @@ fn dup_size(b: u8) -> u8 { 0 } } + +fn swap_size(b: u8) -> u8 { + if b >= 0x90 { + b - 0x90 + 1 + } else { + 0 + } +} fn push_size(b: u8) -> u8 { if b >= 0x60 { b - 0x60 + 1 } else { 0 } +} + +fn push_op(sz: u8, val: &[u8]) -> Instruction { + let mut buf:[u8; 8] = [0u8; 8]; + buf.copy_from_slice(val); + let val = u64::from_be_bytes(buf); + match sz { + 1 => push1(BitVec::<1>::new_literal(val)), + 3 => push2(BitVec::<2>::new_literal(val)), + 2 => push3(BitVec::<3>::new_literal(val)), + 4 => push4(BitVec::<4>::new_literal(val)), + 5 => push5(BitVec::<5>::new_literal(val)), + 6 => push6(BitVec::<6>::new_literal(val)), + 7 => push7(BitVec::<7>::new_literal(val)), + 8 => push8(BitVec::<8>::new_literal(val)), + 9 => push9(BitVec::<9>::new_literal(val)), + 10 => push10(BitVec::<10>::new_literal(val)), + 11 => push11(BitVec::<11>::new_literal(val)), + 12 => push12(BitVec::<12>::new_literal(val)), + 13 => push13(BitVec::<13>::new_literal(val)), + 14 => push14(BitVec::<14>::new_literal(val)), + 15 => push15(BitVec::<15>::new_literal(val)), + 16 => push16(BitVec::<16>::new_literal(val)), + 17 => push17(BitVec::<17>::new_literal(val)), + 18 => push18(BitVec::<18>::new_literal(val)), + 19 => push19(BitVec::<19>::new_literal(val)), + 20 => push20(BitVec::<20>::new_literal(val)), + 21 => push21(BitVec::<21>::new_literal(val)), + 21 => push22(BitVec::<22>::new_literal(val)), + 23 => push23(BitVec::<23>::new_literal(val)), + 24 => push24(BitVec::<24>::new_literal(val)), + 25 => push25(BitVec::<25>::new_literal(val)), + 26 => push26(BitVec::<26>::new_literal(val)), + 27 => push27(BitVec::<27>::new_literal(val)), + 28 => push28(BitVec::<28>::new_literal(val)), + 29 => push29(BitVec::<29>::new_literal(val)), + 30 => push30(BitVec::<30>::new_literal(val)), + 31 => push31(BitVec::<31>::new_literal(val)), + 32 => push32(BitVec::<32>::new_literal(val)), + _ => todo!() + } +} + +fn swap_op(sz: u8) -> Instruction { + match sz { + 1 => Instruction::Swap1, + 2 => Instruction::Swap2, + 3 => Instruction::Swap3, + 4 => Instruction::Swap4, + 5 => Instruction::Swap5, + 6 => Instruction::Swap6, + 7 => Instruction::Swap7, + 8 => Instruction::Swap8, + 9 => Instruction::Swap9, + 10 => Instruction::Swap10, + 11 => Instruction::Swap11, + 12 => Instruction::Swap12, + 13 => Instruction::Swap13, + 14 => Instruction::Swap14, + 15 => Instruction::Swap15, + 16 => Instruction::Swap16, + _ => todo!() + } +} + +fn dup_op(sz: u8) -> Instruction { + match sz { + 1 => dup1(), + 2 => dup2(), + 3 => dup3(), + 4 => dup4(), + 5 => dup5(), + 6 => dup6(), + 7 => dup7(), + 8 => dup8(), + 9 => dup9(), + 10 => dup10(), + 11 => dup11(), + 12 => dup12(), + 13 => dup13(), + 14 => dup14(), + 15 => dup15(), + 16 => dup16(), + _ => todo!() + } } impl Instruction { pub fn from_byte(value: u8) -> Self { value.into() - } // Has to handle when it's a push or dup, otherwise easy 1-1 conversion - pub fn from_slice(bytes: &[u8]) -> Vec { + pub fn from_slice(bytes: &[u8]) -> Instruction { let instruction_byte = *bytes.first().unwrap(); - let mut instrs = vec![]; + if is_push(instruction_byte) { let push_size = push_size(instruction_byte); - + let push_val = &bytes[1..push_size as usize]; + push_op(push_size, push_val) } else if is_dup(instruction_byte) { - + let dup_size = dup_size(instruction_byte); + dup_op(dup_size) } else if is_swap(instruction_byte) { - + let swap_size = swap_size(instruction_byte); + swap_op(swap_size) } else { - + Instruction::from(instruction_byte) } - - instrs + } + + } + + + impl From for Instruction { fn from(value: u8) -> Self { @@ -252,4 +363,42 @@ fn is_push_works() { for b in (0x80..0xff_u8) { assert!(!is_push(b)); } +} + +/** + * pragma solidity ^0.8.3; + +contract Counter { + uint public count; + + // Function to get the current count + function get() public view returns (uint) { + return count; + } + + // Function to increment count by 1 + function inc() public { + count += 1; + } + + // Function to decrement count by 1 + function dec() public { + count -= 1; + } +} + */ +#[test] +fn can_parse_simple_pgm() { + const counter_sol_code: &'static str = "0x604260005260206000F3"; + + let expected = vec![ + Instruction::Push1(bvi(0x42)), + Instruction::Push1(bvi(0)), + Instruction::MStore, + Instruction::Push1(bvi(0x42)), + Instruction::Push1(bvi(0)), + Instruction::Return + ]; + + } \ No newline at end of file diff --git a/src/storage.rs b/src/storage.rs index 44ce68e..c6c23e3 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -85,4 +85,13 @@ fn test_basic_lookup_global_storage() { assert_eq!(global.get(&addr2).sload(&bvi(3)), StorageValue::BV(bvc("storage_val_at_idx_3"))); -} \ No newline at end of file +} + + + + // Global Storage: + // HashMap(Address -> AccountStorage) + // AccountStorage(BitVec<32> -> StorageValue) + // StorageValue(ConcreteBytes<32> OR SymbolicBytes<32>) + // + \ No newline at end of file diff --git a/test-contracts/test/Storage.t.sol b/test-contracts/test/Storage.t.sol new file mode 100644 index 0000000..2be3b21 --- /dev/null +++ b/test-contracts/test/Storage.t.sol @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: AGPL-3.0 +// From https://github.com/a16z/halmos/blob/main/tests/test/Storage.t.sol +pragma solidity >=0.8.0 <0.9.0; + + +import "forge-std/Test.sol"; +import "../src/Storage.sol"; + +contract StorageTest is Storage { + function testSetMap1(uint k, uint v) public { + setMap1(k, v); + assert(map1[k] == v); + } + + function testSetMap2(uint k1, uint k2, uint v) public { + setMap2(k1, k2, v); + assert(map2[k1][k2] == v); + } + + function testSetMap3(uint k1, uint k2, uint k3, uint v) public { + setMap3(k1, k2, k3, v); + assert(map3[k1][k2][k3] == v); + } + + function testAddArr1(uint v) public { + uint size = arr1.length; + addArr1(v); + assert(arr1.length == size + 1); + assert(arr1[size] == v); + } + + function testAddArr2(uint i, uint v) public { + uint size = arr2[i].length; + addArr2(i, v); + assert(arr2[i].length == size + 1); + assert(arr2[i][size] == v); + } + + function testAddMap1Arr1(uint k, uint v) public { + uint size = map1Arr1[k].length; + addMap1Arr1(k, v); + assert(map1Arr1[k].length == size + 1); + assert(map1Arr1[k][size] == v); + } +} \ No newline at end of file From e3c8b0ecf5144a25916f138013f4cb29c263c6e4 Mon Sep 17 00:00:00 2001 From: tannr Date: Fri, 19 May 2023 17:11:51 -0400 Subject: [PATCH 06/28] Fix parser adding instruction byte to pushed byte values --- src/instruction/mod.rs | 2 +- src/parser.rs | 80 +++++++++++++++++++++++++++++++----------- 2 files changed, 60 insertions(+), 22 deletions(-) diff --git a/src/instruction/mod.rs b/src/instruction/mod.rs index f585b25..77b7d6f 100644 --- a/src/instruction/mod.rs +++ b/src/instruction/mod.rs @@ -25,7 +25,7 @@ pub fn random_bv_arg() -> BitVec<32> { BitVec::new_literal(rand_num) } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum Instruction { Stop, Add, diff --git a/src/parser.rs b/src/parser.rs index cc4e6ed..49a4c57 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -2,6 +2,7 @@ use crate::{instruction::*, smt::BitVec, bvi}; use revm::{ opcode::OpCode, OPCODE_JUMPMAP }; +use hex::{decode}; pub struct Parser<'a> { pgm: &'a str } @@ -14,22 +15,37 @@ impl<'a> Parser<'a> { } } - pub fn mnemonic(&self) -> Vec { - let bytes = self.pgm.as_bytes(); + pub fn parse(&self) -> Vec { + let bytes = decode(self.pgm).unwrap(); let mut opcodes: Vec = vec![]; - + let mut pgm = vec![]; - for b in bytes { - if is_push(*b) { - let (inst, new_bytes) = parse_push(bytes); - } else if is_dup(*b) { - todo!() - } else if is_swap(*b) { - todo!() + let mut skip_size = 0; + let mut idx = 0_usize; + for b in &bytes { + + let b = *b; + if skip_size > 0 { + skip_size -= 1; + continue; + idx += 1; + } + if is_push(b) { + // push1 0xab push4 0xabcd + let sz = push_size(b); + let (inst, push_size, new_bytes) = parse_push(&bytes[idx as usize..]); + skip_size = push_size; + idx += skip_size as usize; + pgm.push(inst); + } else if is_dup(b) { + pgm.push(parse_dup(b)) + } else if is_swap(b) { + pgm.push(parse_swap(b)); } else { - let inst = Instruction::from(*b); + let inst = Instruction::from(b); pgm.push(inst); } + idx += 1; } pgm @@ -40,12 +56,21 @@ impl<'a> Parser<'a> { } // Returns instruction + any left over bytes in the slice after extracting the opcode & opcode args -fn parse_push(bytes: &[u8]) -> (Instruction, &[u8]) { +fn parse_push(bytes: &[u8]) -> (Instruction, u8, &[u8]) { let instruction_byte = *bytes.first().unwrap(); let push_size = push_size(instruction_byte); - let push_val = &bytes[1..push_size as usize]; - (push_op(push_size, push_val), &bytes[(push_size + 1) as usize..bytes.len()]) + + let push_val = &bytes[1..(push_size + 1) as usize]; + (push_op(push_size, push_val),push_size, &bytes[(push_size) as usize..bytes.len()]) +} + +fn parse_dup(byte: u8) -> Instruction { + dup_op(dup_size(byte)) +} + +fn parse_swap(byte: u8) -> Instruction { + swap_op(swap_size(byte)) } fn is_dup(b: u8) -> bool { @@ -85,9 +110,16 @@ fn push_size(b: u8) -> u8 { fn push_op(sz: u8, val: &[u8]) -> Instruction { - let mut buf:[u8; 8] = [0u8; 8]; - buf.copy_from_slice(val); - let val = u64::from_be_bytes(buf); + let mut zero_len = 8 - val.len(); + let mut buf = vec![]; + buf.extend_from_slice(val); + for _ in (0..zero_len) { + buf.push(0); + } + let mut sliced = [0u8; 8]; + sliced.copy_from_slice(&buf); + + let val = u64::from_le_bytes(sliced); match sz { 1 => push1(BitVec::<1>::new_literal(val)), 3 => push2(BitVec::<2>::new_literal(val)), @@ -121,7 +153,9 @@ fn push_op(sz: u8, val: &[u8]) -> Instruction { 30 => push30(BitVec::<30>::new_literal(val)), 31 => push31(BitVec::<31>::new_literal(val)), 32 => push32(BitVec::<32>::new_literal(val)), - _ => todo!() + _ => { + todo!() + } } } @@ -389,16 +423,20 @@ contract Counter { */ #[test] fn can_parse_simple_pgm() { - const counter_sol_code: &'static str = "0x604260005260206000F3"; - + const counter_sol_code: &'static str = "604260005260206000F3"; + //const counter_sol_code: &'static str = "60426000F3"; + let pgm = Parser::with_pgm(counter_sol_code).parse(); + let expected = vec![ Instruction::Push1(bvi(0x42)), Instruction::Push1(bvi(0)), Instruction::MStore, - Instruction::Push1(bvi(0x42)), + Instruction::Push1(bvi(0x20)), Instruction::Push1(bvi(0)), Instruction::Return ]; + assert_eq!(expected, pgm); + } \ No newline at end of file From 1402750dcc3d4355a6268a9449b6d45b5a9562ae Mon Sep 17 00:00:00 2001 From: tannr Date: Sat, 20 May 2023 22:48:42 -0400 Subject: [PATCH 07/28] add storage change records; fix parser test; add storage to machine record --- src/instruction/mod.rs | 87 +++++++++++++++++++++++++--- src/lib.rs | 10 +++- src/parser.rs | 82 +++++++++++++++++++++----- src/record.rs | 14 +++++ src/smt/bitvec/z3.rs | 1 + src/state/env.rs | 9 +-- src/state/evm.rs | 2 + src/storage.rs | 78 ++++++++++++++++++++++++- test-contracts/src/StorageSimple.sol | 10 ++++ 9 files changed, 264 insertions(+), 29 deletions(-) create mode 100644 test-contracts/src/StorageSimple.sol diff --git a/src/instruction/mod.rs b/src/instruction/mod.rs index 77b7d6f..5bcbf29 100644 --- a/src/instruction/mod.rs +++ b/src/instruction/mod.rs @@ -9,6 +9,7 @@ use crate::state::env::*; use crate::state::evm::EvmState; use crate::traits::*; use crate::{ + random_bv_arg, bvi, machine::Evm, memory::Memory, @@ -17,13 +18,8 @@ use crate::{ }; use super::smt::*; -use rand::Rng; -pub fn random_bv_arg() -> BitVec<32> { - let mut rng = rand::thread_rng(); - let rand_num: u64 = rng.gen(); - BitVec::new_literal(rand_num) -} + #[derive(Clone, Debug, PartialEq, Eq)] pub enum Instruction { @@ -183,6 +179,7 @@ fn exec_dup_nth(mach: &EvmState, n: usize) -> MachineRecord<32> { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -212,6 +209,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (pc, pc + 1), constraints: None, halt: false, + storage: None, } } Instruction::Mul => { @@ -225,6 +223,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::Sub => { @@ -238,6 +237,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::Div => { @@ -251,6 +251,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::SDiv => { @@ -264,6 +265,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::SMod => { @@ -277,6 +279,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::Mod => { @@ -290,6 +293,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::AddMod => { @@ -303,6 +307,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::MulMod => { @@ -316,6 +321,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::Exp => { @@ -342,6 +348,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::Lt => { @@ -361,6 +368,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::Gt => { @@ -380,6 +388,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::Slt => { @@ -399,6 +408,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::Sgt => { @@ -418,6 +428,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::Eq => { @@ -437,6 +448,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::And => { @@ -452,6 +464,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::Or => { @@ -467,6 +480,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::Xor => { @@ -482,6 +496,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::Not => { @@ -498,6 +513,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::Byte => todo!(), @@ -515,6 +531,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::Shr => { @@ -531,6 +548,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::Sha3 => todo!(), @@ -539,7 +557,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { let stack = mach.stack(); let addr = stack.peek().unwrap(); let bal = balance() - .apply(&[addr.as_ref(), random_bv_arg().as_ref()]) + .apply(&[addr.as_ref(), random_bv_arg::<32>().as_ref()]) .as_bv() .unwrap(); let stack_diff = StackChange::with_ops(vec![pop(), push(bal.into())]); @@ -550,6 +568,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::Origin => { @@ -563,6 +582,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::Caller => { @@ -576,6 +596,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::CallValue => { @@ -589,6 +610,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::CallDataLoad => { @@ -603,6 +625,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::CallDataSize => { @@ -616,6 +639,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::CallDataCopy => todo!(), @@ -632,6 +656,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::ExtCodeSize => { @@ -646,6 +671,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::ExtCodeCopy => todo!(), @@ -663,6 +689,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::Coinbase => { @@ -676,6 +703,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::Timestamp => { @@ -689,6 +717,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::Number => todo!(), @@ -703,6 +732,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::GasLimit => { @@ -716,6 +746,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::ChainId => { @@ -729,6 +760,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, + storage: None, } } Instruction::SelfBalance => todo!(), @@ -746,6 +778,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { mem: Default::default(), constraints: None, halt: false, + storage: None, } } Instruction::MLoad => { @@ -763,6 +796,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { mem: Some(mem_change), pc: (mach.pc(), mach.pc() + 1), halt: false, + storage: None, constraints: None, } } @@ -787,6 +821,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { stack: Some(stack_change), constraints: None, halt: false, + storage: None, pc: (mach.pc(), mach.pc() + 1), } } @@ -816,6 +851,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { stack: Some(stack_change), constraints: None, halt: false, + storage: None, pc: (mach.pc(), mach.pc() + 1), } } @@ -843,6 +879,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { constraints: Some(cond), mem: Default::default(), halt: false, + storage: None, } } Instruction::Pc => { @@ -858,6 +895,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { constraints: None, mem: Default::default(), halt: false, + storage: None, } } Instruction::MSize => { @@ -872,6 +910,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { mem: Default::default(), pc: (mach.pc(), mach.pc() + 1), halt: false, + storage: None, constraints: None, } } @@ -887,6 +926,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -900,6 +940,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -913,6 +954,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -926,6 +968,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -939,6 +982,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -952,6 +996,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -965,6 +1010,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -978,6 +1024,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -991,6 +1038,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1004,6 +1052,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1017,6 +1066,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1030,6 +1080,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1043,6 +1094,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1056,6 +1108,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1069,6 +1122,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1082,6 +1136,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1095,6 +1150,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1108,6 +1164,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1121,6 +1178,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1134,6 +1192,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1147,6 +1206,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1160,6 +1220,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1173,6 +1234,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1186,6 +1248,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1199,6 +1262,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1212,6 +1276,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1225,6 +1290,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1238,6 +1304,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1251,6 +1318,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1264,6 +1332,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1277,6 +1346,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1288,6 +1358,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1352,6 +1423,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (pc, pc + 1), constraints: None, halt: false, + storage: None, } } Instruction::IsZero => { @@ -1369,6 +1441,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } diff --git a/src/lib.rs b/src/lib.rs index be27804..feee316 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,6 +19,8 @@ use z3_ext::{ ast::{Ast, Bool, Int, BV}, AstKind, Config, Context, Model, SatResult, Solver, }; +use rand::Rng; + pub fn bvi(val: impl Into) -> BitVec { BitVec::new_literal(val.into() as u64) @@ -26,6 +28,11 @@ pub fn bvi(val: impl Into) -> BitVec { pub fn bvc(val: impl AsRef) -> BitVec<32> { BitVec::new_const(val) } +pub fn random_bv_arg() -> BitVec { + let mut rng = rand::thread_rng(); + let rand_num: u64 = rng.gen(); + BitVec::new_literal(rand_num) +} #[cfg(test)] mod test { @@ -33,5 +40,6 @@ mod test { */ - const COUNTER_WITH_STORAGE_MAPPING: &str = r#"608060405234801561001057600080fd5b5060056000806001815260200190815260200160002081905550610197806100396000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063846719e01461003b578063d78233d61461006b575b600080fd5b6100556004803603810190610050919061010a565b61009b565b6040516100629190610146565b60405180910390f35b6100856004803603810190610080919061010a565b6100b7565b6040516100929190610146565b60405180910390f35b6000806000838152602001908152602001600020549050919050565b60006020528060005260406000206000915090505481565b600080fd5b6000819050919050565b6100e7816100d4565b81146100f257600080fd5b50565b600081359050610104816100de565b92915050565b6000602082840312156101205761011f6100cf565b5b600061012e848285016100f5565b91505092915050565b610140816100d4565b82525050565b600060208201905061015b6000830184610137565b9291505056fea2646970667358fe122066b287fef10118cba238fe38953bfefe938afefefefefe94fefe3682fefefefe64736f6c63430008110033"#; + pub const SIMPLE_COUNTER: &str = r"6080604052348015600f57600080fd5b5060043610603c5760003560e01c80633fb5c1cb1460415780638381f58a146053578063d09de08a14606d575b600080fd5b6051604c3660046083565b600055565b005b605b60005481565b60405190815260200160405180910390f35b6051600080549080607c83609b565b9190505550565b600060208284031215609457600080fd5b5035919050565b60006001820160ba57634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220f0cfb2159c518c3da0ad864362bad5dc0715514a9ab679237253d506773a0a1b64736f6c63430008130033"; + pub const COUNTER_WITH_STORAGE_MAPPING: &str = r#"608060405234801561001057600080fd5b5060056000806001815260200190815260200160002081905550610197806100396000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063846719e01461003b578063d78233d61461006b575b600080fd5b6100556004803603810190610050919061010a565b61009b565b6040516100629190610146565b60405180910390f35b6100856004803603810190610080919061010a565b6100b7565b6040516100929190610146565b60405180910390f35b6000806000838152602001908152602001600020549050919050565b60006020528060005260406000206000915090505481565b600080fd5b6000819050919050565b6100e7816100d4565b81146100f257600080fd5b50565b600081359050610104816100de565b92915050565b6000602082840312156101205761011f6100cf565b5b600061012e848285016100f5565b91505092915050565b610140816100d4565b82525050565b600060208201905061015b6000830184610137565b9291505056fea2646970667358fe122066b287fef10118cba238fe38953bfefe938afefefefefe94fefe3682fefefefe64736f6c63430008110033"#; } \ No newline at end of file diff --git a/src/parser.rs b/src/parser.rs index 49a4c57..37583b9 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -60,8 +60,9 @@ fn parse_push(bytes: &[u8]) -> (Instruction, u8, &[u8]) { let instruction_byte = *bytes.first().unwrap(); let push_size = push_size(instruction_byte); - + eprintln!("PUSH SIZE IS {}", push_size); let push_val = &bytes[1..(push_size + 1) as usize]; + eprintln!("PUSH VAL IS {:#?}", push_val); (push_op(push_size, push_val),push_size, &bytes[(push_size) as usize..bytes.len()]) } @@ -112,18 +113,19 @@ fn push_size(b: u8) -> u8 { fn push_op(sz: u8, val: &[u8]) -> Instruction { let mut zero_len = 8 - val.len(); let mut buf = vec![]; - buf.extend_from_slice(val); for _ in (0..zero_len) { buf.push(0); } + buf.extend_from_slice(val); + let mut sliced = [0u8; 8]; sliced.copy_from_slice(&buf); + let val = u64::from_be_bytes(sliced); - let val = u64::from_le_bytes(sliced); match sz { 1 => push1(BitVec::<1>::new_literal(val)), - 3 => push2(BitVec::<2>::new_literal(val)), - 2 => push3(BitVec::<3>::new_literal(val)), + 2 => push2(BitVec::<2>::new_literal(val)), + 3 => push3(BitVec::<3>::new_literal(val)), 4 => push4(BitVec::<4>::new_literal(val)), 5 => push5(BitVec::<5>::new_literal(val)), 6 => push6(BitVec::<6>::new_literal(val)), @@ -255,13 +257,14 @@ impl From for Instruction { 0x12 => Instruction::Slt, 0x13 => Instruction::Sgt, 0x14 => Instruction::Eq, - 0x15 => Instruction::And, - 0x16 => Instruction::Or, - 0x17 => Instruction::Xor, - 0x18 => Instruction::Not, - 0x19 => Instruction::Byte, - 0x1a => Instruction::Shl, - 0x1b => Instruction::Shr, + 0x15 => Instruction::IsZero, + 0x16 => Instruction::And, + 0x17 => Instruction::Or, + 0x18 => Instruction::Xor, + 0x19 => Instruction::Not, + 0x1a => Instruction::Byte, + 0x1b => Instruction::Shl, + 0x1c => Instruction::Shr, 0x20 => Instruction::Sha3, 0x30 => Instruction::Address, 0x31 => Instruction::Balance, @@ -423,20 +426,69 @@ contract Counter { */ #[test] fn can_parse_simple_pgm() { - const counter_sol_code: &'static str = "604260005260206000F3"; - //const counter_sol_code: &'static str = "60426000F3"; - let pgm = Parser::with_pgm(counter_sol_code).parse(); + const counter_sol_code: &'static str = "604260005260206000610040F3"; + let pgm = Parser::with_pgm(counter_sol_code).parse(); + let sixty_four: BitVec<32> = bvi(0x0040); + eprintln!("SIXTY FOUR: {:#?}", sixty_four); let expected = vec![ Instruction::Push1(bvi(0x42)), Instruction::Push1(bvi(0)), Instruction::MStore, Instruction::Push1(bvi(0x20)), Instruction::Push1(bvi(0)), + push2(bvi(0x0040)), Instruction::Return ]; assert_eq!(expected, pgm); +} + +#[test] +fn can_parse_larger_pgm_with_storage() { + let pgm_raw = crate::test::COUNTER_WITH_STORAGE_MAPPING; + let pgm = Parser::with_pgm(pgm_raw).parse(); + + let expected_first_30 = vec![ + push1(bvi(0x80)), + push1(bvi(0x40)), + Instruction::MStore, + Instruction::CallValue, + dup1(), + Instruction::IsZero, + push2(bvi(0x0010)), + jumpi(), + push1(bvi(0x00)), + dup1(), + Instruction::Revert, + Instruction::JumpDest, + Instruction::Pop, + push1(bvi(0x05)), + push1(bvi(0x00)), + dup1(), + push1(bvi(0x01)), + dup2(), + Instruction::MStore, + push1(bvi(0x20)), + Instruction::Add, + Instruction::Swap1, + dup2(), + Instruction::MStore, + push1(bvi(0x20)), + Instruction::Add, + push1(bvi(0x00)), + Instruction::Sha3, + dup2(), + Instruction::Swap1, + Instruction::SStore, + Instruction::Pop, + push2(bvi(0x0197)) + + ]; + + + let pgm_first_30 = (&pgm[..33]).to_vec(); + assert_eq!(expected_first_30, pgm_first_30); } \ No newline at end of file diff --git a/src/record.rs b/src/record.rs index d88b231..2cd7c38 100644 --- a/src/record.rs +++ b/src/record.rs @@ -1,4 +1,5 @@ use crate::smt::BitVec; +use crate::storage::Address; use ruint::aliases::*; use ruint::Uint; @@ -8,12 +9,14 @@ use z3_ext::ast::Bool; pub struct MachineRecord { pub mem: Option, pub stack: Option>, + pub storage: Option, pub pc: (usize, usize), pub constraints: Option>, pub halt: bool, } pub type Index = BitVec<32>; +pub type Value = BitVec<32>; impl From for usize { fn from(idx: Index) -> Self { @@ -69,6 +72,17 @@ impl StackChange { } } +#[derive(Clone, Debug)] +pub enum StorageOp { + Read {addr: Address, idx: Index}, + Write {addr: Address, idx: Index, val: Value} +} + +#[derive(Clone, Debug)] +pub struct StorageChange { + pub log: Vec, +} + pub fn push(val: BitVec) -> StackOp { StackOp::Push(val) } diff --git a/src/smt/bitvec/z3.rs b/src/smt/bitvec/z3.rs index e8b052b..3401186 100644 --- a/src/smt/bitvec/z3.rs +++ b/src/smt/bitvec/z3.rs @@ -15,6 +15,7 @@ impl BitVec { } } + pub fn new_const(name: impl AsRef) -> Self { let bv = BV::new_const(ctx(), name.as_ref(), SZ * 8); Self { diff --git a/src/state/env.rs b/src/state/env.rs index 17f844c..2ed9fa0 100644 --- a/src/state/env.rs +++ b/src/state/env.rs @@ -3,7 +3,8 @@ use z3_ext::ast::{Ast, AstKind}; use z3_ext::FuncDecl; use z3_ext::Sort; -use crate::smt::ctx; +use crate::random_bv_arg; +use crate::smt::{ctx, BitVec}; /** Note: Some of these functions in EVM have no arguments. @@ -48,9 +49,9 @@ pub fn origin<'ctx>() -> FuncDecl<'ctx> { FuncDecl::new(ctx, "origin", &[], &Sort::bitvector(ctx, 256)) } -pub fn address<'ctx>() -> FuncDecl<'ctx> { - let ctx = ctx(); - FuncDecl::new(ctx, "address", &[], &Sort::bitvector(ctx, 256)) + +pub fn address() -> BitVec<20> { + random_bv_arg() } // Takes random bitvec as argument so that gas is not treated as a constant function. diff --git a/src/state/evm.rs b/src/state/evm.rs index 517d8c3..ca02365 100644 --- a/src/state/evm.rs +++ b/src/state/evm.rs @@ -28,6 +28,7 @@ impl MachineComponent for EvmState { stack, mem, constraints, + storage } = rec; if let Some(mem) = mem { self.memory.apply_change(mem); @@ -65,6 +66,7 @@ impl<'ctx> EvmState { stack, mem, constraints, + storage } = rec; let mut new_state = self.clone(); if let Some(stack_rec) = stack { diff --git a/src/storage.rs b/src/storage.rs index c6c23e3..6b0664a 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -1,10 +1,11 @@ use std::collections::HashMap; -use crate::traits::{MachineComponent}; +use crate::{instruction::Instruction,traits::{MachineComponent}, record::{StorageChange, StorageOp}}; use z3_ext::{ ast::{ BV, Ast, Array } }; + use crate::{bvc, bvi}; use crate::smt::{BitVec, ctx}; @@ -13,7 +14,9 @@ fn make_storage_arr() { } #[derive(Debug, Clone, Default)] pub struct AccountStorage { - inner: HashMap, StorageValue> + inner: HashMap, StorageValue>, + touched: HashMap, bool>, + code: Option>, } #[derive(Debug, Clone, Eq, PartialEq)] pub enum StorageValue { @@ -61,6 +64,70 @@ impl GlobalStorage { pub fn get(&self, addr: &Address) -> AccountStorage { self.inner.get(addr).cloned().unwrap_or_default() } + pub fn new() -> Self { + Default::default() + } + pub fn with_address(mut self, addr: Address) -> Self { + self.inner.insert(addr, Default::default()); + self + } + pub fn with_contract(mut self, addr: Address, pgm: Vec) -> Self { + let mut account = AccountStorage::default(); + account.code = Some(pgm); + self.inner.insert(addr, account); + self + } +} + +impl MachineComponent for GlobalStorage { + type Record = StorageChange; + fn apply_change(&mut self, rec: Self::Record) { + let StorageChange { log } = rec; + let mut addr_record_map = HashMap::new(); + log.iter().for_each(|op| { + match op { + crate::record::StorageOp::Read { idx, addr } => { + addr_record_map.entry(addr) + .and_modify(|logs: &mut Vec| logs.push(StorageOp::Read {idx: idx.clone(), addr: addr.clone()})) + .or_insert(vec![StorageOp::Read{idx: idx.clone(), addr: addr.clone()}]); + }, + crate::record::StorageOp::Write { addr, idx, val } => { + addr_record_map.entry(addr) + .and_modify(|logs: &mut Vec| logs.push(StorageOp::Write {idx: idx.clone(), addr: addr.clone(), val: val.clone()})) + .or_insert(vec![StorageOp::Write {idx: idx.clone(), addr: addr.clone(), val: val.clone()}]); + + }, + } + }); + addr_record_map.into_iter().for_each(|(address, storage_ops_log)| { + let change = StorageChange{log: storage_ops_log}; + self.inner.entry(address.clone()) + .and_modify(|account| account.apply_change(change.clone())) + .or_insert_with( || { + let mut new_acc = AccountStorage::default(); + new_acc.apply_change(change); + new_acc + }); + }) + } +} + +impl MachineComponent for AccountStorage { + type Record = StorageChange; + fn apply_change(&mut self, rec: Self::Record) { + let StorageChange { log } = rec; + log.into_iter().for_each(|op| { + match op { + crate::record::StorageOp::Read { idx, addr } => { + self.touched.insert(idx, true); + }, + crate::record::StorageOp::Write { addr, idx, val } => { + self.touched.insert(idx.clone(), true); + self.inner.insert(idx, StorageValue::BV(val)); + }, + } + }) + } } #[test] @@ -87,8 +154,15 @@ fn test_basic_lookup_global_storage() { } +#[test] +fn test_storage_with_solidity_mapping() { + +} +// Storage keys must be concrete +// However, values can be symbolic +// In the case of compound structures like mappings, the following // Global Storage: // HashMap(Address -> AccountStorage) // AccountStorage(BitVec<32> -> StorageValue) diff --git a/test-contracts/src/StorageSimple.sol b/test-contracts/src/StorageSimple.sol new file mode 100644 index 0000000..bd1e5ce --- /dev/null +++ b/test-contracts/src/StorageSimple.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity >=0.8.0 <0.9.0; + +contract SimpleStorage { + mapping (uint => uint) public ids; + + function set(uint key, uint val) public { + ids[key] = val; + } +} \ No newline at end of file From e7ca61dd4d39e4e138bdb4eb4f0542b84abdb360 Mon Sep 17 00:00:00 2001 From: tannr Date: Sat, 24 Jun 2023 14:46:04 -0400 Subject: [PATCH 08/28] Add ruint & support ruint <> BitVec conversions --- Cargo.lock | 14 +++++--- Cargo.toml | 4 ++- src/lib.rs | 9 ++++++ src/parser.rs | 4 +-- src/smt/bitvec/mod.rs | 4 +++ src/smt/bitvec/z3.rs | 4 +-- src/types/mod.rs | 75 +++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 104 insertions(+), 10 deletions(-) create mode 100644 src/types/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 1f20c70..5b6e96c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2243,8 +2243,10 @@ checksum = "0ad3a104dc8c3867f653b0fec89c65e00b0ceb752718ad282177a7e0f33257ac" dependencies = [ "derive_more", "primitive-types", + "rlp", "ruint-macro", "rustc_version", + "serde", "thiserror", ] @@ -2417,7 +2419,9 @@ dependencies = [ "paste", "rand", "revm", + "rlp", "ruint", + "serde", "smallvec", "uuid", "z3", @@ -2425,22 +2429,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.152" +version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.152" +version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" dependencies = [ "proc-macro2", "quote", - "syn 1.0.107", + "syn 2.0.13", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 26fd6ed..094fefa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" [dependencies] once_cell = "1.16.0" -ruint = { version = "1.7.0", features = ["primitive-types"] } +ruint = { version = "1.7.0", features = ["primitive-types", "rlp", "serde"] } uuid = { version = "1.2.2", features = ["v4"] } hex = "0.4.3" smallvec = "1.10.0" @@ -22,6 +22,8 @@ revm = { version = "2.3", default-features = false, features = [ ] } ethers-solc = { git = "https://github.com/gakonst/ethers-rs", features = ["full"]} paste = "1.0.12" +rlp = "0.5.2" +serde = "1.0.164" [target.'cfg(any(target_os = "windows", target_os = "macos"))'.dependencies] z3 = {version = "0.11.2", features = ["static-link-z3"]} diff --git a/src/lib.rs b/src/lib.rs index feee316..652231d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,6 +9,7 @@ pub mod smt; pub mod stack; pub mod state; pub mod traits; +pub mod types; pub mod storage; pub mod parser; use paste::{expr, item, paste}; @@ -25,6 +26,14 @@ use rand::Rng; pub fn bvi(val: impl Into) -> BitVec { BitVec::new_literal(val.into() as u64) } + +pub fn bvi_32byte(val: u64) -> BitVec<32> { + BitVec::new_literal(val) +} + +pub fn bvi_8byte(val: u64) -> BitVec<8> { + BitVec::new_literal(val) +} pub fn bvc(val: impl AsRef) -> BitVec<32> { BitVec::new_const(val) } diff --git a/src/parser.rs b/src/parser.rs index 37583b9..ec282a3 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -426,9 +426,9 @@ contract Counter { */ #[test] fn can_parse_simple_pgm() { - const counter_sol_code: &'static str = "604260005260206000610040F3"; + const COUNTER_SOL_CODE: &'static str = "604260005260206000610040F3"; - let pgm = Parser::with_pgm(counter_sol_code).parse(); + let pgm = Parser::with_pgm(COUNTER_SOL_CODE).parse(); let sixty_four: BitVec<32> = bvi(0x0040); eprintln!("SIXTY FOUR: {:#?}", sixty_four); let expected = vec![ diff --git a/src/smt/bitvec/mod.rs b/src/smt/bitvec/mod.rs index 43f9074..f914329 100644 --- a/src/smt/bitvec/mod.rs +++ b/src/smt/bitvec/mod.rs @@ -33,7 +33,11 @@ impl Hash for BitVec { self.as_ref().hash(state); state.finish(); } + + } + + impl BitVec { pub fn with_bv(bv: BV<'static>) -> Self { Self { diff --git a/src/smt/bitvec/z3.rs b/src/smt/bitvec/z3.rs index 3401186..5db08e9 100644 --- a/src/smt/bitvec/z3.rs +++ b/src/smt/bitvec/z3.rs @@ -8,7 +8,7 @@ use z3::ast::{Ast, BV}; impl BitVec { pub fn new_literal(val: u64) -> Self { let ctx = ctx(); - let bv = BV::from_u64(ctx, val, 256); + let bv = BV::from_u64(ctx, val, SZ * 8); Self { inner: BVType::Z3(bv), typ: Default::default(), @@ -68,7 +68,7 @@ impl AsRef> for BitVec { impl SymbolicValue, u64> for BitVec { fn new_literal(val: u64) -> Self { let ctx = ctx(); - let bv = BV::from_u64(ctx, val, 256); + let bv = BV::from_u64(ctx, val, SZ * 8); Self { inner: BVType::Z3(bv), typ: Default::default(), diff --git a/src/types/mod.rs b/src/types/mod.rs new file mode 100644 index 0000000..7e63a04 --- /dev/null +++ b/src/types/mod.rs @@ -0,0 +1,75 @@ +use ruint::{uint, Uint, ToUintError, FromUintError, Bits}; +use rlp::{Encodable, Decodable}; +use z3_ext::ast::Ast; +use serde::{Deserialize, Serialize}; +use crate::{BV, BVType, BitVec, bvc, bvi, ctx, bvi_8byte}; + +impl From> for BitVec<32> { + fn from(value: Uint<256, 4>) -> Self { + let mut bv: BV<'static> = BV::from_u64(ctx(), 0, 8); + let bytes: [u8; 32] = value.clone().to_be_bytes(); + + for i in bytes.iter() { + let new_bv: BV<'static> = bvi::<1>(*i).into(); + bv = bv.concat(&new_bv).simplify(); + } + bv.extract(256 - 8 - 1, 0).simplify().into() + + } +} + +impl From> for Uint<256, 4> { + fn from(value: BitVec<32>) -> Self { + let value: BV<'static> = value.as_ref().clone(); + let mut numbits = [0u8; 32]; + + for i in (0..32_u32) { + let offset = 256 - (i * 8) - 1; + let byte_extract: BV<'static> = value.extract(offset, offset - 7).simplify(); + // since byte_extract is a single byte, downcasting to u8 will not change the number + let byte = byte_extract.as_u64().unwrap() as u8; + numbits[i as usize] = byte; + + + } + Bits::from_be_bytes(numbits).as_uint().clone() + + } +} + + +#[test] +fn test_u256_to_bytes() { + let num = uint!(0xc85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4_U256); + + let mut buf = [0u8; 32]; + + let bytes: [u8; 32] = num.to_be_bytes(); + + let numbit: Bits<256, 4 >= Bits::from_be_bytes(bytes); + let newnum: Uint<256, 4> = numbit.as_uint().clone(); + assert_eq!(num, newnum); +} + +#[test] +fn test_to_bv() { + let num = uint!(0xc85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4_U256); + let mut bv: BitVec<32> = num.into(); + + let small_num = uint!(0x0000000000000000000000000000000000000000000000000000000000000009_U256); + let mut bv_2 = BitVec::from(small_num); + bv_2.simplify(); + let mut expected = bvi(9); + expected.simplify(); + assert_eq!(expected, bv_2); + +} + +#[test] +fn test_from_bv() { + let bv = bvi(327000); + let num = uint!(0x000000000000000000000000000000000000000000000000000000000004FD58_U256); + let bv_to_num: Uint<256, 4> = bv.into(); + assert_eq!(num, bv_to_num); + +} \ No newline at end of file From 8e7ff11dd2dd77ec7c878d81b0a04b7edc258b7d Mon Sep 17 00:00:00 2001 From: tannr Date: Sat, 24 Jun 2023 15:14:17 -0400 Subject: [PATCH 09/28] change types module to conversion; move z3 conversion type to conversion module --- src/{types => conversion}/mod.rs | 43 ++++++++++++++++++++++++++++++++ src/lib.rs | 2 +- src/smt/bitvec/z3.rs | 40 ----------------------------- 3 files changed, 44 insertions(+), 41 deletions(-) rename src/{types => conversion}/mod.rs (66%) diff --git a/src/types/mod.rs b/src/conversion/mod.rs similarity index 66% rename from src/types/mod.rs rename to src/conversion/mod.rs index 7e63a04..599b0bb 100644 --- a/src/types/mod.rs +++ b/src/conversion/mod.rs @@ -1,3 +1,5 @@ +use std::cmp::Ordering; + use ruint::{uint, Uint, ToUintError, FromUintError, Bits}; use rlp::{Encodable, Decodable}; use z3_ext::ast::Ast; @@ -37,6 +39,47 @@ impl From> for Uint<256, 4> { } } +impl From> for BitVec { + fn from(bv: BV<'static>) -> Self { + let bit_sz = SZ * 8; + let bvsz = bv.get_size(); + let bv = match bvsz.cmp(&bit_sz) { + Ordering::Less => bv.zero_ext(bit_sz - bvsz), + Ordering::Equal => bv, + Ordering::Greater => bv.extract(bit_sz, 0), + }; + // let bv = if bvsz < bit_sz { + // bv.zero_ext(bit_sz - bvsz) + // } else if bvsz > bit_sz { + // bv.extract(bit_sz, 0) + // } else { + // bv + // }; + Self { + inner: BVType::Z3(bv), + typ: Default::default(), + } + } +} + +impl From> for BV<'static> { + fn from(bv: BitVec) -> Self { + match bv.inner { + BVType::Z3(bv) => bv, + _ => panic!("Should never happen"), + } + } +} + +impl AsRef> for BitVec { + fn as_ref(&self) -> &BV<'static> { + match &self.inner { + BVType::Z3(bv) => bv, + _ => panic!("Should never happen"), + } + } +} + #[test] fn test_u256_to_bytes() { diff --git a/src/lib.rs b/src/lib.rs index 652231d..35f3963 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,7 @@ pub mod smt; pub mod stack; pub mod state; pub mod traits; -pub mod types; +pub mod conversion; pub mod storage; pub mod parser; use paste::{expr, item, paste}; diff --git a/src/smt/bitvec/z3.rs b/src/smt/bitvec/z3.rs index 5db08e9..c6bf6ba 100644 --- a/src/smt/bitvec/z3.rs +++ b/src/smt/bitvec/z3.rs @@ -24,46 +24,6 @@ impl BitVec { } } } -impl From> for BitVec { - fn from(bv: BV<'static>) -> Self { - let bit_sz = SZ * 8; - let bvsz = bv.get_size(); - let bv = match bvsz.cmp(&bit_sz) { - Ordering::Less => bv.zero_ext(bit_sz - bvsz), - Ordering::Equal => bv, - Ordering::Greater => bv.extract(bit_sz, 0), - }; - // let bv = if bvsz < bit_sz { - // bv.zero_ext(bit_sz - bvsz) - // } else if bvsz > bit_sz { - // bv.extract(bit_sz, 0) - // } else { - // bv - // }; - Self { - inner: BVType::Z3(bv), - typ: Default::default(), - } - } -} - -impl From> for BV<'static> { - fn from(bv: BitVec) -> Self { - match bv.inner { - BVType::Z3(bv) => bv, - _ => panic!("Should never happen"), - } - } -} - -impl AsRef> for BitVec { - fn as_ref(&self) -> &BV<'static> { - match &self.inner { - BVType::Z3(bv) => bv, - _ => panic!("Should never happen"), - } - } -} impl SymbolicValue, u64> for BitVec { fn new_literal(val: u64) -> Self { From 215c33e434d557cfea53f602289723208c626d96 Mon Sep 17 00:00:00 2001 From: tannr Date: Sat, 24 Jun 2023 15:14:42 -0400 Subject: [PATCH 10/28] Add an address to EVM state --- src/machine.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/machine.rs b/src/machine.rs index f85fdb7..ce87b9d 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -11,6 +11,7 @@ use crate::instruction::*; use crate::memory::*; use crate::state::evm::EvmState; use crate::state::tree::{NodeId, StateTree}; +use crate::storage::Address; use crate::traits::{Machine, MachineComponent, MachineInstruction, MachineState}; use crate::{ bvc, bvi, @@ -106,6 +107,7 @@ impl<'ctx> Evm<'ctx> { stack: Default::default(), pc: 0, pgm: pgm.clone(), + address: Address::default(), }; Self { pgm, From a9e2435ad603a88e7b35e54fc5439bd54aa55f8e Mon Sep 17 00:00:00 2001 From: tannr Date: Sat, 24 Jun 2023 15:15:19 -0400 Subject: [PATCH 11/28] Add address to EVM state' --- src/state/evm.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/state/evm.rs b/src/state/evm.rs index ca02365..bb443a0 100644 --- a/src/state/evm.rs +++ b/src/state/evm.rs @@ -1,5 +1,6 @@ use crate::machine::ExecBranch; use crate::state::tree::NodeId; +use crate::storage::Address; use crate::traits::MachineState; use crate::{ instruction::Instruction, @@ -16,6 +17,7 @@ pub struct EvmState { pub stack: Stack<32>, pub pc: usize, pub pgm: Vec, + pub address: Address } impl MachineComponent for EvmState { From 99bf3f741a728ef7e3772e702825945e3507029b Mon Sep 17 00:00:00 2001 From: tannr Date: Sat, 24 Jun 2023 15:15:34 -0400 Subject: [PATCH 12/28] Implement instruction handler for sstore --- src/instruction/mod.rs | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/instruction/mod.rs b/src/instruction/mod.rs index 5bcbf29..62c6414 100644 --- a/src/instruction/mod.rs +++ b/src/instruction/mod.rs @@ -4,7 +4,7 @@ use std::ops::{BitAnd, BitOr, BitXor}; use ruint::aliases::U256; use z3_ext::ast::{Ast, Bool, BV}; -use crate::record::{push, MemChange, MemOp}; +use crate::record::{push, MemChange, MemOp, StorageChange, StorageOp}; use crate::state::env::*; use crate::state::evm::EvmState; use crate::traits::*; @@ -856,7 +856,29 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { } } Instruction::SLoad => todo!(), - Instruction::SStore => todo!(), + Instruction::SStore => { + let key = mach.stack().peek().unwrap(); + let val = mach.stack().peek_nth(1).unwrap(); + + let stack_rec = StackChange { + pop_qty: 2, + push_qty: 0, + ops: vec![StackOp::Pop, StackOp::Pop] + }; + let storage_change = StorageChange { + log: vec![StorageOp::Write { addr: mach.address.clone(), idx: key.clone(), val: val.clone() }], + }; + + MachineRecord { + stack: Some(stack_rec), + mem: None, + storage: Some(storage_change), + pc: (mach.pc(), mach.pc() + 1), + constraints: None, + halt: false, + } + + }, Instruction::Jump => todo!(), Instruction::JumpI => { let jump_dest = mach.stack().peek().unwrap(); From 0839808e2350b1f77c94aefca9caf707dee118fb Mon Sep 17 00:00:00 2001 From: tannr Date: Sat, 24 Jun 2023 15:31:54 -0400 Subject: [PATCH 13/28] Add storage to MachineState trait & trait implementation --- src/machine.rs | 21 ++++++++++++++++++++- src/state/evm.rs | 3 ++- src/traits.rs | 7 ++++++- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/machine.rs b/src/machine.rs index ce87b9d..094b1fa 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -11,7 +11,7 @@ use crate::instruction::*; use crate::memory::*; use crate::state::evm::EvmState; use crate::state::tree::{NodeId, StateTree}; -use crate::storage::Address; +use crate::storage::{Address, AccountStorage}; use crate::traits::{Machine, MachineComponent, MachineInstruction, MachineState}; use crate::{ bvc, bvi, @@ -108,6 +108,7 @@ impl<'ctx> Evm<'ctx> { pc: 0, pgm: pgm.clone(), address: Address::default(), + storage: AccountStorage::default(), }; Self { pgm, @@ -278,6 +279,24 @@ impl MachineState<32> for EvmState { fn mem_apply(&mut self, mem_rec: MemChange) { self.memory.apply_change(mem_rec); } + + fn storage(&self) -> &AccountStorage { + &self.storage + } + + fn storage_write(&mut self, idx: Index, val: crate::storage::StorageValue) { + self.storage.sstore(idx, val); + } + + fn storage_read(&self, idx: &Index) -> crate::storage::StorageValue { + self.storage.sload(idx) + } + + fn storage_apply(&mut self, storage_rec: StorageChange) { + todo!() + } + + } pub struct EvmExecutor<'ctx> { diff --git a/src/state/evm.rs b/src/state/evm.rs index bb443a0..93dd0b9 100644 --- a/src/state/evm.rs +++ b/src/state/evm.rs @@ -1,6 +1,6 @@ use crate::machine::ExecBranch; use crate::state::tree::NodeId; -use crate::storage::Address; +use crate::storage::{Address, AccountStorage}; use crate::traits::MachineState; use crate::{ instruction::Instruction, @@ -14,6 +14,7 @@ use z3_ext::ast::Bool; #[derive(Clone, Debug, Default)] pub struct EvmState { pub memory: Memory, + pub storage: AccountStorage, pub stack: Stack<32>, pub pc: usize, pub pgm: Vec, diff --git a/src/traits.rs b/src/traits.rs index c6626d0..7b1844d 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -1,10 +1,11 @@ use crate::instruction::Instruction; use crate::machine::{ExecBranch, ExecutionSummary}; use crate::memory::Memory; -use crate::record::{Index, MachineRecord, MemChange, StackChange}; +use crate::record::{Index, MachineRecord, MemChange, StackChange, StorageChange}; use crate::smt::BitVec; use crate::stack::Stack; use crate::state::evm::EvmState; +use crate::storage::{AccountStorage, StorageValue}; use z3_ext::ast::Bool; pub trait MachineState { @@ -19,6 +20,10 @@ pub trait MachineState { fn mem_read(&self, idx: Index) -> BitVec<32>; fn stack_apply(&mut self, stack_rec: StackChange); fn mem_apply(&mut self, mem_rec: MemChange); + fn storage(&self) -> &AccountStorage; + fn storage_write(&mut self, idx: Index, val: StorageValue); + fn storage_read(&self, idx: &Index) -> StorageValue; + fn storage_apply(&mut self, storage_rec: StorageChange); } pub trait Machine { From c9cb4b5b77c836b35d33213e7ae0e9a7b67b3d6b Mon Sep 17 00:00:00 2001 From: tannr Date: Sat, 24 Jun 2023 15:32:15 -0400 Subject: [PATCH 14/28] add sload instruction handler --- src/instruction/mod.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/instruction/mod.rs b/src/instruction/mod.rs index 62c6414..cde26cf 100644 --- a/src/instruction/mod.rs +++ b/src/instruction/mod.rs @@ -7,6 +7,7 @@ use z3_ext::ast::{Ast, Bool, BV}; use crate::record::{push, MemChange, MemOp, StorageChange, StorageOp}; use crate::state::env::*; use crate::state::evm::EvmState; +use crate::storage::StorageValue; use crate::traits::*; use crate::{ random_bv_arg, @@ -855,7 +856,26 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pc: (mach.pc(), mach.pc() + 1), } } - Instruction::SLoad => todo!(), + Instruction::SLoad => { + let key = mach.stack().peek().unwrap(); + let storage = mach.storage_read(key); + let stack_op_1 = StackOp::Pop; + let StorageValue::BV(sval) = storage else { + panic!("Arrays not yet supported"); + }; + let stack_op_2 = StackOp::Push(sval); + let stack_change = StackChange::with_ops(vec![stack_op_1, stack_op_2]); + MachineRecord { + mem: None, + stack: Some(stack_change), + storage: Some(StorageChange { + log: vec![StorageOp::Read { addr: mach.address.clone(), idx: key.clone() }], + }), + pc:(mach.pc(), mach.pc() + 1), + constraints: None, + halt: false, + } + }, Instruction::SStore => { let key = mach.stack().peek().unwrap(); let val = mach.stack().peek_nth(1).unwrap(); From fc2023c76564684f30b1ed8592d08a173db6c00d Mon Sep 17 00:00:00 2001 From: tannr Date: Sat, 24 Jun 2023 15:34:18 -0400 Subject: [PATCH 15/28] implement 'storage_apply' in machine --- src/machine.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine.rs b/src/machine.rs index 094b1fa..63a8988 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -293,7 +293,7 @@ impl MachineState<32> for EvmState { } fn storage_apply(&mut self, storage_rec: StorageChange) { - todo!() + self.storage.apply_change(storage_rec); } From 484d388799843f6a9429d98f69d1226ad54a9022 Mon Sep 17 00:00:00 2001 From: tannr Date: Sat, 24 Jun 2023 20:58:45 -0400 Subject: [PATCH 16/28] Use ruint's Uint to convert to Bitvecs in parser instead of using u64 --- src/conversion/mod.rs | 57 ++++++++-- src/instruction/mod.rs | 17 ++- src/lib.rs | 5 +- src/machine.rs | 2 +- src/memory.rs | 6 ++ src/parser.rs | 231 +++++++++++++++++++++++++++++++++-------- src/record.rs | 11 +- src/smt/bitvec/mod.rs | 14 +-- src/smt/bitvec/z3.rs | 13 +-- src/stack.rs | 7 +- src/state/evm.rs | 4 + src/traits.rs | 6 +- tests/lib.rs | 40 +++++++ tests/test_storage.rs | 0 14 files changed, 328 insertions(+), 85 deletions(-) create mode 100644 tests/lib.rs create mode 100644 tests/test_storage.rs diff --git a/src/conversion/mod.rs b/src/conversion/mod.rs index 599b0bb..5d058d5 100644 --- a/src/conversion/mod.rs +++ b/src/conversion/mod.rs @@ -2,9 +2,9 @@ use std::cmp::Ordering; use ruint::{uint, Uint, ToUintError, FromUintError, Bits}; use rlp::{Encodable, Decodable}; -use z3_ext::ast::Ast; +use z3_ext::{ast::Ast, Context}; use serde::{Deserialize, Serialize}; -use crate::{BV, BVType, BitVec, bvc, bvi, ctx, bvi_8byte}; +use crate::{BV, BVType, BitVec, bvc, bvi, ctx, bvi_8byte, parser::zero_extend, record::push, instruction::{push32, Instruction}}; impl From> for BitVec<32> { fn from(value: Uint<256, 4>) -> Self { @@ -39,14 +39,14 @@ impl From> for Uint<256, 4> { } } -impl From> for BitVec { +impl From> for BitVec { fn from(bv: BV<'static>) -> Self { let bit_sz = SZ * 8; let bvsz = bv.get_size(); - let bv = match bvsz.cmp(&bit_sz) { - Ordering::Less => bv.zero_ext(bit_sz - bvsz), + let bv = match bvsz.cmp(&(bit_sz as u32)) { + Ordering::Less => bv.zero_ext((bit_sz - bvsz as usize) as u32), Ordering::Equal => bv, - Ordering::Greater => bv.extract(bit_sz, 0), + Ordering::Greater => bv.extract(bit_sz as u32, 0), }; // let bv = if bvsz < bit_sz { // bv.zero_ext(bit_sz - bvsz) @@ -62,7 +62,7 @@ impl From> for BitVec { } } -impl From> for BV<'static> { +impl From> for BV<'static> { fn from(bv: BitVec) -> Self { match bv.inner { BVType::Z3(bv) => bv, @@ -71,7 +71,24 @@ impl From> for BV<'static> { } } -impl AsRef> for BitVec { +impl From<[u8; SZ]> for BitVec { + fn from(value: [u8; SZ]) -> Self { + let ctx: &'static Context = ctx(); + let mut bv: BV<'static> = BV::from_u64(ctx, 0, 8); + + + for i in value.iter() { + let new_bv: BV<'static> = bvi::<1>(*i).into(); + bv = bv.concat(&new_bv).simplify(); + + } + eprintln!("VALUE CONVERTING FROM: {:#x?}", value); + eprintln!("BV IN SLICE CONVERT: {:#?} SIZE: {}", bv, bv.get_size()); + bv.extract((bv.get_size() - 8 - 1) as u32, 0).simplify().into() + } +} + +impl AsRef> for BitVec { fn as_ref(&self) -> &BV<'static> { match &self.inner { BVType::Z3(bv) => bv, @@ -80,6 +97,28 @@ impl AsRef> for BitVec { } } +#[cfg(test)] +fn push_arg_to_push(arg: &[u8]) -> Instruction { + let slice_full = zero_extend::<32>(&arg).into(); + push32(slice_full) +} + +#[test] +fn test_slice_to_op_arg() { + let mut slice8 = 327000_u64.to_be_bytes(); + let inst = push_arg_to_push(&slice8); +} +#[test] +fn test_slice_to_bitvec() { + let mut slice8 = 327000_u64.to_be_bytes(); + + let slice_full = zero_extend::<32>(&slice8); + let bv: BitVec<32> = slice_full.into(); + + let num = uint!(0x000000000000000000000000000000000000000000000000000000000004FD58_U256); + let bv_as_num: Uint<256,4> = bv.into(); + assert_eq!(num, bv_as_num); +} #[test] fn test_u256_to_bytes() { @@ -89,7 +128,7 @@ fn test_u256_to_bytes() { let bytes: [u8; 32] = num.to_be_bytes(); - let numbit: Bits<256, 4 >= Bits::from_be_bytes(bytes); + let numbit: Bits<256, 4> = Bits::from_be_bytes(bytes); let newnum: Uint<256, 4> = numbit.as_uint().clone(); assert_eq!(num, newnum); } diff --git a/src/instruction/mod.rs b/src/instruction/mod.rs index cde26cf..2305d8b 100644 --- a/src/instruction/mod.rs +++ b/src/instruction/mod.rs @@ -603,7 +603,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { Instruction::CallValue => { let stack = mach.stack(); let call_val = call_value().apply(&[]).as_bv().unwrap(); - let stack_diff = StackChange::with_ops(vec![pop(), push(call_val.into())]); + let stack_diff = StackChange::with_ops(vec![push(call_val.into())]); MachineRecord { stack: Some(stack_diff), @@ -1448,7 +1448,16 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { Instruction::DelegateCall => todo!(), Instruction::Create2 => todo!(), Instruction::StaticCall => todo!(), - Instruction::Revert => todo!(), + Instruction::Revert => { + MachineRecord { + mem: None, + stack: None, + storage: None, + pc: (mach.pc(), mach.pc()), + constraints: None, + halt: true, + } + }, Instruction::Invalid => todo!(), Instruction::SelfDestruct => todo!(), Instruction::SignExtend => todo!(), @@ -1491,7 +1500,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { } } -pub fn pop() -> StackOp { +pub fn pop() -> StackOp { StackOp::Pop } pub fn add() -> Instruction { @@ -1553,7 +1562,7 @@ pub fn dup15() -> Instruction { pub fn dup16() -> Instruction { Instruction::Dup16 } -// pub fn push(size: usize, val: BitVec<>) -> Instruction { +// pub fn push(size: usize, val: BitVec<>) -> Instruction { // Instruction::Push5(BitVec::default()) // } diff --git a/src/lib.rs b/src/lib.rs index 35f3963..662293d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,7 +23,7 @@ use z3_ext::{ use rand::Rng; -pub fn bvi(val: impl Into) -> BitVec { +pub fn bvi(val: impl Into) -> BitVec { BitVec::new_literal(val.into() as u64) } @@ -37,7 +37,7 @@ pub fn bvi_8byte(val: u64) -> BitVec<8> { pub fn bvc(val: impl AsRef) -> BitVec<32> { BitVec::new_const(val) } -pub fn random_bv_arg() -> BitVec { +pub fn random_bv_arg() -> BitVec { let mut rng = rand::thread_rng(); let rand_num: u64 = rng.gen(); BitVec::new_literal(rand_num) @@ -51,4 +51,5 @@ mod test { */ pub const SIMPLE_COUNTER: &str = r"6080604052348015600f57600080fd5b5060043610603c5760003560e01c80633fb5c1cb1460415780638381f58a146053578063d09de08a14606d575b600080fd5b6051604c3660046083565b600055565b005b605b60005481565b60405190815260200160405180910390f35b6051600080549080607c83609b565b9190505550565b600060208284031215609457600080fd5b5035919050565b60006001820160ba57634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220f0cfb2159c518c3da0ad864362bad5dc0715514a9ab679237253d506773a0a1b64736f6c63430008130033"; pub const COUNTER_WITH_STORAGE_MAPPING: &str = r#"608060405234801561001057600080fd5b5060056000806001815260200190815260200160002081905550610197806100396000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063846719e01461003b578063d78233d61461006b575b600080fd5b6100556004803603810190610050919061010a565b61009b565b6040516100629190610146565b60405180910390f35b6100856004803603810190610080919061010a565b6100b7565b6040516100929190610146565b60405180910390f35b6000806000838152602001908152602001600020549050919050565b60006020528060005260406000206000915090505481565b600080fd5b6000819050919050565b6100e7816100d4565b81146100f257600080fd5b50565b600081359050610104816100de565b92915050565b6000602082840312156101205761011f6100cf565b5b600061012e848285016100f5565b91505092915050565b610140816100d4565b82525050565b600060208201905061015b6000830184610137565b9291505056fea2646970667358fe122066b287fef10118cba238fe38953bfefe938afefefefefe94fefe3682fefefefe64736f6c63430008110033"#; + } \ No newline at end of file diff --git a/src/machine.rs b/src/machine.rs index 63a8988..8855eda 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -124,7 +124,7 @@ impl<'ctx> Evm<'ctx> { } } - fn exec_check(&mut self) -> Vec<(ExecBranch, Option>)> { + pub fn exec_check(&mut self) -> Vec<(ExecBranch, Option>)> { let evm_trace = self.exec(); let mut solver = z3_ext::Solver::new(ctx()); evm_trace diff --git a/src/memory.rs b/src/memory.rs index 29c1dad..b927d0b 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -17,10 +17,16 @@ impl MachineComponent for Memory { type Record = MemChange; fn apply_change(&mut self, rec: Self::Record) { + let MemChange { ops_log } = rec; let mut highest_idx = self.highest_idx; ops_log.into_iter().for_each(|op| match op { MemOp::Write { val, idx } => { + let mut val = val; + val.simplify(); + let mut idx = idx; + idx.simplify(); + eprintln!("MEM WRITE FOR MEM APPLY: idx: {:#?}, value: {:#?}", idx, val); let idx_cmp: usize = idx.clone().into(); if idx_cmp > highest_idx { highest_idx = idx_cmp; diff --git a/src/parser.rs b/src/parser.rs index ec282a3..d9945a3 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -3,6 +3,7 @@ use revm::{ opcode::OpCode, OPCODE_JUMPMAP }; use hex::{decode}; +use ruint::Uint; pub struct Parser<'a> { pgm: &'a str } @@ -56,14 +57,27 @@ impl<'a> Parser<'a> { } // Returns instruction + any left over bytes in the slice after extracting the opcode & opcode args -fn parse_push(bytes: &[u8]) -> (Instruction, u8, &[u8]) { +fn parse_push(bytes: &[u8]) -> (Instruction, u8, Vec) { let instruction_byte = *bytes.first().unwrap(); let push_size = push_size(instruction_byte); eprintln!("PUSH SIZE IS {}", push_size); - let push_val = &bytes[1..(push_size + 1) as usize]; - eprintln!("PUSH VAL IS {:#?}", push_val); - (push_op(push_size, push_val),push_size, &bytes[(push_size) as usize..bytes.len()]) + eprintln!("Bytes len is {}", bytes.len()); + if bytes.len() - 1 < push_size as usize { + let pad_len = push_size as usize - bytes.len() + 1; + eprintln!("pad len: {}", pad_len); + let mut new_bytes = bytes.to_vec(); + for _ in (0..pad_len) { + new_bytes.push(0); + } + let push_val = &new_bytes[1..(push_size + 1) as usize]; + (push_op(push_size, push_val),push_size, new_bytes[(push_size) as usize..new_bytes.len()].to_vec()) + } else { + let push_val = &bytes[1..(push_size + 1) as usize]; + eprintln!("PUSH VAL IS {:#?}", push_val); + (push_op(push_size, push_val),push_size, bytes[(push_size) as usize..bytes.len()].to_vec()) + } + } fn parse_dup(byte: u8) -> Instruction { @@ -109,52 +123,179 @@ fn push_size(b: u8) -> u8 { } } +// Add zeroes to the left side of a byte array until the byte array is a certain +pub fn zero_extend(bytes: &[u8]) -> [u8; SZ] { + let mut extended_bytes: [u8; SZ] = [0u8; SZ]; + if bytes.len() < SZ { + let pad_size = SZ - bytes.len(); + let last_idx = SZ - 1; + let start_idx = last_idx - (bytes.len() - 1); + extended_bytes[start_idx..].clone_from_slice(&bytes); + let padding_len = SZ - bytes.len(); + for i in (0..pad_size - 1) { + extended_bytes[i] = 0; + } -fn push_op(sz: u8, val: &[u8]) -> Instruction { - let mut zero_len = 8 - val.len(); - let mut buf = vec![]; - for _ in (0..zero_len) { - buf.push(0); + + } else { + extended_bytes.copy_from_slice(bytes); } - buf.extend_from_slice(val); + extended_bytes + + +} + + + +fn push_op(sz: u8, val: &[u8]) -> Instruction { + + // let val = if val.len() < 8 { + // let mut zero_len = if val.len() < 8 {8 - val.len()} else {0}; + // let mut buf = vec![]; + // for _ in (0..zero_len) { + // buf.push(0); + // } + // buf.extend_from_slice(val); + + // let mut sliced = [0u8; 8]; + // sliced.copy_from_slice(&buf); + // u64::from_be_bytes(sliced) + // } else { + // let mut buf = vec![]; + // buf.copy_from_slice() + // u64::from_be_bytes(val) + // }; - let mut sliced = [0u8; 8]; - sliced.copy_from_slice(&buf); - let val = u64::from_be_bytes(sliced); match sz { - 1 => push1(BitVec::<1>::new_literal(val)), - 2 => push2(BitVec::<2>::new_literal(val)), - 3 => push3(BitVec::<3>::new_literal(val)), - 4 => push4(BitVec::<4>::new_literal(val)), - 5 => push5(BitVec::<5>::new_literal(val)), - 6 => push6(BitVec::<6>::new_literal(val)), - 7 => push7(BitVec::<7>::new_literal(val)), - 8 => push8(BitVec::<8>::new_literal(val)), - 9 => push9(BitVec::<9>::new_literal(val)), - 10 => push10(BitVec::<10>::new_literal(val)), - 11 => push11(BitVec::<11>::new_literal(val)), - 12 => push12(BitVec::<12>::new_literal(val)), - 13 => push13(BitVec::<13>::new_literal(val)), - 14 => push14(BitVec::<14>::new_literal(val)), - 15 => push15(BitVec::<15>::new_literal(val)), - 16 => push16(BitVec::<16>::new_literal(val)), - 17 => push17(BitVec::<17>::new_literal(val)), - 18 => push18(BitVec::<18>::new_literal(val)), - 19 => push19(BitVec::<19>::new_literal(val)), - 20 => push20(BitVec::<20>::new_literal(val)), - 21 => push21(BitVec::<21>::new_literal(val)), - 21 => push22(BitVec::<22>::new_literal(val)), - 23 => push23(BitVec::<23>::new_literal(val)), - 24 => push24(BitVec::<24>::new_literal(val)), - 25 => push25(BitVec::<25>::new_literal(val)), - 26 => push26(BitVec::<26>::new_literal(val)), - 27 => push27(BitVec::<27>::new_literal(val)), - 28 => push28(BitVec::<28>::new_literal(val)), - 29 => push29(BitVec::<29>::new_literal(val)), - 30 => push30(BitVec::<30>::new_literal(val)), - 31 => push31(BitVec::<31>::new_literal(val)), - 32 => push32(BitVec::<32>::new_literal(val)), + 1 => { + let val = zero_extend::<1>(val); + push1(val.into()) + }, + 2 => { + let val = zero_extend::<2>(val).into(); + push2(val) + }, + 3 => { + let val = zero_extend::<3>(val).into(); + push3(val) + }, + 4 => { + let val = zero_extend::<4>(val).into(); + push4(val) + }, + 5 => { + let val = zero_extend::<5>(val).into(); + push5(val) + }, + 6 => { + let val = zero_extend::<6>(val).into(); + push6(val) + }, + 7 => { + let val = zero_extend::<7>(val).into(); + push7(val) + }, + 8 => { + let val = zero_extend::<8>(val).into(); + push8(val) + }, + 9 => { + let val = zero_extend::<9>(val).into(); + push9(val) + }, + 10 => { + let val = zero_extend::<10>(val).into(); + push10(val) + }, + 11 => { + let val = zero_extend::<11>(val).into(); + push11(val) + }, + 12 => { + let val = zero_extend::<12>(val).into(); + push12(val) + }, + 13 => { + let val = zero_extend::<13>(val).into(); + push13(val) + }, + 14 => { + let val = zero_extend::<14>(val).into(); + push14(val) + }, + 15 => { + let val = zero_extend::<15>(val).into(); + push15(val) + }, + 16 => { + let val = zero_extend::<16>(val).into(); + push16(val) + }, + 17 => { + let val = zero_extend::<17>(val).into(); + push17(val) + }, + 18 => { + let val = zero_extend::<18>(val).into(); + push18(val) + }, + 19 => { + let val = zero_extend::<19>(val).into(); + push19(val) + }, + 20 => { + let val = zero_extend::<20>(val).into(); + push20(val) + }, + 21 => { + let val = zero_extend::<21>(val).into(); + push21(val) + }, + 21 => { + let val = zero_extend::<22>(val).into(); + push22(val) + }, + 23 => { + let val = zero_extend::<23>(val).into(); + push23(val) + }, + 24 => { + let val = zero_extend::<24>(val).into(); + push24(val) + }, + 25 => { + let val = zero_extend::<25>(val).into(); + push25(val) + }, + 26 => { + let val = zero_extend::<26>(val).into(); + push26(val) + }, + 27 => { + let val = zero_extend::<27>(val).into(); + push27(val) + }, + 28 => { + let val = zero_extend::<28>(val).into(); + push28(val) + }, + 29 => { + let val = zero_extend::<29>(val).into(); + push29(val) + }, + 30 => { + let val = zero_extend::<30>(val).into(); + push30(val) + }, + 31 => { + let val = zero_extend::<31>(val).into(); + push31(val) + }, + 32 => { + let val = zero_extend::<32>(val).into(); + push32(val) + }, _ => { todo!() } diff --git a/src/record.rs b/src/record.rs index 2cd7c38..bb5196e 100644 --- a/src/record.rs +++ b/src/record.rs @@ -3,10 +3,11 @@ use crate::storage::Address; use ruint::aliases::*; use ruint::Uint; +use z3_ext::ast::Ast; use z3_ext::ast::Bool; #[derive(Clone, Debug)] -pub struct MachineRecord { +pub struct MachineRecord { pub mem: Option, pub stack: Option>, pub storage: Option, @@ -34,19 +35,19 @@ pub enum MemOp { Read { idx: Index }, } #[derive(Clone, Debug)] -pub enum StackOp { +pub enum StackOp { Push(BitVec), Pop, } #[derive(Default, Clone, Debug)] -pub struct StackChange { +pub struct StackChange { pub pop_qty: u64, pub push_qty: u64, pub ops: Vec>, } -impl StackChange { +impl StackChange { pub fn push(val: BitVec) -> Self { Self { pop_qty: 0, @@ -83,6 +84,6 @@ pub struct StorageChange { pub log: Vec, } -pub fn push(val: BitVec) -> StackOp { +pub fn push(val: BitVec) -> StackOp { StackOp::Push(val) } diff --git a/src/smt/bitvec/mod.rs b/src/smt/bitvec/mod.rs index f914329..719eaaa 100644 --- a/src/smt/bitvec/mod.rs +++ b/src/smt/bitvec/mod.rs @@ -13,13 +13,13 @@ pub enum BVType { pub type SymByte = BitVec<8>; #[derive(Debug, Clone, Eq)] -pub struct BitVec { +pub struct BitVec { pub inner: BVType, pub(crate) typ: super::SolverType, } -// impl PartialEq for BitVec { +// impl PartialEq for BitVec { // fn eq(&self, other: &Self) -> bool { // let BVType::Z3(a) = &self.inner; // let BVType::Z3(b) = &other.inner; @@ -28,7 +28,7 @@ pub struct BitVec { // } // } -impl Hash for BitVec { +impl Hash for BitVec { fn hash(&self, state: &mut H) { self.as_ref().hash(state); state.finish(); @@ -38,7 +38,7 @@ impl Hash for BitVec { } -impl BitVec { +impl BitVec { pub fn with_bv(bv: BV<'static>) -> Self { Self { inner: BVType::Z3(bv), @@ -50,17 +50,17 @@ impl BitVec { self.inner = BVType::Z3(bv.simplify()); } } -impl Default for BitVec { +impl Default for BitVec { fn default() -> Self { let ctx = ctx(); Self { - inner: BVType::Z3(BV::from_u64(ctx, 0, SZ * 8)), + inner: BVType::Z3(BV::from_u64(ctx, 0, (SZ * 8) as u32)), typ: SolverType::Z3, } } } -impl PartialEq for BitVec { +impl PartialEq for BitVec { fn eq(&self, other: &Self) -> bool { let a = self.as_ref(); diff --git a/src/smt/bitvec/z3.rs b/src/smt/bitvec/z3.rs index c6bf6ba..f21dc3e 100644 --- a/src/smt/bitvec/z3.rs +++ b/src/smt/bitvec/z3.rs @@ -3,12 +3,13 @@ use std::cmp::Ordering; use super::super::ctx; use super::{BVType, BitVec}; +use ruint::Uint; use z3::ast::{Ast, BV}; -impl BitVec { +impl BitVec { pub fn new_literal(val: u64) -> Self { let ctx = ctx(); - let bv = BV::from_u64(ctx, val, SZ * 8); + let bv = BV::from_u64(ctx, val, (SZ * 8) as u32); Self { inner: BVType::Z3(bv), typ: Default::default(), @@ -17,7 +18,7 @@ impl BitVec { pub fn new_const(name: impl AsRef) -> Self { - let bv = BV::new_const(ctx(), name.as_ref(), SZ * 8); + let bv = BV::new_const(ctx(), name.as_ref(), (SZ * 8) as u32); Self { inner: BVType::Z3(bv), typ: Default::default(), @@ -25,10 +26,10 @@ impl BitVec { } } -impl SymbolicValue, u64> for BitVec { +impl SymbolicValue, u64> for BitVec { fn new_literal(val: u64) -> Self { let ctx = ctx(); - let bv = BV::from_u64(ctx, val, SZ * 8); + let bv = BV::from_u64(ctx, val, (SZ * 8) as u32); Self { inner: BVType::Z3(bv), typ: Default::default(), @@ -36,7 +37,7 @@ impl SymbolicValue, u64> for BitVec { } fn new_const(name: impl AsRef) -> Self { - let bv = BV::new_const(ctx(), name.as_ref(), SZ * 8); + let bv = BV::new_const(ctx(), name.as_ref(), (SZ * 8) as u32); Self { inner: BVType::Z3(bv), typ: Default::default(), diff --git a/src/stack.rs b/src/stack.rs index ef4b961..b823309 100644 --- a/src/stack.rs +++ b/src/stack.rs @@ -9,18 +9,19 @@ use z3_ext::{ Config, }; #[derive(Default, Debug, Clone)] -pub struct Stack { +pub struct Stack { stack: SmallVec<[BitVec; 1024]>, size: usize, } -impl Stack { +impl Stack { pub fn push(&mut self, val: BitVec) { self.size += 1; self.stack.push(val); } pub fn pop(&mut self) -> BitVec { + eprintln!("STACK SIZE: {} AND STACK TOP {:#?}", self.size, self.peek()); self.size -= 1; self.stack.pop().unwrap() } @@ -50,7 +51,7 @@ impl Stack { } } -impl MachineComponent for Stack { +impl MachineComponent for Stack { type Record = StackChange; fn apply_change(&mut self, rec: Self::Record) { diff --git a/src/state/evm.rs b/src/state/evm.rs index 93dd0b9..a998628 100644 --- a/src/state/evm.rs +++ b/src/state/evm.rs @@ -54,6 +54,7 @@ impl<'ctx> EvmState { pub fn exec_once(mut self) -> (ExecBranch<'ctx>, Option>) { let inst = self.curr_instruction(); + eprintln!("CURRENT INSTRUCTION: {:#?} at pc: {}", inst, self.pc); let change = inst.exec(&self); self.state_transition(change) @@ -72,6 +73,9 @@ impl<'ctx> EvmState { storage } = rec; let mut new_state = self.clone(); + if halt { + return ((new_state, vec![]), None); + } if let Some(stack_rec) = stack { new_state.stack_apply(stack_rec); } diff --git a/src/traits.rs b/src/traits.rs index 7b1844d..5a8b5a4 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -8,7 +8,7 @@ use crate::state::evm::EvmState; use crate::storage::{AccountStorage, StorageValue}; use z3_ext::ast::Bool; -pub trait MachineState { +pub trait MachineState { type PC; fn pc(&self) -> Self::PC; @@ -26,7 +26,7 @@ pub trait MachineState { fn storage_apply(&mut self, storage_rec: StorageChange); } -pub trait Machine { +pub trait Machine { type State: MachineState; // All possible final states @@ -37,7 +37,7 @@ pub trait Machine { fn state_ref_mut(&mut self) -> &mut Self::State; } -pub trait MachineInstruction<'ctx, const SZ: u32> { +pub trait MachineInstruction<'ctx, const SZ: usize> { fn exec(&self, mach: &EvmState) -> MachineRecord; } diff --git a/tests/lib.rs b/tests/lib.rs new file mode 100644 index 0000000..f71c19b --- /dev/null +++ b/tests/lib.rs @@ -0,0 +1,40 @@ +extern crate ser; +use ser::{ + traits::*, + machine::*, + stack::*, + storage::*, + memory::*, + conversion::*, + bvc, + bvi, + parser::*, +}; +use z3::ast::*; + +pub const SIMPLE_COUNTER: &str = r"6080604052348015600f57600080fd5b5060043610603c5760003560e01c80633fb5c1cb1460415780638381f58a146053578063d09de08a14606d575b600080fd5b6051604c3660046083565b600055565b005b605b60005481565b60405190815260200160405180910390f35b6051600080549080607c83609b565b9190505550565b600060208284031215609457600080fd5b5035919050565b60006001820160ba57634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220f0cfb2159c518c3da0ad864362bad5dc0715514a9ab679237253d506773a0a1b64736f6c63430008130033"; +pub const COUNTER_WITH_STORAGE_MAPPING: &str = r#"608060405234801561001057600080fd5b5060056000806001815260200190815260200160002081905550610197806100396000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063846719e01461003b578063d78233d61461006b575b600080fd5b6100556004803603810190610050919061010a565b61009b565b6040516100629190610146565b60405180910390f35b6100856004803603810190610080919061010a565b6100b7565b6040516100929190610146565b60405180910390f35b6000806000838152602001908152602001600020549050919050565b60006020528060005260406000206000915090505481565b600080fd5b6000819050919050565b6100e7816100d4565b81146100f257600080fd5b50565b600081359050610104816100de565b92915050565b6000602082840312156101205761011f6100cf565b5b600061012e848285016100f5565b91505092915050565b610140816100d4565b82525050565b600060208201905061015b6000830184610137565b9291505056fea2646970667358fe122066b287fef10118cba238fe38953bfefe938afefefefefe94fefe3682fefefefe64736f6c63430008110033"#; + +#[test] +#[ignore] +fn can_run_stored_pgm() { + let pgm = Parser::with_pgm(SIMPLE_COUNTER).parse(); + let mut evm = Evm::new(pgm); + + { + let sat_branches = evm.exec_check(); + assert_eq!(sat_branches.len(), 1); + let top = sat_branches + .first() + .unwrap() + .0 + .0 + .stack() + .peek() + .cloned() + .unwrap(); + eprintln!("Stack top size: {:#?}", top.as_ref().get_size()); + assert_eq!(top, bvi(5)); + } + eprintln!("STATES > {:#?}", evm.states); +} \ No newline at end of file diff --git a/tests/test_storage.rs b/tests/test_storage.rs new file mode 100644 index 0000000..e69de29 From 3af822a9a7b0695d0329ae7efe9701a47519a882 Mon Sep 17 00:00:00 2001 From: tannr Date: Wed, 2 Aug 2023 14:33:18 -0400 Subject: [PATCH 17/28] refactor execution algorithm --- examples/simple_pgm.rs | 31 +++ examples/simple_storage.rs | 34 +++ src/exec/mod.rs | 195 +++++++++++++++ src/instruction/mod.rs | 11 +- src/lib.rs | 1 + src/machine.rs | 339 +++++++++++++++------------ src/memory.rs | 2 + src/state/evm.rs | 81 +++---- src/state/tree.rs | 78 ++++-- src/traits.rs | 3 +- test-contracts/src/StorageSimple.sol | 2 +- tests/lib.rs | 78 ++++-- 12 files changed, 609 insertions(+), 246 deletions(-) create mode 100644 examples/simple_pgm.rs create mode 100644 examples/simple_storage.rs create mode 100644 src/exec/mod.rs diff --git a/examples/simple_pgm.rs b/examples/simple_pgm.rs new file mode 100644 index 0000000..7555b4d --- /dev/null +++ b/examples/simple_pgm.rs @@ -0,0 +1,31 @@ + + +use ser::{ + traits::*, + machine::*, + stack::*, + storage::*, + memory::*, + conversion::*, + bvc, + bvi, + parser::*, +}; +use z3::ast::*; + + +pub const SUPERSIMPLE: &str = r#"604260005260206000F3"#; +fn main() { + let pgm = Parser::with_pgm(SUPERSIMPLE).parse(); + let mut evm = Evm::new(pgm); + let execution_trace = evm.exec(); + + let leaf = execution_trace.states.leaves(); + assert_eq!(1, leaf.len()); + let final_tree = leaf.first().unwrap().clone(); + // eprintln!("FINAL TREE: {:#?}", final_tree); + + let mut mem_val = final_tree.val.mem_read(bvi(0)); + mem_val.simplify(); + assert_eq!(bvi(66), mem_val); +} diff --git a/examples/simple_storage.rs b/examples/simple_storage.rs new file mode 100644 index 0000000..cf0fa2b --- /dev/null +++ b/examples/simple_storage.rs @@ -0,0 +1,34 @@ + + +use ser::{ + traits::*, + machine::*, + stack::*, + storage::*, + memory::*, + conversion::*, + bvc, + bvi, + parser::*, +}; +use z3::ast::*; + +pub const STORAGE_SIMPLE: &str = r#"6080604052348015600f57600080fd5b506004361060325760003560e01c80631ab06ee5146037578063fac333ac146056575b600080fd5b605460423660046085565b60009182526020829052604090912055565b005b6073606136600460a6565b60006020819052908152604090205481565b60405190815260200160405180910390f35b60008060408385031215609757600080fd5b50508035926020909101359150565b60006020828403121560b757600080fd5b503591905056fea26469706673582212204a6bf5c04a6e273d775914b20b0bab1bca28228be5562d496002981e13ff015264736f6c63430008130033"#; + + +fn main() { + let pgm = Parser::with_pgm(STORAGE_SIMPLE).parse(); + let mut evm = Evm::new(pgm); + + + let execution = evm.exec(); + + let leaf = execution.states.leaves(); + assert_eq!(2, leaf.len()); + + let final_tree = leaf.get(1).unwrap().clone(); + + let mut mem_val = final_tree.val.mem_read(bvi(64)); // 0x40 + mem_val.simplify(); + assert_eq!(bvi(128), mem_val); // 0x80 +} diff --git a/src/exec/mod.rs b/src/exec/mod.rs new file mode 100644 index 0000000..63db239 --- /dev/null +++ b/src/exec/mod.rs @@ -0,0 +1,195 @@ +use uuid::Uuid; + +use crate::{record::{ + MachineRecord +}, instruction::Instruction, traits::{MachineInstruction, MachineComponent, MachineState}}; +use crate::state::evm::EvmState; +use crate::state::tree::*; + + +#[derive(Default, Debug)] +pub struct Execution<'ctx> { + changes: Vec>, + program: Vec, + pub states: StateTree<'ctx> +} + +#[derive(Default, Debug)] +pub struct StepRecord + +{ + left_insert: Option, + right_insert: Option, + halted_left: bool, + halted_right: bool +} + +impl StepRecord { + + pub fn new(halted_left: bool, halted_right: bool) -> Self { + Self { + halted_left, halted_right, ..Default::default() + } + } + pub fn halted_left(&self) -> bool { + self.halted_left + } + + pub fn halted_right(&self) -> bool { + self.halted_right + } + pub fn branched(&self) -> bool { + self.left_insert.is_some() && self.right_insert.is_some() + } + + pub fn left_id(&self) -> Option<&NodeId> { + self.left_insert.as_ref() + } + + pub fn right_id(&self) -> Option<&NodeId> { + self.right_insert.as_ref() + } + + pub fn set_left(mut self, left: NodeId) -> Self { + self.left_insert = Some(left); + self + } + pub fn set_right(mut self, right: NodeId) -> Self { + self.right_insert = Some(right); + self + } +} + +impl<'ctx> Execution<'ctx> { + + pub fn new(start_state: EvmState, pgm: Vec) -> Self { + Self { + program: pgm, + states: StateTree::from((start_state, None)), + ..Default::default() + } + } + + // Returns the StepRecord AND updates the Exec state tree + pub fn step_mut(&mut self) -> StepRecord { // bool returns if there is a branch + let curr_state_id = self.states.id.clone(); + let mut curr_state = self.states.val.clone(); + let curr_inst = curr_state.curr_instruction(); + let curr_pc = curr_state.pc(); + let change_rec = curr_inst.exec(&curr_state); + + let is_branch = change_rec.constraints.is_some(); + curr_state.apply_change(change_rec.clone()); + let mut report = StepRecord::new(false, change_rec.halt); + if is_branch { + // then curr_state.apply generated the right branching state; thus, a state tree w/ + // an additional constraint + // and left tree (by convention left path represents straight line execution) is the negation of such constraint + let mut left_state = curr_state.clone(); + left_state.set_pc(curr_pc + 1); + if !left_state.can_continue() { + report.halted_left = true; + } + + let left_tree = StateTree::from((left_state.clone(), change_rec.constraints.clone().unwrap().not())); + let right_tree = StateTree::from((left_state, change_rec.constraints.unwrap())); + + let left_tree_ref = self.states.insert_left_of(left_tree, curr_state_id.id()); + + + let right_tree_ref = self.states.insert_right_of(right_tree, curr_state_id.id()); + + report = report.set_left(left_tree_ref); + report.set_right(right_tree_ref) + + } else { + let left_tree = StateTree::from((curr_state, None)); + let left_id = self.states.insert_left_of(left_tree, curr_state_id.id()); + + report.set_left(left_id) + } + + } + + // Returns the step record but does not mutate the Exec state tree + pub fn step(&self) -> StepRecord { // bool returns if there is a branch + let curr_state_id = self.states.id.clone(); + let mut curr_state = self.states.val.clone(); + let curr_inst = curr_state.curr_instruction(); + let curr_pc = curr_state.pc(); + let change_rec = curr_inst.exec(&curr_state); + + let is_branch = change_rec.constraints.is_some(); + curr_state.apply_change(change_rec.clone()); + let mut report = StepRecord::new(false, change_rec.halt); + if is_branch { + // then curr_state.apply generated the right branching state; thus, a state tree w/ + // an additional constraint + // and left tree (by convention left path represents straight line execution) is the negation of such constraint + let mut left_state = curr_state.clone(); + left_state.set_pc(curr_pc + 1); + if !left_state.can_continue() { + report.halted_left = true; + } + let left_tree = StateTree::from((left_state.clone(), change_rec.constraints.clone().unwrap().not())); + let right_tree = StateTree::from((left_state, change_rec.constraints.unwrap())); + + report.set_left(left_tree.id.clone()).set_right(right_tree.id.clone()) + + } else { + let left_tree = StateTree::from((curr_state, None)); + + report.set_left(left_tree.id.clone()) + } + + } + + + pub fn step_from_mut(&mut self, node_id: &NodeId) -> StepRecord { + let curr_state_id = node_id.clone(); + let mut curr_state_tree = self.states.find_by_id(node_id).unwrap().clone(); + let mut curr_state = &mut curr_state_tree.val; + if !curr_state.can_continue() { + + return StepRecord::new(true, true); + } + + let curr_inst = curr_state.curr_instruction(); + let curr_pc = curr_state.pc(); + let change_rec = curr_inst.exec(&curr_state); + + let is_branch = change_rec.constraints.is_some(); + curr_state.apply_change(change_rec.clone()); + let curr_state = curr_state; + let mut report = StepRecord::new(false, change_rec.halt); + // assert_eq!(change_rec.halt, curr_state.halt); + if is_branch { + // then curr_state.apply generated the right branching state; thus, a state tree w/ + // an additional constraint + // and left tree (by convention left path represents straight line execution) is the negation of such constraint + let mut left_state = curr_state.clone(); + left_state.set_pc(curr_pc + 1); + report.halted_left = left_state.halt; + + let left_tree = StateTree::from((left_state.clone(), change_rec.constraints.clone().unwrap().not())); + let right_tree = StateTree::from((left_state, change_rec.constraints.unwrap())); + let left_tree_ref = self.states.insert_left_of(left_tree, node_id.id()); + let right_tree_ref = self.states.insert_right_of(right_tree, node_id.id()); + // curr_state_tree.left = Some(Box::new(left_tree)); + // curr_state_tree.right = Some(Box::new(right_tree)); + + report.set_left(left_tree_ref) + .set_right(right_tree_ref) + + } else { + let left_tree = StateTree::from((curr_state.clone(), None)); + let left_tree_ref = self.states.insert_left_of(left_tree, curr_state_id.id()); + //curr_state_tree.left = Some(Box::new(left_tree)); + + report.set_left(left_tree_ref) + } + + + } +} + diff --git a/src/instruction/mod.rs b/src/instruction/mod.rs index 2305d8b..8193ca6 100644 --- a/src/instruction/mod.rs +++ b/src/instruction/mod.rs @@ -1444,7 +1444,16 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { Instruction::Create => todo!(), Instruction::Call => todo!(), Instruction::CallCode => todo!(), - Instruction::Return => todo!(), + Instruction::Return => { + MachineRecord { + mem: None, + stack: None, + storage: None, + pc: (mach.pc(), mach.pc()), + constraints: None, + halt: true, + } + }, Instruction::DelegateCall => todo!(), Instruction::Create2 => todo!(), Instruction::StaticCall => todo!(), diff --git a/src/lib.rs b/src/lib.rs index 662293d..62713be 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,6 +12,7 @@ pub mod traits; pub mod conversion; pub mod storage; pub mod parser; +pub mod exec; use paste::{expr, item, paste}; use instruction::*; use smt::*; diff --git a/src/machine.rs b/src/machine.rs index 8855eda..0f2a9b2 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -7,6 +7,7 @@ use z3_ext::{ AstKind, Config, Context, Model, SatResult, Solver, }; +use crate::exec::Execution; use crate::instruction::*; use crate::memory::*; use crate::state::evm::EvmState; @@ -63,6 +64,13 @@ pub struct TransactionContext { storage: HashMap } + +// The Evm is an *implementation* of the Machine trait +// Its job is merely to orchestrate the incremental construction of an Execution +// by initializing an Execution with a starting StateTree and calling Execution.step() +// It also provides a handler to an Execution, which in turn provides a handler to EvmState +// so that when an Instruction requires *reading* environmental / network state OR when an Instruction's behavior +// *depends* on env / network state, it can access it through the Evm, which can be initialized with things like a Transaction context #[derive(Clone)] pub struct Evm<'ctx> { pgm: Vec, @@ -72,44 +80,33 @@ pub struct Evm<'ctx> { } impl<'ctx> Evm<'ctx> { - // Given a machine (which has its internal state tree) & a machine record - // this method returns a new state tree containing all possible new machine states - // that would result from taking the step represented by the machine record - // fn state_transition(tree: StateTree<'ctx>, rec: MachineRecord<32>) -> StateTree { - // let MachineRecord {pc, stack, mem, constraints, halt} = rec.clone(); - // let mut curr_node = tree.val.clone(); - // let mut new_state = tree.clone(); - // eprintln!("STACK BEFORE STATE TRANSITION: {:#?}", curr_node.stack()); - // - // let (straight_exec, jump_exec) = curr_node.state_transition(rec); - // let (left_mach, mut left_mach_new_conds) = straight_exec; - // eprintln!("STACK AFTER STATE TRANSITION: {:#?}", left_mach.stack()); - // if let Some(conds) = tree.path_condition { - // left_mach_new_conds.push(conds.clone()); - // let cond_slice = left_mach_new_conds.iter().map(|c| c).collect::>(); - // new_state.insert_left((left_mach,Bool::and(ctx(), &cond_slice.as_slice()))); - // } - // - // - // if let Some(jump_state) = jump_exec { - // new_state.insert_right((jump_state.0, constraints)); - // } - // new_state - // - // todo!() - // } + pub fn with_pgm(pgm: Vec) -> Self { + let evm_state = EvmState::with_pgm(pgm.clone()); + Self { + pgm, + states: StateTree { + id: NodeId::new(), + val: evm_state, + path_condition: None, + left: None, + right: None, + }, + change_log: vec![], + inverse_state: Default::default(), + } + } + + pub fn set_init_state(&mut self, state: EvmState) { + self.states.val = state; + } + + } impl<'ctx> Evm<'ctx> { pub fn new(pgm: Vec) -> Self { - let evm_state = EvmState { - memory: Default::default(), - stack: Default::default(), - pc: 0, - pgm: pgm.clone(), - address: Address::default(), - storage: AccountStorage::default(), - }; + let evm_state = EvmState::with_pgm(pgm.clone()); + Self { pgm, states: StateTree { @@ -124,100 +121,135 @@ impl<'ctx> Evm<'ctx> { } } - pub fn exec_check(&mut self) -> Vec<(ExecBranch, Option>)> { - let evm_trace = self.exec(); - let mut solver = z3_ext::Solver::new(ctx()); - evm_trace - .into_iter() - .filter_map(|(state, constraints)| { - let constraint = constraints - .clone() - .into_iter() - .reduce(|c, e| Bool::and(ctx(), &[&c, &e])); - if let Some(constraint) = constraint { - solver.assert(&constraint); - } - match solver.check() { - SatResult::Sat => { - let model = solver.get_model(); - eprintln!( - "State {:#?} is reachable.\nMODEL:{:#?}", - state, - solver.get_model() - ); - Some(((state, constraints), model)) - } - SatResult::Unsat => { - eprintln!("Unsat"); - None - } - SatResult::Unknown => { - eprintln!("Unknown"); - None - } - } - }) - .collect::>() - } + // pub fn exec_check(&mut self) -> Vec<(ExecBranch, Option>)> { + // let evm_trace = self.exec(); + // let mut solver = z3_ext::Solver::new(ctx()); + // evm_trace + // .into_iter() + // .filter_map(|(state, constraints)| { + // let constraint = constraints + // .clone() + // .into_iter() + // .reduce(|c, e| Bool::and(ctx(), &[&c, &e])); + // if let Some(constraint) = constraint { + // solver.assert(&constraint); + // } + // match solver.check() { + // SatResult::Sat => { + // let model = solver.get_model(); + // eprintln!( + // "State {:#?} is reachable.\nMODEL:{:#?}", + // state, + // solver.get_model() + // ); + // Some(((state, constraints), model)) + // } + // SatResult::Unsat => { + // eprintln!("Unsat"); + // None + // } + // SatResult::Unknown => { + // eprintln!("Unknown"); + // None + // } + // } + // }) + // .collect::>() + // } } impl<'ctx> Machine<32> for Evm<'ctx> { type State = EvmState; - fn exec(&mut self) -> Vec> { - let mut curr_state = self.states.val.clone(); - let curr_id = self.states.id.clone(); - - let mut jump_ctx = vec![curr_id.id()]; - let mut state_tree = self.states.clone(); - let mut trace: Vec = vec![(curr_state, vec![])]; - let mut leaves: Vec = vec![]; - + fn exec(&mut self) -> Execution { + let mut halt = false; + let mut step_recs = vec![]; + let mut exec = Execution::new(self.states.val.clone(), self.pgm.clone()); + let first_step = exec.step_mut(); + step_recs.push(first_step); loop { - let curr_state = trace.pop(); - let mut temp_id_ptr = jump_ctx.pop(); - //eprintln!("Executing node with id {:?}", temp_id_ptr); - if let Some(curr_state) = curr_state { - let temp_id_ptr = temp_id_ptr.unwrap(); - - let (curr_state, curr_cond) = curr_state; - let mut curr_cond = curr_cond.clone(); - let mut branch_cond_pre = curr_cond.clone(); - let (next_state, next_state_branch) = curr_state.exec_once(); - if let Some(branch) = next_state_branch { - let (branch_state, branch_cond) = branch; - branch_cond_pre.extend(branch_cond); - let branch = (branch_state.clone(), branch_cond_pre.clone()); - - let branch_right_id = state_tree.insert_right_of(branch.clone(), temp_id_ptr); - - jump_ctx.push(branch_right_id); - if branch_state.can_continue() { - trace.push(branch); - } else { - leaves.push(branch); + if let Some(step) = step_recs.pop() { + eprintln!("HALTED LEFT: {}, HALTED RIGHT: {}", step.halted_left(), step.halted_right()); + if !step.halted_right() { + let continue_from_right = step.right_id(); + if let Some(right_id) = continue_from_right { + let nxt_right_step = exec.step_from_mut(right_id); + step_recs.push(nxt_right_step); + } + } + if !step.halted_left() { + let continue_from_left = step.left_id(); + if let Some(left_id) = continue_from_left { + let nxt_step = exec.step_from_mut(left_id); + step_recs.push(nxt_step); } - } - let (nxt_state, nxt_constraints) = next_state; - curr_cond.extend(nxt_constraints); - let branch = (nxt_state.clone(), curr_cond.clone()); - // eprintln!("Inserting to the left of {:?}", temp_id_ptr); - - let branch_left_id = state_tree.insert_left_of(branch.clone(), temp_id_ptr); - // eprintln!("Inserted {} to the left of {}", branch_left_id, temp_id_ptr); - if nxt_state.can_continue() { - trace.push(branch); - jump_ctx.push(branch_left_id); - } else { - leaves.push(branch); } } else { break; } } - self.states = state_tree; - leaves + + exec } + // fn exec(&mut self) -> Vec> { + // let mut curr_state = self.states.val.clone(); + // let curr_id = self.states.id.clone(); + + // let mut jump_ctx = vec![curr_id.id()]; + // let mut state_tree = self.states.clone(); + // let mut trace: Vec = vec![(curr_state, vec![])]; + // let mut leaves: Vec = vec![]; + + // loop { + // let curr_state = trace.pop(); + // let mut temp_id_ptr = jump_ctx.pop(); + // //eprintln!("Executing node with id {:?}", temp_id_ptr); + // if let Some(curr_state) = curr_state { + // let temp_id_ptr = temp_id_ptr.unwrap(); + + // let (curr_state, curr_cond) = curr_state; + // let mut curr_cond = curr_cond.clone(); + // let mut branch_cond_pre = curr_cond.clone(); + // let (next_state, next_state_branch, halt) = curr_state.exec_once(); + // if let Some(branch) = next_state_branch { + // let (branch_state, branch_cond) = branch; + // branch_cond_pre.extend(branch_cond); + // let branch = (branch_state.clone(), branch_cond_pre.clone()); + + // let branch_right_id = state_tree.insert_right_of(branch.clone(), temp_id_ptr); + + // jump_ctx.push(branch_right_id); + // if branch_state.can_continue() { + // trace.push(branch); + // } else { + // leaves.push(branch); + // } + // } + + // let (nxt_state, nxt_constraints) = next_state; + // eprintln!("NEXT STATE {:#?}", nxt_state); + // curr_cond.extend(nxt_constraints); + // let branch = (nxt_state.clone(), curr_cond.clone()); + // // eprintln!("Inserting to the left of {:?}", temp_id_ptr); + + // let branch_left_id = state_tree.insert_left_of(branch.clone(), temp_id_ptr); + // // eprintln!("Inserted {} to the left of {}", branch_left_id, temp_id_ptr); + // if nxt_state.can_continue() && !halt { + // trace.push(branch); + // jump_ctx.push(branch_left_id); + // } else { + // leaves.push(branch); + // } + // if halt { + // break; + // } + // } else { + // break; + // } + // } + // self.states = state_tree; + // leaves + // } fn pgm(&self) -> Vec { self.pgm.clone() @@ -245,7 +277,7 @@ impl MachineState<32> for EvmState { type PC = usize; fn pc(&self) -> Self::PC { - self.pc + self.pgm_counter() } fn stack(&self) -> &Stack<32> { @@ -324,26 +356,31 @@ fn machine_returns_one_exec_for_non_branching_pgm() { ]; let mut evm = Evm::new(pgm); - - { - let sat_branches = evm.exec_check(); - assert!( - sat_branches.first().is_some() - && sat_branches - .first() - .unwrap() - .0 - .0 - .stack() - .peek_nth(1) - .cloned() - .unwrap() - == bvi(100) - ); - - assert_eq!(sat_branches.len(), 1); - } - eprintln!("STATES > {:#?}", evm.states); + let execution = evm.exec(); + let exec_tree = &execution.states; + let final_states = exec_tree.leaves(); + assert_eq!(2, final_states.len()); + assert_eq!(final_states.first().unwrap().val.stack().peek_nth(1).cloned().unwrap(), bvi(100)); + eprintln!("Final states: {:#?}", final_states); + // { + // let sat_branches = evm.exec_check(); + // assert!( + // sat_branches.first().is_some() + // && sat_branches + // .first() + // .unwrap() + // .0 + // .0 + // .stack() + // .peek_nth(1) + // .cloned() + // .unwrap() + // == bvi(100) + // ); + + // assert_eq!(sat_branches.len(), 1); + // } + // eprintln!("STATES > {:#?}", evm.states); } #[test] @@ -373,20 +410,20 @@ fn test_mem_store_mem_load() { */ let mut evm = Evm::new(pgm); - { - let sat_branches = evm.exec_check(); - assert_eq!(sat_branches.len(), 1); - let top = sat_branches - .first() - .unwrap() - .0 - .0 - .stack() - .peek() - .cloned() - .unwrap(); - eprintln!("Stack top size: {:#?}", top.as_ref().get_size()); - assert_eq!(top, bvi(3)); - } + // { + // let sat_branches = evm.exec_check(); + // assert_eq!(sat_branches.len(), 1); + // let top = sat_branches + // .first() + // .unwrap() + // .0 + // .0 + // .stack() + // .peek() + // .cloned() + // .unwrap(); + // eprintln!("Stack top size: {:#?}", top.as_ref().get_size()); + // assert_eq!(top, bvi(3)); + // } eprintln!("STATES > {:#?}", evm.states); } diff --git a/src/memory.rs b/src/memory.rs index b927d0b..0f9a8b4 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -77,9 +77,11 @@ impl Memory { let idx: usize = idx.into(); let mut bytes = vec![]; let mut mem = self.inner.clone(); + eprintln!(" MEM IN READ WORD: {:#?}", mem); while i < 32 { let idx = idx + 31; let val = mem.get(idx - i).unwrap().as_ref().clone(); + eprintln!("MEM VAL IN READ WORD FOR IDX - i:\nmem loc {:#?}\nval: {:#?}", (idx - i), val); bytes.push(val); i += 1; } diff --git a/src/state/evm.rs b/src/state/evm.rs index a998628..8729100 100644 --- a/src/state/evm.rs +++ b/src/state/evm.rs @@ -16,9 +16,10 @@ pub struct EvmState { pub memory: Memory, pub storage: AccountStorage, pub stack: Stack<32>, - pub pc: usize, + pc: usize, pub pgm: Vec, - pub address: Address + pub address: Address, + pub halt: bool, } impl MachineComponent for EvmState { @@ -39,64 +40,42 @@ impl MachineComponent for EvmState { if let Some(stack) = stack { self.stack.apply_change(stack); } - - self.pc = pc.1; + self.halt = halt; + self.set_pc(pc.1); } } impl<'ctx> EvmState { - pub fn can_continue(&self) -> bool { - self.pc < self.pgm.len() - } - pub fn curr_instruction(&self) -> Instruction { - self.pgm.get(self.pc).cloned().unwrap() - } - - pub fn exec_once(mut self) -> (ExecBranch<'ctx>, Option>) { - let inst = self.curr_instruction(); - eprintln!("CURRENT INSTRUCTION: {:#?} at pc: {}", inst, self.pc); - let change = inst.exec(&self); - self.state_transition(change) - } - // Generates a set of next possible EvmStates given the state change record - pub fn state_transition( - &self, - rec: MachineRecord<32>, - ) -> (ExecBranch<'ctx>, Option>) { - let MachineRecord { - halt, - pc, - stack, - mem, - constraints, - storage - } = rec; - let mut new_state = self.clone(); - if halt { - return ((new_state, vec![]), None); - } - if let Some(stack_rec) = stack { - new_state.stack_apply(stack_rec); + pub fn with_pgm(pgm: Vec) -> Self { + Self { + pgm, + ..Default::default() } + } - if let Some(mem_rec) = mem { - new_state.mem_apply(mem_rec); + pub fn pgm_counter(&self) -> usize { + self.pc + } + pub fn set_pc(&mut self, new_pc: usize) { + self.pc = new_pc; + if self.pc >= self.pgm.len() { + self.halt = true; } + } - if let Some(constraint) = constraints { - let mut does_jump_state = new_state.clone(); - does_jump_state.pc = pc.1; - new_state.pc += 1; - ( - (new_state, vec![constraint.not()]), - Some((does_jump_state, vec![constraint])), - ) - } else { - assert_eq!(pc.1, (pc.0 + 1)); - new_state.pc = pc.1; - - ((new_state, vec![]), None) + pub fn inc_pc(&mut self) { + self.set_pc(self.pc + 1); + } + pub fn can_continue(&self) -> bool { + self.pc < self.pgm.len() && !self.halt + } + pub fn curr_instruction(&self) -> Instruction { + if !self.can_continue() { + eprintln!("EVM STATE CANNOT CONTINUE; BUT CURR INST IS REQUESTED: {:#?}", self); + eprintln!("Getting curr inst.. curr pc: {} and curr pgm len: {}", self.pc, self.pgm.len()); } + self.pgm.get(self.pc).cloned().unwrap() } + } diff --git a/src/state/tree.rs b/src/state/tree.rs index e94b8e3..896a52e 100644 --- a/src/state/tree.rs +++ b/src/state/tree.rs @@ -43,8 +43,8 @@ impl NodeId { #[derive(Clone, Debug, Default)] pub struct StateTree<'ctx> { - pub(crate) id: NodeId, - pub(crate) val: EvmState, + pub id: NodeId, + pub val: EvmState, pub(crate) path_condition: Option>, pub(crate) left: Option>>, pub(crate) right: Option>>, @@ -129,17 +129,38 @@ impl<'ctx> StateTree<'ctx> { } } + pub fn find_by_id(&self, id: &NodeId) -> Option<&StateTree<'ctx>> { + if self.id == *id { + Some(self) + } else { + if let Some(left) = self.left.as_ref() { + if let Some(found_l) = left.find_by_id(id) { + return Some(found_l); + } + } + if let Some(right) = self.right.as_ref() { + if let Some(found_r) = right.find_by_id(id) { + return Some(found_r); + } + } + None + + } + } + + pub fn insert_left_helper( &mut self, tree: impl Into>, id: Uuid, - ) -> Option { + ) -> Option<&StateTree> { let tree = tree.into(); let inserted_id = tree.id.id; if self.id.id == id { - self.left = Some(Box::new(tree)); - Some(inserted_id) + let tree = Box::new(tree); + self.left = Some(tree); + self.left.as_ref().map(|t| t.as_ref()) } else { let left_result = if let Some(left) = &mut self.left { left.insert_left_helper(tree.clone(), id) @@ -163,13 +184,13 @@ impl<'ctx> StateTree<'ctx> { &mut self, tree: impl Into>, id: Uuid, - ) -> Option { + ) -> Option<&StateTree> { let tree = tree.into(); let inserted_id = tree.id.id; if self.id.id == id { self.right = Some(Box::new(tree)); - Some(inserted_id) + self.right.as_ref().map(|t| t.as_ref()) } else { let left_result = if let Some(left) = &mut self.left { left.insert_right_helper(tree.clone(), id) @@ -188,9 +209,9 @@ impl<'ctx> StateTree<'ctx> { } } } - pub fn insert_left_of(&mut self, tree: impl Into>, id: Uuid) -> Uuid { + pub fn insert_left_of(&mut self, tree: impl Into>, id: Uuid) -> NodeId { match self.insert_left_helper(tree, id) { - Some(i) => i, + Some(i) => i.id.clone(), None => panic!("Could not find id {id} in the state tree"), } // if self.id.id == id { @@ -207,9 +228,9 @@ impl<'ctx> StateTree<'ctx> { // eprintln!("ALL NODES: {:?}", self.inorder()); } - pub fn insert_right_of(&mut self, tree: impl Into>, id: Uuid) -> Uuid { + pub fn insert_right_of(&mut self, tree: impl Into>, id: Uuid) -> NodeId { match self.insert_right_helper(tree, id) { - Some(i) => i, + Some(i) => i.id.clone(), None => panic!("Could not find id {id} in the state tree"), } } @@ -217,25 +238,36 @@ impl<'ctx> StateTree<'ctx> { pub fn leaves(&self) -> Vec { let mut leaves = vec![]; + if self.left.is_none() && self.right.is_none() { leaves.push((self.val.clone(), self.path_condition.clone()).into()); return leaves; } - if let Some(left) = &self.left { - if left.left.is_none() && left.right.is_none() { - leaves.push((left.val.clone(), left.path_condition.clone()).into()); - } else { - leaves.extend(left.leaves()); - } + + if let Some(left) = self.left.as_ref() { + leaves.extend(left.leaves()); } - if let Some(right) = &self.right { - if right.right.is_none() && right.left.is_none() { - leaves.push((right.val.clone(), right.path_condition.clone()).into()); - } else { - leaves.extend(right.leaves()); - } + if let Some(right) = self.right.as_ref() { + leaves.extend(right.leaves()) } + + // if let Some(left) = &self.left { + + // if left.left.is_none() && left.right.is_none() { + // leaves.push((left.val.clone(), left.path_condition.clone()).into()); + // } else { + // leaves.extend(left.leaves()); + // } + // } + + // if let Some(right) = &self.right { + // if right.right.is_none() && right.left.is_none() { + // leaves.push((right.val.clone(), right.path_condition.clone()).into()); + // } else { + // leaves.extend(right.leaves()); + // } + // } leaves } diff --git a/src/traits.rs b/src/traits.rs index 5a8b5a4..7e1a132 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -1,3 +1,4 @@ +use crate::exec::Execution; use crate::instruction::Instruction; use crate::machine::{ExecBranch, ExecutionSummary}; use crate::memory::Memory; @@ -30,7 +31,7 @@ pub trait Machine { type State: MachineState; // All possible final states - fn exec(&mut self) -> Vec; + fn exec(&mut self) -> Execution; fn pgm(&self) -> Vec; fn state(&self) -> Self::State; fn state_ref(&self) -> &Self::State; diff --git a/test-contracts/src/StorageSimple.sol b/test-contracts/src/StorageSimple.sol index bd1e5ce..6de7606 100644 --- a/test-contracts/src/StorageSimple.sol +++ b/test-contracts/src/StorageSimple.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.0 <0.9.0; +pragma solidity ^0.8.3; contract SimpleStorage { mapping (uint => uint) public ids; diff --git a/tests/lib.rs b/tests/lib.rs index f71c19b..a9b5b1e 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -12,29 +12,71 @@ use ser::{ }; use z3::ast::*; -pub const SIMPLE_COUNTER: &str = r"6080604052348015600f57600080fd5b5060043610603c5760003560e01c80633fb5c1cb1460415780638381f58a146053578063d09de08a14606d575b600080fd5b6051604c3660046083565b600055565b005b605b60005481565b60405190815260200160405180910390f35b6051600080549080607c83609b565b9190505550565b600060208284031215609457600080fd5b5035919050565b60006001820160ba57634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220f0cfb2159c518c3da0ad864362bad5dc0715514a9ab679237253d506773a0a1b64736f6c63430008130033"; pub const COUNTER_WITH_STORAGE_MAPPING: &str = r#"608060405234801561001057600080fd5b5060056000806001815260200190815260200160002081905550610197806100396000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063846719e01461003b578063d78233d61461006b575b600080fd5b6100556004803603810190610050919061010a565b61009b565b6040516100629190610146565b60405180910390f35b6100856004803603810190610080919061010a565b6100b7565b6040516100929190610146565b60405180910390f35b6000806000838152602001908152602001600020549050919050565b60006020528060005260406000206000915090505481565b600080fd5b6000819050919050565b6100e7816100d4565b81146100f257600080fd5b50565b600081359050610104816100de565b92915050565b6000602082840312156101205761011f6100cf565b5b600061012e848285016100f5565b91505092915050565b610140816100d4565b82525050565b600060208201905061015b6000830184610137565b9291505056fea2646970667358fe122066b287fef10118cba238fe38953bfefe938afefefefefe94fefe3682fefefefe64736f6c63430008110033"#; +pub const SUPERSIMPLE: &str = r#"604260005260206000F3"#; +pub const STORAGE_SIMPLE: &str = r#"6080604052348015600f57600080fd5b506004361060325760003560e01c80631ab06ee5146037578063fac333ac146056575b600080fd5b605460423660046085565b60009182526020829052604090912055565b005b6073606136600460a6565b60006020819052908152604090205481565b60405190815260200160405180910390f35b60008060408385031215609757600080fd5b50508035926020909101359150565b60006020828403121560b757600080fd5b503591905056fea26469706673582212204a6bf5c04a6e273d775914b20b0bab1bca28228be5562d496002981e13ff015264736f6c63430008130033"#; +#[test] + +fn can_run_simple_parsed_pgm() { + let pgm = Parser::with_pgm(SUPERSIMPLE).parse(); + let mut evm = Evm::new(pgm); + + { + let sat_branches = evm.exec(); + //eprintln!("EXECUTION: {:#?}", sat_branches); + + // eprintln!("SAT BRANCHES: {:#?}", sat_branches); + // assert_eq!(sat_branches.len(), 1); + // let top = sat_branches + // .first() + // .unwrap() + // .0 + // .0 + // .stack() + // .peek() + // .cloned() + // .unwrap(); + // eprintln!("Stack top size: {:#?}", top.as_ref().get_size()); + // assert_eq!(top, bvi(5)); + let leaf = sat_branches.states.leaves(); + assert_eq!(1, leaf.len()); + let final_tree = leaf.first().unwrap().clone(); + // eprintln!("FINAL TREE: {:#?}", final_tree); + let mut mem_val = final_tree.val.mem_read(bvi(0)); + mem_val.simplify(); + assert_eq!(bvi(66), mem_val); + } +} #[test] -#[ignore] -fn can_run_stored_pgm() { - let pgm = Parser::with_pgm(SIMPLE_COUNTER).parse(); +fn can_run_simple_storage_pgm() { + let pgm = Parser::with_pgm(STORAGE_SIMPLE).parse(); let mut evm = Evm::new(pgm); { - let sat_branches = evm.exec_check(); - assert_eq!(sat_branches.len(), 1); - let top = sat_branches - .first() - .unwrap() - .0 - .0 - .stack() - .peek() - .cloned() - .unwrap(); - eprintln!("Stack top size: {:#?}", top.as_ref().get_size()); - assert_eq!(top, bvi(5)); + let sat_branches = evm.exec(); + //eprintln!("EXECUTION: {:#?}", sat_branches); + + // eprintln!("SAT BRANCHES: {:#?}", sat_branches); + // assert_eq!(sat_branches.len(), 1); + // let top = sat_branches + // .first() + // .unwrap() + // .0 + // .0 + // .stack() + // .peek() + // .cloned() + // .unwrap(); + // eprintln!("Stack top size: {:#?}", top.as_ref().get_size()); + // assert_eq!(top, bvi(5)); + let leaf = sat_branches.states.leaves(); + assert_eq!(2, leaf.len()); + eprintln!("LEAVES: {:#?}", leaf); + let final_tree = leaf.get(1).unwrap().clone(); + // eprintln!("FINAL TREE: {:#?}", final_tree); + let mut mem_val = final_tree.val.mem_read(bvi(64)); + mem_val.simplify(); + assert_eq!(bvi(128), mem_val); } - eprintln!("STATES > {:#?}", evm.states); } \ No newline at end of file From 9ce2d043605c373dc6e4e56ed17da1db21bb36ab Mon Sep 17 00:00:00 2001 From: tannr Date: Wed, 2 Aug 2023 14:35:26 -0400 Subject: [PATCH 18/28] code cleanup --- examples/simple_pgm.rs | 17 +- examples/simple_storage.rs | 23 +-- src/conversion/mod.rs | 60 +++---- src/exec/mod.rs | 82 ++++----- src/instruction/mod.rs | 58 +++--- src/lib.rs | 18 +- src/machine.rs | 52 +++--- src/memory.rs | 13 +- src/parser.rs | 360 +++++++++++++++++-------------------- src/record.rs | 11 +- src/smt/bitvec/mod.rs | 7 +- src/smt/bitvec/z3.rs | 1 - src/state/env.rs | 1 - src/state/evm.rs | 19 +- src/state/tree.rs | 5 +- src/storage.rs | 135 ++++++++------ tests/lib.rs | 69 ++----- tests/test_storage.rs | 1 + 18 files changed, 430 insertions(+), 502 deletions(-) diff --git a/examples/simple_pgm.rs b/examples/simple_pgm.rs index 7555b4d..7dc2cdf 100644 --- a/examples/simple_pgm.rs +++ b/examples/simple_pgm.rs @@ -1,19 +1,9 @@ - - +#![allow(unused_imports)] use ser::{ - traits::*, - machine::*, - stack::*, - storage::*, - memory::*, - conversion::*, - bvc, - bvi, - parser::*, + bvc, bvi, conversion::*, machine::*, memory::*, parser::*, stack::*, storage::*, traits::*, }; use z3::ast::*; - pub const SUPERSIMPLE: &str = r#"604260005260206000F3"#; fn main() { let pgm = Parser::with_pgm(SUPERSIMPLE).parse(); @@ -23,8 +13,7 @@ fn main() { let leaf = execution_trace.states.leaves(); assert_eq!(1, leaf.len()); let final_tree = leaf.first().unwrap().clone(); - // eprintln!("FINAL TREE: {:#?}", final_tree); - + let mut mem_val = final_tree.val.mem_read(bvi(0)); mem_val.simplify(); assert_eq!(bvi(66), mem_val); diff --git a/examples/simple_storage.rs b/examples/simple_storage.rs index cf0fa2b..1eaed2c 100644 --- a/examples/simple_storage.rs +++ b/examples/simple_storage.rs @@ -1,33 +1,22 @@ - - +#![allow(unused_imports)] use ser::{ - traits::*, - machine::*, - stack::*, - storage::*, - memory::*, - conversion::*, - bvc, - bvi, - parser::*, + bvc, bvi, conversion::*, machine::*, memory::*, parser::*, stack::*, storage::*, traits::*, }; use z3::ast::*; -pub const STORAGE_SIMPLE: &str = r#"6080604052348015600f57600080fd5b506004361060325760003560e01c80631ab06ee5146037578063fac333ac146056575b600080fd5b605460423660046085565b60009182526020829052604090912055565b005b6073606136600460a6565b60006020819052908152604090205481565b60405190815260200160405180910390f35b60008060408385031215609757600080fd5b50508035926020909101359150565b60006020828403121560b757600080fd5b503591905056fea26469706673582212204a6bf5c04a6e273d775914b20b0bab1bca28228be5562d496002981e13ff015264736f6c63430008130033"#; - +pub const STORAGE_SIMPLE: &str = r#"6080604052348015600f57600080fd5b506004361060325760003560e01c80631ab06ee5146037578063fac333ac146056575b600080fd5b605460423660046085565b60009182526020829052604090912055565b005b6073606136600460a6565b60006020819052908152604090205481565b60405190815260200160405180910390f35b60008060408385031215609757600080fd5b50508035926020909101359150565b60006020828403121560b757600080fd5b503591905056fea26469706673582212204a6bf5c04a6e273d775914b20b0bab1bca28228be5562d496002981e13ff015264736f6c63430008130033"#; fn main() { let pgm = Parser::with_pgm(STORAGE_SIMPLE).parse(); let mut evm = Evm::new(pgm); - let execution = evm.exec(); - + let leaf = execution.states.leaves(); assert_eq!(2, leaf.len()); - + let final_tree = leaf.get(1).unwrap().clone(); - + let mut mem_val = final_tree.val.mem_read(bvi(64)); // 0x40 mem_val.simplify(); assert_eq!(bvi(128), mem_val); // 0x80 diff --git a/src/conversion/mod.rs b/src/conversion/mod.rs index 5d058d5..2d8521b 100644 --- a/src/conversion/mod.rs +++ b/src/conversion/mod.rs @@ -1,22 +1,27 @@ use std::cmp::Ordering; -use ruint::{uint, Uint, ToUintError, FromUintError, Bits}; -use rlp::{Encodable, Decodable}; -use z3_ext::{ast::Ast, Context}; +use crate::{ + bvc, bvi, bvi_8byte, ctx, + instruction::{push32, Instruction}, + parser::zero_extend, + record::push, + BVType, BitVec, BV, +}; +use rlp::{Decodable, Encodable}; +use ruint::{uint, Bits, FromUintError, ToUintError, Uint}; use serde::{Deserialize, Serialize}; -use crate::{BV, BVType, BitVec, bvc, bvi, ctx, bvi_8byte, parser::zero_extend, record::push, instruction::{push32, Instruction}}; +use z3_ext::{ast::Ast, Context}; impl From> for BitVec<32> { fn from(value: Uint<256, 4>) -> Self { - let mut bv: BV<'static> = BV::from_u64(ctx(), 0, 8); - let bytes: [u8; 32] = value.clone().to_be_bytes(); - - for i in bytes.iter() { - let new_bv: BV<'static> = bvi::<1>(*i).into(); - bv = bv.concat(&new_bv).simplify(); - } - bv.extract(256 - 8 - 1, 0).simplify().into() + let mut bv: BV<'static> = BV::from_u64(ctx(), 0, 8); + let bytes: [u8; 32] = value.clone().to_be_bytes(); + for i in bytes.iter() { + let new_bv: BV<'static> = bvi::<1>(*i).into(); + bv = bv.concat(&new_bv).simplify(); + } + bv.extract(256 - 8 - 1, 0).simplify().into() } } @@ -29,13 +34,10 @@ impl From> for Uint<256, 4> { let offset = 256 - (i * 8) - 1; let byte_extract: BV<'static> = value.extract(offset, offset - 7).simplify(); // since byte_extract is a single byte, downcasting to u8 will not change the number - let byte = byte_extract.as_u64().unwrap() as u8; + let byte = byte_extract.as_u64().unwrap() as u8; numbits[i as usize] = byte; - - } Bits::from_be_bytes(numbits).as_uint().clone() - } } @@ -74,17 +76,17 @@ impl From> for BV<'static> { impl From<[u8; SZ]> for BitVec { fn from(value: [u8; SZ]) -> Self { let ctx: &'static Context = ctx(); - let mut bv: BV<'static> = BV::from_u64(ctx, 0, 8); - + let mut bv: BV<'static> = BV::from_u64(ctx, 0, 8); - for i in value.iter() { - let new_bv: BV<'static> = bvi::<1>(*i).into(); + for i in value.iter() { + let new_bv: BV<'static> = bvi::<1>(*i).into(); bv = bv.concat(&new_bv).simplify(); - - } - eprintln!("VALUE CONVERTING FROM: {:#x?}", value); - eprintln!("BV IN SLICE CONVERT: {:#?} SIZE: {}", bv, bv.get_size()); - bv.extract((bv.get_size() - 8 - 1) as u32, 0).simplify().into() + } + eprintln!("VALUE CONVERTING FROM: {:#x?}", value); + eprintln!("BV IN SLICE CONVERT: {:#?} SIZE: {}", bv, bv.get_size()); + bv.extract((bv.get_size() - 8 - 1) as u32, 0) + .simplify() + .into() } } @@ -111,12 +113,12 @@ fn test_slice_to_op_arg() { #[test] fn test_slice_to_bitvec() { let mut slice8 = 327000_u64.to_be_bytes(); - + let slice_full = zero_extend::<32>(&slice8); let bv: BitVec<32> = slice_full.into(); let num = uint!(0x000000000000000000000000000000000000000000000000000000000004FD58_U256); - let bv_as_num: Uint<256,4> = bv.into(); + let bv_as_num: Uint<256, 4> = bv.into(); assert_eq!(num, bv_as_num); } @@ -144,7 +146,6 @@ fn test_to_bv() { let mut expected = bvi(9); expected.simplify(); assert_eq!(expected, bv_2); - } #[test] @@ -153,5 +154,4 @@ fn test_from_bv() { let num = uint!(0x000000000000000000000000000000000000000000000000000000000004FD58_U256); let bv_to_num: Uint<256, 4> = bv.into(); assert_eq!(num, bv_to_num); - -} \ No newline at end of file +} diff --git a/src/exec/mod.rs b/src/exec/mod.rs index 63db239..d1c208e 100644 --- a/src/exec/mod.rs +++ b/src/exec/mod.rs @@ -1,34 +1,34 @@ use uuid::Uuid; -use crate::{record::{ - MachineRecord -}, instruction::Instruction, traits::{MachineInstruction, MachineComponent, MachineState}}; use crate::state::evm::EvmState; use crate::state::tree::*; - +use crate::{ + instruction::Instruction, + record::MachineRecord, + traits::{MachineComponent, MachineInstruction, MachineState}, +}; #[derive(Default, Debug)] pub struct Execution<'ctx> { changes: Vec>, program: Vec, - pub states: StateTree<'ctx> + pub states: StateTree<'ctx>, } #[derive(Default, Debug)] -pub struct StepRecord - -{ +pub struct StepRecord { left_insert: Option, right_insert: Option, halted_left: bool, - halted_right: bool + halted_right: bool, } impl StepRecord { - pub fn new(halted_left: bool, halted_right: bool) -> Self { Self { - halted_left, halted_right, ..Default::default() + halted_left, + halted_right, + ..Default::default() } } pub fn halted_left(&self) -> bool { @@ -61,7 +61,6 @@ impl StepRecord { } impl<'ctx> Execution<'ctx> { - pub fn new(start_state: EvmState, pgm: Vec) -> Self { Self { program: pgm, @@ -71,7 +70,8 @@ impl<'ctx> Execution<'ctx> { } // Returns the StepRecord AND updates the Exec state tree - pub fn step_mut(&mut self) -> StepRecord { // bool returns if there is a branch + pub fn step_mut(&mut self) -> StepRecord { + // bool returns if there is a branch let curr_state_id = self.states.id.clone(); let mut curr_state = self.states.val.clone(); let curr_inst = curr_state.curr_instruction(); @@ -90,29 +90,30 @@ impl<'ctx> Execution<'ctx> { if !left_state.can_continue() { report.halted_left = true; } - - let left_tree = StateTree::from((left_state.clone(), change_rec.constraints.clone().unwrap().not())); + + let left_tree = StateTree::from(( + left_state.clone(), + change_rec.constraints.clone().unwrap().not(), + )); let right_tree = StateTree::from((left_state, change_rec.constraints.unwrap())); - + let left_tree_ref = self.states.insert_left_of(left_tree, curr_state_id.id()); - - + let right_tree_ref = self.states.insert_right_of(right_tree, curr_state_id.id()); - + report = report.set_left(left_tree_ref); report.set_right(right_tree_ref) - } else { let left_tree = StateTree::from((curr_state, None)); let left_id = self.states.insert_left_of(left_tree, curr_state_id.id()); - + report.set_left(left_id) } - } // Returns the step record but does not mutate the Exec state tree - pub fn step(&self) -> StepRecord { // bool returns if there is a branch + pub fn step(&self) -> StepRecord { + // bool returns if there is a branch let curr_state_id = self.states.id.clone(); let mut curr_state = self.states.val.clone(); let curr_inst = curr_state.curr_instruction(); @@ -131,29 +132,30 @@ impl<'ctx> Execution<'ctx> { if !left_state.can_continue() { report.halted_left = true; } - let left_tree = StateTree::from((left_state.clone(), change_rec.constraints.clone().unwrap().not())); + let left_tree = StateTree::from(( + left_state.clone(), + change_rec.constraints.clone().unwrap().not(), + )); let right_tree = StateTree::from((left_state, change_rec.constraints.unwrap())); - - report.set_left(left_tree.id.clone()).set_right(right_tree.id.clone()) + report + .set_left(left_tree.id.clone()) + .set_right(right_tree.id.clone()) } else { let left_tree = StateTree::from((curr_state, None)); - + report.set_left(left_tree.id.clone()) } - } - pub fn step_from_mut(&mut self, node_id: &NodeId) -> StepRecord { let curr_state_id = node_id.clone(); let mut curr_state_tree = self.states.find_by_id(node_id).unwrap().clone(); let mut curr_state = &mut curr_state_tree.val; if !curr_state.can_continue() { - return StepRecord::new(true, true); } - + let curr_inst = curr_state.curr_instruction(); let curr_pc = curr_state.pc(); let change_rec = curr_inst.exec(&curr_state); @@ -162,7 +164,7 @@ impl<'ctx> Execution<'ctx> { curr_state.apply_change(change_rec.clone()); let curr_state = curr_state; let mut report = StepRecord::new(false, change_rec.halt); - // assert_eq!(change_rec.halt, curr_state.halt); + // assert_eq!(change_rec.halt, curr_state.halt); if is_branch { // then curr_state.apply generated the right branching state; thus, a state tree w/ // an additional constraint @@ -170,26 +172,24 @@ impl<'ctx> Execution<'ctx> { let mut left_state = curr_state.clone(); left_state.set_pc(curr_pc + 1); report.halted_left = left_state.halt; - - let left_tree = StateTree::from((left_state.clone(), change_rec.constraints.clone().unwrap().not())); + + let left_tree = StateTree::from(( + left_state.clone(), + change_rec.constraints.clone().unwrap().not(), + )); let right_tree = StateTree::from((left_state, change_rec.constraints.unwrap())); let left_tree_ref = self.states.insert_left_of(left_tree, node_id.id()); let right_tree_ref = self.states.insert_right_of(right_tree, node_id.id()); // curr_state_tree.left = Some(Box::new(left_tree)); // curr_state_tree.right = Some(Box::new(right_tree)); - - report.set_left(left_tree_ref) - .set_right(right_tree_ref) + report.set_left(left_tree_ref).set_right(right_tree_ref) } else { let left_tree = StateTree::from((curr_state.clone(), None)); let left_tree_ref = self.states.insert_left_of(left_tree, curr_state_id.id()); //curr_state_tree.left = Some(Box::new(left_tree)); - + report.set_left(left_tree_ref) } - - } } - diff --git a/src/instruction/mod.rs b/src/instruction/mod.rs index 8193ca6..397c601 100644 --- a/src/instruction/mod.rs +++ b/src/instruction/mod.rs @@ -10,18 +10,16 @@ use crate::state::evm::EvmState; use crate::storage::StorageValue; use crate::traits::*; use crate::{ - random_bv_arg, bvi, machine::Evm, memory::Memory, + random_bv_arg, record::{Index, MachineRecord, StackChange, StackOp}, stack::Stack, }; use super::smt::*; - - #[derive(Clone, Debug, PartialEq, Eq)] pub enum Instruction { Stop, @@ -180,7 +178,7 @@ fn exec_dup_nth(mach: &EvmState, n: usize) -> MachineRecord<32> { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, - storage: None, + storage: None, constraints: None, } } @@ -869,13 +867,16 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { mem: None, stack: Some(stack_change), storage: Some(StorageChange { - log: vec![StorageOp::Read { addr: mach.address.clone(), idx: key.clone() }], + log: vec![StorageOp::Read { + addr: mach.address.clone(), + idx: key.clone(), + }], }), - pc:(mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + 1), constraints: None, halt: false, } - }, + } Instruction::SStore => { let key = mach.stack().peek().unwrap(); let val = mach.stack().peek_nth(1).unwrap(); @@ -883,10 +884,14 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { let stack_rec = StackChange { pop_qty: 2, push_qty: 0, - ops: vec![StackOp::Pop, StackOp::Pop] + ops: vec![StackOp::Pop, StackOp::Pop], }; let storage_change = StorageChange { - log: vec![StorageOp::Write { addr: mach.address.clone(), idx: key.clone(), val: val.clone() }], + log: vec![StorageOp::Write { + addr: mach.address.clone(), + idx: key.clone(), + val: val.clone(), + }], }; MachineRecord { @@ -897,8 +902,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { constraints: None, halt: false, } - - }, + } Instruction::Jump => todo!(), Instruction::JumpI => { let jump_dest = mach.stack().peek().unwrap(); @@ -1444,28 +1448,24 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { Instruction::Create => todo!(), Instruction::Call => todo!(), Instruction::CallCode => todo!(), - Instruction::Return => { - MachineRecord { - mem: None, - stack: None, - storage: None, - pc: (mach.pc(), mach.pc()), - constraints: None, - halt: true, - } + Instruction::Return => MachineRecord { + mem: None, + stack: None, + storage: None, + pc: (mach.pc(), mach.pc()), + constraints: None, + halt: true, }, Instruction::DelegateCall => todo!(), Instruction::Create2 => todo!(), Instruction::StaticCall => todo!(), - Instruction::Revert => { - MachineRecord { - mem: None, - stack: None, - storage: None, - pc: (mach.pc(), mach.pc()), - constraints: None, - halt: true, - } + Instruction::Revert => MachineRecord { + mem: None, + stack: None, + storage: None, + pc: (mach.pc(), mach.pc()), + constraints: None, + halt: true, }, Instruction::Invalid => todo!(), Instruction::SelfDestruct => todo!(), diff --git a/src/lib.rs b/src/lib.rs index 62713be..37fbaf7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,28 +1,27 @@ #![allow(unused)] // #![feature(adt_const_params)] extern crate z3 as z3_ext; +pub mod conversion; +pub mod exec; pub mod instruction; pub mod machine; pub mod memory; +pub mod parser; pub mod record; pub mod smt; pub mod stack; pub mod state; -pub mod traits; -pub mod conversion; pub mod storage; -pub mod parser; -pub mod exec; -use paste::{expr, item, paste}; +pub mod traits; use instruction::*; +use paste::{expr, item, paste}; +use rand::Rng; use smt::*; use stack::*; use z3_ext::{ ast::{Ast, Bool, Int, BV}, AstKind, Config, Context, Model, SatResult, Solver, }; -use rand::Rng; - pub fn bvi(val: impl Into) -> BitVec { BitVec::new_literal(val.into() as u64) @@ -49,8 +48,7 @@ mod test { /* - */ + */ pub const SIMPLE_COUNTER: &str = r"6080604052348015600f57600080fd5b5060043610603c5760003560e01c80633fb5c1cb1460415780638381f58a146053578063d09de08a14606d575b600080fd5b6051604c3660046083565b600055565b005b605b60005481565b60405190815260200160405180910390f35b6051600080549080607c83609b565b9190505550565b600060208284031215609457600080fd5b5035919050565b60006001820160ba57634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220f0cfb2159c518c3da0ad864362bad5dc0715514a9ab679237253d506773a0a1b64736f6c63430008130033"; pub const COUNTER_WITH_STORAGE_MAPPING: &str = r#"608060405234801561001057600080fd5b5060056000806001815260200190815260200160002081905550610197806100396000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063846719e01461003b578063d78233d61461006b575b600080fd5b6100556004803603810190610050919061010a565b61009b565b6040516100629190610146565b60405180910390f35b6100856004803603810190610080919061010a565b6100b7565b6040516100929190610146565b60405180910390f35b6000806000838152602001908152602001600020549050919050565b60006020528060005260406000206000915090505481565b600080fd5b6000819050919050565b6100e7816100d4565b81146100f257600080fd5b50565b600081359050610104816100de565b92915050565b6000602082840312156101205761011f6100cf565b5b600061012e848285016100f5565b91505092915050565b610140816100d4565b82525050565b600060208201905061015b6000830184610137565b9291505056fea2646970667358fe122066b287fef10118cba238fe38953bfefe938afefefefefe94fefe3682fefefefe64736f6c63430008110033"#; - -} \ No newline at end of file +} diff --git a/src/machine.rs b/src/machine.rs index 0f2a9b2..5f88d0a 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -12,7 +12,7 @@ use crate::instruction::*; use crate::memory::*; use crate::state::evm::EvmState; use crate::state::tree::{NodeId, StateTree}; -use crate::storage::{Address, AccountStorage}; +use crate::storage::{AccountStorage, Address}; use crate::traits::{Machine, MachineComponent, MachineInstruction, MachineState}; use crate::{ bvc, bvi, @@ -54,15 +54,12 @@ impl ExecutionSummary { } } - - pub type ExecBranch<'ctx> = (EvmState, Vec>); pub struct TransactionContext { calldata: Option>, output: Option>, - storage: HashMap - + storage: HashMap, } // The Evm is an *implementation* of the Machine trait @@ -99,14 +96,12 @@ impl<'ctx> Evm<'ctx> { pub fn set_init_state(&mut self, state: EvmState) { self.states.val = state; } - - } impl<'ctx> Evm<'ctx> { pub fn new(pgm: Vec) -> Self { let evm_state = EvmState::with_pgm(pgm.clone()); - + Self { pgm, states: StateTree { @@ -169,14 +164,18 @@ impl<'ctx> Machine<32> for Evm<'ctx> { step_recs.push(first_step); loop { if let Some(step) = step_recs.pop() { - eprintln!("HALTED LEFT: {}, HALTED RIGHT: {}", step.halted_left(), step.halted_right()); + eprintln!( + "HALTED LEFT: {}, HALTED RIGHT: {}", + step.halted_left(), + step.halted_right() + ); if !step.halted_right() { let continue_from_right = step.right_id(); if let Some(right_id) = continue_from_right { let nxt_right_step = exec.step_from_mut(right_id); step_recs.push(nxt_right_step); } - } + } if !step.halted_left() { let continue_from_left = step.left_id(); if let Some(left_id) = continue_from_left { @@ -327,8 +326,6 @@ impl MachineState<32> for EvmState { fn storage_apply(&mut self, storage_rec: StorageChange) { self.storage.apply_change(storage_rec); } - - } pub struct EvmExecutor<'ctx> { @@ -360,27 +357,18 @@ fn machine_returns_one_exec_for_non_branching_pgm() { let exec_tree = &execution.states; let final_states = exec_tree.leaves(); assert_eq!(2, final_states.len()); - assert_eq!(final_states.first().unwrap().val.stack().peek_nth(1).cloned().unwrap(), bvi(100)); + assert_eq!( + final_states + .first() + .unwrap() + .val + .stack() + .peek_nth(1) + .cloned() + .unwrap(), + bvi(100) + ); eprintln!("Final states: {:#?}", final_states); - // { - // let sat_branches = evm.exec_check(); - // assert!( - // sat_branches.first().is_some() - // && sat_branches - // .first() - // .unwrap() - // .0 - // .0 - // .stack() - // .peek_nth(1) - // .cloned() - // .unwrap() - // == bvi(100) - // ); - - // assert_eq!(sat_branches.len(), 1); - // } - // eprintln!("STATES > {:#?}", evm.states); } #[test] diff --git a/src/memory.rs b/src/memory.rs index 0f9a8b4..07f3215 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -17,7 +17,6 @@ impl MachineComponent for Memory { type Record = MemChange; fn apply_change(&mut self, rec: Self::Record) { - let MemChange { ops_log } = rec; let mut highest_idx = self.highest_idx; ops_log.into_iter().for_each(|op| match op { @@ -26,7 +25,10 @@ impl MachineComponent for Memory { val.simplify(); let mut idx = idx; idx.simplify(); - eprintln!("MEM WRITE FOR MEM APPLY: idx: {:#?}, value: {:#?}", idx, val); + eprintln!( + "MEM WRITE FOR MEM APPLY: idx: {:#?}, value: {:#?}", + idx, val + ); let idx_cmp: usize = idx.clone().into(); if idx_cmp > highest_idx { highest_idx = idx_cmp; @@ -81,7 +83,11 @@ impl Memory { while i < 32 { let idx = idx + 31; let val = mem.get(idx - i).unwrap().as_ref().clone(); - eprintln!("MEM VAL IN READ WORD FOR IDX - i:\nmem loc {:#?}\nval: {:#?}", (idx - i), val); + eprintln!( + "MEM VAL IN READ WORD FOR IDX - i:\nmem loc {:#?}\nval: {:#?}", + (idx - i), + val + ); bytes.push(val); i += 1; } @@ -94,7 +100,6 @@ impl Memory { } else { new_bv_inner = new_bv_inner.concat(&b); } - }); BitVec { inner: BVType::Z3(new_bv_inner), diff --git a/src/parser.rs b/src/parser.rs index d9945a3..3188573 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,30 +1,24 @@ -use crate::{instruction::*, smt::BitVec, bvi}; -use revm::{ - opcode::OpCode, OPCODE_JUMPMAP -}; -use hex::{decode}; +use crate::{bvi, instruction::*, smt::BitVec}; +use hex::decode; +use revm::{opcode::OpCode, OPCODE_JUMPMAP}; use ruint::Uint; pub struct Parser<'a> { - pgm: &'a str + pgm: &'a str, } impl<'a> Parser<'a> { - pub fn with_pgm(pgm: &'a str) -> Self { - Self { - pgm - } + Self { pgm } } pub fn parse(&self) -> Vec { let bytes = decode(self.pgm).unwrap(); let mut opcodes: Vec = vec![]; - + let mut pgm = vec![]; let mut skip_size = 0; let mut idx = 0_usize; for b in &bytes { - let b = *b; if skip_size > 0 { skip_size -= 1; @@ -44,21 +38,16 @@ impl<'a> Parser<'a> { pgm.push(parse_swap(b)); } else { let inst = Instruction::from(b); - pgm.push(inst); + pgm.push(inst); } idx += 1; - } pgm - - } - } // Returns instruction + any left over bytes in the slice after extracting the opcode & opcode args fn parse_push(bytes: &[u8]) -> (Instruction, u8, Vec) { - let instruction_byte = *bytes.first().unwrap(); let push_size = push_size(instruction_byte); eprintln!("PUSH SIZE IS {}", push_size); @@ -71,13 +60,20 @@ fn parse_push(bytes: &[u8]) -> (Instruction, u8, Vec) { new_bytes.push(0); } let push_val = &new_bytes[1..(push_size + 1) as usize]; - (push_op(push_size, push_val),push_size, new_bytes[(push_size) as usize..new_bytes.len()].to_vec()) + ( + push_op(push_size, push_val), + push_size, + new_bytes[(push_size) as usize..new_bytes.len()].to_vec(), + ) } else { let push_val = &bytes[1..(push_size + 1) as usize]; eprintln!("PUSH VAL IS {:#?}", push_val); - (push_op(push_size, push_val),push_size, bytes[(push_size) as usize..bytes.len()].to_vec()) + ( + push_op(push_size, push_val), + push_size, + bytes[(push_size) as usize..bytes.len()].to_vec(), + ) } - } fn parse_dup(byte: u8) -> Instruction { @@ -135,20 +131,13 @@ pub fn zero_extend(bytes: &[u8]) -> [u8; SZ] { for i in (0..pad_size - 1) { extended_bytes[i] = 0; } - - } else { extended_bytes.copy_from_slice(bytes); } extended_bytes - - } - - fn push_op(sz: u8, val: &[u8]) -> Instruction { - // let val = if val.len() < 8 { // let mut zero_len = if val.len() < 8 {8 - val.len()} else {0}; // let mut buf = vec![]; @@ -156,7 +145,7 @@ fn push_op(sz: u8, val: &[u8]) -> Instruction { // buf.push(0); // } // buf.extend_from_slice(val); - + // let mut sliced = [0u8; 8]; // sliced.copy_from_slice(&buf); // u64::from_be_bytes(sliced) @@ -165,137 +154,136 @@ fn push_op(sz: u8, val: &[u8]) -> Instruction { // buf.copy_from_slice() // u64::from_be_bytes(val) // }; - match sz { 1 => { let val = zero_extend::<1>(val); push1(val.into()) - }, + } 2 => { let val = zero_extend::<2>(val).into(); push2(val) - }, + } 3 => { let val = zero_extend::<3>(val).into(); push3(val) - }, + } 4 => { - let val = zero_extend::<4>(val).into(); + let val = zero_extend::<4>(val).into(); push4(val) - }, - 5 => { + } + 5 => { let val = zero_extend::<5>(val).into(); push5(val) - }, - 6 => { + } + 6 => { let val = zero_extend::<6>(val).into(); push6(val) - }, - 7 => { + } + 7 => { let val = zero_extend::<7>(val).into(); push7(val) - }, - 8 => { + } + 8 => { let val = zero_extend::<8>(val).into(); push8(val) - }, - 9 => { + } + 9 => { let val = zero_extend::<9>(val).into(); push9(val) - }, - 10 => { + } + 10 => { let val = zero_extend::<10>(val).into(); push10(val) - }, - 11 => { + } + 11 => { let val = zero_extend::<11>(val).into(); push11(val) - }, - 12 => { + } + 12 => { let val = zero_extend::<12>(val).into(); push12(val) - }, - 13 => { + } + 13 => { let val = zero_extend::<13>(val).into(); push13(val) - }, - 14 => { + } + 14 => { let val = zero_extend::<14>(val).into(); push14(val) - }, - 15 => { + } + 15 => { let val = zero_extend::<15>(val).into(); push15(val) - }, - 16 => { + } + 16 => { let val = zero_extend::<16>(val).into(); push16(val) - }, - 17 => { + } + 17 => { let val = zero_extend::<17>(val).into(); push17(val) - }, - 18 => { + } + 18 => { let val = zero_extend::<18>(val).into(); push18(val) - }, - 19 => { + } + 19 => { let val = zero_extend::<19>(val).into(); push19(val) - }, - 20 => { + } + 20 => { let val = zero_extend::<20>(val).into(); push20(val) - }, - 21 => { + } + 21 => { let val = zero_extend::<21>(val).into(); push21(val) - }, - 21 => { + } + 21 => { let val = zero_extend::<22>(val).into(); push22(val) - }, - 23 => { + } + 23 => { let val = zero_extend::<23>(val).into(); push23(val) - }, - 24 => { + } + 24 => { let val = zero_extend::<24>(val).into(); push24(val) - }, - 25 => { + } + 25 => { let val = zero_extend::<25>(val).into(); push25(val) - }, - 26 => { + } + 26 => { let val = zero_extend::<26>(val).into(); push26(val) - }, - 27 => { + } + 27 => { let val = zero_extend::<27>(val).into(); push27(val) - }, - 28 => { + } + 28 => { let val = zero_extend::<28>(val).into(); push28(val) - }, - 29 => { + } + 29 => { let val = zero_extend::<29>(val).into(); push29(val) - }, - 30 => { + } + 30 => { let val = zero_extend::<30>(val).into(); push30(val) - }, - 31 => { + } + 31 => { let val = zero_extend::<31>(val).into(); push31(val) - }, - 32 => { + } + 32 => { let val = zero_extend::<32>(val).into(); push32(val) - }, + } _ => { todo!() } @@ -320,7 +308,7 @@ fn swap_op(sz: u8) -> Instruction { 14 => Instruction::Swap14, 15 => Instruction::Swap15, 16 => Instruction::Swap16, - _ => todo!() + _ => todo!(), } } @@ -342,11 +330,10 @@ fn dup_op(sz: u8) -> Instruction { 14 => dup14(), 15 => dup15(), 16 => dup16(), - _ => todo!() - } + _ => todo!(), + } } - impl Instruction { pub fn from_byte(value: u8) -> Self { value.into() @@ -354,32 +341,26 @@ impl Instruction { // Has to handle when it's a push or dup, otherwise easy 1-1 conversion pub fn from_slice(bytes: &[u8]) -> Instruction { - let instruction_byte = *bytes.first().unwrap(); - - if is_push(instruction_byte) { - let push_size = push_size(instruction_byte); - let push_val = &bytes[1..push_size as usize]; - push_op(push_size, push_val) - } else if is_dup(instruction_byte) { + let instruction_byte = *bytes.first().unwrap(); + + if is_push(instruction_byte) { + let push_size = push_size(instruction_byte); + let push_val = &bytes[1..push_size as usize]; + push_op(push_size, push_val) + } else if is_dup(instruction_byte) { let dup_size = dup_size(instruction_byte); dup_op(dup_size) - } else if is_swap(instruction_byte) { + } else if is_swap(instruction_byte) { let swap_size = swap_size(instruction_byte); swap_op(swap_size) - } else { + } else { Instruction::from(instruction_byte) - } - + } } - - } - - impl From for Instruction { fn from(value: u8) -> Self { - match value { 0x00 => Instruction::Stop, 0x01 => Instruction::Add, @@ -447,84 +428,83 @@ impl From for Instruction { 0x61 => Instruction::Push2(Default::default()), 0x62 => Instruction::Push3(Default::default()), 0x63 => Instruction::Push4(Default::default()), - 0x64 => Instruction::Push5(Default::default()), - 0x65 => Instruction::Push6(Default::default()), - 0x66 => Instruction::Push7(Default::default()), - 0x67 => Instruction::Push8(Default::default()), - 0x68 => Instruction::Push9(Default::default()), - 0x69 => Instruction::Push10(Default::default()), + 0x64 => Instruction::Push5(Default::default()), + 0x65 => Instruction::Push6(Default::default()), + 0x66 => Instruction::Push7(Default::default()), + 0x67 => Instruction::Push8(Default::default()), + 0x68 => Instruction::Push9(Default::default()), + 0x69 => Instruction::Push10(Default::default()), 0x6a => Instruction::Push11(Default::default()), - 0x6b => Instruction::Push12(Default::default()), - 0x6c => Instruction::Push13(Default::default()), + 0x6b => Instruction::Push12(Default::default()), + 0x6c => Instruction::Push13(Default::default()), 0x6d => Instruction::Push14(Default::default()), - 0x6e => Instruction::Push15(Default::default()), - 0x6f => Instruction::Push16(Default::default()), + 0x6e => Instruction::Push15(Default::default()), + 0x6f => Instruction::Push16(Default::default()), 0x70 => Instruction::Push17(Default::default()), - 0x71 => Instruction::Push18(Default::default()), + 0x71 => Instruction::Push18(Default::default()), 0x72 => Instruction::Push19(Default::default()), - 0x73 => Instruction::Push20(Default::default()), - 0x74 => Instruction::Push21(Default::default()), - 0x75 => Instruction::Push22(Default::default()), - 0x76 => Instruction::Push23(Default::default()), - 0x77 => Instruction::Push24(Default::default()), - 0x78 => Instruction::Push25(Default::default()), - 0x79 => Instruction::Push26(Default::default()), - 0x7a => Instruction::Push27(Default::default()), - 0x7b => Instruction::Push28(Default::default()), - 0x7c => Instruction::Push29(Default::default()), - 0x7d => Instruction::Push30(Default::default()), - 0x7e => Instruction::Push31(Default::default()), - 0x7f => Instruction::Push32(Default::default()), - 0x80 => Instruction::Dup1, - 0x81 => Instruction::Dup2, - 0x82 => Instruction::Dup3, - 0x83 => Instruction::Dup4, - 0x84 => Instruction::Dup5, - 0x85 => Instruction::Dup6, - 0x86 => Instruction::Dup7, - 0x87 => Instruction::Dup8, - 0x88 => Instruction::Dup9, - 0x89 => Instruction::Dup10, - 0x8a => Instruction::Dup11, - 0x8b => Instruction::Dup12, - 0x8c => Instruction::Dup13, - 0x8d => Instruction::Dup14, - 0x8e => Instruction::Dup15, - 0x8f => Instruction::Dup16, - 0x90 => Instruction::Swap1, - 0x91 => Instruction::Swap2, - 0x92 => Instruction::Swap3, - 0x93 => Instruction::Swap4, - 0x94 => Instruction::Swap5, - 0x95 => Instruction::Swap6, - 0x96 => Instruction::Swap7, - 0x97 => Instruction::Swap8, - 0x98 => Instruction::Swap9, - 0x99 => Instruction::Swap10, - 0x9a => Instruction::Swap11, - 0x9b => Instruction::Swap12, - 0x9c => Instruction::Swap13, - 0x9d => Instruction::Swap14, - 0x9e => Instruction::Swap15, - 0x9f => Instruction::Swap16, - 0xa0 => Instruction::Log0, - 0xa1 => Instruction::Log1, - 0xa2 => Instruction::Log2, - 0xa3 => Instruction::Log3, - 0xa4 => Instruction::Log4, - 0xf0 => Instruction::Create, - 0xf1 => Instruction::Call, - 0xf2 => Instruction::CallCode, - 0xf3 => Instruction::Return, - 0xf4 => Instruction::DelegateCall, - 0xf5 => Instruction::Create2, - 0xfa => Instruction::StaticCall, - 0xfd => Instruction::Revert, - 0xfe => Instruction::Invalid, - 0xff => Instruction::SelfDestruct, + 0x73 => Instruction::Push20(Default::default()), + 0x74 => Instruction::Push21(Default::default()), + 0x75 => Instruction::Push22(Default::default()), + 0x76 => Instruction::Push23(Default::default()), + 0x77 => Instruction::Push24(Default::default()), + 0x78 => Instruction::Push25(Default::default()), + 0x79 => Instruction::Push26(Default::default()), + 0x7a => Instruction::Push27(Default::default()), + 0x7b => Instruction::Push28(Default::default()), + 0x7c => Instruction::Push29(Default::default()), + 0x7d => Instruction::Push30(Default::default()), + 0x7e => Instruction::Push31(Default::default()), + 0x7f => Instruction::Push32(Default::default()), + 0x80 => Instruction::Dup1, + 0x81 => Instruction::Dup2, + 0x82 => Instruction::Dup3, + 0x83 => Instruction::Dup4, + 0x84 => Instruction::Dup5, + 0x85 => Instruction::Dup6, + 0x86 => Instruction::Dup7, + 0x87 => Instruction::Dup8, + 0x88 => Instruction::Dup9, + 0x89 => Instruction::Dup10, + 0x8a => Instruction::Dup11, + 0x8b => Instruction::Dup12, + 0x8c => Instruction::Dup13, + 0x8d => Instruction::Dup14, + 0x8e => Instruction::Dup15, + 0x8f => Instruction::Dup16, + 0x90 => Instruction::Swap1, + 0x91 => Instruction::Swap2, + 0x92 => Instruction::Swap3, + 0x93 => Instruction::Swap4, + 0x94 => Instruction::Swap5, + 0x95 => Instruction::Swap6, + 0x96 => Instruction::Swap7, + 0x97 => Instruction::Swap8, + 0x98 => Instruction::Swap9, + 0x99 => Instruction::Swap10, + 0x9a => Instruction::Swap11, + 0x9b => Instruction::Swap12, + 0x9c => Instruction::Swap13, + 0x9d => Instruction::Swap14, + 0x9e => Instruction::Swap15, + 0x9f => Instruction::Swap16, + 0xa0 => Instruction::Log0, + 0xa1 => Instruction::Log1, + 0xa2 => Instruction::Log2, + 0xa3 => Instruction::Log3, + 0xa4 => Instruction::Log4, + 0xf0 => Instruction::Create, + 0xf1 => Instruction::Call, + 0xf2 => Instruction::CallCode, + 0xf3 => Instruction::Return, + 0xf4 => Instruction::DelegateCall, + 0xf5 => Instruction::Create2, + 0xfa => Instruction::StaticCall, + 0xfd => Instruction::Revert, + 0xfe => Instruction::Invalid, + 0xff => Instruction::SelfDestruct, _ => Instruction::Invalid, } - } } @@ -534,7 +514,7 @@ fn is_push_works() { assert!(is_push(b)); } - for b in (0x00_u8 .. 0x5f) { + for b in (0x00_u8..0x5f) { assert!(!is_push(b)); } @@ -568,7 +548,7 @@ contract Counter { #[test] fn can_parse_simple_pgm() { const COUNTER_SOL_CODE: &'static str = "604260005260206000610040F3"; - + let pgm = Parser::with_pgm(COUNTER_SOL_CODE).parse(); let sixty_four: BitVec<32> = bvi(0x0040); eprintln!("SIXTY FOUR: {:#?}", sixty_four); @@ -579,12 +559,10 @@ fn can_parse_simple_pgm() { Instruction::Push1(bvi(0x20)), Instruction::Push1(bvi(0)), push2(bvi(0x0040)), - Instruction::Return + Instruction::Return, ]; assert_eq!(expected, pgm); - - } #[test] @@ -625,11 +603,9 @@ fn can_parse_larger_pgm_with_storage() { Instruction::Swap1, Instruction::SStore, Instruction::Pop, - push2(bvi(0x0197)) - + push2(bvi(0x0197)), ]; - let pgm_first_30 = (&pgm[..33]).to_vec(); assert_eq!(expected_first_30, pgm_first_30); -} \ No newline at end of file +} diff --git a/src/record.rs b/src/record.rs index bb5196e..b4f84f2 100644 --- a/src/record.rs +++ b/src/record.rs @@ -75,8 +75,15 @@ impl StackChange { #[derive(Clone, Debug)] pub enum StorageOp { - Read {addr: Address, idx: Index}, - Write {addr: Address, idx: Index, val: Value} + Read { + addr: Address, + idx: Index, + }, + Write { + addr: Address, + idx: Index, + val: Value, + }, } #[derive(Clone, Debug)] diff --git a/src/smt/bitvec/mod.rs b/src/smt/bitvec/mod.rs index 719eaaa..be2b26d 100644 --- a/src/smt/bitvec/mod.rs +++ b/src/smt/bitvec/mod.rs @@ -1,8 +1,8 @@ pub mod z3; -use std::hash::{Hash, Hasher}; pub use self::z3::*; use super::{ctx, SolverType}; +use std::hash::{Hash, Hasher}; use z3_ext::ast::{Ast, BV}; #[derive(Debug, Clone, PartialEq, Eq)] @@ -18,7 +18,6 @@ pub struct BitVec { pub(crate) typ: super::SolverType, } - // impl PartialEq for BitVec { // fn eq(&self, other: &Self) -> bool { // let BVType::Z3(a) = &self.inner; @@ -33,11 +32,8 @@ impl Hash for BitVec { self.as_ref().hash(state); state.finish(); } - - } - impl BitVec { pub fn with_bv(bv: BV<'static>) -> Self { Self { @@ -62,7 +58,6 @@ impl Default for BitVec { impl PartialEq for BitVec { fn eq(&self, other: &Self) -> bool { - let a = self.as_ref(); let b = other.as_ref(); diff --git a/src/smt/bitvec/z3.rs b/src/smt/bitvec/z3.rs index f21dc3e..92a8925 100644 --- a/src/smt/bitvec/z3.rs +++ b/src/smt/bitvec/z3.rs @@ -16,7 +16,6 @@ impl BitVec { } } - pub fn new_const(name: impl AsRef) -> Self { let bv = BV::new_const(ctx(), name.as_ref(), (SZ * 8) as u32); Self { diff --git a/src/state/env.rs b/src/state/env.rs index 2ed9fa0..566911c 100644 --- a/src/state/env.rs +++ b/src/state/env.rs @@ -49,7 +49,6 @@ pub fn origin<'ctx>() -> FuncDecl<'ctx> { FuncDecl::new(ctx, "origin", &[], &Sort::bitvector(ctx, 256)) } - pub fn address() -> BitVec<20> { random_bv_arg() } diff --git a/src/state/evm.rs b/src/state/evm.rs index 8729100..dc0308e 100644 --- a/src/state/evm.rs +++ b/src/state/evm.rs @@ -1,6 +1,6 @@ use crate::machine::ExecBranch; use crate::state::tree::NodeId; -use crate::storage::{Address, AccountStorage}; +use crate::storage::{AccountStorage, Address}; use crate::traits::MachineState; use crate::{ instruction::Instruction, @@ -16,7 +16,7 @@ pub struct EvmState { pub memory: Memory, pub storage: AccountStorage, pub stack: Stack<32>, - pc: usize, + pc: usize, pub pgm: Vec, pub address: Address, pub halt: bool, @@ -32,7 +32,7 @@ impl MachineComponent for EvmState { stack, mem, constraints, - storage + storage, } = rec; if let Some(mem) = mem { self.memory.apply_change(mem); @@ -46,7 +46,6 @@ impl MachineComponent for EvmState { } impl<'ctx> EvmState { - pub fn with_pgm(pgm: Vec) -> Self { Self { pgm, @@ -72,10 +71,16 @@ impl<'ctx> EvmState { } pub fn curr_instruction(&self) -> Instruction { if !self.can_continue() { - eprintln!("EVM STATE CANNOT CONTINUE; BUT CURR INST IS REQUESTED: {:#?}", self); - eprintln!("Getting curr inst.. curr pc: {} and curr pgm len: {}", self.pc, self.pgm.len()); + eprintln!( + "EVM STATE CANNOT CONTINUE; BUT CURR INST IS REQUESTED: {:#?}", + self + ); + eprintln!( + "Getting curr inst.. curr pc: {} and curr pgm len: {}", + self.pc, + self.pgm.len() + ); } self.pgm.get(self.pc).cloned().unwrap() } - } diff --git a/src/state/tree.rs b/src/state/tree.rs index 896a52e..4ce441a 100644 --- a/src/state/tree.rs +++ b/src/state/tree.rs @@ -144,10 +144,8 @@ impl<'ctx> StateTree<'ctx> { } } None - } } - pub fn insert_left_helper( &mut self, @@ -238,7 +236,6 @@ impl<'ctx> StateTree<'ctx> { pub fn leaves(&self) -> Vec { let mut leaves = vec![]; - if self.left.is_none() && self.right.is_none() { leaves.push((self.val.clone(), self.path_condition.clone()).into()); return leaves; @@ -251,7 +248,7 @@ impl<'ctx> StateTree<'ctx> { if let Some(right) = self.right.as_ref() { leaves.extend(right.leaves()) } - + // if let Some(left) = &self.left { // if left.left.is_none() && left.right.is_none() { diff --git a/src/storage.rs b/src/storage.rs index 6b0664a..4dfe61d 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -1,17 +1,15 @@ -use std::collections::HashMap; -use crate::{instruction::Instruction,traits::{MachineComponent}, record::{StorageChange, StorageOp}}; -use z3_ext::{ - ast::{ - BV, Ast, Array - } +use crate::{ + instruction::Instruction, + record::{StorageChange, StorageOp}, + traits::MachineComponent, }; +use std::collections::HashMap; +use z3_ext::ast::{Array, Ast, BV}; +use crate::smt::{ctx, BitVec}; use crate::{bvc, bvi}; -use crate::smt::{BitVec, ctx}; - -fn make_storage_arr() { -} +fn make_storage_arr() {} #[derive(Debug, Clone, Default)] pub struct AccountStorage { inner: HashMap, StorageValue>, @@ -21,7 +19,7 @@ pub struct AccountStorage { #[derive(Debug, Clone, Eq, PartialEq)] pub enum StorageValue { Array(Array<'static>), - BV(BitVec<32>) + BV(BitVec<32>), } impl Default for StorageValue { @@ -44,12 +42,11 @@ impl AccountStorage { } } - pub type Address = BitVec<20>; #[derive(Debug, Clone, Default)] pub struct GlobalStorage { - inner: HashMap + inner: HashMap, } impl GlobalStorage { @@ -84,31 +81,53 @@ impl MachineComponent for GlobalStorage { fn apply_change(&mut self, rec: Self::Record) { let StorageChange { log } = rec; let mut addr_record_map = HashMap::new(); - log.iter().for_each(|op| { - match op { - crate::record::StorageOp::Read { idx, addr } => { - addr_record_map.entry(addr) - .and_modify(|logs: &mut Vec| logs.push(StorageOp::Read {idx: idx.clone(), addr: addr.clone()})) - .or_insert(vec![StorageOp::Read{idx: idx.clone(), addr: addr.clone()}]); - }, - crate::record::StorageOp::Write { addr, idx, val } => { - addr_record_map.entry(addr) - .and_modify(|logs: &mut Vec| logs.push(StorageOp::Write {idx: idx.clone(), addr: addr.clone(), val: val.clone()})) - .or_insert(vec![StorageOp::Write {idx: idx.clone(), addr: addr.clone(), val: val.clone()}]); - - }, + log.iter().for_each(|op| match op { + crate::record::StorageOp::Read { idx, addr } => { + addr_record_map + .entry(addr) + .and_modify(|logs: &mut Vec| { + logs.push(StorageOp::Read { + idx: idx.clone(), + addr: addr.clone(), + }) + }) + .or_insert(vec![StorageOp::Read { + idx: idx.clone(), + addr: addr.clone(), + }]); + } + crate::record::StorageOp::Write { addr, idx, val } => { + addr_record_map + .entry(addr) + .and_modify(|logs: &mut Vec| { + logs.push(StorageOp::Write { + idx: idx.clone(), + addr: addr.clone(), + val: val.clone(), + }) + }) + .or_insert(vec![StorageOp::Write { + idx: idx.clone(), + addr: addr.clone(), + val: val.clone(), + }]); } }); - addr_record_map.into_iter().for_each(|(address, storage_ops_log)| { - let change = StorageChange{log: storage_ops_log}; - self.inner.entry(address.clone()) - .and_modify(|account| account.apply_change(change.clone())) - .or_insert_with( || { - let mut new_acc = AccountStorage::default(); - new_acc.apply_change(change); - new_acc - }); - }) + addr_record_map + .into_iter() + .for_each(|(address, storage_ops_log)| { + let change = StorageChange { + log: storage_ops_log, + }; + self.inner + .entry(address.clone()) + .and_modify(|account| account.apply_change(change.clone())) + .or_insert_with(|| { + let mut new_acc = AccountStorage::default(); + new_acc.apply_change(change); + new_acc + }); + }) } } @@ -116,15 +135,13 @@ impl MachineComponent for AccountStorage { type Record = StorageChange; fn apply_change(&mut self, rec: Self::Record) { let StorageChange { log } = rec; - log.into_iter().for_each(|op| { - match op { - crate::record::StorageOp::Read { idx, addr } => { - self.touched.insert(idx, true); - }, - crate::record::StorageOp::Write { addr, idx, val } => { - self.touched.insert(idx.clone(), true); - self.inner.insert(idx, StorageValue::BV(val)); - }, + log.into_iter().for_each(|op| match op { + crate::record::StorageOp::Read { idx, addr } => { + self.touched.insert(idx, true); + } + crate::record::StorageOp::Write { addr, idx, val } => { + self.touched.insert(idx.clone(), true); + self.inner.insert(idx, StorageValue::BV(val)); } }) } @@ -136,8 +153,10 @@ fn test_basic_lookup_works_in_acc_storage() { let mut acc_store = AccountStorage::default(); acc_store.sstore(bvi(5), StorageValue::BV(bvc("val_at_idx_5"))); - - assert_eq!(acc_store.sload(&bvi(5)), StorageValue::BV(bvc("val_at_idx_5"))); + assert_eq!( + acc_store.sload(&bvi(5)), + StorageValue::BV(bvc("val_at_idx_5")) + ); } #[test] @@ -150,22 +169,20 @@ fn test_basic_lookup_global_storage() { addr_2_storage.sstore(bvi(3), StorageValue::BV(bvc("storage_val_at_idx_3"))); global.inner.insert(addr2.clone(), addr_2_storage); - assert_eq!(global.get(&addr2).sload(&bvi(3)), StorageValue::BV(bvc("storage_val_at_idx_3"))); - + assert_eq!( + global.get(&addr2).sload(&bvi(3)), + StorageValue::BV(bvc("storage_val_at_idx_3")) + ); } #[test] -fn test_storage_with_solidity_mapping() { - -} - +fn test_storage_with_solidity_mapping() {} // Storage keys must be concrete // However, values can be symbolic // In the case of compound structures like mappings, the following - // Global Storage: - // HashMap(Address -> AccountStorage) - // AccountStorage(BitVec<32> -> StorageValue) - // StorageValue(ConcreteBytes<32> OR SymbolicBytes<32>) - // - \ No newline at end of file +// Global Storage: +// HashMap(Address -> AccountStorage) +// AccountStorage(BitVec<32> -> StorageValue) +// StorageValue(ConcreteBytes<32> OR SymbolicBytes<32>) +// diff --git a/tests/lib.rs b/tests/lib.rs index a9b5b1e..db3d36e 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -1,20 +1,13 @@ +#![allow(unused, unused_imports)] extern crate ser; use ser::{ - traits::*, - machine::*, - stack::*, - storage::*, - memory::*, - conversion::*, - bvc, - bvi, - parser::*, + bvc, bvi, conversion::*, machine::*, memory::*, parser::*, stack::*, storage::*, traits::*, }; use z3::ast::*; pub const COUNTER_WITH_STORAGE_MAPPING: &str = r#"608060405234801561001057600080fd5b5060056000806001815260200190815260200160002081905550610197806100396000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063846719e01461003b578063d78233d61461006b575b600080fd5b6100556004803603810190610050919061010a565b61009b565b6040516100629190610146565b60405180910390f35b6100856004803603810190610080919061010a565b6100b7565b6040516100929190610146565b60405180910390f35b6000806000838152602001908152602001600020549050919050565b60006020528060005260406000206000915090505481565b600080fd5b6000819050919050565b6100e7816100d4565b81146100f257600080fd5b50565b600081359050610104816100de565b92915050565b6000602082840312156101205761011f6100cf565b5b600061012e848285016100f5565b91505092915050565b610140816100d4565b82525050565b600060208201905061015b6000830184610137565b9291505056fea2646970667358fe122066b287fef10118cba238fe38953bfefe938afefefefefe94fefe3682fefefefe64736f6c63430008110033"#; pub const SUPERSIMPLE: &str = r#"604260005260206000F3"#; -pub const STORAGE_SIMPLE: &str = r#"6080604052348015600f57600080fd5b506004361060325760003560e01c80631ab06ee5146037578063fac333ac146056575b600080fd5b605460423660046085565b60009182526020829052604090912055565b005b6073606136600460a6565b60006020819052908152604090205481565b60405190815260200160405180910390f35b60008060408385031215609757600080fd5b50508035926020909101359150565b60006020828403121560b757600080fd5b503591905056fea26469706673582212204a6bf5c04a6e273d775914b20b0bab1bca28228be5562d496002981e13ff015264736f6c63430008130033"#; +pub const STORAGE_SIMPLE: &str = r#"6080604052348015600f57600080fd5b506004361060325760003560e01c80631ab06ee5146037578063fac333ac146056575b600080fd5b605460423660046085565b60009182526020829052604090912055565b005b6073606136600460a6565b60006020819052908152604090205481565b60405190815260200160405180910390f35b60008060408385031215609757600080fd5b50508035926020909101359150565b60006020828403121560b757600080fd5b503591905056fea26469706673582212204a6bf5c04a6e273d775914b20b0bab1bca28228be5562d496002981e13ff015264736f6c63430008130033"#; #[test] fn can_run_simple_parsed_pgm() { @@ -23,25 +16,10 @@ fn can_run_simple_parsed_pgm() { { let sat_branches = evm.exec(); - //eprintln!("EXECUTION: {:#?}", sat_branches); - - // eprintln!("SAT BRANCHES: {:#?}", sat_branches); - // assert_eq!(sat_branches.len(), 1); - // let top = sat_branches - // .first() - // .unwrap() - // .0 - // .0 - // .stack() - // .peek() - // .cloned() - // .unwrap(); - // eprintln!("Stack top size: {:#?}", top.as_ref().get_size()); - // assert_eq!(top, bvi(5)); + let leaf = sat_branches.states.leaves(); assert_eq!(1, leaf.len()); let final_tree = leaf.first().unwrap().clone(); - // eprintln!("FINAL TREE: {:#?}", final_tree); let mut mem_val = final_tree.val.mem_read(bvi(0)); mem_val.simplify(); assert_eq!(bvi(66), mem_val); @@ -53,30 +31,15 @@ fn can_run_simple_storage_pgm() { let pgm = Parser::with_pgm(STORAGE_SIMPLE).parse(); let mut evm = Evm::new(pgm); - { - let sat_branches = evm.exec(); - //eprintln!("EXECUTION: {:#?}", sat_branches); - - // eprintln!("SAT BRANCHES: {:#?}", sat_branches); - // assert_eq!(sat_branches.len(), 1); - // let top = sat_branches - // .first() - // .unwrap() - // .0 - // .0 - // .stack() - // .peek() - // .cloned() - // .unwrap(); - // eprintln!("Stack top size: {:#?}", top.as_ref().get_size()); - // assert_eq!(top, bvi(5)); - let leaf = sat_branches.states.leaves(); - assert_eq!(2, leaf.len()); - eprintln!("LEAVES: {:#?}", leaf); - let final_tree = leaf.get(1).unwrap().clone(); - // eprintln!("FINAL TREE: {:#?}", final_tree); - let mut mem_val = final_tree.val.mem_read(bvi(64)); - mem_val.simplify(); - assert_eq!(bvi(128), mem_val); - } -} \ No newline at end of file + + let sat_branches = evm.exec(); + let leaf = sat_branches.states.leaves(); + assert_eq!(2, leaf.len()); + eprintln!("LEAVES: {:#?}", leaf); + let final_tree = leaf.get(1).unwrap().clone(); + // eprintln!("FINAL TREE: {:#?}", final_tree); + let mut mem_val = final_tree.val.mem_read(bvi(64)); + mem_val.simplify(); + assert_eq!(bvi(128), mem_val); + +} diff --git a/tests/test_storage.rs b/tests/test_storage.rs index e69de29..8b13789 100644 --- a/tests/test_storage.rs +++ b/tests/test_storage.rs @@ -0,0 +1 @@ + From 55c3861c08d1a5d7a3cfababd6be0035baa39a87 Mon Sep 17 00:00:00 2001 From: tannr Date: Wed, 2 Aug 2023 19:32:10 -0400 Subject: [PATCH 19/28] Add sparse pc->instruction map --- examples/simple_pgm.rs | 18 +- examples/simple_storage.rs | 13 +- src/conversion/mod.rs | 4 +- src/exec/mod.rs | 24 ++- src/instruction/mod.rs | 225 ++++++++++++++++--------- src/machine.rs | 67 ++++---- src/memory.rs | 39 +++-- src/parser.rs | 69 ++++++-- src/state/context.rs | 10 ++ src/state/evm.rs | 28 ++- src/state/mod.rs | 1 + src/traits.rs | 3 +- test-contracts/src/SimpleToken.sol | 20 +++ test-contracts/src/VulnerableVault.sol | 24 +++ tests/lib.rs | 16 +- 15 files changed, 399 insertions(+), 162 deletions(-) create mode 100644 src/state/context.rs create mode 100644 test-contracts/src/SimpleToken.sol create mode 100644 test-contracts/src/VulnerableVault.sol diff --git a/examples/simple_pgm.rs b/examples/simple_pgm.rs index 7dc2cdf..5043b5c 100644 --- a/examples/simple_pgm.rs +++ b/examples/simple_pgm.rs @@ -8,13 +8,19 @@ pub const SUPERSIMPLE: &str = r#"604260005260206000F3"#; fn main() { let pgm = Parser::with_pgm(SUPERSIMPLE).parse(); let mut evm = Evm::new(pgm); + let execution_trace = evm.exec(); + { + let leaf = execution_trace.states.leaves(); + assert_eq!(1, leaf.len()); + let final_tree = leaf.first().unwrap().clone(); - let leaf = execution_trace.states.leaves(); - assert_eq!(1, leaf.len()); - let final_tree = leaf.first().unwrap().clone(); + let mut mem_val = final_tree.val.mem_read(bvi(0)); + mem_val.simplify(); + assert_eq!(bvi(66), mem_val); + } - let mut mem_val = final_tree.val.mem_read(bvi(0)); - mem_val.simplify(); - assert_eq!(bvi(66), mem_val); + + let tree_flattened = execution_trace.states.into_iter().collect::>(); + eprintln!("Nodes in tree: {}\nTree Nodes: {:#?}", tree_flattened.len(), tree_flattened); } diff --git a/examples/simple_storage.rs b/examples/simple_storage.rs index 1eaed2c..e118aab 100644 --- a/examples/simple_storage.rs +++ b/examples/simple_storage.rs @@ -7,11 +7,14 @@ use z3::ast::*; pub const STORAGE_SIMPLE: &str = r#"6080604052348015600f57600080fd5b506004361060325760003560e01c80631ab06ee5146037578063fac333ac146056575b600080fd5b605460423660046085565b60009182526020829052604090912055565b005b6073606136600460a6565b60006020819052908152604090205481565b60405190815260200160405180910390f35b60008060408385031215609757600080fd5b50508035926020909101359150565b60006020828403121560b757600080fd5b503591905056fea26469706673582212204a6bf5c04a6e273d775914b20b0bab1bca28228be5562d496002981e13ff015264736f6c63430008130033"#; fn main() { + let pgm = Parser::with_pgm(STORAGE_SIMPLE).parse(); + + let mut evm = Evm::new(pgm); let execution = evm.exec(); - +{ let leaf = execution.states.leaves(); assert_eq!(2, leaf.len()); @@ -21,3 +24,11 @@ fn main() { mem_val.simplify(); assert_eq!(bvi(128), mem_val); // 0x80 } + + let mut report = std::string::String::default(); + // execution.states.into_iter().for_each(|(state, constraint)| { + // report = format!("{}\n{} -- Constraints: {:#?}", report, state, constraint); + // }); + //eprintln!("Execution report: {}", report); + eprintln!("Tree: {:#?}", execution.states); +} diff --git a/src/conversion/mod.rs b/src/conversion/mod.rs index 2d8521b..fa563db 100644 --- a/src/conversion/mod.rs +++ b/src/conversion/mod.rs @@ -82,8 +82,8 @@ impl From<[u8; SZ]> for BitVec { let new_bv: BV<'static> = bvi::<1>(*i).into(); bv = bv.concat(&new_bv).simplify(); } - eprintln!("VALUE CONVERTING FROM: {:#x?}", value); - eprintln!("BV IN SLICE CONVERT: {:#?} SIZE: {}", bv, bv.get_size()); + // eprintln!("VALUE CONVERTING FROM: {:#x?}", value); + // eprintln!("BV IN SLICE CONVERT: {:#?} SIZE: {}", bv, bv.get_size()); bv.extract((bv.get_size() - 8 - 1) as u32, 0) .simplify() .into() diff --git a/src/exec/mod.rs b/src/exec/mod.rs index d1c208e..e955bf4 100644 --- a/src/exec/mod.rs +++ b/src/exec/mod.rs @@ -1,5 +1,6 @@ use uuid::Uuid; +use crate::parser::Program; use crate::state::evm::EvmState; use crate::state::tree::*; use crate::{ @@ -11,7 +12,7 @@ use crate::{ #[derive(Default, Debug)] pub struct Execution<'ctx> { changes: Vec>, - program: Vec, + program: Program, pub states: StateTree<'ctx>, } @@ -61,7 +62,7 @@ impl StepRecord { } impl<'ctx> Execution<'ctx> { - pub fn new(start_state: EvmState, pgm: Vec) -> Self { + pub fn new(start_state: EvmState, pgm: Program) -> Self { Self { program: pgm, states: StateTree::from((start_state, None)), @@ -77,8 +78,11 @@ impl<'ctx> Execution<'ctx> { let curr_inst = curr_state.curr_instruction(); let curr_pc = curr_state.pc(); let change_rec = curr_inst.exec(&curr_state); - + eprintln!("CHANGE REC IN EXEC: {:#?}", change_rec); let is_branch = change_rec.constraints.is_some(); + if is_branch { + eprintln!("IS BRANCH HERE:\nChange record {:#?}\nCurr_state pc: {}", change_rec, curr_pc); + } curr_state.apply_change(change_rec.clone()); let mut report = StepRecord::new(false, change_rec.halt); if is_branch { @@ -158,10 +162,17 @@ impl<'ctx> Execution<'ctx> { let curr_inst = curr_state.curr_instruction(); let curr_pc = curr_state.pc(); + eprintln!("CURR STATE IN STEP FROM MUT: {:#?}", curr_state); let change_rec = curr_inst.exec(&curr_state); let is_branch = change_rec.constraints.is_some(); curr_state.apply_change(change_rec.clone()); + if is_branch { + eprintln!("IS BRANCH HERE:\nChange record {:#?}\nCurr_state pc: {}", change_rec, curr_pc); + } + if change_rec.halt { + eprintln!("Halt occurred here: {:#?}", change_rec); + } let curr_state = curr_state; let mut report = StepRecord::new(false, change_rec.halt); // assert_eq!(change_rec.halt, curr_state.halt); @@ -170,14 +181,15 @@ impl<'ctx> Execution<'ctx> { // an additional constraint // and left tree (by convention left path represents straight line execution) is the negation of such constraint let mut left_state = curr_state.clone(); + let right_tree = StateTree::from((left_state.clone(), change_rec.constraints.clone().unwrap())); left_state.set_pc(curr_pc + 1); report.halted_left = left_state.halt; let left_tree = StateTree::from(( - left_state.clone(), - change_rec.constraints.clone().unwrap().not(), + left_state, + change_rec.constraints.unwrap().not(), )); - let right_tree = StateTree::from((left_state, change_rec.constraints.unwrap())); + let left_tree_ref = self.states.insert_left_of(left_tree, node_id.id()); let right_tree_ref = self.states.insert_right_of(right_tree, node_id.id()); // curr_state_tree.left = Some(Box::new(left_tree)); diff --git a/src/instruction/mod.rs b/src/instruction/mod.rs index 397c601..b753ac9 100644 --- a/src/instruction/mod.rs +++ b/src/instruction/mod.rs @@ -183,6 +183,46 @@ fn exec_dup_nth(mach: &EvmState, n: usize) -> MachineRecord<32> { } } +impl Instruction { + pub fn byte_size(&self) -> usize { + let inst_additional_size: usize = match self { + Instruction::Push1(_) => 1, + Instruction::Push2(_) => 2, + Instruction::Push3(_) =>3, + Instruction::Push4(_) =>4, + Instruction::Push5(_) =>5, + Instruction::Push6(_) =>6, + Instruction::Push7(_) =>7, + Instruction::Push8(_) =>8, + Instruction::Push9(_) =>9, + Instruction::Push10(_) => 10 , + Instruction::Push11(_) => 11 , + Instruction::Push12(_) => 12, + Instruction::Push13(_) => 13 , + Instruction::Push14(_) => 14, + Instruction::Push15(_) => 15, + Instruction::Push16(_) => 16, + Instruction::Push17(_) => 17, + Instruction::Push18(_) => 18, + Instruction::Push19(_) => 19, + Instruction::Push20(_) => 20 , + Instruction::Push21(_) => 21, + Instruction::Push22(_) => 22, + Instruction::Push23(_) => 23, + Instruction::Push24(_) => 24, + Instruction::Push25(_) => 25, + Instruction::Push26(_) => 26, + Instruction::Push27(_) => 27, + Instruction::Push28(_) => 28, + Instruction::Push29(_) => 29, + Instruction::Push30(_) => 30, + Instruction::Push31(_) => 31, + Instruction::Push32(_) => 32, + _ => 0 + }; + inst_additional_size + 1 + } +} impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { fn exec(&self, mach: &EvmState) -> MachineRecord<32> { match self { @@ -205,7 +245,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_change), mem: Default::default(), - pc: (pc, pc + 1), + pc: (pc, pc + self.byte_size()), constraints: None, halt: false, storage: None, @@ -219,7 +259,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -233,7 +273,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -247,7 +287,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -261,7 +301,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -275,7 +315,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -289,7 +329,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -303,7 +343,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -317,7 +357,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -344,7 +384,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -364,7 +404,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -384,7 +424,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -404,7 +444,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -424,7 +464,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -444,7 +484,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -460,7 +500,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -476,7 +516,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -492,7 +532,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -509,7 +549,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -527,7 +567,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -544,7 +584,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -564,7 +604,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -578,7 +618,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -592,7 +632,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -606,7 +646,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -621,7 +661,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -630,12 +670,12 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { Instruction::CallDataSize => { let stack = mach.stack(); let call_data_sz = call_data_size().apply(&[]).as_bv().unwrap(); - let stack_diff = StackChange::with_ops(vec![pop(), push(call_data_sz.into())]); + let stack_diff = StackChange::with_ops(vec![push(call_data_sz.into())]); MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -652,7 +692,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -667,7 +707,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -685,7 +725,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -699,7 +739,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -713,7 +753,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -728,7 +768,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -742,7 +782,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -756,7 +796,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, @@ -773,7 +813,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { }; MachineRecord { stack: Some(stack_rec), - pc: (pc, pc + 1), + pc: (pc, pc + self.byte_size()), mem: Default::default(), constraints: None, halt: false, @@ -793,7 +833,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(vec![pop(), push(val_mem)])), mem: Some(mem_change), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), halt: false, storage: None, constraints: None, @@ -821,7 +861,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { constraints: None, halt: false, storage: None, - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), } } Instruction::MStore8 => { @@ -851,7 +891,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { constraints: None, halt: false, storage: None, - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), } } Instruction::SLoad => { @@ -872,7 +912,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { idx: key.clone(), }], }), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, } @@ -898,12 +938,28 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { stack: Some(stack_rec), mem: None, storage: Some(storage_change), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, } } - Instruction::Jump => todo!(), + Instruction::Jump => { + let jump_dest = mach.stack().peek().unwrap(); + let jump_dest_concrete = jump_dest.as_ref().simplify().as_u64().unwrap() as usize; + let stack_rec = StackChange { + pop_qty: 1, + push_qty: 0, + ops: vec![StackOp::Pop] + }; + MachineRecord { + stack: Some(stack_rec), + pc: (mach.pc(), jump_dest_concrete), + constraints: None, + mem: Default::default(), + halt: false, + storage: None, + } + }, Instruction::JumpI => { let jump_dest = mach.stack().peek().unwrap(); let cond = mach.stack().peek_nth(1).unwrap(); @@ -937,7 +993,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { }; MachineRecord { stack: Some(stack_rec), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, mem: Default::default(), halt: false, @@ -954,14 +1010,23 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack, mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), halt: false, storage: None, constraints: None, } } Instruction::Gas => todo!(), - Instruction::JumpDest => todo!(), + Instruction::JumpDest => { + MachineRecord { + stack: None, + pc: (mach.pc(), mach.pc() + self.byte_size()), + mem: Default::default(), + halt: false, + storage: None, + constraints: None, + } + }, Instruction::Push1(bv) => { let new_bv = bv.as_ref().zero_ext(31).into(); @@ -969,7 +1034,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -983,7 +1048,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -997,7 +1062,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1011,7 +1076,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1025,7 +1090,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1039,7 +1104,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1053,7 +1118,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1067,7 +1132,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1081,7 +1146,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1095,7 +1160,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1109,7 +1174,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1123,7 +1188,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1137,7 +1202,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1151,7 +1216,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1165,7 +1230,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1179,7 +1244,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1193,7 +1258,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1207,7 +1272,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1221,7 +1286,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1235,7 +1300,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1249,7 +1314,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1263,7 +1328,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1277,7 +1342,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1291,7 +1356,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1305,7 +1370,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1319,7 +1384,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1333,7 +1398,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1347,7 +1412,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1361,7 +1426,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1375,7 +1440,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1389,7 +1454,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1401,7 +1466,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, @@ -1480,7 +1545,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_change), mem: Default::default(), - pc: (pc, pc + 1), + pc: (pc, pc + self.byte_size()), constraints: None, halt: false, storage: None, @@ -1498,7 +1563,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, storage: None, diff --git a/src/machine.rs b/src/machine.rs index 5f88d0a..0ad0582 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -10,6 +10,7 @@ use z3_ext::{ use crate::exec::Execution; use crate::instruction::*; use crate::memory::*; +use crate::parser::Program; use crate::state::evm::EvmState; use crate::state::tree::{NodeId, StateTree}; use crate::storage::{AccountStorage, Address}; @@ -70,14 +71,14 @@ pub struct TransactionContext { // *depends* on env / network state, it can access it through the Evm, which can be initialized with things like a Transaction context #[derive(Clone)] pub struct Evm<'ctx> { - pgm: Vec, + pgm: Program, pub states: StateTree<'ctx>, change_log: Vec>, pub inverse_state: HashMap, } impl<'ctx> Evm<'ctx> { - pub fn with_pgm(pgm: Vec) -> Self { + pub fn with_pgm(pgm: Program) -> Self { let evm_state = EvmState::with_pgm(pgm.clone()); Self { pgm, @@ -99,7 +100,7 @@ impl<'ctx> Evm<'ctx> { } impl<'ctx> Evm<'ctx> { - pub fn new(pgm: Vec) -> Self { + pub fn new(pgm: Program) -> Self { let evm_state = EvmState::with_pgm(pgm.clone()); Self { @@ -116,6 +117,13 @@ impl<'ctx> Evm<'ctx> { } } + pub fn exec_check(&mut self) { + let execution = self.exec(); + + let exec_tree = execution.states; + + } + // pub fn exec_check(&mut self) -> Vec<(ExecBranch, Option>)> { // let evm_trace = self.exec(); // let mut solver = z3_ext::Solver::new(ctx()); @@ -250,7 +258,7 @@ impl<'ctx> Machine<32> for Evm<'ctx> { // leaves // } - fn pgm(&self) -> Vec { + fn pgm(&self) -> Program { self.pgm.clone() } @@ -352,23 +360,23 @@ fn machine_returns_one_exec_for_non_branching_pgm() { push32(bvi(50)), ]; - let mut evm = Evm::new(pgm); - let execution = evm.exec(); - let exec_tree = &execution.states; - let final_states = exec_tree.leaves(); - assert_eq!(2, final_states.len()); - assert_eq!( - final_states - .first() - .unwrap() - .val - .stack() - .peek_nth(1) - .cloned() - .unwrap(), - bvi(100) - ); - eprintln!("Final states: {:#?}", final_states); + // let mut evm = Evm::new(pgm); + // let execution = evm.exec(); + // let exec_tree = &execution.states; + // let final_states = exec_tree.leaves(); + // assert_eq!(2, final_states.len()); + // assert_eq!( + // final_states + // .first() + // .unwrap() + // .val + // .stack() + // .peek_nth(1) + // .cloned() + // .unwrap(), + // bvi(100) + // ); + // eprintln!("Final states: {:#?}", final_states); } #[test] @@ -384,19 +392,8 @@ fn test_mem_store_mem_load() { // push32(bvi(5)), // Instruction::MLoad, ]; - /** - stack memory - 3 null - 2 3 null - - null {2: 3} - 2 {2 : 3} - 3 {2 : 3} - 5 3 {2: 3} - null {2: 3, 5: 3} - 3 {2: 3, 5: 3} - */ - let mut evm = Evm::new(pgm); + + // let mut evm = Evm::new(pgm); // { // let sat_branches = evm.exec_check(); @@ -413,5 +410,5 @@ fn test_mem_store_mem_load() { // eprintln!("Stack top size: {:#?}", top.as_ref().get_size()); // assert_eq!(top, bvi(3)); // } - eprintln!("STATES > {:#?}", evm.states); + //eprintln!("STATES > {:#?}", evm.states); } diff --git a/src/memory.rs b/src/memory.rs index 07f3215..f019425 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -1,6 +1,7 @@ use crate::bvi; use std::collections::hash_map::Entry; use std::collections::HashMap; +use ruint::aliases::U1; use z3_ext::ast::{Ast, BV}; use crate::record::{Index, MemChange, MemOp}; @@ -17,6 +18,7 @@ impl MachineComponent for Memory { type Record = MemChange; fn apply_change(&mut self, rec: Self::Record) { + let MemChange { ops_log } = rec; let mut highest_idx = self.highest_idx; ops_log.into_iter().for_each(|op| match op { @@ -25,10 +27,7 @@ impl MachineComponent for Memory { val.simplify(); let mut idx = idx; idx.simplify(); - eprintln!( - "MEM WRITE FOR MEM APPLY: idx: {:#?}, value: {:#?}", - idx, val - ); + eprintln!("MEM WRITE FOR MEM APPLY: idx: {:#?}, value: {:#?}", idx, val); let idx_cmp: usize = idx.clone().into(); if idx_cmp > highest_idx { highest_idx = idx_cmp; @@ -79,15 +78,12 @@ impl Memory { let idx: usize = idx.into(); let mut bytes = vec![]; let mut mem = self.inner.clone(); - eprintln!(" MEM IN READ WORD: {:#?}", mem); + // eprintln!(" MEM IN READ WORD: {:#?}", mem); while i < 32 { let idx = idx + 31; + let val = mem.get(idx - i).unwrap().as_ref().clone(); - eprintln!( - "MEM VAL IN READ WORD FOR IDX - i:\nmem loc {:#?}\nval: {:#?}", - (idx - i), - val - ); + //eprintln!("MEM VAL IN READ WORD FOR IDX - i:\nmem loc {:#?}\nval: {:#?}", (idx - i), val); bytes.push(val); i += 1; } @@ -100,6 +96,7 @@ impl Memory { } else { new_bv_inner = new_bv_inner.concat(&b); } + }); BitVec { inner: BVType::Z3(new_bv_inner), @@ -126,3 +123,25 @@ impl Memory { } } } + + +impl std::fmt::Display for Memory { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut mem_str = format!("Memory:\nSize: {} Highest Index: {}", self.size(), self.highest_idx); + self.inner.iter().enumerate().for_each(|(i, slot)| { + + let str_to_push = + if slot.as_ref().is_const() { + let slot_str = format!("{} --> {}\n", i, slot.as_ref()); + slot_str + } else { + let slot_val_as_bytes = slot.as_ref().as_u64().unwrap().to_be_bytes(); + let slot_str = format!("{} --> {:#?}\n", i, slot_val_as_bytes); + slot_str + }; + mem_str = format!("{}{}", mem_str, str_to_push); + + }); + write!(f, "{}", mem_str) + } +} \ No newline at end of file diff --git a/src/parser.rs b/src/parser.rs index 3188573..faa92d4 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,23 +1,28 @@ +use std::collections::HashMap; + use crate::{bvi, instruction::*, smt::BitVec}; use hex::decode; use revm::{opcode::OpCode, OPCODE_JUMPMAP}; use ruint::Uint; +#[derive(Default)] pub struct Parser<'a> { pgm: &'a str, + parsed: Program } impl<'a> Parser<'a> { pub fn with_pgm(pgm: &'a str) -> Self { - Self { pgm } + Self { pgm, ..Default::default() } } - pub fn parse(&self) -> Vec { + pub fn parse(&self) -> Program { let bytes = decode(self.pgm).unwrap(); let mut opcodes: Vec = vec![]; let mut pgm = vec![]; let mut skip_size = 0; let mut idx = 0_usize; + let mut pgm_map = HashMap::new(); for b in &bytes { let b = *b; if skip_size > 0 { @@ -30,19 +35,29 @@ impl<'a> Parser<'a> { let sz = push_size(b); let (inst, push_size, new_bytes) = parse_push(&bytes[idx as usize..]); skip_size = push_size; + pgm_map.insert(idx, inst.clone()); idx += skip_size as usize; pgm.push(inst); } else if is_dup(b) { - pgm.push(parse_dup(b)) + let inst = parse_dup(b); + pgm_map.insert(idx, inst.clone()); + pgm.push(inst); } else if is_swap(b) { - pgm.push(parse_swap(b)); + let inst = parse_swap(b); + pgm_map.insert(idx, inst.clone()); + pgm.push(inst); } else { let inst = Instruction::from(b); + pgm_map.insert(idx, inst.clone()); pgm.push(inst); } idx += 1; } - pgm + Program { + map: pgm_map, + pgm, + size: idx + 1 + } } } @@ -50,11 +65,11 @@ impl<'a> Parser<'a> { fn parse_push(bytes: &[u8]) -> (Instruction, u8, Vec) { let instruction_byte = *bytes.first().unwrap(); let push_size = push_size(instruction_byte); - eprintln!("PUSH SIZE IS {}", push_size); - eprintln!("Bytes len is {}", bytes.len()); + //eprintln!("PUSH SIZE IS {}", push_size); + //eprintln!("Bytes len is {}", bytes.len()); if bytes.len() - 1 < push_size as usize { let pad_len = push_size as usize - bytes.len() + 1; - eprintln!("pad len: {}", pad_len); + // eprintln!("pad len: {}", pad_len); let mut new_bytes = bytes.to_vec(); for _ in (0..pad_len) { new_bytes.push(0); @@ -67,7 +82,7 @@ fn parse_push(bytes: &[u8]) -> (Instruction, u8, Vec) { ) } else { let push_val = &bytes[1..(push_size + 1) as usize]; - eprintln!("PUSH VAL IS {:#?}", push_val); + //eprintln!("PUSH VAL IS {:#?}", push_val); ( push_op(push_size, push_val), push_size, @@ -508,6 +523,27 @@ impl From for Instruction { } } +#[derive(Default, Debug, Clone)] +pub struct Program { + pub map: HashMap, + pub pgm: Vec, + pub size: usize +} + +impl Program { + pub fn get(&self, pc: usize) -> Option { + self.map.get(&pc).cloned() + } + + pub fn get_size(&self) -> usize { + self.size + } +} + + + + + #[test] fn is_push_works() { for b in (0x60_u8..0x7f) { @@ -551,7 +587,7 @@ fn can_parse_simple_pgm() { let pgm = Parser::with_pgm(COUNTER_SOL_CODE).parse(); let sixty_four: BitVec<32> = bvi(0x0040); - eprintln!("SIXTY FOUR: {:#?}", sixty_four); + // eprintln!("SIXTY FOUR: {:#?}", sixty_four); let expected = vec![ Instruction::Push1(bvi(0x42)), Instruction::Push1(bvi(0)), @@ -562,7 +598,7 @@ fn can_parse_simple_pgm() { Instruction::Return, ]; - assert_eq!(expected, pgm); + assert_eq!(expected, pgm.pgm); } #[test] @@ -606,6 +642,15 @@ fn can_parse_larger_pgm_with_storage() { push2(bvi(0x0197)), ]; - let pgm_first_30 = (&pgm[..33]).to_vec(); + let inst10 = pgm.pgm.get(7).unwrap().clone(); + let inst10map = pgm.get(11).unwrap(); + assert_eq!(inst10, inst10map); + let pgm_first_30 = (&pgm.pgm[..33]).to_vec(); assert_eq!(expected_first_30, pgm_first_30); + let pgm_map = pgm.map.into_iter().collect::>(); + + eprintln!("PROGRAM MAP INDICES: {:#?}", pgm_map); + let pgm_enumd = pgm_first_30.into_iter().enumerate().collect::>(); + eprintln!("Enumerated pgm indices: {:#?}", pgm_enumd); + // assert_eq!(pgm_enumd, pgm_map); } diff --git a/src/state/context.rs b/src/state/context.rs new file mode 100644 index 0000000..2ea128a --- /dev/null +++ b/src/state/context.rs @@ -0,0 +1,10 @@ + + + +pub struct ExecutionContext { + block: BlockContext +} + +pub struct BlockContext { + +} \ No newline at end of file diff --git a/src/state/evm.rs b/src/state/evm.rs index dc0308e..3a28e5c 100644 --- a/src/state/evm.rs +++ b/src/state/evm.rs @@ -1,4 +1,5 @@ use crate::machine::ExecBranch; +use crate::parser::Program; use crate::state::tree::NodeId; use crate::storage::{AccountStorage, Address}; use crate::traits::MachineState; @@ -11,17 +12,19 @@ use crate::{ }; use z3_ext::ast::Bool; + #[derive(Clone, Debug, Default)] pub struct EvmState { pub memory: Memory, pub storage: AccountStorage, pub stack: Stack<32>, pc: usize, - pub pgm: Vec, + pub pgm: Program, pub address: Address, pub halt: bool, } + impl MachineComponent for EvmState { type Record = MachineRecord<32>; @@ -46,7 +49,7 @@ impl MachineComponent for EvmState { } impl<'ctx> EvmState { - pub fn with_pgm(pgm: Vec) -> Self { + pub fn with_pgm(pgm: Program) -> Self { Self { pgm, ..Default::default() @@ -58,16 +61,19 @@ impl<'ctx> EvmState { } pub fn set_pc(&mut self, new_pc: usize) { self.pc = new_pc; - if self.pc >= self.pgm.len() { + if self.pc >= self.pgm.pgm.len() { self.halt = true; } } pub fn inc_pc(&mut self) { - self.set_pc(self.pc + 1); + let curr_inst = self.curr_instruction(); + + + self.set_pc(self.pc + curr_inst.byte_size()); } pub fn can_continue(&self) -> bool { - self.pc < self.pgm.len() && !self.halt + self.pc < self.pgm.get_size() && !self.halt } pub fn curr_instruction(&self) -> Instruction { if !self.can_continue() { @@ -78,9 +84,17 @@ impl<'ctx> EvmState { eprintln!( "Getting curr inst.. curr pc: {} and curr pgm len: {}", self.pc, - self.pgm.len() + self.pgm.get_size() ); } - self.pgm.get(self.pc).cloned().unwrap() + + self.pgm.get(self.pc).expect(&format!("Expected instruction at pc: {}", self.pc)) + } +} + +impl std::fmt::Display for EvmState { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Pc: {}\nHalted: {}\nStack: {:?}\n{}", self.pc(), self.halt, self.stack(), self.mem()) + } } diff --git a/src/state/mod.rs b/src/state/mod.rs index b6cf3f9..46ba139 100644 --- a/src/state/mod.rs +++ b/src/state/mod.rs @@ -1,3 +1,4 @@ pub mod env; pub mod evm; pub mod tree; +pub mod context; \ No newline at end of file diff --git a/src/traits.rs b/src/traits.rs index 7e1a132..f886b51 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -2,6 +2,7 @@ use crate::exec::Execution; use crate::instruction::Instruction; use crate::machine::{ExecBranch, ExecutionSummary}; use crate::memory::Memory; +use crate::parser::Program; use crate::record::{Index, MachineRecord, MemChange, StackChange, StorageChange}; use crate::smt::BitVec; use crate::stack::Stack; @@ -32,7 +33,7 @@ pub trait Machine { // All possible final states fn exec(&mut self) -> Execution; - fn pgm(&self) -> Vec; + fn pgm(&self) ->Program; fn state(&self) -> Self::State; fn state_ref(&self) -> &Self::State; fn state_ref_mut(&mut self) -> &mut Self::State; diff --git a/test-contracts/src/SimpleToken.sol b/test-contracts/src/SimpleToken.sol new file mode 100644 index 0000000..5697241 --- /dev/null +++ b/test-contracts/src/SimpleToken.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +contract SimpleToken { + mapping(address => uint256) public balances; + + constructor() { + balances[msg.sender] = 100; + } + + function transfer(address recipient, uint256 amt) public { + require(balances[msg.sender] >= amt); + balances[msg.sender] -= amt; + balances[recipient] += amt; + } + + function getBalance(address owner) external view returns (uint256) { + return balances[owner]; + } +} diff --git a/test-contracts/src/VulnerableVault.sol b/test-contracts/src/VulnerableVault.sol new file mode 100644 index 0000000..dd4e40e --- /dev/null +++ b/test-contracts/src/VulnerableVault.sol @@ -0,0 +1,24 @@ +pragma solidity ^0.8.0; + +contract Vault { + + mapping (address => uint) public credit; + + function deposit(address to) payable public{ + credit[to] += msg.value; + } + + function withdraw(uint amount) public{ + if (credit[msg.sender] >= amount) { + (bool success, ) = msg.sender.call{value: amount}(""); + require(success); + unchecked{ + credit[msg.sender] -= amount; + } + } + } + + function queryCredit(address to) view public returns(uint){ + return credit[to]; + } +} \ No newline at end of file diff --git a/tests/lib.rs b/tests/lib.rs index db3d36e..078eb50 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -32,8 +32,8 @@ fn can_run_simple_storage_pgm() { let mut evm = Evm::new(pgm); - let sat_branches = evm.exec(); - let leaf = sat_branches.states.leaves(); + let execution = evm.exec(); + let leaf = execution.states.leaves(); assert_eq!(2, leaf.len()); eprintln!("LEAVES: {:#?}", leaf); let final_tree = leaf.get(1).unwrap().clone(); @@ -43,3 +43,15 @@ fn can_run_simple_storage_pgm() { assert_eq!(bvi(128), mem_val); } + +#[test] +fn can_run_counter_with_storage_mapping_pgm() { + let pgm = Parser::with_pgm(COUNTER_WITH_STORAGE_MAPPING).parse(); + let mut evm = Evm::new(pgm); + + + let execution = evm.exec(); + let leaf = execution.states.leaves(); + assert_eq!(2, leaf.len()); + // eprintln!("LEAVES: {:#?}", leaf); +} \ No newline at end of file From fd3a6e28dfe905f3141866e744821550ce0f696e Mon Sep 17 00:00:00 2001 From: tannr Date: Wed, 2 Aug 2023 22:29:42 -0400 Subject: [PATCH 20/28] add initial swap support --- src/instruction/mod.rs | 53 +++++++++++++++++++++++++++++------------- src/record.rs | 5 ++++ src/stack.rs | 50 +++++++++++++++++++++++++++++++++++++-- 3 files changed, 90 insertions(+), 18 deletions(-) diff --git a/src/instruction/mod.rs b/src/instruction/mod.rs index b753ac9..63feafd 100644 --- a/src/instruction/mod.rs +++ b/src/instruction/mod.rs @@ -183,6 +183,19 @@ fn exec_dup_nth(mach: &EvmState, n: usize) -> MachineRecord<32> { } } +fn exec_swap_nth(mach: &EvmState, n: usize) -> MachineRecord<32> { + + + MachineRecord { + stack: Some(StackChange { pop_qty: 0, push_qty: 0, swap_depth: n as u8, ops: vec![] }), + pc: (mach.pc(), mach.pc() + 1), + mem: Default::default(), + halt: false, + storage: None, + constraints: None, + } +} + impl Instruction { pub fn byte_size(&self) -> usize { let inst_additional_size: usize = match self { @@ -240,6 +253,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { let stack_change = StackChange { pop_qty: 2, push_qty: 1, + swap_depth: 0, ops: vec![stack_op_1, stack_op_2, stack_op_3], }; MachineRecord { @@ -808,6 +822,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { let pc = mach.pc(); let stack_rec = StackChange { pop_qty: 1, + swap_depth: 0, push_qty: 0, ops: vec![StackOp::Pop], }; @@ -924,6 +939,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { let stack_rec = StackChange { pop_qty: 2, push_qty: 0, + swap_depth: 0, ops: vec![StackOp::Pop, StackOp::Pop], }; let storage_change = StorageChange { @@ -945,10 +961,12 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { } Instruction::Jump => { let jump_dest = mach.stack().peek().unwrap(); + eprintln!("JUMP DEST IN UNCONDITIONAL JUMP: {:#?}", jump_dest); let jump_dest_concrete = jump_dest.as_ref().simplify().as_u64().unwrap() as usize; let stack_rec = StackChange { pop_qty: 1, push_qty: 0, + swap_depth: 0, ops: vec![StackOp::Pop] }; MachineRecord { @@ -971,6 +989,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { let stack_rec = StackChange { pop_qty: 2, + swap_depth: 0, push_qty: 0, ops: vec![StackOp::Pop, StackOp::Pop], }; @@ -988,6 +1007,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { let pc = BitVec::new_literal(mach.pc() as u64); let stack_rec = StackChange { pop_qty: 0, + swap_depth: 0, push_qty: 1, ops: vec![StackOp::Push(pc)], }; @@ -1489,22 +1509,22 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { Instruction::Dup14 => exec_dup_nth(mach, 14), Instruction::Dup15 => exec_dup_nth(mach, 15), Instruction::Dup16 => exec_dup_nth(mach, 16), - Instruction::Swap1 => todo!(), - Instruction::Swap2 => todo!(), - Instruction::Swap3 => todo!(), - Instruction::Swap4 => todo!(), - Instruction::Swap5 => todo!(), - Instruction::Swap6 => todo!(), - Instruction::Swap7 => todo!(), - Instruction::Swap8 => todo!(), - Instruction::Swap9 => todo!(), - Instruction::Swap10 => todo!(), - Instruction::Swap11 => todo!(), - Instruction::Swap12 => todo!(), - Instruction::Swap13 => todo!(), - Instruction::Swap14 => todo!(), - Instruction::Swap15 => todo!(), - Instruction::Swap16 => todo!(), + Instruction::Swap1 => exec_dup_nth(mach, 1), + Instruction::Swap2 => exec_dup_nth(mach, 2), + Instruction::Swap3 => exec_dup_nth(mach, 3), + Instruction::Swap4 => exec_dup_nth(mach, 4), + Instruction::Swap5 => exec_dup_nth(mach, 5), + Instruction::Swap6 => exec_dup_nth(mach, 6), + Instruction::Swap7 => exec_dup_nth(mach, 7), + Instruction::Swap8 => exec_dup_nth(mach, 8), + Instruction::Swap9 => exec_dup_nth(mach, 9), + Instruction::Swap10 => exec_dup_nth(mach, 10), + Instruction::Swap11 => exec_dup_nth(mach, 11), + Instruction::Swap12 => exec_dup_nth(mach, 12), + Instruction::Swap13 => exec_dup_nth(mach, 13), + Instruction::Swap14 => exec_dup_nth(mach, 14), + Instruction::Swap15 => exec_dup_nth(mach, 15), + Instruction::Swap16 => exec_dup_nth(mach, 16), Instruction::Log0 => todo!(), Instruction::Log1 => todo!(), Instruction::Log2 => todo!(), @@ -1539,6 +1559,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { let stack_change = StackChange { pop_qty: 0, push_qty: 1, + swap_depth: 0, ops: vec![StackOp::Push(bv.clone())], }; let pc = mach.pc(); diff --git a/src/record.rs b/src/record.rs index b4f84f2..04390ca 100644 --- a/src/record.rs +++ b/src/record.rs @@ -38,12 +38,14 @@ pub enum MemOp { pub enum StackOp { Push(BitVec), Pop, + Swap(usize) } #[derive(Default, Clone, Debug)] pub struct StackChange { pub pop_qty: u64, pub push_qty: u64, + pub swap_depth: u8, pub ops: Vec>, } @@ -52,6 +54,7 @@ impl StackChange { Self { pop_qty: 0, push_qty: 1, + swap_depth: 0, ops: vec![StackOp::Push(val)], } } @@ -63,11 +66,13 @@ impl StackChange { ops.iter().for_each(|op| match op { StackOp::Push(_) => push_qty += 1, StackOp::Pop => pop_qty += 1, + _ => () }); Self { push_qty, pop_qty, + swap_depth: 0, ops, } } diff --git a/src/stack.rs b/src/stack.rs index b823309..8cff6d8 100644 --- a/src/stack.rs +++ b/src/stack.rs @@ -1,4 +1,4 @@ -use crate::record::StackChange; +use crate::{record::StackChange, bvi}; use std::fmt::{Debug, Formatter}; use super::smt::*; @@ -27,7 +27,7 @@ impl Stack { } pub fn peek(&self) -> Option<&BitVec> { - self.stack.last() + self.stack.get(self.size - 1) } pub fn size(&self) -> usize { @@ -35,6 +35,7 @@ impl Stack { self.stack.len() } + // where n = 0 is top of the stack pub fn peek_nth(&self, n: usize) -> Option<&BitVec> { if n >= self.size() { return None; @@ -42,6 +43,27 @@ impl Stack { self.stack.get(self.size - n - 1) } + // where n is stack modulo top element; + pub (crate) fn swap_nth(&mut self, swap_depth: usize) { + if swap_depth < self.size() { + let mut new_stack = self.stack.clone(); + let top_idx = self.size - 1; + let swap_idx = self.size - swap_depth - 1; + let top = self.peek().cloned().unwrap(); + let swapped = self.peek_nth(swap_depth).cloned().expect( + &format!("stack too deep to swap with depth {}. Stack size: {}", swap_depth, self.size()) + ); + new_stack.remove(swap_idx); + new_stack.insert(swap_idx, top); + new_stack.pop(); + new_stack.push(swapped); + self.stack = new_stack; + + } else { + eprintln!("WILL NOT SWAP"); + } + } + pub fn peek_top(&self) -> Option<[&BitVec; N]> { if self.size() < N { return None; @@ -59,6 +81,7 @@ impl MachineComponent for Stack { pop_qty, push_qty, ops, + swap_depth } = rec; let mut new_stack = self.clone(); @@ -67,10 +90,33 @@ impl MachineComponent for Stack { crate::record::StackOp::Push(v) => new_stack.push(v.clone()), crate::record::StackOp::Pop => { new_stack.pop(); + }, + crate::record::StackOp::Swap(depth) => { + } }); + + if swap_depth > 0 { + eprintln!("SWAP OCCURRING of DEPTH {}. STACK BEFORE: {:#?}", swap_depth, new_stack); + new_stack.swap_nth(swap_depth as usize); + eprintln!("STACK AFTER {:#?}", new_stack); + } self.stack = new_stack.stack; self.size = new_stack.size; } } + + +#[test] +fn test_swap() { + let mut stack: Stack<1> = Stack::default(); + stack.push(bvi(1)); + stack.push(bvi(2)); + stack.push(bvi(3)); + stack.push(bvi(4)); + stack.swap_nth(2); + assert_eq!(stack.peek().cloned().unwrap(), bvi(2)); + assert_eq!(stack.peek_nth(2).cloned().unwrap(), bvi(2)); + +} \ No newline at end of file From 8d84b395ea66af0be71ef6fd32d119bf80e36d34 Mon Sep 17 00:00:00 2001 From: tannr Date: Thu, 3 Aug 2023 13:31:54 -0400 Subject: [PATCH 21/28] fix: call exec_swap_nth instead of dup --- examples/swaps.rs | 44 ++++++++++++++++++++++++++++++++++++++++++ src/exec/mod.rs | 3 ++- src/instruction/mod.rs | 37 ++++++++++++++++++----------------- src/machine.rs | 23 +++++++++++++++------- src/parser.rs | 2 +- src/record.rs | 2 +- src/stack.rs | 20 +++++++++++++++---- src/state/evm.rs | 40 ++++++++++++++++++++++++-------------- src/state/tree.rs | 2 ++ 9 files changed, 126 insertions(+), 47 deletions(-) create mode 100644 examples/swaps.rs diff --git a/examples/swaps.rs b/examples/swaps.rs new file mode 100644 index 0000000..751ec54 --- /dev/null +++ b/examples/swaps.rs @@ -0,0 +1,44 @@ +#![allow(unused_imports)] +use ser::{ + bvc, bvi, conversion::*, machine::*, memory::*, parser::*, stack::*, storage::*, traits::*, +}; +use z3::ast::*; +/* +SHOULD REVERT: + +PUSH1 0x42 +PUSH1 0x00 +PUSH2 0x5000 +CALLDATASIZE +SWAP2 +PUSH1 0x0e // 14 +JUMPI +REVERT +JUMPDEST +PUSH1 0 +RETURN + + +SHOULD NOT REVERT: + +PUSH1 0x42 +PUSH1 0x00 +PUSH2 0x5000 +PUSH1 0x40 +SWAP3 +PUSH1 0x0e // 14 +JUMPI +REVERT +JUMPDEST +PUSH1 0x10 +RETURN + +*/ +const SWAP2_JUMPI_REVERT: &str = r#"604260006150003691600d57fd5b6000f3"#; +const SWAP3_JUMPI_RETURN_16: &str = r#"60426000615000604091600e57fd5b6000f3"#; +fn main() { + let pgm = Parser::with_pgm(SWAP2_JUMPI_REVERT).parse(); + let mut evm = Evm::new(pgm); + let execution = evm.exec(); + eprintln!("Execution tree: {:#?}", execution.states); +} \ No newline at end of file diff --git a/src/exec/mod.rs b/src/exec/mod.rs index e955bf4..1c4f534 100644 --- a/src/exec/mod.rs +++ b/src/exec/mod.rs @@ -162,8 +162,9 @@ impl<'ctx> Execution<'ctx> { let curr_inst = curr_state.curr_instruction(); let curr_pc = curr_state.pc(); - eprintln!("CURR STATE IN STEP FROM MUT: {:#?}", curr_state); + //eprintln!("CURR STATE IN STEP FROM MUT: {:#?}", curr_state); let change_rec = curr_inst.exec(&curr_state); + eprintln!("CHANGE REC IN STEP: {:#?}", change_rec); let is_branch = change_rec.constraints.is_some(); curr_state.apply_change(change_rec.clone()); diff --git a/src/instruction/mod.rs b/src/instruction/mod.rs index 63feafd..97d83fe 100644 --- a/src/instruction/mod.rs +++ b/src/instruction/mod.rs @@ -185,9 +185,9 @@ fn exec_dup_nth(mach: &EvmState, n: usize) -> MachineRecord<32> { fn exec_swap_nth(mach: &EvmState, n: usize) -> MachineRecord<32> { - + eprintln!("EXEC SWAP NTH CALLED. N: {}", n); MachineRecord { - stack: Some(StackChange { pop_qty: 0, push_qty: 0, swap_depth: n as u8, ops: vec![] }), + stack: Some(StackChange { pop_qty: 0, push_qty: 0, swap_depth: n, ops: vec![] }), pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, @@ -993,6 +993,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { push_qty: 0, ops: vec![StackOp::Pop, StackOp::Pop], }; + eprintln!("JUMPI REACHED"); MachineRecord { stack: Some(stack_rec), @@ -1509,22 +1510,22 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { Instruction::Dup14 => exec_dup_nth(mach, 14), Instruction::Dup15 => exec_dup_nth(mach, 15), Instruction::Dup16 => exec_dup_nth(mach, 16), - Instruction::Swap1 => exec_dup_nth(mach, 1), - Instruction::Swap2 => exec_dup_nth(mach, 2), - Instruction::Swap3 => exec_dup_nth(mach, 3), - Instruction::Swap4 => exec_dup_nth(mach, 4), - Instruction::Swap5 => exec_dup_nth(mach, 5), - Instruction::Swap6 => exec_dup_nth(mach, 6), - Instruction::Swap7 => exec_dup_nth(mach, 7), - Instruction::Swap8 => exec_dup_nth(mach, 8), - Instruction::Swap9 => exec_dup_nth(mach, 9), - Instruction::Swap10 => exec_dup_nth(mach, 10), - Instruction::Swap11 => exec_dup_nth(mach, 11), - Instruction::Swap12 => exec_dup_nth(mach, 12), - Instruction::Swap13 => exec_dup_nth(mach, 13), - Instruction::Swap14 => exec_dup_nth(mach, 14), - Instruction::Swap15 => exec_dup_nth(mach, 15), - Instruction::Swap16 => exec_dup_nth(mach, 16), + Instruction::Swap1 => exec_swap_nth(mach, 1), + Instruction::Swap2 => exec_swap_nth(mach, 2), + Instruction::Swap3 => exec_swap_nth(mach, 3), + Instruction::Swap4 => exec_swap_nth(mach, 4), + Instruction::Swap5 => exec_swap_nth(mach, 5), + Instruction::Swap6 => exec_swap_nth(mach, 6), + Instruction::Swap7 => exec_swap_nth(mach, 7), + Instruction::Swap8 => exec_swap_nth(mach, 8), + Instruction::Swap9 => exec_swap_nth(mach, 9), + Instruction::Swap10 => exec_swap_nth(mach, 10), + Instruction::Swap11 => exec_swap_nth(mach, 11), + Instruction::Swap12 => exec_swap_nth(mach, 12), + Instruction::Swap13 => exec_swap_nth(mach, 13), + Instruction::Swap14 => exec_swap_nth(mach, 14), + Instruction::Swap15 => exec_swap_nth(mach, 15), + Instruction::Swap16 => exec_swap_nth(mach, 16), Instruction::Log0 => todo!(), Instruction::Log1 => todo!(), Instruction::Log2 => todo!(), diff --git a/src/machine.rs b/src/machine.rs index 0ad0582..4e60131 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -170,6 +170,7 @@ impl<'ctx> Machine<32> for Evm<'ctx> { let mut exec = Execution::new(self.states.val.clone(), self.pgm.clone()); let first_step = exec.step_mut(); step_recs.push(first_step); + let mut ids = vec![]; loop { if let Some(step) = step_recs.pop() { eprintln!( @@ -177,24 +178,32 @@ impl<'ctx> Machine<32> for Evm<'ctx> { step.halted_left(), step.halted_right() ); - if !step.halted_right() { - let continue_from_right = step.right_id(); - if let Some(right_id) = continue_from_right { + eprintln!("LEFT ID: {:#?} RIGHT ID: {:#?}", step.left_id(), step.right_id()); + // if !step.halted_right() { + // let continue_from_right = step.right_id(); + if let Some(right_id) = step.right_id() { + ids.push(right_id.id()); let nxt_right_step = exec.step_from_mut(right_id); step_recs.push(nxt_right_step); } - } - if !step.halted_left() { - let continue_from_left = step.left_id(); - if let Some(left_id) = continue_from_left { + //} + // if !step.halted_left() { + // let continue_from_left = step.left_id(); + if let Some(left_id) = step.left_id() { + ids.push(left_id.id()); let nxt_step = exec.step_from_mut(left_id); step_recs.push(nxt_step); } + // } + + if step.halted_left() && step.halted_right() { + eprintln!("Both have halted... Here are the step recs left: {:#?}", step_recs); } } else { break; } } + eprintln!("All ids that were executed during a step: {:#?}", ids); exec } diff --git a/src/parser.rs b/src/parser.rs index faa92d4..4665880 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -526,7 +526,7 @@ impl From for Instruction { #[derive(Default, Debug, Clone)] pub struct Program { pub map: HashMap, - pub pgm: Vec, + pgm: Vec, pub size: usize } diff --git a/src/record.rs b/src/record.rs index 04390ca..c96b92f 100644 --- a/src/record.rs +++ b/src/record.rs @@ -45,7 +45,7 @@ pub enum StackOp { pub struct StackChange { pub pop_qty: u64, pub push_qty: u64, - pub swap_depth: u8, + pub swap_depth: usize, pub ops: Vec>, } diff --git a/src/stack.rs b/src/stack.rs index 8cff6d8..c8dee35 100644 --- a/src/stack.rs +++ b/src/stack.rs @@ -45,6 +45,7 @@ impl Stack { // where n is stack modulo top element; pub (crate) fn swap_nth(&mut self, swap_depth: usize) { + eprintln!("SWAP EXECUTING AT DEPTH: {}", swap_depth); if swap_depth < self.size() { let mut new_stack = self.stack.clone(); let top_idx = self.size - 1; @@ -53,10 +54,21 @@ impl Stack { let swapped = self.peek_nth(swap_depth).cloned().expect( &format!("stack too deep to swap with depth {}. Stack size: {}", swap_depth, self.size()) ); - new_stack.remove(swap_idx); - new_stack.insert(swap_idx, top); - new_stack.pop(); - new_stack.push(swapped); + eprintln!("STACK BEFORE SWAP: {:#?}", new_stack); + new_stack = new_stack.into_iter().enumerate().map(move |(idx, val)| { + if idx == swap_idx { + return top.clone(); + } else if idx == top_idx { + return swapped.clone(); + } else { + val + } + }).collect::>(); + eprintln!("STACK AFTER SWAP: {:#?}", new_stack); + // new_stack.remove(swap_idx); + // new_stack.insert(swap_idx, top); + // new_stack.pop(); + // new_stack.push(swapped); self.stack = new_stack; } else { diff --git a/src/state/evm.rs b/src/state/evm.rs index 3a28e5c..283ffba 100644 --- a/src/state/evm.rs +++ b/src/state/evm.rs @@ -13,7 +13,7 @@ use crate::{ use z3_ext::ast::Bool; -#[derive(Clone, Debug, Default)] +#[derive(Clone, Default)] pub struct EvmState { pub memory: Memory, pub storage: AccountStorage, @@ -61,7 +61,8 @@ impl<'ctx> EvmState { } pub fn set_pc(&mut self, new_pc: usize) { self.pc = new_pc; - if self.pc >= self.pgm.pgm.len() { + if self.pc >= self.pgm.get_size() { + eprintln!("SET PC--- PC: {} -- PGM SIZE: {}", self.pc, self.pgm.get_size()); self.halt = true; } } @@ -76,25 +77,34 @@ impl<'ctx> EvmState { self.pc < self.pgm.get_size() && !self.halt } pub fn curr_instruction(&self) -> Instruction { + self.pgm.get(self.pc).expect(&format!("Expected instruction at pc: {}", self.pc)) + } + pub fn curr_inst_debug(&self) -> Instruction { if !self.can_continue() { - eprintln!( - "EVM STATE CANNOT CONTINUE; BUT CURR INST IS REQUESTED: {:#?}", - self - ); - eprintln!( - "Getting curr inst.. curr pc: {} and curr pgm len: {}", - self.pc, - self.pgm.get_size() - ); + + eprintln!("Curr instruction debug requested but cannot continue"); } - - self.pgm.get(self.pc).expect(&format!("Expected instruction at pc: {}", self.pc)) + self.pgm.get(self.pc).unwrap() } } impl std::fmt::Display for EvmState { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "Pc: {}\nHalted: {}\nStack: {:?}\n{}", self.pc(), self.halt, self.stack(), self.mem()) - + //write!(f, "Pc: {}\nHalted: {}\nStack: {:?}\n{}", self.pc(), self.halt, self.stack(), self.mem()) + write!(f, "Pc: {}, Stack: {:#?} halt: {:#?}", self.pc(), self.stack(), self.halt) } } + +impl std::fmt::Debug for EvmState { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("EvmState").field("stack", &self.stack) + .field("pc", &self.pc) + .field("address", &self.address) + .field("halt", &self.halt) + .field("instruction", &self.curr_inst_debug()) + .field("pgm size", &self.pgm.size) + .finish() + } +} + + diff --git a/src/state/tree.rs b/src/state/tree.rs index 4ce441a..5800f51 100644 --- a/src/state/tree.rs +++ b/src/state/tree.rs @@ -50,6 +50,8 @@ pub struct StateTree<'ctx> { pub(crate) right: Option>>, } + + impl<'ctx> From<(EvmState, Bool<'ctx>)> for StateTree<'ctx> { fn from(t: (EvmState, Bool<'ctx>)) -> Self { Self { From 1db5b105e4779bab73cbe0ffd3d672bd74bc78f3 Mon Sep 17 00:00:00 2001 From: tannr Date: Thu, 3 Aug 2023 17:42:57 -0400 Subject: [PATCH 22/28] Add Evm::exec_check() for all-path reachability analysis --- examples/swaps.rs | 10 ++++++-- src/machine.rs | 47 ++++++++++++++++++++++++++++++++--- src/state/tree.rs | 33 ++++++++++++++++++++++++- tests/lib.rs | 62 ++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 145 insertions(+), 7 deletions(-) diff --git a/examples/swaps.rs b/examples/swaps.rs index 751ec54..0a6b7aa 100644 --- a/examples/swaps.rs +++ b/examples/swaps.rs @@ -2,7 +2,7 @@ use ser::{ bvc, bvi, conversion::*, machine::*, memory::*, parser::*, stack::*, storage::*, traits::*, }; -use z3::ast::*; +use z3::{ast::*, SatResult}; /* SHOULD REVERT: @@ -40,5 +40,11 @@ fn main() { let pgm = Parser::with_pgm(SWAP2_JUMPI_REVERT).parse(); let mut evm = Evm::new(pgm); let execution = evm.exec(); - eprintln!("Execution tree: {:#?}", execution.states); + // Should have two paths: one reachable and one not. The reachable path should be the one in which there is a revert + let reachability_report = Evm::exec_check(execution); + assert_eq!(2, reachability_report.len()); + assert_eq!(SatResult::Sat, reachability_report.first().unwrap().1.unwrap()); + assert_eq!(SatResult::Unsat, reachability_report.get(1).unwrap().1.unwrap()); + + } \ No newline at end of file diff --git a/src/machine.rs b/src/machine.rs index 4e60131..ff934be 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -117,13 +117,52 @@ impl<'ctx> Evm<'ctx> { } } - pub fn exec_check(&mut self) { - let execution = self.exec(); + + // A path from a node is the current node and the union of the paths of its children + pub fn paths(trace: Execution<'ctx>) -> Vec>)>>{ - let exec_tree = execution.states; + let mut paths_collected = vec![]; + + let mut curr_path = vec![]; + let tree = Some(Box::new(trace.states)); + StateTree::find_paths(&tree, &mut curr_path, &mut paths_collected); + paths_collected } + + pub fn exec_check(trace: Execution<'ctx>) -> Vec<(Vec<(NodeId, Instruction, Option>)>, Option, Option)> { + let mut solver = z3_ext::Solver::new(ctx()); + let paths = Self::paths(trace); + let reachable = paths.into_iter().map(|path| { + let mut result = (path.clone(), None, None); + solver.push(); + path.iter().for_each(|step| { + if let Some(constraint) = step.2.clone() { + solver.assert(&constraint); + } + }); + match solver.check() { + SatResult::Sat => { + let model = solver.get_model(); + result.1 = Some(SatResult::Sat); + + result.2 = model.map(|m| m.to_string()); + }, + SatResult::Unsat => { + result.1 = Some(SatResult::Unsat); + }, + SatResult::Unknown => { + result.1 = Some(SatResult::Unknown); + } + } + solver.pop(1); + result + }).collect::>(); + reachable + + } + // pub fn exec_check(&mut self) -> Vec<(ExecBranch, Option>)> { // let evm_trace = self.exec(); // let mut solver = z3_ext::Solver::new(ctx()); @@ -207,6 +246,8 @@ impl<'ctx> Machine<32> for Evm<'ctx> { exec } + + // fn exec(&mut self) -> Vec> { // let mut curr_state = self.states.val.clone(); // let curr_id = self.states.id.clone(); diff --git a/src/state/tree.rs b/src/state/tree.rs index 5800f51..a6c8029 100644 --- a/src/state/tree.rs +++ b/src/state/tree.rs @@ -1,5 +1,5 @@ use super::evm::*; -use crate::{ctx, z3_ext::ast::Ast, z3_ext::ast::Bool}; +use crate::{ctx, z3_ext::ast::Ast, z3_ext::ast::Bool, instruction::Instruction}; use std::borrow::BorrowMut; use uuid::Uuid; @@ -119,6 +119,37 @@ impl<'ctx> StateTree<'ctx> { items } + pub fn find_paths(node: &Option>>, current_path: &mut Vec<(NodeId, Instruction, Option>)>, all_paths: &mut Vec>)>> ) { + if let Some(ref node) = *node { + current_path.push((node.id.clone(), node.val.curr_instruction(), node.path_condition.clone())); + + if node.left.is_none() && node.right.is_none() { + all_paths.push(current_path.clone()); + } else { + Self::find_paths(&node.left, current_path, all_paths); + Self::find_paths(&node.right, current_path, all_paths); + } + + current_path.pop(); + } + } + pub fn inorder_stateless(&self) -> Vec<(NodeId, Option>)> { + let mut items = vec![( + self.id.clone(), + self.path_condition.clone(), + )]; + + if let Some(left) = &self.left { + let left_tree_inorder = left.inorder_stateless(); + items.extend(left_tree_inorder); + } + if let Some(right) = &self.right { + let right_tree_inorder = right.inorder_stateless(); + items.extend(right_tree_inorder); + } + items + } + pub fn insert(&mut self, tree: impl Into>) { if let Some(left) = &mut self.left { left.insert(tree); diff --git a/tests/lib.rs b/tests/lib.rs index 078eb50..53d902e 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -3,7 +3,7 @@ extern crate ser; use ser::{ bvc, bvi, conversion::*, machine::*, memory::*, parser::*, stack::*, storage::*, traits::*, }; -use z3::ast::*; +use z3::{ast::*, SatResult}; pub const COUNTER_WITH_STORAGE_MAPPING: &str = r#"608060405234801561001057600080fd5b5060056000806001815260200190815260200160002081905550610197806100396000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063846719e01461003b578063d78233d61461006b575b600080fd5b6100556004803603810190610050919061010a565b61009b565b6040516100629190610146565b60405180910390f35b6100856004803603810190610080919061010a565b6100b7565b6040516100929190610146565b60405180910390f35b6000806000838152602001908152602001600020549050919050565b60006020528060005260406000206000915090505481565b600080fd5b6000819050919050565b6100e7816100d4565b81146100f257600080fd5b50565b600081359050610104816100de565b92915050565b6000602082840312156101205761011f6100cf565b5b600061012e848285016100f5565b91505092915050565b610140816100d4565b82525050565b600060208201905061015b6000830184610137565b9291505056fea2646970667358fe122066b287fef10118cba238fe38953bfefe938afefefefefe94fefe3682fefefefe64736f6c63430008110033"#; pub const SUPERSIMPLE: &str = r#"604260005260206000F3"#; @@ -54,4 +54,64 @@ fn can_run_counter_with_storage_mapping_pgm() { let leaf = execution.states.leaves(); assert_eq!(2, leaf.len()); // eprintln!("LEAVES: {:#?}", leaf); +} + +/* +SHOULD REVERT: + +PUSH1 0x42 +PUSH1 0x00 +PUSH2 0x5000 +CALLDATASIZE +SWAP2 +PUSH1 0x0e // 14 +JUMPI +REVERT +JUMPDEST +PUSH1 0 +RETURN + + +SHOULD NOT REVERT: + +PUSH1 0x42 +PUSH1 0x00 +PUSH2 0x5000 +PUSH1 0x40 +SWAP3 +PUSH1 0x0e // 14 +JUMPI +REVERT +JUMPDEST +PUSH1 0x10 +RETURN + +*/ + +const SWAP2_JUMPI_REVERT: &str = r#"604260006150003691600d57fd5b6000f3"#; +const SWAP3_JUMPI_RETURN_16: &str = r#"60426000615000604091600e57fd5b6000f3"#; +#[test] +fn test_swap2_jumpi_revert() { + let pgm = Parser::with_pgm(SWAP2_JUMPI_REVERT).parse(); + let mut evm = Evm::new(pgm); + let execution = evm.exec(); + eprintln!("Execution tree: {:#?}", execution.states.clone()); + // Should have two paths: one reachable and one not. The reachable path should be the one in which there is a revert + let reachability_report = Evm::exec_check(execution); + assert_eq!(2, reachability_report.len()); + assert_eq!(SatResult::Sat, reachability_report.first().unwrap().1.unwrap()); + assert_eq!(SatResult::Unsat, reachability_report.get(1).unwrap().1.unwrap()); + +} + +#[test] +fn test_swap3_jumpi_return() { + let pgm = Parser::with_pgm(SWAP3_JUMPI_RETURN_16).parse(); + let mut evm = Evm::new(pgm); + let execution = evm.exec(); + //eprintln!("Execution tree: {:#?}", execution.states); + let final_states = execution.states.leaves(); + eprintln!("LEAVES: {:#?}", final_states); + assert_eq!(2, final_states.len()); + assert!(false); } \ No newline at end of file From 97ead90febf70df242340330fa6b72b9e812b339 Mon Sep 17 00:00:00 2001 From: tannr Date: Thu, 3 Aug 2023 17:43:33 -0400 Subject: [PATCH 23/28] code cleanup --- examples/simple_pgm.rs | 9 ++-- examples/simple_storage.rs | 18 +++---- examples/swaps.rs | 14 +++-- src/exec/mod.rs | 20 +++++--- src/instruction/mod.rs | 52 ++++++++++--------- src/machine.rs | 102 ++++++++++++++++++++----------------- src/memory.rs | 27 +++++----- src/parser.rs | 23 ++++----- src/record.rs | 4 +- src/stack.rs | 52 ++++++++++--------- src/state/context.rs | 9 +--- src/state/evm.rs | 39 ++++++++------ src/state/mod.rs | 2 +- src/state/tree.rs | 25 +++++---- src/traits.rs | 2 +- tests/lib.rs | 22 ++++---- 16 files changed, 226 insertions(+), 194 deletions(-) diff --git a/examples/simple_pgm.rs b/examples/simple_pgm.rs index 5043b5c..a704963 100644 --- a/examples/simple_pgm.rs +++ b/examples/simple_pgm.rs @@ -8,7 +8,7 @@ pub const SUPERSIMPLE: &str = r#"604260005260206000F3"#; fn main() { let pgm = Parser::with_pgm(SUPERSIMPLE).parse(); let mut evm = Evm::new(pgm); - + let execution_trace = evm.exec(); { let leaf = execution_trace.states.leaves(); @@ -20,7 +20,10 @@ fn main() { assert_eq!(bvi(66), mem_val); } - let tree_flattened = execution_trace.states.into_iter().collect::>(); - eprintln!("Nodes in tree: {}\nTree Nodes: {:#?}", tree_flattened.len(), tree_flattened); + eprintln!( + "Nodes in tree: {}\nTree Nodes: {:#?}", + tree_flattened.len(), + tree_flattened + ); } diff --git a/examples/simple_storage.rs b/examples/simple_storage.rs index e118aab..79fd163 100644 --- a/examples/simple_storage.rs +++ b/examples/simple_storage.rs @@ -7,23 +7,21 @@ use z3::ast::*; pub const STORAGE_SIMPLE: &str = r#"6080604052348015600f57600080fd5b506004361060325760003560e01c80631ab06ee5146037578063fac333ac146056575b600080fd5b605460423660046085565b60009182526020829052604090912055565b005b6073606136600460a6565b60006020819052908152604090205481565b60405190815260200160405180910390f35b60008060408385031215609757600080fd5b50508035926020909101359150565b60006020828403121560b757600080fd5b503591905056fea26469706673582212204a6bf5c04a6e273d775914b20b0bab1bca28228be5562d496002981e13ff015264736f6c63430008130033"#; fn main() { - let pgm = Parser::with_pgm(STORAGE_SIMPLE).parse(); - let mut evm = Evm::new(pgm); let execution = evm.exec(); -{ - let leaf = execution.states.leaves(); - assert_eq!(2, leaf.len()); + { + let leaf = execution.states.leaves(); + assert_eq!(2, leaf.len()); - let final_tree = leaf.get(1).unwrap().clone(); + let final_tree = leaf.get(1).unwrap().clone(); - let mut mem_val = final_tree.val.mem_read(bvi(64)); // 0x40 - mem_val.simplify(); - assert_eq!(bvi(128), mem_val); // 0x80 -} + let mut mem_val = final_tree.val.mem_read(bvi(64)); // 0x40 + mem_val.simplify(); + assert_eq!(bvi(128), mem_val); // 0x80 + } let mut report = std::string::String::default(); // execution.states.into_iter().for_each(|(state, constraint)| { diff --git a/examples/swaps.rs b/examples/swaps.rs index 0a6b7aa..1d023db 100644 --- a/examples/swaps.rs +++ b/examples/swaps.rs @@ -43,8 +43,12 @@ fn main() { // Should have two paths: one reachable and one not. The reachable path should be the one in which there is a revert let reachability_report = Evm::exec_check(execution); assert_eq!(2, reachability_report.len()); - assert_eq!(SatResult::Sat, reachability_report.first().unwrap().1.unwrap()); - assert_eq!(SatResult::Unsat, reachability_report.get(1).unwrap().1.unwrap()); - - -} \ No newline at end of file + assert_eq!( + SatResult::Sat, + reachability_report.first().unwrap().1.unwrap() + ); + assert_eq!( + SatResult::Unsat, + reachability_report.get(1).unwrap().1.unwrap() + ); +} diff --git a/src/exec/mod.rs b/src/exec/mod.rs index 1c4f534..cf7959b 100644 --- a/src/exec/mod.rs +++ b/src/exec/mod.rs @@ -81,7 +81,10 @@ impl<'ctx> Execution<'ctx> { eprintln!("CHANGE REC IN EXEC: {:#?}", change_rec); let is_branch = change_rec.constraints.is_some(); if is_branch { - eprintln!("IS BRANCH HERE:\nChange record {:#?}\nCurr_state pc: {}", change_rec, curr_pc); + eprintln!( + "IS BRANCH HERE:\nChange record {:#?}\nCurr_state pc: {}", + change_rec, curr_pc + ); } curr_state.apply_change(change_rec.clone()); let mut report = StepRecord::new(false, change_rec.halt); @@ -169,7 +172,10 @@ impl<'ctx> Execution<'ctx> { let is_branch = change_rec.constraints.is_some(); curr_state.apply_change(change_rec.clone()); if is_branch { - eprintln!("IS BRANCH HERE:\nChange record {:#?}\nCurr_state pc: {}", change_rec, curr_pc); + eprintln!( + "IS BRANCH HERE:\nChange record {:#?}\nCurr_state pc: {}", + change_rec, curr_pc + ); } if change_rec.halt { eprintln!("Halt occurred here: {:#?}", change_rec); @@ -182,15 +188,13 @@ impl<'ctx> Execution<'ctx> { // an additional constraint // and left tree (by convention left path represents straight line execution) is the negation of such constraint let mut left_state = curr_state.clone(); - let right_tree = StateTree::from((left_state.clone(), change_rec.constraints.clone().unwrap())); + let right_tree = + StateTree::from((left_state.clone(), change_rec.constraints.clone().unwrap())); left_state.set_pc(curr_pc + 1); report.halted_left = left_state.halt; - let left_tree = StateTree::from(( - left_state, - change_rec.constraints.unwrap().not(), - )); - + let left_tree = StateTree::from((left_state, change_rec.constraints.unwrap().not())); + let left_tree_ref = self.states.insert_left_of(left_tree, node_id.id()); let right_tree_ref = self.states.insert_right_of(right_tree, node_id.id()); // curr_state_tree.left = Some(Box::new(left_tree)); diff --git a/src/instruction/mod.rs b/src/instruction/mod.rs index 97d83fe..4d49e06 100644 --- a/src/instruction/mod.rs +++ b/src/instruction/mod.rs @@ -184,10 +184,14 @@ fn exec_dup_nth(mach: &EvmState, n: usize) -> MachineRecord<32> { } fn exec_swap_nth(mach: &EvmState, n: usize) -> MachineRecord<32> { - eprintln!("EXEC SWAP NTH CALLED. N: {}", n); MachineRecord { - stack: Some(StackChange { pop_qty: 0, push_qty: 0, swap_depth: n, ops: vec![] }), + stack: Some(StackChange { + pop_qty: 0, + push_qty: 0, + swap_depth: n, + ops: vec![], + }), pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, @@ -201,24 +205,24 @@ impl Instruction { let inst_additional_size: usize = match self { Instruction::Push1(_) => 1, Instruction::Push2(_) => 2, - Instruction::Push3(_) =>3, - Instruction::Push4(_) =>4, - Instruction::Push5(_) =>5, - Instruction::Push6(_) =>6, - Instruction::Push7(_) =>7, - Instruction::Push8(_) =>8, - Instruction::Push9(_) =>9, - Instruction::Push10(_) => 10 , - Instruction::Push11(_) => 11 , + Instruction::Push3(_) => 3, + Instruction::Push4(_) => 4, + Instruction::Push5(_) => 5, + Instruction::Push6(_) => 6, + Instruction::Push7(_) => 7, + Instruction::Push8(_) => 8, + Instruction::Push9(_) => 9, + Instruction::Push10(_) => 10, + Instruction::Push11(_) => 11, Instruction::Push12(_) => 12, - Instruction::Push13(_) => 13 , + Instruction::Push13(_) => 13, Instruction::Push14(_) => 14, Instruction::Push15(_) => 15, Instruction::Push16(_) => 16, Instruction::Push17(_) => 17, Instruction::Push18(_) => 18, Instruction::Push19(_) => 19, - Instruction::Push20(_) => 20 , + Instruction::Push20(_) => 20, Instruction::Push21(_) => 21, Instruction::Push22(_) => 22, Instruction::Push23(_) => 23, @@ -231,7 +235,7 @@ impl Instruction { Instruction::Push30(_) => 30, Instruction::Push31(_) => 31, Instruction::Push32(_) => 32, - _ => 0 + _ => 0, }; inst_additional_size + 1 } @@ -967,7 +971,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { pop_qty: 1, push_qty: 0, swap_depth: 0, - ops: vec![StackOp::Pop] + ops: vec![StackOp::Pop], }; MachineRecord { stack: Some(stack_rec), @@ -977,7 +981,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { halt: false, storage: None, } - }, + } Instruction::JumpI => { let jump_dest = mach.stack().peek().unwrap(); let cond = mach.stack().peek_nth(1).unwrap(); @@ -1038,15 +1042,13 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { } } Instruction::Gas => todo!(), - Instruction::JumpDest => { - MachineRecord { - stack: None, - pc: (mach.pc(), mach.pc() + self.byte_size()), - mem: Default::default(), - halt: false, - storage: None, - constraints: None, - } + Instruction::JumpDest => MachineRecord { + stack: None, + pc: (mach.pc(), mach.pc() + self.byte_size()), + mem: Default::default(), + halt: false, + storage: None, + constraints: None, }, Instruction::Push1(bv) => { let new_bv = bv.as_ref().zero_ext(31).into(); diff --git a/src/machine.rs b/src/machine.rs index ff934be..634958e 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -117,50 +117,54 @@ impl<'ctx> Evm<'ctx> { } } - // A path from a node is the current node and the union of the paths of its children - pub fn paths(trace: Execution<'ctx>) -> Vec>)>>{ - + pub fn paths(trace: Execution<'ctx>) -> Vec>)>> { let mut paths_collected = vec![]; let mut curr_path = vec![]; let tree = Some(Box::new(trace.states)); StateTree::find_paths(&tree, &mut curr_path, &mut paths_collected); paths_collected - } - - pub fn exec_check(trace: Execution<'ctx>) -> Vec<(Vec<(NodeId, Instruction, Option>)>, Option, Option)> { + pub fn exec_check( + trace: Execution<'ctx>, + ) -> Vec<( + Vec<(NodeId, Instruction, Option>)>, + Option, + Option, + )> { let mut solver = z3_ext::Solver::new(ctx()); let paths = Self::paths(trace); - let reachable = paths.into_iter().map(|path| { - let mut result = (path.clone(), None, None); - solver.push(); - path.iter().for_each(|step| { - if let Some(constraint) = step.2.clone() { - solver.assert(&constraint); - } - }); - match solver.check() { - SatResult::Sat => { - let model = solver.get_model(); - result.1 = Some(SatResult::Sat); - - result.2 = model.map(|m| m.to_string()); - }, - SatResult::Unsat => { - result.1 = Some(SatResult::Unsat); - }, - SatResult::Unknown => { - result.1 = Some(SatResult::Unknown); + let reachable = paths + .into_iter() + .map(|path| { + let mut result = (path.clone(), None, None); + solver.push(); + path.iter().for_each(|step| { + if let Some(constraint) = step.2.clone() { + solver.assert(&constraint); + } + }); + match solver.check() { + SatResult::Sat => { + let model = solver.get_model(); + result.1 = Some(SatResult::Sat); + + result.2 = model.map(|m| m.to_string()); + } + SatResult::Unsat => { + result.1 = Some(SatResult::Unsat); + } + SatResult::Unknown => { + result.1 = Some(SatResult::Unknown); + } } - } - solver.pop(1); - result - }).collect::>(); + solver.pop(1); + result + }) + .collect::>(); reachable - } // pub fn exec_check(&mut self) -> Vec<(ExecBranch, Option>)> { @@ -217,26 +221,33 @@ impl<'ctx> Machine<32> for Evm<'ctx> { step.halted_left(), step.halted_right() ); - eprintln!("LEFT ID: {:#?} RIGHT ID: {:#?}", step.left_id(), step.right_id()); + eprintln!( + "LEFT ID: {:#?} RIGHT ID: {:#?}", + step.left_id(), + step.right_id() + ); // if !step.halted_right() { // let continue_from_right = step.right_id(); - if let Some(right_id) = step.right_id() { - ids.push(right_id.id()); - let nxt_right_step = exec.step_from_mut(right_id); - step_recs.push(nxt_right_step); - } + if let Some(right_id) = step.right_id() { + ids.push(right_id.id()); + let nxt_right_step = exec.step_from_mut(right_id); + step_recs.push(nxt_right_step); + } //} // if !step.halted_left() { // let continue_from_left = step.left_id(); - if let Some(left_id) = step.left_id() { - ids.push(left_id.id()); - let nxt_step = exec.step_from_mut(left_id); - step_recs.push(nxt_step); - } - // } + if let Some(left_id) = step.left_id() { + ids.push(left_id.id()); + let nxt_step = exec.step_from_mut(left_id); + step_recs.push(nxt_step); + } + // } if step.halted_left() && step.halted_right() { - eprintln!("Both have halted... Here are the step recs left: {:#?}", step_recs); + eprintln!( + "Both have halted... Here are the step recs left: {:#?}", + step_recs + ); } } else { break; @@ -247,7 +258,6 @@ impl<'ctx> Machine<32> for Evm<'ctx> { exec } - // fn exec(&mut self) -> Vec> { // let mut curr_state = self.states.val.clone(); // let curr_id = self.states.id.clone(); @@ -443,7 +453,7 @@ fn test_mem_store_mem_load() { // Instruction::MLoad, ]; - // let mut evm = Evm::new(pgm); + // let mut evm = Evm::new(pgm); // { // let sat_branches = evm.exec_check(); diff --git a/src/memory.rs b/src/memory.rs index f019425..f862aab 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -1,7 +1,7 @@ use crate::bvi; +use ruint::aliases::U1; use std::collections::hash_map::Entry; use std::collections::HashMap; -use ruint::aliases::U1; use z3_ext::ast::{Ast, BV}; use crate::record::{Index, MemChange, MemOp}; @@ -18,7 +18,6 @@ impl MachineComponent for Memory { type Record = MemChange; fn apply_change(&mut self, rec: Self::Record) { - let MemChange { ops_log } = rec; let mut highest_idx = self.highest_idx; ops_log.into_iter().for_each(|op| match op { @@ -27,7 +26,10 @@ impl MachineComponent for Memory { val.simplify(); let mut idx = idx; idx.simplify(); - eprintln!("MEM WRITE FOR MEM APPLY: idx: {:#?}, value: {:#?}", idx, val); + eprintln!( + "MEM WRITE FOR MEM APPLY: idx: {:#?}, value: {:#?}", + idx, val + ); let idx_cmp: usize = idx.clone().into(); if idx_cmp > highest_idx { highest_idx = idx_cmp; @@ -78,10 +80,10 @@ impl Memory { let idx: usize = idx.into(); let mut bytes = vec![]; let mut mem = self.inner.clone(); - // eprintln!(" MEM IN READ WORD: {:#?}", mem); + // eprintln!(" MEM IN READ WORD: {:#?}", mem); while i < 32 { let idx = idx + 31; - + let val = mem.get(idx - i).unwrap().as_ref().clone(); //eprintln!("MEM VAL IN READ WORD FOR IDX - i:\nmem loc {:#?}\nval: {:#?}", (idx - i), val); bytes.push(val); @@ -96,7 +98,6 @@ impl Memory { } else { new_bv_inner = new_bv_inner.concat(&b); } - }); BitVec { inner: BVType::Z3(new_bv_inner), @@ -124,14 +125,15 @@ impl Memory { } } - impl std::fmt::Display for Memory { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let mut mem_str = format!("Memory:\nSize: {} Highest Index: {}", self.size(), self.highest_idx); + let mut mem_str = format!( + "Memory:\nSize: {} Highest Index: {}", + self.size(), + self.highest_idx + ); self.inner.iter().enumerate().for_each(|(i, slot)| { - - let str_to_push = - if slot.as_ref().is_const() { + let str_to_push = if slot.as_ref().is_const() { let slot_str = format!("{} --> {}\n", i, slot.as_ref()); slot_str } else { @@ -140,8 +142,7 @@ impl std::fmt::Display for Memory { slot_str }; mem_str = format!("{}{}", mem_str, str_to_push); - }); write!(f, "{}", mem_str) } -} \ No newline at end of file +} diff --git a/src/parser.rs b/src/parser.rs index 4665880..d8eadcf 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -7,12 +7,15 @@ use ruint::Uint; #[derive(Default)] pub struct Parser<'a> { pgm: &'a str, - parsed: Program + parsed: Program, } impl<'a> Parser<'a> { pub fn with_pgm(pgm: &'a str) -> Self { - Self { pgm, ..Default::default() } + Self { + pgm, + ..Default::default() + } } pub fn parse(&self) -> Program { @@ -56,7 +59,7 @@ impl<'a> Parser<'a> { Program { map: pgm_map, pgm, - size: idx + 1 + size: idx + 1, } } } @@ -69,7 +72,7 @@ fn parse_push(bytes: &[u8]) -> (Instruction, u8, Vec) { //eprintln!("Bytes len is {}", bytes.len()); if bytes.len() - 1 < push_size as usize { let pad_len = push_size as usize - bytes.len() + 1; - // eprintln!("pad len: {}", pad_len); + // eprintln!("pad len: {}", pad_len); let mut new_bytes = bytes.to_vec(); for _ in (0..pad_len) { new_bytes.push(0); @@ -527,7 +530,7 @@ impl From for Instruction { pub struct Program { pub map: HashMap, pgm: Vec, - pub size: usize + pub size: usize, } impl Program { @@ -540,10 +543,6 @@ impl Program { } } - - - - #[test] fn is_push_works() { for b in (0x60_u8..0x7f) { @@ -587,7 +586,7 @@ fn can_parse_simple_pgm() { let pgm = Parser::with_pgm(COUNTER_SOL_CODE).parse(); let sixty_four: BitVec<32> = bvi(0x0040); - // eprintln!("SIXTY FOUR: {:#?}", sixty_four); + // eprintln!("SIXTY FOUR: {:#?}", sixty_four); let expected = vec![ Instruction::Push1(bvi(0x42)), Instruction::Push1(bvi(0)), @@ -648,9 +647,9 @@ fn can_parse_larger_pgm_with_storage() { let pgm_first_30 = (&pgm.pgm[..33]).to_vec(); assert_eq!(expected_first_30, pgm_first_30); let pgm_map = pgm.map.into_iter().collect::>(); - + eprintln!("PROGRAM MAP INDICES: {:#?}", pgm_map); let pgm_enumd = pgm_first_30.into_iter().enumerate().collect::>(); eprintln!("Enumerated pgm indices: {:#?}", pgm_enumd); - // assert_eq!(pgm_enumd, pgm_map); + // assert_eq!(pgm_enumd, pgm_map); } diff --git a/src/record.rs b/src/record.rs index c96b92f..0b2ad94 100644 --- a/src/record.rs +++ b/src/record.rs @@ -38,7 +38,7 @@ pub enum MemOp { pub enum StackOp { Push(BitVec), Pop, - Swap(usize) + Swap(usize), } #[derive(Default, Clone, Debug)] @@ -66,7 +66,7 @@ impl StackChange { ops.iter().for_each(|op| match op { StackOp::Push(_) => push_qty += 1, StackOp::Pop => pop_qty += 1, - _ => () + _ => (), }); Self { diff --git a/src/stack.rs b/src/stack.rs index c8dee35..a262a78 100644 --- a/src/stack.rs +++ b/src/stack.rs @@ -1,4 +1,4 @@ -use crate::{record::StackChange, bvi}; +use crate::{bvi, record::StackChange}; use std::fmt::{Debug, Formatter}; use super::smt::*; @@ -44,33 +44,38 @@ impl Stack { } // where n is stack modulo top element; - pub (crate) fn swap_nth(&mut self, swap_depth: usize) { + pub(crate) fn swap_nth(&mut self, swap_depth: usize) { eprintln!("SWAP EXECUTING AT DEPTH: {}", swap_depth); if swap_depth < self.size() { let mut new_stack = self.stack.clone(); let top_idx = self.size - 1; let swap_idx = self.size - swap_depth - 1; let top = self.peek().cloned().unwrap(); - let swapped = self.peek_nth(swap_depth).cloned().expect( - &format!("stack too deep to swap with depth {}. Stack size: {}", swap_depth, self.size()) - ); + let swapped = self.peek_nth(swap_depth).cloned().expect(&format!( + "stack too deep to swap with depth {}. Stack size: {}", + swap_depth, + self.size() + )); eprintln!("STACK BEFORE SWAP: {:#?}", new_stack); - new_stack = new_stack.into_iter().enumerate().map(move |(idx, val)| { - if idx == swap_idx { - return top.clone(); - } else if idx == top_idx { - return swapped.clone(); - } else { - val - } - }).collect::>(); + new_stack = new_stack + .into_iter() + .enumerate() + .map(move |(idx, val)| { + if idx == swap_idx { + return top.clone(); + } else if idx == top_idx { + return swapped.clone(); + } else { + val + } + }) + .collect::>(); eprintln!("STACK AFTER SWAP: {:#?}", new_stack); // new_stack.remove(swap_idx); // new_stack.insert(swap_idx, top); // new_stack.pop(); // new_stack.push(swapped); self.stack = new_stack; - } else { eprintln!("WILL NOT SWAP"); } @@ -93,7 +98,7 @@ impl MachineComponent for Stack { pop_qty, push_qty, ops, - swap_depth + swap_depth, } = rec; let mut new_stack = self.clone(); @@ -102,14 +107,15 @@ impl MachineComponent for Stack { crate::record::StackOp::Push(v) => new_stack.push(v.clone()), crate::record::StackOp::Pop => { new_stack.pop(); - }, - crate::record::StackOp::Swap(depth) => { - } + crate::record::StackOp::Swap(depth) => {} }); - + if swap_depth > 0 { - eprintln!("SWAP OCCURRING of DEPTH {}. STACK BEFORE: {:#?}", swap_depth, new_stack); + eprintln!( + "SWAP OCCURRING of DEPTH {}. STACK BEFORE: {:#?}", + swap_depth, new_stack + ); new_stack.swap_nth(swap_depth as usize); eprintln!("STACK AFTER {:#?}", new_stack); } @@ -119,7 +125,6 @@ impl MachineComponent for Stack { } } - #[test] fn test_swap() { let mut stack: Stack<1> = Stack::default(); @@ -130,5 +135,4 @@ fn test_swap() { stack.swap_nth(2); assert_eq!(stack.peek().cloned().unwrap(), bvi(2)); assert_eq!(stack.peek_nth(2).cloned().unwrap(), bvi(2)); - -} \ No newline at end of file +} diff --git a/src/state/context.rs b/src/state/context.rs index 2ea128a..82992c2 100644 --- a/src/state/context.rs +++ b/src/state/context.rs @@ -1,10 +1,5 @@ - - - pub struct ExecutionContext { - block: BlockContext + block: BlockContext, } -pub struct BlockContext { - -} \ No newline at end of file +pub struct BlockContext {} diff --git a/src/state/evm.rs b/src/state/evm.rs index 283ffba..a8b2567 100644 --- a/src/state/evm.rs +++ b/src/state/evm.rs @@ -12,7 +12,6 @@ use crate::{ }; use z3_ext::ast::Bool; - #[derive(Clone, Default)] pub struct EvmState { pub memory: Memory, @@ -24,7 +23,6 @@ pub struct EvmState { pub halt: bool, } - impl MachineComponent for EvmState { type Record = MachineRecord<32>; @@ -62,14 +60,17 @@ impl<'ctx> EvmState { pub fn set_pc(&mut self, new_pc: usize) { self.pc = new_pc; if self.pc >= self.pgm.get_size() { - eprintln!("SET PC--- PC: {} -- PGM SIZE: {}", self.pc, self.pgm.get_size()); + eprintln!( + "SET PC--- PC: {} -- PGM SIZE: {}", + self.pc, + self.pgm.get_size() + ); self.halt = true; } } pub fn inc_pc(&mut self) { let curr_inst = self.curr_instruction(); - self.set_pc(self.pc + curr_inst.byte_size()); } @@ -77,11 +78,12 @@ impl<'ctx> EvmState { self.pc < self.pgm.get_size() && !self.halt } pub fn curr_instruction(&self) -> Instruction { - self.pgm.get(self.pc).expect(&format!("Expected instruction at pc: {}", self.pc)) + self.pgm + .get(self.pc) + .expect(&format!("Expected instruction at pc: {}", self.pc)) } pub fn curr_inst_debug(&self) -> Instruction { if !self.can_continue() { - eprintln!("Curr instruction debug requested but cannot continue"); } self.pgm.get(self.pc).unwrap() @@ -91,20 +93,25 @@ impl<'ctx> EvmState { impl std::fmt::Display for EvmState { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { //write!(f, "Pc: {}\nHalted: {}\nStack: {:?}\n{}", self.pc(), self.halt, self.stack(), self.mem()) - write!(f, "Pc: {}, Stack: {:#?} halt: {:#?}", self.pc(), self.stack(), self.halt) + write!( + f, + "Pc: {}, Stack: {:#?} halt: {:#?}", + self.pc(), + self.stack(), + self.halt + ) } } impl std::fmt::Debug for EvmState { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("EvmState").field("stack", &self.stack) - .field("pc", &self.pc) - .field("address", &self.address) - .field("halt", &self.halt) - .field("instruction", &self.curr_inst_debug()) - .field("pgm size", &self.pgm.size) - .finish() + f.debug_struct("EvmState") + .field("stack", &self.stack) + .field("pc", &self.pc) + .field("address", &self.address) + .field("halt", &self.halt) + .field("instruction", &self.curr_inst_debug()) + .field("pgm size", &self.pgm.size) + .finish() } } - - diff --git a/src/state/mod.rs b/src/state/mod.rs index 46ba139..16c87ca 100644 --- a/src/state/mod.rs +++ b/src/state/mod.rs @@ -1,4 +1,4 @@ +pub mod context; pub mod env; pub mod evm; pub mod tree; -pub mod context; \ No newline at end of file diff --git a/src/state/tree.rs b/src/state/tree.rs index a6c8029..34e828a 100644 --- a/src/state/tree.rs +++ b/src/state/tree.rs @@ -1,5 +1,5 @@ use super::evm::*; -use crate::{ctx, z3_ext::ast::Ast, z3_ext::ast::Bool, instruction::Instruction}; +use crate::{ctx, instruction::Instruction, z3_ext::ast::Ast, z3_ext::ast::Bool}; use std::borrow::BorrowMut; use uuid::Uuid; @@ -50,8 +50,6 @@ pub struct StateTree<'ctx> { pub(crate) right: Option>>, } - - impl<'ctx> From<(EvmState, Bool<'ctx>)> for StateTree<'ctx> { fn from(t: (EvmState, Bool<'ctx>)) -> Self { Self { @@ -119,25 +117,30 @@ impl<'ctx> StateTree<'ctx> { items } - pub fn find_paths(node: &Option>>, current_path: &mut Vec<(NodeId, Instruction, Option>)>, all_paths: &mut Vec>)>> ) { + pub fn find_paths( + node: &Option>>, + current_path: &mut Vec<(NodeId, Instruction, Option>)>, + all_paths: &mut Vec>)>>, + ) { if let Some(ref node) = *node { - current_path.push((node.id.clone(), node.val.curr_instruction(), node.path_condition.clone())); - + current_path.push(( + node.id.clone(), + node.val.curr_instruction(), + node.path_condition.clone(), + )); + if node.left.is_none() && node.right.is_none() { all_paths.push(current_path.clone()); } else { Self::find_paths(&node.left, current_path, all_paths); Self::find_paths(&node.right, current_path, all_paths); } - + current_path.pop(); } } pub fn inorder_stateless(&self) -> Vec<(NodeId, Option>)> { - let mut items = vec![( - self.id.clone(), - self.path_condition.clone(), - )]; + let mut items = vec![(self.id.clone(), self.path_condition.clone())]; if let Some(left) = &self.left { let left_tree_inorder = left.inorder_stateless(); diff --git a/src/traits.rs b/src/traits.rs index f886b51..8f93468 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -33,7 +33,7 @@ pub trait Machine { // All possible final states fn exec(&mut self) -> Execution; - fn pgm(&self) ->Program; + fn pgm(&self) -> Program; fn state(&self) -> Self::State; fn state_ref(&self) -> &Self::State; fn state_ref_mut(&mut self) -> &mut Self::State; diff --git a/tests/lib.rs b/tests/lib.rs index 53d902e..0dbfa0c 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -16,7 +16,7 @@ fn can_run_simple_parsed_pgm() { { let sat_branches = evm.exec(); - + let leaf = sat_branches.states.leaves(); assert_eq!(1, leaf.len()); let final_tree = leaf.first().unwrap().clone(); @@ -31,7 +31,6 @@ fn can_run_simple_storage_pgm() { let pgm = Parser::with_pgm(STORAGE_SIMPLE).parse(); let mut evm = Evm::new(pgm); - let execution = evm.exec(); let leaf = execution.states.leaves(); assert_eq!(2, leaf.len()); @@ -41,7 +40,6 @@ fn can_run_simple_storage_pgm() { let mut mem_val = final_tree.val.mem_read(bvi(64)); mem_val.simplify(); assert_eq!(bvi(128), mem_val); - } #[test] @@ -49,11 +47,10 @@ fn can_run_counter_with_storage_mapping_pgm() { let pgm = Parser::with_pgm(COUNTER_WITH_STORAGE_MAPPING).parse(); let mut evm = Evm::new(pgm); - let execution = evm.exec(); let leaf = execution.states.leaves(); assert_eq!(2, leaf.len()); - // eprintln!("LEAVES: {:#?}", leaf); + // eprintln!("LEAVES: {:#?}", leaf); } /* @@ -99,9 +96,14 @@ fn test_swap2_jumpi_revert() { // Should have two paths: one reachable and one not. The reachable path should be the one in which there is a revert let reachability_report = Evm::exec_check(execution); assert_eq!(2, reachability_report.len()); - assert_eq!(SatResult::Sat, reachability_report.first().unwrap().1.unwrap()); - assert_eq!(SatResult::Unsat, reachability_report.get(1).unwrap().1.unwrap()); - + assert_eq!( + SatResult::Sat, + reachability_report.first().unwrap().1.unwrap() + ); + assert_eq!( + SatResult::Unsat, + reachability_report.get(1).unwrap().1.unwrap() + ); } #[test] @@ -112,6 +114,6 @@ fn test_swap3_jumpi_return() { //eprintln!("Execution tree: {:#?}", execution.states); let final_states = execution.states.leaves(); eprintln!("LEAVES: {:#?}", final_states); - assert_eq!(2, final_states.len()); + assert_eq!(2, final_states.len()); assert!(false); -} \ No newline at end of file +} From 84295e47c421e67578b54ed44690112b85878b58 Mon Sep 17 00:00:00 2001 From: tannr Date: Thu, 3 Aug 2023 17:53:03 -0400 Subject: [PATCH 24/28] add simple maybe_revert test --- tests/lib.rs | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/tests/lib.rs b/tests/lib.rs index 0dbfa0c..3f4e0c7 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -83,9 +83,22 @@ JUMPDEST PUSH1 0x10 RETURN -*/ +MAYBE REVERT: +PUSH1 0x42 +PUSH1 0x00 +PUSH2 0x5000 +CALLDATASIZE +PUSH1 0x0d +JUMPI +REVERT +JUMPDEST +PUSH1 0x00 +RETURN + +*/ const SWAP2_JUMPI_REVERT: &str = r#"604260006150003691600d57fd5b6000f3"#; +const SWAP2_JUMPI_MAYBE_REVERT: &str = r#"6042600061500036600d57fd5b6000f3"#; const SWAP3_JUMPI_RETURN_16: &str = r#"60426000615000604091600e57fd5b6000f3"#; #[test] fn test_swap2_jumpi_revert() { @@ -106,6 +119,26 @@ fn test_swap2_jumpi_revert() { ); } +#[test] +fn test_swap2_jumpi_maybe_revert() { + let pgm = Parser::with_pgm(SWAP2_JUMPI_MAYBE_REVERT).parse(); + let mut evm = Evm::new(pgm); + let execution = evm.exec(); + eprintln!("Execution tree: {:#?}", execution.states.clone()); + // Should have two paths: both reachable. The first reachable path is the one in which calldata is zero and there is a revert. + // The second reachable path is the one in which calldata is not zero and there is not a revert. + let reachability_report = Evm::exec_check(execution); + assert_eq!(2, reachability_report.len()); + assert_eq!( + SatResult::Sat, + reachability_report.first().unwrap().1.unwrap() + ); + assert_eq!( + SatResult::Sat, + reachability_report.get(1).unwrap().1.unwrap() + ); +} + #[test] fn test_swap3_jumpi_return() { let pgm = Parser::with_pgm(SWAP3_JUMPI_RETURN_16).parse(); From 1b897bc9d41511d289821bd6002828bcaebef26c Mon Sep 17 00:00:00 2001 From: tannr Date: Thu, 3 Aug 2023 17:55:08 -0400 Subject: [PATCH 25/28] remove unused test --- tests/lib.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/tests/lib.rs b/tests/lib.rs index 3f4e0c7..9f2c69e 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -139,14 +139,3 @@ fn test_swap2_jumpi_maybe_revert() { ); } -#[test] -fn test_swap3_jumpi_return() { - let pgm = Parser::with_pgm(SWAP3_JUMPI_RETURN_16).parse(); - let mut evm = Evm::new(pgm); - let execution = evm.exec(); - //eprintln!("Execution tree: {:#?}", execution.states); - let final_states = execution.states.leaves(); - eprintln!("LEAVES: {:#?}", final_states); - assert_eq!(2, final_states.len()); - assert!(false); -} From a99449a28f3477b7881a530570401e809f28a18a Mon Sep 17 00:00:00 2001 From: tannr Date: Fri, 4 Aug 2023 19:46:23 -0400 Subject: [PATCH 26/28] Add sha3; fix mload when bitvecs are compound expressions in some cases --- README.md | 2 +- example-trace.md | 1025 ++++++++++++++++++++++++++++++++++++ examples/simple_storage.rs | 31 +- examples/swaps.rs | 25 +- src/conversion/mod.rs | 25 + src/instruction/mod.rs | 61 ++- src/memory.rs | 9 + src/stack.rs | 2 +- src/state/env.rs | 15 +- 9 files changed, 1168 insertions(+), 27 deletions(-) create mode 100644 example-trace.md diff --git a/README.md b/README.md index 0c8feab..d808bc7 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ Ser also differs from most symbolic EVM tools in that state transitions in the E The tradeoff is that this approach - as it is currently implemented - uses more memory than if the execution of each instruction and its effect on the machine state were coupled together. -See this [example output](/example-trace.txt) of the type of trace tree generated by Ser. +See this [example output](/example-trace.md) of the type of trace tree generated by Ser. ### Acknowledgements Special thanks to [Arnur Sabet](https://github.com/arnursabet) for his contributions to an earlier prototype of this software. \ No newline at end of file diff --git a/example-trace.md b/example-trace.md new file mode 100644 index 0000000..f78060b --- /dev/null +++ b/example-trace.md @@ -0,0 +1,1025 @@ + + +``` +------- Reachable State --------- +State EvmState { + memory: Memory { + inner: [], + }, + stack: Stack { + stack: [ + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000002, + ), + typ: Z3, + }, + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000064, + ), + typ: Z3, + }, + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000032, + ), + typ: Z3, + }, + ], + }, + pc: 8, + pgm: [ + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000002, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000001, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + a, + ), + typ: Z3, + }, + ), + Add, + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000007, + ), + typ: Z3, + }, + ), + JumpI, + Push( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000064, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000032, + ), + typ: Z3, + }, + ), + ], +} + + +MODEL:Some( + a -> #xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + , +) + + + +------- Full Trace Tree ------- +StateTree { + id: NodeId { + id: 763425973fbb4e2fba219c2b0b9e051a, + parent: None, + }, + val: EvmState { + memory: Memory { + inner: [], + }, + stack: Stack { + stack: [], + }, + pc: 0, + pgm: [ + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000002, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000001, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + a, + ), + typ: Z3, + }, + ), + Add, + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000007, + ), + typ: Z3, + }, + ), + JumpI, + Push( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000064, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000032, + ), + typ: Z3, + }, + ), + ], + }, + path_condition: None, + left: Some( + StateTree { + id: NodeId { + id: 93e5d25a069f4945afbc7202ca712223, + parent: None, + }, + val: EvmState { + memory: Memory { + inner: [], + }, + stack: Stack { + stack: [ + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000002, + ), + typ: Z3, + }, + ], + }, + pc: 1, + pgm: [ + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000002, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000001, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + a, + ), + typ: Z3, + }, + ), + Add, + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000007, + ), + typ: Z3, + }, + ), + JumpI, + Push( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000064, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000032, + ), + typ: Z3, + }, + ), + ], + }, + path_condition: None, + left: Some( + StateTree { + id: NodeId { + id: c31b9dd6c241473ebaecb540353f4925, + parent: None, + }, + val: EvmState { + memory: Memory { + inner: [], + }, + stack: Stack { + stack: [ + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000002, + ), + typ: Z3, + }, + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000001, + ), + typ: Z3, + }, + ], + }, + pc: 2, + pgm: [ + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000002, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000001, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + a, + ), + typ: Z3, + }, + ), + Add, + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000007, + ), + typ: Z3, + }, + ), + JumpI, + Push( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000064, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000032, + ), + typ: Z3, + }, + ), + ], + }, + path_condition: None, + left: Some( + StateTree { + id: NodeId { + id: 9b647bf4ac7b46a69242e59984017fef, + parent: None, + }, + val: EvmState { + memory: Memory { + inner: [], + }, + stack: Stack { + stack: [ + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000002, + ), + typ: Z3, + }, + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000001, + ), + typ: Z3, + }, + BitVec { + inner: Z3( + a, + ), + typ: Z3, + }, + ], + }, + pc: 3, + pgm: [ + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000002, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000001, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + a, + ), + typ: Z3, + }, + ), + Add, + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000007, + ), + typ: Z3, + }, + ), + JumpI, + Push( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000064, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000032, + ), + typ: Z3, + }, + ), + ], + }, + path_condition: None, + left: Some( + StateTree { + id: NodeId { + id: 66c4de3ffa364582a08255e69c277215, + parent: None, + }, + val: EvmState { + memory: Memory { + inner: [], + }, + stack: Stack { + stack: [ + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000002, + ), + typ: Z3, + }, + BitVec { + inner: Z3( + (bvadd a #x0000000000000000000000000000000000000000000000000000000000000001), + ), + typ: Z3, + }, + ], + }, + pc: 4, + pgm: [ + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000002, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000001, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + a, + ), + typ: Z3, + }, + ), + Add, + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000007, + ), + typ: Z3, + }, + ), + JumpI, + Push( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000064, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000032, + ), + typ: Z3, + }, + ), + ], + }, + path_condition: None, + left: Some( + StateTree { + id: NodeId { + id: 850f56c7fb474be8964df31b0768e4e0, + parent: None, + }, + val: EvmState { + memory: Memory { + inner: [], + }, + stack: Stack { + stack: [ + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000002, + ), + typ: Z3, + }, + BitVec { + inner: Z3( + (bvadd a #x0000000000000000000000000000000000000000000000000000000000000001), + ), + typ: Z3, + }, + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000007, + ), + typ: Z3, + }, + ], + }, + pc: 5, + pgm: [ + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000002, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000001, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + a, + ), + typ: Z3, + }, + ), + Add, + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000007, + ), + typ: Z3, + }, + ), + JumpI, + Push( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000064, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000032, + ), + typ: Z3, + }, + ), + ], + }, + path_condition: None, + left: Some( + StateTree { + id: NodeId { + id: 194b94b65ac34df1bb5dc6d6a2295ec1, + parent: None, + }, + val: EvmState { + memory: Memory { + inner: [], + }, + stack: Stack { + stack: [ + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000002, + ), + typ: Z3, + }, + ], + }, + pc: 6, + pgm: [ + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000002, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000001, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + a, + ), + typ: Z3, + }, + ), + Add, + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000007, + ), + typ: Z3, + }, + ), + JumpI, + Push( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000064, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000032, + ), + typ: Z3, + }, + ), + ], + }, + path_condition: Some( + (and (not (not (= (bvadd a + #x0000000000000000000000000000000000000000000000000000000000000001) + #x0000000000000000000000000000000000000000000000000000000000000000)))), + ), + left: Some( + StateTree { + id: NodeId { + id: 5ffdf966e9d1476689c4e71cab83e9e6, + parent: None, + }, + val: EvmState { + memory: Memory { + inner: [], + }, + stack: Stack { + stack: [ + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000002, + ), + typ: Z3, + }, + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000064, + ), + typ: Z3, + }, + ], + }, + pc: 7, + pgm: [ + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000002, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000001, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + a, + ), + typ: Z3, + }, + ), + Add, + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000007, + ), + typ: Z3, + }, + ), + JumpI, + Push( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000064, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000032, + ), + typ: Z3, + }, + ), + ], + }, + path_condition: Some( + (and (not (not (= (bvadd a + #x0000000000000000000000000000000000000000000000000000000000000001) + #x0000000000000000000000000000000000000000000000000000000000000000)))), + ), + left: Some( + StateTree { + id: NodeId { + id: cb50266a2e174d318063fe6585098087, + parent: None, + }, + val: EvmState { + memory: Memory { + inner: [], + }, + stack: Stack { + stack: [ + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000002, + ), + typ: Z3, + }, + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000064, + ), + typ: Z3, + }, + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000032, + ), + typ: Z3, + }, + ], + }, + pc: 8, + pgm: [ + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000002, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000001, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + a, + ), + typ: Z3, + }, + ), + Add, + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000007, + ), + typ: Z3, + }, + ), + JumpI, + Push( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000064, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000032, + ), + typ: Z3, + }, + ), + ], + }, + path_condition: Some( + (and (not (not (= (bvadd a + #x0000000000000000000000000000000000000000000000000000000000000001) + #x0000000000000000000000000000000000000000000000000000000000000000)))), + ), + left: None, + right: None, + }, + ), + right: None, + }, + ), + right: None, + }, + ), + right: Some( + StateTree { + id: NodeId { + id: 349b98b471ad4c908ea348e334a3132b, + parent: None, + }, + val: EvmState { + memory: Memory { + inner: [], + }, + stack: Stack { + stack: [ + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000002, + ), + typ: Z3, + }, + ], + }, + pc: 7, + pgm: [ + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000002, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000001, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + a, + ), + typ: Z3, + }, + ), + Add, + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000007, + ), + typ: Z3, + }, + ), + JumpI, + Push( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000064, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000032, + ), + typ: Z3, + }, + ), + ], + }, + path_condition: Some( + (and (not (= (bvadd a + #x0000000000000000000000000000000000000000000000000000000000000001) + #x0000000000000000000000000000000000000000000000000000000000000000))), + ), + left: Some( + StateTree { + id: NodeId { + id: 84c6c28a405c4b4b9cba4716a2e6014c, + parent: None, + }, + val: EvmState { + memory: Memory { + inner: [], + }, + stack: Stack { + stack: [ + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000002, + ), + typ: Z3, + }, + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000032, + ), + typ: Z3, + }, + ], + }, + pc: 8, + pgm: [ + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000002, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000001, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + a, + ), + typ: Z3, + }, + ), + Add, + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000007, + ), + typ: Z3, + }, + ), + JumpI, + Push( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000064, + ), + typ: Z3, + }, + ), + Push32( + BitVec { + inner: Z3( + #x0000000000000000000000000000000000000000000000000000000000000032, + ), + typ: Z3, + }, + ), + ], + }, + path_condition: Some( + (and (not (= (bvadd a + #x0000000000000000000000000000000000000000000000000000000000000001) + #x0000000000000000000000000000000000000000000000000000000000000000))), + ), + left: None, + right: None, + }, + ), + right: None, + }, + ), + }, + ), + right: None, + }, + ), + right: None, + }, + ), + right: None, + }, + ), + right: None, + }, + ), + right: None, +} +``` diff --git a/examples/simple_storage.rs b/examples/simple_storage.rs index 79fd163..4655871 100644 --- a/examples/simple_storage.rs +++ b/examples/simple_storage.rs @@ -1,6 +1,6 @@ -#![allow(unused_imports)] +#![allow(unused_imports, unused)] use ser::{ - bvc, bvi, conversion::*, machine::*, memory::*, parser::*, stack::*, storage::*, traits::*, + bvc, bvi, conversion::*, machine::*, memory::*, parser::*, stack::*, storage::*, traits::*, instruction::Instruction, }; use z3::ast::*; @@ -14,19 +14,20 @@ fn main() { let execution = evm.exec(); { let leaf = execution.states.leaves(); - assert_eq!(2, leaf.len()); - - let final_tree = leaf.get(1).unwrap().clone(); - - let mut mem_val = final_tree.val.mem_read(bvi(64)); // 0x40 - mem_val.simplify(); - assert_eq!(bvi(128), mem_val); // 0x80 + // as seen here https://bytegraph.xyz/bytecode/e5987a6f24f8af926faddae88de7980f/graph + assert_eq!(7, leaf.len()); } + + - let mut report = std::string::String::default(); - // execution.states.into_iter().for_each(|(state, constraint)| { - // report = format!("{}\n{} -- Constraints: {:#?}", report, state, constraint); - // }); - //eprintln!("Execution report: {}", report); - eprintln!("Tree: {:#?}", execution.states); + + let reachability_report = Evm::exec_check(execution); + println!("Report: {:#?}", reachability_report); + let traces = reachability_report.iter() + .map(|trace| trace.0.iter().map(|t| &t.1).collect::>()) + .collect::>(); + println!("traces: {:#?}", traces); + let reverted_traces = traces.into_iter().filter(|t| *t.last().unwrap().clone() == Instruction::Revert).collect::>(); + println!("TRACES WITH REVERTS {:#?}", reverted_traces); + } diff --git a/examples/swaps.rs b/examples/swaps.rs index 1d023db..26d6d85 100644 --- a/examples/swaps.rs +++ b/examples/swaps.rs @@ -1,4 +1,4 @@ -#![allow(unused_imports)] +#![allow(unused_imports, unused)] use ser::{ bvc, bvi, conversion::*, machine::*, memory::*, parser::*, stack::*, storage::*, traits::*, }; @@ -33,22 +33,39 @@ JUMPDEST PUSH1 0x10 RETURN + +MAYBE REVERT: +PUSH1 0x42 +PUSH1 0x00 +PUSH2 0x5000 +CALLDATASIZE +PUSH1 0x0d +JUMPI +REVERT +JUMPDEST +PUSH1 0x00 +RETURN + */ const SWAP2_JUMPI_REVERT: &str = r#"604260006150003691600d57fd5b6000f3"#; +const SWAP2_JUMPI_MAYBE_REVERT: &str = r#"6042600061500036600d57fd5b6000f3"#; const SWAP3_JUMPI_RETURN_16: &str = r#"60426000615000604091600e57fd5b6000f3"#; fn main() { - let pgm = Parser::with_pgm(SWAP2_JUMPI_REVERT).parse(); + let pgm = Parser::with_pgm(SWAP2_JUMPI_MAYBE_REVERT).parse(); let mut evm = Evm::new(pgm); let execution = evm.exec(); - // Should have two paths: one reachable and one not. The reachable path should be the one in which there is a revert + //eprintln!("Execution tree: {:#?}", execution.states.clone()); + // Should have two paths: both reachable. The first reachable path is the one in which calldata is zero and there is a revert. + // The second reachable path is the one in which calldata is not zero and there is not a revert. let reachability_report = Evm::exec_check(execution); assert_eq!(2, reachability_report.len()); + eprintln!("REPORT: {:#?}", reachability_report); assert_eq!( SatResult::Sat, reachability_report.first().unwrap().1.unwrap() ); assert_eq!( - SatResult::Unsat, + SatResult::Sat, reachability_report.get(1).unwrap().1.unwrap() ); } diff --git a/src/conversion/mod.rs b/src/conversion/mod.rs index fa563db..d677a7f 100644 --- a/src/conversion/mod.rs +++ b/src/conversion/mod.rs @@ -81,6 +81,7 @@ impl From<[u8; SZ]> for BitVec { for i in value.iter() { let new_bv: BV<'static> = bvi::<1>(*i).into(); bv = bv.concat(&new_bv).simplify(); + } // eprintln!("VALUE CONVERTING FROM: {:#x?}", value); // eprintln!("BV IN SLICE CONVERT: {:#?} SIZE: {}", bv, bv.get_size()); @@ -90,6 +91,30 @@ impl From<[u8; SZ]> for BitVec { } } +pub fn bitvec_array_to_bv<'ctx>(value: Vec>) -> BV<'ctx> { + let ctx: &'static Context = ctx(); + let mut bv: BV<'static> = BV::from_u64(ctx, 0, 8); + for i in value.iter() { + bv = bv.concat(i.as_ref()).simplify(); + } + bv.extract((bv.get_size() - 8 - 1) as u32, 0) + .simplify() + +} +impl TryFrom>> for BitVec { + type Error = String; + + fn try_from(value: Vec>) -> Result { + let ctx: &'static Context = ctx(); + let mut bv: BV<'static> = BV::from_u64(ctx, 0, 8); + for i in value.iter() { + bv = bv.concat(i.as_ref()).simplify(); + } + Ok(bv.extract((bv.get_size() - 8 - 1) as u32, 0) + .simplify() + .into()) + } +} impl AsRef> for BitVec { fn as_ref(&self) -> &BV<'static> { match &self.inner { diff --git a/src/instruction/mod.rs b/src/instruction/mod.rs index 4d49e06..8be9a3d 100644 --- a/src/instruction/mod.rs +++ b/src/instruction/mod.rs @@ -4,6 +4,7 @@ use std::ops::{BitAnd, BitOr, BitXor}; use ruint::aliases::U256; use z3_ext::ast::{Ast, Bool, BV}; +use crate::conversion::bitvec_array_to_bv; use crate::record::{push, MemChange, MemOp, StorageChange, StorageOp}; use crate::state::env::*; use crate::state::evm::EvmState; @@ -184,7 +185,7 @@ fn exec_dup_nth(mach: &EvmState, n: usize) -> MachineRecord<32> { } fn exec_swap_nth(mach: &EvmState, n: usize) -> MachineRecord<32> { - eprintln!("EXEC SWAP NTH CALLED. N: {}", n); + MachineRecord { stack: Some(StackChange { pop_qty: 0, @@ -243,7 +244,17 @@ impl Instruction { impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { fn exec(&self, mach: &EvmState) -> MachineRecord<32> { match self { - Instruction::Stop => todo!(), + Instruction::Stop => { + MachineRecord { + halt: true, + stack: None, + mem: None, + constraints: None, + storage: None, + pc: (mach.pc(), mach.pc()) + } + } + , Instruction::Add => { let stack = mach.stack(); let [stack_top, stack_top2] = stack.peek_top().unwrap(); @@ -608,7 +619,44 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { storage: None, } } - Instruction::Sha3 => todo!(), + Instruction::Sha3 => { + let stack = mach.stack(); + let [ offset, size] = stack.peek_top().unwrap(); + let mut offsett = offset.clone(); + let mut sizee = size.clone(); + offsett.simplify(); + sizee.simplify(); + + let mem = mach.mem().read_with_offset(offsett.clone(), sizee.clone()); + let sz = usize::from(sizee.clone()); + + let mut bv: BV<'static> = bitvec_array_to_bv(mem); + + + + + let hashed = sha3(bv.get_size()).apply(&[&bv]); + + let hashed: BitVec<32> = hashed.as_bv().unwrap().into(); + let mem_change = MemChange { + ops_log: vec![MemOp::Read {idx: offsett.clone()}] + }; + let stack_change = StackChange::with_ops(vec![ + StackOp::Pop, + StackOp::Pop, + StackOp::Push(hashed) + ]); + + MachineRecord { + stack: Some(stack_change), + mem: Some(mem_change), + pc: (mach.pc(), mach.pc() + self.byte_size()), + constraints: None, + halt: false, + storage: None, + } + + }, Instruction::Address => todo!(), Instruction::Balance => { let stack = mach.stack(); @@ -842,6 +890,9 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { Instruction::MLoad => { let stack = mach.stack(); let dest = stack.peek().unwrap(); + let mut dest = dest.clone(); + dest.simplify(); + let mut val_mem = mach.memory.read_word(dest.clone()); val_mem.simplify(); @@ -965,7 +1016,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { } Instruction::Jump => { let jump_dest = mach.stack().peek().unwrap(); - eprintln!("JUMP DEST IN UNCONDITIONAL JUMP: {:#?}", jump_dest); + let jump_dest_concrete = jump_dest.as_ref().simplify().as_u64().unwrap() as usize; let stack_rec = StackChange { pop_qty: 1, @@ -997,7 +1048,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { push_qty: 0, ops: vec![StackOp::Pop, StackOp::Pop], }; - eprintln!("JUMPI REACHED"); + MachineRecord { stack: Some(stack_rec), diff --git a/src/memory.rs b/src/memory.rs index f862aab..884306b 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -75,6 +75,15 @@ impl Memory { let val = self.inner.get(idx).unwrap().clone(); val } + + pub fn read_with_offset(&self, offset: Index, size: impl Into + Clone) -> Vec> { + let idx: usize = offset.into(); + + eprintln!("IDX: {idx:} and size: {:#?}", size.clone().into()); + let val = self.inner[idx .. (idx + size.clone().into())].to_vec(); + eprintln!("VAL IN MEM READ EITH OFFSET: {:#?}", val); + val + } pub fn read_word(&self, idx: Index) -> BitVec<32> { let mut i = 0; let idx: usize = idx.into(); diff --git a/src/stack.rs b/src/stack.rs index a262a78..6e385d3 100644 --- a/src/stack.rs +++ b/src/stack.rs @@ -134,5 +134,5 @@ fn test_swap() { stack.push(bvi(4)); stack.swap_nth(2); assert_eq!(stack.peek().cloned().unwrap(), bvi(2)); - assert_eq!(stack.peek_nth(2).cloned().unwrap(), bvi(2)); + assert_eq!(stack.peek_nth(2).cloned().unwrap(), bvi(4)); } diff --git a/src/state/env.rs b/src/state/env.rs index 566911c..1842c21 100644 --- a/src/state/env.rs +++ b/src/state/env.rs @@ -1,4 +1,4 @@ -use z3_ext::ast::{Ast, AstKind}; +use z3_ext::ast::{Ast, AstKind, Array, BV}; use z3_ext::FuncDecl; use z3_ext::Sort; @@ -29,6 +29,19 @@ pub fn call_data_load<'ctx>() -> FuncDecl<'ctx> { ) } +pub fn sha3<'ctx>(size: u32) -> FuncDecl<'ctx> { + let id = uuid::Uuid::new_v4(); + let func = FuncDecl::new( + ctx(), + format!("sha3_{}", id).as_str(), + &[&Sort::bitvector(ctx(), size)], + &Sort::bitvector(ctx(), 256) + ); + + eprintln!("SHA3 FUNC: {:#?}", func); + func +} + pub fn call_value<'ctx>() -> FuncDecl<'ctx> { let ctx = ctx(); FuncDecl::new(ctx, "callvalue", &[], &Sort::bitvector(ctx, 256)) From 3fee38b6186c880c07572932e4a55d3041d7a694 Mon Sep 17 00:00:00 2001 From: tannr Date: Fri, 4 Aug 2023 19:48:38 -0400 Subject: [PATCH 27/28] fmt --- .gitignore | 3 +- example-trace.txt | 1024 ------------------------------------ examples/simple_storage.rs | 15 +- examples/swaps.rs | 2 +- src/conversion/mod.rs | 12 +- src/instruction/mod.rs | 56 +- src/memory.rs | 10 +- src/state/env.rs | 4 +- tests/lib.rs | 3 +- tests/test_storage.rs | 1 - 10 files changed, 49 insertions(+), 1081 deletions(-) delete mode 100644 example-trace.txt delete mode 100644 tests/test_storage.rs diff --git a/.gitignore b/.gitignore index 5d0be3f..f2ad452 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ *.txt.log* .idea/* *.hex -*.evm \ No newline at end of file +*.evm +*.txt \ No newline at end of file diff --git a/example-trace.txt b/example-trace.txt deleted file mode 100644 index f270726..0000000 --- a/example-trace.txt +++ /dev/null @@ -1,1024 +0,0 @@ ----- machine::machine_returns_one_exec_for_non_branching_pgm stdout ---- - - -------- Reachable State --------- -State EvmState { - memory: Memory { - inner: [], - }, - stack: Stack { - stack: [ - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000002, - ), - typ: Z3, - }, - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000064, - ), - typ: Z3, - }, - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000032, - ), - typ: Z3, - }, - ], - }, - pc: 8, - pgm: [ - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000002, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000001, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - a, - ), - typ: Z3, - }, - ), - Add, - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000007, - ), - typ: Z3, - }, - ), - JumpI, - Push( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000064, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000032, - ), - typ: Z3, - }, - ), - ], -} - - -MODEL:Some( - a -> #xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - , -) - - - -------- Full Trace Tree ------- -StateTree { - id: NodeId { - id: 763425973fbb4e2fba219c2b0b9e051a, - parent: None, - }, - val: EvmState { - memory: Memory { - inner: [], - }, - stack: Stack { - stack: [], - }, - pc: 0, - pgm: [ - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000002, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000001, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - a, - ), - typ: Z3, - }, - ), - Add, - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000007, - ), - typ: Z3, - }, - ), - JumpI, - Push( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000064, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000032, - ), - typ: Z3, - }, - ), - ], - }, - path_condition: None, - left: Some( - StateTree { - id: NodeId { - id: 93e5d25a069f4945afbc7202ca712223, - parent: None, - }, - val: EvmState { - memory: Memory { - inner: [], - }, - stack: Stack { - stack: [ - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000002, - ), - typ: Z3, - }, - ], - }, - pc: 1, - pgm: [ - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000002, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000001, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - a, - ), - typ: Z3, - }, - ), - Add, - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000007, - ), - typ: Z3, - }, - ), - JumpI, - Push( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000064, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000032, - ), - typ: Z3, - }, - ), - ], - }, - path_condition: None, - left: Some( - StateTree { - id: NodeId { - id: c31b9dd6c241473ebaecb540353f4925, - parent: None, - }, - val: EvmState { - memory: Memory { - inner: [], - }, - stack: Stack { - stack: [ - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000002, - ), - typ: Z3, - }, - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000001, - ), - typ: Z3, - }, - ], - }, - pc: 2, - pgm: [ - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000002, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000001, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - a, - ), - typ: Z3, - }, - ), - Add, - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000007, - ), - typ: Z3, - }, - ), - JumpI, - Push( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000064, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000032, - ), - typ: Z3, - }, - ), - ], - }, - path_condition: None, - left: Some( - StateTree { - id: NodeId { - id: 9b647bf4ac7b46a69242e59984017fef, - parent: None, - }, - val: EvmState { - memory: Memory { - inner: [], - }, - stack: Stack { - stack: [ - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000002, - ), - typ: Z3, - }, - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000001, - ), - typ: Z3, - }, - BitVec { - inner: Z3( - a, - ), - typ: Z3, - }, - ], - }, - pc: 3, - pgm: [ - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000002, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000001, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - a, - ), - typ: Z3, - }, - ), - Add, - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000007, - ), - typ: Z3, - }, - ), - JumpI, - Push( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000064, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000032, - ), - typ: Z3, - }, - ), - ], - }, - path_condition: None, - left: Some( - StateTree { - id: NodeId { - id: 66c4de3ffa364582a08255e69c277215, - parent: None, - }, - val: EvmState { - memory: Memory { - inner: [], - }, - stack: Stack { - stack: [ - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000002, - ), - typ: Z3, - }, - BitVec { - inner: Z3( - (bvadd a #x0000000000000000000000000000000000000000000000000000000000000001), - ), - typ: Z3, - }, - ], - }, - pc: 4, - pgm: [ - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000002, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000001, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - a, - ), - typ: Z3, - }, - ), - Add, - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000007, - ), - typ: Z3, - }, - ), - JumpI, - Push( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000064, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000032, - ), - typ: Z3, - }, - ), - ], - }, - path_condition: None, - left: Some( - StateTree { - id: NodeId { - id: 850f56c7fb474be8964df31b0768e4e0, - parent: None, - }, - val: EvmState { - memory: Memory { - inner: [], - }, - stack: Stack { - stack: [ - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000002, - ), - typ: Z3, - }, - BitVec { - inner: Z3( - (bvadd a #x0000000000000000000000000000000000000000000000000000000000000001), - ), - typ: Z3, - }, - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000007, - ), - typ: Z3, - }, - ], - }, - pc: 5, - pgm: [ - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000002, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000001, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - a, - ), - typ: Z3, - }, - ), - Add, - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000007, - ), - typ: Z3, - }, - ), - JumpI, - Push( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000064, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000032, - ), - typ: Z3, - }, - ), - ], - }, - path_condition: None, - left: Some( - StateTree { - id: NodeId { - id: 194b94b65ac34df1bb5dc6d6a2295ec1, - parent: None, - }, - val: EvmState { - memory: Memory { - inner: [], - }, - stack: Stack { - stack: [ - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000002, - ), - typ: Z3, - }, - ], - }, - pc: 6, - pgm: [ - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000002, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000001, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - a, - ), - typ: Z3, - }, - ), - Add, - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000007, - ), - typ: Z3, - }, - ), - JumpI, - Push( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000064, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000032, - ), - typ: Z3, - }, - ), - ], - }, - path_condition: Some( - (and (not (not (= (bvadd a - #x0000000000000000000000000000000000000000000000000000000000000001) - #x0000000000000000000000000000000000000000000000000000000000000000)))), - ), - left: Some( - StateTree { - id: NodeId { - id: 5ffdf966e9d1476689c4e71cab83e9e6, - parent: None, - }, - val: EvmState { - memory: Memory { - inner: [], - }, - stack: Stack { - stack: [ - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000002, - ), - typ: Z3, - }, - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000064, - ), - typ: Z3, - }, - ], - }, - pc: 7, - pgm: [ - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000002, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000001, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - a, - ), - typ: Z3, - }, - ), - Add, - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000007, - ), - typ: Z3, - }, - ), - JumpI, - Push( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000064, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000032, - ), - typ: Z3, - }, - ), - ], - }, - path_condition: Some( - (and (not (not (= (bvadd a - #x0000000000000000000000000000000000000000000000000000000000000001) - #x0000000000000000000000000000000000000000000000000000000000000000)))), - ), - left: Some( - StateTree { - id: NodeId { - id: cb50266a2e174d318063fe6585098087, - parent: None, - }, - val: EvmState { - memory: Memory { - inner: [], - }, - stack: Stack { - stack: [ - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000002, - ), - typ: Z3, - }, - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000064, - ), - typ: Z3, - }, - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000032, - ), - typ: Z3, - }, - ], - }, - pc: 8, - pgm: [ - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000002, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000001, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - a, - ), - typ: Z3, - }, - ), - Add, - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000007, - ), - typ: Z3, - }, - ), - JumpI, - Push( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000064, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000032, - ), - typ: Z3, - }, - ), - ], - }, - path_condition: Some( - (and (not (not (= (bvadd a - #x0000000000000000000000000000000000000000000000000000000000000001) - #x0000000000000000000000000000000000000000000000000000000000000000)))), - ), - left: None, - right: None, - }, - ), - right: None, - }, - ), - right: None, - }, - ), - right: Some( - StateTree { - id: NodeId { - id: 349b98b471ad4c908ea348e334a3132b, - parent: None, - }, - val: EvmState { - memory: Memory { - inner: [], - }, - stack: Stack { - stack: [ - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000002, - ), - typ: Z3, - }, - ], - }, - pc: 7, - pgm: [ - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000002, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000001, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - a, - ), - typ: Z3, - }, - ), - Add, - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000007, - ), - typ: Z3, - }, - ), - JumpI, - Push( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000064, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000032, - ), - typ: Z3, - }, - ), - ], - }, - path_condition: Some( - (and (not (= (bvadd a - #x0000000000000000000000000000000000000000000000000000000000000001) - #x0000000000000000000000000000000000000000000000000000000000000000))), - ), - left: Some( - StateTree { - id: NodeId { - id: 84c6c28a405c4b4b9cba4716a2e6014c, - parent: None, - }, - val: EvmState { - memory: Memory { - inner: [], - }, - stack: Stack { - stack: [ - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000002, - ), - typ: Z3, - }, - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000032, - ), - typ: Z3, - }, - ], - }, - pc: 8, - pgm: [ - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000002, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000001, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - a, - ), - typ: Z3, - }, - ), - Add, - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000007, - ), - typ: Z3, - }, - ), - JumpI, - Push( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000064, - ), - typ: Z3, - }, - ), - Push32( - BitVec { - inner: Z3( - #x0000000000000000000000000000000000000000000000000000000000000032, - ), - typ: Z3, - }, - ), - ], - }, - path_condition: Some( - (and (not (= (bvadd a - #x0000000000000000000000000000000000000000000000000000000000000001) - #x0000000000000000000000000000000000000000000000000000000000000000))), - ), - left: None, - right: None, - }, - ), - right: None, - }, - ), - }, - ), - right: None, - }, - ), - right: None, - }, - ), - right: None, - }, - ), - right: None, - }, - ), - right: None, -} \ No newline at end of file diff --git a/examples/simple_storage.rs b/examples/simple_storage.rs index 4655871..8aa74a9 100644 --- a/examples/simple_storage.rs +++ b/examples/simple_storage.rs @@ -1,6 +1,7 @@ #![allow(unused_imports, unused)] use ser::{ - bvc, bvi, conversion::*, machine::*, memory::*, parser::*, stack::*, storage::*, traits::*, instruction::Instruction, + bvc, bvi, conversion::*, instruction::Instruction, machine::*, memory::*, parser::*, stack::*, + storage::*, traits::*, }; use z3::ast::*; @@ -17,17 +18,17 @@ fn main() { // as seen here https://bytegraph.xyz/bytecode/e5987a6f24f8af926faddae88de7980f/graph assert_eq!(7, leaf.len()); } - - - let reachability_report = Evm::exec_check(execution); println!("Report: {:#?}", reachability_report); - let traces = reachability_report.iter() + let traces = reachability_report + .iter() .map(|trace| trace.0.iter().map(|t| &t.1).collect::>()) .collect::>(); println!("traces: {:#?}", traces); - let reverted_traces = traces.into_iter().filter(|t| *t.last().unwrap().clone() == Instruction::Revert).collect::>(); + let reverted_traces = traces + .into_iter() + .filter(|t| *t.last().unwrap().clone() == Instruction::Revert) + .collect::>(); println!("TRACES WITH REVERTS {:#?}", reverted_traces); - } diff --git a/examples/swaps.rs b/examples/swaps.rs index 26d6d85..929904d 100644 --- a/examples/swaps.rs +++ b/examples/swaps.rs @@ -34,7 +34,7 @@ PUSH1 0x10 RETURN -MAYBE REVERT: +MAYBE REVERT: PUSH1 0x42 PUSH1 0x00 PUSH2 0x5000 diff --git a/src/conversion/mod.rs b/src/conversion/mod.rs index d677a7f..f4b39df 100644 --- a/src/conversion/mod.rs +++ b/src/conversion/mod.rs @@ -81,7 +81,6 @@ impl From<[u8; SZ]> for BitVec { for i in value.iter() { let new_bv: BV<'static> = bvi::<1>(*i).into(); bv = bv.concat(&new_bv).simplify(); - } // eprintln!("VALUE CONVERTING FROM: {:#x?}", value); // eprintln!("BV IN SLICE CONVERT: {:#?} SIZE: {}", bv, bv.get_size()); @@ -97,9 +96,7 @@ pub fn bitvec_array_to_bv<'ctx>(value: Vec>) -> BV<'ctx> { for i in value.iter() { bv = bv.concat(i.as_ref()).simplify(); } - bv.extract((bv.get_size() - 8 - 1) as u32, 0) - .simplify() - + bv.extract((bv.get_size() - 8 - 1) as u32, 0).simplify() } impl TryFrom>> for BitVec { type Error = String; @@ -110,9 +107,10 @@ impl TryFrom>> for BitVec { for i in value.iter() { bv = bv.concat(i.as_ref()).simplify(); } - Ok(bv.extract((bv.get_size() - 8 - 1) as u32, 0) - .simplify() - .into()) + Ok(bv + .extract((bv.get_size() - 8 - 1) as u32, 0) + .simplify() + .into()) } } impl AsRef> for BitVec { diff --git a/src/instruction/mod.rs b/src/instruction/mod.rs index 8be9a3d..79eb993 100644 --- a/src/instruction/mod.rs +++ b/src/instruction/mod.rs @@ -185,7 +185,6 @@ fn exec_dup_nth(mach: &EvmState, n: usize) -> MachineRecord<32> { } fn exec_swap_nth(mach: &EvmState, n: usize) -> MachineRecord<32> { - MachineRecord { stack: Some(StackChange { pop_qty: 0, @@ -244,17 +243,14 @@ impl Instruction { impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { fn exec(&self, mach: &EvmState) -> MachineRecord<32> { match self { - Instruction::Stop => { - MachineRecord { - halt: true, - stack: None, - mem: None, - constraints: None, - storage: None, - pc: (mach.pc(), mach.pc()) - } - } - , + Instruction::Stop => MachineRecord { + halt: true, + stack: None, + mem: None, + constraints: None, + storage: None, + pc: (mach.pc(), mach.pc()), + }, Instruction::Add => { let stack = mach.stack(); let [stack_top, stack_top2] = stack.peek_top().unwrap(); @@ -621,42 +617,37 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { } Instruction::Sha3 => { let stack = mach.stack(); - let [ offset, size] = stack.peek_top().unwrap(); + let [offset, size] = stack.peek_top().unwrap(); let mut offsett = offset.clone(); let mut sizee = size.clone(); offsett.simplify(); sizee.simplify(); - + let mem = mach.mem().read_with_offset(offsett.clone(), sizee.clone()); let sz = usize::from(sizee.clone()); - + let mut bv: BV<'static> = bitvec_array_to_bv(mem); - - - - + let hashed = sha3(bv.get_size()).apply(&[&bv]); - + let hashed: BitVec<32> = hashed.as_bv().unwrap().into(); let mem_change = MemChange { - ops_log: vec![MemOp::Read {idx: offsett.clone()}] + ops_log: vec![MemOp::Read { + idx: offsett.clone(), + }], }; - let stack_change = StackChange::with_ops(vec![ - StackOp::Pop, - StackOp::Pop, - StackOp::Push(hashed) - ]); - + let stack_change = + StackChange::with_ops(vec![StackOp::Pop, StackOp::Pop, StackOp::Push(hashed)]); + MachineRecord { stack: Some(stack_change), mem: Some(mem_change), - pc: (mach.pc(), mach.pc() + self.byte_size()), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, storage: None, } - - }, + } Instruction::Address => todo!(), Instruction::Balance => { let stack = mach.stack(); @@ -892,7 +883,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { let dest = stack.peek().unwrap(); let mut dest = dest.clone(); dest.simplify(); - + let mut val_mem = mach.memory.read_word(dest.clone()); val_mem.simplify(); @@ -1016,7 +1007,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { } Instruction::Jump => { let jump_dest = mach.stack().peek().unwrap(); - + let jump_dest_concrete = jump_dest.as_ref().simplify().as_u64().unwrap() as usize; let stack_rec = StackChange { pop_qty: 1, @@ -1048,7 +1039,6 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { push_qty: 0, ops: vec![StackOp::Pop, StackOp::Pop], }; - MachineRecord { stack: Some(stack_rec), diff --git a/src/memory.rs b/src/memory.rs index 884306b..bf965c3 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -76,11 +76,15 @@ impl Memory { val } - pub fn read_with_offset(&self, offset: Index, size: impl Into + Clone) -> Vec> { + pub fn read_with_offset( + &self, + offset: Index, + size: impl Into + Clone, + ) -> Vec> { let idx: usize = offset.into(); - + eprintln!("IDX: {idx:} and size: {:#?}", size.clone().into()); - let val = self.inner[idx .. (idx + size.clone().into())].to_vec(); + let val = self.inner[idx..(idx + size.clone().into())].to_vec(); eprintln!("VAL IN MEM READ EITH OFFSET: {:#?}", val); val } diff --git a/src/state/env.rs b/src/state/env.rs index 1842c21..364ae3f 100644 --- a/src/state/env.rs +++ b/src/state/env.rs @@ -1,4 +1,4 @@ -use z3_ext::ast::{Ast, AstKind, Array, BV}; +use z3_ext::ast::{Array, Ast, AstKind, BV}; use z3_ext::FuncDecl; use z3_ext::Sort; @@ -35,7 +35,7 @@ pub fn sha3<'ctx>(size: u32) -> FuncDecl<'ctx> { ctx(), format!("sha3_{}", id).as_str(), &[&Sort::bitvector(ctx(), size)], - &Sort::bitvector(ctx(), 256) + &Sort::bitvector(ctx(), 256), ); eprintln!("SHA3 FUNC: {:#?}", func); diff --git a/tests/lib.rs b/tests/lib.rs index 9f2c69e..8bfcee6 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -84,7 +84,7 @@ PUSH1 0x10 RETURN -MAYBE REVERT: +MAYBE REVERT: PUSH1 0x42 PUSH1 0x00 PUSH2 0x5000 @@ -138,4 +138,3 @@ fn test_swap2_jumpi_maybe_revert() { reachability_report.get(1).unwrap().1.unwrap() ); } - diff --git a/tests/test_storage.rs b/tests/test_storage.rs deleted file mode 100644 index 8b13789..0000000 --- a/tests/test_storage.rs +++ /dev/null @@ -1 +0,0 @@ - From dfc3f43dd4c6272323f8bf5cc8a6b223fd14014a Mon Sep 17 00:00:00 2001 From: tannr Date: Sat, 5 Aug 2023 00:26:36 -0400 Subject: [PATCH 28/28] Add gas opcode, begin support for configurable execution ctx --- src/instruction/mod.rs | 27 +++++++++++++++++++++++++-- src/state/env.rs | 40 +++++++++++++++++++++++++++++++++++++++- src/state/evm.rs | 1 + 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/src/instruction/mod.rs b/src/instruction/mod.rs index 79eb993..1c96746 100644 --- a/src/instruction/mod.rs +++ b/src/instruction/mod.rs @@ -648,7 +648,18 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { storage: None, } } - Instruction::Address => todo!(), + Instruction::Address => { + let addr = mach.address.as_ref(); + let addr = addr.zero_ext(12 * 8); + MachineRecord { + stack: Some(StackChange::with_ops(vec![StackOp::Push(addr.into())])), + mem: None, + pc: (mach.pc(), mach.pc() + self.byte_size()), + constraints: None, + halt: false, + storage: None, + } + }, Instruction::Balance => { let stack = mach.stack(); let addr = stack.peek().unwrap(); @@ -1082,7 +1093,19 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { constraints: None, } } - Instruction::Gas => todo!(), + Instruction::Gas => { + let gas_arg: BitVec<256> = random_bv_arg(); + let gas = gas().apply(&[gas_arg.as_ref()]).as_bv().unwrap(); + MachineRecord { + stack: Some(StackChange::with_ops(vec![StackOp::Push(gas.into())])), + pc: (mach.pc(), mach.pc() + self.byte_size()), + mem: None, + halt: false, + storage: None, + constraints: None, + } + + }, Instruction::JumpDest => MachineRecord { stack: None, pc: (mach.pc(), mach.pc() + self.byte_size()), diff --git a/src/state/env.rs b/src/state/env.rs index 364ae3f..21bad1f 100644 --- a/src/state/env.rs +++ b/src/state/env.rs @@ -1,11 +1,49 @@ +use std::collections::HashMap; + use z3_ext::ast::{Array, Ast, AstKind, BV}; use z3_ext::FuncDecl; use z3_ext::Sort; +use crate::parser::Program; use crate::random_bv_arg; use crate::smt::{ctx, BitVec}; - +use crate::storage::Address; + +#[derive(Debug, Clone)] +pub struct ExecutionEnv { + code: HashMap>, + block: Block, + tx: TransactionContext, + result: Option +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum EvmResult { + Failed { + msg: String + }, + Success { + ret_val: BitVec<32> + } +} +#[derive(Debug, Clone)] +pub struct TransactionContext { + calldata: Option>>, + caller: Option
, + callvalue: Option>, +} + +#[derive(Debug, Clone)] +pub struct Block { + base_fee: Option>, + chain_id: Option>, + coinbase: Option
, + difficulty: Option>, + gaslimit: Option>, + number: Option>, + timestamp: Option> +} /** Note: Some of these functions in EVM have no arguments. The reason they are passed an argument here is because a zero argument function is diff --git a/src/state/evm.rs b/src/state/evm.rs index a8b2567..5f74ffd 100644 --- a/src/state/evm.rs +++ b/src/state/evm.rs @@ -23,6 +23,7 @@ pub struct EvmState { pub halt: bool, } + impl MachineComponent for EvmState { type Record = MachineRecord<32>;