Compare commits
13 Commits
master
...
refcell/we
Author | SHA1 | Date |
---|---|---|
Andreas Bigger | 18e99eea35 | |
Andreas Bigger | 4279c65cda | |
Andreas Bigger | f679a7c5c8 | |
Andreas Bigger | 43850702c2 | |
Andreas Bigger | 2a37dbcb22 | |
Andreas Bigger | 38091aaa00 | |
Andreas Bigger | 4f99cfef95 | |
Andreas Bigger | 81e5a08828 | |
Andreas Bigger | f28483dfd7 | |
Andreas Bigger | cda8f39b4c | |
Andreas Bigger | 2b1aeba534 | |
andreas | 8d240c2fe3 | |
Andreas Bigger | 55839e5479 |
|
@ -407,7 +407,7 @@ checksum = "08a1ec454bc3eead8719cb56e15dbbfecdbc14e4b3a3ae4936cc6e31f5fc0d07"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"camino",
|
"camino",
|
||||||
"cargo-platform",
|
"cargo-platform",
|
||||||
"semver 1.0.16",
|
"semver 1.0.17",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
@ -433,9 +433,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chrono"
|
name = "chrono"
|
||||||
version = "0.4.23"
|
version = "0.4.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f"
|
checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"iana-time-zone",
|
"iana-time-zone",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
|
@ -524,13 +524,12 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cli"
|
name = "cli"
|
||||||
version = "0.3.0"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"client",
|
"client",
|
||||||
"common",
|
"common",
|
||||||
"config",
|
"config",
|
||||||
"ctrlc",
|
|
||||||
"dirs",
|
"dirs",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"eyre",
|
"eyre",
|
||||||
|
@ -541,11 +540,12 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "client"
|
name = "client"
|
||||||
version = "0.3.0"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"common",
|
"common",
|
||||||
"config",
|
"config",
|
||||||
"consensus",
|
"consensus",
|
||||||
|
"ctrlc",
|
||||||
"ethers",
|
"ethers",
|
||||||
"execution",
|
"execution",
|
||||||
"eyre",
|
"eyre",
|
||||||
|
@ -645,7 +645,7 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "common"
|
name = "common"
|
||||||
version = "0.3.0"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ethers",
|
"ethers",
|
||||||
"eyre",
|
"eyre",
|
||||||
|
@ -657,7 +657,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "config"
|
name = "config"
|
||||||
version = "0.3.0"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"common",
|
"common",
|
||||||
"ethers",
|
"ethers",
|
||||||
|
@ -677,7 +677,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "consensus"
|
name = "consensus"
|
||||||
version = "0.3.0"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
@ -695,7 +695,6 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"ssz-rs",
|
"ssz-rs",
|
||||||
"superstruct",
|
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"toml",
|
"toml",
|
||||||
|
@ -976,41 +975,6 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "darling"
|
|
||||||
version = "0.13.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c"
|
|
||||||
dependencies = [
|
|
||||||
"darling_core",
|
|
||||||
"darling_macro",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "darling_core"
|
|
||||||
version = "0.13.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610"
|
|
||||||
dependencies = [
|
|
||||||
"fnv",
|
|
||||||
"ident_case",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"strsim",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "darling_macro"
|
|
||||||
version = "0.13.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835"
|
|
||||||
dependencies = [
|
|
||||||
"darling_core",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "der"
|
name = "der"
|
||||||
version = "0.6.1"
|
version = "0.6.1"
|
||||||
|
@ -1433,7 +1397,7 @@ dependencies = [
|
||||||
"ethers-core",
|
"ethers-core",
|
||||||
"getrandom 0.2.8",
|
"getrandom 0.2.8",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"semver 1.0.16",
|
"semver 1.0.17",
|
||||||
"serde",
|
"serde",
|
||||||
"serde-aux",
|
"serde-aux",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -1477,6 +1441,7 @@ dependencies = [
|
||||||
"auto_impl 1.0.1",
|
"auto_impl 1.0.1",
|
||||||
"base64 0.13.1",
|
"base64 0.13.1",
|
||||||
"ethers-core",
|
"ethers-core",
|
||||||
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-timer",
|
"futures-timer",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
@ -1492,6 +1457,7 @@ dependencies = [
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tokio-tungstenite",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-futures",
|
"tracing-futures",
|
||||||
"url",
|
"url",
|
||||||
|
@ -1528,7 +1494,7 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "execution"
|
name = "execution"
|
||||||
version = "0.3.0"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
@ -1724,9 +1690,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures"
|
name = "futures"
|
||||||
version = "0.3.26"
|
version = "0.3.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84"
|
checksum = "531ac96c6ff5fd7c62263c5e3c67a603af4fcaee2e1a0ae5565ba3a11e69e549"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
@ -1739,9 +1705,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-channel"
|
name = "futures-channel"
|
||||||
version = "0.3.26"
|
version = "0.3.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5"
|
checksum = "164713a5a0dcc3e7b4b1ed7d3b433cabc18025386f9339346e8daf15963cf7ac"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
|
@ -1749,15 +1715,15 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-core"
|
name = "futures-core"
|
||||||
version = "0.3.26"
|
version = "0.3.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608"
|
checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-executor"
|
name = "futures-executor"
|
||||||
version = "0.3.26"
|
version = "0.3.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e"
|
checksum = "1997dd9df74cdac935c76252744c1ed5794fac083242ea4fe77ef3ed60ba0f83"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-task",
|
"futures-task",
|
||||||
|
@ -1766,9 +1732,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-io"
|
name = "futures-io"
|
||||||
version = "0.3.26"
|
version = "0.3.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531"
|
checksum = "89d422fa3cbe3b40dca574ab087abb5bc98258ea57eea3fd6f1fa7162c778b91"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-locks"
|
name = "futures-locks"
|
||||||
|
@ -1782,9 +1748,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-macro"
|
name = "futures-macro"
|
||||||
version = "0.3.26"
|
version = "0.3.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70"
|
checksum = "3eb14ed937631bd8b8b8977f2c198443447a8355b6e3ca599f38c975e5a963b6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -1793,15 +1759,15 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-sink"
|
name = "futures-sink"
|
||||||
version = "0.3.26"
|
version = "0.3.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364"
|
checksum = "ec93083a4aecafb2a80a885c9de1f0ccae9dbd32c2bb54b0c3a65690e0b8d2f2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-task"
|
name = "futures-task"
|
||||||
version = "0.3.26"
|
version = "0.3.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366"
|
checksum = "fd65540d33b37b16542a0438c12e6aeead10d4ac5d05bd3f805b8f35ab592879"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-timer"
|
name = "futures-timer"
|
||||||
|
@ -1815,9 +1781,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-util"
|
name = "futures-util"
|
||||||
version = "0.3.26"
|
version = "0.3.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1"
|
checksum = "3ef6b17e481503ec85211fed8f39d1970f128935ca1f814cd32ac4a6842e84ab"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
@ -2026,7 +1992,7 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "helios"
|
name = "helios"
|
||||||
version = "0.3.0"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"client",
|
"client",
|
||||||
"common",
|
"common",
|
||||||
|
@ -2085,6 +2051,12 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hex"
|
name = "hex"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
|
@ -2145,9 +2117,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
version = "0.14.24"
|
version = "0.14.25"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c"
|
checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
|
@ -2220,12 +2192,6 @@ dependencies = [
|
||||||
"cxx-build",
|
"cxx-build",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ident_case"
|
|
||||||
version = "1.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
@ -2370,10 +2336,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "io-lifetimes"
|
name = "io-lifetimes"
|
||||||
version = "1.0.6"
|
version = "1.0.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cfa919a82ea574332e2de6e74b4c36e74d41982b335080fa59d4ef31be20fdf3"
|
checksum = "76e86b86ae312accbf05ade23ce76b625e0e47a255712b7414037385a1c05380"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"hermit-abi 0.3.1",
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.45.0",
|
"windows-sys 0.45.0",
|
||||||
]
|
]
|
||||||
|
@ -2950,9 +2917,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl"
|
name = "openssl"
|
||||||
version = "0.10.45"
|
version = "0.10.46"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1"
|
checksum = "fd2523381e46256e40930512c7fd25562b9eae4812cb52078f155e87217c9d1e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
@ -2991,9 +2958,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl-sys"
|
name = "openssl-sys"
|
||||||
version = "0.9.80"
|
version = "0.9.81"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7"
|
checksum = "176be2629957c157240f68f61f2d0053ad3a4ecfdd9ebf1e6521d18d9635cf67"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"cc",
|
"cc",
|
||||||
|
@ -3376,9 +3343,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.51"
|
version = "1.0.52"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
|
checksum = "1d0e1ae9e836cc3beddd63db0df682593d7e2d3d891ae8c9083d2113e1744224"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
@ -3398,9 +3365,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.23"
|
version = "1.0.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
@ -3727,7 +3694,7 @@ version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"semver 1.0.16",
|
"semver 1.0.17",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3922,9 +3889,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "1.0.16"
|
version = "1.0.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
|
checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
@ -3952,9 +3919,9 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.154"
|
version = "1.0.156"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8cdd151213925e7f1ab45a9bbfb129316bd00799784b174b7cc7bcd16961c49e"
|
checksum = "314b5b092c0ade17c00142951e50ced110ec27cea304b1037c6969246c2469a4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
@ -3982,9 +3949,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.154"
|
version = "1.0.156"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4fc80d722935453bcafdc2c9a73cd6fac4dc1938f0346035d84bf99fa9e33217"
|
checksum = "d7e29c4601e36bcec74a223228dce795f4cd3616341a4af93520ca1a837c087d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -4040,6 +4007,17 @@ dependencies = [
|
||||||
"opaque-debug 0.3.0",
|
"opaque-debug 0.3.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha-1"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest 0.10.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha2"
|
name = "sha2"
|
||||||
version = "0.8.2"
|
version = "0.8.2"
|
||||||
|
@ -4151,7 +4129,7 @@ dependencies = [
|
||||||
"httparse",
|
"httparse",
|
||||||
"log",
|
"log",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"sha-1",
|
"sha-1 0.9.8",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -4248,20 +4226,6 @@ version = "2.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
|
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "superstruct"
|
|
||||||
version = "0.7.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6f4e1f478a7728f8855d7e620e9a152cf8932c6614f86564c886f9b8141f3201"
|
|
||||||
dependencies = [
|
|
||||||
"darling",
|
|
||||||
"itertools",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"smallvec",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.109"
|
version = "1.0.109"
|
||||||
|
@ -4454,6 +4418,18 @@ dependencies = [
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-tungstenite"
|
||||||
|
version = "0.17.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181"
|
||||||
|
dependencies = [
|
||||||
|
"futures-util",
|
||||||
|
"log",
|
||||||
|
"tokio",
|
||||||
|
"tungstenite",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-util"
|
name = "tokio-util"
|
||||||
version = "0.7.7"
|
version = "0.7.7"
|
||||||
|
@ -4486,9 +4462,9 @@ checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_edit"
|
name = "toml_edit"
|
||||||
version = "0.19.4"
|
version = "0.19.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9a1eb0622d28f4b9c90adc4ea4b2b46b47663fde9ac5fafcb14a1369d5508825"
|
checksum = "dc18466501acd8ac6a3f615dd29a3438f8ca6bb3b19537138b3106e575621274"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"toml_datetime",
|
"toml_datetime",
|
||||||
|
@ -4628,6 +4604,25 @@ version = "0.15.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7b3e06c9b9d80ed6b745c7159c40b311ad2916abb34a49e9be2653b90db0d8dd"
|
checksum = "7b3e06c9b9d80ed6b745c7159c40b311ad2916abb34a49e9be2653b90db0d8dd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tungstenite"
|
||||||
|
version = "0.17.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.13.1",
|
||||||
|
"byteorder",
|
||||||
|
"bytes",
|
||||||
|
"http",
|
||||||
|
"httparse",
|
||||||
|
"log",
|
||||||
|
"rand 0.8.5",
|
||||||
|
"sha-1 0.10.1",
|
||||||
|
"thiserror",
|
||||||
|
"url",
|
||||||
|
"utf-8",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.16.0"
|
version = "1.16.0"
|
||||||
|
@ -4744,6 +4739,12 @@ dependencies = [
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf-8"
|
||||||
|
version = "0.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "0.8.2"
|
version = "0.8.2"
|
||||||
|
@ -4774,12 +4775,11 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "walkdir"
|
name = "walkdir"
|
||||||
version = "2.3.2"
|
version = "2.3.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
|
checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"same-file",
|
"same-file",
|
||||||
"winapi",
|
|
||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -4984,9 +4984,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-targets"
|
name = "windows-targets"
|
||||||
version = "0.42.1"
|
version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
|
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows_aarch64_gnullvm",
|
"windows_aarch64_gnullvm",
|
||||||
"windows_aarch64_msvc",
|
"windows_aarch64_msvc",
|
||||||
|
@ -4999,51 +4999,51 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_gnullvm"
|
name = "windows_aarch64_gnullvm"
|
||||||
version = "0.42.1"
|
version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
|
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.42.1"
|
version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
|
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
version = "0.42.1"
|
version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
|
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
version = "0.42.1"
|
version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
|
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
version = "0.42.1"
|
version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
|
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
version = "0.42.1"
|
version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
|
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.42.1"
|
version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
|
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winnow"
|
name = "winnow"
|
||||||
version = "0.3.5"
|
version = "0.3.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ee7b2c67f962bf5042bfd8b6a916178df33a26eec343ae064cb8e069f638fa6f"
|
checksum = "23d020b441f92996c80d94ae9166e8501e59c7bb56121189dc9eab3bd8216966"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "helios"
|
name = "helios"
|
||||||
version = "0.3.0"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
autobenches = false
|
autobenches = false
|
||||||
exclude = [
|
exclude = [
|
||||||
|
@ -17,7 +17,6 @@ members = [
|
||||||
"execution",
|
"execution",
|
||||||
"helios-ts",
|
"helios-ts",
|
||||||
]
|
]
|
||||||
default-members = ["cli"]
|
|
||||||
|
|
||||||
[profile.bench]
|
[profile.bench]
|
||||||
debug = true
|
debug = true
|
||||||
|
|
|
@ -2,7 +2,7 @@ cargo-features = ["different-binary-name"]
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "cli"
|
name = "cli"
|
||||||
version = "0.3.0"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
|
@ -17,7 +17,6 @@ eyre = "0.6.8"
|
||||||
dirs = "4.0.0"
|
dirs = "4.0.0"
|
||||||
env_logger = "0.9.0"
|
env_logger = "0.9.0"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
ctrlc = "3.2.3"
|
|
||||||
futures = "0.3.23"
|
futures = "0.3.23"
|
||||||
|
|
||||||
client = { path = "../client" }
|
client = { path = "../client" }
|
||||||
|
|
|
@ -6,16 +6,16 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use common::utils::hex_str_to_bytes;
|
|
||||||
use dirs::home_dir;
|
use dirs::home_dir;
|
||||||
use env_logger::Env;
|
use env_logger::Env;
|
||||||
use eyre::Result;
|
use eyre::Result;
|
||||||
|
|
||||||
use client::{database::FileDB, Client, ClientBuilder};
|
|
||||||
use config::{CliConfig, Config};
|
|
||||||
use futures::executor::block_on;
|
use futures::executor::block_on;
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
|
|
||||||
|
use client::{database::FileDB, Client, ClientBuilder};
|
||||||
|
use common::utils::hex_str_to_bytes;
|
||||||
|
use config::{CliConfig, Config};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
|
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
|
||||||
|
@ -34,7 +34,7 @@ async fn main() -> Result<()> {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
register_shutdown_handler(client);
|
Client::register_shutdown_handler(client);
|
||||||
std::future::pending().await
|
std::future::pending().await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,8 +80,6 @@ fn get_config() -> Config {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[clap(version, about)]
|
|
||||||
/// Helios is a fast, secure, and portable light client for Ethereum
|
|
||||||
struct Cli {
|
struct Cli {
|
||||||
#[clap(short, long, default_value = "mainnet")]
|
#[clap(short, long, default_value = "mainnet")]
|
||||||
network: String,
|
network: String,
|
||||||
|
@ -101,6 +99,10 @@ struct Cli {
|
||||||
load_external_fallback: bool,
|
load_external_fallback: bool,
|
||||||
#[clap(short = 's', long, env)]
|
#[clap(short = 's', long, env)]
|
||||||
strict_checkpoint_age: bool,
|
strict_checkpoint_age: bool,
|
||||||
|
#[clap(short = 's', long, env)]
|
||||||
|
with_ws: bool,
|
||||||
|
#[clap(short = 'h', long, env)]
|
||||||
|
with_http: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cli {
|
impl Cli {
|
||||||
|
@ -119,6 +121,8 @@ impl Cli {
|
||||||
fallback: self.fallback.clone(),
|
fallback: self.fallback.clone(),
|
||||||
load_external_fallback: self.load_external_fallback,
|
load_external_fallback: self.load_external_fallback,
|
||||||
strict_checkpoint_age: self.strict_checkpoint_age,
|
strict_checkpoint_age: self.strict_checkpoint_age,
|
||||||
|
with_ws: self.with_ws,
|
||||||
|
with_http: self.with_http,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "client"
|
name = "client"
|
||||||
version = "0.3.0"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -8,10 +8,12 @@ eyre = "0.6.8"
|
||||||
serde = { version = "1.0.143", features = ["derive"] }
|
serde = { version = "1.0.143", features = ["derive"] }
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs", rev = "d09f55b4f8554491e3431e01af1c32347a8781cd" }
|
ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs", rev = "d09f55b4f8554491e3431e01af1c32347a8781cd" }
|
||||||
ethers = "1.0.0"
|
ethers = { version = "1.0.2", features = [ "ws", "default" ] }
|
||||||
|
jsonrpsee = { version = "0.15.1", features = ["full"] }
|
||||||
futures = "0.3.23"
|
futures = "0.3.23"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
thiserror = "1.0.37"
|
thiserror = "1.0.37"
|
||||||
|
ctrlc = "3.2.3"
|
||||||
|
|
||||||
common = { path = "../common" }
|
common = { path = "../common" }
|
||||||
consensus = { path = "../consensus" }
|
consensus = { path = "../consensus" }
|
||||||
|
|
|
@ -0,0 +1,236 @@
|
||||||
|
use eyre::{eyre, Result};
|
||||||
|
|
||||||
|
use config::{Config, Network};
|
||||||
|
use execution::rpc::WsRpc;
|
||||||
|
|
||||||
|
use crate::{database::FileDB, Client};
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct ClientBuilder {
|
||||||
|
pub network: Option<Network>,
|
||||||
|
pub consensus_rpc: Option<String>,
|
||||||
|
pub execution_rpc: Option<String>,
|
||||||
|
pub checkpoint: Option<Vec<u8>>,
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
pub rpc_port: Option<u16>,
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
pub data_dir: Option<PathBuf>,
|
||||||
|
pub config: Option<Config>,
|
||||||
|
pub fallback: Option<String>,
|
||||||
|
pub load_external_fallback: bool,
|
||||||
|
pub strict_checkpoint_age: bool,
|
||||||
|
pub with_ws: bool,
|
||||||
|
pub with_http: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ClientBuilder {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default().with_http(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn network(mut self, network: Network) -> Self {
|
||||||
|
self.network = Some(network);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn consensus_rpc(mut self, consensus_rpc: &str) -> Self {
|
||||||
|
self.consensus_rpc = Some(consensus_rpc.to_string());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn execution_rpc(mut self, execution_rpc: &str) -> Self {
|
||||||
|
self.execution_rpc = Some(execution_rpc.to_string());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn checkpoint(mut self, checkpoint: &str) -> Self {
|
||||||
|
let checkpoint = hex::decode(checkpoint.strip_prefix("0x").unwrap_or(checkpoint))
|
||||||
|
.expect("cannot parse checkpoint");
|
||||||
|
self.checkpoint = Some(checkpoint);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enables the client to serve a websocket connection.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```rust
|
||||||
|
/// let mut client_builder = client::ClientBuilder::new().with_ws(true);
|
||||||
|
/// assert_eq!(client_builder.with_ws, true);
|
||||||
|
/// client_builder = client_builder.with_ws(false);
|
||||||
|
/// assert_eq!(client_builder.with_ws, false);
|
||||||
|
/// ```
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
pub fn with_ws(mut self, option: bool) -> Self {
|
||||||
|
self.with_ws = option;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enables the client to serve an http connection (enabled by default).
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```rust
|
||||||
|
/// let mut client_builder = client::ClientBuilder::new();
|
||||||
|
/// assert_eq!(client_builder.with_http, true);
|
||||||
|
/// client_builder = client_builder.with_http(false);
|
||||||
|
/// assert_eq!(client_builder.with_http, false);
|
||||||
|
/// ```
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
pub fn with_http(mut self, option: bool) -> Self {
|
||||||
|
self.with_http = option;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the port for the client to serve an RPC server.
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
pub fn rpc_port(mut self, port: u16) -> Self {
|
||||||
|
self.rpc_port = Some(port);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
pub fn data_dir(mut self, data_dir: PathBuf) -> Self {
|
||||||
|
self.data_dir = Some(data_dir);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn config(mut self, config: Config) -> Self {
|
||||||
|
self.config = Some(config);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fallback(mut self, fallback: &str) -> Self {
|
||||||
|
self.fallback = Some(fallback.to_string());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_external_fallback(mut self) -> Self {
|
||||||
|
self.load_external_fallback = true;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn strict_checkpoint_age(mut self) -> Self {
|
||||||
|
self.strict_checkpoint_age = true;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_config(&self) -> Result<Config> {
|
||||||
|
let base_config = if let Some(network) = self.network {
|
||||||
|
network.to_base_config()
|
||||||
|
} else {
|
||||||
|
let config = self
|
||||||
|
.config
|
||||||
|
.as_ref()
|
||||||
|
.ok_or(eyre!("missing network config"))?;
|
||||||
|
config.to_base_config()
|
||||||
|
};
|
||||||
|
|
||||||
|
let consensus_rpc = self.consensus_rpc.clone().unwrap_or_else(|| {
|
||||||
|
self.config
|
||||||
|
.as_ref()
|
||||||
|
.expect("missing consensus rpc")
|
||||||
|
.consensus_rpc
|
||||||
|
.clone()
|
||||||
|
});
|
||||||
|
|
||||||
|
let execution_rpc = self.execution_rpc.clone().unwrap_or_else(|| {
|
||||||
|
self.config
|
||||||
|
.as_ref()
|
||||||
|
.expect("missing execution rpc")
|
||||||
|
.execution_rpc
|
||||||
|
.clone()
|
||||||
|
});
|
||||||
|
|
||||||
|
let checkpoint = if let Some(checkpoint) = self.checkpoint {
|
||||||
|
Some(checkpoint)
|
||||||
|
} else if let Some(config) = &self.config {
|
||||||
|
config.checkpoint.clone()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let default_checkpoint = if let Some(config) = &self.config {
|
||||||
|
config.default_checkpoint.clone()
|
||||||
|
} else {
|
||||||
|
base_config.default_checkpoint.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
let rpc_port = if self.rpc_port.is_some() {
|
||||||
|
self.rpc_port
|
||||||
|
} else if let Some(config) = &self.config {
|
||||||
|
config.rpc_port
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
let data_dir = if self.data_dir.is_some() {
|
||||||
|
self.data_dir.clone()
|
||||||
|
} else if let Some(config) = &self.config {
|
||||||
|
config.data_dir.clone()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let fallback = if self.fallback.is_some() {
|
||||||
|
self.fallback.clone()
|
||||||
|
} else if let Some(config) = &self.config {
|
||||||
|
config.fallback.clone()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let load_external_fallback = if let Some(config) = &self.config {
|
||||||
|
self.load_external_fallback || config.load_external_fallback
|
||||||
|
} else {
|
||||||
|
self.load_external_fallback
|
||||||
|
};
|
||||||
|
|
||||||
|
let with_ws = if let Some(config) = &self.config {
|
||||||
|
self.with_ws || config.with_ws
|
||||||
|
} else {
|
||||||
|
self.with_ws
|
||||||
|
};
|
||||||
|
|
||||||
|
let with_http = if let Some(config) = &self.config {
|
||||||
|
self.with_http || config.with_http
|
||||||
|
} else {
|
||||||
|
self.with_http
|
||||||
|
};
|
||||||
|
|
||||||
|
let strict_checkpoint_age = if let Some(config) = &self.config {
|
||||||
|
self.strict_checkpoint_age || config.strict_checkpoint_age
|
||||||
|
} else {
|
||||||
|
self.strict_checkpoint_age
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Config {
|
||||||
|
consensus_rpc,
|
||||||
|
execution_rpc,
|
||||||
|
checkpoint,
|
||||||
|
default_checkpoint,
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
rpc_port,
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
data_dir,
|
||||||
|
chain: base_config.chain,
|
||||||
|
forks: base_config.forks,
|
||||||
|
max_checkpoint_age: base_config.max_checkpoint_age,
|
||||||
|
fallback,
|
||||||
|
load_external_fallback,
|
||||||
|
strict_checkpoint_age,
|
||||||
|
with_ws,
|
||||||
|
with_http,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ClientBuilder {
|
||||||
|
pub fn build(self) -> Result<Client<FileDB, WsRpc>> {
|
||||||
|
let config = self.build_config()?;
|
||||||
|
Client::new(config)
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,17 +6,16 @@ use ethers::prelude::{Address, U256};
|
||||||
use ethers::types::{
|
use ethers::types::{
|
||||||
FeeHistory, Filter, Log, SyncingStatus, Transaction, TransactionReceipt, H256,
|
FeeHistory, Filter, Log, SyncingStatus, Transaction, TransactionReceipt, H256,
|
||||||
};
|
};
|
||||||
use eyre::{eyre, Result};
|
use eyre::Result;
|
||||||
|
|
||||||
use common::types::BlockTag;
|
use common::types::BlockTag;
|
||||||
use config::{CheckpointFallback, Config};
|
use config::{CheckpointFallback, Config};
|
||||||
use consensus::{types::Header, ConsensusClient};
|
use consensus::{types::Header, ConsensusClient};
|
||||||
|
use execution::rpc::ExecutionRpc;
|
||||||
use execution::types::{CallOpts, ExecutionBlock};
|
use execution::types::{CallOpts, ExecutionBlock};
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
use std::path::PathBuf;
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use tokio::spawn;
|
use tokio::spawn;
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
@ -34,196 +33,19 @@ use crate::node::Node;
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use crate::rpc::Rpc;
|
use crate::rpc::Rpc;
|
||||||
|
|
||||||
#[derive(Default)]
|
pub struct Client<DB: Database, R: ExecutionRpc> {
|
||||||
pub struct ClientBuilder {
|
node: Arc<RwLock<Node<R>>>,
|
||||||
network: Option<Network>,
|
|
||||||
consensus_rpc: Option<String>,
|
|
||||||
execution_rpc: Option<String>,
|
|
||||||
checkpoint: Option<Vec<u8>>,
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
rpc_port: Option<u16>,
|
rpc: Option<Rpc<R>>,
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
data_dir: Option<PathBuf>,
|
|
||||||
config: Option<Config>,
|
|
||||||
fallback: Option<String>,
|
|
||||||
load_external_fallback: bool,
|
|
||||||
strict_checkpoint_age: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ClientBuilder {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn network(mut self, network: Network) -> Self {
|
|
||||||
self.network = Some(network);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn consensus_rpc(mut self, consensus_rpc: &str) -> Self {
|
|
||||||
self.consensus_rpc = Some(consensus_rpc.to_string());
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn execution_rpc(mut self, execution_rpc: &str) -> Self {
|
|
||||||
self.execution_rpc = Some(execution_rpc.to_string());
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn checkpoint(mut self, checkpoint: &str) -> Self {
|
|
||||||
let checkpoint = hex::decode(checkpoint.strip_prefix("0x").unwrap_or(checkpoint))
|
|
||||||
.expect("cannot parse checkpoint");
|
|
||||||
self.checkpoint = Some(checkpoint);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
pub fn rpc_port(mut self, port: u16) -> Self {
|
|
||||||
self.rpc_port = Some(port);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
pub fn data_dir(mut self, data_dir: PathBuf) -> Self {
|
|
||||||
self.data_dir = Some(data_dir);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn config(mut self, config: Config) -> Self {
|
|
||||||
self.config = Some(config);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fallback(mut self, fallback: &str) -> Self {
|
|
||||||
self.fallback = Some(fallback.to_string());
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn load_external_fallback(mut self) -> Self {
|
|
||||||
self.load_external_fallback = true;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn strict_checkpoint_age(mut self) -> Self {
|
|
||||||
self.strict_checkpoint_age = true;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build<DB: Database>(self) -> Result<Client<DB>> {
|
|
||||||
let base_config = if let Some(network) = self.network {
|
|
||||||
network.to_base_config()
|
|
||||||
} else {
|
|
||||||
let config = self
|
|
||||||
.config
|
|
||||||
.as_ref()
|
|
||||||
.ok_or(eyre!("missing network config"))?;
|
|
||||||
config.to_base_config()
|
|
||||||
};
|
|
||||||
|
|
||||||
let consensus_rpc = self.consensus_rpc.unwrap_or_else(|| {
|
|
||||||
self.config
|
|
||||||
.as_ref()
|
|
||||||
.expect("missing consensus rpc")
|
|
||||||
.consensus_rpc
|
|
||||||
.clone()
|
|
||||||
});
|
|
||||||
|
|
||||||
let execution_rpc = self.execution_rpc.unwrap_or_else(|| {
|
|
||||||
self.config
|
|
||||||
.as_ref()
|
|
||||||
.expect("missing execution rpc")
|
|
||||||
.execution_rpc
|
|
||||||
.clone()
|
|
||||||
});
|
|
||||||
|
|
||||||
let checkpoint = if let Some(checkpoint) = self.checkpoint {
|
|
||||||
Some(checkpoint)
|
|
||||||
} else if let Some(config) = &self.config {
|
|
||||||
config.checkpoint.clone()
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let default_checkpoint = if let Some(config) = &self.config {
|
|
||||||
config.default_checkpoint.clone()
|
|
||||||
} else {
|
|
||||||
base_config.default_checkpoint.clone()
|
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
let rpc_port = if self.rpc_port.is_some() {
|
|
||||||
self.rpc_port
|
|
||||||
} else if let Some(config) = &self.config {
|
|
||||||
config.rpc_port
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
let data_dir = if self.data_dir.is_some() {
|
|
||||||
self.data_dir
|
|
||||||
} else if let Some(config) = &self.config {
|
|
||||||
config.data_dir.clone()
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let fallback = if self.fallback.is_some() {
|
|
||||||
self.fallback
|
|
||||||
} else if let Some(config) = &self.config {
|
|
||||||
config.fallback.clone()
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let load_external_fallback = if let Some(config) = &self.config {
|
|
||||||
self.load_external_fallback || config.load_external_fallback
|
|
||||||
} else {
|
|
||||||
self.load_external_fallback
|
|
||||||
};
|
|
||||||
|
|
||||||
let strict_checkpoint_age = if let Some(config) = &self.config {
|
|
||||||
self.strict_checkpoint_age || config.strict_checkpoint_age
|
|
||||||
} else {
|
|
||||||
self.strict_checkpoint_age
|
|
||||||
};
|
|
||||||
|
|
||||||
let config = Config {
|
|
||||||
consensus_rpc,
|
|
||||||
execution_rpc,
|
|
||||||
checkpoint,
|
|
||||||
default_checkpoint,
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
rpc_port,
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
rpc_port: None,
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
data_dir,
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
data_dir: None,
|
|
||||||
chain: base_config.chain,
|
|
||||||
forks: base_config.forks,
|
|
||||||
max_checkpoint_age: base_config.max_checkpoint_age,
|
|
||||||
fallback,
|
|
||||||
load_external_fallback,
|
|
||||||
strict_checkpoint_age,
|
|
||||||
};
|
|
||||||
|
|
||||||
Client::new(config)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Client<DB: Database> {
|
|
||||||
node: Arc<RwLock<Node>>,
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
rpc: Option<Rpc>,
|
|
||||||
db: DB,
|
db: DB,
|
||||||
fallback: Option<String>,
|
fallback: Option<String>,
|
||||||
load_external_fallback: bool,
|
load_external_fallback: bool,
|
||||||
|
ws: bool,
|
||||||
|
http: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<DB: Database> Client<DB> {
|
impl<DB: Database, R: ExecutionRpc> Client<DB, R> {
|
||||||
fn new(mut config: Config) -> Result<Self> {
|
pub fn new(mut config: Config) -> Result<Self> {
|
||||||
let db = DB::new(&config)?;
|
let db = DB::new(&config)?;
|
||||||
if config.checkpoint.is_none() {
|
if config.checkpoint.is_none() {
|
||||||
let checkpoint = db.load_checkpoint()?;
|
let checkpoint = db.load_checkpoint()?;
|
||||||
|
@ -231,11 +53,14 @@ impl<DB: Database> Client<DB> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let config = Arc::new(config);
|
let config = Arc::new(config);
|
||||||
|
|
||||||
let node = Node::new(config.clone())?;
|
let node = Node::new(config.clone())?;
|
||||||
let node = Arc::new(RwLock::new(node));
|
let node = Arc::new(RwLock::new(node));
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
let rpc = config.rpc_port.map(|port| Rpc::new(node.clone(), port));
|
let rpc = config
|
||||||
|
.rpc_port
|
||||||
|
.map(|port| Rpc::new(node.clone(), config.with_http, config.with_ws, port));
|
||||||
|
|
||||||
Ok(Client {
|
Ok(Client {
|
||||||
node,
|
node,
|
||||||
|
@ -244,13 +69,20 @@ impl<DB: Database> Client<DB> {
|
||||||
db,
|
db,
|
||||||
fallback: config.fallback.clone(),
|
fallback: config.fallback.clone(),
|
||||||
load_external_fallback: config.load_external_fallback,
|
load_external_fallback: config.load_external_fallback,
|
||||||
|
ws: config.with_ws,
|
||||||
|
http: config.with_http,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn start(&mut self) -> Result<()> {
|
pub async fn start(&mut self) -> Result<()> {
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
if let Some(rpc) = &mut self.rpc {
|
if let Some(rpc) = &mut self.rpc {
|
||||||
rpc.start().await?;
|
if self.ws {
|
||||||
|
rpc.start_ws().await?;
|
||||||
|
}
|
||||||
|
if self.http {
|
||||||
|
rpc.start_http().await?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let sync_res = self.node.write().await.sync().await;
|
let sync_res = self.node.write().await.sync().await;
|
||||||
|
@ -407,7 +239,7 @@ impl<DB: Database> Client<DB> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn call(&self, opts: &CallOpts, block: BlockTag) -> Result<Vec<u8>> {
|
pub async fn call(&self, opts: &CallOpts, block: BlockTag) -> eyre::Result<Vec<u8>> {
|
||||||
self.node
|
self.node
|
||||||
.read()
|
.read()
|
||||||
.await
|
.await
|
||||||
|
@ -416,7 +248,7 @@ impl<DB: Database> Client<DB> {
|
||||||
.map_err(|err| err.into())
|
.map_err(|err| err.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn estimate_gas(&self, opts: &CallOpts) -> Result<u64> {
|
pub async fn estimate_gas(&self, opts: &CallOpts) -> eyre::Result<u64> {
|
||||||
self.node
|
self.node
|
||||||
.read()
|
.read()
|
||||||
.await
|
.await
|
||||||
|
@ -425,11 +257,11 @@ impl<DB: Database> Client<DB> {
|
||||||
.map_err(|err| err.into())
|
.map_err(|err| err.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_balance(&self, address: &Address, block: BlockTag) -> Result<U256> {
|
pub async fn get_balance(&self, address: &Address, block: BlockTag) -> eyre::Result<U256> {
|
||||||
self.node.read().await.get_balance(address, block).await
|
self.node.read().await.get_balance(address, block).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_nonce(&self, address: &Address, block: BlockTag) -> Result<u64> {
|
pub async fn get_nonce(&self, address: &Address, block: BlockTag) -> eyre::Result<u64> {
|
||||||
self.node.read().await.get_nonce(address, block).await
|
self.node.read().await.get_nonce(address, block).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -464,14 +296,14 @@ impl<DB: Database> Client<DB> {
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_raw_transaction(&self, bytes: &[u8]) -> Result<H256> {
|
pub async fn send_raw_transaction(&self, bytes: &[u8]) -> eyre::Result<H256> {
|
||||||
self.node.read().await.send_raw_transaction(bytes).await
|
self.node.read().await.send_raw_transaction(bytes).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_transaction_receipt(
|
pub async fn get_transaction_receipt(
|
||||||
&self,
|
&self,
|
||||||
tx_hash: &H256,
|
tx_hash: &H256,
|
||||||
) -> Result<Option<TransactionReceipt>> {
|
) -> eyre::Result<Option<TransactionReceipt>> {
|
||||||
self.node
|
self.node
|
||||||
.read()
|
.read()
|
||||||
.await
|
.await
|
||||||
|
@ -479,7 +311,10 @@ impl<DB: Database> Client<DB> {
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_transaction_by_hash(&self, tx_hash: &H256) -> Result<Option<Transaction>> {
|
pub async fn get_transaction_by_hash(
|
||||||
|
&self,
|
||||||
|
tx_hash: &H256,
|
||||||
|
) -> eyre::Result<Option<Transaction>> {
|
||||||
self.node
|
self.node
|
||||||
.read()
|
.read()
|
||||||
.await
|
.await
|
||||||
|
@ -487,19 +322,19 @@ impl<DB: Database> Client<DB> {
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_logs(&self, filter: &Filter) -> Result<Vec<Log>> {
|
pub async fn get_logs(&self, filter: &Filter) -> eyre::Result<Vec<Log>> {
|
||||||
self.node.read().await.get_logs(filter).await
|
self.node.read().await.get_logs(filter).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_gas_price(&self) -> Result<U256> {
|
pub async fn get_gas_price(&self) -> eyre::Result<U256> {
|
||||||
self.node.read().await.get_gas_price()
|
self.node.read().await.get_gas_price()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_priority_fee(&self) -> Result<U256> {
|
pub async fn get_priority_fee(&self) -> eyre::Result<U256> {
|
||||||
self.node.read().await.get_priority_fee()
|
self.node.read().await.get_priority_fee()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_block_number(&self) -> Result<u64> {
|
pub async fn get_block_number(&self) -> eyre::Result<u64> {
|
||||||
self.node.read().await.get_block_number()
|
self.node.read().await.get_block_number()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -520,7 +355,7 @@ impl<DB: Database> Client<DB> {
|
||||||
&self,
|
&self,
|
||||||
block: BlockTag,
|
block: BlockTag,
|
||||||
full_tx: bool,
|
full_tx: bool,
|
||||||
) -> Result<Option<ExecutionBlock>> {
|
) -> eyre::Result<Option<ExecutionBlock>> {
|
||||||
self.node
|
self.node
|
||||||
.read()
|
.read()
|
||||||
.await
|
.await
|
||||||
|
@ -532,7 +367,7 @@ impl<DB: Database> Client<DB> {
|
||||||
&self,
|
&self,
|
||||||
hash: &Vec<u8>,
|
hash: &Vec<u8>,
|
||||||
full_tx: bool,
|
full_tx: bool,
|
||||||
) -> Result<Option<ExecutionBlock>> {
|
) -> eyre::Result<Option<ExecutionBlock>> {
|
||||||
self.node
|
self.node
|
||||||
.read()
|
.read()
|
||||||
.await
|
.await
|
||||||
|
|
|
@ -1,10 +1,20 @@
|
||||||
|
/// Re-export builder logic
|
||||||
|
mod builder;
|
||||||
|
pub use crate::builder::*;
|
||||||
|
|
||||||
|
/// Re-export client logic
|
||||||
mod client;
|
mod client;
|
||||||
pub use crate::client::*;
|
pub use crate::client::*;
|
||||||
|
|
||||||
|
/// Expose database module
|
||||||
pub mod database;
|
pub mod database;
|
||||||
|
|
||||||
|
/// Expose errors module
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
|
|
||||||
|
/// Expose rpc module
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
pub mod rpc;
|
pub mod rpc;
|
||||||
|
|
||||||
|
/// Node module is internal to the client crate
|
||||||
pub mod node;
|
pub mod node;
|
||||||
|
|
|
@ -3,9 +3,12 @@ use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use ethers::prelude::{Address, U256};
|
use ethers::prelude::{Address, U256};
|
||||||
|
|
||||||
use ethers::types::{
|
use ethers::types::{
|
||||||
FeeHistory, Filter, Log, SyncProgress, SyncingStatus, Transaction, TransactionReceipt, H256,
|
FeeHistory, Filter, Log, SyncProgress, SyncingStatus, Transaction, TransactionReceipt, H256,
|
||||||
};
|
};
|
||||||
|
use execution::rpc::{ExecutionRpc, WsRpc};
|
||||||
|
|
||||||
use eyre::{eyre, Result};
|
use eyre::{eyre, Result};
|
||||||
|
|
||||||
use common::errors::BlockNotFoundError;
|
use common::errors::BlockNotFoundError;
|
||||||
|
@ -16,15 +19,15 @@ use consensus::rpc::nimbus_rpc::NimbusRpc;
|
||||||
use consensus::types::{ExecutionPayload, Header};
|
use consensus::types::{ExecutionPayload, Header};
|
||||||
use consensus::ConsensusClient;
|
use consensus::ConsensusClient;
|
||||||
use execution::evm::Evm;
|
use execution::evm::Evm;
|
||||||
use execution::rpc::http_rpc::HttpRpc;
|
// use execution::rpc::http_rpc::HttpRpc;
|
||||||
use execution::types::{CallOpts, ExecutionBlock};
|
use execution::types::{CallOpts, ExecutionBlock};
|
||||||
use execution::ExecutionClient;
|
use execution::ExecutionClient;
|
||||||
|
|
||||||
use crate::errors::NodeError;
|
use crate::errors::NodeError;
|
||||||
|
|
||||||
pub struct Node {
|
pub struct Node<R: ExecutionRpc> {
|
||||||
pub consensus: ConsensusClient<NimbusRpc>,
|
pub consensus: ConsensusClient<NimbusRpc>,
|
||||||
pub execution: Arc<ExecutionClient<HttpRpc>>,
|
pub execution: Arc<ExecutionClient<R>>,
|
||||||
pub config: Arc<Config>,
|
pub config: Arc<Config>,
|
||||||
payloads: BTreeMap<u64, ExecutionPayload>,
|
payloads: BTreeMap<u64, ExecutionPayload>,
|
||||||
finalized_payloads: BTreeMap<u64, ExecutionPayload>,
|
finalized_payloads: BTreeMap<u64, ExecutionPayload>,
|
||||||
|
@ -32,7 +35,7 @@ pub struct Node {
|
||||||
pub history_size: usize,
|
pub history_size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node {
|
impl Node<WsRpc> {
|
||||||
pub fn new(config: Arc<Config>) -> Result<Self, NodeError> {
|
pub fn new(config: Arc<Config>) -> Result<Self, NodeError> {
|
||||||
let consensus_rpc = &config.consensus_rpc;
|
let consensus_rpc = &config.consensus_rpc;
|
||||||
let checkpoint_hash = &config.checkpoint.as_ref().unwrap();
|
let checkpoint_hash = &config.checkpoint.as_ref().unwrap();
|
||||||
|
@ -40,9 +43,18 @@ impl Node {
|
||||||
|
|
||||||
let consensus = ConsensusClient::new(consensus_rpc, checkpoint_hash, config.clone())
|
let consensus = ConsensusClient::new(consensus_rpc, checkpoint_hash, config.clone())
|
||||||
.map_err(NodeError::ConsensusClientCreationError)?;
|
.map_err(NodeError::ConsensusClientCreationError)?;
|
||||||
let execution = Arc::new(
|
|
||||||
ExecutionClient::new(execution_rpc).map_err(NodeError::ExecutionClientCreationError)?,
|
let execution = if config.with_ws {
|
||||||
);
|
Arc::new(
|
||||||
|
ExecutionClient::new_with_ws(execution_rpc)
|
||||||
|
.map_err(NodeError::ExecutionClientCreationError)?,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Arc::new(
|
||||||
|
ExecutionClient::new(execution_rpc)
|
||||||
|
.map_err(NodeError::ExecutionClientCreationError)?,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
let payloads = BTreeMap::new();
|
let payloads = BTreeMap::new();
|
||||||
let finalized_payloads = BTreeMap::new();
|
let finalized_payloads = BTreeMap::new();
|
||||||
|
@ -57,7 +69,12 @@ impl Node {
|
||||||
history_size: 64,
|
history_size: 64,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R> Node<R>
|
||||||
|
where
|
||||||
|
R: ExecutionRpc,
|
||||||
|
{
|
||||||
pub async fn sync(&mut self) -> Result<(), NodeError> {
|
pub async fn sync(&mut self) -> Result<(), NodeError> {
|
||||||
let chain_id = self.config.chain.chain_id;
|
let chain_id = self.config.chain.chain_id;
|
||||||
self.execution
|
self.execution
|
||||||
|
@ -109,11 +126,11 @@ impl Node {
|
||||||
.map_err(NodeError::ConsensusPayloadError)?;
|
.map_err(NodeError::ConsensusPayloadError)?;
|
||||||
|
|
||||||
self.payloads
|
self.payloads
|
||||||
.insert(*latest_payload.block_number(), latest_payload);
|
.insert(latest_payload.block_number, latest_payload);
|
||||||
self.payloads
|
self.payloads
|
||||||
.insert(*finalized_payload.block_number(), finalized_payload.clone());
|
.insert(finalized_payload.block_number, finalized_payload.clone());
|
||||||
self.finalized_payloads
|
self.finalized_payloads
|
||||||
.insert(*finalized_payload.block_number(), finalized_payload);
|
.insert(finalized_payload.block_number, finalized_payload);
|
||||||
|
|
||||||
let start_slot = self
|
let start_slot = self
|
||||||
.current_slot
|
.current_slot
|
||||||
|
@ -124,7 +141,7 @@ impl Node {
|
||||||
.await
|
.await
|
||||||
.map_err(NodeError::ConsensusPayloadError)?;
|
.map_err(NodeError::ConsensusPayloadError)?;
|
||||||
for payload in backfill_payloads {
|
for payload in backfill_payloads {
|
||||||
self.payloads.insert(*payload.block_number(), payload);
|
self.payloads.insert(payload.block_number, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.current_slot = Some(latest_header.slot);
|
self.current_slot = Some(latest_header.slot);
|
||||||
|
@ -188,14 +205,14 @@ impl Node {
|
||||||
|
|
||||||
pub fn get_block_transaction_count_by_hash(&self, hash: &Vec<u8>) -> Result<u64> {
|
pub fn get_block_transaction_count_by_hash(&self, hash: &Vec<u8>) -> Result<u64> {
|
||||||
let payload = self.get_payload_by_hash(hash)?;
|
let payload = self.get_payload_by_hash(hash)?;
|
||||||
let transaction_count = payload.1.transactions().len();
|
let transaction_count = payload.1.transactions.len();
|
||||||
|
|
||||||
Ok(transaction_count as u64)
|
Ok(transaction_count as u64)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_block_transaction_count_by_number(&self, block: BlockTag) -> Result<u64> {
|
pub fn get_block_transaction_count_by_number(&self, block: BlockTag) -> Result<u64> {
|
||||||
let payload = self.get_payload(block)?;
|
let payload = self.get_payload(block)?;
|
||||||
let transaction_count = payload.transactions().len();
|
let transaction_count = payload.transactions.len();
|
||||||
|
|
||||||
Ok(transaction_count as u64)
|
Ok(transaction_count as u64)
|
||||||
}
|
}
|
||||||
|
@ -269,7 +286,7 @@ impl Node {
|
||||||
self.check_head_age()?;
|
self.check_head_age()?;
|
||||||
|
|
||||||
let payload = self.get_payload(BlockTag::Latest)?;
|
let payload = self.get_payload(BlockTag::Latest)?;
|
||||||
let base_fee = U256::from_little_endian(&payload.base_fee_per_gas().to_bytes_le());
|
let base_fee = U256::from_little_endian(&payload.base_fee_per_gas.to_bytes_le());
|
||||||
let tip = U256::from(10_u64.pow(9));
|
let tip = U256::from(10_u64.pow(9));
|
||||||
Ok(base_fee + tip)
|
Ok(base_fee + tip)
|
||||||
}
|
}
|
||||||
|
@ -284,7 +301,7 @@ impl Node {
|
||||||
self.check_head_age()?;
|
self.check_head_age()?;
|
||||||
|
|
||||||
let payload = self.get_payload(BlockTag::Latest)?;
|
let payload = self.get_payload(BlockTag::Latest)?;
|
||||||
Ok(*payload.block_number())
|
Ok(payload.block_number)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_block_by_number(
|
pub async fn get_block_by_number(
|
||||||
|
@ -367,7 +384,7 @@ impl Node {
|
||||||
pub fn get_coinbase(&self) -> Result<Address> {
|
pub fn get_coinbase(&self) -> Result<Address> {
|
||||||
self.check_head_age()?;
|
self.check_head_age()?;
|
||||||
let payload = self.get_payload(BlockTag::Latest)?;
|
let payload = self.get_payload(BlockTag::Latest)?;
|
||||||
let coinbase_address = Address::from_slice(payload.fee_recipient());
|
let coinbase_address = Address::from_slice(&payload.fee_recipient);
|
||||||
Ok(coinbase_address)
|
Ok(coinbase_address)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,7 +415,7 @@ impl Node {
|
||||||
let payloads = self
|
let payloads = self
|
||||||
.payloads
|
.payloads
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|entry| &entry.1.block_hash().to_vec() == hash)
|
.filter(|entry| &entry.1.block_hash.to_vec() == hash)
|
||||||
.collect::<Vec<(&u64, &ExecutionPayload)>>();
|
.collect::<Vec<(&u64, &ExecutionPayload)>>();
|
||||||
|
|
||||||
payloads
|
payloads
|
||||||
|
|
|
@ -3,7 +3,6 @@ use ethers::{
|
||||||
types::{Address, Filter, Log, SyncingStatus, Transaction, TransactionReceipt, H256, U256},
|
types::{Address, Filter, Log, SyncingStatus, Transaction, TransactionReceipt, H256, U256},
|
||||||
};
|
};
|
||||||
use eyre::Result;
|
use eyre::Result;
|
||||||
use log::info;
|
|
||||||
use std::{fmt::Display, net::SocketAddr, str::FromStr, sync::Arc};
|
use std::{fmt::Display, net::SocketAddr, str::FromStr, sync::Arc};
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
|
@ -11,6 +10,7 @@ use jsonrpsee::{
|
||||||
core::{async_trait, server::rpc_module::Methods, Error},
|
core::{async_trait, server::rpc_module::Methods, Error},
|
||||||
http_server::{HttpServerBuilder, HttpServerHandle},
|
http_server::{HttpServerBuilder, HttpServerHandle},
|
||||||
proc_macros::rpc,
|
proc_macros::rpc,
|
||||||
|
ws_server::{WsServerBuilder, WsServerHandle},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{errors::NodeError, node::Node};
|
use crate::{errors::NodeError, node::Node};
|
||||||
|
@ -19,35 +19,50 @@ use common::{
|
||||||
types::BlockTag,
|
types::BlockTag,
|
||||||
utils::{hex_str_to_bytes, u64_to_hex_string},
|
utils::{hex_str_to_bytes, u64_to_hex_string},
|
||||||
};
|
};
|
||||||
use execution::types::{CallOpts, ExecutionBlock};
|
use execution::{
|
||||||
|
rpc::ExecutionRpc,
|
||||||
|
types::{CallOpts, ExecutionBlock},
|
||||||
|
};
|
||||||
|
|
||||||
pub struct Rpc {
|
pub struct Rpc<R: ExecutionRpc> {
|
||||||
node: Arc<RwLock<Node>>,
|
node: Arc<RwLock<Node<R>>>,
|
||||||
handle: Option<HttpServerHandle>,
|
http_handle: Option<HttpServerHandle>,
|
||||||
|
ws_handle: Option<WsServerHandle>,
|
||||||
|
pub with_http: bool,
|
||||||
|
pub with_ws: bool,
|
||||||
port: u16,
|
port: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rpc {
|
impl<R: ExecutionRpc> Rpc<R> {
|
||||||
pub fn new(node: Arc<RwLock<Node>>, port: u16) -> Self {
|
pub fn new(node: Arc<RwLock<Node<R>>>, with_http: bool, with_ws: bool, port: u16) -> Self {
|
||||||
Rpc {
|
Rpc {
|
||||||
node,
|
node,
|
||||||
handle: None,
|
http_handle: None,
|
||||||
|
ws_handle: None,
|
||||||
|
with_http,
|
||||||
|
with_ws,
|
||||||
port,
|
port,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn start(&mut self) -> Result<SocketAddr> {
|
pub async fn start_http(&mut self) -> Result<Option<SocketAddr>> {
|
||||||
let rpc_inner = RpcInner {
|
if self.with_http {
|
||||||
node: self.node.clone(),
|
let (handle, addr) = RpcInner::from(&*self).start_http().await?;
|
||||||
port: self.port,
|
self.http_handle = Some(handle);
|
||||||
};
|
log::info!("http rpc server started at {}", addr);
|
||||||
|
return Ok(Some(addr));
|
||||||
|
}
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
let (handle, addr) = start(rpc_inner).await?;
|
pub async fn start_ws(&mut self) -> Result<Option<SocketAddr>> {
|
||||||
self.handle = Some(handle);
|
if self.with_ws {
|
||||||
|
let (handle, addr) = RpcInner::from(&*self).start_ws().await?;
|
||||||
info!("rpc server started at {}", addr);
|
self.ws_handle = Some(handle);
|
||||||
|
log::info!("http rpc server started at {}", addr);
|
||||||
Ok(addr)
|
return Ok(Some(addr));
|
||||||
|
}
|
||||||
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,19 +140,68 @@ trait NetRpc {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct RpcInner {
|
struct RpcInner<R: ExecutionRpc> {
|
||||||
node: Arc<RwLock<Node>>,
|
node: Arc<RwLock<Node<R>>>,
|
||||||
port: u16,
|
http_port: u16,
|
||||||
|
ws_port: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R: ExecutionRpc> From<&Rpc<R>> for RpcInner<R> {
|
||||||
|
fn from(rpc: &Rpc<R>) -> Self {
|
||||||
|
RpcInner {
|
||||||
|
node: Arc::clone(&rpc.node),
|
||||||
|
http_port: rpc.port,
|
||||||
|
ws_port: 4443,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R: ExecutionRpc> RpcInner<R> {
|
||||||
|
pub async fn start_http(&self) -> Result<(HttpServerHandle, SocketAddr)> {
|
||||||
|
let addr = format!("127.0.0.1:{}", self.http_port);
|
||||||
|
let server = HttpServerBuilder::default().build(addr).await?;
|
||||||
|
|
||||||
|
let addr = server.local_addr()?;
|
||||||
|
|
||||||
|
let mut methods = Methods::new();
|
||||||
|
let eth_methods: Methods = EthRpcServer::into_rpc(self.clone()).into();
|
||||||
|
let net_methods: Methods = NetRpcServer::into_rpc(self.clone()).into();
|
||||||
|
|
||||||
|
methods.merge(eth_methods)?;
|
||||||
|
methods.merge(net_methods)?;
|
||||||
|
|
||||||
|
let handle = server.start(methods)?;
|
||||||
|
|
||||||
|
Ok((handle, addr))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn start_ws(&self) -> Result<(WsServerHandle, SocketAddr)> {
|
||||||
|
let addr = format!("127.0.0.1:{}", self.ws_port);
|
||||||
|
let server = WsServerBuilder::default().build(addr).await?;
|
||||||
|
|
||||||
|
let addr = server.local_addr()?;
|
||||||
|
|
||||||
|
let mut methods = Methods::new();
|
||||||
|
let eth_methods: Methods = EthRpcServer::into_rpc(self.clone()).into();
|
||||||
|
let net_methods: Methods = NetRpcServer::into_rpc(self.clone()).into();
|
||||||
|
|
||||||
|
methods.merge(eth_methods)?;
|
||||||
|
methods.merge(net_methods)?;
|
||||||
|
|
||||||
|
let handle = server.start(methods)?;
|
||||||
|
|
||||||
|
Ok((handle, addr))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl EthRpcServer for RpcInner {
|
impl<R: ExecutionRpc> EthRpcServer for RpcInner<R> {
|
||||||
async fn get_balance(&self, address: &str, block: BlockTag) -> Result<String, Error> {
|
async fn get_balance(&self, address: &str, block: BlockTag) -> Result<String, Error> {
|
||||||
let address = convert_err(Address::from_str(address))?;
|
let address = convert_err(Address::from_str(address))?;
|
||||||
let node = self.node.read().await;
|
let node = self.node.read().await;
|
||||||
let balance = convert_err(node.get_balance(&address, block).await)?;
|
let balance = convert_err(node.get_balance(&address, block).await)?;
|
||||||
|
|
||||||
Ok(format_hex(&balance))
|
Ok(common::utils::format_hex(&balance))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_transaction_count(&self, address: &str, block: BlockTag) -> Result<String, Error> {
|
async fn get_transaction_count(&self, address: &str, block: BlockTag) -> Result<String, Error> {
|
||||||
|
@ -203,13 +267,13 @@ impl EthRpcServer for RpcInner {
|
||||||
async fn gas_price(&self) -> Result<String, Error> {
|
async fn gas_price(&self) -> Result<String, Error> {
|
||||||
let node = self.node.read().await;
|
let node = self.node.read().await;
|
||||||
let gas_price = convert_err(node.get_gas_price())?;
|
let gas_price = convert_err(node.get_gas_price())?;
|
||||||
Ok(format_hex(&gas_price))
|
Ok(common::utils::format_hex(&gas_price))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn max_priority_fee_per_gas(&self) -> Result<String, Error> {
|
async fn max_priority_fee_per_gas(&self) -> Result<String, Error> {
|
||||||
let node = self.node.read().await;
|
let node = self.node.read().await;
|
||||||
let tip = convert_err(node.get_priority_fee())?;
|
let tip = convert_err(node.get_priority_fee())?;
|
||||||
Ok(format_hex(&tip))
|
Ok(common::utils::format_hex(&tip))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn block_number(&self) -> Result<String, Error> {
|
async fn block_number(&self) -> Result<String, Error> {
|
||||||
|
@ -305,31 +369,13 @@ impl EthRpcServer for RpcInner {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl NetRpcServer for RpcInner {
|
impl<R: ExecutionRpc> NetRpcServer for RpcInner<R> {
|
||||||
async fn version(&self) -> Result<String, Error> {
|
async fn version(&self) -> Result<String, Error> {
|
||||||
let node = self.node.read().await;
|
let node = self.node.read().await;
|
||||||
Ok(node.chain_id().to_string())
|
Ok(node.chain_id().to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn start(rpc: RpcInner) -> Result<(HttpServerHandle, SocketAddr)> {
|
|
||||||
let addr = format!("127.0.0.1:{}", rpc.port);
|
|
||||||
let server = HttpServerBuilder::default().build(addr).await?;
|
|
||||||
|
|
||||||
let addr = server.local_addr()?;
|
|
||||||
|
|
||||||
let mut methods = Methods::new();
|
|
||||||
let eth_methods: Methods = EthRpcServer::into_rpc(rpc.clone()).into();
|
|
||||||
let net_methods: Methods = NetRpcServer::into_rpc(rpc).into();
|
|
||||||
|
|
||||||
methods.merge(eth_methods)?;
|
|
||||||
methods.merge(net_methods)?;
|
|
||||||
|
|
||||||
let handle = server.start(methods)?;
|
|
||||||
|
|
||||||
Ok((handle, addr))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn convert_err<T, E: Display>(res: Result<T, E>) -> Result<T, Error> {
|
fn convert_err<T, E: Display>(res: Result<T, E>) -> Result<T, Error> {
|
||||||
res.map_err(|err| Error::Custom(err.to_string()))
|
res.map_err(|err| Error::Custom(err.to_string()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "common"
|
name = "common"
|
||||||
version = "0.3.0"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -8,5 +8,5 @@ eyre = "0.6.8"
|
||||||
serde = { version = "1.0.143", features = ["derive"] }
|
serde = { version = "1.0.143", features = ["derive"] }
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs", rev = "d09f55b4f8554491e3431e01af1c32347a8781cd" }
|
ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs", rev = "d09f55b4f8554491e3431e01af1c32347a8781cd" }
|
||||||
ethers = "1.0.0"
|
ethers = { version = "1.0.2", features = [ "ws", "default" ] }
|
||||||
thiserror = "1.0.37"
|
thiserror = "1.0.37"
|
||||||
|
|
|
@ -1,9 +1,22 @@
|
||||||
use ethers::prelude::Address;
|
use ethers::{
|
||||||
|
abi::AbiEncode,
|
||||||
|
types::{Address, U256},
|
||||||
|
};
|
||||||
use eyre::Result;
|
use eyre::Result;
|
||||||
use ssz_rs::{Node, Vector};
|
use ssz_rs::{Node, Vector};
|
||||||
|
|
||||||
use super::types::Bytes32;
|
use super::types::Bytes32;
|
||||||
|
|
||||||
|
pub fn format_hex(num: &U256) -> String {
|
||||||
|
let stripped = num
|
||||||
|
.encode_hex()
|
||||||
|
.strip_prefix("0x")
|
||||||
|
.unwrap()
|
||||||
|
.trim_start_matches('0')
|
||||||
|
.to_string();
|
||||||
|
format!("0x{stripped}")
|
||||||
|
}
|
||||||
|
|
||||||
pub fn hex_str_to_bytes(s: &str) -> Result<Vec<u8>> {
|
pub fn hex_str_to_bytes(s: &str) -> Result<Vec<u8>> {
|
||||||
let stripped = s.strip_prefix("0x").unwrap_or(s);
|
let stripped = s.strip_prefix("0x").unwrap_or(s);
|
||||||
Ok(hex::decode(stripped)?)
|
Ok(hex::decode(stripped)?)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "config"
|
name = "config"
|
||||||
version = "0.3.0"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -9,7 +9,7 @@ eyre = "0.6.8"
|
||||||
serde = { version = "1.0.143", features = ["derive"] }
|
serde = { version = "1.0.143", features = ["derive"] }
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs", rev = "d09f55b4f8554491e3431e01af1c32347a8781cd" }
|
ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs", rev = "d09f55b4f8554491e3431e01af1c32347a8781cd" }
|
||||||
ethers = "1.0.0"
|
ethers = { version = "1.0.2", features = [ "ws", "default" ] }
|
||||||
figment = { version = "0.10.7", features = ["toml", "env"] }
|
figment = { version = "0.10.7", features = ["toml", "env"] }
|
||||||
thiserror = "1.0.37"
|
thiserror = "1.0.37"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
|
|
|
@ -14,6 +14,8 @@ pub struct CliConfig {
|
||||||
pub fallback: Option<String>,
|
pub fallback: Option<String>,
|
||||||
pub load_external_fallback: bool,
|
pub load_external_fallback: bool,
|
||||||
pub strict_checkpoint_age: bool,
|
pub strict_checkpoint_age: bool,
|
||||||
|
pub with_ws: bool,
|
||||||
|
pub with_http: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CliConfig {
|
impl CliConfig {
|
||||||
|
@ -52,6 +54,10 @@ impl CliConfig {
|
||||||
Value::from(self.strict_checkpoint_age),
|
Value::from(self.strict_checkpoint_age),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
user_dict.insert("with_ws", Value::from(self.with_ws));
|
||||||
|
|
||||||
|
user_dict.insert("with_http", Value::from(self.with_http));
|
||||||
|
|
||||||
Serialized::from(user_dict, network)
|
Serialized::from(user_dict, network)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,8 @@ pub struct Config {
|
||||||
pub fallback: Option<String>,
|
pub fallback: Option<String>,
|
||||||
pub load_external_fallback: bool,
|
pub load_external_fallback: bool,
|
||||||
pub strict_checkpoint_age: bool,
|
pub strict_checkpoint_age: bool,
|
||||||
|
pub with_ws: bool,
|
||||||
|
pub with_http: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
|
@ -73,9 +75,7 @@ impl Config {
|
||||||
pub fn fork_version(&self, slot: u64) -> Vec<u8> {
|
pub fn fork_version(&self, slot: u64) -> Vec<u8> {
|
||||||
let epoch = slot / 32;
|
let epoch = slot / 32;
|
||||||
|
|
||||||
if epoch >= self.forks.capella.epoch {
|
if epoch >= self.forks.bellatrix.epoch {
|
||||||
self.forks.capella.fork_version.clone()
|
|
||||||
} else if epoch >= self.forks.bellatrix.epoch {
|
|
||||||
self.forks.bellatrix.fork_version.clone()
|
self.forks.bellatrix.fork_version.clone()
|
||||||
} else if epoch >= self.forks.altair.epoch {
|
} else if epoch >= self.forks.altair.epoch {
|
||||||
self.forks.altair.fork_version.clone()
|
self.forks.altair.fork_version.clone()
|
||||||
|
|
|
@ -62,10 +62,6 @@ pub fn mainnet() -> BaseConfig {
|
||||||
epoch: 144896,
|
epoch: 144896,
|
||||||
fork_version: hex_str_to_bytes("0x02000000").unwrap(),
|
fork_version: hex_str_to_bytes("0x02000000").unwrap(),
|
||||||
},
|
},
|
||||||
capella: Fork {
|
|
||||||
epoch: u64::MAX, // TODO: set epoch when known
|
|
||||||
fork_version: hex_str_to_bytes("0x03000000").unwrap(),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
max_checkpoint_age: 1_209_600, // 14 days
|
max_checkpoint_age: 1_209_600, // 14 days
|
||||||
}
|
}
|
||||||
|
@ -100,10 +96,6 @@ pub fn goerli() -> BaseConfig {
|
||||||
epoch: 112260,
|
epoch: 112260,
|
||||||
fork_version: hex_str_to_bytes("0x02001020").unwrap(),
|
fork_version: hex_str_to_bytes("0x02001020").unwrap(),
|
||||||
},
|
},
|
||||||
capella: Fork {
|
|
||||||
epoch: 162304,
|
|
||||||
fork_version: hex_str_to_bytes("0x03001020").unwrap(),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
max_checkpoint_age: 1_209_600, // 14 days
|
max_checkpoint_age: 1_209_600, // 14 days
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@ pub struct Forks {
|
||||||
pub genesis: Fork,
|
pub genesis: Fork,
|
||||||
pub altair: Fork,
|
pub altair: Fork,
|
||||||
pub bellatrix: Fork,
|
pub bellatrix: Fork,
|
||||||
pub capella: Fork,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "consensus"
|
name = "consensus"
|
||||||
version = "0.3.0"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -11,7 +11,7 @@ serde_json = "1.0.85"
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs", rev = "d09f55b4f8554491e3431e01af1c32347a8781cd" }
|
ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs", rev = "d09f55b4f8554491e3431e01af1c32347a8781cd" }
|
||||||
milagro_bls = { git = "https://github.com/Snowfork/milagro_bls" }
|
milagro_bls = { git = "https://github.com/Snowfork/milagro_bls" }
|
||||||
ethers = "1.0.0"
|
ethers = { version = "1.0.2", features = [ "ws", "default" ] }
|
||||||
bytes = "1.2.1"
|
bytes = "1.2.1"
|
||||||
toml = "0.5.9"
|
toml = "0.5.9"
|
||||||
async-trait = "0.1.57"
|
async-trait = "0.1.57"
|
||||||
|
@ -19,7 +19,6 @@ log = "0.4.17"
|
||||||
chrono = "0.4.23"
|
chrono = "0.4.23"
|
||||||
thiserror = "1.0.37"
|
thiserror = "1.0.37"
|
||||||
reqwest = { version = "0.11.13", features = ["json"] }
|
reqwest = { version = "0.11.13", features = ["json"] }
|
||||||
superstruct = "0.7.0"
|
|
||||||
|
|
||||||
common = { path = "../common" }
|
common = { path = "../common" }
|
||||||
config = { path = "../config" }
|
config = { path = "../config" }
|
||||||
|
|
|
@ -103,7 +103,7 @@ impl<R: ConsensusRpc> ConsensusClient<R> {
|
||||||
)
|
)
|
||||||
.into())
|
.into())
|
||||||
} else {
|
} else {
|
||||||
Ok(block.body.execution_payload().clone())
|
Ok(block.body.execution_payload)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,33 +115,30 @@ impl<R: ConsensusRpc> ConsensusClient<R> {
|
||||||
let payloads_fut = (start_slot..end_slot)
|
let payloads_fut = (start_slot..end_slot)
|
||||||
.rev()
|
.rev()
|
||||||
.map(|slot| self.rpc.get_block(slot));
|
.map(|slot| self.rpc.get_block(slot));
|
||||||
|
|
||||||
let mut prev_parent_hash: Bytes32 = self
|
let mut prev_parent_hash: Bytes32 = self
|
||||||
.rpc
|
.rpc
|
||||||
.get_block(end_slot)
|
.get_block(end_slot)
|
||||||
.await?
|
.await?
|
||||||
.body
|
.body
|
||||||
.execution_payload()
|
.execution_payload
|
||||||
.parent_hash()
|
.parent_hash;
|
||||||
.clone();
|
|
||||||
|
|
||||||
let mut payloads: Vec<ExecutionPayload> = Vec::new();
|
let mut payloads: Vec<ExecutionPayload> = Vec::new();
|
||||||
for result in join_all(payloads_fut).await {
|
for result in join_all(payloads_fut).await {
|
||||||
if result.is_err() {
|
if result.is_err() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let payload = result.unwrap().body.execution_payload().clone();
|
let payload = result.unwrap().body.execution_payload;
|
||||||
if payload.block_hash() != &prev_parent_hash {
|
if payload.block_hash != prev_parent_hash {
|
||||||
warn!(
|
warn!(
|
||||||
"error while backfilling blocks: {}",
|
"error while backfilling blocks: {}",
|
||||||
ConsensusError::InvalidHeaderHash(
|
ConsensusError::InvalidHeaderHash(
|
||||||
format!("{prev_parent_hash:02X?}"),
|
format!("{prev_parent_hash:02X?}"),
|
||||||
format!("{:02X?}", payload.parent_hash()),
|
format!("{:02X?}", payload.parent_hash),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
prev_parent_hash = payload.parent_hash().clone();
|
prev_parent_hash = payload.parent_hash.clone();
|
||||||
payloads.push(payload);
|
payloads.push(payload);
|
||||||
}
|
}
|
||||||
Ok(payloads)
|
Ok(payloads)
|
||||||
|
|
|
@ -4,7 +4,6 @@ use ssz_rs::prelude::*;
|
||||||
|
|
||||||
use common::types::Bytes32;
|
use common::types::Bytes32;
|
||||||
use common::utils::hex_str_to_bytes;
|
use common::utils::hex_str_to_bytes;
|
||||||
use superstruct::superstruct;
|
|
||||||
|
|
||||||
pub type BLSPubKey = Vector<u8, 48>;
|
pub type BLSPubKey = Vector<u8, 48>;
|
||||||
pub type SignatureBytes = Vector<u8, 96>;
|
pub type SignatureBytes = Vector<u8, 96>;
|
||||||
|
@ -25,15 +24,7 @@ pub struct BeaconBlock {
|
||||||
pub body: BeaconBlockBody,
|
pub body: BeaconBlockBody,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[superstruct(
|
#[derive(serde::Deserialize, Debug, Default, SimpleSerialize, Clone)]
|
||||||
variants(Bellatrix, Capella),
|
|
||||||
variant_attributes(
|
|
||||||
derive(serde::Deserialize, Clone, Debug, SimpleSerialize, Default),
|
|
||||||
serde(deny_unknown_fields)
|
|
||||||
)
|
|
||||||
)]
|
|
||||||
#[derive(serde::Deserialize, Debug, Clone)]
|
|
||||||
#[serde(untagged)]
|
|
||||||
pub struct BeaconBlockBody {
|
pub struct BeaconBlockBody {
|
||||||
#[serde(deserialize_with = "signature_deserialize")]
|
#[serde(deserialize_with = "signature_deserialize")]
|
||||||
randao_reveal: SignatureBytes,
|
randao_reveal: SignatureBytes,
|
||||||
|
@ -47,79 +38,9 @@ pub struct BeaconBlockBody {
|
||||||
voluntary_exits: List<SignedVoluntaryExit, 16>,
|
voluntary_exits: List<SignedVoluntaryExit, 16>,
|
||||||
sync_aggregate: SyncAggregate,
|
sync_aggregate: SyncAggregate,
|
||||||
pub execution_payload: ExecutionPayload,
|
pub execution_payload: ExecutionPayload,
|
||||||
#[superstruct(only(Capella))]
|
|
||||||
bls_to_execution_changes: List<SignedBlsToExecutionChange, 16>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ssz_rs::Merkleized for BeaconBlockBody {
|
#[derive(serde::Deserialize, Debug, Default, SimpleSerialize, Clone)]
|
||||||
fn hash_tree_root(&mut self) -> Result<Node, MerkleizationError> {
|
|
||||||
match self {
|
|
||||||
BeaconBlockBody::Bellatrix(body) => body.hash_tree_root(),
|
|
||||||
BeaconBlockBody::Capella(body) => body.hash_tree_root(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ssz_rs::Sized for BeaconBlockBody {
|
|
||||||
fn is_variable_size() -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn size_hint() -> usize {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ssz_rs::Serialize for BeaconBlockBody {
|
|
||||||
fn serialize(&self, buffer: &mut Vec<u8>) -> Result<usize, SerializeError> {
|
|
||||||
match self {
|
|
||||||
BeaconBlockBody::Bellatrix(body) => body.serialize(buffer),
|
|
||||||
BeaconBlockBody::Capella(body) => body.serialize(buffer),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ssz_rs::Deserialize for BeaconBlockBody {
|
|
||||||
fn deserialize(_encoding: &[u8]) -> Result<Self, DeserializeError>
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
panic!("not implemented");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Clone, Debug, SimpleSerialize, serde::Deserialize)]
|
|
||||||
pub struct SignedBlsToExecutionChange {
|
|
||||||
message: BlsToExecutionChange,
|
|
||||||
#[serde(deserialize_with = "signature_deserialize")]
|
|
||||||
signature: SignatureBytes,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Clone, Debug, SimpleSerialize, serde::Deserialize)]
|
|
||||||
pub struct BlsToExecutionChange {
|
|
||||||
#[serde(deserialize_with = "u64_deserialize")]
|
|
||||||
validator_index: u64,
|
|
||||||
#[serde(deserialize_with = "pubkey_deserialize")]
|
|
||||||
from_bls_pubkey: BLSPubKey,
|
|
||||||
#[serde(deserialize_with = "address_deserialize")]
|
|
||||||
to_execution_address: Address,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for BeaconBlockBody {
|
|
||||||
fn default() -> Self {
|
|
||||||
BeaconBlockBody::Bellatrix(BeaconBlockBodyBellatrix::default())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[superstruct(
|
|
||||||
variants(Bellatrix, Capella),
|
|
||||||
variant_attributes(
|
|
||||||
derive(serde::Deserialize, Debug, Default, SimpleSerialize, Clone),
|
|
||||||
serde(deny_unknown_fields)
|
|
||||||
)
|
|
||||||
)]
|
|
||||||
#[derive(serde::Deserialize, Debug, Clone)]
|
|
||||||
#[serde(untagged)]
|
|
||||||
pub struct ExecutionPayload {
|
pub struct ExecutionPayload {
|
||||||
#[serde(deserialize_with = "bytes32_deserialize")]
|
#[serde(deserialize_with = "bytes32_deserialize")]
|
||||||
pub parent_hash: Bytes32,
|
pub parent_hash: Bytes32,
|
||||||
|
@ -149,67 +70,10 @@ pub struct ExecutionPayload {
|
||||||
pub block_hash: Bytes32,
|
pub block_hash: Bytes32,
|
||||||
#[serde(deserialize_with = "transactions_deserialize")]
|
#[serde(deserialize_with = "transactions_deserialize")]
|
||||||
pub transactions: List<Transaction, 1048576>,
|
pub transactions: List<Transaction, 1048576>,
|
||||||
#[superstruct(only(Capella))]
|
|
||||||
withdrawals: List<Withdrawal, 16>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Clone, Debug, SimpleSerialize, serde::Deserialize)]
|
|
||||||
pub struct Withdrawal {
|
|
||||||
#[serde(deserialize_with = "u64_deserialize")]
|
|
||||||
index: u64,
|
|
||||||
#[serde(deserialize_with = "u64_deserialize")]
|
|
||||||
validator_index: u64,
|
|
||||||
#[serde(deserialize_with = "address_deserialize")]
|
|
||||||
address: Address,
|
|
||||||
#[serde(deserialize_with = "u64_deserialize")]
|
|
||||||
amount: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ssz_rs::Merkleized for ExecutionPayload {
|
|
||||||
fn hash_tree_root(&mut self) -> Result<Node, MerkleizationError> {
|
|
||||||
match self {
|
|
||||||
ExecutionPayload::Bellatrix(payload) => payload.hash_tree_root(),
|
|
||||||
ExecutionPayload::Capella(payload) => payload.hash_tree_root(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ssz_rs::Sized for ExecutionPayload {
|
|
||||||
fn is_variable_size() -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn size_hint() -> usize {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ssz_rs::Serialize for ExecutionPayload {
|
|
||||||
fn serialize(&self, buffer: &mut Vec<u8>) -> Result<usize, SerializeError> {
|
|
||||||
match self {
|
|
||||||
ExecutionPayload::Bellatrix(payload) => payload.serialize(buffer),
|
|
||||||
ExecutionPayload::Capella(payload) => payload.serialize(buffer),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ssz_rs::Deserialize for ExecutionPayload {
|
|
||||||
fn deserialize(_encoding: &[u8]) -> Result<Self, DeserializeError>
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
panic!("not implemented");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for ExecutionPayload {
|
|
||||||
fn default() -> Self {
|
|
||||||
ExecutionPayload::Bellatrix(ExecutionPayloadBellatrix::default())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize, Debug, Default, SimpleSerialize, Clone)]
|
#[derive(serde::Deserialize, Debug, Default, SimpleSerialize, Clone)]
|
||||||
pub struct ProposerSlashing {
|
struct ProposerSlashing {
|
||||||
signed_header_1: SignedBeaconBlockHeader,
|
signed_header_1: SignedBeaconBlockHeader,
|
||||||
signed_header_2: SignedBeaconBlockHeader,
|
signed_header_2: SignedBeaconBlockHeader,
|
||||||
}
|
}
|
||||||
|
@ -236,7 +100,7 @@ struct BeaconBlockHeader {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize, Debug, Default, SimpleSerialize, Clone)]
|
#[derive(serde::Deserialize, Debug, Default, SimpleSerialize, Clone)]
|
||||||
pub struct AttesterSlashing {
|
struct AttesterSlashing {
|
||||||
attestation_1: IndexedAttestation,
|
attestation_1: IndexedAttestation,
|
||||||
attestation_2: IndexedAttestation,
|
attestation_2: IndexedAttestation,
|
||||||
}
|
}
|
||||||
|
@ -251,7 +115,7 @@ struct IndexedAttestation {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize, Debug, Default, SimpleSerialize, Clone)]
|
#[derive(serde::Deserialize, Debug, Default, SimpleSerialize, Clone)]
|
||||||
pub struct Attestation {
|
struct Attestation {
|
||||||
aggregation_bits: Bitlist<2048>,
|
aggregation_bits: Bitlist<2048>,
|
||||||
data: AttestationData,
|
data: AttestationData,
|
||||||
#[serde(deserialize_with = "signature_deserialize")]
|
#[serde(deserialize_with = "signature_deserialize")]
|
||||||
|
@ -279,7 +143,7 @@ struct Checkpoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize, Debug, Default, SimpleSerialize, Clone)]
|
#[derive(serde::Deserialize, Debug, Default, SimpleSerialize, Clone)]
|
||||||
pub struct SignedVoluntaryExit {
|
struct SignedVoluntaryExit {
|
||||||
message: VoluntaryExit,
|
message: VoluntaryExit,
|
||||||
#[serde(deserialize_with = "signature_deserialize")]
|
#[serde(deserialize_with = "signature_deserialize")]
|
||||||
signature: SignatureBytes,
|
signature: SignatureBytes,
|
||||||
|
@ -294,7 +158,7 @@ struct VoluntaryExit {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize, Debug, Default, SimpleSerialize, Clone)]
|
#[derive(serde::Deserialize, Debug, Default, SimpleSerialize, Clone)]
|
||||||
pub struct Deposit {
|
struct Deposit {
|
||||||
#[serde(deserialize_with = "bytes_vector_deserialize")]
|
#[serde(deserialize_with = "bytes_vector_deserialize")]
|
||||||
proof: Vector<Bytes32, 33>,
|
proof: Vector<Bytes32, 33>,
|
||||||
data: DepositData,
|
data: DepositData,
|
||||||
|
|
|
@ -38,5 +38,5 @@ async fn test_get_payload() {
|
||||||
client.sync().await.unwrap();
|
client.sync().await.unwrap();
|
||||||
|
|
||||||
let payload = client.get_execution_payload(&None).await.unwrap();
|
let payload = client.get_execution_payload(&None).await.unwrap();
|
||||||
assert_eq!(*payload.block_number(), 7530932);
|
assert_eq!(payload.block_number, 7530932);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "execution"
|
name = "execution"
|
||||||
version = "0.3.0"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -10,8 +10,8 @@ serde = { version = "1.0.143", features = ["derive"] }
|
||||||
serde_json = "1.0.85"
|
serde_json = "1.0.85"
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs", rev = "d09f55b4f8554491e3431e01af1c32347a8781cd" }
|
ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs", rev = "d09f55b4f8554491e3431e01af1c32347a8781cd" }
|
||||||
|
ethers = { version = "1.0.2", features = [ "ws", "default" ] }
|
||||||
revm = { version = "2.3", default-features = false, features = ["std", "k256", "with-serde"] }
|
revm = { version = "2.3", default-features = false, features = ["std", "k256", "with-serde"] }
|
||||||
ethers = "1.0.0"
|
|
||||||
bytes = "1.2.1"
|
bytes = "1.2.1"
|
||||||
futures = "0.3.23"
|
futures = "0.3.23"
|
||||||
toml = "0.5.9"
|
toml = "0.5.9"
|
||||||
|
|
|
@ -111,7 +111,7 @@ impl<'a, R: ExecutionRpc> Evm<'a, R> {
|
||||||
let rpc = db.execution.rpc.clone();
|
let rpc = db.execution.rpc.clone();
|
||||||
let payload = db.current_payload.clone();
|
let payload = db.current_payload.clone();
|
||||||
let execution = db.execution.clone();
|
let execution = db.execution.clone();
|
||||||
let block = *db.current_payload.block_number();
|
let block = db.current_payload.block_number;
|
||||||
|
|
||||||
let opts_moved = CallOpts {
|
let opts_moved = CallOpts {
|
||||||
from: opts.from,
|
from: opts.from,
|
||||||
|
@ -139,7 +139,7 @@ impl<'a, R: ExecutionRpc> Evm<'a, R> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let producer_account = AccessListItem {
|
let producer_account = AccessListItem {
|
||||||
address: Address::from_slice(payload.fee_recipient()),
|
address: Address::from_slice(&payload.fee_recipient),
|
||||||
storage_keys: Vec::default(),
|
storage_keys: Vec::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -182,10 +182,10 @@ impl<'a, R: ExecutionRpc> Evm<'a, R> {
|
||||||
env.tx.gas_limit = opts.gas.map(|v| v.as_u64()).unwrap_or(u64::MAX);
|
env.tx.gas_limit = opts.gas.map(|v| v.as_u64()).unwrap_or(u64::MAX);
|
||||||
env.tx.gas_price = opts.gas_price.unwrap_or(U256::zero());
|
env.tx.gas_price = opts.gas_price.unwrap_or(U256::zero());
|
||||||
|
|
||||||
env.block.number = U256::from(*payload.block_number());
|
env.block.number = U256::from(payload.block_number);
|
||||||
env.block.coinbase = Address::from_slice(payload.fee_recipient());
|
env.block.coinbase = Address::from_slice(&payload.fee_recipient);
|
||||||
env.block.timestamp = U256::from(*payload.timestamp());
|
env.block.timestamp = U256::from(payload.timestamp);
|
||||||
env.block.difficulty = U256::from_little_endian(payload.prev_randao());
|
env.block.difficulty = U256::from_little_endian(&payload.prev_randao);
|
||||||
|
|
||||||
env.cfg.chain_id = self.chain_id.into();
|
env.cfg.chain_id = self.chain_id.into();
|
||||||
|
|
||||||
|
@ -266,7 +266,7 @@ impl<'a, R: ExecutionRpc> Database for ProofDB<'a, R> {
|
||||||
.payloads
|
.payloads
|
||||||
.get(&number)
|
.get(&number)
|
||||||
.ok_or(BlockNotFoundError::new(BlockTag::Number(number)))?;
|
.ok_or(BlockNotFoundError::new(BlockTag::Number(number)))?;
|
||||||
Ok(H256::from_slice(payload.block_hash()))
|
Ok(H256::from_slice(&payload.block_hash))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn storage(&mut self, address: H160, slot: U256) -> Result<U256, Report> {
|
fn storage(&mut self, address: H160, slot: U256) -> Result<U256, Report> {
|
||||||
|
@ -304,7 +304,6 @@ fn is_precompile(address: &Address) -> bool {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use common::utils::hex_str_to_bytes;
|
use common::utils::hex_str_to_bytes;
|
||||||
use consensus::types::ExecutionPayloadBellatrix;
|
|
||||||
use ssz_rs::Vector;
|
use ssz_rs::Vector;
|
||||||
|
|
||||||
use crate::rpc::mock_rpc::MockRpc;
|
use crate::rpc::mock_rpc::MockRpc;
|
||||||
|
@ -320,16 +319,15 @@ mod tests {
|
||||||
// Construct proofdb params
|
// Construct proofdb params
|
||||||
let execution = get_client();
|
let execution = get_client();
|
||||||
let address = Address::from_str("14f9D4aF749609c1438528C0Cce1cC3f6D411c47").unwrap();
|
let address = Address::from_str("14f9D4aF749609c1438528C0Cce1cC3f6D411c47").unwrap();
|
||||||
let payload = ExecutionPayload::Bellatrix(ExecutionPayloadBellatrix {
|
let payload = ExecutionPayload {
|
||||||
state_root: Vector::from_iter(
|
state_root: Vector::from_iter(
|
||||||
hex_str_to_bytes(
|
hex_str_to_bytes(
|
||||||
"0xaa02f5db2ee75e3da400d10f3c30e894b6016ce8a2501680380a907b6674ce0d",
|
"0xaa02f5db2ee75e3da400d10f3c30e894b6016ce8a2501680380a907b6674ce0d",
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
),
|
),
|
||||||
..ExecutionPayloadBellatrix::default()
|
..ExecutionPayload::default()
|
||||||
});
|
};
|
||||||
|
|
||||||
let mut payloads = BTreeMap::new();
|
let mut payloads = BTreeMap::new();
|
||||||
payloads.insert(7530933, payload.clone());
|
payloads.insert(7530933, payload.clone());
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ use revm::KECCAK_EMPTY;
|
||||||
use triehash_ethereum::ordered_trie_root;
|
use triehash_ethereum::ordered_trie_root;
|
||||||
|
|
||||||
use crate::errors::ExecutionError;
|
use crate::errors::ExecutionError;
|
||||||
|
use crate::rpc::WsRpc;
|
||||||
use crate::types::Transactions;
|
use crate::types::Transactions;
|
||||||
|
|
||||||
use super::proof::{encode_account, verify_proof};
|
use super::proof::{encode_account, verify_proof};
|
||||||
|
@ -30,6 +31,13 @@ pub struct ExecutionClient<R: ExecutionRpc> {
|
||||||
pub rpc: R,
|
pub rpc: R,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ExecutionClient<WsRpc> {
|
||||||
|
pub fn new_with_ws(rpc: &str) -> Result<Self> {
|
||||||
|
let rpc = WsRpc::new(rpc)?;
|
||||||
|
Ok(Self { rpc })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<R: ExecutionRpc> ExecutionClient<R> {
|
impl<R: ExecutionRpc> ExecutionClient<R> {
|
||||||
pub fn new(rpc: &str) -> Result<Self> {
|
pub fn new(rpc: &str) -> Result<Self> {
|
||||||
let rpc: R = ExecutionRpc::new(rpc)?;
|
let rpc: R = ExecutionRpc::new(rpc)?;
|
||||||
|
@ -54,7 +62,7 @@ impl<R: ExecutionRpc> ExecutionClient<R> {
|
||||||
|
|
||||||
let proof = self
|
let proof = self
|
||||||
.rpc
|
.rpc
|
||||||
.get_proof(address, slots, *payload.block_number())
|
.get_proof(address, slots, payload.block_number)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let account_path = keccak256(address.as_bytes()).to_vec();
|
let account_path = keccak256(address.as_bytes()).to_vec();
|
||||||
|
@ -62,7 +70,7 @@ impl<R: ExecutionRpc> ExecutionClient<R> {
|
||||||
|
|
||||||
let is_valid = verify_proof(
|
let is_valid = verify_proof(
|
||||||
&proof.account_proof,
|
&proof.account_proof,
|
||||||
payload.state_root(),
|
&payload.state_root,
|
||||||
&account_path,
|
&account_path,
|
||||||
&account_encoded,
|
&account_encoded,
|
||||||
);
|
);
|
||||||
|
@ -98,7 +106,7 @@ impl<R: ExecutionRpc> ExecutionClient<R> {
|
||||||
let code = if proof.code_hash == KECCAK_EMPTY {
|
let code = if proof.code_hash == KECCAK_EMPTY {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
} else {
|
} else {
|
||||||
let code = self.rpc.get_code(address, *payload.block_number()).await?;
|
let code = self.rpc.get_code(address, payload.block_number).await?;
|
||||||
let code_hash = keccak256(&code).into();
|
let code_hash = keccak256(&code).into();
|
||||||
|
|
||||||
if proof.code_hash != code_hash {
|
if proof.code_hash != code_hash {
|
||||||
|
@ -136,7 +144,7 @@ impl<R: ExecutionRpc> ExecutionClient<R> {
|
||||||
let empty_uncle_hash = "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347";
|
let empty_uncle_hash = "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347";
|
||||||
|
|
||||||
let tx_hashes = payload
|
let tx_hashes = payload
|
||||||
.transactions()
|
.transactions
|
||||||
.iter()
|
.iter()
|
||||||
.map(|tx| H256::from_slice(&keccak256(tx)))
|
.map(|tx| H256::from_slice(&keccak256(tx)))
|
||||||
.collect::<Vec<H256>>();
|
.collect::<Vec<H256>>();
|
||||||
|
@ -144,7 +152,7 @@ impl<R: ExecutionRpc> ExecutionClient<R> {
|
||||||
let txs = if full_tx {
|
let txs = if full_tx {
|
||||||
let txs_fut = tx_hashes.iter().map(|hash| async move {
|
let txs_fut = tx_hashes.iter().map(|hash| async move {
|
||||||
let mut payloads = BTreeMap::new();
|
let mut payloads = BTreeMap::new();
|
||||||
payloads.insert(*payload.block_number(), payload.clone());
|
payloads.insert(payload.block_number, payload.clone());
|
||||||
let tx = self
|
let tx = self
|
||||||
.get_transaction(hash, &payloads)
|
.get_transaction(hash, &payloads)
|
||||||
.await?
|
.await?
|
||||||
|
@ -163,22 +171,22 @@ impl<R: ExecutionRpc> ExecutionClient<R> {
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(ExecutionBlock {
|
Ok(ExecutionBlock {
|
||||||
number: *payload.block_number(),
|
number: payload.block_number,
|
||||||
base_fee_per_gas: U256::from_little_endian(&payload.base_fee_per_gas().to_bytes_le()),
|
base_fee_per_gas: U256::from_little_endian(&payload.base_fee_per_gas.to_bytes_le()),
|
||||||
difficulty: U256::from(0),
|
difficulty: U256::from(0),
|
||||||
extra_data: payload.extra_data().to_vec(),
|
extra_data: payload.extra_data.to_vec(),
|
||||||
gas_limit: *payload.gas_limit(),
|
gas_limit: payload.gas_limit,
|
||||||
gas_used: *payload.gas_used(),
|
gas_used: payload.gas_used,
|
||||||
hash: H256::from_slice(payload.block_hash()),
|
hash: H256::from_slice(&payload.block_hash),
|
||||||
logs_bloom: payload.logs_bloom().to_vec(),
|
logs_bloom: payload.logs_bloom.to_vec(),
|
||||||
miner: Address::from_slice(payload.fee_recipient()),
|
miner: Address::from_slice(&payload.fee_recipient),
|
||||||
parent_hash: H256::from_slice(payload.parent_hash()),
|
parent_hash: H256::from_slice(&payload.parent_hash),
|
||||||
receipts_root: H256::from_slice(payload.receipts_root()),
|
receipts_root: H256::from_slice(&payload.receipts_root),
|
||||||
state_root: H256::from_slice(payload.state_root()),
|
state_root: H256::from_slice(&payload.state_root),
|
||||||
timestamp: *payload.timestamp(),
|
timestamp: payload.timestamp,
|
||||||
total_difficulty: 0,
|
total_difficulty: 0,
|
||||||
transactions: txs,
|
transactions: txs,
|
||||||
mix_hash: H256::from_slice(payload.prev_randao()),
|
mix_hash: H256::from_slice(&payload.prev_randao),
|
||||||
nonce: empty_nonce,
|
nonce: empty_nonce,
|
||||||
sha3_uncles: H256::from_str(empty_uncle_hash)?,
|
sha3_uncles: H256::from_str(empty_uncle_hash)?,
|
||||||
size: 0,
|
size: 0,
|
||||||
|
@ -192,10 +200,10 @@ impl<R: ExecutionRpc> ExecutionClient<R> {
|
||||||
payload: &ExecutionPayload,
|
payload: &ExecutionPayload,
|
||||||
index: usize,
|
index: usize,
|
||||||
) -> Result<Option<Transaction>> {
|
) -> Result<Option<Transaction>> {
|
||||||
let tx = payload.transactions()[index].clone();
|
let tx = payload.transactions[index].clone();
|
||||||
let tx_hash = H256::from_slice(&keccak256(tx));
|
let tx_hash = H256::from_slice(&keccak256(tx));
|
||||||
let mut payloads = BTreeMap::new();
|
let mut payloads = BTreeMap::new();
|
||||||
payloads.insert(*payload.block_number(), payload.clone());
|
payloads.insert(payload.block_number, payload.clone());
|
||||||
let tx_option = self.get_transaction(&tx_hash, &payloads).await?;
|
let tx_option = self.get_transaction(&tx_hash, &payloads).await?;
|
||||||
let tx = tx_option.ok_or(eyre::eyre!("not reachable"))?;
|
let tx = tx_option.ok_or(eyre::eyre!("not reachable"))?;
|
||||||
|
|
||||||
|
@ -222,7 +230,7 @@ impl<R: ExecutionRpc> ExecutionClient<R> {
|
||||||
let payload = payload.unwrap();
|
let payload = payload.unwrap();
|
||||||
|
|
||||||
let tx_hashes = payload
|
let tx_hashes = payload
|
||||||
.transactions()
|
.transactions
|
||||||
.iter()
|
.iter()
|
||||||
.map(|tx| H256::from_slice(&keccak256(tx)))
|
.map(|tx| H256::from_slice(&keccak256(tx)))
|
||||||
.collect::<Vec<H256>>();
|
.collect::<Vec<H256>>();
|
||||||
|
@ -239,7 +247,7 @@ impl<R: ExecutionRpc> ExecutionClient<R> {
|
||||||
|
|
||||||
let expected_receipt_root = ordered_trie_root(receipts_encoded);
|
let expected_receipt_root = ordered_trie_root(receipts_encoded);
|
||||||
let expected_receipt_root = H256::from_slice(&expected_receipt_root.to_fixed_bytes());
|
let expected_receipt_root = H256::from_slice(&expected_receipt_root.to_fixed_bytes());
|
||||||
let payload_receipt_root = H256::from_slice(payload.receipts_root());
|
let payload_receipt_root = H256::from_slice(&payload.receipts_root);
|
||||||
|
|
||||||
if expected_receipt_root != payload_receipt_root || !receipts.contains(&receipt) {
|
if expected_receipt_root != payload_receipt_root || !receipts.contains(&receipt) {
|
||||||
return Err(ExecutionError::ReceiptRootMismatch(tx_hash.to_string()).into());
|
return Err(ExecutionError::ReceiptRootMismatch(tx_hash.to_string()).into());
|
||||||
|
@ -275,7 +283,7 @@ impl<R: ExecutionRpc> ExecutionClient<R> {
|
||||||
|
|
||||||
let tx_encoded = tx.rlp().to_vec();
|
let tx_encoded = tx.rlp().to_vec();
|
||||||
let txs_encoded = payload
|
let txs_encoded = payload
|
||||||
.transactions()
|
.transactions
|
||||||
.iter()
|
.iter()
|
||||||
.map(|tx| tx.to_vec())
|
.map(|tx| tx.to_vec())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
@ -396,19 +404,29 @@ impl<R: ExecutionRpc> ExecutionClient<R> {
|
||||||
.get(&block_id)
|
.get(&block_id)
|
||||||
.ok_or(ExecutionError::EmptyExecutionPayload())?;
|
.ok_or(ExecutionError::EmptyExecutionPayload())?;
|
||||||
let converted_base_fee_per_gas = ethers::types::U256::from_little_endian(
|
let converted_base_fee_per_gas = ethers::types::U256::from_little_endian(
|
||||||
&execution_payload.base_fee_per_gas().to_bytes_le(),
|
&execution_payload.base_fee_per_gas.to_bytes_le(),
|
||||||
);
|
);
|
||||||
fee_history
|
fee_history
|
||||||
.base_fee_per_gas
|
.base_fee_per_gas
|
||||||
.push(converted_base_fee_per_gas);
|
.push(converted_base_fee_per_gas);
|
||||||
let gas_used_ratio_helios = ((*execution_payload.gas_used() as f64
|
let gas_used_ratio_helios = ((execution_payload.gas_used as f64
|
||||||
/ *execution_payload.gas_limit() as f64)
|
/ execution_payload.gas_limit as f64)
|
||||||
* 10.0_f64.powi(12))
|
* 10.0_f64.powi(12))
|
||||||
.round()
|
.round()
|
||||||
/ 10.0_f64.powi(12);
|
/ 10.0_f64.powi(12);
|
||||||
fee_history.gas_used_ratio.push(gas_used_ratio_helios);
|
fee_history.gas_used_ratio.push(gas_used_ratio_helios);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Maybe place behind a query option param?
|
||||||
|
// Optionally verify the computed fee history using the rpc
|
||||||
|
// verify_fee_history(
|
||||||
|
// &self.rpc,
|
||||||
|
// &fee_history,
|
||||||
|
// fee_history.base_fee_per_gas.len(),
|
||||||
|
// request_latest_block,
|
||||||
|
// reward_percentiles,
|
||||||
|
// ).await?;
|
||||||
|
|
||||||
Ok(Some(fee_history))
|
Ok(Some(fee_history))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,10 @@ impl ExecutionRpc for HttpRpc {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn connect(&mut self) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
async fn get_proof(
|
async fn get_proof(
|
||||||
&self,
|
&self,
|
||||||
address: &Address,
|
address: &Address,
|
||||||
|
|
|
@ -25,6 +25,10 @@ impl ExecutionRpc for MockRpc {
|
||||||
Ok(MockRpc { path })
|
Ok(MockRpc { path })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn connect(&mut self) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
async fn get_proof(
|
async fn get_proof(
|
||||||
&self,
|
&self,
|
||||||
_address: &Address,
|
_address: &Address,
|
||||||
|
|
|
@ -8,6 +8,9 @@ use eyre::Result;
|
||||||
use crate::types::CallOpts;
|
use crate::types::CallOpts;
|
||||||
|
|
||||||
pub mod http_rpc;
|
pub mod http_rpc;
|
||||||
|
pub use http_rpc::*;
|
||||||
|
pub mod ws_rpc;
|
||||||
|
pub use ws_rpc::*;
|
||||||
pub mod mock_rpc;
|
pub mod mock_rpc;
|
||||||
|
|
||||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||||
|
@ -17,6 +20,9 @@ pub trait ExecutionRpc: Send + Clone + Sync + 'static {
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
|
|
||||||
|
/// Connect allows the rpc to connect if asynchronous connection is required (eg websockets).
|
||||||
|
async fn connect(&mut self) -> Result<()>;
|
||||||
|
|
||||||
async fn get_proof(
|
async fn get_proof(
|
||||||
&self,
|
&self,
|
||||||
address: &Address,
|
address: &Address,
|
||||||
|
|
|
@ -0,0 +1,195 @@
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use common::errors::RpcError;
|
||||||
|
use ethers::{
|
||||||
|
prelude::*,
|
||||||
|
types::transaction::{eip2718::TypedTransaction, eip2930::AccessList},
|
||||||
|
};
|
||||||
|
use eyre::Result;
|
||||||
|
|
||||||
|
use crate::types::CallOpts;
|
||||||
|
|
||||||
|
use super::ExecutionRpc;
|
||||||
|
|
||||||
|
pub struct WsRpc {
|
||||||
|
pub url: String,
|
||||||
|
pub provider: Option<Provider<Ws>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for WsRpc {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self::new(&self.url).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl ExecutionRpc for WsRpc {
|
||||||
|
fn new(rpc: &str) -> Result<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
url: rpc.to_string(),
|
||||||
|
provider: None::<Provider<Ws>>,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn connect(&mut self) -> Result<()> {
|
||||||
|
let provider = Provider::<Ws>::connect(&self.url).await?;
|
||||||
|
self.provider = Some(provider);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_proof(
|
||||||
|
&self,
|
||||||
|
address: &Address,
|
||||||
|
slots: &[H256],
|
||||||
|
block: u64,
|
||||||
|
) -> Result<EIP1186ProofResponse> {
|
||||||
|
let block = Some(BlockId::from(block));
|
||||||
|
let proof_response = self
|
||||||
|
.provider
|
||||||
|
.as_ref()
|
||||||
|
.ok_or(RpcError::new(
|
||||||
|
"get_proof",
|
||||||
|
eyre::eyre!("Provider not connected!"),
|
||||||
|
))?
|
||||||
|
.get_proof(*address, slots.to_vec(), block)
|
||||||
|
.await
|
||||||
|
.map_err(|e| RpcError::new("get_proof", e))?;
|
||||||
|
|
||||||
|
Ok(proof_response)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_access_list(&self, opts: &CallOpts, block: u64) -> Result<AccessList> {
|
||||||
|
let block = Some(BlockId::from(block));
|
||||||
|
|
||||||
|
let mut raw_tx = Eip1559TransactionRequest::new();
|
||||||
|
raw_tx.to = opts.to.map(Into::into);
|
||||||
|
raw_tx.from = opts.from;
|
||||||
|
raw_tx.value = opts.value;
|
||||||
|
raw_tx.gas = Some(opts.gas.unwrap_or(U256::from(100_000_000)));
|
||||||
|
raw_tx.max_fee_per_gas = Some(U256::zero());
|
||||||
|
raw_tx.max_priority_fee_per_gas = Some(U256::zero());
|
||||||
|
raw_tx.data = opts
|
||||||
|
.data
|
||||||
|
.as_ref()
|
||||||
|
.map(|data| Bytes::from(data.as_slice().to_owned()));
|
||||||
|
|
||||||
|
let tx = TypedTransaction::Eip1559(raw_tx);
|
||||||
|
let list = self
|
||||||
|
.provider
|
||||||
|
.as_ref()
|
||||||
|
.ok_or(RpcError::new(
|
||||||
|
"create_access_list",
|
||||||
|
eyre::eyre!("Provider not connected!"),
|
||||||
|
))?
|
||||||
|
.create_access_list(&tx, block)
|
||||||
|
.await
|
||||||
|
.map_err(|e| RpcError::new("create_access_list", e))?;
|
||||||
|
|
||||||
|
Ok(list.access_list)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_code(&self, address: &Address, block: u64) -> Result<Vec<u8>> {
|
||||||
|
let block = Some(BlockId::from(block));
|
||||||
|
let code = self
|
||||||
|
.provider
|
||||||
|
.as_ref()
|
||||||
|
.ok_or(RpcError::new(
|
||||||
|
"get_code",
|
||||||
|
eyre::eyre!("Provider not connected!"),
|
||||||
|
))?
|
||||||
|
.get_code(*address, block)
|
||||||
|
.await
|
||||||
|
.map_err(|e| RpcError::new("get_code", e))?;
|
||||||
|
|
||||||
|
Ok(code.to_vec())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn send_raw_transaction(&self, bytes: &[u8]) -> Result<H256> {
|
||||||
|
let bytes = Bytes::from(bytes.to_owned());
|
||||||
|
let tx = self
|
||||||
|
.provider
|
||||||
|
.as_ref()
|
||||||
|
.ok_or(RpcError::new(
|
||||||
|
"send_raw_transaction",
|
||||||
|
eyre::eyre!("Provider not connected!"),
|
||||||
|
))?
|
||||||
|
.send_raw_transaction(bytes)
|
||||||
|
.await
|
||||||
|
.map_err(|e| RpcError::new("send_raw_transaction", e))?;
|
||||||
|
|
||||||
|
Ok(tx.tx_hash())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_transaction_receipt(&self, tx_hash: &H256) -> Result<Option<TransactionReceipt>> {
|
||||||
|
let receipt = self
|
||||||
|
.provider
|
||||||
|
.as_ref()
|
||||||
|
.ok_or(RpcError::new(
|
||||||
|
"get_transaction_receipt",
|
||||||
|
eyre::eyre!("Provider not connected!"),
|
||||||
|
))?
|
||||||
|
.get_transaction_receipt(*tx_hash)
|
||||||
|
.await
|
||||||
|
.map_err(|e| RpcError::new("get_transaction_receipt", e))?;
|
||||||
|
|
||||||
|
Ok(receipt)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_transaction(&self, tx_hash: &H256) -> Result<Option<Transaction>> {
|
||||||
|
Ok(self
|
||||||
|
.provider
|
||||||
|
.as_ref()
|
||||||
|
.ok_or(RpcError::new(
|
||||||
|
"get_transaction",
|
||||||
|
eyre::eyre!("Provider not connected!"),
|
||||||
|
))?
|
||||||
|
.get_transaction(*tx_hash)
|
||||||
|
.await
|
||||||
|
.map_err(|e| RpcError::new("get_transaction", e))?)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_logs(&self, filter: &Filter) -> Result<Vec<Log>> {
|
||||||
|
Ok(self
|
||||||
|
.provider
|
||||||
|
.as_ref()
|
||||||
|
.ok_or(RpcError::new(
|
||||||
|
"get_logs",
|
||||||
|
eyre::eyre!("Provider not connected!"),
|
||||||
|
))?
|
||||||
|
.get_logs(filter)
|
||||||
|
.await
|
||||||
|
.map_err(|e| RpcError::new("get_logs", e))?)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn chain_id(&self) -> Result<u64> {
|
||||||
|
Ok(self
|
||||||
|
.provider
|
||||||
|
.as_ref()
|
||||||
|
.ok_or(RpcError::new(
|
||||||
|
"get_chainid",
|
||||||
|
eyre::eyre!("Provider not connected!"),
|
||||||
|
))?
|
||||||
|
.get_chainid()
|
||||||
|
.await
|
||||||
|
.map_err(|e| RpcError::new("chain_id", e))?
|
||||||
|
.as_u64())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_fee_history(
|
||||||
|
&self,
|
||||||
|
block_count: u64,
|
||||||
|
last_block: u64,
|
||||||
|
reward_percentiles: &[f64],
|
||||||
|
) -> Result<FeeHistory> {
|
||||||
|
let block = BlockNumber::from(last_block);
|
||||||
|
Ok(self
|
||||||
|
.provider
|
||||||
|
.as_ref()
|
||||||
|
.ok_or(RpcError::new(
|
||||||
|
"fee_history",
|
||||||
|
eyre::eyre!("Provider not connected!"),
|
||||||
|
))?
|
||||||
|
.fee_history(block_count, block, reward_percentiles)
|
||||||
|
.await
|
||||||
|
.map_err(|e| RpcError::new("fee_history", e))?)
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,7 @@ use ethers::types::{Address, Filter, H256, U256};
|
||||||
use ssz_rs::{List, Vector};
|
use ssz_rs::{List, Vector};
|
||||||
|
|
||||||
use common::utils::hex_str_to_bytes;
|
use common::utils::hex_str_to_bytes;
|
||||||
use consensus::types::{ExecutionPayload, ExecutionPayloadBellatrix};
|
use consensus::types::ExecutionPayload;
|
||||||
use execution::rpc::mock_rpc::MockRpc;
|
use execution::rpc::mock_rpc::MockRpc;
|
||||||
use execution::ExecutionClient;
|
use execution::ExecutionClient;
|
||||||
|
|
||||||
|
@ -18,13 +18,13 @@ async fn test_get_account() {
|
||||||
let execution = get_client();
|
let execution = get_client();
|
||||||
let address = Address::from_str("14f9D4aF749609c1438528C0Cce1cC3f6D411c47").unwrap();
|
let address = Address::from_str("14f9D4aF749609c1438528C0Cce1cC3f6D411c47").unwrap();
|
||||||
|
|
||||||
let payload = ExecutionPayload::Bellatrix(ExecutionPayloadBellatrix {
|
let payload = ExecutionPayload {
|
||||||
state_root: Vector::from_iter(
|
state_root: Vector::from_iter(
|
||||||
hex_str_to_bytes("0xaa02f5db2ee75e3da400d10f3c30e894b6016ce8a2501680380a907b6674ce0d")
|
hex_str_to_bytes("0xaa02f5db2ee75e3da400d10f3c30e894b6016ce8a2501680380a907b6674ce0d")
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
),
|
),
|
||||||
..ExecutionPayloadBellatrix::default()
|
..ExecutionPayload::default()
|
||||||
});
|
};
|
||||||
|
|
||||||
let account = execution
|
let account = execution
|
||||||
.get_account(&address, None, &payload)
|
.get_account(&address, None, &payload)
|
||||||
|
@ -55,7 +55,7 @@ async fn test_get_tx() {
|
||||||
H256::from_str("2dac1b27ab58b493f902dda8b63979a112398d747f1761c0891777c0983e591f").unwrap();
|
H256::from_str("2dac1b27ab58b493f902dda8b63979a112398d747f1761c0891777c0983e591f").unwrap();
|
||||||
|
|
||||||
let mut payload = ExecutionPayload::default();
|
let mut payload = ExecutionPayload::default();
|
||||||
payload.transactions_mut().push(List::from_iter(hex_str_to_bytes("0x02f8b20583623355849502f900849502f91082ea6094326c977e6efc84e512bb9c30f76e30c160ed06fb80b844a9059cbb0000000000000000000000007daccf9b3c1ae2fa5c55f1c978aeef700bc83be0000000000000000000000000000000000000000000000001158e460913d00000c080a0e1445466b058b6f883c0222f1b1f3e2ad9bee7b5f688813d86e3fa8f93aa868ca0786d6e7f3aefa8fe73857c65c32e4884d8ba38d0ecfb947fbffb82e8ee80c167").unwrap()));
|
payload.transactions.push(List::from_iter(hex_str_to_bytes("0x02f8b20583623355849502f900849502f91082ea6094326c977e6efc84e512bb9c30f76e30c160ed06fb80b844a9059cbb0000000000000000000000007daccf9b3c1ae2fa5c55f1c978aeef700bc83be0000000000000000000000000000000000000000000000001158e460913d00000c080a0e1445466b058b6f883c0222f1b1f3e2ad9bee7b5f688813d86e3fa8f93aa868ca0786d6e7f3aefa8fe73857c65c32e4884d8ba38d0ecfb947fbffb82e8ee80c167").unwrap()));
|
||||||
|
|
||||||
let mut payloads = BTreeMap::new();
|
let mut payloads = BTreeMap::new();
|
||||||
payloads.insert(7530933, payload);
|
payloads.insert(7530933, payload);
|
||||||
|
@ -104,15 +104,15 @@ async fn test_get_tx_not_included() {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_get_logs() {
|
async fn test_get_logs() {
|
||||||
let execution = get_client();
|
let execution = get_client();
|
||||||
let mut payload = ExecutionPayload::Bellatrix(ExecutionPayloadBellatrix {
|
let mut payload = ExecutionPayload {
|
||||||
receipts_root: Vector::from_iter(
|
receipts_root: Vector::from_iter(
|
||||||
hex_str_to_bytes("dd82a78eccb333854f0c99e5632906e092d8a49c27a21c25cae12b82ec2a113f")
|
hex_str_to_bytes("dd82a78eccb333854f0c99e5632906e092d8a49c27a21c25cae12b82ec2a113f")
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
),
|
),
|
||||||
..ExecutionPayloadBellatrix::default()
|
..ExecutionPayload::default()
|
||||||
});
|
};
|
||||||
|
|
||||||
payload.transactions_mut().push(List::from_iter(hex_str_to_bytes("0x02f8b20583623355849502f900849502f91082ea6094326c977e6efc84e512bb9c30f76e30c160ed06fb80b844a9059cbb0000000000000000000000007daccf9b3c1ae2fa5c55f1c978aeef700bc83be0000000000000000000000000000000000000000000000001158e460913d00000c080a0e1445466b058b6f883c0222f1b1f3e2ad9bee7b5f688813d86e3fa8f93aa868ca0786d6e7f3aefa8fe73857c65c32e4884d8ba38d0ecfb947fbffb82e8ee80c167").unwrap()));
|
payload.transactions.push(List::from_iter(hex_str_to_bytes("0x02f8b20583623355849502f900849502f91082ea6094326c977e6efc84e512bb9c30f76e30c160ed06fb80b844a9059cbb0000000000000000000000007daccf9b3c1ae2fa5c55f1c978aeef700bc83be0000000000000000000000000000000000000000000000001158e460913d00000c080a0e1445466b058b6f883c0222f1b1f3e2ad9bee7b5f688813d86e3fa8f93aa868ca0786d6e7f3aefa8fe73857c65c32e4884d8ba38d0ecfb947fbffb82e8ee80c167").unwrap()));
|
||||||
|
|
||||||
let mut payloads = BTreeMap::new();
|
let mut payloads = BTreeMap::new();
|
||||||
payloads.insert(7530933, payload);
|
payloads.insert(7530933, payload);
|
||||||
|
@ -134,15 +134,15 @@ async fn test_get_receipt() {
|
||||||
let tx_hash =
|
let tx_hash =
|
||||||
H256::from_str("2dac1b27ab58b493f902dda8b63979a112398d747f1761c0891777c0983e591f").unwrap();
|
H256::from_str("2dac1b27ab58b493f902dda8b63979a112398d747f1761c0891777c0983e591f").unwrap();
|
||||||
|
|
||||||
let mut payload = ExecutionPayload::Bellatrix(ExecutionPayloadBellatrix {
|
let mut payload = ExecutionPayload {
|
||||||
receipts_root: Vector::from_iter(
|
receipts_root: Vector::from_iter(
|
||||||
hex_str_to_bytes("dd82a78eccb333854f0c99e5632906e092d8a49c27a21c25cae12b82ec2a113f")
|
hex_str_to_bytes("dd82a78eccb333854f0c99e5632906e092d8a49c27a21c25cae12b82ec2a113f")
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
),
|
),
|
||||||
..ExecutionPayloadBellatrix::default()
|
..ExecutionPayload::default()
|
||||||
});
|
};
|
||||||
|
|
||||||
payload.transactions_mut().push(List::from_iter(hex_str_to_bytes("0x02f8b20583623355849502f900849502f91082ea6094326c977e6efc84e512bb9c30f76e30c160ed06fb80b844a9059cbb0000000000000000000000007daccf9b3c1ae2fa5c55f1c978aeef700bc83be0000000000000000000000000000000000000000000000001158e460913d00000c080a0e1445466b058b6f883c0222f1b1f3e2ad9bee7b5f688813d86e3fa8f93aa868ca0786d6e7f3aefa8fe73857c65c32e4884d8ba38d0ecfb947fbffb82e8ee80c167").unwrap()));
|
payload.transactions.push(List::from_iter(hex_str_to_bytes("0x02f8b20583623355849502f900849502f91082ea6094326c977e6efc84e512bb9c30f76e30c160ed06fb80b844a9059cbb0000000000000000000000007daccf9b3c1ae2fa5c55f1c978aeef700bc83be0000000000000000000000000000000000000000000000001158e460913d00000c080a0e1445466b058b6f883c0222f1b1f3e2ad9bee7b5f688813d86e3fa8f93aa868ca0786d6e7f3aefa8fe73857c65c32e4884d8ba38d0ecfb947fbffb82e8ee80c167").unwrap()));
|
||||||
|
|
||||||
let mut payloads = BTreeMap::new();
|
let mut payloads = BTreeMap::new();
|
||||||
payloads.insert(7530933, payload);
|
payloads.insert(7530933, payload);
|
||||||
|
@ -163,7 +163,7 @@ async fn test_get_receipt_bad_proof() {
|
||||||
H256::from_str("2dac1b27ab58b493f902dda8b63979a112398d747f1761c0891777c0983e591f").unwrap();
|
H256::from_str("2dac1b27ab58b493f902dda8b63979a112398d747f1761c0891777c0983e591f").unwrap();
|
||||||
|
|
||||||
let mut payload = ExecutionPayload::default();
|
let mut payload = ExecutionPayload::default();
|
||||||
payload.transactions_mut().push(List::from_iter(hex_str_to_bytes("0x02f8b20583623355849502f900849502f91082ea6094326c977e6efc84e512bb9c30f76e30c160ed06fb80b844a9059cbb0000000000000000000000007daccf9b3c1ae2fa5c55f1c978aeef700bc83be0000000000000000000000000000000000000000000000001158e460913d00000c080a0e1445466b058b6f883c0222f1b1f3e2ad9bee7b5f688813d86e3fa8f93aa868ca0786d6e7f3aefa8fe73857c65c32e4884d8ba38d0ecfb947fbffb82e8ee80c167").unwrap()));
|
payload.transactions.push(List::from_iter(hex_str_to_bytes("0x02f8b20583623355849502f900849502f91082ea6094326c977e6efc84e512bb9c30f76e30c160ed06fb80b844a9059cbb0000000000000000000000007daccf9b3c1ae2fa5c55f1c978aeef700bc83be0000000000000000000000000000000000000000000000001158e460913d00000c080a0e1445466b058b6f883c0222f1b1f3e2ad9bee7b5f688813d86e3fa8f93aa868ca0786d6e7f3aefa8fe73857c65c32e4884d8ba38d0ecfb947fbffb82e8ee80c167").unwrap()));
|
||||||
|
|
||||||
let mut payloads = BTreeMap::new();
|
let mut payloads = BTreeMap::new();
|
||||||
payloads.insert(7530933, payload);
|
payloads.insert(7530933, payload);
|
||||||
|
@ -191,10 +191,10 @@ async fn test_get_receipt_not_included() {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_get_block() {
|
async fn test_get_block() {
|
||||||
let execution = get_client();
|
let execution = get_client();
|
||||||
let payload = ExecutionPayload::Bellatrix(ExecutionPayloadBellatrix {
|
let payload = ExecutionPayload {
|
||||||
block_number: 12345,
|
block_number: 12345,
|
||||||
..ExecutionPayloadBellatrix::default()
|
..ExecutionPayload::default()
|
||||||
});
|
};
|
||||||
|
|
||||||
let block = execution.get_block(&payload, false).await.unwrap();
|
let block = execution.get_block(&payload, false).await.unwrap();
|
||||||
|
|
||||||
|
@ -207,11 +207,11 @@ async fn test_get_tx_by_block_hash_and_index() {
|
||||||
let tx_hash =
|
let tx_hash =
|
||||||
H256::from_str("2dac1b27ab58b493f902dda8b63979a112398d747f1761c0891777c0983e591f").unwrap();
|
H256::from_str("2dac1b27ab58b493f902dda8b63979a112398d747f1761c0891777c0983e591f").unwrap();
|
||||||
|
|
||||||
let mut payload = ExecutionPayload::Bellatrix(ExecutionPayloadBellatrix {
|
let mut payload = ExecutionPayload {
|
||||||
block_number: 7530933,
|
block_number: 7530933,
|
||||||
..ExecutionPayloadBellatrix::default()
|
..ExecutionPayload::default()
|
||||||
});
|
};
|
||||||
payload.transactions_mut().push(List::from_iter(hex_str_to_bytes("0x02f8b20583623355849502f900849502f91082ea6094326c977e6efc84e512bb9c30f76e30c160ed06fb80b844a9059cbb0000000000000000000000007daccf9b3c1ae2fa5c55f1c978aeef700bc83be0000000000000000000000000000000000000000000000001158e460913d00000c080a0e1445466b058b6f883c0222f1b1f3e2ad9bee7b5f688813d86e3fa8f93aa868ca0786d6e7f3aefa8fe73857c65c32e4884d8ba38d0ecfb947fbffb82e8ee80c167").unwrap()));
|
payload.transactions.push(List::from_iter(hex_str_to_bytes("0x02f8b20583623355849502f900849502f91082ea6094326c977e6efc84e512bb9c30f76e30c160ed06fb80b844a9059cbb0000000000000000000000007daccf9b3c1ae2fa5c55f1c978aeef700bc83be0000000000000000000000000000000000000000000000001158e460913d00000c080a0e1445466b058b6f883c0222f1b1f3e2ad9bee7b5f688813d86e3fa8f93aa868ca0786d6e7f3aefa8fe73857c65c32e4884d8ba38d0ecfb947fbffb82e8ee80c167").unwrap()));
|
||||||
|
|
||||||
let tx = execution
|
let tx = execution
|
||||||
.get_transaction_by_block_hash_and_index(&payload, 0)
|
.get_transaction_by_block_hash_and_index(&payload, 0)
|
||||||
|
|
|
@ -3,8 +3,6 @@ name = "helios-ts"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["cdylib"]
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue