use alloy::primitives::{aliases::U192, keccak256, Address, FixedBytes, U256};
use eigen_crypto_bls::{convert_to_g1_point, error::BlsError, BlsG1Point, BlsKeyPair};
use eigen_utils::common::get_url_content;
use num_bigint::BigUint;
use thiserror::Error;
use url::Url;
pub use crate::operator_metadata::OperatorMetadata;
use crate::operator_metadata::OperatorMetadataError;
pub use crate::operator_pubkeys::OperatorPubKeys;
#[derive(Debug, Error)]
pub enum OperatorTypesError {
#[error("Operator id from pub key conversion failed")]
OperatorIdFromPubKey(#[from] BlsError),
#[error("Invalid Metadata URL")]
InvalidMetadataUrl,
#[error("Metadata Not Found")]
MetadataNotFound,
#[error("Metadata Parse Error")]
MetadataParseError,
#[error("Metadata Validation Error")]
MetadataValidationError(#[from] OperatorMetadataError),
#[error("Invalid Address")]
InvalidAddress,
#[error("Invalid Delegation Approver Address")]
InvalidDelegationApproverAddress,
}
const MAX_NUMBER_OF_QUORUMS: u8 = 192;
pub type OperatorId = FixedBytes<32>;
pub fn bitmap_to_quorum_ids(quorum_bitmaps: U256) -> Vec<u8> {
let bytes = quorum_bitmaps.to_be_bytes::<32>();
let mut quorum_ids: Vec<u8> = Vec::with_capacity(usize::from(MAX_NUMBER_OF_QUORUMS));
for i in 0..MAX_NUMBER_OF_QUORUMS {
let bitmap = BigUint::from_bytes_be(&bytes);
if bitmap.bit(u64::from(i)) {
quorum_ids.push(i);
}
}
quorum_ids
}
pub fn bitmap_to_quorum_ids_from_u192(quorum_bitmaps: U192) -> Vec<u8> {
let bytes = quorum_bitmaps.to_be_bytes::<24>();
let mut quorum_ids: Vec<u8> = Vec::with_capacity(usize::from(MAX_NUMBER_OF_QUORUMS));
for i in 0..MAX_NUMBER_OF_QUORUMS {
let bitmap = BigUint::from_bytes_be(&bytes);
if bitmap.bit(u64::from(i)) {
quorum_ids.push(i);
}
}
quorum_ids
}
pub struct Operator {
pub address: Address,
pub delegation_approver_address: Address,
pub metadata_url: String,
pub allocation_delay: Option<u32>,
pub _deprecated_earnings_receiver_address: Option<Address>,
pub staker_opt_out_window_blocks: Option<u32>,
}
impl Operator {
pub fn new(
address: &str,
delegation_approver_address: &str,
metadata_url: String,
allocation_delay: Option<u32>,
_deprecated_earnings_receiver_address: Option<Address>,
staker_opt_out_window_blocks: Option<u32>,
) -> Result<Self, OperatorTypesError> {
let address = Address::try_from(address.as_bytes())
.map_err(|_| OperatorTypesError::InvalidAddress)?;
let delegation_approver_address = Address::try_from(delegation_approver_address.as_bytes())
.map_err(|_| OperatorTypesError::InvalidDelegationApproverAddress)?;
Ok(Self {
address,
delegation_approver_address,
metadata_url,
allocation_delay,
_deprecated_earnings_receiver_address,
staker_opt_out_window_blocks,
})
}
pub async fn validate(&self) -> Result<(), OperatorTypesError> {
Url::parse(&self.metadata_url).map_err(|_| OperatorTypesError::InvalidMetadataUrl)?;
let body = get_url_content(&self.metadata_url)
.await
.map_err(|_| OperatorTypesError::MetadataNotFound)?;
let operator_metadata: OperatorMetadata =
serde_json::from_str(&body).map_err(|_| OperatorTypesError::MetadataParseError)?;
operator_metadata
.validate()
.await
.map_err(OperatorTypesError::MetadataValidationError)
}
pub fn operator_id_from_key_pair(
keypair: BlsKeyPair,
) -> Result<OperatorId, OperatorTypesError> {
operator_id_from_g1_pub_key(keypair.public_key())
}
}
pub type Socket = String;
pub type QuorumNum = u8;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct OperatorInfo {
pub pub_keys: Option<OperatorPubKeys>,
pub socket: Option<Socket>,
}
pub fn operator_id_from_g1_pub_key(pub_key: BlsG1Point) -> Result<OperatorId, OperatorTypesError> {
let x: [u8; 32] = convert_to_g1_point(pub_key.g1())?.X.to_be_bytes();
let y: [u8; 32] = convert_to_g1_point(pub_key.g1())?.Y.to_be_bytes();
let mut bytes = [0_u8; 64];
bytes[..32].copy_from_slice(&x);
bytes[32..].copy_from_slice(&y);
Ok(keccak256(bytes))
}
pub type QuorumThresholdPercentage = u8;
pub type QuorumThresholdPercentages = Vec<QuorumThresholdPercentage>;