Skip to content

Commit 65fa572

Browse files
committed
Moved Lido implementation to interop
1 parent 8bf5e09 commit 65fa572

5 files changed

Lines changed: 289 additions & 270 deletions

File tree

crates/common/src/config/mux.rs

Lines changed: 3 additions & 270 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@ use std::{
66
time::Duration,
77
};
88

9-
use LidoCSMRegistry::getNodeOperatorSummaryReturn;
109
use alloy::{
11-
primitives::{Address, Bytes, U256, address},
10+
primitives::{Address, Bytes, U256},
1211
providers::ProviderBuilder,
1312
rpc::{client::RpcClient, types::beacon::constants::BLS_PUBLIC_KEY_BYTES_LEN},
14-
sol,
1513
transports::http::Http,
1614
};
1715
use eyre::{Context, bail, ensure};
@@ -23,9 +21,9 @@ use url::Url;
2321
use super::{MUX_PATH_ENV, PbsConfig, RelayConfig, load_optional_env_var};
2422
use crate::{
2523
config::{remove_duplicate_keys, safe_read_http_response},
26-
interop::ssv::utils::fetch_ssv_pubkeys_from_url,
24+
interop::{lido::utils::*, ssv::utils::*},
2725
pbs::RelayClient,
28-
types::{BlsPublicKey, Chain, HoleskyLidoModule, HoodiLidoModule, MainnetLidoModule},
26+
types::{BlsPublicKey, Chain},
2927
utils::default_bool,
3028
};
3129

@@ -291,194 +289,6 @@ fn get_mux_path(mux_id: &str) -> String {
291289
format!("/{mux_id}-mux_keys.json")
292290
}
293291

294-
sol! {
295-
#[allow(missing_docs)]
296-
#[sol(rpc)]
297-
LidoRegistry,
298-
"src/abi/LidoNORegistry.json"
299-
}
300-
301-
sol! {
302-
#[allow(missing_docs)]
303-
#[sol(rpc)]
304-
LidoCSMRegistry,
305-
"src/abi/LidoCSModuleNORegistry.json"
306-
}
307-
308-
fn lido_registry_addresses_by_module() -> HashMap<Chain, HashMap<u8, Address>> {
309-
let mut map: HashMap<Chain, HashMap<u8, Address>> = HashMap::new();
310-
311-
// --- Mainnet ---
312-
let mut mainnet = HashMap::new();
313-
mainnet.insert(
314-
MainnetLidoModule::Curated as u8,
315-
address!("55032650b14df07b85bF18A3a3eC8E0Af2e028d5"),
316-
);
317-
mainnet.insert(
318-
MainnetLidoModule::SimpleDVT as u8,
319-
address!("aE7B191A31f627b4eB1d4DaC64eaB9976995b433"),
320-
);
321-
mainnet.insert(
322-
MainnetLidoModule::CommunityStaking as u8,
323-
address!("dA7dE2ECdDfccC6c3AF10108Db212ACBBf9EA83F"),
324-
);
325-
map.insert(Chain::Mainnet, mainnet);
326-
327-
// --- Holesky ---
328-
let mut holesky = HashMap::new();
329-
holesky.insert(
330-
HoleskyLidoModule::Curated as u8,
331-
address!("595F64Ddc3856a3b5Ff4f4CC1d1fb4B46cFd2bAC"),
332-
);
333-
holesky.insert(
334-
HoleskyLidoModule::SimpleDVT as u8,
335-
address!("11a93807078f8BB880c1BD0ee4C387537de4b4b6"),
336-
);
337-
holesky.insert(
338-
HoleskyLidoModule::Sandbox as u8,
339-
address!("D6C2ce3BB8bea2832496Ac8b5144819719f343AC"),
340-
);
341-
holesky.insert(
342-
HoleskyLidoModule::CommunityStaking as u8,
343-
address!("4562c3e63c2e586cD1651B958C22F88135aCAd4f"),
344-
);
345-
map.insert(Chain::Holesky, holesky);
346-
347-
// --- Hoodi ---
348-
let mut hoodi = HashMap::new();
349-
hoodi.insert(
350-
HoodiLidoModule::Curated as u8,
351-
address!("5cDbE1590c083b5A2A64427fAA63A7cfDB91FbB5"),
352-
);
353-
hoodi.insert(
354-
HoodiLidoModule::SimpleDVT as u8,
355-
address!("0B5236BECA68004DB89434462DfC3BB074d2c830"),
356-
);
357-
hoodi.insert(
358-
HoodiLidoModule::Sandbox as u8,
359-
address!("682E94d2630846a503BDeE8b6810DF71C9806891"),
360-
);
361-
hoodi.insert(
362-
HoodiLidoModule::CommunityStaking as u8,
363-
address!("79CEf36D84743222f37765204Bec41E92a93E59d"),
364-
);
365-
map.insert(Chain::Hoodi, hoodi);
366-
367-
// --- Sepolia --
368-
let mut sepolia = HashMap::new();
369-
sepolia.insert(1, address!("33d6E15047E8644F8DDf5CD05d202dfE587DA6E3"));
370-
map.insert(Chain::Sepolia, sepolia);
371-
372-
map
373-
}
374-
375-
// Fetching appropiate registry address
376-
fn lido_registry_address(chain: Chain, lido_module_id: u8) -> eyre::Result<Address> {
377-
lido_registry_addresses_by_module()
378-
.get(&chain)
379-
.ok_or_else(|| eyre::eyre!("Lido registry not supported for chain: {chain:?}"))?
380-
.get(&lido_module_id)
381-
.copied()
382-
.ok_or_else(|| {
383-
eyre::eyre!("Lido module id {:?} not found for chain: {chain:?}", lido_module_id)
384-
})
385-
}
386-
387-
fn is_csm_module(chain: Chain, module_id: u8) -> bool {
388-
match chain {
389-
Chain::Mainnet => module_id == MainnetLidoModule::CommunityStaking as u8,
390-
Chain::Holesky => module_id == HoleskyLidoModule::CommunityStaking as u8,
391-
Chain::Hoodi => module_id == HoodiLidoModule::CommunityStaking as u8,
392-
_ => false,
393-
}
394-
}
395-
396-
fn get_lido_csm_registry<P>(
397-
registry_address: Address,
398-
provider: P,
399-
) -> LidoCSMRegistry::LidoCSMRegistryInstance<P>
400-
where
401-
P: Clone + Send + Sync + 'static + alloy::providers::Provider,
402-
{
403-
LidoCSMRegistry::new(registry_address, provider)
404-
}
405-
406-
fn get_lido_module_registry<P>(
407-
registry_address: Address,
408-
provider: P,
409-
) -> LidoRegistry::LidoRegistryInstance<P>
410-
where
411-
P: Clone + Send + Sync + 'static + alloy::providers::Provider,
412-
{
413-
LidoRegistry::new(registry_address, provider)
414-
}
415-
416-
async fn fetch_lido_csm_keys_total<P>(
417-
registry: &LidoCSMRegistry::LidoCSMRegistryInstance<P>,
418-
node_operator_id: U256,
419-
) -> eyre::Result<u64>
420-
where
421-
P: Clone + Send + Sync + 'static + alloy::providers::Provider,
422-
{
423-
let summary: getNodeOperatorSummaryReturn =
424-
registry.getNodeOperatorSummary(node_operator_id).call().await?;
425-
426-
let total_u256 = summary.totalDepositedValidators + summary.depositableValidatorsCount;
427-
428-
let total_u64 = u64::try_from(total_u256)
429-
.wrap_err_with(|| format!("total keys ({total_u256}) does not fit into u64"))?;
430-
431-
Ok(total_u64)
432-
}
433-
434-
async fn fetch_lido_module_keys_total<P>(
435-
registry: &LidoRegistry::LidoRegistryInstance<P>,
436-
node_operator_id: U256,
437-
) -> eyre::Result<u64>
438-
where
439-
P: Clone + Send + Sync + 'static + alloy::providers::Provider,
440-
{
441-
let total_keys: u64 =
442-
registry.getTotalSigningKeyCount(node_operator_id).call().await?.try_into()?;
443-
444-
Ok(total_keys)
445-
}
446-
447-
async fn fetch_lido_csm_keys_batch<P>(
448-
registry: &LidoCSMRegistry::LidoCSMRegistryInstance<P>,
449-
node_operator_id: U256,
450-
offset: u64,
451-
limit: u64,
452-
) -> eyre::Result<Bytes>
453-
where
454-
P: Clone + Send + Sync + 'static + alloy::providers::Provider,
455-
{
456-
let pubkeys = registry
457-
.getSigningKeys(node_operator_id, U256::from(offset), U256::from(limit))
458-
.call()
459-
.await?;
460-
461-
Ok(pubkeys)
462-
}
463-
464-
async fn fetch_lido_module_keys_batch<P>(
465-
registry: &LidoRegistry::LidoRegistryInstance<P>,
466-
node_operator_id: U256,
467-
offset: u64,
468-
limit: u64,
469-
) -> eyre::Result<Bytes>
470-
where
471-
P: Clone + Send + Sync + 'static + alloy::providers::Provider,
472-
{
473-
let pubkeys = registry
474-
.getSigningKeys(node_operator_id, U256::from(offset), U256::from(limit))
475-
.call()
476-
.await?
477-
.pubkeys;
478-
479-
Ok(pubkeys)
480-
}
481-
482292
async fn collect_registry_keys<F, Fut>(
483293
total_keys: u64,
484294
mut fetch_batch: F,
@@ -634,80 +444,3 @@ async fn fetch_ssv_pubkeys(
634444

635445
Ok(pubkeys)
636446
}
637-
638-
#[cfg(test)]
639-
mod tests {
640-
use alloy::{primitives::U256, providers::ProviderBuilder};
641-
use url::Url;
642-
643-
use super::*;
644-
645-
#[tokio::test]
646-
async fn test_lido_registry_address() -> eyre::Result<()> {
647-
let url = Url::parse("https://ethereum-rpc.publicnode.com")?;
648-
let provider = ProviderBuilder::new().connect_http(url);
649-
650-
let registry =
651-
LidoRegistry::new(address!("55032650b14df07b85bF18A3a3eC8E0Af2e028d5"), provider);
652-
653-
const LIMIT: usize = 3;
654-
let node_operator_id = U256::from(1);
655-
656-
let total_keys: u64 =
657-
registry.getTotalSigningKeyCount(node_operator_id).call().await?.try_into()?;
658-
659-
assert!(total_keys > LIMIT as u64);
660-
661-
let pubkeys = registry
662-
.getSigningKeys(node_operator_id, U256::ZERO, U256::from(LIMIT))
663-
.call()
664-
.await?
665-
.pubkeys;
666-
667-
let mut vec = vec![];
668-
for chunk in pubkeys.chunks(BLS_PUBLIC_KEY_BYTES_LEN) {
669-
vec.push(
670-
BlsPublicKey::deserialize(chunk)
671-
.map_err(|_| eyre::eyre!("invalid BLS public key"))?,
672-
);
673-
}
674-
675-
assert_eq!(vec.len(), LIMIT);
676-
677-
Ok(())
678-
}
679-
680-
#[tokio::test]
681-
async fn test_lido_csm_registry_address() -> eyre::Result<()> {
682-
let url = Url::parse("https://ethereum-rpc.publicnode.com")?;
683-
let provider = ProviderBuilder::new().connect_http(url);
684-
685-
let registry =
686-
LidoCSMRegistry::new(address!("dA7dE2ECdDfccC6c3AF10108Db212ACBBf9EA83F"), provider);
687-
688-
const LIMIT: usize = 3;
689-
let node_operator_id = U256::from(1);
690-
691-
let summary = registry.getNodeOperatorSummary(node_operator_id).call().await?;
692-
693-
let total_keys_u256 = summary.totalDepositedValidators + summary.depositableValidatorsCount;
694-
let total_keys: u64 = total_keys_u256.try_into()?;
695-
696-
assert!(total_keys > LIMIT as u64, "expected more than {LIMIT} keys, got {total_keys}");
697-
698-
let pubkeys =
699-
registry.getSigningKeys(node_operator_id, U256::ZERO, U256::from(LIMIT)).call().await?;
700-
701-
let mut vec = Vec::new();
702-
for chunk in pubkeys.chunks(BLS_PUBLIC_KEY_BYTES_LEN) {
703-
vec.push(
704-
BlsPublicKey::deserialize(chunk)
705-
.map_err(|_| eyre::eyre!("invalid BLS public key"))?,
706-
);
707-
}
708-
709-
assert_eq!(vec.len(), LIMIT, "expected {LIMIT} keys, got {}", vec.len());
710-
711-
Ok(())
712-
}
713-
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pub mod types;
2+
pub mod utils;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
use alloy::sol;
2+
3+
sol! {
4+
#[allow(missing_docs)]
5+
#[sol(rpc)]
6+
LidoRegistry,
7+
"src/abi/LidoNORegistry.json"
8+
}
9+
10+
sol! {
11+
#[allow(missing_docs)]
12+
#[sol(rpc)]
13+
LidoCSMRegistry,
14+
"src/abi/LidoCSModuleNORegistry.json"
15+
}

0 commit comments

Comments
 (0)