Skip to content

Commit

Permalink
validator tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Zacholme7 committed Dec 11, 2024
1 parent 05650ab commit 6a39998
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 15 deletions.
34 changes: 32 additions & 2 deletions anchor/database/src/state.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use crate::{DatabaseError, NetworkDatabase, NetworkState, Pool, PoolConn, SqlStatement, SQL};
use ssv_types::{
Cluster, ClusterId, ClusterMember, Operator, OperatorId, Share, ValidatorMetadata,
Cluster, ClusterId, ClusterMember, Operator, OperatorId, Share, ValidatorIndex,
ValidatorMetadata,
};
use std::collections::{HashMap, HashSet};
use types::Address;

impl NetworkState {
// Main constructor that builds the network state from the database data
/// Build the network state from the database data
pub(crate) fn new_with_state(conn_pool: &Pool, id: OperatorId) -> Result<Self, DatabaseError> {
// Get database connection from the pool
let conn = conn_pool.get()?;
Expand Down Expand Up @@ -125,8 +127,36 @@ impl NetworkDatabase {
self.state.clusters.contains(id)
}

/// Get own share of key for a Cluster we are a member in
pub fn get_share(&self, id: &ClusterId) -> Option<&Share> {
self.state.shares.get(id)
}

/// Set the id of our own operator
pub fn set_own_id(&mut self, id: OperatorId) {
self.state.id = Some(id);
}

/// Get the metatdata for the cluster
pub fn get_validator_metadata(&self, id: &ClusterId) -> Option<&ValidatorMetadata> {
self.state.validator_metadata.get(id)
}

/// Get the Fee Recipient address
pub fn get_fee_recipient(&self, id: &ClusterId) -> Option<Address> {
if let Some(metadata) = self.state.validator_metadata.get(id) {
Some(metadata.fee_recipient)
} else {
None
}
}

/// Get the Validator Index
pub fn get_validator_index(&self, id: &ClusterId) -> Option<ValidatorIndex> {
if let Some(metadata) = self.state.validator_metadata.get(id) {
Some(metadata.validator_index)
} else {
None
}
}
}
1 change: 1 addition & 0 deletions anchor/database/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ mod cluster_tests;
mod operator_tests;
mod state_tests;
mod utils;
mod validator_tests;

pub mod test_prelude {
pub use super::utils::*;
Expand Down
10 changes: 10 additions & 0 deletions anchor/database/src/tests/operator_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,14 @@ mod operator_database_tests {
assertions::assert_operator_not_exists_fully(&fixture.db, operator.id);
}
}

#[test]
/// Try to delete an operator that does not exist
fn test_delete_dne_operator() {
let mut fixture = TestFixture::new_empty();
fixture
.db
.delete_operator(OperatorId(1))
.expect_err("Deletion should fail. Operator DNE");
}
}
6 changes: 3 additions & 3 deletions anchor/database/src/tests/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,11 +236,11 @@ pub mod queries {
pub fn get_validator(
db: &NetworkDatabase,
validator_pubkey: &str,
) -> Option<(String, i64, String)> {
) -> Option<(String, i64, String, String, i64)> {
let conn = db.connection().unwrap();
let validator = conn.prepare("SELECT validator_pubkey, cluster_id, owner FROM validators WHERE validator_pubkey = ?1")
let validator = conn.prepare("SELECT validator_pubkey, cluster_id, owner, fee_recipient, validator_index FROM validators WHERE validator_pubkey = ?1")
.unwrap()
.query_row(params![validator_pubkey], |row| Ok((row.get(0)?, row.get(1)?, row.get(2)?)))
.query_row(params![validator_pubkey], |row| Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?, row.get(4)?)))
.optional()
.unwrap();
validator
Expand Down
69 changes: 69 additions & 0 deletions anchor/database/src/tests/validator_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use super::test_prelude::*;

#[cfg(test)]
mod validator_database_tests {
use super::*;
use types::Address;

#[test]
/// Test updating the fee recipient address
fn test_update_fee_recipient() {
let mut fixture = TestFixture::new(Some(1));

let validator_pubkey = fixture.cluster.validator_metadata.validator_pubkey;
let updated_fee_recipient = Address::random();
let cluster_id = fixture.cluster.cluster_id;
fixture
.db
.update_fee_recipient(cluster_id, validator_pubkey.clone(), updated_fee_recipient)
.expect("Failed to update fee recipient");

// make sure the state store has changed, then check the db
assert_eq!(
updated_fee_recipient,
fixture
.db
.get_fee_recipient(&cluster_id)
.expect("Failed to get fee recipient")
);
assert_eq!(
updated_fee_recipient.to_string(),
queries::get_validator(&fixture.db, &(validator_pubkey.to_string()))
.expect("Failed to fetch Validator")
.3
);
}

#[test]
/// Test setting the validator index
fn test_set_validator_index() {
let mut fixture = TestFixture::new(Some(1));

let validator_pubkey = fixture.cluster.validator_metadata.validator_pubkey;
let updated_validator_index = ValidatorIndex(10);
let cluster_id = fixture.cluster.cluster_id;
fixture
.db
.set_validator_index(
cluster_id,
validator_pubkey.clone(),
updated_validator_index,
)
.expect("Failed to update validator index");

// make sure the state store has changed, then check the db
assert_eq!(
updated_validator_index,
fixture
.db
.get_validator_index(&cluster_id)
.expect("Failed to get validator index")
);
assert_eq!(
*updated_validator_index as i64,
queries::get_validator(&fixture.db, &(validator_pubkey.to_string()))
.expect("Failed to fetch Validator")
.4
);
}
}
45 changes: 35 additions & 10 deletions anchor/database/src/validator_operations.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,64 @@
use super::{DatabaseError, NetworkDatabase, SqlStatement, SQL};
use rusqlite::params;
use ssv_types::{ClusterId, ValidatorIndex, ValidatorMetadata};
use ssv_types::{ClusterId, ValidatorIndex};
use types::{Address, PublicKey};

/// Implements all validator related db functionality
impl NetworkDatabase {
/// Populates or updates the fee recipient for the validator
/// Update the fee recipient address for a validator
pub fn update_fee_recipient(
&mut self,
cluster_id: ClusterId,
validator_pubkey: PublicKey,
fee_recipient: Address,
) -> Result<(), DatabaseError> {
// Make sure we are part of the cluster for this Validator
if !self.state.clusters.contains(&cluster_id) {
return Err(DatabaseError::NotFound(format!(
"Validator for Cluster {} not in database",
*cluster_id
)));
}

let conn = self.connection()?;
conn.prepare_cached(SQL[&SqlStatement::UpdateFeeRecipient])?
.execute(params![
validator_pubkey.to_string(),
fee_recipient.to_string()
fee_recipient.to_string(),
validator_pubkey.to_string()
])?;
let metadata = self
.state
.validator_metadata
.get_mut(&cluster_id)
.expect("Cluster should exist");
metadata.fee_recipient = fee_recipient;
Ok(())
}

/// Set the index of the validator
pub fn set_validator_index(
&mut self,
cluster_id: ClusterId,
validator_pubkey: PublicKey,
index: ValidatorIndex,
) -> Result<(), DatabaseError> {
// Make sure we are part of the cluster for this validaor
if !self.state.clusters.contains(&cluster_id) {
return Err(DatabaseError::NotFound(format!(
"Validator for Cluster {} not in database",
*cluster_id
)));
}

let conn = self.connection()?;
conn.prepare_cached(SQL[&SqlStatement::SetValidatorIndex])?
.execute(params![validator_pubkey.to_string(), *index])?;
.execute(params![*index, validator_pubkey.to_string()])?;
let metadata = self
.state
.validator_metadata
.get_mut(&cluster_id)
.expect("Cluster should exist");
metadata.validator_index = index;
Ok(())
}

/// Get the metatdata for the cluster
pub fn get_validator_metadata(&self, id: &ClusterId) -> Option<&ValidatorMetadata> {
self.state.validator_metadata.get(id)
}
}

0 comments on commit 6a39998

Please sign in to comment.