-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
316 additions
and
164 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,65 @@ | ||
use crate::{Operator, OperatorID, OperatorPublicKey}; | ||
use crate::util::parse_rsa; | ||
use crate::{Operator, OperatorId}; | ||
use derive_more::{Deref, From}; | ||
use rsa::RsaPublicKey; | ||
use std::cmp::Eq; | ||
use std::fmt::Debug; | ||
use std::hash::Hash; | ||
use types::Domain; | ||
|
||
/// Unique identifier for a committee. | ||
pub type CommitteeID = u64; | ||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash, From, Deref)] | ||
pub struct CommitteeId(u64); | ||
|
||
/// Member of a SSV Committee. A `CommitteeMember` is just an operator that is part of the committee | ||
/// Member of a SSV Committee. A CommitteeMember is just an operator that is part of the committee | ||
/// a validator has chosen to distribute its keyshares to. | ||
#[derive(Debug, Clone)] | ||
pub struct CommitteeMember { | ||
// Unique identifier for the operator | ||
pub operator_id: OperatorID, | ||
// Unique identifier for the committee this member is a part of | ||
pub committee_id: CommitteeID, | ||
// Base-64 encoded PEM RSA public key of the operator | ||
pub share_public_key: OperatorPublicKey, | ||
// Number of nodes that are faulty/malicious in the committee | ||
/// Unique identifier for the operator | ||
pub operator_id: OperatorId, | ||
/// Unique identifier for the committee this member is a part of | ||
pub committee_id: CommitteeId, | ||
/// Base-64 encoded PEM RSA public key of the operator | ||
pub operator_public_key: RsaPublicKey, | ||
/// Number of nodes that are faulty/malicious in the committee | ||
pub faulty: u64, | ||
// All of the operators that are a part of this committee | ||
/// All of the operators that are a part of this committee | ||
pub members: Vec<Operator>, | ||
// Signature domain | ||
/// Signature domain | ||
pub domain: Domain, | ||
} | ||
|
||
impl CommitteeMember { | ||
/// Creates a new committee member from a PEM-encoded public key string | ||
pub fn new( | ||
pem_data: &str, | ||
operator_id: OperatorId, | ||
committee_id: CommitteeId, | ||
domain: Domain, | ||
) -> Result<Self, String> { | ||
let rsa_pubkey = parse_rsa(pem_data)?; | ||
Ok(Self::new_with_pubkey( | ||
rsa_pubkey, | ||
operator_id, | ||
committee_id, | ||
domain, | ||
)) | ||
} | ||
|
||
/// Creates a new committee member from an existing RSA public key | ||
pub fn new_with_pubkey( | ||
rsa_pubkey: RsaPublicKey, | ||
operator_id: OperatorId, | ||
committee_id: CommitteeId, | ||
domain: Domain, | ||
) -> Self { | ||
Self { | ||
operator_id, | ||
committee_id, | ||
operator_public_key: rsa_pubkey, | ||
faulty: 0, | ||
members: Vec::new(), | ||
domain, | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
pub use committee::{CommitteeID, CommitteeMember}; | ||
pub use operator::{Operator, OperatorID, OperatorPublicKey}; | ||
pub use committee::{CommitteeId, CommitteeMember}; | ||
pub use operator::{Operator, OperatorId}; | ||
pub use share::SSVShare; | ||
mod committee; | ||
mod operator; | ||
mod share; | ||
mod util; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,54 @@ | ||
/// Unique identifier for an Operator | ||
pub type OperatorID = u64; | ||
use crate::util::parse_rsa; | ||
use derive_more::{Deref, From}; | ||
use rsa::RsaPublicKey; | ||
use std::cmp::Eq; | ||
use std::fmt::Debug; | ||
use std::hash::Hash; | ||
|
||
/// Operator RSA public key | ||
pub type OperatorPublicKey = [u8; 459]; | ||
/// Unique identifier for an Operator. | ||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash, From, Deref)] | ||
pub struct OperatorId(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 public_key: OperatorPublicKey, | ||
/// ID to uniquely identify this operator | ||
pub id: OperatorId, | ||
/// Base-64 encoded PEM RSA public key | ||
pub public_key: RsaPublicKey, | ||
} | ||
|
||
impl Operator { | ||
/// Creates a new operator from its OperatorId and PEM-encoded public key string | ||
pub fn new(pem_data: &str, operator_id: OperatorId) -> Result<Self, String> { | ||
let rsa_pubkey = parse_rsa(pem_data)?; | ||
Ok(Self::new_with_pubkey(rsa_pubkey, operator_id)) | ||
} | ||
|
||
// Creates a new operator from an existing RSA public key and OperatorId | ||
pub fn new_with_pubkey(rsa_pubkey: RsaPublicKey, operator_id: OperatorId) -> Self { | ||
Self { | ||
id: operator_id, | ||
public_key: rsa_pubkey, | ||
} | ||
} | ||
} | ||
|
||
#[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 operator = Operator::new(pem_data, operator_id.into()); | ||
assert!(operator.is_ok()); | ||
|
||
if let Ok(op) = operator { | ||
assert_eq!(op.id.0, operator_id); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
use base64::prelude::*; | ||
use rsa::pkcs8::DecodePublicKey; | ||
use rsa::RsaPublicKey; | ||
|
||
// Parse from a RSA public key string into the associated RSA representation | ||
pub fn parse_rsa(pem_data: &str) -> Result<RsaPublicKey, 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 = RsaPublicKey::from_public_key_pem(&pem_string) | ||
.map_err(|e| format!("Failed to parse RSA public key: {}", e))?; | ||
|
||
Ok(rsa_pubkey) | ||
} |