Skip to content

Commit fca1d62

Browse files
cong-orstevenj
andauthored
feat(cat-gateway): CIP36 Registration queries (#933)
* feat(barebones): scylla queries * feat(barebones): scylla queries * feat(barebones): scylla queries * feat(barebones): scylla queries * feat(barebones): scylla queries * feat(latest registration endpoints): given stake addr and stake key hash * feat(latest registration endpoints): given stake addr and stake key hash * feat(latest registration endpoints): given stake addr and stake key hash * feat(latest registration endpoints): given stake addr and stake key hash * feat(latest registration endpoints): given stake addr and stake key hash * feat(latest registration endpoints): given stake addr and stake key hash * feat(latest registration endpoints): given stake addr and stake key hash * feat(latest registration endpoints): given stake addr and stake key hash * feat(latest registration endpoints): given stake addr and stake key hash * feat(latest registration endpoints): given stake addr and stake key hash * feat(latest registration endpoints): given stake addr and stake key hash * feat(latest registration endpoints): given stake addr and stake key hash * feat(latest registration endpoints): given stake addr and stake key hash * refactor(stake addr voting key association): check pair is active stake addresses need to be individually checked to make sure they are still actively associated with the voting key, and have not been registered to another voting key. * feat(invalids): add error reporting in resp * feat(error reporting): invalids include any erroneous registrations which occur AFTER the slot# of the last valid registration * feat(error reporting): invalids include any erroneous registrations which occur AFTER the slot# of the last valid registration * refactor(docs): clean * refactor(housekeeping): clean * feat(error reporting): vote key * feat(error reporting): vote key * feat(error reporting): vote key * fix(code formatting): format * style(spelling): cspell * fix(cat-gateway): spelling * fix(cat-gateway): docs * fix(cat-gateway): generated dart openapi files * ci(docs): lints * ci(docs): lints * fix(cat-gateway): bump cache version * docs(cat-gateway): fix docs * ci(oai lints): add missing endpoint annotations --------- Co-authored-by: Steven Johnson <[email protected]> Co-authored-by: Steven Johnson <[email protected]>
1 parent d3346f9 commit fca1d62

20 files changed

+1356
-8
lines changed

.config/dictionaries/project.dic

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ adminer
77
afinet
88
androidx
99
anypolicy
10+
appbar
1011
appspot
1112
Arbritrary
1213
ARGB
@@ -294,4 +295,3 @@ xctestrun
294295
xcworkspace
295296
xvfb
296297
yoroi
297-
appbar

catalyst-gateway/Earthfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ COPY_SRC:
1616

1717
# builder : Set up our target toolchains, and copy our files.
1818
builder:
19-
DO rust-ci+SETUP
19+
DO rust-ci+SETUP --CACHE_VERSION="00002"
2020

2121
# sync-cfg: Synchronize local config with CI version.
2222
# Must be run by the developer manually.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
SELECT error_report,
2+
stake_address,
3+
vote_key,
4+
payment_address,
5+
is_payable,
6+
cip36
7+
FROM cip36_registration_invalid
8+
WHERE stake_address = :stake_address
9+
AND slot_no >= :slot_no
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
SELECT stake_address,
2+
nonce,
3+
slot_no,
4+
txn,
5+
vote_key,
6+
payment_address,
7+
is_payable,
8+
cip36
9+
FROM cip36_registration
10+
WHERE stake_address = :stake_address
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
SELECT stake_address
2+
FROM stake_registration
3+
WHERE stake_hash = :stake_hash;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
SELECT stake_address
2+
FROM cip36_registration_for_vote_key
3+
WHERE vote_key = :vote_key
4+
ALLOW FILTERING;

catalyst-gateway/bin/src/db/index/queries/mod.rs

+42-4
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,18 @@
22
//!
33
//! This improves query execution time.
44
5+
pub(crate) mod registrations;
56
pub(crate) mod staked_ada;
67
pub(crate) mod sync_status;
78

89
use std::{fmt::Debug, sync::Arc};
910

1011
use anyhow::{bail, Context};
1112
use crossbeam_skiplist::SkipMap;
13+
use registrations::{
14+
get_from_stake_addr::GetRegistrationQuery, get_from_stake_hash::GetStakeAddrQuery,
15+
get_from_vote_key::GetStakeAddrFromVoteKeyQuery, get_invalid::GetInvalidRegistrationQuery,
16+
};
1217
use scylla::{
1318
batch::Batch, prepared_statement::PreparedStatement, serialize::row::SerializeRow,
1419
transport::iterator::RowIterator, QueryResult, Session,
@@ -56,9 +61,17 @@ pub(crate) enum PreparedQuery {
5661
/// All prepared SELECT query statements (return data).
5762
pub(crate) enum PreparedSelectQuery {
5863
/// Get TXO by stake address query.
59-
GetTxoByStakeAddress,
64+
TxoByStakeAddress,
6065
/// Get TXI by transaction hash query.
61-
GetTxiByTransactionHash,
66+
TxiByTransactionHash,
67+
/// Get Registrations
68+
RegistrationFromStakeAddr,
69+
/// Get invalid Registration
70+
InvalidRegistrationsFromStakeAddr,
71+
/// Get stake addr from stake hash
72+
StakeAddrFromStakeHash,
73+
/// Get stake addr from vote key
74+
StakeAddrFromVoteKey,
6275
}
6376

6477
/// All prepared UPSERT query statements (inserts/updates a single value of data).
@@ -94,6 +107,14 @@ pub(crate) struct PreparedQueries {
94107
txo_by_stake_address_query: PreparedStatement,
95108
/// Get TXI by transaction hash.
96109
txi_by_txn_hash_query: PreparedStatement,
110+
/// Get registrations
111+
registration_from_stake_addr_query: PreparedStatement,
112+
/// stake addr from stake hash
113+
stake_addr_from_stake_hash_query: PreparedStatement,
114+
/// stake addr from vote key
115+
stake_addr_from_vote_key_query: PreparedStatement,
116+
/// Get invalid registrations
117+
invalid_registrations_from_stake_addr_query: PreparedStatement,
97118
/// Insert Sync Status update.
98119
sync_status_insert: PreparedStatement,
99120
}
@@ -120,6 +141,11 @@ impl PreparedQueries {
120141
UpdateTxoSpentQuery::prepare_batch(session.clone(), cfg).await;
121142
let txo_by_stake_address_query = GetTxoByStakeAddressQuery::prepare(session.clone()).await;
122143
let txi_by_txn_hash_query = GetTxiByTxnHashesQuery::prepare(session.clone()).await;
144+
let registration_from_stake_addr_query =
145+
GetRegistrationQuery::prepare(session.clone()).await;
146+
let stake_addr_from_stake_hash = GetStakeAddrQuery::prepare(session.clone()).await;
147+
let stake_addr_from_vote_key = GetStakeAddrFromVoteKeyQuery::prepare(session.clone()).await;
148+
let invalid_registrations = GetInvalidRegistrationQuery::prepare(session.clone()).await;
123149
let sync_status_insert = SyncStatusInsertQuery::prepare(session).await;
124150

125151
let (
@@ -148,6 +174,10 @@ impl PreparedQueries {
148174
txo_spent_update_queries: txo_spent_update_queries?,
149175
txo_by_stake_address_query: txo_by_stake_address_query?,
150176
txi_by_txn_hash_query: txi_by_txn_hash_query?,
177+
registration_from_stake_addr_query: registration_from_stake_addr_query?,
178+
stake_addr_from_stake_hash_query: stake_addr_from_stake_hash?,
179+
stake_addr_from_vote_key_query: stake_addr_from_vote_key?,
180+
invalid_registrations_from_stake_addr_query: invalid_registrations?,
151181
sync_status_insert: sync_status_insert?,
152182
})
153183
}
@@ -223,8 +253,16 @@ impl PreparedQueries {
223253
) -> anyhow::Result<RowIterator>
224254
where P: SerializeRow {
225255
let prepared_stmt = match select_query {
226-
PreparedSelectQuery::GetTxoByStakeAddress => &self.txo_by_stake_address_query,
227-
PreparedSelectQuery::GetTxiByTransactionHash => &self.txi_by_txn_hash_query,
256+
PreparedSelectQuery::TxoByStakeAddress => &self.txo_by_stake_address_query,
257+
PreparedSelectQuery::TxiByTransactionHash => &self.txi_by_txn_hash_query,
258+
PreparedSelectQuery::RegistrationFromStakeAddr => {
259+
&self.registration_from_stake_addr_query
260+
},
261+
PreparedSelectQuery::StakeAddrFromStakeHash => &self.stake_addr_from_stake_hash_query,
262+
PreparedSelectQuery::StakeAddrFromVoteKey => &self.stake_addr_from_vote_key_query,
263+
PreparedSelectQuery::InvalidRegistrationsFromStakeAddr => {
264+
&self.invalid_registrations_from_stake_addr_query
265+
},
228266
};
229267

230268
session
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
//! Get stake addr registrations
2+
3+
use std::sync::Arc;
4+
5+
use scylla::{
6+
prepared_statement::PreparedStatement, transport::iterator::TypedRowIterator, SerializeRow,
7+
Session,
8+
};
9+
use tracing::error;
10+
11+
use crate::db::index::{
12+
queries::{PreparedQueries, PreparedSelectQuery},
13+
session::CassandraSession,
14+
};
15+
16+
/// Get registrations from stake addr query.
17+
const GET_REGISTRATIONS_FROM_STAKE_ADDR_QUERY: &str =
18+
include_str!("../cql/get_registrations_w_stake_addr.cql");
19+
20+
/// Get registration
21+
#[derive(SerializeRow)]
22+
pub(crate) struct GetRegistrationParams {
23+
/// Stake address.
24+
pub stake_address: Vec<u8>,
25+
}
26+
27+
impl GetRegistrationParams {
28+
/// Create a new instance of [`GetRegistrationParams`]
29+
pub(crate) fn new(stake_addr: Vec<u8>) -> GetRegistrationParams {
30+
Self {
31+
stake_address: stake_addr,
32+
}
33+
}
34+
}
35+
36+
/// Get registration given stake addr or vote key
37+
#[allow(clippy::expect_used)]
38+
mod result {
39+
use scylla::FromRow;
40+
41+
/// Get registration query result.
42+
#[derive(FromRow)]
43+
pub(crate) struct GetRegistrationQuery {
44+
/// Full Stake Address (not hashed, 32 byte ED25519 Public key).
45+
pub stake_address: Vec<u8>,
46+
/// Nonce value after normalization.
47+
pub nonce: num_bigint::BigInt,
48+
/// Slot Number the cert is in.
49+
pub slot_no: num_bigint::BigInt,
50+
/// Transaction Index.
51+
pub txn: i16,
52+
/// Voting Public Key
53+
pub vote_key: Vec<u8>,
54+
/// Full Payment Address (not hashed, 32 byte ED25519 Public key).
55+
pub payment_address: Vec<u8>,
56+
/// Is the stake address a script or not.
57+
pub is_payable: bool,
58+
/// Is the Registration CIP36 format, or CIP15
59+
pub cip36: bool,
60+
}
61+
}
62+
/// Get registration query.
63+
pub(crate) struct GetRegistrationQuery;
64+
65+
impl GetRegistrationQuery {
66+
/// Prepares a get registration query.
67+
pub(crate) async fn prepare(session: Arc<Session>) -> anyhow::Result<PreparedStatement> {
68+
let get_registrations_query = PreparedQueries::prepare(
69+
session,
70+
GET_REGISTRATIONS_FROM_STAKE_ADDR_QUERY,
71+
scylla::statement::Consistency::All,
72+
true,
73+
)
74+
.await;
75+
76+
if let Err(ref error) = get_registrations_query {
77+
error!(error=%error, "Failed to prepare get registration query.");
78+
};
79+
80+
get_registrations_query
81+
}
82+
83+
/// Executes get registration info for given stake addr query.
84+
pub(crate) async fn execute(
85+
session: &CassandraSession, params: GetRegistrationParams,
86+
) -> anyhow::Result<TypedRowIterator<result::GetRegistrationQuery>> {
87+
let iter = session
88+
.execute_iter(PreparedSelectQuery::RegistrationFromStakeAddr, params)
89+
.await?
90+
.into_typed::<result::GetRegistrationQuery>();
91+
92+
Ok(iter)
93+
}
94+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
//! Get stake addr from stake hash
2+
3+
use std::sync::Arc;
4+
5+
use scylla::{
6+
prepared_statement::PreparedStatement, transport::iterator::TypedRowIterator, SerializeRow,
7+
Session,
8+
};
9+
use tracing::error;
10+
11+
use crate::db::index::{
12+
queries::{PreparedQueries, PreparedSelectQuery},
13+
session::CassandraSession,
14+
};
15+
16+
/// Get stake addr from stake hash query string.
17+
const GET_STAKE_ADDR_FROM_STAKE_HASH: &str =
18+
include_str!("../cql/get_stake_addr_w_stake_key_hash.cql");
19+
20+
/// Get stake addr
21+
#[derive(SerializeRow)]
22+
pub(crate) struct GetStakeAddrParams {
23+
/// Stake hash.
24+
pub stake_hash: Vec<u8>,
25+
}
26+
27+
impl GetStakeAddrParams {
28+
/// Create a new instance of [`GetStakeAddrParams`]
29+
pub(crate) fn new(stake_hash: Vec<u8>) -> GetStakeAddrParams {
30+
Self { stake_hash }
31+
}
32+
}
33+
34+
/// Get stake addr from stake hash query string.
35+
#[allow(clippy::expect_used)]
36+
mod result {
37+
use scylla::FromRow;
38+
39+
/// Get stake addr from stake hash query result.
40+
#[derive(FromRow)]
41+
pub(crate) struct GetStakeAddrQuery {
42+
/// Full Stake Address (not hashed, 32 byte ED25519 Public key).
43+
pub stake_address: Vec<u8>,
44+
}
45+
}
46+
/// Get registration query.
47+
pub(crate) struct GetStakeAddrQuery;
48+
49+
impl GetStakeAddrQuery {
50+
/// Prepares a get get stake addr from stake hash query.
51+
pub(crate) async fn prepare(session: Arc<Session>) -> anyhow::Result<PreparedStatement> {
52+
let get_stake_addr_query = PreparedQueries::prepare(
53+
session,
54+
GET_STAKE_ADDR_FROM_STAKE_HASH,
55+
scylla::statement::Consistency::All,
56+
true,
57+
)
58+
.await;
59+
60+
if let Err(ref error) = get_stake_addr_query {
61+
error!(error=%error, "Failed to prepare get stake addr query.");
62+
};
63+
64+
get_stake_addr_query
65+
}
66+
67+
/// Executes a get txi by transaction hashes query.
68+
pub(crate) async fn execute(
69+
session: &CassandraSession, params: GetStakeAddrParams,
70+
) -> anyhow::Result<TypedRowIterator<result::GetStakeAddrQuery>> {
71+
let iter = session
72+
.execute_iter(PreparedSelectQuery::StakeAddrFromStakeHash, params)
73+
.await?
74+
.into_typed::<result::GetStakeAddrQuery>();
75+
76+
Ok(iter)
77+
}
78+
}

0 commit comments

Comments
 (0)