diff --git a/catalyst-gateway/bin/src/db/index/block/rbac509/mod.rs b/catalyst-gateway/bin/src/db/index/block/rbac509/mod.rs index 03e9c1ffb3f..86ac43a9e6f 100644 --- a/catalyst-gateway/bin/src/db/index/block/rbac509/mod.rs +++ b/catalyst-gateway/bin/src/db/index/block/rbac509/mod.rs @@ -9,7 +9,6 @@ use std::sync::{Arc, LazyLock}; use cardano_blockchain_types::{Cip0134Uri, MultiEraBlock, Slot, TransactionHash, TxnIndex}; use catalyst_types::id_uri::IdUri; -use der_parser::{asn1_rs::oid, Oid}; use moka::{policy::EvictionPolicy, sync::Cache}; use pallas::ledger::addresses::Address; use rbac_registration::cardano::cip509::{Cip509, Cip509RbacMetadata}; @@ -27,13 +26,6 @@ use crate::{ settings::cassandra_db::EnvVars, }; -/// Context-specific primitive type with tag number 6 (`raw_tag` 134) for -/// uniform resource identifier (URI) in the subject alternative name extension. -pub const SAN_URI: u8 = 134; - -/// Subject Alternative Name OID -pub(crate) const SUBJECT_ALT_NAME_OID: Oid = oid!(2.5.29 .17); - /// A Catalyst ID by transaction ID cache. static CATALYST_ID_BY_TXN_ID_CACHE: LazyLock> = LazyLock::new(|| { Cache::builder() @@ -192,7 +184,7 @@ impl Rbac509InsertQuery { query_handles.push(tokio::spawn(async move { inner_session .execute_batch( - PreparedQuery::CatalystIdForTxnIdInsertQuery, + PreparedQuery::RbacCatalystIdForTxnIdInsertQuery, self.catalyst_id_for_txn_id, ) .await @@ -204,7 +196,7 @@ impl Rbac509InsertQuery { query_handles.push(tokio::spawn(async move { inner_session .execute_batch( - PreparedQuery::CatalystIdForStakeAddressInsertQuery, + PreparedQuery::RbacCatalystIdForStakeAddressInsertQuery, self.catalyst_id_for_stake_address, ) .await diff --git a/catalyst-gateway/bin/src/db/index/queries/cql/get_rbac_chain_root_for_stake_addr.cql b/catalyst-gateway/bin/src/db/index/queries/cql/get_rbac_chain_root_for_stake_addr.cql index bfd8db0dcd3..48f412c47fe 100644 --- a/catalyst-gateway/bin/src/db/index/queries/cql/get_rbac_chain_root_for_stake_addr.cql +++ b/catalyst-gateway/bin/src/db/index/queries/cql/get_rbac_chain_root_for_stake_addr.cql @@ -1,10 +1,8 @@ SELECT slot_no, txn, - chain_root, - chain_root_slot, - chain_root_txn + catalyst_id, FROM - rbac_chain_root_for_stake_addr + rbac_catalyst_id_for_stake_addr WHERE stake_addr = :stake_address diff --git a/catalyst-gateway/bin/src/db/index/queries/mod.rs b/catalyst-gateway/bin/src/db/index/queries/mod.rs index 4d75a9895b2..a55158e5add 100644 --- a/catalyst-gateway/bin/src/db/index/queries/mod.rs +++ b/catalyst-gateway/bin/src/db/index/queries/mod.rs @@ -34,7 +34,9 @@ use super::block::{ certs::CertInsertQuery, cip36::Cip36InsertQuery, rbac509::Rbac509InsertQuery, txi::TxiInsertQuery, txo::TxoInsertQuery, }; -use crate::settings::cassandra_db; +use crate::{ + db::index::queries::rbac::get_catalyst_id_from_transaction_id, settings::cassandra_db, +}; /// Batches of different sizes, prepared and ready for use. pub(crate) type SizedBatch = SkipMap>; @@ -68,9 +70,9 @@ pub(crate) enum PreparedQuery { /// Invalid RBAC 509 registration Insert query. Rbac509InvalidInsertQuery, /// Chain Root For Transaction ID Insert query. - CatalystIdForTxnIdInsertQuery, + RbacCatalystIdForTxnIdInsertQuery, /// Chain Root For Stake Address Insert query. - CatalystIdForStakeAddressInsertQuery, + RbacCatalystIdForStakeAddressInsertQuery, } /// All prepared SELECT query statements (return data). @@ -93,8 +95,8 @@ pub(crate) enum PreparedSelectQuery { CatalystIdByTransactionId, /// Get Catalyst ID by stake address. CatalystIdByStakeAddress, - /// Get registrations by chain root - RegistrationsByChainRoot, + /// Get registrations by Catalyst ID. + RegistrationsByCatalystId, /// Get all stake and vote keys for snapshot (`stake_pub_key,vote_key`) GetAllStakesAndVoteKeys, } @@ -137,9 +139,9 @@ pub(crate) struct PreparedQueries { /// Invalid RBAC 509 registrations. rbac509_invalid_registration_insert_queries: SizedBatch, /// Chain Root for TX ID Insert Query.. - catalyst_id_for_txn_id_insert_queries: SizedBatch, + rbac509_catalyst_id_for_txn_id_insert_queries: SizedBatch, /// Chain Root for Stake Address Insert Query.. - catalyst_id_for_stake_address_insert_queries: SizedBatch, + rbac509_catalyst_id_for_stake_address_insert_queries: SizedBatch, /// Get native assets by stake address query. native_assets_by_stake_address_query: PreparedStatement, /// Get registrations @@ -154,10 +156,10 @@ pub(crate) struct PreparedQueries { sync_status_insert: PreparedStatement, /// Get chain root by stake address catalyst_id_by_stake_address_query: PreparedStatement, - /// Get registrations by chain root - registrations_by_chain_root_query: PreparedStatement, /// Get chain root by transaction ID catalyst_id_by_transaction_id_query: PreparedStatement, + /// Get registrations by chain root + registrations_by_catalyst_id_query: PreparedStatement, /// Get all stake and vote keys (`stake_key,vote_key`) for snapshot get_all_stakes_and_vote_keys_query: PreparedStatement, } @@ -174,12 +176,13 @@ impl PreparedQueries { session: Arc, cfg: &cassandra_db::EnvVars, ) -> anyhow::Result { // We initialize like this, so that all errors preparing querys get shown before aborting. - let txi_insert_queries = TxiInsertQuery::prepare_batch(&session, cfg).await; + let txi_insert_queries = TxiInsertQuery::prepare_batch(&session, cfg).await?; let all_txo_queries = TxoInsertQuery::prepare_batch(&session, cfg).await; - let stake_registration_insert_queries = CertInsertQuery::prepare_batch(&session, cfg).await; + let stake_registration_insert_queries = + CertInsertQuery::prepare_batch(&session, cfg).await?; let all_cip36_queries = Cip36InsertQuery::prepare_batch(&session, cfg).await; let txo_spent_update_queries = - UpdateTxoSpentQuery::prepare_batch(session.clone(), cfg).await; + UpdateTxoSpentQuery::prepare_batch(session.clone(), cfg).await?; let txo_by_stake_address_query = GetTxoByStakeAddressQuery::prepare(session.clone()).await; let txi_by_txn_hash_query = GetTxiByTxnHashesQuery::prepare(session.clone()).await; let all_rbac_queries = Rbac509InsertQuery::prepare_batch(&session, cfg).await; @@ -190,13 +193,15 @@ impl PreparedQueries { let stake_addr_from_stake_hash = GetStakeAddrQuery::prepare(session.clone()).await; let stake_addr_from_vote_key = GetStakeAddrFromVoteKeyQuery::prepare(session.clone()).await; let invalid_registrations = GetInvalidRegistrationQuery::prepare(session.clone()).await; - let sync_status_insert = SyncStatusInsertQuery::prepare(session.clone()).await; - let chain_root_by_stake_address = - get_catalyst_id_from_stake_addr::Query::prepare(session.clone()).await; - let registrations_by_chain_root = - GetRegistrationsByCatalystIdQuery::prepare(session.clone()).await; + let sync_status_insert = SyncStatusInsertQuery::prepare(session.clone()).await?; + let catalyst_id_by_stake_address_query = + get_catalyst_id_from_stake_addr::Query::prepare(session.clone()).await?; + let catalyst_id_by_transaction_id_query = + get_catalyst_id_from_transaction_id::Query::prepare(session.clone()).await?; + let registrations_by_catalyst_id_query = + GetRegistrationsByCatalystIdQuery::prepare(session.clone()).await?; let get_all_stakes_and_vote_keys_query = - GetAllStakesAndVoteKeysQuery::prepare(session).await; + GetAllStakesAndVoteKeysQuery::prepare(session).await?; let ( txo_insert_queries, @@ -214,8 +219,8 @@ impl PreparedQueries { let ( rbac509_registration_insert_queries, rbac509_invalid_registration_insert_queries, - chain_root_for_txn_id_insert_queries, - chain_root_for_stake_address_insert_queries, + rbac509_catalyst_id_for_txn_id_insert_queries, + rbac509_catalyst_id_for_stake_address_insert_queries, ) = all_rbac_queries?; Ok(Self { @@ -223,26 +228,28 @@ impl PreparedQueries { txo_asset_insert_queries, unstaked_txo_insert_queries, unstaked_txo_asset_insert_queries, - txi_insert_queries: txi_insert_queries?, - stake_registration_insert_queries: stake_registration_insert_queries?, + txi_insert_queries, + stake_registration_insert_queries, cip36_registration_insert_queries, cip36_registration_error_insert_queries, cip36_registration_for_stake_address_insert_queries, - txo_spent_update_queries: txo_spent_update_queries?, + txo_spent_update_queries, txo_by_stake_address_query: txo_by_stake_address_query?, txi_by_txn_hash_query: txi_by_txn_hash_query?, rbac509_registration_insert_queries, rbac509_invalid_registration_insert_queries, - chain_root_for_txn_id_insert_queries, - chain_root_for_stake_address_insert_queries, + rbac509_catalyst_id_for_txn_id_insert_queries, + rbac509_catalyst_id_for_stake_address_insert_queries, native_assets_by_stake_address_query: native_assets_by_stake_address_query?, registration_from_stake_addr_query: registration_from_stake_addr_query?, stake_addr_from_stake_hash_query: stake_addr_from_stake_hash?, stake_addr_from_vote_key_query: stake_addr_from_vote_key?, invalid_registrations_from_stake_addr_query: invalid_registrations?, - sync_status_insert: sync_status_insert?, - registrations_by_chain_root_query: registrations_by_chain_root?, - get_all_stakes_and_vote_keys_query: get_all_stakes_and_vote_keys_query?, + sync_status_insert, + registrations_by_catalyst_id_query, + get_all_stakes_and_vote_keys_query, + catalyst_id_by_stake_address_query, + catalyst_id_by_transaction_id_query, }) } @@ -328,11 +335,14 @@ impl PreparedQueries { PreparedSelectQuery::InvalidRegistrationsFromStakeAddr => { &self.invalid_registrations_from_stake_addr_query }, - PreparedSelectQuery::RegistrationsByChainRoot => { - &self.registrations_by_chain_root_query + PreparedSelectQuery::RegistrationsByCatalystId => { + &self.registrations_by_catalyst_id_query + }, + PreparedSelectQuery::CatalystIdByTransactionId => { + &self.catalyst_id_by_transaction_id_query }, - PreparedSelectQuery::ChainRootByTransactionId => { - &self.chain_root_by_transaction_id_query + PreparedSelectQuery::CatalystIdByStakeAddress => { + &self.catalyst_id_by_stake_address_query }, PreparedSelectQuery::GetAllStakesAndVoteKeys => { &self.get_all_stakes_and_vote_keys_query @@ -371,11 +381,11 @@ impl PreparedQueries { PreparedQuery::Rbac509InvalidInsertQuery => { &self.rbac509_invalid_registration_insert_queries }, - PreparedQuery::CatalystIdForTxnIdInsertQuery => { - &self.catalyst_id_for_txn_id_insert_queries + PreparedQuery::RbacCatalystIdForTxnIdInsertQuery => { + &self.rbac509_catalyst_id_for_txn_id_insert_queries }, - PreparedQuery::CatalystIdForStakeAddressInsertQuery => { - &self.catalyst_id_for_stake_address_insert_queries + PreparedQuery::RbacCatalystIdForStakeAddressInsertQuery => { + &self.rbac509_catalyst_id_for_stake_address_insert_queries }, }; session_execute_batch(session, query_map, cfg, query, values).await diff --git a/catalyst-gateway/bin/src/db/index/queries/purge/mod.rs b/catalyst-gateway/bin/src/db/index/queries/purge/mod.rs index 96c65cf9288..49a285924f2 100644 --- a/catalyst-gateway/bin/src/db/index/queries/purge/mod.rs +++ b/catalyst-gateway/bin/src/db/index/queries/purge/mod.rs @@ -50,6 +50,8 @@ pub(crate) enum PreparedDeleteQuery { Cip36RegistrationForVoteKey, /// RBAC 509 Registration Delete query. Rbac509, + /// Invalid RBAC 509 Registration Delete query. + Rbac509Invalid, /// Chain Root For Transaction ID Delete query. ChainRootForTxnId, /// Chain Root For Stake Address Delete query. @@ -79,6 +81,8 @@ pub(crate) enum PreparedSelectQuery { Cip36RegistrationForVoteKey, /// RBAC 509 Registration Select query. Rbac509, + /// Invalid RBAC 509 Registration Select query. + Rbac509Invalid, /// Chain Root For Transaction ID Select query. CatalystIdForTxnId, /// Chain Root For Stake Address Select query. @@ -127,6 +131,10 @@ pub(crate) struct PreparedQueries { select_rbac509_registration: PreparedStatement, /// RBAC 509 Registrations Delete Query. delete_rbac509_registration: SizedBatch, + /// RBAC 509 invalid registrations Primary Key Query. + select_rbac509_invalid_registration: PreparedStatement, + /// RBAC 509 invalid registrations Delete Query. + delete_rbac509_invalid_registration: SizedBatch, /// Chain Root for TX ID Primary Key Query.. select_chain_root_for_txn_id: PreparedStatement, /// Chain Root for TX ID Delete Query.. @@ -185,6 +193,10 @@ impl PreparedQueries { &session, cfg, ) .await?, + select_rbac509_invalid_registration: + rbac509_invalid_registration::PrimaryKeyQuery::prepare(&session).await?, + delete_rbac509_invalid_registration: + rbac509_invalid_registration::DeleteQuery::prepare_batch(&session, cfg).await?, select_chain_root_for_txn_id: catalyst_id_for_txn_id::PrimaryKeyQuery::prepare( &session, ) @@ -241,6 +253,7 @@ impl PreparedQueries { &self.select_cip36_registration_for_vote_key }, PreparedSelectQuery::Rbac509 => &self.select_rbac509_registration, + PreparedSelectQuery::Rbac509Invalid => &self.select_rbac509_invalid_registration, PreparedSelectQuery::CatalystIdForTxnId => &self.select_chain_root_for_txn_id, PreparedSelectQuery::ChainRootForStakeAddress => { &self.select_chain_root_for_stake_address @@ -270,6 +283,7 @@ impl PreparedQueries { &self.delete_cip36_registration_for_vote_key }, PreparedDeleteQuery::Rbac509 => &self.delete_rbac509_registration, + PreparedDeleteQuery::Rbac509Invalid => &self.delete_rbac509_invalid_registration, PreparedDeleteQuery::ChainRootForTxnId => &self.delete_chain_root_for_txn_id, PreparedDeleteQuery::ChainRootForStakeAddress => { &self.delete_chain_root_for_stake_address diff --git a/catalyst-gateway/bin/src/db/index/queries/rbac/get_catalyst_id_from_stake_addr.rs b/catalyst-gateway/bin/src/db/index/queries/rbac/get_catalyst_id_from_stake_addr.rs index 26b3fabdb8c..95d9d89367f 100644 --- a/catalyst-gateway/bin/src/db/index/queries/rbac/get_catalyst_id_from_stake_addr.rs +++ b/catalyst-gateway/bin/src/db/index/queries/rbac/get_catalyst_id_from_stake_addr.rs @@ -2,7 +2,7 @@ use std::sync::{Arc, LazyLock}; -use anyhow::bail; +use anyhow::Context; use futures::StreamExt; use moka::{policy::EvictionPolicy, sync::Cache}; use pallas::ledger::addresses::StakeAddress; @@ -17,11 +17,11 @@ use crate::db::{ queries::{PreparedQueries, PreparedSelectQuery}, session::CassandraSession, }, - types::{DbSlot, DbTransactionHash, DbTxnIndex}, + types::{DbCatalystId, DbSlot, DbTxnIndex}, }; /// Cached Chain Root By Stake Address. -static CATALYST_ID_BY_STAKE_ADDRESS_CACHE: LazyLock> = +static CATALYST_ID_BY_STAKE_ADDRESS_CACHE: LazyLock> = LazyLock::new(|| { Cache::builder() // Set Eviction Policy to `LRU` @@ -30,95 +30,69 @@ static CATALYST_ID_BY_STAKE_ADDRESS_CACHE: LazyLock> .build() }); -/// Get get chain root by stake address query string. -const GET_CHAIN_ROOT: &str = include_str!("../cql/get_rbac_chain_root_for_stake_addr.cql"); +/// Get Catalyst ID by stake address query string. +const QUERY: &str = include_str!("../cql/get_rbac_chain_root_for_stake_addr.cql"); -/// Get chain root by stake address query params. +/// Get Catalyst ID by stake address query params. #[derive(SerializeRow)] pub(crate) struct QueryParams { - /// Stake address to get the chain root for. + /// Stake address to get the Catalyst ID for. pub(crate) stake_address: Vec, } -/// Get chain root by stake address query. -#[derive(DeserializeRow)] +/// Get Catalyst ID by stake address query. +#[derive(Debug, Clone, DeserializeRow)] pub(crate) struct Query { /// Slot Number the stake address was registered in. - pub(crate) slot_no: num_bigint::BigInt, + pub(crate) slot_no: DbSlot, /// Transaction Offset the stake address was registered in. pub(crate) txn: DbTxnIndex, - /// Chain root for the queries stake address. - pub(crate) chain_root: DbTransactionHash, - /// Chain roots slot number - pub(crate) chain_root_slot: DbSlot, - /// Chain roots txn index - pub(crate) chain_root_txn: DbTxnIndex, + /// Catalyst ID for the queries stake address. + pub(crate) catalyst_id: DbCatalystId, } impl Query { - /// Prepares a get chain root by stake address query. + /// Prepares a get Catalyst ID by stake address query. pub(crate) async fn prepare(session: Arc) -> anyhow::Result { - let get_chain_root_by_stake_address_query = PreparedQueries::prepare( - session, - GET_CHAIN_ROOT, - scylla::statement::Consistency::All, - true, - ) - .await; - - if let Err(ref error) = get_chain_root_by_stake_address_query { - error!(error=%error, "Failed to prepare get chain root by stake address query"); - }; - - get_chain_root_by_stake_address_query + PreparedQueries::prepare(session, QUERY, scylla::statement::Consistency::All, true) + .await + .inspect_err( + |e| error!(error=%e, "Failed to prepare get Catalyst ID by stake address query"), + ) } - /// Executes a get chain root by stake address query. + /// Executes a get Catalyst ID by stake address query. /// Don't call directly, use one of the methods instead. pub(crate) async fn execute( session: &CassandraSession, params: QueryParams, ) -> anyhow::Result> { - let iter = session - .execute_iter(PreparedSelectQuery::ChainRootByStakeAddress, params) + session + .execute_iter(PreparedSelectQuery::CatalystIdByStakeAddress, params) .await? - .rows_stream::()?; - - Ok(iter) + .rows_stream::() + .map_err(Into::into) } - /// Get latest Chain Root for a given stake address, uncached. + /// Get latest Catalyst ID for a given stake address, uncached. /// /// Unless you really know you need an uncached result, use the cached version. pub(crate) async fn get_latest_uncached( session: &CassandraSession, stake_addr: &StakeAddress, - ) -> anyhow::Result> { - let mut result = Self::execute(session, QueryParams { + ) -> anyhow::Result> { + Self::execute(session, QueryParams { stake_address: stake_addr.to_vec(), }) - .await?; - - match result.next().await { - Some(Ok(first_row)) => { - Ok(Some(ChainRoot::new( - first_row.chain_root.into(), - first_row.chain_root_slot.into(), - first_row.chain_root_txn.into(), - ))) - }, - Some(Err(err)) => { - bail!( - "Failed to get chain root by stake address query row: {}", - err - ); - }, - None => Ok(None), // Nothing found, but query ran OK. - } + .await? + .next() + .await + .transpose() + .context("Failed to get Catalyst ID by stake address query row") } /// Get latest chain-root registration for a stake address. pub(crate) async fn get_latest( session: &CassandraSession, stake_addr: &StakeAddress, - ) -> anyhow::Result> { + ) -> anyhow::Result> { match CATALYST_ID_BY_STAKE_ADDRESS_CACHE.get(stake_addr) { Some(chain_root) => Ok(Some(chain_root)), None => { @@ -130,6 +104,13 @@ impl Query { } /// Update the cache when a rbac registration is indexed. -pub(crate) fn cache_for_stake_addr(stake: &StakeAddress, catalyst_id: &str) { - CATALYST_ID_BY_STAKE_ADDRESS_CACHE.insert(stake.clone(), catalyst_id.to_owned()) +pub(crate) fn cache_for_stake_addr( + stake: &StakeAddress, slot_no: DbSlot, txn: DbTxnIndex, catalyst_id: DbCatalystId, +) { + let value = Query { + slot_no, + txn, + catalyst_id, + }; + CATALYST_ID_BY_STAKE_ADDRESS_CACHE.insert(stake.clone(), value) } diff --git a/catalyst-gateway/bin/src/db/index/queries/rbac/get_catalyst_id_from_transaction_id.rs b/catalyst-gateway/bin/src/db/index/queries/rbac/get_catalyst_id_from_transaction_id.rs index 1624bbcc7fa..e5fdccdf4f5 100644 --- a/catalyst-gateway/bin/src/db/index/queries/rbac/get_catalyst_id_from_transaction_id.rs +++ b/catalyst-gateway/bin/src/db/index/queries/rbac/get_catalyst_id_from_transaction_id.rs @@ -64,7 +64,7 @@ impl Query { session: &CassandraSession, params: QueryParams, ) -> Result> { session - .execute_iter(PreparedSelectQuery::ChainRootByStakeAddress, params) + .execute_iter(PreparedSelectQuery::CatalystIdByTransactionId, params) .await? .rows_stream::() .map_err(Into::into) diff --git a/catalyst-gateway/bin/src/db/index/queries/rbac/get_registrations.rs b/catalyst-gateway/bin/src/db/index/queries/rbac/get_registrations.rs index 0ba1b0a1799..a3d32068c1b 100644 --- a/catalyst-gateway/bin/src/db/index/queries/rbac/get_registrations.rs +++ b/catalyst-gateway/bin/src/db/index/queries/rbac/get_registrations.rs @@ -51,7 +51,7 @@ impl GetRegistrationsByCatalystIdQuery { session: &CassandraSession, params: GetRegistrationsByChainRootQueryParams, ) -> anyhow::Result> { let iter = session - .execute_iter(PreparedSelectQuery::RegistrationsByChainRoot, params) + .execute_iter(PreparedSelectQuery::RegistrationsByCatalystId, params) .await? .rows_stream::()?; diff --git a/catalyst-gateway/bin/src/service/api/cardano/rbac/chain_root_get.rs b/catalyst-gateway/bin/src/service/api/cardano/rbac/chain_root_get.rs index f3938aeef08..bda863a10be 100644 --- a/catalyst-gateway/bin/src/service/api/cardano/rbac/chain_root_get.rs +++ b/catalyst-gateway/bin/src/service/api/cardano/rbac/chain_root_get.rs @@ -1,6 +1,7 @@ //! Implementation of the GET `/rbac/chain_root` endpoint. use anyhow::anyhow; +use catalyst_types::id_uri::IdUri; use der_parser::asn1_rs::ToDer; use futures::StreamExt; use poem_openapi::{payload::Json, ApiResponse, Object}; @@ -76,8 +77,9 @@ pub(crate) async fn endpoint(stake_address: Cip19StakeAddress) -> AllResponses { }, }; + let id: IdUri = row.catalyst_id.into(); let res = Response { - chain_root: row.chain_root.to_string(), + chain_root: id.to_string(), }; Responses::Ok(Json(res)).into() diff --git a/catalyst-gateway/bin/src/service/utilities/convert.rs b/catalyst-gateway/bin/src/service/utilities/convert.rs index 90f8fe6bc18..04f5424dc59 100644 --- a/catalyst-gateway/bin/src/service/utilities/convert.rs +++ b/catalyst-gateway/bin/src/service/utilities/convert.rs @@ -28,20 +28,6 @@ pub(crate) fn from_saturating< } } -/// Convert a big uint to a u64, saturating if its out of range. -pub(crate) fn big_uint_to_u64(value: &num_bigint::BigInt) -> u64 { - let (sign, digits) = value.to_u64_digits(); - if sign == num_bigint::Sign::Minus || digits.is_empty() { - return 0; - } - if digits.len() > 1 { - return u64::MAX; - } - // 100% safe due to the above checks. - #[allow(clippy::indexing_slicing)] - digits[0] -} - #[cfg(test)] mod tests {