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::Address;
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.payment_address().map_or(Vec::new(), Address::to_vec);
84        let problem_report = serde_json::to_string(cip36.err_report()).unwrap_or_else(|e| {
85            error!(
86                "Failed to serialize problem report: {e:?}. Report = {:?}",
87                cip36.err_report()
88            );
89            String::new()
90        });
91
92        Params {
93            stake_public_key,
94            slot_no: slot_no.into(),
95            txn_index: txn_index.into(),
96            vote_key,
97            payment_address,
98            is_payable: cip36.is_payable().unwrap_or_default(),
99            raw_nonce: cip36.raw_nonce().unwrap_or_default().into(),
100            nonce: cip36.nonce().unwrap_or_default().into(),
101            cip36: is_cip36,
102            signed: cip36.is_valid_signature(),
103            problem_report,
104        }
105    }
106
107    /// Prepare Batch of Insert CIP-36 Registration Index Data Queries
108    pub(crate) async fn prepare_batch(
109        session: &Arc<Session>, cfg: &cassandra_db::EnvVars,
110    ) -> anyhow::Result<SizedBatch> {
111        PreparedQueries::prepare_batch(
112            session.clone(),
113            INSERT_CIP36_REGISTRATION_INVALID_QUERY,
114            cfg,
115            scylla::statement::Consistency::Any,
116            true,
117            false,
118        )
119        .await
120        .inspect_err(|error| error!(error=%error,"Failed to prepare Insert CIP-36 Registration Invalid Query."))
121        .map_err(|error| anyhow::anyhow!("{error}\n--\n{INSERT_CIP36_REGISTRATION_INVALID_QUERY}"))
122    }
123}