Skip to content

Commit

Permalink
feat: implement GetCurrentPParams local state query (#322)
Browse files Browse the repository at this point in the history
  • Loading branch information
falcucci authored Jan 8, 2024
1 parent a6a6ffc commit 14e0809
Show file tree
Hide file tree
Showing 4 changed files with 251 additions and 3 deletions.
7 changes: 6 additions & 1 deletion examples/n2c-miniprotocols/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -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();
}

Expand Down
29 changes: 28 additions & 1 deletion pallas-network/src/miniprotocols/localstate/queries_v16/codec.rs
Original file line number Diff line number Diff line change
@@ -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<W: encode::Write>(
Expand Down Expand Up @@ -305,3 +305,30 @@ impl<C> minicbor::encode::Encode<C> for Value {
Ok(())
}
}

impl<'b, C> minicbor::decode::Decode<'b, C> for RationalNumber {
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
d.tag()?;
d.array()?;

Ok(RationalNumber {
numerator: d.decode_with(ctx)?,
denominator: d.decode_with(ctx)?,
})
}
}

impl<C> minicbor::encode::Encode<C> for RationalNumber {
fn encode<W: minicbor::encode::Write>(
&self,
e: &mut minicbor::Encoder<W>,
ctx: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> {
e.tag(Tag::Unassigned(30))?;
e.array(2)?;
e.encode_with(self.numerator, ctx)?;
e.encode_with(self.denominator, ctx)?;

Ok(())
}
}
105 changes: 105 additions & 0 deletions pallas-network/src/miniprotocols/localstate/queries_v16/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ pub enum HardForkQuery {
GetCurrentEra,
}

pub type Epoch = u64;
pub type Proto = u16;
pub type Era = u16;

Expand Down Expand Up @@ -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<i64>;

#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)]
#[cbor(map)]
pub struct CostMdls {
#[n(0)]
pub plutus_v1: Option<CostModel>,

#[n(1)]
pub plutus_v2: Option<CostModel>,
}

#[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<u32>,
#[n(1)]
pub minfee_b: Option<u32>,
#[n(2)]
pub max_block_body_size: Option<u32>,
#[n(3)]
pub max_transaction_size: Option<u32>,
#[n(4)]
pub max_block_header_size: Option<u32>,
#[n(5)]
pub key_deposit: Option<Coin>,
#[n(6)]
pub pool_deposit: Option<Coin>,
#[n(7)]
pub maximum_epoch: Option<Epoch>,
#[n(8)]
pub desired_number_of_stake_pools: Option<u32>,
#[n(9)]
pub pool_pledge_influence: Option<RationalNumber>,
#[n(10)]
pub expansion_rate: Option<UnitInterval>,
#[n(11)]
pub treasury_growth_rate: Option<UnitInterval>,
#[n(12)]
pub protocol_version_major: Option<ProtocolVersionMajor>,
#[n(13)]
pub protocol_version_minor: Option<ProtocolVersionMinor>,
#[n(14)]
pub min_pool_cost: Option<Coin>,
#[n(15)]
pub ada_per_utxo_byte: Option<Coin>,
#[n(16)]
pub cost_models_for_script_languages: Option<CostMdls>,
#[n(17)]
pub execution_costs: Option<ExUnitPrices>,
#[n(18)]
pub max_tx_ex_units: Option<ExUnits>,
#[n(19)]
pub max_block_ex_units: Option<ExUnits>,
#[n(20)]
pub max_value_size: Option<u32>,
#[n(21)]
pub collateral_percentage: Option<u32>,
#[n(22)]
pub max_collateral_inputs: Option<u32>,
}

#[derive(Debug, Encode, Decode, PartialEq)]
pub struct StakeDistribution {
#[n(0)]
Expand Down Expand Up @@ -179,6 +272,18 @@ pub async fn get_system_start(client: &mut Client) -> Result<SystemStart, Client
Ok(result)
}

pub async fn get_current_pparams(
client: &mut Client,
era: u16,
) -> Result<Vec<ProtocolParam>, 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<u32, ClientError> {
let query = BlockQuery::GetEpochNo;
let query = LedgerQuery::BlockQuery(era, query);
Expand Down
113 changes: 112 additions & 1 deletion pallas-network/tests/protocols.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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<localstate::queries_v16::ProtocolParam> = 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()
Expand Down

0 comments on commit 14e0809

Please sign in to comment.