Skip to content

Commit ec16a5f

Browse files
authored
wip: bonds and unbonds (#4)
* wip: tx size * wip: added batch size * wip: added bonds and unbonds * added prometheus metrics
1 parent 39acd32 commit ec16a5f

File tree

6 files changed

+247
-7
lines changed

6 files changed

+247
-7
lines changed

src/checks/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
11
pub mod block;
22
pub mod epoch;
33
pub mod total_supply_native;
4+
pub mod tx_size;
45

56
use block::BlockHeigtCheck;
67
use epoch::EpochCheck;
78
use total_supply_native::TotalSupplyNativeCheck;
9+
use tx_size::TxSizeCheck;
810

911
pub enum Checks {
1012
BlockHeightCheck(BlockHeigtCheck),
1113
EpochCheck(EpochCheck),
1214
TotalSupplyNative(TotalSupplyNativeCheck),
15+
TxSize(TxSizeCheck),
1316
}
1417

1518
pub fn all_checks() -> Vec<Checks> {
1619
vec![
1720
Checks::BlockHeightCheck(BlockHeigtCheck::default()),
1821
Checks::EpochCheck(EpochCheck::default()),
1922
Checks::TotalSupplyNative(TotalSupplyNativeCheck::default()),
23+
Checks::TxSize(TxSizeCheck::default()),
2024
]
2125
}

src/checks/tx_size.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#[derive(Clone, Debug, Default)]
2+
pub struct TxSizeCheck {}
3+
4+
impl TxSizeCheck {
5+
pub async fn run(
6+
&self,
7+
pre_state: &crate::state::State,
8+
post_state: &crate::state::State,
9+
) -> anyhow::Result<()> {
10+
Ok(())
11+
}
12+
}

src/main.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,13 @@ async fn main() -> anyhow::Result<()> {
8080
.query_total_supply(&native_token)
8181
.await
8282
.into_retry_error()?;
83+
let (future_bonds, future_unbonds) = rpc
84+
.query_future_bonds_and_unbonds(epoch)
85+
.await
86+
.into_retry_error()?;
8387

8488
let mut post_state_lock = state.write().await;
85-
post_state_lock.update(block, total_supply_native);
89+
post_state_lock.update(block, total_supply_native, future_bonds, future_unbonds);
8690
let post_state = post_state_lock.clone();
8791
drop(post_state_lock);
8892

@@ -97,6 +101,7 @@ async fn main() -> anyhow::Result<()> {
97101
checks::Checks::TotalSupplyNative(check) => {
98102
check.run(&pre_state, &post_state).await
99103
}
104+
checks::Checks::TxSize(check) => check.run(&pre_state, &post_state).await,
100105
};
101106
if let Err(error) = check_res {
102107
tracing::error!("Error: {}", error.to_string());
@@ -107,6 +112,8 @@ async fn main() -> anyhow::Result<()> {
107112
}
108113
}
109114

115+
tracing::info!("Done block {}", block_height);
116+
110117
Ok(())
111118
},
112119
notify,

src/rpc.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::str::FromStr;
33
use anyhow::Context;
44
use futures::FutureExt;
55
use namada_sdk::{
6-
address::Address as NamadaAddress, hash::Hash, io::Client, rpc,
6+
address::Address as NamadaAddress, hash::Hash, io::Client, rpc, state::Epoch as NamadaEpoch,
77
state::Key,
88
};
99
use tendermint_rpc::{HttpClient, Url};
@@ -106,4 +106,28 @@ impl Rpc {
106106
res.context("Should be able to query native token")
107107
.map(|amount| amount.raw_amount().as_u64())
108108
}
109+
110+
pub async fn query_future_bonds_and_unbonds(&self, epoch: Epoch) -> anyhow::Result<(u64, u64)> {
111+
let pipeline_epoch = NamadaEpoch(epoch + 1);
112+
let futures = self.clients.iter().map(|client| {
113+
rpc::enriched_bonds_and_unbonds(client, pipeline_epoch, &None, &None).boxed()
114+
});
115+
116+
let (res, _ready_future_index, _remaining_futures) =
117+
futures::future::select_all(futures).await;
118+
119+
res.context("Should be able to query native token")
120+
.map(|summary| {
121+
(
122+
summary
123+
.bonds_total_active()
124+
.map(|amount| amount.raw_amount().as_u64())
125+
.unwrap_or(0),
126+
summary
127+
.unbonds_total_active()
128+
.map(|amount| amount.raw_amount().as_u64())
129+
.unwrap_or(0),
130+
)
131+
})
132+
}
109133
}

src/shared/namada.rs

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
use namada_sdk::borsh::BorshDeserialize;
1+
use std::fmt::Display;
2+
3+
use namada_sdk::borsh::{BorshDeserialize, BorshSerializeExt};
24
use namada_sdk::governance::{InitProposalData, VoteProposalData};
35
use namada_sdk::ibc::{decode_message, IbcMessage};
46
use namada_sdk::key::common::PublicKey;
@@ -49,6 +51,28 @@ pub enum InnerKind {
4951
Unknown(Vec<u8>),
5052
}
5153

54+
impl Display for InnerKind {
55+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56+
match self {
57+
InnerKind::TransparentTransfer(_) => write!(f, "transparent_transfer"),
58+
InnerKind::ShieldedTransfer(_) => write!(f, "shielded_transfer"),
59+
InnerKind::IbcMsgTransfer(_) => write!(f, "ibc"),
60+
InnerKind::Bond(_) => write!(f, "bond"),
61+
InnerKind::Redelegation(_) => write!(f, "redelegate"),
62+
InnerKind::Unbond(_) => write!(f, "unbond"),
63+
InnerKind::Withdraw(_) => write!(f, "withdraw"),
64+
InnerKind::ClaimRewards(_) => write!(f, "claim_rewards"),
65+
InnerKind::ProposalVote(_) => write!(f, "vote_proposal"),
66+
InnerKind::InitProposal(_) => write!(f, "init_proposal"),
67+
InnerKind::MetadataChange(_) => write!(f, "metadata_change"),
68+
InnerKind::CommissionChange(_) => write!(f, "commission_change"),
69+
InnerKind::RevealPk(_) => write!(f, "reveal_public_key"),
70+
InnerKind::BecomeValidator(_) => write!(f, "become_validator"),
71+
InnerKind::Unknown(_) => write!(f, "unknown"),
72+
}
73+
}
74+
}
75+
5276
impl InnerKind {
5377
pub fn from_code_name(name: &str, data: &[u8]) -> Self {
5478
match name {
@@ -160,6 +184,74 @@ impl InnerKind {
160184
_ => InnerKind::Unknown(data.to_vec()),
161185
}
162186
}
187+
188+
pub fn size(&self) -> usize {
189+
match self {
190+
InnerKind::TransparentTransfer(tx) => tx
191+
.clone()
192+
.map(|data| data.serialize_to_vec().len())
193+
.unwrap_or(0),
194+
InnerKind::ShieldedTransfer(tx) => tx
195+
.clone()
196+
.map(|data| data.serialize_to_vec().len())
197+
.unwrap_or(0),
198+
InnerKind::IbcMsgTransfer(tx) => tx
199+
.clone()
200+
.map(|data| match data {
201+
IbcMessage::Envelope(msg_envelope) => msg_envelope.serialize_to_vec().len(),
202+
IbcMessage::Transfer(msg_transfer) => msg_transfer.serialize_to_vec().len(),
203+
IbcMessage::NftTransfer(msg_nft_transfer) => {
204+
msg_nft_transfer.serialize_to_vec().len()
205+
}
206+
})
207+
.unwrap_or(0),
208+
InnerKind::Bond(tx) => tx
209+
.clone()
210+
.map(|data| data.serialize_to_vec().len())
211+
.unwrap_or(0),
212+
InnerKind::Redelegation(tx) => tx
213+
.clone()
214+
.map(|data| data.serialize_to_vec().len())
215+
.unwrap_or(0),
216+
InnerKind::Unbond(tx) => tx
217+
.clone()
218+
.map(|data| data.serialize_to_vec().len())
219+
.unwrap_or(0),
220+
InnerKind::Withdraw(tx) => tx
221+
.clone()
222+
.map(|data| data.serialize_to_vec().len())
223+
.unwrap_or(0),
224+
InnerKind::ClaimRewards(tx) => tx
225+
.clone()
226+
.map(|data| data.serialize_to_vec().len())
227+
.unwrap_or(0),
228+
InnerKind::ProposalVote(tx) => tx
229+
.clone()
230+
.map(|data| data.serialize_to_vec().len())
231+
.unwrap_or(0),
232+
InnerKind::InitProposal(tx) => tx
233+
.clone()
234+
.map(|data| data.serialize_to_vec().len())
235+
.unwrap_or(0),
236+
InnerKind::MetadataChange(tx) => tx
237+
.clone()
238+
.map(|data| data.serialize_to_vec().len())
239+
.unwrap_or(0),
240+
InnerKind::CommissionChange(tx) => tx
241+
.clone()
242+
.map(|data| data.serialize_to_vec().len())
243+
.unwrap_or(0),
244+
InnerKind::RevealPk(tx) => tx
245+
.clone()
246+
.map(|data| data.serialize_to_vec().len())
247+
.unwrap_or(0),
248+
InnerKind::BecomeValidator(tx) => tx
249+
.clone()
250+
.map(|data| data.serialize_to_vec().len())
251+
.unwrap_or(0),
252+
InnerKind::Unknown(tx) => tx.len(),
253+
}
254+
}
163255
}
164256

165257
#[derive(Clone, Debug)]

src/state.rs

Lines changed: 105 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use std::num::NonZeroUsize;
22

33
use lru::LruCache;
44
use prometheus_exporter::prometheus::{
5-
core::{AtomicU64, GenericCounter},
6-
Registry,
5+
core::{AtomicU64, GenericCounter, GenericCounterVec},
6+
Histogram, HistogramOpts, IntCounterVec, Opts, Registry,
77
};
88

99
use crate::shared::{
@@ -26,6 +26,11 @@ pub struct PrometheusMetrics {
2626
pub block_height_counter: GenericCounter<AtomicU64>,
2727
pub epoch_counter: GenericCounter<AtomicU64>,
2828
pub total_supply_native_token: GenericCounter<AtomicU64>,
29+
pub transaction_size: Histogram,
30+
pub transaction_inner_size: Histogram,
31+
pub bonds_per_epoch: GenericCounterVec<AtomicU64>,
32+
pub unbonds_per_epoch: GenericCounterVec<AtomicU64>,
33+
pub transaction_kind: GenericCounterVec<AtomicU64>,
2934
registry: Registry,
3035
}
3136

@@ -52,18 +57,65 @@ impl PrometheusMetrics {
5257
)
5358
.expect("unable to create counter total supply");
5459

60+
let transaction_size_opts = HistogramOpts::new(
61+
"transaction_size_bytes",
62+
"The sizes of transactions in bytes",
63+
)
64+
.buckets(vec![
65+
10.0, 50.0, 100.0, 500.0, 1000.0, 5000.0, 10000.0, 50000.0,
66+
]);
67+
let transaction_size = Histogram::with_opts(transaction_size_opts)
68+
.expect("unable to create histogram transaction sizes");
69+
70+
let transaction_inner_size_opts =
71+
HistogramOpts::new("transaction_inners", "The number of inner tx for a wrapper")
72+
.buckets(vec![2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0]);
73+
let transaction_inner_size = Histogram::with_opts(transaction_inner_size_opts)
74+
.expect("unable to create histogram transaction sizes");
75+
76+
let bonds_per_epoch_opts = Opts::new("bonds_per_epoch", "Total bonds per epoch");
77+
let bonds_per_epoch = IntCounterVec::new(bonds_per_epoch_opts, &["epoch"])
78+
.expect("unable to create histogram transaction sizes");
79+
80+
let unbonds_per_epoch_opts = Opts::new("unbonds_per_epoch", "Total unbonds per epoch");
81+
let unbonds_per_epoch = IntCounterVec::new(unbonds_per_epoch_opts, &["epoch"])
82+
.expect("unable to create histogram transaction sizes");
83+
84+
let transaction_kind_opts =
85+
Opts::new("transaction_kind", "Total transaction per transaction kind");
86+
let transaction_kind =
87+
IntCounterVec::new(transaction_kind_opts, &["kind", "epoch", "height"])
88+
.expect("unable to create histogram transaction sizes");
89+
5590
registry
5691
.register(Box::new(block_height_counter.clone()))
5792
.unwrap();
5893
registry.register(Box::new(epoch_counter.clone())).unwrap();
5994
registry
6095
.register(Box::new(total_supply_native_token.clone()))
6196
.unwrap();
97+
registry
98+
.register(Box::new(transaction_size.clone()))
99+
.unwrap();
100+
registry
101+
.register(Box::new(bonds_per_epoch.clone()))
102+
.unwrap();
103+
registry
104+
.register(Box::new(unbonds_per_epoch.clone()))
105+
.unwrap();
106+
registry
107+
.register(Box::new(transaction_kind.clone()))
108+
.unwrap();
62109

63110
Self {
64111
block_height_counter,
65112
epoch_counter,
66113
total_supply_native_token,
114+
transaction_size,
115+
transaction_inner_size,
116+
bonds_per_epoch,
117+
unbonds_per_epoch,
118+
transaction_kind,
67119
registry,
68120
}
69121
}
@@ -95,7 +147,13 @@ impl State {
95147
.unwrap_or(1)
96148
}
97149

98-
pub fn update(&mut self, block: Block, total_supply_native: u64) {
150+
pub fn update(
151+
&mut self,
152+
block: Block,
153+
total_supply_native: u64,
154+
future_bonds: u64,
155+
future_unbonds: u64,
156+
) {
99157
if let Some(height) = self.latest_block_height {
100158
self.metrics
101159
.block_height_counter
@@ -110,7 +168,7 @@ impl State {
110168
.block_height_counter
111169
.inc_by(block.epoch - epoch);
112170
} else {
113-
self.metrics.block_height_counter.inc_by(block.epoch);
171+
self.metrics.epoch_counter.inc_by(block.epoch);
114172
}
115173
self.latest_epoch = Some(block.epoch);
116174

@@ -125,6 +183,49 @@ impl State {
125183
}
126184
self.latest_total_supply_native = Some(total_supply_native);
127185

186+
for tx in &block.transactions {
187+
self.metrics
188+
.transaction_inner_size
189+
.observe(tx.inners.len() as f64);
190+
}
191+
192+
for tx in &block.transactions {
193+
for inner in &tx.inners {
194+
let inner_kind = inner.kind.to_string();
195+
196+
self.metrics
197+
.transaction_kind
198+
.with_label_values(&[
199+
&inner_kind,
200+
&block.epoch.to_string(),
201+
&block.height.to_string(),
202+
])
203+
.inc();
204+
205+
self.metrics
206+
.transaction_size
207+
.observe(inner.kind.size() as f64);
208+
}
209+
}
210+
211+
self.metrics
212+
.bonds_per_epoch
213+
.with_label_values(&[&(block.epoch + 1).to_string()])
214+
.reset();
215+
self.metrics
216+
.bonds_per_epoch
217+
.with_label_values(&[&(block.epoch + 1).to_string()])
218+
.inc_by(future_bonds);
219+
220+
self.metrics
221+
.unbonds_per_epoch
222+
.with_label_values(&[&(block.epoch + 1).to_string()])
223+
.reset();
224+
self.metrics
225+
.unbonds_per_epoch
226+
.with_label_values(&[&(block.epoch + 1).to_string()])
227+
.inc_by(future_unbonds);
228+
128229
self.blocks.put(block.height, block);
129230
}
130231

0 commit comments

Comments
 (0)