From d7d5b05bc6f8415d8e69d76a6259be93bbf111bc Mon Sep 17 00:00:00 2001 From: Jouzo <15011228+Jouzo@users.noreply.github.com> Date: Mon, 8 May 2023 07:28:02 +0100 Subject: [PATCH] EVM State Trie (#1973) --- lib/.cargo/config.toml | 2 +- lib/Cargo.lock | 1565 ++++++++++++++++- lib/Makefile.am | 8 +- lib/ain-cpp-imports/build.rs | 2 +- lib/ain-cpp-imports/src/lib.rs | 2 +- lib/ain-evm/Cargo.toml | 10 + lib/ain-evm/src/backend.rs | 320 ++++ lib/ain-evm/src/block.rs | 9 +- lib/ain-evm/src/evm.rs | 244 ++- lib/ain-evm/src/executor.rs | 28 +- lib/ain-evm/src/handler.rs | 114 +- lib/ain-evm/src/lib.rs | 1 + lib/ain-evm/src/receipt.rs | 2 +- lib/ain-evm/src/storage/data_handler.rs | 33 +- lib/ain-evm/src/storage/mod.rs | 12 +- lib/ain-evm/src/storage/traits.rs | 9 +- lib/ain-evm/src/traits.rs | 8 +- lib/ain-evm/src/transaction/bridge.rs | 13 + .../{transaction.rs => transaction/mod.rs} | 9 +- lib/ain-evm/src/tx_queue.rs | 143 +- lib/ain-grpc/build.rs | 2 +- lib/ain-grpc/src/block.rs | 23 +- lib/ain-grpc/src/codegen.rs | 12 +- lib/ain-grpc/src/impls.rs | 12 +- lib/ain-grpc/src/lib.rs | 4 +- lib/ain-grpc/src/rpc.rs | 268 +-- lib/ain-rs-exports/src/lib.rs | 29 +- lib/labs-grpc2/proto/eth.proto | 715 ++------ src/masternodes/rpc_accounts.cpp | 3 +- src/masternodes/rpc_evm.cpp | 69 + test/functional/feature_evm_rpc.py | 17 +- test/functional/feature_evm_smart_contract.py | 137 ++ test/functional/test_runner.py | 1 + 33 files changed, 2826 insertions(+), 1000 deletions(-) create mode 100644 lib/ain-evm/src/backend.rs create mode 100644 lib/ain-evm/src/transaction/bridge.rs rename lib/ain-evm/src/{transaction.rs => transaction/mod.rs} (97%) create mode 100755 test/functional/feature_evm_smart_contract.py diff --git a/lib/.cargo/config.toml b/lib/.cargo/config.toml index 14633573a6..1d00d50ea7 100644 --- a/lib/.cargo/config.toml +++ b/lib/.cargo/config.toml @@ -15,4 +15,4 @@ rustflags = [ rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", -] \ No newline at end of file +] diff --git a/lib/Cargo.lock b/lib/Cargo.lock index bbb7f14364..eeeacc4c30 100644 --- a/lib/Cargo.lock +++ b/lib/Cargo.lock @@ -2,13 +2,32 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "addr2line" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +dependencies = [ + "gimli 0.26.2", +] + [[package]] name = "addr2line" version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" dependencies = [ - "gimli", + "gimli 0.27.2", ] [[package]] @@ -35,6 +54,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" dependencies = [ "cfg-if", + "getrandom 0.2.9", "once_cell", "version_check", ] @@ -77,6 +97,7 @@ dependencies = [ "ethereum", "ethereum-types", "evm", + "hash-db 0.16.0", "hex", "hex-literal", "jsonrpsee-core", @@ -87,12 +108,17 @@ dependencies = [ "libsecp256k1", "log", "lru 0.10.0", + "once_cell", "primitive-types", "rand 0.8.5", "rlp", "serde", "sha3", + "sp-core", + "tempdir", "tokio", + "vsdb_core", + "vsdb_trie_db", ] [[package]] @@ -175,12 +201,24 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344" +[[package]] +name = "array-bytes" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52f63c5c1316a16a4b35eaac8b76a98248961a533f061684cb2a7cb0eafb6c6" + [[package]] name = "arrayref" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + [[package]] name = "arrayvec" version = "0.7.2" @@ -352,12 +390,12 @@ version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" dependencies = [ - "addr2line", + "addr2line 0.19.0", "cc", "cfg-if", "libc", "miniz_oxide 0.6.2", - "object", + "object 0.30.3", "rustc-demangle", ] @@ -373,6 +411,16 @@ version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" +[[package]] +name = "bcs" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bd3ffe8b19a604421a5d461d4a70346223e535903fbc3067138bddbebddcf77" +dependencies = [ + "serde", + "thiserror", +] + [[package]] name = "beef" version = "0.5.2" @@ -391,6 +439,26 @@ dependencies = [ "serde", ] +[[package]] +name = "bindgen" +version = "0.64.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4243e6031260db77ede97ad86c27e501d646a27ab57b59a574f725d98ab1fb4" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 1.0.109", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -409,19 +477,51 @@ dependencies = [ "wyz", ] +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.6", +] + +[[package]] +name = "blake2b_simd" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c2f0dc9a68c6317d884f97cc36cf5a3d20ba14ce404227df55e1af708ab04bc" +dependencies = [ + "arrayref", + "arrayvec 0.7.2", + "constant_time_eq", +] + [[package]] name = "block" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding", + "byte-tools", + "byteorder", + "generic-array 0.12.4", +] + [[package]] name = "block-buffer" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -430,7 +530,16 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array", + "generic-array 0.14.7", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", ] [[package]] @@ -448,6 +557,24 @@ dependencies = [ "log", ] +[[package]] +name = "bounded-collections" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3888522b497857eb606bf51695988dba7096941822c1bcf676e3a929a9ae7a0" +dependencies = [ + "log", + "parity-scale-codec", + "scale-info", + "serde", +] + +[[package]] +name = "bs58" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" + [[package]] name = "bstr" version = "1.4.0" @@ -479,6 +606,12 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + [[package]] name = "bytemuck" version = "1.13.1" @@ -497,6 +630,17 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + [[package]] name = "cairo-rs" version = "0.15.12" @@ -532,6 +676,9 @@ name = "cc" version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +dependencies = [ + "jobserver", +] [[package]] name = "cesu8" @@ -539,6 +686,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfb" version = "0.7.3" @@ -585,11 +741,22 @@ dependencies = [ "js-sys", "num-integer", "num-traits", - "time", + "time 0.1.45", "wasm-bindgen", "winapi", ] +[[package]] +name = "clang-sys" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clap" version = "2.34.0" @@ -681,6 +848,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "constant_time_eq" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13418e745008f7349ec7e449155f419a61b92b58a99cc3616942b926825ec76b" + [[package]] name = "convert_case" version = "0.4.0" @@ -728,6 +901,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cpp_demangle" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeaa953eaad386a53111e47172c2fedba671e5684c8dd601a5f474f4f118710f" +dependencies = [ + "cfg-if", +] + [[package]] name = "cpufeatures" version = "0.2.7" @@ -737,6 +919,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cranelift-entity" +version = "0.93.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f42ea692c7b450ad18b8c9889661505d51c09ec4380cf1c2d278dbb2da22cae1" +dependencies = [ + "serde", +] + [[package]] name = "crc32fast" version = "1.3.2" @@ -762,6 +953,19 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-epoch" +version = "0.9.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset 0.8.0", + "scopeguard", +] + [[package]] name = "crossbeam-utils" version = "0.8.15" @@ -824,7 +1028,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array", + "generic-array 0.14.7", "typenum", ] @@ -834,7 +1038,17 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" dependencies = [ - "generic-array", + "generic-array 0.14.7", + "subtle", +] + +[[package]] +name = "crypto-mac" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +dependencies = [ + "generic-array 0.14.7", "subtle", ] @@ -865,6 +1079,32 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "curve25519-dalek" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b85542f99a2dfa2a1b8e192662741c9859a846b296bef1c92ef9b58b5a216" +dependencies = [ + "byteorder", + "digest 0.8.1", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + [[package]] name = "cxx" version = "1.0.94" @@ -968,13 +1208,22 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array 0.12.4", +] + [[package]] name = "digest" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -985,6 +1234,7 @@ checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ "block-buffer 0.10.4", "crypto-common", + "subtle", ] [[package]] @@ -1288,6 +1538,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" +[[package]] +name = "downcast-rs" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" + [[package]] name = "dtoa" version = "0.4.8" @@ -1309,6 +1565,47 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +[[package]] +name = "dyn-clonable" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e9232f0e607a262ceb9bd5141a3dfb3e4db6994b31989bbfd845878cba59fd4" +dependencies = [ + "dyn-clonable-impl", + "dyn-clone", +] + +[[package]] +name = "dyn-clonable-impl" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "558e40ea573c374cf53507fd240b7ee2f5477df7cfebdb97323ec61c719399c5" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "dyn-clone" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30" + +[[package]] +name = "ed25519-zebra" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" +dependencies = [ + "curve25519-dalek 3.2.0", + "hashbrown 0.12.3", + "hex", + "rand_core 0.6.4", + "sha2 0.9.9", + "zeroize", +] + [[package]] name = "either" version = "1.8.1" @@ -1349,6 +1646,12 @@ dependencies = [ "termcolor", ] +[[package]] +name = "environmental" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48c92028aaa870e83d51c64e5d4e0b6981b360c522198c23959f219a4e1b15b" + [[package]] name = "erased-serde" version = "0.3.25" @@ -1402,7 +1705,7 @@ checksum = "6a89fb87a9e103f71b903b80b670200b54cc67a07578f070681f1fffb7396fb7" dependencies = [ "bytes", "ethereum-types", - "hash-db", + "hash-db 0.15.2", "hash256-std-hasher", "parity-scale-codec", "rlp", @@ -1503,7 +1806,7 @@ checksum = "16d9a9ea4c04632c16bc5c71a2fcc63d308481f7fc67eb1a1ce6315c44a426ae" dependencies = [ "execute-command-macro", "execute-command-tokens", - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -1541,6 +1844,18 @@ dependencies = [ "rand 0.8.5", ] +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + [[package]] name = "fastrand" version = "1.9.0" @@ -1565,7 +1880,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3cf3a800ff6e860c863ca6d4b16fd999db8b752819c1606884047b73e468535" dependencies = [ - "memoffset", + "memoffset 0.8.0", "rustc_version", ] @@ -1639,6 +1954,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs4" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cef5c93884e5cef757f63446122c2f420713c3e03f85540d09485b9415983b4a" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "fsevent-sys" version = "4.1.0" @@ -1648,6 +1973,12 @@ dependencies = [ "libc", ] +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + [[package]] name = "funty" version = "2.0.0" @@ -1704,6 +2035,7 @@ dependencies = [ "futures-core", "futures-task", "futures-util", + "num_cpus", ] [[package]] @@ -1849,6 +2181,15 @@ dependencies = [ "x11", ] +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -1881,6 +2222,16 @@ dependencies = [ "wasi 0.11.0+wasi-snapshot-preview1", ] +[[package]] +name = "gimli" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" +dependencies = [ + "fallible-iterator", + "stable_deref_trait", +] + [[package]] name = "gimli" version = "0.27.2" @@ -1962,6 +2313,12 @@ dependencies = [ "system-deps 6.0.5", ] +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "globset" version = "0.4.10" @@ -2078,6 +2435,12 @@ version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a" +[[package]] +name = "hash-db" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e7d7786361d7425ae2fe4f9e407eb0efaa0840f5212d109cc018c40c35c6ab4" + [[package]] name = "hash256-std-hasher" version = "0.15.2" @@ -2195,25 +2558,44 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" dependencies = [ - "crypto-mac", + "crypto-mac 0.8.0", "digest 0.9.0", ] [[package]] -name = "hmac-drbg" -version = "0.3.0" +name = "hmac" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" dependencies = [ + "crypto-mac 0.11.1", "digest 0.9.0", - "generic-array", - "hmac", ] [[package]] -name = "html5ever" -version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.6", +] + +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest 0.9.0", + "generic-array 0.14.7", + "hmac 0.8.1", +] + +[[package]] +name = "html5ever" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5c13fb08e5d4dfc151ee5e88bae63f7773d61852f3bdc73c9f4b9e1bde03148" dependencies = [ "log", @@ -2432,6 +2814,7 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", + "serde", ] [[package]] @@ -2527,7 +2910,7 @@ checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" dependencies = [ "hermit-abi 0.3.1", "io-lifetimes", - "rustix", + "rustix 0.37.18", "windows-sys 0.48.0", ] @@ -2611,6 +2994,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +[[package]] +name = "jobserver" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.61" @@ -2641,7 +3033,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3dc3e9cf2ba50b7b1d7d76a667619f82846caa39e8e8daa8a4962d74acaddca" dependencies = [ "anyhow", - "arrayvec", + "arrayvec 0.7.2", "async-trait", "beef", "futures-channel", @@ -2745,6 +3137,17 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "keccak-hasher" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ea4653859ca2266a86419d3f592d3f22e7a854b482f99180d2498507902048" +dependencies = [ + "hash-db 0.16.0", + "hash256-std-hasher", + "tiny-keccak", +] + [[package]] name = "keyboard-types" version = "0.6.2" @@ -2826,12 +3229,49 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.142" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "libm" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" + +[[package]] +name = "librocksdb-sys" +version = "0.10.0+7.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fe4d5874f5ff2bc616e55e8c6086d478fcda13faf9495768a4aa1c22042d30b" +dependencies = [ + "bindgen", + "bzip2-sys", + "cc", + "glob", + "libc", + "libz-sys", + "zstd-sys", +] + [[package]] name = "libsecp256k1" version = "0.7.1" @@ -2880,6 +3320,17 @@ dependencies = [ "libsecp256k1-core", ] +[[package]] +name = "libz-sys" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ee889ecc9568871456d42f603d6a0ce59ff328d291063a45cbdf0036baf6db" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + [[package]] name = "link-cplusplus" version = "1.0.8" @@ -2889,6 +3340,12 @@ dependencies = [ "cc", ] +[[package]] +name = "linux-raw-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" + [[package]] name = "linux-raw-sys" version = "0.3.6" @@ -2944,6 +3401,15 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" +[[package]] +name = "mach" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +dependencies = [ + "libc", +] + [[package]] name = "malloc_buf" version = "0.0.6" @@ -2967,6 +3433,15 @@ dependencies = [ "tendril", ] +[[package]] +name = "matchers" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" +dependencies = [ + "regex-automata", +] + [[package]] name = "matches" version = "0.1.10" @@ -2985,6 +3460,24 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "memfd" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc89ccdc6e10d6907450f753537ebc5c5d3460d2e4e62ea74bd571db62c0f9e" +dependencies = [ + "rustix 0.37.18", +] + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + [[package]] name = "memoffset" version = "0.8.0" @@ -2994,6 +3487,33 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memory-db" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808b50db46293432a45e63bc15ea51e0ab4c0a1647b8eb114e31a3e698dd6fbe" +dependencies = [ + "hash-db 0.16.0", +] + +[[package]] +name = "memory_units" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" + +[[package]] +name = "merlin" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e261cf0f8b3c42ded9f7d2bb59dea03aa52bc8a1cbc7482f9fc3fd1229d3b42" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.5.1", + "zeroize", +] + [[package]] name = "metachain-cli" version = "0.1.0" @@ -3015,6 +3535,12 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.6.2" @@ -3114,6 +3640,22 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "notify" version = "5.1.0" @@ -3141,6 +3683,27 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-format" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" +dependencies = [ + "arrayvec 0.7.2", + "itoa 1.0.6", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -3158,6 +3721,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" dependencies = [ "autocfg", + "num-bigint", "num-integer", "num-traits", ] @@ -3230,6 +3794,18 @@ dependencies = [ "objc", ] +[[package]] +name = "object" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" +dependencies = [ + "crc32fast", + "hashbrown 0.12.3", + "indexmap", + "memchr", +] + [[package]] name = "object" version = "0.30.3" @@ -3245,6 +3821,12 @@ version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + [[package]] name = "opaque-debug" version = "0.3.0" @@ -3297,9 +3879,10 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "637935964ff85a605d114591d4d2c13c5d1ba2806dae97cea6bf180238a749ac" dependencies = [ - "arrayvec", + "arrayvec 0.7.2", "bitvec", "byte-slice-cast", + "bytes", "impl-trait-for-tuples", "parity-scale-codec-derive", "serde", @@ -3317,6 +3900,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "parity-wasm" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1ad0aff30c1da14b1254fcb2af73e1fa9a28670e584a626f53a369d0e157304" + [[package]] name = "parking" version = "2.1.0" @@ -3377,6 +3966,30 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" +[[package]] +name = "pbkdf2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa" +dependencies = [ + "crypto-mac 0.11.1", +] + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.6", +] + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + [[package]] name = "percent-encoding" version = "2.2.0" @@ -3675,6 +4288,15 @@ dependencies = [ "autotools", ] +[[package]] +name = "psm" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" +dependencies = [ + "cc", +] + [[package]] name = "quote" version = "1.0.26" @@ -3690,6 +4312,19 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +dependencies = [ + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi", +] + [[package]] name = "rand" version = "0.7.3" @@ -3735,6 +4370,21 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + [[package]] name = "rand_core" version = "0.5.1" @@ -3777,6 +4427,15 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -3806,6 +4465,26 @@ dependencies = [ "thiserror", ] +[[package]] +name = "ref-cast" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43faa91b1c8b36841ee70e97188a869d37ae21759da6846d4be66de5bf7b12c" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d2275aab483050ab2a7364c1a46604865ee7d6906684e08db0f090acf74f9e7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.15", +] + [[package]] name = "regex" version = "1.8.1" @@ -3814,15 +4493,39 @@ checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" dependencies = [ "aho-corasick 1.0.1", "memchr", - "regex-syntax", + "regex-syntax 0.7.1", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", ] +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + [[package]] name = "regex-syntax" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + [[package]] name = "ring" version = "0.16.20" @@ -3860,6 +4563,26 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "rocksdb" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "015439787fce1e75d55f279078d33ff14b4af5d93d995e8838ee4631301c8a99" +dependencies = [ + "libc", + "librocksdb-sys", +] + +[[package]] +name = "ruc" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20d7f74d19a4608c0e78c2d742c31c1e864aeeecd003651aa3e64e0a91749276" +dependencies = [ + "once_cell", + "time 0.3.20", +] + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -3889,21 +4612,35 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.18" +version = "0.36.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bbfc1d1c7c40c01715f47d71444744a81669ca84e8b63e25a55e169b1f86433" +checksum = "3a38f9520be93aba504e8ca974197f46158de5dcaa9fa04b57c57cd6a679d658" dependencies = [ "bitflags", "errno", "io-lifetimes", "libc", - "linux-raw-sys", - "windows-sys 0.48.0", + "linux-raw-sys 0.1.4", + "windows-sys 0.45.0", ] [[package]] -name = "rustls" -version = "0.20.8" +name = "rustix" +version = "0.37.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bbfc1d1c7c40c01715f47d71444744a81669ca84e8b63e25a55e169b1f86433" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.6", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustls" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" dependencies = [ @@ -3989,6 +4726,35 @@ dependencies = [ "windows-sys 0.42.0", ] +[[package]] +name = "schnellru" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "772575a524feeb803e5b0fcbc6dd9f367e579488197c94c6e4023aad2305774d" +dependencies = [ + "ahash 0.8.3", + "cfg-if", + "hashbrown 0.13.2", +] + +[[package]] +name = "schnorrkel" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "021b403afe70d81eea68f6ea12f6b3c9588e5d536a94c3bf80f15e7faa267862" +dependencies = [ + "arrayref", + "arrayvec 0.5.2", + "curve25519-dalek 2.1.3", + "getrandom 0.1.16", + "merlin", + "rand 0.7.3", + "rand_core 0.5.1", + "sha2 0.8.2", + "subtle", + "zeroize", +] + [[package]] name = "scopeguard" version = "1.1.0" @@ -4011,6 +4777,33 @@ dependencies = [ "untrusted", ] +[[package]] +name = "secp256k1" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" +dependencies = [ + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b" +dependencies = [ + "cc", +] + +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "zeroize", +] + [[package]] name = "security-framework" version = "2.8.2" @@ -4142,6 +4935,18 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "sha2" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug 0.2.3", +] + [[package]] name = "sha2" version = "0.9.9" @@ -4152,7 +4957,7 @@ dependencies = [ "cfg-if", "cpufeatures", "digest 0.9.0", - "opaque-debug", + "opaque-debug 0.3.0", ] [[package]] @@ -4176,6 +4981,21 @@ dependencies = [ "keccak", ] +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" + [[package]] name = "signal-hook" version = "0.3.15" @@ -4309,6 +5129,192 @@ dependencies = [ "system-deps 5.0.0", ] +[[package]] +name = "sp-core" +version = "20.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7789372146f8ad40d0b40fad0596cb1db5771187a258eabe19b06f00767fcbd6" +dependencies = [ + "array-bytes", + "bitflags", + "blake2", + "bounded-collections", + "bs58", + "dyn-clonable", + "ed25519-zebra", + "futures", + "hash-db 0.16.0", + "hash256-std-hasher", + "impl-serde", + "lazy_static", + "libsecp256k1", + "log", + "merlin", + "parity-scale-codec", + "parking_lot 0.12.1", + "primitive-types", + "rand 0.8.5", + "regex", + "scale-info", + "schnorrkel", + "secp256k1", + "secrecy", + "serde", + "sp-core-hashing", + "sp-debug-derive", + "sp-externalities", + "sp-runtime-interface", + "sp-std", + "sp-storage", + "ss58-registry", + "substrate-bip39", + "thiserror", + "tiny-bip39", + "zeroize", +] + +[[package]] +name = "sp-core-hashing" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27449abdfbe41b473e625bce8113745e81d65777dd1d5a8462cf24137930dad8" +dependencies = [ + "blake2b_simd", + "byteorder", + "digest 0.10.6", + "sha2 0.10.6", + "sha3", + "sp-std", + "twox-hash", +] + +[[package]] +name = "sp-debug-derive" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62211eed9ef9dac4b9d837c56ccc9f8ee4fc49d9d9b7e6b9daf098fe173389ab" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "sp-externalities" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae0f275760689aaefe967943331d458cd99f5169d18364365d4cb584b246d1c" +dependencies = [ + "environmental", + "parity-scale-codec", + "sp-std", + "sp-storage", +] + +[[package]] +name = "sp-runtime-interface" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca5d0cd80200bf85b8b064238b2508b69b6146b13adf36066ec5d924825af737" +dependencies = [ + "bytes", + "impl-trait-for-tuples", + "parity-scale-codec", + "primitive-types", + "sp-externalities", + "sp-runtime-interface-proc-macro", + "sp-std", + "sp-storage", + "sp-tracing", + "sp-wasm-interface", + "static_assertions", +] + +[[package]] +name = "sp-runtime-interface-proc-macro" +version = "10.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ae5b00aef477127ddb6177b3464ad1e2bdcc12ee913fc5dfc9d065c6cea89b" +dependencies = [ + "Inflector", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "sp-std" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1de8eef39962b5b97478719c493bed2926cf70cb621005bbf68ebe58252ff986" + +[[package]] +name = "sp-storage" +version = "12.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ad1f8c52d4700ac7bc42b3375679a6c6fc1fe876f4b40c6efdf36f933ef0291" +dependencies = [ + "impl-serde", + "parity-scale-codec", + "ref-cast", + "serde", + "sp-debug-derive", + "sp-std", +] + +[[package]] +name = "sp-tracing" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00fab60bf3d42255ce3f678903d3a2564662371c75623de4a1ffc7cac46143df" +dependencies = [ + "parity-scale-codec", + "sp-std", + "tracing", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "sp-trie" +version = "21.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58401c53c08b6ecad83acd7e14534c8bbcb3fa73e81e26685e0ac70e51b00c56" +dependencies = [ + "ahash 0.8.3", + "hash-db 0.16.0", + "hashbrown 0.13.2", + "lazy_static", + "memory-db", + "nohash-hasher", + "parity-scale-codec", + "parking_lot 0.12.1", + "scale-info", + "schnellru", + "sp-core", + "sp-std", + "thiserror", + "tracing", + "trie-db", + "trie-root", +] + +[[package]] +name = "sp-wasm-interface" +version = "13.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "153b7374179439e2aa783c66ed439bd86920c67bbc95d34c76390561972bc02f" +dependencies = [ + "anyhow", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "sp-std", + "wasmi", + "wasmtime", +] + [[package]] name = "spin" version = "0.5.2" @@ -4333,6 +5339,21 @@ dependencies = [ "lock_api", ] +[[package]] +name = "ss58-registry" +version = "1.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb47a8ad42e5fc72d5b1eb104a5546937eaf39843499948bb666d6e93c62423b" +dependencies = [ + "Inflector", + "num-format", + "proc-macro2", + "quote", + "serde", + "serde_json", + "unicode-xid", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -4351,7 +5372,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c8e640c9e28d216546bb5ebfd18e31e84347595743e092291c4047530b29701" dependencies = [ - "arrayvec", + "arrayvec 0.7.2", "hash32", "hash32-derive", "heapless", @@ -4415,11 +5436,24 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "substrate-bip39" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49eee6965196b32f882dd2ee85a92b1dbead41b04e53907f269de3b0dc04733c" +dependencies = [ + "hmac 0.11.0", + "pbkdf2 0.8.0", + "schnorrkel", + "sha2 0.9.9", + "zeroize", +] + [[package]] name = "subtle" -version = "2.5.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" @@ -4533,6 +5567,16 @@ version = "0.12.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd1ba337640d60c3e96bc6f0638a939b9c9a7f2c316a1598c279828b3d1dc8c5" +[[package]] +name = "tempdir" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" +dependencies = [ + "rand 0.4.6", + "remove_dir_all", +] + [[package]] name = "tempfile" version = "3.5.0" @@ -4542,7 +5586,7 @@ dependencies = [ "cfg-if", "fastrand", "redox_syscall 0.3.5", - "rustix", + "rustix 0.37.18", "windows-sys 0.45.0", ] @@ -4611,6 +5655,15 @@ dependencies = [ "once_cell", ] +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + [[package]] name = "time" version = "0.1.45" @@ -4622,6 +5675,52 @@ dependencies = [ "winapi", ] +[[package]] +name = "time" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" +dependencies = [ + "itoa 1.0.6", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + +[[package]] +name = "time-macros" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36" +dependencies = [ + "time-core", +] + +[[package]] +name = "tiny-bip39" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62cc94d358b5a1e84a5cb9109f559aa3c4d634d2b1b4de3d0fa4adc7c78e2861" +dependencies = [ + "anyhow", + "hmac 0.12.1", + "once_cell", + "pbkdf2 0.11.0", + "rand 0.8.5", + "rustc-hash", + "sha2 0.10.6", + "thiserror", + "unicode-normalization", + "wasm-bindgen", + "zeroize", +] + [[package]] name = "tiny-keccak" version = "2.0.2" @@ -4874,6 +5973,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ "once_cell", + "valuable", ] [[package]] @@ -4886,13 +5986,78 @@ dependencies = [ "tracing", ] +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-serde" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +dependencies = [ + "serde", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" +dependencies = [ + "ansi_term", + "chrono", + "lazy_static", + "matchers", + "regex", + "serde", + "serde_json", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", + "tracing-serde", +] + +[[package]] +name = "trie-db" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "767abe6ffed88a1889671a102c2861ae742726f52e0a5a425b92c9fbfa7e9c85" +dependencies = [ + "hash-db 0.16.0", + "hashbrown 0.13.2", + "log", + "rustc-hex", + "smallvec", +] + +[[package]] +name = "trie-root" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ed310ef5ab98f5fa467900ed906cb9232dd5376597e00fd4cba2a449d06c0b" +dependencies = [ + "hash-db 0.16.0", +] + [[package]] name = "triehash" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1631b201eb031b563d2e85ca18ec8092508e262a3196ce9bd10a67ec87b9f5c" dependencies = [ - "hash-db", + "hash-db 0.15.2", "rlp", ] @@ -4915,6 +6080,18 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "digest 0.10.6", + "rand 0.8.5", + "static_assertions", +] + [[package]] name = "typenum" version = "1.16.0" @@ -4975,6 +6152,12 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + [[package]] name = "untrusted" version = "0.7.1" @@ -5013,6 +6196,18 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2cb3ff47e36907a6267572c1e398ff32ef78ac5131de8aa272e53846592c207e" +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "vec_map" version = "0.8.2" @@ -5037,6 +6232,77 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "vsdb" +version = "0.55.0" +source = "git+https://github.com/jouzo/vsdb.git#54659a979f7215eefe6ca7239c96271d02f94f15" +dependencies = [ + "once_cell", + "parking_lot 0.12.1", + "ruc", + "serde", + "vsdb_core", +] + +[[package]] +name = "vsdb_core" +version = "0.55.6" +source = "git+https://github.com/jouzo/vsdb.git#54659a979f7215eefe6ca7239c96271d02f94f15" +dependencies = [ + "once_cell", + "parking_lot 0.12.1", + "rand 0.8.5", + "rocksdb", + "ruc", + "serde", + "threadpool", + "vsdbsled", +] + +[[package]] +name = "vsdb_hash_db" +version = "0.6.0" +source = "git+https://github.com/jouzo/vsdb.git#54659a979f7215eefe6ca7239c96271d02f94f15" +dependencies = [ + "bcs", + "hash-db 0.16.0", + "keccak-hasher", + "ruc", + "serde", + "sp-trie", + "trie-db", + "vsdb", +] + +[[package]] +name = "vsdb_trie_db" +version = "0.7.0" +source = "git+https://github.com/jouzo/vsdb.git#54659a979f7215eefe6ca7239c96271d02f94f15" +dependencies = [ + "ruc", + "serde", + "sp-trie", + "vsdb", + "vsdb_hash_db", +] + +[[package]] +name = "vsdbsled" +version = "0.34.7-p1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b42602d283268f887952376e41ce60f5ab5f79e8725dab731de4ab1b0e70e53" +dependencies = [ + "crc32fast", + "crossbeam-epoch", + "crossbeam-utils", + "fs4", + "fxhash", + "libc", + "log", + "parking_lot 0.12.1", + "zstd", +] + [[package]] name = "waker-fn" version = "1.1.0" @@ -5147,6 +6413,181 @@ version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" +[[package]] +name = "wasmi" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06c326c93fbf86419608361a2c925a31754cf109da1b8b55737070b4d6669422" +dependencies = [ + "parity-wasm", + "wasmi-validation", + "wasmi_core", +] + +[[package]] +name = "wasmi-validation" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ff416ad1ff0c42e5a926ed5d5fab74c0f098749aa0ad8b2a34b982ce0e867b" +dependencies = [ + "parity-wasm", +] + +[[package]] +name = "wasmi_core" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57d20cb3c59b788653d99541c646c561c9dd26506f25c0cebfe810659c54c6d7" +dependencies = [ + "downcast-rs", + "libm", + "memory_units", + "num-rational", + "num-traits", +] + +[[package]] +name = "wasmparser" +version = "0.100.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64b20236ab624147dfbb62cf12a19aaf66af0e41b8398838b66e997d07d269d4" +dependencies = [ + "indexmap", + "url", +] + +[[package]] +name = "wasmtime" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a222f5fa1e14b2cefc286f1b68494d7a965f4bf57ec04c59bb62673d639af6" +dependencies = [ + "anyhow", + "bincode", + "cfg-if", + "indexmap", + "libc", + "log", + "object 0.29.0", + "once_cell", + "paste", + "psm", + "serde", + "target-lexicon", + "wasmparser", + "wasmtime-environ", + "wasmtime-jit", + "wasmtime-runtime", + "windows-sys 0.42.0", +] + +[[package]] +name = "wasmtime-asm-macros" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4407a7246e7d2f3d8fb1cf0c72fda8dbafdb6dd34d555ae8bea0e5ae031089cc" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "wasmtime-environ" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b8b50962eae38ee319f7b24900b7cf371f03eebdc17400c1dc8575fc10c9a7" +dependencies = [ + "anyhow", + "cranelift-entity", + "gimli 0.26.2", + "indexmap", + "log", + "object 0.29.0", + "serde", + "target-lexicon", + "thiserror", + "wasmparser", + "wasmtime-types", +] + +[[package]] +name = "wasmtime-jit" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffaed4f9a234ba5225d8e64eac7b4a5d13b994aeb37353cde2cbeb3febda9eaa" +dependencies = [ + "addr2line 0.17.0", + "anyhow", + "bincode", + "cfg-if", + "cpp_demangle", + "gimli 0.26.2", + "log", + "object 0.29.0", + "rustc-demangle", + "serde", + "target-lexicon", + "wasmtime-environ", + "wasmtime-jit-icache-coherence", + "wasmtime-runtime", + "windows-sys 0.42.0", +] + +[[package]] +name = "wasmtime-jit-debug" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed41cbcbf74ce3ff6f1d07d1b707888166dc408d1a880f651268f4f7c9194b2" +dependencies = [ + "once_cell", +] + +[[package]] +name = "wasmtime-jit-icache-coherence" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a28ae1e648461bfdbb79db3efdaee1bca5b940872e4175390f465593a2e54c" +dependencies = [ + "cfg-if", + "libc", + "windows-sys 0.42.0", +] + +[[package]] +name = "wasmtime-runtime" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e704b126e4252788ccfc3526d4d4511d4b23c521bf123e447ac726c14545217b" +dependencies = [ + "anyhow", + "cc", + "cfg-if", + "indexmap", + "libc", + "log", + "mach", + "memfd", + "memoffset 0.6.5", + "paste", + "rand 0.8.5", + "rustix 0.36.13", + "wasmtime-asm-macros", + "wasmtime-environ", + "wasmtime-jit-debug", + "windows-sys 0.42.0", +] + +[[package]] +name = "wasmtime-types" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83e5572c5727c1ee7e8f28717aaa8400e4d22dcbd714ea5457d85b5005206568" +dependencies = [ + "cranelift-entity", + "serde", + "thiserror", + "wasmparser", +] + [[package]] name = "web-sys" version = "0.3.61" @@ -5628,3 +7069,53 @@ dependencies = [ "once_cell", "pkg-config", ] + +[[package]] +name = "zeroize" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +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.15", +] + +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.8+zstd.1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c" +dependencies = [ + "cc", + "libc", + "pkg-config", +] diff --git a/lib/Makefile.am b/lib/Makefile.am index e90683fa85..e0e073b7ef 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,14 +1,14 @@ # TODO: Refine these vars with graceful swichover to local and # ensure it works without them set as well as with them set -CARGO_HOME ?= -RUSTUP_HOME ?= +CARGO_HOME ?= +RUSTUP_HOME ?= CARGO ?= cargo # RUST_TARGET is set from configure TARGET = $(if $(RUST_TARGET),$(RUST_TARGET),x86_64-unknown-linux-gnu) # This is set from configure -RUST_DEBUG ?= +RUST_DEBUG ?= # We use DEBUG as well, since that's the more conventional # setup. Either of them set will result in debug builds DEBUG ?= $(RUST_DEBUG) @@ -21,7 +21,7 @@ CARGO_MANIFEST_PATH = $(abs_srcdir)/Cargo.toml # don't end up in unexpected places (Currently protobuf-src is affected) .PHONY: -all: +all: DESTDIR= TARGET_DIR=$(TARGET_DIR) \ RUSTUP_HOME=$(RUSTUP_HOME) \ CARGO_HOME=$(CARGO_HOME) \ diff --git a/lib/ain-cpp-imports/build.rs b/lib/ain-cpp-imports/build.rs index b30ca7e2ae..a3d813acde 100644 --- a/lib/ain-cpp-imports/build.rs +++ b/lib/ain-cpp-imports/build.rs @@ -8,7 +8,7 @@ fn main() -> Result<()> { let cpp_src_path = &manifest_path .parent() - .and_then(|x| x.parent()) + .and_then(std::path::Path::parent) .map(|x| x.join("src")) .ok_or(format_err!("path err"))?; diff --git a/lib/ain-cpp-imports/src/lib.rs b/lib/ain-cpp-imports/src/lib.rs index 0f9fa87033..8c81f74697 100644 --- a/lib/ain-cpp-imports/src/lib.rs +++ b/lib/ain-cpp-imports/src/lib.rs @@ -9,7 +9,7 @@ use bridge::ffi; #[cfg(any(test, bench, example, doc))] #[allow(non_snake_case)] mod ffi { - const UNIMPL_MSG: &'static str = "This cannot be used on a test path"; + const UNIMPL_MSG: &str = "This cannot be used on a test path"; pub fn getChainId() -> u64 { unimplemented!("{}", UNIMPL_MSG) } diff --git a/lib/ain-evm/Cargo.toml b/lib/ain-evm/Cargo.toml index 87825f98be..b7ebd0d58b 100644 --- a/lib/ain-evm/Cargo.toml +++ b/lib/ain-evm/Cargo.toml @@ -23,6 +23,12 @@ serde = { version = "1.0", features = ["derive"] } ethbloom = "0.13.0" ethereum-types = "0.14.1" +# Trie dependencies +hash-db = "0.16.0" +sp-core = "20.0.0" +vsdb_trie_db = { version = "0.7.0", git = "https://github.com/jouzo/vsdb.git", features = ["rocks_engine"] } +vsdb_core = { version = "0.55.0", git = "https://github.com/jouzo/vsdb.git", features = ["rocks_engine", "compress"] } + # Runtime dependencies lazy_static = "1.4" jsonrpsee-core = "0.15" @@ -32,3 +38,7 @@ tokio = { version = "1.1", features = ["rt-multi-thread"] } # Cache dependencies lru = "0.10.0" + +[dev-dependencies] +tempdir = "0.3.7" +once_cell = "1.17.1" diff --git a/lib/ain-evm/src/backend.rs b/lib/ain-evm/src/backend.rs new file mode 100644 index 0000000000..f25be4297e --- /dev/null +++ b/lib/ain-evm/src/backend.rs @@ -0,0 +1,320 @@ +use ethereum::{Account, Log}; +use evm::backend::{Apply, ApplyBackend, Backend, Basic}; +use hash_db::Hasher as _; +use log::debug; +use primitive_types::{H160, H256, U256}; +use rlp::{Decodable, Encodable, Rlp}; +use sp_core::hexdisplay::AsBytesRef; +use sp_core::Blake2Hasher; +use vsdb_trie_db::MptOnce; + +use crate::{evm::TrieDBStore, storage::Storage, traits::BridgeBackend}; + +type Hasher = Blake2Hasher; + +fn is_empty_account(account: &Account) -> bool { + account.balance.is_zero() && account.nonce.is_zero() && account.code_hash.is_zero() +} + +// TBD +pub struct Vicinity; + +pub struct EVMBackend { + state: MptOnce, + trie_store: Arc, + storage: Arc, + _vicinity: Vicinity, +} + +type Result = std::result::Result; + +impl EVMBackend { + pub fn from_root( + state_root: H256, + trie_store: Arc, + storage: Arc, + _vicinity: Vicinity, + ) -> Result { + let state = trie_store + .trie_db + .trie_restore(&[0], None, state_root.into()) + .map_err(|e| EVMBackendError::TrieRestoreFailed(e.to_string()))?; + + Ok(EVMBackend { + state, + trie_store, + storage, + _vicinity, + }) + } + + pub fn apply>( + &mut self, + address: H160, + basic: Basic, + code: Option>, + storage: I, + reset_storage: bool, + ) -> Result { + let account = self.get_account(address).unwrap_or(Account { + nonce: U256::zero(), + balance: U256::zero(), + storage_root: H256::zero(), + code_hash: H256::zero(), + }); + + let mut storage_trie = if reset_storage || is_empty_account(&account) { + self.trie_store + .trie_db + .trie_create(address.as_bytes(), None, true) + .map_err(|e| EVMBackendError::TrieCreationFailed(e.to_string()))? + } else { + self.trie_store + .trie_db + .trie_restore(address.as_bytes(), None, account.storage_root.into()) + .map_err(|e| EVMBackendError::TrieRestoreFailed(e.to_string()))? + }; + + storage.into_iter().for_each(|(k, v)| { + let _ = storage_trie.insert(k.as_bytes(), v.as_bytes()); + }); + + let code_hash = code + .map(|code| { + let code_hash = Hasher::hash(&code); + self.storage.put_code(code_hash, code); + code_hash + }) + .unwrap_or(account.code_hash); + + let new_account = Account { + nonce: basic.nonce, + balance: basic.balance, + code_hash, + storage_root: storage_trie.commit().into(), + }; + + self.state + .insert(address.as_bytes(), new_account.rlp_bytes().as_ref()) + .map_err(|e| EVMBackendError::TrieError(format!("{}", e)))?; + + Ok(new_account) + } + + pub fn commit(&mut self) -> H256 { + self.state.commit().into() + } +} + +impl EVMBackend { + pub fn get_account(&self, address: H160) -> Option { + self.state + .get(address.as_bytes()) + .unwrap_or(None) + .and_then(|addr| Account::decode(&Rlp::new(addr.as_bytes_ref())).ok()) + } +} + +impl Backend for EVMBackend { + fn gas_price(&self) -> U256 { + unimplemented!() + } + + fn origin(&self) -> H160 { + unimplemented!() + } + + fn block_hash(&self, _number: U256) -> H256 { + unimplemented!("Implement block_hash function") + } + + fn block_number(&self) -> U256 { + unimplemented!() + } + + fn block_coinbase(&self) -> H160 { + unimplemented!("Implement block_coinbase function") + } + + fn block_timestamp(&self) -> U256 { + unimplemented!("Implement block_timestamp function") + } + + fn block_difficulty(&self) -> U256 { + U256::zero() + } + + fn block_gas_limit(&self) -> U256 { + unimplemented!("Implement block_gas_limit function") + } + + fn block_base_fee_per_gas(&self) -> U256 { + unimplemented!("Implement block_base_fee_per_gas function") + } + + fn chain_id(&self) -> U256 { + U256::from(ain_cpp_imports::get_chain_id().expect("Error getting chain_id")) + } + + fn exists(&self, address: H160) -> bool { + self.state.contains(address.as_bytes()).unwrap_or(false) + } + + fn basic(&self, address: H160) -> Basic { + self.get_account(address) + .map(|account| Basic { + balance: account.balance, + nonce: account.nonce, + }) + .unwrap_or_default() + } + + fn code(&self, address: H160) -> Vec { + self.get_account(address) + .and_then(|account| self.storage.get_code_by_hash(account.code_hash)) + .unwrap_or_default() + } + + fn storage(&self, address: H160, index: H256) -> H256 { + self.get_account(address) + .and_then(|account| { + self.trie_store + .trie_db + .trie_restore(address.as_bytes(), None, account.storage_root.into()) + .ok() + }) + .and_then(|trie| trie.get(index.as_bytes()).ok().flatten()) + .map(|res| H256::from_slice(res.as_ref())) + .unwrap_or_default() + } + + fn original_storage(&self, address: H160, index: H256) -> Option { + Some(self.storage(address, index)) + } +} + +impl ApplyBackend for EVMBackend { + fn apply(&mut self, values: A, _logs: L, delete_empty: bool) + where + A: IntoIterator>, + I: IntoIterator, + L: IntoIterator, + { + for apply in values.into_iter() { + match apply { + Apply::Modify { + address, + basic, + code, + storage, + reset_storage, + } => { + let new_account = self + .apply(address, basic, code, storage, reset_storage) + .expect("Error applying state"); + + if is_empty_account(&new_account) && delete_empty { + debug!("Deleting empty address {}", address); + self.trie_store.trie_db.trie_remove(address.as_bytes()); + self.state + .remove(address.as_bytes()) + .expect("Error removing address in state"); + } + } + Apply::Delete { address } => { + debug!("Deleting address {}", address); + self.trie_store.trie_db.trie_remove(address.as_bytes()); + self.state + .remove(address.as_bytes()) + .expect("Error removing address in state"); + } + } + } + } +} + +impl BridgeBackend for EVMBackend { + fn add_balance(&mut self, address: H160, amount: U256) -> Result<()> { + let basic = self.basic(address); + + let new_basic = Basic { + balance: basic.balance + amount, + ..basic + }; + + self.apply(address, new_basic, None, Vec::new(), false)?; + self.state.commit(); + Ok(()) + } + + fn sub_balance(&mut self, address: H160, amount: U256) -> Result<()> { + let account = self + .get_account(address) + .ok_or(EVMBackendError::NoSuchAccount(address))?; + + if account.balance < amount { + Err(EVMBackendError::InsufficientBalance(InsufficientBalance { + address, + account_balance: account.balance, + amount, + })) + } else { + let new_basic = Basic { + balance: account.balance - amount, + nonce: account.nonce, + }; + + self.apply(address, new_basic, None, Vec::new(), false)?; + self.state.commit(); + Ok(()) + } + } +} + +use std::{error::Error, fmt, sync::Arc}; + +#[derive(Debug)] +pub struct InsufficientBalance { + address: H160, + account_balance: U256, + amount: U256, +} + +#[derive(Debug)] +pub enum EVMBackendError { + TrieCreationFailed(String), + TrieRestoreFailed(String), + TrieError(String), + NoSuchAccount(H160), + InsufficientBalance(InsufficientBalance), +} + +impl fmt::Display for EVMBackendError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + EVMBackendError::TrieCreationFailed(e) => { + write!(f, "EVMBackendError: Failed to create trie {}", e) + } + EVMBackendError::TrieRestoreFailed(e) => { + write!(f, "EVMBackendError: Failed to restore trie {}", e) + } + EVMBackendError::TrieError(e) => write!(f, "EVMBackendError: Trie error {}", e), + EVMBackendError::NoSuchAccount(address) => { + write!( + f, + "EVMBackendError: No such acccount for address {}", + address + ) + } + EVMBackendError::InsufficientBalance(InsufficientBalance { + address, + account_balance, + amount, + }) => { + write!(f, "EVMBackendError: Insufficient balance for address {}, trying to deduct {} but address has only {}", address, amount, account_balance) + } + } + } +} + +impl Error for EVMBackendError {} diff --git a/lib/ain-evm/src/block.rs b/lib/ain-evm/src/block.rs index 8596cabf04..98db301e4a 100644 --- a/lib/ain-evm/src/block.rs +++ b/lib/ain-evm/src/block.rs @@ -17,10 +17,17 @@ impl BlockHandler { pub fn get_latest_block_hash_and_number(&self) -> (H256, U256) { self.storage .get_latest_block() - .map(|latest_block| (latest_block.header.hash(), latest_block.header.number + 1)) + .map(|latest_block| (latest_block.header.hash(), latest_block.header.number)) .unwrap_or((H256::default(), U256::zero())) } + pub fn get_latest_state_root(&self) -> H256 { + self.storage + .get_latest_block() + .map(|block| block.header.state_root) + .unwrap_or_default() + } + pub fn connect_block(&self, block: BlockAny) { self.storage.put_latest_block(&block); self.storage.put_block(&block) diff --git a/lib/ain-evm/src/evm.rs b/lib/ain-evm/src/evm.rs index 24bb27bf45..7aa38c5869 100644 --- a/lib/ain-evm/src/evm.rs +++ b/lib/ain-evm/src/evm.rs @@ -1,4 +1,7 @@ -use crate::storage::traits::{PersistentState, PersistentStateError}; +use crate::backend::{EVMBackend, EVMBackendError, Vicinity}; +use crate::executor::TxResponse; +use crate::storage::traits::{BlockStorage, PersistentState, PersistentStateError}; +use crate::storage::Storage; use crate::tx_queue::TransactionQueueMap; use crate::{ executor::AinExecutor, @@ -6,49 +9,72 @@ use crate::{ transaction::SignedTx, }; use anyhow::anyhow; -use ethereum::{AccessList, Log, TransactionV2}; +use ethereum::{AccessList, Account, Log, TransactionV2}; use ethereum_types::{Bloom, BloomInput}; -use evm::backend::MemoryAccount; -use evm::{ - backend::{MemoryBackend, MemoryVicinity}, - ExitReason, -}; + use hex::FromHex; +use log::debug; use primitive_types::{H160, H256, U256}; -use std::collections::BTreeMap; +use serde::{Deserialize, Serialize}; use std::error::Error; -use std::sync::{Arc, RwLock}; - -pub static EVM_STATE_FILE: &str = "evm_state.bin"; +use std::sync::Arc; +use vsdb_core::vsdb_set_base_dir; +use vsdb_trie_db::MptStore; -pub type EVMState = BTreeMap; +pub static TRIE_DB_STORE: &str = "trie_db_store.bin"; -#[derive(Clone, Debug)] pub struct EVMHandler { - pub state: Arc>, pub tx_queues: Arc, + pub trie_store: Arc, + storage: Arc, } -impl PersistentState for EVMState {} +#[derive(Serialize, Deserialize)] +pub struct TrieDBStore { + pub trie_db: MptStore, +} -impl Default for EVMHandler { +impl Default for TrieDBStore { fn default() -> Self { Self::new() } } -impl EVMHandler { +impl TrieDBStore { pub fn new() -> Self { + debug!("Creating new trie store"); + let trie_store = MptStore::new(); + let mut trie = trie_store + .trie_create(&[0], None, false) + .expect("Error creating initial backend"); + let state_root: H256 = trie.commit().into(); + debug!("Initial state_root : {:#x}", state_root); + Self { + trie_db: trie_store, + } + } +} + +impl PersistentState for TrieDBStore {} + +impl EVMHandler { + pub fn new(storage: Arc) -> Self { + let datadir = ain_cpp_imports::get_datadir().expect("Could not get imported datadir"); + let vsdb_dir = format!("{datadir}/.vsdb"); + vsdb_set_base_dir(&vsdb_dir).expect("Could not update vsdb base dir"); + debug!("VSDB dir : {}", vsdb_dir); + Self { - state: Arc::new(RwLock::new( - EVMState::load_from_disk(EVM_STATE_FILE).expect("Error loading state"), - )), tx_queues: Arc::new(TransactionQueueMap::new()), + trie_store: Arc::new( + TrieDBStore::load_from_disk(TRIE_DB_STORE).expect("Error loading trie db store"), + ), + storage, } } pub fn flush(&self) -> Result<(), PersistentStateError> { - self.state.write().unwrap().save_to_disk(EVM_STATE_FILE) + self.trie_store.save_to_disk(TRIE_DB_STORE) } pub fn call( @@ -59,13 +85,21 @@ impl EVMHandler { data: &[u8], gas_limit: u64, access_list: AccessList, - ) -> (ExitReason, Vec, u64) { - // TODO Add actual gas, chain_id, block_number from header - let vicinity = get_vicinity(caller, None); - - let state = self.state.read().unwrap().clone(); - let backend = MemoryBackend::new(&vicinity, state); - let tx_response = AinExecutor::new(backend).call( + ) -> Result> { + let state_root = self + .storage + .get_latest_block() + .map(|block| block.header.state_root) + .unwrap_or_default(); + let vicinity = Vicinity {}; + let mut backend = EVMBackend::from_root( + state_root, + Arc::clone(&self.trie_store), + Arc::clone(&self.storage), + vicinity, + ) + .map_err(|e| anyhow!("------ Could not restore backend {}", e))?; + Ok(AinExecutor::new(&mut backend).call( ExecutorContext { caller, to, @@ -75,17 +109,17 @@ impl EVMHandler { access_list, }, false, - ); - ( - tx_response.exit_reason, - tx_response.data, - tx_response.used_gas, - ) + )) } - // TODO wrap in EVM transaction and dryrun with evm_call - pub fn add_balance(&self, context: u64, address: H160, value: U256) { - self.tx_queues.add_balance(context, address, value) + pub fn add_balance( + &self, + context: u64, + address: H160, + value: U256, + ) -> Result<(), Box> { + self.tx_queues.add_balance(context, address, value)?; + Ok(()) } pub fn sub_balance( @@ -107,8 +141,11 @@ impl EVMHandler { // TODO Validate gas limit and chain_id let signed_tx: SignedTx = tx.try_into()?; - let account = self.get_account(signed_tx.sender); - if account.nonce > signed_tx.nonce() { + let nonce = self + .get_nonce(signed_tx.sender, U256::zero()) + .map_err(|_| anyhow!("Error getting nonce"))?; + + if nonce > signed_tx.nonce() { return Err(anyhow!("Invalid nonce").into()); } // TODO validate balance to pay gas @@ -124,23 +161,26 @@ impl EVMHandler { signed_tx.gas_limit().as_u64(), signed_tx.access_list(), ) { - (exit_reason, _, _) if exit_reason.is_succeed() => Ok(signed_tx), - (exit_reason, _, _) => Err(anyhow!("Error calling EVM {:?}", exit_reason).into()), + Ok(TxResponse { exit_reason, .. }) if exit_reason.is_succeed() => Ok(signed_tx), + Ok(TxResponse { exit_reason, .. }) => { + Err(anyhow!("Error calling EVM {:?}", exit_reason).into()) + } + Err(e) => Err(anyhow!("Error calling EVM {:?}", e).into()), } } pub fn get_context(&self) -> u64 { - let state = self.state.read().unwrap().clone(); - self.tx_queues.get_context(state) + self.tx_queues.get_context() } - pub fn discard_context(&self, context: u64) { - self.tx_queues.clear(context) + pub fn discard_context(&self, context: u64) -> Result<(), Box> { + self.tx_queues.clear(context)?; + Ok(()) } pub fn queue_tx(&self, context: u64, raw_tx: &str) -> Result<(), Box> { let signed_tx = self.validate_raw_tx(raw_tx)?; - self.tx_queues.add_signed_tx(context, signed_tx); + self.tx_queues.add_signed_tx(context, signed_tx)?; Ok(()) } @@ -155,43 +195,99 @@ impl EVMHandler { } impl EVMHandler { - pub fn get_account(&self, account: H160) -> MemoryAccount { - self.state - .read() - .unwrap() - .get(&account) - .unwrap_or(&Default::default()) - .to_owned() + pub fn get_account( + &self, + address: H160, + block_number: U256, + ) -> Result, EVMError> { + let state_root = self + .storage + .get_block_by_number(&block_number) + .or_else(|| self.storage.get_latest_block()) + .map(|block| block.header.state_root) + .unwrap_or_default(); + let vicinity = Vicinity {}; + + let backend = EVMBackend::from_root( + state_root, + Arc::clone(&self.trie_store), + Arc::clone(&self.storage), + vicinity, + )?; + Ok(backend.get_account(address)) } - pub fn get_code(&self, account: H160) -> Vec { - self.get_account(account).code + pub fn get_code(&self, address: H160, block_number: U256) -> Result>, EVMError> { + self.get_account(address, block_number).map(|opt_account| { + opt_account.map_or_else( + || None, + |account| self.storage.get_code_by_hash(account.code_hash), + ) + }) + } + + pub fn get_storage_at( + &self, + address: H160, + position: U256, + block_number: U256, + ) -> Result>, EVMError> { + self.get_account(address, block_number)? + .ok_or(EVMError::NoSuchAccount(address)) + .map(|account| { + let storage_trie = self + .trie_store + .trie_db + .trie_restore(address.as_bytes(), None, account.storage_root.into()) + .unwrap(); + + let tmp: &mut [u8; 32] = &mut [0; 32]; + position.to_big_endian(tmp); + storage_trie + .get(tmp.as_slice()) + .map_err(|e| EVMError::TrieError(format!("{e}"))) + })? } - pub fn get_storage(&self, account: H160) -> BTreeMap { - self.get_account(account).storage + pub fn get_balance(&self, address: H160, block_number: U256) -> Result { + self.get_account(address, block_number)? + .ok_or(EVMError::NoSuchAccount(address)) + .map(|account| account.balance) } - pub fn get_balance(&self, account: H160) -> U256 { - self.get_account(account).balance + pub fn get_nonce(&self, address: H160, block_number: U256) -> Result { + self.get_account(address, block_number)? + .ok_or(EVMError::NoSuchAccount(address)) + .map(|account| account.nonce) } - pub fn get_nonce(&self, account: H160) -> U256 { - self.get_account(account).nonce +} + +use std::fmt; +#[derive(Debug)] +pub enum EVMError { + BackendError(EVMBackendError), + NoSuchAccount(H160), + TrieError(String), +} + +impl fmt::Display for EVMError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + EVMError::BackendError(e) => write!(f, "EVMError: Backend error: {e}"), + EVMError::NoSuchAccount(address) => { + write!(f, "EVMError: No such acccount for address {address}") + } + EVMError::TrieError(e) => { + write!(f, "EVMError: Trie error {e}") + } + } } } -// TBD refine what vicinity we need. gas_price and origin only ? -pub fn get_vicinity(origin: Option, gas_price: Option) -> MemoryVicinity { - MemoryVicinity { - gas_price: gas_price.unwrap_or(U256::MAX), - origin: origin.unwrap_or_default(), - block_hashes: Vec::new(), - block_number: Default::default(), - block_coinbase: Default::default(), - block_timestamp: Default::default(), - block_difficulty: Default::default(), - block_gas_limit: U256::MAX, - chain_id: U256::one(), - block_base_fee_per_gas: U256::MAX, +impl From for EVMError { + fn from(e: EVMBackendError) -> Self { + EVMError::BackendError(e) } } + +impl std::error::Error for EVMError {} diff --git a/lib/ain-evm/src/executor.rs b/lib/ain-evm/src/executor.rs index d0a67d53d7..b4d3772c2b 100644 --- a/lib/ain-evm/src/executor.rs +++ b/lib/ain-evm/src/executor.rs @@ -1,8 +1,9 @@ use std::collections::BTreeMap; use crate::{ + backend::EVMBackendError, evm::EVMHandler, - traits::{Executor, ExecutorContext}, + traits::{BridgeBackend, Executor, ExecutorContext}, transaction::SignedTx, }; use ethereum::{EIP658ReceiptData, Log, ReceiptV3}; @@ -12,26 +13,31 @@ use evm::{ executor::stack::{MemoryStackState, StackExecutor, StackSubstateMetadata}, Config, ExitReason, }; +use primitive_types::H160; #[derive(Debug)] -pub struct AinExecutor { - backend: B, +pub struct AinExecutor<'backend, B: Backend> { + pub backend: &'backend mut B, } -impl AinExecutor +impl<'backend, B> AinExecutor<'backend, B> where - B: Backend + ApplyBackend, + B: Backend + ApplyBackend + BridgeBackend, { - pub fn new(backend: B) -> Self { + pub fn new(backend: &'backend mut B) -> Self { Self { backend } } - pub fn backend(&self) -> &B { - &self.backend + pub fn add_balance(&mut self, address: H160, amount: U256) -> Result<(), EVMBackendError> { + self.backend.add_balance(address, amount) + } + + pub fn sub_balance(&mut self, address: H160, amount: U256) -> Result<(), EVMBackendError> { + self.backend.sub_balance(address, amount) } } -impl Executor for AinExecutor +impl<'backend, B> Executor for AinExecutor<'backend, B> where B: Backend + ApplyBackend, { @@ -39,7 +45,7 @@ where fn call(&mut self, ctx: ExecutorContext, apply: bool) -> TxResponse { let metadata = StackSubstateMetadata::new(ctx.gas_limit, &Self::CONFIG); - let state = MemoryStackState::new(metadata, &self.backend); + let state = MemoryStackState::new(metadata, self.backend); let precompiles = BTreeMap::new(); // TODO Add precompile crate let mut executor = StackExecutor::new_with_precompiles(state, &Self::CONFIG, &precompiles); let access_list = ctx @@ -78,7 +84,7 @@ where EVMHandler::logs_bloom(logs.clone(), &mut bloom); bloom }, - status_code: exit_reason.is_succeed() as u8, + status_code: u8::from(exit_reason.is_succeed()), logs: logs.clone(), used_gas: U256::from(used_gas), }); diff --git a/lib/ain-evm/src/handler.rs b/lib/ain-evm/src/handler.rs index 5dca21977b..e020907574 100644 --- a/lib/ain-evm/src/handler.rs +++ b/lib/ain-evm/src/handler.rs @@ -1,22 +1,30 @@ +use crate::backend::{EVMBackend, Vicinity}; use crate::block::BlockHandler; -use crate::evm::{get_vicinity, EVMHandler}; +use crate::evm::EVMHandler; use crate::executor::{AinExecutor, TxResponse}; use crate::receipt::ReceiptHandler; +use crate::storage::traits::BlockStorage; use crate::storage::Storage; use crate::traits::Executor; +use crate::transaction::bridge::{BalanceUpdate, BridgeTx}; +use crate::tx_queue::QueueTx; use ethereum::{Block, BlockAny, PartialHeader, ReceiptV3, TransactionV2}; -use ethereum_types::{Bloom, H160, U256}; -use evm::backend::MemoryBackend; +use ethereum_types::{Bloom, H160, H64, U256}; +use log::debug; +use primitive_types::H256; use std::error::Error; use std::sync::Arc; use std::time::{SystemTime, UNIX_EPOCH}; +const GENESIS_STATE_ROOT: &str = + "0xbc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a"; + pub struct Handlers { pub evm: EVMHandler, pub block: BlockHandler, - pub storage: Arc, pub receipt: ReceiptHandler, + pub storage: Arc, } impl Default for Handlers { @@ -29,7 +37,7 @@ impl Handlers { pub fn new() -> Self { let storage = Arc::new(Storage::new()); Self { - evm: EVMHandler::new(), + evm: EVMHandler::new(Arc::clone(&storage)), block: BlockHandler::new(Arc::clone(&storage)), receipt: ReceiptHandler::new(Arc::clone(&storage)), storage, @@ -47,38 +55,68 @@ impl Handlers { let mut failed_transactions = Vec::with_capacity(self.evm.tx_queues.len(context)); let mut receipts_v3: Vec = Vec::with_capacity(self.evm.tx_queues.len(context)); let mut gas_used = 0u64; - let mut logs_bloom: Bloom = Default::default(); - - let vicinity = get_vicinity(None, None); - let state = self.evm.tx_queues.state(context).expect("Wrong context"); - let backend = MemoryBackend::new(&vicinity, state); - let mut executor = AinExecutor::new(backend); - - for signed_tx in self.evm.tx_queues.drain_all(context) { - let TxResponse { - exit_reason, - logs, - used_gas, - receipt, - .. - } = executor.exec(&signed_tx); - if exit_reason.is_succeed() { - all_transactions.push(signed_tx); - } else { - failed_transactions.push(signed_tx.transaction.clone()); - all_transactions.push(signed_tx); - } + let mut logs_bloom: Bloom = Bloom::default(); + + let state_root = self + .storage + .get_latest_block() + .map_or(GENESIS_STATE_ROOT.parse().unwrap(), |block| { + block.header.state_root + }); + + let vicinity = Vicinity {}; - gas_used += used_gas; - EVMHandler::logs_bloom(logs, &mut logs_bloom); - receipts_v3.push(receipt); + let mut backend = EVMBackend::from_root( + state_root, + Arc::clone(&self.evm.trie_store), + Arc::clone(&self.storage), + vicinity, + )?; + + let mut executor = AinExecutor::new(&mut backend); + + for queue_tx in self.evm.tx_queues.drain_all(context) { + match queue_tx { + QueueTx::SignedTx(signed_tx) => { + let TxResponse { + exit_reason, + logs, + used_gas, + receipt, + .. + } = executor.exec(&signed_tx); + if exit_reason.is_succeed() { + all_transactions.push(signed_tx); + } else { + failed_transactions.push(signed_tx.transaction.clone()); + all_transactions.push(signed_tx); + } + + gas_used += used_gas; + EVMHandler::logs_bloom(logs, &mut logs_bloom); + receipts_v3.push(receipt); + + executor.backend.commit(); + } + QueueTx::BridgeTx(BridgeTx::EvmIn(BalanceUpdate { address, amount })) => { + debug!( + "EvmIn for address {:x?}, amount: {}, context {}", + address, amount, context + ); + executor.add_balance(address, amount).unwrap(); // Need to return this fail tx somehow + } + QueueTx::BridgeTx(BridgeTx::EvmOut(BalanceUpdate { address, amount })) => { + debug!("EvmOut for address {}, amount: {}", address, amount); + executor.sub_balance(address, amount).unwrap(); // Need to return this fail tx somehow + } + } } self.evm.tx_queues.remove(context); - let (parent_hash, number) = self.block.get_latest_block_hash_and_number(); + let (parent_hash, parent_number) = self.block.get_latest_block_hash_and_number(); - let block = Block::new( + let mut block = Block::new( PartialHeader { parent_hash, beneficiary: miner_address.unwrap_or_default(), @@ -86,16 +124,16 @@ impl Handlers { receipts_root: ReceiptHandler::get_receipts_root(&receipts_v3), logs_bloom, difficulty: U256::from(difficulty), - number, + number: parent_number + 1, gas_limit: U256::from(30000000), gas_used: U256::from(gas_used), timestamp: SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap() .as_millis() as u64, - extra_data: Default::default(), - mix_hash: Default::default(), - nonce: Default::default(), + extra_data: Vec::default(), + mix_hash: H256::default(), + nonce: H64::default(), }, all_transactions .iter() @@ -112,9 +150,11 @@ impl Handlers { ); if update_state { - let mut state = self.evm.state.write().unwrap(); - *state = executor.backend().state().clone(); + let new_state_root = backend.commit(); + + debug!("new_state_root : {:#x}", new_state_root); + block.header.state_root = new_state_root; self.block.connect_block(block.clone()); self.receipt.put_receipts(receipts); } diff --git a/lib/ain-evm/src/lib.rs b/lib/ain-evm/src/lib.rs index ece1ec3f7d..f9e24b4227 100644 --- a/lib/ain-evm/src/lib.rs +++ b/lib/ain-evm/src/lib.rs @@ -1,3 +1,4 @@ +mod backend; mod block; mod ecrecover; pub mod evm; diff --git a/lib/ain-evm/src/receipt.rs b/lib/ain-evm/src/receipt.rs index 26da765a43..339291568b 100644 --- a/lib/ain-evm/src/receipt.rs +++ b/lib/ain-evm/src/receipt.rs @@ -49,7 +49,7 @@ impl ReceiptHandler { pub fn generate_receipts( &self, - transactions: &[SignedTx], + transactions: &[Box], receipts: Vec, block_hash: H256, block_number: U256, diff --git a/lib/ain-evm/src/storage/data_handler.rs b/lib/ain-evm/src/storage/data_handler.rs index b1ff501cb3..86f83d8cc9 100644 --- a/lib/ain-evm/src/storage/data_handler.rs +++ b/lib/ain-evm/src/storage/data_handler.rs @@ -15,6 +15,7 @@ pub static BLOCK_MAP_PATH: &str = "block_map.bin"; pub static BLOCK_DATA_PATH: &str = "block_data.bin"; pub static LATEST_BLOCK_DATA_PATH: &str = "latest_block_data.bin"; pub static RECEIPT_MAP_PATH: &str = "receipt_map.bin"; +pub static CODE_MAP_PATH: &str = "code_map.bin"; // pub static TRANSACTION_DATA_PATH: &str = "transaction_data.bin"; type BlockHashtoBlock = HashMap; @@ -22,11 +23,13 @@ type Blocks = HashMap; type TxHashToTx = HashMap; type LatestBlockNumber = U256; type TransactionHashToReceipt = HashMap; +type CodeHashToCode = HashMap>; impl PersistentState for BlockHashtoBlock {} impl PersistentState for Blocks {} impl PersistentState for LatestBlockNumber {} impl PersistentState for TransactionHashToReceipt {} +impl PersistentState for CodeHashToCode {} #[derive(Debug)] pub struct BlockchainDataHandler { @@ -38,6 +41,8 @@ pub struct BlockchainDataHandler { block_map: RwLock, blocks: RwLock, latest_block_number: RwLock>, + + code_map: RwLock, } impl BlockchainDataHandler { @@ -57,6 +62,9 @@ impl BlockchainDataHandler { TransactionHashToReceipt::load_from_disk(RECEIPT_MAP_PATH) .expect("Error loading receipts data"), ), + code_map: RwLock::new( + CodeHashToCode::load_from_disk(CODE_MAP_PATH).expect("Error loading code data"), + ), } } } @@ -73,8 +81,12 @@ impl TransactionStorage for BlockchainDataHandler { } fn get_transaction_by_hash(&self, _hash: &H256) -> Option { - // TODO: Feature flag - None // Unimplement without tx index + None + // self.transactions + // .read() + // .unwrap() + // .get(hash) + // .map(ToOwned::to_owned) } fn get_transaction_by_block_hash_and_index( @@ -184,6 +196,21 @@ impl FlushableStorage for BlockchainDataHandler { self.receipts .write() .unwrap() - .save_to_disk(RECEIPT_MAP_PATH) + .save_to_disk(RECEIPT_MAP_PATH)?; + self.code_map.write().unwrap().save_to_disk(CODE_MAP_PATH) + } +} + +impl BlockchainDataHandler { + pub fn get_code_by_hash(&self, hash: &H256) -> Option> { + self.code_map + .read() + .unwrap() + .get(hash) + .map(ToOwned::to_owned) + } + + pub fn put_code(&self, hash: &H256, code: &[u8]) -> Option> { + self.code_map.write().unwrap().insert(*hash, code.to_vec()) } } diff --git a/lib/ain-evm/src/storage/mod.rs b/lib/ain-evm/src/storage/mod.rs index 51a2ae78f7..d6cae1601c 100644 --- a/lib/ain-evm/src/storage/mod.rs +++ b/lib/ain-evm/src/storage/mod.rs @@ -74,7 +74,7 @@ impl BlockStorage for Storage { fn put_latest_block(&self, block: &BlockAny) { self.cache.put_latest_block(block); - self.blockchain_data_handler.put_latest_block(block) + self.blockchain_data_handler.put_latest_block(block); } } @@ -154,3 +154,13 @@ impl FlushableStorage for Storage { self.blockchain_data_handler.flush() } } + +impl Storage { + pub fn get_code_by_hash(&self, hash: H256) -> Option> { + self.blockchain_data_handler.get_code_by_hash(&hash) + } + + pub fn put_code(&self, hash: H256, code: Vec) -> Option> { + self.blockchain_data_handler.put_code(&hash, &code) + } +} diff --git a/lib/ain-evm/src/storage/traits.rs b/lib/ain-evm/src/storage/traits.rs index ad9649c092..6e35fb9420 100644 --- a/lib/ain-evm/src/storage/traits.rs +++ b/lib/ain-evm/src/storage/traits.rs @@ -2,6 +2,7 @@ use crate::receipt::Receipt; use ethereum::BlockAny; use ethereum::TransactionV2; use keccak_hash::H256; +use log::debug; use primitive_types::U256; use std::fs::File; @@ -54,7 +55,7 @@ pub trait PersistentState { Ok(path) => { let path = PathBuf::from(path).join("evm"); if !path.exists() { - std::fs::create_dir(&path).expect("Error creating `evm` dir") + std::fs::create_dir(&path).expect("Error creating `evm` dir"); } path.join(file_path) } @@ -71,6 +72,8 @@ pub trait PersistentState { where Self: Sized + serde::de::DeserializeOwned + Default, { + debug!("Restoring {} from disk", file_path); + // Automatically resolves from datadir for now let path = match ain_cpp_imports::get_datadir() { Ok(path) => PathBuf::from(path).join("evm").join(file_path), @@ -96,8 +99,8 @@ pub enum PersistentStateError { impl fmt::Display for PersistentStateError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - PersistentStateError::IoError(err) => write!(f, "IO error: {}", err), - PersistentStateError::BincodeError(err) => write!(f, "Bincode error: {}", err), + PersistentStateError::IoError(err) => write!(f, "IO error: {err}"), + PersistentStateError::BincodeError(err) => write!(f, "Bincode error: {err}"), } } } diff --git a/lib/ain-evm/src/traits.rs b/lib/ain-evm/src/traits.rs index 63ac57df4a..2552cc8129 100644 --- a/lib/ain-evm/src/traits.rs +++ b/lib/ain-evm/src/traits.rs @@ -1,4 +1,4 @@ -use crate::{executor::TxResponse, transaction::SignedTx}; +use crate::{backend::EVMBackendError, executor::TxResponse, transaction::SignedTx}; use ethereum::AccessList; use evm::Config; use primitive_types::{H160, U256}; @@ -19,3 +19,9 @@ pub trait Executor { fn exec(&mut self, tx: &SignedTx) -> TxResponse; } + +pub trait BridgeBackend { + fn add_balance(&mut self, address: H160, amount: U256) -> Result<(), EVMBackendError>; + + fn sub_balance(&mut self, address: H160, amount: U256) -> Result<(), EVMBackendError>; +} diff --git a/lib/ain-evm/src/transaction/bridge.rs b/lib/ain-evm/src/transaction/bridge.rs new file mode 100644 index 0000000000..e40f8e4a5f --- /dev/null +++ b/lib/ain-evm/src/transaction/bridge.rs @@ -0,0 +1,13 @@ +use primitive_types::{H160, U256}; + +#[derive(Debug)] +pub struct BalanceUpdate { + pub address: H160, + pub amount: U256, +} + +#[derive(Debug)] +pub enum BridgeTx { + EvmIn(BalanceUpdate), + EvmOut(BalanceUpdate), +} diff --git a/lib/ain-evm/src/transaction.rs b/lib/ain-evm/src/transaction/mod.rs similarity index 97% rename from lib/ain-evm/src/transaction.rs rename to lib/ain-evm/src/transaction/mod.rs index fb8a5ba09b..4823e7fc0f 100644 --- a/lib/ain-evm/src/transaction.rs +++ b/lib/ain-evm/src/transaction/mod.rs @@ -1,3 +1,4 @@ +pub mod bridge; use crate::ecrecover::{public_key_to_address, recover_public_key}; use ethereum::{ AccessList, EnvelopedDecoderError, LegacyTransaction, TransactionAction, TransactionSignature, @@ -137,7 +138,7 @@ impl TryFrom for SignedTx { }; let signing_message = libsecp256k1::Message::parse_slice(&msg.hash()[..]).unwrap(); let hash = H256::from(signing_message.serialize()); - recover_public_key(&hash, &tx.r, &tx.s, tx.odd_y_parity as u8) + recover_public_key(&hash, &tx.r, &tx.s, u8::from(tx.odd_y_parity)) } TransactionV2::EIP1559(tx) => { let msg = ethereum::EIP1559TransactionMessage { @@ -153,7 +154,7 @@ impl TryFrom for SignedTx { }; let signing_message = libsecp256k1::Message::parse_slice(&msg.hash()[..]).unwrap(); let hash = H256::from(signing_message.serialize()); - recover_public_key(&hash, &tx.r, &tx.s, tx.odd_y_parity as u8) + recover_public_key(&hash, &tx.r, &tx.s, u8::from(tx.odd_y_parity)) } }?; Ok(SignedTx { @@ -281,7 +282,7 @@ pub enum TransactionError { impl fmt::Display for TransactionError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { - TransactionError::Secp256k1Error(ref e) => write!(f, "Secp256k1 error: {}", e), + TransactionError::Secp256k1Error(ref e) => write!(f, "Secp256k1 error: {e}"), TransactionError::DecodingError => { write!(f, "Error decoding raw transaction") } @@ -289,7 +290,7 @@ impl fmt::Display for TransactionError { write!(f, "Error creating new signature") } TransactionError::FromHexError(ref e) => { - write!(f, "Error parsing hex: {}", e) + write!(f, "Error parsing hex: {e}") } } } diff --git a/lib/ain-evm/src/tx_queue.rs b/lib/ain-evm/src/tx_queue.rs index e3d8f81357..abfe58f888 100644 --- a/lib/ain-evm/src/tx_queue.rs +++ b/lib/ain-evm/src/tx_queue.rs @@ -5,9 +5,10 @@ use std::{ sync::{Mutex, RwLock}, }; -use crate::transaction::SignedTx; - -use crate::evm::EVMState; +use crate::transaction::{ + bridge::{BalanceUpdate, BridgeTx}, + SignedTx, +}; #[derive(Debug)] pub struct TransactionQueueMap { @@ -27,14 +28,14 @@ impl TransactionQueueMap { } } - pub fn get_context(&self, state: EVMState) -> u64 { + pub fn get_context(&self) -> u64 { let mut rng = rand::thread_rng(); loop { let context = rng.gen(); let mut write_guard = self.queues.write().unwrap(); if let std::collections::hash_map::Entry::Vacant(e) = write_guard.entry(context) { - e.insert(TransactionQueue::new(state)); + e.insert(TransactionQueue::new()); return context; } } @@ -44,36 +45,52 @@ impl TransactionQueueMap { self.queues.write().unwrap().remove(&context_id) } - pub fn clear(&self, context_id: u64) { - if let Some(queue) = self.queues.read().unwrap().get(&context_id) { - queue.clear() - } + pub fn clear(&self, context_id: u64) -> Result<(), QueueError> { + self.queues + .read() + .unwrap() + .get(&context_id) + .ok_or(QueueError::NoSuchContext) + .map(TransactionQueue::clear) } - pub fn add_signed_tx(&self, context_id: u64, signed_tx: SignedTx) { - if let Some(queue) = self.queues.read().unwrap().get(&context_id) { - queue.add_signed_tx(signed_tx) - } + pub fn add_signed_tx(&self, context_id: u64, signed_tx: SignedTx) -> Result<(), QueueError> { + self.queues + .read() + .unwrap() + .get(&context_id) + .ok_or(QueueError::NoSuchContext) + .map(|queue| queue.add_signed_tx(signed_tx)) } - pub fn drain_all(&self, context_id: u64) -> Vec { - match self.queues.read().unwrap().get(&context_id) { - Some(queue) => queue.drain_all(), - None => Vec::new(), - } + pub fn drain_all(&self, context_id: u64) -> Vec { + self.queues + .read() + .unwrap() + .get(&context_id) + .map_or(Vec::new(), TransactionQueue::drain_all) } pub fn len(&self, context_id: u64) -> usize { - match self.queues.read().unwrap().get(&context_id) { - Some(queue) => queue.len(), - None => 0, - } + self.queues + .read() + .unwrap() + .get(&context_id) + .map_or(0, TransactionQueue::len) } - pub fn add_balance(&self, context_id: u64, address: H160, value: U256) { - if let Some(queue) = self.queues.read().unwrap().get(&context_id) { - queue.add_balance(address, value) - } + pub fn add_balance( + &self, + context_id: u64, + address: H160, + value: U256, + ) -> Result<(), QueueError> { + self.queues + .read() + .unwrap() + .get(&context_id) + .ok_or(QueueError::NoSuchContext) + .map(|queue| queue.add_balance(address, value)) } pub fn sub_balance( @@ -82,94 +99,86 @@ impl TransactionQueueMap { address: H160, value: U256, ) -> Result<(), QueueError> { - if let Some(queue) = self.queues.read().unwrap().get(&context_id) { - queue.sub_balance(address, value) - } else { - Err(QueueError::NoSuchContext) - } - } - - pub fn state(&self, context_id: u64) -> Option { self.queues .read() .unwrap() .get(&context_id) - .map(|queue| queue.state()) + .ok_or(QueueError::NoSuchContext) + .map(|queue| queue.sub_balance(address, value)) } } #[derive(Debug)] +pub enum QueueTx { + SignedTx(Box), + BridgeTx(BridgeTx), +} + +#[derive(Debug, Default)] pub struct TransactionQueue { - transactions: Mutex>, - state: RwLock, + transactions: Mutex>, } impl TransactionQueue { - pub fn new(state: EVMState) -> Self { + pub fn new() -> Self { Self { transactions: Mutex::new(Vec::new()), - state: RwLock::new(state), } } pub fn clear(&self) { - self.transactions.lock().unwrap().clear() + self.transactions.lock().unwrap().clear(); } - pub fn drain_all(&self) -> Vec { + pub fn drain_all(&self) -> Vec { self.transactions .lock() .unwrap() .drain(..) - .collect::>() + .collect::>() } pub fn add_signed_tx(&self, signed_tx: SignedTx) { - self.transactions.lock().unwrap().push(signed_tx) + self.transactions + .lock() + .unwrap() + .push(QueueTx::SignedTx(Box::new(signed_tx))); } pub fn len(&self) -> usize { self.transactions.lock().unwrap().len() } - pub fn state(&self) -> EVMState { - self.state.read().unwrap().clone() - } - - pub fn add_balance(&self, address: H160, value: U256) { - let mut state = self.state.write().unwrap(); - let account = state.entry(address).or_default(); - account.balance += value; + pub fn add_balance(&self, address: H160, amount: U256) { + self.transactions + .lock() + .unwrap() + .push(QueueTx::BridgeTx(BridgeTx::EvmIn(BalanceUpdate { + address, + amount, + }))); } - pub fn sub_balance(&self, address: H160, value: U256) -> Result<(), QueueError> { - let mut state = self.state.write().unwrap(); - let account = state - .get_mut(&address) - .ok_or(QueueError::NoSuchAccount(address))?; - - if account.balance >= value { - account.balance -= value; - Ok(()) - } else { - Err(QueueError::InsufficientBalance) - } + pub fn sub_balance(&self, address: H160, amount: U256) { + self.transactions + .lock() + .unwrap() + .push(QueueTx::BridgeTx(BridgeTx::EvmOut(BalanceUpdate { + address, + amount, + }))); } } #[derive(Debug)] pub enum QueueError { NoSuchContext, - InsufficientBalance, - NoSuchAccount(H160), } impl std::fmt::Display for QueueError { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { QueueError::NoSuchContext => write!(f, "No transaction queue for this context"), - QueueError::InsufficientBalance => write!(f, "Insufficient balance"), - QueueError::NoSuchAccount(address) => write!(f, "No such account {}", address), } } } diff --git a/lib/ain-grpc/build.rs b/lib/ain-grpc/build.rs index b6ea8df1f5..793e71c010 100644 --- a/lib/ain-grpc/build.rs +++ b/lib/ain-grpc/build.rs @@ -391,7 +391,7 @@ fn fix_type(ty: &mut Type) { } } -/// Extracts "T" from std::option::Option for example +/// Extracts "T" from `std::option::Option` for example fn get_path_bracketed_ty_simple(ty: &Type) -> Type { match ty { Type::Path(ref p) => { diff --git a/lib/ain-grpc/src/block.rs b/lib/ain-grpc/src/block.rs index e2ddc86972..18964e2296 100644 --- a/lib/ain-grpc/src/block.rs +++ b/lib/ain-grpc/src/block.rs @@ -55,9 +55,9 @@ impl From for RpcBlock { uncles: vec![], nonce: U256::default(), extra_data: b.header.extra_data, - sha3_uncles: Default::default(), - logs_bloom: Default::default(), - size: format!("{:#x}", header_size), + sha3_uncles: String::default(), + logs_bloom: String::default(), + size: format!("{header_size:#x}"), } } } @@ -100,6 +100,7 @@ impl<'a> Deserialize<'a> for BlockNumber { impl BlockNumber { /// Convert block number to min block target. + #[must_use] pub fn convert_to_min_block_num(&self) -> Option { match *self { BlockNumber::Num(ref x) => Some(*x), @@ -119,10 +120,9 @@ impl Serialize for BlockNumber { hash, require_canonical, } => serializer.serialize_str(&format!( - "{{ 'hash': '{}', 'requireCanonical': '{}' }}", - hash, require_canonical + "{{ 'hash': '{hash}', 'requireCanonical': '{require_canonical}' }}" )), - BlockNumber::Num(ref x) => serializer.serialize_str(&format!("0x{:x}", x)), + BlockNumber::Num(ref x) => serializer.serialize_str(&format!("0x{x:x}")), BlockNumber::Latest => serializer.serialize_str("latest"), BlockNumber::Earliest => serializer.serialize_str("earliest"), BlockNumber::Pending => serializer.serialize_str("pending"), @@ -159,9 +159,8 @@ impl<'a> Visitor<'a> for BlockNumberVisitor { "blockNumber" => { let value: String = visitor.next_value()?; if let Some(stripped) = value.strip_prefix("0x") { - let number = u64::from_str_radix(stripped, 16).map_err(|e| { - Error::custom(format!("Invalid block number: {}", e)) - })?; + let number = u64::from_str_radix(stripped, 16) + .map_err(|e| Error::custom(format!("Invalid block number: {e}")))?; block_number = Some(number); break; @@ -177,7 +176,7 @@ impl<'a> Visitor<'a> for BlockNumberVisitor { "requireCanonical" => { require_canonical = visitor.next_value()?; } - key => return Err(Error::custom(format!("Unknown key: {}", key))), + key => return Err(Error::custom(format!("Unknown key: {key}"))), }, None => break, }; @@ -209,7 +208,7 @@ impl<'a> Visitor<'a> for BlockNumberVisitor { "finalized" => Ok(BlockNumber::Finalized), _ if value.starts_with("0x") => u64::from_str_radix(&value[2..], 16) .map(BlockNumber::Num) - .map_err(|e| Error::custom(format!("Invalid block number: {}", e))), + .map_err(|e| Error::custom(format!("Invalid block number: {e}"))), _ => value.parse::().map(BlockNumber::Num).map_err(|_| { Error::custom("Invalid block number: non-decimal or missing 0x prefix".to_string()) }), @@ -239,7 +238,7 @@ impl FromStr for BlockNumber { fn from_str(s: &str) -> Result { let visitor = BlockNumberVisitor; let result = visitor.visit_str(s).map_err(|e: serde::de::value::Error| { - serde_json::Error::custom(format!("Error while parsing BlockNumber: {}", e)) + serde_json::Error::custom(format!("Error while parsing BlockNumber: {e}")) }); result } diff --git a/lib/ain-grpc/src/codegen.rs b/lib/ain-grpc/src/codegen.rs index 6a03a8a062..09ae36b8f5 100644 --- a/lib/ain-grpc/src/codegen.rs +++ b/lib/ain-grpc/src/codegen.rs @@ -40,7 +40,7 @@ impl<'de> Deserialize<'de> for types::BlockResult { block: None, }), Res::Block(b) => Ok(types::BlockResult { - hash: "".into(), + hash: String::new(), block: Some(b), }), } @@ -79,7 +79,7 @@ impl<'de> Deserialize<'de> for types::Transaction { match Tx::deserialize(deserializer)? { Tx::Hash(s) => Ok(types::Transaction { hash: s, raw: None }), Tx::Raw(tx) => Ok(types::Transaction { - hash: "".into(), + hash: String::new(), raw: Some(tx), }), } @@ -96,9 +96,9 @@ mod tests { hash: "foobar".into(), block: None, }; - let res = serde_json::to_value(&foo).unwrap(); + let res = serde_json::to_value(foo).unwrap(); let foo2: BlockResult = serde_json::from_value(res).unwrap(); - assert_eq!(serde_json::to_value(&foo2).unwrap(), "foobar"); + assert_eq!(serde_json::to_value(foo2).unwrap(), "foobar"); } #[test] @@ -107,8 +107,8 @@ mod tests { hash: "booya".into(), raw: None, }; - let res = serde_json::to_value(&foo).unwrap(); + let res = serde_json::to_value(foo).unwrap(); let foo2: Transaction = serde_json::from_value(res).unwrap(); - assert_eq!(serde_json::to_value(&foo2).unwrap(), "booya"); + assert_eq!(serde_json::to_value(foo2).unwrap(), "booya"); } } diff --git a/lib/ain-grpc/src/impls.rs b/lib/ain-grpc/src/impls.rs index a04b8ddae3..e0efd656c4 100644 --- a/lib/ain-grpc/src/impls.rs +++ b/lib/ain-grpc/src/impls.rs @@ -8,15 +8,15 @@ use primitive_types::{H160, H256, U256}; use crate::codegen::types::{EthBlockInfo, EthPendingTransactionInfo, EthTransactionInfo}; fn format_hash(hash: H256) -> String { - format!("{:#x}", hash) + format!("{hash:#x}") } fn format_address(hash: H160) -> String { - format!("{:#x}", hash) + format!("{hash:#x}") } fn format_number(number: U256) -> String { - format!("{:#x}", number) + format!("{number:#x}") } impl From for EthBlockInfo { @@ -83,10 +83,10 @@ impl TryFrom<&str> for EthPendingTransactionInfo { String::from("null") }; - let input = if !signed_tx.data().is_empty() { - format!("0x{}", hex::encode(signed_tx.data())) - } else { + let input = if signed_tx.data().is_empty() { String::from("0x0") + } else { + format!("0x{}", hex::encode(signed_tx.data())) }; let pending_transaction = EthPendingTransactionInfo { diff --git a/lib/ain-grpc/src/lib.rs b/lib/ain-grpc/src/lib.rs index df73785222..2814ca61c2 100644 --- a/lib/ain-grpc/src/lib.rs +++ b/lib/ain-grpc/src/lib.rs @@ -2,13 +2,13 @@ extern crate serde; extern crate serde_json; -mod block; +pub mod block; mod call_request; mod codegen; mod impls; mod receipt; pub mod rpc; -pub use ain_evm::evm::EVMState; +// pub use ain_evm::evm::EVMState; use env_logger::{Builder as LogBuilder, Env, Target}; use jsonrpsee::core::server::rpc_module::Methods; diff --git a/lib/ain-grpc/src/rpc.rs b/lib/ain-grpc/src/rpc.rs index a0153bf63d..b53ef32279 100644 --- a/lib/ain-grpc/src/rpc.rs +++ b/lib/ain-grpc/src/rpc.rs @@ -3,7 +3,8 @@ use crate::call_request::CallRequest; use crate::codegen::types::{EthPendingTransactionInfo, EthTransactionInfo}; use crate::receipt::ReceiptResult; -use ain_evm::evm::EVMState; +// use ain_evm::evm::EVMState; +use ain_evm::executor::TxResponse; use ain_evm::handler::Handlers; use ain_evm::storage::traits::{BlockStorage, ReceiptStorage, TransactionStorage}; @@ -24,7 +25,7 @@ pub trait MetachainRPC { fn accounts(&self) -> RpcResult>; #[method(name = "eth_getBalance")] - fn get_balance(&self, address: H160) -> RpcResult; + fn get_balance(&self, address: H160, block_number: Option) -> RpcResult; #[method(name = "eth_getBlockByHash")] fn get_block_by_hash(&self, hash: H256) -> RpcResult>; @@ -78,23 +79,29 @@ pub trait MetachainRPC { fn get_pending_transaction(&self) -> RpcResult>; #[method(name = "eth_getCode")] - fn get_code(&self, address: H160) -> RpcResult; + fn get_code(&self, address: H160, block_number: Option) -> RpcResult; #[method(name = "eth_getStorageAt")] - fn get_storage_at(&self, address: H160, position: H256) -> RpcResult; + fn get_storage_at( + &self, + address: H160, + position: U256, + block_number: Option, + ) -> RpcResult; #[method(name = "eth_sendRawTransaction")] fn send_raw_transaction(&self, tx: &str) -> RpcResult; #[method(name = "eth_getTransactionCount")] - fn get_transaction_count(&self, address: H160) -> RpcResult; + fn get_transaction_count( + &self, + address: H160, + block_number: Option, + ) -> RpcResult; #[method(name = "eth_estimateGas")] fn estimate_gas(&self, input: CallRequest) -> RpcResult; - #[method(name = "mc_getState")] - fn get_state(&self) -> RpcResult; - #[method(name = "eth_gasPrice")] fn gas_price(&self) -> RpcResult; @@ -116,9 +123,43 @@ pub struct MetachainRPCModule { } impl MetachainRPCModule { + #[must_use] pub fn new(handler: Arc) -> Self { Self { handler } } + + fn block_number_to_u256(&self, block_number: Option) -> U256 { + match block_number.unwrap_or_default() { + BlockNumber::Hash { + hash, + .. + } => { + self.handler + .storage + .get_block_by_hash(&hash) + .map(|block| block.header.number) + .unwrap_or_default() + } + BlockNumber::Num(n) => { + self.handler + .storage + .get_block_by_number(&U256::from(n)) + .map(|block| block.header.number) + .unwrap_or_default() + }, + _ => { + self.handler + .storage + .get_latest_block() + .map(|block| block.header.number) + .unwrap_or_default() + } + // BlockNumber::Earliest => todo!(), + // BlockNumber::Pending => todo!(), + // BlockNumber::Safe => todo!(), + // BlockNumber::Finalized => todo!(), + } + } } impl MetachainRPCServer for MetachainRPCModule { @@ -131,14 +172,18 @@ impl MetachainRPCServer for MetachainRPCModule { data, .. } = input; - let (_, data, ..) = self.handler.evm.call( - from, - to, - value.unwrap_or_default(), - &data.unwrap_or_default(), - gas.unwrap_or_default().as_u64(), - vec![], - ); + let TxResponse { data, .. } = self + .handler + .evm + .call( + from, + to, + value.unwrap_or_default(), + &data.unwrap_or_default(), + gas.unwrap_or_default().as_u64(), + vec![], + ) + .map_err(|e| Error::Custom(format!("Error getting address balance : {e:?}")))?; Ok(hex::encode(data)) } @@ -148,11 +193,62 @@ impl MetachainRPCServer for MetachainRPCModule { Ok(accounts) } - fn get_balance(&self, address: H160) -> RpcResult { - debug!("Getting balance for address: {:?}", address); - Ok(self.handler.evm.get_balance(address)) + // State RPC + + fn get_balance(&self, address: H160, block_number: Option) -> RpcResult { + let block_number = self.block_number_to_u256(block_number); + debug!( + "Getting balance for address: {:?} at block : {} ", + address, block_number + ); + self.handler + .evm + .get_balance(address, block_number) + .map_err(|e| Error::Custom(format!("Error getting address balance : {e:?}"))) + } + + fn get_code(&self, address: H160, block_number: Option) -> RpcResult { + let block_number = self.block_number_to_u256(block_number); + + debug!( + "Getting code for address: {:?} at block : {}", + address, block_number + ); + + let code = self + .handler + .evm + .get_code(address, block_number) + .map_err(|e| Error::Custom(format!("Error getting address code : {e:?}")))?; + + match code { + Some(code) => Ok(format!("0x{}", hex::encode(code))), + None => Ok(String::from("0x")), + } } + fn get_storage_at( + &self, + address: H160, + position: U256, + block_number: Option, + ) -> RpcResult { + let block_number = self.block_number_to_u256(block_number); + debug!( + "Getting storage for address: {:?}, at position {:?}, for block {}", + address, position, block_number + ); + + self.handler + .evm + .get_storage_at(address, position, block_number) + .map_err(|e| Error::Custom(format!("Error getting address storage at : {e:?}")))? + .map_or(Ok(H256::default()), |storage| { + Ok(H256::from_slice(&storage)) + }) + } + // ------ + fn get_block_by_hash(&self, hash: H256) -> RpcResult> { self.handler .storage @@ -162,9 +258,9 @@ impl MetachainRPCServer for MetachainRPCModule { fn chain_id(&self) -> RpcResult { let chain_id = ain_cpp_imports::get_chain_id() - .map_err(|e| Error::Custom(format!("ain_cpp_imports::get_chain_id error : {:?}", e)))?; + .map_err(|e| Error::Custom(format!("ain_cpp_imports::get_chain_id error : {e:?}")))?; - Ok(format!("{:#x}", chain_id)) + Ok(format!("{chain_id:#x}")) } fn hash_rate(&self) -> RpcResult { @@ -173,9 +269,9 @@ impl MetachainRPCServer for MetachainRPCModule { fn net_version(&self) -> RpcResult { let chain_id = ain_cpp_imports::get_chain_id() - .map_err(|e| Error::Custom(format!("ain_cpp_imports::get_chain_id error : {:?}", e)))?; + .map_err(|e| Error::Custom(format!("ain_cpp_imports::get_chain_id error : {e:?}")))?; - Ok(format!("{}", chain_id)) + Ok(format!("{chain_id}")) } fn block_number(&self) -> RpcResult { @@ -196,26 +292,11 @@ impl MetachainRPCServer for MetachainRPCModule { _full_transaction: bool, ) -> RpcResult> { debug!("Getting block by number : {:#?}", block_number); - match block_number { - BlockNumber::Num(number) => { - let number = U256::from(number); - self.handler - .storage - .get_block_by_number(&number) - .map_or(Ok(None), |block| Ok(Some(block.into()))) - } - BlockNumber::Latest => self - .handler - .storage - .get_latest_block() - .map_or(Ok(None), |block| Ok(Some(block.into()))), - _ => Ok(None), - // BlockNumber::Hash { hash, require_canonical } => todo!(), - // BlockNumber::Earliest => todo!(), - // BlockNumber::Pending => todo!(), - // BlockNumber::Safe => todo!(), - // BlockNumber::Finalized => todo!(), - } + let block_number = self.block_number_to_u256(Some(block_number)); + self.handler + .storage + .get_block_by_number(&block_number) + .map_or(Ok(None), |block| Ok(Some(block.into()))) } fn mining(&self) -> RpcResult { @@ -283,63 +364,24 @@ impl MetachainRPCServer for MetachainRPCModule { .map_or(Ok(0), |b| Ok(b.transactions.len())) } - fn get_block_transaction_count_by_number(&self, number: BlockNumber) -> RpcResult { - match number { - BlockNumber::Pending => Ok(0), // TODO get from mempool ? - BlockNumber::Num(number) if number > 0 => self - .handler - .storage - .get_block_by_number(&U256::from(number)) - .map_or(Ok(0), |b| Ok(b.transactions.len())), - BlockNumber::Num(_) => Err(Error::Custom(String::from("Block number should be >= 0."))), - BlockNumber::Latest => self - .handler - .storage - .get_latest_block() - .map_or(Ok(0), |b| Ok(b.transactions.len())), - BlockNumber::Hash { - .. - // hash, - // require_canonical, - } => todo!(), - BlockNumber::Earliest => todo!(), - BlockNumber::Safe => todo!(), - BlockNumber::Finalized => todo!(), - } - } - - fn get_code(&self, address: H160) -> RpcResult { - debug!("Getting code for address: {:?}", address); - let code = self.handler.evm.get_code(address); - - if code.is_empty() { - return Ok(String::from("0x")); - } - - Ok(format!("{:#x?}", code)) - } - - fn get_storage_at(&self, address: H160, position: H256) -> RpcResult { - debug!( - "Getting storage for address: {:?}, at position {:?}", - address, position - ); - let storage = self.handler.evm.get_storage(address); - let &value = storage.get(&position).unwrap_or(&H256::zero()); - - Ok(format!("{:#x}", value)) + fn get_block_transaction_count_by_number(&self, block_number: BlockNumber) -> RpcResult { + let block_number = self.block_number_to_u256(Some(block_number)); + self.handler + .storage + .get_block_by_number(&block_number) + .map_or(Ok(0), |b| Ok(b.transactions.len())) } fn send_raw_transaction(&self, tx: &str) -> RpcResult { debug!("Sending raw transaction: {:?}", tx); let raw_tx = tx.strip_prefix("0x").unwrap_or(tx); let hex = - hex::decode(raw_tx).map_err(|e| Error::Custom(format!("Eror decoding TX {:?}", e)))?; + hex::decode(raw_tx).map_err(|e| Error::Custom(format!("Eror decoding TX {e:?}")))?; let stat = ain_cpp_imports::publish_eth_transaction(hex) - .map_err(|e| Error::Custom(format!("Error publishing TX {:?}", e)))?; + .map_err(|e| Error::Custom(format!("Error publishing TX {e:?}")))?; let signed_tx = - SignedTx::try_from(raw_tx).map_err(|e| Error::Custom(format!("TX error {:?}", e)))?; + SignedTx::try_from(raw_tx).map_err(|e| Error::Custom(format!("TX error {e:?}")))?; debug!( "Transaction status: {:?}, hash: {}", @@ -349,12 +391,23 @@ impl MetachainRPCServer for MetachainRPCModule { Ok(format!("{:#x}", signed_tx.transaction.hash())) } - fn get_transaction_count(&self, address: H160) -> RpcResult { + fn get_transaction_count( + &self, + address: H160, + block_number: Option, + ) -> RpcResult { debug!("Getting transaction count for address: {:?}", address); - let nonce = self.handler.evm.get_nonce(address); + let block_number = self.block_number_to_u256(block_number); + let nonce = self + .handler + .evm + .get_nonce(address, block_number) + .map_err(|e| { + Error::Custom(format!("Error getting address transaction count : {e:?}")) + })?; debug!("Count: {:#?}", nonce); - Ok(format!("{:#x}", nonce)) + Ok(format!("{nonce:#x}")) } fn estimate_gas(&self, input: CallRequest) -> RpcResult { @@ -367,14 +420,19 @@ impl MetachainRPCServer for MetachainRPCModule { .. } = input; - let (_, data, used_gas) = self.handler.evm.call( - from, - to, - value.unwrap_or_default(), - &data.unwrap_or_default(), - gas.unwrap_or_default().as_u64(), - vec![], - ); + let TxResponse { data, used_gas, .. } = self + .handler + .evm + .call( + from, + to, + value.unwrap_or_default(), + &data.unwrap_or_default(), + gas.unwrap_or_default().as_u64(), + vec![], + ) + .map_err(|e| Error::Custom(format!("Error calling EVM : {e:?}")))?; + let native_size = ain_cpp_imports::get_native_tx_size(data).unwrap_or(0); debug!("estimateGas: {:#?} + {:#?}", native_size, used_gas); Ok(format!( @@ -383,14 +441,10 @@ impl MetachainRPCServer for MetachainRPCModule { )) } - fn get_state(&self) -> RpcResult { - Ok(self.handler.evm.state.read().unwrap().clone()) - } - fn gas_price(&self) -> RpcResult { let gas_price = ain_cpp_imports::get_min_relay_tx_fee().unwrap_or(10); debug!("gasPrice: {:#?}", gas_price); - Ok(format!("{:#x}", gas_price)) + Ok(format!("{gas_price:#x}")) } fn get_receipt(&self, hash: H256) -> RpcResult> { diff --git a/lib/ain-rs-exports/src/lib.rs b/lib/ain-rs-exports/src/lib.rs index bff36b8cd7..edcf729310 100644 --- a/lib/ain-rs-exports/src/lib.rs +++ b/lib/ain-rs-exports/src/lib.rs @@ -1,5 +1,5 @@ -use ain_evm::*; -use ain_grpc::*; +use ain_evm::transaction; +use ain_grpc::{init_runtime, start_servers, stop_runtime}; use ain_evm::runtime::RUNTIME; use log::debug; @@ -9,7 +9,7 @@ use ethereum::{EnvelopedEncodable, TransactionAction, TransactionSignature}; use primitive_types::{H160, H256, U256}; use transaction::{LegacyUnsignedTransaction, TransactionError, LOWER_H256}; -pub const WEI_TO_GWEI: u64 = 1000000000; +pub const WEI_TO_GWEI: u64 = 1_000_000_000; pub const GWEI_TO_SATS: u64 = 10; #[cxx::bridge] @@ -26,13 +26,13 @@ pub mod ffi { } extern "Rust" { - fn evm_get_balance(address: &str) -> Result; + fn evm_get_balance(address: &str, block_number: [u8; 32]) -> Result; fn evm_add_balance(context: u64, address: &str, amount: [u8; 32]) -> Result<()>; fn evm_sub_balance(context: u64, address: &str, amount: [u8; 32]) -> Result; fn evm_validate_raw_tx(tx: &str) -> Result; fn evm_get_context() -> u64; - fn evm_discard_context(context: u64); + fn evm_discard_context(context: u64) -> Result<()>; fn evm_queue_tx(context: u64, raw_tx: &str) -> Result; fn evm_finalize( context: u64, @@ -80,9 +80,13 @@ pub fn create_and_sign_tx(ctx: ffi::CreateTransactionContext) -> Result, Ok(signed.encode().into()) } -pub fn evm_get_balance(address: &str) -> Result> { +pub fn evm_get_balance(address: &str, block_number: [u8; 32]) -> Result> { let account = address.parse()?; - let mut balance = RUNTIME.handlers.evm.get_balance(account); + let mut balance = RUNTIME + .handlers + .evm + .get_balance(account, U256::from(block_number)) + .unwrap_or_default(); // convert to try_evm_get_balance - Default to 0 for now balance /= WEI_TO_GWEI; balance /= GWEI_TO_SATS; Ok(balance.as_u64()) @@ -94,10 +98,11 @@ pub fn evm_add_balance( amount: [u8; 32], ) -> Result<(), Box> { let address = address.parse()?; + RUNTIME .handlers .evm - .add_balance(context, address, amount.into()); + .add_balance(context, address, amount.into())?; Ok(()) } @@ -121,19 +126,21 @@ pub fn evm_validate_raw_tx(tx: &str) -> Result> { match RUNTIME.handlers.evm.validate_raw_tx(tx) { Ok(_) => Ok(true), Err(e) => { - debug!("{:?}", e); + debug!("evm_validate_raw_tx fails with error: {:?}", e); Ok(false) } } } +#[must_use] pub fn evm_get_context() -> u64 { RUNTIME.handlers.evm.get_context() } -fn evm_discard_context(context: u64) { +fn evm_discard_context(context: u64) -> Result<(), Box> { // TODO discard - RUNTIME.handlers.evm.discard_context(context) + RUNTIME.handlers.evm.discard_context(context)?; + Ok(()) } fn evm_queue_tx(context: u64, raw_tx: &str) -> Result> { diff --git a/lib/labs-grpc2/proto/eth.proto b/lib/labs-grpc2/proto/eth.proto index 6f6979e131..61c1c6216a 100644 --- a/lib/labs-grpc2/proto/eth.proto +++ b/lib/labs-grpc2/proto/eth.proto @@ -3,10 +3,6 @@ package eth; import "google/protobuf/empty.proto"; -/* - This package is made for implementing the EVM RPCs here is the reference that we used to build them: - https://ethereum.github.io/execution-apis/api-documentation/ -*/ service Api { /// Returns eth_accounts list. rpc EthAccounts(google.protobuf.Empty) returns (EthAccountsResponse); @@ -63,76 +59,62 @@ service Api { rpc EthSendRawTransaction(EthSendRawTransactionRequest) returns (EthSendRawTransactionResponse); } -/* - This is the return of the RPC call: EthAccounts. - In case that there is no ethereum addresses, it will return an empty array. - Here is an example of the return of this proto message: - result: ["0x407d73d8a49eeb85d32cf465507dd71d507100c1",] - result: [] -*/ message EthAccountsResponse { - repeated string accounts = 1; // [Hex string] The list of accounts + repeated string accounts = 1; // The list of accounts (Hex) } message EthTransactionInfo { - optional string from = 1; // [Hex string] The address from which the transaction is sent - optional string to = 2; // [Hex string] The address to which the transaction is addressed + optional string from = 1; // The address from which the transaction is sent + optional string to = 2; // The address to which the transaction is addressed optional uint64 gas = 3; // The integer of gas provided for the transaction execution - optional string price = 4; // [Hex string] The integer of gas price used for each paid gas - optional string value = 5; // [Hex string] The integer of value sent with this transaction - optional string data = 6; // [Hex string] The hash of the method signature and encoded parameters. - optional string nonce = 7; // [Hex string] The integer of a nonce. This allows to overwrite your own pending transactions that use the same nonce. -} - -/* - This is the return of the RPC call: EthChainId - This RPC cannot return null or empty string - Here is an example of the return of this proto message: - result: "0x1" - result: "0x2" -*/ + optional string price = 4; // The integer of gas price used for each paid gas encoded as hexadecimal + optional string value = 5; // The integer of value sent with this transaction encoded as hexadecimal + optional string data = 6; // The hash of the method signature and encoded parameters. + optional string nonce = 7; // The integer of a nonce. This allows to overwrite your own pending transactions that use the same nonce. +} + message EthChainIdResponse { - string id = 1; // [Hex string] Integer of the current chain id. + string id = 1; // Hexadecimal value as a string representing the integer of the current chain id. } message EthBlockInfo { - string block_number = 1; // [Hex string] The block number. null when its pending block. - string hash = 2; // [Hex string] Hash of the block. null when its pending block. - string parent_hash = 3; // [Hex string] Hash of the parent block. - string nonce = 4; // [Hex string] Hash of the generated proof-of-work. null when its pending block. - string sha3_uncles = 5; // [Hex string] SHA3 of the uncles data in the block. - string logs_bloom = 6; // [Hex string] The bloom filter for the logs of the block. null when its pending block. - string transactions_root = 7; // [Hex string] The root of the transaction trie of the block. - string state_root = 8; // [Hex string] The root of the final state trie of the block. - string receipt_root = 9; // [Hex string] The root of the receipts trie of the block. - string miner = 10; // [Hex string] The address of the beneficiary to whom the mining rewards were given. - string difficulty = 11; // [Hex string] Integer of the difficulty for this block. - string total_difficulty = 12; // [Hex string] Integer of the total difficulty of the chain until this block. - string extra_data = 13; // [Hex string] The "extra data" field of this block. - string size = 14; // [Hex string] Integer the size of this block in bytes. - string gas_limit = 15; // [Hex string] The maximum gas allowed in this block. - string gas_used = 16; // [Hex string] The total used gas by all transactions in this block. - string timestamps = 17; // [Hex string] The unix timestamp for when the block was collated. - repeated string transactions = 18; // [Array Hex string] Array of transaction objects, or 32 Bytes transaction hashes depending on the last given parameter. - repeated string uncles = 19; // [Array Hex string] Array of uncle hashes. + string block_number = 1; // The block number. null when its pending block. + string hash = 2; // Hash of the block. null when its pending block. + string parent_hash = 3; // Hash of the parent block. + string nonce = 4; // Hash of the generated proof-of-work. null when its pending block. + string sha3_uncles = 5; // SHA3 of the uncles data in the block. + string logs_bloom = 6; // The bloom filter for the logs of the block. null when its pending block. + string transactions_root = 7; // The root of the transaction trie of the block. + string state_root = 8; // The root of the final state trie of the block. + string receipt_root = 9; // The root of the receipts trie of the block. + string miner = 10; // The address of the beneficiary to whom the mining rewards were given. + string difficulty = 11; // Integer of the difficulty for this block. + string total_difficulty = 12; // Integer of the total difficulty of the chain until this block. + string extra_data = 13; // The "extra data" field of this block. + string size = 14; // Integer the size of this block in bytes. + string gas_limit = 15; // The maximum gas allowed in this block. + string gas_used = 16; // The total used gas by all transactions in this block. + string timestamps = 17; // The unix timestamp for when the block was collated. + repeated string transactions = 18; // Array of transaction objects, or 32 Bytes transaction hashes depending on the last given parameter. + repeated string uncles = 19; // Array of uncle hashes. } message EthTransactionReceipt { - string transaction_hash = 1; // [Hex string] Hash of the transaction. - string transaction_index = 2; // [Hex string] Integer of the transactions index position in the block. - string block_hash = 3; // [Hex string] Hash of the block where this transaction was in. - string block_number = 4; // [Hex string] Block number where this transaction was in. - string from = 5; // [Hex string] Address of the sender. - string to = 6; // [Hex string] Address of the receiver. null when its a contract creation transaction. - string cumulative_gas_used = 7; // [Hex string] The total amount of gas used when this transaction was executed in the block. - string effective_gas_price = 8; // [Hex string] The sum of the base fee and tip paid per unit of gas. - string gas_used = 9; // [Hex string] The amount of gas used by this specific transaction alone. - string contract_address = 10; // [Hex string] The contract address created, if the transaction was a contract creation, otherwise null. - repeated string logs = 11; // [Array Hex string] Array of log objects, which this transaction generated. - string logs_bloom = 12; // [Hex string] Bloom filter for light clients to quickly retrieve related logs. - string type = 13; // [Hex string] Integer of the transaction type, 0x00 for legacy transactions, 0x01 for access list types, 0x02 for dynamic fees. It also returns either : - optional string root = 14; // [Hex string] 32 bytes of post-transaction stateroot (pre Byzantium) - optional string status = 15; // [Hex string] Either 1 (success) or 0 (failure) + string transaction_hash = 1; // Hash of the transaction. + string transaction_index = 2; // Integer of the transactions index position in the block. + string block_hash = 3; // Hash of the block where this transaction was in. + string block_number = 4; // Block number where this transaction was in. + string from = 5; // Address of the sender. + string to = 6; // Address of the receiver. null when its a contract creation transaction. + string cumulative_gas_used = 7; // The total amount of gas used when this transaction was executed in the block. + string effective_gas_price = 8; // The sum of the base fee and tip paid per unit of gas. + string gas_used = 9; // The amount of gas used by this specific transaction alone. + string contract_address = 10; // The contract address created, if the transaction was a contract creation, otherwise null. + repeated string logs = 11; // Array of log objects, which this transaction generated. + string logs_bloom = 12; // Bloom filter for light clients to quickly retrieve related logs. + string type = 13; // Integer of the transaction type, 0x00 for legacy transactions, 0x01 for access list types, 0x02 for dynamic fees. It also returns either : + optional string root = 14; // 32 bytes of post-transaction stateroot (pre Byzantium) + optional string status = 15; // Either 1 (success) or 0 (failure) } message EthCallRequest { @@ -140,581 +122,189 @@ message EthCallRequest { string block_number = 2; // Block number in hexadecimal format or the string latest, earliest, pending, safe or finalized } -/* - This is the return of the RPC call: EthCall. - Here is an example of the return of this proto message: - "result": "0x" - "result": "0xb1770efb14906e509893b6190359658208ae64d0c56e22f748a1b0869885559e" -*/ message EthCallResponse { - string data = 1; // [Hex string] The return value of the executed contract method + string data = 1; // The return value of the executed contract method } -/* - This is the request of the RPC call: EthSign. - Here is an example of the parameters of this proto message: - "params":["0x9b2055d370f73ec7d8a03e965129118dc8f5bf83", "0xdeadbeaf"] -*/ message EthSignRequest { - string address = 1; // [Hex string] Address you want to use to sign the message - string message = 2; // [Hex string] Value of the message that you want to sign + string address = 1; // Address you want to use to sign the message + string message = 2; // Hexadecimal value of the message that you want to sign } -/* - This is the return of the RPC call: EthSign. - Here is an example of the return of this proto message: - "result": "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b" -*/ message EthSignResponse { - string signature = 1; // [Hex string] Value of the signed message + string signature = 1; // Hexadecimal value of the signed message } -/* - This is the request of the RPC call: EthGetBalance. - Here is an example of the parameters of this proto message: - params: ["0x407d73d8a49eeb85d32cf465507dd71d507100c1", "latest"] - params: ["0x407d73d8a49eeb85d32cf465507dd71d507100c1", "0x20"] -*/ message EthGetBalanceRequest { - string address = 1; // [Hex string] Address you want to check the balance - string block_number = 2; // [Hex string] Integer block number, or the string "latest", "earliest" or "pending" + string address = 1; // Address you want to check the balance + string block_number = 2; // Integer block number, or the string "latest", "earliest" or "pending" (Hex) if it's the block number } -/* - This is the return of the RPC call: EthGetBalance. - This request will fail of the address or the block number is incorrect. - Here is an example of the return of this proto message: - "result": "0x0234c8a3397aab58" // 158972490234375000 -*/ message EthGetBalanceResponse { - string balance = 1; // [Hex string] Integer of the current balance in wei -} - -/* - This is the request of the RPC call: EthSendTransaction. - Here is an example of the parameters of this proto message: - params: [{ - from: "0xb60e8dd61c5d32be8058bb8eb970870f07233155", - to: "0xd46e8dd67c5d32be8058bb8eb970870f07244567", - gas: "0x76c0", // 30400 - gasPrice: "0x9184e72a000", // 10000000000000 - value: "0x9184e72a", // 2441406250 - data: "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675", - },] -*/ + string balance = 1; // Integer of the current balance in wei (Hex) +} + message EthSendTransactionRequest { EthTransactionInfo transaction_info = 1; // The transaction object } -/* - This is the return of the RPC call: EthSendTransaction. - This request will return "0x" if the transaction is not available yet. - Here is an example of the return of this proto message: - "result": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331" - "result": "0x" -*/ message EthSendTransactionResponse { - string hash = 1; // [Hex string] The transaction hash, or the zero hash if the transaction is not yet available + string hash = 1; // The transaction hash, or the zero hash if the transaction is not yet available } -/* - This is the return of the RPC call: EthCoinbase. - Here is an example of the return of this proto message: - "result": "0x407d73d8a49eeb85d32cf465507dd71d507100c1" -*/ message EthCoinBaseResponse { - string address = 1; // [Hex string] The current coinbase address + string address = 1; // The current coinbase address } -/* - This is the return of the RPC call: EthMining. - Here are the two possible return of this proto message: - "result": true - "result": false -*/ message EthMiningResponse { bool isMining = 1; // True if the client is mining, otherwise False } -/* - This is the return of the RPC call: EthHashRate. - This RPC will always return "0x" - "result": "0x" -*/ message EthHashRateResponse { - string hash_rate = 1; // [Hex string] Number of hashes per second + string hash_rate = 1; // Number of hashes per second (Hex) } -/* - This is the return of the RPC call: EthGasPrice. - Here is an example of the return of this proto message: - "result": "0x1dfd14000" // 8049999872 Wei -*/ message EthGasPriceResponse { - string gas_price = 1; // [Hex string] Integer of the current gas price in wei + string gas_price = 1; // Integer of the current gas price in wei (Hex) } -/* - This is the return of the RPC call: EthBlockNumber. - Here is an example of the return of this proto message: - "result": "0x4b7" // 1207 -*/ message EthBlockNumberResponse { - string block_number = 1; // [Hex string] Integer of the current block number the client is on + string block_number = 1; // Integer of the current block number the client is on (Hex) } -/* - This is the request of the RPC call: EthGetTransactionCount. - Here is an example of the parameters of this proto message: - params: ["0x407d73d8a49eeb85d32cf465507dd71d507100c1", "latest", // state at the latest block] - params: ["0x407d73d8a49eeb85d32cf465507dd71d507100c1", "0x20"] -*/ message EthGetTransactionCountRequest { string address = 1; - string block_number = 2; // [Hex string] Integer block number, or the string "latest", "earliest" or "pending" + string block_number = 2; // Integer block number, or the string "latest", "earliest" or "pending" (Hex) if it's the block number } -/* - This is the return of the RPC call: EthGetTransactionCount. - Here is an example of the return of this proto message: - "result": "0x1" // 1 -*/ message EthGetTransactionCountResponse { - string number_transaction = 1; // [Hex string] Integer of the number of transactions send from this address + string number_transaction = 1; // Integer of the number of transactions send from this address (Hex) } -/* - This is the request of the RPC call: EthGetBlockTransactionCountByHash. - Here is an example of the parameters of this proto message: - params: ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"] -*/ message EthGetBlockTransactionCountByHashRequest { - string block_hash = 1; // [Hex string] Hash of a block + string block_hash = 1; // Hash of a block (Hex) } -/* - This is the return of the RPC call: EthGetBlockTransactionCountByHash. - Here is an example of the return of this proto message: - "result": "0xb" // 11 -*/ message EthGetBlockTransactionCountByHashResponse { string number_transaction = 1; // Integer of the number of transactions in this block (Hex) } -/* - This is the request of the RPC call: EthGetBlockTransactionCountByNumber. - Here is an example of the parameters of this proto message: - "params":["0xe8"] - "params":["earliest"] -*/ message EthGetBlockTransactionCountByNumberRequest { - string block_number = 1; // [Hex string] Integer block number, or the string "latest", "earliest" or "pending" + string block_number = 1; // Integer block number, or the string "latest", "earliest" or "pending" (Hex) if it's the block number } -/* - This is the return of the RPC call: EthGetBlockTransactionCountByNumber. - Here is an example of the return of this proto message: - "result": "0xb" // 11 -*/ message EthGetBlockTransactionCountByNumberResponse { - string number_transaction = 1; // [Hex string] Integer of the number of transactions in this block + string number_transaction = 1; // Integer of the number of transactions in this block (Hex) } -/* - This is the request of the RPC call: EthGetUncleCountByBlockHash. - Here is an example of the parameters of this proto message: - params: ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"] -*/ message EthGetUncleCountByBlockHashRequest { - string block_hash = 1; // [Hex string] Hash of a block + string block_hash = 1; // Hash of a block (Hex) } -/* - This is the return of the RPC call: EthGetUncleCountByBlockHash. - Here is an example of the return of this proto message: - "result": "0x1" // 1 -*/ message EthGetUncleCountByBlockHashResponse { - string number_uncles = 1; // [Hex string] Integer of the number of uncles in this block + string number_uncles = 1; // Integer of the number of uncles in this block (Hex) } -/* - This is the request of the RPC call: EthGetUncleCountByBlockNumber. - Here is an example of the parameters of this proto message: - "params":["0xe8"] - "params":["pending"] -*/ message EthGetUncleCountByBlockNumberRequest { - string block_number = 1; // [Hex string] Integer block number, or the string "latest", "earliest" or "pending" + string block_number = 1; // Integer block number, or the string "latest", "earliest" or "pending" (Hex) if it's the block number } -/* - This is the return of the RPC call: EthGetUncleCountByBlockNumber. - Here is an example of the return of this proto message: - "result": "0x1" // 1 -*/ message EthGetUncleCountByBlockNumberResponse { - string number_uncles = 1; // [Hex string] Integer of the number of uncles in this block -} - -/* - This is the request of the RPC call: EthGetCode. - Here is an example of the parameters of this proto message: - params: [ - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "0x2", // 2 - ] - params: [ - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "pending", - ] -*/ + string number_uncles = 1; // Integer of the number of uncles in this block (Hex) +} + message EthGetCodeRequest { - string address = 1; // [Hex string] Address you wan to get the code from - string block_number = 2; // [Hex string] Integer block number, or the string "latest", "earliest" or "pending" + string address = 1; // Address you wan to get the code from + string block_number = 2; // Integer block number, or the string "latest", "earliest" or "pending" (Hex) if it's the block number } -/* - This is the return of the RPC call: EthGetCode. - Here is an example of the return of this proto message: - "result": "0x600160008035811a818181146012578301005b601b6001356025565b8060005260206000f25b600060078202905091905056" -*/ message EthGetCodeResponse { - string code = 1; // [Hex string] The code from the given address -} - -/* - This is the request of the RPC call: EthSignTransaction. - Here is an example of the parameters of this proto message: - "params": [{ - "data":"0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675", - "from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155", - "gas": "0x76c0", - "gasPrice": "0x9184e72a000", - "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", - "value": "0x9184e72a" - }] -*/ + string code = 1; // The code from the given address +} + message EthSignTransactionRequest { EthTransactionInfo transaction_info = 1; // The transaction object to be signed } -/* - This is the return of the RPC call: EthSignTransaction. - Here is an example of the return of this proto message: - "result": "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b" -*/ message EthSignTransactionResponse { - string transaction = 1; // [Hex string] The signed transaction object + string transaction = 1; // The signed transaction object } -/* - This is the request of the RPC call: EthSendRawTransaction. - Here is an example of the parameters of this proto message: - params: ["0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675",] -*/ message EthSendRawTransactionRequest { - string transaction = 1; // [Hex string] signed transaction + string transaction = 1; // Hexadecimal encoded signed transaction } -/* - This is the return of the RPC call: EthSendRawTransaction. - Here is an example of the return of this proto message: - "result": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331" - "result": "0x" -*/ message EthSendRawTransactionResponse { - string hash = 1; // [Hex string] The transaction hash, or the zero hash if the transaction is not yet available. + string hash = 1; // The transaction hash, or the zero hash if the transaction is not yet available. } message EthEstimateGasRequest { EthTransactionInfo transaction_info = 1; // Transaction info - optional string block_number = 2; // [Hex string] Block number or the string latest, earliest, pending, safe or finalized + optional string block_number = 2; // Block number in hexadecimal format or the string latest, earliest, pending, safe or finalized } -/* - This is the return of the RPC call: EthEstimateGas. - Here is an example of the return of this proto message: - "result": "0x5208" // 21000 -*/ message EthEstimateGasResponse { - string gas_used = 1; // [Hex string] The amount of gas used + string gas_used = 1; // The amount of gas used (Hex) } -/* - This is the request of the RPC call: EthGetBlockByHash. - Here is an example of the parameters of this proto message: - params: ["0xdc0818cf78f21a8e70579cb46a43643f78291264dda342ae31049421c82d21ae", false,] -*/ message EthGetBlockByHashRequest { - string hash = 1; // [Hex string] Hash of a block + string hash = 1; // Hash of a block (Hex) bool full_transaction = 2; // If true it returns the full transaction objects, if false only the hashes of the transactions } -/* - This is the return of the RPC call: EthGetBlockByHash. - Here is an example of the return of this proto message: - "result": { - "difficulty": "0x4ea3f27bc", - "extraData": "0x476574682f4c5649562f76312e302e302f6c696e75782f676f312e342e32", - "gasLimit": "0x1388", - "gasUsed": "0x0", - "hash": "0xdc0818cf78f21a8e70579cb46a43643f78291264dda342ae31049421c82d21ae", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0xbb7b8287f3f0a933474a79eae42cbca977791171", - "mixHash": "0x4fffe9ae21f1c9e15207b1f472d5bbdd68c9595d461666602f2be20daf5e7843", - "nonce": "0x689056015818adbe", - "number": "0x1b4", - "parentHash": "0xe99e022112df268087ea7eafaf4790497fd21dbeeb6bd7a1721df161a6657a54", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x220", - "stateRoot": "0xddc8b0234c2e0cad087c8b389aa7ef01f7d79b2570bccb77ce48648aa61c904d", - "timestamp": "0x55ba467c", - "totalDifficulty": "0x78ed983323d", - "transactions": [], - "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "uncles": [] - } -*/ message EthGetBlockByHashResponse { EthBlockInfo block_info = 1; // A block object, or null when no block was found } -/* - This is the request of the RPC call: EthGetBlockByNumber. - Here is an example of the parameters of this proto message: - params: [ - "0x1b4", // 436 - true, - ] -*/ message EthGetBlockByNumberRequest { - string number = 1; // [Hex string] Block number + string number = 1; // Block number (Hex) bool full_transaction = 2; // If true it returns the full transaction objects, if false only the hashes of the transactions } -/* - This is the return of the RPC call: EthGetBlockByNumber. - Here is an example of the return of this proto message: - "result": { - "difficulty": "0x4ea3f27bc", - "extraData": "0x476574682f4c5649562f76312e302e302f6c696e75782f676f312e342e32", - "gasLimit": "0x1388", - "gasUsed": "0x0", - "hash": "0xdc0818cf78f21a8e70579cb46a43643f78291264dda342ae31049421c82d21ae", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0xbb7b8287f3f0a933474a79eae42cbca977791171", - "mixHash": "0x4fffe9ae21f1c9e15207b1f472d5bbdd68c9595d461666602f2be20daf5e7843", - "nonce": "0x689056015818adbe", - "number": "0x1b4", - "parentHash": "0xe99e022112df268087ea7eafaf4790497fd21dbeeb6bd7a1721df161a6657a54", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x220", - "stateRoot": "0xddc8b0234c2e0cad087c8b389aa7ef01f7d79b2570bccb77ce48648aa61c904d", - "timestamp": "0x55ba467c", - "totalDifficulty": "0x78ed983323d", - "transactions": [], - "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "uncles": [] - } -*/ message EthGetBlockByNumberResponse { EthBlockInfo block_info = 1; // A block object, or null when no block was found } -/* - This is the request of the RPC call: EthGetTransactionByHash. - Here is an example of the parameters of this proto message: - params: ["0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b"] -*/ message EthGetTransactionByHashRequest { - string hash = 1; // [Hex string] Hash of the transaction -} - -/* - This is the return of the RPC call: EthGetTransactionByHash. - Here is an example of the return of this proto message: - "result":{ - "blockHash":"0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2", - "blockNumber":"0x5daf3b", // 6139707 - "from":"0xa7d9ddbe1f17865597fbd27ec712455208b6b76d", - "gas":"0xc350", // 50000 - "gasPrice":"0x4a817c800", // 20000000000 - "hash":"0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b", - "input":"0x68656c6c6f21", - "nonce":"0x15", // 21 - "to":"0xf02c1c8e6114b1dbe8937a39260b5b0a374432bb", - "transactionIndex":"0x41", // 65 - "value":"0xf3dbb76162000", // 4290000000000000 - "v":"0x25", // 37 - "r":"0x1b5e176d927f8e9ab405058b2d2457392da3e20f328b16ddabcebc33eaac5fea", - "s":"0x4ba69724e8f69de52f0125ad8b3c5c2cef33019bac3249e2c0a2192766d1721c" - } -*/ + string hash = 1; // Hash of the transaction +} + message EthGetTransactionByHashResponse { EthTransactionInfo transaction = 1; // A transaction object, or null when no transaction was found } -/* - This is the request of the RPC call: EthGetTransactionByBlockHashAndIndex. - Here is an example of the parameters of this proto message: - params: [ - "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331", - "0x0", // 0 - ] -*/ message EthGetTransactionByBlockHashAndIndexRequest { - string block_hash = 1; // [Hex string] Hash of a block - string index = 2; // [Hex string] Integer of the transaction index position -} - -/* - This is the return of the RPC call: EthGetTransactionByBlockHashAndIndex. - Here is an example of the return of this proto message: - "result":{ - "blockHash":"0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2", - "blockNumber":"0x5daf3b", // 6139707 - "from":"0xa7d9ddbe1f17865597fbd27ec712455208b6b76d", - "gas":"0xc350", // 50000 - "gasPrice":"0x4a817c800", // 20000000000 - "hash":"0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b", - "input":"0x68656c6c6f21", - "nonce":"0x15", // 21 - "to":"0xf02c1c8e6114b1dbe8937a39260b5b0a374432bb", - "transactionIndex":"0x41", // 65 - "value":"0xf3dbb76162000", // 4290000000000000 - "v":"0x25", // 37 - "r":"0x1b5e176d927f8e9ab405058b2d2457392da3e20f328b16ddabcebc33eaac5fea", - "s":"0x4ba69724e8f69de52f0125ad8b3c5c2cef33019bac3249e2c0a2192766d1721c" - } -*/ + string block_hash = 1; // Hash of a block + string index = 2; // Integer of the transaction index position (Hex) +} + message EthGetTransactionByBlockHashAndIndexResponse { EthTransactionInfo transaction = 1; // A transaction object, or null when no transaction was found } -/* - This is the request of the RPC call: EthGetTransactionByBlockNumberAndIndex. - Here is an example of the parameters of this proto message: - params: [ - "0x29c", // 668 - "0x0", // 0 - ] - params: ["lastest", "0x0",] -*/ message EthGetTransactionByBlockNumberAndIndexRequest { - string block_number = 1; // [Hex string] Integer block number, or the string "latest", "earliest" or "pending" - string index = 2; // [Hex string] Integer of the transaction index position -} - -/* - This is the return of the RPC call: EthGetTransactionByBlockNumberAndIndex. - Here is an example of the return of this proto message: - "result":{ - "blockHash":"0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2", - "blockNumber":"0x5daf3b", // 6139707 - "from":"0xa7d9ddbe1f17865597fbd27ec712455208b6b76d", - "gas":"0xc350", // 50000 - "gasPrice":"0x4a817c800", // 20000000000 - "hash":"0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b", - "input":"0x68656c6c6f21", - "nonce":"0x15", // 21 - "to":"0xf02c1c8e6114b1dbe8937a39260b5b0a374432bb", - "transactionIndex":"0x41", // 65 - "value":"0xf3dbb76162000", // 4290000000000000 - "v":"0x25", // 37 - "r":"0x1b5e176d927f8e9ab405058b2d2457392da3e20f328b16ddabcebc33eaac5fea", - "s":"0x4ba69724e8f69de52f0125ad8b3c5c2cef33019bac3249e2c0a2192766d1721c" - } -*/ + string block_number = 1; // Integer block number, or the string "latest", "earliest" or "pending" (Hex) if it's the block number + string index = 2; // Integer of the transaction index position (Hex) +} + message EthGetTransactionByBlockNumberAndIndexResponse { EthTransactionInfo transaction = 1; // A transaction object, or null when no transaction was found } -/* - This is the request of the RPC call: EthGetUncleByBlockHashAndIndex. - Here is an example of the parameters of this proto message: - params: [ - "0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b", - "0x0", // 0 - ] -*/ message EthGetUncleByBlockHashAndIndexRequest { - string block_hash = 1; // [Hex string] Hash of a block - string index = 2; // [Hex string] Integer of the transaction index position -} - -/* - This is the return of the RPC call: EthGetUncleByBlockHashAndIndex. - Here is an example of the return of this proto message: - "result": { - "difficulty": "0x4ea3f27bc", - "extraData": "0x476574682f4c5649562f76312e302e302f6c696e75782f676f312e342e32", - "gasLimit": "0x1388", - "gasUsed": "0x0", - "hash": "0xdc0818cf78f21a8e70579cb46a43643f78291264dda342ae31049421c82d21ae", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0xbb7b8287f3f0a933474a79eae42cbca977791171", - "mixHash": "0x4fffe9ae21f1c9e15207b1f472d5bbdd68c9595d461666602f2be20daf5e7843", - "nonce": "0x689056015818adbe", - "number": "0x1b4", - "parentHash": "0xe99e022112df268087ea7eafaf4790497fd21dbeeb6bd7a1721df161a6657a54", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x220", - "stateRoot": "0xddc8b0234c2e0cad087c8b389aa7ef01f7d79b2570bccb77ce48648aa61c904d", - "timestamp": "0x55ba467c", - "totalDifficulty": "0x78ed983323d", - "transactions": [], - "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "uncles": [] - } -*/ + string block_hash = 1; // Hash of a block + string index = 2; // Integer of the transaction index position (Hex) +} + message EthGetUncleByBlockHashAndIndexResponse { EthBlockInfo block_info = 1; // A block object, or null when no block was found } -/* - This is the request of the RPC call: EthGetUncleByBlockNumberAndIndex. - Here is an example of the parameters of this proto message: - params: [ - "0x29c", // 668 - "0x0", // 0 - ] - params: ["earliest", "0x0",] -*/ message EthGetUncleByBlockNumberAndIndexRequest { - string block_number = 1; // [Hex string] Integer block number, or the string "latest", "earliest" or "pending" - string index = 2; // [Hex string] Integer of the transaction index position -} - -/* - This is the return of the RPC call: EthGetUncleByBlockNumberAndIndex. - Here is an example of the return of this proto message: - "result": { - "difficulty": "0x4ea3f27bc", - "extraData": "0x476574682f4c5649562f76312e302e302f6c696e75782f676f312e342e32", - "gasLimit": "0x1388", - "gasUsed": "0x0", - "hash": "0xdc0818cf78f21a8e70579cb46a43643f78291264dda342ae31049421c82d21ae", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0xbb7b8287f3f0a933474a79eae42cbca977791171", - "mixHash": "0x4fffe9ae21f1c9e15207b1f472d5bbdd68c9595d461666602f2be20daf5e7843", - "nonce": "0x689056015818adbe", - "number": "0x1b4", - "parentHash": "0xe99e022112df268087ea7eafaf4790497fd21dbeeb6bd7a1721df161a6657a54", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x220", - "stateRoot": "0xddc8b0234c2e0cad087c8b389aa7ef01f7d79b2570bccb77ce48648aa61c904d", - "timestamp": "0x55ba467c", - "totalDifficulty": "0x78ed983323d", - "transactions": [], - "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "uncles": [] - } -*/ + string block_number = 1; // Integer block number, or the string "latest", "earliest" or "pending" (Hex) if it's the block number + string index = 2; // Integer of the transaction index position (Hex) +} + message EthGetUncleByBlockNumberAndIndexResponse { EthBlockInfo block_info = 1; // A block object, or null when no block was found } @@ -747,143 +337,69 @@ message EthCompileSerpentResponse { string compiled_code = 1; // The compiled source code } -/* - This is the return of the RPC call: EthProtocolVersion. - Here is an example of the return of this proto message: - "result": "54" -*/ message EthProtocolVersionResponse { string protocol_version = 1; // The current DMC protocol version } -/* - This is the request of the RPC call: Web3Sha3. - Here is an example of the parameters of this proto message: - params: ["0x68656c6c6f20776f726c64"] -*/ message Web3Sha3Request { - string data = 1; // [Hex string] The data to convert into a SHA3 hash + string data = 1; // The data to convert into a SHA3 hash } -/* - This is the return of the RPC call: Web3Sha3. - Here is an example of the return of this proto message: - "result": "0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad" -*/ message Web3Sha3Response { - string data = 1; // [Hex string] The SHA3 result of the given string. + string data = 1; // The SHA3 result of the given string. } -/* - This is the return of the RPC call: NetPeerCount. - Here is an example of the return of this proto message: - "result": "0x2" // 2 -*/ message NetPeerCountResponse { - string number_peer = 1; // [Hex string] Integer of the number of connected peers + string number_peer = 1; // Integer of the number of connected peers (Hex) } -/* - This is the return of the RPC call: NetVersion. - Here is an example of the return of this proto message: - "result": "3" -*/ message NetVersionResponse { string network_version = 1; // The current network id } -/* - This is the return of the RPC call: Web3ClientVersion. - Here is an example of the return of this proto message: - "result": "Mist/v0.9.3/darwin/go1.4.1" -*/ message Web3ClientVersionResponse { string client_version = 1; // The current client version } -// Return always "0x0" for all the fields message EthGetWorkResponse { string currentblock = 1; // Current block header pow-hash string seed_hash = 2; // The seed hash used for the DAG. string target = 3; // The boundary condition ("target"), 2^256 / difficulty. } -// This request will never succeed message EthSubmitWorkRequest { string nounce = 1; // The nonce found (64 bits) string pow_hash = 2; // The header's pow-hash (256 bits) string mix_digest = 3; // The mix digest (256 bits) } -// Will always return False message EthSubmitWorkResponse { bool is_valid = 1; // Returns true if the provided solution is valid, otherwise false } -// This request will never succeed message EthSubmitHashrateRequest { string hash_rate = 1; // Hexadecimal string representation (32 bytes) of the hashrate string id = 2; // A random hexadecimal(32 bytes) ID identifying the client } -// Will always return False message EthSubmitHashrateResponse { bool is_valid = 1; // Returns true if submitting went through successfully and false otherwise } -/* - This is the request of the RPC call: EthGetStorageAt. - Here is an example of the parameters of this proto message: - "params": ["0x295a70b2de5e3953354a6a8344e616ed314d7251", "0x0", "0xfa"] - "params": ["0x295a70b2de5e3953354a6a8344e616ed314d7251", "0x0", "latest"] -*/ message EthGetStorageAtRequest { - string address = 1; // [Hex string] Address of the storage - string position = 2; // [Hex string] integer of the position in the storage - string block_number = 3; // [Hex string] Integer block number, or the string "latest", "earliest" or "pending" + string address = 1; // Address of the storage + string position = 2; // integer of the position in the storage (Hex) + string block_number = 3; // Integer block number, or the string "latest", "earliest" or "pending" (Hex) if it's the block number } -/* - This is the return of the RPC call: EthGetStorageAt. - Here is an example of the return of this proto message: - "result":"0x00000000000000000000000000000000000000000000000000000000000004d2" -*/ message EthGetStorageAtResponse { - string value = 1; // [Hex string] The value at this storage position. + string value = 1; // The value at this storage position. } -/* - This is the request of the RPC call: EthGetTransactionReceipt. - Here is an example of the parameters of this proto message: - params: ["0x85d995eba9763907fdf35cd2034144dd9d53ce32cbec21349d4b12823c6860c5"] -*/ message EthGetTransactionReceiptRequest { - string transaction_hash = 1; // [Hex string] Hash of a transaction -} - -/* - This is the return of the RPC call: EthGetTransactionReceipt. - Here is an example of the return of this proto message: - "result": { - "blockHash":"0xa957d47df264a31badc3ae823e10ac1d444b098d9b73d204c40426e57f47e8c3", - "blockNumber": "0xeff35f", - "contractAddress": null, // string of the address if it was created - "cumulativeGasUsed": "0xa12515", - "effectiveGasPrice": "0x5a9c688d4", - "from": "0x6221a9c005f6e47eb398fd867784cacfdcfff4e7", - "gasUsed": "0xb4c8", - "logs": [{ - // logs as returned by getFilterLogs, etc. - }], - "logsBloom": "0x00...0", // 256 byte bloom filter - "status": "0x1", - "to": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", - "transactionHash": - "0x85d995eba9763907fdf35cd2034144dd9d53ce32cbec21349d4b12823c6860c5", - "transactionIndex": "0x66", - "type": "0x2" - } -*/ + string transaction_hash = 1; // Hash of a transaction +} + message EthGetTransactionReceiptResponse { EthTransactionReceipt transaction_receipt = 1; // A transaction receipt object, or null when no receipt was found } @@ -894,17 +410,6 @@ message EthSyncingInfo { string highest_block = 3; // The estimated highest block } -/* - This is the return of the RPC call: EthSyncing. - This request will return an object with the sync status data or false when not syncing. - Here is an example of the return of this proto message: - "result": { - startingBlock: '0x384', - currentBlock: '0x386', - highestBlock: '0x454' - } - "result": false -*/ message EthSyncingResponse { oneof value { bool status = 1; // Return False when not syncing diff --git a/src/masternodes/rpc_accounts.cpp b/src/masternodes/rpc_accounts.cpp index 6f41840430..09409c112a 100644 --- a/src/masternodes/rpc_accounts.cpp +++ b/src/masternodes/rpc_accounts.cpp @@ -586,7 +586,8 @@ UniValue gettokenbalances(const JSONRPCRequest& request) { if (eth_lookup) { for (const auto keyID : pwallet->GetEthKeys()) { - const auto evmAmount = evm_get_balance(HexStr(keyID.begin(), keyID.end())); + const arith_uint256 height = targetHeight; + const auto evmAmount = evm_get_balance(HexStr(keyID.begin(), keyID.end()), ArithToUint256(height).ToArrayReversed()); totalBalances.Add({{}, static_cast(evmAmount)}); } } diff --git a/src/masternodes/rpc_evm.cpp b/src/masternodes/rpc_evm.cpp index ba646013d3..eaa1c6ec12 100644 --- a/src/masternodes/rpc_evm.cpp +++ b/src/masternodes/rpc_evm.cpp @@ -3,6 +3,18 @@ #include #include +std::vector HexToBytes(const std::string& hex) { + std::vector bytes; + + for (unsigned int i = 0; i < hex.length(); i += 2) { + std::string byteString = hex.substr(i, 2); + uint8_t byte = (uint8_t) strtol(byteString.c_str(), NULL, 16); + bytes.push_back(byte); + } + + return bytes; +} + UniValue evmtx(const JSONRPCRequest& request) { auto pwallet = GetWallet(request); @@ -94,6 +106,7 @@ UniValue evmtx(const JSONRPCRequest& request) { std::copy(key.begin(), key.end(), privKey.begin()); const auto signedTx = create_and_sign_tx(CreateTransactionContext{chainID, nonce.ToArrayReversed(), gasPrice.ToArrayReversed(), gasLimit.ToArrayReversed(), to, value.ToArrayReversed(), input, privKey}); + std::vector evmTx(signedTx.size()); std::copy(signedTx.begin(), signedTx.end(), evmTx.begin()); @@ -120,11 +133,67 @@ UniValue evmtx(const JSONRPCRequest& request) { return send(MakeTransactionRef(std::move(rawTx)), optAuthTx)->GetHash().ToString(); } +UniValue evmrawtx(const JSONRPCRequest& request) { + auto pwallet = GetWallet(request); + + RPCHelpMan{"evmrawtx", + "Creates (and submits to local node and network) a tx to send DFI token to EVM address.\n" + + HelpRequiringPassphrase(pwallet) + "\n", + { + {"rawtx", RPCArg::Type::STR, RPCArg::Optional::NO, "EVM raw tx"}, + }, + RPCResult{ + "\"hash\" (string) The hex-encoded hash of broadcasted transaction\n" + }, + RPCExamples{ + HelpExampleCli("evmrawtx", R"('""')") + }, + }.Check(request); + + if (pwallet->chain().isInitialBlockDownload()) { + throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Cannot create transactions while still in Initial Block Download"); + } + pwallet->BlockUntilSyncedToCurrentChain(); + + int targetHeight; + { + LOCK(cs_main); + targetHeight = ::ChainActive().Height() + 1; + } + + const auto signedTx = request.params[0].get_str(); + + std::vector evmTx = HexToBytes(signedTx); + + CDataStream metadata(DfTxMarker, SER_NETWORK, PROTOCOL_VERSION); + metadata << static_cast(CustomTxType::EvmTx) + << CEvmTxMessage{evmTx}; + + CScript scriptMeta; + scriptMeta << OP_RETURN << ToByteVector(metadata); + + const auto txVersion = GetTransactionVersion(targetHeight); + CMutableTransaction rawTx(txVersion); + + rawTx.vin.resize(2); + rawTx.vin[0].scriptSig = CScript() << OP_0; + rawTx.vin[1].scriptSig = CScript() << OP_0; + + rawTx.vout.emplace_back(0, scriptMeta); + + // check execution + CTransactionRef optAuthTx; + execTestTx(CTransaction(rawTx), targetHeight, optAuthTx); + + return send(MakeTransactionRef(std::move(rawTx)), optAuthTx)->GetHash().ToString(); +} + static const CRPCCommand commands[] = { // category name actor (function) params // --------------- ---------------------- --------------------- ---------- {"evm", "evmtx", &evmtx, {"rawEvmTx", "inputs"}}, + {"evm", "evmrawtx", &evmrawtx, {"rawEvmTx", "inputs"}}, }; void RegisterEVMRPCCommands(CRPCTable& tableRPC) { diff --git a/test/functional/feature_evm_rpc.py b/test/functional/feature_evm_rpc.py index fd61476e45..1fce80dbe2 100755 --- a/test/functional/feature_evm_rpc.py +++ b/test/functional/feature_evm_rpc.py @@ -66,7 +66,7 @@ def setup(self): self.nodes[0].generate(4) self.nodes[0].getbalance() - self.nodes[0].utxostoaccount({self.address: "101@DFI"}) + self.nodes[0].utxostoaccount({self.address: "201@DFI"}) self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/feature/evm': 'true'}}) self.nodes[0].generate(1) @@ -108,9 +108,21 @@ def test_address_state(self, address): code = self.nodes[0].eth_getCode(address) assert_equal(code, "0x") + blockNumber = self.nodes[0].eth_blockNumber() + + self.nodes[0].transferbalance("evmin",{self.address:["50@DFI"]}, {self.ethAddress:["50@DFI"]}) + self.nodes[0].generate(1) + + balance = self.nodes[0].eth_getBalance(address, "latest") + assert_equal(balance, int_to_eth_u256(150)) + + balance = self.nodes[0].eth_getBalance(address, blockNumber) # Test querying previous block + assert_equal(balance, int_to_eth_u256(100)) + + def test_block(self): latest_block = self.nodes[0].eth_getBlockByNumber("latest", False) - assert_equal(latest_block['number'], "0x1") + assert_equal(latest_block['number'], "0x3") def run_test(self): self.setup() @@ -128,5 +140,6 @@ def run_test(self): self.test_block() + if __name__ == '__main__': EVMTest().main() diff --git a/test/functional/feature_evm_smart_contract.py b/test/functional/feature_evm_smart_contract.py new file mode 100755 index 0000000000..1ed6639ced --- /dev/null +++ b/test/functional/feature_evm_smart_contract.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python3 +# Copyright (c) 2014-2019 The Bitcoin Core developers +# Copyright (c) DeFi Blockchain Developers +# Distributed under the MIT software license, see the accompanying +# file LICENSE or http://www.opensource.org/licenses/mit-license.php. +"""Test EVM behaviour""" + +from test_framework.test_framework import DefiTestFramework +from test_framework.util import ( + assert_equal, + assert_raises_rpc_error +) + +# Utility function to assert value of U256 output +def int_to_eth_u256(value): + """ + Convert a non-negative integer to an Ethereum U256-compatible format. + + The input value is multiplied by a fixed factor of 10^18 (1 ether in wei) + and represented as a hexadecimal string. This function validates that the + input is a non-negative integer and checks if the converted value is within + the range of U256 values (0 to 2^256 - 1). If the input is valid and within + range, it returns the corresponding U256-compatible hexadecimal representation. + + Args: + value (int): The non-negative integer to convert. + + Returns: + str: The U256-compatible hexadecimal representation of the input value. + + Raises: + ValueError: If the input is not a non-negative integer or if the + converted value is outside the U256 range. + """ + if not isinstance(value, int) or value < 0: + raise ValueError("Value must be a non-negative integer") + + max_u256_value = 2**256 - 1 + factor = 10**18 + + converted_value = value * factor + if converted_value > max_u256_value: + raise ValueError(f"Value must be less than or equal to {max_u256_value}") + + return hex(converted_value) + +rawTx = "f9044e808502540be400832dc6c08080b903fb608060405234801561001057600080fd5b506103db806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063131a06801461003b5780632e64cec114610050575b600080fd5b61004e61004936600461015d565b61006e565b005b6100586100b5565b604051610065919061020e565b60405180910390f35b600061007a82826102e5565b507ffe3101cc3119e1fe29a9c3464a3ff7e98501e65122abab6937026311367dc516816040516100aa919061020e565b60405180910390a150565b6060600080546100c49061025c565b80601f01602080910402602001604051908101604052809291908181526020018280546100f09061025c565b801561013d5780601f106101125761010080835404028352916020019161013d565b820191906000526020600020905b81548152906001019060200180831161012057829003601f168201915b5050505050905090565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561016f57600080fd5b813567ffffffffffffffff8082111561018757600080fd5b818401915084601f83011261019b57600080fd5b8135818111156101ad576101ad610147565b604051601f8201601f19908116603f011681019083821181831017156101d5576101d5610147565b816040528281528760208487010111156101ee57600080fd5b826020860160208301376000928101602001929092525095945050505050565b600060208083528351808285015260005b8181101561023b5785810183015185820160400152820161021f565b506000604082860101526040601f19601f8301168501019250505092915050565b600181811c9082168061027057607f821691505b60208210810361029057634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156102e057600081815260208120601f850160051c810160208610156102bd5750805b601f850160051c820191505b818110156102dc578281556001016102c9565b5050505b505050565b815167ffffffffffffffff8111156102ff576102ff610147565b6103138161030d845461025c565b84610296565b602080601f83116001811461034857600084156103305750858301515b600019600386901b1c1916600185901b1785556102dc565b600085815260208120601f198616915b8281101561037757888601518255948401946001909101908401610358565b50858210156103955787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea2646970667358221220f5c9bb4feb3fa563cfe06a38d411044d98edf92f98726288036607edd71587b564736f6c634300081100332aa04ba71a6cfe81e1fc346a9720140e01bfff57a8712fbdd57394306dadf1668ac6a02407389762aa0e9c5dd4c79dc6c4fcf550eb6309fe3aaa776d45d5a5874b892c" + +class EVMTest(DefiTestFramework): + def set_test_params(self): + self.num_nodes = 1 + self.setup_clean_chain = True + self.extra_args = [ + ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', '-fortcanningepilogueheight=96', '-grandcentralheight=101', '-nextnetworkupgradeheight=105', '-subsidytest=1', '-txindex=1'], + ] + + def setup(self): + self.address = self.nodes[0].get_genesis_keys().ownerAuthAddress + self.ethAddress = self.nodes[0].getnewaddress("","eth") + self.to_address = self.nodes[0].getnewaddress("","eth") + + # Generate chain + self.nodes[0].generate(101) + + assert_raises_rpc_error(-32600, "called before NextNetworkUpgrade height", self.nodes[0].evmtx, self.ethAddress, 0, 21, 21000, self.to_address, 0.1) + + # Move to fork height + self.nodes[0].generate(4) + + self.nodes[0].getbalance() + self.nodes[0].utxostoaccount({self.address: "201@DFI"}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/feature/evm': 'true'}}) + self.nodes[0].generate(1) + + self.creationAddress = "0xe61a3a6eb316d773c773f4ce757a542f673023c6" + self.nodes[0].importprivkey("957ac3be2a08afe1fafb55bd3e1d479c4ae6d7bf1c9b2a0dcc5caad6929e6617") + + def test_deploy_smart_contract(self): + # deploy smart contract + self.nodes[0].evmrawtx(rawTx) + self.nodes[0].generate(1) + + # get smart contract address + blockNumber = self.nodes[0].eth_blockNumber() + block = self.nodes[0].eth_getBlockByNumber(blockNumber, False) + smartContractInfoReceipt = self.nodes[0].eth_getTransactionReceipt(block['transactions'][0]) + self.smartContractAddress = smartContractInfoReceipt["contractAddress"] + + code = self.nodes[0].eth_getCode(self.smartContractAddress) + assert_equal(code, "0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063131a06801461003b5780632e64cec114610050575b600080fd5b61004e61004936600461015d565b61006e565b005b6100586100b5565b604051610065919061020e565b60405180910390f35b600061007a82826102e5565b507ffe3101cc3119e1fe29a9c3464a3ff7e98501e65122abab6937026311367dc516816040516100aa919061020e565b60405180910390a150565b6060600080546100c49061025c565b80601f01602080910402602001604051908101604052809291908181526020018280546100f09061025c565b801561013d5780601f106101125761010080835404028352916020019161013d565b820191906000526020600020905b81548152906001019060200180831161012057829003601f168201915b5050505050905090565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561016f57600080fd5b813567ffffffffffffffff8082111561018757600080fd5b818401915084601f83011261019b57600080fd5b8135818111156101ad576101ad610147565b604051601f8201601f19908116603f011681019083821181831017156101d5576101d5610147565b816040528281528760208487010111156101ee57600080fd5b826020860160208301376000928101602001929092525095945050505050565b600060208083528351808285015260005b8181101561023b5785810183015185820160400152820161021f565b506000604082860101526040601f19601f8301168501019250505092915050565b600181811c9082168061027057607f821691505b60208210810361029057634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156102e057600081815260208120601f850160051c810160208610156102bd5750805b601f850160051c820191505b818110156102dc578281556001016102c9565b5050505b505050565b815167ffffffffffffffff8111156102ff576102ff610147565b6103138161030d845461025c565b84610296565b602080601f83116001811461034857600084156103305750858301515b600019600386901b1c1916600185901b1785556102dc565b600085815260208120601f198616915b8281101561037757888601518255948401946001909101908401610358565b50858210156103955787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea2646970667358221220f5c9bb4feb3fa563cfe06a38d411044d98edf92f98726288036607edd71587b564736f6c63430008110033") + + def test_smart_contract_address_state_balance(self): + initialBlockNumber = self.nodes[0].eth_blockNumber() + + balance = self.nodes[0].eth_getBalance(self.smartContractAddress) + assert_equal(balance, int_to_eth_u256(0)) + + self.nodes[0].transferbalance("evmin",{self.address:["50@DFI"]}, {self.smartContractAddress:["50@DFI"]}) + self.nodes[0].generate(1) + + balance = self.nodes[0].eth_getBalance(self.smartContractAddress, "latest") + assert_equal(balance, int_to_eth_u256(50)) + + balance = self.nodes[0].eth_getBalance(self.smartContractAddress, initialBlockNumber) # Test querying previous block + assert_equal(balance, int_to_eth_u256(0)) + + def test_smart_contract_address_state_storage(self): + initialBlockNumber = self.nodes[0].eth_blockNumber() + + storage = self.nodes[0].eth_getStorageAt(self.smartContractAddress, "0x0", "latest") + assert_equal(storage, "0x0000000000000000000000000000000000000000000000000000000000000000") + + # Call smart contract + callRawTx = "f8ca018502540be400832dc6c094e27a95f0d6fafa131927ac50861a4190f5a9c60b80b864131a06800000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d48656c6c6f2c20576f726c6421000000000000000000000000000000000000002aa06e2e1dc55471cbd7ec4b0f38822152b2dfb1c31f9f7bb17f0581e81b7ab1d978a05fef62334fec720c614c138d11b78f855cd0f53ad44b2d86ff1ee68c04cfbb65" + self.nodes[0].evmrawtx(callRawTx) + self.nodes[0].generate(1) + + storage = self.nodes[0].eth_getStorageAt(self.smartContractAddress, "0x0", "latest") + assert_equal(storage, "0x48656c6c6f2c20576f726c64210000000000000000000000000000000000001a") + + storage = self.nodes[0].eth_getStorageAt(self.smartContractAddress, "0x0", initialBlockNumber) # Test querying previous block + assert_equal(storage, "0x0000000000000000000000000000000000000000000000000000000000000000") + + def run_test(self): + self.setup() + + self.nodes[0].transferbalance("evmin",{self.address:["100@DFI"]}, {self.creationAddress:["100@DFI"]}) + self.nodes[0].generate(1) + + self.test_deploy_smart_contract() + + self.test_smart_contract_address_state_balance() + + self.test_smart_contract_address_state_storage() + +if __name__ == '__main__': + EVMTest().main() diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 69f6df10a8..de2bce0567 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -293,6 +293,7 @@ 'feature_loan.py', 'feature_evm.py', 'feature_evm_rpc.py', + 'feature_evm_smart_contract.py', 'feature_loan_low_interest.py', 'feature_loan_estimatecollateral.py', 'feature_vault_pct_check_factor.py',