diff --git a/examples/n2c-miniprotocols/src/main.rs b/examples/n2c-miniprotocols/src/main.rs index ed1f139..4693f07 100644 --- a/examples/n2c-miniprotocols/src/main.rs +++ b/examples/n2c-miniprotocols/src/main.rs @@ -39,7 +39,9 @@ async fn do_localstate_query(client: &mut NodeClient) { let addrx: Address = Address::from_bech32(&addrx).unwrap(); let addrx: Addr = addrx.to_vec().into(); - let addry = "008c5bf0f2af6f1ef08bb3f6ec702dd16e1c514b7e1d12f7549b47db9f4d943c7af0aaec774757d4745d1a2c8dd3220e6ec2c9df23f757a2f8".to_string(); + let addry = + "008c5bf0f2af6f1ef08bb3f6ec702dd16e1c514b7e1d12f7549b47db9f4d943c7af0aaec774757d4745d1a2c8dd3220e6ec2c9df23f757a2f8" + .to_string(); let addry: Address = Address::from_hex(&addry).unwrap(); let addry: Addr = addry.to_vec().into(); @@ -49,6 +51,9 @@ async fn do_localstate_query(client: &mut NodeClient) { .unwrap(); info!("result: {:?}", result); + let result = queries_v16::get_current_pparams(client, era).await.unwrap(); + println!("result: {:?}", result); + client.send_release().await.unwrap(); } diff --git a/pallas-network/src/miniprotocols/localstate/queries_v16/codec.rs b/pallas-network/src/miniprotocols/localstate/queries_v16/codec.rs index 1bd9941..d157a6c 100644 --- a/pallas-network/src/miniprotocols/localstate/queries_v16/codec.rs +++ b/pallas-network/src/miniprotocols/localstate/queries_v16/codec.rs @@ -1,5 +1,5 @@ use super::*; -use pallas_codec::minicbor::{decode, encode, Decode, Decoder, Encode, Encoder}; +use pallas_codec::minicbor::{data::Tag, decode, encode, Decode, Decoder, Encode, Encoder}; impl Encode<()> for BlockQuery { fn encode( @@ -305,3 +305,30 @@ impl minicbor::encode::Encode for Value { Ok(()) } } + +impl<'b, C> minicbor::decode::Decode<'b, C> for RationalNumber { + fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result { + d.tag()?; + d.array()?; + + Ok(RationalNumber { + numerator: d.decode_with(ctx)?, + denominator: d.decode_with(ctx)?, + }) + } +} + +impl minicbor::encode::Encode for RationalNumber { + fn encode( + &self, + e: &mut minicbor::Encoder, + ctx: &mut C, + ) -> Result<(), minicbor::encode::Error> { + e.tag(Tag::Unassigned(30))?; + e.array(2)?; + e.encode_with(self.numerator, ctx)?; + e.encode_with(self.denominator, ctx)?; + + Ok(()) + } +} diff --git a/pallas-network/src/miniprotocols/localstate/queries_v16/mod.rs b/pallas-network/src/miniprotocols/localstate/queries_v16/mod.rs index 021a2aa..590034d 100644 --- a/pallas-network/src/miniprotocols/localstate/queries_v16/mod.rs +++ b/pallas-network/src/miniprotocols/localstate/queries_v16/mod.rs @@ -54,6 +54,7 @@ pub enum HardForkQuery { GetCurrentEra, } +pub type Epoch = u64; pub type Proto = u16; pub type Era = u16; @@ -89,6 +90,98 @@ pub struct SystemStart { pub picoseconds_of_day: u64, } +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct RationalNumber { + pub numerator: u64, + pub denominator: u64, +} + +pub type UnitInterval = RationalNumber; +pub type PositiveInterval = RationalNumber; + +pub type ProtocolVersionMajor = u64; +pub type ProtocolVersionMinor = u64; + +pub type CostModel = Vec; + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[cbor(map)] +pub struct CostMdls { + #[n(0)] + pub plutus_v1: Option, + + #[n(1)] + pub plutus_v2: Option, +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +pub struct ExUnitPrices { + #[n(0)] + mem_price: PositiveInterval, + + #[n(1)] + step_price: PositiveInterval, +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +pub struct ExUnits { + #[n(0)] + pub mem: u32, + #[n(1)] + pub steps: u64, +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[cbor(array)] +pub struct ProtocolParam { + #[n(0)] + pub minfee_a: Option, + #[n(1)] + pub minfee_b: Option, + #[n(2)] + pub max_block_body_size: Option, + #[n(3)] + pub max_transaction_size: Option, + #[n(4)] + pub max_block_header_size: Option, + #[n(5)] + pub key_deposit: Option, + #[n(6)] + pub pool_deposit: Option, + #[n(7)] + pub maximum_epoch: Option, + #[n(8)] + pub desired_number_of_stake_pools: Option, + #[n(9)] + pub pool_pledge_influence: Option, + #[n(10)] + pub expansion_rate: Option, + #[n(11)] + pub treasury_growth_rate: Option, + #[n(12)] + pub protocol_version_major: Option, + #[n(13)] + pub protocol_version_minor: Option, + #[n(14)] + pub min_pool_cost: Option, + #[n(15)] + pub ada_per_utxo_byte: Option, + #[n(16)] + pub cost_models_for_script_languages: Option, + #[n(17)] + pub execution_costs: Option, + #[n(18)] + pub max_tx_ex_units: Option, + #[n(19)] + pub max_block_ex_units: Option, + #[n(20)] + pub max_value_size: Option, + #[n(21)] + pub collateral_percentage: Option, + #[n(22)] + pub max_collateral_inputs: Option, +} + #[derive(Debug, Encode, Decode, PartialEq)] pub struct StakeDistribution { #[n(0)] @@ -179,6 +272,18 @@ pub async fn get_system_start(client: &mut Client) -> Result Result, ClientError> { + let query = BlockQuery::GetCurrentPParams; + let query = LedgerQuery::BlockQuery(era, query); + let query = Request::LedgerQuery(query); + let result = client.query(query).await?; + + Ok(result) +} + pub async fn get_block_epoch_number(client: &mut Client, era: u16) -> Result { let query = BlockQuery::GetEpochNo; let query = LedgerQuery::BlockQuery(era, query); diff --git a/pallas-network/tests/protocols.rs b/pallas-network/tests/protocols.rs index 436f07f..84f3d5a 100644 --- a/pallas-network/tests/protocols.rs +++ b/pallas-network/tests/protocols.rs @@ -8,7 +8,7 @@ use pallas_network::facades::{NodeClient, PeerClient, PeerServer}; use pallas_network::miniprotocols::blockfetch::BlockRequest; use pallas_network::miniprotocols::chainsync::{ClientRequest, HeaderContent, Tip}; use pallas_network::miniprotocols::handshake::n2n::VersionData; -use pallas_network::miniprotocols::localstate::queries_v16::{Addr, Addrs, Value}; +use pallas_network::miniprotocols::localstate::queries_v16::{Addr, Addrs, UnitInterval, Value}; use pallas_network::miniprotocols::localstate::ClientQueryRequest; use pallas_network::miniprotocols::txsubmission::{EraTxBody, TxIdAndSize}; use pallas_network::miniprotocols::{ @@ -599,6 +599,62 @@ pub async fn local_state_query_server_and_client_happy_path() { let result = AnyCbor::from_encode(localstate::queries_v16::UTxOByAddress { utxo }); server.statequery().send_result(result).await.unwrap(); + // server receives query from client + + let query: localstate::queries_v16::Request = + match server.statequery().recv_while_acquired().await.unwrap() { + ClientQueryRequest::Query(q) => q.into_decode().unwrap(), + x => panic!("unexpected message from client: {x:?}"), + }; + + assert_eq!( + query, + localstate::queries_v16::Request::LedgerQuery( + localstate::queries_v16::LedgerQuery::BlockQuery( + 5, + localstate::queries_v16::BlockQuery::GetCurrentPParams, + ), + ) + ); + assert_eq!(*server.statequery().state(), localstate::State::Querying); + + let result = AnyCbor::from_encode(vec![localstate::queries_v16::ProtocolParam { + minfee_a: Some(44), + minfee_b: Some(155381), + max_block_body_size: Some(65536), + max_transaction_size: Some(16384), + max_block_header_size: Some(1100), + key_deposit: Some(AnyUInt::U32(2000000)), + pool_deposit: Some(AnyUInt::U32(500000000)), + maximum_epoch: Some(100000), + desired_number_of_stake_pools: Some(500), + pool_pledge_influence: Some(UnitInterval { + numerator: 150, + denominator: 100, + }), + expansion_rate: Some(UnitInterval { + numerator: 3, + denominator: 1000000, + }), + treasury_growth_rate: Some(UnitInterval { + numerator: 3, + denominator: 1000000, + }), + protocol_version_major: Some(5), + protocol_version_minor: Some(0), + min_pool_cost: Some(AnyUInt::U32(340000000)), + ada_per_utxo_byte: Some(AnyUInt::U16(44)), + cost_models_for_script_languages: None, + execution_costs: None, + max_tx_ex_units: None, + max_block_ex_units: None, + max_value_size: None, + collateral_percentage: None, + max_collateral_inputs: None, + }]); + + server.statequery().send_result(result).await.unwrap(); + assert_eq!(*server.statequery().state(), localstate::State::Acquired); // server receives re-acquire from the client @@ -757,6 +813,61 @@ pub async fn local_state_query_server_and_client_happy_path() { assert_eq!(result, localstate::queries_v16::UTxOByAddress { utxo }); + let request = AnyCbor::from_encode(localstate::queries_v16::Request::LedgerQuery( + localstate::queries_v16::LedgerQuery::BlockQuery( + 5, + localstate::queries_v16::BlockQuery::GetCurrentPParams, + ), + )); + + client.statequery().send_query(request).await.unwrap(); + + let result: Vec = client + .statequery() + .recv_while_querying() + .await + .unwrap() + .into_decode() + .unwrap(); + + assert_eq!( + result, + vec![localstate::queries_v16::ProtocolParam { + minfee_a: Some(44), + minfee_b: Some(155381), + max_block_body_size: Some(65536), + max_transaction_size: Some(16384), + max_block_header_size: Some(1100), + key_deposit: Some(AnyUInt::U32(2000000)), + pool_deposit: Some(AnyUInt::U32(500000000)), + maximum_epoch: Some(100000), + desired_number_of_stake_pools: Some(500), + pool_pledge_influence: Some(UnitInterval { + numerator: 150, + denominator: 100, + }), + expansion_rate: Some(UnitInterval { + numerator: 3, + denominator: 1000000, + }), + treasury_growth_rate: Some(UnitInterval { + numerator: 3, + denominator: 1000000, + }), + protocol_version_major: Some(5), + protocol_version_minor: Some(0), + min_pool_cost: Some(AnyUInt::U32(340000000)), + ada_per_utxo_byte: Some(AnyUInt::U16(44)), + cost_models_for_script_languages: None, + execution_costs: None, + max_tx_ex_units: None, + max_block_ex_units: None, + max_value_size: None, + collateral_percentage: None, + max_collateral_inputs: None, + }] + ); + // client sends a ReAquire client .statequery()