diff --git a/Cargo.lock b/Cargo.lock
index 0f91f52627..fe4ac3f292 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -102,6 +102,16 @@ version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
+[[package]]
+name = "aead"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
+dependencies = [
+ "crypto-common",
+ "generic-array 0.14.7",
+]
+
[[package]]
name = "aes"
version = "0.8.4"
@@ -113,6 +123,20 @@ dependencies = [
"cpufeatures",
]
+[[package]]
+name = "aes-gcm"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1"
+dependencies = [
+ "aead",
+ "aes",
+ "cipher",
+ "ctr",
+ "ghash",
+ "subtle",
+]
+
[[package]]
name = "ahash"
version = "0.8.12"
@@ -2325,6 +2349,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
dependencies = [
"generic-array 0.14.7",
+ "rand_core 0.6.4",
"typenum",
]
@@ -3882,6 +3907,7 @@ name = "ethrex-p2p"
version = "8.0.0"
dependencies = [
"aes",
+ "aes-gcm",
"async-trait",
"bytes",
"concat-kdf",
@@ -3900,6 +3926,7 @@ dependencies = [
"futures",
"hex",
"hex-literal 0.4.1",
+ "hkdf",
"hmac",
"indexmap 2.12.1",
"lazy_static",
@@ -4645,6 +4672,16 @@ dependencies = [
"syn 2.0.111",
]
+[[package]]
+name = "ghash"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1"
+dependencies = [
+ "opaque-debug",
+ "polyval",
+]
+
[[package]]
name = "gimli"
version = "0.31.1"
@@ -5176,6 +5213,15 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e712f64ec3850b98572bffac52e2c6f282b29fe6c5fa6d42334b30be438d95c1"
+[[package]]
+name = "hkdf"
+version = "0.12.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
+dependencies = [
+ "hmac",
+]
+
[[package]]
name = "hmac"
version = "0.12.1"
@@ -7266,6 +7312,12 @@ version = "11.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e"
+[[package]]
+name = "opaque-debug"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
+
[[package]]
name = "open-fastrlp"
version = "0.1.4"
@@ -9502,6 +9554,18 @@ dependencies = [
"plotters-backend",
]
+[[package]]
+name = "polyval"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25"
+dependencies = [
+ "cfg-if 1.0.4",
+ "cpufeatures",
+ "opaque-debug",
+ "universal-hash",
+]
+
[[package]]
name = "portable-atomic"
version = "1.11.1"
@@ -13767,6 +13831,16 @@ version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
+[[package]]
+name = "universal-hash"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
+dependencies = [
+ "crypto-common",
+ "subtle",
+]
+
[[package]]
name = "unroll"
version = "0.1.5"
diff --git a/cmd/ethrex/Cargo.toml b/cmd/ethrex/Cargo.toml
index be18f8ffd2..02aac989b7 100644
--- a/cmd/ethrex/Cargo.toml
+++ b/cmd/ethrex/Cargo.toml
@@ -102,6 +102,8 @@ jemalloc_profiling = [
"ethrex-rpc/jemalloc_profiling",
]
sync-test = ["ethrex-p2p/sync-test"]
+# discv5 is currently experimental and should only be enabled for development purposes
+experimental-discv5 = ["ethrex-p2p/experimental-discv5"]
l2 = [
"ethrex-l2",
diff --git a/cmd/ethrex/ethrex.rs b/cmd/ethrex/ethrex.rs
index 348c0b279d..106ae70ebc 100644
--- a/cmd/ethrex/ethrex.rs
+++ b/cmd/ethrex/ethrex.rs
@@ -140,6 +140,9 @@ async fn main() -> eyre::Result<()> {
info!("ethrex version: {}", get_client_version());
tokio::spawn(periodically_check_version_update());
+ #[cfg(feature = "experimental-discv5")]
+ tracing::warn!("Experimental Discovery V5 protocol enabled");
+
let (datadir, cancel_token, peer_table, local_node_record) =
init_l1(opts, Some(log_filter_handler)).await?;
diff --git a/crates/common/types/transaction.rs b/crates/common/types/transaction.rs
index 6e38ed04a3..49aa761d73 100644
--- a/crates/common/types/transaction.rs
+++ b/crates/common/types/transaction.rs
@@ -3,7 +3,6 @@ use std::{cmp::min, fmt::Display};
use crate::{errors::EcdsaError, utils::keccak};
use bytes::Bytes;
use ethereum_types::{Address, H256, Signature, U256};
-use ethrex_crypto::keccak::keccak_hash;
pub use mempool::MempoolTransaction;
use rkyv::{Archive, Deserialize as RDeserialize, Serialize as RSerialize};
use serde::{Serialize, ser::SerializeStruct};
@@ -1431,7 +1430,7 @@ pub fn recover_address(signature: Signature, payload: H256) -> Result
,
+}
+
+impl Discv5Codec {
+ pub fn new(dest_id: H256) -> Self {
+ Self {
+ dest_id,
+ counter: 0,
+ session: None,
+ }
+ }
+
+ pub fn with_session(dest_id: H256, session: Session) -> Self {
+ Self {
+ dest_id,
+ counter: 0,
+ session: Some(session),
+ }
+ }
+
+ pub fn set_session(&mut self, session: Session) {
+ self.session = Some(session);
+ }
+
+ /// Generates a 96-bit AES-GCM nonce
+ /// ## Spec Recommendation
+ /// Encode the current outgoing message count into the first 32 bits of the nonce and fill the remaining 64 bits with random data generated
+ /// by a cryptographically secure random number generator.
+ pub fn next_nonce(&mut self, rng: &mut R) -> [u8; 12] {
+ let counter = self.counter;
+ self.counter = self.counter.wrapping_add(1);
+
+ let mut nonce = [0u8; 12];
+ nonce[..4].copy_from_slice(&counter.to_be_bytes());
+ rng.fill_bytes(&mut nonce[4..]);
+ nonce
+ }
+}
+
+impl Decoder for Discv5Codec {
+ type Item = Packet;
+ type Error = PacketCodecError;
+
+ fn decode(&mut self, buf: &mut BytesMut) -> Result