Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
244 changes: 244 additions & 0 deletions crates/common/src/abi/StaderRegistry.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
[
{
"constant": true,
"inputs": [
{
"name": "_operatorId",
"type": "uint256"
}
],
"name": "operatorStructById",
"outputs": [
{
"name": "active",
"type": "bool"
},
{
"name": "optedForSocializingPool",
"type": "bool"
},
{
"name": "operatorName",
"type": "string"
},
{
"name": "operatorRewardAddress",
"type": "address"
},
{
"name": "operatorAddress",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_operator",
"type": "address"
}
],
"name": "operatorIDByAddress",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_operatorId",
"type": "uint256"
}
],
"name": "getOperatorTotalKeys",
"outputs": [
{
"name": "_totalKeys",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_operator",
"type": "address"
},
{
"name": "_pageNumber",
"type": "uint256"
},
{
"name": "_pageSize",
"type": "uint256"
}
],
"name": "getValidatorsByOperator",
"outputs": [
{
"name": "",
"type": "tuple[]",
"components": [
{
"name": "status",
"type": "uint8"
},
{
"name": "pubkey",
"type": "bytes"
},
{
"name": "preDepositSignature",
"type": "bytes"
},
{
"name": "depositSignature",
"type": "bytes"
},
{
"name": "withdrawVaultAddress",
"type": "address"
},
{
"name": "operatorId",
"type": "uint256"
},
{
"name": "depositBlock",
"type": "uint256"
},
{
"name": "withdrawnBlock",
"type": "uint256"
}
]
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_operatorId",
"type": "uint256"
},
{
"name": "_index",
"type": "uint256"
}
],
"name": "validatorIdsByOperatorId",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_validatorId",
"type": "uint256"
}
],
"name": "validatorRegistry",
"outputs": [
{
"name": "status",
"type": "uint8"
},
{
"name": "pubkey",
"type": "bytes"
},
{
"name": "preDepositSignature",
"type": "bytes"
},
{
"name": "depositSignature",
"type": "bytes"
},
{
"name": "withdrawVaultAddress",
"type": "address"
},
{
"name": "operatorId",
"type": "uint256"
},
{
"name": "depositBlock",
"type": "uint256"
},
{
"name": "withdrawnBlock",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_operatorId",
"type": "uint256"
}
],
"name": "getOperatorRewardAddress",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_operAddr",
"type": "address"
}
],
"name": "isExistingOperator",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
}
]
109 changes: 82 additions & 27 deletions crates/common/src/config/mux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ use tracing::{debug, info, warn};
use url::Url;

use super::{MUX_PATH_ENV, PbsConfig, RelayConfig, load_optional_env_var};
use crate::types::StaderPool;
use crate::{
config::{remove_duplicate_keys, safe_read_http_response},
interop::{lido::utils::*, ssv::utils::*},
interop::{lido::utils::*, ssv::utils::*, stader::utils::*},
pbs::RelayClient,
types::{BlsPublicKey, Chain},
utils::default_bool,
Expand Down Expand Up @@ -194,6 +195,8 @@ pub enum MuxKeysLoader {
node_operator_id: u64,
#[serde(default)]
lido_module_id: Option<u8>,
#[serde(default)]
stader_pool: Option<StaderPool>,
#[serde(default = "default_bool::<false>")]
enable_refreshing: bool,
},
Expand All @@ -205,6 +208,8 @@ pub enum NORegistry {
Lido,
#[serde(alias = "ssv")]
SSV,
#[serde(alias = "stader")]
Stader,
}

impl MuxKeysLoader {
Expand Down Expand Up @@ -240,33 +245,56 @@ impl MuxKeysLoader {
.wrap_err("failed to fetch mux keys from HTTP endpoint")
}

Self::Registry { registry, node_operator_id, lido_module_id, enable_refreshing: _ } => {
match registry {
NORegistry::Lido => {
let Some(rpc_url) = rpc_url else {
bail!("Lido registry requires RPC URL to be set in the PBS config");
};

fetch_lido_registry_keys(
rpc_url,
chain,
U256::from(*node_operator_id),
lido_module_id.unwrap_or(1),
http_timeout,
)
.await
}
NORegistry::SSV => {
fetch_ssv_pubkeys(
ssv_api_url,
chain,
U256::from(*node_operator_id),
http_timeout,
)
.await
}
Self::Registry {
registry,
node_operator_id,
lido_module_id,
stader_pool,
enable_refreshing: _,
..
} => match registry {
NORegistry::Lido => {
let Some(rpc_url) = rpc_url else {
bail!("Lido registry requires RPC URL to be set in the PBS config");
};

fetch_lido_registry_keys(
rpc_url,
chain,
U256::from(*node_operator_id),
lido_module_id.unwrap_or(1),
http_timeout,
)
.await
}
}
NORegistry::SSV => {
fetch_ssv_pubkeys(
ssv_api_url,
chain,
U256::from(*node_operator_id),
http_timeout,
)
.await
}
NORegistry::Stader => {
let Some(rpc_url) = rpc_url else {
bail!("Stader registry requires RPC URL to be set in the PBS config");
};

let Some(stader_pool) = stader_pool else {
bail!("Stader registry requires `stader_pool` to be set in the mux config");
};

fetch_stader_registry_keys(
rpc_url,
chain,
stader_pool.clone(),
U256::from(*node_operator_id),
http_timeout,
)
.await
}
},
}?;

// Remove duplicates
Expand Down Expand Up @@ -390,6 +418,33 @@ async fn fetch_lido_registry_keys(
}
}

async fn fetch_stader_registry_keys(
rpc_url: Url,
chain: Chain,
stader_pool: StaderPool,
node_operator_id: U256,
http_timeout: Duration,
) -> eyre::Result<Vec<BlsPublicKey>> {
let client = Client::builder().timeout(http_timeout).build()?;
let http = Http::with_client(client, rpc_url);
let is_local = http.guess_local();
let rpc_client = RpcClient::new(http, is_local);

let registry_address = stader_registry_address(chain, stader_pool)?;

let provider = ProviderBuilder::new().connect_client(rpc_client);
let registry = get_stader_registry(registry_address, provider);

let operator_address = fetch_stader_operator_address(&registry, node_operator_id).await?;

let total_keys = fetch_stader_keys_total(&registry, node_operator_id).await?;

collect_registry_keys(total_keys, |offset, limit| {
fetch_stader_keys_batch(&registry, operator_address, offset, limit)
})
.await
}

async fn fetch_ssv_pubkeys(
mut api_url: Url,
chain: Chain,
Expand Down
1 change: 1 addition & 0 deletions crates/common/src/interop/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod lido;
pub mod ssv;
pub mod stader;
2 changes: 2 additions & 0 deletions crates/common/src/interop/stader/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod types;
pub mod utils;
Loading
Loading