Skip to content

Commit

Permalink
Define FMD Meta Parameters
Browse files Browse the repository at this point in the history
BREAKING: requires migration because we broke protobufs for shielded
pool params.
  • Loading branch information
cronokirby committed Apr 2, 2024
1 parent dba2702 commit 8b30eb9
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 14 deletions.
10 changes: 2 additions & 8 deletions crates/core/app/src/params/change.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,7 @@ impl AppParameters {
outbound_ics20_transfers_enabled: _,
},
sct_params: SctParameters { epoch_duration },
shielded_pool_params:
ShieldedPoolParameters {
fixed_fmd_params: _,
},
shielded_pool_params: ShieldedPoolParameters { fmd_meta_params: _ },
stake_params:
StakeParameters {
active_validator_limit,
Expand Down Expand Up @@ -149,10 +146,7 @@ impl AppParameters {
outbound_ics20_transfers_enabled,
},
sct_params: SctParameters { epoch_duration },
shielded_pool_params:
ShieldedPoolParameters {
fixed_fmd_params: _,
},
shielded_pool_params: ShieldedPoolParameters { fmd_meta_params: _ },
stake_params:
StakeParameters {
active_validator_limit,
Expand Down
43 changes: 43 additions & 0 deletions crates/core/component/shielded-pool/src/fmd.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use anyhow::anyhow;
use decaf377_fmd::Precision;
use penumbra_proto::{core::component::shielded_pool::v1 as pb, DomainType};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -45,3 +46,45 @@ impl Default for Parameters {
}
}
}

/// Meta parameters are an algorithm for dynamically choosing FMD parameters.
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(try_from = "pb::FmdMetaParameters", into = "pb::FmdMetaParameters")]
pub enum MetaParameters {
/// Used a fixed precision forever.
Fixed(Precision),
}

impl TryFrom<pb::FmdMetaParameters> for MetaParameters {
type Error = anyhow::Error;

fn try_from(value: pb::FmdMetaParameters) -> Result<Self, Self::Error> {
match value.algorithm.ok_or(anyhow!("missing algorithm"))? {
pb::fmd_meta_parameters::Algorithm::FixedPrecisionBits(p) => {
Ok(MetaParameters::Fixed(Precision::new(p as u8)?))
}
}
}
}

impl From<MetaParameters> for pb::FmdMetaParameters {
fn from(value: MetaParameters) -> Self {
match value {
MetaParameters::Fixed(p) => pb::FmdMetaParameters {
algorithm: Some(pb::fmd_meta_parameters::Algorithm::FixedPrecisionBits(
p.bits().into(),
)),
},
}
}
}

impl DomainType for MetaParameters {
type Proto = pb::FmdMetaParameters;
}

impl Default for MetaParameters {
fn default() -> Self {
Self::Fixed(Precision::default())
}
}
12 changes: 7 additions & 5 deletions crates/core/component/shielded-pool/src/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::fmd;
into = "pb::ShieldedPoolParameters"
)]
pub struct ShieldedPoolParameters {
pub fixed_fmd_params: fmd::Parameters,
pub fmd_meta_params: fmd::MetaParameters,
}

impl DomainType for ShieldedPoolParameters {
Expand All @@ -23,18 +23,20 @@ impl TryFrom<pb::ShieldedPoolParameters> for ShieldedPoolParameters {

fn try_from(msg: pb::ShieldedPoolParameters) -> anyhow::Result<Self> {
Ok(ShieldedPoolParameters {
fixed_fmd_params: msg
.fixed_fmd_params
.ok_or_else(|| anyhow::anyhow!("missing fmd_parameters"))?
fmd_meta_params: msg
.fmd_meta_params
.ok_or_else(|| anyhow::anyhow!("missing fmd_meta_params"))?
.try_into()?,
})
}
}

impl From<ShieldedPoolParameters> for pb::ShieldedPoolParameters {
fn from(params: ShieldedPoolParameters) -> Self {
#[allow(deprecated)]
pb::ShieldedPoolParameters {
fixed_fmd_params: Some(params.fixed_fmd_params.into()),
fmd_meta_params: Some(params.fmd_meta_params.into()),
fixed_fmd_params: None,
}
}
}
27 changes: 27 additions & 0 deletions crates/proto/src/gen/penumbra.core.component.shielded_pool.v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ShieldedPoolParameters {
#[deprecated]
#[prost(message, optional, tag = "1")]
pub fixed_fmd_params: ::core::option::Option<FmdParameters>,
#[prost(message, optional, tag = "2")]
pub fmd_meta_params: ::core::option::Option<FmdMetaParameters>,
}
impl ::prost::Name for ShieldedPoolParameters {
const NAME: &'static str = "ShieldedPoolParameters";
Expand Down Expand Up @@ -57,6 +60,30 @@ impl ::prost::Name for GenesisContent {
)
}
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct FmdMetaParameters {
#[prost(oneof = "fmd_meta_parameters::Algorithm", tags = "1")]
pub algorithm: ::core::option::Option<fmd_meta_parameters::Algorithm>,
}
/// Nested message and enum types in `FmdMetaParameters`.
pub mod fmd_meta_parameters {
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Oneof)]
pub enum Algorithm {
#[prost(uint32, tag = "1")]
FixedPrecisionBits(u32),
}
}
impl ::prost::Name for FmdMetaParameters {
const NAME: &'static str = "FmdMetaParameters";
const PACKAGE: &'static str = "penumbra.core.component.shielded_pool.v1";
fn full_name() -> ::prost::alloc::string::String {
::prost::alloc::format!(
"penumbra.core.component.shielded_pool.v1.{}", Self::NAME
)
}
}
/// Parameters for Fuzzy Message Detection
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
Expand Down
118 changes: 118 additions & 0 deletions crates/proto/src/gen/penumbra.core.component.shielded_pool.v1.serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,106 @@ impl<'de> serde::Deserialize<'de> for EventSpend {
deserializer.deserialize_struct("penumbra.core.component.shielded_pool.v1.EventSpend", FIELDS, GeneratedVisitor)
}
}
impl serde::Serialize for FmdMetaParameters {
#[allow(deprecated)]
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::ser::SerializeStruct;
let mut len = 0;
if self.algorithm.is_some() {
len += 1;
}
let mut struct_ser = serializer.serialize_struct("penumbra.core.component.shielded_pool.v1.FmdMetaParameters", len)?;
if let Some(v) = self.algorithm.as_ref() {
match v {
fmd_meta_parameters::Algorithm::FixedPrecisionBits(v) => {
struct_ser.serialize_field("fixedPrecisionBits", v)?;
}
}
}
struct_ser.end()
}
}
impl<'de> serde::Deserialize<'de> for FmdMetaParameters {
#[allow(deprecated)]
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
const FIELDS: &[&str] = &[
"fixed_precision_bits",
"fixedPrecisionBits",
];

#[allow(clippy::enum_variant_names)]
enum GeneratedField {
FixedPrecisionBits,
__SkipField__,
}
impl<'de> serde::Deserialize<'de> for GeneratedField {
fn deserialize<D>(deserializer: D) -> std::result::Result<GeneratedField, D::Error>
where
D: serde::Deserializer<'de>,
{
struct GeneratedVisitor;

impl<'de> serde::de::Visitor<'de> for GeneratedVisitor {
type Value = GeneratedField;

fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(formatter, "expected one of: {:?}", &FIELDS)
}

#[allow(unused_variables)]
fn visit_str<E>(self, value: &str) -> std::result::Result<GeneratedField, E>
where
E: serde::de::Error,
{
match value {
"fixedPrecisionBits" | "fixed_precision_bits" => Ok(GeneratedField::FixedPrecisionBits),
_ => Ok(GeneratedField::__SkipField__),
}
}
}
deserializer.deserialize_identifier(GeneratedVisitor)
}
}
struct GeneratedVisitor;
impl<'de> serde::de::Visitor<'de> for GeneratedVisitor {
type Value = FmdMetaParameters;

fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str("struct penumbra.core.component.shielded_pool.v1.FmdMetaParameters")
}

fn visit_map<V>(self, mut map_: V) -> std::result::Result<FmdMetaParameters, V::Error>
where
V: serde::de::MapAccess<'de>,
{
let mut algorithm__ = None;
while let Some(k) = map_.next_key()? {
match k {
GeneratedField::FixedPrecisionBits => {
if algorithm__.is_some() {
return Err(serde::de::Error::duplicate_field("fixedPrecisionBits"));
}
algorithm__ = map_.next_value::<::std::option::Option<::pbjson::private::NumberDeserialize<_>>>()?.map(|x| fmd_meta_parameters::Algorithm::FixedPrecisionBits(x.0));
}
GeneratedField::__SkipField__ => {
let _ = map_.next_value::<serde::de::IgnoredAny>()?;
}
}
}
Ok(FmdMetaParameters {
algorithm: algorithm__,
})
}
}
deserializer.deserialize_struct("penumbra.core.component.shielded_pool.v1.FmdMetaParameters", FIELDS, GeneratedVisitor)
}
}
impl serde::Serialize for FmdParameters {
#[allow(deprecated)]
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
Expand Down Expand Up @@ -2052,10 +2152,16 @@ impl serde::Serialize for ShieldedPoolParameters {
if self.fixed_fmd_params.is_some() {
len += 1;
}
if self.fmd_meta_params.is_some() {
len += 1;
}
let mut struct_ser = serializer.serialize_struct("penumbra.core.component.shielded_pool.v1.ShieldedPoolParameters", len)?;
if let Some(v) = self.fixed_fmd_params.as_ref() {
struct_ser.serialize_field("fixedFmdParams", v)?;
}
if let Some(v) = self.fmd_meta_params.as_ref() {
struct_ser.serialize_field("fmdMetaParams", v)?;
}
struct_ser.end()
}
}
Expand All @@ -2068,11 +2174,14 @@ impl<'de> serde::Deserialize<'de> for ShieldedPoolParameters {
const FIELDS: &[&str] = &[
"fixed_fmd_params",
"fixedFmdParams",
"fmd_meta_params",
"fmdMetaParams",
];

#[allow(clippy::enum_variant_names)]
enum GeneratedField {
FixedFmdParams,
FmdMetaParams,
__SkipField__,
}
impl<'de> serde::Deserialize<'de> for GeneratedField {
Expand All @@ -2096,6 +2205,7 @@ impl<'de> serde::Deserialize<'de> for ShieldedPoolParameters {
{
match value {
"fixedFmdParams" | "fixed_fmd_params" => Ok(GeneratedField::FixedFmdParams),
"fmdMetaParams" | "fmd_meta_params" => Ok(GeneratedField::FmdMetaParams),
_ => Ok(GeneratedField::__SkipField__),
}
}
Expand All @@ -2116,6 +2226,7 @@ impl<'de> serde::Deserialize<'de> for ShieldedPoolParameters {
V: serde::de::MapAccess<'de>,
{
let mut fixed_fmd_params__ = None;
let mut fmd_meta_params__ = None;
while let Some(k) = map_.next_key()? {
match k {
GeneratedField::FixedFmdParams => {
Expand All @@ -2124,13 +2235,20 @@ impl<'de> serde::Deserialize<'de> for ShieldedPoolParameters {
}
fixed_fmd_params__ = map_.next_value()?;
}
GeneratedField::FmdMetaParams => {
if fmd_meta_params__.is_some() {
return Err(serde::de::Error::duplicate_field("fmdMetaParams"));
}
fmd_meta_params__ = map_.next_value()?;
}
GeneratedField::__SkipField__ => {
let _ = map_.next_value::<serde::de::IgnoredAny>()?;
}
}
}
Ok(ShieldedPoolParameters {
fixed_fmd_params: fixed_fmd_params__,
fmd_meta_params: fmd_meta_params__,
})
}
}
Expand Down
Binary file modified crates/proto/src/gen/proto_descriptor.bin.no_lfs
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import "penumbra/crypto/tct/v1/tct.proto";

// Configuration data for the shielded pool component.
message ShieldedPoolParameters {
FmdParameters fixed_fmd_params = 1;
FmdParameters fixed_fmd_params = 1 [deprecated = true];
FmdMetaParameters fmd_meta_params = 2;
}

// Genesis data for the shielded pool component.
Expand All @@ -26,6 +27,12 @@ message GenesisContent {
repeated Allocation allocations = 3;
}

message FmdMetaParameters {
oneof algorithm {
uint32 fixed_precision_bits = 1;
}
}

// Parameters for Fuzzy Message Detection
message FmdParameters {
uint32 precision_bits = 1;
Expand Down

0 comments on commit 8b30eb9

Please sign in to comment.