Skip to content

Commit

Permalink
feat: Add /cardano/sync_state endpoint, refactor (#359)
Browse files Browse the repository at this point in the history
* fix CardanoStakeAddress error handling

* refactor, add sync_state_get endpoint

* refactor types

* refactor

* add block_hash validation

* wip

* wip

* wip

* wip

* add check_network fn

* fix

* fix schematisis test

* try

* wip

* try

* try

* try

* try

* wip

* try

* try

* fix

* update Network

* wip

* wip

* fix

* fix
  • Loading branch information
Mr-Leshiy authored Apr 1, 2024
1 parent 147168e commit b258bbc
Show file tree
Hide file tree
Showing 35 changed files with 553 additions and 300 deletions.
65 changes: 30 additions & 35 deletions catalyst-gateway/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion catalyst-gateway/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ local-ip-address = "0.5.7"
gethostname = "0.4.3"
hex = "0.4.3"
async-recursion = "1.0.5"
pallas = "0.23.0"
pallas = { git = "https://github.com/input-output-hk/catalyst-pallas.git", branch = "fix/immutable-secondary", version = "0.24.0" }
anyhow = "1.0.71"
cardano-chain-follower= { git = "https://github.com/input-output-hk/hermes.git", version="0.0.1" }

Expand Down
2 changes: 1 addition & 1 deletion catalyst-gateway/Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ VERSION --try --global-cache 0.7

# Set up our target toolchains, and copy our files.
builder:
DO github.com/input-output-hk/catalyst-ci/earthly/rust:v2.10.0+SETUP
DO github.com/input-output-hk/catalyst-ci/earthly/rust:v2.10.1+SETUP

COPY --dir .cargo .config Cargo.* clippy.toml deny.toml rustfmt.toml bin crates tests .
COPY --dir ./event-db/queries ./event-db/queries
Expand Down
35 changes: 31 additions & 4 deletions catalyst-gateway/bin/src/event_db/config.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,46 @@
//! Config Queries
use std::str::FromStr;

use cardano_chain_follower::Network;
use serde::{Deserialize, Serialize};

use crate::event_db::{Error, EventDB};

#[derive(Serialize, Deserialize, Debug, PartialEq, PartialOrd, Clone)]
/// Representation of the `config` table id fields `id`, `id2`, `id3`
enum ConfigId {
/// `id` field
#[allow(dead_code)]
Id,
/// `id2` field
#[allow(dead_code)]
Id2,
/// `id3` field
Id3,
}

impl ConfigId {
/// Returns the id field as a string
fn as_str(&self) -> &str {
match self {
ConfigId::Id => "id",
ConfigId::Id2 => "id2",
ConfigId::Id3 => "id3",
}
}
}

#[derive(Debug, PartialEq, Clone)]
/// Network config metadata
pub(crate) struct FollowerConfig {
/// Mainnet, preview, preprod
pub(crate) network: String,
pub(crate) network: Network,
/// Cardano relay address
pub(crate) relay: String,
/// Mithril snapshot info
pub(crate) mithril_snapshot: MithrilSnapshotConfig,
}

#[derive(Serialize, Deserialize, Debug, PartialEq, PartialOrd, Clone)]
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
/// Follower metadata
pub(crate) struct MithrilSnapshotConfig {
/// Path to snapshot file for bootstrap
Expand All @@ -40,7 +66,8 @@ impl EventDB {

let mut follower_configs = Vec::new();
for row in rows {
let network = row.try_get("id3")?;
let network = Network::from_str(row.try_get::<_, &str>(ConfigId::Id3.as_str())?)
.map_err(|e| Error::Unknown(e.to_string()))?;
let config: serde_json::Value = row.try_get("value")?;

let relay = config
Expand Down
10 changes: 2 additions & 8 deletions catalyst-gateway/bin/src/event_db/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ pub(crate) enum Error {
#[error("DB URL is undefined")]
NoDatabaseUrl,
/// Cannot find this item
#[error("Cannot find this item, error: {0}")]
NotFound(String),
#[error("Cannot find this item")]
NotFound,
/// DB connection timeout
#[error("Connection to DB timed out")]
TimedOut,
Expand All @@ -38,12 +38,6 @@ pub(crate) enum Error {
#[error("Decode Error: {0}")]
/// Unable to decode hex
DecodeHex(String),
/// No previous followers hence no last updates metadata
#[error("LastUpdate metadata not present: {0}")]
NoLastUpdateMetadata(String),
/// Conversion error
#[error("Unable to convert u64 to i64 for sql type compatibility: {0}")]
SqlTypeConversionFailure(String),
/// Unable to extract policy assets
#[error("Unable parse assets: {0}")]
AssetParsingIssue(String),
Expand Down
30 changes: 12 additions & 18 deletions catalyst-gateway/bin/src/event_db/follower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,37 +49,31 @@ impl EventDB {
/// Check when last update occurred.
/// Start follower from where previous follower left off.
pub(crate) async fn last_updated_metadata(
&self, network: String,
&self, network: Network,
) -> Result<(SlotNumber, BlockHash, BlockTime), Error> {
let conn = self.pool.get().await?;

let network = match network {
Network::Mainnet => "mainnet".to_string(),
Network::Preview => "preview".to_string(),
Network::Preprod => "preprod".to_string(),
Network::Testnet => "testnet".to_string(),
};

let rows = conn
.query(
include_str!("../../../event-db/queries/follower/select_update_state.sql"),
&[&network],
)
.await?;
if rows.is_empty() {
return Err(Error::NoLastUpdateMetadata("No metadata".to_string()));
}

let Some(row) = rows.first() else {
return Err(Error::NoLastUpdateMetadata("No metadata".to_string()));
};

let slot_no = match row.try_get("slot_no") {
Ok(slot) => slot,
Err(e) => return Err(Error::NoLastUpdateMetadata(e.to_string())),
return Err(Error::NotFound);
};

let block_hash = match row.try_get::<_, Vec<u8>>("block_hash") {
Ok(block_hash) => hex::encode(block_hash),
Err(e) => return Err(Error::NoLastUpdateMetadata(e.to_string())),
};
let last_updated = match row.try_get("ended") {
Ok(last_updated) => last_updated,
Err(e) => return Err(Error::NoLastUpdateMetadata(e.to_string())),
};
let slot_no = row.try_get("slot_no")?;
let block_hash = hex::encode(row.try_get::<_, Vec<u8>>("block_hash")?);
let last_updated = row.try_get("ended")?;

Ok((slot_no, block_hash, last_updated))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,7 @@ impl EventDB {
&proposal.0,
])
.await?;
let row = rows
.first()
.ok_or_else(|| Error::NotFound("cat not find ballot value".to_string()))?;
let row = rows.first().ok_or(Error::NotFound)?;
let choices = row.try_get("objective")?;

let rows = conn
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,7 @@ impl EventDB {
let conn = self.pool.get().await?;

let rows = conn.query(Self::EVENT_QUERY, &[&event.0]).await?;
let row = rows
.first()
.ok_or_else(|| Error::NotFound("Cannot find event value".to_string()))?;
let row = rows.first().ok_or(Error::NotFound)?;

let ends = row
.try_get::<&'static str, Option<NaiveDateTime>>("end_time")?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,7 @@ impl EventDB {
let rows = conn
.query(Self::PROPOSAL_QUERY, &[&event.0, &objective.0, &proposal.0])
.await?;
let row = rows
.first()
.ok_or_else(|| Error::NotFound("Cannot find proposal value".to_string()))?;
let row = rows.first().ok_or(Error::NotFound)?;

let proposer = vec![ProposerDetails {
name: row.try_get("proposer_name")?,
Expand Down
16 changes: 5 additions & 11 deletions catalyst-gateway/bin/src/event_db/legacy/queries/registration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,7 @@ impl EventDB {
conn.query(Self::VOTER_BY_LAST_EVENT_QUERY, &[&voting_key])
.await?
};
let voter = rows
.first()
.ok_or_else(|| Error::NotFound("Cannot find voter value".to_string()))?;
let voter = rows.first().ok_or(Error::NotFound)?;

let voting_group = VoterGroupId(voter.try_get("voting_group")?);
let voting_power = voter.try_get("voting_power")?;
Expand All @@ -104,9 +102,7 @@ impl EventDB {

let total_voting_power_per_group: i64 = rows
.first()
.ok_or_else(|| {
Error::NotFound("Cannot find total voting power per group value".to_string())
})?
.ok_or(Error::NotFound)?
.try_get("total_voting_power")?;

let voting_power_saturation = if total_voting_power_per_group == 0 {
Expand Down Expand Up @@ -176,9 +172,7 @@ impl EventDB {
conn.query(Self::DELEGATOR_SNAPSHOT_INFO_BY_LAST_EVENT_QUERY, &[])
.await?
};
let delegator_snapshot_info = rows
.first()
.ok_or_else(|| Error::NotFound("Cannot find delegator value".to_string()))?;
let delegator_snapshot_info = rows.first().ok_or(Error::NotFound)?;

let delegation_rows = if let Some(event) = event {
conn.query(Self::DELEGATIONS_BY_EVENT_QUERY, &[
Expand All @@ -194,7 +188,7 @@ impl EventDB {
.await?
};
if delegation_rows.is_empty() {
return Err(Error::NotFound("Cannot find delegator value".to_string()));
return Err(Error::NotFound);
}

let mut delegations = Vec::new();
Expand All @@ -216,7 +210,7 @@ impl EventDB {
};
let total_power: i64 = rows
.first()
.ok_or_else(|| Error::NotFound("Cannot find total power value".to_string()))?
.ok_or(Error::NotFound)?
.try_get("total_voting_power")?;

#[allow(clippy::indexing_slicing)] // delegation_rows already checked to be not empty.
Expand Down
Loading

0 comments on commit b258bbc

Please sign in to comment.