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"
}
]
116 changes: 86 additions & 30 deletions crates/common/src/config/mux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ use url::Url;

use super::{MUX_PATH_ENV, MUXER_HTTP_MAX_LENGTH, PbsConfig, RelayConfig, load_optional_env_var};
use crate::{
config::remove_duplicate_keys,
interop::{lido::utils::*, ssv::utils::*},
config::{remove_duplicate_keys, safe_read_http_response},
interop::{lido::utils::*, ssv::utils::*, stader::utils::*},
pbs::RelayClient,
types::{BlsPublicKey, Chain},
types::{BlsPublicKey, Chain, StaderPool},
utils::default_bool,
wire::safe_read_http_response,
};
Expand Down Expand Up @@ -196,6 +196,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 @@ -207,6 +209,8 @@ pub enum NORegistry {
Lido,
#[serde(alias = "ssv")]
SSV,
#[serde(alias = "stader")]
Stader,
}

impl MuxKeysLoader {
Expand Down Expand Up @@ -244,34 +248,57 @@ 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_node_api_url,
ssv_public_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_node_api_url,
ssv_public_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 @@ -395,6 +422,35 @@ 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>> {
debug!(?chain, %node_operator_id, ?stader_pool, "loading operator keys from Stader registry");

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(
node_url: Url,
public_url: Url,
Expand Down
Loading
Loading