cat_gateway/rbac/
provider.rs1use anyhow::Context;
4use cardano_chain_follower::{StakeAddress, hashes::TransactionId};
5use catalyst_types::catalyst_id::CatalystId;
6use ed25519_dalek::VerifyingKey;
7use futures::StreamExt;
8
9use crate::{
10 db::index::session::CassandraSession,
11 rbac::{
12 RbacBlockIndexingContext,
13 chains_cache::cached_persistent_rbac_chain,
14 get_chain::{apply_regs, build_rbac_chain, persistent_rbac_chain},
15 latest_rbac_chain,
16 },
17};
18
19pub(crate) struct RbacChainsProvider<'a> {
22 is_persistent: bool,
24 context: &'a RbacBlockIndexingContext,
26}
27
28impl<'a> RbacChainsProvider<'a> {
29 pub fn new(
31 is_persistent: bool,
32 context: &'a RbacBlockIndexingContext,
33 ) -> Self {
34 Self {
35 is_persistent,
36 context,
37 }
38 }
39
40 pub async fn catalyst_id_from_txn_id(
42 &self,
43 txn_id: TransactionId,
44 ) -> anyhow::Result<Option<CatalystId>> {
45 use crate::db::index::queries::rbac::get_catalyst_id_from_transaction_id::Query;
46
47 if let Some(catalyst_id) = self.context.find_transaction(&txn_id) {
49 return Ok(Some(catalyst_id.to_owned()));
50 }
51
52 let session =
54 CassandraSession::get(true).context("Failed to get Cassandra persistent session")?;
55 if let Some(id) = Query::get(&session, txn_id).await? {
56 return Ok(Some(id));
57 }
58
59 if !self.is_persistent {
61 let session =
62 CassandraSession::get(false).context("Failed to get Cassandra volatile session")?;
63 return Query::get(&session, txn_id).await;
64 }
65
66 Ok(None)
67 }
68}
69
70impl rbac_registration::cardano::provider::RbacChainsProvider for RbacChainsProvider<'_> {
71 async fn chain(
72 &self,
73 id: &CatalystId,
74 ) -> anyhow::Result<Option<rbac_registration::registration::cardano::RegistrationChain>> {
75 let chain = if self.is_persistent {
76 persistent_rbac_chain(id).await?
77 } else {
78 latest_rbac_chain(id).await?.map(|i| i.chain)
79 };
80
81 if let Some(regs) = self.context.find_registrations(id) {
83 let regs = regs.iter().cloned();
84 match chain {
85 Some(c) => return apply_regs(c, regs).await.map(Some),
86 None => return build_rbac_chain(regs).await,
87 }
88 }
89
90 Ok(chain)
91 }
92
93 async fn is_chain_known(
94 &self,
95 id: &CatalystId,
96 ) -> anyhow::Result<bool> {
97 if self.context.find_registrations(id).is_some() {
98 return Ok(true);
99 }
100
101 let session =
102 CassandraSession::get(true).context("Failed to get Cassandra persistent session")?;
103
104 if cached_persistent_rbac_chain(&session, id).is_some() {
107 return Ok(true);
108 }
109
110 if is_cat_id_known(&session, id).await? {
111 return Ok(true);
112 }
113
114 if !self.is_persistent {
116 let session =
117 CassandraSession::get(false).context("Failed to get Cassandra volatile session")?;
118 if is_cat_id_known(&session, id).await? {
119 return Ok(true);
120 }
121 }
122
123 Ok(false)
124 }
125
126 async fn chain_catalyst_id_from_stake_address(
127 &self,
128 address: &StakeAddress,
129 ) -> anyhow::Result<Option<CatalystId>> {
130 use crate::db::index::queries::rbac::get_catalyst_id_from_stake_address::Query;
131
132 if let Some(catalyst_id) = self.context.find_address(address) {
134 return Ok(Some(catalyst_id.to_owned()));
135 }
136
137 let session =
139 CassandraSession::get(true).context("Failed to get Cassandra persistent session")?;
140 if let Some(id) = Query::latest(&session, address).await? {
141 return Ok(Some(id));
142 }
143
144 if !self.is_persistent {
146 let session =
147 CassandraSession::get(false).context("Failed to get Cassandra volatile session")?;
148 return Query::latest(&session, address).await;
149 }
150
151 Ok(None)
152 }
153
154 async fn chain_catalyst_id_from_signing_public_key(
155 &self,
156 key: &VerifyingKey,
157 ) -> anyhow::Result<Option<CatalystId>> {
158 use crate::db::index::queries::rbac::get_catalyst_id_from_public_key::Query;
159
160 if let Some(catalyst_id) = self.context.find_public_key(key) {
162 return Ok(Some(catalyst_id.to_owned()));
163 }
164
165 let session =
167 CassandraSession::get(true).context("Failed to get Cassandra persistent session")?;
168 if let Some(id) = Query::get(&session, *key).await? {
169 return Ok(Some(id));
170 }
171
172 if !self.is_persistent {
174 let session =
175 CassandraSession::get(false).context("Failed to get Cassandra volatile session")?;
176 return Query::get(&session, *key).await;
177 }
178
179 Ok(None)
180 }
181}
182
183async fn is_cat_id_known(
185 session: &CassandraSession,
186 id: &CatalystId,
187) -> anyhow::Result<bool> {
188 use crate::db::index::queries::rbac::get_rbac_registrations::{Query, QueryParams};
189
190 Ok(Query::execute(session, QueryParams {
191 catalyst_id: id.clone().into(),
192 })
193 .await?
194 .next()
195 .await
196 .is_some())
197}