Skip to content

Commit

Permalink
Merge branch 'unstable' into stable
Browse files Browse the repository at this point in the history
  • Loading branch information
magick93 authored Dec 16, 2024
2 parents 502e5d5 + 4182bf6 commit f35765e
Show file tree
Hide file tree
Showing 8 changed files with 300 additions and 132 deletions.
257 changes: 125 additions & 132 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ members = [
"anchor/network",
"anchor/processor",
"anchor/qbft",
"anchor/common/ssv_types",
]
resolver = "2"

Expand All @@ -23,13 +24,15 @@ http_metrics = { path = "anchor/http_metrics" }
network = { path ="anchor/network"}
version = { path ="anchor/common/version"}
processor = { path = "anchor/processor" }
ssv_types = { path = "anchor/common/ssv_types" }
lighthouse_network = { git = "https://github.com/sigp/lighthouse", branch = "unstable"}
task_executor = { git = "https://github.com/sigp/lighthouse", branch = "unstable", default-features = false, features = [ "tracing", ] }
metrics = { git = "https://github.com/agemanning/lighthouse", branch = "modularize-vc" }
validator_metrics = { git = "https://github.com/agemanning/lighthouse", branch = "modularize-vc" }
sensitive_url = { git = "https://github.com/agemanning/lighthouse", branch = "modularize-vc" }
slot_clock = { git = "https://github.com/agemanning/lighthouse", branch = "modularize-vc" }
unused_port = { git = "https://github.com/sigp/lighthouse", branch = "unstable" }
types = { git = "https://github.com/sigp/lighthouse", branch = "unstable" }
derive_more = { version = "1.0.0", features = ["full"] }
async-channel = "1.9"
axum = "0.7.7"
Expand All @@ -53,6 +56,8 @@ tokio = { version = "1.39.2", features = [
] }
tracing = "0.1.40"
tracing-subscriber = { version = "0.3.18", features = ["fmt", "env-filter"] }
base64 = "0.22.1"
openssl = "0.10.68"

[profile.maxperf]
inherits = "release"
Expand Down
11 changes: 11 additions & 0 deletions anchor/common/ssv_types/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "ssv_types"
version = "0.1.0"
edition = { workspace = true }
authors = ["Sigma Prime <[email protected]>"]

[dependencies]
types = { workspace = true}
openssl = { workspace = true }
derive_more = { workspace = true }
base64 = { workspace = true }
53 changes: 53 additions & 0 deletions anchor/common/ssv_types/src/cluster.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use crate::OperatorId;
use crate::Share;
use derive_more::{Deref, From};
use types::{Address, Graffiti, PublicKey};

/// Unique identifier for a cluster
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash, From, Deref)]
pub struct ClusterId(pub u64);

/// A Cluster is a group of Operators that are acting on behalf of a Validator
#[derive(Debug, Clone)]
pub struct Cluster {
/// Unique identifier for a Cluster
pub cluster_id: ClusterId,
/// All of the members of this Cluster
pub cluster_members: Vec<ClusterMember>,
/// The number of faulty operator in the Cluster
pub faulty: u64,
/// If the Cluster is liquidated or active
pub liquidated: bool,
/// Metadata about the validator this committee represents
pub validator_metadata: ValidatorMetadata,
}

/// A member of a Cluster. This is just an Operator that holds onto a share of the Validator key
#[derive(Debug, Clone)]
pub struct ClusterMember {
/// Unique identifier for the Operator this member represents
pub operator_id: OperatorId,
/// Unique identifier for the Cluster this member is a part of
pub cluster_id: ClusterId,
/// The Share this member is responsible for
pub share: Share,
}

/// Index of the validator in the validator registry.
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash, From, Deref)]
pub struct ValidatorIndex(pub usize);

/// General Metadata about a Validator
#[derive(Debug, Clone)]
pub struct ValidatorMetadata {
/// Index of the validator
pub validator_index: ValidatorIndex,
/// Public key of the validator
pub validator_pubkey: PublicKey,
/// Eth1 fee address
pub fee_recipient: Address,
/// Graffiti
pub graffiti: Graffiti,
/// The owner of the validator
pub owner: Address,
}
7 changes: 7 additions & 0 deletions anchor/common/ssv_types/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pub use cluster::{Cluster, ClusterId, ClusterMember, ValidatorIndex, ValidatorMetadata};
pub use operator::{Operator, OperatorId};
pub use share::Share;
mod cluster;
mod operator;
mod share;
mod util;
60 changes: 60 additions & 0 deletions anchor/common/ssv_types/src/operator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use crate::util::parse_rsa;
use derive_more::{Deref, From};
use openssl::pkey::Public;
use openssl::rsa::Rsa;
use std::cmp::Eq;
use std::fmt::Debug;
use std::hash::Hash;
use types::Address;

/// Unique identifier for an Operator.
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash, From, Deref)]
pub struct OperatorId(pub u64);

/// Client responsible for maintaining the overall health of the network.
#[derive(Debug, Clone)]
pub struct Operator {
/// ID to uniquely identify this operator
pub id: OperatorId,
/// Base-64 encoded PEM RSA public key
pub rsa_pubkey: Rsa<Public>,
/// Owner of the operator
pub owner: Address,
}

impl Operator {
/// Creates a new operator from its OperatorId and PEM-encoded public key string
pub fn new(pem_data: &str, operator_id: OperatorId, owner: Address) -> Result<Self, String> {
let rsa_pubkey = parse_rsa(pem_data)?;
Ok(Self::new_with_pubkey(rsa_pubkey, operator_id, owner))
}

// Creates a new operator from an existing RSA public key and OperatorId
pub fn new_with_pubkey(rsa_pubkey: Rsa<Public>, id: OperatorId, owner: Address) -> Self {
Self {
id,
rsa_pubkey,
owner,
}
}
}

#[cfg(test)]
mod operator_tests {
use super::*;

#[test]
fn operator_from_pubkey_and_id() {
// Random valid operator public key and id: https://explorer.ssv.network/operators/1141
let pem_data = "LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBbFFmQVIzMEd4bFpacEwrNDByU0IKTEpSYlkwY2laZDBVMXhtTlp1bFB0NzZKQXJ5d2lia0Y4SFlQV2xkM3dERVdWZXZjRzRGVVBSZ0hDM1MrTHNuMwpVVC9TS280eE9nNFlnZ0xqbVVXQysyU3ZGRFhXYVFvdFRXYW5UU0drSEllNGFnTVNEYlUzOWhSMWdOSTJhY2NNCkVCcjU2eXpWcFMvKytkSk5xU002S1FQM3RnTU5ia2IvbEtlY0piTXM0ZWNRMTNkWUQwY3dFNFQxcEdTYUdhcEkKbFNaZ2lYd0cwSGFNTm5GUkt0OFlkZjNHaTFMRlh3Zlo5NHZFRjJMLzg3RCtidjdkSFVpSGRjRnh0Vm0rVjVvawo3VFptcnpVdXB2NWhKZ3lDVE9zc0xHOW1QSGNORnhEVDJ4NUJKZ2FFOVpJYnMrWVZ5a1k3UTE4VEhRS2lWcDFaCmp3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K";
let operator_id = 1141;
let address = Address::random();

let operator = Operator::new(pem_data, operator_id.into(), address);
assert!(operator.is_ok());

if let Ok(op) = operator {
assert_eq!(op.id.0, operator_id);
}
}
}
10 changes: 10 additions & 0 deletions anchor/common/ssv_types/src/share.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use types::PublicKey;

/// One of N shares of a split validator key.
#[derive(Debug, Clone)]
pub struct Share {
/// The public key of this Share
pub share_pubkey: PublicKey,
/// The encrypted private key of the share
pub encrypted_private_key: [u8; 256],
}
29 changes: 29 additions & 0 deletions anchor/common/ssv_types/src/util.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use base64::prelude::*;
use openssl::pkey::Public;
use openssl::rsa::Rsa;

// Parse from a RSA public key string into the associated RSA representation
pub fn parse_rsa(pem_data: &str) -> Result<Rsa<Public>, String> {
// First decode the base64 data
let pem_decoded = BASE64_STANDARD
.decode(pem_data)
.map_err(|e| format!("Unable to decode base64 pem data: {}", e))?;

// Convert the decoded data to a string
let mut pem_string = String::from_utf8(pem_decoded)
.map_err(|e| format!("Unable to convert decoded pem data into a string: {}", e))?;

// Fix the header - replace PKCS1 header with PKCS8 header
pem_string = pem_string
.replace(
"-----BEGIN RSA PUBLIC KEY-----",
"-----BEGIN PUBLIC KEY-----",
)
.replace("-----END RSA PUBLIC KEY-----", "-----END PUBLIC KEY-----");

// Parse the PEM string into an RSA public key using PKCS8 format
let rsa_pubkey = Rsa::public_key_from_pem(pem_string.as_bytes())
.map_err(|e| format!("Failed to parse RSA public key: {}", e))?;

Ok(rsa_pubkey)
}

0 comments on commit f35765e

Please sign in to comment.