From 2e8b5f2c45c201d84f1b8f5e0685362d010b8356 Mon Sep 17 00:00:00 2001 From: ethanoroshiba Date: Wed, 18 Dec 2024 08:40:40 -0600 Subject: [PATCH 1/8] add market map actions --- .../src/generated/astria.protocol.fees.v1.rs | 90 ++ .../astria.protocol.fees.v1.serde.rs | 826 ++++++++++++++++-- .../generated/astria.protocol.genesis.v1.rs | 24 + .../astria.protocol.genesis.v1.serde.rs | 108 +++ .../astria.protocol.transaction.v1.rs | 129 ++- .../astria.protocol.transaction.v1.serde.rs | 717 +++++++++++++++ crates/astria-core/src/protocol/fees/v1.rs | 12 + crates/astria-core/src/protocol/genesis/v1.rs | 81 ++ .../transaction/v1/action/group/mod.rs | 18 + .../src/protocol/transaction/v1/action/mod.rs | 458 ++++++++++ .../src/genesis_example.rs | 34 +- .../action_handler/impls/create_markets.rs | 208 +++++ .../src/action_handler/impls/fee_change.rs | 18 + .../src/action_handler/impls/mod.rs | 6 + .../impls/remove_market_authorities.rs | 192 ++++ .../action_handler/impls/remove_markets.rs | 207 +++++ .../src/action_handler/impls/transaction.rs | 42 + .../action_handler/impls/update_markets.rs | 302 +++++++ .../src/action_handler/impls/update_params.rs | 117 +++ .../action_handler/impls/upsert_markets.rs | 278 ++++++ .../src/app/benchmark_and_test_utils.rs | 14 +- ...breaking_changes__app_hash_at_genesis.snap | 61 +- ...hanges__app_hash_execute_every_action.snap | 61 +- ...king_changes__app_hash_finalize_block.snap | 61 +- crates/astria-sequencer/src/app/test_utils.rs | 26 + .../src/app/tests_breaking_changes.rs | 68 ++ .../src/app/tests_execute_transaction.rs | 338 ++++++- .../src/connect/market_map/component.rs | 3 - crates/astria-sequencer/src/fees/component.rs | 42 + crates/astria-sequencer/src/fees/mod.rs | 138 +++ crates/astria-sequencer/src/fees/query.rs | 37 + .../src/fees/storage/values.rs | 18 + crates/astria-sequencer/src/test_utils.rs | 23 + .../src/transaction/checks.rs | 6 + .../astria/protocol/fees/v1/types.proto | 30 + .../astria/protocol/genesis/v1/types.proto | 6 + .../protocol/transaction/v1/action.proto | 52 ++ 37 files changed, 4653 insertions(+), 198 deletions(-) create mode 100644 crates/astria-sequencer/src/action_handler/impls/create_markets.rs create mode 100644 crates/astria-sequencer/src/action_handler/impls/remove_market_authorities.rs create mode 100644 crates/astria-sequencer/src/action_handler/impls/remove_markets.rs create mode 100644 crates/astria-sequencer/src/action_handler/impls/update_markets.rs create mode 100644 crates/astria-sequencer/src/action_handler/impls/update_params.rs create mode 100644 crates/astria-sequencer/src/action_handler/impls/upsert_markets.rs diff --git a/crates/astria-core/src/generated/astria.protocol.fees.v1.rs b/crates/astria-core/src/generated/astria.protocol.fees.v1.rs index 8d03de6cd6..4e7753d10e 100644 --- a/crates/astria-core/src/generated/astria.protocol.fees.v1.rs +++ b/crates/astria-core/src/generated/astria.protocol.fees.v1.rs @@ -223,6 +223,96 @@ impl ::prost::Name for IbcSudoChangeFeeComponents { ::prost::alloc::format!("astria.protocol.fees.v1.{}", Self::NAME) } } +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct UpsertMarketsFeeComponents { + #[prost(message, optional, tag = "1")] + pub base: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub multiplier: ::core::option::Option, +} +impl ::prost::Name for UpsertMarketsFeeComponents { + const NAME: &'static str = "UpsertMarketsFeeComponents"; + const PACKAGE: &'static str = "astria.protocol.fees.v1"; + fn full_name() -> ::prost::alloc::string::String { + ::prost::alloc::format!("astria.protocol.fees.v1.{}", Self::NAME) + } +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CreateMarketsFeeComponents { + #[prost(message, optional, tag = "1")] + pub base: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub multiplier: ::core::option::Option, +} +impl ::prost::Name for CreateMarketsFeeComponents { + const NAME: &'static str = "CreateMarketsFeeComponents"; + const PACKAGE: &'static str = "astria.protocol.fees.v1"; + fn full_name() -> ::prost::alloc::string::String { + ::prost::alloc::format!("astria.protocol.fees.v1.{}", Self::NAME) + } +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct UpdateMarketsFeeComponents { + #[prost(message, optional, tag = "1")] + pub base: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub multiplier: ::core::option::Option, +} +impl ::prost::Name for UpdateMarketsFeeComponents { + const NAME: &'static str = "UpdateMarketsFeeComponents"; + const PACKAGE: &'static str = "astria.protocol.fees.v1"; + fn full_name() -> ::prost::alloc::string::String { + ::prost::alloc::format!("astria.protocol.fees.v1.{}", Self::NAME) + } +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct UpdateParamsFeeComponents { + #[prost(message, optional, tag = "1")] + pub base: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub multiplier: ::core::option::Option, +} +impl ::prost::Name for UpdateParamsFeeComponents { + const NAME: &'static str = "UpdateParamsFeeComponents"; + const PACKAGE: &'static str = "astria.protocol.fees.v1"; + fn full_name() -> ::prost::alloc::string::String { + ::prost::alloc::format!("astria.protocol.fees.v1.{}", Self::NAME) + } +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RemoveMarketAuthoritiesFeeComponents { + #[prost(message, optional, tag = "1")] + pub base: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub multiplier: ::core::option::Option, +} +impl ::prost::Name for RemoveMarketAuthoritiesFeeComponents { + const NAME: &'static str = "RemoveMarketAuthoritiesFeeComponents"; + const PACKAGE: &'static str = "astria.protocol.fees.v1"; + fn full_name() -> ::prost::alloc::string::String { + ::prost::alloc::format!("astria.protocol.fees.v1.{}", Self::NAME) + } +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RemoveMarketsFeeComponents { + #[prost(message, optional, tag = "1")] + pub base: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub multiplier: ::core::option::Option, +} +impl ::prost::Name for RemoveMarketsFeeComponents { + const NAME: &'static str = "RemoveMarketsFeeComponents"; + const PACKAGE: &'static str = "astria.protocol.fees.v1"; + fn full_name() -> ::prost::alloc::string::String { + ::prost::alloc::format!("astria.protocol.fees.v1.{}", Self::NAME) + } +} /// Response to a transaction fee ABCI query. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] diff --git a/crates/astria-core/src/generated/astria.protocol.fees.v1.serde.rs b/crates/astria-core/src/generated/astria.protocol.fees.v1.serde.rs index 90c71b03f9..c2245ae908 100644 --- a/crates/astria-core/src/generated/astria.protocol.fees.v1.serde.rs +++ b/crates/astria-core/src/generated/astria.protocol.fees.v1.serde.rs @@ -322,6 +322,114 @@ impl<'de> serde::Deserialize<'de> for BridgeUnlockFeeComponents { deserializer.deserialize_struct("astria.protocol.fees.v1.BridgeUnlockFeeComponents", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for CreateMarketsFeeComponents { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.base.is_some() { + len += 1; + } + if self.multiplier.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("astria.protocol.fees.v1.CreateMarketsFeeComponents", len)?; + if let Some(v) = self.base.as_ref() { + struct_ser.serialize_field("base", v)?; + } + if let Some(v) = self.multiplier.as_ref() { + struct_ser.serialize_field("multiplier", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for CreateMarketsFeeComponents { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "base", + "multiplier", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Base, + Multiplier, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + 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(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "base" => Ok(GeneratedField::Base), + "multiplier" => Ok(GeneratedField::Multiplier), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = CreateMarketsFeeComponents; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct astria.protocol.fees.v1.CreateMarketsFeeComponents") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut base__ = None; + let mut multiplier__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Base => { + if base__.is_some() { + return Err(serde::de::Error::duplicate_field("base")); + } + base__ = map_.next_value()?; + } + GeneratedField::Multiplier => { + if multiplier__.is_some() { + return Err(serde::de::Error::duplicate_field("multiplier")); + } + multiplier__ = map_.next_value()?; + } + } + } + Ok(CreateMarketsFeeComponents { + base: base__, + multiplier: multiplier__, + }) + } + } + deserializer.deserialize_struct("astria.protocol.fees.v1.CreateMarketsFeeComponents", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for FeeAssetChangeFeeComponents { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -1078,7 +1186,7 @@ impl<'de> serde::Deserialize<'de> for InitBridgeAccountFeeComponents { deserializer.deserialize_struct("astria.protocol.fees.v1.InitBridgeAccountFeeComponents", FIELDS, GeneratedVisitor) } } -impl serde::Serialize for RollupDataSubmissionFeeComponents { +impl serde::Serialize for RemoveMarketAuthoritiesFeeComponents { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result where @@ -1092,7 +1200,7 @@ impl serde::Serialize for RollupDataSubmissionFeeComponents { if self.multiplier.is_some() { len += 1; } - let mut struct_ser = serializer.serialize_struct("astria.protocol.fees.v1.RollupDataSubmissionFeeComponents", len)?; + let mut struct_ser = serializer.serialize_struct("astria.protocol.fees.v1.RemoveMarketAuthoritiesFeeComponents", len)?; if let Some(v) = self.base.as_ref() { struct_ser.serialize_field("base", v)?; } @@ -1102,7 +1210,7 @@ impl serde::Serialize for RollupDataSubmissionFeeComponents { struct_ser.end() } } -impl<'de> serde::Deserialize<'de> for RollupDataSubmissionFeeComponents { +impl<'de> serde::Deserialize<'de> for RemoveMarketAuthoritiesFeeComponents { #[allow(deprecated)] fn deserialize(deserializer: D) -> std::result::Result where @@ -1149,13 +1257,13 @@ impl<'de> serde::Deserialize<'de> for RollupDataSubmissionFeeComponents { } struct GeneratedVisitor; impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = RollupDataSubmissionFeeComponents; + type Value = RemoveMarketAuthoritiesFeeComponents; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct astria.protocol.fees.v1.RollupDataSubmissionFeeComponents") + formatter.write_str("struct astria.protocol.fees.v1.RemoveMarketAuthoritiesFeeComponents") } - fn visit_map(self, mut map_: V) -> std::result::Result + fn visit_map(self, mut map_: V) -> std::result::Result where V: serde::de::MapAccess<'de>, { @@ -1177,16 +1285,16 @@ impl<'de> serde::Deserialize<'de> for RollupDataSubmissionFeeComponents { } } } - Ok(RollupDataSubmissionFeeComponents { + Ok(RemoveMarketAuthoritiesFeeComponents { base: base__, multiplier: multiplier__, }) } } - deserializer.deserialize_struct("astria.protocol.fees.v1.RollupDataSubmissionFeeComponents", FIELDS, GeneratedVisitor) + deserializer.deserialize_struct("astria.protocol.fees.v1.RemoveMarketAuthoritiesFeeComponents", FIELDS, GeneratedVisitor) } } -impl serde::Serialize for SudoAddressChangeFeeComponents { +impl serde::Serialize for RemoveMarketsFeeComponents { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result where @@ -1200,7 +1308,7 @@ impl serde::Serialize for SudoAddressChangeFeeComponents { if self.multiplier.is_some() { len += 1; } - let mut struct_ser = serializer.serialize_struct("astria.protocol.fees.v1.SudoAddressChangeFeeComponents", len)?; + let mut struct_ser = serializer.serialize_struct("astria.protocol.fees.v1.RemoveMarketsFeeComponents", len)?; if let Some(v) = self.base.as_ref() { struct_ser.serialize_field("base", v)?; } @@ -1210,7 +1318,7 @@ impl serde::Serialize for SudoAddressChangeFeeComponents { struct_ser.end() } } -impl<'de> serde::Deserialize<'de> for SudoAddressChangeFeeComponents { +impl<'de> serde::Deserialize<'de> for RemoveMarketsFeeComponents { #[allow(deprecated)] fn deserialize(deserializer: D) -> std::result::Result where @@ -1257,13 +1365,13 @@ impl<'de> serde::Deserialize<'de> for SudoAddressChangeFeeComponents { } struct GeneratedVisitor; impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = SudoAddressChangeFeeComponents; + type Value = RemoveMarketsFeeComponents; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct astria.protocol.fees.v1.SudoAddressChangeFeeComponents") + formatter.write_str("struct astria.protocol.fees.v1.RemoveMarketsFeeComponents") } - fn visit_map(self, mut map_: V) -> std::result::Result + fn visit_map(self, mut map_: V) -> std::result::Result where V: serde::de::MapAccess<'de>, { @@ -1285,16 +1393,16 @@ impl<'de> serde::Deserialize<'de> for SudoAddressChangeFeeComponents { } } } - Ok(SudoAddressChangeFeeComponents { + Ok(RemoveMarketsFeeComponents { base: base__, multiplier: multiplier__, }) } } - deserializer.deserialize_struct("astria.protocol.fees.v1.SudoAddressChangeFeeComponents", FIELDS, GeneratedVisitor) + deserializer.deserialize_struct("astria.protocol.fees.v1.RemoveMarketsFeeComponents", FIELDS, GeneratedVisitor) } } -impl serde::Serialize for TransactionFee { +impl serde::Serialize for RollupDataSubmissionFeeComponents { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result where @@ -1302,37 +1410,37 @@ impl serde::Serialize for TransactionFee { { use serde::ser::SerializeStruct; let mut len = 0; - if !self.asset.is_empty() { + if self.base.is_some() { len += 1; } - if self.fee.is_some() { + if self.multiplier.is_some() { len += 1; } - let mut struct_ser = serializer.serialize_struct("astria.protocol.fees.v1.TransactionFee", len)?; - if !self.asset.is_empty() { - struct_ser.serialize_field("asset", &self.asset)?; + let mut struct_ser = serializer.serialize_struct("astria.protocol.fees.v1.RollupDataSubmissionFeeComponents", len)?; + if let Some(v) = self.base.as_ref() { + struct_ser.serialize_field("base", v)?; } - if let Some(v) = self.fee.as_ref() { - struct_ser.serialize_field("fee", v)?; + if let Some(v) = self.multiplier.as_ref() { + struct_ser.serialize_field("multiplier", v)?; } struct_ser.end() } } -impl<'de> serde::Deserialize<'de> for TransactionFee { +impl<'de> serde::Deserialize<'de> for RollupDataSubmissionFeeComponents { #[allow(deprecated)] fn deserialize(deserializer: D) -> std::result::Result where D: serde::Deserializer<'de>, { const FIELDS: &[&str] = &[ - "asset", - "fee", + "base", + "multiplier", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { - Asset, - Fee, + Base, + Multiplier, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -1354,8 +1462,8 @@ impl<'de> serde::Deserialize<'de> for TransactionFee { E: serde::de::Error, { match value { - "asset" => Ok(GeneratedField::Asset), - "fee" => Ok(GeneratedField::Fee), + "base" => Ok(GeneratedField::Base), + "multiplier" => Ok(GeneratedField::Multiplier), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -1365,44 +1473,44 @@ impl<'de> serde::Deserialize<'de> for TransactionFee { } struct GeneratedVisitor; impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = TransactionFee; + type Value = RollupDataSubmissionFeeComponents; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct astria.protocol.fees.v1.TransactionFee") + formatter.write_str("struct astria.protocol.fees.v1.RollupDataSubmissionFeeComponents") } - fn visit_map(self, mut map_: V) -> std::result::Result + fn visit_map(self, mut map_: V) -> std::result::Result where V: serde::de::MapAccess<'de>, { - let mut asset__ = None; - let mut fee__ = None; + let mut base__ = None; + let mut multiplier__ = None; while let Some(k) = map_.next_key()? { match k { - GeneratedField::Asset => { - if asset__.is_some() { - return Err(serde::de::Error::duplicate_field("asset")); + GeneratedField::Base => { + if base__.is_some() { + return Err(serde::de::Error::duplicate_field("base")); } - asset__ = Some(map_.next_value()?); + base__ = map_.next_value()?; } - GeneratedField::Fee => { - if fee__.is_some() { - return Err(serde::de::Error::duplicate_field("fee")); + GeneratedField::Multiplier => { + if multiplier__.is_some() { + return Err(serde::de::Error::duplicate_field("multiplier")); } - fee__ = map_.next_value()?; + multiplier__ = map_.next_value()?; } } } - Ok(TransactionFee { - asset: asset__.unwrap_or_default(), - fee: fee__, + Ok(RollupDataSubmissionFeeComponents { + base: base__, + multiplier: multiplier__, }) } } - deserializer.deserialize_struct("astria.protocol.fees.v1.TransactionFee", FIELDS, GeneratedVisitor) + deserializer.deserialize_struct("astria.protocol.fees.v1.RollupDataSubmissionFeeComponents", FIELDS, GeneratedVisitor) } } -impl serde::Serialize for TransactionFeeResponse { +impl serde::Serialize for SudoAddressChangeFeeComponents { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result where @@ -1410,38 +1518,37 @@ impl serde::Serialize for TransactionFeeResponse { { use serde::ser::SerializeStruct; let mut len = 0; - if self.height != 0 { + if self.base.is_some() { len += 1; } - if !self.fees.is_empty() { + if self.multiplier.is_some() { len += 1; } - let mut struct_ser = serializer.serialize_struct("astria.protocol.fees.v1.TransactionFeeResponse", len)?; - if self.height != 0 { - #[allow(clippy::needless_borrow)] - struct_ser.serialize_field("height", ToString::to_string(&self.height).as_str())?; + let mut struct_ser = serializer.serialize_struct("astria.protocol.fees.v1.SudoAddressChangeFeeComponents", len)?; + if let Some(v) = self.base.as_ref() { + struct_ser.serialize_field("base", v)?; } - if !self.fees.is_empty() { - struct_ser.serialize_field("fees", &self.fees)?; + if let Some(v) = self.multiplier.as_ref() { + struct_ser.serialize_field("multiplier", v)?; } struct_ser.end() } } -impl<'de> serde::Deserialize<'de> for TransactionFeeResponse { +impl<'de> serde::Deserialize<'de> for SudoAddressChangeFeeComponents { #[allow(deprecated)] fn deserialize(deserializer: D) -> std::result::Result where D: serde::Deserializer<'de>, { const FIELDS: &[&str] = &[ - "height", - "fees", + "base", + "multiplier", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { - Height, - Fees, + Base, + Multiplier, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -1463,8 +1570,8 @@ impl<'de> serde::Deserialize<'de> for TransactionFeeResponse { E: serde::de::Error, { match value { - "height" => Ok(GeneratedField::Height), - "fees" => Ok(GeneratedField::Fees), + "base" => Ok(GeneratedField::Base), + "multiplier" => Ok(GeneratedField::Multiplier), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -1474,46 +1581,44 @@ impl<'de> serde::Deserialize<'de> for TransactionFeeResponse { } struct GeneratedVisitor; impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = TransactionFeeResponse; + type Value = SudoAddressChangeFeeComponents; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct astria.protocol.fees.v1.TransactionFeeResponse") + formatter.write_str("struct astria.protocol.fees.v1.SudoAddressChangeFeeComponents") } - fn visit_map(self, mut map_: V) -> std::result::Result + fn visit_map(self, mut map_: V) -> std::result::Result where V: serde::de::MapAccess<'de>, { - let mut height__ = None; - let mut fees__ = None; + let mut base__ = None; + let mut multiplier__ = None; while let Some(k) = map_.next_key()? { match k { - GeneratedField::Height => { - if height__.is_some() { - return Err(serde::de::Error::duplicate_field("height")); + GeneratedField::Base => { + if base__.is_some() { + return Err(serde::de::Error::duplicate_field("base")); } - height__ = - Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) - ; + base__ = map_.next_value()?; } - GeneratedField::Fees => { - if fees__.is_some() { - return Err(serde::de::Error::duplicate_field("fees")); + GeneratedField::Multiplier => { + if multiplier__.is_some() { + return Err(serde::de::Error::duplicate_field("multiplier")); } - fees__ = Some(map_.next_value()?); + multiplier__ = map_.next_value()?; } } } - Ok(TransactionFeeResponse { - height: height__.unwrap_or_default(), - fees: fees__.unwrap_or_default(), + Ok(SudoAddressChangeFeeComponents { + base: base__, + multiplier: multiplier__, }) } } - deserializer.deserialize_struct("astria.protocol.fees.v1.TransactionFeeResponse", FIELDS, GeneratedVisitor) + deserializer.deserialize_struct("astria.protocol.fees.v1.SudoAddressChangeFeeComponents", FIELDS, GeneratedVisitor) } } -impl serde::Serialize for TransferFeeComponents { +impl serde::Serialize for TransactionFee { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result where @@ -1521,15 +1626,234 @@ impl serde::Serialize for TransferFeeComponents { { use serde::ser::SerializeStruct; let mut len = 0; - if self.base.is_some() { + if !self.asset.is_empty() { len += 1; } - if self.multiplier.is_some() { + if self.fee.is_some() { len += 1; } - let mut struct_ser = serializer.serialize_struct("astria.protocol.fees.v1.TransferFeeComponents", len)?; - if let Some(v) = self.base.as_ref() { - struct_ser.serialize_field("base", v)?; + let mut struct_ser = serializer.serialize_struct("astria.protocol.fees.v1.TransactionFee", len)?; + if !self.asset.is_empty() { + struct_ser.serialize_field("asset", &self.asset)?; + } + if let Some(v) = self.fee.as_ref() { + struct_ser.serialize_field("fee", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for TransactionFee { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "asset", + "fee", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Asset, + Fee, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + 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(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "asset" => Ok(GeneratedField::Asset), + "fee" => Ok(GeneratedField::Fee), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = TransactionFee; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct astria.protocol.fees.v1.TransactionFee") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut asset__ = None; + let mut fee__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Asset => { + if asset__.is_some() { + return Err(serde::de::Error::duplicate_field("asset")); + } + asset__ = Some(map_.next_value()?); + } + GeneratedField::Fee => { + if fee__.is_some() { + return Err(serde::de::Error::duplicate_field("fee")); + } + fee__ = map_.next_value()?; + } + } + } + Ok(TransactionFee { + asset: asset__.unwrap_or_default(), + fee: fee__, + }) + } + } + deserializer.deserialize_struct("astria.protocol.fees.v1.TransactionFee", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for TransactionFeeResponse { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.height != 0 { + len += 1; + } + if !self.fees.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("astria.protocol.fees.v1.TransactionFeeResponse", len)?; + if self.height != 0 { + #[allow(clippy::needless_borrow)] + struct_ser.serialize_field("height", ToString::to_string(&self.height).as_str())?; + } + if !self.fees.is_empty() { + struct_ser.serialize_field("fees", &self.fees)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for TransactionFeeResponse { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "height", + "fees", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Height, + Fees, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + 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(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "height" => Ok(GeneratedField::Height), + "fees" => Ok(GeneratedField::Fees), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = TransactionFeeResponse; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct astria.protocol.fees.v1.TransactionFeeResponse") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut height__ = None; + let mut fees__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Height => { + if height__.is_some() { + return Err(serde::de::Error::duplicate_field("height")); + } + height__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::Fees => { + if fees__.is_some() { + return Err(serde::de::Error::duplicate_field("fees")); + } + fees__ = Some(map_.next_value()?); + } + } + } + Ok(TransactionFeeResponse { + height: height__.unwrap_or_default(), + fees: fees__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("astria.protocol.fees.v1.TransactionFeeResponse", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for TransferFeeComponents { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.base.is_some() { + len += 1; + } + if self.multiplier.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("astria.protocol.fees.v1.TransferFeeComponents", len)?; + if let Some(v) = self.base.as_ref() { + struct_ser.serialize_field("base", v)?; } if let Some(v) = self.multiplier.as_ref() { struct_ser.serialize_field("multiplier", v)?; @@ -1621,6 +1945,330 @@ impl<'de> serde::Deserialize<'de> for TransferFeeComponents { deserializer.deserialize_struct("astria.protocol.fees.v1.TransferFeeComponents", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for UpdateMarketsFeeComponents { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.base.is_some() { + len += 1; + } + if self.multiplier.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("astria.protocol.fees.v1.UpdateMarketsFeeComponents", len)?; + if let Some(v) = self.base.as_ref() { + struct_ser.serialize_field("base", v)?; + } + if let Some(v) = self.multiplier.as_ref() { + struct_ser.serialize_field("multiplier", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for UpdateMarketsFeeComponents { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "base", + "multiplier", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Base, + Multiplier, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + 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(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "base" => Ok(GeneratedField::Base), + "multiplier" => Ok(GeneratedField::Multiplier), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = UpdateMarketsFeeComponents; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct astria.protocol.fees.v1.UpdateMarketsFeeComponents") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut base__ = None; + let mut multiplier__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Base => { + if base__.is_some() { + return Err(serde::de::Error::duplicate_field("base")); + } + base__ = map_.next_value()?; + } + GeneratedField::Multiplier => { + if multiplier__.is_some() { + return Err(serde::de::Error::duplicate_field("multiplier")); + } + multiplier__ = map_.next_value()?; + } + } + } + Ok(UpdateMarketsFeeComponents { + base: base__, + multiplier: multiplier__, + }) + } + } + deserializer.deserialize_struct("astria.protocol.fees.v1.UpdateMarketsFeeComponents", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for UpdateParamsFeeComponents { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.base.is_some() { + len += 1; + } + if self.multiplier.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("astria.protocol.fees.v1.UpdateParamsFeeComponents", len)?; + if let Some(v) = self.base.as_ref() { + struct_ser.serialize_field("base", v)?; + } + if let Some(v) = self.multiplier.as_ref() { + struct_ser.serialize_field("multiplier", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for UpdateParamsFeeComponents { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "base", + "multiplier", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Base, + Multiplier, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + 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(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "base" => Ok(GeneratedField::Base), + "multiplier" => Ok(GeneratedField::Multiplier), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = UpdateParamsFeeComponents; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct astria.protocol.fees.v1.UpdateParamsFeeComponents") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut base__ = None; + let mut multiplier__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Base => { + if base__.is_some() { + return Err(serde::de::Error::duplicate_field("base")); + } + base__ = map_.next_value()?; + } + GeneratedField::Multiplier => { + if multiplier__.is_some() { + return Err(serde::de::Error::duplicate_field("multiplier")); + } + multiplier__ = map_.next_value()?; + } + } + } + Ok(UpdateParamsFeeComponents { + base: base__, + multiplier: multiplier__, + }) + } + } + deserializer.deserialize_struct("astria.protocol.fees.v1.UpdateParamsFeeComponents", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for UpsertMarketsFeeComponents { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.base.is_some() { + len += 1; + } + if self.multiplier.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("astria.protocol.fees.v1.UpsertMarketsFeeComponents", len)?; + if let Some(v) = self.base.as_ref() { + struct_ser.serialize_field("base", v)?; + } + if let Some(v) = self.multiplier.as_ref() { + struct_ser.serialize_field("multiplier", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for UpsertMarketsFeeComponents { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "base", + "multiplier", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Base, + Multiplier, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + 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(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "base" => Ok(GeneratedField::Base), + "multiplier" => Ok(GeneratedField::Multiplier), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = UpsertMarketsFeeComponents; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct astria.protocol.fees.v1.UpsertMarketsFeeComponents") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut base__ = None; + let mut multiplier__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Base => { + if base__.is_some() { + return Err(serde::de::Error::duplicate_field("base")); + } + base__ = map_.next_value()?; + } + GeneratedField::Multiplier => { + if multiplier__.is_some() { + return Err(serde::de::Error::duplicate_field("multiplier")); + } + multiplier__ = map_.next_value()?; + } + } + } + Ok(UpsertMarketsFeeComponents { + base: base__, + multiplier: multiplier__, + }) + } + } + deserializer.deserialize_struct("astria.protocol.fees.v1.UpsertMarketsFeeComponents", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for ValidatorUpdateFeeComponents { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result diff --git a/crates/astria-core/src/generated/astria.protocol.genesis.v1.rs b/crates/astria-core/src/generated/astria.protocol.genesis.v1.rs index 991867b813..116d3ca0ff 100644 --- a/crates/astria-core/src/generated/astria.protocol.genesis.v1.rs +++ b/crates/astria-core/src/generated/astria.protocol.genesis.v1.rs @@ -147,6 +147,30 @@ pub struct GenesisFees { pub validator_update: ::core::option::Option< super::super::fees::v1::ValidatorUpdateFeeComponents, >, + #[prost(message, optional, tag = "15")] + pub upsert_markets: ::core::option::Option< + super::super::fees::v1::UpsertMarketsFeeComponents, + >, + #[prost(message, optional, tag = "16")] + pub create_markets: ::core::option::Option< + super::super::fees::v1::CreateMarketsFeeComponents, + >, + #[prost(message, optional, tag = "17")] + pub update_markets: ::core::option::Option< + super::super::fees::v1::UpdateMarketsFeeComponents, + >, + #[prost(message, optional, tag = "18")] + pub update_params: ::core::option::Option< + super::super::fees::v1::UpdateParamsFeeComponents, + >, + #[prost(message, optional, tag = "19")] + pub remove_market_authorities: ::core::option::Option< + super::super::fees::v1::RemoveMarketAuthoritiesFeeComponents, + >, + #[prost(message, optional, tag = "20")] + pub remove_markets: ::core::option::Option< + super::super::fees::v1::RemoveMarketsFeeComponents, + >, } impl ::prost::Name for GenesisFees { const NAME: &'static str = "GenesisFees"; diff --git a/crates/astria-core/src/generated/astria.protocol.genesis.v1.serde.rs b/crates/astria-core/src/generated/astria.protocol.genesis.v1.serde.rs index 9ca59c33ca..8d8bf38905 100644 --- a/crates/astria-core/src/generated/astria.protocol.genesis.v1.serde.rs +++ b/crates/astria-core/src/generated/astria.protocol.genesis.v1.serde.rs @@ -643,6 +643,24 @@ impl serde::Serialize for GenesisFees { if self.validator_update.is_some() { len += 1; } + if self.upsert_markets.is_some() { + len += 1; + } + if self.create_markets.is_some() { + len += 1; + } + if self.update_markets.is_some() { + len += 1; + } + if self.update_params.is_some() { + len += 1; + } + if self.remove_market_authorities.is_some() { + len += 1; + } + if self.remove_markets.is_some() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("astria.protocol.genesis.v1.GenesisFees", len)?; if let Some(v) = self.bridge_lock.as_ref() { struct_ser.serialize_field("bridgeLock", v)?; @@ -686,6 +704,24 @@ impl serde::Serialize for GenesisFees { if let Some(v) = self.validator_update.as_ref() { struct_ser.serialize_field("validatorUpdate", v)?; } + if let Some(v) = self.upsert_markets.as_ref() { + struct_ser.serialize_field("upsertMarkets", v)?; + } + if let Some(v) = self.create_markets.as_ref() { + struct_ser.serialize_field("createMarkets", v)?; + } + if let Some(v) = self.update_markets.as_ref() { + struct_ser.serialize_field("updateMarkets", v)?; + } + if let Some(v) = self.update_params.as_ref() { + struct_ser.serialize_field("updateParams", v)?; + } + if let Some(v) = self.remove_market_authorities.as_ref() { + struct_ser.serialize_field("removeMarketAuthorities", v)?; + } + if let Some(v) = self.remove_markets.as_ref() { + struct_ser.serialize_field("removeMarkets", v)?; + } struct_ser.end() } } @@ -723,6 +759,18 @@ impl<'de> serde::Deserialize<'de> for GenesisFees { "transfer", "validator_update", "validatorUpdate", + "upsert_markets", + "upsertMarkets", + "create_markets", + "createMarkets", + "update_markets", + "updateMarkets", + "update_params", + "updateParams", + "remove_market_authorities", + "removeMarketAuthorities", + "remove_markets", + "removeMarkets", ]; #[allow(clippy::enum_variant_names)] @@ -741,6 +789,12 @@ impl<'de> serde::Deserialize<'de> for GenesisFees { SudoAddressChange, Transfer, ValidatorUpdate, + UpsertMarkets, + CreateMarkets, + UpdateMarkets, + UpdateParams, + RemoveMarketAuthorities, + RemoveMarkets, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -776,6 +830,12 @@ impl<'de> serde::Deserialize<'de> for GenesisFees { "sudoAddressChange" | "sudo_address_change" => Ok(GeneratedField::SudoAddressChange), "transfer" => Ok(GeneratedField::Transfer), "validatorUpdate" | "validator_update" => Ok(GeneratedField::ValidatorUpdate), + "upsertMarkets" | "upsert_markets" => Ok(GeneratedField::UpsertMarkets), + "createMarkets" | "create_markets" => Ok(GeneratedField::CreateMarkets), + "updateMarkets" | "update_markets" => Ok(GeneratedField::UpdateMarkets), + "updateParams" | "update_params" => Ok(GeneratedField::UpdateParams), + "removeMarketAuthorities" | "remove_market_authorities" => Ok(GeneratedField::RemoveMarketAuthorities), + "removeMarkets" | "remove_markets" => Ok(GeneratedField::RemoveMarkets), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -809,6 +869,12 @@ impl<'de> serde::Deserialize<'de> for GenesisFees { let mut sudo_address_change__ = None; let mut transfer__ = None; let mut validator_update__ = None; + let mut upsert_markets__ = None; + let mut create_markets__ = None; + let mut update_markets__ = None; + let mut update_params__ = None; + let mut remove_market_authorities__ = None; + let mut remove_markets__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::BridgeLock => { @@ -895,6 +961,42 @@ impl<'de> serde::Deserialize<'de> for GenesisFees { } validator_update__ = map_.next_value()?; } + GeneratedField::UpsertMarkets => { + if upsert_markets__.is_some() { + return Err(serde::de::Error::duplicate_field("upsertMarkets")); + } + upsert_markets__ = map_.next_value()?; + } + GeneratedField::CreateMarkets => { + if create_markets__.is_some() { + return Err(serde::de::Error::duplicate_field("createMarkets")); + } + create_markets__ = map_.next_value()?; + } + GeneratedField::UpdateMarkets => { + if update_markets__.is_some() { + return Err(serde::de::Error::duplicate_field("updateMarkets")); + } + update_markets__ = map_.next_value()?; + } + GeneratedField::UpdateParams => { + if update_params__.is_some() { + return Err(serde::de::Error::duplicate_field("updateParams")); + } + update_params__ = map_.next_value()?; + } + GeneratedField::RemoveMarketAuthorities => { + if remove_market_authorities__.is_some() { + return Err(serde::de::Error::duplicate_field("removeMarketAuthorities")); + } + remove_market_authorities__ = map_.next_value()?; + } + GeneratedField::RemoveMarkets => { + if remove_markets__.is_some() { + return Err(serde::de::Error::duplicate_field("removeMarkets")); + } + remove_markets__ = map_.next_value()?; + } } } Ok(GenesisFees { @@ -912,6 +1014,12 @@ impl<'de> serde::Deserialize<'de> for GenesisFees { sudo_address_change: sudo_address_change__, transfer: transfer__, validator_update: validator_update__, + upsert_markets: upsert_markets__, + create_markets: create_markets__, + update_markets: update_markets__, + update_params: update_params__, + remove_market_authorities: remove_market_authorities__, + remove_markets: remove_markets__, }) } } diff --git a/crates/astria-core/src/generated/astria.protocol.transaction.v1.rs b/crates/astria-core/src/generated/astria.protocol.transaction.v1.rs index 0b38628394..14dbbc3368 100644 --- a/crates/astria-core/src/generated/astria.protocol.transaction.v1.rs +++ b/crates/astria-core/src/generated/astria.protocol.transaction.v1.rs @@ -3,7 +3,7 @@ pub struct Action { #[prost( oneof = "action::Value", - tags = "1, 2, 11, 12, 13, 14, 21, 22, 50, 51, 52, 53, 55, 56" + tags = "1, 2, 11, 12, 13, 14, 21, 22, 50, 51, 52, 53, 55, 56, 71, 72, 73, 74, 75, 76" )] pub value: ::core::option::Option, } @@ -46,6 +46,19 @@ pub mod action { FeeChange(super::FeeChange), #[prost(message, tag = "56")] IbcSudoChange(super::IbcSudoChange), + /// MarketMap actions are defined on 71-80 + #[prost(message, tag = "71")] + UpsertMarkets(super::UpsertMarkets), + #[prost(message, tag = "72")] + CreateMarkets(super::CreateMarkets), + #[prost(message, tag = "73")] + UpdateMarkets(super::UpdateMarkets), + #[prost(message, tag = "74")] + UpdateParams(super::UpdateParams), + #[prost(message, tag = "75")] + RemoveMarketAuthorities(super::RemoveMarketAuthorities), + #[prost(message, tag = "76")] + RemoveMarkets(super::RemoveMarkets), } } impl ::prost::Name for Action { @@ -402,7 +415,7 @@ pub struct FeeChange { /// the new fee components values #[prost( oneof = "fee_change::FeeComponents", - tags = "1, 2, 3, 4, 5, 7, 6, 8, 9, 10, 11, 12, 13, 14" + tags = "1, 2, 3, 4, 5, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20" )] pub fee_components: ::core::option::Option, } @@ -442,6 +455,20 @@ pub mod fee_change { Transfer(super::super::super::fees::v1::TransferFeeComponents), #[prost(message, tag = "14")] ValidatorUpdate(super::super::super::fees::v1::ValidatorUpdateFeeComponents), + #[prost(message, tag = "15")] + UpsertMarkets(super::super::super::fees::v1::UpsertMarketsFeeComponents), + #[prost(message, tag = "16")] + CreateMarkets(super::super::super::fees::v1::CreateMarketsFeeComponents), + #[prost(message, tag = "17")] + UpdateMarkets(super::super::super::fees::v1::UpdateMarketsFeeComponents), + #[prost(message, tag = "18")] + UpdateParams(super::super::super::fees::v1::UpdateParamsFeeComponents), + #[prost(message, tag = "19")] + RemoveMarketAuthorities( + super::super::super::fees::v1::RemoveMarketAuthoritiesFeeComponents, + ), + #[prost(message, tag = "20")] + RemoveMarkets(super::super::super::fees::v1::RemoveMarketsFeeComponents), } } impl ::prost::Name for FeeChange { @@ -464,6 +491,104 @@ impl ::prost::Name for IbcSudoChange { ::prost::alloc::format!("astria.protocol.transaction.v1.{}", Self::NAME) } } +/// Updates or creates markets in the market map. If a market does not exist, it will be created. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct UpsertMarkets { + /// The list of all markets to be created or updated for the given transaction. + #[prost(message, repeated, tag = "2")] + pub markets: ::prost::alloc::vec::Vec< + super::super::super::super::connect::marketmap::v2::Market, + >, +} +impl ::prost::Name for UpsertMarkets { + const NAME: &'static str = "UpsertMarkets"; + const PACKAGE: &'static str = "astria.protocol.transaction.v1"; + fn full_name() -> ::prost::alloc::string::String { + ::prost::alloc::format!("astria.protocol.transaction.v1.{}", Self::NAME) + } +} +/// Creates new markets in the market map. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CreateMarkets { + /// The list of all markets to be created. + #[prost(message, repeated, tag = "2")] + pub create_markets: ::prost::alloc::vec::Vec< + super::super::super::super::connect::marketmap::v2::Market, + >, +} +impl ::prost::Name for CreateMarkets { + const NAME: &'static str = "CreateMarkets"; + const PACKAGE: &'static str = "astria.protocol.transaction.v1"; + fn full_name() -> ::prost::alloc::string::String { + ::prost::alloc::format!("astria.protocol.transaction.v1.{}", Self::NAME) + } +} +/// Updates existing markets in the market map. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct UpdateMarkets { + /// The list of all markets to be updated. + #[prost(message, repeated, tag = "2")] + pub update_markets: ::prost::alloc::vec::Vec< + super::super::super::super::connect::marketmap::v2::Market, + >, +} +impl ::prost::Name for UpdateMarkets { + const NAME: &'static str = "UpdateMarkets"; + const PACKAGE: &'static str = "astria.protocol.transaction.v1"; + fn full_name() -> ::prost::alloc::string::String { + ::prost::alloc::format!("astria.protocol.transaction.v1.{}", Self::NAME) + } +} +/// Updates the market map parameters. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct UpdateParams { + /// Params defines the new parameters for the x/marketmap module. + #[prost(message, optional, tag = "1")] + pub params: ::core::option::Option< + super::super::super::super::connect::marketmap::v2::Params, + >, +} +impl ::prost::Name for UpdateParams { + const NAME: &'static str = "UpdateParams"; + const PACKAGE: &'static str = "astria.protocol.transaction.v1"; + fn full_name() -> ::prost::alloc::string::String { + ::prost::alloc::format!("astria.protocol.transaction.v1.{}", Self::NAME) + } +} +/// Removes market map authorities. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RemoveMarketAuthorities { + /// RemoveAddresses is the list of addresses to remove. + #[prost(string, repeated, tag = "1")] + pub remove_addresses: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, +} +impl ::prost::Name for RemoveMarketAuthorities { + const NAME: &'static str = "RemoveMarketAuthorities"; + const PACKAGE: &'static str = "astria.protocol.transaction.v1"; + fn full_name() -> ::prost::alloc::string::String { + ::prost::alloc::format!("astria.protocol.transaction.v1.{}", Self::NAME) + } +} +/// Removes markets from the market map. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RemoveMarkets { + /// Markets is the list of markets to remove. + #[prost(string, repeated, tag = "2")] + pub markets: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, +} +impl ::prost::Name for RemoveMarkets { + const NAME: &'static str = "RemoveMarkets"; + const PACKAGE: &'static str = "astria.protocol.transaction.v1"; + fn full_name() -> ::prost::alloc::string::String { + ::prost::alloc::format!("astria.protocol.transaction.v1.{}", Self::NAME) + } +} /// `Transaction` is a transaction `TransactionBody` together with a public /// ket and a signature. #[allow(clippy::derive_partial_eq_without_eq)] diff --git a/crates/astria-core/src/generated/astria.protocol.transaction.v1.serde.rs b/crates/astria-core/src/generated/astria.protocol.transaction.v1.serde.rs index 4c77666d12..c8da12dd7b 100644 --- a/crates/astria-core/src/generated/astria.protocol.transaction.v1.serde.rs +++ b/crates/astria-core/src/generated/astria.protocol.transaction.v1.serde.rs @@ -54,6 +54,24 @@ impl serde::Serialize for Action { action::Value::IbcSudoChange(v) => { struct_ser.serialize_field("ibcSudoChange", v)?; } + action::Value::UpsertMarkets(v) => { + struct_ser.serialize_field("upsertMarkets", v)?; + } + action::Value::CreateMarkets(v) => { + struct_ser.serialize_field("createMarkets", v)?; + } + action::Value::UpdateMarkets(v) => { + struct_ser.serialize_field("updateMarkets", v)?; + } + action::Value::UpdateParams(v) => { + struct_ser.serialize_field("updateParams", v)?; + } + action::Value::RemoveMarketAuthorities(v) => { + struct_ser.serialize_field("removeMarketAuthorities", v)?; + } + action::Value::RemoveMarkets(v) => { + struct_ser.serialize_field("removeMarkets", v)?; + } } } struct_ser.end() @@ -92,6 +110,18 @@ impl<'de> serde::Deserialize<'de> for Action { "feeChange", "ibc_sudo_change", "ibcSudoChange", + "upsert_markets", + "upsertMarkets", + "create_markets", + "createMarkets", + "update_markets", + "updateMarkets", + "update_params", + "updateParams", + "remove_market_authorities", + "removeMarketAuthorities", + "remove_markets", + "removeMarkets", ]; #[allow(clippy::enum_variant_names)] @@ -110,6 +140,12 @@ impl<'de> serde::Deserialize<'de> for Action { FeeAssetChange, FeeChange, IbcSudoChange, + UpsertMarkets, + CreateMarkets, + UpdateMarkets, + UpdateParams, + RemoveMarketAuthorities, + RemoveMarkets, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -145,6 +181,12 @@ impl<'de> serde::Deserialize<'de> for Action { "feeAssetChange" | "fee_asset_change" => Ok(GeneratedField::FeeAssetChange), "feeChange" | "fee_change" => Ok(GeneratedField::FeeChange), "ibcSudoChange" | "ibc_sudo_change" => Ok(GeneratedField::IbcSudoChange), + "upsertMarkets" | "upsert_markets" => Ok(GeneratedField::UpsertMarkets), + "createMarkets" | "create_markets" => Ok(GeneratedField::CreateMarkets), + "updateMarkets" | "update_markets" => Ok(GeneratedField::UpdateMarkets), + "updateParams" | "update_params" => Ok(GeneratedField::UpdateParams), + "removeMarketAuthorities" | "remove_market_authorities" => Ok(GeneratedField::RemoveMarketAuthorities), + "removeMarkets" | "remove_markets" => Ok(GeneratedField::RemoveMarkets), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -263,6 +305,48 @@ impl<'de> serde::Deserialize<'de> for Action { return Err(serde::de::Error::duplicate_field("ibcSudoChange")); } value__ = map_.next_value::<::std::option::Option<_>>()?.map(action::Value::IbcSudoChange) +; + } + GeneratedField::UpsertMarkets => { + if value__.is_some() { + return Err(serde::de::Error::duplicate_field("upsertMarkets")); + } + value__ = map_.next_value::<::std::option::Option<_>>()?.map(action::Value::UpsertMarkets) +; + } + GeneratedField::CreateMarkets => { + if value__.is_some() { + return Err(serde::de::Error::duplicate_field("createMarkets")); + } + value__ = map_.next_value::<::std::option::Option<_>>()?.map(action::Value::CreateMarkets) +; + } + GeneratedField::UpdateMarkets => { + if value__.is_some() { + return Err(serde::de::Error::duplicate_field("updateMarkets")); + } + value__ = map_.next_value::<::std::option::Option<_>>()?.map(action::Value::UpdateMarkets) +; + } + GeneratedField::UpdateParams => { + if value__.is_some() { + return Err(serde::de::Error::duplicate_field("updateParams")); + } + value__ = map_.next_value::<::std::option::Option<_>>()?.map(action::Value::UpdateParams) +; + } + GeneratedField::RemoveMarketAuthorities => { + if value__.is_some() { + return Err(serde::de::Error::duplicate_field("removeMarketAuthorities")); + } + value__ = map_.next_value::<::std::option::Option<_>>()?.map(action::Value::RemoveMarketAuthorities) +; + } + GeneratedField::RemoveMarkets => { + if value__.is_some() { + return Err(serde::de::Error::duplicate_field("removeMarkets")); + } + value__ = map_.next_value::<::std::option::Option<_>>()?.map(action::Value::RemoveMarkets) ; } } @@ -782,6 +866,98 @@ impl<'de> serde::Deserialize<'de> for BridgeUnlock { deserializer.deserialize_struct("astria.protocol.transaction.v1.BridgeUnlock", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for CreateMarkets { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.create_markets.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("astria.protocol.transaction.v1.CreateMarkets", len)?; + if !self.create_markets.is_empty() { + struct_ser.serialize_field("createMarkets", &self.create_markets)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for CreateMarkets { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "create_markets", + "createMarkets", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + CreateMarkets, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + 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(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "createMarkets" | "create_markets" => Ok(GeneratedField::CreateMarkets), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = CreateMarkets; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct astria.protocol.transaction.v1.CreateMarkets") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut create_markets__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::CreateMarkets => { + if create_markets__.is_some() { + return Err(serde::de::Error::duplicate_field("createMarkets")); + } + create_markets__ = Some(map_.next_value()?); + } + } + } + Ok(CreateMarkets { + create_markets: create_markets__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("astria.protocol.transaction.v1.CreateMarkets", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for FeeAssetChange { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -945,6 +1121,24 @@ impl serde::Serialize for FeeChange { fee_change::FeeComponents::ValidatorUpdate(v) => { struct_ser.serialize_field("validatorUpdate", v)?; } + fee_change::FeeComponents::UpsertMarkets(v) => { + struct_ser.serialize_field("upsertMarkets", v)?; + } + fee_change::FeeComponents::CreateMarkets(v) => { + struct_ser.serialize_field("createMarkets", v)?; + } + fee_change::FeeComponents::UpdateMarkets(v) => { + struct_ser.serialize_field("updateMarkets", v)?; + } + fee_change::FeeComponents::UpdateParams(v) => { + struct_ser.serialize_field("updateParams", v)?; + } + fee_change::FeeComponents::RemoveMarketAuthorities(v) => { + struct_ser.serialize_field("removeMarketAuthorities", v)?; + } + fee_change::FeeComponents::RemoveMarkets(v) => { + struct_ser.serialize_field("removeMarkets", v)?; + } } } struct_ser.end() @@ -984,6 +1178,18 @@ impl<'de> serde::Deserialize<'de> for FeeChange { "transfer", "validator_update", "validatorUpdate", + "upsert_markets", + "upsertMarkets", + "create_markets", + "createMarkets", + "update_markets", + "updateMarkets", + "update_params", + "updateParams", + "remove_market_authorities", + "removeMarketAuthorities", + "remove_markets", + "removeMarkets", ]; #[allow(clippy::enum_variant_names)] @@ -1002,6 +1208,12 @@ impl<'de> serde::Deserialize<'de> for FeeChange { SudoAddressChange, Transfer, ValidatorUpdate, + UpsertMarkets, + CreateMarkets, + UpdateMarkets, + UpdateParams, + RemoveMarketAuthorities, + RemoveMarkets, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -1037,6 +1249,12 @@ impl<'de> serde::Deserialize<'de> for FeeChange { "sudoAddressChange" | "sudo_address_change" => Ok(GeneratedField::SudoAddressChange), "transfer" => Ok(GeneratedField::Transfer), "validatorUpdate" | "validator_update" => Ok(GeneratedField::ValidatorUpdate), + "upsertMarkets" | "upsert_markets" => Ok(GeneratedField::UpsertMarkets), + "createMarkets" | "create_markets" => Ok(GeneratedField::CreateMarkets), + "updateMarkets" | "update_markets" => Ok(GeneratedField::UpdateMarkets), + "updateParams" | "update_params" => Ok(GeneratedField::UpdateParams), + "removeMarketAuthorities" | "remove_market_authorities" => Ok(GeneratedField::RemoveMarketAuthorities), + "removeMarkets" | "remove_markets" => Ok(GeneratedField::RemoveMarkets), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -1155,6 +1373,48 @@ impl<'de> serde::Deserialize<'de> for FeeChange { return Err(serde::de::Error::duplicate_field("validatorUpdate")); } fee_components__ = map_.next_value::<::std::option::Option<_>>()?.map(fee_change::FeeComponents::ValidatorUpdate) +; + } + GeneratedField::UpsertMarkets => { + if fee_components__.is_some() { + return Err(serde::de::Error::duplicate_field("upsertMarkets")); + } + fee_components__ = map_.next_value::<::std::option::Option<_>>()?.map(fee_change::FeeComponents::UpsertMarkets) +; + } + GeneratedField::CreateMarkets => { + if fee_components__.is_some() { + return Err(serde::de::Error::duplicate_field("createMarkets")); + } + fee_components__ = map_.next_value::<::std::option::Option<_>>()?.map(fee_change::FeeComponents::CreateMarkets) +; + } + GeneratedField::UpdateMarkets => { + if fee_components__.is_some() { + return Err(serde::de::Error::duplicate_field("updateMarkets")); + } + fee_components__ = map_.next_value::<::std::option::Option<_>>()?.map(fee_change::FeeComponents::UpdateMarkets) +; + } + GeneratedField::UpdateParams => { + if fee_components__.is_some() { + return Err(serde::de::Error::duplicate_field("updateParams")); + } + fee_components__ = map_.next_value::<::std::option::Option<_>>()?.map(fee_change::FeeComponents::UpdateParams) +; + } + GeneratedField::RemoveMarketAuthorities => { + if fee_components__.is_some() { + return Err(serde::de::Error::duplicate_field("removeMarketAuthorities")); + } + fee_components__ = map_.next_value::<::std::option::Option<_>>()?.map(fee_change::FeeComponents::RemoveMarketAuthorities) +; + } + GeneratedField::RemoveMarkets => { + if fee_components__.is_some() { + return Err(serde::de::Error::duplicate_field("removeMarkets")); + } + fee_components__ = map_.next_value::<::std::option::Option<_>>()?.map(fee_change::FeeComponents::RemoveMarkets) ; } } @@ -1919,6 +2179,189 @@ impl<'de> serde::Deserialize<'de> for InitBridgeAccount { deserializer.deserialize_struct("astria.protocol.transaction.v1.InitBridgeAccount", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for RemoveMarketAuthorities { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.remove_addresses.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("astria.protocol.transaction.v1.RemoveMarketAuthorities", len)?; + if !self.remove_addresses.is_empty() { + struct_ser.serialize_field("removeAddresses", &self.remove_addresses)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for RemoveMarketAuthorities { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "remove_addresses", + "removeAddresses", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + RemoveAddresses, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + 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(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "removeAddresses" | "remove_addresses" => Ok(GeneratedField::RemoveAddresses), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = RemoveMarketAuthorities; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct astria.protocol.transaction.v1.RemoveMarketAuthorities") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut remove_addresses__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::RemoveAddresses => { + if remove_addresses__.is_some() { + return Err(serde::de::Error::duplicate_field("removeAddresses")); + } + remove_addresses__ = Some(map_.next_value()?); + } + } + } + Ok(RemoveMarketAuthorities { + remove_addresses: remove_addresses__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("astria.protocol.transaction.v1.RemoveMarketAuthorities", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for RemoveMarkets { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.markets.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("astria.protocol.transaction.v1.RemoveMarkets", len)?; + if !self.markets.is_empty() { + struct_ser.serialize_field("markets", &self.markets)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for RemoveMarkets { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "markets", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Markets, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + 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(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "markets" => Ok(GeneratedField::Markets), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = RemoveMarkets; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct astria.protocol.transaction.v1.RemoveMarkets") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut markets__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Markets => { + if markets__.is_some() { + return Err(serde::de::Error::duplicate_field("markets")); + } + markets__ = Some(map_.next_value()?); + } + } + } + Ok(RemoveMarkets { + markets: markets__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("astria.protocol.transaction.v1.RemoveMarkets", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for RollupDataSubmission { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -2635,3 +3078,277 @@ impl<'de> serde::Deserialize<'de> for Transfer { deserializer.deserialize_struct("astria.protocol.transaction.v1.Transfer", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for UpdateMarkets { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.update_markets.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("astria.protocol.transaction.v1.UpdateMarkets", len)?; + if !self.update_markets.is_empty() { + struct_ser.serialize_field("updateMarkets", &self.update_markets)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for UpdateMarkets { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "update_markets", + "updateMarkets", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + UpdateMarkets, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + 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(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "updateMarkets" | "update_markets" => Ok(GeneratedField::UpdateMarkets), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = UpdateMarkets; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct astria.protocol.transaction.v1.UpdateMarkets") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut update_markets__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::UpdateMarkets => { + if update_markets__.is_some() { + return Err(serde::de::Error::duplicate_field("updateMarkets")); + } + update_markets__ = Some(map_.next_value()?); + } + } + } + Ok(UpdateMarkets { + update_markets: update_markets__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("astria.protocol.transaction.v1.UpdateMarkets", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for UpdateParams { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.params.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("astria.protocol.transaction.v1.UpdateParams", len)?; + if let Some(v) = self.params.as_ref() { + struct_ser.serialize_field("params", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for UpdateParams { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "params", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Params, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + 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(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "params" => Ok(GeneratedField::Params), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = UpdateParams; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct astria.protocol.transaction.v1.UpdateParams") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut params__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Params => { + if params__.is_some() { + return Err(serde::de::Error::duplicate_field("params")); + } + params__ = map_.next_value()?; + } + } + } + Ok(UpdateParams { + params: params__, + }) + } + } + deserializer.deserialize_struct("astria.protocol.transaction.v1.UpdateParams", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for UpsertMarkets { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.markets.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("astria.protocol.transaction.v1.UpsertMarkets", len)?; + if !self.markets.is_empty() { + struct_ser.serialize_field("markets", &self.markets)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for UpsertMarkets { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "markets", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Markets, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + 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(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "markets" => Ok(GeneratedField::Markets), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = UpsertMarkets; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct astria.protocol.transaction.v1.UpsertMarkets") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut markets__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Markets => { + if markets__.is_some() { + return Err(serde::de::Error::duplicate_field("markets")); + } + markets__ = Some(map_.next_value()?); + } + } + } + Ok(UpsertMarkets { + markets: markets__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("astria.protocol.transaction.v1.UpsertMarkets", FIELDS, GeneratedVisitor) + } +} diff --git a/crates/astria-core/src/protocol/fees/v1.rs b/crates/astria-core/src/protocol/fees/v1.rs index fb5571e9b9..7249cc6d4b 100644 --- a/crates/astria-core/src/protocol/fees/v1.rs +++ b/crates/astria-core/src/protocol/fees/v1.rs @@ -17,15 +17,21 @@ use crate::{ BridgeLock, BridgeSudoChange, BridgeUnlock, + CreateMarkets, FeeAssetChange, FeeChange, IbcRelayerChange, IbcSudoChange, Ics20Withdrawal, InitBridgeAccount, + RemoveMarketAuthorities, + RemoveMarkets, RollupDataSubmission, SudoAddressChange, Transfer, + UpdateMarkets, + UpdateParams, + UpsertMarkets, ValidatorUpdate, }, Protobuf, @@ -108,6 +114,12 @@ impl_protobuf_for_fee_components!( FeeComponents => raw::FeeChangeFeeComponents, FeeComponents => raw::SudoAddressChangeFeeComponents, FeeComponents => raw::IbcSudoChangeFeeComponents, + FeeComponents => raw::UpsertMarketsFeeComponents, + FeeComponents => raw::CreateMarketsFeeComponents, + FeeComponents => raw::UpdateMarketsFeeComponents, + FeeComponents => raw::UpdateParamsFeeComponents, + FeeComponents => raw::RemoveMarketAuthoritiesFeeComponents, + FeeComponents => raw::RemoveMarketsFeeComponents, ); pub struct FeeComponents { diff --git a/crates/astria-core/src/protocol/genesis/v1.rs b/crates/astria-core/src/protocol/genesis/v1.rs index f5383d1d7e..c374d1b3ca 100644 --- a/crates/astria-core/src/protocol/genesis/v1.rs +++ b/crates/astria-core/src/protocol/genesis/v1.rs @@ -29,15 +29,21 @@ use crate::{ BridgeLock, BridgeSudoChange, BridgeUnlock, + CreateMarkets, FeeAssetChange, FeeChange, IbcRelayerChange, IbcSudoChange, Ics20Withdrawal, InitBridgeAccount, + RemoveMarketAuthorities, + RemoveMarkets, RollupDataSubmission, SudoAddressChange, Transfer, + UpdateMarkets, + UpdateParams, + UpsertMarkets, ValidatorUpdate, }, }, @@ -763,6 +769,12 @@ pub struct GenesisFees { pub ibc_relayer_change: Option>, pub sudo_address_change: Option>, pub ibc_sudo_change: Option>, + pub upsert_markets: Option>, + pub create_markets: Option>, + pub update_markets: Option>, + pub update_params: Option>, + pub remove_market_authorities: Option>, + pub remove_markets: Option>, } impl Protobuf for GenesisFees { @@ -789,6 +801,12 @@ impl Protobuf for GenesisFees { ibc_relayer_change, sudo_address_change, ibc_sudo_change, + upsert_markets, + create_markets, + update_markets, + update_params, + remove_market_authorities, + remove_markets, } = raw; let rollup_data_submission = rollup_data_submission .clone() @@ -875,6 +893,42 @@ impl Protobuf for GenesisFees { .transpose() .map_err(|e| FeesError::fee_components("ibc_sudo_change", e))?; + let upsert_markets = upsert_markets + .clone() + .map(FeeComponents::::try_from_raw) + .transpose() + .map_err(|e| FeesError::fee_components("upsert_markets", e))?; + + let create_markets = create_markets + .clone() + .map(FeeComponents::::try_from_raw) + .transpose() + .map_err(|e| FeesError::fee_components("create_markets", e))?; + + let update_markets = update_markets + .clone() + .map(FeeComponents::::try_from_raw) + .transpose() + .map_err(|e| FeesError::fee_components("update_markets", e))?; + + let update_params = update_params + .clone() + .map(FeeComponents::::try_from_raw) + .transpose() + .map_err(|e| FeesError::fee_components("update_params", e))?; + + let remove_market_authorities = remove_market_authorities + .clone() + .map(FeeComponents::::try_from_raw) + .transpose() + .map_err(|e| FeesError::fee_components("remove_market_authorities", e))?; + + let remove_markets = remove_markets + .clone() + .map(FeeComponents::::try_from_raw) + .transpose() + .map_err(|e| FeesError::fee_components("remove_markets", e))?; + Ok(Self { rollup_data_submission, transfer, @@ -890,6 +944,12 @@ impl Protobuf for GenesisFees { ibc_relayer_change, sudo_address_change, ibc_sudo_change, + upsert_markets, + create_markets, + update_markets, + update_params, + remove_market_authorities, + remove_markets, }) } @@ -909,6 +969,12 @@ impl Protobuf for GenesisFees { ibc_relayer_change, sudo_address_change, ibc_sudo_change, + upsert_markets, + create_markets, + update_markets, + update_params, + remove_market_authorities, + remove_markets, } = self; Self::Raw { transfer: transfer.map(|act| FeeComponents::::to_raw(&act)), @@ -934,6 +1000,13 @@ impl Protobuf for GenesisFees { .map(|act| FeeComponents::::to_raw(&act)), ibc_sudo_change: ibc_sudo_change .map(|act| FeeComponents::::to_raw(&act)), + upsert_markets: upsert_markets.map(|act| FeeComponents::::to_raw(&act)), + create_markets: create_markets.map(|act| FeeComponents::::to_raw(&act)), + update_markets: update_markets.map(|act| FeeComponents::::to_raw(&act)), + update_params: update_params.map(|act| FeeComponents::::to_raw(&act)), + remove_market_authorities: remove_market_authorities + .map(|act| FeeComponents::::to_raw(&act)), + remove_markets: remove_markets.map(|act| FeeComponents::::to_raw(&act)), } } } @@ -1120,6 +1193,14 @@ mod tests { ibc_relayer_change: Some(FeeComponents::::new(0, 0).to_raw()), sudo_address_change: Some(FeeComponents::::new(0, 0).to_raw()), ibc_sudo_change: Some(FeeComponents::::new(0, 0).to_raw()), + upsert_markets: Some(FeeComponents::::new(0, 0).to_raw()), + create_markets: Some(FeeComponents::::new(0, 0).to_raw()), + update_markets: Some(FeeComponents::::new(0, 0).to_raw()), + update_params: Some(FeeComponents::::new(0, 0).to_raw()), + remove_market_authorities: Some( + FeeComponents::::new(0, 0).to_raw(), + ), + remove_markets: Some(FeeComponents::::new(0, 0).to_raw()), }), connect: Some( ConnectGenesis { diff --git a/crates/astria-core/src/protocol/transaction/v1/action/group/mod.rs b/crates/astria-core/src/protocol/transaction/v1/action/group/mod.rs index c145176803..57a6e14630 100644 --- a/crates/astria-core/src/protocol/transaction/v1/action/group/mod.rs +++ b/crates/astria-core/src/protocol/transaction/v1/action/group/mod.rs @@ -14,15 +14,21 @@ use super::{ BridgeLock, BridgeSudoChange, BridgeUnlock, + CreateMarkets, FeeAssetChange, FeeChange, IbcRelayerChange, IbcSudoChange, Ics20Withdrawal, InitBridgeAccount, + RemoveMarketAuthorities, + RemoveMarkets, RollupDataSubmission, SudoAddressChange, Transfer, + UpdateMarkets, + UpdateParams, + UpsertMarkets, ValidatorUpdate, }; @@ -55,6 +61,12 @@ impl_belong_to_group!( (FeeAssetChange, Group::BundleableSudo), (IbcRelay, Group::BundleableGeneral), (IbcSudoChange, Group::UnbundleableSudo), + (UpsertMarkets, Group::BundleableGeneral), + (CreateMarkets, Group::BundleableGeneral), + (UpdateMarkets, Group::BundleableGeneral), + (UpdateParams, Group::BundleableSudo), + (RemoveMarketAuthorities, Group::BundleableGeneral), + (RemoveMarkets, Group::BundleableGeneral), ); impl Action { @@ -74,6 +86,12 @@ impl Action { Action::FeeAssetChange(_) => FeeAssetChange::GROUP, Action::Ibc(_) => IbcRelay::GROUP, Action::IbcSudoChange(_) => IbcSudoChange::GROUP, + Action::UpsertMarkets(_) => UpsertMarkets::GROUP, + Action::CreateMarkets(_) => CreateMarkets::GROUP, + Action::UpdateMarkets(_) => UpdateMarkets::GROUP, + Action::UpdateParams(_) => UpdateParams::GROUP, + Action::RemoveMarketAuthorities(_) => RemoveMarketAuthorities::GROUP, + Action::RemoveMarkets(_) => RemoveMarkets::GROUP, } } } diff --git a/crates/astria-core/src/protocol/transaction/v1/action/mod.rs b/crates/astria-core/src/protocol/transaction/v1/action/mod.rs index 5c2b93745b..50b1603b55 100644 --- a/crates/astria-core/src/protocol/transaction/v1/action/mod.rs +++ b/crates/astria-core/src/protocol/transaction/v1/action/mod.rs @@ -1,3 +1,5 @@ +use std::str::FromStr as _; + use bytes::Bytes; use ibc_types::{ core::{ @@ -11,6 +13,12 @@ use prost::Name as _; use super::raw; use crate::{ + connect::market_map::v2::{ + Market, + MarketError, + Params, + ParamsError, + }, primitive::v1::{ asset::{ self, @@ -51,6 +59,12 @@ pub enum Action { BridgeUnlock(BridgeUnlock), BridgeSudoChange(BridgeSudoChange), FeeChange(FeeChange), + UpsertMarkets(UpsertMarkets), + CreateMarkets(CreateMarkets), + UpdateMarkets(UpdateMarkets), + UpdateParams(UpdateParams), + RemoveMarketAuthorities(RemoveMarketAuthorities), + RemoveMarkets(RemoveMarkets), } impl Protobuf for Action { @@ -75,6 +89,12 @@ impl Protobuf for Action { Action::BridgeUnlock(act) => Value::BridgeUnlock(act.to_raw()), Action::BridgeSudoChange(act) => Value::BridgeSudoChange(act.to_raw()), Action::FeeChange(act) => Value::FeeChange(act.to_raw()), + Action::UpsertMarkets(act) => Value::UpsertMarkets(act.to_raw()), + Action::CreateMarkets(act) => Value::CreateMarkets(act.to_raw()), + Action::UpdateMarkets(act) => Value::UpdateMarkets(act.to_raw()), + Action::UpdateParams(act) => Value::UpdateParams(act.to_raw()), + Action::RemoveMarketAuthorities(act) => Value::RemoveMarketAuthorities(act.to_raw()), + Action::RemoveMarkets(act) => Value::RemoveMarkets(act.to_raw()), }; raw::Action { value: Some(kind), @@ -148,6 +168,25 @@ impl Protobuf for Action { Value::FeeChange(act) => { Self::FeeChange(FeeChange::try_from_raw_ref(&act).map_err(Error::fee_change)?) } + Value::UpsertMarkets(act) => Self::UpsertMarkets( + UpsertMarkets::try_from_raw(act).map_err(Error::upsert_markets)?, + ), + Value::CreateMarkets(act) => Self::CreateMarkets( + CreateMarkets::try_from_raw(act).map_err(Error::create_markets)?, + ), + Value::UpdateMarkets(act) => Self::UpdateMarkets( + UpdateMarkets::try_from_raw(act).map_err(Error::update_markets)?, + ), + Value::UpdateParams(act) => { + Self::UpdateParams(UpdateParams::try_from_raw(act).map_err(Error::update_params)?) + } + Value::RemoveMarketAuthorities(act) => Self::RemoveMarketAuthorities( + RemoveMarketAuthorities::try_from_raw(act) + .map_err(Error::remove_market_authorities)?, + ), + Value::RemoveMarkets(act) => Self::RemoveMarkets( + RemoveMarkets::try_from_raw(act).map_err(Error::remove_markets)?, + ), }; Ok(action) } @@ -258,6 +297,42 @@ impl From for Action { } } +impl From for Action { + fn from(value: UpsertMarkets) -> Self { + Self::UpsertMarkets(value) + } +} + +impl From for Action { + fn from(value: CreateMarkets) -> Self { + Self::CreateMarkets(value) + } +} + +impl From for Action { + fn from(value: UpdateMarkets) -> Self { + Self::UpdateMarkets(value) + } +} + +impl From for Action { + fn from(value: UpdateParams) -> Self { + Self::UpdateParams(value) + } +} + +impl From for Action { + fn from(value: RemoveMarketAuthorities) -> Self { + Self::RemoveMarketAuthorities(value) + } +} + +impl From for Action { + fn from(value: RemoveMarkets) -> Self { + Self::RemoveMarkets(value) + } +} + impl From for raw::Action { fn from(value: Action) -> Self { value.into_raw() @@ -295,6 +370,12 @@ impl ActionName for Action { Action::BridgeUnlock(_) => "BridgeUnlock", Action::BridgeSudoChange(_) => "BridgeSudoChange", Action::FeeChange(_) => "FeeChange", + Action::UpsertMarkets(_) => "UpsertMarkets", + Action::CreateMarkets(_) => "CreateMarkets", + Action::UpdateMarkets(_) => "UpdateMarkets", + Action::UpdateParams(_) => "UpdateParams", + Action::RemoveMarketAuthorities(_) => "RemoveMarketAuthorities", + Action::RemoveMarkets(_) => "RemoveMarkets", } } } @@ -363,6 +444,30 @@ impl Error { fn fee_change(inner: FeeChangeError) -> Self { Self(ActionErrorKind::FeeChange(inner)) } + + fn upsert_markets(inner: UpsertMarketsError) -> Self { + Self(ActionErrorKind::UpsertMarkets(inner)) + } + + fn create_markets(inner: CreateMarketsError) -> Self { + Self(ActionErrorKind::CreateMarkets(inner)) + } + + fn update_markets(inner: UpdateMarketsError) -> Self { + Self(ActionErrorKind::UpdateMarkets(inner)) + } + + fn update_params(inner: UpdateParamsError) -> Self { + Self(ActionErrorKind::UpdateParams(inner)) + } + + fn remove_market_authorities(inner: RemoveMarketAuthoritiesError) -> Self { + Self(ActionErrorKind::RemoveMarketAuthorities(inner)) + } + + fn remove_markets(inner: RemoveMarketsError) -> Self { + Self(ActionErrorKind::RemoveMarkets(inner)) + } } #[derive(Debug, thiserror::Error)] @@ -397,6 +502,18 @@ enum ActionErrorKind { BridgeSudoChange(#[source] BridgeSudoChangeError), #[error("fee change action was not valid")] FeeChange(#[source] FeeChangeError), + #[error("upsert markets action was not valid")] + UpsertMarkets(#[source] UpsertMarketsError), + #[error("create markets action was not valid")] + CreateMarkets(#[source] CreateMarketsError), + #[error("update markets action was not valid")] + UpdateMarkets(#[source] UpdateMarketsError), + #[error("update params action was not valid")] + UpdateParams(#[source] UpdateParamsError), + #[error("remove market authorities action was not valid")] + RemoveMarketAuthorities(#[source] RemoveMarketAuthoritiesError), + #[error("remove markets action was not valid")] + RemoveMarkets(#[source] RemoveMarketsError), } #[derive(Debug, thiserror::Error)] @@ -1943,6 +2060,12 @@ pub enum FeeChange { IbcRelayerChange(FeeComponents), SudoAddressChange(FeeComponents), IbcSudoChange(FeeComponents), + UpsertMarkets(FeeComponents), + CreateMarkets(FeeComponents), + UpdateMarkets(FeeComponents), + UpdateParams(FeeComponents), + RemoveMarketAuthorities(FeeComponents), + RemoveMarkets(FeeComponents), } impl Protobuf for FeeChange { @@ -1995,6 +2118,24 @@ impl Protobuf for FeeChange { Self::IbcSudoChange(fee_change) => { raw::fee_change::FeeComponents::IbcSudoChange(fee_change.to_raw()) } + Self::UpsertMarkets(fee_change) => { + raw::fee_change::FeeComponents::UpsertMarkets(fee_change.to_raw()) + } + Self::CreateMarkets(fee_change) => { + raw::fee_change::FeeComponents::CreateMarkets(fee_change.to_raw()) + } + Self::UpdateMarkets(fee_change) => { + raw::fee_change::FeeComponents::UpdateMarkets(fee_change.to_raw()) + } + Self::UpdateParams(fee_change) => { + raw::fee_change::FeeComponents::UpdateParams(fee_change.to_raw()) + } + Self::RemoveMarketAuthorities(fee_change) => { + raw::fee_change::FeeComponents::RemoveMarketAuthorities(fee_change.to_raw()) + } + Self::RemoveMarkets(fee_change) => { + raw::fee_change::FeeComponents::RemoveMarkets(fee_change.to_raw()) + } }), } } @@ -2065,6 +2206,26 @@ impl Protobuf for FeeChange { Some(raw::fee_change::FeeComponents::IbcSudoChange(fee_change)) => Self::IbcSudoChange( FeeComponents::::try_from_raw_ref(fee_change)?, ), + Some(raw::fee_change::FeeComponents::UpsertMarkets(fee_change)) => Self::UpsertMarkets( + FeeComponents::::try_from_raw_ref(fee_change)?, + ), + Some(raw::fee_change::FeeComponents::CreateMarkets(fee_change)) => Self::CreateMarkets( + FeeComponents::::try_from_raw_ref(fee_change)?, + ), + Some(raw::fee_change::FeeComponents::UpdateMarkets(fee_change)) => Self::UpdateMarkets( + FeeComponents::::try_from_raw_ref(fee_change)?, + ), + Some(raw::fee_change::FeeComponents::UpdateParams(fee_change)) => { + Self::UpdateParams(FeeComponents::::try_from_raw_ref(fee_change)?) + } + Some(raw::fee_change::FeeComponents::RemoveMarketAuthorities(fee_change)) => { + Self::RemoveMarketAuthorities( + FeeComponents::::try_from_raw_ref(fee_change)?, + ) + } + Some(raw::fee_change::FeeComponents::RemoveMarkets(fee_change)) => Self::RemoveMarkets( + FeeComponents::::try_from_raw_ref(fee_change)?, + ), None => return Err(FeeChangeError::field_unset("fee_components")), }) } @@ -2153,3 +2314,300 @@ impl From> for FeeChange { FeeChange::IbcSudoChange(fee) } } + +/// Updates markets or creates them if they do not exist in the market map. +#[derive(Debug, Clone)] +pub struct UpsertMarkets { + // The list of all markets to be upserted for the given + // transaction. + pub markets: Vec, +} + +impl Protobuf for UpsertMarkets { + type Error = UpsertMarketsError; + type Raw = raw::UpsertMarkets; + + fn try_from_raw_ref(raw: &Self::Raw) -> Result { + let markets = raw + .markets + .iter() + .map(|market| Market::try_from_raw(market.clone())) + .collect::, _>>() + .map_err(UpsertMarketsError::invalid_market)?; + Ok(Self { + markets, + }) + } + + fn to_raw(&self) -> Self::Raw { + Self::Raw { + markets: self + .markets + .iter() + .map(|market| market.clone().into_raw()) + .collect(), + } + } +} + +#[derive(Debug, thiserror::Error)] +#[error(transparent)] +pub struct UpsertMarketsError(UpsertMarketsErrorKind); + +impl UpsertMarketsError { + #[must_use] + pub fn invalid_market(err: MarketError) -> Self { + Self(UpsertMarketsErrorKind::InvalidMarket(err)) + } +} + +#[derive(Debug, thiserror::Error)] +pub enum UpsertMarketsErrorKind { + #[error("invalid market in market list")] + InvalidMarket(#[from] MarketError), +} + +/// Creates new markets in the market map. +#[derive(Debug, Clone)] +pub struct CreateMarkets { + /// The list of all markets to be created for the given + /// transaction. + pub create_markets: Vec, +} + +impl Protobuf for CreateMarkets { + type Error = CreateMarketsError; + type Raw = raw::CreateMarkets; + + fn try_from_raw_ref(raw: &Self::Raw) -> Result { + let create_markets = raw + .create_markets + .iter() + .map(|market| Market::try_from_raw(market.clone())) + .collect::, _>>() + .map_err(CreateMarketsError::invalid_market)?; + Ok(Self { + create_markets, + }) + } + + fn to_raw(&self) -> Self::Raw { + Self::Raw { + create_markets: self + .create_markets + .iter() + .map(|market| market.clone().into_raw()) + .collect(), + } + } +} + +#[derive(Debug, thiserror::Error)] +#[error(transparent)] +pub struct CreateMarketsError(CreateMarketsErrorKind); + +impl CreateMarketsError { + #[must_use] + pub fn invalid_market(err: MarketError) -> Self { + Self(CreateMarketsErrorKind::InvalidMarket(err)) + } +} + +#[derive(Debug, thiserror::Error)] +pub enum CreateMarketsErrorKind { + #[error("invalid market in create_market list")] + InvalidMarket(#[from] MarketError), + #[error("authority string could not be parsed to address")] + AuthorityParse(#[from] AddressError), +} + +/// Updates existing markets in the market map. +#[derive(Debug, Clone)] +pub struct UpdateMarkets { + /// The list of all markets to be updated for the given + /// transaction. + pub update_markets: Vec, +} + +impl Protobuf for UpdateMarkets { + type Error = UpdateMarketsError; + type Raw = raw::UpdateMarkets; + + fn try_from_raw_ref(raw: &Self::Raw) -> Result { + let update_markets = raw + .update_markets + .iter() + .map(|market| Market::try_from_raw(market.clone())) + .collect::, _>>() + .map_err(UpdateMarketsError::invalid_market)?; + Ok(Self { + update_markets, + }) + } + + fn to_raw(&self) -> Self::Raw { + Self::Raw { + update_markets: self + .update_markets + .iter() + .map(|market| market.clone().into_raw()) + .collect(), + } + } +} + +#[derive(Debug, thiserror::Error)] +#[error(transparent)] +pub struct UpdateMarketsError(UpdateMarketsErrorKind); + +impl UpdateMarketsError { + #[must_use] + pub fn invalid_market(err: MarketError) -> Self { + Self(UpdateMarketsErrorKind::InvalidMarket(err)) + } +} + +#[derive(Debug, thiserror::Error)] +pub enum UpdateMarketsErrorKind { + #[error("invalid market in update_market list")] + InvalidMarket(#[from] MarketError), +} + +/// Updates the market map params. +#[derive(Debug, Clone)] +pub struct UpdateParams { + /// The new parameters for the `connect/marketmap` module. + pub params: Params, +} + +impl Protobuf for UpdateParams { + type Error = UpdateParamsError; + type Raw = raw::UpdateParams; + + fn try_from_raw_ref(raw: &Self::Raw) -> Result { + let params = Params::try_from_raw( + raw.params + .clone() + .ok_or(UpdateParamsError::missing_params())?, + ) + .map_err(UpdateParamsError::invalid_params)?; + Ok(Self { + params, + }) + } + + fn to_raw(&self) -> Self::Raw { + Self::Raw { + params: Some(self.params.clone().into_raw()), + } + } +} + +#[derive(Debug, thiserror::Error)] +#[error(transparent)] +pub struct UpdateParamsError(UpdateParamsErrorKind); + +impl UpdateParamsError { + #[must_use] + pub fn missing_params() -> Self { + Self(UpdateParamsErrorKind::MissingParams) + } + + #[must_use] + pub fn invalid_params(err: ParamsError) -> Self { + Self(UpdateParamsErrorKind::InvalidParams(err)) + } +} + +#[derive(Debug, thiserror::Error)] +pub enum UpdateParamsErrorKind { + #[error("missing params")] + MissingParams, + #[error("invalid params")] + InvalidParams(#[from] ParamsError), + #[error("authority string could not be parsed to address")] + AuthorityParse(#[from] AddressError), +} + +/// Removes addresses from the market map list of authorities. +#[derive(Debug, Clone)] +pub struct RemoveMarketAuthorities { + /// The list of addresses to remove. + pub remove_addresses: Vec
, +} + +impl Protobuf for RemoveMarketAuthorities { + type Error = RemoveMarketAuthoritiesError; + type Raw = raw::RemoveMarketAuthorities; + + fn try_from_raw_ref(raw: &Self::Raw) -> Result { + let remove_addresses = raw + .remove_addresses + .iter() + .map(|address| Address::from_str(address.as_str())) + .collect::>() + .map_err(RemoveMarketAuthoritiesError::remove_address_parse)?; + Ok(Self { + remove_addresses, + }) + } + + fn to_raw(&self) -> Self::Raw { + let remove_addresses = self + .remove_addresses + .iter() + .map(ToString::to_string) + .collect(); + Self::Raw { + remove_addresses, + } + } +} + +#[derive(Debug, thiserror::Error)] +#[error(transparent)] +pub struct RemoveMarketAuthoritiesError(RemoveMarketAuthoritiesErrorKind); + +impl RemoveMarketAuthoritiesError { + #[must_use] + pub fn remove_address_parse(err: AddressError) -> Self { + Self(RemoveMarketAuthoritiesErrorKind::RemoveAddressParse(err)) + } +} + +#[derive(Debug, thiserror::Error)] +pub enum RemoveMarketAuthoritiesErrorKind { + #[error("address in remove_addresses could not be parsed to domain type")] + RemoveAddressParse(#[source] AddressError), +} + +/// Removes markets from the market map. +#[derive(Debug, Clone)] +pub struct RemoveMarkets { + /// The list of all markets to be removed. + pub markets: Vec, +} + +impl Protobuf for RemoveMarkets { + type Error = RemoveMarketsError; + type Raw = raw::RemoveMarkets; + + fn try_from_raw_ref(raw: &Self::Raw) -> Result { + Ok(Self { + markets: raw.markets.clone(), + }) + } + + fn to_raw(&self) -> Self::Raw { + Self::Raw { + markets: self.markets.clone(), + } + } +} + +#[derive(Debug, thiserror::Error)] +#[error(transparent)] +pub struct RemoveMarketsError(RemoveMarketsErrorKind); + +#[derive(Debug, thiserror::Error)] +pub enum RemoveMarketsErrorKind {} diff --git a/crates/astria-sequencer-utils/src/genesis_example.rs b/crates/astria-sequencer-utils/src/genesis_example.rs index b84f29a70e..8813eaf5cf 100644 --- a/crates/astria-sequencer-utils/src/genesis_example.rs +++ b/crates/astria-sequencer-utils/src/genesis_example.rs @@ -12,15 +12,19 @@ use astria_core::{ IbcParameters, }, connect::{ - marketmap, - marketmap::v2::{ - Market, - MarketMap, + marketmap::{ + self, + v2::{ + Market, + MarketMap, + }, }, - oracle, - oracle::v2::{ - CurrencyPairGenesis, - QuotePrice, + oracle::{ + self, + v2::{ + CurrencyPairGenesis, + QuotePrice, + }, }, types::v2::CurrencyPair, }, @@ -36,15 +40,21 @@ use astria_core::{ BridgeLock, BridgeSudoChange, BridgeUnlock, + CreateMarkets, FeeAssetChange, FeeChange, IbcRelayerChange, IbcSudoChange, Ics20Withdrawal, InitBridgeAccount, + RemoveMarketAuthorities, + RemoveMarkets, RollupDataSubmission, SudoAddressChange, Transfer, + UpdateMarkets, + UpdateParams, + UpsertMarkets, ValidatorUpdate, }, }, @@ -243,6 +253,14 @@ fn proto_genesis_state() -> astria_core::generated::astria::protocol::genesis::v ibc_relayer_change: Some(FeeComponents::::new(0, 0).to_raw()), sudo_address_change: Some(FeeComponents::::new(0, 0).to_raw()), ibc_sudo_change: Some(FeeComponents::::new(0, 0).to_raw()), + upsert_markets: Some(FeeComponents::::new(0, 0).to_raw()), + create_markets: Some(FeeComponents::::new(0, 0).to_raw()), + update_markets: Some(FeeComponents::::new(0, 0).to_raw()), + update_params: Some(FeeComponents::::new(0, 0).to_raw()), + remove_market_authorities: Some( + FeeComponents::::new(0, 0).to_raw(), + ), + remove_markets: Some(FeeComponents::::new(0, 0).to_raw()), }), } } diff --git a/crates/astria-sequencer/src/action_handler/impls/create_markets.rs b/crates/astria-sequencer/src/action_handler/impls/create_markets.rs new file mode 100644 index 0000000000..a25c41f0c7 --- /dev/null +++ b/crates/astria-sequencer/src/action_handler/impls/create_markets.rs @@ -0,0 +1,208 @@ +use astria_core::{ + connect::market_map::v2::MarketMap, + protocol::transaction::v1::action::CreateMarkets, +}; +use astria_eyre::eyre::{ + self, + bail, + Context as _, + OptionExt as _, +}; +use cnidarium::StateWrite; +use indexmap::IndexMap; + +use crate::{ + action_handler::ActionHandler, + address::StateReadExt as _, + app::StateReadExt as _, + connect::market_map::state_ext::{ + StateReadExt as _, + StateWriteExt as _, + }, + transaction::StateReadExt as _, +}; + +#[async_trait::async_trait] +impl ActionHandler for CreateMarkets { + async fn check_stateless(&self) -> eyre::Result<()> { + Ok(()) + } + + async fn check_and_execute(&self, mut state: S) -> eyre::Result<()> { + // check that the signer of the transaction is a market authority + let from = state + .try_base_prefixed( + &state + .get_transaction_context() + .expect("transaction source must be present in state when executing an action") + .address_bytes(), + ) + .await + .wrap_err("failed to convert signer address to base prefixed address")?; + let market_authorities = state + .get_params() + .await? + .ok_or_eyre("market map params not found in state")? + .market_authorities; + if !market_authorities.contains(&from) { + bail!("address {from} is not a market authority"); + } + + // create markets, erroring if any already exist + let mut market_map = state + .get_market_map() + .await + .wrap_err("failed to get market map")? + .unwrap_or(MarketMap { + markets: IndexMap::new(), + }); + for market in &self.create_markets { + let ticker_key = market.ticker.currency_pair.to_string(); + if market_map.markets.contains_key(&ticker_key) { + bail!("market for ticker {ticker_key} already exists"); + } + market_map.markets.insert(ticker_key, market.clone()); + } + state + .put_market_map(market_map) + .wrap_err("failed to put market map into state")?; + + // update the last updated height for the market map + state + .put_market_map_last_updated_height( + state + .get_block_height() + .await + .wrap_err("failed to get block height")?, + ) + .wrap_err("failed to update latest market map height")?; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + + use astria_core::{ + connect::market_map::v2::{ + Market, + Params, + }, + primitive::v1::TransactionId, + }; + + use super::*; + use crate::{ + accounts::AddressBytes, + address::StateWriteExt as _, + app::StateWriteExt as _, + benchmark_and_test_utils::{ + astria_address, + ASTRIA_PREFIX, + }, + test_utils::example_ticker, + transaction::{ + StateWriteExt as _, + TransactionContext, + }, + }; + + #[tokio::test] + async fn create_markets_executes_as_expected() { + let storage = cnidarium::TempStorage::new().await.unwrap(); + let snapshot = storage.latest_snapshot(); + let mut state = cnidarium::StateDelta::new(snapshot); + + let authority_address = astria_address(&[0; 20]); + + let params = Params { + market_authorities: vec![authority_address], + admin: authority_address, + }; + state.put_params(params).unwrap(); + + state.put_block_height(1).unwrap(); + state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); + state.put_transaction_context(TransactionContext { + address_bytes: *authority_address.address_bytes(), + transaction_id: TransactionId::new([0; 32]), + position_in_transaction: 0, + }); + + let ticker = example_ticker(String::new()); + let market = Market { + ticker: ticker.clone(), + provider_configs: vec![], + }; + + let action = CreateMarkets { + create_markets: vec![market.clone()], + }; + action.check_and_execute(&mut state).await.unwrap(); + let market_map = state.get_market_map().await.unwrap().unwrap(); + assert_eq!(market_map.markets.len(), 1); + assert_eq!( + *market_map + .markets + .get(&ticker.currency_pair.to_string()) + .unwrap(), + market, + ); + assert_eq!(state.get_market_map_last_updated_height().await.unwrap(), 1); + } + + #[tokio::test] + async fn create_markets_fails_if_authority_is_invalid() { + let storage = cnidarium::TempStorage::new().await.unwrap(); + let snapshot = storage.latest_snapshot(); + let mut state = cnidarium::StateDelta::new(snapshot); + + let authority_address = astria_address(&[0; 20]); + + let params = Params { + market_authorities: vec![], // should fail even though the authority address is admin + admin: authority_address, + }; + state.put_params(params).unwrap(); + + state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); + state.put_transaction_context(TransactionContext { + address_bytes: *authority_address.address_bytes(), + transaction_id: TransactionId::new([0; 32]), + position_in_transaction: 0, + }); + + let action = CreateMarkets { + create_markets: vec![], + }; + let res = action.check_and_execute(&mut state).await.unwrap_err(); + assert!(res.to_string().contains(&format!( + "address {authority_address} is not a market authority" + ))); + assert!(state.get_market_map().await.unwrap().is_none()); + } + + #[tokio::test] + async fn create_markets_fails_if_params_not_found() { + let storage = cnidarium::TempStorage::new().await.unwrap(); + let snapshot = storage.latest_snapshot(); + let mut state = cnidarium::StateDelta::new(snapshot); + + state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); + state.put_transaction_context(TransactionContext { + address_bytes: [0; 20], + transaction_id: TransactionId::new([0; 32]), + position_in_transaction: 0, + }); + + let action = CreateMarkets { + create_markets: vec![], + }; + let res = action.check_and_execute(&mut state).await.unwrap_err(); + assert!( + res.to_string() + .contains("market map params not found in state") + ); + assert!(state.get_market_map().await.unwrap().is_none()); + } +} diff --git a/crates/astria-sequencer/src/action_handler/impls/fee_change.rs b/crates/astria-sequencer/src/action_handler/impls/fee_change.rs index f066ded9ea..69d8b2da6c 100644 --- a/crates/astria-sequencer/src/action_handler/impls/fee_change.rs +++ b/crates/astria-sequencer/src/action_handler/impls/fee_change.rs @@ -77,6 +77,24 @@ impl ActionHandler for FeeChange { Self::IbcSudoChange(fees) => state .put_fees(*fees) .wrap_err("failed to put ibc sudo change fees"), + Self::UpsertMarkets(fees) => state + .put_fees(*fees) + .wrap_err("failed to put upsert markets fees"), + Self::CreateMarkets(fees) => state + .put_fees(*fees) + .wrap_err("failed to put create markets fees"), + Self::UpdateMarkets(fees) => state + .put_fees(*fees) + .wrap_err("failed to put update markets fees"), + Self::UpdateParams(fees) => state + .put_fees(*fees) + .wrap_err("failed to put update params fees"), + Self::RemoveMarketAuthorities(fees) => state + .put_fees(*fees) + .wrap_err("failed to put remove market authorities fees"), + Self::RemoveMarkets(fees) => state + .put_fees(*fees) + .wrap_err("failed to put remove markets fees"), } } } diff --git a/crates/astria-sequencer/src/action_handler/impls/mod.rs b/crates/astria-sequencer/src/action_handler/impls/mod.rs index c273cc26ff..054d959e5b 100644 --- a/crates/astria-sequencer/src/action_handler/impls/mod.rs +++ b/crates/astria-sequencer/src/action_handler/impls/mod.rs @@ -1,16 +1,22 @@ pub(crate) mod bridge_lock; pub(crate) mod bridge_sudo_change; pub(crate) mod bridge_unlock; +pub(crate) mod create_markets; pub(crate) mod fee_asset_change; pub(crate) mod fee_change; pub(crate) mod ibc_relayer_change; pub(crate) mod ibc_sudo_change; pub(crate) mod ics20_withdrawal; pub(crate) mod init_bridge_account; +pub(crate) mod remove_market_authorities; +pub(crate) mod remove_markets; pub(crate) mod rollup_data_submission; pub(crate) mod sudo_address_change; #[cfg(test)] pub(crate) mod test_utils; pub(crate) mod transaction; pub(crate) mod transfer; +pub(crate) mod update_markets; +pub(crate) mod update_params; +pub(crate) mod upsert_markets; pub(crate) mod validator_update; diff --git a/crates/astria-sequencer/src/action_handler/impls/remove_market_authorities.rs b/crates/astria-sequencer/src/action_handler/impls/remove_market_authorities.rs new file mode 100644 index 0000000000..672480336b --- /dev/null +++ b/crates/astria-sequencer/src/action_handler/impls/remove_market_authorities.rs @@ -0,0 +1,192 @@ +use astria_core::protocol::transaction::v1::action::RemoveMarketAuthorities; +use astria_eyre::eyre::{ + self, + ensure, + Context as _, + OptionExt as _, +}; +use cnidarium::StateWrite; + +use crate::{ + action_handler::ActionHandler, + address::StateReadExt as _, + connect::market_map::state_ext::{ + StateReadExt as _, + StateWriteExt as _, + }, + transaction::StateReadExt as _, +}; + +#[async_trait::async_trait] +impl ActionHandler for RemoveMarketAuthorities { + async fn check_stateless(&self) -> eyre::Result<()> { + Ok(()) + } + + async fn check_and_execute(&self, mut state: S) -> eyre::Result<()> { + let from = state + .try_base_prefixed( + &state + .get_transaction_context() + .expect("transaction source must be present in state when executing an action") + .address_bytes(), + ) + .await + .wrap_err("failed to convert signer address to base prefixed address")?; + let mut params = state + .get_params() + .await + .wrap_err("failed to obtain market map params from state")? + .ok_or_eyre("market map params not found in state")?; + ensure!(params.admin == from, "signer is not the market map admin"); + for address in &self.remove_addresses { + params.market_authorities.retain(|a| a != address); + } + state + .put_params(params) + .wrap_err("failed to put params into state")?; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use astria_core::{ + connect::market_map::v2::Params, + primitive::v1::TransactionId, + protocol::transaction::v1::action::RemoveMarketAuthorities, + }; + + use super::*; + use crate::{ + accounts::AddressBytes as _, + address::StateWriteExt as _, + benchmark_and_test_utils::{ + astria_address, + ASTRIA_PREFIX, + }, + transaction::{ + StateWriteExt as _, + TransactionContext, + }, + }; + + #[tokio::test] + async fn remove_market_authorities_executes_as_expected() { + let storage = cnidarium::TempStorage::new().await.unwrap(); + let snapshot = storage.latest_snapshot(); + let mut state = cnidarium::StateDelta::new(snapshot); + + let admin_address = astria_address(&[0; 20]); + let address_1 = astria_address(&[1; 20]); + let address_2 = astria_address(&[2; 20]); + + state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); + state.put_transaction_context(TransactionContext { + address_bytes: *admin_address.address_bytes(), + transaction_id: TransactionId::new([0; 32]), + position_in_transaction: 0, + }); + + let params = Params { + market_authorities: vec![address_1, address_2], + admin: admin_address, + }; + state.put_params(params.clone()).unwrap(); + + assert_eq!(state.get_params().await.unwrap().unwrap(), params); + + let action = RemoveMarketAuthorities { + remove_addresses: vec![address_1], + }; + action.check_and_execute(&mut state).await.unwrap(); + let params = state.get_params().await.unwrap().unwrap(); + assert_eq!(params.market_authorities, vec![address_2]); + } + + #[tokio::test] + async fn remove_market_authorities_fails_if_admin_address_is_invalid() { + let storage = cnidarium::TempStorage::new().await.unwrap(); + let snapshot = storage.latest_snapshot(); + let mut state = cnidarium::StateDelta::new(snapshot); + + let admin_address = astria_address(&[0; 20]); + let other_address = astria_address(&[1; 20]); + + state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); + state.put_transaction_context(TransactionContext { + address_bytes: *other_address.address_bytes(), + transaction_id: TransactionId::new([0; 32]), + position_in_transaction: 0, + }); + + let params = Params { + market_authorities: vec![], + admin: admin_address, + }; + state.put_params(params.clone()).unwrap(); + + let action = RemoveMarketAuthorities { + remove_addresses: vec![], + }; + let res = action.check_and_execute(&mut state).await.unwrap_err(); + assert_eq!(res.to_string(), "signer is not the market map admin"); + } + + #[tokio::test] + async fn remove_market_authorities_skips_missing_addresses() { + let storage = cnidarium::TempStorage::new().await.unwrap(); + let snapshot = storage.latest_snapshot(); + let mut state = cnidarium::StateDelta::new(snapshot); + + let admin_address = astria_address(&[0; 20]); + let address_1 = astria_address(&[1; 20]); + let address_2 = astria_address(&[2; 20]); + + state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); + state.put_transaction_context(TransactionContext { + address_bytes: *admin_address.address_bytes(), + transaction_id: TransactionId::new([0; 32]), + position_in_transaction: 0, + }); + + let params = Params { + market_authorities: vec![address_2], + admin: admin_address, + }; + state.put_params(params.clone()).unwrap(); + + assert_eq!(state.get_params().await.unwrap().unwrap(), params); + + let action = RemoveMarketAuthorities { + remove_addresses: vec![address_1], + }; + action.check_and_execute(&mut state).await.unwrap(); + let params = state.get_params().await.unwrap().unwrap(); + assert_eq!(params.market_authorities, vec![address_2]); + } + + #[tokio::test] + async fn remove_market_authorities_fails_if_params_not_found() { + let storage = cnidarium::TempStorage::new().await.unwrap(); + let snapshot = storage.latest_snapshot(); + let mut state = cnidarium::StateDelta::new(snapshot); + + state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); + state.put_transaction_context(TransactionContext { + address_bytes: [0; 20], + transaction_id: TransactionId::new([0; 32]), + position_in_transaction: 0, + }); + + let action = RemoveMarketAuthorities { + remove_addresses: vec![], + }; + let res = action.check_and_execute(&mut state).await.unwrap_err(); + assert!( + res.to_string() + .contains("market map params not found in state") + ); + assert!(state.get_market_map().await.unwrap().is_none()); + } +} diff --git a/crates/astria-sequencer/src/action_handler/impls/remove_markets.rs b/crates/astria-sequencer/src/action_handler/impls/remove_markets.rs new file mode 100644 index 0000000000..deca5d6ffb --- /dev/null +++ b/crates/astria-sequencer/src/action_handler/impls/remove_markets.rs @@ -0,0 +1,207 @@ +use astria_core::{ + connect::market_map::v2::MarketMap, + protocol::transaction::v1::action::RemoveMarkets, +}; +use astria_eyre::eyre::{ + self, + bail, + Context as _, + OptionExt as _, +}; +use cnidarium::StateWrite; +use indexmap::IndexMap; + +use crate::{ + action_handler::ActionHandler, + address::StateReadExt as _, + app::StateReadExt as _, + connect::market_map::state_ext::{ + StateReadExt as _, + StateWriteExt as _, + }, + transaction::StateReadExt as _, +}; + +#[async_trait::async_trait] +impl ActionHandler for RemoveMarkets { + async fn check_stateless(&self) -> eyre::Result<()> { + Ok(()) + } + + async fn check_and_execute(&self, mut state: S) -> eyre::Result<()> { + // check that the signer of the transaction is a market authority + let from = state + .try_base_prefixed( + &state + .get_transaction_context() + .expect("transaction source must be present in state when executing an action") + .address_bytes(), + ) + .await + .wrap_err("failed to convert signer address to base prefixed address")?; + let market_authorities = state + .get_params() + .await? + .ok_or_eyre("market map params not found in state")? + .market_authorities; + if !market_authorities.contains(&from) { + bail!("address {from} is not a market authority"); + } + + // remove markets, skipping any which do not exist + let mut market_map = state + .get_market_map() + .await + .wrap_err("failed to get market map")? + .unwrap_or(MarketMap { + markets: IndexMap::new(), + }); + for key in &self.markets { + market_map.markets.shift_remove(key); + } + state + .put_market_map(market_map) + .wrap_err("failed to put market map into state")?; + + // update the last updated height for the market map + state + .put_market_map_last_updated_height( + state + .get_block_height() + .await + .wrap_err("failed to get block height")?, + ) + .wrap_err("failed to update latest market map height")?; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use astria_core::{ + connect::market_map::v2::{ + Market, + Params, + }, + primitive::v1::TransactionId, + }; + + use super::*; + use crate::{ + accounts::AddressBytes as _, + address::StateWriteExt as _, + app::StateWriteExt as _, + benchmark_and_test_utils::{ + astria_address, + ASTRIA_PREFIX, + }, + test_utils::example_ticker, + transaction::{ + StateWriteExt as _, + TransactionContext, + }, + }; + + #[tokio::test] + async fn remove_markets_executes_as_expected() { + let storage = cnidarium::TempStorage::new().await.unwrap(); + let snapshot = storage.latest_snapshot(); + let mut state = cnidarium::StateDelta::new(snapshot); + + let authority_address = astria_address(&[0; 20]); + + state.put_block_height(1).unwrap(); + state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); + state.put_transaction_context(TransactionContext { + address_bytes: *authority_address.address_bytes(), + transaction_id: TransactionId::new([0; 32]), + position_in_transaction: 0, + }); + + let params = Params { + market_authorities: vec![authority_address], + admin: authority_address, + }; + state.put_params(params).unwrap(); + + let ticker = example_ticker(String::new()); + + let mut markets = IndexMap::new(); + markets.insert( + ticker.currency_pair.to_string(), + Market { + ticker: ticker.clone(), + provider_configs: vec![], + }, + ); + + state + .put_market_map(MarketMap { + markets, + }) + .unwrap(); + + let action = RemoveMarkets { + markets: vec![ticker.currency_pair.to_string()], + }; + action.check_and_execute(&mut state).await.unwrap(); + let market_map = state.get_market_map().await.unwrap().unwrap(); + assert_eq!(market_map.markets.len(), 0); + assert_eq!(state.get_market_map_last_updated_height().await.unwrap(), 1); + } + + #[tokio::test] + async fn remove_markets_fails_if_authority_is_invalid() { + let storage = cnidarium::TempStorage::new().await.unwrap(); + let snapshot = storage.latest_snapshot(); + let mut state = cnidarium::StateDelta::new(snapshot); + + let authority_address = astria_address(&[0; 20]); + + state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); + state.put_transaction_context(TransactionContext { + address_bytes: *authority_address.address_bytes(), + transaction_id: TransactionId::new([0; 32]), + position_in_transaction: 0, + }); + + let params = Params { + market_authorities: vec![], // should fail even though authority address is admin + admin: authority_address, + }; + state.put_params(params).unwrap(); + + let action = RemoveMarkets { + markets: vec![], + }; + let res = action.check_and_execute(&mut state).await.unwrap_err(); + assert!(state.get_market_map().await.unwrap().is_none()); + assert!(res.to_string().contains(&format!( + "address {authority_address} is not a market authority" + ))); + } + + #[tokio::test] + async fn remove_markets_fails_if_params_not_found() { + let storage = cnidarium::TempStorage::new().await.unwrap(); + let snapshot = storage.latest_snapshot(); + let mut state = cnidarium::StateDelta::new(snapshot); + + state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); + state.put_transaction_context(TransactionContext { + address_bytes: [0; 20], + transaction_id: TransactionId::new([0; 32]), + position_in_transaction: 0, + }); + + let action = RemoveMarkets { + markets: vec![], + }; + let res = action.check_and_execute(&mut state).await.unwrap_err(); + assert!(state.get_market_map().await.unwrap().is_none()); + assert!( + res.to_string() + .contains("market map params not found in state") + ); + } +} diff --git a/crates/astria-sequencer/src/action_handler/impls/transaction.rs b/crates/astria-sequencer/src/action_handler/impls/transaction.rs index a5b66bf4fd..c2e595b204 100644 --- a/crates/astria-sequencer/src/action_handler/impls/transaction.rs +++ b/crates/astria-sequencer/src/action_handler/impls/transaction.rs @@ -141,6 +141,30 @@ impl ActionHandler for Transaction { .check_stateless() .await .wrap_err("stateless check failed for BridgeSudoChange action")?, + Action::UpsertMarkets(act) => act + .check_stateless() + .await + .wrap_err("stateless check failed for UpsertMarkets action")?, + Action::CreateMarkets(act) => act + .check_stateless() + .await + .wrap_err("stateless check failed for CreateMarkets action")?, + Action::UpdateMarkets(act) => act + .check_stateless() + .await + .wrap_err("stateless check failed for UpdateMarkets action")?, + Action::UpdateParams(act) => act + .check_stateless() + .await + .wrap_err("stateless check failed for UpdateParams action")?, + Action::RemoveMarketAuthorities(act) => act + .check_stateless() + .await + .wrap_err("stateless check failed for RemoveMarketAuthorities action")?, + Action::RemoveMarkets(act) => act + .check_stateless() + .await + .wrap_err("stateless check failed for RemoveMarkets action")?, } } Ok(()) @@ -267,6 +291,24 @@ impl ActionHandler for Transaction { Action::BridgeSudoChange(act) => check_execute_and_pay_fees(act, &mut state) .await .wrap_err("failed executing bridge sudo change")?, + Action::UpsertMarkets(act) => check_execute_and_pay_fees(act, &mut state) + .await + .wrap_err("failed executing upsert markets")?, + Action::CreateMarkets(act) => check_execute_and_pay_fees(act, &mut state) + .await + .wrap_err("failed executing create markets")?, + Action::UpdateMarkets(act) => check_execute_and_pay_fees(act, &mut state) + .await + .wrap_err("failed executing update markets")?, + Action::UpdateParams(act) => check_execute_and_pay_fees(act, &mut state) + .await + .wrap_err("failed executing update params")?, + Action::RemoveMarketAuthorities(act) => check_execute_and_pay_fees(act, &mut state) + .await + .wrap_err("failed executing remove market authorities")?, + Action::RemoveMarkets(act) => check_execute_and_pay_fees(act, &mut state) + .await + .wrap_err("failed executing remove markets")?, } } diff --git a/crates/astria-sequencer/src/action_handler/impls/update_markets.rs b/crates/astria-sequencer/src/action_handler/impls/update_markets.rs new file mode 100644 index 0000000000..8d7016d0c4 --- /dev/null +++ b/crates/astria-sequencer/src/action_handler/impls/update_markets.rs @@ -0,0 +1,302 @@ +use astria_core::protocol::transaction::v1::action::UpdateMarkets; +use astria_eyre::eyre::{ + self, + bail, + eyre, + Context as _, + OptionExt as _, +}; +use cnidarium::StateWrite; + +use crate::{ + action_handler::ActionHandler, + address::StateReadExt as _, + app::StateReadExt as _, + connect::market_map::state_ext::{ + StateReadExt as _, + StateWriteExt as _, + }, + transaction::StateReadExt as _, +}; + +#[async_trait::async_trait] +impl ActionHandler for UpdateMarkets { + async fn check_stateless(&self) -> eyre::Result<()> { + Ok(()) + } + + async fn check_and_execute(&self, mut state: S) -> eyre::Result<()> { + // check that the signer of the transaction is a market authority + let from = state + .try_base_prefixed( + &state + .get_transaction_context() + .expect("transaction source must be present in state when executing an action") + .address_bytes(), + ) + .await + .wrap_err("failed to convert signer address to base prefixed address")?; + let market_authorities = state + .get_params() + .await? + .ok_or_eyre("market map params not found in state")? + .market_authorities; + if !market_authorities.contains(&from) { + bail!("address {from} is not a market authority"); + } + + // update existing markets, erroring if any do not exist in the current map + let mut market_map = state + .get_market_map() + .await + .wrap_err("failed to get market map")? + .ok_or_eyre("market map not found in state")?; + for market in &self.update_markets { + let ticker_key = market.ticker.currency_pair.to_string(); + *market_map + .markets + .get_mut(&ticker_key) + .ok_or_else(|| eyre!("market for ticker {ticker_key} not found in market map"))? = + market.clone(); + } + state + .put_market_map(market_map) + .wrap_err("failed to put market map into state")?; + + // update the last updated height for the market map + state + .put_market_map_last_updated_height( + state + .get_block_height() + .await + .wrap_err("failed to get block height")?, + ) + .wrap_err("failed to update latest market map height")?; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + + use astria_core::{ + connect::market_map::v2::{ + Market, + MarketMap, + Params, + }, + primitive::v1::TransactionId, + }; + use indexmap::IndexMap; + + use super::*; + use crate::{ + accounts::AddressBytes as _, + address::StateWriteExt as _, + app::StateWriteExt as _, + benchmark_and_test_utils::{ + astria_address, + ASTRIA_PREFIX, + }, + test_utils::example_ticker, + transaction::{ + StateWriteExt as _, + TransactionContext, + }, + }; + + #[tokio::test] + async fn update_markets_executes_as_expected() { + let storage = cnidarium::TempStorage::new().await.unwrap(); + let snapshot = storage.latest_snapshot(); + let mut state = cnidarium::StateDelta::new(snapshot); + + let authority_address = astria_address(&[0; 20]); + + state.put_block_height(1).unwrap(); + state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); + state.put_transaction_context(TransactionContext { + address_bytes: *authority_address.address_bytes(), + transaction_id: TransactionId::new([0; 32]), + position_in_transaction: 0, + }); + + let params = Params { + market_authorities: vec![authority_address], + admin: authority_address, + }; + state.put_params(params).unwrap(); + + let ticker_1 = example_ticker("ticker_1".to_string()); + let market_1 = Market { + ticker: ticker_1.clone(), + provider_configs: vec![], + }; + + let mut markets = IndexMap::new(); + markets.insert(ticker_1.currency_pair.to_string(), market_1.clone()); + let initial_market_map = MarketMap { + markets, + }; + state.put_market_map(initial_market_map).unwrap(); + let market_map = state.get_market_map().await.unwrap().unwrap(); + assert_eq!(market_map.markets.len(), 1); + assert_eq!( + *market_map + .markets + .get(&ticker_1.currency_pair.to_string()) + .unwrap(), + market_1, + ); + + let ticker = example_ticker("ticker".to_string()); + let market = Market { + ticker: ticker.clone(), + provider_configs: vec![], + }; + + let action = UpdateMarkets { + update_markets: vec![market.clone()], + }; + + action.check_and_execute(&mut state).await.unwrap(); + let market_map = state.get_market_map().await.unwrap().unwrap(); + assert_eq!(market_map.markets.len(), 1); + assert_eq!( + *market_map + .markets + .get(&ticker.currency_pair.to_string()) + .unwrap(), + market, + ); + assert_eq!(state.get_market_map_last_updated_height().await.unwrap(), 1); + } + + #[tokio::test] + async fn update_markets_fails_if_market_is_not_in_market_map() { + let storage = cnidarium::TempStorage::new().await.unwrap(); + let snapshot = storage.latest_snapshot(); + let mut state = cnidarium::StateDelta::new(snapshot); + + let authority_address = astria_address(&[0; 20]); + + state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); + state.put_transaction_context(TransactionContext { + address_bytes: *authority_address.address_bytes(), + transaction_id: TransactionId::new([0; 32]), + position_in_transaction: 0, + }); + + let params = Params { + market_authorities: vec![authority_address], + admin: authority_address, + }; + state.put_params(params).unwrap(); + + state + .put_market_map(MarketMap { + markets: IndexMap::new(), + }) + .unwrap(); + + let ticker = example_ticker("ticker".to_string()); + let market = Market { + ticker: ticker.clone(), + provider_configs: vec![], + }; + + let action = UpdateMarkets { + update_markets: vec![market.clone()], + }; + + let res = action.check_and_execute(&mut state).await.unwrap_err(); + assert!(res.to_string().contains(&format!( + "market for ticker {} not found in market map", + ticker.currency_pair + ))); + } + + #[tokio::test] + async fn update_markets_fails_if_market_map_is_not_in_state() { + let storage = cnidarium::TempStorage::new().await.unwrap(); + let snapshot = storage.latest_snapshot(); + let mut state = cnidarium::StateDelta::new(snapshot); + + let authority_address = astria_address(&[0; 20]); + + state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); + state.put_transaction_context(TransactionContext { + address_bytes: *authority_address.address_bytes(), + transaction_id: TransactionId::new([0; 32]), + position_in_transaction: 0, + }); + + let params = Params { + market_authorities: vec![authority_address], + admin: authority_address, + }; + state.put_params(params).unwrap(); + + let action = UpdateMarkets { + update_markets: vec![], + }; + + let res = action.check_and_execute(&mut state).await.unwrap_err(); + assert!(res.to_string().contains("market map not found in state")); + } + + #[tokio::test] + async fn update_markets_fails_if_authority_is_invalid() { + let storage = cnidarium::TempStorage::new().await.unwrap(); + let snapshot = storage.latest_snapshot(); + let mut state = cnidarium::StateDelta::new(snapshot); + + let authority_address = astria_address(&[0; 20]); + + state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); + state.put_transaction_context(TransactionContext { + address_bytes: *authority_address.address_bytes(), + transaction_id: TransactionId::new([0; 32]), + position_in_transaction: 0, + }); + + let params = Params { + market_authorities: vec![], // should fail even though the authority address is admin + admin: authority_address, + }; + state.put_params(params).unwrap(); + + let action = UpdateMarkets { + update_markets: vec![], + }; + let res = action.check_and_execute(&mut state).await.unwrap_err(); + assert!(res.to_string().contains(&format!( + "address {authority_address} is not a market authority" + ))); + assert!(state.get_market_map().await.unwrap().is_none()); + } + + #[tokio::test] + async fn update_markets_fails_if_params_not_found() { + let storage = cnidarium::TempStorage::new().await.unwrap(); + let snapshot = storage.latest_snapshot(); + let mut state = cnidarium::StateDelta::new(snapshot); + + state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); + state.put_transaction_context(TransactionContext { + address_bytes: [0; 20], + transaction_id: TransactionId::new([0; 32]), + position_in_transaction: 0, + }); + + let action = UpdateMarkets { + update_markets: vec![], + }; + let res = action.check_and_execute(&mut state).await.unwrap_err(); + assert!( + res.to_string() + .contains("market map params not found in state") + ); + assert!(state.get_market_map().await.unwrap().is_none()); + } +} diff --git a/crates/astria-sequencer/src/action_handler/impls/update_params.rs b/crates/astria-sequencer/src/action_handler/impls/update_params.rs new file mode 100644 index 0000000000..629cc9f045 --- /dev/null +++ b/crates/astria-sequencer/src/action_handler/impls/update_params.rs @@ -0,0 +1,117 @@ +use astria_core::protocol::transaction::v1::action::UpdateParams; +use astria_eyre::eyre::{ + self, + ensure, + Context, +}; + +use crate::{ + action_handler::ActionHandler, + authority::StateReadExt as _, + connect::market_map::state_ext::StateWriteExt as _, + transaction::StateReadExt as _, +}; + +#[async_trait::async_trait] +impl ActionHandler for UpdateParams { + async fn check_stateless(&self) -> eyre::Result<()> { + Ok(()) + } + + async fn check_and_execute(&self, mut state: S) -> eyre::Result<()> { + let from = &state + .get_transaction_context() + .expect("transaction source must be present in state when executing an action") + .address_bytes(); + let sudo_address = state + .get_sudo_address() + .await + .wrap_err("failed to get sudo address from state")?; + ensure!(sudo_address == *from, "signer is not the sudo key"); + state + .put_params(self.params.clone()) + .wrap_err("failed to put params into state")?; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + + use astria_core::{ + connect::market_map::v2::Params, + primitive::v1::TransactionId, + }; + + use super::*; + use crate::{ + accounts::AddressBytes, + authority::StateWriteExt as _, + benchmark_and_test_utils::astria_address, + connect::market_map::state_ext::StateReadExt as _, + transaction::{ + StateWriteExt as _, + TransactionContext, + }, + }; + + #[tokio::test] + async fn update_params_executes_as_expected() { + let storage = cnidarium::TempStorage::new().await.unwrap(); + let snapshot = storage.latest_snapshot(); + let mut state = cnidarium::StateDelta::new(snapshot); + + let authority_address = astria_address(&[0; 20]); + + state.put_sudo_address(authority_address).unwrap(); + + state.put_transaction_context(TransactionContext { + address_bytes: *authority_address.address_bytes(), + transaction_id: TransactionId::new([0; 32]), + position_in_transaction: 0, + }); + + assert!(state.get_params().await.unwrap().is_none()); + + let action = UpdateParams { + params: Params { + market_authorities: vec![authority_address], + admin: authority_address, + }, + }; + action.check_and_execute(&mut state).await.unwrap(); + let params = state + .get_params() + .await + .unwrap() + .expect("params should be present"); + assert_eq!(params, action.params); + } + + #[tokio::test] + async fn update_params_fails_if_signer_is_invalid() { + let storage = cnidarium::TempStorage::new().await.unwrap(); + let snapshot = storage.latest_snapshot(); + let mut state = cnidarium::StateDelta::new(snapshot); + + let authority_address = astria_address(&[0; 20]); + let invalid_address = astria_address(&[1; 20]); + + state.put_sudo_address(authority_address).unwrap(); + + state.put_transaction_context(TransactionContext { + address_bytes: *invalid_address.address_bytes(), + transaction_id: TransactionId::new([0; 32]), + position_in_transaction: 0, + }); + + let action = UpdateParams { + params: Params { + market_authorities: vec![invalid_address], + admin: invalid_address, + }, + }; + let res = action.check_and_execute(&mut state).await.unwrap_err(); + assert!(res.to_string().contains("signer is not the sudo key")); + } +} diff --git a/crates/astria-sequencer/src/action_handler/impls/upsert_markets.rs b/crates/astria-sequencer/src/action_handler/impls/upsert_markets.rs new file mode 100644 index 0000000000..b2e157b09f --- /dev/null +++ b/crates/astria-sequencer/src/action_handler/impls/upsert_markets.rs @@ -0,0 +1,278 @@ +use astria_core::{ + connect::market_map::v2::MarketMap, + protocol::transaction::v1::action::UpsertMarkets, +}; +use astria_eyre::eyre::{ + self, + bail, + Context as _, + OptionExt as _, +}; +use cnidarium::StateWrite; +use indexmap::IndexMap; + +use crate::{ + action_handler::ActionHandler, + address::StateReadExt as _, + app::StateReadExt as _, + connect::market_map::state_ext::{ + StateReadExt as _, + StateWriteExt as _, + }, + transaction::StateReadExt as _, +}; + +#[async_trait::async_trait] +impl ActionHandler for UpsertMarkets { + async fn check_stateless(&self) -> eyre::Result<()> { + Ok(()) + } + + async fn check_and_execute(&self, mut state: S) -> eyre::Result<()> { + // check that the signer of the transaction is a market authority + let from = state + .try_base_prefixed( + &state + .get_transaction_context() + .expect("transaction source must be present in state when executing an action") + .address_bytes(), + ) + .await + .wrap_err("failed to convert signer address to base prefixed address")?; + let market_authorities = state + .get_params() + .await? + .ok_or_eyre("market map params not found in state")? + .market_authorities; + if !market_authorities.contains(&from) { + bail!("address {from} is not a market authority"); + } + + // upsert markets, updating any that already exist and creating any that do not + let mut market_map = state + .get_market_map() + .await + .wrap_err("failed to get market map")? + .unwrap_or(MarketMap { + markets: IndexMap::new(), + }); + for market in &self.markets { + let ticker_key = market.ticker.currency_pair.to_string(); + market_map + .markets + .entry(ticker_key) + .and_modify(|existing_market| { + *existing_market = market.clone(); + }) + .or_insert(market.clone()); + } + state + .put_market_map(market_map) + .wrap_err("failed to put market map into state")?; + + // update the last updated height of the market map + state + .put_market_map_last_updated_height( + state + .get_block_height() + .await + .wrap_err("failed to get block height")?, + ) + .wrap_err("failed to update latest market map height")?; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + + use astria_core::{ + connect::market_map::v2::{ + Market, + Params, + }, + primitive::v1::TransactionId, + }; + + use super::*; + use crate::{ + accounts::AddressBytes as _, + address::StateWriteExt as _, + app::StateWriteExt as _, + benchmark_and_test_utils::{ + astria_address, + ASTRIA_PREFIX, + }, + test_utils::example_ticker, + transaction::{ + StateWriteExt as _, + TransactionContext, + }, + }; + + #[tokio::test] + async fn upsert_markets_creates_market_as_expected() { + let storage = cnidarium::TempStorage::new().await.unwrap(); + let snapshot = storage.latest_snapshot(); + let mut state = cnidarium::StateDelta::new(snapshot); + + let authority_address = astria_address(&[0; 20]); + + state.put_block_height(1).unwrap(); + state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); + state.put_transaction_context(TransactionContext { + address_bytes: *authority_address.address_bytes(), + transaction_id: TransactionId::new([0; 32]), + position_in_transaction: 0, + }); + + let params = Params { + market_authorities: vec![authority_address], + admin: authority_address, + }; + state.put_params(params).unwrap(); + + let ticker = example_ticker(String::new()); + let market = Market { + ticker: ticker.clone(), + provider_configs: vec![], + }; + + let action = UpsertMarkets { + markets: vec![market.clone()], + }; + action.check_and_execute(&mut state).await.unwrap(); + let market_map = state.get_market_map().await.unwrap().unwrap(); + assert_eq!(market_map.markets.len(), 1); + assert_eq!( + *market_map + .markets + .get(&ticker.currency_pair.to_string()) + .unwrap(), + market, + ); + assert_eq!(state.get_market_map_last_updated_height().await.unwrap(), 1); + } + + #[tokio::test] + async fn upsert_markets_updates_market_if_it_already_exists() { + let storage = cnidarium::TempStorage::new().await.unwrap(); + let snapshot = storage.latest_snapshot(); + let mut state = cnidarium::StateDelta::new(snapshot); + + let authority_address = astria_address(&[0; 20]); + + let params = Params { + market_authorities: vec![authority_address], + admin: authority_address, + }; + state.put_params(params).unwrap(); + + state.put_block_height(1).unwrap(); + state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); + state.put_transaction_context(TransactionContext { + address_bytes: *authority_address.address_bytes(), + transaction_id: TransactionId::new([0; 32]), + position_in_transaction: 0, + }); + + let ticker_1 = example_ticker("ticker_1".to_string()); + let market_1 = Market { + ticker: ticker_1.clone(), + provider_configs: vec![], + }; + + let mut markets = IndexMap::new(); + markets.insert(ticker_1.currency_pair.to_string(), market_1.clone()); + let initial_market_map = MarketMap { + markets, + }; + state.put_market_map(initial_market_map).unwrap(); + let market_map = state.get_market_map().await.unwrap().unwrap(); + assert_eq!(market_map.markets.len(), 1); + assert_eq!( + *market_map + .markets + .get(&ticker_1.currency_pair.to_string()) + .unwrap(), + market_1, + ); + + let ticker_2 = example_ticker("ticker_2".to_string()); + let market_2 = Market { + ticker: ticker_2.clone(), + provider_configs: vec![], + }; + + let action = UpsertMarkets { + markets: vec![market_2.clone()], + }; + + action.check_and_execute(&mut state).await.unwrap(); + let market_map = state.get_market_map().await.unwrap().unwrap(); + assert_eq!(market_map.markets.len(), 1); + assert_eq!( + *market_map + .markets + .get(&ticker_2.currency_pair.to_string()) + .unwrap(), + market_2, + ); + assert_eq!(state.get_market_map_last_updated_height().await.unwrap(), 1); + } + + #[tokio::test] + async fn upsert_markets_fails_if_authority_is_invalid() { + let storage = cnidarium::TempStorage::new().await.unwrap(); + let snapshot = storage.latest_snapshot(); + let mut state = cnidarium::StateDelta::new(snapshot); + + let authority_address = astria_address(&[0; 20]); + + state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); + state.put_transaction_context(TransactionContext { + address_bytes: *authority_address.address_bytes(), + transaction_id: TransactionId::new([0; 32]), + position_in_transaction: 0, + }); + + let params = Params { + market_authorities: vec![], // should fail even though the authority address is admin + admin: authority_address, + }; + state.put_params(params).unwrap(); + + let action = UpsertMarkets { + markets: vec![], + }; + let res = action.check_and_execute(&mut state).await.unwrap_err(); + assert!(res.to_string().contains(&format!( + "address {authority_address} is not a market authority" + ))); + assert!(state.get_market_map().await.unwrap().is_none()); + } + + #[tokio::test] + async fn upsert_markets_fails_if_params_not_found() { + let storage = cnidarium::TempStorage::new().await.unwrap(); + let snapshot = storage.latest_snapshot(); + let mut state = cnidarium::StateDelta::new(snapshot); + + state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); + state.put_transaction_context(TransactionContext { + address_bytes: [0; 20], + transaction_id: TransactionId::new([0; 32]), + position_in_transaction: 0, + }); + + let action = UpsertMarkets { + markets: vec![], + }; + let res = action.check_and_execute(&mut state).await.unwrap_err(); + assert!( + res.to_string() + .contains("market map params not found in state") + ); + assert!(state.get_market_map().await.unwrap().is_none()); + } +} diff --git a/crates/astria-sequencer/src/app/benchmark_and_test_utils.rs b/crates/astria-sequencer/src/app/benchmark_and_test_utils.rs index 7ec8062d45..519c04027c 100644 --- a/crates/astria-sequencer/src/app/benchmark_and_test_utils.rs +++ b/crates/astria-sequencer/src/app/benchmark_and_test_utils.rs @@ -21,15 +21,21 @@ use astria_core::{ BridgeLock, BridgeSudoChange, BridgeUnlock, + CreateMarkets, FeeAssetChange, FeeChange, IbcRelayerChange, IbcSudoChange, Ics20Withdrawal, InitBridgeAccount, + RemoveMarketAuthorities, + RemoveMarkets, RollupDataSubmission, SudoAddressChange, Transfer, + UpdateMarkets, + UpdateParams, + UpsertMarkets, ValidatorUpdate, }, }, @@ -91,6 +97,12 @@ pub(crate) fn default_fees() -> astria_core::protocol::genesis::v1::GenesisFees ibc_relayer_change: Some(FeeComponents::::new(0, 0)), sudo_address_change: Some(FeeComponents::::new(0, 0)), ibc_sudo_change: Some(FeeComponents::::new(0, 0)), + upsert_markets: Some(FeeComponents::::new(0, 0)), + create_markets: Some(FeeComponents::::new(0, 0)), + update_markets: Some(FeeComponents::::new(0, 0)), + update_params: Some(FeeComponents::::new(0, 0)), + remove_market_authorities: Some(FeeComponents::::new(0, 0)), + remove_markets: Some(FeeComponents::::new(0, 0)), } } @@ -126,7 +138,7 @@ pub(crate) fn proto_genesis_state() }, last_updated: 0, params: Params { - market_authorities: vec![], + market_authorities: vec![astria_address_from_hex_string(ALICE_ADDRESS)], admin: astria_address_from_hex_string(ALICE_ADDRESS), }, } diff --git a/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_at_genesis.snap b/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_at_genesis.snap index f6c9833e83..6b2fa5a633 100644 --- a/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_at_genesis.snap +++ b/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_at_genesis.snap @@ -1,39 +1,38 @@ --- source: crates/astria-sequencer/src/app/tests_breaking_changes.rs -assertion_line: 78 expression: app.app_hash.as_bytes() --- [ - 53, - 138, + 74, + 173, + 202, + 26, + 80, + 172, + 76, + 78, + 72, 44, - 156, - 111, 243, - 242, - 225, - 251, - 114, - 33, - 182, - 11, - 173, - 107, - 58, - 204, - 168, - 230, - 127, - 25, - 143, - 211, - 168, - 91, - 18, - 167, - 229, - 221, - 230, - 107, - 85 + 51, + 32, + 207, + 88, + 78, + 145, + 19, + 219, + 238, + 222, + 150, + 170, + 61, + 187, + 166, + 240, + 247, + 123, + 74, + 48, + 2 ] diff --git a/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_execute_every_action.snap b/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_execute_every_action.snap index b8bbde8d49..dbb73b9059 100644 --- a/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_execute_every_action.snap +++ b/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_execute_every_action.snap @@ -1,39 +1,38 @@ --- source: crates/astria-sequencer/src/app/tests_breaking_changes.rs -assertion_line: 353 expression: app.app_hash.as_bytes() --- [ - 36, - 17, + 24, 125, - 110, - 25, - 11, - 235, - 211, - 94, - 235, - 13, - 113, - 63, - 150, - 42, - 51, - 123, - 133, - 22, - 198, - 180, - 136, - 152, - 182, - 124, - 193, - 188, - 48, - 9, - 215, + 203, + 19, + 36, + 212, + 106, + 216, + 119, + 208, + 90, + 228, + 196, + 72, + 241, + 146, + 86, + 142, + 214, 118, - 202 + 247, + 96, + 199, + 206, + 14, + 68, + 224, + 130, + 130, + 73, + 237, + 42 ] diff --git a/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_finalize_block.snap b/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_finalize_block.snap index 051cc94ebd..aa4cd999e3 100644 --- a/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_finalize_block.snap +++ b/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_finalize_block.snap @@ -1,39 +1,38 @@ --- source: crates/astria-sequencer/src/app/tests_breaking_changes.rs -assertion_line: 160 expression: app.app_hash.as_bytes() --- [ - 16, - 234, - 26, - 31, - 30, - 140, - 161, - 180, - 247, - 182, - 185, - 153, - 253, - 236, - 69, - 32, - 60, - 164, - 33, - 20, - 135, + 218, 188, - 98, - 107, - 198, - 164, + 129, + 21, + 106, + 40, + 73, + 115, + 162, + 158, + 86, + 10, + 128, + 231, + 163, + 214, + 201, + 68, + 162, + 136, + 154, + 216, + 227, + 220, + 176, + 24, + 100, + 206, + 14, + 2, 95, - 223, - 50, - 124, - 146, - 122 + 223 ] diff --git a/crates/astria-sequencer/src/app/test_utils.rs b/crates/astria-sequencer/src/app/test_utils.rs index 70ff395c7c..b3f1c7ad7c 100644 --- a/crates/astria-sequencer/src/app/test_utils.rs +++ b/crates/astria-sequencer/src/app/test_utils.rs @@ -1,9 +1,18 @@ use std::{ collections::HashMap, + str::FromStr as _, sync::Arc, }; use astria_core::{ + connect::{ + market_map::v2::Ticker, + types::v2::{ + Base, + CurrencyPair, + Quote, + }, + }, crypto::SigningKey, primitive::v1::RollupId, protocol::{ @@ -201,3 +210,20 @@ pub(crate) fn transactions_with_extended_commit_info_and_commitments( .collect(); txs_with_commit_info } + +pub(crate) fn example_ticker_from_currency_pair( + base: &str, + quote: &str, + metadata: String, +) -> Ticker { + Ticker { + currency_pair: CurrencyPair::from_parts( + Base::from_str(base).unwrap(), + Quote::from_str(quote).unwrap(), + ), + decimals: 2, + min_provider_count: 2, + enabled: true, + metadata_json: metadata, + } +} diff --git a/crates/astria-sequencer/src/app/tests_breaking_changes.rs b/crates/astria-sequencer/src/app/tests_breaking_changes.rs index 1e2b186712..11ec9c7dac 100644 --- a/crates/astria-sequencer/src/app/tests_breaking_changes.rs +++ b/crates/astria-sequencer/src/app/tests_breaking_changes.rs @@ -15,6 +15,10 @@ use std::{ }; use astria_core::{ + connect::market_map::v2::{ + Market, + Params, + }, primitive::v1::{ Address, RollupId, @@ -26,10 +30,16 @@ use astria_core::{ BridgeLock, BridgeSudoChange, BridgeUnlock, + CreateMarkets, IbcRelayerChange, IbcSudoChange, + RemoveMarketAuthorities, + RemoveMarkets, RollupDataSubmission, Transfer, + UpdateMarkets, + UpdateParams, + UpsertMarkets, ValidatorUpdate, }, Action, @@ -55,10 +65,12 @@ use crate::{ default_genesis_accounts, initialize_app_with_storage, proto_genesis_state, + ALICE_ADDRESS, BOB_ADDRESS, CAROL_ADDRESS, }, test_utils::{ + example_ticker_from_currency_pair, get_alice_signing_key, get_bridge_signing_key, initialize_app, @@ -238,6 +250,55 @@ async fn app_execute_transaction_with_every_action_snapshot() { } .into(), Action::ValidatorUpdate(update.clone()), + CreateMarkets { + create_markets: vec![Market { + ticker: example_ticker_from_currency_pair( + "testAssetOne", + "testAssetTwo", + String::new(), + ), + provider_configs: vec![], + }], + } + .into(), + UpsertMarkets { + markets: vec![Market { + ticker: example_ticker_from_currency_pair( + "testAssetThree", + "testAssetFour", + "upsert market".to_string(), + ), + provider_configs: vec![], + }], + } + .into(), + UpdateMarkets { + update_markets: vec![Market { + ticker: example_ticker_from_currency_pair( + "testAssetOne", + "testAssetTwo", + "updated market".to_string(), + ), + provider_configs: vec![], + }], + } + .into(), + RemoveMarkets { + markets: vec![ + example_ticker_from_currency_pair( + "testAssetOne", + "testAssetTwo", + "remove market".to_string(), + ) + .currency_pair + .to_string(), + ], + } + .into(), + RemoveMarketAuthorities { + remove_addresses: vec![astria_address_from_hex_string(ALICE_ADDRESS)], + } + .into(), ]) .chain_id("test") .try_build() @@ -251,6 +312,13 @@ async fn app_execute_transaction_with_every_action_snapshot() { FeeAssetChange::Addition("test-0".parse().unwrap()).into(), FeeAssetChange::Addition("test-1".parse().unwrap()).into(), FeeAssetChange::Removal("test-0".parse().unwrap()).into(), + UpdateParams { + params: Params { + market_authorities: vec![bob_address, carol_address], + admin: bob_address, + }, + } + .into(), ]) .nonce(1) .chain_id("test") diff --git a/crates/astria-sequencer/src/app/tests_execute_transaction.rs b/crates/astria-sequencer/src/app/tests_execute_transaction.rs index 7f5d778e36..2cf8e58532 100644 --- a/crates/astria-sequencer/src/app/tests_execute_transaction.rs +++ b/crates/astria-sequencer/src/app/tests_execute_transaction.rs @@ -1,6 +1,11 @@ use std::sync::Arc; use astria_core::{ + connect::market_map::v2::{ + Market, + MarketMap, + Params, + }, crypto::SigningKey, primitive::v1::{ asset, @@ -14,11 +19,17 @@ use astria_core::{ action::{ BridgeLock, BridgeUnlock, + CreateMarkets, IbcRelayerChange, IbcSudoChange, + RemoveMarketAuthorities, + RemoveMarkets, RollupDataSubmission, SudoAddressChange, Transfer, + UpdateMarkets, + UpdateParams, + UpsertMarkets, ValidatorUpdate, }, Action, @@ -33,6 +44,7 @@ use cnidarium::{ ArcStateDeltaExt as _, StateDelta, }; +use indexmap::IndexMap; use super::test_utils::get_alice_signing_key; use crate::{ @@ -43,16 +55,21 @@ use crate::{ }, app::{ benchmark_and_test_utils::{ + ALICE_ADDRESS, BOB_ADDRESS, CAROL_ADDRESS, }, test_utils::{ + example_ticker_from_currency_pair, get_bridge_signing_key, initialize_app, }, InvalidNonce, }, - authority::StateReadExt as _, + authority::{ + StateReadExt as _, + StateWriteExt, + }, benchmark_and_test_utils::{ astria_address, astria_address_from_hex_string, @@ -64,12 +81,19 @@ use crate::{ StateReadExt as _, StateWriteExt as _, }, + connect::market_map::state_ext::{ + StateReadExt as _, + StateWriteExt as _, + }, fees::{ StateReadExt as _, StateWriteExt as _, }, ibc::StateReadExt as _, - test_utils::calculate_rollup_data_submission_fee_from_state, + test_utils::{ + calculate_rollup_data_submission_fee_from_state, + example_ticker, + }, utils::create_deposit_event, }; @@ -1325,3 +1349,313 @@ async fn ensure_all_event_attributes_are_indexed() { ); }); } + +#[tokio::test] +async fn upsert_markets_executes_as_expected() { + let mut app = initialize_app(None, vec![]).await; + let mut state_tx = StateDelta::new(app.state.clone()); + + let alice_signing_key = get_alice_signing_key(); + + let ticker_1 = example_ticker("create_market_1".to_string()); + let market_1 = Market { + ticker: ticker_1.clone(), + provider_configs: vec![], + }; + let mut market_map = MarketMap { + markets: IndexMap::new(), + }; + market_map + .markets + .insert(ticker_1.currency_pair.to_string(), market_1); + state_tx.put_market_map(market_map).unwrap(); + + app.apply(state_tx); + + // market_2 should replace market_1, since they share the same currency pair + let ticker_2 = example_ticker("update market 1 to market 2".to_string()); + let market_2 = Market { + ticker: ticker_2.clone(), + provider_configs: vec![], + }; + + // market_3 should be added to the market map + let ticker_3 = example_ticker_from_currency_pair("USDC", "TIA", "create market 3".to_string()); + let market_3 = Market { + ticker: ticker_3.clone(), + provider_configs: vec![], + }; + + let upsert_markets_action = UpsertMarkets { + markets: vec![market_2.clone(), market_3.clone()], + }; + + let tx = TransactionBody::builder() + .actions(vec![upsert_markets_action.into()]) + .chain_id("test") + .try_build() + .unwrap(); + + let signed_tx = Arc::new(tx.sign(&alice_signing_key)); + app.execute_transaction(signed_tx).await.unwrap(); + + let market_map = app.state.get_market_map().await.unwrap().unwrap(); + assert_eq!(market_map.markets.len(), 2); + assert_eq!( + market_map.markets.get(&ticker_1.currency_pair.to_string()), + Some(&market_2) + ); + assert_eq!( + market_map.markets.get(&ticker_2.currency_pair.to_string()), + Some(&market_2) + ); + assert_eq!( + market_map.markets.get(&ticker_3.currency_pair.to_string()), + Some(&market_3) + ); +} + +#[tokio::test] +async fn create_markets_executes_as_expected() { + let mut app = initialize_app(None, vec![]).await; + + let alice_signing_key = get_alice_signing_key(); + + let ticker_1 = example_ticker("create market 1".to_string()); + let market_1 = Market { + ticker: ticker_1.clone(), + provider_configs: vec![], + }; + + let ticker_2 = example_ticker_from_currency_pair("USDC", "TIA", "create market 2".to_string()); + let market_2 = Market { + ticker: ticker_2.clone(), + provider_configs: vec![], + }; + + let create_markets_action = CreateMarkets { + create_markets: vec![market_1.clone(), market_2.clone()], + }; + + let tx = TransactionBody::builder() + .actions(vec![create_markets_action.into()]) + .chain_id("test") + .try_build() + .unwrap(); + + let signed_tx = Arc::new(tx.sign(&alice_signing_key)); + app.execute_transaction(signed_tx).await.unwrap(); + + let market_map = app.state.get_market_map().await.unwrap().unwrap(); + assert_eq!(market_map.markets.len(), 2); + assert_eq!( + market_map.markets.get(&ticker_1.currency_pair.to_string()), + Some(&market_1) + ); + assert_eq!( + market_map.markets.get(&ticker_2.currency_pair.to_string()), + Some(&market_2) + ); +} + +#[tokio::test] +async fn update_markets_executes_as_expected() { + let mut app = initialize_app(None, vec![]).await; + let mut state_tx = StateDelta::new(app.state.clone()); + + let alice_signing_key = get_alice_signing_key(); + + let ticker_1 = example_ticker("create market 1".to_string()); + let market_1 = Market { + ticker: ticker_1.clone(), + provider_configs: vec![], + }; + let ticker_2 = example_ticker_from_currency_pair("USDC", "TIA", "create market 2".to_string()); + let market_2 = Market { + ticker: ticker_2.clone(), + provider_configs: vec![], + }; + + let mut market_map = MarketMap { + markets: IndexMap::new(), + }; + + market_map + .markets + .insert(ticker_1.currency_pair.to_string(), market_1); + market_map + .markets + .insert(ticker_2.currency_pair.to_string(), market_2.clone()); + + state_tx.put_market_map(market_map).unwrap(); + app.apply(state_tx); + + // market_3 should replace market_1, since they share the same currency pair + let ticker_3 = example_ticker("update market 1 to market 2".to_string()); + let market_3 = Market { + ticker: ticker_3.clone(), + provider_configs: vec![], + }; + + let update_markets_action = UpdateMarkets { + update_markets: vec![market_3.clone()], + }; + + let tx = TransactionBody::builder() + .actions(vec![update_markets_action.into()]) + .chain_id("test") + .try_build() + .unwrap(); + + let signed_tx = Arc::new(tx.sign(&alice_signing_key)); + app.execute_transaction(signed_tx).await.unwrap(); + + let market_map = app.state.get_market_map().await.unwrap().unwrap(); + assert_eq!(market_map.markets.len(), 2); + assert_eq!( + market_map.markets.get(&ticker_1.currency_pair.to_string()), + Some(&market_3) + ); + assert_eq!( + market_map.markets.get(&ticker_2.currency_pair.to_string()), + Some(&market_2) + ); + assert_eq!( + market_map.markets.get(&ticker_3.currency_pair.to_string()), + Some(&market_3) + ); +} + +#[tokio::test] +async fn remove_markets_executes_as_expected() { + let mut app = initialize_app(None, vec![]).await; + let mut state_tx = StateDelta::new(app.state.clone()); + + let alice_signing_key = get_alice_signing_key(); + + let ticker_1 = example_ticker("create market 1".to_string()); + let market_1 = Market { + ticker: ticker_1.clone(), + provider_configs: vec![], + }; + let ticker_2 = example_ticker_from_currency_pair("USDC", "TIA", "create market 2".to_string()); + let market_2 = Market { + ticker: ticker_2.clone(), + provider_configs: vec![], + }; + + let mut market_map = MarketMap { + markets: IndexMap::new(), + }; + + market_map + .markets + .insert(ticker_1.currency_pair.to_string(), market_1); + market_map + .markets + .insert(ticker_2.currency_pair.to_string(), market_2.clone()); + + state_tx.put_market_map(market_map).unwrap(); + app.apply(state_tx); + + let remove_markets_action = RemoveMarkets { + markets: vec![ticker_1.currency_pair.to_string()], + }; + + let tx = TransactionBody::builder() + .actions(vec![remove_markets_action.into()]) + .chain_id("test") + .try_build() + .unwrap(); + + let signed_tx = Arc::new(tx.sign(&alice_signing_key)); + app.execute_transaction(signed_tx).await.unwrap(); + + let market_map = app.state.get_market_map().await.unwrap().unwrap(); + assert_eq!(market_map.markets.len(), 1); + assert!( + market_map + .markets + .get(&ticker_1.currency_pair.to_string()) + .is_none() + ); + assert_eq!( + market_map.markets.get(&ticker_2.currency_pair.to_string()), + Some(&market_2) + ); +} + +#[tokio::test] +async fn remove_market_authorities_executes_as_expected() { + let mut app = initialize_app(None, vec![]).await; + let mut state_tx = StateDelta::new(app.state.clone()); + + let alice_signing_key = get_alice_signing_key(); + let alice_address = astria_address_from_hex_string(ALICE_ADDRESS); + let bob_address = astria_address_from_hex_string(BOB_ADDRESS); + let carol_address = astria_address_from_hex_string(CAROL_ADDRESS); + + let params = Params { + market_authorities: vec![alice_address, bob_address], + admin: alice_address, + }; + state_tx.put_params(params).unwrap(); + app.apply(state_tx); + + let remove_market_authorities_action = RemoveMarketAuthorities { + remove_addresses: vec![bob_address, carol_address], + }; + + let tx = TransactionBody::builder() + .actions(vec![remove_market_authorities_action.into()]) + .chain_id("test") + .try_build() + .unwrap(); + + let signed_tx = Arc::new(tx.sign(&alice_signing_key)); + app.execute_transaction(signed_tx).await.unwrap(); + + let params = app.state.get_params().await.unwrap().unwrap(); + assert_eq!(params.market_authorities.len(), 1); + assert_eq!(params.market_authorities[0], alice_address); +} + +#[tokio::test] +async fn update_params_executes_as_expected() { + let mut app = initialize_app(None, vec![]).await; + let mut state_tx = StateDelta::new(app.state.clone()); + + let alice_signing_key = get_alice_signing_key(); + let alice_address = astria_address_from_hex_string(ALICE_ADDRESS); + let bob_address = astria_address_from_hex_string(BOB_ADDRESS); + let carol_address = astria_address_from_hex_string(CAROL_ADDRESS); + + let params_1 = Params { + market_authorities: vec![alice_address, bob_address], + admin: alice_address, + }; + state_tx.put_params(params_1.clone()).unwrap(); + state_tx.put_sudo_address(alice_address).unwrap(); + app.apply(state_tx); + + let params_2 = Params { + market_authorities: vec![bob_address, carol_address], + admin: alice_address, + }; + let update_params_action = UpdateParams { + params: params_2.clone(), + }; + + let tx = TransactionBody::builder() + .actions(vec![update_params_action.into()]) + .chain_id("test") + .try_build() + .unwrap(); + + let signed_tx = Arc::new(tx.sign(&alice_signing_key)); + app.execute_transaction(signed_tx).await.unwrap(); + + let params = app.state.get_params().await.unwrap().unwrap(); + assert_ne!(params, params_1); + assert_eq!(params, params_2); +} diff --git a/crates/astria-sequencer/src/connect/market_map/component.rs b/crates/astria-sequencer/src/connect/market_map/component.rs index 337d53b479..7c7e13a238 100644 --- a/crates/astria-sequencer/src/connect/market_map/component.rs +++ b/crates/astria-sequencer/src/connect/market_map/component.rs @@ -25,9 +25,6 @@ impl Component for MarketMapComponent { #[instrument(name = "MarketMapComponent::init_chain", skip_all, err)] async fn init_chain(mut state: S, app_state: &Self::AppState) -> Result<()> { if let Some(connect) = app_state.connect() { - // TODO: put market map authorities and admin in state; - // only required for related actions however - state .put_market_map(connect.market_map().market_map.clone()) .wrap_err("failed to put market map")?; diff --git a/crates/astria-sequencer/src/fees/component.rs b/crates/astria-sequencer/src/fees/component.rs index e22e4480d7..f77938f08e 100644 --- a/crates/astria-sequencer/src/fees/component.rs +++ b/crates/astria-sequencer/src/fees/component.rs @@ -130,6 +130,48 @@ impl Component for FeesComponent { .wrap_err("failed to store ibc sudo change fee components")?; } + let upsert_markets_fees = app_state.fees().upsert_markets; + if let Some(upsert_markets_fees) = upsert_markets_fees { + state + .put_fees(upsert_markets_fees) + .wrap_err("failed to store upsert markets fee components")?; + } + + let create_markets_fees = app_state.fees().create_markets; + if let Some(create_markets_fees) = create_markets_fees { + state + .put_fees(create_markets_fees) + .wrap_err("failed to store create markets fee components")?; + } + + let update_markets_fees = app_state.fees().update_markets; + if let Some(update_markets_fees) = update_markets_fees { + state + .put_fees(update_markets_fees) + .wrap_err("failed to store update markets fee components")?; + } + + let remove_markets_fees = app_state.fees().remove_markets; + if let Some(remove_markets_fees) = remove_markets_fees { + state + .put_fees(remove_markets_fees) + .wrap_err("failed to store remove markets fee components")?; + } + + let remove_market_authorities_fees = app_state.fees().remove_market_authorities; + if let Some(remove_market_authorities_fees) = remove_market_authorities_fees { + state + .put_fees(remove_market_authorities_fees) + .wrap_err("failed to store remove market authorities fee components")?; + } + + let update_params_fees = app_state.fees().update_params; + if let Some(update_params_fees) = update_params_fees { + state + .put_fees(update_params_fees) + .wrap_err("failed to store update params fee components")?; + } + Ok(()) } diff --git a/crates/astria-sequencer/src/fees/mod.rs b/crates/astria-sequencer/src/fees/mod.rs index ba6557d522..4d6eb7357d 100644 --- a/crates/astria-sequencer/src/fees/mod.rs +++ b/crates/astria-sequencer/src/fees/mod.rs @@ -6,15 +6,21 @@ use astria_core::{ BridgeLock, BridgeSudoChange, BridgeUnlock, + CreateMarkets, FeeAssetChange, FeeChange, IbcRelayerChange, IbcSudoChange, Ics20Withdrawal, InitBridgeAccount, + RemoveMarketAuthorities, + RemoveMarkets, RollupDataSubmission, SudoAddressChange, Transfer, + UpdateMarkets, + UpdateParams, + UpsertMarkets, ValidatorUpdate, }, }, @@ -458,6 +464,138 @@ impl FeeHandler for IbcRelay { } } +impl FeeHandler for UpsertMarkets { + fn name() -> &'static str { + ::Raw::NAME + } + + fn full_name() -> String { + ::full_name() + } + + fn snake_case_name() -> &'static str { + "upsert_markets" + } + + fn variable_component(&self) -> u128 { + 0 + } + + fn fee_asset(&self) -> Option<&asset::Denom> { + None + } +} + +impl FeeHandler for CreateMarkets { + fn name() -> &'static str { + ::Raw::NAME + } + + fn full_name() -> String { + ::full_name() + } + + fn snake_case_name() -> &'static str { + "create_markets" + } + + fn variable_component(&self) -> u128 { + 0 + } + + fn fee_asset(&self) -> Option<&asset::Denom> { + None + } +} + +impl FeeHandler for UpdateMarkets { + fn name() -> &'static str { + ::Raw::NAME + } + + fn full_name() -> String { + ::full_name() + } + + fn snake_case_name() -> &'static str { + "update_markets" + } + + fn variable_component(&self) -> u128 { + 0 + } + + fn fee_asset(&self) -> Option<&asset::Denom> { + None + } +} + +impl FeeHandler for UpdateParams { + fn name() -> &'static str { + ::Raw::NAME + } + + fn full_name() -> String { + ::full_name() + } + + fn snake_case_name() -> &'static str { + "update_params" + } + + fn variable_component(&self) -> u128 { + 0 + } + + fn fee_asset(&self) -> Option<&asset::Denom> { + None + } +} + +impl FeeHandler for RemoveMarketAuthorities { + fn name() -> &'static str { + ::Raw::NAME + } + + fn full_name() -> String { + ::full_name() + } + + fn snake_case_name() -> &'static str { + "remove_market_authorities" + } + + fn variable_component(&self) -> u128 { + 0 + } + + fn fee_asset(&self) -> Option<&asset::Denom> { + None + } +} + +impl FeeHandler for RemoveMarkets { + fn name() -> &'static str { + ::Raw::NAME + } + + fn full_name() -> String { + ::full_name() + } + + fn snake_case_name() -> &'static str { + "remove_markets" + } + + fn variable_component(&self) -> u128 { + 0 + } + + fn fee_asset(&self) -> Option<&asset::Denom> { + None + } +} + /// Returns a modified byte length of the deposit event. Length is calculated with reasonable values /// for all fields except `asset` and `destination_chain_address`, ergo it may not be representative /// of on-wire length. diff --git a/crates/astria-sequencer/src/fees/query.rs b/crates/astria-sequencer/src/fees/query.rs index d4b28dc768..8ab08d74ff 100644 --- a/crates/astria-sequencer/src/fees/query.rs +++ b/crates/astria-sequencer/src/fees/query.rs @@ -18,15 +18,21 @@ use astria_core::{ BridgeLock, BridgeSudoChange, BridgeUnlock, + CreateMarkets, FeeAssetChange, FeeChange, IbcRelayerChange, IbcSudoChange, Ics20Withdrawal, InitBridgeAccount, + RemoveMarketAuthorities, + RemoveMarkets, RollupDataSubmission, SudoAddressChange, Transfer, + UpdateMarkets, + UpdateParams, + UpsertMarkets, ValidatorUpdate, }, Action, @@ -299,6 +305,13 @@ pub(crate) async fn get_fees_for_transaction( OnceCell::new(); let fee_asset_change_fees: OnceCell>> = OnceCell::new(); let fee_change_fees: OnceCell>> = OnceCell::new(); + let upsert_markets_fees: OnceCell>> = OnceCell::new(); + let create_markets_fees: OnceCell>> = OnceCell::new(); + let update_markets_fees: OnceCell>> = OnceCell::new(); + let update_params_fees: OnceCell>> = OnceCell::new(); + let remove_market_authorities_fees: OnceCell>> = + OnceCell::new(); + let remove_markets_fees: OnceCell>> = OnceCell::new(); let mut fees_by_asset = HashMap::new(); for action in tx.actions() { @@ -359,6 +372,30 @@ pub(crate) async fn get_fees_for_transaction( let fees = get_or_init_fees(state, &fee_change_fees).await?; calculate_and_add_fees(act, &mut fees_by_asset, fees); } + Action::UpsertMarkets(act) => { + let fees = get_or_init_fees(state, &upsert_markets_fees).await?; + calculate_and_add_fees(act, &mut fees_by_asset, fees); + } + Action::CreateMarkets(act) => { + let fees = get_or_init_fees(state, &create_markets_fees).await?; + calculate_and_add_fees(act, &mut fees_by_asset, fees); + } + Action::UpdateMarkets(act) => { + let fees = get_or_init_fees(state, &update_markets_fees).await?; + calculate_and_add_fees(act, &mut fees_by_asset, fees); + } + Action::UpdateParams(act) => { + let fees = get_or_init_fees(state, &update_params_fees).await?; + calculate_and_add_fees(act, &mut fees_by_asset, fees); + } + Action::RemoveMarketAuthorities(act) => { + let fees = get_or_init_fees(state, &remove_market_authorities_fees).await?; + calculate_and_add_fees(act, &mut fees_by_asset, fees); + } + Action::RemoveMarkets(act) => { + let fees = get_or_init_fees(state, &remove_markets_fees).await?; + calculate_and_add_fees(act, &mut fees_by_asset, fees); + } } } Ok(fees_by_asset) diff --git a/crates/astria-sequencer/src/fees/storage/values.rs b/crates/astria-sequencer/src/fees/storage/values.rs index 138b2f8cbd..a844ea5996 100644 --- a/crates/astria-sequencer/src/fees/storage/values.rs +++ b/crates/astria-sequencer/src/fees/storage/values.rs @@ -4,15 +4,21 @@ use astria_core::protocol::{ BridgeLock, BridgeSudoChange, BridgeUnlock, + CreateMarkets, FeeAssetChange, FeeChange, IbcRelayerChange, IbcSudoChange, Ics20Withdrawal, InitBridgeAccount, + RemoveMarketAuthorities, + RemoveMarkets, RollupDataSubmission, SudoAddressChange, Transfer, + UpdateMarkets, + UpdateParams, + UpsertMarkets, ValidatorUpdate, }, }; @@ -46,6 +52,12 @@ enum ValueImpl { IbcRelayerChangeFees(FeeComponents), IbcSudoChangeFees(FeeComponents), SudoAddressChangeFees(FeeComponents), + UpsertMarketsFees(FeeComponents), + CreateMarketsFees(FeeComponents), + UpdateMarketsFees(FeeComponents), + UpdateParamsFees(FeeComponents), + RemoveMarketAuthoritiesFees(FeeComponents), + RemoveMarketsFees(FeeComponents), } macro_rules! impl_from_for_fee_storage { @@ -109,4 +121,10 @@ impl_from_for_fee_storage!( DomainFeeComponents => IbcRelayerChangeFees, DomainFeeComponents => IbcSudoChangeFees, DomainFeeComponents => SudoAddressChangeFees, + DomainFeeComponents => UpsertMarketsFees, + DomainFeeComponents => CreateMarketsFees, + DomainFeeComponents => UpdateMarketsFees, + DomainFeeComponents => UpdateParamsFees, + DomainFeeComponents => RemoveMarketAuthoritiesFees, + DomainFeeComponents => RemoveMarketsFees, ); diff --git a/crates/astria-sequencer/src/test_utils.rs b/crates/astria-sequencer/src/test_utils.rs index d9d7934239..2a96f4e5b3 100644 --- a/crates/astria-sequencer/src/test_utils.rs +++ b/crates/astria-sequencer/src/test_utils.rs @@ -1,4 +1,14 @@ +use std::str::FromStr as _; + use astria_core::{ + connect::{ + market_map::v2::Ticker, + types::v2::{ + Base, + CurrencyPair, + Quote, + }, + }, primitive::v1::{ Address, Bech32, @@ -47,3 +57,16 @@ pub(crate) async fn calculate_rollup_data_submission_fee_from_state< ) .expect("fee addition should not overflow") } + +pub(crate) fn example_ticker(metadata: String) -> Ticker { + Ticker { + currency_pair: CurrencyPair::from_parts( + Base::from_str("BTC").unwrap(), + Quote::from_str("USD").unwrap(), + ), + decimals: 2, + min_provider_count: 2, + enabled: true, + metadata_json: metadata, + } +} diff --git a/crates/astria-sequencer/src/transaction/checks.rs b/crates/astria-sequencer/src/transaction/checks.rs index bff86e838e..63f87190f9 100644 --- a/crates/astria-sequencer/src/transaction/checks.rs +++ b/crates/astria-sequencer/src/transaction/checks.rs @@ -114,6 +114,12 @@ pub(crate) async fn get_total_transaction_cost( | Action::Ibc(_) | Action::IbcRelayerChange(_) | Action::FeeAssetChange(_) + | Action::UpdateParams(_) + | Action::UpsertMarkets(_) + | Action::CreateMarkets(_) + | Action::UpdateMarkets(_) + | Action::RemoveMarketAuthorities(_) + | Action::RemoveMarkets(_) | Action::FeeChange(_) => { continue; } diff --git a/proto/protocolapis/astria/protocol/fees/v1/types.proto b/proto/protocolapis/astria/protocol/fees/v1/types.proto index 1d3edc2701..7565390106 100644 --- a/proto/protocolapis/astria/protocol/fees/v1/types.proto +++ b/proto/protocolapis/astria/protocol/fees/v1/types.proto @@ -79,6 +79,36 @@ message IbcSudoChangeFeeComponents { astria.primitive.v1.Uint128 multiplier = 2; } +message UpsertMarketsFeeComponents { + astria.primitive.v1.Uint128 base = 1; + astria.primitive.v1.Uint128 multiplier = 2; +} + +message CreateMarketsFeeComponents { + astria.primitive.v1.Uint128 base = 1; + astria.primitive.v1.Uint128 multiplier = 2; +} + +message UpdateMarketsFeeComponents { + astria.primitive.v1.Uint128 base = 1; + astria.primitive.v1.Uint128 multiplier = 2; +} + +message UpdateParamsFeeComponents { + astria.primitive.v1.Uint128 base = 1; + astria.primitive.v1.Uint128 multiplier = 2; +} + +message RemoveMarketAuthoritiesFeeComponents { + astria.primitive.v1.Uint128 base = 1; + astria.primitive.v1.Uint128 multiplier = 2; +} + +message RemoveMarketsFeeComponents { + astria.primitive.v1.Uint128 base = 1; + astria.primitive.v1.Uint128 multiplier = 2; +} + // Response to a transaction fee ABCI query. message TransactionFeeResponse { uint64 height = 2; diff --git a/proto/protocolapis/astria/protocol/genesis/v1/types.proto b/proto/protocolapis/astria/protocol/genesis/v1/types.proto index 2fb05eb0ea..2783611e2b 100644 --- a/proto/protocolapis/astria/protocol/genesis/v1/types.proto +++ b/proto/protocolapis/astria/protocol/genesis/v1/types.proto @@ -59,6 +59,12 @@ message GenesisFees { astria.protocol.fees.v1.SudoAddressChangeFeeComponents sudo_address_change = 12; astria.protocol.fees.v1.TransferFeeComponents transfer = 13; astria.protocol.fees.v1.ValidatorUpdateFeeComponents validator_update = 14; + astria.protocol.fees.v1.UpsertMarketsFeeComponents upsert_markets = 15; + astria.protocol.fees.v1.CreateMarketsFeeComponents create_markets = 16; + astria.protocol.fees.v1.UpdateMarketsFeeComponents update_markets = 17; + astria.protocol.fees.v1.UpdateParamsFeeComponents update_params = 18; + astria.protocol.fees.v1.RemoveMarketAuthoritiesFeeComponents remove_market_authorities = 19; + astria.protocol.fees.v1.RemoveMarketsFeeComponents remove_markets = 20; } message ConnectGenesis { diff --git a/proto/protocolapis/astria/protocol/transaction/v1/action.proto b/proto/protocolapis/astria/protocol/transaction/v1/action.proto index 26cab7579d..8d05d13913 100644 --- a/proto/protocolapis/astria/protocol/transaction/v1/action.proto +++ b/proto/protocolapis/astria/protocol/transaction/v1/action.proto @@ -6,6 +6,8 @@ import "astria/primitive/v1/types.proto"; import "astria/protocol/fees/v1/types.proto"; import "astria_vendored/penumbra/core/component/ibc/v1/ibc.proto"; import "astria_vendored/tendermint/abci/types.proto"; +import "connect/marketmap/v2/market.proto"; +import "connect/marketmap/v2/params.proto"; message Action { oneof value { @@ -30,6 +32,14 @@ message Action { FeeAssetChange fee_asset_change = 53; FeeChange fee_change = 55; IbcSudoChange ibc_sudo_change = 56; + + // MarketMap actions are defined on 71-80 + UpsertMarkets upsert_markets = 71; + CreateMarkets create_markets = 72; + UpdateMarkets update_markets = 73; + UpdateParams update_params = 74; + RemoveMarketAuthorities remove_market_authorities = 75; + RemoveMarkets remove_markets = 76; } } @@ -228,9 +238,51 @@ message FeeChange { astria.protocol.fees.v1.SudoAddressChangeFeeComponents sudo_address_change = 12; astria.protocol.fees.v1.TransferFeeComponents transfer = 13; astria.protocol.fees.v1.ValidatorUpdateFeeComponents validator_update = 14; + astria.protocol.fees.v1.UpsertMarketsFeeComponents upsert_markets = 15; + astria.protocol.fees.v1.CreateMarketsFeeComponents create_markets = 16; + astria.protocol.fees.v1.UpdateMarketsFeeComponents update_markets = 17; + astria.protocol.fees.v1.UpdateParamsFeeComponents update_params = 18; + astria.protocol.fees.v1.RemoveMarketAuthoritiesFeeComponents remove_market_authorities = 19; + astria.protocol.fees.v1.RemoveMarketsFeeComponents remove_markets = 20; } } message IbcSudoChange { astria.primitive.v1.Address new_address = 1; } + +// Updates or creates markets in the market map. If a market does not exist, it will be created. +message UpsertMarkets { + // The list of all markets to be created or updated for the given transaction. + repeated connect.marketmap.v2.Market markets = 2; +} + +// Creates new markets in the market map. +message CreateMarkets { + // The list of all markets to be created. + repeated connect.marketmap.v2.Market create_markets = 2; +} + +// Updates existing markets in the market map. +message UpdateMarkets { + // The list of all markets to be updated. + repeated connect.marketmap.v2.Market update_markets = 2; +} + +// Updates the market map parameters. +message UpdateParams { + // Params defines the new parameters for the x/marketmap module. + connect.marketmap.v2.Params params = 1; +} + +// Removes market map authorities. +message RemoveMarketAuthorities { + // RemoveAddresses is the list of addresses to remove. + repeated string remove_addresses = 1; +} + +// Removes markets from the market map. +message RemoveMarkets { + // Markets is the list of markets to remove. + repeated string markets = 2; +} From 06b20e2d31da875270a87988731e2c8323e711a6 Mon Sep 17 00:00:00 2001 From: ethanoroshiba Date: Wed, 18 Dec 2024 09:17:01 -0600 Subject: [PATCH 2/8] add better comments, new test, fix snapshot --- ...ol__genesis__v1__tests__genesis_state.snap | 24 ++++++++ .../src/protocol/transaction/v1/action/mod.rs | 25 ++++++-- .../action_handler/impls/remove_markets.rs | 59 ++++++++++++++++++- crates/astria-sequencer/src/app/test_utils.rs | 26 -------- .../src/app/tests_breaking_changes.rs | 2 +- .../src/app/tests_execute_transaction.rs | 2 +- crates/astria-sequencer/src/test_utils.rs | 17 ++++++ 7 files changed, 120 insertions(+), 35 deletions(-) diff --git a/crates/astria-core/src/protocol/genesis/snapshots/astria_core__protocol__genesis__v1__tests__genesis_state.snap b/crates/astria-core/src/protocol/genesis/snapshots/astria_core__protocol__genesis__v1__tests__genesis_state.snap index 21acc3a521..679f31d074 100644 --- a/crates/astria-core/src/protocol/genesis/snapshots/astria_core__protocol__genesis__v1__tests__genesis_state.snap +++ b/crates/astria-core/src/protocol/genesis/snapshots/astria_core__protocol__genesis__v1__tests__genesis_state.snap @@ -131,6 +131,30 @@ expression: genesis_state() "validatorUpdate": { "base": {}, "multiplier": {} + }, + "upsertMarkets": { + "base": {}, + "multiplier": {} + }, + "createMarkets": { + "base": {}, + "multiplier": {} + }, + "updateMarkets": { + "base": {}, + "multiplier": {} + }, + "updateParams": { + "base": {}, + "multiplier": {} + }, + "removeMarketAuthorities": { + "base": {}, + "multiplier": {} + }, + "removeMarkets": { + "base": {}, + "multiplier": {} } }, "connect": { diff --git a/crates/astria-core/src/protocol/transaction/v1/action/mod.rs b/crates/astria-core/src/protocol/transaction/v1/action/mod.rs index 50b1603b55..43522edcb8 100644 --- a/crates/astria-core/src/protocol/transaction/v1/action/mod.rs +++ b/crates/astria-core/src/protocol/transaction/v1/action/mod.rs @@ -2315,7 +2315,9 @@ impl From> for FeeChange { } } -/// Updates markets or creates them if they do not exist in the market map. +/// Takes a list of markets and either updates them if they are already in the market map, or +/// creates them if they are not. If no market map is found, one will be created. Must be signed by +/// an address included in the market map [`Params`]' `market_authorities`. #[derive(Debug, Clone)] pub struct UpsertMarkets { // The list of all markets to be upserted for the given @@ -2367,7 +2369,9 @@ pub enum UpsertMarketsErrorKind { InvalidMarket(#[from] MarketError), } -/// Creates new markets in the market map. +/// Takes a list of markets and creates them in the market map. If any already exist, this will err. +/// If no market map is found, one will be created. Must be signed by an address included in the +/// market map [`Params`]' `market_authorities`. #[derive(Debug, Clone)] pub struct CreateMarkets { /// The list of all markets to be created for the given @@ -2421,7 +2425,10 @@ pub enum CreateMarketsErrorKind { AuthorityParse(#[from] AddressError), } -/// Updates existing markets in the market map. +/// Takes a list of markets and updates them in the market map (matching based on its +/// ticker's `currency_pair`). If no market map is found, or any market is missing a counterpart in +/// the map, this will err. Must be signed by an address included in the market map [`Params`]' +/// `market_authorities`. #[derive(Debug, Clone)] pub struct UpdateMarkets { /// The list of all markets to be updated for the given @@ -2473,7 +2480,9 @@ pub enum UpdateMarketsErrorKind { InvalidMarket(#[from] MarketError), } -/// Updates the market map params. +/// Updates the market map Params, which contains the market authority addresses as well as an admin +/// address. This will execute whether there are params in the state already or not. Must be signed +/// by the sequencer network authority sudo address. #[derive(Debug, Clone)] pub struct UpdateParams { /// The new parameters for the `connect/marketmap` module. @@ -2529,7 +2538,9 @@ pub enum UpdateParamsErrorKind { AuthorityParse(#[from] AddressError), } -/// Removes addresses from the market map list of authorities. +/// Takes a list of addresses and removes them from the market authorities. If an address does not +/// exist in `market_authorities`, it will be ignored. Must be signed by the market map admin (as +/// defined in the market map [`Params`]). #[derive(Debug, Clone)] pub struct RemoveMarketAuthorities { /// The list of addresses to remove. @@ -2581,7 +2592,9 @@ pub enum RemoveMarketAuthoritiesErrorKind { RemoveAddressParse(#[source] AddressError), } -/// Removes markets from the market map. +/// Takes a list of markets and removes them from the market map. If a market is not found in the +/// map, it will be ignored. Must be signed by an address included in the market map [`Params`]' +/// `market_authorities`. #[derive(Debug, Clone)] pub struct RemoveMarkets { /// The list of all markets to be removed. diff --git a/crates/astria-sequencer/src/action_handler/impls/remove_markets.rs b/crates/astria-sequencer/src/action_handler/impls/remove_markets.rs index deca5d6ffb..c34b9cece1 100644 --- a/crates/astria-sequencer/src/action_handler/impls/remove_markets.rs +++ b/crates/astria-sequencer/src/action_handler/impls/remove_markets.rs @@ -95,7 +95,10 @@ mod tests { astria_address, ASTRIA_PREFIX, }, - test_utils::example_ticker, + test_utils::{ + example_ticker, + example_ticker_from_currency_pair, + }, transaction::{ StateWriteExt as _, TransactionContext, @@ -204,4 +207,58 @@ mod tests { .contains("market map params not found in state") ); } + + #[tokio::test] + async fn remove_markets_skips_missing_markets() { + let storage = cnidarium::TempStorage::new().await.unwrap(); + let snapshot = storage.latest_snapshot(); + let mut state = cnidarium::StateDelta::new(snapshot); + + let authority_address = astria_address(&[0; 20]); + + state.put_block_height(1).unwrap(); + state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); + state.put_transaction_context(TransactionContext { + address_bytes: *authority_address.address_bytes(), + transaction_id: TransactionId::new([0; 32]), + position_in_transaction: 0, + }); + + let params = Params { + market_authorities: vec![authority_address], + admin: authority_address, + }; + state.put_params(params).unwrap(); + + let ticker = example_ticker(String::new()); + let market = Market { + ticker: ticker.clone(), + provider_configs: vec![], + }; + + let mut markets = IndexMap::new(); + markets.insert(ticker.currency_pair.to_string(), market.clone()); + + state + .put_market_map(MarketMap { + markets, + }) + .unwrap(); + + let action = RemoveMarkets { + markets: vec![ + example_ticker_from_currency_pair("DIFBASE", "DIFQUOTE", String::new()) + .currency_pair + .to_string(), + ], + }; + action.check_and_execute(&mut state).await.unwrap(); + let market_map = state.get_market_map().await.unwrap().unwrap(); + assert_eq!(market_map.markets.len(), 1); + assert_eq!( + market_map.markets.get(&ticker.currency_pair.to_string()), + Some(&market) + ); + assert_eq!(state.get_market_map_last_updated_height().await.unwrap(), 1); + } } diff --git a/crates/astria-sequencer/src/app/test_utils.rs b/crates/astria-sequencer/src/app/test_utils.rs index b3f1c7ad7c..70ff395c7c 100644 --- a/crates/astria-sequencer/src/app/test_utils.rs +++ b/crates/astria-sequencer/src/app/test_utils.rs @@ -1,18 +1,9 @@ use std::{ collections::HashMap, - str::FromStr as _, sync::Arc, }; use astria_core::{ - connect::{ - market_map::v2::Ticker, - types::v2::{ - Base, - CurrencyPair, - Quote, - }, - }, crypto::SigningKey, primitive::v1::RollupId, protocol::{ @@ -210,20 +201,3 @@ pub(crate) fn transactions_with_extended_commit_info_and_commitments( .collect(); txs_with_commit_info } - -pub(crate) fn example_ticker_from_currency_pair( - base: &str, - quote: &str, - metadata: String, -) -> Ticker { - Ticker { - currency_pair: CurrencyPair::from_parts( - Base::from_str(base).unwrap(), - Quote::from_str(quote).unwrap(), - ), - decimals: 2, - min_provider_count: 2, - enabled: true, - metadata_json: metadata, - } -} diff --git a/crates/astria-sequencer/src/app/tests_breaking_changes.rs b/crates/astria-sequencer/src/app/tests_breaking_changes.rs index 11ec9c7dac..b700153f4d 100644 --- a/crates/astria-sequencer/src/app/tests_breaking_changes.rs +++ b/crates/astria-sequencer/src/app/tests_breaking_changes.rs @@ -70,7 +70,6 @@ use crate::{ CAROL_ADDRESS, }, test_utils::{ - example_ticker_from_currency_pair, get_alice_signing_key, get_bridge_signing_key, initialize_app, @@ -85,6 +84,7 @@ use crate::{ ASTRIA_PREFIX, }, bridge::StateWriteExt as _, + test_utils::example_ticker_from_currency_pair, }; #[tokio::test] diff --git a/crates/astria-sequencer/src/app/tests_execute_transaction.rs b/crates/astria-sequencer/src/app/tests_execute_transaction.rs index 2cf8e58532..e058f14b99 100644 --- a/crates/astria-sequencer/src/app/tests_execute_transaction.rs +++ b/crates/astria-sequencer/src/app/tests_execute_transaction.rs @@ -60,7 +60,6 @@ use crate::{ CAROL_ADDRESS, }, test_utils::{ - example_ticker_from_currency_pair, get_bridge_signing_key, initialize_app, }, @@ -93,6 +92,7 @@ use crate::{ test_utils::{ calculate_rollup_data_submission_fee_from_state, example_ticker, + example_ticker_from_currency_pair, }, utils::create_deposit_event, }; diff --git a/crates/astria-sequencer/src/test_utils.rs b/crates/astria-sequencer/src/test_utils.rs index 2a96f4e5b3..127c6b2639 100644 --- a/crates/astria-sequencer/src/test_utils.rs +++ b/crates/astria-sequencer/src/test_utils.rs @@ -70,3 +70,20 @@ pub(crate) fn example_ticker(metadata: String) -> Ticker { metadata_json: metadata, } } + +pub(crate) fn example_ticker_from_currency_pair( + base: &str, + quote: &str, + metadata: String, +) -> Ticker { + Ticker { + currency_pair: CurrencyPair::from_parts( + Base::from_str(base).unwrap(), + Quote::from_str(quote).unwrap(), + ), + decimals: 2, + min_provider_count: 2, + enabled: true, + metadata_json: metadata, + } +} From 7681fa188df35f061e13a70345a9c466abdc370d Mon Sep 17 00:00:00 2001 From: ethanoroshiba Date: Wed, 18 Dec 2024 09:26:05 -0600 Subject: [PATCH 3/8] add fee change tests --- .../src/protocol/transaction/v1/action/mod.rs | 30 +++++++++++++++++++ .../src/action_handler/impls/fee_change.rs | 25 ++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/crates/astria-core/src/protocol/transaction/v1/action/mod.rs b/crates/astria-core/src/protocol/transaction/v1/action/mod.rs index 43522edcb8..9c93c4ca7b 100644 --- a/crates/astria-core/src/protocol/transaction/v1/action/mod.rs +++ b/crates/astria-core/src/protocol/transaction/v1/action/mod.rs @@ -2315,6 +2315,36 @@ impl From> for FeeChange { } } +impl From> for FeeChange { + fn from(fee: FeeComponents) -> Self { + FeeChange::UpsertMarkets(fee) + } +} + +impl From> for FeeChange { + fn from(fee: FeeComponents) -> Self { + FeeChange::CreateMarkets(fee) + } +} + +impl From> for FeeChange { + fn from(fee: FeeComponents) -> Self { + FeeChange::UpdateMarkets(fee) + } +} + +impl From> for FeeChange { + fn from(fee: FeeComponents) -> Self { + FeeChange::RemoveMarketAuthorities(fee) + } +} + +impl From> for FeeChange { + fn from(fee: FeeComponents) -> Self { + FeeChange::RemoveMarkets(fee) + } +} + /// Takes a list of markets and either updates them if they are already in the market map, or /// creates them if they are not. If no market map is found, one will be created. Must be signed by /// an address included in the market map [`Params`]' `market_authorities`. diff --git a/crates/astria-sequencer/src/action_handler/impls/fee_change.rs b/crates/astria-sequencer/src/action_handler/impls/fee_change.rs index 69d8b2da6c..7223a5632b 100644 --- a/crates/astria-sequencer/src/action_handler/impls/fee_change.rs +++ b/crates/astria-sequencer/src/action_handler/impls/fee_change.rs @@ -197,6 +197,31 @@ mod tests { test_fee_change_action::().await; } + #[tokio::test] + async fn upsert_markets_fee_change_action_executes_as_expected() { + test_fee_change_action::().await; + } + + #[tokio::test] + async fn create_markets_fee_change_action_executes_as_expected() { + test_fee_change_action::().await; + } + + #[tokio::test] + async fn update_markets_fee_change_action_executes_as_expected() { + test_fee_change_action::().await; + } + + #[tokio::test] + async fn remove_market_authorities_fee_change_action_executes_as_expected() { + test_fee_change_action::().await; + } + + #[tokio::test] + async fn remove_markets_fee_change_action_executes_as_expected() { + test_fee_change_action::().await; + } + async fn test_fee_change_action<'a, F>() where F: FeeHandler, From 378e9981f47ad6d606923dc0d6468d00388338a9 Mon Sep 17 00:00:00 2001 From: ethanoroshiba Date: Thu, 19 Dec 2024 12:47:54 -0600 Subject: [PATCH 4/8] requested changes --- .../src/generated/astria.protocol.fees.v1.rs | 6 +- .../astria.protocol.fees.v1.serde.rs | 32 ++--- .../generated/astria.protocol.genesis.v1.rs | 4 +- .../astria.protocol.genesis.v1.serde.rs | 26 ++-- .../astria.protocol.transaction.v1.rs | 12 +- .../astria.protocol.transaction.v1.serde.rs | 118 +++++++++--------- crates/astria-core/src/protocol/fees/v1.rs | 4 +- ...ol__genesis__v1__tests__genesis_state.snap | 2 +- crates/astria-core/src/protocol/genesis/v1.rs | 77 ++++++------ .../transaction/v1/action/group/mod.rs | 6 +- .../src/protocol/transaction/v1/action/mod.rs | 59 ++++----- .../src/genesis_example.rs | 6 +- .../action_handler/impls/create_markets.rs | 12 +- .../src/action_handler/impls/fee_change.rs | 2 +- .../src/action_handler/impls/mod.rs | 2 +- .../action_handler/impls/remove_markets.rs | 15 +-- .../src/action_handler/impls/transaction.rs | 6 +- ..._params.rs => update_market_map_params.rs} | 12 +- .../action_handler/impls/update_markets.rs | 17 +-- .../action_handler/impls/upsert_markets.rs | 17 +-- .../src/app/benchmark_and_test_utils.rs | 4 +- ...breaking_changes__app_hash_at_genesis.snap | 60 ++++----- ...hanges__app_hash_execute_every_action.snap | 60 ++++----- ...king_changes__app_hash_finalize_block.snap | 60 ++++----- .../src/app/tests_breaking_changes.rs | 4 +- .../src/app/tests_execute_transaction.rs | 22 ++-- crates/astria-sequencer/src/fees/component.rs | 6 +- crates/astria-sequencer/src/fees/mod.rs | 6 +- crates/astria-sequencer/src/fees/query.rs | 9 +- .../src/fees/storage/values.rs | 6 +- crates/astria-sequencer/src/test_utils.rs | 2 +- .../src/transaction/checks.rs | 2 +- .../astria/protocol/fees/v1/types.proto | 2 +- .../astria/protocol/genesis/v1/types.proto | 2 +- .../protocol/transaction/v1/action.proto | 6 +- 35 files changed, 353 insertions(+), 333 deletions(-) rename crates/astria-sequencer/src/action_handler/impls/{update_params.rs => update_market_map_params.rs} (90%) diff --git a/crates/astria-core/src/generated/astria.protocol.fees.v1.rs b/crates/astria-core/src/generated/astria.protocol.fees.v1.rs index 4e7753d10e..d948cbaa59 100644 --- a/crates/astria-core/src/generated/astria.protocol.fees.v1.rs +++ b/crates/astria-core/src/generated/astria.protocol.fees.v1.rs @@ -270,14 +270,14 @@ impl ::prost::Name for UpdateMarketsFeeComponents { } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] -pub struct UpdateParamsFeeComponents { +pub struct UpdateMarketMapParamsFeeComponents { #[prost(message, optional, tag = "1")] pub base: ::core::option::Option, #[prost(message, optional, tag = "2")] pub multiplier: ::core::option::Option, } -impl ::prost::Name for UpdateParamsFeeComponents { - const NAME: &'static str = "UpdateParamsFeeComponents"; +impl ::prost::Name for UpdateMarketMapParamsFeeComponents { + const NAME: &'static str = "UpdateMarketMapParamsFeeComponents"; const PACKAGE: &'static str = "astria.protocol.fees.v1"; fn full_name() -> ::prost::alloc::string::String { ::prost::alloc::format!("astria.protocol.fees.v1.{}", Self::NAME) diff --git a/crates/astria-core/src/generated/astria.protocol.fees.v1.serde.rs b/crates/astria-core/src/generated/astria.protocol.fees.v1.serde.rs index c2245ae908..01260c0aaa 100644 --- a/crates/astria-core/src/generated/astria.protocol.fees.v1.serde.rs +++ b/crates/astria-core/src/generated/astria.protocol.fees.v1.serde.rs @@ -1945,7 +1945,7 @@ impl<'de> serde::Deserialize<'de> for TransferFeeComponents { deserializer.deserialize_struct("astria.protocol.fees.v1.TransferFeeComponents", FIELDS, GeneratedVisitor) } } -impl serde::Serialize for UpdateMarketsFeeComponents { +impl serde::Serialize for UpdateMarketMapParamsFeeComponents { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result where @@ -1959,7 +1959,7 @@ impl serde::Serialize for UpdateMarketsFeeComponents { if self.multiplier.is_some() { len += 1; } - let mut struct_ser = serializer.serialize_struct("astria.protocol.fees.v1.UpdateMarketsFeeComponents", len)?; + let mut struct_ser = serializer.serialize_struct("astria.protocol.fees.v1.UpdateMarketMapParamsFeeComponents", len)?; if let Some(v) = self.base.as_ref() { struct_ser.serialize_field("base", v)?; } @@ -1969,7 +1969,7 @@ impl serde::Serialize for UpdateMarketsFeeComponents { struct_ser.end() } } -impl<'de> serde::Deserialize<'de> for UpdateMarketsFeeComponents { +impl<'de> serde::Deserialize<'de> for UpdateMarketMapParamsFeeComponents { #[allow(deprecated)] fn deserialize(deserializer: D) -> std::result::Result where @@ -2016,13 +2016,13 @@ impl<'de> serde::Deserialize<'de> for UpdateMarketsFeeComponents { } struct GeneratedVisitor; impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = UpdateMarketsFeeComponents; + type Value = UpdateMarketMapParamsFeeComponents; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct astria.protocol.fees.v1.UpdateMarketsFeeComponents") + formatter.write_str("struct astria.protocol.fees.v1.UpdateMarketMapParamsFeeComponents") } - fn visit_map(self, mut map_: V) -> std::result::Result + fn visit_map(self, mut map_: V) -> std::result::Result where V: serde::de::MapAccess<'de>, { @@ -2044,16 +2044,16 @@ impl<'de> serde::Deserialize<'de> for UpdateMarketsFeeComponents { } } } - Ok(UpdateMarketsFeeComponents { + Ok(UpdateMarketMapParamsFeeComponents { base: base__, multiplier: multiplier__, }) } } - deserializer.deserialize_struct("astria.protocol.fees.v1.UpdateMarketsFeeComponents", FIELDS, GeneratedVisitor) + deserializer.deserialize_struct("astria.protocol.fees.v1.UpdateMarketMapParamsFeeComponents", FIELDS, GeneratedVisitor) } } -impl serde::Serialize for UpdateParamsFeeComponents { +impl serde::Serialize for UpdateMarketsFeeComponents { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result where @@ -2067,7 +2067,7 @@ impl serde::Serialize for UpdateParamsFeeComponents { if self.multiplier.is_some() { len += 1; } - let mut struct_ser = serializer.serialize_struct("astria.protocol.fees.v1.UpdateParamsFeeComponents", len)?; + let mut struct_ser = serializer.serialize_struct("astria.protocol.fees.v1.UpdateMarketsFeeComponents", len)?; if let Some(v) = self.base.as_ref() { struct_ser.serialize_field("base", v)?; } @@ -2077,7 +2077,7 @@ impl serde::Serialize for UpdateParamsFeeComponents { struct_ser.end() } } -impl<'de> serde::Deserialize<'de> for UpdateParamsFeeComponents { +impl<'de> serde::Deserialize<'de> for UpdateMarketsFeeComponents { #[allow(deprecated)] fn deserialize(deserializer: D) -> std::result::Result where @@ -2124,13 +2124,13 @@ impl<'de> serde::Deserialize<'de> for UpdateParamsFeeComponents { } struct GeneratedVisitor; impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = UpdateParamsFeeComponents; + type Value = UpdateMarketsFeeComponents; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct astria.protocol.fees.v1.UpdateParamsFeeComponents") + formatter.write_str("struct astria.protocol.fees.v1.UpdateMarketsFeeComponents") } - fn visit_map(self, mut map_: V) -> std::result::Result + fn visit_map(self, mut map_: V) -> std::result::Result where V: serde::de::MapAccess<'de>, { @@ -2152,13 +2152,13 @@ impl<'de> serde::Deserialize<'de> for UpdateParamsFeeComponents { } } } - Ok(UpdateParamsFeeComponents { + Ok(UpdateMarketsFeeComponents { base: base__, multiplier: multiplier__, }) } } - deserializer.deserialize_struct("astria.protocol.fees.v1.UpdateParamsFeeComponents", FIELDS, GeneratedVisitor) + deserializer.deserialize_struct("astria.protocol.fees.v1.UpdateMarketsFeeComponents", FIELDS, GeneratedVisitor) } } impl serde::Serialize for UpsertMarketsFeeComponents { diff --git a/crates/astria-core/src/generated/astria.protocol.genesis.v1.rs b/crates/astria-core/src/generated/astria.protocol.genesis.v1.rs index 116d3ca0ff..12875fdef4 100644 --- a/crates/astria-core/src/generated/astria.protocol.genesis.v1.rs +++ b/crates/astria-core/src/generated/astria.protocol.genesis.v1.rs @@ -160,8 +160,8 @@ pub struct GenesisFees { super::super::fees::v1::UpdateMarketsFeeComponents, >, #[prost(message, optional, tag = "18")] - pub update_params: ::core::option::Option< - super::super::fees::v1::UpdateParamsFeeComponents, + pub update_market_map_params: ::core::option::Option< + super::super::fees::v1::UpdateMarketMapParamsFeeComponents, >, #[prost(message, optional, tag = "19")] pub remove_market_authorities: ::core::option::Option< diff --git a/crates/astria-core/src/generated/astria.protocol.genesis.v1.serde.rs b/crates/astria-core/src/generated/astria.protocol.genesis.v1.serde.rs index 8d8bf38905..79ae34a609 100644 --- a/crates/astria-core/src/generated/astria.protocol.genesis.v1.serde.rs +++ b/crates/astria-core/src/generated/astria.protocol.genesis.v1.serde.rs @@ -652,7 +652,7 @@ impl serde::Serialize for GenesisFees { if self.update_markets.is_some() { len += 1; } - if self.update_params.is_some() { + if self.update_market_map_params.is_some() { len += 1; } if self.remove_market_authorities.is_some() { @@ -713,8 +713,8 @@ impl serde::Serialize for GenesisFees { if let Some(v) = self.update_markets.as_ref() { struct_ser.serialize_field("updateMarkets", v)?; } - if let Some(v) = self.update_params.as_ref() { - struct_ser.serialize_field("updateParams", v)?; + if let Some(v) = self.update_market_map_params.as_ref() { + struct_ser.serialize_field("updateMarketMapParams", v)?; } if let Some(v) = self.remove_market_authorities.as_ref() { struct_ser.serialize_field("removeMarketAuthorities", v)?; @@ -765,8 +765,8 @@ impl<'de> serde::Deserialize<'de> for GenesisFees { "createMarkets", "update_markets", "updateMarkets", - "update_params", - "updateParams", + "update_market_map_params", + "updateMarketMapParams", "remove_market_authorities", "removeMarketAuthorities", "remove_markets", @@ -792,7 +792,7 @@ impl<'de> serde::Deserialize<'de> for GenesisFees { UpsertMarkets, CreateMarkets, UpdateMarkets, - UpdateParams, + UpdateMarketMapParams, RemoveMarketAuthorities, RemoveMarkets, } @@ -833,7 +833,7 @@ impl<'de> serde::Deserialize<'de> for GenesisFees { "upsertMarkets" | "upsert_markets" => Ok(GeneratedField::UpsertMarkets), "createMarkets" | "create_markets" => Ok(GeneratedField::CreateMarkets), "updateMarkets" | "update_markets" => Ok(GeneratedField::UpdateMarkets), - "updateParams" | "update_params" => Ok(GeneratedField::UpdateParams), + "updateMarketMapParams" | "update_market_map_params" => Ok(GeneratedField::UpdateMarketMapParams), "removeMarketAuthorities" | "remove_market_authorities" => Ok(GeneratedField::RemoveMarketAuthorities), "removeMarkets" | "remove_markets" => Ok(GeneratedField::RemoveMarkets), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), @@ -872,7 +872,7 @@ impl<'de> serde::Deserialize<'de> for GenesisFees { let mut upsert_markets__ = None; let mut create_markets__ = None; let mut update_markets__ = None; - let mut update_params__ = None; + let mut update_market_map_params__ = None; let mut remove_market_authorities__ = None; let mut remove_markets__ = None; while let Some(k) = map_.next_key()? { @@ -979,11 +979,11 @@ impl<'de> serde::Deserialize<'de> for GenesisFees { } update_markets__ = map_.next_value()?; } - GeneratedField::UpdateParams => { - if update_params__.is_some() { - return Err(serde::de::Error::duplicate_field("updateParams")); + GeneratedField::UpdateMarketMapParams => { + if update_market_map_params__.is_some() { + return Err(serde::de::Error::duplicate_field("updateMarketMapParams")); } - update_params__ = map_.next_value()?; + update_market_map_params__ = map_.next_value()?; } GeneratedField::RemoveMarketAuthorities => { if remove_market_authorities__.is_some() { @@ -1017,7 +1017,7 @@ impl<'de> serde::Deserialize<'de> for GenesisFees { upsert_markets: upsert_markets__, create_markets: create_markets__, update_markets: update_markets__, - update_params: update_params__, + update_market_map_params: update_market_map_params__, remove_market_authorities: remove_market_authorities__, remove_markets: remove_markets__, }) diff --git a/crates/astria-core/src/generated/astria.protocol.transaction.v1.rs b/crates/astria-core/src/generated/astria.protocol.transaction.v1.rs index 14dbbc3368..11e1c10126 100644 --- a/crates/astria-core/src/generated/astria.protocol.transaction.v1.rs +++ b/crates/astria-core/src/generated/astria.protocol.transaction.v1.rs @@ -54,7 +54,7 @@ pub mod action { #[prost(message, tag = "73")] UpdateMarkets(super::UpdateMarkets), #[prost(message, tag = "74")] - UpdateParams(super::UpdateParams), + UpdateMarketMapParams(super::UpdateMarketMapParams), #[prost(message, tag = "75")] RemoveMarketAuthorities(super::RemoveMarketAuthorities), #[prost(message, tag = "76")] @@ -462,7 +462,9 @@ pub mod fee_change { #[prost(message, tag = "17")] UpdateMarkets(super::super::super::fees::v1::UpdateMarketsFeeComponents), #[prost(message, tag = "18")] - UpdateParams(super::super::super::fees::v1::UpdateParamsFeeComponents), + UpdateMarketMapParams( + super::super::super::fees::v1::UpdateMarketMapParamsFeeComponents, + ), #[prost(message, tag = "19")] RemoveMarketAuthorities( super::super::super::fees::v1::RemoveMarketAuthoritiesFeeComponents, @@ -545,15 +547,15 @@ impl ::prost::Name for UpdateMarkets { /// Updates the market map parameters. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] -pub struct UpdateParams { +pub struct UpdateMarketMapParams { /// Params defines the new parameters for the x/marketmap module. #[prost(message, optional, tag = "1")] pub params: ::core::option::Option< super::super::super::super::connect::marketmap::v2::Params, >, } -impl ::prost::Name for UpdateParams { - const NAME: &'static str = "UpdateParams"; +impl ::prost::Name for UpdateMarketMapParams { + const NAME: &'static str = "UpdateMarketMapParams"; const PACKAGE: &'static str = "astria.protocol.transaction.v1"; fn full_name() -> ::prost::alloc::string::String { ::prost::alloc::format!("astria.protocol.transaction.v1.{}", Self::NAME) diff --git a/crates/astria-core/src/generated/astria.protocol.transaction.v1.serde.rs b/crates/astria-core/src/generated/astria.protocol.transaction.v1.serde.rs index c8da12dd7b..0441f90160 100644 --- a/crates/astria-core/src/generated/astria.protocol.transaction.v1.serde.rs +++ b/crates/astria-core/src/generated/astria.protocol.transaction.v1.serde.rs @@ -63,8 +63,8 @@ impl serde::Serialize for Action { action::Value::UpdateMarkets(v) => { struct_ser.serialize_field("updateMarkets", v)?; } - action::Value::UpdateParams(v) => { - struct_ser.serialize_field("updateParams", v)?; + action::Value::UpdateMarketMapParams(v) => { + struct_ser.serialize_field("updateMarketMapParams", v)?; } action::Value::RemoveMarketAuthorities(v) => { struct_ser.serialize_field("removeMarketAuthorities", v)?; @@ -116,8 +116,8 @@ impl<'de> serde::Deserialize<'de> for Action { "createMarkets", "update_markets", "updateMarkets", - "update_params", - "updateParams", + "update_market_map_params", + "updateMarketMapParams", "remove_market_authorities", "removeMarketAuthorities", "remove_markets", @@ -143,7 +143,7 @@ impl<'de> serde::Deserialize<'de> for Action { UpsertMarkets, CreateMarkets, UpdateMarkets, - UpdateParams, + UpdateMarketMapParams, RemoveMarketAuthorities, RemoveMarkets, } @@ -184,7 +184,7 @@ impl<'de> serde::Deserialize<'de> for Action { "upsertMarkets" | "upsert_markets" => Ok(GeneratedField::UpsertMarkets), "createMarkets" | "create_markets" => Ok(GeneratedField::CreateMarkets), "updateMarkets" | "update_markets" => Ok(GeneratedField::UpdateMarkets), - "updateParams" | "update_params" => Ok(GeneratedField::UpdateParams), + "updateMarketMapParams" | "update_market_map_params" => Ok(GeneratedField::UpdateMarketMapParams), "removeMarketAuthorities" | "remove_market_authorities" => Ok(GeneratedField::RemoveMarketAuthorities), "removeMarkets" | "remove_markets" => Ok(GeneratedField::RemoveMarkets), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), @@ -328,11 +328,11 @@ impl<'de> serde::Deserialize<'de> for Action { value__ = map_.next_value::<::std::option::Option<_>>()?.map(action::Value::UpdateMarkets) ; } - GeneratedField::UpdateParams => { + GeneratedField::UpdateMarketMapParams => { if value__.is_some() { - return Err(serde::de::Error::duplicate_field("updateParams")); + return Err(serde::de::Error::duplicate_field("updateMarketMapParams")); } - value__ = map_.next_value::<::std::option::Option<_>>()?.map(action::Value::UpdateParams) + value__ = map_.next_value::<::std::option::Option<_>>()?.map(action::Value::UpdateMarketMapParams) ; } GeneratedField::RemoveMarketAuthorities => { @@ -1130,8 +1130,8 @@ impl serde::Serialize for FeeChange { fee_change::FeeComponents::UpdateMarkets(v) => { struct_ser.serialize_field("updateMarkets", v)?; } - fee_change::FeeComponents::UpdateParams(v) => { - struct_ser.serialize_field("updateParams", v)?; + fee_change::FeeComponents::UpdateMarketMapParams(v) => { + struct_ser.serialize_field("updateMarketMapParams", v)?; } fee_change::FeeComponents::RemoveMarketAuthorities(v) => { struct_ser.serialize_field("removeMarketAuthorities", v)?; @@ -1184,8 +1184,8 @@ impl<'de> serde::Deserialize<'de> for FeeChange { "createMarkets", "update_markets", "updateMarkets", - "update_params", - "updateParams", + "update_market_map_params", + "updateMarketMapParams", "remove_market_authorities", "removeMarketAuthorities", "remove_markets", @@ -1211,7 +1211,7 @@ impl<'de> serde::Deserialize<'de> for FeeChange { UpsertMarkets, CreateMarkets, UpdateMarkets, - UpdateParams, + UpdateMarketMapParams, RemoveMarketAuthorities, RemoveMarkets, } @@ -1252,7 +1252,7 @@ impl<'de> serde::Deserialize<'de> for FeeChange { "upsertMarkets" | "upsert_markets" => Ok(GeneratedField::UpsertMarkets), "createMarkets" | "create_markets" => Ok(GeneratedField::CreateMarkets), "updateMarkets" | "update_markets" => Ok(GeneratedField::UpdateMarkets), - "updateParams" | "update_params" => Ok(GeneratedField::UpdateParams), + "updateMarketMapParams" | "update_market_map_params" => Ok(GeneratedField::UpdateMarketMapParams), "removeMarketAuthorities" | "remove_market_authorities" => Ok(GeneratedField::RemoveMarketAuthorities), "removeMarkets" | "remove_markets" => Ok(GeneratedField::RemoveMarkets), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), @@ -1396,11 +1396,11 @@ impl<'de> serde::Deserialize<'de> for FeeChange { fee_components__ = map_.next_value::<::std::option::Option<_>>()?.map(fee_change::FeeComponents::UpdateMarkets) ; } - GeneratedField::UpdateParams => { + GeneratedField::UpdateMarketMapParams => { if fee_components__.is_some() { - return Err(serde::de::Error::duplicate_field("updateParams")); + return Err(serde::de::Error::duplicate_field("updateMarketMapParams")); } - fee_components__ = map_.next_value::<::std::option::Option<_>>()?.map(fee_change::FeeComponents::UpdateParams) + fee_components__ = map_.next_value::<::std::option::Option<_>>()?.map(fee_change::FeeComponents::UpdateMarketMapParams) ; } GeneratedField::RemoveMarketAuthorities => { @@ -3078,7 +3078,7 @@ impl<'de> serde::Deserialize<'de> for Transfer { deserializer.deserialize_struct("astria.protocol.transaction.v1.Transfer", FIELDS, GeneratedVisitor) } } -impl serde::Serialize for UpdateMarkets { +impl serde::Serialize for UpdateMarketMapParams { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result where @@ -3086,30 +3086,29 @@ impl serde::Serialize for UpdateMarkets { { use serde::ser::SerializeStruct; let mut len = 0; - if !self.update_markets.is_empty() { + if self.params.is_some() { len += 1; } - let mut struct_ser = serializer.serialize_struct("astria.protocol.transaction.v1.UpdateMarkets", len)?; - if !self.update_markets.is_empty() { - struct_ser.serialize_field("updateMarkets", &self.update_markets)?; + let mut struct_ser = serializer.serialize_struct("astria.protocol.transaction.v1.UpdateMarketMapParams", len)?; + if let Some(v) = self.params.as_ref() { + struct_ser.serialize_field("params", v)?; } struct_ser.end() } } -impl<'de> serde::Deserialize<'de> for UpdateMarkets { +impl<'de> serde::Deserialize<'de> for UpdateMarketMapParams { #[allow(deprecated)] fn deserialize(deserializer: D) -> std::result::Result where D: serde::Deserializer<'de>, { const FIELDS: &[&str] = &[ - "update_markets", - "updateMarkets", + "params", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { - UpdateMarkets, + Params, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -3131,7 +3130,7 @@ impl<'de> serde::Deserialize<'de> for UpdateMarkets { E: serde::de::Error, { match value { - "updateMarkets" | "update_markets" => Ok(GeneratedField::UpdateMarkets), + "params" => Ok(GeneratedField::Params), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -3141,36 +3140,36 @@ impl<'de> serde::Deserialize<'de> for UpdateMarkets { } struct GeneratedVisitor; impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = UpdateMarkets; + type Value = UpdateMarketMapParams; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct astria.protocol.transaction.v1.UpdateMarkets") + formatter.write_str("struct astria.protocol.transaction.v1.UpdateMarketMapParams") } - fn visit_map(self, mut map_: V) -> std::result::Result + fn visit_map(self, mut map_: V) -> std::result::Result where V: serde::de::MapAccess<'de>, { - let mut update_markets__ = None; + let mut params__ = None; while let Some(k) = map_.next_key()? { match k { - GeneratedField::UpdateMarkets => { - if update_markets__.is_some() { - return Err(serde::de::Error::duplicate_field("updateMarkets")); + GeneratedField::Params => { + if params__.is_some() { + return Err(serde::de::Error::duplicate_field("params")); } - update_markets__ = Some(map_.next_value()?); + params__ = map_.next_value()?; } } } - Ok(UpdateMarkets { - update_markets: update_markets__.unwrap_or_default(), + Ok(UpdateMarketMapParams { + params: params__, }) } } - deserializer.deserialize_struct("astria.protocol.transaction.v1.UpdateMarkets", FIELDS, GeneratedVisitor) + deserializer.deserialize_struct("astria.protocol.transaction.v1.UpdateMarketMapParams", FIELDS, GeneratedVisitor) } } -impl serde::Serialize for UpdateParams { +impl serde::Serialize for UpdateMarkets { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result where @@ -3178,29 +3177,30 @@ impl serde::Serialize for UpdateParams { { use serde::ser::SerializeStruct; let mut len = 0; - if self.params.is_some() { + if !self.update_markets.is_empty() { len += 1; } - let mut struct_ser = serializer.serialize_struct("astria.protocol.transaction.v1.UpdateParams", len)?; - if let Some(v) = self.params.as_ref() { - struct_ser.serialize_field("params", v)?; + let mut struct_ser = serializer.serialize_struct("astria.protocol.transaction.v1.UpdateMarkets", len)?; + if !self.update_markets.is_empty() { + struct_ser.serialize_field("updateMarkets", &self.update_markets)?; } struct_ser.end() } } -impl<'de> serde::Deserialize<'de> for UpdateParams { +impl<'de> serde::Deserialize<'de> for UpdateMarkets { #[allow(deprecated)] fn deserialize(deserializer: D) -> std::result::Result where D: serde::Deserializer<'de>, { const FIELDS: &[&str] = &[ - "params", + "update_markets", + "updateMarkets", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { - Params, + UpdateMarkets, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -3222,7 +3222,7 @@ impl<'de> serde::Deserialize<'de> for UpdateParams { E: serde::de::Error, { match value { - "params" => Ok(GeneratedField::Params), + "updateMarkets" | "update_markets" => Ok(GeneratedField::UpdateMarkets), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -3232,33 +3232,33 @@ impl<'de> serde::Deserialize<'de> for UpdateParams { } struct GeneratedVisitor; impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = UpdateParams; + type Value = UpdateMarkets; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct astria.protocol.transaction.v1.UpdateParams") + formatter.write_str("struct astria.protocol.transaction.v1.UpdateMarkets") } - fn visit_map(self, mut map_: V) -> std::result::Result + fn visit_map(self, mut map_: V) -> std::result::Result where V: serde::de::MapAccess<'de>, { - let mut params__ = None; + let mut update_markets__ = None; while let Some(k) = map_.next_key()? { match k { - GeneratedField::Params => { - if params__.is_some() { - return Err(serde::de::Error::duplicate_field("params")); + GeneratedField::UpdateMarkets => { + if update_markets__.is_some() { + return Err(serde::de::Error::duplicate_field("updateMarkets")); } - params__ = map_.next_value()?; + update_markets__ = Some(map_.next_value()?); } } } - Ok(UpdateParams { - params: params__, + Ok(UpdateMarkets { + update_markets: update_markets__.unwrap_or_default(), }) } } - deserializer.deserialize_struct("astria.protocol.transaction.v1.UpdateParams", FIELDS, GeneratedVisitor) + deserializer.deserialize_struct("astria.protocol.transaction.v1.UpdateMarkets", FIELDS, GeneratedVisitor) } } impl serde::Serialize for UpsertMarkets { diff --git a/crates/astria-core/src/protocol/fees/v1.rs b/crates/astria-core/src/protocol/fees/v1.rs index 7249cc6d4b..fec3dd4194 100644 --- a/crates/astria-core/src/protocol/fees/v1.rs +++ b/crates/astria-core/src/protocol/fees/v1.rs @@ -29,8 +29,8 @@ use crate::{ RollupDataSubmission, SudoAddressChange, Transfer, + UpdateMarketMapParams, UpdateMarkets, - UpdateParams, UpsertMarkets, ValidatorUpdate, }, @@ -117,7 +117,7 @@ impl_protobuf_for_fee_components!( FeeComponents => raw::UpsertMarketsFeeComponents, FeeComponents => raw::CreateMarketsFeeComponents, FeeComponents => raw::UpdateMarketsFeeComponents, - FeeComponents => raw::UpdateParamsFeeComponents, + FeeComponents => raw::UpdateMarketMapParamsFeeComponents, FeeComponents => raw::RemoveMarketAuthoritiesFeeComponents, FeeComponents => raw::RemoveMarketsFeeComponents, ); diff --git a/crates/astria-core/src/protocol/genesis/snapshots/astria_core__protocol__genesis__v1__tests__genesis_state.snap b/crates/astria-core/src/protocol/genesis/snapshots/astria_core__protocol__genesis__v1__tests__genesis_state.snap index 679f31d074..d90e54f4fb 100644 --- a/crates/astria-core/src/protocol/genesis/snapshots/astria_core__protocol__genesis__v1__tests__genesis_state.snap +++ b/crates/astria-core/src/protocol/genesis/snapshots/astria_core__protocol__genesis__v1__tests__genesis_state.snap @@ -144,7 +144,7 @@ expression: genesis_state() "base": {}, "multiplier": {} }, - "updateParams": { + "updateMarketMapParams": { "base": {}, "multiplier": {} }, diff --git a/crates/astria-core/src/protocol/genesis/v1.rs b/crates/astria-core/src/protocol/genesis/v1.rs index c374d1b3ca..1ae33ce2de 100644 --- a/crates/astria-core/src/protocol/genesis/v1.rs +++ b/crates/astria-core/src/protocol/genesis/v1.rs @@ -41,8 +41,8 @@ use crate::{ RollupDataSubmission, SudoAddressChange, Transfer, + UpdateMarketMapParams, UpdateMarkets, - UpdateParams, UpsertMarkets, ValidatorUpdate, }, @@ -772,7 +772,7 @@ pub struct GenesisFees { pub upsert_markets: Option>, pub create_markets: Option>, pub update_markets: Option>, - pub update_params: Option>, + pub update_market_map_params: Option>, pub remove_market_authorities: Option>, pub remove_markets: Option>, } @@ -804,7 +804,7 @@ impl Protobuf for GenesisFees { upsert_markets, create_markets, update_markets, - update_params, + update_market_map_params, remove_market_authorities, remove_markets, } = raw; @@ -911,11 +911,11 @@ impl Protobuf for GenesisFees { .transpose() .map_err(|e| FeesError::fee_components("update_markets", e))?; - let update_params = update_params + let update_market_map_params = update_market_map_params .clone() - .map(FeeComponents::::try_from_raw) + .map(FeeComponents::::try_from_raw) .transpose() - .map_err(|e| FeesError::fee_components("update_params", e))?; + .map_err(|e| FeesError::fee_components("update_market_map_params", e))?; let remove_market_authorities = remove_market_authorities .clone() @@ -947,7 +947,7 @@ impl Protobuf for GenesisFees { upsert_markets, create_markets, update_markets, - update_params, + update_market_map_params, remove_market_authorities, remove_markets, }) @@ -972,7 +972,7 @@ impl Protobuf for GenesisFees { upsert_markets, create_markets, update_markets, - update_params, + update_market_map_params, remove_market_authorities, remove_markets, } = self; @@ -1003,7 +1003,8 @@ impl Protobuf for GenesisFees { upsert_markets: upsert_markets.map(|act| FeeComponents::::to_raw(&act)), create_markets: create_markets.map(|act| FeeComponents::::to_raw(&act)), update_markets: update_markets.map(|act| FeeComponents::::to_raw(&act)), - update_params: update_params.map(|act| FeeComponents::::to_raw(&act)), + update_market_map_params: update_market_map_params + .map(|act| FeeComponents::::to_raw(&act)), remove_market_authorities: remove_market_authorities .map(|act| FeeComponents::::to_raw(&act)), remove_markets: remove_markets.map(|act| FeeComponents::::to_raw(&act)), @@ -1133,6 +1134,37 @@ mod tests { } } + fn genesis_fees() -> raw::GenesisFees { + raw::GenesisFees { + transfer: Some(FeeComponents::::new(12, 0).to_raw()), + rollup_data_submission: Some( + FeeComponents::::new(32, 1).to_raw(), + ), + init_bridge_account: Some(FeeComponents::::new(48, 0).to_raw()), + bridge_lock: Some(FeeComponents::::new(12, 1).to_raw()), + bridge_unlock: Some(FeeComponents::::new(12, 0).to_raw()), + bridge_sudo_change: Some(FeeComponents::::new(24, 0).to_raw()), + ics20_withdrawal: Some(FeeComponents::::new(24, 0).to_raw()), + ibc_relay: Some(FeeComponents::::new(0, 0).to_raw()), + validator_update: Some(FeeComponents::::new(0, 0).to_raw()), + fee_asset_change: Some(FeeComponents::::new(0, 0).to_raw()), + fee_change: Some(FeeComponents::::new(0, 0).to_raw()), + ibc_relayer_change: Some(FeeComponents::::new(0, 0).to_raw()), + sudo_address_change: Some(FeeComponents::::new(0, 0).to_raw()), + ibc_sudo_change: Some(FeeComponents::::new(0, 0).to_raw()), + upsert_markets: Some(FeeComponents::::new(0, 0).to_raw()), + create_markets: Some(FeeComponents::::new(0, 0).to_raw()), + update_markets: Some(FeeComponents::::new(0, 0).to_raw()), + update_market_map_params: Some( + FeeComponents::::new(0, 0).to_raw(), + ), + remove_market_authorities: Some( + FeeComponents::::new(0, 0).to_raw(), + ), + remove_markets: Some(FeeComponents::::new(0, 0).to_raw()), + } + } + fn proto_genesis_state() -> raw::GenesisAppState { use crate::connect::{ oracle::v2::{ @@ -1176,32 +1208,7 @@ mod tests { outbound_ics20_transfers_enabled: true, }), allowed_fee_assets: vec!["nria".into()], - fees: Some(raw::GenesisFees { - transfer: Some(FeeComponents::::new(12, 0).to_raw()), - rollup_data_submission: Some( - FeeComponents::::new(32, 1).to_raw(), - ), - init_bridge_account: Some(FeeComponents::::new(48, 0).to_raw()), - bridge_lock: Some(FeeComponents::::new(12, 1).to_raw()), - bridge_unlock: Some(FeeComponents::::new(12, 0).to_raw()), - bridge_sudo_change: Some(FeeComponents::::new(24, 0).to_raw()), - ics20_withdrawal: Some(FeeComponents::::new(24, 0).to_raw()), - ibc_relay: Some(FeeComponents::::new(0, 0).to_raw()), - validator_update: Some(FeeComponents::::new(0, 0).to_raw()), - fee_asset_change: Some(FeeComponents::::new(0, 0).to_raw()), - fee_change: Some(FeeComponents::::new(0, 0).to_raw()), - ibc_relayer_change: Some(FeeComponents::::new(0, 0).to_raw()), - sudo_address_change: Some(FeeComponents::::new(0, 0).to_raw()), - ibc_sudo_change: Some(FeeComponents::::new(0, 0).to_raw()), - upsert_markets: Some(FeeComponents::::new(0, 0).to_raw()), - create_markets: Some(FeeComponents::::new(0, 0).to_raw()), - update_markets: Some(FeeComponents::::new(0, 0).to_raw()), - update_params: Some(FeeComponents::::new(0, 0).to_raw()), - remove_market_authorities: Some( - FeeComponents::::new(0, 0).to_raw(), - ), - remove_markets: Some(FeeComponents::::new(0, 0).to_raw()), - }), + fees: Some(genesis_fees()), connect: Some( ConnectGenesis { market_map: market_map::v2::GenesisState { diff --git a/crates/astria-core/src/protocol/transaction/v1/action/group/mod.rs b/crates/astria-core/src/protocol/transaction/v1/action/group/mod.rs index 57a6e14630..5d7da4789f 100644 --- a/crates/astria-core/src/protocol/transaction/v1/action/group/mod.rs +++ b/crates/astria-core/src/protocol/transaction/v1/action/group/mod.rs @@ -26,8 +26,8 @@ use super::{ RollupDataSubmission, SudoAddressChange, Transfer, + UpdateMarketMapParams, UpdateMarkets, - UpdateParams, UpsertMarkets, ValidatorUpdate, }; @@ -64,7 +64,7 @@ impl_belong_to_group!( (UpsertMarkets, Group::BundleableGeneral), (CreateMarkets, Group::BundleableGeneral), (UpdateMarkets, Group::BundleableGeneral), - (UpdateParams, Group::BundleableSudo), + (UpdateMarketMapParams, Group::BundleableSudo), (RemoveMarketAuthorities, Group::BundleableGeneral), (RemoveMarkets, Group::BundleableGeneral), ); @@ -89,7 +89,7 @@ impl Action { Action::UpsertMarkets(_) => UpsertMarkets::GROUP, Action::CreateMarkets(_) => CreateMarkets::GROUP, Action::UpdateMarkets(_) => UpdateMarkets::GROUP, - Action::UpdateParams(_) => UpdateParams::GROUP, + Action::UpdateMarketMapParams(_) => UpdateMarketMapParams::GROUP, Action::RemoveMarketAuthorities(_) => RemoveMarketAuthorities::GROUP, Action::RemoveMarkets(_) => RemoveMarkets::GROUP, } diff --git a/crates/astria-core/src/protocol/transaction/v1/action/mod.rs b/crates/astria-core/src/protocol/transaction/v1/action/mod.rs index 9c93c4ca7b..89651ab9b6 100644 --- a/crates/astria-core/src/protocol/transaction/v1/action/mod.rs +++ b/crates/astria-core/src/protocol/transaction/v1/action/mod.rs @@ -62,7 +62,7 @@ pub enum Action { UpsertMarkets(UpsertMarkets), CreateMarkets(CreateMarkets), UpdateMarkets(UpdateMarkets), - UpdateParams(UpdateParams), + UpdateMarketMapParams(UpdateMarketMapParams), RemoveMarketAuthorities(RemoveMarketAuthorities), RemoveMarkets(RemoveMarkets), } @@ -92,7 +92,7 @@ impl Protobuf for Action { Action::UpsertMarkets(act) => Value::UpsertMarkets(act.to_raw()), Action::CreateMarkets(act) => Value::CreateMarkets(act.to_raw()), Action::UpdateMarkets(act) => Value::UpdateMarkets(act.to_raw()), - Action::UpdateParams(act) => Value::UpdateParams(act.to_raw()), + Action::UpdateMarketMapParams(act) => Value::UpdateMarketMapParams(act.to_raw()), Action::RemoveMarketAuthorities(act) => Value::RemoveMarketAuthorities(act.to_raw()), Action::RemoveMarkets(act) => Value::RemoveMarkets(act.to_raw()), }; @@ -177,9 +177,10 @@ impl Protobuf for Action { Value::UpdateMarkets(act) => Self::UpdateMarkets( UpdateMarkets::try_from_raw(act).map_err(Error::update_markets)?, ), - Value::UpdateParams(act) => { - Self::UpdateParams(UpdateParams::try_from_raw(act).map_err(Error::update_params)?) - } + Value::UpdateMarketMapParams(act) => Self::UpdateMarketMapParams( + UpdateMarketMapParams::try_from_raw(act) + .map_err(Error::update_market_map_params)?, + ), Value::RemoveMarketAuthorities(act) => Self::RemoveMarketAuthorities( RemoveMarketAuthorities::try_from_raw(act) .map_err(Error::remove_market_authorities)?, @@ -315,9 +316,9 @@ impl From for Action { } } -impl From for Action { - fn from(value: UpdateParams) -> Self { - Self::UpdateParams(value) +impl From for Action { + fn from(value: UpdateMarketMapParams) -> Self { + Self::UpdateMarketMapParams(value) } } @@ -373,7 +374,7 @@ impl ActionName for Action { Action::UpsertMarkets(_) => "UpsertMarkets", Action::CreateMarkets(_) => "CreateMarkets", Action::UpdateMarkets(_) => "UpdateMarkets", - Action::UpdateParams(_) => "UpdateParams", + Action::UpdateMarketMapParams(_) => "UpdateMarketMapParams", Action::RemoveMarketAuthorities(_) => "RemoveMarketAuthorities", Action::RemoveMarkets(_) => "RemoveMarkets", } @@ -457,8 +458,8 @@ impl Error { Self(ActionErrorKind::UpdateMarkets(inner)) } - fn update_params(inner: UpdateParamsError) -> Self { - Self(ActionErrorKind::UpdateParams(inner)) + fn update_market_map_params(inner: UpdateMarketMapParamsError) -> Self { + Self(ActionErrorKind::UpdateMarketMapParams(inner)) } fn remove_market_authorities(inner: RemoveMarketAuthoritiesError) -> Self { @@ -509,7 +510,7 @@ enum ActionErrorKind { #[error("update markets action was not valid")] UpdateMarkets(#[source] UpdateMarketsError), #[error("update params action was not valid")] - UpdateParams(#[source] UpdateParamsError), + UpdateMarketMapParams(#[source] UpdateMarketMapParamsError), #[error("remove market authorities action was not valid")] RemoveMarketAuthorities(#[source] RemoveMarketAuthoritiesError), #[error("remove markets action was not valid")] @@ -2063,7 +2064,7 @@ pub enum FeeChange { UpsertMarkets(FeeComponents), CreateMarkets(FeeComponents), UpdateMarkets(FeeComponents), - UpdateParams(FeeComponents), + UpdateMarketMapParams(FeeComponents), RemoveMarketAuthorities(FeeComponents), RemoveMarkets(FeeComponents), } @@ -2127,8 +2128,8 @@ impl Protobuf for FeeChange { Self::UpdateMarkets(fee_change) => { raw::fee_change::FeeComponents::UpdateMarkets(fee_change.to_raw()) } - Self::UpdateParams(fee_change) => { - raw::fee_change::FeeComponents::UpdateParams(fee_change.to_raw()) + Self::UpdateMarketMapParams(fee_change) => { + raw::fee_change::FeeComponents::UpdateMarketMapParams(fee_change.to_raw()) } Self::RemoveMarketAuthorities(fee_change) => { raw::fee_change::FeeComponents::RemoveMarketAuthorities(fee_change.to_raw()) @@ -2215,8 +2216,10 @@ impl Protobuf for FeeChange { Some(raw::fee_change::FeeComponents::UpdateMarkets(fee_change)) => Self::UpdateMarkets( FeeComponents::::try_from_raw_ref(fee_change)?, ), - Some(raw::fee_change::FeeComponents::UpdateParams(fee_change)) => { - Self::UpdateParams(FeeComponents::::try_from_raw_ref(fee_change)?) + Some(raw::fee_change::FeeComponents::UpdateMarketMapParams(fee_change)) => { + Self::UpdateMarketMapParams( + FeeComponents::::try_from_raw_ref(fee_change)?, + ) } Some(raw::fee_change::FeeComponents::RemoveMarketAuthorities(fee_change)) => { Self::RemoveMarketAuthorities( @@ -2514,22 +2517,22 @@ pub enum UpdateMarketsErrorKind { /// address. This will execute whether there are params in the state already or not. Must be signed /// by the sequencer network authority sudo address. #[derive(Debug, Clone)] -pub struct UpdateParams { +pub struct UpdateMarketMapParams { /// The new parameters for the `connect/marketmap` module. pub params: Params, } -impl Protobuf for UpdateParams { - type Error = UpdateParamsError; - type Raw = raw::UpdateParams; +impl Protobuf for UpdateMarketMapParams { + type Error = UpdateMarketMapParamsError; + type Raw = raw::UpdateMarketMapParams; fn try_from_raw_ref(raw: &Self::Raw) -> Result { let params = Params::try_from_raw( raw.params .clone() - .ok_or(UpdateParamsError::missing_params())?, + .ok_or(UpdateMarketMapParamsError::missing_params())?, ) - .map_err(UpdateParamsError::invalid_params)?; + .map_err(UpdateMarketMapParamsError::invalid_params)?; Ok(Self { params, }) @@ -2544,22 +2547,22 @@ impl Protobuf for UpdateParams { #[derive(Debug, thiserror::Error)] #[error(transparent)] -pub struct UpdateParamsError(UpdateParamsErrorKind); +pub struct UpdateMarketMapParamsError(UpdateMarketMapParamsErrorKind); -impl UpdateParamsError { +impl UpdateMarketMapParamsError { #[must_use] pub fn missing_params() -> Self { - Self(UpdateParamsErrorKind::MissingParams) + Self(UpdateMarketMapParamsErrorKind::MissingParams) } #[must_use] pub fn invalid_params(err: ParamsError) -> Self { - Self(UpdateParamsErrorKind::InvalidParams(err)) + Self(UpdateMarketMapParamsErrorKind::InvalidParams(err)) } } #[derive(Debug, thiserror::Error)] -pub enum UpdateParamsErrorKind { +pub enum UpdateMarketMapParamsErrorKind { #[error("missing params")] MissingParams, #[error("invalid params")] diff --git a/crates/astria-sequencer-utils/src/genesis_example.rs b/crates/astria-sequencer-utils/src/genesis_example.rs index 8813eaf5cf..7f3dbba1b0 100644 --- a/crates/astria-sequencer-utils/src/genesis_example.rs +++ b/crates/astria-sequencer-utils/src/genesis_example.rs @@ -52,8 +52,8 @@ use astria_core::{ RollupDataSubmission, SudoAddressChange, Transfer, + UpdateMarketMapParams, UpdateMarkets, - UpdateParams, UpsertMarkets, ValidatorUpdate, }, @@ -256,7 +256,9 @@ fn proto_genesis_state() -> astria_core::generated::astria::protocol::genesis::v upsert_markets: Some(FeeComponents::::new(0, 0).to_raw()), create_markets: Some(FeeComponents::::new(0, 0).to_raw()), update_markets: Some(FeeComponents::::new(0, 0).to_raw()), - update_params: Some(FeeComponents::::new(0, 0).to_raw()), + update_market_map_params: Some( + FeeComponents::::new(0, 0).to_raw(), + ), remove_market_authorities: Some( FeeComponents::::new(0, 0).to_raw(), ), diff --git a/crates/astria-sequencer/src/action_handler/impls/create_markets.rs b/crates/astria-sequencer/src/action_handler/impls/create_markets.rs index a25c41f0c7..7691302ca5 100644 --- a/crates/astria-sequencer/src/action_handler/impls/create_markets.rs +++ b/crates/astria-sequencer/src/action_handler/impls/create_markets.rs @@ -5,6 +5,7 @@ use astria_core::{ use astria_eyre::eyre::{ self, bail, + ensure, Context as _, OptionExt as _, }; @@ -44,9 +45,10 @@ impl ActionHandler for CreateMarkets { .await? .ok_or_eyre("market map params not found in state")? .market_authorities; - if !market_authorities.contains(&from) { - bail!("address {from} is not a market authority"); - } + ensure!( + market_authorities.contains(&from), + "address {from} is not a market authority" + ); // create markets, erroring if any already exist let mut market_map = state @@ -100,7 +102,7 @@ mod tests { astria_address, ASTRIA_PREFIX, }, - test_utils::example_ticker, + test_utils::example_ticker_with_metadata, transaction::{ StateWriteExt as _, TransactionContext, @@ -129,7 +131,7 @@ mod tests { position_in_transaction: 0, }); - let ticker = example_ticker(String::new()); + let ticker = example_ticker_with_metadata(String::new()); let market = Market { ticker: ticker.clone(), provider_configs: vec![], diff --git a/crates/astria-sequencer/src/action_handler/impls/fee_change.rs b/crates/astria-sequencer/src/action_handler/impls/fee_change.rs index 7223a5632b..39a42537a4 100644 --- a/crates/astria-sequencer/src/action_handler/impls/fee_change.rs +++ b/crates/astria-sequencer/src/action_handler/impls/fee_change.rs @@ -86,7 +86,7 @@ impl ActionHandler for FeeChange { Self::UpdateMarkets(fees) => state .put_fees(*fees) .wrap_err("failed to put update markets fees"), - Self::UpdateParams(fees) => state + Self::UpdateMarketMapParams(fees) => state .put_fees(*fees) .wrap_err("failed to put update params fees"), Self::RemoveMarketAuthorities(fees) => state diff --git a/crates/astria-sequencer/src/action_handler/impls/mod.rs b/crates/astria-sequencer/src/action_handler/impls/mod.rs index 054d959e5b..d9c89581f0 100644 --- a/crates/astria-sequencer/src/action_handler/impls/mod.rs +++ b/crates/astria-sequencer/src/action_handler/impls/mod.rs @@ -16,7 +16,7 @@ pub(crate) mod sudo_address_change; pub(crate) mod test_utils; pub(crate) mod transaction; pub(crate) mod transfer; +pub(crate) mod update_market_map_params; pub(crate) mod update_markets; -pub(crate) mod update_params; pub(crate) mod upsert_markets; pub(crate) mod validator_update; diff --git a/crates/astria-sequencer/src/action_handler/impls/remove_markets.rs b/crates/astria-sequencer/src/action_handler/impls/remove_markets.rs index c34b9cece1..71009e425c 100644 --- a/crates/astria-sequencer/src/action_handler/impls/remove_markets.rs +++ b/crates/astria-sequencer/src/action_handler/impls/remove_markets.rs @@ -4,7 +4,7 @@ use astria_core::{ }; use astria_eyre::eyre::{ self, - bail, + ensure, Context as _, OptionExt as _, }; @@ -44,9 +44,10 @@ impl ActionHandler for RemoveMarkets { .await? .ok_or_eyre("market map params not found in state")? .market_authorities; - if !market_authorities.contains(&from) { - bail!("address {from} is not a market authority"); - } + ensure!( + market_authorities.contains(&from), + "address {from} is not a market authority" + ); // remove markets, skipping any which do not exist let mut market_map = state @@ -96,8 +97,8 @@ mod tests { ASTRIA_PREFIX, }, test_utils::{ - example_ticker, example_ticker_from_currency_pair, + example_ticker_with_metadata, }, transaction::{ StateWriteExt as _, @@ -127,7 +128,7 @@ mod tests { }; state.put_params(params).unwrap(); - let ticker = example_ticker(String::new()); + let ticker = example_ticker_with_metadata(String::new()); let mut markets = IndexMap::new(); markets.insert( @@ -230,7 +231,7 @@ mod tests { }; state.put_params(params).unwrap(); - let ticker = example_ticker(String::new()); + let ticker = example_ticker_with_metadata(String::new()); let market = Market { ticker: ticker.clone(), provider_configs: vec![], diff --git a/crates/astria-sequencer/src/action_handler/impls/transaction.rs b/crates/astria-sequencer/src/action_handler/impls/transaction.rs index c2e595b204..66b4a1f191 100644 --- a/crates/astria-sequencer/src/action_handler/impls/transaction.rs +++ b/crates/astria-sequencer/src/action_handler/impls/transaction.rs @@ -153,10 +153,10 @@ impl ActionHandler for Transaction { .check_stateless() .await .wrap_err("stateless check failed for UpdateMarkets action")?, - Action::UpdateParams(act) => act + Action::UpdateMarketMapParams(act) => act .check_stateless() .await - .wrap_err("stateless check failed for UpdateParams action")?, + .wrap_err("stateless check failed for UpdateMarketMapParams action")?, Action::RemoveMarketAuthorities(act) => act .check_stateless() .await @@ -300,7 +300,7 @@ impl ActionHandler for Transaction { Action::UpdateMarkets(act) => check_execute_and_pay_fees(act, &mut state) .await .wrap_err("failed executing update markets")?, - Action::UpdateParams(act) => check_execute_and_pay_fees(act, &mut state) + Action::UpdateMarketMapParams(act) => check_execute_and_pay_fees(act, &mut state) .await .wrap_err("failed executing update params")?, Action::RemoveMarketAuthorities(act) => check_execute_and_pay_fees(act, &mut state) diff --git a/crates/astria-sequencer/src/action_handler/impls/update_params.rs b/crates/astria-sequencer/src/action_handler/impls/update_market_map_params.rs similarity index 90% rename from crates/astria-sequencer/src/action_handler/impls/update_params.rs rename to crates/astria-sequencer/src/action_handler/impls/update_market_map_params.rs index 629cc9f045..c10da16e3b 100644 --- a/crates/astria-sequencer/src/action_handler/impls/update_params.rs +++ b/crates/astria-sequencer/src/action_handler/impls/update_market_map_params.rs @@ -1,4 +1,4 @@ -use astria_core::protocol::transaction::v1::action::UpdateParams; +use astria_core::protocol::transaction::v1::action::UpdateMarketMapParams; use astria_eyre::eyre::{ self, ensure, @@ -13,7 +13,7 @@ use crate::{ }; #[async_trait::async_trait] -impl ActionHandler for UpdateParams { +impl ActionHandler for UpdateMarketMapParams { async fn check_stateless(&self) -> eyre::Result<()> { Ok(()) } @@ -56,7 +56,7 @@ mod tests { }; #[tokio::test] - async fn update_params_executes_as_expected() { + async fn update_market_map_params_executes_as_expected() { let storage = cnidarium::TempStorage::new().await.unwrap(); let snapshot = storage.latest_snapshot(); let mut state = cnidarium::StateDelta::new(snapshot); @@ -73,7 +73,7 @@ mod tests { assert!(state.get_params().await.unwrap().is_none()); - let action = UpdateParams { + let action = UpdateMarketMapParams { params: Params { market_authorities: vec![authority_address], admin: authority_address, @@ -89,7 +89,7 @@ mod tests { } #[tokio::test] - async fn update_params_fails_if_signer_is_invalid() { + async fn update_market_map_params_fails_if_signer_is_invalid() { let storage = cnidarium::TempStorage::new().await.unwrap(); let snapshot = storage.latest_snapshot(); let mut state = cnidarium::StateDelta::new(snapshot); @@ -105,7 +105,7 @@ mod tests { position_in_transaction: 0, }); - let action = UpdateParams { + let action = UpdateMarketMapParams { params: Params { market_authorities: vec![invalid_address], admin: invalid_address, diff --git a/crates/astria-sequencer/src/action_handler/impls/update_markets.rs b/crates/astria-sequencer/src/action_handler/impls/update_markets.rs index 8d7016d0c4..49716eb581 100644 --- a/crates/astria-sequencer/src/action_handler/impls/update_markets.rs +++ b/crates/astria-sequencer/src/action_handler/impls/update_markets.rs @@ -1,7 +1,7 @@ use astria_core::protocol::transaction::v1::action::UpdateMarkets; use astria_eyre::eyre::{ self, - bail, + ensure, eyre, Context as _, OptionExt as _, @@ -41,9 +41,10 @@ impl ActionHandler for UpdateMarkets { .await? .ok_or_eyre("market map params not found in state")? .market_authorities; - if !market_authorities.contains(&from) { - bail!("address {from} is not a market authority"); - } + ensure!( + market_authorities.contains(&from), + "address {from} is not a market authority" + ); // update existing markets, erroring if any do not exist in the current map let mut market_map = state @@ -98,7 +99,7 @@ mod tests { astria_address, ASTRIA_PREFIX, }, - test_utils::example_ticker, + test_utils::example_ticker_with_metadata, transaction::{ StateWriteExt as _, TransactionContext, @@ -127,7 +128,7 @@ mod tests { }; state.put_params(params).unwrap(); - let ticker_1 = example_ticker("ticker_1".to_string()); + let ticker_1 = example_ticker_with_metadata("ticker_1".to_string()); let market_1 = Market { ticker: ticker_1.clone(), provider_configs: vec![], @@ -149,7 +150,7 @@ mod tests { market_1, ); - let ticker = example_ticker("ticker".to_string()); + let ticker = example_ticker_with_metadata("ticker".to_string()); let market = Market { ticker: ticker.clone(), provider_configs: vec![], @@ -199,7 +200,7 @@ mod tests { }) .unwrap(); - let ticker = example_ticker("ticker".to_string()); + let ticker = example_ticker_with_metadata("ticker".to_string()); let market = Market { ticker: ticker.clone(), provider_configs: vec![], diff --git a/crates/astria-sequencer/src/action_handler/impls/upsert_markets.rs b/crates/astria-sequencer/src/action_handler/impls/upsert_markets.rs index b2e157b09f..b9c0c5452a 100644 --- a/crates/astria-sequencer/src/action_handler/impls/upsert_markets.rs +++ b/crates/astria-sequencer/src/action_handler/impls/upsert_markets.rs @@ -4,7 +4,7 @@ use astria_core::{ }; use astria_eyre::eyre::{ self, - bail, + ensure, Context as _, OptionExt as _, }; @@ -44,9 +44,10 @@ impl ActionHandler for UpsertMarkets { .await? .ok_or_eyre("market map params not found in state")? .market_authorities; - if !market_authorities.contains(&from) { - bail!("address {from} is not a market authority"); - } + ensure!( + market_authorities.contains(&from), + "address {from} is not a market authority" + ); // upsert markets, updating any that already exist and creating any that do not let mut market_map = state @@ -103,7 +104,7 @@ mod tests { astria_address, ASTRIA_PREFIX, }, - test_utils::example_ticker, + test_utils::example_ticker_with_metadata, transaction::{ StateWriteExt as _, TransactionContext, @@ -132,7 +133,7 @@ mod tests { }; state.put_params(params).unwrap(); - let ticker = example_ticker(String::new()); + let ticker = example_ticker_with_metadata(String::new()); let market = Market { ticker: ticker.clone(), provider_configs: vec![], @@ -176,7 +177,7 @@ mod tests { position_in_transaction: 0, }); - let ticker_1 = example_ticker("ticker_1".to_string()); + let ticker_1 = example_ticker_with_metadata("ticker_1".to_string()); let market_1 = Market { ticker: ticker_1.clone(), provider_configs: vec![], @@ -198,7 +199,7 @@ mod tests { market_1, ); - let ticker_2 = example_ticker("ticker_2".to_string()); + let ticker_2 = example_ticker_with_metadata("ticker_2".to_string()); let market_2 = Market { ticker: ticker_2.clone(), provider_configs: vec![], diff --git a/crates/astria-sequencer/src/app/benchmark_and_test_utils.rs b/crates/astria-sequencer/src/app/benchmark_and_test_utils.rs index 519c04027c..f895bbe19a 100644 --- a/crates/astria-sequencer/src/app/benchmark_and_test_utils.rs +++ b/crates/astria-sequencer/src/app/benchmark_and_test_utils.rs @@ -33,8 +33,8 @@ use astria_core::{ RollupDataSubmission, SudoAddressChange, Transfer, + UpdateMarketMapParams, UpdateMarkets, - UpdateParams, UpsertMarkets, ValidatorUpdate, }, @@ -100,7 +100,7 @@ pub(crate) fn default_fees() -> astria_core::protocol::genesis::v1::GenesisFees upsert_markets: Some(FeeComponents::::new(0, 0)), create_markets: Some(FeeComponents::::new(0, 0)), update_markets: Some(FeeComponents::::new(0, 0)), - update_params: Some(FeeComponents::::new(0, 0)), + update_market_map_params: Some(FeeComponents::::new(0, 0)), remove_market_authorities: Some(FeeComponents::::new(0, 0)), remove_markets: Some(FeeComponents::::new(0, 0)), } diff --git a/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_at_genesis.snap b/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_at_genesis.snap index 6b2fa5a633..da9baed897 100644 --- a/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_at_genesis.snap +++ b/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_at_genesis.snap @@ -3,36 +3,36 @@ source: crates/astria-sequencer/src/app/tests_breaking_changes.rs expression: app.app_hash.as_bytes() --- [ - 74, - 173, - 202, - 26, - 80, + 45, + 176, + 182, + 39, + 232, + 244, + 147, + 225, + 213, + 155, + 56, + 203, 172, - 76, - 78, - 72, - 44, - 243, - 51, - 32, - 207, - 88, - 78, - 145, - 19, - 219, - 238, - 222, - 150, - 170, - 61, - 187, - 166, - 240, - 247, - 123, + 168, + 66, 74, - 48, - 2 + 24, + 167, + 236, + 91, + 73, + 179, + 230, + 49, + 100, + 71, + 201, + 224, + 69, + 11, + 195, + 202 ] diff --git a/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_execute_every_action.snap b/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_execute_every_action.snap index dbb73b9059..e678444d35 100644 --- a/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_execute_every_action.snap +++ b/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_execute_every_action.snap @@ -3,36 +3,36 @@ source: crates/astria-sequencer/src/app/tests_breaking_changes.rs expression: app.app_hash.as_bytes() --- [ - 24, - 125, - 203, - 19, - 36, - 212, - 106, - 216, - 119, - 208, - 90, - 228, - 196, + 135, + 124, + 66, + 33, + 47, + 219, + 249, + 100, 72, - 241, - 146, - 86, - 142, - 214, - 118, - 247, - 96, + 182, + 201, + 179, + 50, + 188, + 182, + 194, + 181, 199, - 206, - 14, - 68, - 224, - 130, - 130, - 73, - 237, - 42 + 16, + 117, + 247, + 65, + 38, + 38, + 205, + 183, + 71, + 163, + 158, + 177, + 255, + 136 ] diff --git a/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_finalize_block.snap b/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_finalize_block.snap index aa4cd999e3..176da36fab 100644 --- a/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_finalize_block.snap +++ b/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_finalize_block.snap @@ -3,36 +3,36 @@ source: crates/astria-sequencer/src/app/tests_breaking_changes.rs expression: app.app_hash.as_bytes() --- [ - 218, - 188, - 129, - 21, - 106, - 40, - 73, - 115, - 162, - 158, - 86, - 10, - 128, - 231, - 163, - 214, - 201, + 140, + 239, + 168, + 255, + 54, + 206, + 191, 68, - 162, - 136, - 154, + 137, + 65, + 112, + 105, + 0, + 7, + 19, + 142, + 134, + 123, + 239, + 152, + 217, + 133, + 238, + 142, + 93, + 38, + 120, + 244, 216, - 227, - 220, - 176, - 24, - 100, - 206, - 14, - 2, - 95, - 223 + 237, + 196, + 224 ] diff --git a/crates/astria-sequencer/src/app/tests_breaking_changes.rs b/crates/astria-sequencer/src/app/tests_breaking_changes.rs index b700153f4d..0b68790d55 100644 --- a/crates/astria-sequencer/src/app/tests_breaking_changes.rs +++ b/crates/astria-sequencer/src/app/tests_breaking_changes.rs @@ -37,8 +37,8 @@ use astria_core::{ RemoveMarkets, RollupDataSubmission, Transfer, + UpdateMarketMapParams, UpdateMarkets, - UpdateParams, UpsertMarkets, ValidatorUpdate, }, @@ -312,7 +312,7 @@ async fn app_execute_transaction_with_every_action_snapshot() { FeeAssetChange::Addition("test-0".parse().unwrap()).into(), FeeAssetChange::Addition("test-1".parse().unwrap()).into(), FeeAssetChange::Removal("test-0".parse().unwrap()).into(), - UpdateParams { + UpdateMarketMapParams { params: Params { market_authorities: vec![bob_address, carol_address], admin: bob_address, diff --git a/crates/astria-sequencer/src/app/tests_execute_transaction.rs b/crates/astria-sequencer/src/app/tests_execute_transaction.rs index e058f14b99..c4ed2e2018 100644 --- a/crates/astria-sequencer/src/app/tests_execute_transaction.rs +++ b/crates/astria-sequencer/src/app/tests_execute_transaction.rs @@ -27,8 +27,8 @@ use astria_core::{ RollupDataSubmission, SudoAddressChange, Transfer, + UpdateMarketMapParams, UpdateMarkets, - UpdateParams, UpsertMarkets, ValidatorUpdate, }, @@ -91,8 +91,8 @@ use crate::{ ibc::StateReadExt as _, test_utils::{ calculate_rollup_data_submission_fee_from_state, - example_ticker, example_ticker_from_currency_pair, + example_ticker_with_metadata, }, utils::create_deposit_event, }; @@ -1357,7 +1357,7 @@ async fn upsert_markets_executes_as_expected() { let alice_signing_key = get_alice_signing_key(); - let ticker_1 = example_ticker("create_market_1".to_string()); + let ticker_1 = example_ticker_with_metadata("create_market_1".to_string()); let market_1 = Market { ticker: ticker_1.clone(), provider_configs: vec![], @@ -1373,7 +1373,7 @@ async fn upsert_markets_executes_as_expected() { app.apply(state_tx); // market_2 should replace market_1, since they share the same currency pair - let ticker_2 = example_ticker("update market 1 to market 2".to_string()); + let ticker_2 = example_ticker_with_metadata("update market 1 to market 2".to_string()); let market_2 = Market { ticker: ticker_2.clone(), provider_configs: vec![], @@ -1421,7 +1421,7 @@ async fn create_markets_executes_as_expected() { let alice_signing_key = get_alice_signing_key(); - let ticker_1 = example_ticker("create market 1".to_string()); + let ticker_1 = example_ticker_with_metadata("create market 1".to_string()); let market_1 = Market { ticker: ticker_1.clone(), provider_configs: vec![], @@ -1465,7 +1465,7 @@ async fn update_markets_executes_as_expected() { let alice_signing_key = get_alice_signing_key(); - let ticker_1 = example_ticker("create market 1".to_string()); + let ticker_1 = example_ticker_with_metadata("create market 1".to_string()); let market_1 = Market { ticker: ticker_1.clone(), provider_configs: vec![], @@ -1491,7 +1491,7 @@ async fn update_markets_executes_as_expected() { app.apply(state_tx); // market_3 should replace market_1, since they share the same currency pair - let ticker_3 = example_ticker("update market 1 to market 2".to_string()); + let ticker_3 = example_ticker_with_metadata("update market 1 to market 2".to_string()); let market_3 = Market { ticker: ticker_3.clone(), provider_configs: vec![], @@ -1533,7 +1533,7 @@ async fn remove_markets_executes_as_expected() { let alice_signing_key = get_alice_signing_key(); - let ticker_1 = example_ticker("create market 1".to_string()); + let ticker_1 = example_ticker_with_metadata("create market 1".to_string()); let market_1 = Market { ticker: ticker_1.clone(), provider_configs: vec![], @@ -1621,7 +1621,7 @@ async fn remove_market_authorities_executes_as_expected() { } #[tokio::test] -async fn update_params_executes_as_expected() { +async fn update_market_map_params_executes_as_expected() { let mut app = initialize_app(None, vec![]).await; let mut state_tx = StateDelta::new(app.state.clone()); @@ -1642,12 +1642,12 @@ async fn update_params_executes_as_expected() { market_authorities: vec![bob_address, carol_address], admin: alice_address, }; - let update_params_action = UpdateParams { + let update_market_map_params_action = UpdateMarketMapParams { params: params_2.clone(), }; let tx = TransactionBody::builder() - .actions(vec![update_params_action.into()]) + .actions(vec![update_market_map_params_action.into()]) .chain_id("test") .try_build() .unwrap(); diff --git a/crates/astria-sequencer/src/fees/component.rs b/crates/astria-sequencer/src/fees/component.rs index f77938f08e..40890ffc1e 100644 --- a/crates/astria-sequencer/src/fees/component.rs +++ b/crates/astria-sequencer/src/fees/component.rs @@ -165,10 +165,10 @@ impl Component for FeesComponent { .wrap_err("failed to store remove market authorities fee components")?; } - let update_params_fees = app_state.fees().update_params; - if let Some(update_params_fees) = update_params_fees { + let update_market_map_params_fees = app_state.fees().update_market_map_params; + if let Some(update_market_map_params_fees) = update_market_map_params_fees { state - .put_fees(update_params_fees) + .put_fees(update_market_map_params_fees) .wrap_err("failed to store update params fee components")?; } diff --git a/crates/astria-sequencer/src/fees/mod.rs b/crates/astria-sequencer/src/fees/mod.rs index 4d6eb7357d..65ca176b50 100644 --- a/crates/astria-sequencer/src/fees/mod.rs +++ b/crates/astria-sequencer/src/fees/mod.rs @@ -18,8 +18,8 @@ use astria_core::{ RollupDataSubmission, SudoAddressChange, Transfer, + UpdateMarketMapParams, UpdateMarkets, - UpdateParams, UpsertMarkets, ValidatorUpdate, }, @@ -530,7 +530,7 @@ impl FeeHandler for UpdateMarkets { } } -impl FeeHandler for UpdateParams { +impl FeeHandler for UpdateMarketMapParams { fn name() -> &'static str { ::Raw::NAME } @@ -540,7 +540,7 @@ impl FeeHandler for UpdateParams { } fn snake_case_name() -> &'static str { - "update_params" + "update_market_map_params" } fn variable_component(&self) -> u128 { diff --git a/crates/astria-sequencer/src/fees/query.rs b/crates/astria-sequencer/src/fees/query.rs index 8ab08d74ff..a22da27645 100644 --- a/crates/astria-sequencer/src/fees/query.rs +++ b/crates/astria-sequencer/src/fees/query.rs @@ -30,8 +30,8 @@ use astria_core::{ RollupDataSubmission, SudoAddressChange, Transfer, + UpdateMarketMapParams, UpdateMarkets, - UpdateParams, UpsertMarkets, ValidatorUpdate, }, @@ -308,7 +308,8 @@ pub(crate) async fn get_fees_for_transaction( let upsert_markets_fees: OnceCell>> = OnceCell::new(); let create_markets_fees: OnceCell>> = OnceCell::new(); let update_markets_fees: OnceCell>> = OnceCell::new(); - let update_params_fees: OnceCell>> = OnceCell::new(); + let update_market_map_params_fees: OnceCell>> = + OnceCell::new(); let remove_market_authorities_fees: OnceCell>> = OnceCell::new(); let remove_markets_fees: OnceCell>> = OnceCell::new(); @@ -384,8 +385,8 @@ pub(crate) async fn get_fees_for_transaction( let fees = get_or_init_fees(state, &update_markets_fees).await?; calculate_and_add_fees(act, &mut fees_by_asset, fees); } - Action::UpdateParams(act) => { - let fees = get_or_init_fees(state, &update_params_fees).await?; + Action::UpdateMarketMapParams(act) => { + let fees = get_or_init_fees(state, &update_market_map_params_fees).await?; calculate_and_add_fees(act, &mut fees_by_asset, fees); } Action::RemoveMarketAuthorities(act) => { diff --git a/crates/astria-sequencer/src/fees/storage/values.rs b/crates/astria-sequencer/src/fees/storage/values.rs index a844ea5996..0f32eb85a3 100644 --- a/crates/astria-sequencer/src/fees/storage/values.rs +++ b/crates/astria-sequencer/src/fees/storage/values.rs @@ -16,8 +16,8 @@ use astria_core::protocol::{ RollupDataSubmission, SudoAddressChange, Transfer, + UpdateMarketMapParams, UpdateMarkets, - UpdateParams, UpsertMarkets, ValidatorUpdate, }, @@ -55,7 +55,7 @@ enum ValueImpl { UpsertMarketsFees(FeeComponents), CreateMarketsFees(FeeComponents), UpdateMarketsFees(FeeComponents), - UpdateParamsFees(FeeComponents), + UpdateMarketMapParamsFees(FeeComponents), RemoveMarketAuthoritiesFees(FeeComponents), RemoveMarketsFees(FeeComponents), } @@ -124,7 +124,7 @@ impl_from_for_fee_storage!( DomainFeeComponents => UpsertMarketsFees, DomainFeeComponents => CreateMarketsFees, DomainFeeComponents => UpdateMarketsFees, - DomainFeeComponents => UpdateParamsFees, + DomainFeeComponents => UpdateMarketMapParamsFees, DomainFeeComponents => RemoveMarketAuthoritiesFees, DomainFeeComponents => RemoveMarketsFees, ); diff --git a/crates/astria-sequencer/src/test_utils.rs b/crates/astria-sequencer/src/test_utils.rs index 127c6b2639..9e80a7683d 100644 --- a/crates/astria-sequencer/src/test_utils.rs +++ b/crates/astria-sequencer/src/test_utils.rs @@ -58,7 +58,7 @@ pub(crate) async fn calculate_rollup_data_submission_fee_from_state< .expect("fee addition should not overflow") } -pub(crate) fn example_ticker(metadata: String) -> Ticker { +pub(crate) fn example_ticker_with_metadata(metadata: String) -> Ticker { Ticker { currency_pair: CurrencyPair::from_parts( Base::from_str("BTC").unwrap(), diff --git a/crates/astria-sequencer/src/transaction/checks.rs b/crates/astria-sequencer/src/transaction/checks.rs index 63f87190f9..d887313d37 100644 --- a/crates/astria-sequencer/src/transaction/checks.rs +++ b/crates/astria-sequencer/src/transaction/checks.rs @@ -114,7 +114,7 @@ pub(crate) async fn get_total_transaction_cost( | Action::Ibc(_) | Action::IbcRelayerChange(_) | Action::FeeAssetChange(_) - | Action::UpdateParams(_) + | Action::UpdateMarketMapParams(_) | Action::UpsertMarkets(_) | Action::CreateMarkets(_) | Action::UpdateMarkets(_) diff --git a/proto/protocolapis/astria/protocol/fees/v1/types.proto b/proto/protocolapis/astria/protocol/fees/v1/types.proto index 7565390106..63e85f37e1 100644 --- a/proto/protocolapis/astria/protocol/fees/v1/types.proto +++ b/proto/protocolapis/astria/protocol/fees/v1/types.proto @@ -94,7 +94,7 @@ message UpdateMarketsFeeComponents { astria.primitive.v1.Uint128 multiplier = 2; } -message UpdateParamsFeeComponents { +message UpdateMarketMapParamsFeeComponents { astria.primitive.v1.Uint128 base = 1; astria.primitive.v1.Uint128 multiplier = 2; } diff --git a/proto/protocolapis/astria/protocol/genesis/v1/types.proto b/proto/protocolapis/astria/protocol/genesis/v1/types.proto index 2783611e2b..fd168ab026 100644 --- a/proto/protocolapis/astria/protocol/genesis/v1/types.proto +++ b/proto/protocolapis/astria/protocol/genesis/v1/types.proto @@ -62,7 +62,7 @@ message GenesisFees { astria.protocol.fees.v1.UpsertMarketsFeeComponents upsert_markets = 15; astria.protocol.fees.v1.CreateMarketsFeeComponents create_markets = 16; astria.protocol.fees.v1.UpdateMarketsFeeComponents update_markets = 17; - astria.protocol.fees.v1.UpdateParamsFeeComponents update_params = 18; + astria.protocol.fees.v1.UpdateMarketMapParamsFeeComponents update_market_map_params = 18; astria.protocol.fees.v1.RemoveMarketAuthoritiesFeeComponents remove_market_authorities = 19; astria.protocol.fees.v1.RemoveMarketsFeeComponents remove_markets = 20; } diff --git a/proto/protocolapis/astria/protocol/transaction/v1/action.proto b/proto/protocolapis/astria/protocol/transaction/v1/action.proto index 8d05d13913..ef04aff27c 100644 --- a/proto/protocolapis/astria/protocol/transaction/v1/action.proto +++ b/proto/protocolapis/astria/protocol/transaction/v1/action.proto @@ -37,7 +37,7 @@ message Action { UpsertMarkets upsert_markets = 71; CreateMarkets create_markets = 72; UpdateMarkets update_markets = 73; - UpdateParams update_params = 74; + UpdateMarketMapParams update_market_map_params = 74; RemoveMarketAuthorities remove_market_authorities = 75; RemoveMarkets remove_markets = 76; } @@ -241,7 +241,7 @@ message FeeChange { astria.protocol.fees.v1.UpsertMarketsFeeComponents upsert_markets = 15; astria.protocol.fees.v1.CreateMarketsFeeComponents create_markets = 16; astria.protocol.fees.v1.UpdateMarketsFeeComponents update_markets = 17; - astria.protocol.fees.v1.UpdateParamsFeeComponents update_params = 18; + astria.protocol.fees.v1.UpdateMarketMapParamsFeeComponents update_market_map_params = 18; astria.protocol.fees.v1.RemoveMarketAuthoritiesFeeComponents remove_market_authorities = 19; astria.protocol.fees.v1.RemoveMarketsFeeComponents remove_markets = 20; } @@ -270,7 +270,7 @@ message UpdateMarkets { } // Updates the market map parameters. -message UpdateParams { +message UpdateMarketMapParams { // Params defines the new parameters for the x/marketmap module. connect.marketmap.v2.Params params = 1; } From 4bd1f7485b80b82ad105688d9b071d5816b382a2 Mon Sep 17 00:00:00 2001 From: ethanoroshiba Date: Wed, 8 Jan 2025 14:48:38 -0600 Subject: [PATCH 5/8] condolidate create, update, and remove market actions into 'ChangeMarkets'. Removed upsert markets --- .../src/generated/astria.protocol.fees.v1.rs | 51 +- .../astria.protocol.fees.v1.serde.rs | 340 +------------ .../generated/astria.protocol.genesis.v1.rs | 16 +- .../astria.protocol.genesis.v1.serde.rs | 80 +-- .../astria.protocol.transaction.v1.rs | 93 ++-- .../astria.protocol.transaction.v1.serde.rs | 457 +++++------------- crates/astria-core/src/protocol/fees/v1.rs | 10 +- crates/astria-core/src/protocol/genesis/v1.rs | 59 +-- .../transaction/v1/action/group/mod.rs | 15 +- .../src/protocol/transaction/v1/action/mod.rs | 367 ++++---------- .../src/genesis_example.rs | 10 +- .../{update_markets.rs => change_markets.rs} | 341 +++++++++---- .../action_handler/impls/create_markets.rs | 210 -------- .../src/action_handler/impls/fee_change.rs | 32 +- .../src/action_handler/impls/mod.rs | 5 +- .../action_handler/impls/remove_markets.rs | 265 ---------- .../src/action_handler/impls/transaction.rs | 29 +- .../action_handler/impls/upsert_markets.rs | 279 ----------- .../src/app/benchmark_and_test_utils.rs | 10 +- ...breaking_changes__app_hash_at_genesis.snap | 60 +-- ...hanges__app_hash_execute_every_action.snap | 60 +-- ...king_changes__app_hash_finalize_block.snap | 62 +-- .../src/app/tests_breaking_changes.rs | 71 +-- .../src/app/tests_execute_transaction.rs | 85 +--- crates/astria-sequencer/src/fees/component.rs | 29 +- crates/astria-sequencer/src/fees/mod.rs | 75 +-- crates/astria-sequencer/src/fees/query.rs | 26 +- .../src/fees/storage/values.rs | 15 +- .../src/transaction/checks.rs | 5 +- .../astria/protocol/fees/v1/types.proto | 17 +- .../astria/protocol/genesis/v1/types.proto | 5 +- .../protocol/transaction/v1/action.proto | 48 +- 32 files changed, 694 insertions(+), 2533 deletions(-) rename crates/astria-sequencer/src/action_handler/impls/{update_markets.rs => change_markets.rs} (53%) delete mode 100644 crates/astria-sequencer/src/action_handler/impls/create_markets.rs delete mode 100644 crates/astria-sequencer/src/action_handler/impls/remove_markets.rs delete mode 100644 crates/astria-sequencer/src/action_handler/impls/upsert_markets.rs diff --git a/crates/astria-core/src/generated/astria.protocol.fees.v1.rs b/crates/astria-core/src/generated/astria.protocol.fees.v1.rs index d948cbaa59..83c505abbe 100644 --- a/crates/astria-core/src/generated/astria.protocol.fees.v1.rs +++ b/crates/astria-core/src/generated/astria.protocol.fees.v1.rs @@ -225,44 +225,14 @@ impl ::prost::Name for IbcSudoChangeFeeComponents { } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] -pub struct UpsertMarketsFeeComponents { +pub struct ChangeMarketsFeeComponents { #[prost(message, optional, tag = "1")] pub base: ::core::option::Option, #[prost(message, optional, tag = "2")] pub multiplier: ::core::option::Option, } -impl ::prost::Name for UpsertMarketsFeeComponents { - const NAME: &'static str = "UpsertMarketsFeeComponents"; - const PACKAGE: &'static str = "astria.protocol.fees.v1"; - fn full_name() -> ::prost::alloc::string::String { - ::prost::alloc::format!("astria.protocol.fees.v1.{}", Self::NAME) - } -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct CreateMarketsFeeComponents { - #[prost(message, optional, tag = "1")] - pub base: ::core::option::Option, - #[prost(message, optional, tag = "2")] - pub multiplier: ::core::option::Option, -} -impl ::prost::Name for CreateMarketsFeeComponents { - const NAME: &'static str = "CreateMarketsFeeComponents"; - const PACKAGE: &'static str = "astria.protocol.fees.v1"; - fn full_name() -> ::prost::alloc::string::String { - ::prost::alloc::format!("astria.protocol.fees.v1.{}", Self::NAME) - } -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct UpdateMarketsFeeComponents { - #[prost(message, optional, tag = "1")] - pub base: ::core::option::Option, - #[prost(message, optional, tag = "2")] - pub multiplier: ::core::option::Option, -} -impl ::prost::Name for UpdateMarketsFeeComponents { - const NAME: &'static str = "UpdateMarketsFeeComponents"; +impl ::prost::Name for ChangeMarketsFeeComponents { + const NAME: &'static str = "ChangeMarketsFeeComponents"; const PACKAGE: &'static str = "astria.protocol.fees.v1"; fn full_name() -> ::prost::alloc::string::String { ::prost::alloc::format!("astria.protocol.fees.v1.{}", Self::NAME) @@ -298,21 +268,6 @@ impl ::prost::Name for RemoveMarketAuthoritiesFeeComponents { ::prost::alloc::format!("astria.protocol.fees.v1.{}", Self::NAME) } } -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct RemoveMarketsFeeComponents { - #[prost(message, optional, tag = "1")] - pub base: ::core::option::Option, - #[prost(message, optional, tag = "2")] - pub multiplier: ::core::option::Option, -} -impl ::prost::Name for RemoveMarketsFeeComponents { - const NAME: &'static str = "RemoveMarketsFeeComponents"; - const PACKAGE: &'static str = "astria.protocol.fees.v1"; - fn full_name() -> ::prost::alloc::string::String { - ::prost::alloc::format!("astria.protocol.fees.v1.{}", Self::NAME) - } -} /// Response to a transaction fee ABCI query. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] diff --git a/crates/astria-core/src/generated/astria.protocol.fees.v1.serde.rs b/crates/astria-core/src/generated/astria.protocol.fees.v1.serde.rs index 01260c0aaa..93cef61a19 100644 --- a/crates/astria-core/src/generated/astria.protocol.fees.v1.serde.rs +++ b/crates/astria-core/src/generated/astria.protocol.fees.v1.serde.rs @@ -322,7 +322,7 @@ impl<'de> serde::Deserialize<'de> for BridgeUnlockFeeComponents { deserializer.deserialize_struct("astria.protocol.fees.v1.BridgeUnlockFeeComponents", FIELDS, GeneratedVisitor) } } -impl serde::Serialize for CreateMarketsFeeComponents { +impl serde::Serialize for ChangeMarketsFeeComponents { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result where @@ -336,7 +336,7 @@ impl serde::Serialize for CreateMarketsFeeComponents { if self.multiplier.is_some() { len += 1; } - let mut struct_ser = serializer.serialize_struct("astria.protocol.fees.v1.CreateMarketsFeeComponents", len)?; + let mut struct_ser = serializer.serialize_struct("astria.protocol.fees.v1.ChangeMarketsFeeComponents", len)?; if let Some(v) = self.base.as_ref() { struct_ser.serialize_field("base", v)?; } @@ -346,7 +346,7 @@ impl serde::Serialize for CreateMarketsFeeComponents { struct_ser.end() } } -impl<'de> serde::Deserialize<'de> for CreateMarketsFeeComponents { +impl<'de> serde::Deserialize<'de> for ChangeMarketsFeeComponents { #[allow(deprecated)] fn deserialize(deserializer: D) -> std::result::Result where @@ -393,13 +393,13 @@ impl<'de> serde::Deserialize<'de> for CreateMarketsFeeComponents { } struct GeneratedVisitor; impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = CreateMarketsFeeComponents; + type Value = ChangeMarketsFeeComponents; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct astria.protocol.fees.v1.CreateMarketsFeeComponents") + formatter.write_str("struct astria.protocol.fees.v1.ChangeMarketsFeeComponents") } - fn visit_map(self, mut map_: V) -> std::result::Result + fn visit_map(self, mut map_: V) -> std::result::Result where V: serde::de::MapAccess<'de>, { @@ -421,13 +421,13 @@ impl<'de> serde::Deserialize<'de> for CreateMarketsFeeComponents { } } } - Ok(CreateMarketsFeeComponents { + Ok(ChangeMarketsFeeComponents { base: base__, multiplier: multiplier__, }) } } - deserializer.deserialize_struct("astria.protocol.fees.v1.CreateMarketsFeeComponents", FIELDS, GeneratedVisitor) + deserializer.deserialize_struct("astria.protocol.fees.v1.ChangeMarketsFeeComponents", FIELDS, GeneratedVisitor) } } impl serde::Serialize for FeeAssetChangeFeeComponents { @@ -1294,114 +1294,6 @@ impl<'de> serde::Deserialize<'de> for RemoveMarketAuthoritiesFeeComponents { deserializer.deserialize_struct("astria.protocol.fees.v1.RemoveMarketAuthoritiesFeeComponents", FIELDS, GeneratedVisitor) } } -impl serde::Serialize for RemoveMarketsFeeComponents { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if self.base.is_some() { - len += 1; - } - if self.multiplier.is_some() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("astria.protocol.fees.v1.RemoveMarketsFeeComponents", len)?; - if let Some(v) = self.base.as_ref() { - struct_ser.serialize_field("base", v)?; - } - if let Some(v) = self.multiplier.as_ref() { - struct_ser.serialize_field("multiplier", v)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for RemoveMarketsFeeComponents { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "base", - "multiplier", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - Base, - Multiplier, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - 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(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "base" => Ok(GeneratedField::Base), - "multiplier" => Ok(GeneratedField::Multiplier), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = RemoveMarketsFeeComponents; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct astria.protocol.fees.v1.RemoveMarketsFeeComponents") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut base__ = None; - let mut multiplier__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::Base => { - if base__.is_some() { - return Err(serde::de::Error::duplicate_field("base")); - } - base__ = map_.next_value()?; - } - GeneratedField::Multiplier => { - if multiplier__.is_some() { - return Err(serde::de::Error::duplicate_field("multiplier")); - } - multiplier__ = map_.next_value()?; - } - } - } - Ok(RemoveMarketsFeeComponents { - base: base__, - multiplier: multiplier__, - }) - } - } - deserializer.deserialize_struct("astria.protocol.fees.v1.RemoveMarketsFeeComponents", FIELDS, GeneratedVisitor) - } -} impl serde::Serialize for RollupDataSubmissionFeeComponents { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -2053,222 +1945,6 @@ impl<'de> serde::Deserialize<'de> for UpdateMarketMapParamsFeeComponents { deserializer.deserialize_struct("astria.protocol.fees.v1.UpdateMarketMapParamsFeeComponents", FIELDS, GeneratedVisitor) } } -impl serde::Serialize for UpdateMarketsFeeComponents { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if self.base.is_some() { - len += 1; - } - if self.multiplier.is_some() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("astria.protocol.fees.v1.UpdateMarketsFeeComponents", len)?; - if let Some(v) = self.base.as_ref() { - struct_ser.serialize_field("base", v)?; - } - if let Some(v) = self.multiplier.as_ref() { - struct_ser.serialize_field("multiplier", v)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for UpdateMarketsFeeComponents { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "base", - "multiplier", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - Base, - Multiplier, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - 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(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "base" => Ok(GeneratedField::Base), - "multiplier" => Ok(GeneratedField::Multiplier), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = UpdateMarketsFeeComponents; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct astria.protocol.fees.v1.UpdateMarketsFeeComponents") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut base__ = None; - let mut multiplier__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::Base => { - if base__.is_some() { - return Err(serde::de::Error::duplicate_field("base")); - } - base__ = map_.next_value()?; - } - GeneratedField::Multiplier => { - if multiplier__.is_some() { - return Err(serde::de::Error::duplicate_field("multiplier")); - } - multiplier__ = map_.next_value()?; - } - } - } - Ok(UpdateMarketsFeeComponents { - base: base__, - multiplier: multiplier__, - }) - } - } - deserializer.deserialize_struct("astria.protocol.fees.v1.UpdateMarketsFeeComponents", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for UpsertMarketsFeeComponents { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if self.base.is_some() { - len += 1; - } - if self.multiplier.is_some() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("astria.protocol.fees.v1.UpsertMarketsFeeComponents", len)?; - if let Some(v) = self.base.as_ref() { - struct_ser.serialize_field("base", v)?; - } - if let Some(v) = self.multiplier.as_ref() { - struct_ser.serialize_field("multiplier", v)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for UpsertMarketsFeeComponents { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "base", - "multiplier", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - Base, - Multiplier, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - 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(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "base" => Ok(GeneratedField::Base), - "multiplier" => Ok(GeneratedField::Multiplier), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = UpsertMarketsFeeComponents; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct astria.protocol.fees.v1.UpsertMarketsFeeComponents") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut base__ = None; - let mut multiplier__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::Base => { - if base__.is_some() { - return Err(serde::de::Error::duplicate_field("base")); - } - base__ = map_.next_value()?; - } - GeneratedField::Multiplier => { - if multiplier__.is_some() { - return Err(serde::de::Error::duplicate_field("multiplier")); - } - multiplier__ = map_.next_value()?; - } - } - } - Ok(UpsertMarketsFeeComponents { - base: base__, - multiplier: multiplier__, - }) - } - } - deserializer.deserialize_struct("astria.protocol.fees.v1.UpsertMarketsFeeComponents", FIELDS, GeneratedVisitor) - } -} impl serde::Serialize for ValidatorUpdateFeeComponents { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result diff --git a/crates/astria-core/src/generated/astria.protocol.genesis.v1.rs b/crates/astria-core/src/generated/astria.protocol.genesis.v1.rs index 12875fdef4..686ae12d48 100644 --- a/crates/astria-core/src/generated/astria.protocol.genesis.v1.rs +++ b/crates/astria-core/src/generated/astria.protocol.genesis.v1.rs @@ -148,16 +148,8 @@ pub struct GenesisFees { super::super::fees::v1::ValidatorUpdateFeeComponents, >, #[prost(message, optional, tag = "15")] - pub upsert_markets: ::core::option::Option< - super::super::fees::v1::UpsertMarketsFeeComponents, - >, - #[prost(message, optional, tag = "16")] - pub create_markets: ::core::option::Option< - super::super::fees::v1::CreateMarketsFeeComponents, - >, - #[prost(message, optional, tag = "17")] - pub update_markets: ::core::option::Option< - super::super::fees::v1::UpdateMarketsFeeComponents, + pub change_markets: ::core::option::Option< + super::super::fees::v1::ChangeMarketsFeeComponents, >, #[prost(message, optional, tag = "18")] pub update_market_map_params: ::core::option::Option< @@ -167,10 +159,6 @@ pub struct GenesisFees { pub remove_market_authorities: ::core::option::Option< super::super::fees::v1::RemoveMarketAuthoritiesFeeComponents, >, - #[prost(message, optional, tag = "20")] - pub remove_markets: ::core::option::Option< - super::super::fees::v1::RemoveMarketsFeeComponents, - >, } impl ::prost::Name for GenesisFees { const NAME: &'static str = "GenesisFees"; diff --git a/crates/astria-core/src/generated/astria.protocol.genesis.v1.serde.rs b/crates/astria-core/src/generated/astria.protocol.genesis.v1.serde.rs index 79ae34a609..23353ef09c 100644 --- a/crates/astria-core/src/generated/astria.protocol.genesis.v1.serde.rs +++ b/crates/astria-core/src/generated/astria.protocol.genesis.v1.serde.rs @@ -643,13 +643,7 @@ impl serde::Serialize for GenesisFees { if self.validator_update.is_some() { len += 1; } - if self.upsert_markets.is_some() { - len += 1; - } - if self.create_markets.is_some() { - len += 1; - } - if self.update_markets.is_some() { + if self.change_markets.is_some() { len += 1; } if self.update_market_map_params.is_some() { @@ -658,9 +652,6 @@ impl serde::Serialize for GenesisFees { if self.remove_market_authorities.is_some() { len += 1; } - if self.remove_markets.is_some() { - len += 1; - } let mut struct_ser = serializer.serialize_struct("astria.protocol.genesis.v1.GenesisFees", len)?; if let Some(v) = self.bridge_lock.as_ref() { struct_ser.serialize_field("bridgeLock", v)?; @@ -704,14 +695,8 @@ impl serde::Serialize for GenesisFees { if let Some(v) = self.validator_update.as_ref() { struct_ser.serialize_field("validatorUpdate", v)?; } - if let Some(v) = self.upsert_markets.as_ref() { - struct_ser.serialize_field("upsertMarkets", v)?; - } - if let Some(v) = self.create_markets.as_ref() { - struct_ser.serialize_field("createMarkets", v)?; - } - if let Some(v) = self.update_markets.as_ref() { - struct_ser.serialize_field("updateMarkets", v)?; + if let Some(v) = self.change_markets.as_ref() { + struct_ser.serialize_field("changeMarkets", v)?; } if let Some(v) = self.update_market_map_params.as_ref() { struct_ser.serialize_field("updateMarketMapParams", v)?; @@ -719,9 +704,6 @@ impl serde::Serialize for GenesisFees { if let Some(v) = self.remove_market_authorities.as_ref() { struct_ser.serialize_field("removeMarketAuthorities", v)?; } - if let Some(v) = self.remove_markets.as_ref() { - struct_ser.serialize_field("removeMarkets", v)?; - } struct_ser.end() } } @@ -759,18 +741,12 @@ impl<'de> serde::Deserialize<'de> for GenesisFees { "transfer", "validator_update", "validatorUpdate", - "upsert_markets", - "upsertMarkets", - "create_markets", - "createMarkets", - "update_markets", - "updateMarkets", + "change_markets", + "changeMarkets", "update_market_map_params", "updateMarketMapParams", "remove_market_authorities", "removeMarketAuthorities", - "remove_markets", - "removeMarkets", ]; #[allow(clippy::enum_variant_names)] @@ -789,12 +765,9 @@ impl<'de> serde::Deserialize<'de> for GenesisFees { SudoAddressChange, Transfer, ValidatorUpdate, - UpsertMarkets, - CreateMarkets, - UpdateMarkets, + ChangeMarkets, UpdateMarketMapParams, RemoveMarketAuthorities, - RemoveMarkets, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -830,12 +803,9 @@ impl<'de> serde::Deserialize<'de> for GenesisFees { "sudoAddressChange" | "sudo_address_change" => Ok(GeneratedField::SudoAddressChange), "transfer" => Ok(GeneratedField::Transfer), "validatorUpdate" | "validator_update" => Ok(GeneratedField::ValidatorUpdate), - "upsertMarkets" | "upsert_markets" => Ok(GeneratedField::UpsertMarkets), - "createMarkets" | "create_markets" => Ok(GeneratedField::CreateMarkets), - "updateMarkets" | "update_markets" => Ok(GeneratedField::UpdateMarkets), + "changeMarkets" | "change_markets" => Ok(GeneratedField::ChangeMarkets), "updateMarketMapParams" | "update_market_map_params" => Ok(GeneratedField::UpdateMarketMapParams), "removeMarketAuthorities" | "remove_market_authorities" => Ok(GeneratedField::RemoveMarketAuthorities), - "removeMarkets" | "remove_markets" => Ok(GeneratedField::RemoveMarkets), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -869,12 +839,9 @@ impl<'de> serde::Deserialize<'de> for GenesisFees { let mut sudo_address_change__ = None; let mut transfer__ = None; let mut validator_update__ = None; - let mut upsert_markets__ = None; - let mut create_markets__ = None; - let mut update_markets__ = None; + let mut change_markets__ = None; let mut update_market_map_params__ = None; let mut remove_market_authorities__ = None; - let mut remove_markets__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::BridgeLock => { @@ -961,23 +928,11 @@ impl<'de> serde::Deserialize<'de> for GenesisFees { } validator_update__ = map_.next_value()?; } - GeneratedField::UpsertMarkets => { - if upsert_markets__.is_some() { - return Err(serde::de::Error::duplicate_field("upsertMarkets")); - } - upsert_markets__ = map_.next_value()?; - } - GeneratedField::CreateMarkets => { - if create_markets__.is_some() { - return Err(serde::de::Error::duplicate_field("createMarkets")); + GeneratedField::ChangeMarkets => { + if change_markets__.is_some() { + return Err(serde::de::Error::duplicate_field("changeMarkets")); } - create_markets__ = map_.next_value()?; - } - GeneratedField::UpdateMarkets => { - if update_markets__.is_some() { - return Err(serde::de::Error::duplicate_field("updateMarkets")); - } - update_markets__ = map_.next_value()?; + change_markets__ = map_.next_value()?; } GeneratedField::UpdateMarketMapParams => { if update_market_map_params__.is_some() { @@ -991,12 +946,6 @@ impl<'de> serde::Deserialize<'de> for GenesisFees { } remove_market_authorities__ = map_.next_value()?; } - GeneratedField::RemoveMarkets => { - if remove_markets__.is_some() { - return Err(serde::de::Error::duplicate_field("removeMarkets")); - } - remove_markets__ = map_.next_value()?; - } } } Ok(GenesisFees { @@ -1014,12 +963,9 @@ impl<'de> serde::Deserialize<'de> for GenesisFees { sudo_address_change: sudo_address_change__, transfer: transfer__, validator_update: validator_update__, - upsert_markets: upsert_markets__, - create_markets: create_markets__, - update_markets: update_markets__, + change_markets: change_markets__, update_market_map_params: update_market_map_params__, remove_market_authorities: remove_market_authorities__, - remove_markets: remove_markets__, }) } } diff --git a/crates/astria-core/src/generated/astria.protocol.transaction.v1.rs b/crates/astria-core/src/generated/astria.protocol.transaction.v1.rs index 11e1c10126..26eefa61d7 100644 --- a/crates/astria-core/src/generated/astria.protocol.transaction.v1.rs +++ b/crates/astria-core/src/generated/astria.protocol.transaction.v1.rs @@ -3,7 +3,7 @@ pub struct Action { #[prost( oneof = "action::Value", - tags = "1, 2, 11, 12, 13, 14, 21, 22, 50, 51, 52, 53, 55, 56, 71, 72, 73, 74, 75, 76" + tags = "1, 2, 11, 12, 13, 14, 21, 22, 50, 51, 52, 53, 55, 56, 71, 72, 73" )] pub value: ::core::option::Option, } @@ -48,17 +48,11 @@ pub mod action { IbcSudoChange(super::IbcSudoChange), /// MarketMap actions are defined on 71-80 #[prost(message, tag = "71")] - UpsertMarkets(super::UpsertMarkets), + ChangeMarkets(super::ChangeMarkets), #[prost(message, tag = "72")] - CreateMarkets(super::CreateMarkets), - #[prost(message, tag = "73")] - UpdateMarkets(super::UpdateMarkets), - #[prost(message, tag = "74")] UpdateMarketMapParams(super::UpdateMarketMapParams), - #[prost(message, tag = "75")] + #[prost(message, tag = "73")] RemoveMarketAuthorities(super::RemoveMarketAuthorities), - #[prost(message, tag = "76")] - RemoveMarkets(super::RemoveMarkets), } } impl ::prost::Name for Action { @@ -415,7 +409,7 @@ pub struct FeeChange { /// the new fee components values #[prost( oneof = "fee_change::FeeComponents", - tags = "1, 2, 3, 4, 5, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20" + tags = "1, 2, 3, 4, 5, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17" )] pub fee_components: ::core::option::Option, } @@ -456,21 +450,15 @@ pub mod fee_change { #[prost(message, tag = "14")] ValidatorUpdate(super::super::super::fees::v1::ValidatorUpdateFeeComponents), #[prost(message, tag = "15")] - UpsertMarkets(super::super::super::fees::v1::UpsertMarketsFeeComponents), + ChangeMarkets(super::super::super::fees::v1::ChangeMarketsFeeComponents), #[prost(message, tag = "16")] - CreateMarkets(super::super::super::fees::v1::CreateMarketsFeeComponents), - #[prost(message, tag = "17")] - UpdateMarkets(super::super::super::fees::v1::UpdateMarketsFeeComponents), - #[prost(message, tag = "18")] UpdateMarketMapParams( super::super::super::fees::v1::UpdateMarketMapParamsFeeComponents, ), - #[prost(message, tag = "19")] + #[prost(message, tag = "17")] RemoveMarketAuthorities( super::super::super::fees::v1::RemoveMarketAuthoritiesFeeComponents, ), - #[prost(message, tag = "20")] - RemoveMarkets(super::super::super::fees::v1::RemoveMarketsFeeComponents), } } impl ::prost::Name for FeeChange { @@ -493,52 +481,44 @@ impl ::prost::Name for IbcSudoChange { ::prost::alloc::format!("astria.protocol.transaction.v1.{}", Self::NAME) } } -/// Updates or creates markets in the market map. If a market does not exist, it will be created. +/// Either creates, updates existing, or removes markets. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] -pub struct UpsertMarkets { - /// The list of all markets to be created or updated for the given transaction. - #[prost(message, repeated, tag = "2")] - pub markets: ::prost::alloc::vec::Vec< - super::super::super::super::connect::marketmap::v2::Market, - >, +pub struct ChangeMarkets { + #[prost(oneof = "change_markets::Action", tags = "1, 2, 3")] + pub action: ::core::option::Option, } -impl ::prost::Name for UpsertMarkets { - const NAME: &'static str = "UpsertMarkets"; - const PACKAGE: &'static str = "astria.protocol.transaction.v1"; - fn full_name() -> ::prost::alloc::string::String { - ::prost::alloc::format!("astria.protocol.transaction.v1.{}", Self::NAME) +/// Nested message and enum types in `ChangeMarkets`. +pub mod change_markets { + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Action { + #[prost(message, tag = "1")] + Create(super::Markets), + #[prost(message, tag = "2")] + Update(super::Markets), + #[prost(message, tag = "3")] + Remove(super::Markets), } } -/// Creates new markets in the market map. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct CreateMarkets { - /// The list of all markets to be created. - #[prost(message, repeated, tag = "2")] - pub create_markets: ::prost::alloc::vec::Vec< - super::super::super::super::connect::marketmap::v2::Market, - >, -} -impl ::prost::Name for CreateMarkets { - const NAME: &'static str = "CreateMarkets"; +impl ::prost::Name for ChangeMarkets { + const NAME: &'static str = "ChangeMarkets"; const PACKAGE: &'static str = "astria.protocol.transaction.v1"; fn full_name() -> ::prost::alloc::string::String { ::prost::alloc::format!("astria.protocol.transaction.v1.{}", Self::NAME) } } -/// Updates existing markets in the market map. +/// A list of markets for creation, updating, or removal. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] -pub struct UpdateMarkets { - /// The list of all markets to be updated. - #[prost(message, repeated, tag = "2")] - pub update_markets: ::prost::alloc::vec::Vec< +pub struct Markets { + #[prost(message, repeated, tag = "1")] + pub markets: ::prost::alloc::vec::Vec< super::super::super::super::connect::marketmap::v2::Market, >, } -impl ::prost::Name for UpdateMarkets { - const NAME: &'static str = "UpdateMarkets"; +impl ::prost::Name for Markets { + const NAME: &'static str = "Markets"; const PACKAGE: &'static str = "astria.protocol.transaction.v1"; fn full_name() -> ::prost::alloc::string::String { ::prost::alloc::format!("astria.protocol.transaction.v1.{}", Self::NAME) @@ -576,21 +556,6 @@ impl ::prost::Name for RemoveMarketAuthorities { ::prost::alloc::format!("astria.protocol.transaction.v1.{}", Self::NAME) } } -/// Removes markets from the market map. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct RemoveMarkets { - /// Markets is the list of markets to remove. - #[prost(string, repeated, tag = "2")] - pub markets: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, -} -impl ::prost::Name for RemoveMarkets { - const NAME: &'static str = "RemoveMarkets"; - const PACKAGE: &'static str = "astria.protocol.transaction.v1"; - fn full_name() -> ::prost::alloc::string::String { - ::prost::alloc::format!("astria.protocol.transaction.v1.{}", Self::NAME) - } -} /// `Transaction` is a transaction `TransactionBody` together with a public /// ket and a signature. #[allow(clippy::derive_partial_eq_without_eq)] diff --git a/crates/astria-core/src/generated/astria.protocol.transaction.v1.serde.rs b/crates/astria-core/src/generated/astria.protocol.transaction.v1.serde.rs index 0441f90160..c2acdd19c2 100644 --- a/crates/astria-core/src/generated/astria.protocol.transaction.v1.serde.rs +++ b/crates/astria-core/src/generated/astria.protocol.transaction.v1.serde.rs @@ -54,14 +54,8 @@ impl serde::Serialize for Action { action::Value::IbcSudoChange(v) => { struct_ser.serialize_field("ibcSudoChange", v)?; } - action::Value::UpsertMarkets(v) => { - struct_ser.serialize_field("upsertMarkets", v)?; - } - action::Value::CreateMarkets(v) => { - struct_ser.serialize_field("createMarkets", v)?; - } - action::Value::UpdateMarkets(v) => { - struct_ser.serialize_field("updateMarkets", v)?; + action::Value::ChangeMarkets(v) => { + struct_ser.serialize_field("changeMarkets", v)?; } action::Value::UpdateMarketMapParams(v) => { struct_ser.serialize_field("updateMarketMapParams", v)?; @@ -69,9 +63,6 @@ impl serde::Serialize for Action { action::Value::RemoveMarketAuthorities(v) => { struct_ser.serialize_field("removeMarketAuthorities", v)?; } - action::Value::RemoveMarkets(v) => { - struct_ser.serialize_field("removeMarkets", v)?; - } } } struct_ser.end() @@ -110,18 +101,12 @@ impl<'de> serde::Deserialize<'de> for Action { "feeChange", "ibc_sudo_change", "ibcSudoChange", - "upsert_markets", - "upsertMarkets", - "create_markets", - "createMarkets", - "update_markets", - "updateMarkets", + "change_markets", + "changeMarkets", "update_market_map_params", "updateMarketMapParams", "remove_market_authorities", "removeMarketAuthorities", - "remove_markets", - "removeMarkets", ]; #[allow(clippy::enum_variant_names)] @@ -140,12 +125,9 @@ impl<'de> serde::Deserialize<'de> for Action { FeeAssetChange, FeeChange, IbcSudoChange, - UpsertMarkets, - CreateMarkets, - UpdateMarkets, + ChangeMarkets, UpdateMarketMapParams, RemoveMarketAuthorities, - RemoveMarkets, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -181,12 +163,9 @@ impl<'de> serde::Deserialize<'de> for Action { "feeAssetChange" | "fee_asset_change" => Ok(GeneratedField::FeeAssetChange), "feeChange" | "fee_change" => Ok(GeneratedField::FeeChange), "ibcSudoChange" | "ibc_sudo_change" => Ok(GeneratedField::IbcSudoChange), - "upsertMarkets" | "upsert_markets" => Ok(GeneratedField::UpsertMarkets), - "createMarkets" | "create_markets" => Ok(GeneratedField::CreateMarkets), - "updateMarkets" | "update_markets" => Ok(GeneratedField::UpdateMarkets), + "changeMarkets" | "change_markets" => Ok(GeneratedField::ChangeMarkets), "updateMarketMapParams" | "update_market_map_params" => Ok(GeneratedField::UpdateMarketMapParams), "removeMarketAuthorities" | "remove_market_authorities" => Ok(GeneratedField::RemoveMarketAuthorities), - "removeMarkets" | "remove_markets" => Ok(GeneratedField::RemoveMarkets), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -307,25 +286,11 @@ impl<'de> serde::Deserialize<'de> for Action { value__ = map_.next_value::<::std::option::Option<_>>()?.map(action::Value::IbcSudoChange) ; } - GeneratedField::UpsertMarkets => { + GeneratedField::ChangeMarkets => { if value__.is_some() { - return Err(serde::de::Error::duplicate_field("upsertMarkets")); + return Err(serde::de::Error::duplicate_field("changeMarkets")); } - value__ = map_.next_value::<::std::option::Option<_>>()?.map(action::Value::UpsertMarkets) -; - } - GeneratedField::CreateMarkets => { - if value__.is_some() { - return Err(serde::de::Error::duplicate_field("createMarkets")); - } - value__ = map_.next_value::<::std::option::Option<_>>()?.map(action::Value::CreateMarkets) -; - } - GeneratedField::UpdateMarkets => { - if value__.is_some() { - return Err(serde::de::Error::duplicate_field("updateMarkets")); - } - value__ = map_.next_value::<::std::option::Option<_>>()?.map(action::Value::UpdateMarkets) + value__ = map_.next_value::<::std::option::Option<_>>()?.map(action::Value::ChangeMarkets) ; } GeneratedField::UpdateMarketMapParams => { @@ -340,13 +305,6 @@ impl<'de> serde::Deserialize<'de> for Action { return Err(serde::de::Error::duplicate_field("removeMarketAuthorities")); } value__ = map_.next_value::<::std::option::Option<_>>()?.map(action::Value::RemoveMarketAuthorities) -; - } - GeneratedField::RemoveMarkets => { - if value__.is_some() { - return Err(serde::de::Error::duplicate_field("removeMarkets")); - } - value__ = map_.next_value::<::std::option::Option<_>>()?.map(action::Value::RemoveMarkets) ; } } @@ -866,7 +824,7 @@ impl<'de> serde::Deserialize<'de> for BridgeUnlock { deserializer.deserialize_struct("astria.protocol.transaction.v1.BridgeUnlock", FIELDS, GeneratedVisitor) } } -impl serde::Serialize for CreateMarkets { +impl serde::Serialize for ChangeMarkets { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result where @@ -874,30 +832,43 @@ impl serde::Serialize for CreateMarkets { { use serde::ser::SerializeStruct; let mut len = 0; - if !self.create_markets.is_empty() { + if self.action.is_some() { len += 1; } - let mut struct_ser = serializer.serialize_struct("astria.protocol.transaction.v1.CreateMarkets", len)?; - if !self.create_markets.is_empty() { - struct_ser.serialize_field("createMarkets", &self.create_markets)?; + let mut struct_ser = serializer.serialize_struct("astria.protocol.transaction.v1.ChangeMarkets", len)?; + if let Some(v) = self.action.as_ref() { + match v { + change_markets::Action::Create(v) => { + struct_ser.serialize_field("create", v)?; + } + change_markets::Action::Update(v) => { + struct_ser.serialize_field("update", v)?; + } + change_markets::Action::Remove(v) => { + struct_ser.serialize_field("remove", v)?; + } + } } struct_ser.end() } } -impl<'de> serde::Deserialize<'de> for CreateMarkets { +impl<'de> serde::Deserialize<'de> for ChangeMarkets { #[allow(deprecated)] fn deserialize(deserializer: D) -> std::result::Result where D: serde::Deserializer<'de>, { const FIELDS: &[&str] = &[ - "create_markets", - "createMarkets", + "create", + "update", + "remove", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { - CreateMarkets, + Create, + Update, + Remove, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -919,7 +890,9 @@ impl<'de> serde::Deserialize<'de> for CreateMarkets { E: serde::de::Error, { match value { - "createMarkets" | "create_markets" => Ok(GeneratedField::CreateMarkets), + "create" => Ok(GeneratedField::Create), + "update" => Ok(GeneratedField::Update), + "remove" => Ok(GeneratedField::Remove), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -929,33 +902,48 @@ impl<'de> serde::Deserialize<'de> for CreateMarkets { } struct GeneratedVisitor; impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = CreateMarkets; + type Value = ChangeMarkets; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct astria.protocol.transaction.v1.CreateMarkets") + formatter.write_str("struct astria.protocol.transaction.v1.ChangeMarkets") } - fn visit_map(self, mut map_: V) -> std::result::Result + fn visit_map(self, mut map_: V) -> std::result::Result where V: serde::de::MapAccess<'de>, { - let mut create_markets__ = None; + let mut action__ = None; while let Some(k) = map_.next_key()? { match k { - GeneratedField::CreateMarkets => { - if create_markets__.is_some() { - return Err(serde::de::Error::duplicate_field("createMarkets")); + GeneratedField::Create => { + if action__.is_some() { + return Err(serde::de::Error::duplicate_field("create")); + } + action__ = map_.next_value::<::std::option::Option<_>>()?.map(change_markets::Action::Create) +; + } + GeneratedField::Update => { + if action__.is_some() { + return Err(serde::de::Error::duplicate_field("update")); + } + action__ = map_.next_value::<::std::option::Option<_>>()?.map(change_markets::Action::Update) +; + } + GeneratedField::Remove => { + if action__.is_some() { + return Err(serde::de::Error::duplicate_field("remove")); } - create_markets__ = Some(map_.next_value()?); + action__ = map_.next_value::<::std::option::Option<_>>()?.map(change_markets::Action::Remove) +; } } } - Ok(CreateMarkets { - create_markets: create_markets__.unwrap_or_default(), + Ok(ChangeMarkets { + action: action__, }) } } - deserializer.deserialize_struct("astria.protocol.transaction.v1.CreateMarkets", FIELDS, GeneratedVisitor) + deserializer.deserialize_struct("astria.protocol.transaction.v1.ChangeMarkets", FIELDS, GeneratedVisitor) } } impl serde::Serialize for FeeAssetChange { @@ -1121,14 +1109,8 @@ impl serde::Serialize for FeeChange { fee_change::FeeComponents::ValidatorUpdate(v) => { struct_ser.serialize_field("validatorUpdate", v)?; } - fee_change::FeeComponents::UpsertMarkets(v) => { - struct_ser.serialize_field("upsertMarkets", v)?; - } - fee_change::FeeComponents::CreateMarkets(v) => { - struct_ser.serialize_field("createMarkets", v)?; - } - fee_change::FeeComponents::UpdateMarkets(v) => { - struct_ser.serialize_field("updateMarkets", v)?; + fee_change::FeeComponents::ChangeMarkets(v) => { + struct_ser.serialize_field("changeMarkets", v)?; } fee_change::FeeComponents::UpdateMarketMapParams(v) => { struct_ser.serialize_field("updateMarketMapParams", v)?; @@ -1136,9 +1118,6 @@ impl serde::Serialize for FeeChange { fee_change::FeeComponents::RemoveMarketAuthorities(v) => { struct_ser.serialize_field("removeMarketAuthorities", v)?; } - fee_change::FeeComponents::RemoveMarkets(v) => { - struct_ser.serialize_field("removeMarkets", v)?; - } } } struct_ser.end() @@ -1178,18 +1157,12 @@ impl<'de> serde::Deserialize<'de> for FeeChange { "transfer", "validator_update", "validatorUpdate", - "upsert_markets", - "upsertMarkets", - "create_markets", - "createMarkets", - "update_markets", - "updateMarkets", + "change_markets", + "changeMarkets", "update_market_map_params", "updateMarketMapParams", "remove_market_authorities", "removeMarketAuthorities", - "remove_markets", - "removeMarkets", ]; #[allow(clippy::enum_variant_names)] @@ -1208,12 +1181,9 @@ impl<'de> serde::Deserialize<'de> for FeeChange { SudoAddressChange, Transfer, ValidatorUpdate, - UpsertMarkets, - CreateMarkets, - UpdateMarkets, + ChangeMarkets, UpdateMarketMapParams, RemoveMarketAuthorities, - RemoveMarkets, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -1249,12 +1219,9 @@ impl<'de> serde::Deserialize<'de> for FeeChange { "sudoAddressChange" | "sudo_address_change" => Ok(GeneratedField::SudoAddressChange), "transfer" => Ok(GeneratedField::Transfer), "validatorUpdate" | "validator_update" => Ok(GeneratedField::ValidatorUpdate), - "upsertMarkets" | "upsert_markets" => Ok(GeneratedField::UpsertMarkets), - "createMarkets" | "create_markets" => Ok(GeneratedField::CreateMarkets), - "updateMarkets" | "update_markets" => Ok(GeneratedField::UpdateMarkets), + "changeMarkets" | "change_markets" => Ok(GeneratedField::ChangeMarkets), "updateMarketMapParams" | "update_market_map_params" => Ok(GeneratedField::UpdateMarketMapParams), "removeMarketAuthorities" | "remove_market_authorities" => Ok(GeneratedField::RemoveMarketAuthorities), - "removeMarkets" | "remove_markets" => Ok(GeneratedField::RemoveMarkets), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -1375,25 +1342,11 @@ impl<'de> serde::Deserialize<'de> for FeeChange { fee_components__ = map_.next_value::<::std::option::Option<_>>()?.map(fee_change::FeeComponents::ValidatorUpdate) ; } - GeneratedField::UpsertMarkets => { - if fee_components__.is_some() { - return Err(serde::de::Error::duplicate_field("upsertMarkets")); - } - fee_components__ = map_.next_value::<::std::option::Option<_>>()?.map(fee_change::FeeComponents::UpsertMarkets) -; - } - GeneratedField::CreateMarkets => { - if fee_components__.is_some() { - return Err(serde::de::Error::duplicate_field("createMarkets")); - } - fee_components__ = map_.next_value::<::std::option::Option<_>>()?.map(fee_change::FeeComponents::CreateMarkets) -; - } - GeneratedField::UpdateMarkets => { + GeneratedField::ChangeMarkets => { if fee_components__.is_some() { - return Err(serde::de::Error::duplicate_field("updateMarkets")); + return Err(serde::de::Error::duplicate_field("changeMarkets")); } - fee_components__ = map_.next_value::<::std::option::Option<_>>()?.map(fee_change::FeeComponents::UpdateMarkets) + fee_components__ = map_.next_value::<::std::option::Option<_>>()?.map(fee_change::FeeComponents::ChangeMarkets) ; } GeneratedField::UpdateMarketMapParams => { @@ -1408,13 +1361,6 @@ impl<'de> serde::Deserialize<'de> for FeeChange { return Err(serde::de::Error::duplicate_field("removeMarketAuthorities")); } fee_components__ = map_.next_value::<::std::option::Option<_>>()?.map(fee_change::FeeComponents::RemoveMarketAuthorities) -; - } - GeneratedField::RemoveMarkets => { - if fee_components__.is_some() { - return Err(serde::de::Error::duplicate_field("removeMarkets")); - } - fee_components__ = map_.next_value::<::std::option::Option<_>>()?.map(fee_change::FeeComponents::RemoveMarkets) ; } } @@ -2179,7 +2125,7 @@ impl<'de> serde::Deserialize<'de> for InitBridgeAccount { deserializer.deserialize_struct("astria.protocol.transaction.v1.InitBridgeAccount", FIELDS, GeneratedVisitor) } } -impl serde::Serialize for RemoveMarketAuthorities { +impl serde::Serialize for Markets { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result where @@ -2187,30 +2133,29 @@ impl serde::Serialize for RemoveMarketAuthorities { { use serde::ser::SerializeStruct; let mut len = 0; - if !self.remove_addresses.is_empty() { + if !self.markets.is_empty() { len += 1; } - let mut struct_ser = serializer.serialize_struct("astria.protocol.transaction.v1.RemoveMarketAuthorities", len)?; - if !self.remove_addresses.is_empty() { - struct_ser.serialize_field("removeAddresses", &self.remove_addresses)?; + let mut struct_ser = serializer.serialize_struct("astria.protocol.transaction.v1.Markets", len)?; + if !self.markets.is_empty() { + struct_ser.serialize_field("markets", &self.markets)?; } struct_ser.end() } } -impl<'de> serde::Deserialize<'de> for RemoveMarketAuthorities { +impl<'de> serde::Deserialize<'de> for Markets { #[allow(deprecated)] fn deserialize(deserializer: D) -> std::result::Result where D: serde::Deserializer<'de>, { const FIELDS: &[&str] = &[ - "remove_addresses", - "removeAddresses", + "markets", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { - RemoveAddresses, + Markets, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -2232,7 +2177,7 @@ impl<'de> serde::Deserialize<'de> for RemoveMarketAuthorities { E: serde::de::Error, { match value { - "removeAddresses" | "remove_addresses" => Ok(GeneratedField::RemoveAddresses), + "markets" => Ok(GeneratedField::Markets), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -2242,36 +2187,36 @@ impl<'de> serde::Deserialize<'de> for RemoveMarketAuthorities { } struct GeneratedVisitor; impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = RemoveMarketAuthorities; + type Value = Markets; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct astria.protocol.transaction.v1.RemoveMarketAuthorities") + formatter.write_str("struct astria.protocol.transaction.v1.Markets") } - fn visit_map(self, mut map_: V) -> std::result::Result + fn visit_map(self, mut map_: V) -> std::result::Result where V: serde::de::MapAccess<'de>, { - let mut remove_addresses__ = None; + let mut markets__ = None; while let Some(k) = map_.next_key()? { match k { - GeneratedField::RemoveAddresses => { - if remove_addresses__.is_some() { - return Err(serde::de::Error::duplicate_field("removeAddresses")); + GeneratedField::Markets => { + if markets__.is_some() { + return Err(serde::de::Error::duplicate_field("markets")); } - remove_addresses__ = Some(map_.next_value()?); + markets__ = Some(map_.next_value()?); } } } - Ok(RemoveMarketAuthorities { - remove_addresses: remove_addresses__.unwrap_or_default(), + Ok(Markets { + markets: markets__.unwrap_or_default(), }) } } - deserializer.deserialize_struct("astria.protocol.transaction.v1.RemoveMarketAuthorities", FIELDS, GeneratedVisitor) + deserializer.deserialize_struct("astria.protocol.transaction.v1.Markets", FIELDS, GeneratedVisitor) } } -impl serde::Serialize for RemoveMarkets { +impl serde::Serialize for RemoveMarketAuthorities { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result where @@ -2279,29 +2224,30 @@ impl serde::Serialize for RemoveMarkets { { use serde::ser::SerializeStruct; let mut len = 0; - if !self.markets.is_empty() { + if !self.remove_addresses.is_empty() { len += 1; } - let mut struct_ser = serializer.serialize_struct("astria.protocol.transaction.v1.RemoveMarkets", len)?; - if !self.markets.is_empty() { - struct_ser.serialize_field("markets", &self.markets)?; + let mut struct_ser = serializer.serialize_struct("astria.protocol.transaction.v1.RemoveMarketAuthorities", len)?; + if !self.remove_addresses.is_empty() { + struct_ser.serialize_field("removeAddresses", &self.remove_addresses)?; } struct_ser.end() } } -impl<'de> serde::Deserialize<'de> for RemoveMarkets { +impl<'de> serde::Deserialize<'de> for RemoveMarketAuthorities { #[allow(deprecated)] fn deserialize(deserializer: D) -> std::result::Result where D: serde::Deserializer<'de>, { const FIELDS: &[&str] = &[ - "markets", + "remove_addresses", + "removeAddresses", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { - Markets, + RemoveAddresses, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -2323,7 +2269,7 @@ impl<'de> serde::Deserialize<'de> for RemoveMarkets { E: serde::de::Error, { match value { - "markets" => Ok(GeneratedField::Markets), + "removeAddresses" | "remove_addresses" => Ok(GeneratedField::RemoveAddresses), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -2333,33 +2279,33 @@ impl<'de> serde::Deserialize<'de> for RemoveMarkets { } struct GeneratedVisitor; impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = RemoveMarkets; + type Value = RemoveMarketAuthorities; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct astria.protocol.transaction.v1.RemoveMarkets") + formatter.write_str("struct astria.protocol.transaction.v1.RemoveMarketAuthorities") } - fn visit_map(self, mut map_: V) -> std::result::Result + fn visit_map(self, mut map_: V) -> std::result::Result where V: serde::de::MapAccess<'de>, { - let mut markets__ = None; + let mut remove_addresses__ = None; while let Some(k) = map_.next_key()? { match k { - GeneratedField::Markets => { - if markets__.is_some() { - return Err(serde::de::Error::duplicate_field("markets")); + GeneratedField::RemoveAddresses => { + if remove_addresses__.is_some() { + return Err(serde::de::Error::duplicate_field("removeAddresses")); } - markets__ = Some(map_.next_value()?); + remove_addresses__ = Some(map_.next_value()?); } } } - Ok(RemoveMarkets { - markets: markets__.unwrap_or_default(), + Ok(RemoveMarketAuthorities { + remove_addresses: remove_addresses__.unwrap_or_default(), }) } } - deserializer.deserialize_struct("astria.protocol.transaction.v1.RemoveMarkets", FIELDS, GeneratedVisitor) + deserializer.deserialize_struct("astria.protocol.transaction.v1.RemoveMarketAuthorities", FIELDS, GeneratedVisitor) } } impl serde::Serialize for RollupDataSubmission { @@ -3169,186 +3115,3 @@ impl<'de> serde::Deserialize<'de> for UpdateMarketMapParams { deserializer.deserialize_struct("astria.protocol.transaction.v1.UpdateMarketMapParams", FIELDS, GeneratedVisitor) } } -impl serde::Serialize for UpdateMarkets { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if !self.update_markets.is_empty() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("astria.protocol.transaction.v1.UpdateMarkets", len)?; - if !self.update_markets.is_empty() { - struct_ser.serialize_field("updateMarkets", &self.update_markets)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for UpdateMarkets { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "update_markets", - "updateMarkets", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - UpdateMarkets, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - 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(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "updateMarkets" | "update_markets" => Ok(GeneratedField::UpdateMarkets), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = UpdateMarkets; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct astria.protocol.transaction.v1.UpdateMarkets") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut update_markets__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::UpdateMarkets => { - if update_markets__.is_some() { - return Err(serde::de::Error::duplicate_field("updateMarkets")); - } - update_markets__ = Some(map_.next_value()?); - } - } - } - Ok(UpdateMarkets { - update_markets: update_markets__.unwrap_or_default(), - }) - } - } - deserializer.deserialize_struct("astria.protocol.transaction.v1.UpdateMarkets", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for UpsertMarkets { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if !self.markets.is_empty() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("astria.protocol.transaction.v1.UpsertMarkets", len)?; - if !self.markets.is_empty() { - struct_ser.serialize_field("markets", &self.markets)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for UpsertMarkets { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "markets", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - Markets, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - 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(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "markets" => Ok(GeneratedField::Markets), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = UpsertMarkets; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct astria.protocol.transaction.v1.UpsertMarkets") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut markets__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::Markets => { - if markets__.is_some() { - return Err(serde::de::Error::duplicate_field("markets")); - } - markets__ = Some(map_.next_value()?); - } - } - } - Ok(UpsertMarkets { - markets: markets__.unwrap_or_default(), - }) - } - } - deserializer.deserialize_struct("astria.protocol.transaction.v1.UpsertMarkets", FIELDS, GeneratedVisitor) - } -} diff --git a/crates/astria-core/src/protocol/fees/v1.rs b/crates/astria-core/src/protocol/fees/v1.rs index fec3dd4194..9db71f3b59 100644 --- a/crates/astria-core/src/protocol/fees/v1.rs +++ b/crates/astria-core/src/protocol/fees/v1.rs @@ -17,7 +17,7 @@ use crate::{ BridgeLock, BridgeSudoChange, BridgeUnlock, - CreateMarkets, + ChangeMarkets, FeeAssetChange, FeeChange, IbcRelayerChange, @@ -25,13 +25,10 @@ use crate::{ Ics20Withdrawal, InitBridgeAccount, RemoveMarketAuthorities, - RemoveMarkets, RollupDataSubmission, SudoAddressChange, Transfer, UpdateMarketMapParams, - UpdateMarkets, - UpsertMarkets, ValidatorUpdate, }, Protobuf, @@ -114,12 +111,9 @@ impl_protobuf_for_fee_components!( FeeComponents => raw::FeeChangeFeeComponents, FeeComponents => raw::SudoAddressChangeFeeComponents, FeeComponents => raw::IbcSudoChangeFeeComponents, - FeeComponents => raw::UpsertMarketsFeeComponents, - FeeComponents => raw::CreateMarketsFeeComponents, - FeeComponents => raw::UpdateMarketsFeeComponents, + FeeComponents => raw::ChangeMarketsFeeComponents, FeeComponents => raw::UpdateMarketMapParamsFeeComponents, FeeComponents => raw::RemoveMarketAuthoritiesFeeComponents, - FeeComponents => raw::RemoveMarketsFeeComponents, ); pub struct FeeComponents { diff --git a/crates/astria-core/src/protocol/genesis/v1.rs b/crates/astria-core/src/protocol/genesis/v1.rs index 1ae33ce2de..5d6a724045 100644 --- a/crates/astria-core/src/protocol/genesis/v1.rs +++ b/crates/astria-core/src/protocol/genesis/v1.rs @@ -29,7 +29,7 @@ use crate::{ BridgeLock, BridgeSudoChange, BridgeUnlock, - CreateMarkets, + ChangeMarkets, FeeAssetChange, FeeChange, IbcRelayerChange, @@ -37,13 +37,10 @@ use crate::{ Ics20Withdrawal, InitBridgeAccount, RemoveMarketAuthorities, - RemoveMarkets, RollupDataSubmission, SudoAddressChange, Transfer, UpdateMarketMapParams, - UpdateMarkets, - UpsertMarkets, ValidatorUpdate, }, }, @@ -769,12 +766,9 @@ pub struct GenesisFees { pub ibc_relayer_change: Option>, pub sudo_address_change: Option>, pub ibc_sudo_change: Option>, - pub upsert_markets: Option>, - pub create_markets: Option>, - pub update_markets: Option>, + pub change_markets: Option>, pub update_market_map_params: Option>, pub remove_market_authorities: Option>, - pub remove_markets: Option>, } impl Protobuf for GenesisFees { @@ -801,12 +795,9 @@ impl Protobuf for GenesisFees { ibc_relayer_change, sudo_address_change, ibc_sudo_change, - upsert_markets, - create_markets, - update_markets, + change_markets, update_market_map_params, remove_market_authorities, - remove_markets, } = raw; let rollup_data_submission = rollup_data_submission .clone() @@ -893,23 +884,11 @@ impl Protobuf for GenesisFees { .transpose() .map_err(|e| FeesError::fee_components("ibc_sudo_change", e))?; - let upsert_markets = upsert_markets + let change_markets = change_markets .clone() - .map(FeeComponents::::try_from_raw) + .map(FeeComponents::::try_from_raw) .transpose() - .map_err(|e| FeesError::fee_components("upsert_markets", e))?; - - let create_markets = create_markets - .clone() - .map(FeeComponents::::try_from_raw) - .transpose() - .map_err(|e| FeesError::fee_components("create_markets", e))?; - - let update_markets = update_markets - .clone() - .map(FeeComponents::::try_from_raw) - .transpose() - .map_err(|e| FeesError::fee_components("update_markets", e))?; + .map_err(|e| FeesError::fee_components("change_markets", e))?; let update_market_map_params = update_market_map_params .clone() @@ -923,12 +902,6 @@ impl Protobuf for GenesisFees { .transpose() .map_err(|e| FeesError::fee_components("remove_market_authorities", e))?; - let remove_markets = remove_markets - .clone() - .map(FeeComponents::::try_from_raw) - .transpose() - .map_err(|e| FeesError::fee_components("remove_markets", e))?; - Ok(Self { rollup_data_submission, transfer, @@ -944,12 +917,9 @@ impl Protobuf for GenesisFees { ibc_relayer_change, sudo_address_change, ibc_sudo_change, - upsert_markets, - create_markets, - update_markets, + change_markets, update_market_map_params, remove_market_authorities, - remove_markets, }) } @@ -969,12 +939,9 @@ impl Protobuf for GenesisFees { ibc_relayer_change, sudo_address_change, ibc_sudo_change, - upsert_markets, - create_markets, - update_markets, + change_markets, update_market_map_params, remove_market_authorities, - remove_markets, } = self; Self::Raw { transfer: transfer.map(|act| FeeComponents::::to_raw(&act)), @@ -1000,14 +967,11 @@ impl Protobuf for GenesisFees { .map(|act| FeeComponents::::to_raw(&act)), ibc_sudo_change: ibc_sudo_change .map(|act| FeeComponents::::to_raw(&act)), - upsert_markets: upsert_markets.map(|act| FeeComponents::::to_raw(&act)), - create_markets: create_markets.map(|act| FeeComponents::::to_raw(&act)), - update_markets: update_markets.map(|act| FeeComponents::::to_raw(&act)), + change_markets: change_markets.map(|act| FeeComponents::::to_raw(&act)), update_market_map_params: update_market_map_params .map(|act| FeeComponents::::to_raw(&act)), remove_market_authorities: remove_market_authorities .map(|act| FeeComponents::::to_raw(&act)), - remove_markets: remove_markets.map(|act| FeeComponents::::to_raw(&act)), } } } @@ -1152,16 +1116,13 @@ mod tests { ibc_relayer_change: Some(FeeComponents::::new(0, 0).to_raw()), sudo_address_change: Some(FeeComponents::::new(0, 0).to_raw()), ibc_sudo_change: Some(FeeComponents::::new(0, 0).to_raw()), - upsert_markets: Some(FeeComponents::::new(0, 0).to_raw()), - create_markets: Some(FeeComponents::::new(0, 0).to_raw()), - update_markets: Some(FeeComponents::::new(0, 0).to_raw()), + change_markets: Some(FeeComponents::::new(0, 0).to_raw()), update_market_map_params: Some( FeeComponents::::new(0, 0).to_raw(), ), remove_market_authorities: Some( FeeComponents::::new(0, 0).to_raw(), ), - remove_markets: Some(FeeComponents::::new(0, 0).to_raw()), } } diff --git a/crates/astria-core/src/protocol/transaction/v1/action/group/mod.rs b/crates/astria-core/src/protocol/transaction/v1/action/group/mod.rs index 5d7da4789f..1ed1d483af 100644 --- a/crates/astria-core/src/protocol/transaction/v1/action/group/mod.rs +++ b/crates/astria-core/src/protocol/transaction/v1/action/group/mod.rs @@ -14,7 +14,7 @@ use super::{ BridgeLock, BridgeSudoChange, BridgeUnlock, - CreateMarkets, + ChangeMarkets, FeeAssetChange, FeeChange, IbcRelayerChange, @@ -22,13 +22,10 @@ use super::{ Ics20Withdrawal, InitBridgeAccount, RemoveMarketAuthorities, - RemoveMarkets, RollupDataSubmission, SudoAddressChange, Transfer, UpdateMarketMapParams, - UpdateMarkets, - UpsertMarkets, ValidatorUpdate, }; @@ -61,12 +58,9 @@ impl_belong_to_group!( (FeeAssetChange, Group::BundleableSudo), (IbcRelay, Group::BundleableGeneral), (IbcSudoChange, Group::UnbundleableSudo), - (UpsertMarkets, Group::BundleableGeneral), - (CreateMarkets, Group::BundleableGeneral), - (UpdateMarkets, Group::BundleableGeneral), + (ChangeMarkets, Group::BundleableGeneral), (UpdateMarketMapParams, Group::BundleableSudo), (RemoveMarketAuthorities, Group::BundleableGeneral), - (RemoveMarkets, Group::BundleableGeneral), ); impl Action { @@ -86,12 +80,9 @@ impl Action { Action::FeeAssetChange(_) => FeeAssetChange::GROUP, Action::Ibc(_) => IbcRelay::GROUP, Action::IbcSudoChange(_) => IbcSudoChange::GROUP, - Action::UpsertMarkets(_) => UpsertMarkets::GROUP, - Action::CreateMarkets(_) => CreateMarkets::GROUP, - Action::UpdateMarkets(_) => UpdateMarkets::GROUP, + Action::ChangeMarkets(_) => ChangeMarkets::GROUP, Action::UpdateMarketMapParams(_) => UpdateMarketMapParams::GROUP, Action::RemoveMarketAuthorities(_) => RemoveMarketAuthorities::GROUP, - Action::RemoveMarkets(_) => RemoveMarkets::GROUP, } } } diff --git a/crates/astria-core/src/protocol/transaction/v1/action/mod.rs b/crates/astria-core/src/protocol/transaction/v1/action/mod.rs index 89651ab9b6..9038dfa374 100644 --- a/crates/astria-core/src/protocol/transaction/v1/action/mod.rs +++ b/crates/astria-core/src/protocol/transaction/v1/action/mod.rs @@ -59,12 +59,9 @@ pub enum Action { BridgeUnlock(BridgeUnlock), BridgeSudoChange(BridgeSudoChange), FeeChange(FeeChange), - UpsertMarkets(UpsertMarkets), - CreateMarkets(CreateMarkets), - UpdateMarkets(UpdateMarkets), + ChangeMarkets(ChangeMarkets), UpdateMarketMapParams(UpdateMarketMapParams), RemoveMarketAuthorities(RemoveMarketAuthorities), - RemoveMarkets(RemoveMarkets), } impl Protobuf for Action { @@ -89,12 +86,9 @@ impl Protobuf for Action { Action::BridgeUnlock(act) => Value::BridgeUnlock(act.to_raw()), Action::BridgeSudoChange(act) => Value::BridgeSudoChange(act.to_raw()), Action::FeeChange(act) => Value::FeeChange(act.to_raw()), - Action::UpsertMarkets(act) => Value::UpsertMarkets(act.to_raw()), - Action::CreateMarkets(act) => Value::CreateMarkets(act.to_raw()), - Action::UpdateMarkets(act) => Value::UpdateMarkets(act.to_raw()), + Action::ChangeMarkets(act) => Value::ChangeMarkets(act.to_raw()), Action::UpdateMarketMapParams(act) => Value::UpdateMarketMapParams(act.to_raw()), Action::RemoveMarketAuthorities(act) => Value::RemoveMarketAuthorities(act.to_raw()), - Action::RemoveMarkets(act) => Value::RemoveMarkets(act.to_raw()), }; raw::Action { value: Some(kind), @@ -168,14 +162,8 @@ impl Protobuf for Action { Value::FeeChange(act) => { Self::FeeChange(FeeChange::try_from_raw_ref(&act).map_err(Error::fee_change)?) } - Value::UpsertMarkets(act) => Self::UpsertMarkets( - UpsertMarkets::try_from_raw(act).map_err(Error::upsert_markets)?, - ), - Value::CreateMarkets(act) => Self::CreateMarkets( - CreateMarkets::try_from_raw(act).map_err(Error::create_markets)?, - ), - Value::UpdateMarkets(act) => Self::UpdateMarkets( - UpdateMarkets::try_from_raw(act).map_err(Error::update_markets)?, + Value::ChangeMarkets(act) => Self::ChangeMarkets( + ChangeMarkets::try_from_raw(act).map_err(Error::change_markets)?, ), Value::UpdateMarketMapParams(act) => Self::UpdateMarketMapParams( UpdateMarketMapParams::try_from_raw(act) @@ -185,9 +173,6 @@ impl Protobuf for Action { RemoveMarketAuthorities::try_from_raw(act) .map_err(Error::remove_market_authorities)?, ), - Value::RemoveMarkets(act) => Self::RemoveMarkets( - RemoveMarkets::try_from_raw(act).map_err(Error::remove_markets)?, - ), }; Ok(action) } @@ -298,21 +283,9 @@ impl From for Action { } } -impl From for Action { - fn from(value: UpsertMarkets) -> Self { - Self::UpsertMarkets(value) - } -} - -impl From for Action { - fn from(value: CreateMarkets) -> Self { - Self::CreateMarkets(value) - } -} - -impl From for Action { - fn from(value: UpdateMarkets) -> Self { - Self::UpdateMarkets(value) +impl From for Action { + fn from(value: ChangeMarkets) -> Self { + Self::ChangeMarkets(value) } } @@ -328,12 +301,6 @@ impl From for Action { } } -impl From for Action { - fn from(value: RemoveMarkets) -> Self { - Self::RemoveMarkets(value) - } -} - impl From for raw::Action { fn from(value: Action) -> Self { value.into_raw() @@ -371,12 +338,9 @@ impl ActionName for Action { Action::BridgeUnlock(_) => "BridgeUnlock", Action::BridgeSudoChange(_) => "BridgeSudoChange", Action::FeeChange(_) => "FeeChange", - Action::UpsertMarkets(_) => "UpsertMarkets", - Action::CreateMarkets(_) => "CreateMarkets", - Action::UpdateMarkets(_) => "UpdateMarkets", + Action::ChangeMarkets(_) => "ChangeMarkets", Action::UpdateMarketMapParams(_) => "UpdateMarketMapParams", Action::RemoveMarketAuthorities(_) => "RemoveMarketAuthorities", - Action::RemoveMarkets(_) => "RemoveMarkets", } } } @@ -446,16 +410,8 @@ impl Error { Self(ActionErrorKind::FeeChange(inner)) } - fn upsert_markets(inner: UpsertMarketsError) -> Self { - Self(ActionErrorKind::UpsertMarkets(inner)) - } - - fn create_markets(inner: CreateMarketsError) -> Self { - Self(ActionErrorKind::CreateMarkets(inner)) - } - - fn update_markets(inner: UpdateMarketsError) -> Self { - Self(ActionErrorKind::UpdateMarkets(inner)) + fn change_markets(inner: ChangeMarketsError) -> Self { + Self(ActionErrorKind::ChangeMarkets(inner)) } fn update_market_map_params(inner: UpdateMarketMapParamsError) -> Self { @@ -465,10 +421,6 @@ impl Error { fn remove_market_authorities(inner: RemoveMarketAuthoritiesError) -> Self { Self(ActionErrorKind::RemoveMarketAuthorities(inner)) } - - fn remove_markets(inner: RemoveMarketsError) -> Self { - Self(ActionErrorKind::RemoveMarkets(inner)) - } } #[derive(Debug, thiserror::Error)] @@ -503,18 +455,12 @@ enum ActionErrorKind { BridgeSudoChange(#[source] BridgeSudoChangeError), #[error("fee change action was not valid")] FeeChange(#[source] FeeChangeError), - #[error("upsert markets action was not valid")] - UpsertMarkets(#[source] UpsertMarketsError), - #[error("create markets action was not valid")] - CreateMarkets(#[source] CreateMarketsError), - #[error("update markets action was not valid")] - UpdateMarkets(#[source] UpdateMarketsError), + #[error("change markets action was not valid")] + ChangeMarkets(#[source] ChangeMarketsError), #[error("update params action was not valid")] UpdateMarketMapParams(#[source] UpdateMarketMapParamsError), #[error("remove market authorities action was not valid")] RemoveMarketAuthorities(#[source] RemoveMarketAuthoritiesError), - #[error("remove markets action was not valid")] - RemoveMarkets(#[source] RemoveMarketsError), } #[derive(Debug, thiserror::Error)] @@ -2061,12 +2007,9 @@ pub enum FeeChange { IbcRelayerChange(FeeComponents), SudoAddressChange(FeeComponents), IbcSudoChange(FeeComponents), - UpsertMarkets(FeeComponents), - CreateMarkets(FeeComponents), - UpdateMarkets(FeeComponents), + ChangeMarkets(FeeComponents), UpdateMarketMapParams(FeeComponents), RemoveMarketAuthorities(FeeComponents), - RemoveMarkets(FeeComponents), } impl Protobuf for FeeChange { @@ -2119,14 +2062,8 @@ impl Protobuf for FeeChange { Self::IbcSudoChange(fee_change) => { raw::fee_change::FeeComponents::IbcSudoChange(fee_change.to_raw()) } - Self::UpsertMarkets(fee_change) => { - raw::fee_change::FeeComponents::UpsertMarkets(fee_change.to_raw()) - } - Self::CreateMarkets(fee_change) => { - raw::fee_change::FeeComponents::CreateMarkets(fee_change.to_raw()) - } - Self::UpdateMarkets(fee_change) => { - raw::fee_change::FeeComponents::UpdateMarkets(fee_change.to_raw()) + Self::ChangeMarkets(fee_change) => { + raw::fee_change::FeeComponents::ChangeMarkets(fee_change.to_raw()) } Self::UpdateMarketMapParams(fee_change) => { raw::fee_change::FeeComponents::UpdateMarketMapParams(fee_change.to_raw()) @@ -2134,9 +2071,6 @@ impl Protobuf for FeeChange { Self::RemoveMarketAuthorities(fee_change) => { raw::fee_change::FeeComponents::RemoveMarketAuthorities(fee_change.to_raw()) } - Self::RemoveMarkets(fee_change) => { - raw::fee_change::FeeComponents::RemoveMarkets(fee_change.to_raw()) - } }), } } @@ -2207,14 +2141,8 @@ impl Protobuf for FeeChange { Some(raw::fee_change::FeeComponents::IbcSudoChange(fee_change)) => Self::IbcSudoChange( FeeComponents::::try_from_raw_ref(fee_change)?, ), - Some(raw::fee_change::FeeComponents::UpsertMarkets(fee_change)) => Self::UpsertMarkets( - FeeComponents::::try_from_raw_ref(fee_change)?, - ), - Some(raw::fee_change::FeeComponents::CreateMarkets(fee_change)) => Self::CreateMarkets( - FeeComponents::::try_from_raw_ref(fee_change)?, - ), - Some(raw::fee_change::FeeComponents::UpdateMarkets(fee_change)) => Self::UpdateMarkets( - FeeComponents::::try_from_raw_ref(fee_change)?, + Some(raw::fee_change::FeeComponents::ChangeMarkets(fee_change)) => Self::ChangeMarkets( + FeeComponents::::try_from_raw_ref(fee_change)?, ), Some(raw::fee_change::FeeComponents::UpdateMarketMapParams(fee_change)) => { Self::UpdateMarketMapParams( @@ -2226,9 +2154,6 @@ impl Protobuf for FeeChange { FeeComponents::::try_from_raw_ref(fee_change)?, ) } - Some(raw::fee_change::FeeComponents::RemoveMarkets(fee_change)) => Self::RemoveMarkets( - FeeComponents::::try_from_raw_ref(fee_change)?, - ), None => return Err(FeeChangeError::field_unset("fee_components")), }) } @@ -2318,21 +2243,9 @@ impl From> for FeeChange { } } -impl From> for FeeChange { - fn from(fee: FeeComponents) -> Self { - FeeChange::UpsertMarkets(fee) - } -} - -impl From> for FeeChange { - fn from(fee: FeeComponents) -> Self { - FeeChange::CreateMarkets(fee) - } -} - -impl From> for FeeChange { - fn from(fee: FeeComponents) -> Self { - FeeChange::UpdateMarkets(fee) +impl From> for FeeChange { + fn from(fee: FeeComponents) -> Self { + FeeChange::ChangeMarkets(fee) } } @@ -2342,175 +2255,98 @@ impl From> for FeeChange { } } -impl From> for FeeChange { - fn from(fee: FeeComponents) -> Self { - FeeChange::RemoveMarkets(fee) - } -} - -/// Takes a list of markets and either updates them if they are already in the market map, or -/// creates them if they are not. If no market map is found, one will be created. Must be signed by -/// an address included in the market map [`Params`]' `market_authorities`. +/// Takes a list of markets and either creates, updates existing, or removes existing markets. Must +/// be signed by an address included in the market map [`Params`]' `market_authorities`. #[derive(Debug, Clone)] -pub struct UpsertMarkets { - // The list of all markets to be upserted for the given - // transaction. - pub markets: Vec, +pub enum ChangeMarkets { + Create(Vec), + Update(Vec), + Remove(Vec), } -impl Protobuf for UpsertMarkets { - type Error = UpsertMarketsError; - type Raw = raw::UpsertMarkets; +impl Protobuf for ChangeMarkets { + type Error = ChangeMarketsError; + type Raw = raw::ChangeMarkets; fn try_from_raw_ref(raw: &Self::Raw) -> Result { - let markets = raw - .markets - .iter() - .map(|market| Market::try_from_raw(market.clone())) - .collect::, _>>() - .map_err(UpsertMarketsError::invalid_market)?; - Ok(Self { - markets, - }) - } - - fn to_raw(&self) -> Self::Raw { - Self::Raw { - markets: self - .markets - .iter() - .map(|market| market.clone().into_raw()) - .collect(), + match &raw.action { + Some(raw::change_markets::Action::Create(markets)) => Ok(Self::Create( + markets + .markets + .iter() + .map(|market| Market::try_from_raw(market.clone())) + .collect::>() + .map_err(ChangeMarketsError::invalid_market)?, + )), + Some(raw::change_markets::Action::Update(markets)) => Ok(Self::Update( + markets + .markets + .iter() + .map(|market| Market::try_from_raw(market.clone())) + .collect::>() + .map_err(ChangeMarketsError::invalid_market)?, + )), + Some(raw::change_markets::Action::Remove(markets)) => Ok(Self::Remove( + markets + .markets + .iter() + .map(|market| Market::try_from_raw(market.clone())) + .collect::>() + .map_err(ChangeMarketsError::invalid_market)?, + )), + None => Err(ChangeMarketsError::missing_markets()), } } -} - -#[derive(Debug, thiserror::Error)] -#[error(transparent)] -pub struct UpsertMarketsError(UpsertMarketsErrorKind); - -impl UpsertMarketsError { - #[must_use] - pub fn invalid_market(err: MarketError) -> Self { - Self(UpsertMarketsErrorKind::InvalidMarket(err)) - } -} - -#[derive(Debug, thiserror::Error)] -pub enum UpsertMarketsErrorKind { - #[error("invalid market in market list")] - InvalidMarket(#[from] MarketError), -} - -/// Takes a list of markets and creates them in the market map. If any already exist, this will err. -/// If no market map is found, one will be created. Must be signed by an address included in the -/// market map [`Params`]' `market_authorities`. -#[derive(Debug, Clone)] -pub struct CreateMarkets { - /// The list of all markets to be created for the given - /// transaction. - pub create_markets: Vec, -} - -impl Protobuf for CreateMarkets { - type Error = CreateMarketsError; - type Raw = raw::CreateMarkets; - - fn try_from_raw_ref(raw: &Self::Raw) -> Result { - let create_markets = raw - .create_markets - .iter() - .map(|market| Market::try_from_raw(market.clone())) - .collect::, _>>() - .map_err(CreateMarketsError::invalid_market)?; - Ok(Self { - create_markets, - }) - } fn to_raw(&self) -> Self::Raw { + let action = match self { + Self::Create(markets) => raw::change_markets::Action::Create(raw::Markets { + markets: markets + .iter() + .map(|market| Market::into_raw(market.clone())) + .collect(), + }), + Self::Update(markets) => raw::change_markets::Action::Update(raw::Markets { + markets: markets + .iter() + .map(|market| Market::into_raw(market.clone())) + .collect(), + }), + Self::Remove(markets) => raw::change_markets::Action::Remove(raw::Markets { + markets: markets + .iter() + .map(|market| Market::into_raw(market.clone())) + .collect(), + }), + }; Self::Raw { - create_markets: self - .create_markets - .iter() - .map(|market| market.clone().into_raw()) - .collect(), + action: Some(action), } } } #[derive(Debug, thiserror::Error)] #[error(transparent)] -pub struct CreateMarketsError(CreateMarketsErrorKind); +pub struct ChangeMarketsError(ChangeMarketsErrorKind); -impl CreateMarketsError { +impl ChangeMarketsError { #[must_use] pub fn invalid_market(err: MarketError) -> Self { - Self(CreateMarketsErrorKind::InvalidMarket(err)) - } -} - -#[derive(Debug, thiserror::Error)] -pub enum CreateMarketsErrorKind { - #[error("invalid market in create_market list")] - InvalidMarket(#[from] MarketError), - #[error("authority string could not be parsed to address")] - AuthorityParse(#[from] AddressError), -} - -/// Takes a list of markets and updates them in the market map (matching based on its -/// ticker's `currency_pair`). If no market map is found, or any market is missing a counterpart in -/// the map, this will err. Must be signed by an address included in the market map [`Params`]' -/// `market_authorities`. -#[derive(Debug, Clone)] -pub struct UpdateMarkets { - /// The list of all markets to be updated for the given - /// transaction. - pub update_markets: Vec, -} - -impl Protobuf for UpdateMarkets { - type Error = UpdateMarketsError; - type Raw = raw::UpdateMarkets; - - fn try_from_raw_ref(raw: &Self::Raw) -> Result { - let update_markets = raw - .update_markets - .iter() - .map(|market| Market::try_from_raw(market.clone())) - .collect::, _>>() - .map_err(UpdateMarketsError::invalid_market)?; - Ok(Self { - update_markets, - }) - } - - fn to_raw(&self) -> Self::Raw { - Self::Raw { - update_markets: self - .update_markets - .iter() - .map(|market| market.clone().into_raw()) - .collect(), - } + Self(ChangeMarketsErrorKind::InvalidMarket(err)) } -} -#[derive(Debug, thiserror::Error)] -#[error(transparent)] -pub struct UpdateMarketsError(UpdateMarketsErrorKind); - -impl UpdateMarketsError { #[must_use] - pub fn invalid_market(err: MarketError) -> Self { - Self(UpdateMarketsErrorKind::InvalidMarket(err)) + pub fn missing_markets() -> Self { + Self(ChangeMarketsErrorKind::MissingMarkets) } } #[derive(Debug, thiserror::Error)] -pub enum UpdateMarketsErrorKind { - #[error("invalid market in update_market list")] +pub enum ChangeMarketsErrorKind { + #[error("invalid market in market list")] InvalidMarket(#[from] MarketError), + #[error("change market action contained no markets to change")] + MissingMarkets, } /// Updates the market map Params, which contains the market authority addresses as well as an admin @@ -2624,36 +2460,3 @@ pub enum RemoveMarketAuthoritiesErrorKind { #[error("address in remove_addresses could not be parsed to domain type")] RemoveAddressParse(#[source] AddressError), } - -/// Takes a list of markets and removes them from the market map. If a market is not found in the -/// map, it will be ignored. Must be signed by an address included in the market map [`Params`]' -/// `market_authorities`. -#[derive(Debug, Clone)] -pub struct RemoveMarkets { - /// The list of all markets to be removed. - pub markets: Vec, -} - -impl Protobuf for RemoveMarkets { - type Error = RemoveMarketsError; - type Raw = raw::RemoveMarkets; - - fn try_from_raw_ref(raw: &Self::Raw) -> Result { - Ok(Self { - markets: raw.markets.clone(), - }) - } - - fn to_raw(&self) -> Self::Raw { - Self::Raw { - markets: self.markets.clone(), - } - } -} - -#[derive(Debug, thiserror::Error)] -#[error(transparent)] -pub struct RemoveMarketsError(RemoveMarketsErrorKind); - -#[derive(Debug, thiserror::Error)] -pub enum RemoveMarketsErrorKind {} diff --git a/crates/astria-sequencer-utils/src/genesis_example.rs b/crates/astria-sequencer-utils/src/genesis_example.rs index 7f3dbba1b0..eb4255d827 100644 --- a/crates/astria-sequencer-utils/src/genesis_example.rs +++ b/crates/astria-sequencer-utils/src/genesis_example.rs @@ -40,7 +40,7 @@ use astria_core::{ BridgeLock, BridgeSudoChange, BridgeUnlock, - CreateMarkets, + ChangeMarkets, FeeAssetChange, FeeChange, IbcRelayerChange, @@ -48,13 +48,10 @@ use astria_core::{ Ics20Withdrawal, InitBridgeAccount, RemoveMarketAuthorities, - RemoveMarkets, RollupDataSubmission, SudoAddressChange, Transfer, UpdateMarketMapParams, - UpdateMarkets, - UpsertMarkets, ValidatorUpdate, }, }, @@ -253,16 +250,13 @@ fn proto_genesis_state() -> astria_core::generated::astria::protocol::genesis::v ibc_relayer_change: Some(FeeComponents::::new(0, 0).to_raw()), sudo_address_change: Some(FeeComponents::::new(0, 0).to_raw()), ibc_sudo_change: Some(FeeComponents::::new(0, 0).to_raw()), - upsert_markets: Some(FeeComponents::::new(0, 0).to_raw()), - create_markets: Some(FeeComponents::::new(0, 0).to_raw()), - update_markets: Some(FeeComponents::::new(0, 0).to_raw()), + change_markets: Some(FeeComponents::::new(0, 0).to_raw()), update_market_map_params: Some( FeeComponents::::new(0, 0).to_raw(), ), remove_market_authorities: Some( FeeComponents::::new(0, 0).to_raw(), ), - remove_markets: Some(FeeComponents::::new(0, 0).to_raw()), }), } } diff --git a/crates/astria-sequencer/src/action_handler/impls/update_markets.rs b/crates/astria-sequencer/src/action_handler/impls/change_markets.rs similarity index 53% rename from crates/astria-sequencer/src/action_handler/impls/update_markets.rs rename to crates/astria-sequencer/src/action_handler/impls/change_markets.rs index 49716eb581..547ca8af4a 100644 --- a/crates/astria-sequencer/src/action_handler/impls/update_markets.rs +++ b/crates/astria-sequencer/src/action_handler/impls/change_markets.rs @@ -1,12 +1,22 @@ -use astria_core::protocol::transaction::v1::action::UpdateMarkets; +use astria_core::{ + connect::market_map::v2::MarketMap, + protocol::transaction::v1::action::ChangeMarkets::{ + self, + Create, + Remove, + Update, + }, +}; use astria_eyre::eyre::{ self, + bail, ensure, eyre, Context as _, OptionExt as _, }; use cnidarium::StateWrite; +use indexmap::IndexMap; use crate::{ action_handler::ActionHandler, @@ -20,7 +30,7 @@ use crate::{ }; #[async_trait::async_trait] -impl ActionHandler for UpdateMarkets { +impl ActionHandler for ChangeMarkets { async fn check_stateless(&self) -> eyre::Result<()> { Ok(()) } @@ -46,20 +56,44 @@ impl ActionHandler for UpdateMarkets { "address {from} is not a market authority" ); - // update existing markets, erroring if any do not exist in the current map + // create a new market map if one does not already exist let mut market_map = state .get_market_map() .await .wrap_err("failed to get market map")? - .ok_or_eyre("market map not found in state")?; - for market in &self.update_markets { - let ticker_key = market.ticker.currency_pair.to_string(); - *market_map - .markets - .get_mut(&ticker_key) - .ok_or_else(|| eyre!("market for ticker {ticker_key} not found in market map"))? = - market.clone(); - } + .unwrap_or(MarketMap { + markets: IndexMap::new(), + }); + match self { + Create(create_markets) => { + for market in create_markets { + let ticker_key = market.ticker.currency_pair.to_string(); + if market_map.markets.contains_key(&ticker_key) { + bail!("market for ticker {ticker_key} already exists"); + } + market_map.markets.insert(ticker_key, market.clone()); + } + } + Update(update_markets) => { + if market_map.markets.is_empty() { + bail!("market map is empty"); + } + for market in update_markets { + let ticker_key = market.ticker.currency_pair.to_string(); + *market_map.markets.get_mut(&ticker_key).ok_or_else(|| { + eyre!("market for ticker {ticker_key} not found in market map") + })? = market.clone(); + } + } + Remove(remove_markets) => { + for key in remove_markets { + market_map + .markets + .shift_remove(&key.ticker.currency_pair.to_string()); + } + } + }; + state .put_market_map(market_map) .wrap_err("failed to put market map into state")?; @@ -83,23 +117,24 @@ mod tests { use astria_core::{ connect::market_map::v2::{ Market, - MarketMap, Params, }, primitive::v1::TransactionId, }; - use indexmap::IndexMap; use super::*; use crate::{ - accounts::AddressBytes as _, + accounts::AddressBytes, address::StateWriteExt as _, app::StateWriteExt as _, benchmark_and_test_utils::{ astria_address, ASTRIA_PREFIX, }, - test_utils::example_ticker_with_metadata, + test_utils::{ + example_ticker_from_currency_pair, + example_ticker_with_metadata, + }, transaction::{ StateWriteExt as _, TransactionContext, @@ -107,13 +142,19 @@ mod tests { }; #[tokio::test] - async fn update_markets_executes_as_expected() { + async fn create_markets_executes_as_expected() { let storage = cnidarium::TempStorage::new().await.unwrap(); let snapshot = storage.latest_snapshot(); let mut state = cnidarium::StateDelta::new(snapshot); let authority_address = astria_address(&[0; 20]); + let params = Params { + market_authorities: vec![authority_address], + admin: authority_address, + }; + state.put_params(params).unwrap(); + state.put_block_height(1).unwrap(); state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); state.put_transaction_context(TransactionContext { @@ -122,44 +163,13 @@ mod tests { position_in_transaction: 0, }); - let params = Params { - market_authorities: vec![authority_address], - admin: authority_address, - }; - state.put_params(params).unwrap(); - - let ticker_1 = example_ticker_with_metadata("ticker_1".to_string()); - let market_1 = Market { - ticker: ticker_1.clone(), - provider_configs: vec![], - }; - - let mut markets = IndexMap::new(); - markets.insert(ticker_1.currency_pair.to_string(), market_1.clone()); - let initial_market_map = MarketMap { - markets, - }; - state.put_market_map(initial_market_map).unwrap(); - let market_map = state.get_market_map().await.unwrap().unwrap(); - assert_eq!(market_map.markets.len(), 1); - assert_eq!( - *market_map - .markets - .get(&ticker_1.currency_pair.to_string()) - .unwrap(), - market_1, - ); - - let ticker = example_ticker_with_metadata("ticker".to_string()); + let ticker = example_ticker_with_metadata(String::new()); let market = Market { ticker: ticker.clone(), provider_configs: vec![], }; - let action = UpdateMarkets { - update_markets: vec![market.clone()], - }; - + let action = ChangeMarkets::Create(vec![market.clone()]); action.check_and_execute(&mut state).await.unwrap(); let market_map = state.get_market_map().await.unwrap().unwrap(); assert_eq!(market_map.markets.len(), 1); @@ -174,13 +184,65 @@ mod tests { } #[tokio::test] - async fn update_markets_fails_if_market_is_not_in_market_map() { + async fn change_markets_fails_if_authority_is_invalid() { + let storage = cnidarium::TempStorage::new().await.unwrap(); + let snapshot = storage.latest_snapshot(); + let mut state = cnidarium::StateDelta::new(snapshot); + + let authority_address = astria_address(&[0; 20]); + + let params = Params { + market_authorities: vec![], // should fail even though the authority address is admin + admin: authority_address, + }; + state.put_params(params).unwrap(); + + state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); + state.put_transaction_context(TransactionContext { + address_bytes: *authority_address.address_bytes(), + transaction_id: TransactionId::new([0; 32]), + position_in_transaction: 0, + }); + + let action = ChangeMarkets::Create(vec![]); + let res = action.check_and_execute(&mut state).await.unwrap_err(); + assert!(res.to_string().contains(&format!( + "address {authority_address} is not a market authority" + ))); + assert!(state.get_market_map().await.unwrap().is_none()); + } + + #[tokio::test] + async fn change_markets_fails_if_params_not_found() { + let storage = cnidarium::TempStorage::new().await.unwrap(); + let snapshot = storage.latest_snapshot(); + let mut state = cnidarium::StateDelta::new(snapshot); + + state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); + state.put_transaction_context(TransactionContext { + address_bytes: [0; 20], + transaction_id: TransactionId::new([0; 32]), + position_in_transaction: 0, + }); + + let action = ChangeMarkets::Create(vec![]); + let res = action.check_and_execute(&mut state).await.unwrap_err(); + assert!( + res.to_string() + .contains("market map params not found in state") + ); + assert!(state.get_market_map().await.unwrap().is_none()); + } + + #[tokio::test] + async fn remove_markets_executes_as_expected() { let storage = cnidarium::TempStorage::new().await.unwrap(); let snapshot = storage.latest_snapshot(); let mut state = cnidarium::StateDelta::new(snapshot); let authority_address = astria_address(&[0; 20]); + state.put_block_height(1).unwrap(); state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); state.put_transaction_context(TransactionContext { address_bytes: *authority_address.address_bytes(), @@ -194,37 +256,93 @@ mod tests { }; state.put_params(params).unwrap(); + let ticker = example_ticker_with_metadata(String::new()); + + let mut markets = IndexMap::new(); + markets.insert( + ticker.currency_pair.to_string(), + Market { + ticker: ticker.clone(), + provider_configs: vec![], + }, + ); + state .put_market_map(MarketMap { - markets: IndexMap::new(), + markets, }) .unwrap(); - let ticker = example_ticker_with_metadata("ticker".to_string()); + let action = ChangeMarkets::Remove(vec![Market { + ticker, + provider_configs: vec![], + }]); + action.check_and_execute(&mut state).await.unwrap(); + let market_map = state.get_market_map().await.unwrap().unwrap(); + assert_eq!(market_map.markets.len(), 0); + assert_eq!(state.get_market_map_last_updated_height().await.unwrap(), 1); + } + + #[tokio::test] + async fn remove_markets_skips_missing_markets() { + let storage = cnidarium::TempStorage::new().await.unwrap(); + let snapshot = storage.latest_snapshot(); + let mut state = cnidarium::StateDelta::new(snapshot); + + let authority_address = astria_address(&[0; 20]); + + state.put_block_height(1).unwrap(); + state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); + state.put_transaction_context(TransactionContext { + address_bytes: *authority_address.address_bytes(), + transaction_id: TransactionId::new([0; 32]), + position_in_transaction: 0, + }); + + let params = Params { + market_authorities: vec![authority_address], + admin: authority_address, + }; + state.put_params(params).unwrap(); + + let ticker = example_ticker_with_metadata(String::new()); let market = Market { ticker: ticker.clone(), provider_configs: vec![], }; - let action = UpdateMarkets { - update_markets: vec![market.clone()], - }; + let mut markets = IndexMap::new(); + markets.insert(ticker.currency_pair.to_string(), market.clone()); - let res = action.check_and_execute(&mut state).await.unwrap_err(); - assert!(res.to_string().contains(&format!( - "market for ticker {} not found in market map", - ticker.currency_pair - ))); + state + .put_market_map(MarketMap { + markets, + }) + .unwrap(); + + let action = ChangeMarkets::Remove(vec![Market { + ticker: example_ticker_from_currency_pair("DIFBASE", "DIFQUOTE", String::new()), + provider_configs: vec![], + }]); + action.check_and_execute(&mut state).await.unwrap(); + let market_map = state.get_market_map().await.unwrap().unwrap(); + assert_eq!(market_map.markets.len(), 1); + assert_eq!( + market_map.markets.get(&ticker.currency_pair.to_string()), + Some(&market) + ); + assert_eq!(state.get_market_map_last_updated_height().await.unwrap(), 1); } #[tokio::test] - async fn update_markets_fails_if_market_map_is_not_in_state() { + async fn update_markets_executes_as_expected() { let storage = cnidarium::TempStorage::new().await.unwrap(); let snapshot = storage.latest_snapshot(); let mut state = cnidarium::StateDelta::new(snapshot); let authority_address = astria_address(&[0; 20]); + state.put_block_height(1).unwrap(); state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); state.put_transaction_context(TransactionContext { address_bytes: *authority_address.address_bytes(), @@ -238,16 +356,51 @@ mod tests { }; state.put_params(params).unwrap(); - let action = UpdateMarkets { - update_markets: vec![], + let ticker_1 = example_ticker_with_metadata("ticker_1".to_string()); + let market_1 = Market { + ticker: ticker_1.clone(), + provider_configs: vec![], }; - let res = action.check_and_execute(&mut state).await.unwrap_err(); - assert!(res.to_string().contains("market map not found in state")); + let mut markets = IndexMap::new(); + markets.insert(ticker_1.currency_pair.to_string(), market_1.clone()); + let initial_market_map = MarketMap { + markets, + }; + state.put_market_map(initial_market_map).unwrap(); + let market_map = state.get_market_map().await.unwrap().unwrap(); + assert_eq!(market_map.markets.len(), 1); + assert_eq!( + *market_map + .markets + .get(&ticker_1.currency_pair.to_string()) + .unwrap(), + market_1, + ); + + let ticker = example_ticker_with_metadata("ticker".to_string()); + let market = Market { + ticker: ticker.clone(), + provider_configs: vec![], + }; + + let action = ChangeMarkets::Update(vec![market.clone()]); + + action.check_and_execute(&mut state).await.unwrap(); + let market_map = state.get_market_map().await.unwrap().unwrap(); + assert_eq!(market_map.markets.len(), 1); + assert_eq!( + *market_map + .markets + .get(&ticker.currency_pair.to_string()) + .unwrap(), + market, + ); + assert_eq!(state.get_market_map_last_updated_height().await.unwrap(), 1); } #[tokio::test] - async fn update_markets_fails_if_authority_is_invalid() { + async fn update_markets_fails_if_market_is_not_in_market_map() { let storage = cnidarium::TempStorage::new().await.unwrap(); let snapshot = storage.latest_snapshot(); let mut state = cnidarium::StateDelta::new(snapshot); @@ -262,42 +415,68 @@ mod tests { }); let params = Params { - market_authorities: vec![], // should fail even though the authority address is admin + market_authorities: vec![authority_address], admin: authority_address, }; state.put_params(params).unwrap(); - let action = UpdateMarkets { - update_markets: vec![], + let ticker = example_ticker_with_metadata("ticker".to_string()); + let market = Market { + ticker: ticker.clone(), + provider_configs: vec![], + }; + + let different_ticker = example_ticker_from_currency_pair( + "difbase", + "difquote", + "different ticker".to_string(), + ); + let different_market = Market { + ticker: different_ticker.clone(), + provider_configs: vec![], }; + let mut market_map = MarketMap { + markets: IndexMap::new(), + }; + market_map.markets.insert( + different_ticker.currency_pair.to_string(), + different_market.clone(), + ); + state.put_market_map(market_map).unwrap(); + + let action = ChangeMarkets::Update(vec![market.clone()]); + let res = action.check_and_execute(&mut state).await.unwrap_err(); assert!(res.to_string().contains(&format!( - "address {authority_address} is not a market authority" + "market for ticker {} not found in market map", + ticker.currency_pair ))); - assert!(state.get_market_map().await.unwrap().is_none()); } #[tokio::test] - async fn update_markets_fails_if_params_not_found() { + async fn update_markets_fails_if_market_map_is_not_in_state() { let storage = cnidarium::TempStorage::new().await.unwrap(); let snapshot = storage.latest_snapshot(); let mut state = cnidarium::StateDelta::new(snapshot); + let authority_address = astria_address(&[0; 20]); + state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); state.put_transaction_context(TransactionContext { - address_bytes: [0; 20], + address_bytes: *authority_address.address_bytes(), transaction_id: TransactionId::new([0; 32]), position_in_transaction: 0, }); - let action = UpdateMarkets { - update_markets: vec![], + let params = Params { + market_authorities: vec![authority_address], + admin: authority_address, }; + state.put_params(params).unwrap(); + + let action = ChangeMarkets::Update(vec![]); + let res = action.check_and_execute(&mut state).await.unwrap_err(); - assert!( - res.to_string() - .contains("market map params not found in state") - ); - assert!(state.get_market_map().await.unwrap().is_none()); + assert!(res.to_string().contains("market map is empty")); } } diff --git a/crates/astria-sequencer/src/action_handler/impls/create_markets.rs b/crates/astria-sequencer/src/action_handler/impls/create_markets.rs deleted file mode 100644 index 7691302ca5..0000000000 --- a/crates/astria-sequencer/src/action_handler/impls/create_markets.rs +++ /dev/null @@ -1,210 +0,0 @@ -use astria_core::{ - connect::market_map::v2::MarketMap, - protocol::transaction::v1::action::CreateMarkets, -}; -use astria_eyre::eyre::{ - self, - bail, - ensure, - Context as _, - OptionExt as _, -}; -use cnidarium::StateWrite; -use indexmap::IndexMap; - -use crate::{ - action_handler::ActionHandler, - address::StateReadExt as _, - app::StateReadExt as _, - connect::market_map::state_ext::{ - StateReadExt as _, - StateWriteExt as _, - }, - transaction::StateReadExt as _, -}; - -#[async_trait::async_trait] -impl ActionHandler for CreateMarkets { - async fn check_stateless(&self) -> eyre::Result<()> { - Ok(()) - } - - async fn check_and_execute(&self, mut state: S) -> eyre::Result<()> { - // check that the signer of the transaction is a market authority - let from = state - .try_base_prefixed( - &state - .get_transaction_context() - .expect("transaction source must be present in state when executing an action") - .address_bytes(), - ) - .await - .wrap_err("failed to convert signer address to base prefixed address")?; - let market_authorities = state - .get_params() - .await? - .ok_or_eyre("market map params not found in state")? - .market_authorities; - ensure!( - market_authorities.contains(&from), - "address {from} is not a market authority" - ); - - // create markets, erroring if any already exist - let mut market_map = state - .get_market_map() - .await - .wrap_err("failed to get market map")? - .unwrap_or(MarketMap { - markets: IndexMap::new(), - }); - for market in &self.create_markets { - let ticker_key = market.ticker.currency_pair.to_string(); - if market_map.markets.contains_key(&ticker_key) { - bail!("market for ticker {ticker_key} already exists"); - } - market_map.markets.insert(ticker_key, market.clone()); - } - state - .put_market_map(market_map) - .wrap_err("failed to put market map into state")?; - - // update the last updated height for the market map - state - .put_market_map_last_updated_height( - state - .get_block_height() - .await - .wrap_err("failed to get block height")?, - ) - .wrap_err("failed to update latest market map height")?; - Ok(()) - } -} - -#[cfg(test)] -mod tests { - - use astria_core::{ - connect::market_map::v2::{ - Market, - Params, - }, - primitive::v1::TransactionId, - }; - - use super::*; - use crate::{ - accounts::AddressBytes, - address::StateWriteExt as _, - app::StateWriteExt as _, - benchmark_and_test_utils::{ - astria_address, - ASTRIA_PREFIX, - }, - test_utils::example_ticker_with_metadata, - transaction::{ - StateWriteExt as _, - TransactionContext, - }, - }; - - #[tokio::test] - async fn create_markets_executes_as_expected() { - let storage = cnidarium::TempStorage::new().await.unwrap(); - let snapshot = storage.latest_snapshot(); - let mut state = cnidarium::StateDelta::new(snapshot); - - let authority_address = astria_address(&[0; 20]); - - let params = Params { - market_authorities: vec![authority_address], - admin: authority_address, - }; - state.put_params(params).unwrap(); - - state.put_block_height(1).unwrap(); - state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); - state.put_transaction_context(TransactionContext { - address_bytes: *authority_address.address_bytes(), - transaction_id: TransactionId::new([0; 32]), - position_in_transaction: 0, - }); - - let ticker = example_ticker_with_metadata(String::new()); - let market = Market { - ticker: ticker.clone(), - provider_configs: vec![], - }; - - let action = CreateMarkets { - create_markets: vec![market.clone()], - }; - action.check_and_execute(&mut state).await.unwrap(); - let market_map = state.get_market_map().await.unwrap().unwrap(); - assert_eq!(market_map.markets.len(), 1); - assert_eq!( - *market_map - .markets - .get(&ticker.currency_pair.to_string()) - .unwrap(), - market, - ); - assert_eq!(state.get_market_map_last_updated_height().await.unwrap(), 1); - } - - #[tokio::test] - async fn create_markets_fails_if_authority_is_invalid() { - let storage = cnidarium::TempStorage::new().await.unwrap(); - let snapshot = storage.latest_snapshot(); - let mut state = cnidarium::StateDelta::new(snapshot); - - let authority_address = astria_address(&[0; 20]); - - let params = Params { - market_authorities: vec![], // should fail even though the authority address is admin - admin: authority_address, - }; - state.put_params(params).unwrap(); - - state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); - state.put_transaction_context(TransactionContext { - address_bytes: *authority_address.address_bytes(), - transaction_id: TransactionId::new([0; 32]), - position_in_transaction: 0, - }); - - let action = CreateMarkets { - create_markets: vec![], - }; - let res = action.check_and_execute(&mut state).await.unwrap_err(); - assert!(res.to_string().contains(&format!( - "address {authority_address} is not a market authority" - ))); - assert!(state.get_market_map().await.unwrap().is_none()); - } - - #[tokio::test] - async fn create_markets_fails_if_params_not_found() { - let storage = cnidarium::TempStorage::new().await.unwrap(); - let snapshot = storage.latest_snapshot(); - let mut state = cnidarium::StateDelta::new(snapshot); - - state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); - state.put_transaction_context(TransactionContext { - address_bytes: [0; 20], - transaction_id: TransactionId::new([0; 32]), - position_in_transaction: 0, - }); - - let action = CreateMarkets { - create_markets: vec![], - }; - let res = action.check_and_execute(&mut state).await.unwrap_err(); - assert!( - res.to_string() - .contains("market map params not found in state") - ); - assert!(state.get_market_map().await.unwrap().is_none()); - } -} diff --git a/crates/astria-sequencer/src/action_handler/impls/fee_change.rs b/crates/astria-sequencer/src/action_handler/impls/fee_change.rs index 546c757635..9a301aa7f5 100644 --- a/crates/astria-sequencer/src/action_handler/impls/fee_change.rs +++ b/crates/astria-sequencer/src/action_handler/impls/fee_change.rs @@ -82,24 +82,15 @@ impl ActionHandler for FeeChange { Self::IbcSudoChange(fees) => state .put_fees(*fees) .wrap_err("failed to put ibc sudo change fees"), - Self::UpsertMarkets(fees) => state + Self::ChangeMarkets(fees) => state .put_fees(*fees) - .wrap_err("failed to put upsert markets fees"), - Self::CreateMarkets(fees) => state - .put_fees(*fees) - .wrap_err("failed to put create markets fees"), - Self::UpdateMarkets(fees) => state - .put_fees(*fees) - .wrap_err("failed to put update markets fees"), + .wrap_err("failed to put change markets fees"), Self::UpdateMarketMapParams(fees) => state .put_fees(*fees) .wrap_err("failed to put update params fees"), Self::RemoveMarketAuthorities(fees) => state .put_fees(*fees) .wrap_err("failed to put remove market authorities fees"), - Self::RemoveMarkets(fees) => state - .put_fees(*fees) - .wrap_err("failed to put remove markets fees"), } } } @@ -203,18 +194,8 @@ mod tests { } #[tokio::test] - async fn upsert_markets_fee_change_action_executes_as_expected() { - test_fee_change_action::().await; - } - - #[tokio::test] - async fn create_markets_fee_change_action_executes_as_expected() { - test_fee_change_action::().await; - } - - #[tokio::test] - async fn update_markets_fee_change_action_executes_as_expected() { - test_fee_change_action::().await; + async fn change_markets_fee_change_action_executes_as_expected() { + test_fee_change_action::().await; } #[tokio::test] @@ -222,11 +203,6 @@ mod tests { test_fee_change_action::().await; } - #[tokio::test] - async fn remove_markets_fee_change_action_executes_as_expected() { - test_fee_change_action::().await; - } - async fn test_fee_change_action<'a, F>() where F: FeeHandler, diff --git a/crates/astria-sequencer/src/action_handler/impls/mod.rs b/crates/astria-sequencer/src/action_handler/impls/mod.rs index d9c89581f0..a79ec9059e 100644 --- a/crates/astria-sequencer/src/action_handler/impls/mod.rs +++ b/crates/astria-sequencer/src/action_handler/impls/mod.rs @@ -1,7 +1,7 @@ pub(crate) mod bridge_lock; pub(crate) mod bridge_sudo_change; pub(crate) mod bridge_unlock; -pub(crate) mod create_markets; +pub(crate) mod change_markets; pub(crate) mod fee_asset_change; pub(crate) mod fee_change; pub(crate) mod ibc_relayer_change; @@ -9,7 +9,6 @@ pub(crate) mod ibc_sudo_change; pub(crate) mod ics20_withdrawal; pub(crate) mod init_bridge_account; pub(crate) mod remove_market_authorities; -pub(crate) mod remove_markets; pub(crate) mod rollup_data_submission; pub(crate) mod sudo_address_change; #[cfg(test)] @@ -17,6 +16,4 @@ pub(crate) mod test_utils; pub(crate) mod transaction; pub(crate) mod transfer; pub(crate) mod update_market_map_params; -pub(crate) mod update_markets; -pub(crate) mod upsert_markets; pub(crate) mod validator_update; diff --git a/crates/astria-sequencer/src/action_handler/impls/remove_markets.rs b/crates/astria-sequencer/src/action_handler/impls/remove_markets.rs deleted file mode 100644 index 71009e425c..0000000000 --- a/crates/astria-sequencer/src/action_handler/impls/remove_markets.rs +++ /dev/null @@ -1,265 +0,0 @@ -use astria_core::{ - connect::market_map::v2::MarketMap, - protocol::transaction::v1::action::RemoveMarkets, -}; -use astria_eyre::eyre::{ - self, - ensure, - Context as _, - OptionExt as _, -}; -use cnidarium::StateWrite; -use indexmap::IndexMap; - -use crate::{ - action_handler::ActionHandler, - address::StateReadExt as _, - app::StateReadExt as _, - connect::market_map::state_ext::{ - StateReadExt as _, - StateWriteExt as _, - }, - transaction::StateReadExt as _, -}; - -#[async_trait::async_trait] -impl ActionHandler for RemoveMarkets { - async fn check_stateless(&self) -> eyre::Result<()> { - Ok(()) - } - - async fn check_and_execute(&self, mut state: S) -> eyre::Result<()> { - // check that the signer of the transaction is a market authority - let from = state - .try_base_prefixed( - &state - .get_transaction_context() - .expect("transaction source must be present in state when executing an action") - .address_bytes(), - ) - .await - .wrap_err("failed to convert signer address to base prefixed address")?; - let market_authorities = state - .get_params() - .await? - .ok_or_eyre("market map params not found in state")? - .market_authorities; - ensure!( - market_authorities.contains(&from), - "address {from} is not a market authority" - ); - - // remove markets, skipping any which do not exist - let mut market_map = state - .get_market_map() - .await - .wrap_err("failed to get market map")? - .unwrap_or(MarketMap { - markets: IndexMap::new(), - }); - for key in &self.markets { - market_map.markets.shift_remove(key); - } - state - .put_market_map(market_map) - .wrap_err("failed to put market map into state")?; - - // update the last updated height for the market map - state - .put_market_map_last_updated_height( - state - .get_block_height() - .await - .wrap_err("failed to get block height")?, - ) - .wrap_err("failed to update latest market map height")?; - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use astria_core::{ - connect::market_map::v2::{ - Market, - Params, - }, - primitive::v1::TransactionId, - }; - - use super::*; - use crate::{ - accounts::AddressBytes as _, - address::StateWriteExt as _, - app::StateWriteExt as _, - benchmark_and_test_utils::{ - astria_address, - ASTRIA_PREFIX, - }, - test_utils::{ - example_ticker_from_currency_pair, - example_ticker_with_metadata, - }, - transaction::{ - StateWriteExt as _, - TransactionContext, - }, - }; - - #[tokio::test] - async fn remove_markets_executes_as_expected() { - let storage = cnidarium::TempStorage::new().await.unwrap(); - let snapshot = storage.latest_snapshot(); - let mut state = cnidarium::StateDelta::new(snapshot); - - let authority_address = astria_address(&[0; 20]); - - state.put_block_height(1).unwrap(); - state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); - state.put_transaction_context(TransactionContext { - address_bytes: *authority_address.address_bytes(), - transaction_id: TransactionId::new([0; 32]), - position_in_transaction: 0, - }); - - let params = Params { - market_authorities: vec![authority_address], - admin: authority_address, - }; - state.put_params(params).unwrap(); - - let ticker = example_ticker_with_metadata(String::new()); - - let mut markets = IndexMap::new(); - markets.insert( - ticker.currency_pair.to_string(), - Market { - ticker: ticker.clone(), - provider_configs: vec![], - }, - ); - - state - .put_market_map(MarketMap { - markets, - }) - .unwrap(); - - let action = RemoveMarkets { - markets: vec![ticker.currency_pair.to_string()], - }; - action.check_and_execute(&mut state).await.unwrap(); - let market_map = state.get_market_map().await.unwrap().unwrap(); - assert_eq!(market_map.markets.len(), 0); - assert_eq!(state.get_market_map_last_updated_height().await.unwrap(), 1); - } - - #[tokio::test] - async fn remove_markets_fails_if_authority_is_invalid() { - let storage = cnidarium::TempStorage::new().await.unwrap(); - let snapshot = storage.latest_snapshot(); - let mut state = cnidarium::StateDelta::new(snapshot); - - let authority_address = astria_address(&[0; 20]); - - state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); - state.put_transaction_context(TransactionContext { - address_bytes: *authority_address.address_bytes(), - transaction_id: TransactionId::new([0; 32]), - position_in_transaction: 0, - }); - - let params = Params { - market_authorities: vec![], // should fail even though authority address is admin - admin: authority_address, - }; - state.put_params(params).unwrap(); - - let action = RemoveMarkets { - markets: vec![], - }; - let res = action.check_and_execute(&mut state).await.unwrap_err(); - assert!(state.get_market_map().await.unwrap().is_none()); - assert!(res.to_string().contains(&format!( - "address {authority_address} is not a market authority" - ))); - } - - #[tokio::test] - async fn remove_markets_fails_if_params_not_found() { - let storage = cnidarium::TempStorage::new().await.unwrap(); - let snapshot = storage.latest_snapshot(); - let mut state = cnidarium::StateDelta::new(snapshot); - - state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); - state.put_transaction_context(TransactionContext { - address_bytes: [0; 20], - transaction_id: TransactionId::new([0; 32]), - position_in_transaction: 0, - }); - - let action = RemoveMarkets { - markets: vec![], - }; - let res = action.check_and_execute(&mut state).await.unwrap_err(); - assert!(state.get_market_map().await.unwrap().is_none()); - assert!( - res.to_string() - .contains("market map params not found in state") - ); - } - - #[tokio::test] - async fn remove_markets_skips_missing_markets() { - let storage = cnidarium::TempStorage::new().await.unwrap(); - let snapshot = storage.latest_snapshot(); - let mut state = cnidarium::StateDelta::new(snapshot); - - let authority_address = astria_address(&[0; 20]); - - state.put_block_height(1).unwrap(); - state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); - state.put_transaction_context(TransactionContext { - address_bytes: *authority_address.address_bytes(), - transaction_id: TransactionId::new([0; 32]), - position_in_transaction: 0, - }); - - let params = Params { - market_authorities: vec![authority_address], - admin: authority_address, - }; - state.put_params(params).unwrap(); - - let ticker = example_ticker_with_metadata(String::new()); - let market = Market { - ticker: ticker.clone(), - provider_configs: vec![], - }; - - let mut markets = IndexMap::new(); - markets.insert(ticker.currency_pair.to_string(), market.clone()); - - state - .put_market_map(MarketMap { - markets, - }) - .unwrap(); - - let action = RemoveMarkets { - markets: vec![ - example_ticker_from_currency_pair("DIFBASE", "DIFQUOTE", String::new()) - .currency_pair - .to_string(), - ], - }; - action.check_and_execute(&mut state).await.unwrap(); - let market_map = state.get_market_map().await.unwrap().unwrap(); - assert_eq!(market_map.markets.len(), 1); - assert_eq!( - market_map.markets.get(&ticker.currency_pair.to_string()), - Some(&market) - ); - assert_eq!(state.get_market_map_last_updated_height().await.unwrap(), 1); - } -} diff --git a/crates/astria-sequencer/src/action_handler/impls/transaction.rs b/crates/astria-sequencer/src/action_handler/impls/transaction.rs index 64dbbf83fc..458645b8ad 100644 --- a/crates/astria-sequencer/src/action_handler/impls/transaction.rs +++ b/crates/astria-sequencer/src/action_handler/impls/transaction.rs @@ -146,18 +146,10 @@ impl ActionHandler for Transaction { .check_stateless() .await .wrap_err("stateless check failed for BridgeSudoChange action")?, - Action::UpsertMarkets(act) => act + Action::ChangeMarkets(act) => act .check_stateless() .await - .wrap_err("stateless check failed for UpsertMarkets action")?, - Action::CreateMarkets(act) => act - .check_stateless() - .await - .wrap_err("stateless check failed for CreateMarkets action")?, - Action::UpdateMarkets(act) => act - .check_stateless() - .await - .wrap_err("stateless check failed for UpdateMarkets action")?, + .wrap_err("stateless check failed for ChangeMarkets action")?, Action::UpdateMarketMapParams(act) => act .check_stateless() .await @@ -166,10 +158,6 @@ impl ActionHandler for Transaction { .check_stateless() .await .wrap_err("stateless check failed for RemoveMarketAuthorities action")?, - Action::RemoveMarkets(act) => act - .check_stateless() - .await - .wrap_err("stateless check failed for RemoveMarkets action")?, } } Ok(()) @@ -296,24 +284,15 @@ impl ActionHandler for Transaction { Action::BridgeSudoChange(act) => check_execute_and_pay_fees(act, &mut state) .await .wrap_err("failed executing bridge sudo change")?, - Action::UpsertMarkets(act) => check_execute_and_pay_fees(act, &mut state) - .await - .wrap_err("failed executing upsert markets")?, - Action::CreateMarkets(act) => check_execute_and_pay_fees(act, &mut state) + Action::ChangeMarkets(act) => check_execute_and_pay_fees(act, &mut state) .await - .wrap_err("failed executing create markets")?, - Action::UpdateMarkets(act) => check_execute_and_pay_fees(act, &mut state) - .await - .wrap_err("failed executing update markets")?, + .wrap_err("failed executing change markets")?, Action::UpdateMarketMapParams(act) => check_execute_and_pay_fees(act, &mut state) .await .wrap_err("failed executing update params")?, Action::RemoveMarketAuthorities(act) => check_execute_and_pay_fees(act, &mut state) .await .wrap_err("failed executing remove market authorities")?, - Action::RemoveMarkets(act) => check_execute_and_pay_fees(act, &mut state) - .await - .wrap_err("failed executing remove markets")?, } } diff --git a/crates/astria-sequencer/src/action_handler/impls/upsert_markets.rs b/crates/astria-sequencer/src/action_handler/impls/upsert_markets.rs deleted file mode 100644 index b9c0c5452a..0000000000 --- a/crates/astria-sequencer/src/action_handler/impls/upsert_markets.rs +++ /dev/null @@ -1,279 +0,0 @@ -use astria_core::{ - connect::market_map::v2::MarketMap, - protocol::transaction::v1::action::UpsertMarkets, -}; -use astria_eyre::eyre::{ - self, - ensure, - Context as _, - OptionExt as _, -}; -use cnidarium::StateWrite; -use indexmap::IndexMap; - -use crate::{ - action_handler::ActionHandler, - address::StateReadExt as _, - app::StateReadExt as _, - connect::market_map::state_ext::{ - StateReadExt as _, - StateWriteExt as _, - }, - transaction::StateReadExt as _, -}; - -#[async_trait::async_trait] -impl ActionHandler for UpsertMarkets { - async fn check_stateless(&self) -> eyre::Result<()> { - Ok(()) - } - - async fn check_and_execute(&self, mut state: S) -> eyre::Result<()> { - // check that the signer of the transaction is a market authority - let from = state - .try_base_prefixed( - &state - .get_transaction_context() - .expect("transaction source must be present in state when executing an action") - .address_bytes(), - ) - .await - .wrap_err("failed to convert signer address to base prefixed address")?; - let market_authorities = state - .get_params() - .await? - .ok_or_eyre("market map params not found in state")? - .market_authorities; - ensure!( - market_authorities.contains(&from), - "address {from} is not a market authority" - ); - - // upsert markets, updating any that already exist and creating any that do not - let mut market_map = state - .get_market_map() - .await - .wrap_err("failed to get market map")? - .unwrap_or(MarketMap { - markets: IndexMap::new(), - }); - for market in &self.markets { - let ticker_key = market.ticker.currency_pair.to_string(); - market_map - .markets - .entry(ticker_key) - .and_modify(|existing_market| { - *existing_market = market.clone(); - }) - .or_insert(market.clone()); - } - state - .put_market_map(market_map) - .wrap_err("failed to put market map into state")?; - - // update the last updated height of the market map - state - .put_market_map_last_updated_height( - state - .get_block_height() - .await - .wrap_err("failed to get block height")?, - ) - .wrap_err("failed to update latest market map height")?; - Ok(()) - } -} - -#[cfg(test)] -mod tests { - - use astria_core::{ - connect::market_map::v2::{ - Market, - Params, - }, - primitive::v1::TransactionId, - }; - - use super::*; - use crate::{ - accounts::AddressBytes as _, - address::StateWriteExt as _, - app::StateWriteExt as _, - benchmark_and_test_utils::{ - astria_address, - ASTRIA_PREFIX, - }, - test_utils::example_ticker_with_metadata, - transaction::{ - StateWriteExt as _, - TransactionContext, - }, - }; - - #[tokio::test] - async fn upsert_markets_creates_market_as_expected() { - let storage = cnidarium::TempStorage::new().await.unwrap(); - let snapshot = storage.latest_snapshot(); - let mut state = cnidarium::StateDelta::new(snapshot); - - let authority_address = astria_address(&[0; 20]); - - state.put_block_height(1).unwrap(); - state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); - state.put_transaction_context(TransactionContext { - address_bytes: *authority_address.address_bytes(), - transaction_id: TransactionId::new([0; 32]), - position_in_transaction: 0, - }); - - let params = Params { - market_authorities: vec![authority_address], - admin: authority_address, - }; - state.put_params(params).unwrap(); - - let ticker = example_ticker_with_metadata(String::new()); - let market = Market { - ticker: ticker.clone(), - provider_configs: vec![], - }; - - let action = UpsertMarkets { - markets: vec![market.clone()], - }; - action.check_and_execute(&mut state).await.unwrap(); - let market_map = state.get_market_map().await.unwrap().unwrap(); - assert_eq!(market_map.markets.len(), 1); - assert_eq!( - *market_map - .markets - .get(&ticker.currency_pair.to_string()) - .unwrap(), - market, - ); - assert_eq!(state.get_market_map_last_updated_height().await.unwrap(), 1); - } - - #[tokio::test] - async fn upsert_markets_updates_market_if_it_already_exists() { - let storage = cnidarium::TempStorage::new().await.unwrap(); - let snapshot = storage.latest_snapshot(); - let mut state = cnidarium::StateDelta::new(snapshot); - - let authority_address = astria_address(&[0; 20]); - - let params = Params { - market_authorities: vec![authority_address], - admin: authority_address, - }; - state.put_params(params).unwrap(); - - state.put_block_height(1).unwrap(); - state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); - state.put_transaction_context(TransactionContext { - address_bytes: *authority_address.address_bytes(), - transaction_id: TransactionId::new([0; 32]), - position_in_transaction: 0, - }); - - let ticker_1 = example_ticker_with_metadata("ticker_1".to_string()); - let market_1 = Market { - ticker: ticker_1.clone(), - provider_configs: vec![], - }; - - let mut markets = IndexMap::new(); - markets.insert(ticker_1.currency_pair.to_string(), market_1.clone()); - let initial_market_map = MarketMap { - markets, - }; - state.put_market_map(initial_market_map).unwrap(); - let market_map = state.get_market_map().await.unwrap().unwrap(); - assert_eq!(market_map.markets.len(), 1); - assert_eq!( - *market_map - .markets - .get(&ticker_1.currency_pair.to_string()) - .unwrap(), - market_1, - ); - - let ticker_2 = example_ticker_with_metadata("ticker_2".to_string()); - let market_2 = Market { - ticker: ticker_2.clone(), - provider_configs: vec![], - }; - - let action = UpsertMarkets { - markets: vec![market_2.clone()], - }; - - action.check_and_execute(&mut state).await.unwrap(); - let market_map = state.get_market_map().await.unwrap().unwrap(); - assert_eq!(market_map.markets.len(), 1); - assert_eq!( - *market_map - .markets - .get(&ticker_2.currency_pair.to_string()) - .unwrap(), - market_2, - ); - assert_eq!(state.get_market_map_last_updated_height().await.unwrap(), 1); - } - - #[tokio::test] - async fn upsert_markets_fails_if_authority_is_invalid() { - let storage = cnidarium::TempStorage::new().await.unwrap(); - let snapshot = storage.latest_snapshot(); - let mut state = cnidarium::StateDelta::new(snapshot); - - let authority_address = astria_address(&[0; 20]); - - state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); - state.put_transaction_context(TransactionContext { - address_bytes: *authority_address.address_bytes(), - transaction_id: TransactionId::new([0; 32]), - position_in_transaction: 0, - }); - - let params = Params { - market_authorities: vec![], // should fail even though the authority address is admin - admin: authority_address, - }; - state.put_params(params).unwrap(); - - let action = UpsertMarkets { - markets: vec![], - }; - let res = action.check_and_execute(&mut state).await.unwrap_err(); - assert!(res.to_string().contains(&format!( - "address {authority_address} is not a market authority" - ))); - assert!(state.get_market_map().await.unwrap().is_none()); - } - - #[tokio::test] - async fn upsert_markets_fails_if_params_not_found() { - let storage = cnidarium::TempStorage::new().await.unwrap(); - let snapshot = storage.latest_snapshot(); - let mut state = cnidarium::StateDelta::new(snapshot); - - state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap(); - state.put_transaction_context(TransactionContext { - address_bytes: [0; 20], - transaction_id: TransactionId::new([0; 32]), - position_in_transaction: 0, - }); - - let action = UpsertMarkets { - markets: vec![], - }; - let res = action.check_and_execute(&mut state).await.unwrap_err(); - assert!( - res.to_string() - .contains("market map params not found in state") - ); - assert!(state.get_market_map().await.unwrap().is_none()); - } -} diff --git a/crates/astria-sequencer/src/app/benchmark_and_test_utils.rs b/crates/astria-sequencer/src/app/benchmark_and_test_utils.rs index f895bbe19a..780b84b341 100644 --- a/crates/astria-sequencer/src/app/benchmark_and_test_utils.rs +++ b/crates/astria-sequencer/src/app/benchmark_and_test_utils.rs @@ -21,7 +21,7 @@ use astria_core::{ BridgeLock, BridgeSudoChange, BridgeUnlock, - CreateMarkets, + ChangeMarkets, FeeAssetChange, FeeChange, IbcRelayerChange, @@ -29,13 +29,10 @@ use astria_core::{ Ics20Withdrawal, InitBridgeAccount, RemoveMarketAuthorities, - RemoveMarkets, RollupDataSubmission, SudoAddressChange, Transfer, UpdateMarketMapParams, - UpdateMarkets, - UpsertMarkets, ValidatorUpdate, }, }, @@ -97,12 +94,9 @@ pub(crate) fn default_fees() -> astria_core::protocol::genesis::v1::GenesisFees ibc_relayer_change: Some(FeeComponents::::new(0, 0)), sudo_address_change: Some(FeeComponents::::new(0, 0)), ibc_sudo_change: Some(FeeComponents::::new(0, 0)), - upsert_markets: Some(FeeComponents::::new(0, 0)), - create_markets: Some(FeeComponents::::new(0, 0)), - update_markets: Some(FeeComponents::::new(0, 0)), + change_markets: Some(FeeComponents::::new(0, 0)), update_market_map_params: Some(FeeComponents::::new(0, 0)), remove_market_authorities: Some(FeeComponents::::new(0, 0)), - remove_markets: Some(FeeComponents::::new(0, 0)), } } diff --git a/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_at_genesis.snap b/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_at_genesis.snap index da9baed897..074e51e6ff 100644 --- a/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_at_genesis.snap +++ b/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_at_genesis.snap @@ -3,36 +3,36 @@ source: crates/astria-sequencer/src/app/tests_breaking_changes.rs expression: app.app_hash.as_bytes() --- [ - 45, - 176, + 115, + 183, + 9, + 143, + 240, + 133, + 246, + 144, 182, - 39, - 232, - 244, - 147, - 225, - 213, - 155, - 56, + 64, + 94, + 199, + 50, + 189, + 218, + 13, + 86, + 218, + 251, + 139, + 58, 203, - 172, - 168, - 66, - 74, - 24, - 167, - 236, - 91, - 73, - 179, - 230, - 49, - 100, - 71, - 201, - 224, - 69, - 11, - 195, - 202 + 194, + 1, + 140, + 212, + 32, + 121, + 141, + 129, + 38, + 162 ] diff --git a/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_execute_every_action.snap b/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_execute_every_action.snap index e678444d35..f71b6cdab4 100644 --- a/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_execute_every_action.snap +++ b/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_execute_every_action.snap @@ -3,36 +3,36 @@ source: crates/astria-sequencer/src/app/tests_breaking_changes.rs expression: app.app_hash.as_bytes() --- [ - 135, - 124, - 66, - 33, - 47, - 219, - 249, - 100, - 72, - 182, - 201, - 179, - 50, - 188, - 182, - 194, - 181, - 199, - 16, - 117, - 247, - 65, - 38, - 38, - 205, - 183, + 60, 71, + 221, + 191, + 167, + 42, + 170, + 193, + 78, + 138, + 26, + 200, + 241, + 175, + 93, + 117, + 109, + 52, + 15, + 86, + 185, + 235, + 173, + 146, 163, - 158, - 177, - 255, - 136 + 32, + 62, + 125, + 142, + 113, + 108, + 102 ] diff --git a/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_finalize_block.snap b/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_finalize_block.snap index 176da36fab..3d7516fbbe 100644 --- a/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_finalize_block.snap +++ b/crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_hash_finalize_block.snap @@ -3,36 +3,36 @@ source: crates/astria-sequencer/src/app/tests_breaking_changes.rs expression: app.app_hash.as_bytes() --- [ - 140, - 239, - 168, - 255, - 54, - 206, - 191, - 68, + 40, + 78, + 167, + 88, + 30, + 156, + 35, + 130, + 82, + 166, + 171, + 55, + 1, + 79, + 49, + 74, + 221, + 189, + 39, + 214, 137, - 65, - 112, - 105, - 0, - 7, - 19, - 142, - 134, - 123, - 239, - 152, - 217, - 133, - 238, - 142, - 93, - 38, - 120, - 244, - 216, - 237, - 196, - 224 + 73, + 110, + 144, + 91, + 203, + 228, + 126, + 247, + 161, + 8, + 83 ] diff --git a/crates/astria-sequencer/src/app/tests_breaking_changes.rs b/crates/astria-sequencer/src/app/tests_breaking_changes.rs index 0b68790d55..0494652a99 100644 --- a/crates/astria-sequencer/src/app/tests_breaking_changes.rs +++ b/crates/astria-sequencer/src/app/tests_breaking_changes.rs @@ -30,16 +30,13 @@ use astria_core::{ BridgeLock, BridgeSudoChange, BridgeUnlock, - CreateMarkets, + ChangeMarkets, IbcRelayerChange, IbcSudoChange, RemoveMarketAuthorities, - RemoveMarkets, RollupDataSubmission, Transfer, UpdateMarketMapParams, - UpdateMarkets, - UpsertMarkets, ValidatorUpdate, }, Action, @@ -250,50 +247,32 @@ async fn app_execute_transaction_with_every_action_snapshot() { } .into(), Action::ValidatorUpdate(update.clone()), - CreateMarkets { - create_markets: vec![Market { - ticker: example_ticker_from_currency_pair( - "testAssetOne", - "testAssetTwo", - String::new(), - ), - provider_configs: vec![], - }], - } + ChangeMarkets::Create(vec![Market { + ticker: example_ticker_from_currency_pair( + "testAssetOne", + "testAssetTwo", + "create market".to_string(), + ), + provider_configs: vec![], + }]) .into(), - UpsertMarkets { - markets: vec![Market { - ticker: example_ticker_from_currency_pair( - "testAssetThree", - "testAssetFour", - "upsert market".to_string(), - ), - provider_configs: vec![], - }], - } + ChangeMarkets::Update(vec![Market { + ticker: example_ticker_from_currency_pair( + "testAssetOne", + "testAssetTwo", + "update market".to_string(), + ), + provider_configs: vec![], + }]) .into(), - UpdateMarkets { - update_markets: vec![Market { - ticker: example_ticker_from_currency_pair( - "testAssetOne", - "testAssetTwo", - "updated market".to_string(), - ), - provider_configs: vec![], - }], - } - .into(), - RemoveMarkets { - markets: vec![ - example_ticker_from_currency_pair( - "testAssetOne", - "testAssetTwo", - "remove market".to_string(), - ) - .currency_pair - .to_string(), - ], - } + ChangeMarkets::Remove(vec![Market { + ticker: example_ticker_from_currency_pair( + "testAssetOne", + "testAssetTwo", + "remove market".to_string(), + ), + provider_configs: vec![], + }]) .into(), RemoveMarketAuthorities { remove_addresses: vec![astria_address_from_hex_string(ALICE_ADDRESS)], diff --git a/crates/astria-sequencer/src/app/tests_execute_transaction.rs b/crates/astria-sequencer/src/app/tests_execute_transaction.rs index c4ed2e2018..d22cf35863 100644 --- a/crates/astria-sequencer/src/app/tests_execute_transaction.rs +++ b/crates/astria-sequencer/src/app/tests_execute_transaction.rs @@ -19,17 +19,14 @@ use astria_core::{ action::{ BridgeLock, BridgeUnlock, - CreateMarkets, + ChangeMarkets, IbcRelayerChange, IbcSudoChange, RemoveMarketAuthorities, - RemoveMarkets, RollupDataSubmission, SudoAddressChange, Transfer, UpdateMarketMapParams, - UpdateMarkets, - UpsertMarkets, ValidatorUpdate, }, Action, @@ -1350,71 +1347,6 @@ async fn ensure_all_event_attributes_are_indexed() { }); } -#[tokio::test] -async fn upsert_markets_executes_as_expected() { - let mut app = initialize_app(None, vec![]).await; - let mut state_tx = StateDelta::new(app.state.clone()); - - let alice_signing_key = get_alice_signing_key(); - - let ticker_1 = example_ticker_with_metadata("create_market_1".to_string()); - let market_1 = Market { - ticker: ticker_1.clone(), - provider_configs: vec![], - }; - let mut market_map = MarketMap { - markets: IndexMap::new(), - }; - market_map - .markets - .insert(ticker_1.currency_pair.to_string(), market_1); - state_tx.put_market_map(market_map).unwrap(); - - app.apply(state_tx); - - // market_2 should replace market_1, since they share the same currency pair - let ticker_2 = example_ticker_with_metadata("update market 1 to market 2".to_string()); - let market_2 = Market { - ticker: ticker_2.clone(), - provider_configs: vec![], - }; - - // market_3 should be added to the market map - let ticker_3 = example_ticker_from_currency_pair("USDC", "TIA", "create market 3".to_string()); - let market_3 = Market { - ticker: ticker_3.clone(), - provider_configs: vec![], - }; - - let upsert_markets_action = UpsertMarkets { - markets: vec![market_2.clone(), market_3.clone()], - }; - - let tx = TransactionBody::builder() - .actions(vec![upsert_markets_action.into()]) - .chain_id("test") - .try_build() - .unwrap(); - - let signed_tx = Arc::new(tx.sign(&alice_signing_key)); - app.execute_transaction(signed_tx).await.unwrap(); - - let market_map = app.state.get_market_map().await.unwrap().unwrap(); - assert_eq!(market_map.markets.len(), 2); - assert_eq!( - market_map.markets.get(&ticker_1.currency_pair.to_string()), - Some(&market_2) - ); - assert_eq!( - market_map.markets.get(&ticker_2.currency_pair.to_string()), - Some(&market_2) - ); - assert_eq!( - market_map.markets.get(&ticker_3.currency_pair.to_string()), - Some(&market_3) - ); -} - #[tokio::test] async fn create_markets_executes_as_expected() { let mut app = initialize_app(None, vec![]).await; @@ -1433,9 +1365,7 @@ async fn create_markets_executes_as_expected() { provider_configs: vec![], }; - let create_markets_action = CreateMarkets { - create_markets: vec![market_1.clone(), market_2.clone()], - }; + let create_markets_action = ChangeMarkets::Create(vec![market_1.clone(), market_2.clone()]); let tx = TransactionBody::builder() .actions(vec![create_markets_action.into()]) @@ -1497,9 +1427,7 @@ async fn update_markets_executes_as_expected() { provider_configs: vec![], }; - let update_markets_action = UpdateMarkets { - update_markets: vec![market_3.clone()], - }; + let update_markets_action = ChangeMarkets::Update(vec![market_3.clone()]); let tx = TransactionBody::builder() .actions(vec![update_markets_action.into()]) @@ -1558,9 +1486,10 @@ async fn remove_markets_executes_as_expected() { state_tx.put_market_map(market_map).unwrap(); app.apply(state_tx); - let remove_markets_action = RemoveMarkets { - markets: vec![ticker_1.currency_pair.to_string()], - }; + let remove_markets_action = ChangeMarkets::Remove(vec![Market { + ticker: ticker_1.clone(), + provider_configs: vec![], + }]); let tx = TransactionBody::builder() .actions(vec![remove_markets_action.into()]) diff --git a/crates/astria-sequencer/src/fees/component.rs b/crates/astria-sequencer/src/fees/component.rs index f03b60dbe8..106666b9e8 100644 --- a/crates/astria-sequencer/src/fees/component.rs +++ b/crates/astria-sequencer/src/fees/component.rs @@ -130,32 +130,11 @@ impl Component for FeesComponent { .wrap_err("failed to store ibc sudo change fee components")?; } - let upsert_markets_fees = app_state.fees().upsert_markets; - if let Some(upsert_markets_fees) = upsert_markets_fees { + let change_markets_fees = app_state.fees().change_markets; + if let Some(change_markets_fees) = change_markets_fees { state - .put_fees(upsert_markets_fees) - .wrap_err("failed to store upsert markets fee components")?; - } - - let create_markets_fees = app_state.fees().create_markets; - if let Some(create_markets_fees) = create_markets_fees { - state - .put_fees(create_markets_fees) - .wrap_err("failed to store create markets fee components")?; - } - - let update_markets_fees = app_state.fees().update_markets; - if let Some(update_markets_fees) = update_markets_fees { - state - .put_fees(update_markets_fees) - .wrap_err("failed to store update markets fee components")?; - } - - let remove_markets_fees = app_state.fees().remove_markets; - if let Some(remove_markets_fees) = remove_markets_fees { - state - .put_fees(remove_markets_fees) - .wrap_err("failed to store remove markets fee components")?; + .put_fees(change_markets_fees) + .wrap_err("failed to store change markets fee components")?; } let remove_market_authorities_fees = app_state.fees().remove_market_authorities; diff --git a/crates/astria-sequencer/src/fees/mod.rs b/crates/astria-sequencer/src/fees/mod.rs index 2721de14ef..3034bf20d4 100644 --- a/crates/astria-sequencer/src/fees/mod.rs +++ b/crates/astria-sequencer/src/fees/mod.rs @@ -6,7 +6,7 @@ use astria_core::{ BridgeLock, BridgeSudoChange, BridgeUnlock, - CreateMarkets, + ChangeMarkets, FeeAssetChange, FeeChange, IbcRelayerChange, @@ -14,13 +14,10 @@ use astria_core::{ Ics20Withdrawal, InitBridgeAccount, RemoveMarketAuthorities, - RemoveMarkets, RollupDataSubmission, SudoAddressChange, Transfer, UpdateMarketMapParams, - UpdateMarkets, - UpsertMarkets, ValidatorUpdate, }, }, @@ -464,7 +461,7 @@ impl FeeHandler for IbcRelay { } } -impl FeeHandler for UpsertMarkets { +impl FeeHandler for ChangeMarkets { fn name() -> &'static str { ::Raw::NAME } @@ -474,51 +471,7 @@ impl FeeHandler for UpsertMarkets { } fn snake_case_name() -> &'static str { - "upsert_markets" - } - - fn variable_component(&self) -> u128 { - 0 - } - - fn fee_asset(&self) -> Option<&asset::Denom> { - None - } -} - -impl FeeHandler for CreateMarkets { - fn name() -> &'static str { - ::Raw::NAME - } - - fn full_name() -> String { - ::full_name() - } - - fn snake_case_name() -> &'static str { - "create_markets" - } - - fn variable_component(&self) -> u128 { - 0 - } - - fn fee_asset(&self) -> Option<&asset::Denom> { - None - } -} - -impl FeeHandler for UpdateMarkets { - fn name() -> &'static str { - ::Raw::NAME - } - - fn full_name() -> String { - ::full_name() - } - - fn snake_case_name() -> &'static str { - "update_markets" + "change_markets" } fn variable_component(&self) -> u128 { @@ -574,28 +527,6 @@ impl FeeHandler for RemoveMarketAuthorities { } } -impl FeeHandler for RemoveMarkets { - fn name() -> &'static str { - ::Raw::NAME - } - - fn full_name() -> String { - ::full_name() - } - - fn snake_case_name() -> &'static str { - "remove_markets" - } - - fn variable_component(&self) -> u128 { - 0 - } - - fn fee_asset(&self) -> Option<&asset::Denom> { - None - } -} - /// Returns a modified byte length of the deposit event. Length is calculated with reasonable values /// for all fields except `asset` and `destination_chain_address`, ergo it may not be representative /// of on-wire length. diff --git a/crates/astria-sequencer/src/fees/query.rs b/crates/astria-sequencer/src/fees/query.rs index d59981747b..c3034518ba 100644 --- a/crates/astria-sequencer/src/fees/query.rs +++ b/crates/astria-sequencer/src/fees/query.rs @@ -18,7 +18,7 @@ use astria_core::{ BridgeLock, BridgeSudoChange, BridgeUnlock, - CreateMarkets, + ChangeMarkets, FeeAssetChange, FeeChange, IbcRelayerChange, @@ -26,13 +26,10 @@ use astria_core::{ Ics20Withdrawal, InitBridgeAccount, RemoveMarketAuthorities, - RemoveMarkets, RollupDataSubmission, SudoAddressChange, Transfer, UpdateMarketMapParams, - UpdateMarkets, - UpsertMarkets, ValidatorUpdate, }, Action, @@ -308,14 +305,11 @@ pub(crate) async fn get_fees_for_transaction( OnceCell::new(); let fee_asset_change_fees: OnceCell>> = OnceCell::new(); let fee_change_fees: OnceCell>> = OnceCell::new(); - let upsert_markets_fees: OnceCell>> = OnceCell::new(); - let create_markets_fees: OnceCell>> = OnceCell::new(); - let update_markets_fees: OnceCell>> = OnceCell::new(); + let change_markets_fees: OnceCell>> = OnceCell::new(); let update_market_map_params_fees: OnceCell>> = OnceCell::new(); let remove_market_authorities_fees: OnceCell>> = OnceCell::new(); - let remove_markets_fees: OnceCell>> = OnceCell::new(); let mut fees_by_asset = HashMap::new(); for action in tx.actions() { @@ -376,16 +370,8 @@ pub(crate) async fn get_fees_for_transaction( let fees = get_or_init_fees(state, &fee_change_fees).await?; calculate_and_add_fees(act, &mut fees_by_asset, fees); } - Action::UpsertMarkets(act) => { - let fees = get_or_init_fees(state, &upsert_markets_fees).await?; - calculate_and_add_fees(act, &mut fees_by_asset, fees); - } - Action::CreateMarkets(act) => { - let fees = get_or_init_fees(state, &create_markets_fees).await?; - calculate_and_add_fees(act, &mut fees_by_asset, fees); - } - Action::UpdateMarkets(act) => { - let fees = get_or_init_fees(state, &update_markets_fees).await?; + Action::ChangeMarkets(act) => { + let fees = get_or_init_fees(state, &change_markets_fees).await?; calculate_and_add_fees(act, &mut fees_by_asset, fees); } Action::UpdateMarketMapParams(act) => { @@ -396,10 +382,6 @@ pub(crate) async fn get_fees_for_transaction( let fees = get_or_init_fees(state, &remove_market_authorities_fees).await?; calculate_and_add_fees(act, &mut fees_by_asset, fees); } - Action::RemoveMarkets(act) => { - let fees = get_or_init_fees(state, &remove_markets_fees).await?; - calculate_and_add_fees(act, &mut fees_by_asset, fees); - } } } Ok(fees_by_asset) diff --git a/crates/astria-sequencer/src/fees/storage/values.rs b/crates/astria-sequencer/src/fees/storage/values.rs index 0f32eb85a3..b8d7193250 100644 --- a/crates/astria-sequencer/src/fees/storage/values.rs +++ b/crates/astria-sequencer/src/fees/storage/values.rs @@ -4,7 +4,7 @@ use astria_core::protocol::{ BridgeLock, BridgeSudoChange, BridgeUnlock, - CreateMarkets, + ChangeMarkets, FeeAssetChange, FeeChange, IbcRelayerChange, @@ -12,13 +12,10 @@ use astria_core::protocol::{ Ics20Withdrawal, InitBridgeAccount, RemoveMarketAuthorities, - RemoveMarkets, RollupDataSubmission, SudoAddressChange, Transfer, UpdateMarketMapParams, - UpdateMarkets, - UpsertMarkets, ValidatorUpdate, }, }; @@ -52,12 +49,9 @@ enum ValueImpl { IbcRelayerChangeFees(FeeComponents), IbcSudoChangeFees(FeeComponents), SudoAddressChangeFees(FeeComponents), - UpsertMarketsFees(FeeComponents), - CreateMarketsFees(FeeComponents), - UpdateMarketsFees(FeeComponents), + ChangeMarketsFees(FeeComponents), UpdateMarketMapParamsFees(FeeComponents), RemoveMarketAuthoritiesFees(FeeComponents), - RemoveMarketsFees(FeeComponents), } macro_rules! impl_from_for_fee_storage { @@ -121,10 +115,7 @@ impl_from_for_fee_storage!( DomainFeeComponents => IbcRelayerChangeFees, DomainFeeComponents => IbcSudoChangeFees, DomainFeeComponents => SudoAddressChangeFees, - DomainFeeComponents => UpsertMarketsFees, - DomainFeeComponents => CreateMarketsFees, - DomainFeeComponents => UpdateMarketsFees, + DomainFeeComponents => ChangeMarketsFees, DomainFeeComponents => UpdateMarketMapParamsFees, DomainFeeComponents => RemoveMarketAuthoritiesFees, - DomainFeeComponents => RemoveMarketsFees, ); diff --git a/crates/astria-sequencer/src/transaction/checks.rs b/crates/astria-sequencer/src/transaction/checks.rs index 645b8b4dd4..a47554c04b 100644 --- a/crates/astria-sequencer/src/transaction/checks.rs +++ b/crates/astria-sequencer/src/transaction/checks.rs @@ -118,11 +118,8 @@ pub(crate) async fn get_total_transaction_cost( | Action::IbcRelayerChange(_) | Action::FeeAssetChange(_) | Action::UpdateMarketMapParams(_) - | Action::UpsertMarkets(_) - | Action::CreateMarkets(_) - | Action::UpdateMarkets(_) + | Action::ChangeMarkets(_) | Action::RemoveMarketAuthorities(_) - | Action::RemoveMarkets(_) | Action::FeeChange(_) => { continue; } diff --git a/proto/protocolapis/astria/protocol/fees/v1/types.proto b/proto/protocolapis/astria/protocol/fees/v1/types.proto index 63e85f37e1..8d7f115891 100644 --- a/proto/protocolapis/astria/protocol/fees/v1/types.proto +++ b/proto/protocolapis/astria/protocol/fees/v1/types.proto @@ -79,17 +79,7 @@ message IbcSudoChangeFeeComponents { astria.primitive.v1.Uint128 multiplier = 2; } -message UpsertMarketsFeeComponents { - astria.primitive.v1.Uint128 base = 1; - astria.primitive.v1.Uint128 multiplier = 2; -} - -message CreateMarketsFeeComponents { - astria.primitive.v1.Uint128 base = 1; - astria.primitive.v1.Uint128 multiplier = 2; -} - -message UpdateMarketsFeeComponents { +message ChangeMarketsFeeComponents { astria.primitive.v1.Uint128 base = 1; astria.primitive.v1.Uint128 multiplier = 2; } @@ -104,11 +94,6 @@ message RemoveMarketAuthoritiesFeeComponents { astria.primitive.v1.Uint128 multiplier = 2; } -message RemoveMarketsFeeComponents { - astria.primitive.v1.Uint128 base = 1; - astria.primitive.v1.Uint128 multiplier = 2; -} - // Response to a transaction fee ABCI query. message TransactionFeeResponse { uint64 height = 2; diff --git a/proto/protocolapis/astria/protocol/genesis/v1/types.proto b/proto/protocolapis/astria/protocol/genesis/v1/types.proto index fd168ab026..f6cd63a2b5 100644 --- a/proto/protocolapis/astria/protocol/genesis/v1/types.proto +++ b/proto/protocolapis/astria/protocol/genesis/v1/types.proto @@ -59,12 +59,9 @@ message GenesisFees { astria.protocol.fees.v1.SudoAddressChangeFeeComponents sudo_address_change = 12; astria.protocol.fees.v1.TransferFeeComponents transfer = 13; astria.protocol.fees.v1.ValidatorUpdateFeeComponents validator_update = 14; - astria.protocol.fees.v1.UpsertMarketsFeeComponents upsert_markets = 15; - astria.protocol.fees.v1.CreateMarketsFeeComponents create_markets = 16; - astria.protocol.fees.v1.UpdateMarketsFeeComponents update_markets = 17; + astria.protocol.fees.v1.ChangeMarketsFeeComponents change_markets = 15; astria.protocol.fees.v1.UpdateMarketMapParamsFeeComponents update_market_map_params = 18; astria.protocol.fees.v1.RemoveMarketAuthoritiesFeeComponents remove_market_authorities = 19; - astria.protocol.fees.v1.RemoveMarketsFeeComponents remove_markets = 20; } message ConnectGenesis { diff --git a/proto/protocolapis/astria/protocol/transaction/v1/action.proto b/proto/protocolapis/astria/protocol/transaction/v1/action.proto index ef04aff27c..7d9e836215 100644 --- a/proto/protocolapis/astria/protocol/transaction/v1/action.proto +++ b/proto/protocolapis/astria/protocol/transaction/v1/action.proto @@ -34,12 +34,9 @@ message Action { IbcSudoChange ibc_sudo_change = 56; // MarketMap actions are defined on 71-80 - UpsertMarkets upsert_markets = 71; - CreateMarkets create_markets = 72; - UpdateMarkets update_markets = 73; - UpdateMarketMapParams update_market_map_params = 74; - RemoveMarketAuthorities remove_market_authorities = 75; - RemoveMarkets remove_markets = 76; + ChangeMarkets change_markets = 71; + UpdateMarketMapParams update_market_map_params = 72; + RemoveMarketAuthorities remove_market_authorities = 73; } } @@ -238,12 +235,9 @@ message FeeChange { astria.protocol.fees.v1.SudoAddressChangeFeeComponents sudo_address_change = 12; astria.protocol.fees.v1.TransferFeeComponents transfer = 13; astria.protocol.fees.v1.ValidatorUpdateFeeComponents validator_update = 14; - astria.protocol.fees.v1.UpsertMarketsFeeComponents upsert_markets = 15; - astria.protocol.fees.v1.CreateMarketsFeeComponents create_markets = 16; - astria.protocol.fees.v1.UpdateMarketsFeeComponents update_markets = 17; - astria.protocol.fees.v1.UpdateMarketMapParamsFeeComponents update_market_map_params = 18; - astria.protocol.fees.v1.RemoveMarketAuthoritiesFeeComponents remove_market_authorities = 19; - astria.protocol.fees.v1.RemoveMarketsFeeComponents remove_markets = 20; + astria.protocol.fees.v1.ChangeMarketsFeeComponents change_markets = 15; + astria.protocol.fees.v1.UpdateMarketMapParamsFeeComponents update_market_map_params = 16; + astria.protocol.fees.v1.RemoveMarketAuthoritiesFeeComponents remove_market_authorities = 17; } } @@ -251,22 +245,18 @@ message IbcSudoChange { astria.primitive.v1.Address new_address = 1; } -// Updates or creates markets in the market map. If a market does not exist, it will be created. -message UpsertMarkets { - // The list of all markets to be created or updated for the given transaction. - repeated connect.marketmap.v2.Market markets = 2; -} - -// Creates new markets in the market map. -message CreateMarkets { - // The list of all markets to be created. - repeated connect.marketmap.v2.Market create_markets = 2; +// Either creates, updates existing, or removes markets. +message ChangeMarkets { + oneof action { + Markets create = 1; + Markets update = 2; + Markets remove = 3; + } } -// Updates existing markets in the market map. -message UpdateMarkets { - // The list of all markets to be updated. - repeated connect.marketmap.v2.Market update_markets = 2; +// A list of markets for creation, updating, or removal. +message Markets { + repeated connect.marketmap.v2.Market markets = 1; } // Updates the market map parameters. @@ -280,9 +270,3 @@ message RemoveMarketAuthorities { // RemoveAddresses is the list of addresses to remove. repeated string remove_addresses = 1; } - -// Removes markets from the market map. -message RemoveMarkets { - // Markets is the list of markets to remove. - repeated string markets = 2; -} From 3e72b08888201bfdfa739f2042504dbc1d250392 Mon Sep 17 00:00:00 2001 From: ethanoroshiba Date: Wed, 8 Jan 2025 14:55:05 -0600 Subject: [PATCH 6/8] update doc comment --- .../src/protocol/transaction/v1/action/mod.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/crates/astria-core/src/protocol/transaction/v1/action/mod.rs b/crates/astria-core/src/protocol/transaction/v1/action/mod.rs index 9038dfa374..9aa96469af 100644 --- a/crates/astria-core/src/protocol/transaction/v1/action/mod.rs +++ b/crates/astria-core/src/protocol/transaction/v1/action/mod.rs @@ -2255,8 +2255,15 @@ impl From> for FeeChange { } } -/// Takes a list of markets and either creates, updates existing, or removes existing markets. Must -/// be signed by an address included in the market map [`Params`]' `market_authorities`. +/// Takes a list of markets and either creates, updates, or removes them depending on its variant. +/// Must be signed by an address included in the market map [`Params`]' `market_authorities`. +/// - **Create:** Creates the markets in the market map. If no market map is found, one will be +/// created. If any of the markets to create already exist, this action will err. +/// - **Update:** Updates the markets in the market map, matching based on `Ticker.currency_pair`). +/// If no market map is found, or any market is missing a counterpart in the map, this action will +/// err. +/// - **Remove:** Removes the markets from the market map. If a market is not found in the map, it +/// will be ignored. #[derive(Debug, Clone)] pub enum ChangeMarkets { Create(Vec), From 8455a7ef11a3221fe73e198acd1065b1be08ed3b Mon Sep 17 00:00:00 2001 From: ethanoroshiba Date: Wed, 8 Jan 2025 15:21:15 -0600 Subject: [PATCH 7/8] proto fmt --- proto/protocolapis/astria/protocol/transaction/v1/action.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proto/protocolapis/astria/protocol/transaction/v1/action.proto b/proto/protocolapis/astria/protocol/transaction/v1/action.proto index d53cbf115f..efcbaa3785 100644 --- a/proto/protocolapis/astria/protocol/transaction/v1/action.proto +++ b/proto/protocolapis/astria/protocol/transaction/v1/action.proto @@ -6,9 +6,9 @@ import "astria/primitive/v1/types.proto"; import "astria/protocol/fees/v1/types.proto"; import "astria_vendored/penumbra/core/component/ibc/v1/ibc.proto"; import "astria_vendored/tendermint/abci/types.proto"; -import "connect/types/v2/currency_pair.proto"; import "connect/marketmap/v2/market.proto"; import "connect/marketmap/v2/params.proto"; +import "connect/types/v2/currency_pair.proto"; message Action { oneof value { From 0897f22303d69536afe42e12abe7cef311488a14 Mon Sep 17 00:00:00 2001 From: ethanoroshiba Date: Wed, 8 Jan 2025 15:35:24 -0600 Subject: [PATCH 8/8] update snapshot --- ...rotocol__genesis__v1__tests__genesis_state.snap | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/crates/astria-core/src/protocol/genesis/snapshots/astria_core__protocol__genesis__v1__tests__genesis_state.snap b/crates/astria-core/src/protocol/genesis/snapshots/astria_core__protocol__genesis__v1__tests__genesis_state.snap index 5759dd2859..48fb9daa0d 100644 --- a/crates/astria-core/src/protocol/genesis/snapshots/astria_core__protocol__genesis__v1__tests__genesis_state.snap +++ b/crates/astria-core/src/protocol/genesis/snapshots/astria_core__protocol__genesis__v1__tests__genesis_state.snap @@ -140,15 +140,7 @@ expression: genesis_state() "base": {}, "multiplier": {} }, - "upsertMarkets": { - "base": {}, - "multiplier": {} - }, - "createMarkets": { - "base": {}, - "multiplier": {} - }, - "updateMarkets": { + "changeMarkets": { "base": {}, "multiplier": {} }, @@ -159,10 +151,6 @@ expression: genesis_state() "removeMarketAuthorities": { "base": {}, "multiplier": {} - }, - "removeMarkets": { - "base": {}, - "multiplier": {} } }, "connect": {