diff --git a/crates/cnidarium/src/gen/proto_descriptor.bin.no_lfs b/crates/cnidarium/src/gen/proto_descriptor.bin.no_lfs index c2c1f4df90..d50e1bd881 100644 Binary files a/crates/cnidarium/src/gen/proto_descriptor.bin.no_lfs and b/crates/cnidarium/src/gen/proto_descriptor.bin.no_lfs differ diff --git a/crates/core/app/src/params/change.rs b/crates/core/app/src/params/change.rs index 9f96c61478..78ff79d57d 100644 --- a/crates/core/app/src/params/change.rs +++ b/crates/core/app/src/params/change.rs @@ -25,7 +25,6 @@ impl AppParameters { new.check_valid()?; // TODO: move the checks below into their respective components. // Tracked by #3593 - let AppParameters { chain_id, community_pool_params: @@ -75,6 +74,7 @@ impl AppParameters { is_enabled: _, fixed_candidates: _, max_hops: _, + max_positions_per_pair: _, }, // IMPORTANT: Don't use `..` here! We want to ensure every single field is verified! } = self; @@ -169,6 +169,7 @@ impl AppParameters { is_enabled: _, fixed_candidates: _, max_hops: _, + max_positions_per_pair: _, }, // IMPORTANT: Don't use `..` here! We want to ensure every single field is verified! } = self; @@ -244,6 +245,7 @@ impl AppParameters { *min_validator_stake >= 1_000_000u128.into(), "the minimum validator stake must be at least 1penumbra", ), + // TODO(erwan): add a `max_positions_per_pair` check ]) } diff --git a/crates/core/component/dex/src/params.rs b/crates/core/component/dex/src/params.rs index 32233c251b..29ae3b2649 100644 --- a/crates/core/component/dex/src/params.rs +++ b/crates/core/component/dex/src/params.rs @@ -10,6 +10,7 @@ pub struct DexParameters { pub is_enabled: bool, pub fixed_candidates: Vec, pub max_hops: u32, + pub max_positions_per_pair: u32, } impl DomainType for DexParameters { @@ -28,6 +29,7 @@ impl TryFrom for DexParameters { .map(|id| id.try_into()) .collect::>()?, max_hops: msg.max_hops, + max_positions_per_pair: msg.max_positions_per_pair, }) } } @@ -42,6 +44,7 @@ impl From for pb::DexParameters { .map(Into::into) .collect(), max_hops: params.max_hops, + max_positions_per_pair: params.max_positions_per_pair, } } } @@ -63,6 +66,8 @@ impl Default for DexParameters { cache.get_unit("test_btc").unwrap().id(), ], max_hops: 4, + // TODO(erwan): setting this to 10 for testing. + max_positions_per_pair: 10, } } } diff --git a/crates/proto/src/gen/penumbra.core.component.dex.v1.rs b/crates/proto/src/gen/penumbra.core.component.dex.v1.rs index 316658f996..118449a51b 100644 --- a/crates/proto/src/gen/penumbra.core.component.dex.v1.rs +++ b/crates/proto/src/gen/penumbra.core.component.dex.v1.rs @@ -1509,6 +1509,11 @@ pub struct DexParameters { /// The number of hops to traverse while routing from A to B. #[prost(uint32, tag = "3")] pub max_hops: u32, + /// The maximum number of positions per trading pair. + /// If this number is exceeded, positions with the least + /// inventory get evicted from the DEX. + #[prost(uint32, tag = "4")] + pub max_positions_per_pair: u32, } impl ::prost::Name for DexParameters { const NAME: &'static str = "DexParameters"; diff --git a/crates/proto/src/gen/penumbra.core.component.dex.v1.serde.rs b/crates/proto/src/gen/penumbra.core.component.dex.v1.serde.rs index b7294296fc..a82e8bc664 100644 --- a/crates/proto/src/gen/penumbra.core.component.dex.v1.serde.rs +++ b/crates/proto/src/gen/penumbra.core.component.dex.v1.serde.rs @@ -1052,6 +1052,9 @@ impl serde::Serialize for DexParameters { if self.max_hops != 0 { len += 1; } + if self.max_positions_per_pair != 0 { + len += 1; + } let mut struct_ser = serializer.serialize_struct("penumbra.core.component.dex.v1.DexParameters", len)?; if self.is_enabled { struct_ser.serialize_field("isEnabled", &self.is_enabled)?; @@ -1062,6 +1065,9 @@ impl serde::Serialize for DexParameters { if self.max_hops != 0 { struct_ser.serialize_field("maxHops", &self.max_hops)?; } + if self.max_positions_per_pair != 0 { + struct_ser.serialize_field("maxPositionsPerPair", &self.max_positions_per_pair)?; + } struct_ser.end() } } @@ -1078,6 +1084,8 @@ impl<'de> serde::Deserialize<'de> for DexParameters { "fixedCandidates", "max_hops", "maxHops", + "max_positions_per_pair", + "maxPositionsPerPair", ]; #[allow(clippy::enum_variant_names)] @@ -1085,6 +1093,7 @@ impl<'de> serde::Deserialize<'de> for DexParameters { IsEnabled, FixedCandidates, MaxHops, + MaxPositionsPerPair, __SkipField__, } impl<'de> serde::Deserialize<'de> for GeneratedField { @@ -1110,6 +1119,7 @@ impl<'de> serde::Deserialize<'de> for DexParameters { "isEnabled" | "is_enabled" => Ok(GeneratedField::IsEnabled), "fixedCandidates" | "fixed_candidates" => Ok(GeneratedField::FixedCandidates), "maxHops" | "max_hops" => Ok(GeneratedField::MaxHops), + "maxPositionsPerPair" | "max_positions_per_pair" => Ok(GeneratedField::MaxPositionsPerPair), _ => Ok(GeneratedField::__SkipField__), } } @@ -1132,6 +1142,7 @@ impl<'de> serde::Deserialize<'de> for DexParameters { let mut is_enabled__ = None; let mut fixed_candidates__ = None; let mut max_hops__ = None; + let mut max_positions_per_pair__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::IsEnabled => { @@ -1154,6 +1165,14 @@ impl<'de> serde::Deserialize<'de> for DexParameters { Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) ; } + GeneratedField::MaxPositionsPerPair => { + if max_positions_per_pair__.is_some() { + return Err(serde::de::Error::duplicate_field("maxPositionsPerPair")); + } + max_positions_per_pair__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } GeneratedField::__SkipField__ => { let _ = map_.next_value::()?; } @@ -1163,6 +1182,7 @@ impl<'de> serde::Deserialize<'de> for DexParameters { is_enabled: is_enabled__.unwrap_or_default(), fixed_candidates: fixed_candidates__.unwrap_or_default(), max_hops: max_hops__.unwrap_or_default(), + max_positions_per_pair: max_positions_per_pair__.unwrap_or_default(), }) } } diff --git a/crates/proto/src/gen/proto_descriptor.bin.no_lfs b/crates/proto/src/gen/proto_descriptor.bin.no_lfs index d2be9305bf..5c5a38007f 100644 Binary files a/crates/proto/src/gen/proto_descriptor.bin.no_lfs and b/crates/proto/src/gen/proto_descriptor.bin.no_lfs differ diff --git a/proto/penumbra/penumbra/core/component/dex/v1/dex.proto b/proto/penumbra/penumbra/core/component/dex/v1/dex.proto index 4ba3cbb394..88bf102fbf 100644 --- a/proto/penumbra/penumbra/core/component/dex/v1/dex.proto +++ b/proto/penumbra/penumbra/core/component/dex/v1/dex.proto @@ -702,6 +702,10 @@ message DexParameters { repeated asset.v1.AssetId fixed_candidates = 2; // The number of hops to traverse while routing from A to B. uint32 max_hops = 3; + // The maximum number of positions per trading pair. + // If this number is exceeded, positions with the least + // inventory get evicted from the DEX. + uint32 max_positions_per_pair = 4; } message GenesisContent {