fix: encode forkid entry in struct, accept trailing fields (#3193)

This commit is contained in:
Dan Cline
2023-06-15 16:04:23 -04:00
committed by GitHub
parent 144f4bdcee
commit 85085896a9
3 changed files with 48 additions and 4 deletions

View File

@ -35,6 +35,7 @@ use reth_primitives::{
bytes::{Bytes, BytesMut}, bytes::{Bytes, BytesMut},
ForkId, PeerId, H256, ForkId, PeerId, H256,
}; };
use reth_rlp::{RlpDecodable, RlpEncodable};
use secp256k1::SecretKey; use secp256k1::SecretKey;
use std::{ use std::{
cell::RefCell, cell::RefCell,
@ -1967,14 +1968,56 @@ pub enum DiscoveryUpdate {
Batch(Vec<DiscoveryUpdate>), Batch(Vec<DiscoveryUpdate>),
} }
/// Represents a forward-compatible ENR entry for including the forkid in a node record via
/// EIP-868. Forward compatibility is achieved by allowing trailing fields.
///
/// See:
/// <https://github.com/ethereum/go-ethereum/blob/9244d5cd61f3ea5a7645fdf2a1a96d53421e412f/eth/protocols/eth/discovery.go#L27-L38>
///
/// for how geth implements ForkId values and forward compatibility.
#[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
#[rlp(trailing)]
pub struct EnrForkIdEntry {
/// The inner forkid
pub fork_id: ForkId,
}
impl From<ForkId> for EnrForkIdEntry {
fn from(fork_id: ForkId) -> Self {
Self { fork_id }
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::test_utils::{create_discv4, create_discv4_with_config, rng_endpoint, rng_record}; use crate::test_utils::{create_discv4, create_discv4_with_config, rng_endpoint, rng_record};
use rand::{thread_rng, Rng}; use rand::{thread_rng, Rng};
use reth_primitives::{hex_literal::hex, mainnet_nodes, ForkHash}; use reth_primitives::{hex_literal::hex, mainnet_nodes, ForkHash};
use reth_rlp::{Decodable, Encodable};
use std::{future::poll_fn, net::Ipv4Addr}; use std::{future::poll_fn, net::Ipv4Addr};
#[test]
fn test_enr_forkid_entry_decode() {
let raw: [u8; 8] = [0xc7, 0xc6, 0x84, 0xdc, 0xe9, 0x6c, 0x2d, 0x80];
let decoded = EnrForkIdEntry::decode(&mut &raw[..]).unwrap();
let expected = EnrForkIdEntry {
fork_id: ForkId { hash: ForkHash([0xdc, 0xe9, 0x6c, 0x2d]), next: 0 },
};
assert_eq!(expected, decoded);
}
#[test]
fn test_enr_forkid_entry_encode() {
let original = EnrForkIdEntry {
fork_id: ForkId { hash: ForkHash([0xdc, 0xe9, 0x6c, 0x2d]), next: 0 },
};
let mut encoded = Vec::new();
original.encode(&mut encoded);
let expected: [u8; 8] = [0xc7, 0xc6, 0x84, 0xdc, 0xe9, 0x6c, 0x2d, 0x80];
assert_eq!(&expected[..], encoded.as_slice());
}
#[test] #[test]
fn test_local_rotator() { fn test_local_rotator() {
let id = PeerId::random(); let id = PeerId::random();

View File

@ -1,6 +1,6 @@
#![allow(missing_docs)] #![allow(missing_docs)]
use crate::{error::DecodePacketError, PeerId, MAX_PACKET_SIZE, MIN_PACKET_SIZE}; use crate::{error::DecodePacketError, EnrForkIdEntry, PeerId, MAX_PACKET_SIZE, MIN_PACKET_SIZE};
use enr::{Enr, EnrKey}; use enr::{Enr, EnrKey};
use reth_primitives::{ use reth_primitives::{
bytes::{Buf, BufMut, Bytes, BytesMut}, bytes::{Buf, BufMut, Bytes, BytesMut},
@ -306,7 +306,7 @@ impl EnrResponse {
/// See also <https://github.com/ethereum/go-ethereum/blob/9244d5cd61f3ea5a7645fdf2a1a96d53421e412f/eth/protocols/eth/discovery.go#L36> /// See also <https://github.com/ethereum/go-ethereum/blob/9244d5cd61f3ea5a7645fdf2a1a96d53421e412f/eth/protocols/eth/discovery.go#L36>
pub fn eth_fork_id(&self) -> Option<ForkId> { pub fn eth_fork_id(&self) -> Option<ForkId> {
let mut maybe_fork_id = self.enr.0.get(b"eth")?; let mut maybe_fork_id = self.enr.0.get(b"eth")?;
ForkId::decode(&mut maybe_fork_id).ok() EnrForkIdEntry::decode(&mut maybe_fork_id).ok().map(|entry| entry.fork_id)
} }
} }

View File

@ -2,7 +2,7 @@
use crate::error::{NetworkError, ServiceKind}; use crate::error::{NetworkError, ServiceKind};
use futures::StreamExt; use futures::StreamExt;
use reth_discv4::{DiscoveryUpdate, Discv4, Discv4Config}; use reth_discv4::{DiscoveryUpdate, Discv4, Discv4Config, EnrForkIdEntry};
use reth_dns_discovery::{ use reth_dns_discovery::{
DnsDiscoveryConfig, DnsDiscoveryHandle, DnsDiscoveryService, DnsNodeRecordUpdate, DnsResolver, DnsDiscoveryConfig, DnsDiscoveryHandle, DnsDiscoveryService, DnsNodeRecordUpdate, DnsResolver,
}; };
@ -100,7 +100,8 @@ impl Discovery {
#[allow(unused)] #[allow(unused)]
pub(crate) fn update_fork_id(&self, fork_id: ForkId) { pub(crate) fn update_fork_id(&self, fork_id: ForkId) {
if let Some(discv4) = &self.discv4 { if let Some(discv4) = &self.discv4 {
discv4.set_eip868_rlp("eth".as_bytes().to_vec(), fork_id) // use forward-compatible forkid entry
discv4.set_eip868_rlp("eth".as_bytes().to_vec(), EnrForkIdEntry::from(fork_id))
} }
} }