Skip to main content

eigen_types/
operator.rs

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