eigen_types/
operator.rs

1use alloy::primitives::{aliases::U192, Address, FixedBytes, U256};
2use eigen_crypto_bls::{convert_to_g1_point, error::BlsError, BlsG1Point, BlsKeyPair};
3use eigen_utils::common::get_url_content;
4use ethers::utils::keccak256;
5use num_bigint::BigUint;
6use thiserror::Error;
7use url::Url;
8
9pub use crate::operator_metadata::OperatorMetadata;
10use crate::operator_metadata::OperatorMetadataError;
11pub use crate::operator_pubkeys::OperatorPubKeys;
12
13#[derive(Debug, Error)]
14pub enum OperatorTypesError {
15    #[error("Operator id from pub key conversion failed")]
16    OperatorIdFromPubKey(#[from] BlsError),
17    #[error("Invalid Metadata URL")]
18    InvalidMetadataUrl,
19    #[error("Metadata Not Found")]
20    MetadataNotFound,
21    #[error("Metadata Parse Error")]
22    MetadataParseError,
23    #[error("Metadata Validation Error")]
24    MetadataValidationError(#[from] OperatorMetadataError),
25    #[error("Invalid Address")]
26    InvalidAddress,
27    #[error("Invalid Delegation Approver Address")]
28    InvalidDelegationApproverAddress,
29}
30
31const MAX_NUMBER_OF_QUORUMS: u8 = 192;
32
33pub type OperatorId = FixedBytes<32>;
34
35pub fn bitmap_to_quorum_ids(quorum_bitmaps: U256) -> Vec<u8> {
36    let bytes = quorum_bitmaps.to_be_bytes::<32>();
37
38    let mut quorum_ids: Vec<u8> = Vec::with_capacity(usize::from(MAX_NUMBER_OF_QUORUMS));
39
40    for i in 0..MAX_NUMBER_OF_QUORUMS {
41        let bitmap = BigUint::from_bytes_be(&bytes);
42        if bitmap.bit(u64::from(i)) {
43            quorum_ids.push(i);
44        }
45    }
46    quorum_ids
47}
48
49pub fn bitmap_to_quorum_ids_from_u192(quorum_bitmaps: U192) -> Vec<u8> {
50    let bytes = quorum_bitmaps.to_be_bytes::<24>();
51
52    let mut quorum_ids: Vec<u8> = Vec::with_capacity(usize::from(MAX_NUMBER_OF_QUORUMS));
53
54    for i in 0..MAX_NUMBER_OF_QUORUMS {
55        let bitmap = BigUint::from_bytes_be(&bytes);
56        if bitmap.bit(u64::from(i)) {
57            quorum_ids.push(i);
58        }
59    }
60    quorum_ids
61}
62
63/// Operator represents EigenLayer's view of an operator
64pub struct Operator {
65    /// Operator Address
66    pub address: Address,
67
68    /// https://github.com/Layr-Labs/eigenlayer-contracts/blob/delegation-redesign/src/contracts/interfaces/IDelegationManager.sol#L18
69    pub delegation_approver_address: Address,
70
71    /// MetadataUrl URL where operator metadata is stored
72    pub metadata_url: String,
73
74    /// `allocation_delay` is the delay in seconds where an operator is allowed to change allocation
75    /// This can only be set once by the operator. Once set this can't be changed
76    pub allocation_delay: Option<u32>,
77
78    pub _deprecated_earnings_receiver_address: Option<Address>,
79
80    pub staker_opt_out_window_blocks: Option<u32>,
81}
82
83impl Operator {
84    pub fn new(
85        address: &str,
86        delegation_approver_address: &str,
87        metadata_url: String,
88        allocation_delay: Option<u32>,
89        _deprecated_earnings_receiver_address: Option<Address>,
90        staker_opt_out_window_blocks: Option<u32>,
91    ) -> Result<Self, OperatorTypesError> {
92        let address = Address::try_from(address.as_bytes())
93            .map_err(|_| OperatorTypesError::InvalidAddress)?;
94        let delegation_approver_address = Address::try_from(delegation_approver_address.as_bytes())
95            .map_err(|_| OperatorTypesError::InvalidDelegationApproverAddress)?;
96
97        Ok(Self {
98            address,
99            delegation_approver_address,
100            metadata_url,
101            allocation_delay,
102            _deprecated_earnings_receiver_address,
103            staker_opt_out_window_blocks,
104        })
105    }
106
107    pub async fn validate(&self) -> Result<(), OperatorTypesError> {
108        // Check for valid URL in metadata_url
109        Url::parse(&self.metadata_url).map_err(|_| OperatorTypesError::InvalidMetadataUrl)?;
110
111        // Check if metadata is valid
112        let body = get_url_content(&self.metadata_url)
113            .await
114            .map_err(|_| OperatorTypesError::MetadataNotFound)?;
115
116        let operator_metadata: OperatorMetadata =
117            serde_json::from_str(&body).map_err(|_| OperatorTypesError::MetadataParseError)?;
118
119        operator_metadata
120            .validate()
121            .await
122            .map_err(OperatorTypesError::MetadataValidationError)
123    }
124
125    pub fn operator_id_from_key_pair(
126        keypair: BlsKeyPair,
127    ) -> Result<OperatorId, OperatorTypesError> {
128        operator_id_from_g1_pub_key(keypair.public_key())
129    }
130}
131
132pub type Socket = String;
133
134pub type QuorumNum = u8;
135
136#[derive(Clone, Debug, PartialEq, Eq)]
137pub struct OperatorInfo {
138    pub pub_keys: Option<OperatorPubKeys>,
139}
140
141pub fn operator_id_from_g1_pub_key(pub_key: BlsG1Point) -> Result<OperatorId, OperatorTypesError> {
142    let x: [u8; 32] = convert_to_g1_point(pub_key.g1())?.X.to_be_bytes();
143    let y: [u8; 32] = convert_to_g1_point(pub_key.g1())?.Y.to_be_bytes();
144    let mut bytes = [0_u8; 64];
145    bytes[..32].copy_from_slice(&x);
146    bytes[32..].copy_from_slice(&y);
147    Ok(keccak256(bytes).into())
148}
149
150pub type QuorumThresholdPercentage = u8;
151
152pub type QuorumThresholdPercentages = Vec<QuorumThresholdPercentage>;