chore(deps): bump enr, discv5, secp256k1 (#7000)

Co-authored-by: Emilia Hane <elsaemiliaevahane@gmail.com>
This commit is contained in:
DaniPopes
2024-04-25 21:50:38 +02:00
committed by GitHub
parent 3ad3bbc593
commit e2e5201d8a
18 changed files with 169 additions and 270 deletions

View File

@@ -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,
);

View File

@@ -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<K: EnrKey>(Enr<K>);
impl<K: EnrKey> EnrWrapper<K> {
/// Creates a new instance of [`EnrWrapper`].
pub fn new(enr: Enr<K>) -> Self {
EnrWrapper(enr)
}
}
impl<K> Encodable for EnrWrapper<K>
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<K: EnrKey> Decodable for EnrWrapper<K> {
fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
let enr = <Enr<K> 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<SecretKey>,
pub enr: Enr<SecretKey>,
}
// === impl EnrResponse ===
@@ -342,37 +260,11 @@ impl EnrResponse {
///
/// See also <https://github.com/ethereum/go-ethereum/blob/9244d5cd61f3ea5a7645fdf2a1a96d53421e412f/eth/protocols/eth/discovery.go#L36>
pub fn eth_fork_id(&self) -> Option<ForkId> {
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<Self> {
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::<SecretKey>::decode(b)?,
};
// TODO: `Decodable` can be derived once we have native alloy_rlp decoding for ENR: <https://github.com/paradigmxyz/reth/issues/482>
// 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::<SecretKey>::decode(&mut &valid_record[..]).unwrap();
let pubkey = enr.0.public_key().encode();
let enr = Enr::<SecretKey>::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::<SecretKey>::decode(&mut valid_record_buf).unwrap();
let pubkey = enr.0.public_key().encode();
let enr = Enr::<SecretKey>::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::<SecretKey>::decode(&mut encoded_bytes).unwrap();
let decoded_enr = Enr::<SecretKey>::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());
}
}