From dda61e8907fcd0c8c802a11e118e4187cd5ae34d Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Tue, 9 Apr 2024 16:21:31 +0200 Subject: [PATCH 1/2] chore(deps): bump enr, discv5, secp256k1 --- Cargo.lock | 74 +++---- Cargo.toml | 16 +- .../interfaces/src/test_utils/generators.rs | 14 +- crates/net/discv4/Cargo.toml | 3 +- crates/net/discv4/src/lib.rs | 4 +- crates/net/discv4/src/proto.rs | 183 ++++-------------- crates/net/discv5/Cargo.toml | 3 +- crates/net/discv5/src/enr.rs | 15 +- crates/net/discv5/src/lib.rs | 3 +- crates/net/dns/Cargo.toml | 2 +- crates/net/dns/src/lib.rs | 6 +- crates/net/dns/src/tree.rs | 2 +- crates/net/ecies/src/algorithm.rs | 6 +- crates/net/network/Cargo.toml | 6 +- crates/primitives/Cargo.toml | 8 +- crates/primitives/src/genesis.rs | 24 +-- crates/primitives/src/transaction/mod.rs | 4 +- crates/primitives/src/transaction/util.rs | 4 +- 18 files changed, 114 insertions(+), 263 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6b2e0d01727b..8b7ceb72c6d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2403,11 +2403,13 @@ dependencies = [ [[package]] name = "discv5" -version = "0.4.1" -source = "git+https://github.com/sigp/discv5?rev=04ac004#04ac0042a345a9edf93b090007e5d31c008261ed" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cafb8ed8d460b7d1c8d4c970270d45ecb5e283179a3945143196624c55cda6ac" dependencies = [ "aes 0.7.5", "aes-gcm", + "alloy-rlp", "arrayvec", "delay_map", "enr", @@ -2422,7 +2424,6 @@ dependencies = [ "more-asserts", "parking_lot 0.11.2", "rand 0.8.5", - "rlp", "smallvec", "socket2 0.4.10", "tokio", @@ -2597,10 +2598,11 @@ checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" [[package]] name = "enr" -version = "0.10.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a3d8dc56e02f954cac8eb489772c552c473346fc34f67412bb6244fd647f7e4" +checksum = "4ab656b89cdd15051d92d0931888103508de14ef9e51177c86d478dfa551ce0f" dependencies = [ + "alloy-rlp", "base64 0.21.7", "bytes", "ed25519-dalek", @@ -2608,8 +2610,7 @@ dependencies = [ "k256", "log", "rand 0.8.5", - "rlp", - "secp256k1 0.27.0", + "secp256k1", "serde", "sha3", "zeroize", @@ -4581,7 +4582,7 @@ dependencies = [ "reth-eth-wire", "reth-network", "reth-primitives", - "secp256k1 0.27.0", + "secp256k1", "tokio", ] @@ -5433,7 +5434,7 @@ dependencies = [ "reth-primitives", "reth-provider", "reth-tracing", - "secp256k1 0.27.0", + "secp256k1", "serde_json", "tokio", "tokio-stream", @@ -6276,7 +6277,7 @@ dependencies = [ "reth-net-nat", "reth-network", "reth-primitives", - "secp256k1 0.27.0", + "secp256k1", "serde", "tempfile", "toml", @@ -6353,8 +6354,7 @@ dependencies = [ "reth-net-nat", "reth-primitives", "reth-tracing", - "rlp", - "secp256k1 0.27.0", + "secp256k1", "serde", "thiserror", "tokio", @@ -6379,8 +6379,7 @@ dependencies = [ "reth-metrics", "reth-primitives", "reth-tracing", - "rlp", - "secp256k1 0.27.0", + "secp256k1", "thiserror", "tokio", "tracing", @@ -6399,7 +6398,7 @@ dependencies = [ "reth-primitives", "reth-tracing", "schnellru", - "secp256k1 0.27.0", + "secp256k1", "serde", "serde_with", "thiserror", @@ -6462,7 +6461,7 @@ dependencies = [ "reth-provider", "reth-rpc", "reth-tracing", - "secp256k1 0.27.0", + "secp256k1", "serde_json", "tokio", "tokio-stream", @@ -6489,7 +6488,7 @@ dependencies = [ "rand 0.8.5", "reth-net-common", "reth-primitives", - "secp256k1 0.27.0", + "secp256k1", "sha2 0.10.8", "sha3", "thiserror", @@ -6533,7 +6532,7 @@ dependencies = [ "reth-net-common", "reth-primitives", "reth-tracing", - "secp256k1 0.27.0", + "secp256k1", "serde", "snap", "test-fuzz", @@ -6560,7 +6559,7 @@ dependencies = [ "reth-net-common", "reth-primitives", "reth-tracing", - "secp256k1 0.27.0", + "secp256k1", "serde", "test-fuzz", "thiserror", @@ -6688,7 +6687,7 @@ dependencies = [ "reth-eth-wire-types", "reth-network-api", "reth-primitives", - "secp256k1 0.27.0", + "secp256k1", "thiserror", "tokio", "tracing", @@ -6837,7 +6836,7 @@ dependencies = [ "reth-tracing", "reth-transaction-pool", "schnellru", - "secp256k1 0.27.0", + "secp256k1", "serde", "serde_json", "serial_test", @@ -6983,7 +6982,7 @@ dependencies = [ "reth-tasks", "reth-tracing", "reth-transaction-pool", - "secp256k1 0.27.0", + "secp256k1", "serde", "serde_json", "shellexpand", @@ -7177,7 +7176,7 @@ dependencies = [ "revm", "revm-primitives", "roaring", - "secp256k1 0.27.0", + "secp256k1", "serde", "serde_json", "serde_with", @@ -7303,7 +7302,7 @@ dependencies = [ "revm-inspectors", "revm-primitives", "schnellru", - "secp256k1 0.27.0", + "secp256k1", "serde", "serde_json", "tempfile", @@ -7426,7 +7425,7 @@ dependencies = [ "proptest", "proptest-derive", "rand 0.8.5", - "secp256k1 0.27.0", + "secp256k1", "serde", "serde_json", "serde_with", @@ -7706,7 +7705,7 @@ dependencies = [ "once_cell", "revm-primitives", "ripemd", - "secp256k1 0.28.2", + "secp256k1", "sha2 0.10.8", "substrate-bn", ] @@ -8139,17 +8138,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "secp256k1" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" -dependencies = [ - "rand 0.8.5", - "secp256k1-sys 0.8.1", - "serde", -] - [[package]] name = "secp256k1" version = "0.28.2" @@ -8157,16 +8145,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" dependencies = [ "rand 0.8.5", - "secp256k1-sys 0.9.2", -] - -[[package]] -name = "secp256k1-sys" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" -dependencies = [ - "cc", + "secp256k1-sys", + "serde", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 73597b311a46..5a5d6bff3f27 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -271,13 +271,8 @@ reth-trie-parallel = { path = "crates/trie-parallel" } reth-node-events = { path = "crates/node/events" } # revm -revm = { version = "8.0.0", features = [ - "std", - "secp256k1", -], default-features = false } -revm-primitives = { version = "3.1.0", features = [ - "std", -], default-features = false } +revm = { version = "8.0.0", features = ["std", "secp256k1"], default-features = false } +revm-primitives = { version = "3.1.0", features = ["std"], default-features = false } revm-inspectors = { git = "https://github.com/paradigmxyz/evm-inspectors", rev = "dc614ee" } # eth @@ -358,7 +353,7 @@ http = "0.2.8" http-body = "0.4.5" # p2p -discv5 = { git = "https://github.com/sigp/discv5", rev = "04ac004" } +discv5 = "0.6.0" igd-next = "0.14.3" # rpc @@ -367,11 +362,12 @@ jsonrpsee-core = "0.22" jsonrpsee-types = "0.22" # crypto -secp256k1 = { version = "0.27.0", default-features = false, features = [ +secp256k1 = { version = "0.28", default-features = false, features = [ "global-context", "recovery", ] } -enr = { version = "=0.10.0", default-features = false, features = ["k256"] } +# TODO: Remove `k256` feature: https://github.com/sigp/enr/pull/74 +enr = { version = "0.12.0", default-features = false, features = ["k256", "rust-secp256k1"] } # for eip-4844 c-kzg = "1.0.0" diff --git a/crates/interfaces/src/test_utils/generators.rs b/crates/interfaces/src/test_utils/generators.rs index 0f1930b6005f..506358276c74 100644 --- a/crates/interfaces/src/test_utils/generators.rs +++ b/crates/interfaces/src/test_utils/generators.rs @@ -6,7 +6,7 @@ use reth_primitives::{ proofs, sign_message, Account, Address, BlockNumber, Bytes, Header, Log, Receipt, SealedBlock, SealedHeader, StorageEntry, Transaction, TransactionSigned, TxKind, TxLegacy, B256, U256, }; -use secp256k1::{KeyPair, Secp256k1}; +use secp256k1::{Keypair, Secp256k1}; use std::{ cmp::{max, min}, collections::{hash_map::DefaultHasher, BTreeMap}, @@ -91,22 +91,22 @@ pub fn random_tx(rng: &mut R) -> Transaction { /// - There is no guarantee that the nonce is not used twice for the same account pub fn random_signed_tx(rng: &mut R) -> TransactionSigned { let secp = Secp256k1::new(); - let key_pair = KeyPair::new(&secp, rng); + let key_pair = Keypair::new(&secp, rng); let tx = random_tx(rng); sign_tx_with_key_pair(key_pair, tx) } /// Signs the [Transaction] with the given key pair. -pub fn sign_tx_with_key_pair(key_pair: KeyPair, tx: Transaction) -> TransactionSigned { +pub fn sign_tx_with_key_pair(key_pair: Keypair, tx: Transaction) -> TransactionSigned { let signature = sign_message(B256::from_slice(&key_pair.secret_bytes()[..]), tx.signature_hash()).unwrap(); TransactionSigned::from_transaction_and_signature(tx, signature) } -/// Generates a set of [KeyPair]s based on the desired count. -pub fn generate_keys(rng: &mut R, count: usize) -> Vec { +/// Generates a set of [Keypair]s based on the desired count. +pub fn generate_keys(rng: &mut R, count: usize) -> Vec { let secp = Secp256k1::new(); - (0..count).map(|_| KeyPair::new(&secp, rng)).collect() + (0..count).map(|_| Keypair::new(&secp, rng)).collect() } /// Generate a random block filled with signed transactions (generated using @@ -404,7 +404,7 @@ mod tests { let signature_hash = tx.signature_hash(); for _ in 0..100 { - let key_pair = KeyPair::new(&secp, &mut rand::thread_rng()); + let key_pair = Keypair::new(&secp, &mut rand::thread_rng()); let signature = sign_message(B256::from_slice(&key_pair.secret_bytes()[..]), signature_hash) diff --git a/crates/net/discv4/Cargo.toml b/crates/net/discv4/Cargo.toml index fa0e284ff2c1..9a7cb943d1f0 100644 --- a/crates/net/discv4/Cargo.toml +++ b/crates/net/discv4/Cargo.toml @@ -21,8 +21,7 @@ reth-net-nat.workspace = true alloy-rlp = { workspace = true, features = ["derive"] } discv5.workspace = true secp256k1 = { workspace = true, features = ["global-context", "rand-std", "recovery", "serde"] } -enr = { workspace = true, default-features = false, features = ["rust-secp256k1"] } -rlp = "0.5" # needed for enr +enr.workspace = true # async/futures tokio = { workspace = true, features = ["io-util", "net", "time"] } tokio-stream.workspace = true diff --git a/crates/net/discv4/src/lib.rs b/crates/net/discv4/src/lib.rs index 48e25c163826..3ac6bfa8cf87 100644 --- a/crates/net/discv4/src/lib.rs +++ b/crates/net/discv4/src/lib.rs @@ -39,7 +39,7 @@ use discv5::{ }; use enr::Enr; use parking_lot::Mutex; -use proto::{EnrRequest, EnrResponse, EnrWrapper}; +use proto::{EnrRequest, EnrResponse}; use reth_primitives::{bytes::Bytes, hex, ForkId, PeerId, B256}; use secp256k1::SecretKey; use std::{ @@ -1279,7 +1279,7 @@ impl Discv4Service { self.send_packet( Message::EnrResponse(EnrResponse { request_hash, - enr: EnrWrapper::new(self.local_eip_868_enr.clone()), + enr: self.local_eip_868_enr.clone(), }), remote_addr, ); diff --git a/crates/net/discv4/src/proto.rs b/crates/net/discv4/src/proto.rs index 8bbb84b62964..bdca3bfb4de8 100644 --- a/crates/net/discv4/src/proto.rs +++ b/crates/net/discv4/src/proto.rs @@ -1,10 +1,8 @@ //! Discovery v4 protocol implementation. use crate::{error::DecodePacketError, EnrForkIdEntry, PeerId, MAX_PACKET_SIZE, MIN_PACKET_SIZE}; -use alloy_rlp::{ - length_of_length, Decodable, Encodable, Error as RlpError, Header, RlpDecodable, RlpEncodable, -}; -use enr::{Enr, EnrKey}; +use alloy_rlp::{Decodable, Encodable, Error as RlpError, Header, RlpDecodable, RlpEncodable}; +use enr::Enr; use reth_primitives::{ bytes::{Buf, BufMut, Bytes, BytesMut}, keccak256, pk2id, ForkId, NodeRecord, B256, @@ -112,8 +110,7 @@ impl Message { // Sign the payload with the secret key using recoverable ECDSA let signature: RecoverableSignature = SECP256K1.sign_ecdsa_recoverable( - &secp256k1::Message::from_slice(keccak256(&payload).as_ref()) - .expect("B256.len() == MESSAGE_SIZE"), + &secp256k1::Message::from_digest(keccak256(&payload).0), secret_key, ); @@ -158,7 +155,7 @@ impl Message { let recoverable_sig = RecoverableSignature::from_compact(signature, recovery_id)?; // recover the public key - let msg = secp256k1::Message::from_slice(keccak256(&packet[97..]).as_slice())?; + let msg = secp256k1::Message::from_digest(keccak256(&packet[97..]).0); let pk = SECP256K1.recover_ecdsa(&msg, &recoverable_sig)?; let node_id = pk2id(&pk); @@ -234,85 +231,6 @@ pub struct Neighbours { pub expire: u64, } -/// Passthrough newtype to [`Enr`]. -/// -/// We need to wrap the ENR type because of Rust's orphan rules not allowing -/// implementing a foreign trait on a foreign type. -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct EnrWrapper(Enr); - -impl EnrWrapper { - /// Creates a new instance of [`EnrWrapper`]. - pub fn new(enr: Enr) -> Self { - EnrWrapper(enr) - } -} - -impl Encodable for EnrWrapper -where - K: EnrKey, -{ - fn encode(&self, out: &mut dyn BufMut) { - let payload_length = self.0.signature().length() + - self.0.seq().length() + - self.0.iter().fold(0, |acc, (k, v)| acc + k.as_slice().length() + v.len()); - - let header = Header { list: true, payload_length }; - header.encode(out); - - self.0.signature().encode(out); - self.0.seq().encode(out); - - for (k, v) in self.0.iter() { - // Keys are byte data - k.as_slice().encode(out); - // Values are raw RLP encoded data - out.put_slice(v); - } - } - - fn length(&self) -> usize { - let payload_length = self.0.signature().length() + - self.0.seq().length() + - self.0.iter().fold(0, |acc, (k, v)| acc + k.as_slice().length() + v.len()); - payload_length + length_of_length(payload_length) - } -} - -fn to_alloy_rlp_error(e: rlp::DecoderError) -> RlpError { - match e { - rlp::DecoderError::RlpIsTooShort => RlpError::InputTooShort, - rlp::DecoderError::RlpInvalidLength => RlpError::Overflow, - rlp::DecoderError::RlpExpectedToBeList => RlpError::UnexpectedString, - rlp::DecoderError::RlpExpectedToBeData => RlpError::UnexpectedList, - rlp::DecoderError::RlpDataLenWithZeroPrefix | - rlp::DecoderError::RlpListLenWithZeroPrefix => RlpError::LeadingZero, - rlp::DecoderError::RlpInvalidIndirection => RlpError::NonCanonicalSize, - rlp::DecoderError::RlpIncorrectListLen => { - RlpError::Custom("incorrect list length when decoding rlp") - } - rlp::DecoderError::RlpIsTooBig => RlpError::Custom("rlp is too big"), - rlp::DecoderError::RlpInconsistentLengthAndData => { - RlpError::Custom("inconsistent length and data when decoding rlp") - } - rlp::DecoderError::Custom(s) => RlpError::Custom(s), - } -} - -impl Decodable for EnrWrapper { - fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { - let enr = as rlp::Decodable>::decode(&rlp::Rlp::new(buf)) - .map_err(to_alloy_rlp_error) - .map(EnrWrapper::new); - if enr.is_ok() { - // Decode was successful, advance buffer - let header = Header::decode(buf)?; - buf.advance(header.payload_length); - } - enr - } -} - /// A [ENRRequest packet](https://github.com/ethereum/devp2p/blob/master/discv4.md#enrrequest-packet-0x05). /// /// This packet is used to request the current version of a node's Ethereum Node Record (ENR). @@ -327,12 +245,12 @@ pub struct EnrRequest { /// /// This packet is used to respond to an ENRRequest packet and includes the requested ENR along with /// the hash of the original request. -#[derive(Clone, Debug, Eq, PartialEq, RlpEncodable)] +#[derive(Clone, Debug, Eq, PartialEq, RlpEncodable, RlpDecodable)] pub struct EnrResponse { /// The hash of the ENRRequest packet being replied to. pub request_hash: B256, /// The ENR (Ethereum Node Record) for the responding node. - pub enr: EnrWrapper, + pub enr: Enr, } // === impl EnrResponse === @@ -342,37 +260,11 @@ impl EnrResponse { /// /// See also pub fn eth_fork_id(&self) -> Option { - let mut maybe_fork_id = self.enr.0.get_raw_rlp(b"eth")?; + let mut maybe_fork_id = self.enr.get_raw_rlp(b"eth")?; EnrForkIdEntry::decode(&mut maybe_fork_id).ok().map(|entry| entry.fork_id) } } -impl Decodable for EnrResponse { - fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { - let b = &mut &**buf; - let rlp_head = Header::decode(b)?; - if !rlp_head.list { - return Err(RlpError::UnexpectedString) - } - // let started_len = b.len(); - let this = Self { - request_hash: alloy_rlp::Decodable::decode(b)?, - enr: EnrWrapper::::decode(b)?, - }; - // TODO: `Decodable` can be derived once we have native alloy_rlp decoding for ENR: - // Skipping the size check here is fine since the `buf` is the UDP datagram - // let consumed = started_len - b.len(); - // if consumed != rlp_head.payload_length { - // return Err(alloy_rlp::Error::ListLengthMismatch { - // expected: rlp_head.payload_length, - // got: consumed, - // }) - // } - *buf = *b; - Ok(this) - } -} - /// Represents a Ping packet. /// /// A [Ping packet](https://github.com/ethereum/devp2p/blob/master/discv4.md#ping-packet-0x01). @@ -750,7 +642,6 @@ mod tests { #[test] fn encode_decode_enr_msg() { - use self::EnrWrapper; use alloy_rlp::Decodable; use enr::secp256k1::SecretKey; use std::net::Ipv4Addr; @@ -770,7 +661,7 @@ mod tests { let forkentry = EnrForkIdEntry { fork_id }; forkentry.encode(&mut buf); builder.add_value_rlp("eth", buf.into()); - EnrWrapper::new(builder.build(&key).unwrap()) + builder.build(&key).unwrap() }; let enr_response = EnrResponse { request_hash: rng.gen(), enr }; @@ -789,30 +680,25 @@ mod tests { #[test] fn encode_known_rlp_enr() { - use self::EnrWrapper; use alloy_rlp::Decodable; use enr::{secp256k1::SecretKey, EnrPublicKey}; use std::net::Ipv4Addr; - let valid_record = - hex!("f884b8407098ad865b00a582051940cb9cf36836572411a47278783077011599ed5cd16b76f2635f4e234738f30813a89eb9137e3e3df5266e3a1f11df72ecf1145ccb9c01826964827634826970847f00000189736563703235366b31a103ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd31388375647082765f" - ); - let signature = - hex!("7098ad865b00a582051940cb9cf36836572411a47278783077011599ed5cd16b76f2635f4e234738f30813a89eb9137e3e3df5266e3a1f11df72ecf1145ccb9c" - ); + let valid_record = hex!("f884b8407098ad865b00a582051940cb9cf36836572411a47278783077011599ed5cd16b76f2635f4e234738f30813a89eb9137e3e3df5266e3a1f11df72ecf1145ccb9c01826964827634826970847f00000189736563703235366b31a103ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd31388375647082765f"); + let signature = hex!("7098ad865b00a582051940cb9cf36836572411a47278783077011599ed5cd16b76f2635f4e234738f30813a89eb9137e3e3df5266e3a1f11df72ecf1145ccb9c"); let expected_pubkey = hex!("03ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd3138"); - let enr = EnrWrapper::::decode(&mut &valid_record[..]).unwrap(); - let pubkey = enr.0.public_key().encode(); + let enr = Enr::::decode(&mut &valid_record[..]).unwrap(); + let pubkey = enr.public_key().encode(); - assert_eq!(enr.0.ip4(), Some(Ipv4Addr::new(127, 0, 0, 1))); - assert_eq!(enr.0.id(), Some(String::from("v4"))); - assert_eq!(enr.0.udp4(), Some(DEFAULT_DISCOVERY_PORT)); - assert_eq!(enr.0.tcp4(), None); - assert_eq!(enr.0.signature(), &signature[..]); + assert_eq!(enr.ip4(), Some(Ipv4Addr::new(127, 0, 0, 1))); + assert_eq!(enr.id(), Some(String::from("v4"))); + assert_eq!(enr.udp4(), Some(DEFAULT_DISCOVERY_PORT)); + assert_eq!(enr.tcp4(), None); + assert_eq!(enr.signature(), &signature[..]); assert_eq!(pubkey.to_vec(), expected_pubkey); - assert!(enr.0.verify()); + assert!(enr.verify()); assert_eq!(&alloy_rlp::encode(&enr)[..], &valid_record[..]); @@ -833,19 +719,19 @@ mod tests { hex!("03ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd3138"); let mut valid_record_buf = valid_record.as_slice(); - let enr = EnrWrapper::::decode(&mut valid_record_buf).unwrap(); - let pubkey = enr.0.public_key().encode(); + let enr = Enr::::decode(&mut valid_record_buf).unwrap(); + let pubkey = enr.public_key().encode(); // Byte array must be consumed after enr has finished decoding assert!(valid_record_buf.is_empty()); - assert_eq!(enr.0.ip4(), Some(Ipv4Addr::new(127, 0, 0, 1))); - assert_eq!(enr.0.id(), Some(String::from("v4"))); - assert_eq!(enr.0.udp4(), Some(DEFAULT_DISCOVERY_PORT)); - assert_eq!(enr.0.tcp4(), None); - assert_eq!(enr.0.signature(), &signature[..]); + assert_eq!(enr.ip4(), Some(Ipv4Addr::new(127, 0, 0, 1))); + assert_eq!(enr.id(), Some(String::from("v4"))); + assert_eq!(enr.udp4(), Some(DEFAULT_DISCOVERY_PORT)); + assert_eq!(enr.tcp4(), None); + assert_eq!(enr.signature(), &signature[..]); assert_eq!(pubkey.to_vec(), expected_pubkey); - assert!(enr.0.verify()); + assert!(enr.verify()); } // test vector from the enr library rlp encoding tests @@ -863,20 +749,23 @@ mod tests { let mut builder = Enr::builder(); builder.ip(ip.into()); builder.tcp4(tcp); - EnrWrapper::new(builder.build(&key).unwrap()) + builder.build(&key).unwrap() }; let mut encoded_bytes = &alloy_rlp::encode(&enr)[..]; - let decoded_enr = EnrWrapper::::decode(&mut encoded_bytes).unwrap(); + let decoded_enr = Enr::::decode(&mut encoded_bytes).unwrap(); // Byte array must be consumed after enr has finished decoding assert!(encoded_bytes.is_empty()); assert_eq!(decoded_enr, enr); - assert_eq!(decoded_enr.0.id(), Some("v4".into())); - assert_eq!(decoded_enr.0.ip4(), Some(ip)); - assert_eq!(decoded_enr.0.tcp4(), Some(tcp)); - assert_eq!(decoded_enr.0.public_key().encode(), key.public().encode()); - assert!(decoded_enr.0.verify()); + assert_eq!(decoded_enr.id(), Some("v4".into())); + assert_eq!(decoded_enr.ip4(), Some(ip)); + assert_eq!(decoded_enr.tcp4(), Some(tcp)); + assert_eq!( + decoded_enr.public_key().encode(), + key.public_key(secp256k1::SECP256K1).encode() + ); + assert!(decoded_enr.verify()); } } diff --git a/crates/net/discv5/Cargo.toml b/crates/net/discv5/Cargo.toml index 03b856be9a00..705ea17a8fbb 100644 --- a/crates/net/discv5/Cargo.toml +++ b/crates/net/discv5/Cargo.toml @@ -18,9 +18,8 @@ reth-metrics.workspace = true # ethereum alloy-rlp.workspace = true -rlp = "0.5.2" discv5 = { workspace = true, features = ["libp2p"] } -enr = { workspace = true, default-features = false, features = ["rust-secp256k1"] } +enr.workspace = true multiaddr = { version = "0.18", default-features = false } libp2p-identity = "0.2" secp256k1.workspace = true diff --git a/crates/net/discv5/src/enr.rs b/crates/net/discv5/src/enr.rs index b810c1dc63e6..088baf18e8ab 100644 --- a/crates/net/discv5/src/enr.rs +++ b/crates/net/discv5/src/enr.rs @@ -41,30 +41,25 @@ pub struct EnrCombinedKeyWrapper(pub discv5::Enr); impl From> for EnrCombinedKeyWrapper { fn from(value: Enr) -> Self { - let encoded_enr = rlp::encode(&value); - let enr = rlp::decode::(&encoded_enr).unwrap(); - - Self(enr) + let encoded_enr = alloy_rlp::encode(&value); + Self(alloy_rlp::Decodable::decode(&mut &encoded_enr[..]).unwrap()) } } impl From for Enr { fn from(val: EnrCombinedKeyWrapper) -> Self { - let EnrCombinedKeyWrapper(enr) = val; - let encoded_enr = rlp::encode(&enr); - - rlp::decode::>(&encoded_enr).unwrap() + let encoded_enr = alloy_rlp::encode(&val.0); + alloy_rlp::Decodable::decode(&mut &encoded_enr[..]).unwrap() } } #[cfg(test)] mod tests { + use super::*; use alloy_rlp::Encodable; use discv5::enr::{CombinedKey, EnrKey}; use reth_primitives::{Hardfork, NodeRecord, MAINNET}; - use super::*; - #[test] fn discv5_discv4_id_conversion() { let discv5_pk = CombinedKey::generate_secp256k1().public(); diff --git a/crates/net/discv5/src/lib.rs b/crates/net/discv5/src/lib.rs index 7e9fd81b1ba5..de74f3fee9e0 100644 --- a/crates/net/discv5/src/lib.rs +++ b/crates/net/discv5/src/lib.rs @@ -377,8 +377,6 @@ impl Discv5 { pub fn on_discv5_update(&mut self, update: discv5::Event) -> Option { match update { discv5::Event::SocketUpdated(_) | discv5::Event::TalkRequest(_) | - // `EnrAdded` not used in discv5 codebase - discv5::Event::EnrAdded { .. } | // `Discovered` not unique discovered peers discv5::Event::Discovered(_) => None, discv5::Event::NodeInserted { replaced: _, .. } => { @@ -404,6 +402,7 @@ impl Discv5 { self.on_discovered_peer(&enr, remote_socket) } + _ => None, } } diff --git a/crates/net/dns/Cargo.toml b/crates/net/dns/Cargo.toml index 003a6cad7444..243bbec71022 100644 --- a/crates/net/dns/Cargo.toml +++ b/crates/net/dns/Cargo.toml @@ -19,7 +19,7 @@ reth-net-common.workspace = true # ethereum alloy-rlp.workspace = true secp256k1 = { workspace = true, features = ["global-context", "rand-std", "recovery", "serde"] } -enr = { workspace = true, default-features = false, features = ["rust-secp256k1"] } +enr.workspace = true # async/futures tokio = { workspace = true, features = ["io-util", "net", "time"] } diff --git a/crates/net/dns/src/lib.rs b/crates/net/dns/src/lib.rs index 6db9c9ee2b2d..99e08ffdd541 100644 --- a/crates/net/dns/src/lib.rs +++ b/crates/net/dns/src/lib.rs @@ -22,7 +22,7 @@ use crate::{ pub use config::DnsDiscoveryConfig; use enr::Enr; use error::ParseDnsEntryError; -use reth_primitives::{pk2id, ForkId, NodeRecord}; +use reth_primitives::{pk2id, Bytes, ForkId, NodeRecord}; use schnellru::{ByLength, LruMap}; use secp256k1::SecretKey; use std::{ @@ -402,8 +402,8 @@ fn convert_enr_node_record(enr: &Enr) -> Option } .into_ipv4_mapped(); - let mut maybe_fork_id = enr.get(b"eth")?; - let fork_id = ForkId::decode(&mut maybe_fork_id).ok(); + let maybe_fork_id = enr.get_decodable::(b"eth").map(Result::ok)??; + let fork_id = ForkId::decode(&mut &maybe_fork_id[..]).ok(); Some(DnsNodeRecordUpdate { node_record, fork_id, enr: enr.clone() }) } diff --git a/crates/net/dns/src/tree.rs b/crates/net/dns/src/tree.rs index 53220f694e52..614d5f1d23ba 100644 --- a/crates/net/dns/src/tree.rs +++ b/crates/net/dns/src/tree.rs @@ -22,7 +22,7 @@ use crate::error::{ ParseEntryResult, }; use data_encoding::{BASE32_NOPAD, BASE64URL_NOPAD}; -use enr::{Enr, EnrError, EnrKey, EnrKeyUnambiguous, EnrPublicKey}; +use enr::{Enr, EnrKey, EnrKeyUnambiguous, EnrPublicKey, Error as EnrError}; use reth_primitives::{hex, Bytes}; use secp256k1::SecretKey; #[cfg(feature = "serde")] diff --git a/crates/net/ecies/src/algorithm.rs b/crates/net/ecies/src/algorithm.rs index 5dce7fee6902..bd1eb1d328f8 100644 --- a/crates/net/ecies/src/algorithm.rs +++ b/crates/net/ecies/src/algorithm.rs @@ -399,7 +399,7 @@ impl ECIES { let msg = x ^ self.nonce; let (rec_id, sig) = SECP256K1 .sign_ecdsa_recoverable( - &secp256k1::Message::from_slice(msg.as_slice()).unwrap(), + &secp256k1::Message::from_digest(msg.0), &self.ephemeral_secret_key, ) .serialize_compact(); @@ -473,7 +473,7 @@ impl ECIES { let x = ecdh_x(&self.remote_public_key.unwrap(), &self.secret_key); self.remote_ephemeral_public_key = Some(SECP256K1.recover_ecdsa( - &secp256k1::Message::from_slice((x ^ self.remote_nonce.unwrap()).as_ref()).unwrap(), + &secp256k1::Message::from_digest((x ^ self.remote_nonce.unwrap()).0), &signature, )?); self.ephemeral_shared_secret = @@ -631,7 +631,7 @@ impl ECIES { let tag = self.egress_mac.as_mut().unwrap().digest(); out.reserve(ECIES::header_len()); - out.extend_from_slice(&header); + out.extend_from_slice(&header[..]); out.extend_from_slice(tag.as_slice()); } diff --git a/crates/net/network/Cargo.toml b/crates/net/network/Cargo.toml index dbf7f5fa2b33..c06ff1518244 100644 --- a/crates/net/network/Cargo.toml +++ b/crates/net/network/Cargo.toml @@ -96,11 +96,7 @@ criterion = { workspace = true, features = ["async_tokio", "html_reports"] } [features] default = ["serde"] serde = ["dep:serde", "dep:humantime-serde", "secp256k1/serde", "enr/serde", "dep:serde_json"] -test-utils = [ - "reth-provider/test-utils", - "dep:tempfile", - "reth-transaction-pool/test-utils", -] +test-utils = ["reth-provider/test-utils", "dep:tempfile", "reth-transaction-pool/test-utils"] geth-tests = [] [[bench]] diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index e3828c913b6b..ab6b44303bc4 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -27,7 +27,7 @@ alloy-trie = { workspace = true, features = ["serde"] } nybbles = { workspace = true, features = ["serde", "rlp"] } alloy-genesis.workspace = true alloy-eips.workspace = true -enr = { workspace = true, features = ["rust-secp256k1"] } +enr.workspace = true # crypto secp256k1 = { workspace = true, features = ["global-context", "recovery", "rand"] } @@ -105,12 +105,10 @@ arbitrary = [ "dep:arbitrary", "dep:proptest", "dep:proptest-derive", - "zstd-codec" + "zstd-codec", ] c-kzg = ["dep:c-kzg", "revm/c-kzg", "revm-primitives/c-kzg", "dep:sha2", "dep:tempfile"] -zstd-codec = [ - "dep:zstd" -] +zstd-codec = ["dep:zstd"] clap = ["dep:clap"] optimism = [ "reth-codecs/optimism", diff --git a/crates/primitives/src/genesis.rs b/crates/primitives/src/genesis.rs index 52b24facbf79..991b01bd7e65 100644 --- a/crates/primitives/src/genesis.rs +++ b/crates/primitives/src/genesis.rs @@ -13,7 +13,7 @@ mod allocator { use alloy_genesis::GenesisAccount; use secp256k1::{ rand::{thread_rng, RngCore}, - KeyPair, Secp256k1, + Keypair, Secp256k1, }; use std::collections::{hash_map::Entry, BTreeMap, HashMap}; @@ -73,9 +73,9 @@ mod allocator { /// Add a funded account to the genesis alloc. /// /// Returns the key pair for the account and the account's address. - pub fn new_funded_account(&mut self, balance: U256) -> (KeyPair, Address) { + pub fn new_funded_account(&mut self, balance: U256) -> (Keypair, Address) { let secp = Secp256k1::new(); - let pair = KeyPair::new(&secp, &mut self.rng); + let pair = Keypair::new(&secp, &mut self.rng); let address = public_key_to_address(pair.public_key()); self.alloc.insert(address, GenesisAccount::default().with_balance(balance)); @@ -90,9 +90,9 @@ mod allocator { &mut self, balance: U256, code: Bytes, - ) -> (KeyPair, Address) { + ) -> (Keypair, Address) { let secp = Secp256k1::new(); - let pair = KeyPair::new(&secp, &mut self.rng); + let pair = Keypair::new(&secp, &mut self.rng); let address = public_key_to_address(pair.public_key()); self.alloc.insert( @@ -110,9 +110,9 @@ mod allocator { &mut self, balance: U256, storage: BTreeMap, - ) -> (KeyPair, Address) { + ) -> (Keypair, Address) { let secp = Secp256k1::new(); - let pair = KeyPair::new(&secp, &mut self.rng); + let pair = Keypair::new(&secp, &mut self.rng); let address = public_key_to_address(pair.public_key()); self.alloc.insert( @@ -130,9 +130,9 @@ mod allocator { &mut self, code: Bytes, storage: BTreeMap, - ) -> (KeyPair, Address) { + ) -> (Keypair, Address) { let secp = Secp256k1::new(); - let pair = KeyPair::new(&secp, &mut self.rng); + let pair = Keypair::new(&secp, &mut self.rng); let address = public_key_to_address(pair.public_key()); self.alloc.insert( @@ -146,9 +146,9 @@ mod allocator { /// Adds an account with code to the genesis alloc. /// /// Returns the key pair for the account and the account's address. - pub fn new_account_with_code(&mut self, code: Bytes) -> (KeyPair, Address) { + pub fn new_account_with_code(&mut self, code: Bytes) -> (Keypair, Address) { let secp = Secp256k1::new(); - let pair = KeyPair::new(&secp, &mut self.rng); + let pair = Keypair::new(&secp, &mut self.rng); let address = public_key_to_address(pair.public_key()); self.alloc.insert(address, GenesisAccount::default().with_code(Some(code))); @@ -169,7 +169,7 @@ mod allocator { /// Returns the key pair for the account and the account's address. pub fn add_account(&mut self, account: GenesisAccount) -> Address { let secp = Secp256k1::new(); - let pair = KeyPair::new(&secp, &mut self.rng); + let pair = Keypair::new(&secp, &mut self.rng); let address = public_key_to_address(pair.public_key()); self.alloc.insert(address, account); diff --git a/crates/primitives/src/transaction/mod.rs b/crates/primitives/src/transaction/mod.rs index dae6ab076840..a4ec978a3fda 100644 --- a/crates/primitives/src/transaction/mod.rs +++ b/crates/primitives/src/transaction/mod.rs @@ -1755,7 +1755,7 @@ mod tests { use alloy_primitives::{address, b256, bytes}; use alloy_rlp::{Decodable, Encodable, Error as RlpError}; use reth_codecs::Compact; - use secp256k1::{KeyPair, Secp256k1}; + use secp256k1::{Keypair, Secp256k1}; use std::str::FromStr; #[test] @@ -2048,7 +2048,7 @@ mod tests { tx.set_chain_id(chain_id % (u64::MAX / 2 - 36)); } - let key_pair = KeyPair::new(&secp, &mut rng); + let key_pair = Keypair::new(&secp, &mut rng); let signature = sign_message(B256::from_slice(&key_pair.secret_bytes()[..]), tx.signature_hash()).unwrap(); diff --git a/crates/primitives/src/transaction/util.rs b/crates/primitives/src/transaction/util.rs index 638064c12f10..b4a2db7f6b52 100644 --- a/crates/primitives/src/transaction/util.rs +++ b/crates/primitives/src/transaction/util.rs @@ -18,7 +18,7 @@ pub(crate) mod secp256k1 { let sig = RecoverableSignature::from_compact(&sig[0..64], RecoveryId::from_i32(sig[64] as i32)?)?; - let public = SECP256K1.recover_ecdsa(&Message::from_slice(&msg[..32])?, &sig)?; + let public = SECP256K1.recover_ecdsa(&Message::from_digest(*msg), &sig)?; Ok(public_key_to_address(public)) } @@ -26,7 +26,7 @@ pub(crate) mod secp256k1 { /// Returns the corresponding signature. pub fn sign_message(secret: B256, message: B256) -> Result { let sec = SecretKey::from_slice(secret.as_ref())?; - let s = SECP256K1.sign_ecdsa_recoverable(&Message::from_slice(&message[..])?, &sec); + let s = SECP256K1.sign_ecdsa_recoverable(&Message::from_digest(message.0), &sec); let (rec_id, data) = s.serialize_compact(); let signature = Signature { From 58cbe40be0062aa84da63811fe247ada56223704 Mon Sep 17 00:00:00 2001 From: Emilia Hane Date: Thu, 25 Apr 2024 21:37:59 +0200 Subject: [PATCH 2/2] fix(dns): broken decoding of rlp data (#7564) Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> --- Cargo.lock | 1 + crates/net/dns/Cargo.toml | 3 +- crates/net/dns/src/lib.rs | 66 +++++++++++++++++++++++++++++++++------ 3 files changed, 59 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8b7ceb72c6d9..13f31f68fd43 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6394,6 +6394,7 @@ dependencies = [ "enr", "linked_hash_set", "parking_lot 0.12.1", + "rand 0.8.5", "reth-net-common", "reth-primitives", "reth-tracing", diff --git a/crates/net/dns/Cargo.toml b/crates/net/dns/Cargo.toml index 243bbec71022..18d7bf81519b 100644 --- a/crates/net/dns/Cargo.toml +++ b/crates/net/dns/Cargo.toml @@ -17,7 +17,6 @@ reth-primitives.workspace = true reth-net-common.workspace = true # ethereum -alloy-rlp.workspace = true secp256k1 = { workspace = true, features = ["global-context", "rand-std", "recovery", "serde"] } enr.workspace = true @@ -39,8 +38,10 @@ serde = { workspace = true, optional = true } serde_with = { version = "3.3.0", optional = true } [dev-dependencies] +alloy-rlp.workspace = true tokio = { workspace = true, features = ["sync", "rt", "rt-multi-thread"] } reth-tracing.workspace = true +rand.workspace = true [features] default = ["serde"] diff --git a/crates/net/dns/src/lib.rs b/crates/net/dns/src/lib.rs index 99e08ffdd541..03c72e33016f 100644 --- a/crates/net/dns/src/lib.rs +++ b/crates/net/dns/src/lib.rs @@ -22,7 +22,7 @@ use crate::{ pub use config::DnsDiscoveryConfig; use enr::Enr; use error::ParseDnsEntryError; -use reth_primitives::{pk2id, Bytes, ForkId, NodeRecord}; +use reth_primitives::{pk2id, ForkId, NodeRecord}; use schnellru::{ByLength, LruMap}; use secp256k1::SecretKey; use std::{ @@ -392,8 +392,6 @@ pub enum DnsDiscoveryEvent { /// Converts an [Enr] into a [NodeRecord] fn convert_enr_node_record(enr: &Enr) -> Option { - use alloy_rlp::Decodable; - let node_record = NodeRecord { address: enr.ip4().map(IpAddr::from).or_else(|| enr.ip6().map(IpAddr::from))?, tcp_port: enr.tcp4().or_else(|| enr.tcp6())?, @@ -402,8 +400,7 @@ fn convert_enr_node_record(enr: &Enr) -> Option } .into_ipv4_mapped(); - let maybe_fork_id = enr.get_decodable::(b"eth").map(Result::ok)??; - let fork_id = ForkId::decode(&mut &maybe_fork_id[..]).ok(); + let fork_id = enr.get_decodable::(b"eth").transpose().ok()?; Some(DnsNodeRecordUpdate { node_record, fork_id, enr: enr.clone() }) } @@ -412,12 +409,63 @@ fn convert_enr_node_record(enr: &Enr) -> Option mod tests { use super::*; use crate::tree::TreeRootEntry; - use alloy_rlp::Encodable; + use alloy_rlp::{Decodable, Encodable}; use enr::EnrKey; - use reth_primitives::{Chain, Hardfork, MAINNET}; + use reth_primitives::{Chain, ForkHash, Hardfork, MAINNET}; use secp256k1::rand::thread_rng; use std::{future::poll_fn, net::Ipv4Addr}; + #[test] + fn test_convert_enr_node_record() { + // rig + let secret_key = SecretKey::new(&mut secp256k1::rand::thread_rng()); + let enr = Enr::builder() + .ip("127.0.0.1".parse().unwrap()) + .udp4(9000) + .tcp4(30303) + .add_value(b"eth", &MAINNET.latest_fork_id()) + .build(&secret_key) + .unwrap(); + + // test + let node_record_update = convert_enr_node_record(&enr).unwrap(); + + assert_eq!(node_record_update.node_record.address, "127.0.0.1".parse::().unwrap()); + assert_eq!(node_record_update.node_record.tcp_port, 30303); + assert_eq!(node_record_update.node_record.udp_port, 9000); + assert_eq!(node_record_update.fork_id, Some(MAINNET.latest_fork_id())); + assert_eq!(node_record_update.enr, enr); + } + + #[test] + fn test_decode_and_convert_enr_node_record() { + // rig + + let secret_key = SecretKey::new(&mut secp256k1::rand::thread_rng()); + let enr = Enr::builder() + .ip("127.0.0.1".parse().unwrap()) + .udp4(9000) + .tcp4(30303) + .add_value(b"eth", &MAINNET.latest_fork_id()) + .add_value(b"opstack", &ForkId { hash: ForkHash(rand::random()), next: rand::random() }) + .build(&secret_key) + .unwrap(); + + let mut encoded_enr = vec![]; + enr.encode(&mut encoded_enr); + + // test + let decoded_enr = Enr::decode(&mut &encoded_enr[..]).unwrap(); + + let node_record_update = convert_enr_node_record(&decoded_enr).unwrap(); + + assert_eq!(node_record_update.node_record.address, "127.0.0.1".parse::().unwrap()); + assert_eq!(node_record_update.node_record.tcp_port, 30303); + assert_eq!(node_record_update.node_record.udp_port, 9000); + assert_eq!(node_record_update.fork_id, Some(MAINNET.latest_fork_id())); + assert_eq!(node_record_update.enr, enr); + } + #[tokio::test] async fn test_start_root_sync() { reth_tracing::init_test_tracing(); @@ -461,10 +509,8 @@ mod tests { resolver.insert(link.domain.clone(), root.to_string()); let mut builder = Enr::builder(); - let mut buf = Vec::new(); let fork_id = MAINNET.hardfork_fork_id(Hardfork::Frontier).unwrap(); - fork_id.encode(&mut buf); - builder.ip4(Ipv4Addr::LOCALHOST).udp4(30303).tcp4(30303).add_value(b"eth", &buf); + builder.ip4(Ipv4Addr::LOCALHOST).udp4(30303).tcp4(30303).add_value(b"eth", &fork_id); let enr = builder.build(&secret_key).unwrap(); resolver.insert(format!("{}.{}", root.enr_root.clone(), link.domain), enr.to_base64());