Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support liquidated vaults in metrics #559

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions clients/vault/src/metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ use lazy_static::lazy_static;
use primitives::{stellar, Asset, DecimalsLookup};
use runtime::{
prometheus::{
gather, proto::MetricFamily, Encoder, Gauge, GaugeVec, IntCounter, IntGaugeVec, Opts,
Registry, TextEncoder,
core::{AtomicI64, GenericGauge},
gather,
proto::MetricFamily,
Encoder, Gauge, GaugeVec, IntCounter, IntGaugeVec, Opts, Registry, TextEncoder,
},
types::currency_id::CurrencyIdExt,
AggregateUpdatedEvent, CollateralBalancesPallet, CurrencyId, Error as RuntimeError, FixedU128,
Expand Down Expand Up @@ -83,6 +85,11 @@ lazy_static! {
pub static ref RESTART_COUNT: IntCounter =
IntCounter::new("restart_count", "Number of service restarts")
.expect("Failed to create prometheus metric");
pub static ref LIQUIDATED: IntGaugeVec = IntGaugeVec::new(
Opts::new("liquidated", "Boolean reporting if the vault is currently liquidated"),
&[CURRENCY_LABEL]
)
.expect("Failed to create prometheus metric");
}
const STELLAR_NATIVE_ASSET_TYPE: [u8; 6] = *b"native";

Expand All @@ -108,6 +115,7 @@ pub struct PerCurrencyMetrics {
asset_balance: XLMBalance,
issues: RequestCounter,
redeems: RequestCounter,
liquidated: GenericGauge<AtomicI64>,
}

#[async_trait]
Expand All @@ -117,8 +125,9 @@ pub trait VaultDataReader {

#[async_trait]
impl VaultDataReader for VaultIdManager {
// get_all_entries fetches from active and liquidated vaults
async fn get_entries(&self) -> Vec<VaultData> {
self.get_entries().await
self.get_all_entries().await
}
}

Expand Down Expand Up @@ -231,6 +240,7 @@ impl PerCurrencyMetrics {
completed_count: REDEEMS.with(&request_type_label("completed")),
expired_count: REDEEMS.with(&request_type_label("expired")),
},
liquidated: LIQUIDATED.with(&labels),
}
}

Expand All @@ -242,6 +252,7 @@ impl PerCurrencyMetrics {
publish_locked_collateral(vault, parachain_rpc.clone()),
publish_required_collateral(vault, parachain_rpc.clone()),
publish_collateralization(vault, parachain_rpc.clone()),
update_liquidation_status(vault)
);
}
}
Expand All @@ -259,6 +270,7 @@ pub fn register_custom_metrics() -> Result<(), RuntimeError> {
REGISTRY.register(Box::new(MEAN_POLL_DURATION.clone()))?;
REGISTRY.register(Box::new(MEAN_SCHEDULED_DURATION.clone()))?;
REGISTRY.register(Box::new(RESTART_COUNT.clone()))?;
REGISTRY.register(Box::new(LIQUIDATED.clone()))?;

Ok(())
}
Expand Down Expand Up @@ -481,6 +493,11 @@ async fn publish_redeem_count<V: VaultDataReader>(
}
}

async fn update_liquidation_status(vault: &VaultData) {
let liquidated_flag: i64 = if vault.liquidated { 1 } else { 0 };
vault.metrics.liquidated.set(liquidated_flag);
}

pub async fn monitor_bridge_metrics(
parachain_rpc: SpacewalkParachain,
vault_id_manager: VaultIdManager,
Expand All @@ -499,6 +516,7 @@ pub async fn monitor_bridge_metrics(
.iter()
.filter(|vault| vault.vault_id.collateral_currency() == **currency_id)
{
let _ = update_liquidation_status(vault).await;
let _ = publish_locked_collateral(vault, parachain_rpc.clone()).await;
let _ = publish_required_collateral(vault, parachain_rpc.clone()).await;
publish_collateralization(vault, parachain_rpc.clone()).await;
Expand Down
43 changes: 36 additions & 7 deletions clients/vault/src/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ pub struct VaultData {
pub vault_id: VaultId,
pub stellar_wallet: ArcRwLock<StellarWallet>,
pub metrics: PerCurrencyMetrics,
pub liquidated: bool,
}

#[derive(Clone)]
Expand Down Expand Up @@ -88,19 +89,21 @@ impl VaultIdManager {
vault_id: key.clone(),
stellar_wallet: stellar_wallet.clone(),
metrics: PerCurrencyMetrics::dummy(),
liquidated: false,
},
)
})
.collect();
Self { vault_data: Arc::new(RwLock::new(vault_data)), spacewalk_parachain, stellar_wallet }
}

async fn add_vault_id(&self, vault_id: VaultId) -> Result<(), Error> {
async fn add_vault_id(&self, vault_id: VaultId, is_liquidated: bool) -> Result<(), Error> {
let metrics = PerCurrencyMetrics::new(&vault_id);
let data = VaultData {
vault_id: vault_id.clone(),
stellar_wallet: self.stellar_wallet.clone(),
metrics,
liquidated: is_liquidated,
};
PerCurrencyMetrics::initialize_values(self.spacewalk_parachain.clone(), &data).await;

Expand All @@ -119,11 +122,14 @@ impl VaultIdManager {
{
// check if vault is registered
match self.spacewalk_parachain.get_vault(&vault_id).await {
Ok(_) => self.add_vault_id(vault_id.clone()).await?,
Err(RuntimeError::VaultLiquidated) => tracing::error!(
"[{}] Vault is liquidated -- not going to process events for this vault.",
vault_id.pretty_print()
),
Ok(_) => self.add_vault_id(vault_id.clone(), false).await?,
Err(RuntimeError::VaultLiquidated) => {
self.add_vault_id(vault_id.clone(), true).await?;
tracing::error!(
"[{}] Vault is liquidated -- not going to process events for this vault.",
vault_id.pretty_print()
);
},
Err(e) => return Err(e.into()),
}
}
Expand All @@ -138,7 +144,7 @@ impl VaultIdManager {
let vault_id = event.vault_id;
if self.spacewalk_parachain.is_this_vault(&vault_id) {
tracing::info!("New vault registered: {}", vault_id.pretty_print());
let _ = self.add_vault_id(vault_id).await;
let _ = self.add_vault_id(vault_id, false).await;
}
},
|err| tracing::error!("Error (RegisterVaultEvent): {}", err.to_string()),
Expand All @@ -150,11 +156,32 @@ impl VaultIdManager {
self.vault_data.read().await.get(vault_id).map(|x| x.stellar_wallet.clone())
}

pub async fn get_active_vault(&self, vault_id: &VaultId) -> Option<VaultData> {
Copy link
Contributor Author

@gianfra-t gianfra-t Oct 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason I added this method is to have it into account for the future. Now, get_vault will bring the data even if the vault is liquidated. This impacts a few processes, namely:

I think these are all processes that the liquidated vault should be able to perform anyway. This is the most critical difference about this change, simply replacing in those instances with get_active_vault will not modify the functionality, in case this assumptions are wrong.

let vault = self.vault_data.read().await.get(vault_id)?.clone();
// Filter liquidated
if vault.liquidated {
return None;
}
return Some(vault);
}

pub async fn get_vault(&self, vault_id: &VaultId) -> Option<VaultData> {
self.vault_data.read().await.get(vault_id).cloned()
}

// Get all ACTIVE vaults
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't want to change the name of this method to get_active_entries since it is used in other places and wanted to minimize the modifications to the rest of the code, but we could of course.

pub async fn get_entries(&self) -> Vec<VaultData> {
self.vault_data
.read()
.await
.iter()
.filter(|(_, value)| !value.liquidated)
.map(|(_, value)| value.clone())
.collect()
}

// Get all vaults including liquidated ones.
pub async fn get_all_entries(&self) -> Vec<VaultData> {
self.vault_data.read().await.iter().map(|(_, value)| value.clone()).collect()
}

Expand All @@ -163,6 +190,7 @@ impl VaultIdManager {
.read()
.await
.iter()
.filter(|(_, value)| !value.liquidated)
.map(|(vault_id, _)| vault_id.clone())
.collect()
}
Expand All @@ -174,6 +202,7 @@ impl VaultIdManager {
.read()
.await
.iter()
.filter(|(_, value)| !value.liquidated)
.map(|(vault_id, data)| (vault_id.clone(), data.stellar_wallet.clone()))
.collect()
}
Expand Down
4 changes: 2 additions & 2 deletions pallets/stellar-relay/src/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ fn is_node_id_exist<T: Config>(
envelope.statement.slot_index,
envelope.statement.node_id
);
return None
return None;
}

Some(node_id)
Expand Down Expand Up @@ -174,7 +174,7 @@ pub fn validate_envelopes<'a, T: Config>(
for envelope in envelopes {
let Some(node_id) = is_node_id_exist::<T>(envelope, validators) else {
// ignore this envelope; continue to the next ones
continue
continue;
};

// Check if all envelopes are using the same slot index
Expand Down
Loading