cat_gateway/db/index/block/cip36/
insert_cip36_invalid.rs

1//! Insert CIP36 Registration Query (Invalid Records)
2
3use std::{fmt::Debug, sync::Arc};
4
5use cardano_blockchain_types::{Cip36, Slot, TxnIndex, VotingPubKey};
6use pallas::ledger::addresses::ShelleyAddress;
7use scylla::{frame::value::MaybeUnset, SerializeRow, Session};
8use tracing::error;
9
10use crate::{
11    db::{
12        index::queries::{PreparedQueries, SizedBatch},
13        types::{DbSlot, DbTxnIndex},
14    },
15    settings::cassandra_db,
16};
17
18/// Index Registration by Stake Address (Invalid Registrations)
19const INSERT_CIP36_REGISTRATION_INVALID_QUERY: &str =
20    include_str!("./cql/insert_cip36_invalid.cql");
21
22/// Insert CIP-36 Registration Invalid Query Parameters
23#[derive(SerializeRow, Clone)]
24pub(crate) struct Params {
25    /// Full Stake Address (not hashed, 32 byte ED25519 Public key).
26    stake_public_key: Vec<u8>,
27    /// Slot Number the cert is in.
28    slot_no: DbSlot,
29    /// Transaction Index.
30    txn_index: DbTxnIndex,
31    /// Voting Public Key
32    vote_key: Vec<u8>,
33    /// Full Payment Address (not hashed, 32 byte ED25519 Public key).
34    payment_address: Vec<u8>,
35    /// Is the stake address a script or not.
36    is_payable: bool,
37    /// Raw nonce value.
38    raw_nonce: num_bigint::BigInt,
39    /// Nonce value after normalization.
40    nonce: num_bigint::BigInt,
41    /// Strict Catalyst validated.
42    cip36: MaybeUnset<bool>,
43    /// Signature validates.
44    signed: bool,
45    /// List of serialization errors.
46    problem_report: String,
47}
48
49impl Debug for Params {
50    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51        let cip36 = match self.cip36 {
52            MaybeUnset::Unset => "UNSET",
53            MaybeUnset::Set(v) => &format!("{v:?}"),
54        };
55        f.debug_struct("Params")
56            .field("stake_public_key", &self.stake_public_key)
57            .field("slot_no", &self.slot_no)
58            .field("txn_index", &self.txn_index)
59            .field("vote_key", &self.vote_key)
60            .field("payment_address", &self.payment_address)
61            .field("is_payable", &self.is_payable)
62            .field("raw_nonce", &self.raw_nonce)
63            .field("nonce", &self.nonce)
64            .field("cip36", &cip36)
65            .field("signed", &self.signed)
66            .field("problem_report", &self.problem_report)
67            .finish()
68    }
69}
70
71impl Params {
72    /// Create a new Insert Query.
73    pub fn new(
74        vote_key: Option<&VotingPubKey>, slot_no: Slot, txn_index: TxnIndex, cip36: &Cip36,
75    ) -> Self {
76        let stake_public_key = cip36
77            .stake_pk()
78            .map_or_else(Vec::new, |s| s.to_bytes().to_vec());
79        let vote_key = vote_key
80            .and_then(|k| k.voting_pk().map(|k| k.as_bytes().to_vec()))
81            .unwrap_or_default();
82        let is_cip36 = cip36.is_cip36().map_or(MaybeUnset::Unset, MaybeUnset::Set);
83        let payment_address = cip36
84            .payment_address()
85            .map_or(Vec::new(), ShelleyAddress::to_vec);
86        let problem_report = serde_json::to_string(cip36.err_report()).unwrap_or_else(|e| {
87            error!(
88                "Failed to serialize problem report: {e:?}. Report = {:?}",
89                cip36.err_report()
90            );
91            String::new()
92        });
93
94        Params {
95            stake_public_key,
96            slot_no: slot_no.into(),
97            txn_index: txn_index.into(),
98            vote_key,
99            payment_address,
100            is_payable: cip36.is_payable().unwrap_or_default(),
101            raw_nonce: cip36.raw_nonce().unwrap_or_default().into(),
102            nonce: cip36.nonce().unwrap_or_default().into(),
103            cip36: is_cip36,
104            signed: cip36.is_valid_signature(),
105            problem_report,
106        }
107    }
108
109    /// Prepare Batch of Insert CIP-36 Registration Index Data Queries
110    pub(crate) async fn prepare_batch(
111        session: &Arc<Session>, cfg: &cassandra_db::EnvVars,
112    ) -> anyhow::Result<SizedBatch> {
113        PreparedQueries::prepare_batch(
114            session.clone(),
115            INSERT_CIP36_REGISTRATION_INVALID_QUERY,
116            cfg,
117            scylla::statement::Consistency::Any,
118            true,
119            false,
120        )
121        .await
122        .inspect_err(|error| error!(error=%error,"Failed to prepare Insert CIP-36 Registration Invalid Query."))
123        .map_err(|error| anyhow::anyhow!("{error}\n--\n{INSERT_CIP36_REGISTRATION_INVALID_QUERY}"))
124    }
125}