Skip to content

Commit b763c29

Browse files
authored
enhancement: store raw data for unknown transaction kinds in order to capture them so they can be parsed later (#183)
* enhancement: store raw data for unknown transaction kinds in order to capture them so they can be parsed later * [checksums] Add all tx_* wasms from namada-sdk * [transactions] Add on_conflict handling so that old blocks can be re-crawled for transactions without failing
1 parent 718e836 commit b763c29

File tree

5 files changed

+81
-11
lines changed

5 files changed

+81
-11
lines changed

orm/src/transactions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ impl From<TransactionKind> for TransactionKindDb {
5858
TransactionKind::BecomeValidator(_) => {
5959
TransactionKindDb::BecomeValidator
6060
}
61-
TransactionKind::Unknown => TransactionKindDb::Unknown,
61+
TransactionKind::Unknown(_) => TransactionKindDb::Unknown,
6262
}
6363
}
6464
}

parameters/src/repository/parameters.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ pub fn upsert_chain_parameters(
1919
.eq(excluded(chain_parameters::max_block_time)),
2020
chain_parameters::cubic_slashing_window_length
2121
.eq(excluded(chain_parameters::cubic_slashing_window_length)),
22+
chain_parameters::checksums
23+
.eq(excluded(chain_parameters::checksums)),
2224
))
2325
.execute(transaction_conn)
2426
.context("Failed to update chain_parameters state in db")?;

shared/src/checksums.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
use bimap::BiMap;
22
use namada_sdk::tx::{
3-
TX_BECOME_VALIDATOR_WASM, TX_BOND_WASM, TX_CHANGE_COMMISSION_WASM,
4-
TX_CHANGE_METADATA_WASM, TX_CLAIM_REWARDS_WASM, TX_IBC_WASM,
5-
TX_INIT_PROPOSAL, TX_REDELEGATE_WASM, TX_REVEAL_PK, TX_TRANSFER_WASM,
6-
TX_UNBOND_WASM, TX_VOTE_PROPOSAL, TX_WITHDRAW_WASM,
3+
TX_BECOME_VALIDATOR_WASM, TX_BOND_WASM, TX_BRIDGE_POOL_WASM,
4+
TX_CHANGE_COMMISSION_WASM, TX_CHANGE_CONSENSUS_KEY_WASM,
5+
TX_CHANGE_METADATA_WASM, TX_CLAIM_REWARDS_WASM,
6+
TX_DEACTIVATE_VALIDATOR_WASM, TX_IBC_WASM, TX_INIT_ACCOUNT_WASM,
7+
TX_INIT_PROPOSAL, TX_REACTIVATE_VALIDATOR_WASM, TX_REDELEGATE_WASM,
8+
TX_RESIGN_STEWARD, TX_REVEAL_PK, TX_TRANSFER_WASM, TX_UNBOND_WASM,
9+
TX_UNJAIL_VALIDATOR_WASM, TX_UPDATE_ACCOUNT_WASM,
10+
TX_UPDATE_STEWARD_COMMISSION, TX_VOTE_PROPOSAL, TX_WITHDRAW_WASM,
711
};
812
use serde::{Deserialize, Serialize};
913

@@ -44,6 +48,15 @@ impl Checksums {
4448
TX_CHANGE_COMMISSION_WASM.to_string(),
4549
TX_IBC_WASM.to_string(),
4650
TX_BECOME_VALIDATOR_WASM.to_string(),
51+
TX_INIT_ACCOUNT_WASM.to_string(),
52+
TX_UNJAIL_VALIDATOR_WASM.to_string(),
53+
TX_DEACTIVATE_VALIDATOR_WASM.to_string(),
54+
TX_REACTIVATE_VALIDATOR_WASM.to_string(),
55+
TX_UPDATE_ACCOUNT_WASM.to_string(),
56+
TX_BRIDGE_POOL_WASM.to_string(),
57+
TX_CHANGE_CONSENSUS_KEY_WASM.to_string(),
58+
TX_RESIGN_STEWARD.to_string(),
59+
TX_UPDATE_STEWARD_COMMISSION.to_string(),
4760
]
4861
}
4962
}

shared/src/transaction.rs

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,39 @@ pub struct RevealPkData {
2929
pub public_key: PublicKey,
3030
}
3131

32+
// Capture details for unknown transactions so we can store them in the db
33+
#[derive(Serialize, Debug, Clone)]
34+
pub struct UnknownTransaction {
35+
#[serde(skip_serializing_if = "Option::is_none")]
36+
pub id: Option<String>,
37+
#[serde(skip_serializing_if = "Option::is_none")]
38+
pub name: Option<String>,
39+
#[serde(skip_serializing_if = "Option::is_none")]
40+
#[serde(serialize_with = "serialize_optional_bytes_to_hex")]
41+
pub data: Option<Vec<u8>>,
42+
}
43+
44+
fn serialize_optional_bytes_to_hex<S>(
45+
bytes: &Option<Vec<u8>>,
46+
serializer: S,
47+
) -> Result<S::Ok, S::Error>
48+
where
49+
S: serde::Serializer,
50+
{
51+
bytes
52+
.as_ref()
53+
.map(|b| {
54+
let mut s = String::with_capacity(2 + (b.len() * 2)); // "0x" + 2 chars per byte
55+
s.push_str("0x");
56+
for byte in b {
57+
use std::fmt::Write;
58+
write!(s, "{:02x}", byte).unwrap();
59+
}
60+
s
61+
})
62+
.serialize(serializer)
63+
}
64+
3265
#[derive(Serialize, Debug, Clone)]
3366
#[serde(untagged)]
3467
pub enum TransactionKind {
@@ -48,15 +81,15 @@ pub enum TransactionKind {
4881
CommissionChange(Option<CommissionChange>),
4982
RevealPk(Option<RevealPkData>),
5083
BecomeValidator(Option<Box<BecomeValidator>>),
51-
Unknown,
84+
Unknown(Option<UnknownTransaction>),
5285
}
5386

5487
impl TransactionKind {
5588
pub fn to_json(&self) -> Option<String> {
5689
serde_json::to_string(&self).ok()
5790
}
5891

59-
pub fn from(tx_kind_name: &str, data: &[u8]) -> Self {
92+
pub fn from(id: &str, tx_kind_name: &str, data: &[u8]) -> Self {
6093
match tx_kind_name {
6194
"tx_transfer" => {
6295
let data = if let Ok(data) = Transfer::try_from_slice(data) {
@@ -174,7 +207,11 @@ impl TransactionKind {
174207
}
175208
_ => {
176209
tracing::warn!("Unknown transaction kind: {}", tx_kind_name);
177-
TransactionKind::Unknown
210+
TransactionKind::Unknown(Some(UnknownTransaction {
211+
id: Some(id.to_string()),
212+
name: Some(tx_kind_name.to_string()),
213+
data: Some(data.to_vec()),
214+
}))
178215
}
179216
}
180217
}
@@ -325,12 +362,20 @@ impl Transaction {
325362
if let Some(tx_kind_name) =
326363
checksums.get_name_by_id(&id)
327364
{
328-
TransactionKind::from(&tx_kind_name, &tx_data)
365+
TransactionKind::from(&id, &tx_kind_name, &tx_data)
329366
} else {
330-
TransactionKind::Unknown
367+
TransactionKind::Unknown(Some(UnknownTransaction {
368+
id: Some(id),
369+
name: None,
370+
data: Some(tx_data.clone()),
371+
}))
331372
}
332373
} else {
333-
TransactionKind::Unknown
374+
TransactionKind::Unknown(Some(UnknownTransaction {
375+
id: None,
376+
name: None,
377+
data: Some(tx_data.clone()),
378+
}))
334379
};
335380

336381
let encoded_tx_data = if !tx_data.is_empty() {

transactions/src/repository/transactions.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@ pub fn insert_inner_transactions(
1818
.map(InnerTransactionInsertDb::from)
1919
.collect::<Vec<_>>(),
2020
)
21+
.on_conflict(inner_transactions::id)
22+
.do_update()
23+
.set((
24+
// Allow updating transactions kind + data so that if the indexer is updated with
25+
// new transaction type support, we can easily go back & reindex any old transactions
26+
// that were previously marked as "unknown".
27+
inner_transactions::kind.eq(excluded(inner_transactions::kind)),
28+
inner_transactions::data.eq(excluded(inner_transactions::data)),
29+
))
2130
.execute(transaction_conn)
2231
.context("Failed to insert inner transactions in db")?;
2332

@@ -34,6 +43,7 @@ pub fn insert_wrapper_transactions(
3443
.map(WrapperTransactionInsertDb::from)
3544
.collect::<Vec<_>>(),
3645
)
46+
.on_conflict_do_nothing()
3747
.execute(transaction_conn)
3848
.context("Failed to insert wrapper transactions in db")?;
3949

0 commit comments

Comments
 (0)