Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ETCM-8596 query ogmios for network params instead of asking user for them #157

Merged
merged 2 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ provider will not query the main chain state or produce inherent data at all.
* Implemented batch queries and caching for the native token observability. Improves performance of the full-sync.
* Decoupled the native token inherent data provider from the `main-chain-follower-api` crate.
* Added ogmios-client interal library for communication with Ogmios
* Using Ogmios for reading Cardano Network parameters in `partner-chains-cli`, instead of asking user to choose them

## Removed

Expand Down
7 changes: 7 additions & 0 deletions partner-chains-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ thiserror = { workspace = true }
tempfile = { workspace = true }
secp256k1 = { workspace = true, features = ["std"] }
colored = { version = "2.1.0" }
jsonrpsee = { workspace = true, features = [
"client-core",
"http-client",
"macros",
] }
ogmios-client = { workspace = true, features = ["jsonrpsee-client"] }
tokio = { workspace = true }

[dev-dependencies]
pretty_assertions = { workspace = true }
34 changes: 7 additions & 27 deletions partner-chains-cli/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::config::config_fields::{
CARDANO_ACTIVE_SLOTS_COEFF, CARDANO_EPOCH_DURATION_MILLIS, CARDANO_FIRST_EPOCH_NUMBER,
CARDANO_FIRST_EPOCH_TIMESTAMP_MILLIS, CARDANO_FIRST_SLOT_NUMBER, CARDANO_SECURITY_PARAMETER,
CARDANO_FIRST_EPOCH_TIMESTAMP_MILLIS, CARDANO_FIRST_SLOT_NUMBER, CARDANO_NETWORK,
CARDANO_SECURITY_PARAMETER,
};
use crate::io::IOContext;
use anyhow::anyhow;
Expand Down Expand Up @@ -274,41 +275,17 @@ impl CardanoNetwork {
}
}

impl FromStr for CardanoNetwork {
type Err = String;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"mainnet" => Ok(CardanoNetwork(0)),
"preprod" => Ok(CardanoNetwork(1)),
"preview" => Ok(CardanoNetwork(2)),
_ => Ok(CardanoNetwork(3)),
}
}
}

impl std::fmt::Display for CardanoNetwork {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
CardanoNetwork(0) => write!(f, "mainnet"),
CardanoNetwork(1) => write!(f, "preprod"),
CardanoNetwork(2) => write!(f, "preview"),
CardanoNetwork(_) => write!(f, "custom"),
CardanoNetwork(n) => write!(f, "custom({})", n),
}
}
}

impl SelectOptions for CardanoNetwork {
fn select_options() -> Vec<String> {
vec![
CardanoNetwork(0).to_string(),
CardanoNetwork(1).to_string(),
CardanoNetwork(2).to_string(),
CardanoNetwork(3).to_string(),
]
}
}

#[derive(Deserialize)]
pub struct MainChainAddresses {
pub committee_candidates_address: String,
Expand All @@ -324,10 +301,12 @@ pub struct CardanoParameters {
pub first_slot_number: u64,
pub epoch_duration_millis: u64,
pub first_epoch_timestamp_millis: u64,
pub network: CardanoNetwork,
}

impl CardanoParameters {
pub fn save(&self, context: &impl IOContext) {
CARDANO_NETWORK.save_to_file(&self.network, context);
CARDANO_SECURITY_PARAMETER.save_to_file(&self.security_parameter, context);
CARDANO_ACTIVE_SLOTS_COEFF.save_to_file(&self.active_slots_coeff, context);
CARDANO_FIRST_EPOCH_NUMBER.save_to_file(&self.first_epoch_number, context);
Expand All @@ -346,6 +325,7 @@ impl CardanoParameters {
epoch_duration_millis: CARDANO_EPOCH_DURATION_MILLIS.load_from_file(context)?,
first_epoch_timestamp_millis: CARDANO_FIRST_EPOCH_TIMESTAMP_MILLIS
.load_from_file(context)?,
network: CARDANO_NETWORK.load_from_file(context)?,
})
}
}
Expand Down Expand Up @@ -419,7 +399,7 @@ pub fn load_chain_config(context: &impl IOContext) -> anyhow::Result<ChainConfig
}

pub fn get_cardano_network_from_file(context: &impl IOContext) -> anyhow::Result<CardanoNetwork> {
config_fields::CARDANO_NETWORK.load_from_file(context).ok_or(anyhow!(
CARDANO_NETWORK.load_from_file(context).ok_or(anyhow!(
"Cardano network not configured. Please run prepare-main-chain-config command first."
))
}
Expand Down
6 changes: 6 additions & 0 deletions partner-chains-cli/src/io.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::ogmios::{ogmios_request, OgmiosRequest, OgmiosResponse};
use anyhow::{anyhow, Context};
use sp_core::offchain::Timestamp;
use std::path::PathBuf;
Expand Down Expand Up @@ -26,6 +27,7 @@ pub trait IOContext {
fn delete_file(&self, path: &str) -> anyhow::Result<()>;
fn set_env_var(&self, key: &str, value: &str);
fn current_timestamp(&self) -> Timestamp;
fn ogmios_rpc(&self, addr: &str, req: OgmiosRequest) -> anyhow::Result<OgmiosResponse>;
}

pub struct DefaultCmdRunContext;
Expand Down Expand Up @@ -154,6 +156,10 @@ impl IOContext for DefaultCmdRunContext {
.expect("Current time is always after unix epoch");
Timestamp::from_unix_millis(duration.as_millis() as u64)
}

fn ogmios_rpc(&self, addr: &str, req: OgmiosRequest) -> anyhow::Result<OgmiosResponse> {
ogmios_request(addr, req)
}
}

pub fn prompt_can_write<C: IOContext>(name: &str, path: &str, context: &C) -> bool {
Expand Down
1 change: 1 addition & 0 deletions partner-chains-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod generate_keys;
pub mod io;
pub mod keystore;
pub(crate) mod main_chain_follower;
pub(crate) mod ogmios;
pub(crate) mod pc_contracts_cli_resources;
pub(crate) mod permissioned_candidates;
mod prepare_configuration;
Expand Down
114 changes: 114 additions & 0 deletions partner-chains-cli/src/ogmios/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
use anyhow::anyhow;
use jsonrpsee::http_client::HttpClient;
use ogmios_client::{query_ledger_state::QueryLedgerState, query_network::QueryNetwork};

#[derive(Debug, Eq, PartialEq)]
pub enum OgmiosRequest {
QueryLedgerStateEraSummaries,
QueryNetworkShelleyGenesis,
}

#[derive(Debug)]
pub enum OgmiosResponse {
QueryLedgerStateEraSummaries(Vec<EraSummary>),
QueryNetworkShelleyGenesis(ShelleyGenesisConfiguration),
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct EraSummary {
pub start: EpochBoundary,
pub parameters: EpochParameters,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct EpochBoundary {
pub time_seconds: u64,
pub slot: u64,
pub epoch: u32,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct EpochParameters {
pub epoch_length: u32,
pub slot_length_millis: u64,
}

#[derive(Clone, Debug, PartialEq)]
pub struct ShelleyGenesisConfiguration {
pub network_magic: u32,
pub security_parameter: u32,
pub active_slots_coefficient: f64,
pub epoch_length: u32,
pub slot_length_millis: u64,
// Seconds since UNIX epoch
pub start_time: u64,
}

pub fn ogmios_request(addr: &str, req: OgmiosRequest) -> anyhow::Result<OgmiosResponse> {
let tokio_runtime = tokio::runtime::Runtime::new().map_err(|e| anyhow::anyhow!(e))?;
let client = HttpClient::builder().build(addr).map_err(|e| anyhow::anyhow!(e))?;
match req {
OgmiosRequest::QueryLedgerStateEraSummaries => {
let era_summaries =
tokio_runtime.block_on(client.era_summaries()).map_err(|e| anyhow::anyhow!(e))?;
let era_summaries = era_summaries.into_iter().map(From::from).collect();
Ok(OgmiosResponse::QueryLedgerStateEraSummaries(era_summaries))
},
OgmiosRequest::QueryNetworkShelleyGenesis => {
let shelley_genesis = tokio_runtime
.block_on(client.shelley_genesis_configuration())
.map_err(|e| anyhow::anyhow!(e))?;
let shelley_genesis = ShelleyGenesisConfiguration::try_from(shelley_genesis)?;
Ok(OgmiosResponse::QueryNetworkShelleyGenesis(shelley_genesis))
},
}
}

impl From<ogmios_client::query_ledger_state::EraSummary> for EraSummary {
fn from(era_summary: ogmios_client::query_ledger_state::EraSummary) -> Self {
Self {
start: From::from(era_summary.start),
parameters: From::from(era_summary.parameters),
}
}
}

impl From<ogmios_client::query_ledger_state::EpochBoundary> for EpochBoundary {
fn from(epoch_boundary: ogmios_client::query_ledger_state::EpochBoundary) -> Self {
Self {
time_seconds: epoch_boundary.time.seconds,
slot: epoch_boundary.slot,
epoch: epoch_boundary.epoch,
}
}
}

impl From<ogmios_client::query_ledger_state::EpochParameters> for EpochParameters {
fn from(epoch_boundary: ogmios_client::query_ledger_state::EpochParameters) -> Self {
Self {
epoch_length: epoch_boundary.epoch_length,
slot_length_millis: epoch_boundary.slot_length.milliseconds.into(),
}
}
}

impl TryFrom<ogmios_client::query_network::ShelleyGenesisConfigurationResponse>
for ShelleyGenesisConfiguration
{
type Error = anyhow::Error;

fn try_from(
shelley_genesis: ogmios_client::query_network::ShelleyGenesisConfigurationResponse,
) -> Result<Self, Self::Error> {
let active_slots_coefficient = TryFrom::try_from(shelley_genesis.active_slots_coefficient)
.map_err(|_| anyhow!("Cannot convert active_slots_coefficient"))?;
Ok(Self {
network_magic: shelley_genesis.network_magic,
security_parameter: shelley_genesis.security_parameter,
active_slots_coefficient,
epoch_length: shelley_genesis.epoch_length,
slot_length_millis: shelley_genesis.slot_length.milliseconds.into(),
start_time: shelley_genesis.start_time.unix_timestamp().try_into()?,
})
}
}
Loading
Loading