Skip to content

feat(l1): properly calculate enr sequence field #2679

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 42 commits into from
May 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
d97afae
Change struct name
mechanix97 May 6, 2025
a2c8f49
add store config file
mechanix97 May 6, 2025
bb26b62
read config file
mechanix97 May 6, 2025
bc8968b
remove clone
mechanix97 May 6, 2025
53acf85
chane info msg
mechanix97 May 6, 2025
2a46284
refactor P2Pcontext
mechanix97 May 6, 2025
6da35d7
Add mutex node record
mechanix97 May 6, 2025
2a57cb5
add seq to save
mechanix97 May 6, 2025
6d1152e
try fix test
mechanix97 May 6, 2025
bda131d
fix tests
mechanix97 May 7, 2025
e18bf60
fix clippy
mechanix97 May 7, 2025
8f7072c
fix clippy now
mechanix97 May 7, 2025
a130f43
change seq to 1
mechanix97 May 7, 2025
d0474ce
Fix test
mechanix97 May 7, 2025
875cc2c
Fix l2 clippy
mechanix97 May 7, 2025
97423da
Merge branch 'main' into feat/properly-calculate-enr-seq
mechanix97 May 7, 2025
1f787b9
Merge branch 'main' into feat/properly-calculate-enr-seq
mechanix97 May 8, 2025
b647c08
Merge branch 'main' into feat/properly-calculate-enr-seq
mechanix97 May 8, 2025
0893f60
Fix initilizer 0 to 1
mechanix97 May 8, 2025
29ea80c
Remove arc mutex
mechanix97 May 8, 2025
c0fe29d
Merge branch 'main' into feat/properly-calculate-enr-seq
mechanix97 May 8, 2025
bc8275d
fix l2
mechanix97 May 8, 2025
98a1f77
Merge branch 'feat/properly-calculate-enr-seq' of github.com:lambdacl…
mechanix97 May 8, 2025
5e0cf28
fix clippy l2
mechanix97 May 8, 2025
dec4aae
Merge branch 'main' into feat/properly-calculate-enr-seq
mechanix97 May 8, 2025
fe799c0
Remove arc from RPC
mechanix97 May 8, 2025
d4d7f46
Merge branch 'main' into feat/properly-calculate-enr-seq
mechanix97 May 8, 2025
115ad7c
Update node record when opening config file
mechanix97 May 9, 2025
eb08378
Merge branch 'feat/properly-calculate-enr-seq' of github.com:lambdacl…
mechanix97 May 9, 2025
a1aaf58
fix lint
mechanix97 May 9, 2025
f98b056
fix lint l2
mechanix97 May 9, 2025
f4b0bf1
Update seq properly
mechanix97 May 9, 2025
987c540
Merge branch 'main' into feat/properly-calculate-enr-seq
mechanix97 May 12, 2025
736e046
fix clippy
mechanix97 May 12, 2025
751dff6
Merge branch 'main' into feat/properly-calculate-enr-seq
mechanix97 May 13, 2025
cc197ab
Merge branch 'main' into feat/properly-calculate-enr-seq
mechanix97 May 13, 2025
ff25b47
Use timestamp as default seq
mechanix97 May 13, 2025
c7609bc
Fix l2
mechanix97 May 13, 2025
6bd37b7
Remove async/await
mechanix97 May 14, 2025
81d887a
Merge branch 'main' into feat/properly-calculate-enr-seq
mechanix97 May 14, 2025
5ea5708
Merge branch 'main' into feat/properly-calculate-enr-seq
mechanix97 May 19, 2025
aced208
Fix typo
mechanix97 May 19, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions cmd/ethrex/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ clap = { workspace = true, features = ["string"] }
clap_complete.workspace = true
eyre.workspace = true
directories = "5.0.1"
serde.workspace = true
serde_json.workspace = true
tokio = { version = "1.38.0", features = ["full"] }
anyhow = "1.0.86"
Expand Down
25 changes: 17 additions & 8 deletions cmd/ethrex/ethrex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ use clap::Parser;
use ethrex::{
cli::CLI,
initializers::{
get_local_p2p_node, get_network, get_signer, init_blockchain, init_metrics, init_rpc_api,
init_store, init_tracing,
get_local_node_record, get_local_p2p_node, get_network, get_signer, init_blockchain,
init_metrics, init_rpc_api, init_store, init_tracing,
},
utils::{set_datadir, store_known_peers},
utils::{set_datadir, store_node_config_file, NodeConfigFile},
};
use ethrex_p2p::network::peer_table;
use std::{path::PathBuf, time::Duration};
use std::{path::PathBuf, sync::Arc, time::Duration};
use tokio::sync::Mutex;
use tokio_util::task::TaskTracker;
use tracing::info;

Expand Down Expand Up @@ -39,6 +40,12 @@ async fn main() -> eyre::Result<()> {

let local_p2p_node = get_local_p2p_node(&opts, &signer);

let local_node_record = Arc::new(Mutex::new(get_local_node_record(
&data_dir,
&local_p2p_node,
&signer,
)));

let peer_table = peer_table(local_p2p_node.node_id());

// TODO: Check every module starts properly.
Expand All @@ -50,9 +57,9 @@ async fn main() -> eyre::Result<()> {
&opts,
#[cfg(any(feature = "l2", feature = "based"))]
&L2Options::default(),
&signer,
peer_table.clone(),
local_p2p_node.clone(),
local_node_record.lock().await.clone(),
store.clone(),
blockchain.clone(),
cancel_token.clone(),
Expand Down Expand Up @@ -80,6 +87,7 @@ async fn main() -> eyre::Result<()> {
&network,
&data_dir,
local_p2p_node,
local_node_record.clone(),
signer,
peer_table.clone(),
store.clone(),
Expand All @@ -96,10 +104,11 @@ async fn main() -> eyre::Result<()> {
tokio::select! {
_ = tokio::signal::ctrl_c() => {
info!("Server shut down started...");
let peers_file = PathBuf::from(data_dir + "/peers.json");
info!("Storing known peers at {:?}...", peers_file);
let node_config_path = PathBuf::from(data_dir + "/node_config.json");
info!("Storing config at {:?}...", node_config_path);
cancel_token.cancel();
store_known_peers(peer_table, peers_file).await;
let node_config = NodeConfigFile::new(peer_table, local_node_record.lock().await.clone()).await;
store_node_config_file(node_config, node_config_path).await;
tokio::time::sleep(Duration::from_secs(1)).await;
info!("Server shutting down!");
}
Expand Down
58 changes: 39 additions & 19 deletions cmd/ethrex/initializers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ use crate::{
networks,
utils::{
get_client_version, parse_socket_addr, read_genesis_file, read_jwtsecret_file,
read_known_peers,
read_node_config_file,
},
};
use ethrex_blockchain::Blockchain;
use ethrex_p2p::{
kademlia::KademliaTable,
network::public_key_from_signing_key,
network::{public_key_from_signing_key, P2PContext},
sync_manager::SyncManager,
types::{Node, NodeRecord},
};
Expand All @@ -18,6 +18,7 @@ use ethrex_vm::EvmEngine;
use k256::ecdsa::SigningKey;
use local_ip_address::local_ip;
use rand::rngs::OsRng;
use std::time::{SystemTime, UNIX_EPOCH};
use std::{
fs,
future::IntoFuture,
Expand Down Expand Up @@ -124,22 +125,15 @@ pub fn init_blockchain(evm_engine: EvmEngine, store: Store) -> Arc<Blockchain> {
pub async fn init_rpc_api(
opts: &Options,
#[cfg(feature = "l2")] l2_opts: &L2Options,
signer: &SigningKey,
peer_table: Arc<Mutex<KademliaTable>>,
local_p2p_node: Node,
local_node_record: NodeRecord,
store: Store,
blockchain: Arc<Blockchain>,
cancel_token: CancellationToken,
tracker: TaskTracker,
#[cfg(feature = "l2")] rollup_store: StoreRollup,
) {
let enr_seq = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_secs();
let local_node_record = NodeRecord::from_node(&local_p2p_node, enr_seq, signer)
.expect("Node record could not be created from local node");

// Create SyncManager
let syncer = SyncManager::new(
peer_table.clone(),
Expand Down Expand Up @@ -209,6 +203,7 @@ pub async fn init_network(
network: &str,
data_dir: &str,
local_p2p_node: Node,
local_node_record: Arc<Mutex<NodeRecord>>,
signer: SigningKey,
peer_table: Arc<Mutex<KademliaTable>>,
store: Store,
Expand All @@ -224,18 +219,20 @@ pub async fn init_network(

let bootnodes = get_bootnodes(opts, network, data_dir);

ethrex_p2p::start_network(
let context = P2PContext::new(
local_p2p_node,
local_node_record,
tracker.clone(),
bootnodes,
signer,
peer_table.clone(),
store,
blockchain,
get_client_version(),
)
.await
.expect("Network starts");
);

ethrex_p2p::start_network(context, bootnodes)
.await
.expect("Network starts");

tracker.spawn(ethrex_p2p::periodically_show_peer_stats(peer_table.clone()));
}
Expand Down Expand Up @@ -324,12 +321,12 @@ pub fn get_bootnodes(opts: &Options, network: &str, data_dir: &str) -> Vec<Node>
warn!("No bootnodes specified. This node will not be able to connect to the network.");
}

let peers_file = PathBuf::from(data_dir.to_owned() + "/peers.json");
let config_file = PathBuf::from(data_dir.to_owned() + "/config.json");

info!("Reading known peers from {:?}", peers_file);
info!("Reading known peers from config file {:?}", config_file);

match read_known_peers(peers_file.clone()) {
Ok(ref mut known_peers) => bootnodes.append(known_peers),
match read_node_config_file(config_file) {
Ok(ref mut config) => bootnodes.append(&mut config.known_peers),
Err(e) => error!("Could not read from peers file: {e}"),
};

Expand Down Expand Up @@ -389,6 +386,29 @@ pub fn get_local_p2p_node(opts: &Options, signer: &SigningKey) -> Node {
node
}

pub fn get_local_node_record(
data_dir: &str,
local_p2p_node: &Node,
signer: &SigningKey,
) -> NodeRecord {
let config_file = PathBuf::from(data_dir.to_owned() + "/node_config.json");

match read_node_config_file(config_file) {
Ok(ref mut config) => {
NodeRecord::from_node(local_p2p_node, config.node_record.seq + 1, signer)
.expect("Node record could not be created from local node")
}
Err(_) => {
let timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_secs();
NodeRecord::from_node(local_p2p_node, timestamp, signer)
.expect("Node record could not be created from local node")
}
}
}

pub fn get_authrpc_socket_addr(opts: &Options) -> SocketAddr {
parse_socket_addr(&opts.authrpc_addr, &opts.authrpc_port)
.expect("Failed to parse authrpc address and port")
Expand Down
25 changes: 17 additions & 8 deletions cmd/ethrex/l2/command.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use crate::{
cli::{self as ethrex_cli, Options as NodeOptions},
initializers::{
get_local_p2p_node, get_network, get_signer, init_blockchain, init_metrics, init_network,
init_rollup_store, init_rpc_api, init_store,
get_local_node_record, get_local_p2p_node, get_network, get_signer, init_blockchain,
init_metrics, init_network, init_rollup_store, init_rpc_api, init_store,
},
l2::options::Options,
utils::{set_datadir, store_known_peers},
utils::{set_datadir, store_node_config_file, NodeConfigFile},
DEFAULT_L2_DATADIR,
};
use clap::Subcommand;
Expand All @@ -19,7 +19,8 @@ use ethrex_rpc::{
use eyre::OptionExt;
use keccak_hash::keccak;
use reqwest::Url;
use std::{fs::create_dir_all, future::IntoFuture, path::PathBuf, time::Duration};
use std::{fs::create_dir_all, future::IntoFuture, path::PathBuf, sync::Arc, time::Duration};
use tokio::sync::Mutex;
use tokio_util::task::TaskTracker;
use tracing::info;

Expand Down Expand Up @@ -73,6 +74,12 @@ impl Command {

let local_p2p_node = get_local_p2p_node(&opts.node_opts, &signer);

let local_node_record = Arc::new(Mutex::new(get_local_node_record(
&data_dir,
&local_p2p_node,
&signer,
)));

let peer_table = peer_table(local_p2p_node.node_id());

// TODO: Check every module starts properly.
Expand All @@ -83,9 +90,9 @@ impl Command {
init_rpc_api(
&opts.node_opts,
&opts,
&signer,
peer_table.clone(),
local_p2p_node.clone(),
local_node_record.lock().await.clone(),
store.clone(),
blockchain.clone(),
cancel_token.clone(),
Expand All @@ -105,6 +112,7 @@ impl Command {
&network,
&data_dir,
local_p2p_node,
local_node_record.clone(),
signer,
peer_table.clone(),
store.clone(),
Expand All @@ -127,10 +135,11 @@ impl Command {
tokio::select! {
_ = tokio::signal::ctrl_c() => {
info!("Server shut down started...");
let peers_file = PathBuf::from(data_dir + "/peers.json");
info!("Storing known peers at {:?}...", peers_file);
let node_config_path = PathBuf::from(data_dir + "/node_config.json");
info!("Storing config at {:?}...", node_config_path);
cancel_token.cancel();
store_known_peers(peer_table, peers_file).await;
let node_config = NodeConfigFile::new(peer_table, local_node_record.lock().await.clone()).await;
store_node_config_file(node_config, node_config_path).await;
tokio::time::sleep(Duration::from_secs(1)).await;
info!("Server shutting down!");
}
Expand Down
58 changes: 39 additions & 19 deletions cmd/ethrex/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@ use crate::decode;
use bytes::Bytes;
use directories::ProjectDirs;
use ethrex_common::types::{Block, Genesis};
use ethrex_p2p::{kademlia::KademliaTable, sync::SyncMode, types::Node};
use ethrex_p2p::{
kademlia::KademliaTable,
sync::SyncMode,
types::{Node, NodeRecord},
};
use ethrex_rlp::decode::RLPDecode;
use ethrex_vm::EvmEngine;
use hex::FromHexError;
#[cfg(feature = "l2")]
use secp256k1::SecretKey;
use serde::{Deserialize, Serialize};
use std::{
fs::File,
io,
Expand All @@ -18,6 +23,28 @@ use std::{
use tokio::sync::Mutex;
use tracing::{error, info};

#[derive(Serialize, Deserialize)]
pub struct NodeConfigFile {
pub known_peers: Vec<Node>,
pub node_record: NodeRecord,
}

impl NodeConfigFile {
pub async fn new(table: Arc<Mutex<KademliaTable>>, node_record: NodeRecord) -> Self {
let mut connected_peers = vec![];

for peer in table.lock().await.iter_peers() {
if peer.is_connected {
connected_peers.push(peer.node.clone());
}
}
NodeConfigFile {
known_peers: connected_peers,
node_record,
}
}
}

pub fn read_jwtsecret_file(jwt_secret_path: &str) -> Bytes {
match File::open(jwt_secret_path) {
Ok(mut file) => decode::jwtsecret_file(&mut file),
Expand Down Expand Up @@ -93,35 +120,28 @@ pub fn set_datadir(datadir: &str) -> String {
.to_owned()
}

pub async fn store_known_peers(table: Arc<Mutex<KademliaTable>>, file_path: PathBuf) {
let mut connected_peers = vec![];

for peer in table.lock().await.iter_peers() {
if peer.is_connected {
connected_peers.push(peer.node.enode_url());
}
}

let json = match serde_json::to_string(&connected_peers) {
pub async fn store_node_config_file(config: NodeConfigFile, file_path: PathBuf) {
let json = match serde_json::to_string(&config) {
Ok(json) => json,
Err(e) => {
error!("Could not store peers in file: {:?}", e);
error!("Could not store config in file: {:?}", e);
return;
}
};

if let Err(e) = std::fs::write(file_path, json) {
error!("Could not store peers in file: {:?}", e);
error!("Could not store config in file: {:?}", e);
};
}

#[allow(dead_code)]
pub fn read_known_peers(file_path: PathBuf) -> Result<Vec<Node>, serde_json::Error> {
let Ok(file) = std::fs::File::open(file_path) else {
return Ok(vec![]);
};

serde_json::from_reader(file)
pub fn read_node_config_file(file_path: PathBuf) -> Result<NodeConfigFile, String> {
match std::fs::File::open(file_path) {
Ok(file) => {
serde_json::from_reader(file).map_err(|e| format!("Invalid node config file {}", e))
}
Err(e) => Err(format!("No config file found: {}", e)),
}
}

#[cfg(feature = "l2")]
Expand Down
Loading
Loading