diff --git a/docker/assets/grafana/dashboards/analytics_dashboard.json b/docker/assets/grafana/dashboards/analytics_dashboard.json index 175f40c21..d2e889812 100644 --- a/docker/assets/grafana/dashboards/analytics_dashboard.json +++ b/docker/assets/grafana/dashboards/analytics_dashboard.json @@ -1380,7 +1380,7 @@ "h": 9, "w": 12, "x": 12, - "y": 27 + "y": 36 }, "id": 63, "options": { @@ -1441,7 +1441,7 @@ "h": 1, "w": 24, "x": 0, - "y": 36 + "y": 45 }, "id": 59, "panels": [], @@ -1511,7 +1511,7 @@ "h": 9, "w": 12, "x": 0, - "y": 37 + "y": 46 }, "id": 22, "options": { @@ -1695,7 +1695,7 @@ "h": 9, "w": 12, "x": 12, - "y": 37 + "y": 46 }, "id": 60, "options": { @@ -1804,7 +1804,7 @@ "h": 1, "w": 24, "x": 0, - "y": 46 + "y": 55 }, "id": 49, "panels": [], @@ -1873,7 +1873,7 @@ "h": 8, "w": 12, "x": 0, - "y": 47 + "y": 56 }, "id": 51, "options": { @@ -2038,7 +2038,7 @@ "h": 8, "w": 12, "x": 12, - "y": 47 + "y": 56 }, "id": 61, "options": { @@ -2165,7 +2165,7 @@ "h": 1, "w": 24, "x": 0, - "y": 55 + "y": 64 }, "id": 31, "panels": [], @@ -2235,7 +2235,7 @@ "h": 8, "w": 12, "x": 0, - "y": 56 + "y": 65 }, "id": 33, "options": { @@ -2302,6 +2302,135 @@ "title": "Unclaimed Tokens", "type": "timeseries" }, + { + "datasource": { + "type": "influxdb", + "uid": "PE5723DBC504634E6" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 15, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "stepBefore", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "SMR" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 65 + }, + "id": 64, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "targets": [ + { + "alias": "Return Amount", + "datasource": { + "type": "influxdb", + "uid": "PE5723DBC504634E6" + }, + "groupBy": [ + { + "params": [ + "$aggregation_interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "measurement": "stardust_unlock_conditions", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "storage_deposit_return_inner_value" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + }, + { + "params": [ + " / 1000000" + ], + "type": "math" + } + ] + ], + "tags": [] + } + ], + "title": "Amount in Storage Deposit Return Unlock Condition", + "type": "timeseries" + }, { "datasource": { "type": "influxdb", @@ -2365,8 +2494,8 @@ "gridPos": { "h": 8, "w": 12, - "x": 12, - "y": 56 + "x": 0, + "y": 73 }, "id": 36, "options": { @@ -2433,7 +2562,7 @@ "h": 1, "w": 24, "x": 0, - "y": 64 + "y": 81 }, "id": 29, "panels": [], @@ -2502,7 +2631,7 @@ "h": 8, "w": 12, "x": 0, - "y": 65 + "y": 82 }, "id": 39, "options": { @@ -2649,7 +2778,7 @@ "h": 8, "w": 12, "x": 12, - "y": 65 + "y": 82 }, "id": 41, "options": { @@ -2704,7 +2833,7 @@ }, { "params": [ - " * 100 / 1000000" + " / 1000000" ], "type": "math" } diff --git a/src/db/collections/analytics/influx.rs b/src/db/collections/analytics/influx.rs index 2a9a07560..7a73221b3 100644 --- a/src/db/collections/analytics/influx.rs +++ b/src/db/collections/analytics/influx.rs @@ -58,18 +58,9 @@ impl From for influxdb::WriteQuery { ), Measurement::LedgerSizeAnalytics(m) => m .prepare_query("stardust_ledger_size") - .add_field( - "total_storage_deposit_value", - m.inner.total_storage_deposit_value.to_string().parse::().unwrap(), - ) - .add_field( - "total_key_bytes", - m.inner.total_key_bytes.to_string().parse::().unwrap(), - ) - .add_field( - "total_data_bytes", - m.inner.total_data_bytes.to_string().parse::().unwrap(), - ), + .add_field("total_key_bytes", m.inner.total_key_bytes) + .add_field("total_data_bytes", m.inner.total_data_bytes) + .add_field("total_storage_deposit_value", m.inner.total_storage_deposit_value), Measurement::OutputActivityAnalytics(m) => m .prepare_query("stardust_output_activity") .add_field("alias_created_count", m.inner.alias.created_count) @@ -110,6 +101,14 @@ impl From for influxdb::WriteQuery { .add_field( "storage_deposit_return_value", m.inner.storage_deposit_return_value.to_string().parse::().unwrap(), + ) + .add_field( + "storage_deposit_return_inner_value", + m.inner + .storage_deposit_return_inner_value + .to_string() + .parse::() + .unwrap(), ), } } diff --git a/src/db/collections/analytics/ledger_size.rs b/src/db/collections/analytics/ledger_size.rs index 975dbd9d8..69a5edf7e 100644 --- a/src/db/collections/analytics/ledger_size.rs +++ b/src/db/collections/analytics/ledger_size.rs @@ -2,17 +2,20 @@ // SPDX-License-Identifier: Apache-2.0 use async_trait::async_trait; -use decimal::d128; use futures::TryStreamExt; use mongodb::bson::doc; use serde::{Deserialize, Serialize}; use super::{Analytic, Error, Measurement, PerMilestone}; use crate::{ - db::{collections::OutputCollection, MongoDb, MongoDbCollectionExt}, + db::{ + collections::{OutputCollection, ProtocolUpdateCollection}, + MongoDb, MongoDbCollection, MongoDbCollectionExt, + }, types::{ + ledger::RentStructureBytes, stardust::milestone::MilestoneTimestamp, - tangle::{MilestoneIndex, ProtocolParameters}, + tangle::{MilestoneIndex, RentStructure}, }, }; @@ -22,18 +25,9 @@ pub struct LedgerSizeAnalytics; #[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] pub struct LedgerSizeAnalyticsResult { - pub total_storage_deposit_value: d128, - pub total_key_bytes: d128, - pub total_data_bytes: d128, -} - -impl LedgerSizeAnalyticsResult { - pub fn total_byte_cost(&self, protocol_params: &ProtocolParameters) -> d128 { - let rent_structure = protocol_params.rent_structure; - d128::from(rent_structure.v_byte_cost) - * ((self.total_key_bytes * d128::from(rent_structure.v_byte_factor_key as u32)) - + (self.total_data_bytes * d128::from(rent_structure.v_byte_factor_data as u32))) - } + pub total_key_bytes: u64, + pub total_data_bytes: u64, + pub total_storage_deposit_value: u64, } #[async_trait] @@ -64,30 +58,60 @@ impl OutputCollection { &self, ledger_index: MilestoneIndex, ) -> Result { - Ok(self - .aggregate( - vec![ - doc! { "$match": { - "metadata.booked.milestone_index": { "$lte": ledger_index }, - "metadata.spent_metadata.spent.milestone_index": { "$not": { "$lte": ledger_index } } - } }, - doc! { "$group" : { - "_id": null, - "total_key_bytes": { "$sum": { "$toDecimal": "$details.rent_structure.num_key_bytes" } }, - "total_data_bytes": { "$sum": { "$toDecimal": "$details.rent_structure.num_data_bytes" } }, - "total_storage_deposit_value": { "$sum": { "$toDecimal": "$output.storage_deposit_return_unlock_condition.amount" } }, - } }, - doc! { "$project": { - "total_storage_deposit_value": { "$toString": "$total_storage_deposit_value" }, - "total_key_bytes": { "$toString": "$total_key_bytes" }, - "total_data_bytes": { "$toString": "$total_data_bytes" }, - } }, - ], - None, - ) - .await? - .try_next() - .await? - .unwrap_or_default()) + #[derive(Deserialize)] + struct Res { + total_key_bytes: String, + total_data_bytes: String, + rent_structure: RentStructure, + } + + let res = self + .aggregate::( + vec![ + doc! { "$match": { + "metadata.booked.milestone_index": { "$lte": ledger_index }, + "metadata.spent_metadata.spent.milestone_index": { "$not": { "$lte": ledger_index } } + } }, + doc! { "$group" : { + "_id": null, + "total_key_bytes": { "$sum": { "$toDecimal": "$details.rent_structure.num_key_bytes" } }, + "total_data_bytes": { "$sum": { "$toDecimal": "$details.rent_structure.num_data_bytes" } }, + } }, + doc! { "$lookup": { + "from": ProtocolUpdateCollection::NAME, + "pipeline": [ + { "$match": { "_id": { "$lte": ledger_index } } }, + { "$sort": { "_id": -1 } }, + { "$limit": 1 }, + { "$replaceWith": "$parameters.rent_structure" } + ], + "as": "rent_structure", + } }, + doc! { "$project": { + "total_key_bytes": { "$toString": "$total_key_bytes" }, + "total_data_bytes": { "$toString": "$total_data_bytes" }, + "rent_structure": { "$first": "$rent_structure" }, + } }, + ], + None, + ) + .await? + .try_next() + .await?; + + Ok(res + .map(|res| { + let rent_structure_bytes = RentStructureBytes { + num_key_bytes: res.total_key_bytes.parse().unwrap(), + num_data_bytes: res.total_data_bytes.parse().unwrap(), + }; + + LedgerSizeAnalyticsResult { + total_key_bytes: rent_structure_bytes.num_key_bytes, + total_data_bytes: rent_structure_bytes.num_data_bytes, + total_storage_deposit_value: rent_structure_bytes.rent_cost(&res.rent_structure.into()), + } + }) + .unwrap_or_default()) } } diff --git a/src/db/collections/analytics/unlock_condition.rs b/src/db/collections/analytics/unlock_condition.rs index 20dc75b0f..498bbdef1 100644 --- a/src/db/collections/analytics/unlock_condition.rs +++ b/src/db/collections/analytics/unlock_condition.rs @@ -26,6 +26,7 @@ pub struct UnlockConditionAnalyticsResult { pub expiration_value: d128, pub storage_deposit_return_count: u64, pub storage_deposit_return_value: d128, + pub storage_deposit_return_inner_value: d128, } #[async_trait] @@ -90,10 +91,46 @@ impl OutputCollection { ) }; + #[derive(Default, Deserialize)] + struct ResSdruc { + count: u64, + value: d128, + inner: d128, + } + + let sdruc_query = async move { + Result::::Ok( + self.aggregate( + vec![ + doc! { "$match": { + "output.storage_deposit_return_unlock_condition": { "$exists": true }, + "metadata.booked.milestone_index": { "$lte": ledger_index }, + "metadata.spent_metadata.spent.milestone_index": { "$not": { "$lte": ledger_index } } + } }, + doc! { "$group": { + "_id": null, + "count": { "$sum": 1 }, + "value": { "$sum": { "$toDecimal": "$output.amount" } }, + "inner": { "$sum": { "$toDecimal": "$output.storage_deposit_return_unlock_condition.amount" } }, + } }, + doc! { "$project": { + "count": 1, + "value": { "$toString": "$value" }, + "inner": { "$toString": "$inner" }, + } }, + ], + None, + ) + .await? + .try_next() + .await? + .unwrap_or_default()) + }; + let (timelock, expiration, sdruc) = tokio::try_join!( query("timelock_unlock_condition"), query("expiration_unlock_condition"), - query("storage_deposit_return_unlock_condition"), + sdruc_query, )?; Ok(UnlockConditionAnalyticsResult { @@ -103,6 +140,7 @@ impl OutputCollection { expiration_value: expiration.value, storage_deposit_return_count: sdruc.count, storage_deposit_return_value: sdruc.value, + storage_deposit_return_inner_value: sdruc.inner, }) } } diff --git a/src/types/ledger/output_metadata.rs b/src/types/ledger/output_metadata.rs index 98c91d43e..ede4daf37 100644 --- a/src/types/ledger/output_metadata.rs +++ b/src/types/ledger/output_metadata.rs @@ -61,29 +61,34 @@ pub struct RentStructureBytes { pub num_data_bytes: u64, } -#[cfg(feature = "inx")] -fn compute_rent_structure(output: &iota_types::block::output::Output) -> RentStructureBytes { - use iota_types::block::output::{Rent, RentStructureBuilder}; - - let rent_cost = |byte_cost, data_factor, key_factor| { - output.rent_cost( - &RentStructureBuilder::new() - .byte_cost(byte_cost) - .byte_factor_data(data_factor) - .byte_factor_key(key_factor) - .finish(), - ) - }; - - RentStructureBytes { - num_data_bytes: rent_cost(1, 1, 0), - num_key_bytes: rent_cost(1, 0, 1), +impl RentStructureBytes { + pub fn compute(output: &iota_types::block::output::Output) -> Self { + use iota_types::block::output::{Rent, RentStructureBuilder}; + + let rent_cost = |byte_cost, data_factor, key_factor| { + output.rent_cost( + &RentStructureBuilder::new() + .byte_cost(byte_cost) + .byte_factor_data(data_factor) + .byte_factor_key(key_factor) + .finish(), + ) + }; + + RentStructureBytes { + num_data_bytes: rent_cost(1, 1, 0), + num_key_bytes: rent_cost(1, 0, 1), + } + } + + pub fn rent_cost(&self, config: &iota_types::block::output::RentStructure) -> u64 { + (self.num_data_bytes * config.byte_factor_data() as u64 + self.num_key_bytes * config.byte_factor_key() as u64) + * config.byte_cost() as u64 } } #[cfg(feature = "inx")] mod inx { - use packable::PackableExt; use super::*; @@ -99,7 +104,7 @@ mod inx { .map_err(|e| InxError::InvalidRawBytes(format!("{e:?}")))?; Ok(Self { - rent_structure: compute_rent_structure(&bee_output), + rent_structure: RentStructureBytes::compute(&bee_output), output: Into::into(&bee_output), output_id: maybe_missing!(value.output_id).try_into()?, block_id: maybe_missing!(value.block_id).try_into()?, @@ -139,7 +144,7 @@ mod test { fn test_compute_rent_structure() { use iota_types::block::{output::Rent, rand::output}; - use super::compute_rent_structure; + use super::RentStructureBytes; let protocol_params = iota_types::block::protocol::protocol_parameters(); @@ -151,11 +156,9 @@ mod test { ]; for output in outputs { - let rent = compute_rent_structure(&output); + let rent = RentStructureBytes::compute(&output); assert_eq!( - (rent.num_data_bytes * protocol_params.rent_structure().byte_factor_data() as u64 - + rent.num_key_bytes * protocol_params.rent_structure().byte_factor_key() as u64) - * protocol_params.rent_structure().byte_cost() as u64, + rent.rent_cost(protocol_params.rent_structure()), output.rent_cost(protocol_params.rent_structure()) ); }