diff --git a/Cargo.lock b/Cargo.lock index d8258af25..5b937788a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "anyhow" +version = "1.0.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602" + [[package]] name = "arrayvec" version = "0.7.2" @@ -52,12 +58,33 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + [[package]] name = "base64ct" version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea2b2456fd614d856680dcd9fcc660a51a820fa09daef2e49772b56a193c8474" +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitvec" version = "1.0.1" @@ -70,6 +97,15 @@ dependencies = [ "wyz", ] +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + [[package]] name = "block-buffer" version = "0.10.3" @@ -79,6 +115,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bstr" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +dependencies = [ + "memchr", +] + [[package]] name = "byte-slice-cast" version = "1.2.1" @@ -169,13 +214,22 @@ dependencies = [ "zeroize", ] +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + [[package]] name = "digest" version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" dependencies = [ - "block-buffer", + "block-buffer 0.10.3", "crypto-common", "subtle", ] @@ -201,7 +255,7 @@ dependencies = [ "base16ct", "crypto-bigint", "der", - "digest", + "digest 0.10.5", "ff", "generic-array", "group", @@ -328,12 +382,95 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "funty" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +[[package]] +name = "futures" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f21eda599937fba36daeb58a22e8f5cee2d14c4a17b5b7739c7c8e5e3b8230c" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf" + +[[package]] +name = "futures-io" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68" + +[[package]] +name = "futures-macro" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56" + +[[package]] +name = "futures-task" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1" + +[[package]] +name = "futures-util" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + [[package]] name = "generic-array" version = "0.14.6" @@ -355,6 +492,19 @@ dependencies = [ "wasi", ] +[[package]] +name = "globset" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" +dependencies = [ + "aho-corasick", + "bstr", + "fnv", + "log", + "regex", +] + [[package]] name = "group" version = "0.12.0" @@ -366,12 +516,46 @@ dependencies = [ "subtle", ] +[[package]] +name = "h2" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "heck" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + [[package]] name = "hex" version = "0.4.3" @@ -384,7 +568,65 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest", + "digest 0.10.5", +] + +[[package]] +name = "http" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "hyper" +version = "0.14.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", ] [[package]] @@ -425,12 +667,129 @@ dependencies = [ "syn", ] +[[package]] +name = "indexmap" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +dependencies = [ + "autocfg", + "hashbrown", +] + [[package]] name = "itoa" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" +[[package]] +name = "jsonrpsee" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bd0d559d5e679b1ab2f869b486a11182923863b1b3ee8b421763cdd707b783a" +dependencies = [ + "jsonrpsee-core", + "jsonrpsee-http-server", + "jsonrpsee-proc-macros", + "jsonrpsee-types", + "jsonrpsee-ws-server", + "tracing", +] + +[[package]] +name = "jsonrpsee-core" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3dc3e9cf2ba50b7b1d7d76a667619f82846caa39e8e8daa8a4962d74acaddca" +dependencies = [ + "anyhow", + "arrayvec", + "async-trait", + "beef", + "futures-channel", + "futures-util", + "globset", + "http", + "hyper", + "jsonrpsee-types", + "lazy_static", + "parking_lot", + "rand", + "rustc-hash", + "serde", + "serde_json", + "soketto", + "thiserror", + "tokio", + "tracing", + "unicase", +] + +[[package]] +name = "jsonrpsee-http-server" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03802f0373a38c2420c70b5144742d800b509e2937edc4afb116434f07120117" +dependencies = [ + "futures-channel", + "futures-util", + "hyper", + "jsonrpsee-core", + "jsonrpsee-types", + "serde", + "serde_json", + "tokio", + "tracing", + "tracing-futures", +] + +[[package]] +name = "jsonrpsee-proc-macros" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd67957d4280217247588ac86614ead007b301ca2fa9f19c19f880a536f029e3" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "jsonrpsee-types" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e290bba767401b646812f608c099b922d8142603c9e73a50fb192d3ac86f4a0d" +dependencies = [ + "anyhow", + "beef", + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "jsonrpsee-ws-server" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d488ba74fb369e5ab68926feb75a483458b88e768d44319f37e4ecad283c7325" +dependencies = [ + "futures-channel", + "futures-util", + "http", + "jsonrpsee-core", + "jsonrpsee-types", + "serde_json", + "soketto", + "tokio", + "tokio-stream", + "tokio-util", + "tracing", + "tracing-futures", +] + [[package]] name = "k256" version = "0.11.6" @@ -450,18 +809,55 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9b7d56ba4a8344d6be9729995e6b06f928af29998cdf79fe390cbf6b1fee838" +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.134" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb" +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + [[package]] name = "memchr" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "mio" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -481,12 +877,28 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "once_cell" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + [[package]] name = "parity-scale-codec" version = "3.2.1" @@ -513,6 +925,61 @@ dependencies = [ "syn", ] +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + +[[package]] +name = "pin-project" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "pkcs8" version = "0.9.0" @@ -631,6 +1098,15 @@ dependencies = [ "getrandom", ] +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + [[package]] name = "regex" version = "1.6.0" @@ -667,6 +1143,37 @@ dependencies = [ "ethers-core", ] +[[package]] +name = "reth-rpc" +version = "0.1.0" +dependencies = [ + "reth-primitives", + "reth-rpc-api", + "reth-rpc-types", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "reth-rpc-api" +version = "0.1.0" +dependencies = [ + "jsonrpsee", + "reth-primitives", + "reth-rpc-types", +] + +[[package]] +name = "reth-rpc-types" +version = "0.1.0" +dependencies = [ + "fastrlp", + "reth-primitives", + "serde", + "serde_json", +] + [[package]] name = "reth-stages" version = "0.1.0" @@ -719,6 +1226,12 @@ dependencies = [ "serde", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc-hex" version = "2.1.0" @@ -737,6 +1250,12 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + [[package]] name = "sec1" version = "0.3.0" @@ -782,6 +1301,19 @@ dependencies = [ "serde", ] +[[package]] +name = "sha-1" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + [[package]] name = "sha2" version = "0.10.6" @@ -790,7 +1322,7 @@ checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if", "cpufeatures", - "digest", + "digest 0.10.5", ] [[package]] @@ -799,7 +1331,7 @@ version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2904bea16a1ae962b483322a1c7b81d976029203aea1f461e51cd7705db7ba9" dependencies = [ - "digest", + "digest 0.10.5", "keccak", ] @@ -809,10 +1341,50 @@ version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "deb766570a2825fa972bceff0d195727876a9cdf2460ab2e52d455dc2de47fd9" dependencies = [ - "digest", + "digest 0.10.5", "rand_core", ] +[[package]] +name = "slab" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" + +[[package]] +name = "socket2" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "soketto" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" +dependencies = [ + "base64", + "bytes", + "futures", + "httparse", + "log", + "rand", + "sha-1", +] + [[package]] name = "spki" version = "0.6.0" @@ -903,6 +1475,61 @@ dependencies = [ "crunchy", ] +[[package]] +name = "tokio" +version = "1.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" +dependencies = [ + "autocfg", + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "pin-project-lite", + "socket2", + "tokio-macros", + "winapi", +] + +[[package]] +name = "tokio-macros" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-stream" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6edf2d6bc038a43d31353570e27270603f4648d18f5ed10c0e179abe43255af" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" +dependencies = [ + "bytes", + "futures-core", + "futures-io", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + [[package]] name = "toml" version = "0.5.9" @@ -912,6 +1539,60 @@ dependencies = [ "serde", ] +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + [[package]] name = "typenum" version = "1.15.0" @@ -930,6 +1611,15 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check", +] + [[package]] name = "unicode-ident" version = "1.0.4" @@ -948,12 +1638,87 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + [[package]] name = "wyz" version = "0.5.0" diff --git a/Cargo.toml b/Cargo.toml index 506f1e54d..9ec2f7668 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,8 +6,11 @@ edition = "2021" [workspace] members = [ "crate-template", - "crates/primitives", "crates/net/p2p", + "crates/net/rpc", + "crates/net/rpc-api", + "crates/net/rpc-types", + "crates/primitives", "crates/stages" ] diff --git a/crates/net/rpc-api/Cargo.toml b/crates/net/rpc-api/Cargo.toml new file mode 100644 index 000000000..1d0359189 --- /dev/null +++ b/crates/net/rpc-api/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "reth-rpc-api" +version = "0.1.0" +edition = "2021" +license = "MIT OR Apache-2.0" +repository = "https://github.com/foundry-rs/reth" +readme = "README.md" +description = """ +Reth RPC interfaces +""" + +[dependencies] +# reth +reth-primitives = { path = "../../primitives" } +reth-rpc-types = { path = "../rpc-types" } + +# misc +jsonrpsee = { version = "0.15", features = ["server", "macros"] } \ No newline at end of file diff --git a/crates/net/rpc-api/src/debug.rs b/crates/net/rpc-api/src/debug.rs new file mode 100644 index 000000000..8282b8bcd --- /dev/null +++ b/crates/net/rpc-api/src/debug.rs @@ -0,0 +1,27 @@ +use jsonrpsee::{core::RpcResult as Result, proc_macros::rpc}; +use reth_primitives::{BlockId, Bytes, H256}; +use reth_rpc_types::RichBlock; + +/// Debug rpc interface. +#[rpc(server)] +pub trait DebugApi { + /// Returns an RLP-encoded header. + #[method(name = "debug_getRawHeader")] + async fn raw_header(&self, block_id: BlockId) -> Result; + + /// Returns an RLP-encoded block. + #[method(name = "debug_getRawBlock")] + async fn raw_block(&self, block_id: BlockId) -> Result; + + /// Returns a EIP-2718 binary-encoded transaction. + #[method(name = "debug_getRawTransaction")] + async fn raw_transaction(&self, hash: H256) -> Result; + + /// Returns an array of EIP-2718 binary-encoded receipts. + #[method(name = "debug_getRawReceipts")] + async fn raw_receipts(&self, block_id: BlockId) -> Result>; + + /// Returns an array of recent bad blocks that the client has seen on the network. + #[method(name = "debug_getBadBlocks")] + async fn bad_blocks(&self) -> Result>; +} diff --git a/crates/net/rpc-api/src/engine.rs b/crates/net/rpc-api/src/engine.rs new file mode 100644 index 000000000..d7f7b28a6 --- /dev/null +++ b/crates/net/rpc-api/src/engine.rs @@ -0,0 +1,32 @@ +use jsonrpsee::{core::RpcResult as Result, proc_macros::rpc}; +use reth_primitives::H64; +use reth_rpc_types::engine::{ + ExecutionPayload, ForkchoiceState, ForkchoiceUpdated, PayloadAttributes, PayloadStatus, + TransitionConfiguration, +}; + +#[rpc(server)] +pub trait EngineApi { + /// See also + #[method(name = "engine_newPayloadV1")] + async fn new_payload(&self, payload: ExecutionPayload) -> Result; + + /// See also + #[method(name = "engine_forkchoiceUpdatedV1")] + async fn fork_choice_updated( + &self, + fork_choice_state: ForkchoiceState, + payload_attributes: Option, + ) -> Result; + + /// See also + #[method(name = "engine_getPayloadV1")] + async fn get_payload(&self, payload_id: H64) -> Result; + + /// See also + #[method(name = "engine_exchangeTransitionConfigurationV1")] + async fn exchange_transition_configuration( + &self, + transition_configuration: TransitionConfiguration, + ) -> Result; +} diff --git a/crates/net/rpc-api/src/eth.rs b/crates/net/rpc-api/src/eth.rs new file mode 100644 index 000000000..3e84de20c --- /dev/null +++ b/crates/net/rpc-api/src/eth.rs @@ -0,0 +1,225 @@ +use jsonrpsee::{ + core::{RpcResult as Result, __reexports::serde_json}, + proc_macros::rpc, +}; +use reth_primitives::{ + transaction::eip2930::AccessListWithGasUsed, Address, BlockId, BlockNumber, Bytes, H256, H64, + U256, U64, +}; +use reth_rpc_types::{ + CallRequest, EIP1186AccountProofResponse, FeeHistory, Index, RichBlock, SyncStatus, + Transaction, TransactionReceipt, TransactionRequest, Work, +}; + +/// Eth rpc interface. +#[rpc(server)] +#[async_trait] +pub trait EthApi { + /// Returns protocol version encoded as a string (quotes are necessary). + #[method(name = "eth_protocolVersion")] + fn protocol_version(&self) -> Result; + + /// Returns an object with data about the sync status or false. (wtf?) + #[method(name = "eth_syncing")] + fn syncing(&self) -> Result; + + /// Returns block author. + #[method(name = "eth_coinbase")] + fn author(&self) -> Result
; + + /// Returns accounts list. + #[method(name = "eth_accounts")] + fn accounts(&self) -> Result>; + + /// Returns highest block number. + #[method(name = "eth_blockNumber")] + fn block_number(&self) -> Result; + + /// Returns the chain ID used for transaction signing at the + /// current best block. None is returned if not + /// available. + #[method(name = "eth_chainId")] + fn chain_id(&self) -> Result>; + + /// Returns block with given hash. + #[method(name = "eth_getBlockByHash")] + async fn block_by_hash(&self, hash: H256, full: bool) -> Result>; + + /// Returns block with given number. + #[method(name = "eth_getBlockByNumber")] + async fn block_by_number(&self, number: BlockNumber, full: bool) -> Result>; + + /// Returns the number of transactions in a block with given hash. + #[method(name = "eth_getBlockTransactionCountByHash")] + fn block_transaction_count_by_hash(&self, hash: H256) -> Result>; + + /// Returns the number of transactions in a block with given block number. + #[method(name = "eth_getBlockTransactionCountByNumber")] + fn block_transaction_count_by_number(&self, number: BlockNumber) -> Result>; + + /// Returns the number of uncles in a block with given hash. + #[method(name = "eth_getUncleCountByBlockHash")] + fn block_uncles_count_by_hash(&self, hash: H256) -> Result; + + /// Returns the number of uncles in a block with given block number. + #[method(name = "eth_getUncleCountByBlockNumber")] + fn block_uncles_count_by_number(&self, number: BlockNumber) -> Result; + + /// Returns an uncles at given block and index. + #[method(name = "eth_getUncleByBlockHashAndIndex")] + fn uncle_by_block_hash_and_index(&self, hash: H256, index: Index) -> Result>; + + /// Returns an uncles at given block and index. + #[method(name = "eth_getUncleByBlockNumberAndIndex")] + fn uncle_by_block_number_and_index( + &self, + number: BlockNumber, + index: Index, + ) -> Result>; + + /// Get transaction by its hash. + #[method(name = "eth_getTransactionByHash")] + async fn transaction_by_hash(&self, hash: H256) -> Result>; + + /// Returns transaction at given block hash and index. + #[method(name = "eth_getTransactionByBlockHashAndIndex")] + async fn transaction_by_block_hash_and_index( + &self, + hash: H256, + index: Index, + ) -> Result>; + + /// Returns transaction by given block number and index. + #[method(name = "eth_getTransactionByBlockNumberAndIndex")] + async fn transaction_by_block_number_and_index( + &self, + number: BlockNumber, + index: Index, + ) -> Result>; + + /// Returns transaction receipt by transaction hash. + #[method(name = "eth_getTransactionReceipt")] + async fn transaction_receipt(&self, hash: H256) -> Result>; + + /// Returns balance of the given account. + #[method(name = "eth_getBalance")] + fn balance(&self, address: Address, block_number: Option) -> Result; + + /// Returns content of the storage at given address. + #[method(name = "eth_getStorageAt")] + fn storage_at( + &self, + address: Address, + index: U256, + block_number: Option, + ) -> Result; + + /// Returns the number of transactions sent from given address at given time (block number). + #[method(name = "eth_getTransactionCount")] + fn transaction_count(&self, address: Address, block_number: Option) -> Result; + + /// Returns the code at given address at given time (block number). + #[method(name = "eth_getCode")] + fn code_at(&self, address: Address, block_number: Option) -> Result; + + /// Call contract, returning the output data. + #[method(name = "eth_call")] + fn call(&self, request: CallRequest, block_number: Option) -> Result; + + /// This method creates an EIP2930 type accessList based on a given Transaction. The accessList + /// contains all storage slots and addresses read and written by the transaction, except for the + /// sender account and the precompiles. + /// + /// It returns list of addresses and storage keys used by the transaction, plus the gas + /// consumed when the access list is added. That is, it gives you the list of addresses and + /// storage keys that will be used by that transaction, plus the gas consumed if the access + /// list is included. Like eth_estimateGas, this is an estimation; the list could change + /// when the transaction is actually mined. Adding an accessList to your transaction does + /// not necessary result in lower gas usage compared to a transaction without an access + /// list. + #[method(name = "eth_createAccessList")] + async fn create_access_list( + &self, + request: CallRequest, + block_number: Option, + ) -> Result; + + /// Estimate gas needed for execution of given contract. + #[method(name = "eth_estimateGas")] + async fn estimate_gas( + &self, + request: CallRequest, + block_number: Option, + ) -> Result; + + /// Returns current gas_price. + #[method(name = "eth_gasPrice")] + fn gas_price(&self) -> Result; + + /// Introduced in EIP-1159 for getting information on the appropriate priority fee to use. + #[method(name = "eth_feeHistory")] + fn fee_history( + &self, + block_count: U256, + newest_block: BlockNumber, + reward_percentiles: Option>, + ) -> Result; + + /// Introduced in EIP-1159, a Geth-specific and simplified priority fee oracle. + /// Leverages the already existing fee history cache. + #[method(name = "eth_maxPriorityFeePerGas")] + fn max_priority_fee_per_gas(&self) -> Result; + + /// Returns true if client is actively mining new blocks. + #[method(name = "eth_mining")] + fn is_mining(&self) -> Result; + + /// Returns the number of hashes per second that the node is mining with. + #[method(name = "eth_hashrate")] + fn hashrate(&self) -> Result; + + /// Returns the hash of the current block, the seedHash, and the boundary condition to be met. + #[method(name = "eth_getWork")] + fn work(&self) -> Result; + + /// Used for submitting mining hashrate. + #[method(name = "eth_submitHashrate")] + fn submit_hashrate(&self, hashrate: U256, id: H256) -> Result; + + /// Used for submitting a proof-of-work solution. + #[method(name = "eth_submitWork")] + fn submit_work(&self, nonce: H64, pow_hash: H256, mix_digest: H256) -> Result; + + /// Sends transaction; will block waiting for signer to return the + /// transaction hash. + #[method(name = "eth_sendTransaction")] + async fn send_transaction(&self, request: TransactionRequest) -> Result; + + /// Sends signed transaction, returning its hash. + #[method(name = "eth_sendRawTransaction")] + async fn send_raw_transaction(&self, bytes: Bytes) -> Result; + + /// Returns an Ethereum specific signature with: sign(keccak256("\x19Ethereum Signed Message:\n" + /// + len(message) + message))). + #[method(name = "eth_sign")] + async fn sign(&self, address: Address, message: Bytes) -> Result; + + /// Signs a transaction that can be submitted to the network at a later time using with + /// `eth_sendRawTransaction.` + #[method(name = "eth_signTransaction")] + async fn sign_transaction(&self, transaction: CallRequest) -> Result; + + /// Signs data via [EIP-712](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md). + #[method(name = "eth_signTypedData")] + async fn sign_typed_data(&self, address: Address, data: serde_json::Value) -> Result; + + /// Returns the account and storage values of the specified account including the Merkle-proof. + /// This call can be used to verify that the data you are pulling from is not tampered with. + #[method(name = "eth_getProof")] + async fn get_proof( + &self, + address: Address, + keys: Vec, + block_number: Option, + ) -> Result; +} diff --git a/crates/net/rpc-api/src/eth_filter.rs b/crates/net/rpc-api/src/eth_filter.rs new file mode 100644 index 000000000..d76dbec64 --- /dev/null +++ b/crates/net/rpc-api/src/eth_filter.rs @@ -0,0 +1,35 @@ +use jsonrpsee::{core::RpcResult as Result, proc_macros::rpc}; +use reth_primitives::U256; +use reth_rpc_types::{Filter, FilterChanges, Index, Log}; + +/// Rpc Interface for poll-based ethereum filter API. +#[rpc(server)] +pub trait EthFilterApi { + /// Creates anew filter and returns its id. + #[method(name = "eth_newFilter")] + fn new_filter(&self, filter: Filter) -> Result; + + /// Creates a new block filter and returns its id. + #[method(name = "eth_newBlockFilter")] + fn new_block_filter(&self) -> Result; + + /// Creates a pending transaction filter and returns its id. + #[method(name = "eth_newPendingTransactionFilter")] + fn new_pending_transaction_filter(&self) -> Result; + + /// Returns all filter changes since last poll. + #[method(name = "eth_getFilterChanges")] + async fn filter_changes(&self, index: Index) -> Result; + + /// Returns all logs matching given filter (in a range 'from' - 'to'). + #[method(name = "eth_getFilterLogs")] + async fn filter_logs(&self, index: Index) -> Result>; + + /// Uninstalls filter. + #[method(name = "eth_uninstallFilter")] + fn uninstall_filter(&self, index: Index) -> Result; + + /// Returns logs matching given filter object. + #[method(name = "eth_getLogs")] + async fn logs(&self, filter: Filter) -> Result>; +} diff --git a/crates/net/rpc-api/src/eth_pubsub.rs b/crates/net/rpc-api/src/eth_pubsub.rs new file mode 100644 index 000000000..b0fccb728 --- /dev/null +++ b/crates/net/rpc-api/src/eth_pubsub.rs @@ -0,0 +1,14 @@ +use jsonrpsee::proc_macros::rpc; +use reth_rpc_types::pubsub::{Kind, Params}; + +/// Ethereum pub-sub rpc interface. +#[rpc(server)] +pub trait EthPubSubApi { + /// Create an ethereum subscription. + #[subscription( + name = "eth_subscribe" => "eth_subscription", + unsubscribe = "eth_unsubscribe", + item = pubsub::Result + )] + fn subscribe(&self, kind: Kind, params: Option); +} diff --git a/crates/net/rpc-api/src/lib.rs b/crates/net/rpc-api/src/lib.rs new file mode 100644 index 000000000..4da4cbeea --- /dev/null +++ b/crates/net/rpc-api/src/lib.rs @@ -0,0 +1,25 @@ +#![warn(missing_debug_implementations, missing_docs, unreachable_pub, unused_crate_dependencies)] +#![deny(unused_must_use, rust_2018_idioms)] +#![doc(test( + no_crate_inject, + attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables)) +))] + +//! Reth RPC interface definitions +//! +//! Provides all RPC interfaces. + +mod debug; +mod engine; +mod eth; +mod eth_filter; +mod eth_pubsub; +mod net; +mod trace; +mod web3; + +pub use self::{ + debug::DebugApiServer, engine::EngineApiServer, eth::EthApiServer, + eth_filter::EthFilterApiServer, eth_pubsub::EthPubSubApiServer, net::NetApiServer, + web3::Web3ApiServer, +}; diff --git a/crates/net/rpc-api/src/net.rs b/crates/net/rpc-api/src/net.rs new file mode 100644 index 000000000..fbe8599b2 --- /dev/null +++ b/crates/net/rpc-api/src/net.rs @@ -0,0 +1,19 @@ +use jsonrpsee::{core::RpcResult as Result, proc_macros::rpc}; +use reth_rpc_types::PeerCount; + +/// Net rpc interface. +#[rpc(server)] +pub trait NetApi { + /// Returns protocol version. + #[method(name = "net_version")] + fn version(&self) -> Result; + + /// Returns number of peers connected to node. + #[method(name = "net_peerCount")] + fn peer_count(&self) -> Result; + + /// Returns true if client is actively listening for network connections. + /// Otherwise false. + #[method(name = "net_listening")] + fn is_listening(&self) -> Result; +} diff --git a/crates/net/rpc-api/src/trace.rs b/crates/net/rpc-api/src/trace.rs new file mode 100644 index 000000000..7d990905a --- /dev/null +++ b/crates/net/rpc-api/src/trace.rs @@ -0,0 +1,73 @@ +use jsonrpsee::{core::RpcResult as Result, proc_macros::rpc}; +use reth_primitives::{BlockId, Bytes, H256}; +use reth_rpc_types::{ + trace::{filter::TraceFilter, parity::*}, + CallRequest, Index, +}; +use std::collections::HashSet; + +/// Ethereum trace API +#[rpc(server)] +pub trait TraceApi { + /// Executes the given call and returns a number of possible traces for it. + #[method(name = "trace_call")] + async fn call( + &self, + call: CallRequest, + trace_types: HashSet, + block_id: Option, + ) -> Result; + + /// Performs multiple call traces on top of the same block. i.e. transaction n will be executed + /// on top of a pending block with all n-1 transactions applied (traced) first. Allows to trace + /// dependent transactions. + #[method(name = "trace_callMany")] + async fn call_many( + &self, + calls: Vec<(CallRequest, HashSet)>, + block_id: Option, + ) -> Result>; + + /// Traces a call to `eth_sendRawTransaction` without making the call, returning the traces. + /// + /// Expects a raw transaction data + #[method(name = "trace_rawTransaction")] + async fn raw_transaction( + &self, + data: Bytes, + trace_types: HashSet, + block_id: Option, + ) -> Result; + + /// Replays all transactions in a block returning the requested traces for each transaction. + #[method(name = "trace_replayBlockTransactions")] + async fn replay_block_transactions( + &self, + block_id: BlockId, + trace_types: HashSet, + ) -> Result>>; + + /// Replays a transaction, returning the traces. + #[method(name = "trace_replayTransaction")] + async fn replay_transaction( + &self, + transaction: H256, + trace_types: HashSet, + ) -> Result; + + /// Returns traces created at given block. + #[method(name = "trace_block")] + async fn block(&self, block_id: BlockId) -> Result>>; + + /// Returns traces matching given filter + #[method(name = "trace_filter")] + async fn filter(&self, filter: TraceFilter) -> Result>; + + /// Returns transaction trace at given index. + #[method(name = "trace_get")] + fn trace(&self, hash: H256, indices: Vec) -> Result>; + + /// Returns all traces of given transaction. + #[method(name = "trace_transaction")] + fn transaction_traces(&self, hash: H256) -> Result>>; +} diff --git a/crates/net/rpc-api/src/web3.rs b/crates/net/rpc-api/src/web3.rs new file mode 100644 index 000000000..3d411b032 --- /dev/null +++ b/crates/net/rpc-api/src/web3.rs @@ -0,0 +1,14 @@ +use jsonrpsee::{core::RpcResult as Result, proc_macros::rpc}; +use reth_primitives::{Bytes, H256}; + +/// Web3 rpc interface. +#[rpc(server)] +pub trait Web3Api { + /// Returns current client version. + #[method(name = "web3_clientVersion")] + fn client_version(&self) -> Result; + + /// Returns sha3 of the given data. + #[method(name = "web3_sha3")] + fn sha3(&self, input: Bytes) -> Result; +} diff --git a/crates/net/rpc-types/Cargo.toml b/crates/net/rpc-types/Cargo.toml new file mode 100644 index 000000000..2fdbda370 --- /dev/null +++ b/crates/net/rpc-types/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "reth-rpc-types" +version = "0.1.0" +edition = "2021" +license = "MIT OR Apache-2.0" +repository = "https://github.com/foundry-rs/reth" +readme = "README.md" +description = """ +Reth RPC types +""" +[dependencies] +# reth +reth-primitives = { path = "../../primitives" } + +# eth +fastrlp = { version = "0.1" } + +# misc +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" \ No newline at end of file diff --git a/crates/net/rpc-types/src/eth/account.rs b/crates/net/rpc-types/src/eth/account.rs new file mode 100644 index 000000000..dab9ee9f0 --- /dev/null +++ b/crates/net/rpc-types/src/eth/account.rs @@ -0,0 +1,63 @@ +#![allow(missing_docs)] +use reth_primitives::{Address, Bytes, H256, H512, U256, U64}; +use serde::Serialize; + +/// Account information. +#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize)] +pub struct AccountInfo { + /// Account name + pub name: String, +} + +/// Data structure with proof for one single storage-entry +#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct StorageProof { + /// Storage key. + pub key: U256, + /// Value that the key holds + pub value: U256, + /// proof for the pair + pub proof: Vec, +} + +/// Response for EIP-1186 account proof `eth_getProof` +#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct EIP1186AccountProofResponse { + pub address: Address, + pub balance: U256, + pub code_hash: H256, + pub nonce: U64, + pub storage_hash: H256, + pub account_proof: Vec, + pub storage_proof: Vec, +} + +/// Extended account information (used by `parity_allAccountInfo`). +#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize)] +pub struct ExtAccountInfo { + /// Account name + pub name: String, + /// Account meta JSON + pub meta: String, + /// Account UUID (`None` for address book entries) + #[serde(skip_serializing_if = "Option::is_none")] + pub uuid: Option, +} + +/// account derived from a signature +/// as well as information that tells if it is valid for +/// the current chain +#[derive(Debug, Clone, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct RecoveredAccount { + /// address of the recovered account + pub address: Address, + /// public key of the recovered account + pub public_key: H512, + /// If the signature contains chain replay protection, + /// And the chain_id encoded within the signature + /// matches the current chain this would be true, otherwise false. + pub is_valid_for_current_chain: bool, +} diff --git a/crates/net/rpc-types/src/eth/block.rs b/crates/net/rpc-types/src/eth/block.rs new file mode 100644 index 000000000..00f977aa1 --- /dev/null +++ b/crates/net/rpc-types/src/eth/block.rs @@ -0,0 +1,119 @@ +use reth_primitives::{Address, Bloom, Bytes, Transaction, H256, H64, U256}; +use serde::{ser::Error, Serialize, Serializer}; +use std::{collections::BTreeMap, ops::Deref}; + +/// Block Transactions depending on the boolean attribute of `eth_getBlockBy*` +#[derive(Debug, Clone, Eq, PartialEq, Serialize)] +#[serde(untagged)] +pub enum BlockTransactions { + /// Only hashes + Hashes(Vec), + /// Full transactions + Full(Vec), +} + +/// Block representation +#[derive(Debug, Clone, Eq, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct Block { + /// Header of the block + #[serde(flatten)] + pub header: Header, + /// Total difficulty + pub total_difficulty: U256, + /// Uncles' hashes + pub uncles: Vec, + /// Transactions + pub transactions: BlockTransactions, + /// Size in bytes + pub size: Option, + /// Base Fee for post-EIP1559 blocks. + #[serde(skip_serializing_if = "Option::is_none")] + pub base_fee_per_gas: Option, +} + +/// Block header representation. +#[derive(Debug, Clone, Serialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct Header { + /// Hash of the block + pub hash: Option, + /// Hash of the parent + pub parent_hash: H256, + /// Hash of the uncles + #[serde(rename = "sha3Uncles")] + pub uncles_hash: H256, + /// Authors address + pub author: Address, + /// Alias of `author` + pub miner: Address, + /// State root hash + pub state_root: H256, + /// Transactions root hash + pub transactions_root: H256, + /// Transactions receipts root hash + pub receipts_root: H256, + /// Block number + pub number: Option, + /// Gas Used + pub gas_used: U256, + /// Gas Limit + pub gas_limit: U256, + /// Extra data + pub extra_data: Bytes, + /// Logs bloom + pub logs_bloom: Bloom, + /// Timestamp + pub timestamp: U256, + /// Difficulty + pub difficulty: U256, + /// Nonce + pub nonce: Option, + /// Size in bytes + pub size: Option, +} + +/// A Block representation that allows to include additional fields +pub type RichBlock = Rich; + +/// Header representation with additional info. +pub type RichHeader = Rich
; + +/// Value representation with additional info +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Rich { + /// Standard value. + pub inner: T, + /// Additional fields that should be serialized into the `Block` object + pub extra_info: BTreeMap, +} + +impl Deref for Rich { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl Serialize for Rich { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + if self.extra_info.is_empty() { + return self.inner.serialize(serializer) + } + + let inner = serde_json::to_value(&self.inner); + let extras = serde_json::to_value(&self.extra_info); + + if let (Ok(serde_json::Value::Object(mut value)), Ok(serde_json::Value::Object(extras))) = + (inner, extras) + { + value.extend(extras); + value.serialize(serializer) + } else { + Err(S::Error::custom("Unserializable structures: expected objects")) + } + } +} diff --git a/crates/net/rpc-types/src/eth/call.rs b/crates/net/rpc-types/src/eth/call.rs new file mode 100644 index 000000000..568fd3a81 --- /dev/null +++ b/crates/net/rpc-types/src/eth/call.rs @@ -0,0 +1,31 @@ +use reth_primitives::{transaction::eip2930::AccessListItem, Address, Bytes, U256}; +use serde::Deserialize; + +/// Call request +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize)] +#[serde(default, rename_all = "camelCase", deny_unknown_fields)] +pub struct CallRequest { + /// From + pub from: Option
, + /// To + pub to: Option
, + /// Gas Price + pub gas_price: Option, + /// EIP-1559 Max base fee the caller is willing to pay + pub max_fee_per_gas: Option, + /// EIP-1559 Priority fee the caller is paying to the block author + pub max_priority_fee_per_gas: Option, + /// Gas + pub gas: Option, + /// Value + pub value: Option, + /// Data + pub data: Option, + /// Nonce + pub nonce: Option, + /// AccessList + pub access_list: Option>, + /// EIP-2718 type + #[serde(rename = "type")] + pub transaction_type: Option, +} diff --git a/crates/net/rpc-types/src/eth/engine.rs b/crates/net/rpc-types/src/eth/engine.rs new file mode 100644 index 000000000..2559f4067 --- /dev/null +++ b/crates/net/rpc-types/src/eth/engine.rs @@ -0,0 +1,89 @@ +#![allow(missing_docs)] +//! Engine API types: + +use reth_primitives::{Address, BlockNumber, Bloom, Bytes, H256, H64, U256, U64}; +use serde::{Deserialize, Serialize}; + +/// This structure maps on the ExecutionPayload structure of the beacon chain spec. +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ExecutionPayload { + pub parent_hash: H256, + pub fee_recipient: Address, + pub state_root: H256, + pub receipts_root: H256, + pub logs_bloom: Bloom, + pub prev_randao: H256, + pub block_number: U64, + pub gas_limit: U64, + pub gas_used: U64, + pub timestamp: U64, + pub extra_data: Bytes, + pub base_fee_per_gas: U256, + pub block_hash: H256, + pub transactions: Vec, +} + +/// This structure encapsulates the fork choice state +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ForkchoiceState { + pub head_block_hash: H256, + pub safe_block_hash: H256, + pub finalized_block_hash: H256, +} + +/// This structure contains the attributes required to initiate a payload build process in the +/// context of an `engine_forkchoiceUpdated` call. +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PayloadAttributes { + pub timestamp: U64, + pub prev_randao: H256, + pub suggested_fee_recipient: Address, +} + +/// This structure contains the result of processing a payload +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PayloadStatus { + #[serde(flatten)] + pub status: PayloadStatusEnum, + /// Hash of the most recent valid block in the branch defined by payload and its ancestors + pub latest_valid_hash: Option, +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "status", rename_all = "SCREAMING_SNAKE_CASE")] +pub enum PayloadStatusEnum { + Valid, + Invalid { + #[serde(rename = "validationError")] + validation_error: String, + }, + Syncing, + Accepted, + InvalidBlockHash { + #[serde(rename = "validationError")] + validation_error: String, + }, +} + +/// This structure contains configurable settings of the transition process. +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TransitionConfiguration { + /// maps on the TERMINAL_TOTAL_DIFFICULTY parameter of EIP-3675 + pub terminal_total_difficulty: U256, + /// maps on TERMINAL_BLOCK_HASH parameter of EIP-3675 + pub terminal_block_hash: H256, + /// maps on TERMINAL_BLOCK_NUMBER parameter of EIP-3675 + pub terminal_block_number: BlockNumber, +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ForkchoiceUpdated { + pub payload_status: PayloadStatus, + pub payload_id: Option, +} diff --git a/crates/net/rpc-types/src/eth/fee.rs b/crates/net/rpc-types/src/eth/fee.rs new file mode 100644 index 000000000..256113151 --- /dev/null +++ b/crates/net/rpc-types/src/eth/fee.rs @@ -0,0 +1,22 @@ +use reth_primitives::U256; +use serde::{Deserialize, Serialize}; + +/// Response type for `eth_feeHistory` +#[derive(Debug, Clone, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct FeeHistory { + /// An array of block base fees per gas. + /// This includes the next block after the newest of the returned range, + /// because this value can be derived from the newest block. Zeroes are + /// returned for pre-EIP-1559 blocks. + pub base_fee_per_gas: Vec, + /// An array of block gas used ratios. These are calculated as the ratio + /// of `gasUsed` and `gasLimit`. + pub gas_used_ratio: Vec, + /// Lowest number block of the returned range. + pub oldest_block: U256, + /// An (optional) array of effective priority fee per gas data points from a single + /// block. All zeroes are returned if the block is empty. + #[serde(default)] + pub reward: Option>>, +} diff --git a/crates/net/rpc-types/src/eth/filter.rs b/crates/net/rpc-types/src/eth/filter.rs new file mode 100644 index 000000000..d1ac1c556 --- /dev/null +++ b/crates/net/rpc-types/src/eth/filter.rs @@ -0,0 +1,28 @@ +use crate::Log; +use reth_primitives::H256; +pub use reth_primitives::{Filter, FilteredParams}; +use serde::{Serialize, Serializer}; + +/// Response of the `eth_getFilterChanges` RPC. +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum FilterChanges { + /// New logs. + Logs(Vec), + /// New hashes (block or transactions) + Hashes(Vec), + /// Empty result, + Empty, +} + +impl Serialize for FilterChanges { + fn serialize(&self, s: S) -> Result + where + S: Serializer, + { + match self { + FilterChanges::Logs(logs) => logs.serialize(s), + FilterChanges::Hashes(hashes) => hashes.serialize(s), + FilterChanges::Empty => (&[] as &[serde_json::Value]).serialize(s), + } + } +} diff --git a/crates/net/rpc-types/src/eth/index.rs b/crates/net/rpc-types/src/eth/index.rs new file mode 100644 index 000000000..7839d06b4 --- /dev/null +++ b/crates/net/rpc-types/src/eth/index.rs @@ -0,0 +1,64 @@ +use serde::{ + de::{Error, Visitor}, + Deserialize, Deserializer, +}; +use std::fmt; + +/// A hex encoded or decimal index +#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] +pub struct Index(usize); + +impl From for usize { + fn from(idx: Index) -> Self { + idx.0 + } +} + +impl<'a> Deserialize<'a> for Index { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'a>, + { + struct IndexVisitor; + + impl<'a> Visitor<'a> for IndexVisitor { + type Value = Index; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(formatter, "hex-encoded or decimal index") + } + + fn visit_u64(self, value: u64) -> Result + where + E: Error, + { + Ok(Index(value as usize)) + } + + fn visit_str(self, value: &str) -> Result + where + E: Error, + { + if let Some(val) = value.strip_prefix("0x") { + usize::from_str_radix(val, 16).map(Index).map_err(|e| { + Error::custom(format!("Failed to parse hex encoded index value: {}", e)) + }) + } else { + value + .parse::() + .map(Index) + .map_err(|e| Error::custom(format!("Failed to parse numeric index: {}", e))) + } + } + + fn visit_string(self, value: String) -> Result + where + E: Error, + { + self.visit_str(value.as_ref()) + } + } + + deserializer.deserialize_any(IndexVisitor) + } +} diff --git a/crates/net/rpc-types/src/eth/log.rs b/crates/net/rpc-types/src/eth/log.rs new file mode 100644 index 000000000..f17eda38d --- /dev/null +++ b/crates/net/rpc-types/src/eth/log.rs @@ -0,0 +1,29 @@ +use reth_primitives::{Address, Bytes, H256, U256}; +use serde::{Deserialize, Serialize}; + +/// Ethereum Log emitted by a transaction +#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Log { + /// Address + pub address: Address, + /// All topics of the log + pub topics: Vec, + /// Additional data fields of the log + pub data: Bytes, + /// Hash of the block the transaction that emitted this log was mined in + pub block_hash: Option, + /// Number of the block the transaction that emitted this log was mined in + pub block_number: Option, + /// Transaction Hash + pub transaction_hash: Option, + /// Index of the Transaction in the block + pub transaction_index: Option, + /// Log Index in Block + pub log_index: Option, + /// Log Index in Transaction + pub transaction_log_index: Option, + /// Geth Compatibility Field: whether this log was removed + #[serde(default)] + pub removed: bool, +} diff --git a/crates/net/rpc-types/src/eth/mod.rs b/crates/net/rpc-types/src/eth/mod.rs new file mode 100644 index 000000000..2ea643335 --- /dev/null +++ b/crates/net/rpc-types/src/eth/mod.rs @@ -0,0 +1,26 @@ +//! Ethereum related types + +mod account; +mod block; +mod call; +pub mod engine; +mod fee; +mod filter; +mod index; +mod log; +pub mod pubsub; +mod syncing; +pub mod trace; +mod transaction; +mod work; + +pub use account::*; +pub use block::*; +pub use call::CallRequest; +pub use fee::FeeHistory; +pub use filter::*; +pub use index::Index; +pub use log::Log; +pub use syncing::*; +pub use transaction::*; +pub use work::Work; diff --git a/crates/net/rpc-types/src/eth/pubsub.rs b/crates/net/rpc-types/src/eth/pubsub.rs new file mode 100644 index 000000000..dfd187425 --- /dev/null +++ b/crates/net/rpc-types/src/eth/pubsub.rs @@ -0,0 +1,96 @@ +//! Ethereum types for pub-sub + +use crate::{Filter, Log, RichHeader}; +use reth_primitives::H256; +use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; + +/// Subscription result. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum SubscriptionResult { + /// New block header. + Header(Box), + /// Log + Log(Box), + /// Transaction hash + TransactionHash(H256), + /// SyncStatus + SyncState(PubSubSyncStatus), +} + +/// Response type for a SyncStatus subscription +#[derive(Debug, Serialize, Eq, PartialEq, Clone)] +#[serde(untagged)] +pub enum PubSubSyncStatus { + /// If not currently syncing, this should always be `false` + Simple(bool), + /// Current Stats about syncing + Detailed(SyncStatusMetadata), +} + +/// Sync status infos +#[derive(Debug, Serialize, Eq, PartialEq, Clone)] +#[serde(rename_all = "camelCase")] +#[allow(missing_docs)] +pub struct SyncStatusMetadata { + pub syncing: bool, + pub starting_block: u64, + pub current_block: u64, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub highest_block: Option, +} + +impl Serialize for SubscriptionResult { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match *self { + SubscriptionResult::Header(ref header) => header.serialize(serializer), + SubscriptionResult::Log(ref log) => log.serialize(serializer), + SubscriptionResult::TransactionHash(ref hash) => hash.serialize(serializer), + SubscriptionResult::SyncState(ref sync) => sync.serialize(serializer), + } + } +} + +/// Subscription kind. +#[derive(Debug, Deserialize, PartialEq, Eq, Hash, Clone)] +#[serde(deny_unknown_fields)] +#[serde(rename_all = "camelCase")] +pub enum Kind { + /// New block headers subscription. + NewHeads, + /// Logs subscription. + Logs, + /// New Pending Transactions subscription. + NewPendingTransactions, + /// Node syncing status subscription. + Syncing, +} + +/// Subscription kind. +#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)] +pub enum Params { + /// No parameters passed. + #[default] + None, + /// Log parameters. + Logs(Box), +} + +impl<'a> Deserialize<'a> for Params { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'a>, + { + let v = serde_json::Value::deserialize(deserializer)?; + + if v.is_null() { + return Ok(Params::None) + } + + serde_json::from_value(v) + .map(|f| Params::Logs(Box::new(f))) + .map_err(|e| D::Error::custom(format!("Invalid Pub-Sub parameters: {}", e))) + } +} diff --git a/crates/net/rpc-types/src/eth/syncing.rs b/crates/net/rpc-types/src/eth/syncing.rs new file mode 100644 index 000000000..dfd3d224e --- /dev/null +++ b/crates/net/rpc-types/src/eth/syncing.rs @@ -0,0 +1,137 @@ +use reth_primitives::{H512, U256, U64}; +use serde::{Serialize, Serializer}; +use std::collections::BTreeMap; + +/// Syncing info +#[derive(Debug, Clone, Default, Serialize, Eq, PartialEq)] +#[serde(rename_all = "camelCase")] +pub struct SyncInfo { + /// Starting block + pub starting_block: U256, + /// Current block + pub current_block: U256, + /// Highest block seen so far + pub highest_block: U256, + /// Warp sync snapshot chunks total. + pub warp_chunks_amount: Option, + /// Warp sync snapshot chunks processed. + pub warp_chunks_processed: Option, +} + +/// Peers info +#[derive(Debug, Clone, Default, Serialize)] +pub struct Peers { + /// Number of active peers + pub active: usize, + /// Number of connected peers + pub connected: usize, + /// Max number of peers + pub max: u32, + /// Detailed information on peers + pub peers: Vec, +} + +/// Number of peers connected to. +#[derive(Debug, Serialize)] +#[serde(untagged)] +pub enum PeerCount { + /// Peer count as integer + Number(u32), + /// Peer count as hex + Hex(U64), +} + +/// Peer connection information +#[derive(Debug, Clone, Default, Serialize)] +pub struct PeerInfo { + /// Public node id + pub id: Option, + /// Node client ID + pub name: String, + /// Capabilities + pub caps: Vec, + /// Network information + pub network: PeerNetworkInfo, + /// Protocols information + pub protocols: PeerProtocolsInfo, +} + +/// Peer network information +#[derive(Debug, Clone, Default, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct PeerNetworkInfo { + /// Remote endpoint address + pub remote_address: String, + /// Local endpoint address + pub local_address: String, +} + +/// Peer protocols information +#[derive(Debug, Clone, Default, Serialize)] +pub struct PeerProtocolsInfo { + /// Ethereum protocol information + pub eth: Option, + /// PIP protocol information. + pub pip: Option, +} + +/// Peer Ethereum protocol information +#[derive(Debug, Clone, Default, Serialize)] +pub struct EthProtocolInfo { + /// Negotiated ethereum protocol version + pub version: u32, + /// Peer total difficulty if known + pub difficulty: Option, + /// SHA3 of peer best block hash + pub head: String, +} + +/// Peer PIP protocol information +#[derive(Debug, Clone, Default, Serialize)] +pub struct PipProtocolInfo { + /// Negotiated PIP protocol version + pub version: u32, + /// Peer total difficulty + pub difficulty: U256, + /// SHA3 of peer best block hash + pub head: String, +} + +/// Sync status +#[derive(Debug, Eq, PartialEq)] +pub enum SyncStatus { + /// Info when syncing + Info(SyncInfo), + /// Not syncing + None, +} + +impl Serialize for SyncStatus { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self { + SyncStatus::Info(info) => info.serialize(serializer), + SyncStatus::None => serializer.serialize_bool(false), + } + } +} + +/// Propagation statistics for pending transaction. +#[derive(Debug, Clone, Default, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct TransactionStats { + /// Block no this transaction was first seen. + pub first_seen: u64, + /// Peers this transaction was propagated to with count. + pub propagated_to: BTreeMap, +} + +/// Chain status. +#[derive(Debug, Clone, Default, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct ChainStatus { + /// Describes the gap in the blockchain, if there is one: (first, last) + pub block_gap: Option<(U256, U256)>, +} diff --git a/crates/net/rpc-types/src/eth/trace/filter.rs b/crates/net/rpc-types/src/eth/trace/filter.rs new file mode 100644 index 000000000..e17d4fa22 --- /dev/null +++ b/crates/net/rpc-types/src/eth/trace/filter.rs @@ -0,0 +1,22 @@ +//! `trace_filter` types and support +use reth_primitives::{Address, BlockNumber}; +use serde::Deserialize; + +/// Trace filter. +#[derive(Debug, PartialEq, Eq, Deserialize)] +#[serde(deny_unknown_fields)] +#[serde(rename_all = "camelCase")] +pub struct TraceFilter { + /// From block + pub from_block: Option, + /// To block + pub to_block: Option, + /// From address + pub from_address: Option>, + /// To address + pub to_address: Option>, + /// Output offset + pub after: Option, + /// Output amount + pub count: Option, +} diff --git a/crates/net/rpc-types/src/eth/trace/mod.rs b/crates/net/rpc-types/src/eth/trace/mod.rs new file mode 100644 index 000000000..9270dbe1e --- /dev/null +++ b/crates/net/rpc-types/src/eth/trace/mod.rs @@ -0,0 +1,4 @@ +//! Types for tracing + +pub mod filter; +pub mod parity; diff --git a/crates/net/rpc-types/src/eth/trace/parity.rs b/crates/net/rpc-types/src/eth/trace/parity.rs new file mode 100644 index 000000000..d41649ec1 --- /dev/null +++ b/crates/net/rpc-types/src/eth/trace/parity.rs @@ -0,0 +1,223 @@ +#![allow(missing_docs)] +//! Types for trace module: Ref https://openethereum.github.io/JSONRPC-trace-module + +use reth_primitives::{Address, Bytes, H256, U256, U64}; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; + +#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum TraceType { + Trace, + VmTrace, + StateDiff, +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TraceResults { + pub output: Bytes, + pub trace: Option>, + pub vm_trace: Option, + pub state_diff: Option, +} + +/// A `FullTrace` with an additional transaction hash +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TraceResultsWithTransactionHash { + #[serde(flatten)] + pub full_trace: TraceResults, + pub transaction_hash: H256, +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct ChangedType { + pub from: T, + pub to: T, +} + +#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] +pub enum Delta { + #[default] + #[serde(rename = "=")] + Unchanged, + #[serde(rename = "+")] + Added(T), + #[serde(rename = "-")] + Removed(T), + #[serde(rename = "*")] + Changed(ChangedType), +} + +#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct AccountDiff { + pub balance: Delta, + pub nonce: Delta, + pub code: Delta, + pub storage: BTreeMap>, +} + +/// New-type for list of account diffs +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(transparent)] +pub struct StateDiff(pub BTreeMap); + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase", tag = "type", content = "action")] +pub enum Action { + Call(CallAction), + Create(CreateAction), + Selfdestruct(SelfdestructAction), + Reward(RewardAction), +} + +/// Call type. +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum CallType { + /// None + None, + /// Call + Call, + /// Call code + CallCode, + /// Delegate call + DelegateCall, + /// Static call + StaticCall, +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CallAction { + pub from: Address, + pub to: Address, + pub value: U256, + pub gas: U64, + pub input: Bytes, + pub call_type: CallType, +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CreateAction { + pub from: Address, + pub value: U256, + pub gas: U64, + pub init: Bytes, +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum RewardType { + Block, + Uncle, +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct RewardAction { + pub author: Address, + pub value: U256, + pub reward_type: RewardType, +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SelfdestructAction { + pub address: Address, + pub refund_address: Address, + pub balance: U256, +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CallOutput { + pub gas_used: U64, + pub output: Bytes, +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CreateOutput { + pub gas_used: U64, + pub code: Bytes, + pub address: Address, +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(untagged)] +pub enum TraceOutput { + Call(CallOutput), + Create(CreateOutput), +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(untagged)] +pub enum TraceResult { + Success { result: TraceOutput }, + Error { error: String }, +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TransactionTrace { + pub trace_address: Vec, + pub subtraces: usize, + #[serde(flatten)] + pub action: Action, + #[serde(flatten)] + pub result: Option, +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct LocalizedTransactionTrace { + #[serde(flatten)] + pub trace: TransactionTrace, + pub transaction_position: Option, + pub transaction_hash: Option, + pub block_number: U64, + pub block_hash: H256, +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct VmTrace { + pub code: Bytes, + pub ops: Vec, +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct VmInstruction { + pub pc: usize, + pub cost: u64, + pub ex: Option, + pub sub: Option, +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct VmExecutedOperation { + pub used: u64, + pub push: Option, + pub mem: Option, + pub store: Option, +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct MemoryDelta { + pub off: usize, + pub data: Bytes, +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct StorageDelta { + pub key: U256, + pub val: U256, +} diff --git a/crates/net/rpc-types/src/eth/transaction/mod.rs b/crates/net/rpc-types/src/eth/transaction/mod.rs new file mode 100644 index 000000000..a698f3d63 --- /dev/null +++ b/crates/net/rpc-types/src/eth/transaction/mod.rs @@ -0,0 +1,69 @@ +mod receipt; +mod request; +mod typed; + +pub use receipt::TransactionReceipt; +pub use request::TransactionRequest; +pub use typed::*; + +use reth_primitives::{ + transaction::eip2930::AccessListItem, Address, Bytes, H256, H512, U256, U64, +}; +use serde::Serialize; + +/// Transaction object +#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct Transaction { + /// Hash + pub hash: H256, + /// Nonce + pub nonce: U256, + /// Block hash + pub block_hash: Option, + /// Block number + pub block_number: Option, + /// Transaction Index + pub transaction_index: Option, + /// Sender + pub from: Address, + /// Recipient + pub to: Option
, + /// Transfered value + pub value: U256, + /// Gas Price + #[serde(skip_serializing_if = "Option::is_none")] + pub gas_price: Option, + /// Max BaseFeePerGas the user is willing to pay. + #[serde(skip_serializing_if = "Option::is_none")] + pub max_fee_per_gas: Option, + /// The miner's tip. + #[serde(skip_serializing_if = "Option::is_none")] + pub max_priority_fee_per_gas: Option, + /// Gas + pub gas: U256, + /// Data + pub input: Bytes, + /// Creates contract + pub creates: Option
, + /// Raw transaction data + pub raw: Bytes, + /// Public key of the signer. + pub public_key: Option, + /// The network id of the transaction, if any. + pub chain_id: Option, + /// The standardised V field of the signature (0 or 1). + pub standard_v: U256, + /// The standardised V field of the signature. + pub v: U256, + /// The R field of the signature. + pub r: U256, + /// The S field of the signature. + pub s: U256, + /// Pre-pay to warm storage access. + #[cfg_attr(feature = "std", serde(skip_serializing_if = "Option::is_none"))] + pub access_list: Option>, + /// EIP-2718 type + #[serde(rename = "type", skip_serializing_if = "Option::is_none")] + pub transaction_type: Option, +} diff --git a/crates/net/rpc-types/src/eth/transaction/receipt.rs b/crates/net/rpc-types/src/eth/transaction/receipt.rs new file mode 100644 index 000000000..fda645df4 --- /dev/null +++ b/crates/net/rpc-types/src/eth/transaction/receipt.rs @@ -0,0 +1,45 @@ +use reth_primitives::{Address, Bloom, Log, H256, U256, U64}; +use serde::Serialize; + +/// Transaction receipt +#[derive(Clone, Debug, Serialize, Eq, PartialEq)] +#[serde(rename_all = "camelCase")] +pub struct TransactionReceipt { + /// Transaction Hash. + pub transaction_hash: Option, + /// Index within the block. + pub transaction_index: Option, + /// Hash of the block this transaction was included within. + pub block_hash: Option, + /// Number of the block this transaction was included within. + pub block_number: Option, + /// Address of the sender + pub from: Address, + /// Address of the receiver. null when its a contract creation transaction. + pub to: Option
, + /// Cumulative gas used within the block after this was executed. + pub cumulative_gas_used: U256, + /// Gas used by this transaction alone. + pub gas_used: Option, + /// Contract address created, or None if not a deployment. + pub contract_address: Option
, + /// Logs emitted by this transaction. + pub logs: Vec, + /// The state root + /// + /// EIP98 makes this optional field, if it's missing then skip serializing it + #[serde(skip_serializing_if = "Option::is_none", rename = "root")] + pub state_root: Option, + /// Logs bloom + pub logs_bloom: Bloom, + /// Status: either 1 (success) or 0 (failure). Only present after activation of EIP-658 + #[serde(skip_serializing_if = "Option::is_none", rename = "status")] + pub status_code: Option, + /// The price paid post-execution by the transaction (i.e. base fee + priority fee). Both + /// fields in 1559-style transactions are maximums (max fee + max priority fee), the amount + /// that's actually paid by users can only be determined post-execution + pub effective_gas_price: U256, + /// EIP-2718 Transaction type, Some(1) for AccessList transaction, None for Legacy + #[serde(rename = "type")] + pub transaction_type: U256, +} diff --git a/crates/net/rpc-types/src/eth/transaction/request.rs b/crates/net/rpc-types/src/eth/transaction/request.rs new file mode 100644 index 000000000..3f53b7ba4 --- /dev/null +++ b/crates/net/rpc-types/src/eth/transaction/request.rs @@ -0,0 +1,115 @@ +use crate::eth::transaction::typed::{ + EIP1559TransactionRequest, EIP2930TransactionRequest, LegacyTransactionRequest, + TransactionKind, TypedTransactionRequest, +}; +use reth_primitives::{transaction::eip2930::AccessListItem, Address, Bytes, U256}; +use serde::{Deserialize, Serialize}; + +/// Represents _all_ transaction requests received from RPC +#[derive(Clone, Debug, PartialEq, Eq, Default, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +#[serde(rename_all = "camelCase")] +pub struct TransactionRequest { + /// from address + pub from: Option
, + /// to address + pub to: Option
, + /// legacy, gas Price + #[serde(default)] + pub gas_price: Option, + /// max base fee per gas sender is willing to pay + #[serde(default)] + pub max_fee_per_gas: Option, + /// miner tip + #[serde(default)] + pub max_priority_fee_per_gas: Option, + /// gas + pub gas: Option, + /// value of th tx in wei + pub value: Option, + /// Any additional data sent + pub data: Option, + /// Transaction nonce + pub nonce: Option, + /// warm storage access pre-payment + #[serde(default)] + pub access_list: Option>, + /// EIP-2718 type + #[serde(rename = "type")] + pub transaction_type: Option, +} + +// == impl TransactionRequest == + +impl TransactionRequest { + /// Converts the request into a [`TypedTransactionRequest`] + /// + /// Returns None if mutual exclusive fields `gasPrice` and `max_fee_per_gas` are either missing + /// or both set. + pub fn into_typed_request(self) -> Option { + let TransactionRequest { + to, + gas_price, + max_fee_per_gas, + max_priority_fee_per_gas, + gas, + value, + data, + nonce, + mut access_list, + .. + } = self; + match (gas_price, max_fee_per_gas, access_list.take()) { + // legacy transaction + (Some(_), None, None) => { + Some(TypedTransactionRequest::Legacy(LegacyTransactionRequest { + nonce: nonce.unwrap_or(U256::zero()), + gas_price: gas_price.unwrap_or_default(), + gas_limit: gas.unwrap_or_default(), + value: value.unwrap_or(U256::zero()), + input: data.unwrap_or_default(), + kind: match to { + Some(to) => TransactionKind::Call(to), + None => TransactionKind::Create, + }, + chain_id: None, + })) + } + // EIP2930 + (_, None, Some(access_list)) => { + Some(TypedTransactionRequest::EIP2930(EIP2930TransactionRequest { + nonce: nonce.unwrap_or(U256::zero()), + gas_price: gas_price.unwrap_or_default(), + gas_limit: gas.unwrap_or_default(), + value: value.unwrap_or(U256::zero()), + input: data.unwrap_or_default(), + kind: match to { + Some(to) => TransactionKind::Call(to), + None => TransactionKind::Create, + }, + chain_id: 0, + access_list, + })) + } + // EIP1559 + (None, Some(_), access_list) | (None, None, access_list @ None) => { + // Empty fields fall back to the canonical transaction schema. + Some(TypedTransactionRequest::EIP1559(EIP1559TransactionRequest { + nonce: nonce.unwrap_or(U256::zero()), + max_fee_per_gas: max_fee_per_gas.unwrap_or_default(), + max_priority_fee_per_gas: max_priority_fee_per_gas.unwrap_or(U256::zero()), + gas_limit: gas.unwrap_or_default(), + value: value.unwrap_or(U256::zero()), + input: data.unwrap_or_default(), + kind: match to { + Some(to) => TransactionKind::Call(to), + None => TransactionKind::Create, + }, + chain_id: 0, + access_list: access_list.unwrap_or_default(), + })) + } + _ => None, + } + } +} diff --git a/crates/net/rpc-types/src/eth/transaction/typed.rs b/crates/net/rpc-types/src/eth/transaction/typed.rs new file mode 100644 index 000000000..99235537f --- /dev/null +++ b/crates/net/rpc-types/src/eth/transaction/typed.rs @@ -0,0 +1,114 @@ +#![allow(missing_docs)] +//! The [`TransactionRequest`] is a universal representation for a transaction deserialized from the +//! json input of an RPC call. Depending on what fields are set, it can be converted into the +//! container type [`TypedTransactionRequest`]. + +use fastrlp::{RlpDecodable, RlpEncodable}; +use reth_primitives::{transaction::eip2930::AccessListItem, Address, Bytes, U256}; +use serde::{Deserialize, Serialize}; + +/// Container type for various Ethereum transaction requests +/// +/// Its variants correspond to specific allowed transactions: +/// 1. Legacy (pre-EIP2718) [`LegacyTransactionRequest`] +/// 2. EIP2930 (state access lists) [`EIP2930TransactionRequest`] +/// 3. EIP1559 [`EIP1559TransactionRequest`] +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum TypedTransactionRequest { + Legacy(LegacyTransactionRequest), + EIP2930(EIP2930TransactionRequest), + EIP1559(EIP1559TransactionRequest), +} + +/// Represents a legacy transaction request +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct LegacyTransactionRequest { + pub nonce: U256, + pub gas_price: U256, + pub gas_limit: U256, + pub kind: TransactionKind, + pub value: U256, + pub input: Bytes, + pub chain_id: Option, +} + +/// Represents an EIP-2930 transaction request +#[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)] +pub struct EIP2930TransactionRequest { + pub chain_id: u64, + pub nonce: U256, + pub gas_price: U256, + pub gas_limit: U256, + pub kind: TransactionKind, + pub value: U256, + pub input: Bytes, + pub access_list: Vec, +} + +/// Represents an EIP-1559 transaction request +#[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)] +pub struct EIP1559TransactionRequest { + pub chain_id: u64, + pub nonce: U256, + pub max_priority_fee_per_gas: U256, + pub max_fee_per_gas: U256, + pub gas_limit: U256, + pub kind: TransactionKind, + pub value: U256, + pub input: Bytes, + pub access_list: Vec, +} + +/// Represents the `to` field of a transaction request +/// +/// This determines what kind of transaction this is +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum TransactionKind { + /// Transaction will call this address or transfer funds to this address + Call(Address), + /// No `to` field set, this transaction will create a contract + Create, +} + +// == impl TransactionKind == + +impl TransactionKind { + /// If this transaction is a call this returns the address of the callee + pub fn as_call(&self) -> Option<&Address> { + match self { + TransactionKind::Call(to) => Some(to), + TransactionKind::Create => None, + } + } +} + +impl fastrlp::Encodable for TransactionKind { + fn length(&self) -> usize { + match self { + TransactionKind::Call(to) => to.length(), + TransactionKind::Create => ([]).length(), + } + } + fn encode(&self, out: &mut dyn fastrlp::BufMut) { + match self { + TransactionKind::Call(to) => to.encode(out), + TransactionKind::Create => ([]).encode(out), + } + } +} + +impl fastrlp::Decodable for TransactionKind { + fn decode(buf: &mut &[u8]) -> Result { + if let Some(&first) = buf.first() { + if first == 0x80 { + *buf = &buf[1..]; + Ok(TransactionKind::Create) + } else { + let addr =
::decode(buf)?; + Ok(TransactionKind::Call(addr)) + } + } else { + Err(fastrlp::DecodeError::InputTooShort) + } + } +} diff --git a/crates/net/rpc-types/src/eth/work.rs b/crates/net/rpc-types/src/eth/work.rs new file mode 100644 index 000000000..b28eebd5c --- /dev/null +++ b/crates/net/rpc-types/src/eth/work.rs @@ -0,0 +1,29 @@ +use reth_primitives::{H256, U256}; +use serde::{Serialize, Serializer}; + +/// The result of an `eth_getWork` request +#[derive(Clone, Debug, PartialEq, Eq, Default)] +pub struct Work { + /// The proof-of-work hash. + pub pow_hash: H256, + /// The seed hash. + pub seed_hash: H256, + /// The target. + pub target: H256, + /// The block number: this isn't always stored. + pub number: Option, +} + +impl Serialize for Work { + fn serialize(&self, s: S) -> Result + where + S: Serializer, + { + match self.number.as_ref() { + Some(num) => { + (&self.pow_hash, &self.seed_hash, &self.target, U256::from(*num)).serialize(s) + } + None => (&self.pow_hash, &self.seed_hash, &self.target).serialize(s), + } + } +} diff --git a/crates/net/rpc-types/src/lib.rs b/crates/net/rpc-types/src/lib.rs new file mode 100644 index 000000000..a3a3ed7d5 --- /dev/null +++ b/crates/net/rpc-types/src/lib.rs @@ -0,0 +1,14 @@ +#![warn(missing_debug_implementations, missing_docs, unreachable_pub, unused_crate_dependencies)] +#![deny(unused_must_use, rust_2018_idioms)] +#![doc(test( + no_crate_inject, + attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables)) +))] + +//! Reth RPC type definitions +//! +//! Provides all relevant types for the various RPC endpoints, grouped by namespace. + +mod eth; + +pub use eth::*; diff --git a/crates/net/rpc/Cargo.toml b/crates/net/rpc/Cargo.toml new file mode 100644 index 000000000..57fd4fee9 --- /dev/null +++ b/crates/net/rpc/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "reth-rpc" +version = "0.1.0" +edition = "2021" +license = "MIT OR Apache-2.0" +repository = "https://github.com/foundry-rs/reth" +readme = "README.md" +description = """ +Reth RPC implementation +""" +[dependencies] +# reth +reth-primitives = { path = "../../primitives" } +reth-rpc-api = { path = "../rpc-api" } +reth-rpc-types = { path = "../rpc-types" } + +# misc +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +thiserror = "1.0" \ No newline at end of file diff --git a/crates/net/rpc/src/lib.rs b/crates/net/rpc/src/lib.rs new file mode 100644 index 000000000..4236c0d6f --- /dev/null +++ b/crates/net/rpc/src/lib.rs @@ -0,0 +1,10 @@ +#![warn(missing_debug_implementations, missing_docs, unreachable_pub)] +#![deny(unused_must_use, rust_2018_idioms)] +#![doc(test( + no_crate_inject, + attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables)) +))] + +//! Reth RPC implementation +//! +//! Provides the implementation of all RPC interfaces