diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 30befe7f5..fba60cef8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -56,10 +56,16 @@ jobs: steps: - uses: actions/checkout@v3 - # will install toolchain specified in rust-toolchain - name: Install Rust toolchain run: | rustup show + - uses: actions-rust-lang/setup-rust-toolchain@v1 + + - name: Setup Additional Languages (solidity) + uses: foundry-rs/foundry-toolchain@v1.2.0 + uses: pontem-network/get-solc@master + with: + version: v0.8.25 - name: Setup Additional Languages (python3) uses: actions/setup-python@v4 diff --git a/Cargo.lock b/Cargo.lock index 601bf7cc0..8f0c6201f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,161 @@ dependencies = [ "memchr", ] +[[package]] +name = "alloy-eip2930" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0069cf0642457f87a01a014f6dc29d5d893cd4fd8fddf0c3cdfad1bb3ebafc41" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "serde", +] + +[[package]] +name = "alloy-eip7702" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cabf647eb4650c91a9d38cb6f972bb320009e7e9d61765fb688a86f1563b33e8" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "derive_more", + "k256", + "serde", +] + +[[package]] +name = "alloy-json-abi" +version = "0.8.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "731ea743b3d843bc657e120fb1d1e9cc94f5dab8107e35a82125a63e6420a102" +dependencies = [ + "alloy-primitives", + "alloy-sol-type-parser", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-primitives" +version = "0.8.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "788bb18e8f61d5d9340b52143f27771daf7e1dccbaf2741621d2493f9debf52e" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more", + "foldhash", + "hashbrown 0.15.2", + "indexmap 2.7.0", + "itoa", + "k256", + "keccak-asm", + "paste", + "proptest", + "rand", + "ruint", + "rustc-hash", + "serde", + "sha3", + "tiny-keccak", +] + +[[package]] +name = "alloy-rlp" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f542548a609dca89fcd72b3b9f355928cf844d4363c5eed9c5273a3dd225e097" +dependencies = [ + "alloy-rlp-derive", + "arrayvec", + "bytes", +] + +[[package]] +name = "alloy-rlp-derive" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a833d97bf8a5f0f878daf2c8451fff7de7f9de38baa5a45d936ec718d81255a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "alloy-sol-macro" +version = "0.8.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a07b74d48661ab2e4b50bb5950d74dbff5e61dd8ed03bb822281b706d54ebacb" +dependencies = [ + "alloy-sol-macro-expander", + "alloy-sol-macro-input", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "alloy-sol-macro-expander" +version = "0.8.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19cc9c7f20b90f9be1a8f71a3d8e283a43745137b0837b1a1cb13159d37cad72" +dependencies = [ + "alloy-sol-macro-input", + "const-hex", + "heck 0.5.0", + "indexmap 2.7.0", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.85", + "syn-solidity", + "tiny-keccak", +] + +[[package]] +name = "alloy-sol-macro-input" +version = "0.8.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "713b7e6dfe1cb2f55c80fb05fd22ed085a1b4e48217611365ed0ae598a74c6ac" +dependencies = [ + "const-hex", + "dunce", + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.85", + "syn-solidity", +] + +[[package]] +name = "alloy-sol-type-parser" +version = "0.8.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1eda2711ab2e1fb517fc6e2ffa9728c9a232e296d16810810e6957b781a1b8bc" +dependencies = [ + "serde", + "winnow", +] + +[[package]] +name = "alloy-sol-types" +version = "0.8.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b478bc9c0c4737a04cd976accde4df7eba0bdc0d90ad6ff43d58bc93cf79c1" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-macro", + "const-hex", + "serde", +] + [[package]] name = "ansi_term" version = "0.12.1" @@ -22,9 +177,139 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" + +[[package]] +name = "ark-ff" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" +dependencies = [ + "ark-ff-asm 0.3.0", + "ark-ff-macros 0.3.0", + "ark-serialize 0.3.0", + "ark-std 0.3.0", + "derivative", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.3.3", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm 0.4.2", + "ark-ff-macros 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "derivative", + "digest 0.10.7", + "itertools", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.4.1", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +dependencies = [ + "num-bigint", + "num-traits", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-serialize" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" +dependencies = [ + "ark-std 0.3.0", + "digest 0.9.0", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-std 0.4.0", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-std" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "atty" @@ -32,17 +317,50 @@ 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", ] +[[package]] +name = "aurora-engine-modexp" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aef7712851e524f35fbbb74fa6599c5cd8692056a1c36f9ca0d2001b670e7e5" +dependencies = [ + "hex", + "num", +] + +[[package]] +name = "auto_impl" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + [[package]] name = "autocfg" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "bcs" version = "0.1.6" @@ -62,6 +380,21 @@ dependencies = [ "serde", ] +[[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" @@ -69,37 +402,296 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] -name = "bitflags" -version = "2.5.0" +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "blst" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4378725facc195f1a538864863f6de233b500a8862747e7f165078a419d5e874" +dependencies = [ + "cc", + "glob", + "threadpool", + "zeroize", +] + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" +dependencies = [ + "serde", +] + +[[package]] +name = "c-kzg" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0307f72feab3300336fb803a57134159f6e20139af1357f36c54cb90d8e8928" +dependencies = [ + "blst", + "cc", + "glob", + "hex", + "libc", + "once_cell", + "serde", +] + +[[package]] +name = "cc" +version = "1.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags 1.3.2", + "strsim", + "textwrap 0.11.0", + "unicode-width", + "vec_map", +] + +[[package]] +name = "const-hex" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b0485bab839b018a8f1723fc5391819fea5f8f0f32288ef8a735fd096b6160c" +dependencies = [ + "cfg-if", + "cpufeatures", + "hex", + "proptest", + "serde", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "cpufeatures" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +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.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +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.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", + "unicode-xid", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "either" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] -name = "cfg-if" -version = "1.0.0" +name = "elliptic-curve" +version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", +] [[package]] -name = "clap" -version = "2.34.0" +name = "enumn" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38" dependencies = [ - "ansi_term", - "atty", - "bitflags 1.3.2", - "strsim", - "textwrap 0.11.0", - "unicode-width", - "vec_map", + "proc-macro2", + "quote", + "syn 2.0.85", ] [[package]] -name = "either" -version = "1.12.0" +name = "equivalent" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "erased-discriminant" @@ -126,6 +718,79 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +[[package]] +name = "fastrlp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + +[[package]] +name = "fastrlp" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -143,12 +808,33 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +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.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +dependencies = [ + "foldhash", + "serde", +] + [[package]] name = "heck" version = "0.3.3" @@ -158,6 +844,12 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -167,11 +859,29 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + [[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.7", +] [[package]] name = "home" @@ -182,6 +892,26 @@ dependencies = [ "windows-sys", ] +[[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-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.109", +] + [[package]] name = "include_dir" version = "0.6.2" @@ -213,7 +943,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +dependencies = [ + "equivalent", + "hashbrown 0.15.2", + "serde", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", ] [[package]] @@ -222,11 +972,46 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "keccak-asm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "505d1856a39b200489082f90d897c3f07c455563880bc5952e38eabf731c83b6" +dependencies = [ + "digest 0.10.7", + "sha3-asm", +] + [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin", +] [[package]] name = "libc" @@ -234,6 +1019,12 @@ version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +[[package]] +name = "libm" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" + [[package]] name = "linked-hash-map" version = "0.5.6" @@ -258,12 +1049,139 @@ version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi 0.3.9", + "libc", +] + [[package]] name = "once_cell" version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "parity-scale-codec" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pest" +version = "2.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + [[package]] name = "phf" version = "0.10.1" @@ -308,12 +1226,42 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "ppv-lite86" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash", + "impl-codec", + "uint", +] + +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -338,6 +1286,28 @@ dependencies = [ "version_check", ] +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.85", +] + [[package]] name = "proc-macro-hack" version = "0.5.20+deprecated" @@ -353,6 +1323,32 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "proptest" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags 2.6.0", + "lazy_static", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quote" version = "1.0.36" @@ -362,6 +1358,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "rand" version = "0.8.5" @@ -371,6 +1373,7 @@ dependencies = [ "libc", "rand_chacha", "rand_core", + "serde", ] [[package]] @@ -392,6 +1395,15 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + [[package]] name = "regex" version = "1.10.4" @@ -421,25 +1433,249 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +[[package]] +name = "revm" +version = "19.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b829dc9d6e62c5a540dfdceb0c4d2217e445bf5f6f5ed3866817e7a9637c019" +dependencies = [ + "auto_impl", + "cfg-if", + "dyn-clone", + "revm-interpreter", + "revm-precompile", + "serde", + "serde_json", +] + +[[package]] +name = "revm-interpreter" +version = "15.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ff76b50b5a9fa861fbc236fc82ce1afdf58861f65012aea807d679e54630d6" +dependencies = [ + "revm-primitives", + "serde", +] + +[[package]] +name = "revm-precompile" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6542fb37650dfdbf4b9186769e49c4a8bc1901a3280b2ebf32f915b6c8850f36" +dependencies = [ + "aurora-engine-modexp", + "blst", + "c-kzg", + "cfg-if", + "k256", + "once_cell", + "revm-primitives", + "ripemd", + "secp256k1", + "sha2", + "substrate-bn", +] + +[[package]] +name = "revm-primitives" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48faea1ecf2c9f80d9b043bbde0db9da616431faed84c4cfa3dd7393005598e6" +dependencies = [ + "alloy-eip2930", + "alloy-eip7702", + "alloy-primitives", + "auto_impl", + "bitflags 2.6.0", + "bitvec", + "c-kzg", + "cfg-if", + "dyn-clone", + "enumn", + "hex", + "serde", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "ripemd" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" +dependencies = [ + "digest 0.10.7", +] + +[[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.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5ef8fb1dd8de3870cb8400d51b4c2023854bbafd5431a3ac7e7317243e22d2f" +dependencies = [ + "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "bytes", + "fastrlp 0.3.1", + "fastrlp 0.4.0", + "num-bigint", + "num-integer", + "num-traits", + "parity-scale-codec", + "primitive-types", + "proptest", + "rand", + "rlp", + "ruint-macro", + "serde", + "valuable", + "zeroize", +] + +[[package]] +name = "ruint-macro" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" + +[[package]] +name = "rustc-hash" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" + +[[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.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver 1.0.24", +] + [[package]] name = "rustix" version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", "windows-sys", ] +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + [[package]] name = "ryu" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "secp256k1" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" +dependencies = [ + "rand", + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" +dependencies = [ + "cc", +] + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" + +[[package]] +name = "semver-parser" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9900206b54a3527fdc7b8a938bffd94a568bac4f4aa8113b209df75a09c0dec2" +dependencies = [ + "pest", +] + [[package]] name = "serde" version = "1.0.213" @@ -453,18 +1689,22 @@ dependencies = [ name = "serde-generate" version = "0.28.0" dependencies = [ + "alloy-sol-types", + "anyhow", "bcs", "bincode", - "heck", + "heck 0.3.3", "hex", "include_dir", "lazy_static", "maplit", "phf", "regex", + "revm", "serde", "serde-reflection", "serde_bytes", + "serde_json", "serde_yaml", "tempfile", "textwrap 0.13.4", @@ -534,6 +1774,7 @@ version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ + "indexmap 2.7.0", "itoa", "ryu", "serde", @@ -545,12 +1786,59 @@ version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" dependencies = [ - "indexmap", + "indexmap 1.9.3", "ryu", "serde", "yaml-rust", ] +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "sha3-asm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28efc5e327c837aa837c59eae585fc250715ef939ac32881bcc11677cd02d46" +dependencies = [ + "cc", + "cfg-if", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core", +] + [[package]] name = "siphasher" version = "0.3.11" @@ -563,6 +1851,28 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" +[[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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "strsim" version = "0.8.0" @@ -586,13 +1896,32 @@ version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ - "heck", + "heck 0.3.3", "proc-macro-error", "proc-macro2", "quote", "syn 1.0.109", ] +[[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.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" version = "1.0.109" @@ -615,6 +1944,24 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn-solidity" +version = "0.8.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e89d8bf2768d277f40573c83a02a099e96d96dd3104e13ea676194e61ac4b0" +dependencies = [ + "paste", + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "tempfile" version = "3.10.1" @@ -666,12 +2013,77 @@ dependencies = [ "syn 2.0.85", ] +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap 2.7.0", + "toml_datetime", + "winnow", +] + [[package]] name = "typeid" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e13db2e0ccd5e14a544e8a246ba2312cd25223f616442d7f2cb0e3db614236e" +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + [[package]] name = "unicode-ident" version = "1.0.12" @@ -690,6 +2102,18 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "vec_map" version = "0.8.2" @@ -702,6 +2126,15 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -815,6 +2248,24 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +[[package]] +name = "winnow" +version = "0.6.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39281189af81c07ec09db316b302a3e67bf9bd7cbf6c820b50e35fee9c2fa980" +dependencies = [ + "memchr", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "yaml-rust" version = "0.4.5" @@ -823,3 +2274,23 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] diff --git a/serde-generate-bin/src/main.rs b/serde-generate-bin/src/main.rs index ef5321273..242844704 100644 --- a/serde-generate-bin/src/main.rs +++ b/serde-generate-bin/src/main.rs @@ -9,8 +9,8 @@ //! ''' use serde_generate::{ - cpp, csharp, dart, golang, java, ocaml, python3, rust, swift, typescript, CodeGeneratorConfig, - Encoding, SourceInstaller, + cpp, csharp, dart, golang, java, ocaml, python3, rust, solidity, swift, typescript, + CodeGeneratorConfig, Encoding, SourceInstaller, }; use serde_reflection::Registry; use std::path::PathBuf; @@ -21,6 +21,7 @@ arg_enum! { enum Language { Python3, Cpp, + Solidity, Rust, Java, Go, @@ -139,6 +140,9 @@ fn main() { Language::Cpp => cpp::CodeGenerator::new(&config) .output(&mut out, ®istry) .unwrap(), + Language::Solidity => solidity::CodeGenerator::new(&config) + .output(&mut out, ®istry) + .unwrap(), Language::Go => golang::CodeGenerator::new(&config) .output(&mut out, ®istry) .unwrap(), @@ -172,6 +176,7 @@ fn main() { } Language::Rust => Box::new(rust::Installer::new(install_dir)), Language::Cpp => Box::new(cpp::Installer::new(install_dir)), + Language::Solidity => Box::new(solidity::Installer::new(install_dir)), Language::Java => Box::new(java::Installer::new(install_dir)), Language::Go => { Box::new(golang::Installer::new(install_dir, serde_package_name_opt)) diff --git a/serde-generate-bin/tests/cli.rs b/serde-generate-bin/tests/cli.rs index d1cd71c61..969f8ee11 100644 --- a/serde-generate-bin/tests/cli.rs +++ b/serde-generate-bin/tests/cli.rs @@ -247,6 +247,14 @@ fn test_that_installed_rust_code_compiles() { assert!(status.success()); } +#[test] +fn create_test_yaml() { + let registry = test_utils::get_registry().unwrap(); + let dir = tempdir().unwrap(); + let yaml_path = dir.path().join("test.yaml"); + std::fs::write(yaml_path, serde_yaml::to_string(®istry).unwrap()).unwrap(); +} + #[test] fn test_that_installed_cpp_code_compiles() { let registry = test_utils::get_registry().unwrap(); diff --git a/serde-generate/Cargo.toml b/serde-generate/Cargo.toml index d1f8282df..e2e4a15bd 100644 --- a/serde-generate/Cargo.toml +++ b/serde-generate/Cargo.toml @@ -18,6 +18,7 @@ exclude = [ autotests = false [dependencies] +anyhow = "1.0.95" heck = "0.3.2" include_dir = { version = "0.6.0", optional = true } serde = { version = "1.0.126", features = ["derive"] } @@ -26,6 +27,7 @@ phf = { version = "0.10", features = ["macros"], optional = true } serde-reflection = { path = "../serde-reflection", version = "0.5.0" } [dev-dependencies] +alloy-sol-types = "0.8.18" hex = "0.4.3" lazy_static = "1.4.0" regex = "1.5.5" @@ -36,9 +38,11 @@ serde_yaml = "0.8.17" bincode = "1.3.3" bcs = "0.1.3" maplit = "1.0.2" +revm = "19.2.0" +serde_json = "1.0.115" [features] -default = ["cpp", "csharp", "dart", "golang", "java", "ocaml", "python3", "rust", "swift", "typescript"] +default = ["cpp", "csharp", "dart", "golang", "java", "ocaml", "python3", "rust", "swift", "typescript", "solidity"] cpp = [] csharp = ["include_dir"] dart = ["include_dir"] @@ -47,6 +51,7 @@ java = ["include_dir"] ocaml = ["phf", "include_dir"] python3 = [] rust = [] +solidity = [] swift = ["include_dir"] typescript = ["include_dir"] diff --git a/serde-generate/src/lib.rs b/serde-generate/src/lib.rs index 7e53f20ce..34b456e6a 100644 --- a/serde-generate/src/lib.rs +++ b/serde-generate/src/lib.rs @@ -164,6 +164,9 @@ pub mod python3; /// Support for code-generation in Rust #[cfg(feature = "rust")] pub mod rust; +/// Support for code-generation in solidity +#[cfg(feature = "solidity")] +pub mod solidity; /// Support for code-generation in Swift #[cfg(feature = "swift")] pub mod swift; diff --git a/serde-generate/src/solidity.rs b/serde-generate/src/solidity.rs new file mode 100644 index 000000000..ab15bdb14 --- /dev/null +++ b/serde-generate/src/solidity.rs @@ -0,0 +1,1279 @@ +// Copyright (c) Facebook, Inc. and its affiliates +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use crate::{ + indent::{IndentConfig, IndentedWriter}, + CodeGeneratorConfig, +}; +use heck::SnakeCase; +use phf::phf_set; +use serde_reflection::{ContainerFormat, Format, Named, Registry, VariantFormat}; +use std::{ + collections::{HashMap, HashSet}, + io::{Result, Write}, + path::PathBuf, +}; + +/// Main configuration object for code-generation in solidity +pub struct CodeGenerator<'a> { + /// Language-independent configuration. + config: &'a CodeGeneratorConfig, +} + +/// Shared state for the code generation of a solidity source file. +struct SolEmitter<'a, T> { + /// Writer. + out: IndentedWriter, + /// Generator. + generator: &'a CodeGenerator<'a>, +} + +fn get_data_location(need_memory: bool) -> String { + match need_memory { + true => " memory".to_string(), + false => "".to_string(), + } +} + +fn output_generic_bcs_deserialize( + out: &mut IndentedWriter, + key_name: &str, + code_name: &str, + need_memory: bool, +) -> Result<()> { + let data_location = get_data_location(need_memory); + writeln!( + out, + r#" +function bcs_deserialize_{key_name}(bytes memory input) public pure returns ({code_name}{data_location}) {{ + uint256 new_pos; + {code_name}{data_location} value; + (new_pos, value) = bcs_deserialize_offset_{key_name}(0, input); + require(new_pos == input.length, "incomplete deserialization"); + return value; +}}"# + )?; + Ok(()) +} + +static KEYWORDS: phf::Set<&str> = phf_set! { + "abstract", "after", "alias", "anonymous", + "as", "assembly", "break", "catch", "constant", + "continue", "constructor", "contract", "delete", + "do", "else", "emit", "enum", "error", "event", + "external", "fallback", "for", "function", "if", + "immutable", "import", "indexed", "interface", + "internal", "is", "library", "mapping", "memory", + "modifier", "new", "override", "payable", "pragma", + "private", "public", "pure", "receive", "return", + "returns", "revert", "storage", "struct", "throw", + "try", "type", "unchecked", "using", "virtual", + "view", "while", "addmod", "blockhash", "ecrecover", + "keccak256", "mulmod", "sha256", "ripemd160", + "block", "msg", "tx", "balance", "transfer", "send", + "call", "delegatecall", "staticcall", "this", + "super", "gwei", "finney", "szabo", "ether", + "seconds", "minutes", "hours", "days", "weeks", + "years", "wei", "hex", "address", "bool", "bytes", + "string", "int", "int8", "int16", "int32", "int64", + "int128", "int256", "uint", "uint8", "uint16", + "uint32", "uint64", "uint128", "uint256", + "bytes1", "bytes2", "bytes3", "bytes4", "bytes5", + "bytes6", "bytes7", "bytes8", "bytes9", "bytes10", + "bytes11", "bytes12", "bytes13", "bytes14", "bytes15", + "bytes16", "bytes17", "bytes18", "bytes19", "bytes20", + "bytes21", "bytes22", "bytes23", "bytes24", "bytes25", + "bytes26", "bytes27", "bytes28", "bytes29", "bytes30", + "bytes31", "bytes32" +}; + +fn safe_variable(s: &str) -> String { + if KEYWORDS.contains(s) { + s.to_owned() + "_" + } else { + s.to_string() + } +} + +#[derive(Clone, Debug)] +enum Primitive { + Unit, + Bool, + I8, + I16, + I32, + I64, + I128, + U8, + U16, + U32, + U64, + U128, + Char, + Str, + Bytes, +} + +impl Primitive { + pub fn name(&self) -> String { + use Primitive::*; + match self { + Unit => "empty_struct".into(), + Bool => "bool".into(), + I8 => "int8".into(), + I16 => "int16".into(), + I32 => "int32".into(), + I64 => "int64".into(), + I128 => "int128".into(), + U8 => "uint8".into(), + U16 => "uint16".into(), + U32 => "uint32".into(), + U64 => "uint64".into(), + U128 => "uint128".into(), + Char => "bytes1".into(), + Str => "string".into(), + Bytes => "bytes".into(), + } + } + + pub fn output(&self, out: &mut IndentedWriter) -> Result<()> { + use Primitive::*; + match self { + Unit => writeln!( + out, + r#" +struct empty_struct {{ + int8 val; +}} +function bcs_serialize_empty_struct(empty_struct memory input) internal pure returns (bytes memory) {{ + bytes memory result; + return result; +}} +function bcs_deserialize_offset_empty_struct(uint256 pos, bytes memory input) internal pure returns (uint256, empty_struct memory) {{ + int8 val = 0; + return (pos, empty_struct(val)); +}}"# + )?, + Bool => { + writeln!( + out, + r#" +function bcs_serialize_bool(bool input) internal pure returns (bytes memory) {{ + return abi.encodePacked(input); +}} +function bcs_deserialize_offset_bool(uint256 pos, bytes memory input) internal pure returns (uint256, bool) {{ + uint8 val = uint8(input[pos]); + bool result = false; + if (val == 1) {{ + result = true; + }} + return (pos + 1, result); +}}"# + )?; + } + I8 => { + writeln!( + out, + r#" +function bcs_serialize_int8(int8 input) internal pure returns (bytes memory) {{ + return abi.encodePacked(input); +}} +function bcs_deserialize_offset_int8(uint256 pos, bytes memory input) internal pure returns (uint256, int8) {{ + int16 val = int16(uint16(uint8(input[pos]))); + if (val < 128) {{ + return (pos + 1, int8(val)); + }} else {{ + return (pos + 1, int8(val - 256)); + }} +}}"# + )?; + } + I16 => writeln!( + out, + r#" +function bcs_serialize_int16(int16 input) internal pure returns (bytes memory) {{ + bytes memory result = new bytes(2); + uint16 uinput; + if (input >= 0) {{ + uinput = uint16(input); + }} else {{ + int32 input_32 = int32(input) + 65536; + uinput = uint16(uint32(input_32)); + }} + return bcs_serialize_uint16(uinput); +}} +function bcs_deserialize_offset_int16(uint256 pos, bytes memory input) internal pure returns (uint256, int16) {{ + uint256 new_pos; + uint16 uresult; + (new_pos, uresult) = bcs_deserialize_offset_uint16(pos, input); + int16 result; + if (uresult < 32768) {{ + result = int16(uresult); + return (new_pos, result); + }} else {{ + int32 result_32 = int32(uint32(uresult)) - 65536; + result = int16(result_32); + }} + return (new_pos, result); +}}"# + )?, + I32 => { + writeln!( + out, + r#" +function bcs_serialize_int32(int32 input) internal pure returns (bytes memory) {{ + bytes memory result = new bytes(4); + uint32 uinput; + if (input >= 0) {{ + uinput = uint32(input); + }} else {{ + int64 input_64 = int64(input) + 4294967296; + uinput = uint32(uint64(input_64)); + }} + return bcs_serialize_uint32(uinput); +}} +function bcs_deserialize_offset_int32(uint256 pos, bytes memory input) internal pure returns (uint256, int32) {{ + uint256 new_pos; + uint32 uresult; + (new_pos, uresult) = bcs_deserialize_offset_uint32(pos, input); + int32 result; + if (uresult < 2147483648) {{ + result = int32(uresult); + return (new_pos, result); + }} else {{ + int64 result_64 = int64(uint64(uresult)) - 4294967296; + result = int32(result_64); + }} + return (new_pos, result); +}}"# + )?; + } + I64 => { + writeln!( + out, + r#" +function bcs_serialize_int64(int64 input) internal pure returns (bytes memory) {{ + bytes memory result = new bytes(8); + uint64 uinput; + if (input >= 0) {{ + uinput = uint64(input); + }} else {{ + int128 input_128 = int128(input) + 18446744073709551616; + uinput = uint64(uint128(input_128)); + }} + return bcs_serialize_uint64(uinput); +}} +function bcs_deserialize_offset_int64(uint256 pos, bytes memory input) internal pure returns (uint256, int64) {{ + uint256 new_pos; + uint64 uresult; + (new_pos, uresult) = bcs_deserialize_offset_uint64(pos, input); + int64 result; + if (uresult < 9223372036854775808) {{ + result = int64(uresult); + return (new_pos, result); + }} else {{ + int128 result_128 = int128(uint128(uresult)) - 18446744073709551616; + result = int64(result_128); + }} + return (new_pos, result); +}}"# + )?; + } + I128 => { + writeln!( + out, + r#" +function bcs_serialize_int128(int128 input) internal pure returns (bytes memory) {{ + bytes memory result = new bytes(16); + uint128 uinput; + if (input >= 0) {{ + uinput = uint128(input); + }} else {{ + int256 input_256 = int256(input) + 340282366920938463463374607431768211456; + uinput = uint128(uint256(input_256)); + }} + return bcs_serialize_uint128(uinput); +}} +function bcs_deserialize_offset_int128(uint256 pos, bytes memory input) internal pure returns (uint256, int128) {{ + uint256 new_pos; + uint128 uresult; + (new_pos, uresult) = bcs_deserialize_offset_uint128(pos, input); + int128 result; + if (uresult < 170141183460469231731687303715884105728) {{ + result = int128(uresult); + return (new_pos, result); + }} else {{ + int256 result_256 = int256(uint256(uresult)) - 340282366920938463463374607431768211456; + result = int128(result_256); + }} + return (new_pos, result); +}}"# + )?; + } + U8 => { + writeln!( + out, + r#" +function bcs_serialize_uint8(uint8 input) internal pure returns (bytes memory) {{ + return abi.encodePacked(input); +}} +function bcs_deserialize_offset_uint8(uint256 pos, bytes memory input) internal pure returns (uint256, uint8) {{ + require(pos < input.length, "Position out of bound"); + uint8 value = uint8(input[pos]); + return (pos + 1, value); +}}"# + )?; + } + U16 => { + writeln!( + out, + r#" +function bcs_serialize_uint16(uint16 input) internal pure returns (bytes memory) {{ + bytes memory result = new bytes(2); + uint16 value = input; + result[0] = bytes1(uint8(value)); + value = value >> 8; + result[1] = bytes1(uint8(value)); + return result; +}} +function bcs_deserialize_offset_uint16(uint256 pos, bytes memory input) internal pure returns (uint256, uint16) {{ + require(pos + 1 < input.length, "Position out of bound"); + uint16 value = uint8(input[pos+1]); + value = value << 8; + value += uint8(input[pos]); + return (pos + 2, value); +}}"# + )?; + } + U32 => { + writeln!( + out, + r#" +function bcs_serialize_uint32(uint32 input) internal pure returns (bytes memory) {{ + bytes memory result = new bytes(4); + uint32 value = input; + result[0] = bytes1(uint8(value)); + for (uint i=1; i<4; i++) {{ + value = value >> 8; + result[i] = bytes1(uint8(value)); + }} + return result; +}} +function bcs_deserialize_offset_uint32(uint256 pos, bytes memory input) internal pure returns (uint256, uint32) {{ + require(pos + 3 < input.length, "Position out of bound"); + uint32 value = uint8(input[pos + 3]); + for (uint256 i=0; i<3; i++) {{ + value = value << 8; + value += uint8(input[pos + 2 - i]); + }} + return (pos + 4, value); +}}"# + )?; + } + U64 => { + writeln!( + out, + r#" +function bcs_serialize_uint64(uint64 input) internal pure returns (bytes memory) {{ + bytes memory result = new bytes(8); + uint64 value = input; + result[0] = bytes1(uint8(value)); + for (uint i=1; i<8; i++) {{ + value = value >> 8; + result[i] = bytes1(uint8(value)); + }} + return result; +}} +function bcs_deserialize_offset_uint64(uint256 pos, bytes memory input) internal pure returns (uint256, uint64) {{ + require(pos + 7 < input.length, "Position out of bound"); + uint64 value = uint8(input[pos + 7]); + for (uint256 i=0; i<7; i++) {{ + value = value << 8; + value += uint8(input[pos + 6 - i]); + }} + return (pos + 8, value); +}}"# + )?; + } + U128 => { + writeln!( + out, + r#" +function bcs_serialize_uint128(uint128 input) internal pure returns (bytes memory) {{ + bytes memory result = new bytes(16); + uint128 value = input; + result[0] = bytes1(uint8(value)); + for (uint i=1; i<16; i++) {{ + value = value >> 8; + result[i] = bytes1(uint8(value)); + }} + return result; +}} +function bcs_deserialize_offset_uint128(uint256 pos, bytes memory input) internal pure returns (uint256, uint128) {{ + require(pos + 15 < input.length, "Position out of bound"); + uint128 value = uint8(input[pos + 15]); + for (uint256 i=0; i<15; i++) {{ + value = value << 8; + value += uint8(input[pos + 14 - i]); + }} + return (pos + 16, value); +}}"# + )?; + } + Char => { + writeln!( + out, + r#" +function bcs_serialize_bytes1(bytes1 input) internal pure returns (bytes memory) {{ + bytes memory result = abi.encodePacked(input); + return result; +}} +function bcs_deserialize_offset_bytes1(uint256 pos, bytes memory input) internal pure returns (uint256, bytes1) {{ + bytes1 result = bytes1(input[pos]); + return (pos + 1, result); +}}"# + )?; + } + Str => { + writeln!( + out, + r#" +function bcs_serialize_string(string memory input) internal pure returns (bytes memory) {{ + bytes memory input_bytes = bytes(input); + uint256 number_bytes = input_bytes.length; + uint256 number_char = 0; + uint256 pos = 0; + while (true) {{ + if (uint8(input_bytes[pos]) < 128) {{ + number_char += 1; + }} + pos += 1; + if (pos == number_bytes) {{ + break; + }} + }} + bytes memory result_len = bcs_serialize_len(number_char); + return abi.encodePacked(result_len, input); +}} +function bcs_deserialize_offset_string(uint256 pos, bytes memory input) internal pure returns (uint256, string memory) {{ + uint256 len; + uint256 new_pos; + (new_pos, len) = bcs_deserialize_offset_len(pos, input); + uint256 shift = 0; + for (uint256 i=0; i { + writeln!( + out, + r#" +function bcs_serialize_bytes(bytes memory input) internal pure returns (bytes memory) {{ + uint256 len = input.length; + bytes memory result = bcs_serialize_len(len); + return abi.encodePacked(result, input); +}} +function bcs_deserialize_offset_bytes(uint256 pos, bytes memory input) internal pure returns (uint256, bytes memory) {{ + uint256 new_pos; + uint256 len; + (new_pos, len) = bcs_deserialize_offset_len(pos, input); + bytes memory result = new bytes(len); + for (uint256 u=0; u), + /// A simple solidity enum + SimpleEnum { name: String, names: Vec }, + /// A solidity struct. Used also to encapsulates Map and Tuple + Struct { + name: String, + formats: Vec>, + }, + /// An option encapsulated as a solidity struct. + Option(Box), + /// A Tuplearray encapsulated as a solidity struct. + TupleArray { format: Box, size: usize }, + /// A complex enum encapsulated as a solidity struct. + Enum { + name: String, + formats: Vec>>, + }, +} + +impl SolFormat { + pub fn code_name(&self) -> String { + use SolFormat::*; + if let Seq(format) = self { + return format!("{}[]", format.code_name()); + } + self.key_name() + } + + pub fn key_name(&self) -> String { + use SolFormat::*; + match self { + Primitive(primitive) => primitive.name(), + TypeName(name) => name.to_string(), + Option(format) => format!("opt_{}", format.key_name()), + Seq(format) => format!("seq_{}", format.key_name()), + TupleArray { format, size } => format!("tuplearray{}_{}", size, format.key_name()), + Struct { name, formats: _ } => name.to_string(), + SimpleEnum { name, names: _ } => name.to_string(), + Enum { name, formats: _ } => name.to_string(), + } + } + + pub fn output( + &self, + out: &mut IndentedWriter, + sol_registry: &SolRegistry, + ) -> Result<()> { + use SolFormat::*; + match self { + Primitive(primitive) => primitive.output(out)?, + TypeName(_) => { + // by definition for TypeName the code already exists + } + Option(format) => { + let key_name = format.key_name(); + let code_name = format.code_name(); + let full_name = format!("opt_{}", key_name); + let data_location = sol_registry.data_location(format); + writeln!( + out, + r#" +struct {full_name} {{ + bool has_value; + {code_name} value; +}} +function bcs_serialize_{full_name}({full_name} memory input) internal pure returns (bytes memory) {{ + bool has_value = input.has_value; + bytes memory block1 = bcs_serialize_bool(has_value); + if (has_value) {{ + bytes memory block2 = bcs_serialize_{key_name}(input.value); + return abi.encodePacked(block1, block2); + }} else {{ + return block1; + }} +}} +function bcs_deserialize_offset_{full_name}(uint256 pos, bytes memory input) internal pure returns (uint256, {full_name} memory) {{ + uint256 new_pos; + bool has_value; + (new_pos, has_value) = bcs_deserialize_offset_bool(pos, input); + {code_name}{data_location} value; + if (has_value) {{ + (new_pos, value) = bcs_deserialize_offset_{key_name}(new_pos, input); + }} + return (new_pos, {full_name}(true, value)); +}}"# + )?; + output_generic_bcs_deserialize(out, &full_name, &full_name, true)?; + } + Seq(format) => { + let inner_key_name = format.key_name(); + let inner_code_name = format.code_name(); + let code_name = format!("{}[]", format.code_name()); + let key_name = format!("seq_{}", format.key_name()); + let data_location = sol_registry.data_location(format); + writeln!( + out, + r#" +function bcs_serialize_{key_name}({code_name} memory input) internal pure returns (bytes memory) {{ + uint256 len = input.length; + bytes memory result = bcs_serialize_len(len); + for (uint256 i=0; i { + let inner_key_name = format.key_name(); + let inner_code_name = format.code_name(); + let struct_name = format!("tuplearray{}_{}", size, inner_key_name); + writeln!( + out, + r#" +struct {struct_name} {{ + {inner_code_name}[] values; +}} +function bcs_serialize_{struct_name}({struct_name} memory input) internal pure returns (bytes memory) {{ + bytes memory result; + for (uint i=0; i<{size}; i++) {{ + result = abi.encodePacked(result, bcs_serialize_{inner_key_name}(input.values[i])); + }} + return result; +}} +function bcs_deserialize_offset_{struct_name}(uint256 pos, bytes memory input) internal pure returns (uint256, {struct_name} memory) {{ + uint256 new_pos = pos; + {inner_code_name} value; + {inner_code_name}[] memory values; + values = new {inner_code_name}[]({size}); + for (uint i=0; i<{size}; i++) {{ + (new_pos, value) = bcs_deserialize_offset_{inner_key_name}(new_pos, input); + values[i] = value; + }} + return (new_pos, {struct_name}(values)); +}}"# + )?; + output_generic_bcs_deserialize(out, &struct_name, &struct_name, true)?; + } + Struct { name, formats } => { + writeln!(out, "struct {name} {{")?; + for named_format in formats { + writeln!( + out, + " {} {};", + named_format.value.code_name(), + safe_variable(&named_format.name) + )?; + } + writeln!(out, "}}")?; + writeln!(out, "function bcs_serialize_{name}({name} memory input) internal pure returns (bytes memory) {{")?; + writeln!( + out, + " bytes memory result = bcs_serialize_{}(input.{});", + &formats[0].value.key_name(), + safe_variable(&formats[0].name) + )?; + for named_format in &formats[1..] { + let key_name = named_format.value.key_name(); + let safe_name = safe_variable(&named_format.name); + writeln!(out, " result = abi.encodePacked(result, bcs_serialize_{key_name}(input.{safe_name}));")?; + } + writeln!(out, " return result;")?; + writeln!(out, "}}")?; + writeln!(out, "function bcs_deserialize_offset_{name}(uint256 pos, bytes memory input) internal pure returns (uint256, {name} memory) {{")?; + writeln!(out, " uint256 new_pos = pos;")?; + for named_format in formats { + let data_location = sol_registry.data_location(&named_format.value); + let code_name = named_format.value.code_name(); + let key_name = named_format.value.key_name(); + let safe_name = safe_variable(&named_format.name); + writeln!(out, " {code_name}{data_location} {safe_name};")?; + writeln!(out, " (new_pos, {safe_name}) = bcs_deserialize_offset_{key_name}(new_pos, input);")?; + } + writeln!( + out, + " return (new_pos, {name}({}));", + formats + .iter() + .map(|named_format| safe_variable(&named_format.name)) + .collect::>() + .join(", ") + )?; + writeln!(out, "}}")?; + output_generic_bcs_deserialize(out, name, name, true)?; + } + SimpleEnum { name, names } => { + let names_join = names.join(", "); + let number_names = names.len(); + writeln!( + out, + r#" +enum {name} {{ {names_join} }} +function bcs_serialize_{name}({name} input) internal pure returns (bytes memory) {{ + return abi.encodePacked(input); +}} +function bcs_deserialize_offset_{name}(uint256 pos, bytes memory input) internal pure returns (uint256, {name}) {{ + uint8 choice = uint8(input[pos]);"# + )?; + for (idx, name_choice) in names.iter().enumerate() { + writeln!( + out, + r#" + if (choice == {idx}) {{ + return (pos + 1, {name}.{name_choice}); + }}"# + )?; + } + writeln!( + out, + r#" + require(choice < {number_names}); +}}"# + )?; + output_generic_bcs_deserialize(out, name, name, false)?; + } + Enum { name, formats } => { + writeln!(out, "struct {name} {{")?; + writeln!(out, " uint8 choice;")?; + for (idx, named_format) in formats.iter().enumerate() { + let name = named_format.name.clone(); + writeln!(out, " // choice={idx} corresponds to {name}")?; + if let Some(format) = &named_format.value { + let code_name = format.code_name(); + let snake_name = named_format.name.to_snake_case(); + writeln!(out, " {code_name} {snake_name};")?; + } + } + writeln!(out, "}}")?; + writeln!(out, "function bcs_serialize_{name}({name} memory input) internal pure returns (bytes memory) {{")?; + writeln!( + out, + " bytes memory result = abi.encodePacked(input.choice);" + )?; + for (idx, named_format) in formats.iter().enumerate() { + if let Some(format) = &named_format.value { + let key_name = format.key_name(); + let snake_name = named_format.name.to_snake_case(); + writeln!(out, " if (input.choice == {idx}) {{")?; + writeln!(out, " return abi.encodePacked(result, bcs_serialize_{key_name}(input.{snake_name}));")?; + writeln!(out, " }}")?; + } + } + writeln!(out, " return result;")?; + writeln!(out, "}}")?; + writeln!(out, "function bcs_deserialize_offset_{name}(uint256 pos, bytes memory input) internal pure returns (uint256, {name} memory) {{")?; + writeln!(out, " uint256 new_pos;")?; + writeln!(out, " uint8 choice;")?; + writeln!( + out, + " (new_pos, choice) = bcs_deserialize_offset_uint8(pos, input);" + )?; + let mut entries = Vec::new(); + for (idx, named_format) in formats.iter().enumerate() { + if let Some(format) = &named_format.value { + let data_location = sol_registry.data_location(format); + let snake_name = named_format.name.to_snake_case(); + let code_name = format.code_name(); + let key_name = format.key_name(); + writeln!(out, " {code_name}{data_location} {snake_name};")?; + writeln!(out, " if (choice == {idx}) {{")?; + writeln!(out, " (new_pos, {snake_name}) = bcs_deserialize_offset_{key_name}(new_pos, input);")?; + writeln!(out, " }}")?; + entries.push(snake_name); + } + } + writeln!( + out, + " return (new_pos, {name}(choice, {}));", + entries.join(", ") + )?; + writeln!(out, "}}")?; + output_generic_bcs_deserialize(out, name, name, true)?; + } + } + Ok(()) + } + + fn get_dependency(&self) -> Vec { + use SolFormat::*; + match self { + Primitive(_) => vec![], + TypeName(name) => vec![name.to_string()], + Seq(format) => vec![format.key_name()], + SimpleEnum { name: _, names: _ } => vec![], + Struct { name: _, formats } => formats + .iter() + .map(|format| format.value.key_name()) + .collect(), + Option(format) => vec![format.key_name()], + TupleArray { format, size: _ } => vec![format.key_name()], + Enum { name: _, formats } => formats + .iter() + .flat_map(|format| match &format.value { + None => vec![], + Some(format) => vec![format.key_name()], + }) + .collect(), + } + } +} + +#[derive(Default)] +struct SolRegistry { + names: HashMap, +} + +impl SolRegistry { + fn insert(&mut self, sol_format: SolFormat) { + let key_name = sol_format.key_name(); + // If we insert the signed version, then we also need the unsigned one internally + match sol_format { + SolFormat::Primitive(Primitive::I8) => { + self.names.insert(key_name, sol_format); + self.names + .insert("uint8".to_string(), SolFormat::Primitive(Primitive::U8)); + } + SolFormat::Primitive(Primitive::I16) => { + self.names.insert(key_name, sol_format); + self.names + .insert("uint16".to_string(), SolFormat::Primitive(Primitive::U16)); + } + SolFormat::Primitive(Primitive::I32) => { + self.names.insert(key_name, sol_format); + self.names + .insert("uint32".to_string(), SolFormat::Primitive(Primitive::U32)); + } + SolFormat::Primitive(Primitive::I64) => { + self.names.insert(key_name, sol_format); + self.names + .insert("uint64".to_string(), SolFormat::Primitive(Primitive::U64)); + } + SolFormat::Primitive(Primitive::I128) => { + self.names.insert(key_name, sol_format); + self.names + .insert("uint128".to_string(), SolFormat::Primitive(Primitive::U128)); + } + SolFormat::TypeName(_) => { + // Typename entries do not need to be inserted. + } + _ => { + self.names.insert(key_name, sol_format); + } + } + } + + fn has_circular_dependency(&self) -> bool { + for start_key in self.names.keys() { + let mut level = HashSet::::new(); + level.insert(start_key.to_string()); + let mut total_dependency = level.clone(); + loop { + let mut new_level = HashSet::new(); + for key in level { + for depend in self.names.get(&key).unwrap().get_dependency() { + if depend == *start_key { + return true; + } + if !total_dependency.contains(&depend) { + total_dependency.insert(depend.clone()); + new_level.insert(depend); + } + } + } + if new_level.is_empty() { + break; + } + level = new_level; + } + } + false + } + + fn parse_format(&mut self, format: Format) -> SolFormat { + use Format::*; + let sol_format = match format { + Variable(_) => panic!("variable is not supported in solidity"), + TypeName(name) => SolFormat::TypeName(name), + Unit => SolFormat::Primitive(Primitive::Unit), + Bool => SolFormat::Primitive(Primitive::Bool), + I8 => SolFormat::Primitive(Primitive::I8), + I16 => SolFormat::Primitive(Primitive::I16), + I32 => SolFormat::Primitive(Primitive::I32), + I64 => SolFormat::Primitive(Primitive::I64), + I128 => SolFormat::Primitive(Primitive::I128), + U8 => SolFormat::Primitive(Primitive::U8), + U16 => SolFormat::Primitive(Primitive::U16), + U32 => SolFormat::Primitive(Primitive::U32), + U64 => SolFormat::Primitive(Primitive::U64), + U128 => SolFormat::Primitive(Primitive::U128), + F32 => panic!("floating point is not supported in solidity"), + F64 => panic!("floating point is not supported in solidity"), + Char => SolFormat::Primitive(Primitive::Char), + Str => SolFormat::Primitive(Primitive::Str), + Bytes => SolFormat::Primitive(Primitive::Bytes), + Option(format) => { + let format = self.parse_format(*format); + SolFormat::Option(Box::new(format)) + } + Seq(format) => { + let format = self.parse_format(*format); + SolFormat::Seq(Box::new(format)) + } + Map { key, value } => { + let key = self.parse_format(*key); + let value = self.parse_format(*value); + let name = format!("key_values_{}_{}", key.key_name(), value.key_name()); + let formats = vec![ + Named { + name: "key".into(), + value: key, + }, + Named { + name: "value".into(), + value, + }, + ]; + let sol_format = SolFormat::Struct { name, formats }; + self.insert(sol_format.clone()); + SolFormat::Seq(Box::new(sol_format)) + } + Tuple(formats) => { + let formats = formats + .into_iter() + .map(|format| self.parse_format(format)) + .collect::>(); + let name = format!( + "tuple_{}", + formats + .iter() + .map(|format| format.key_name()) + .collect::>() + .join("_") + ); + let formats = formats + .into_iter() + .enumerate() + .map(|(idx, format)| Named { + name: format!("entry{idx}"), + value: format, + }) + .collect(); + SolFormat::Struct { name, formats } + } + TupleArray { content, size } => SolFormat::TupleArray { + format: Box::new(self.parse_format(*content)), + size, + }, + }; + self.insert(sol_format.clone()); + sol_format + } + + fn parse_struct_format(&mut self, name: String, formats: Vec>) -> SolFormat { + let formats = formats + .into_iter() + .map(|named_format| Named { + name: named_format.name, + value: self.parse_format(named_format.value), + }) + .collect(); + let sol_format = SolFormat::Struct { name, formats }; + self.insert(sol_format.clone()); + sol_format + } + + fn parse_container_format(&mut self, container_format: Named) { + use ContainerFormat::*; + let name = container_format.name; + let sol_format = match container_format.value { + UnitStruct => panic!("UnitStruct is not supported in solidity"), + NewTypeStruct(format) => { + let format = Named { + name: "value".to_string(), + value: *format, + }; + let formats = vec![format]; + self.parse_struct_format(name, formats) + } + TupleStruct(formats) => { + assert!( + !formats.is_empty(), + "The TupleStruct should be non-trivial in solidity" + ); + let formats = formats + .into_iter() + .enumerate() + .map(|(idx, value)| Named { + name: format!("entry{idx}"), + value, + }) + .collect(); + self.parse_struct_format(name, formats) + } + Struct(formats) => { + assert!( + !formats.is_empty(), + "The struct should be non-trivial in solidity" + ); + self.parse_struct_format(name, formats) + } + Enum(map) => { + assert!( + !map.is_empty(), + "The enum should be non-trivial in solidity" + ); + assert!(map.len() < 256, "The enum should have at most 256 entries"); + let is_trivial = map + .iter() + .all(|(_, v)| matches!(v.value, VariantFormat::Unit)); + if is_trivial { + let names = map + .into_values() + .map(|named_format| named_format.name) + .collect(); + SolFormat::SimpleEnum { name, names } + } else { + let choice_sol_format = SolFormat::Primitive(Primitive::U8); + self.insert(choice_sol_format); + let mut formats = Vec::new(); + for (_key, value) in map { + use VariantFormat::*; + let name_red = value.name; + let concat_name = format!("{}_{}", name, name_red); + let entry = match value.value { + VariantFormat::Unit => None, + NewType(format) => Some(self.parse_format(*format)), + Tuple(formats) => { + let formats = formats + .into_iter() + .enumerate() + .map(|(idx, value)| Named { + name: format!("entry{idx}"), + value, + }) + .collect::>(); + Some(self.parse_struct_format(concat_name, formats)) + } + Struct(formats) => Some(self.parse_struct_format(concat_name, formats)), + Variable(_) => panic!("Variable is not supported for solidity"), + }; + let format = Named { + name: name_red, + value: entry, + }; + formats.push(format); + } + SolFormat::Enum { name, formats } + } + } + }; + self.insert(sol_format); + } + + fn need_memory(&self, sol_format: &SolFormat) -> bool { + use SolFormat::*; + match sol_format { + Primitive(primitive) => { + use crate::solidity::Primitive; + matches!( + primitive, + Primitive::Unit | Primitive::Bytes | Primitive::Str + ) + } + TypeName(name) => { + let mesg = format!("to find a matching entry for name={name}"); + let sol_format = self.names.get(name).expect(&mesg); + self.need_memory(sol_format) + } + Option(_) => true, + Seq(_) => true, + TupleArray { format: _, size: _ } => true, + Struct { + name: _, + formats: _, + } => true, + SimpleEnum { name: _, names: _ } => false, + Enum { + name: _, + formats: _, + } => true, + } + } + + fn data_location(&self, sol_format: &SolFormat) -> String { + get_data_location(self.need_memory(sol_format)) + } +} + +impl<'a> CodeGenerator<'a> { + /// Create a solidity code generator for the given config. + pub fn new(config: &'a CodeGeneratorConfig) -> Self { + if config.c_style_enums { + panic!("Solidity does not support generating c-style enums"); + } + Self { config } + } + + pub fn output( + &self, + out: &mut dyn Write, + registry: &Registry, + ) -> std::result::Result<(), Box> { + let mut emitter = SolEmitter { + out: IndentedWriter::new(out, IndentConfig::Space(4)), + generator: self, + }; + + emitter.output_preamble()?; + emitter.output_open_library()?; + + let mut sol_registry = SolRegistry::default(); + for (key, container_format) in registry { + let container_format = Named { + name: key.to_string(), + value: container_format.clone(), + }; + sol_registry.parse_container_format(container_format); + } + if sol_registry.has_circular_dependency() { + panic!("solidity does not allow for circular dependencies"); + } + for sol_format in sol_registry.names.values() { + sol_format.output(&mut emitter.out, &sol_registry)?; + } + + emitter.output_close_library()?; + writeln!(emitter.out)?; + Ok(()) + } +} + +impl<'a, T> SolEmitter<'a, T> +where + T: std::io::Write, +{ + fn output_preamble(&mut self) -> Result<()> { + writeln!( + self.out, + r#" +/// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; +function bcs_serialize_len(uint256 x) pure returns (bytes memory) {{ + uint256 power = 128; + bytes memory result; + bytes1 entry; + while (true) {{ + if (x < 128) {{ + entry = bytes1(uint8(x)); + result = abi.encodePacked(result, entry); + return result; + }} else {{ + uint256 xb = x >> 7; + uint256 remainder = x - (xb << 7); + require(remainder < 128); + entry = bytes1(uint8(remainder) + 128); + result = abi.encodePacked(result, entry); + x = xb; + }} + }} +}} +function bcs_deserialize_offset_len(uint256 pos, bytes memory input) pure returns (uint256, uint256) {{ + uint256 idx = 0; + while (true) {{ + if (uint8(input[pos + idx]) < 128) {{ + uint256 result = 0; + uint256 power = 1; + for (uint256 u=0; u Result<()> { + writeln!( + self.out, + "\ncontract {} {{", + self.generator.config.module_name + )?; + self.out.indent(); + Ok(()) + } + + fn output_close_library(&mut self) -> Result<()> { + self.out.unindent(); + writeln!( + self.out, + "\n}} // end of contract {}", + self.generator.config.module_name + )?; + Ok(()) + } +} + +/// Installer for generated source files in solidity +pub struct Installer { + install_dir: PathBuf, +} + +impl Installer { + pub fn new(install_dir: PathBuf) -> Self { + Installer { install_dir } + } + + fn create_header_file(&self, name: &str) -> Result { + let dir_path = &self.install_dir; + std::fs::create_dir_all(dir_path)?; + std::fs::File::create(dir_path.join(name.to_string() + ".sol")) + } + + fn runtime_installation_message(name: &str) { + eprintln!("Not installing sources for published crate {}", name); + } +} + +impl crate::SourceInstaller for Installer { + type Error = Box; + + fn install_module( + &self, + config: &crate::CodeGeneratorConfig, + registry: &Registry, + ) -> std::result::Result<(), Self::Error> { + let mut file = self.create_header_file(&config.module_name)?; + let generator = CodeGenerator::new(config); + generator.output(&mut file, registry) + } + + fn install_serde_runtime(&self) -> std::result::Result<(), Self::Error> { + Self::runtime_installation_message("serde"); + Ok(()) + } + + fn install_bincode_runtime(&self) -> std::result::Result<(), Self::Error> { + Self::runtime_installation_message("bincode"); + Ok(()) + } + + fn install_bcs_runtime(&self) -> std::result::Result<(), Self::Error> { + Self::runtime_installation_message("bcs"); + Ok(()) + } +} diff --git a/serde-generate/tests/lib.rs b/serde-generate/tests/lib.rs index 00d2e7908..37b872121 100644 --- a/serde-generate/tests/lib.rs +++ b/serde-generate/tests/lib.rs @@ -31,6 +31,10 @@ mod python_runtime; mod rust_generation; #[cfg(feature = "rust")] mod rust_runtime; +#[cfg(feature = "solidity")] +mod solidity_generation; +#[cfg(feature = "solidity")] +mod solidity_runtime; #[cfg(feature = "swift")] mod swift_generation; #[cfg(feature = "swift")] diff --git a/serde-generate/tests/solidity_generation.rs b/serde-generate/tests/solidity_generation.rs new file mode 100644 index 000000000..33c2adea0 --- /dev/null +++ b/serde-generate/tests/solidity_generation.rs @@ -0,0 +1,152 @@ +// Copyright (c) Facebook, Inc. and its affiliates +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use crate::test_utils::{NewTypeStruct, OtherTypes, Struct, TupleStruct}; +use revm::primitives::Bytes; +use serde::{ + de::DeserializeOwned, + {Deserialize, Serialize}, +}; +use serde_generate::{solidity, CodeGeneratorConfig}; +use serde_reflection::Samples; +use serde_reflection::{Registry, Tracer, TracerConfig}; +use std::path::Path; +use std::{ + collections::BTreeMap, + fs::File, + io::Write, + process::{Command, Stdio}, +}; +use tempfile::tempdir; + +#[derive(Debug, Serialize, Deserialize, PartialEq)] +pub enum SerdeData { + PrimitiveTypes(PrimitiveTypes), + OtherTypes(OtherTypes), + NewTypeVariant(String), + TupleVariant(u32, u64), + StructVariant { + f0: NewTypeStruct, + f1: TupleStruct, + f2: Struct, + }, + TupleArray([u32; 3]), + ComplexMap(BTreeMap<([u32; 2], [u8; 4]), ()>), +} + +#[derive(Debug, Serialize, Deserialize, PartialEq)] +pub struct PrimitiveTypes { + f_bool: bool, + f_u8: u8, + f_u16: u16, + f_u32: u32, + f_u64: u64, + f_u128: u128, + f_i8: i8, + f_i16: i16, + f_i32: i32, + f_i64: i64, + f_i128: i128, + f_char: Option, +} + +pub fn get_solidity_registry() -> serde_reflection::Result { + let mut tracer = Tracer::new(TracerConfig::default()); + let samples = Samples::new(); + tracer.trace_type::(&samples)?; + tracer.trace_type::(&samples)?; + tracer.registry() +} + +pub fn write_compilation_json(path: &Path, file_name: &str) { + let mut source = File::create(path).unwrap(); + writeln!( + source, + r#" +{{ + "language": "Solidity", + "sources": {{ + "{file_name}": {{ + "urls": ["./{file_name}"] + }} + }}, + "settings": {{ + "viaIR": true, + "outputSelection": {{ + "*": {{ + "*": ["evm.bytecode"] + }} + }} + }} +}} +"# + ) + .unwrap(); +} + +pub fn get_bytecode(path: &Path, file_name: &str, contract_name: &str) -> anyhow::Result { + let config_path = path.join("config.json"); + write_compilation_json(&config_path, file_name); + let config_file = File::open(config_path)?; + + let output_path = path.join("result.json"); + let output_file = File::create(output_path.clone())?; + + let status = Command::new("solc") + .current_dir(path) + .arg("--standard-json") + .stdin(Stdio::from(config_file)) + .stdout(Stdio::from(output_file)) + .status()?; + assert!(status.success()); + + let contents = std::fs::read_to_string(output_path)?; + let json_data: serde_json::Value = serde_json::from_str(&contents)?; + println!("json_data={}", json_data); + let contracts = json_data + .get("contracts") + .ok_or(anyhow::anyhow!("failed to get contract"))?; + let file_name_contract = contracts + .get(file_name) + .ok_or(anyhow::anyhow!("failed to get {file_name}"))?; + let test_data = file_name_contract + .get(contract_name) + .ok_or(anyhow::anyhow!("failed to get test"))?; + let evm_data = test_data + .get("evm") + .ok_or(anyhow::anyhow!("failed to get evm"))?; + let bytecode = evm_data + .get("bytecode") + .ok_or(anyhow::anyhow!("failed to get bytecode"))?; + let object = bytecode + .get("object") + .ok_or(anyhow::anyhow!("failed to get object"))?; + let object = object.to_string(); + let object = object.trim_matches(|c| c == '"').to_string(); + let object = hex::decode(&object)?; + Ok(Bytes::copy_from_slice(&object)) +} + +pub fn get_registry_from_type() -> Registry { + let mut tracer = Tracer::new(TracerConfig::default()); + let samples = Samples::new(); + tracer.trace_type::(&samples).unwrap(); + tracer.registry().unwrap() +} + +#[test] +fn test_solidity_compilation() { + let name = "test".to_string(); + let config = CodeGeneratorConfig::new(name); + let registry = get_solidity_registry().unwrap(); + let dir = tempdir().unwrap(); + let path = dir.path(); + let test_path = path.join("test.sol"); + { + let mut test_file = File::create(&test_path).unwrap(); + let generator = solidity::CodeGenerator::new(&config); + generator.output(&mut test_file, ®istry).unwrap(); + } + + get_bytecode(path, "test.sol", "test").unwrap(); +} diff --git a/serde-generate/tests/solidity_runtime.rs b/serde-generate/tests/solidity_runtime.rs new file mode 100644 index 000000000..4323ccee6 --- /dev/null +++ b/serde-generate/tests/solidity_runtime.rs @@ -0,0 +1,351 @@ +use crate::solidity_generation::{get_bytecode, get_registry_from_type}; +use alloy_sol_types::sol; +use alloy_sol_types::SolCall as _; +use revm::db::InMemoryDB; +use revm::{ + primitives::{Bytes, ExecutionResult, Output, TxKind}, + Evm, +}; +use serde::{ + de::DeserializeOwned, + {Deserialize, Serialize}, +}; +use serde_generate::{solidity, CodeGeneratorConfig}; +use std::{fmt::Display, fs::File, io::Write}; +use tempfile::tempdir; + +fn test_contract(bytecode: Bytes, encoded_args: Bytes) { + let mut database = InMemoryDB::default(); + let contract_address = { + let mut evm: Evm<'_, (), _> = Evm::builder() + .with_ref_db(&mut database) + .modify_tx_env(|tx| { + tx.clear(); + tx.transact_to = TxKind::Create; + tx.data = bytecode; + }) + .build(); + + let result: ExecutionResult = evm.transact_commit().unwrap(); + + let ExecutionResult::Success { output, .. } = result else { + panic!("The TxKind::Create execution failed"); + }; + let Output::Create(_, Some(contract_address)) = output else { + panic!("Failure to create the contract"); + }; + contract_address + }; + + let mut evm: Evm<'_, (), _> = Evm::builder() + .with_ref_db(&mut database) + .modify_tx_env(|tx| { + tx.transact_to = TxKind::Call(contract_address); + tx.data = encoded_args; + }) + .build(); + + let result: ExecutionResult = evm.transact_commit().unwrap(); + + let ExecutionResult::Success { .. } = result else { + panic!("The TxKind::Call execution failed"); + }; +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +pub struct TestVec { + pub vec: Vec, +} + +fn test_vector_serialization( + t: TestVec, +) -> anyhow::Result<()> { + let registry = get_registry_from_type::>(); + let dir = tempdir().unwrap(); + let path = dir.path(); + + // The generated code + let test_code_path = path.join("test_code.sol"); + { + let mut test_code_file = File::create(&test_code_path)?; + let name = "ExampleCodeBase".to_string(); + let config = CodeGeneratorConfig::new(name); + let generator = solidity::CodeGenerator::new(&config); + generator.output(&mut test_code_file, ®istry).unwrap(); + + let len = t.vec.len(); + let first_val = &t.vec[0]; + writeln!( + test_code_file, + r#" +contract ExampleCode is ExampleCodeBase {{ + + function test_deserialization(bytes calldata input) external {{ + TestVec memory t = bcs_deserialize_TestVec(input); + require(t.vec.length == {len}, "The length is incorrect"); + require(t.vec[0] == {first_val}, "incorrect value"); + + bytes memory input_rev = bcs_serialize_TestVec(t); + require(input.length == input_rev.length); + for (uint256 i=0; i anyhow::Result<()> { + let registry = get_registry_from_type::(); + let dir = tempdir().unwrap(); + let path = dir.path(); + + // The generated code + let test_code_path = path.join("test_code.sol"); + { + let mut test_code_file = File::create(&test_code_path)?; + let name = "ExampleCodeBase".to_string(); + let config = CodeGeneratorConfig::new(name); + let generator = solidity::CodeGenerator::new(&config); + generator.output(&mut test_code_file, ®istry).unwrap(); + + writeln!( + test_code_file, + r#" +contract ExampleCode is ExampleCodeBase {{ + + function test_deserialization(bytes calldata input) external {{ + require(input.length == 1); + SimpleEnumTestType t = bcs_deserialize_SimpleEnumTestType(input); + require(t == SimpleEnumTestType.ChoiceB); + + bytes memory input_rev = bcs_serialize_SimpleEnumTestType(t); + require(input_rev.length == 1); + require(input[0] == input_rev[0]); + }} + +}} +"# + )?; + } + + // Compiling the code and reading it. + let bytecode = get_bytecode(path, "test_code.sol", "ExampleCode")?; + + // Building the test entry + let t = SimpleEnumTestType::ChoiceB; + let expected_input = bcs::to_bytes(&t).unwrap(); + + // Building the input to the smart contract + sol! { + function test_deserialization(bytes calldata input); + } + let input = Bytes::copy_from_slice(&expected_input); + let fct_args = test_deserializationCall { input }; + let fct_args = fct_args.abi_encode().into(); + + test_contract(bytecode, fct_args); + Ok(()) +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +pub struct StructBoolString { + a: bool, + b: String, +} + +#[test] +fn test_struct_bool_string() -> anyhow::Result<()> { + let registry = get_registry_from_type::(); + let dir = tempdir().unwrap(); + let path = dir.path(); + + // The generated code + let test_code_path = path.join("test_code.sol"); + { + let mut test_code_file = File::create(&test_code_path)?; + let name = "ExampleCodeBase".to_string(); + let config = CodeGeneratorConfig::new(name); + let generator = solidity::CodeGenerator::new(&config); + generator.output(&mut test_code_file, ®istry).unwrap(); + + writeln!( + test_code_file, + r#" +contract ExampleCode is ExampleCodeBase {{ + + function test_deserialization(bytes calldata input) external {{ + StructBoolString memory t = bcs_deserialize_StructBoolString(input); + + bytes memory input_rev = bcs_serialize_StructBoolString(t); + require(input.length == input_rev.length); + for (uint256 i=0; i anyhow::Result<()> { + let registry = get_registry_from_type::(); + let dir = tempdir().unwrap(); + let path = dir.path(); + + // The generated code + let test_code_path = path.join("test_code.sol"); + { + let mut test_code_file = File::create(&test_code_path)?; + let name = "ExampleCodeBase".to_string(); + let config = CodeGeneratorConfig::new(name); + let generator = solidity::CodeGenerator::new(&config); + generator.output(&mut test_code_file, ®istry).unwrap(); + + writeln!( + test_code_file, + r#" +contract ExampleCode is ExampleCodeBase {{ + + function test_deserialization(bytes calldata input) external {{ + ComplexEnumTestType memory t = bcs_deserialize_ComplexEnumTestType(input); + + bytes memory input_rev = bcs_serialize_ComplexEnumTestType(t); + require(input.length == input_rev.length); + for (uint256 i=0; i