From e5833321b7d8a2e67b0c3afafd67deab8c5fd639 Mon Sep 17 00:00:00 2001 From: Lucas Meier Date: Sat, 8 Feb 2025 00:21:49 -0800 Subject: [PATCH 01/13] bug: actually thread through state(less/full) checks for lqt vote action Previously we had a todo!() there, woops. --- crates/core/app/src/action_handler/actions.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/core/app/src/action_handler/actions.rs b/crates/core/app/src/action_handler/actions.rs index 93f33355e0..7f84627105 100644 --- a/crates/core/app/src/action_handler/actions.rs +++ b/crates/core/app/src/action_handler/actions.rs @@ -56,7 +56,7 @@ impl AppActionHandler for Action { Action::ActionDutchAuctionSchedule(action) => action.check_stateless(()).await, Action::ActionDutchAuctionEnd(action) => action.check_stateless(()).await, Action::ActionDutchAuctionWithdraw(action) => action.check_stateless(()).await, - Action::ActionLiquidityTournamentVote(_action) => todo!(), + Action::ActionLiquidityTournamentVote(action) => action.check_stateless(context).await, } } @@ -98,7 +98,7 @@ impl AppActionHandler for Action { Action::ActionDutchAuctionSchedule(action) => action.check_historical(state).await, Action::ActionDutchAuctionEnd(action) => action.check_historical(state).await, Action::ActionDutchAuctionWithdraw(action) => action.check_historical(state).await, - Action::ActionLiquidityTournamentVote(_action) => todo!(), + Action::ActionLiquidityTournamentVote(action) => action.check_historical(state).await, } } @@ -140,7 +140,7 @@ impl AppActionHandler for Action { Action::ActionDutchAuctionSchedule(action) => action.check_and_execute(state).await, Action::ActionDutchAuctionEnd(action) => action.check_and_execute(state).await, Action::ActionDutchAuctionWithdraw(action) => action.check_and_execute(state).await, - Action::ActionLiquidityTournamentVote(_action) => todo!(), + Action::ActionLiquidityTournamentVote(action) => action.check_and_execute(state).await, } } } From 5535f09f12f2d94eb3b5cf4367895ce28a6f274d Mon Sep 17 00:00:00 2001 From: Lucas Meier Date: Thu, 6 Feb 2025 19:31:09 -0800 Subject: [PATCH 02/13] Define protos for lqt action plans --- crates/core/transaction/src/plan/action.rs | 3 + .../gen/penumbra.core.component.funding.v1.rs | 38 +++ ...enumbra.core.component.funding.v1.serde.rs | 240 ++++++++++++++++++ .../src/gen/penumbra.core.transaction.v1.rs | 7 +- .../gen/penumbra.core.transaction.v1.serde.rs | 14 + .../proto/src/gen/proto_descriptor.bin.no_lfs | Bin 643703 -> 664864 bytes .../core/component/funding/v1/funding.proto | 18 ++ .../core/transaction/v1/transaction.proto | 3 + 8 files changed, 322 insertions(+), 1 deletion(-) diff --git a/crates/core/transaction/src/plan/action.rs b/crates/core/transaction/src/plan/action.rs index 8ef121ce0d..0a59370adc 100644 --- a/crates/core/transaction/src/plan/action.rs +++ b/crates/core/transaction/src/plan/action.rs @@ -617,6 +617,9 @@ impl TryFrom for ActionPlan { pb_t::action_plan::Action::Ics20Withdrawal(inner) => { Ok(ActionPlan::Ics20Withdrawal(inner.try_into()?)) } + pb_t::action_plan::Action::ActionLiquidityTournamentVotePlan(_) => { + unimplemented!() + } } } } diff --git a/crates/proto/src/gen/penumbra.core.component.funding.v1.rs b/crates/proto/src/gen/penumbra.core.component.funding.v1.rs index b6e8305d01..f72c027953 100644 --- a/crates/proto/src/gen/penumbra.core.component.funding.v1.rs +++ b/crates/proto/src/gen/penumbra.core.component.funding.v1.rs @@ -206,6 +206,44 @@ impl ::prost::Name for LiquidityTournamentVoteBody { "/penumbra.core.component.funding.v1.LiquidityTournamentVoteBody".into() } } +/// The plan associated with a `ActionLiquidityTournamentVote`. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ActionLiquidityTournamentVotePlan { + /// The asset the user wants to vote for. + #[prost(message, optional, tag = "1")] + pub incentivized: ::core::option::Option, + /// Where to send any rewards for participating in the tournament. + #[prost(message, optional, tag = "2")] + pub rewards_recipient: ::core::option::Option< + super::super::super::keys::v1::Address, + >, + /// The note containing the staked note used for voting. + #[prost(message, optional, tag = "3")] + pub staked_note: ::core::option::Option, + /// The position of the staked note. + #[prost(uint64, tag = "4")] + pub staked_note_position: u64, + /// The start position of the tournament. + #[prost(uint64, tag = "5")] + pub start_position: u64, + /// Randomizer for proof of spend capability. + #[prost(bytes = "vec", tag = "6")] + pub randomizer: ::prost::alloc::vec::Vec, + #[prost(bytes = "vec", tag = "7")] + pub proof_blinding_r: ::prost::alloc::vec::Vec, + #[prost(bytes = "vec", tag = "8")] + pub proof_blinding_s: ::prost::alloc::vec::Vec, +} +impl ::prost::Name for ActionLiquidityTournamentVotePlan { + const NAME: &'static str = "ActionLiquidityTournamentVotePlan"; + const PACKAGE: &'static str = "penumbra.core.component.funding.v1"; + fn full_name() -> ::prost::alloc::string::String { + "penumbra.core.component.funding.v1.ActionLiquidityTournamentVotePlan".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/penumbra.core.component.funding.v1.ActionLiquidityTournamentVotePlan".into() + } +} /// A proof of the validity of a liquidity vote, wrt private state. #[derive(Clone, PartialEq, ::prost::Message)] pub struct ZkLiquidityTournamentVoteProof { diff --git a/crates/proto/src/gen/penumbra.core.component.funding.v1.serde.rs b/crates/proto/src/gen/penumbra.core.component.funding.v1.serde.rs index 2412560c5d..d3c0965779 100644 --- a/crates/proto/src/gen/penumbra.core.component.funding.v1.serde.rs +++ b/crates/proto/src/gen/penumbra.core.component.funding.v1.serde.rs @@ -128,6 +128,246 @@ impl<'de> serde::Deserialize<'de> for ActionLiquidityTournamentVote { deserializer.deserialize_struct("penumbra.core.component.funding.v1.ActionLiquidityTournamentVote", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for ActionLiquidityTournamentVotePlan { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.incentivized.is_some() { + len += 1; + } + if self.rewards_recipient.is_some() { + len += 1; + } + if self.staked_note.is_some() { + len += 1; + } + if self.staked_note_position != 0 { + len += 1; + } + if self.start_position != 0 { + len += 1; + } + if !self.randomizer.is_empty() { + len += 1; + } + if !self.proof_blinding_r.is_empty() { + len += 1; + } + if !self.proof_blinding_s.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("penumbra.core.component.funding.v1.ActionLiquidityTournamentVotePlan", len)?; + if let Some(v) = self.incentivized.as_ref() { + struct_ser.serialize_field("incentivized", v)?; + } + if let Some(v) = self.rewards_recipient.as_ref() { + struct_ser.serialize_field("rewardsRecipient", v)?; + } + if let Some(v) = self.staked_note.as_ref() { + struct_ser.serialize_field("stakedNote", v)?; + } + if self.staked_note_position != 0 { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("stakedNotePosition", ToString::to_string(&self.staked_note_position).as_str())?; + } + if self.start_position != 0 { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("startPosition", ToString::to_string(&self.start_position).as_str())?; + } + if !self.randomizer.is_empty() { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("randomizer", pbjson::private::base64::encode(&self.randomizer).as_str())?; + } + if !self.proof_blinding_r.is_empty() { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("proofBlindingR", pbjson::private::base64::encode(&self.proof_blinding_r).as_str())?; + } + if !self.proof_blinding_s.is_empty() { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("proofBlindingS", pbjson::private::base64::encode(&self.proof_blinding_s).as_str())?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for ActionLiquidityTournamentVotePlan { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "incentivized", + "rewards_recipient", + "rewardsRecipient", + "staked_note", + "stakedNote", + "staked_note_position", + "stakedNotePosition", + "start_position", + "startPosition", + "randomizer", + "proof_blinding_r", + "proofBlindingR", + "proof_blinding_s", + "proofBlindingS", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Incentivized, + RewardsRecipient, + StakedNote, + StakedNotePosition, + StartPosition, + Randomizer, + ProofBlindingR, + ProofBlindingS, + __SkipField__, + } + 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 { + "incentivized" => Ok(GeneratedField::Incentivized), + "rewardsRecipient" | "rewards_recipient" => Ok(GeneratedField::RewardsRecipient), + "stakedNote" | "staked_note" => Ok(GeneratedField::StakedNote), + "stakedNotePosition" | "staked_note_position" => Ok(GeneratedField::StakedNotePosition), + "startPosition" | "start_position" => Ok(GeneratedField::StartPosition), + "randomizer" => Ok(GeneratedField::Randomizer), + "proofBlindingR" | "proof_blinding_r" => Ok(GeneratedField::ProofBlindingR), + "proofBlindingS" | "proof_blinding_s" => Ok(GeneratedField::ProofBlindingS), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = ActionLiquidityTournamentVotePlan; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct penumbra.core.component.funding.v1.ActionLiquidityTournamentVotePlan") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut incentivized__ = None; + let mut rewards_recipient__ = None; + let mut staked_note__ = None; + let mut staked_note_position__ = None; + let mut start_position__ = None; + let mut randomizer__ = None; + let mut proof_blinding_r__ = None; + let mut proof_blinding_s__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Incentivized => { + if incentivized__.is_some() { + return Err(serde::de::Error::duplicate_field("incentivized")); + } + incentivized__ = map_.next_value()?; + } + GeneratedField::RewardsRecipient => { + if rewards_recipient__.is_some() { + return Err(serde::de::Error::duplicate_field("rewardsRecipient")); + } + rewards_recipient__ = map_.next_value()?; + } + GeneratedField::StakedNote => { + if staked_note__.is_some() { + return Err(serde::de::Error::duplicate_field("stakedNote")); + } + staked_note__ = map_.next_value()?; + } + GeneratedField::StakedNotePosition => { + if staked_note_position__.is_some() { + return Err(serde::de::Error::duplicate_field("stakedNotePosition")); + } + staked_note_position__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::StartPosition => { + if start_position__.is_some() { + return Err(serde::de::Error::duplicate_field("startPosition")); + } + start_position__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::Randomizer => { + if randomizer__.is_some() { + return Err(serde::de::Error::duplicate_field("randomizer")); + } + randomizer__ = + Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) + ; + } + GeneratedField::ProofBlindingR => { + if proof_blinding_r__.is_some() { + return Err(serde::de::Error::duplicate_field("proofBlindingR")); + } + proof_blinding_r__ = + Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) + ; + } + GeneratedField::ProofBlindingS => { + if proof_blinding_s__.is_some() { + return Err(serde::de::Error::duplicate_field("proofBlindingS")); + } + proof_blinding_s__ = + Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) + ; + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(ActionLiquidityTournamentVotePlan { + incentivized: incentivized__, + rewards_recipient: rewards_recipient__, + staked_note: staked_note__, + staked_note_position: staked_note_position__.unwrap_or_default(), + start_position: start_position__.unwrap_or_default(), + randomizer: randomizer__.unwrap_or_default(), + proof_blinding_r: proof_blinding_r__.unwrap_or_default(), + proof_blinding_s: proof_blinding_s__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("penumbra.core.component.funding.v1.ActionLiquidityTournamentVotePlan", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for ActionLiquidityTournamentVoteView { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result diff --git a/crates/proto/src/gen/penumbra.core.transaction.v1.rs b/crates/proto/src/gen/penumbra.core.transaction.v1.rs index ed60879050..e5f9796491 100644 --- a/crates/proto/src/gen/penumbra.core.transaction.v1.rs +++ b/crates/proto/src/gen/penumbra.core.transaction.v1.rs @@ -674,7 +674,7 @@ impl ::prost::Name for DetectionDataPlan { pub struct ActionPlan { #[prost( oneof = "action_plan::Action", - tags = "1, 2, 3, 4, 16, 17, 18, 19, 20, 21, 22, 200, 30, 31, 32, 34, 40, 41, 42, 50, 51, 52, 53, 54, 55" + tags = "1, 2, 3, 4, 16, 17, 18, 19, 20, 21, 22, 200, 30, 31, 32, 34, 40, 41, 42, 50, 51, 52, 53, 54, 55, 70" )] pub action: ::core::option::Option, } @@ -762,6 +762,11 @@ pub mod action_plan { ActionDutchAuctionWithdraw( super::super::super::component::auction::v1::ActionDutchAuctionWithdrawPlan, ), + /// Funding + #[prost(message, tag = "70")] + ActionLiquidityTournamentVotePlan( + super::super::super::component::funding::v1::ActionLiquidityTournamentVotePlan, + ), } } impl ::prost::Name for ActionPlan { diff --git a/crates/proto/src/gen/penumbra.core.transaction.v1.serde.rs b/crates/proto/src/gen/penumbra.core.transaction.v1.serde.rs index 1b09283f15..6e249462da 100644 --- a/crates/proto/src/gen/penumbra.core.transaction.v1.serde.rs +++ b/crates/proto/src/gen/penumbra.core.transaction.v1.serde.rs @@ -533,6 +533,9 @@ impl serde::Serialize for ActionPlan { action_plan::Action::ActionDutchAuctionWithdraw(v) => { struct_ser.serialize_field("actionDutchAuctionWithdraw", v)?; } + action_plan::Action::ActionLiquidityTournamentVotePlan(v) => { + struct_ser.serialize_field("actionLiquidityTournamentVotePlan", v)?; + } } } struct_ser.end() @@ -590,6 +593,8 @@ impl<'de> serde::Deserialize<'de> for ActionPlan { "actionDutchAuctionEnd", "action_dutch_auction_withdraw", "actionDutchAuctionWithdraw", + "action_liquidity_tournament_vote_plan", + "actionLiquidityTournamentVotePlan", ]; #[allow(clippy::enum_variant_names)] @@ -619,6 +624,7 @@ impl<'de> serde::Deserialize<'de> for ActionPlan { ActionDutchAuctionSchedule, ActionDutchAuctionEnd, ActionDutchAuctionWithdraw, + ActionLiquidityTournamentVotePlan, __SkipField__, } impl<'de> serde::Deserialize<'de> for GeneratedField { @@ -666,6 +672,7 @@ impl<'de> serde::Deserialize<'de> for ActionPlan { "actionDutchAuctionSchedule" | "action_dutch_auction_schedule" => Ok(GeneratedField::ActionDutchAuctionSchedule), "actionDutchAuctionEnd" | "action_dutch_auction_end" => Ok(GeneratedField::ActionDutchAuctionEnd), "actionDutchAuctionWithdraw" | "action_dutch_auction_withdraw" => Ok(GeneratedField::ActionDutchAuctionWithdraw), + "actionLiquidityTournamentVotePlan" | "action_liquidity_tournament_vote_plan" => Ok(GeneratedField::ActionLiquidityTournamentVotePlan), _ => Ok(GeneratedField::__SkipField__), } } @@ -861,6 +868,13 @@ impl<'de> serde::Deserialize<'de> for ActionPlan { return Err(serde::de::Error::duplicate_field("actionDutchAuctionWithdraw")); } action__ = map_.next_value::<::std::option::Option<_>>()?.map(action_plan::Action::ActionDutchAuctionWithdraw) +; + } + GeneratedField::ActionLiquidityTournamentVotePlan => { + if action__.is_some() { + return Err(serde::de::Error::duplicate_field("actionLiquidityTournamentVotePlan")); + } + action__ = map_.next_value::<::std::option::Option<_>>()?.map(action_plan::Action::ActionLiquidityTournamentVotePlan) ; } GeneratedField::__SkipField__ => { diff --git a/crates/proto/src/gen/proto_descriptor.bin.no_lfs b/crates/proto/src/gen/proto_descriptor.bin.no_lfs index 677b237ed3aa10eb58e2a3e1591e7d1044cea448..1ed6495312760625529d6461ff5f92fb933101d5 100644 GIT binary patch delta 39850 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 delta 19583 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 diff --git a/proto/penumbra/penumbra/core/component/funding/v1/funding.proto b/proto/penumbra/penumbra/core/component/funding/v1/funding.proto index 47792def4e..9367d74e15 100644 --- a/proto/penumbra/penumbra/core/component/funding/v1/funding.proto +++ b/proto/penumbra/penumbra/core/component/funding/v1/funding.proto @@ -105,6 +105,24 @@ message LiquidityTournamentVoteBody { crypto.decaf377_rdsa.v1.SpendVerificationKey rk = 6; } +// The plan associated with a `ActionLiquidityTournamentVote`. +message ActionLiquidityTournamentVotePlan { + // The asset the user wants to vote for. + asset.v1.Denom incentivized = 1; + // Where to send any rewards for participating in the tournament. + keys.v1.Address rewards_recipient = 2; + // The note containing the staked note used for voting. + penumbra.core.component.shielded_pool.v1.Note staked_note = 3; + // The position of the staked note. + uint64 staked_note_position = 4; + // The start position of the tournament. + uint64 start_position = 5; + // Randomizer for proof of spend capability. + bytes randomizer = 6; + bytes proof_blinding_r = 7; + bytes proof_blinding_s = 8; +} + // A proof of the validity of a liquidity vote, wrt private state. message ZKLiquidityTournamentVoteProof { bytes inner = 1; diff --git a/proto/penumbra/penumbra/core/transaction/v1/transaction.proto b/proto/penumbra/penumbra/core/transaction/v1/transaction.proto index 9a4a195dc0..f0ac40cc9b 100644 --- a/proto/penumbra/penumbra/core/transaction/v1/transaction.proto +++ b/proto/penumbra/penumbra/core/transaction/v1/transaction.proto @@ -341,6 +341,9 @@ message ActionPlan { component.auction.v1.ActionDutchAuctionSchedule action_dutch_auction_schedule = 53; component.auction.v1.ActionDutchAuctionEnd action_dutch_auction_end = 54; component.auction.v1.ActionDutchAuctionWithdrawPlan action_dutch_auction_withdraw = 55; + + // Funding + component.funding.v1.ActionLiquidityTournamentVotePlan action_liquidity_tournament_vote_plan = 70; } } From ed978ad2d754d0b28bde22d654cb5f62f83c350c Mon Sep 17 00:00:00 2001 From: Lucas Meier Date: Thu, 6 Feb 2025 19:47:00 -0800 Subject: [PATCH 03/13] lqt: implement plan struct for votes --- Cargo.lock | 1 + crates/core/component/funding/Cargo.toml | 1 + .../funding/src/liquidity_tournament/mod.rs | 2 + .../src/liquidity_tournament/plan/mod.rs | 125 ++++++++++++++++++ 4 files changed, 129 insertions(+) create mode 100644 crates/core/component/funding/src/liquidity_tournament/plan/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 90be29bdc2..8cb88723e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5244,6 +5244,7 @@ dependencies = [ "penumbra-sdk-tct", "penumbra-sdk-txhash", "proptest", + "rand", "serde", "tendermint 0.40.1", "tonic", diff --git a/crates/core/component/funding/Cargo.toml b/crates/core/component/funding/Cargo.toml index b4ffbc35e3..b103d62511 100644 --- a/crates/core/component/funding/Cargo.toml +++ b/crates/core/component/funding/Cargo.toml @@ -60,6 +60,7 @@ penumbra-sdk-shielded-pool = {workspace = true, default-features = false} penumbra-sdk-stake = {workspace = true, default-features = false} penumbra-sdk-tct = {workspace = true, default-features = false} penumbra-sdk-txhash = {workspace = true, default-features = false} +rand = {workspace = true} serde = {workspace = true, features = ["derive"]} tendermint = {workspace = true} tracing = {workspace = true} diff --git a/crates/core/component/funding/src/liquidity_tournament/mod.rs b/crates/core/component/funding/src/liquidity_tournament/mod.rs index 5a660f69a1..214a6a0af3 100644 --- a/crates/core/component/funding/src/liquidity_tournament/mod.rs +++ b/crates/core/component/funding/src/liquidity_tournament/mod.rs @@ -1,8 +1,10 @@ mod action; +mod plan; mod view; pub mod proof; pub use action::{ActionLiquidityTournamentVote, LiquidityTournamentVoteBody}; +pub use plan::ActionLiquidityTournamentVotePlan; pub use view::ActionLiquidityTournamentVoteView; /// The maximum number of allowable bytes in the denom string. diff --git a/crates/core/component/funding/src/liquidity_tournament/plan/mod.rs b/crates/core/component/funding/src/liquidity_tournament/plan/mod.rs new file mode 100644 index 0000000000..4f917c1205 --- /dev/null +++ b/crates/core/component/funding/src/liquidity_tournament/plan/mod.rs @@ -0,0 +1,125 @@ +use anyhow::{anyhow, Context}; +use decaf377::{Fq, Fr}; +use penumbra_sdk_asset::asset::Denom; +use penumbra_sdk_keys::Address; +use penumbra_sdk_proto::{core::component::funding::v1 as pb, DomainType}; +use penumbra_sdk_shielded_pool::note::Note; +use penumbra_sdk_tct as tct; +use rand::{CryptoRng, RngCore}; +use serde::{Deserialize, Serialize}; +use std::convert::{From, TryFrom}; + +/// A plan to vote in the liquidity tournament. +/// +/// This structure represents the planned vote before it is actually executed, +/// containing the necessary information and blinding factors for the voting proof. +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde( + try_from = "pb::ActionLiquidityTournamentVotePlan", + into = "pb::ActionLiquidityTournamentVotePlan" +)] +pub struct ActionLiquidityTournamentVotePlan { + /// The asset the user wants to vote for. + pub incentivized: Denom, + /// The address the user wants potential rewards to go to. + pub rewards_recipient: Address, + /// The note containing the staked note used for voting. + pub staked_note: Note, + /// The position of the staked note. + pub staked_note_position: tct::Position, + /// The start position of the tournament. + pub start_position: tct::Position, + /// Randomizer for proof of spend capability. + pub randomizer: Fr, + /// The first blinding factor used for generating the ZK proof. + pub proof_blinding_r: Fq, + /// The second blinding factor used for generating the ZK proof. + pub proof_blinding_s: Fq, +} + +impl ActionLiquidityTournamentVotePlan { + /// Create a new [`ActionLiquidityTournamentVotePlan`] that votes using the given positioned [`Note`]. + #[allow(clippy::too_many_arguments)] + pub fn new( + rng: &mut R, + incentivized: Denom, + rewards_recipient: Address, + staked_note: Note, + staked_note_position: tct::Position, + start_position: tct::Position, + ) -> ActionLiquidityTournamentVotePlan { + ActionLiquidityTournamentVotePlan { + incentivized, + rewards_recipient, + staked_note, + staked_note_position, + start_position, + randomizer: Fr::rand(rng), + proof_blinding_r: Fq::rand(rng), + proof_blinding_s: Fq::rand(rng), + } + } +} + +impl DomainType for ActionLiquidityTournamentVotePlan { + type Proto = pb::ActionLiquidityTournamentVotePlan; +} + +impl TryFrom for ActionLiquidityTournamentVotePlan { + type Error = anyhow::Error; + + fn try_from(proto: pb::ActionLiquidityTournamentVotePlan) -> Result { + let proof_blinding_r_bytes: [u8; 32] = proto + .proof_blinding_r + .try_into() + .map_err(|_| anyhow::anyhow!("malformed r in `DelegatorVotePlan`"))?; + let proof_blinding_s_bytes: [u8; 32] = proto + .proof_blinding_s + .try_into() + .map_err(|_| anyhow::anyhow!("malformed s in `DelegatorVotePlan`"))?; + Result::<_, Self::Error>::Ok(Self { + incentivized: proto + .incentivized + .ok_or_else(|| anyhow!("missing `incentivized`"))? + .try_into()?, + rewards_recipient: proto + .rewards_recipient + .ok_or_else(|| anyhow!("missing `rewards_recipient`"))? + .try_into()?, + staked_note: proto + .staked_note + .ok_or_else(|| anyhow!("missing `staked_note`"))? + .try_into()?, + staked_note_position: proto.staked_note_position.into(), + start_position: proto.start_position.into(), + randomizer: Fr::from_bytes_checked( + proto + .randomizer + .as_slice() + .try_into() + .map_err(|_| anyhow::anyhow!("invalid randomizer"))?, + ) + .map_err(|_| anyhow!("randomizer malformed"))?, + proof_blinding_r: Fq::from_bytes_checked(&proof_blinding_r_bytes) + .map_err(|_| anyhow!("proof_blinding_r malformed"))?, + proof_blinding_s: Fq::from_bytes_checked(&proof_blinding_s_bytes) + .map_err(|_| anyhow!("proof_blinding_s malformed"))?, + }) + .with_context(|| format!("while parsing {}", std::any::type_name::())) + } +} + +impl From for pb::ActionLiquidityTournamentVotePlan { + fn from(value: ActionLiquidityTournamentVotePlan) -> Self { + Self { + incentivized: Some(value.incentivized.into()), + rewards_recipient: Some(value.rewards_recipient.into()), + staked_note: Some(value.staked_note.into()), + staked_note_position: value.staked_note_position.into(), + start_position: value.start_position.into(), + randomizer: value.randomizer.to_bytes().to_vec(), + proof_blinding_r: value.proof_blinding_r.to_bytes().to_vec(), + proof_blinding_s: value.proof_blinding_s.to_bytes().to_vec(), + } + } +} From 4144aa0d8cf4d530986795d09a0c3ec41bbe640d Mon Sep 17 00:00:00 2001 From: Lucas Meier Date: Fri, 7 Feb 2025 08:46:35 -0800 Subject: [PATCH 04/13] lqt: propagate lqt vote plan into the app crate --- crates/bin/pcli/src/terminal.rs | 1 + .../app/src/action_handler/actions/submit.rs | 1 + .../src/liquidity_tournament/plan/mod.rs | 83 ++++++++++++++++++- crates/core/transaction/src/gas.rs | 1 + crates/core/transaction/src/plan/action.rs | 28 ++++++- crates/core/transaction/src/view.rs | 1 + 6 files changed, 112 insertions(+), 3 deletions(-) diff --git a/crates/bin/pcli/src/terminal.rs b/crates/bin/pcli/src/terminal.rs index 69dea541d0..df1d36a167 100644 --- a/crates/bin/pcli/src/terminal.rs +++ b/crates/bin/pcli/src/terminal.rs @@ -160,6 +160,7 @@ fn pretty_print_transaction_plan( ActionPlan::ActionDutchAuctionEnd(_) => None, ActionPlan::ActionDutchAuctionWithdraw(_) => None, ActionPlan::IbcAction(_) => todo!(), + ActionPlan::ActionLiquidityTournamentVote(_) => None, } } diff --git a/crates/core/app/src/action_handler/actions/submit.rs b/crates/core/app/src/action_handler/actions/submit.rs index f6abb3b636..23b194a8f3 100644 --- a/crates/core/app/src/action_handler/actions/submit.rs +++ b/crates/core/app/src/action_handler/actions/submit.rs @@ -93,6 +93,7 @@ impl AppActionHandler for ProposalSubmit { anyhow::bail!("invalid action in Community Pool spend proposal (not allowed to manipulate proposals from within proposals)") } ValidatorDefinition(_) + | ActionLiquidityTournamentVote(_) | IbcAction(_) | ValidatorVote(_) | PositionOpen(_) diff --git a/crates/core/component/funding/src/liquidity_tournament/plan/mod.rs b/crates/core/component/funding/src/liquidity_tournament/plan/mod.rs index 4f917c1205..a73d172905 100644 --- a/crates/core/component/funding/src/liquidity_tournament/plan/mod.rs +++ b/crates/core/component/funding/src/liquidity_tournament/plan/mod.rs @@ -1,14 +1,25 @@ use anyhow::{anyhow, Context}; use decaf377::{Fq, Fr}; +use decaf377_rdsa::{Signature, SpendAuth}; use penumbra_sdk_asset::asset::Denom; -use penumbra_sdk_keys::Address; +use penumbra_sdk_keys::{Address, FullViewingKey}; +use penumbra_sdk_proof_params::DELEGATOR_VOTE_PROOF_PROVING_KEY; use penumbra_sdk_proto::{core::component::funding::v1 as pb, DomainType}; +use penumbra_sdk_sct::Nullifier; use penumbra_sdk_shielded_pool::note::Note; -use penumbra_sdk_tct as tct; +use penumbra_sdk_tct::{self as tct}; use rand::{CryptoRng, RngCore}; use serde::{Deserialize, Serialize}; use std::convert::{From, TryFrom}; +use super::{ + proof::{ + LiquidityTournamentVoteProof, LiquidityTournamentVoteProofPrivate, + LiquidityTournamentVoteProofPublic, + }, + ActionLiquidityTournamentVote, LiquidityTournamentVoteBody, +}; + /// A plan to vote in the liquidity tournament. /// /// This structure represents the planned vote before it is actually executed, @@ -59,6 +70,74 @@ impl ActionLiquidityTournamentVotePlan { proof_blinding_s: Fq::rand(rng), } } + + pub fn to_body(&self, fvk: &FullViewingKey) -> LiquidityTournamentVoteBody { + let commitment = self.staked_note.commit(); + + let nk = fvk.nullifier_key(); + let nullifier = Nullifier::derive(nk, self.staked_note_position, &commitment); + let ak = fvk.spend_verification_key(); + let rk = ak.randomize(&self.randomizer); + let value = self.staked_note.value(); + + LiquidityTournamentVoteBody { + incentivized: self.incentivized.clone(), + rewards_recipient: self.rewards_recipient.clone(), + start_position: self.start_position, + value, + nullifier, + rk, + } + } + + /// Convert this plan into an action. + /// + /// * `fvk`: [`FullViewingKey`], in order to derive keys. + /// * `auth_sig`: [`Signature`], as the signature for the transaction. + /// * `auth_path`: [`tct::Proof`], witnessing the inclusion of the spent note. + pub fn to_action( + self, + fvk: &FullViewingKey, + auth_sig: Signature, + auth_path: tct::Proof, + ) -> ActionLiquidityTournamentVote { + let commitment = self.staked_note.commit(); + + let nk = fvk.nullifier_key(); + let nullifier = Nullifier::derive(nk, self.staked_note_position, &commitment); + let ak = fvk.spend_verification_key(); + let rk = ak.randomize(&self.randomizer); + let value = self.staked_note.value(); + + let public = LiquidityTournamentVoteProofPublic { + anchor: auth_path.root(), + value, + nullifier, + rk, + start_position: self.start_position, + }; + let private = LiquidityTournamentVoteProofPrivate { + state_commitment_proof: auth_path, + note: self.staked_note.clone(), + spend_auth_randomizer: self.randomizer, + ak: *ak, + nk: *nk, + }; + let proof = LiquidityTournamentVoteProof::prove( + self.proof_blinding_r, + self.proof_blinding_s, + &DELEGATOR_VOTE_PROOF_PROVING_KEY, + public, + private, + ) + .expect("can generate ZK LQT voting proof"); + + ActionLiquidityTournamentVote { + body: self.to_body(fvk), + auth_sig, + proof, + } + } } impl DomainType for ActionLiquidityTournamentVotePlan { diff --git a/crates/core/transaction/src/gas.rs b/crates/core/transaction/src/gas.rs index af236bb012..8880144249 100644 --- a/crates/core/transaction/src/gas.rs +++ b/crates/core/transaction/src/gas.rs @@ -371,6 +371,7 @@ impl GasCost for ActionPlan { ActionPlan::CommunityPoolOutput(d) => d.gas_cost(), ActionPlan::CommunityPoolDeposit(dd) => dd.gas_cost(), ActionPlan::Ics20Withdrawal(w) => w.gas_cost(), + ActionPlan::ActionLiquidityTournamentVote(_) => liquidity_tournament_vote_gas_cost(), } } } diff --git a/crates/core/transaction/src/plan/action.rs b/crates/core/transaction/src/plan/action.rs index 0a59370adc..35ff93bc2e 100644 --- a/crates/core/transaction/src/plan/action.rs +++ b/crates/core/transaction/src/plan/action.rs @@ -8,6 +8,7 @@ use penumbra_sdk_auction::auction::dutch::actions::ActionDutchAuctionEnd; use penumbra_sdk_auction::auction::dutch::actions::ActionDutchAuctionSchedule; use penumbra_sdk_auction::auction::dutch::actions::ActionDutchAuctionWithdrawPlan; use penumbra_sdk_community_pool::{CommunityPoolDeposit, CommunityPoolOutput, CommunityPoolSpend}; +use penumbra_sdk_funding::liquidity_tournament::ActionLiquidityTournamentVotePlan; use penumbra_sdk_txhash::{EffectHash, EffectingData}; use penumbra_sdk_dex::{ @@ -82,6 +83,8 @@ pub enum ActionPlan { ActionDutchAuctionSchedule(ActionDutchAuctionSchedule), ActionDutchAuctionEnd(ActionDutchAuctionEnd), ActionDutchAuctionWithdraw(ActionDutchAuctionWithdrawPlan), + + ActionLiquidityTournamentVote(ActionLiquidityTournamentVotePlan), } impl ActionPlan { @@ -165,6 +168,18 @@ impl ActionPlan { ActionDutchAuctionWithdraw(plan) => { Action::ActionDutchAuctionWithdraw(plan.to_action()) } + ActionLiquidityTournamentVote(plan) => { + let note_commitment = plan.staked_note.commit(); + let auth_path = witness_data + .state_commitment_proofs + .get(¬e_commitment) + .context(format!("could not get proof for {note_commitment:?}"))?; + Action::ActionLiquidityTournamentVote(plan.to_action( + fvk, + [0; 64].into(), + auth_path.clone(), + )) + } }) } @@ -195,6 +210,7 @@ impl ActionPlan { ActionPlan::ActionDutchAuctionSchedule(_) => 53, ActionPlan::ActionDutchAuctionEnd(_) => 54, ActionPlan::ActionDutchAuctionWithdraw(_) => 55, + ActionPlan::ActionLiquidityTournamentVote(_) => 70, } } @@ -225,7 +241,10 @@ impl ActionPlan { ActionDutchAuctionWithdraw(action) => action.balance(), // None of these contribute to transaction balance: - IbcAction(_) | ValidatorDefinition(_) | ValidatorVote(_) => Balance::default(), + IbcAction(_) + | ValidatorDefinition(_) + | ValidatorVote(_) + | ActionLiquidityTournamentVote(_) => Balance::default(), } } @@ -257,6 +276,7 @@ impl ActionPlan { ActionDutchAuctionSchedule(_) => Fr::zero(), ActionDutchAuctionEnd(_) => Fr::zero(), ActionDutchAuctionWithdraw(_) => Fr::zero(), + ActionLiquidityTournamentVote(_) => Fr::zero(), } } @@ -289,6 +309,7 @@ impl ActionPlan { ActionDutchAuctionSchedule(plan) => plan.effect_hash(), ActionDutchAuctionEnd(plan) => plan.effect_hash(), ActionDutchAuctionWithdraw(plan) => plan.to_action().effect_hash(), + ActionLiquidityTournamentVote(plan) => plan.to_body(fvk).effect_hash(), } } } @@ -532,6 +553,11 @@ impl From for pb_t::ActionPlan { inner.into(), )), }, + ActionPlan::ActionLiquidityTournamentVote(inner) => pb_t::ActionPlan { + action: Some( + pb_t::action_plan::Action::ActionLiquidityTournamentVotePlan(inner.into()), + ), + }, } } } diff --git a/crates/core/transaction/src/view.rs b/crates/core/transaction/src/view.rs index 14ca9e95b6..74d46b1cc6 100644 --- a/crates/core/transaction/src/view.rs +++ b/crates/core/transaction/src/view.rs @@ -710,6 +710,7 @@ mod test { ActionPlan::ActionDutchAuctionEnd(_) => None, ActionPlan::ActionDutchAuctionWithdraw(_) => None, ActionPlan::IbcAction(_) => todo!(), + ActionPlan::ActionLiquidityTournamentVote(_) => todo!(), } } From edc95c0302aa0299c41265e3cc755c8767428ddf Mon Sep 17 00:00:00 2001 From: Lucas Meier Date: Fri, 7 Feb 2025 23:12:04 -0800 Subject: [PATCH 05/13] lqt: add From instance for ActionPlan Missed this in the last commit, needed later for planner, so we can push onto the ActionList. --- crates/core/transaction/src/plan/action.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/core/transaction/src/plan/action.rs b/crates/core/transaction/src/plan/action.rs index 35ff93bc2e..c2ad5eca4b 100644 --- a/crates/core/transaction/src/plan/action.rs +++ b/crates/core/transaction/src/plan/action.rs @@ -460,6 +460,12 @@ impl From for ActionPlan { } } +impl From for ActionPlan { + fn from(inner: ActionLiquidityTournamentVotePlan) -> ActionPlan { + ActionPlan::ActionLiquidityTournamentVote(inner) + } +} + impl DomainType for ActionPlan { type Proto = pb_t::ActionPlan; } From 8b94bd22b0b279a7714b8764486b0a5d0a17768a Mon Sep 17 00:00:00 2001 From: Lucas Meier Date: Thu, 6 Feb 2025 13:02:06 -0800 Subject: [PATCH 06/13] view: add epochs to storage Needed for the LQT, and also matches what prax does. --- crates/view/src/storage.rs | 69 ++++++++++++++++++++++++++++-- crates/view/src/storage/schema.sql | 6 +++ crates/view/src/worker.rs | 11 +++++ 3 files changed, 82 insertions(+), 4 deletions(-) diff --git a/crates/view/src/storage.rs b/crates/view/src/storage.rs index 0d88e650da..d8ae66903a 100644 --- a/crates/view/src/storage.rs +++ b/crates/view/src/storage.rs @@ -37,7 +37,7 @@ use penumbra_sdk_proto::{ use penumbra_sdk_sct::{CommitmentSource, Nullifier}; use penumbra_sdk_shielded_pool::{fmd, note, Note, Rseed}; use penumbra_sdk_stake::{DelegationToken, IdentityKey}; -use penumbra_sdk_tct as tct; +use penumbra_sdk_tct::{self as tct, builder::epoch::Root}; use penumbra_sdk_transaction::Transaction; use sct::TreeStore; use tct::StateCommitment; @@ -207,7 +207,7 @@ impl Storage { // Connect to the database (or create it) let pool = Self::connect(storage_path)?; - spawn_blocking(move || { + let out = spawn_blocking(move || { // In one database transaction, populate everything let mut conn = pool.get()?; let tx = conn.transaction()?; @@ -244,7 +244,7 @@ impl Storage { tx.commit()?; drop(conn); - Ok(Storage { + anyhow::Ok(Storage { pool, uncommitted_height: Arc::new(Mutex::new(None)), scanned_notes_tx: broadcast::channel(128).0, @@ -252,7 +252,11 @@ impl Storage { scanned_swaps_tx: broadcast::channel(128).0, }) }) - .await? + .await??; + + out.update_epoch(0, None, Some(0)).await?; + + Ok(out) } /// Loads asset metadata from a JSON file and use to update the database. @@ -1785,4 +1789,61 @@ impl Storage { }) .await? } + + /// Update information about an epoch. + pub async fn update_epoch( + &self, + epoch: u64, + root: Option, + start_height: Option, + ) -> anyhow::Result<()> { + let pool = self.pool.clone(); + + spawn_blocking(move || { + pool.get()? + .execute( + r#" + INSERT INTO epochs(epoch_index, root, start_height) + VALUES (?1, ?2, ?3) + ON CONFLICT(epoch_index) + DO UPDATE SET + root = COALESCE(?2, root), + start_height = COALESCE(?3, start_height) + "#, + (epoch, root.map(|x| x.encode_to_vec()), start_height), + ) + .map_err(anyhow::Error::from) + }) + .await??; + + Ok(()) + } + + /// Fetch information about the current epoch. + /// + /// This will return the root of the epoch, if present, + /// and the start height of the epoch, if present. + pub async fn get_epoch(&self, epoch: u64) -> anyhow::Result<(Option, Option)> { + let pool = self.pool.clone(); + + spawn_blocking(move || { + pool.get()? + .query_row_and_then( + r#" + SELECT root, start_height + FROM epochs + WHERE epoch_index = ?1 + "#, + (epoch,), + |row| { + let root_raw: Option> = row.get("root")?; + let start_height: Option = row.get("start_height")?; + let root = root_raw.map(|x| Root::decode(x.as_slice())).transpose()?; + anyhow::Ok((root, start_height)) + }, + ) + .map_err(anyhow::Error::from) + }) + .await? + } } diff --git a/crates/view/src/storage/schema.sql b/crates/view/src/storage/schema.sql index 41c52ba820..85f1a95fb2 100644 --- a/crates/view/src/storage/schema.sql +++ b/crates/view/src/storage/schema.sql @@ -140,3 +140,9 @@ CREATE TABLE auctions ( auction_state BIGINT NOT NULL, note_commitment BLOB ); + +CREATE TABLE epochs ( + epoch_index BIGINT PRIMARY KEY, + root BLOB, + start_height BIGINT +); diff --git a/crates/view/src/worker.rs b/crates/view/src/worker.rs index 8ca7bbf5ca..37cab01993 100644 --- a/crates/view/src/worker.rs +++ b/crates/view/src/worker.rs @@ -236,6 +236,17 @@ impl Worker { // Lock the SCT only while processing this block. let mut sct_guard = self.sct.write().await; + if let Some(root) = block.epoch_root { + // We now know the root for this epoch. + self.storage + .update_epoch(block.epoch_index, Some(root), None) + .await?; + // And also where the next epoch starts, since this block is the last. + self.storage + .update_epoch(block.epoch_index + 1, None, Some(block.height + 1)) + .await?; + } + if !block.requires_scanning() { // Optimization: if the block is empty, seal the in-memory SCT, // and skip touching the database: From a54ddc7a1cba1dfaf235ac72d0611ed07df53033 Mon Sep 17 00:00:00 2001 From: Lucas Meier Date: Thu, 6 Feb 2025 15:11:58 -0800 Subject: [PATCH 07/13] view: implement lqt voting notes request --- crates/view/src/service.rs | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/crates/view/src/service.rs b/crates/view/src/service.rs index 204037bc73..a307b55197 100644 --- a/crates/view/src/service.rs +++ b/crates/view/src/service.rs @@ -57,13 +57,13 @@ use penumbra_sdk_proto::{ }, DomainType, }; -use penumbra_sdk_stake::rate::RateData; +use penumbra_sdk_stake::{rate::RateData, IdentityKey}; use penumbra_sdk_tct::{Proof, StateCommitment}; use penumbra_sdk_transaction::{ AuthorizationData, Transaction, TransactionPerspective, TransactionPlan, WitnessData, }; -use crate::{worker::Worker, Planner, Storage}; +use crate::{worker::Worker, Planner, SpendableNoteRecord, Storage}; /// A [`futures::Stream`] of broadcast transaction responses. /// @@ -1886,9 +1886,36 @@ impl ViewService for ViewServer { #[instrument(skip_all, level = "trace")] async fn lqt_voting_notes( &self, - _request: tonic::Request, + request: tonic::Request, ) -> Result, tonic::Status> { - unimplemented!("lqt_voting_notes currently only implemented on web") + async fn inner( + this: &ViewServer, + epoch: u64, + filter: Option, + ) -> anyhow::Result> { + let (_, start_height) = this.storage.get_epoch(epoch).await?; + let start_height = + start_height.ok_or_else(|| anyhow!("missing height for epoch {epoch}"))?; + let notes = this.storage.notes_for_voting(filter, start_height).await?; + Ok(notes) + } + + let request = request.into_inner(); + let epoch = request.epoch_index; + let filter = request + .account_filter + .map(|x| AddressIndex::try_from(x)) + .transpose() + .map_err(|_| tonic::Status::invalid_argument("invalid account filter"))?; + let notes = inner(self, epoch, filter).await.map_err(|e| { + tonic::Status::internal(format!("error fetching voting notes: {:#}", e)) + })?; + let stream = tokio_stream::iter(notes.into_iter().map(|(note, _)| { + Result::<_, tonic::Status>::Ok(pb::LqtVotingNotesResponse { + note_record: Some(note.into()), + }) + })); + Ok(tonic::Response::new(stream.boxed())) } } From 74670e8c35c1c51d6700386cbc1d4a650fc01a52 Mon Sep 17 00:00:00 2001 From: Lucas Meier Date: Thu, 6 Feb 2025 16:13:41 -0800 Subject: [PATCH 08/13] view: implement nice lqt querying api --- crates/proto/src/gen/penumbra.view.v1.rs | 1906 +++++++--------------- crates/view/src/client.rs | 36 + 2 files changed, 667 insertions(+), 1275 deletions(-) diff --git a/crates/proto/src/gen/penumbra.view.v1.rs b/crates/proto/src/gen/penumbra.view.v1.rs index cdae31ef23..c7dfab2f0b 100644 --- a/crates/proto/src/gen/penumbra.view.v1.rs +++ b/crates/proto/src/gen/penumbra.view.v1.rs @@ -6,9 +6,7 @@ pub struct LqtVotingNotesRequest { pub epoch_index: u64, /// If present, filter balances to only include the account specified by the `AddressIndex`. #[prost(message, optional, tag = "2")] - pub account_filter: ::core::option::Option< - super::super::core::keys::v1::AddressIndex, - >, + pub account_filter: ::core::option::Option, } impl ::prost::Name for LqtVotingNotesRequest { const NAME: &'static str = "LqtVotingNotesRequest"; @@ -49,9 +47,7 @@ pub struct TournamentVotesRequest { pub block_height: u64, /// If present, filter balances to only include the account specified by the `AddressIndex`. #[prost(message, optional, tag = "3")] - pub account_filter: ::core::option::Option< - super::super::core::keys::v1::AddressIndex, - >, + pub account_filter: ::core::option::Option, } impl ::prost::Name for TournamentVotesRequest { const NAME: &'static str = "TournamentVotesRequest"; @@ -75,22 +71,18 @@ pub mod tournament_votes_response { pub struct Vote { /// The incentivized asset receiving this vote. #[prost(message, optional, tag = "1")] - pub incentivized_asset: ::core::option::Option< - super::super::super::core::asset::v1::AssetId, - >, + pub incentivized_asset: + ::core::option::Option, /// The amount of voting power that this specific vote contributed. #[prost(message, optional, tag = "2")] - pub vote_power: ::core::option::Option< - super::super::super::core::num::v1::Amount, - >, + pub vote_power: ::core::option::Option, /// The amount of rewards issued for votes on this asset. #[prost(message, optional, tag = "3")] pub reward: ::core::option::Option, /// The transaction ID for the vote. #[prost(message, optional, tag = "4")] - pub transaction: ::core::option::Option< - super::super::super::core::txhash::v1::TransactionId, - >, + pub transaction: + ::core::option::Option, } impl ::prost::Name for Vote { const NAME: &'static str = "Vote"; @@ -152,9 +144,7 @@ impl ::prost::Name for TransparentAddressResponse { pub struct AuctionsRequest { /// If present, filter balances to only include the account specified by the `AddressIndex`. #[prost(message, optional, tag = "1")] - pub account_filter: ::core::option::Option< - super::super::core::keys::v1::AddressIndex, - >, + pub account_filter: ::core::option::Option, /// If present, include inactive auctions as well as active ones. #[prost(bool, tag = "2")] pub include_inactive: bool, @@ -163,9 +153,8 @@ pub struct AuctionsRequest { pub query_latest_state: bool, /// If present, filter to only include auctions whose IDs are in this array. #[prost(message, repeated, tag = "4")] - pub auction_ids_filter: ::prost::alloc::vec::Vec< - super::super::core::component::auction::v1::AuctionId, - >, + pub auction_ids_filter: + ::prost::alloc::vec::Vec, } impl ::prost::Name for AuctionsRequest { const NAME: &'static str = "AuctionsRequest"; @@ -180,9 +169,7 @@ impl ::prost::Name for AuctionsRequest { #[derive(Clone, PartialEq, ::prost::Message)] pub struct AuctionsResponse { #[prost(message, optional, tag = "1")] - pub id: ::core::option::Option< - super::super::core::component::auction::v1::AuctionId, - >, + pub id: ::core::option::Option, /// The state of the returned auction. /// /// Only present when `query_latest_state` was provided. @@ -193,9 +180,7 @@ pub struct AuctionsResponse { /// Only present when `query_latest_state` was provided. /// Could be empty, depending on the auction state. #[prost(message, repeated, tag = "3")] - pub positions: ::prost::alloc::vec::Vec< - super::super::core::component::dex::v1::Position, - >, + pub positions: ::prost::alloc::vec::Vec, /// The note recording the auction NFT. #[prost(message, optional, tag = "4")] pub note_record: ::core::option::Option, @@ -225,9 +210,8 @@ impl ::prost::Name for AuctionsResponse { pub struct AuthorizeAndBuildRequest { /// The transaction plan to authorize and build. #[prost(message, optional, tag = "1")] - pub transaction_plan: ::core::option::Option< - super::super::core::transaction::v1::TransactionPlan, - >, + pub transaction_plan: + ::core::option::Option, } impl ::prost::Name for AuthorizeAndBuildRequest { const NAME: &'static str = "AuthorizeAndBuildRequest"; @@ -268,9 +252,8 @@ pub mod authorize_and_build_response { pub struct Complete { /// The finished transaction. #[prost(message, optional, tag = "1")] - pub transaction: ::core::option::Option< - super::super::super::core::transaction::v1::Transaction, - >, + pub transaction: + ::core::option::Option, } impl ::prost::Name for Complete { const NAME: &'static str = "Complete"; @@ -304,9 +287,7 @@ impl ::prost::Name for AuthorizeAndBuildResponse { pub struct BroadcastTransactionRequest { /// The transaction to broadcast. #[prost(message, optional, tag = "1")] - pub transaction: ::core::option::Option< - super::super::core::transaction::v1::Transaction, - >, + pub transaction: ::core::option::Option, /// If true, wait for the view service to detect the transaction during sync. #[prost(bool, tag = "2")] pub await_detection: bool, @@ -333,9 +314,7 @@ pub mod broadcast_transaction_response { pub struct BroadcastSuccess { /// The hash of the transaction that was broadcast. #[prost(message, optional, tag = "1")] - pub id: ::core::option::Option< - super::super::super::core::txhash::v1::TransactionId, - >, + pub id: ::core::option::Option, } impl ::prost::Name for BroadcastSuccess { const NAME: &'static str = "BroadcastSuccess"; @@ -354,9 +333,7 @@ pub mod broadcast_transaction_response { pub struct Confirmed { /// The hash of the transaction that was broadcast. #[prost(message, optional, tag = "1")] - pub id: ::core::option::Option< - super::super::super::core::txhash::v1::TransactionId, - >, + pub id: ::core::option::Option, /// The height in which the transaction was detected as included in the chain, if any. #[prost(uint64, tag = "2")] pub detection_height: u64, @@ -415,45 +392,30 @@ pub struct TransactionPlannerRequest { #[prost(message, repeated, tag = "50")] pub undelegations: ::prost::alloc::vec::Vec, #[prost(message, repeated, tag = "51")] - pub undelegation_claims: ::prost::alloc::vec::Vec< - transaction_planner_request::UndelegateClaim, - >, + pub undelegation_claims: ::prost::alloc::vec::Vec, #[prost(message, repeated, tag = "60")] - pub ibc_relay_actions: ::prost::alloc::vec::Vec< - super::super::core::component::ibc::v1::IbcRelay, - >, + pub ibc_relay_actions: + ::prost::alloc::vec::Vec, #[prost(message, repeated, tag = "61")] - pub ics20_withdrawals: ::prost::alloc::vec::Vec< - super::super::core::component::ibc::v1::Ics20Withdrawal, - >, + pub ics20_withdrawals: + ::prost::alloc::vec::Vec, #[prost(message, repeated, tag = "70")] - pub position_opens: ::prost::alloc::vec::Vec< - transaction_planner_request::PositionOpen, - >, + pub position_opens: ::prost::alloc::vec::Vec, #[prost(message, repeated, tag = "71")] - pub position_closes: ::prost::alloc::vec::Vec< - transaction_planner_request::PositionClose, - >, + pub position_closes: ::prost::alloc::vec::Vec, #[prost(message, repeated, tag = "72")] - pub position_withdraws: ::prost::alloc::vec::Vec< - transaction_planner_request::PositionWithdraw, - >, + pub position_withdraws: ::prost::alloc::vec::Vec, #[prost(message, repeated, tag = "73")] - pub dutch_auction_schedule_actions: ::prost::alloc::vec::Vec< - transaction_planner_request::ActionDutchAuctionSchedule, - >, + pub dutch_auction_schedule_actions: + ::prost::alloc::vec::Vec, #[prost(message, repeated, tag = "74")] - pub dutch_auction_end_actions: ::prost::alloc::vec::Vec< - transaction_planner_request::ActionDutchAuctionEnd, - >, + pub dutch_auction_end_actions: + ::prost::alloc::vec::Vec, #[prost(message, repeated, tag = "75")] - pub dutch_auction_withdraw_actions: ::prost::alloc::vec::Vec< - transaction_planner_request::ActionDutchAuctionWithdraw, - >, + pub dutch_auction_withdraw_actions: + ::prost::alloc::vec::Vec, #[prost(message, repeated, tag = "76")] - pub delegator_votes: ::prost::alloc::vec::Vec< - transaction_planner_request::DelegatorVote, - >, + pub delegator_votes: ::prost::alloc::vec::Vec, /// The epoch index of the transaction being planned. #[deprecated] #[prost(uint64, tag = "200")] @@ -475,9 +437,7 @@ pub mod transaction_planner_request { pub value: ::core::option::Option, /// The address to which Output will be sent. #[prost(message, optional, tag = "2")] - pub address: ::core::option::Option< - super::super::super::core::keys::v1::Address, - >, + pub address: ::core::option::Option, } impl ::prost::Name for Output { const NAME: &'static str = "Output"; @@ -496,9 +456,7 @@ pub mod transaction_planner_request { pub value: ::core::option::Option, /// The source address from which the Spend will be sent. #[prost(message, optional, tag = "2")] - pub address: ::core::option::Option< - super::super::super::core::keys::v1::Address, - >, + pub address: ::core::option::Option, } impl ::prost::Name for Spend { const NAME: &'static str = "Spend"; @@ -517,19 +475,13 @@ pub mod transaction_planner_request { pub value: ::core::option::Option, /// The denomination to be received as a Output of the Swap. #[prost(message, optional, tag = "2")] - pub target_asset: ::core::option::Option< - super::super::super::core::asset::v1::AssetId, - >, + pub target_asset: ::core::option::Option, /// The pre-paid fee to be paid for claiming the Swap outputs. #[prost(message, optional, tag = "3")] - pub fee: ::core::option::Option< - super::super::super::core::component::fee::v1::Fee, - >, + pub fee: ::core::option::Option, /// The address to which swap claim output will be sent. #[prost(message, optional, tag = "4")] - pub claim_address: ::core::option::Option< - super::super::super::core::keys::v1::Address, - >, + pub claim_address: ::core::option::Option, } impl ::prost::Name for Swap { const NAME: &'static str = "Swap"; @@ -547,9 +499,8 @@ pub mod transaction_planner_request { /// Use the commitment from the Swap message: /// penumbra.core.component.dex.v1.Swap.body.payload.commitment. #[prost(message, optional, tag = "1")] - pub swap_commitment: ::core::option::Option< - super::super::super::crypto::tct::v1::StateCommitment, - >, + pub swap_commitment: + ::core::option::Option, } impl ::prost::Name for SwapClaim { const NAME: &'static str = "SwapClaim"; @@ -566,9 +517,8 @@ pub mod transaction_planner_request { #[prost(message, optional, tag = "1")] pub amount: ::core::option::Option, #[prost(message, optional, tag = "3")] - pub rate_data: ::core::option::Option< - super::super::super::core::component::stake::v1::RateData, - >, + pub rate_data: + ::core::option::Option, } impl ::prost::Name for Delegate { const NAME: &'static str = "Delegate"; @@ -585,9 +535,8 @@ pub mod transaction_planner_request { #[prost(message, optional, tag = "1")] pub value: ::core::option::Option, #[prost(message, optional, tag = "2")] - pub rate_data: ::core::option::Option< - super::super::super::core::component::stake::v1::RateData, - >, + pub rate_data: + ::core::option::Option, } impl ::prost::Name for Undelegate { const NAME: &'static str = "Undelegate"; @@ -603,9 +552,8 @@ pub mod transaction_planner_request { pub struct UndelegateClaim { /// The identity key of the validator to finish undelegating from. #[prost(message, optional, tag = "1")] - pub validator_identity: ::core::option::Option< - super::super::super::core::keys::v1::IdentityKey, - >, + pub validator_identity: + ::core::option::Option, /// The epoch in which unbonding began, used to verify the penalty. #[deprecated] #[prost(uint64, tag = "2")] @@ -613,15 +561,12 @@ pub mod transaction_planner_request { /// The penalty applied to undelegation, in bps^2 (10e-8). /// In the happy path (no slashing), this is 0. #[prost(message, optional, tag = "3")] - pub penalty: ::core::option::Option< - super::super::super::core::component::stake::v1::Penalty, - >, + pub penalty: + ::core::option::Option, /// The amount of unbonding tokens to claim. /// This is a bare number because its denom is determined by the preceding data. #[prost(message, optional, tag = "4")] - pub unbonding_amount: ::core::option::Option< - super::super::super::core::num::v1::Amount, - >, + pub unbonding_amount: ::core::option::Option, /// The height at which unbonding began. #[prost(uint64, tag = "5")] pub unbonding_start_height: u64, @@ -643,9 +588,8 @@ pub mod transaction_planner_request { /// Positions are immutable, so the `PositionData` (and hence the `PositionId`) /// are unchanged over the entire lifetime of the position. #[prost(message, optional, tag = "1")] - pub position: ::core::option::Option< - super::super::super::core::component::dex::v1::Position, - >, + pub position: + ::core::option::Option, } impl ::prost::Name for PositionOpen { const NAME: &'static str = "PositionOpen"; @@ -661,9 +605,8 @@ pub mod transaction_planner_request { pub struct PositionClose { /// The position to close. #[prost(message, optional, tag = "1")] - pub position_id: ::core::option::Option< - super::super::super::core::component::dex::v1::PositionId, - >, + pub position_id: + ::core::option::Option, } impl ::prost::Name for PositionClose { const NAME: &'static str = "PositionClose"; @@ -679,19 +622,16 @@ pub mod transaction_planner_request { pub struct PositionWithdraw { /// The position to withdraw. #[prost(message, optional, tag = "1")] - pub position_id: ::core::option::Option< - super::super::super::core::component::dex::v1::PositionId, - >, + pub position_id: + ::core::option::Option, /// The position's final reserves. #[prost(message, optional, tag = "2")] - pub reserves: ::core::option::Option< - super::super::super::core::component::dex::v1::Reserves, - >, + pub reserves: + ::core::option::Option, /// The trading pair of the position. #[prost(message, optional, tag = "3")] - pub trading_pair: ::core::option::Option< - super::super::super::core::component::dex::v1::TradingPair, - >, + pub trading_pair: + ::core::option::Option, } impl ::prost::Name for PositionWithdraw { const NAME: &'static str = "PositionWithdraw"; @@ -715,21 +655,18 @@ pub mod transaction_planner_request { const NAME: &'static str = "ActionDutchAuctionSchedule"; const PACKAGE: &'static str = "penumbra.view.v1"; fn full_name() -> ::prost::alloc::string::String { - "penumbra.view.v1.TransactionPlannerRequest.ActionDutchAuctionSchedule" - .into() + "penumbra.view.v1.TransactionPlannerRequest.ActionDutchAuctionSchedule".into() } fn type_url() -> ::prost::alloc::string::String { - "/penumbra.view.v1.TransactionPlannerRequest.ActionDutchAuctionSchedule" - .into() + "/penumbra.view.v1.TransactionPlannerRequest.ActionDutchAuctionSchedule".into() } } #[derive(Clone, PartialEq, ::prost::Message)] pub struct ActionDutchAuctionEnd { /// The unique id of the auction to close. #[prost(message, optional, tag = "1")] - pub auction_id: ::core::option::Option< - super::super::super::core::component::auction::v1::AuctionId, - >, + pub auction_id: + ::core::option::Option, } impl ::prost::Name for ActionDutchAuctionEnd { const NAME: &'static str = "ActionDutchAuctionEnd"; @@ -745,9 +682,8 @@ pub mod transaction_planner_request { pub struct ActionDutchAuctionWithdraw { /// The auction to withdraw funds from. #[prost(message, optional, tag = "1")] - pub auction_id: ::core::option::Option< - super::super::super::core::component::auction::v1::AuctionId, - >, + pub auction_id: + ::core::option::Option, /// The sequence number of the withdrawal. #[prost(uint64, tag = "2")] pub seq: u64, @@ -756,12 +692,10 @@ pub mod transaction_planner_request { const NAME: &'static str = "ActionDutchAuctionWithdraw"; const PACKAGE: &'static str = "penumbra.view.v1"; fn full_name() -> ::prost::alloc::string::String { - "penumbra.view.v1.TransactionPlannerRequest.ActionDutchAuctionWithdraw" - .into() + "penumbra.view.v1.TransactionPlannerRequest.ActionDutchAuctionWithdraw".into() } fn type_url() -> ::prost::alloc::string::String { - "/penumbra.view.v1.TransactionPlannerRequest.ActionDutchAuctionWithdraw" - .into() + "/penumbra.view.v1.TransactionPlannerRequest.ActionDutchAuctionWithdraw".into() } } #[derive(Clone, PartialEq, ::prost::Message)] @@ -771,9 +705,8 @@ pub mod transaction_planner_request { pub proposal: u64, /// The vote. #[prost(message, optional, tag = "2")] - pub vote: ::core::option::Option< - super::super::super::core::component::governance::v1::Vote, - >, + pub vote: + ::core::option::Option, /// The block height at which the proposal started voting. #[prost(uint64, tag = "3")] pub start_block_height: u64, @@ -782,9 +715,8 @@ pub mod transaction_planner_request { pub start_position: u64, /// The validators rate data for the proposal. #[prost(message, repeated, tag = "5")] - pub rate_data: ::prost::alloc::vec::Vec< - super::super::super::core::component::stake::v1::RateData, - >, + pub rate_data: + ::prost::alloc::vec::Vec, } impl ::prost::Name for DelegatorVote { const NAME: &'static str = "DelegatorVote"; @@ -820,9 +752,7 @@ impl ::prost::Name for TransactionPlannerRequest { #[derive(Clone, PartialEq, ::prost::Message)] pub struct TransactionPlannerResponse { #[prost(message, optional, tag = "1")] - pub plan: ::core::option::Option< - super::super::core::transaction::v1::TransactionPlan, - >, + pub plan: ::core::option::Option, } impl ::prost::Name for TransactionPlannerResponse { const NAME: &'static str = "TransactionPlannerResponse"; @@ -837,9 +767,7 @@ impl ::prost::Name for TransactionPlannerResponse { #[derive(Clone, PartialEq, ::prost::Message)] pub struct AddressByIndexRequest { #[prost(message, optional, tag = "1")] - pub address_index: ::core::option::Option< - super::super::core::keys::v1::AddressIndex, - >, + pub address_index: ::core::option::Option, } impl ::prost::Name for AddressByIndexRequest { const NAME: &'static str = "AddressByIndexRequest"; @@ -912,9 +840,7 @@ impl ::prost::Name for IndexByAddressRequest { pub struct IndexByAddressResponse { /// Will be absent if given an address not viewable by this viewing service #[prost(message, optional, tag = "1")] - pub address_index: ::core::option::Option< - super::super::core::keys::v1::AddressIndex, - >, + pub address_index: ::core::option::Option, } impl ::prost::Name for IndexByAddressResponse { const NAME: &'static str = "IndexByAddressResponse"; @@ -929,9 +855,7 @@ impl ::prost::Name for IndexByAddressResponse { #[derive(Clone, PartialEq, ::prost::Message)] pub struct EphemeralAddressRequest { #[prost(message, optional, tag = "1")] - pub address_index: ::core::option::Option< - super::super::core::keys::v1::AddressIndex, - >, + pub address_index: ::core::option::Option, } impl ::prost::Name for EphemeralAddressRequest { const NAME: &'static str = "EphemeralAddressRequest"; @@ -962,9 +886,7 @@ impl ::prost::Name for EphemeralAddressResponse { pub struct BalancesRequest { /// If present, filter balances to only include the account specified by the `AddressIndex`. #[prost(message, optional, tag = "1")] - pub account_filter: ::core::option::Option< - super::super::core::keys::v1::AddressIndex, - >, + pub account_filter: ::core::option::Option, /// If present, filter balances to only include the specified asset ID. #[prost(message, optional, tag = "2")] pub asset_id_filter: ::core::option::Option, @@ -994,9 +916,7 @@ pub struct BalancesResponse { /// Note that the returned balance is for all funds sent to the account, /// not just funds sent to its default address. #[prost(message, optional, tag = "3")] - pub account_address: ::core::option::Option< - super::super::core::keys::v1::AddressView, - >, + pub account_address: ::core::option::Option, /// The account's balance, with metadata. #[prost(message, optional, tag = "4")] pub balance_view: ::core::option::Option, @@ -1097,9 +1017,7 @@ pub struct NotesRequest { pub asset_id: ::core::option::Option, /// If set, only return notes with the specified address incore.component.dex.v1. #[prost(message, optional, tag = "4")] - pub address_index: ::core::option::Option< - super::super::core::keys::v1::AddressIndex, - >, + pub address_index: ::core::option::Option, /// If set, stop returning notes once the total exceeds this amount. /// /// Ignored if `asset_id` is unset or if `include_spent` is set. @@ -1124,9 +1042,7 @@ pub struct NotesForVotingRequest { pub votable_at_height: u64, /// If set, only return notes with the specified asset id. #[prost(message, optional, tag = "3")] - pub address_index: ::core::option::Option< - super::super::core::keys::v1::AddressIndex, - >, + pub address_index: ::core::option::Option, } impl ::prost::Name for NotesForVotingRequest { const NAME: &'static str = "NotesForVotingRequest"; @@ -1142,9 +1058,8 @@ impl ::prost::Name for NotesForVotingRequest { pub struct WitnessRequest { /// The transaction plan to witness #[prost(message, optional, tag = "3")] - pub transaction_plan: ::core::option::Option< - super::super::core::transaction::v1::TransactionPlan, - >, + pub transaction_plan: + ::core::option::Option, } impl ::prost::Name for WitnessRequest { const NAME: &'static str = "WitnessRequest"; @@ -1159,9 +1074,7 @@ impl ::prost::Name for WitnessRequest { #[derive(Clone, PartialEq, ::prost::Message)] pub struct WitnessResponse { #[prost(message, optional, tag = "1")] - pub witness_data: ::core::option::Option< - super::super::core::transaction::v1::WitnessData, - >, + pub witness_data: ::core::option::Option, } impl ::prost::Name for WitnessResponse { const NAME: &'static str = "WitnessResponse"; @@ -1176,13 +1089,11 @@ impl ::prost::Name for WitnessResponse { #[derive(Clone, PartialEq, ::prost::Message)] pub struct WitnessAndBuildRequest { #[prost(message, optional, tag = "1")] - pub transaction_plan: ::core::option::Option< - super::super::core::transaction::v1::TransactionPlan, - >, + pub transaction_plan: + ::core::option::Option, #[prost(message, optional, tag = "2")] - pub authorization_data: ::core::option::Option< - super::super::core::transaction::v1::AuthorizationData, - >, + pub authorization_data: + ::core::option::Option, } impl ::prost::Name for WitnessAndBuildRequest { const NAME: &'static str = "WitnessAndBuildRequest"; @@ -1223,9 +1134,8 @@ pub mod witness_and_build_response { pub struct Complete { /// The finished transaction. #[prost(message, optional, tag = "1")] - pub transaction: ::core::option::Option< - super::super::super::core::transaction::v1::Transaction, - >, + pub transaction: + ::core::option::Option, } impl ::prost::Name for Complete { const NAME: &'static str = "Complete"; @@ -1264,9 +1174,8 @@ pub struct AssetsRequest { pub filtered: bool, /// Include these specific denominations in the response. #[prost(message, repeated, tag = "2")] - pub include_specific_denominations: ::prost::alloc::vec::Vec< - super::super::core::asset::v1::Denom, - >, + pub include_specific_denominations: + ::prost::alloc::vec::Vec, /// Include all delegation tokens, to any validator, in the response. #[prost(bool, tag = "3")] pub include_delegation_tokens: bool, @@ -1354,14 +1263,10 @@ impl ::prost::Name for GasPricesRequest { pub struct GasPricesResponse { /// The current gas prices, in the preferred (native) token. #[prost(message, optional, tag = "1")] - pub gas_prices: ::core::option::Option< - super::super::core::component::fee::v1::GasPrices, - >, + pub gas_prices: ::core::option::Option, /// Other gas prices for other accepted tokens. #[prost(message, repeated, tag = "2")] - pub alt_gas_prices: ::prost::alloc::vec::Vec< - super::super::core::component::fee::v1::GasPrices, - >, + pub alt_gas_prices: ::prost::alloc::vec::Vec, } impl ::prost::Name for GasPricesResponse { const NAME: &'static str = "GasPricesResponse"; @@ -1389,9 +1294,8 @@ impl ::prost::Name for FmdParametersRequest { #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct FmdParametersResponse { #[prost(message, optional, tag = "1")] - pub parameters: ::core::option::Option< - super::super::core::component::shielded_pool::v1::FmdParameters, - >, + pub parameters: + ::core::option::Option, } impl ::prost::Name for FmdParametersResponse { const NAME: &'static str = "FMDParametersResponse"; @@ -1406,9 +1310,7 @@ impl ::prost::Name for FmdParametersResponse { #[derive(Clone, PartialEq, ::prost::Message)] pub struct NoteByCommitmentRequest { #[prost(message, optional, tag = "2")] - pub note_commitment: ::core::option::Option< - super::super::crypto::tct::v1::StateCommitment, - >, + pub note_commitment: ::core::option::Option, /// If set to true, waits to return until the requested note is detected. #[prost(bool, tag = "3")] pub await_detection: bool, @@ -1441,9 +1343,7 @@ impl ::prost::Name for NoteByCommitmentResponse { #[derive(Clone, PartialEq, ::prost::Message)] pub struct SwapByCommitmentRequest { #[prost(message, optional, tag = "2")] - pub swap_commitment: ::core::option::Option< - super::super::crypto::tct::v1::StateCommitment, - >, + pub swap_commitment: ::core::option::Option, /// If set to true, waits to return until the requested swap is detected. #[prost(bool, tag = "3")] pub await_detection: bool, @@ -1503,9 +1403,7 @@ impl ::prost::Name for UnclaimedSwapsResponse { #[derive(Clone, PartialEq, ::prost::Message)] pub struct NullifierStatusRequest { #[prost(message, optional, tag = "2")] - pub nullifier: ::core::option::Option< - super::super::core::component::sct::v1::Nullifier, - >, + pub nullifier: ::core::option::Option, #[prost(bool, tag = "3")] pub await_detection: bool, } @@ -1579,19 +1477,14 @@ pub struct TransactionInfo { pub id: ::core::option::Option, /// The transaction data itself. #[prost(message, optional, tag = "3")] - pub transaction: ::core::option::Option< - super::super::core::transaction::v1::Transaction, - >, + pub transaction: ::core::option::Option, /// The transaction perspective, as seen by this view server. #[prost(message, optional, tag = "4")] - pub perspective: ::core::option::Option< - super::super::core::transaction::v1::TransactionPerspective, - >, + pub perspective: + ::core::option::Option, /// A precomputed transaction view of `transaction` from `perspective`, included for convenience of clients that don't have support for viewing transactions on their own. #[prost(message, optional, tag = "5")] - pub view: ::core::option::Option< - super::super::core::transaction::v1::TransactionView, - >, + pub view: ::core::option::Option, } impl ::prost::Name for TransactionInfo { const NAME: &'static str = "TransactionInfo"; @@ -1670,24 +1563,16 @@ impl ::prost::Name for NotesForVotingResponse { pub struct SpendableNoteRecord { /// The note commitment, identifying the note. #[prost(message, optional, tag = "1")] - pub note_commitment: ::core::option::Option< - super::super::crypto::tct::v1::StateCommitment, - >, + pub note_commitment: ::core::option::Option, /// The note plaintext itself. #[prost(message, optional, tag = "2")] - pub note: ::core::option::Option< - super::super::core::component::shielded_pool::v1::Note, - >, + pub note: ::core::option::Option, /// A precomputed decryption of the note's address incore.component.dex.v1. #[prost(message, optional, tag = "3")] - pub address_index: ::core::option::Option< - super::super::core::keys::v1::AddressIndex, - >, + pub address_index: ::core::option::Option, /// The note's nullifier. #[prost(message, optional, tag = "4")] - pub nullifier: ::core::option::Option< - super::super::core::component::sct::v1::Nullifier, - >, + pub nullifier: ::core::option::Option, /// The height at which the note was created. #[prost(uint64, tag = "5")] pub height_created: u64, @@ -1699,14 +1584,10 @@ pub struct SpendableNoteRecord { pub position: u64, /// The source of the note #[prost(message, optional, tag = "8")] - pub source: ::core::option::Option< - super::super::core::component::sct::v1::CommitmentSource, - >, + pub source: ::core::option::Option, /// The sender's return address, if known. #[prost(message, optional, tag = "9")] - pub return_address: ::core::option::Option< - super::super::core::keys::v1::AddressView, - >, + pub return_address: ::core::option::Option, } impl ::prost::Name for SpendableNoteRecord { const NAME: &'static str = "SpendableNoteRecord"; @@ -1721,29 +1602,20 @@ impl ::prost::Name for SpendableNoteRecord { #[derive(Clone, PartialEq, ::prost::Message)] pub struct SwapRecord { #[prost(message, optional, tag = "1")] - pub swap_commitment: ::core::option::Option< - super::super::crypto::tct::v1::StateCommitment, - >, + pub swap_commitment: ::core::option::Option, #[prost(message, optional, tag = "2")] - pub swap: ::core::option::Option< - super::super::core::component::dex::v1::SwapPlaintext, - >, + pub swap: ::core::option::Option, #[prost(uint64, tag = "3")] pub position: u64, #[prost(message, optional, tag = "4")] - pub nullifier: ::core::option::Option< - super::super::core::component::sct::v1::Nullifier, - >, + pub nullifier: ::core::option::Option, #[prost(message, optional, tag = "5")] - pub output_data: ::core::option::Option< - super::super::core::component::dex::v1::BatchSwapOutputData, - >, + pub output_data: + ::core::option::Option, #[prost(uint64, tag = "6")] pub height_claimed: u64, #[prost(message, optional, tag = "7")] - pub source: ::core::option::Option< - super::super::core::component::sct::v1::CommitmentSource, - >, + pub source: ::core::option::Option, } impl ::prost::Name for SwapRecord { const NAME: &'static str = "SwapRecord"; @@ -1759,14 +1631,11 @@ impl ::prost::Name for SwapRecord { pub struct OwnedPositionIdsRequest { /// If present, return only positions with this position state. #[prost(message, optional, tag = "1")] - pub position_state: ::core::option::Option< - super::super::core::component::dex::v1::PositionState, - >, + pub position_state: + ::core::option::Option, /// If present, return only positions for this trading pair. #[prost(message, optional, tag = "2")] - pub trading_pair: ::core::option::Option< - super::super::core::component::dex::v1::TradingPair, - >, + pub trading_pair: ::core::option::Option, /// If present, return only positions for this subaccount index. #[prost(message, optional, tag = "3")] pub subaccount: ::core::option::Option, @@ -1784,9 +1653,7 @@ impl ::prost::Name for OwnedPositionIdsRequest { #[derive(Clone, PartialEq, ::prost::Message)] pub struct OwnedPositionIdsResponse { #[prost(message, optional, tag = "1")] - pub position_id: ::core::option::Option< - super::super::core::component::dex::v1::PositionId, - >, + pub position_id: ::core::option::Option, /// The subaccount this position belongs to. #[prost(message, optional, tag = "2")] pub subaccount: ::core::option::Option, @@ -1843,25 +1710,16 @@ impl ::prost::Name for AssetMetadataByIdResponse { pub struct DelegationsByAddressIndexRequest { /// The address index to fetch delegation balances for. #[prost(message, optional, tag = "1")] - pub address_index: ::core::option::Option< - super::super::core::keys::v1::AddressIndex, - >, - #[prost(enumeration = "delegations_by_address_index_request::Filter", tag = "2")] + pub address_index: ::core::option::Option, + #[prost( + enumeration = "delegations_by_address_index_request::Filter", + tag = "2" + )] pub filter: i32, } /// Nested message and enum types in `DelegationsByAddressIndexRequest`. pub mod delegations_by_address_index_request { - #[derive( - Clone, - Copy, - Debug, - PartialEq, - Eq, - Hash, - PartialOrd, - Ord, - ::prost::Enumeration - )] + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] pub enum Filter { /// By default, returns delegations for all active validators. For validators @@ -1884,9 +1742,7 @@ pub mod delegations_by_address_index_request { pub fn as_str_name(&self) -> &'static str { match self { Self::Unspecified => "FILTER_UNSPECIFIED", - Self::AllActiveWithNonzeroBalances => { - "FILTER_ALL_ACTIVE_WITH_NONZERO_BALANCES" - } + Self::AllActiveWithNonzeroBalances => "FILTER_ALL_ACTIVE_WITH_NONZERO_BALANCES", Self::All => "FILTER_ALL", } } @@ -1942,23 +1798,11 @@ pub struct UnbondingTokensByAddressIndexRequest { pub filter: i32, /// The address index to fetch unbonding tokens for. #[prost(message, optional, tag = "2")] - pub address_index: ::core::option::Option< - super::super::core::keys::v1::AddressIndex, - >, + pub address_index: ::core::option::Option, } /// Nested message and enum types in `UnbondingTokensByAddressIndexRequest`. pub mod unbonding_tokens_by_address_index_request { - #[derive( - Clone, - Copy, - Debug, - PartialEq, - Eq, - Hash, - PartialOrd, - Ord, - ::prost::Enumeration - )] + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] pub enum Filter { /// Return all unbonding tokens, regardless of whether they're claimable @@ -2034,14 +1878,10 @@ impl ::prost::Name for UnbondingTokensByAddressIndexResponse { pub struct LatestSwapsRequest { /// If present, filter balances to only include the account specified by the `AddressIndex`. #[prost(message, optional, tag = "1")] - pub account_filter: ::core::option::Option< - super::super::core::keys::v1::AddressIndex, - >, + pub account_filter: ::core::option::Option, /// If present, filter balances to only include trading activity on the specified pair. #[prost(message, optional, tag = "2")] - pub pair: ::core::option::Option< - super::super::core::component::dex::v1::DirectedTradingPair, - >, + pub pair: ::core::option::Option, /// If present, limit the responses to activity that occured after this block height. #[prost(uint64, tag = "3")] pub after_height: u64, @@ -2063,9 +1903,7 @@ impl ::prost::Name for LatestSwapsRequest { pub struct LatestSwapsResponse { /// The trading pair involved in this swap. #[prost(message, optional, tag = "1")] - pub pair: ::core::option::Option< - super::super::core::component::dex::v1::DirectedTradingPair, - >, + pub pair: ::core::option::Option, /// The input value for the swap. #[prost(message, optional, tag = "2")] pub input: ::core::option::Option, @@ -2097,10 +1935,10 @@ pub mod view_service_client { dead_code, missing_docs, clippy::wildcard_imports, - clippy::let_unit_value, + clippy::let_unit_value )] - use tonic::codegen::*; use tonic::codegen::http::Uri; + use tonic::codegen::*; /// The view RPC is used by a view client, who wants to do some /// transaction-related actions, to request data from a view service, which is /// responsible for synchronizing and scanning the public chain state with one or @@ -2148,9 +1986,8 @@ pub mod view_service_client { >::ResponseBody, >, >, - , - >>::Error: Into + std::marker::Send + std::marker::Sync, + >>::Error: + Into + std::marker::Send + std::marker::Sync, { ViewServiceClient::new(InterceptedService::new(inner, interceptor)) } @@ -2190,18 +2027,11 @@ pub mod view_service_client { &mut self, request: impl tonic::IntoRequest, ) -> std::result::Result, tonic::Status> { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/penumbra.view.v1.ViewService/Status", - ); + let path = http::uri::PathAndQuery::from_static("/penumbra.view.v1.ViewService/Status"); let mut req = request.into_request(); req.extensions_mut() .insert(GrpcMethod::new("penumbra.view.v1.ViewService", "Status")); @@ -2216,21 +2046,17 @@ pub mod view_service_client { tonic::Response>, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/penumbra.view.v1.ViewService/StatusStream", - ); + let path = + http::uri::PathAndQuery::from_static("/penumbra.view.v1.ViewService/StatusStream"); let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("penumbra.view.v1.ViewService", "StatusStream")); + req.extensions_mut().insert(GrpcMethod::new( + "penumbra.view.v1.ViewService", + "StatusStream", + )); self.inner.server_streaming(req, path, codec).await } /// Queries for notes that have been accepted by the chain. @@ -2242,18 +2068,11 @@ pub mod view_service_client { tonic::Response>, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/penumbra.view.v1.ViewService/Notes", - ); + let path = http::uri::PathAndQuery::from_static("/penumbra.view.v1.ViewService/Notes"); let mut req = request.into_request(); req.extensions_mut() .insert(GrpcMethod::new("penumbra.view.v1.ViewService", "Notes")); @@ -2267,23 +2086,18 @@ pub mod view_service_client { tonic::Response>, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/NotesForVoting", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("penumbra.view.v1.ViewService", "NotesForVoting"), - ); + req.extensions_mut().insert(GrpcMethod::new( + "penumbra.view.v1.ViewService", + "NotesForVoting", + )); self.inner.server_streaming(req, path, codec).await } /// Queries for metadata about known assets. @@ -2295,18 +2109,11 @@ pub mod view_service_client { tonic::Response>, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/penumbra.view.v1.ViewService/Assets", - ); + let path = http::uri::PathAndQuery::from_static("/penumbra.view.v1.ViewService/Assets"); let mut req = request.into_request(); req.extensions_mut() .insert(GrpcMethod::new("penumbra.view.v1.ViewService", "Assets")); @@ -2320,76 +2127,52 @@ pub mod view_service_client { pub async fn asset_metadata_by_id( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + ) -> std::result::Result, tonic::Status> + { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/AssetMetadataById", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("penumbra.view.v1.ViewService", "AssetMetadataById"), - ); + req.extensions_mut().insert(GrpcMethod::new( + "penumbra.view.v1.ViewService", + "AssetMetadataById", + )); self.inner.unary(req, path, codec).await } /// Query for the current app parameters. pub async fn app_parameters( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + ) -> std::result::Result, tonic::Status> + { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/penumbra.view.v1.ViewService/AppParameters", - ); + let path = + http::uri::PathAndQuery::from_static("/penumbra.view.v1.ViewService/AppParameters"); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("penumbra.view.v1.ViewService", "AppParameters"), - ); + req.extensions_mut().insert(GrpcMethod::new( + "penumbra.view.v1.ViewService", + "AppParameters", + )); self.inner.unary(req, path, codec).await } /// Query for the current gas prices. pub async fn gas_prices( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + ) -> std::result::Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/penumbra.view.v1.ViewService/GasPrices", - ); + let path = + http::uri::PathAndQuery::from_static("/penumbra.view.v1.ViewService/GasPrices"); let mut req = request.into_request(); req.extensions_mut() .insert(GrpcMethod::new("penumbra.view.v1.ViewService", "GasPrices")); @@ -2399,103 +2182,72 @@ pub mod view_service_client { pub async fn fmd_parameters( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + ) -> std::result::Result, tonic::Status> + { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/penumbra.view.v1.ViewService/FMDParameters", - ); + let path = + http::uri::PathAndQuery::from_static("/penumbra.view.v1.ViewService/FMDParameters"); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("penumbra.view.v1.ViewService", "FMDParameters"), - ); + req.extensions_mut().insert(GrpcMethod::new( + "penumbra.view.v1.ViewService", + "FMDParameters", + )); self.inner.unary(req, path, codec).await } /// Query for an address given an address index pub async fn address_by_index( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + ) -> std::result::Result, tonic::Status> + { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/AddressByIndex", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("penumbra.view.v1.ViewService", "AddressByIndex"), - ); + req.extensions_mut().insert(GrpcMethod::new( + "penumbra.view.v1.ViewService", + "AddressByIndex", + )); self.inner.unary(req, path, codec).await } /// Returns the transparent address for the user's wallet. pub async fn transparent_address( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + ) -> std::result::Result, tonic::Status> + { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/TransparentAddress", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("penumbra.view.v1.ViewService", "TransparentAddress"), - ); + req.extensions_mut().insert(GrpcMethod::new( + "penumbra.view.v1.ViewService", + "TransparentAddress", + )); self.inner.unary(req, path, codec).await } /// Query for wallet id pub async fn wallet_id( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + ) -> std::result::Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/penumbra.view.v1.ViewService/WalletId", - ); + let path = + http::uri::PathAndQuery::from_static("/penumbra.view.v1.ViewService/WalletId"); let mut req = request.into_request(); req.extensions_mut() .insert(GrpcMethod::new("penumbra.view.v1.ViewService", "WalletId")); @@ -2505,54 +2257,40 @@ pub mod view_service_client { pub async fn index_by_address( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + ) -> std::result::Result, tonic::Status> + { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/IndexByAddress", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("penumbra.view.v1.ViewService", "IndexByAddress"), - ); + req.extensions_mut().insert(GrpcMethod::new( + "penumbra.view.v1.ViewService", + "IndexByAddress", + )); self.inner.unary(req, path, codec).await } /// Query for an ephemeral address pub async fn ephemeral_address( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + ) -> std::result::Result, tonic::Status> + { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/EphemeralAddress", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("penumbra.view.v1.ViewService", "EphemeralAddress"), - ); + req.extensions_mut().insert(GrpcMethod::new( + "penumbra.view.v1.ViewService", + "EphemeralAddress", + )); self.inner.unary(req, path, codec).await } /// Query for balance of a given address. @@ -2564,18 +2302,12 @@ pub mod view_service_client { tonic::Response>, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/penumbra.view.v1.ViewService/Balances", - ); + let path = + http::uri::PathAndQuery::from_static("/penumbra.view.v1.ViewService/Balances"); let mut req = request.into_request(); req.extensions_mut() .insert(GrpcMethod::new("penumbra.view.v1.ViewService", "Balances")); @@ -2585,54 +2317,40 @@ pub mod view_service_client { pub async fn note_by_commitment( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + ) -> std::result::Result, tonic::Status> + { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/NoteByCommitment", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("penumbra.view.v1.ViewService", "NoteByCommitment"), - ); + req.extensions_mut().insert(GrpcMethod::new( + "penumbra.view.v1.ViewService", + "NoteByCommitment", + )); self.inner.unary(req, path, codec).await } /// Query for a swap by its swap commitment, optionally waiting until the swap is detected. pub async fn swap_by_commitment( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + ) -> std::result::Result, tonic::Status> + { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/SwapByCommitment", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("penumbra.view.v1.ViewService", "SwapByCommitment"), - ); + req.extensions_mut().insert(GrpcMethod::new( + "penumbra.view.v1.ViewService", + "SwapByCommitment", + )); self.inner.unary(req, path, codec).await } /// Query for all unclaimed swaps. @@ -2643,80 +2361,58 @@ pub mod view_service_client { tonic::Response>, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/UnclaimedSwaps", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("penumbra.view.v1.ViewService", "UnclaimedSwaps"), - ); + req.extensions_mut().insert(GrpcMethod::new( + "penumbra.view.v1.ViewService", + "UnclaimedSwaps", + )); self.inner.server_streaming(req, path, codec).await } /// Query for whether a nullifier has been spent, optionally waiting until it is spent. pub async fn nullifier_status( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + ) -> std::result::Result, tonic::Status> + { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/NullifierStatus", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("penumbra.view.v1.ViewService", "NullifierStatus"), - ); + req.extensions_mut().insert(GrpcMethod::new( + "penumbra.view.v1.ViewService", + "NullifierStatus", + )); self.inner.unary(req, path, codec).await } /// Query for a given transaction by its hash. pub async fn transaction_info_by_hash( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + ) -> std::result::Result, tonic::Status> + { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/TransactionInfoByHash", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new( - "penumbra.view.v1.ViewService", - "TransactionInfoByHash", - ), - ); + req.extensions_mut().insert(GrpcMethod::new( + "penumbra.view.v1.ViewService", + "TransactionInfoByHash", + )); self.inner.unary(req, path, codec).await } /// Query for the full transactions in the given range of blocks. @@ -2728,23 +2424,18 @@ pub mod view_service_client { tonic::Response>, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/TransactionInfo", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("penumbra.view.v1.ViewService", "TransactionInfo"), - ); + req.extensions_mut().insert(GrpcMethod::new( + "penumbra.view.v1.ViewService", + "TransactionInfo", + )); self.inner.server_streaming(req, path, codec).await } /// Query for owned position IDs for the given trading pair and in the given position state. @@ -2755,50 +2446,38 @@ pub mod view_service_client { tonic::Response>, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/OwnedPositionIds", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("penumbra.view.v1.ViewService", "OwnedPositionIds"), - ); + req.extensions_mut().insert(GrpcMethod::new( + "penumbra.view.v1.ViewService", + "OwnedPositionIds", + )); self.inner.server_streaming(req, path, codec).await } /// Translates a high-level intent ("send X funds to Y address") into a complete transaction plan. pub async fn transaction_planner( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + ) -> std::result::Result, tonic::Status> + { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/TransactionPlanner", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("penumbra.view.v1.ViewService", "TransactionPlanner"), - ); + req.extensions_mut().insert(GrpcMethod::new( + "penumbra.view.v1.ViewService", + "TransactionPlanner", + )); self.inner.unary(req, path, codec).await } /// Returns authentication data for the given transaction plan. @@ -2810,22 +2489,13 @@ pub mod view_service_client { pub async fn witness( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + ) -> std::result::Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/penumbra.view.v1.ViewService/Witness", - ); + let path = + http::uri::PathAndQuery::from_static("/penumbra.view.v1.ViewService/Witness"); let mut req = request.into_request(); req.extensions_mut() .insert(GrpcMethod::new("penumbra.view.v1.ViewService", "Witness")); @@ -2845,23 +2515,18 @@ pub mod view_service_client { tonic::Response>, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/WitnessAndBuild", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("penumbra.view.v1.ViewService", "WitnessAndBuild"), - ); + req.extensions_mut().insert(GrpcMethod::new( + "penumbra.view.v1.ViewService", + "WitnessAndBuild", + )); self.inner.server_streaming(req, path, codec).await } /// Authorize a transaction plan and build the transaction. @@ -2882,23 +2547,18 @@ pub mod view_service_client { tonic::Response>, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/AuthorizeAndBuild", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("penumbra.view.v1.ViewService", "AuthorizeAndBuild"), - ); + req.extensions_mut().insert(GrpcMethod::new( + "penumbra.view.v1.ViewService", + "AuthorizeAndBuild", + )); self.inner.server_streaming(req, path, codec).await } /// Broadcast a transaction to the network, optionally waiting for full confirmation. @@ -2908,31 +2568,21 @@ pub mod view_service_client { &mut self, request: impl tonic::IntoRequest, ) -> std::result::Result< - tonic::Response< - tonic::codec::Streaming, - >, + tonic::Response>, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/BroadcastTransaction", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new( - "penumbra.view.v1.ViewService", - "BroadcastTransaction", - ), - ); + req.extensions_mut().insert(GrpcMethod::new( + "penumbra.view.v1.ViewService", + "BroadcastTransaction", + )); self.inner.server_streaming(req, path, codec).await } /// Get delegation tokens for a given address index. Each delegation token will @@ -2943,31 +2593,21 @@ pub mod view_service_client { &mut self, request: impl tonic::IntoRequest, ) -> std::result::Result< - tonic::Response< - tonic::codec::Streaming, - >, + tonic::Response>, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/DelegationsByAddressIndex", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new( - "penumbra.view.v1.ViewService", - "DelegationsByAddressIndex", - ), - ); + req.extensions_mut().insert(GrpcMethod::new( + "penumbra.view.v1.ViewService", + "DelegationsByAddressIndex", + )); self.inner.server_streaming(req, path, codec).await } /// Get unbonding tokens for the given address index, optionally filtered by @@ -2976,31 +2616,21 @@ pub mod view_service_client { &mut self, request: impl tonic::IntoRequest, ) -> std::result::Result< - tonic::Response< - tonic::codec::Streaming, - >, + tonic::Response>, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/UnbondingTokensByAddressIndex", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new( - "penumbra.view.v1.ViewService", - "UnbondingTokensByAddressIndex", - ), - ); + req.extensions_mut().insert(GrpcMethod::new( + "penumbra.view.v1.ViewService", + "UnbondingTokensByAddressIndex", + )); self.inner.server_streaming(req, path, codec).await } /// Gets the auctions controlled by the user's wallet. @@ -3011,18 +2641,12 @@ pub mod view_service_client { tonic::Response>, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/penumbra.view.v1.ViewService/Auctions", - ); + let path = + http::uri::PathAndQuery::from_static("/penumbra.view.v1.ViewService/Auctions"); let mut req = request.into_request(); req.extensions_mut() .insert(GrpcMethod::new("penumbra.view.v1.ViewService", "Auctions")); @@ -3036,48 +2660,37 @@ pub mod view_service_client { tonic::Response>, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/penumbra.view.v1.ViewService/LatestSwaps", - ); + let path = + http::uri::PathAndQuery::from_static("/penumbra.view.v1.ViewService/LatestSwaps"); let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("penumbra.view.v1.ViewService", "LatestSwaps")); + req.extensions_mut().insert(GrpcMethod::new( + "penumbra.view.v1.ViewService", + "LatestSwaps", + )); self.inner.server_streaming(req, path, codec).await } /// Gets details on the list votes cast in the current epoch for incentivized assets. pub async fn tournament_votes( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + ) -> std::result::Result, tonic::Status> + { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/TournamentVotes", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("penumbra.view.v1.ViewService", "TournamentVotes"), - ); + req.extensions_mut().insert(GrpcMethod::new( + "penumbra.view.v1.ViewService", + "TournamentVotes", + )); self.inner.unary(req, path, codec).await } /// Gets the spendable note records that are eligible for voting in the current epoch. @@ -3088,23 +2701,18 @@ pub mod view_service_client { tonic::Response>, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/LqtVotingNotes", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("penumbra.view.v1.ViewService", "LqtVotingNotes"), - ); + req.extensions_mut().insert(GrpcMethod::new( + "penumbra.view.v1.ViewService", + "LqtVotingNotes", + )); self.inner.server_streaming(req, path, codec).await } } @@ -3117,7 +2725,7 @@ pub mod view_service_server { dead_code, missing_docs, clippy::wildcard_imports, - clippy::let_unit_value, + clippy::let_unit_value )] use tonic::codegen::*; /// Generated trait containing gRPC methods that should be implemented for use with ViewServiceServer. @@ -3131,23 +2739,18 @@ pub mod view_service_server { /// Server streaming response type for the StatusStream method. type StatusStreamStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > - + std::marker::Send + > + std::marker::Send + 'static; /// Stream sync status updates until the view service has caught up with the chain. /// Returns a stream of `StatusStreamResponse`s. async fn status_stream( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Server streaming response type for the Notes method. type NotesStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > - + std::marker::Send + > + std::marker::Send + 'static; /// Queries for notes that have been accepted by the chain. /// Returns a stream of `NotesResponse`s. @@ -3158,22 +2761,17 @@ pub mod view_service_server { /// Server streaming response type for the NotesForVoting method. type NotesForVotingStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > - + std::marker::Send + > + std::marker::Send + 'static; /// Returns a stream of `NotesForVotingResponse`s. async fn notes_for_voting( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Server streaming response type for the Assets method. type AssetsStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > - + std::marker::Send + > + std::marker::Send + 'static; /// Queries for metadata about known assets. /// Returns a stream of `AssetsResponse`s. @@ -3189,79 +2787,51 @@ pub mod view_service_server { async fn asset_metadata_by_id( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Query for the current app parameters. async fn app_parameters( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Query for the current gas prices. async fn gas_prices( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Query for the current FMD parameters. async fn fmd_parameters( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Query for an address given an address index async fn address_by_index( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Returns the transparent address for the user's wallet. async fn transparent_address( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Query for wallet id async fn wallet_id( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Query for an address given an address index async fn index_by_address( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Query for an ephemeral address async fn ephemeral_address( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Server streaming response type for the Balances method. type BalancesStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > - + std::marker::Send + > + std::marker::Send + 'static; /// Query for balance of a given address. /// Returns a stream of `BalancesResponses`. @@ -3273,88 +2843,58 @@ pub mod view_service_server { async fn note_by_commitment( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Query for a swap by its swap commitment, optionally waiting until the swap is detected. async fn swap_by_commitment( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Server streaming response type for the UnclaimedSwaps method. type UnclaimedSwapsStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > - + std::marker::Send + > + std::marker::Send + 'static; /// Query for all unclaimed swaps. async fn unclaimed_swaps( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Query for whether a nullifier has been spent, optionally waiting until it is spent. async fn nullifier_status( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Query for a given transaction by its hash. async fn transaction_info_by_hash( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Server streaming response type for the TransactionInfo method. type TransactionInfoStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > - + std::marker::Send + > + std::marker::Send + 'static; /// Query for the full transactions in the given range of blocks. /// Returns a stream of `TransactionInfoResponse`s. async fn transaction_info( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Server streaming response type for the OwnedPositionIds method. type OwnedPositionIdsStream: tonic::codegen::tokio_stream::Stream< - Item = std::result::Result< - super::OwnedPositionIdsResponse, - tonic::Status, - >, - > - + std::marker::Send + Item = std::result::Result, + > + std::marker::Send + 'static; /// Query for owned position IDs for the given trading pair and in the given position state. async fn owned_position_ids( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Translates a high-level intent ("send X funds to Y address") into a complete transaction plan. async fn transaction_planner( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Returns authentication data for the given transaction plan. /// /// This method takes a complete transaction plan, so that the client can get a @@ -3368,8 +2908,7 @@ pub mod view_service_server { /// Server streaming response type for the WitnessAndBuild method. type WitnessAndBuildStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > - + std::marker::Send + > + std::marker::Send + 'static; /// Like `Witness`, but immediately uses the witness data to build (prove) the transaction. /// @@ -3381,18 +2920,11 @@ pub mod view_service_server { async fn witness_and_build( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Server streaming response type for the AuthorizeAndBuild method. type AuthorizeAndBuildStream: tonic::codegen::tokio_stream::Stream< - Item = std::result::Result< - super::AuthorizeAndBuildResponse, - tonic::Status, - >, - > - + std::marker::Send + Item = std::result::Result, + > + std::marker::Send + 'static; /// Authorize a transaction plan and build the transaction. /// @@ -3408,18 +2940,11 @@ pub mod view_service_server { async fn authorize_and_build( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Server streaming response type for the BroadcastTransaction method. type BroadcastTransactionStream: tonic::codegen::tokio_stream::Stream< - Item = std::result::Result< - super::BroadcastTransactionResponse, - tonic::Status, - >, - > - + std::marker::Send + Item = std::result::Result, + > + std::marker::Send + 'static; /// Broadcast a transaction to the network, optionally waiting for full confirmation. /// @@ -3427,18 +2952,11 @@ pub mod view_service_server { async fn broadcast_transaction( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Server streaming response type for the DelegationsByAddressIndex method. type DelegationsByAddressIndexStream: tonic::codegen::tokio_stream::Stream< - Item = std::result::Result< - super::DelegationsByAddressIndexResponse, - tonic::Status, - >, - > - + std::marker::Send + Item = std::result::Result, + > + std::marker::Send + 'static; /// Get delegation tokens for a given address index. Each delegation token will /// be represented by a `ValueView` with the given address index's balance of @@ -3457,8 +2975,7 @@ pub mod view_service_server { super::UnbondingTokensByAddressIndexResponse, tonic::Status, >, - > - + std::marker::Send + > + std::marker::Send + 'static; /// Get unbonding tokens for the given address index, optionally filtered by /// whether the tokens are currently claimable. @@ -3472,8 +2989,7 @@ pub mod view_service_server { /// Server streaming response type for the Auctions method. type AuctionsStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > - + std::marker::Send + > + std::marker::Send + 'static; /// Gets the auctions controlled by the user's wallet. async fn auctions( @@ -3483,39 +2999,28 @@ pub mod view_service_server { /// Server streaming response type for the LatestSwaps method. type LatestSwapsStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > - + std::marker::Send + > + std::marker::Send + 'static; /// Gets the latest swaps controlled by the user's wallet. async fn latest_swaps( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Gets details on the list votes cast in the current epoch for incentivized assets. async fn tournament_votes( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Server streaming response type for the LqtVotingNotes method. type LqtVotingNotesStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > - + std::marker::Send + > + std::marker::Send + 'static; /// Gets the spendable note records that are eligible for voting in the current epoch. async fn lqt_voting_notes( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; } /// The view RPC is used by a view client, who wants to do some /// transaction-related actions, to request data from a view service, which is @@ -3542,10 +3047,7 @@ pub mod view_service_server { max_encoding_message_size: None, } } - pub fn with_interceptor( - inner: T, - interceptor: F, - ) -> InterceptedService + pub fn with_interceptor(inner: T, interceptor: F) -> InterceptedService where F: tonic::service::Interceptor, { @@ -3600,23 +3102,16 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/Status" => { #[allow(non_camel_case_types)] struct StatusSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::UnaryService - for StatusSvc { + impl tonic::server::UnaryService for StatusSvc { type Response = super::StatusResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); - let fut = async move { - ::status(&inner, request).await - }; + let fut = + async move { ::status(&inner, request).await }; Box::pin(fut) } } @@ -3645,16 +3140,14 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/StatusStream" => { #[allow(non_camel_case_types)] struct StatusStreamSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::ServerStreamingService - for StatusStreamSvc { + impl + tonic::server::ServerStreamingService + for StatusStreamSvc + { type Response = super::StatusStreamResponse; type ResponseStream = T::StatusStreamStream; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = + BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, @@ -3691,24 +3184,18 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/Notes" => { #[allow(non_camel_case_types)] struct NotesSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::ServerStreamingService - for NotesSvc { + impl tonic::server::ServerStreamingService for NotesSvc { type Response = super::NotesResponse; type ResponseStream = T::NotesStream; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = + BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); - let fut = async move { - ::notes(&inner, request).await - }; + let fut = + async move { ::notes(&inner, request).await }; Box::pin(fut) } } @@ -3737,16 +3224,14 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/NotesForVoting" => { #[allow(non_camel_case_types)] struct NotesForVotingSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::ServerStreamingService - for NotesForVotingSvc { + impl + tonic::server::ServerStreamingService + for NotesForVotingSvc + { type Response = super::NotesForVotingResponse; type ResponseStream = T::NotesForVotingStream; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = + BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, @@ -3783,24 +3268,18 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/Assets" => { #[allow(non_camel_case_types)] struct AssetsSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::ServerStreamingService - for AssetsSvc { + impl tonic::server::ServerStreamingService for AssetsSvc { type Response = super::AssetsResponse; type ResponseStream = T::AssetsStream; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = + BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); - let fut = async move { - ::assets(&inner, request).await - }; + let fut = + async move { ::assets(&inner, request).await }; Box::pin(fut) } } @@ -3829,23 +3308,19 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/AssetMetadataById" => { #[allow(non_camel_case_types)] struct AssetMetadataByIdSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::UnaryService - for AssetMetadataByIdSvc { + impl + tonic::server::UnaryService + for AssetMetadataByIdSvc + { type Response = super::AssetMetadataByIdResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::asset_metadata_by_id(&inner, request) - .await + ::asset_metadata_by_id(&inner, request).await }; Box::pin(fut) } @@ -3875,15 +3350,11 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/AppParameters" => { #[allow(non_camel_case_types)] struct AppParametersSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::UnaryService - for AppParametersSvc { + impl tonic::server::UnaryService + for AppParametersSvc + { type Response = super::AppParametersResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, @@ -3920,15 +3391,9 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/GasPrices" => { #[allow(non_camel_case_types)] struct GasPricesSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::UnaryService - for GasPricesSvc { + impl tonic::server::UnaryService for GasPricesSvc { type Response = super::GasPricesResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, @@ -3965,15 +3430,11 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/FMDParameters" => { #[allow(non_camel_case_types)] struct FMDParametersSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::UnaryService - for FMDParametersSvc { + impl tonic::server::UnaryService + for FMDParametersSvc + { type Response = super::FmdParametersResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, @@ -4010,15 +3471,11 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/AddressByIndex" => { #[allow(non_camel_case_types)] struct AddressByIndexSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::UnaryService - for AddressByIndexSvc { + impl tonic::server::UnaryService + for AddressByIndexSvc + { type Response = super::AddressByIndexResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, @@ -4055,23 +3512,19 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/TransparentAddress" => { #[allow(non_camel_case_types)] struct TransparentAddressSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::UnaryService - for TransparentAddressSvc { + impl + tonic::server::UnaryService + for TransparentAddressSvc + { type Response = super::TransparentAddressResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::transparent_address(&inner, request) - .await + ::transparent_address(&inner, request).await }; Box::pin(fut) } @@ -4101,23 +3554,16 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/WalletId" => { #[allow(non_camel_case_types)] struct WalletIdSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::UnaryService - for WalletIdSvc { + impl tonic::server::UnaryService for WalletIdSvc { type Response = super::WalletIdResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); - let fut = async move { - ::wallet_id(&inner, request).await - }; + let fut = + async move { ::wallet_id(&inner, request).await }; Box::pin(fut) } } @@ -4146,15 +3592,11 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/IndexByAddress" => { #[allow(non_camel_case_types)] struct IndexByAddressSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::UnaryService - for IndexByAddressSvc { + impl tonic::server::UnaryService + for IndexByAddressSvc + { type Response = super::IndexByAddressResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, @@ -4191,15 +3633,11 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/EphemeralAddress" => { #[allow(non_camel_case_types)] struct EphemeralAddressSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::UnaryService - for EphemeralAddressSvc { + impl tonic::server::UnaryService + for EphemeralAddressSvc + { type Response = super::EphemeralAddressResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, @@ -4236,24 +3674,21 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/Balances" => { #[allow(non_camel_case_types)] struct BalancesSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::ServerStreamingService - for BalancesSvc { + impl + tonic::server::ServerStreamingService + for BalancesSvc + { type Response = super::BalancesResponse; type ResponseStream = T::BalancesStream; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = + BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); - let fut = async move { - ::balances(&inner, request).await - }; + let fut = + async move { ::balances(&inner, request).await }; Box::pin(fut) } } @@ -4282,23 +3717,18 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/NoteByCommitment" => { #[allow(non_camel_case_types)] struct NoteByCommitmentSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::UnaryService - for NoteByCommitmentSvc { + impl tonic::server::UnaryService + for NoteByCommitmentSvc + { type Response = super::NoteByCommitmentResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::note_by_commitment(&inner, request) - .await + ::note_by_commitment(&inner, request).await }; Box::pin(fut) } @@ -4328,23 +3758,18 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/SwapByCommitment" => { #[allow(non_camel_case_types)] struct SwapByCommitmentSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::UnaryService - for SwapByCommitmentSvc { + impl tonic::server::UnaryService + for SwapByCommitmentSvc + { type Response = super::SwapByCommitmentResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::swap_by_commitment(&inner, request) - .await + ::swap_by_commitment(&inner, request).await }; Box::pin(fut) } @@ -4374,16 +3799,14 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/UnclaimedSwaps" => { #[allow(non_camel_case_types)] struct UnclaimedSwapsSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::ServerStreamingService - for UnclaimedSwapsSvc { + impl + tonic::server::ServerStreamingService + for UnclaimedSwapsSvc + { type Response = super::UnclaimedSwapsResponse; type ResponseStream = T::UnclaimedSwapsStream; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = + BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, @@ -4420,15 +3843,11 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/NullifierStatus" => { #[allow(non_camel_case_types)] struct NullifierStatusSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::UnaryService - for NullifierStatusSvc { + impl tonic::server::UnaryService + for NullifierStatusSvc + { type Response = super::NullifierStatusResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, @@ -4465,26 +3884,19 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/TransactionInfoByHash" => { #[allow(non_camel_case_types)] struct TransactionInfoByHashSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::UnaryService - for TransactionInfoByHashSvc { + impl + tonic::server::UnaryService + for TransactionInfoByHashSvc + { type Response = super::TransactionInfoByHashResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::transaction_info_by_hash( - &inner, - request, - ) - .await + ::transaction_info_by_hash(&inner, request).await }; Box::pin(fut) } @@ -4514,17 +3926,14 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/TransactionInfo" => { #[allow(non_camel_case_types)] struct TransactionInfoSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::ServerStreamingService< - super::TransactionInfoRequest, - > for TransactionInfoSvc { + impl + tonic::server::ServerStreamingService + for TransactionInfoSvc + { type Response = super::TransactionInfoResponse; type ResponseStream = T::TransactionInfoStream; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = + BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, @@ -4561,25 +3970,21 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/OwnedPositionIds" => { #[allow(non_camel_case_types)] struct OwnedPositionIdsSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::ServerStreamingService< - super::OwnedPositionIdsRequest, - > for OwnedPositionIdsSvc { + impl + tonic::server::ServerStreamingService + for OwnedPositionIdsSvc + { type Response = super::OwnedPositionIdsResponse; type ResponseStream = T::OwnedPositionIdsStream; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = + BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::owned_position_ids(&inner, request) - .await + ::owned_position_ids(&inner, request).await }; Box::pin(fut) } @@ -4609,23 +4014,19 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/TransactionPlanner" => { #[allow(non_camel_case_types)] struct TransactionPlannerSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::UnaryService - for TransactionPlannerSvc { + impl + tonic::server::UnaryService + for TransactionPlannerSvc + { type Response = super::TransactionPlannerResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::transaction_planner(&inner, request) - .await + ::transaction_planner(&inner, request).await }; Box::pin(fut) } @@ -4655,23 +4056,16 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/Witness" => { #[allow(non_camel_case_types)] struct WitnessSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::UnaryService - for WitnessSvc { + impl tonic::server::UnaryService for WitnessSvc { type Response = super::WitnessResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); - let fut = async move { - ::witness(&inner, request).await - }; + let fut = + async move { ::witness(&inner, request).await }; Box::pin(fut) } } @@ -4700,17 +4094,14 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/WitnessAndBuild" => { #[allow(non_camel_case_types)] struct WitnessAndBuildSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::ServerStreamingService< - super::WitnessAndBuildRequest, - > for WitnessAndBuildSvc { + impl + tonic::server::ServerStreamingService + for WitnessAndBuildSvc + { type Response = super::WitnessAndBuildResponse; type ResponseStream = T::WitnessAndBuildStream; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = + BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, @@ -4747,25 +4138,21 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/AuthorizeAndBuild" => { #[allow(non_camel_case_types)] struct AuthorizeAndBuildSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::ServerStreamingService< - super::AuthorizeAndBuildRequest, - > for AuthorizeAndBuildSvc { + impl + tonic::server::ServerStreamingService + for AuthorizeAndBuildSvc + { type Response = super::AuthorizeAndBuildResponse; type ResponseStream = T::AuthorizeAndBuildStream; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = + BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::authorize_and_build(&inner, request) - .await + ::authorize_and_build(&inner, request).await }; Box::pin(fut) } @@ -4795,25 +4182,21 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/BroadcastTransaction" => { #[allow(non_camel_case_types)] struct BroadcastTransactionSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::ServerStreamingService< - super::BroadcastTransactionRequest, - > for BroadcastTransactionSvc { + impl + tonic::server::ServerStreamingService + for BroadcastTransactionSvc + { type Response = super::BroadcastTransactionResponse; type ResponseStream = T::BroadcastTransactionStream; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = + BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::broadcast_transaction(&inner, request) - .await + ::broadcast_transaction(&inner, request).await }; Box::pin(fut) } @@ -4843,29 +4226,22 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/DelegationsByAddressIndex" => { #[allow(non_camel_case_types)] struct DelegationsByAddressIndexSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::ServerStreamingService< - super::DelegationsByAddressIndexRequest, - > for DelegationsByAddressIndexSvc { + impl + tonic::server::ServerStreamingService< + super::DelegationsByAddressIndexRequest, + > for DelegationsByAddressIndexSvc + { type Response = super::DelegationsByAddressIndexResponse; type ResponseStream = T::DelegationsByAddressIndexStream; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = + BoxFuture, tonic::Status>; fn call( &mut self, - request: tonic::Request< - super::DelegationsByAddressIndexRequest, - >, + request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::delegations_by_address_index( - &inner, - request, - ) + ::delegations_by_address_index(&inner, request) .await }; Box::pin(fut) @@ -4896,30 +4272,25 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/UnbondingTokensByAddressIndex" => { #[allow(non_camel_case_types)] struct UnbondingTokensByAddressIndexSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::ServerStreamingService< - super::UnbondingTokensByAddressIndexRequest, - > for UnbondingTokensByAddressIndexSvc { + impl + tonic::server::ServerStreamingService< + super::UnbondingTokensByAddressIndexRequest, + > for UnbondingTokensByAddressIndexSvc + { type Response = super::UnbondingTokensByAddressIndexResponse; type ResponseStream = T::UnbondingTokensByAddressIndexStream; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = + BoxFuture, tonic::Status>; fn call( &mut self, - request: tonic::Request< - super::UnbondingTokensByAddressIndexRequest, - >, + request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { ::unbonding_tokens_by_address_index( - &inner, - request, - ) - .await + &inner, request, + ) + .await }; Box::pin(fut) } @@ -4949,24 +4320,21 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/Auctions" => { #[allow(non_camel_case_types)] struct AuctionsSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::ServerStreamingService - for AuctionsSvc { + impl + tonic::server::ServerStreamingService + for AuctionsSvc + { type Response = super::AuctionsResponse; type ResponseStream = T::AuctionsStream; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = + BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); - let fut = async move { - ::auctions(&inner, request).await - }; + let fut = + async move { ::auctions(&inner, request).await }; Box::pin(fut) } } @@ -4995,16 +4363,14 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/LatestSwaps" => { #[allow(non_camel_case_types)] struct LatestSwapsSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::ServerStreamingService - for LatestSwapsSvc { + impl + tonic::server::ServerStreamingService + for LatestSwapsSvc + { type Response = super::LatestSwapsResponse; type ResponseStream = T::LatestSwapsStream; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = + BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, @@ -5041,15 +4407,11 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/TournamentVotes" => { #[allow(non_camel_case_types)] struct TournamentVotesSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::UnaryService - for TournamentVotesSvc { + impl tonic::server::UnaryService + for TournamentVotesSvc + { type Response = super::TournamentVotesResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, @@ -5086,16 +4448,14 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/LqtVotingNotes" => { #[allow(non_camel_case_types)] struct LqtVotingNotesSvc(pub Arc); - impl< - T: ViewService, - > tonic::server::ServerStreamingService - for LqtVotingNotesSvc { + impl + tonic::server::ServerStreamingService + for LqtVotingNotesSvc + { type Response = super::LqtVotingNotesResponse; type ResponseStream = T::LqtVotingNotesStream; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = + BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, @@ -5129,23 +4489,19 @@ pub mod view_service_server { }; Box::pin(fut) } - _ => { - Box::pin(async move { - let mut response = http::Response::new(empty_body()); - let headers = response.headers_mut(); - headers - .insert( - tonic::Status::GRPC_STATUS, - (tonic::Code::Unimplemented as i32).into(), - ); - headers - .insert( - http::header::CONTENT_TYPE, - tonic::metadata::GRPC_CONTENT_TYPE, - ); - Ok(response) - }) - } + _ => Box::pin(async move { + let mut response = http::Response::new(empty_body()); + let headers = response.headers_mut(); + headers.insert( + tonic::Status::GRPC_STATUS, + (tonic::Code::Unimplemented as i32).into(), + ); + headers.insert( + http::header::CONTENT_TYPE, + tonic::metadata::GRPC_CONTENT_TYPE, + ); + Ok(response) + }), } } } diff --git a/crates/view/src/client.rs b/crates/view/src/client.rs index 1359c4ff60..1292553f2d 100644 --- a/crates/view/src/client.rs +++ b/crates/view/src/client.rs @@ -338,6 +338,13 @@ pub trait ViewClient { fn unclaimed_swaps( &mut self, ) -> Pin>> + Send + 'static>>; + + /// Get all of the notes that can be used for voting + fn lqt_voting_notes( + &mut self, + epoch: u64, + filter: Option, + ) -> Pin>> + Send + 'static>>; } // We need to tell `async_trait` not to add a `Send` bound to the boxed @@ -1051,4 +1058,33 @@ where } .boxed() } + + fn lqt_voting_notes( + &mut self, + epoch: u64, + filter: Option, + ) -> Pin>> + Send + 'static>> { + let mut client = self.clone(); + async move { + let request = tonic::Request::new(pb::LqtVotingNotesRequest { + epoch_index: epoch, + account_filter: filter.map(|x| x.into()), + }); + let response = client.lqt_voting_notes(request).await?; + let pb_notes: Vec = + response.into_inner().try_collect().await?; + + pb_notes + .into_iter() + .map(|note_rsp| { + let note_record = note_rsp + .note_record + .ok_or_else(|| anyhow::anyhow!("empty LqtVotingNotesResponse message"))? + .try_into()?; + Ok(note_record) + }) + .collect() + } + .boxed() + } } From 568c88714b35995625f5207137e98eff7989b269 Mon Sep 17 00:00:00 2001 From: Lucas Meier Date: Fri, 7 Feb 2025 22:54:24 -0800 Subject: [PATCH 09/13] lqt: planner support --- crates/view/src/planner.rs | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/crates/view/src/planner.rs b/crates/view/src/planner.rs index a0c3f95dd6..6c07421937 100644 --- a/crates/view/src/planner.rs +++ b/crates/view/src/planner.rs @@ -5,6 +5,7 @@ use std::{ }; use anyhow::{Context, Result}; +use penumbra_sdk_funding::liquidity_tournament::ActionLiquidityTournamentVotePlan; use penumbra_sdk_sct::epoch::Epoch; use rand::{CryptoRng, RngCore}; use rand_core::OsRng; @@ -12,7 +13,10 @@ use tracing::instrument; use crate::{SpendableNoteRecord, ViewClient}; use anyhow::anyhow; -use penumbra_sdk_asset::{asset, Value}; +use penumbra_sdk_asset::{ + asset::{self, Denom}, + Value, +}; use penumbra_sdk_auction::auction::dutch::DutchAuctionDescription; use penumbra_sdk_auction::auction::dutch::{actions::ActionDutchAuctionWithdrawPlan, DutchAuction}; use penumbra_sdk_auction::auction::{ @@ -477,6 +481,29 @@ impl Planner { self } + #[instrument(skip(self))] + pub fn lqt_vote( + &mut self, + epoch_index: u16, + incentivized: Denom, + rewards_recipient: Address, + notes: &[SpendableNoteRecord], + ) -> &mut Self { + let start_position = tct::Position::from((epoch_index, 0, 0)); + for note in notes { + self.action_list + .push(ActionLiquidityTournamentVotePlan::new( + &mut self.rng, + incentivized.clone(), + rewards_recipient.clone(), + note.note.clone(), + note.position, + start_position, + )); + } + self + } + /// Prioritize notes to spend to release value of a specific transaction. /// /// Various logic is possible for note selection. Currently, this method From 279ae7c3cb05adf3fbcdbba4c43bdd22f35f575c Mon Sep 17 00:00:00 2001 From: Lucas Meier Date: Fri, 7 Feb 2025 20:25:27 -0800 Subject: [PATCH 10/13] pcli stub out `tx lqt-vote` --- crates/bin/pcli/src/command/tx.rs | 6 ++++++ crates/bin/pcli/src/command/tx/lqt_vote.rs | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 crates/bin/pcli/src/command/tx/lqt_vote.rs diff --git a/crates/bin/pcli/src/command/tx.rs b/crates/bin/pcli/src/command/tx.rs index 6ae6950881..d3aa2fa534 100644 --- a/crates/bin/pcli/src/command/tx.rs +++ b/crates/bin/pcli/src/command/tx.rs @@ -22,6 +22,7 @@ use ibc_types::core::{ client::Height as IbcHeight, }; use ibc_types::lightclients::tendermint::client_state::ClientState as TendermintClientState; +use lqt_vote::LqtVoteCmd; use rand_core::OsRng; use regex::Regex; @@ -82,6 +83,7 @@ use clap::Parser; mod auction; mod liquidity_position; +mod lqt_vote; mod proposal; mod replicate; @@ -311,6 +313,8 @@ pub enum TxCmd { /// The transaction to be broadcast transaction: PathBuf, }, + #[clap(display_order = 700)] + LqtVote(LqtVoteCmd), } /// Vote on a governance proposal. @@ -368,6 +372,7 @@ impl TxCmd { TxCmd::Auction(_) => false, TxCmd::Broadcast { .. } => false, TxCmd::RegisterForwardingAccount { .. } => false, + TxCmd::LqtVote(cmd) => cmd.offline(), } } @@ -1553,6 +1558,7 @@ impl TxCmd { println!("Noble response: {:?}", r); } + TxCmd::LqtVote(cmd) => cmd.exec(app).await?, } Ok(()) diff --git a/crates/bin/pcli/src/command/tx/lqt_vote.rs b/crates/bin/pcli/src/command/tx/lqt_vote.rs new file mode 100644 index 0000000000..d8bd3ce206 --- /dev/null +++ b/crates/bin/pcli/src/command/tx/lqt_vote.rs @@ -0,0 +1,20 @@ +use crate::App; + +/// Vote in the current round of the liquidity tournament. +/// +/// This will plan a transaction which directs all available voting power to a single asset. +#[derive(Debug, clap::Parser)] +pub struct LqtVoteCmd { + /// The denom string for the asset being voted for. + vote: String, +} + +impl LqtVoteCmd { + pub fn offline(&self) -> bool { + false + } + + pub async fn exec(&self, _app: &mut App) -> anyhow::Result<()> { + unimplemented!() + } +} From 7fcd8005ed8106a3a249d0aebd4560dc652b27c2 Mon Sep 17 00:00:00 2001 From: Lucas Meier Date: Fri, 7 Feb 2025 22:53:39 -0800 Subject: [PATCH 11/13] pcli: implement tx lqt-vote --- crates/bin/pcli/src/command/tx.rs | 2 +- crates/bin/pcli/src/command/tx/lqt_vote.rs | 112 ++++++++++++++++++++- 2 files changed, 111 insertions(+), 3 deletions(-) diff --git a/crates/bin/pcli/src/command/tx.rs b/crates/bin/pcli/src/command/tx.rs index d3aa2fa534..0a71282326 100644 --- a/crates/bin/pcli/src/command/tx.rs +++ b/crates/bin/pcli/src/command/tx.rs @@ -1558,7 +1558,7 @@ impl TxCmd { println!("Noble response: {:?}", r); } - TxCmd::LqtVote(cmd) => cmd.exec(app).await?, + TxCmd::LqtVote(cmd) => cmd.exec(app, gas_prices).await?, } Ok(()) diff --git a/crates/bin/pcli/src/command/tx/lqt_vote.rs b/crates/bin/pcli/src/command/tx/lqt_vote.rs index d8bd3ce206..0a06f18c87 100644 --- a/crates/bin/pcli/src/command/tx/lqt_vote.rs +++ b/crates/bin/pcli/src/command/tx/lqt_vote.rs @@ -1,5 +1,37 @@ +use std::collections::BTreeMap; + +use anyhow::anyhow; +use penumbra_sdk_asset::{ + asset::{self, REGISTRY}, + Value, +}; +use penumbra_sdk_fee::{FeeTier, GasPrices}; +use penumbra_sdk_keys::Address; +use penumbra_sdk_num::Amount; +use penumbra_sdk_proto::core::component::sct::v1::{ + query_service_client::QueryServiceClient as SctQueryServiceClient, EpochByHeightRequest, +}; +use penumbra_sdk_sct::epoch::Epoch; +use penumbra_sdk_view::{Planner, ViewClient}; +use rand_core::OsRng; + use crate::App; +async fn fetch_epoch(app: &mut App) -> anyhow::Result { + let mut sct_client = SctQueryServiceClient::new(app.pd_channel().await?); + let latest_sync_height = app.view().status().await?.full_sync_height; + let epoch = sct_client + .epoch_by_height(EpochByHeightRequest { + height: latest_sync_height, + }) + .await? + .into_inner() + .epoch + .expect("epoch must be available") + .into(); + Ok(epoch) +} + /// Vote in the current round of the liquidity tournament. /// /// This will plan a transaction which directs all available voting power to a single asset. @@ -7,6 +39,14 @@ use crate::App; pub struct LqtVoteCmd { /// The denom string for the asset being voted for. vote: String, + /// If provided, make the rewards recipient a particular address instead. + /// + /// This can also be an integer, indicating an ephemeral address of a sub-account. + #[clap(short, long)] + rewards_recipient: Option, + /// The selected fee tier. + #[clap(short, long, default_value_t)] + fee_tier: FeeTier, } impl LqtVoteCmd { @@ -14,7 +54,75 @@ impl LqtVoteCmd { false } - pub async fn exec(&self, _app: &mut App) -> anyhow::Result<()> { - unimplemented!() + fn rewards_addr(&self, app: &App) -> anyhow::Result
{ + let to_parse = match &self.rewards_recipient { + None => { + return Ok(app + .config + .full_viewing_key + .ephemeral_address(OsRng, Default::default()) + .0) + } + Some(x) => x, + }; + let maybe_index: Option = to_parse.parse().ok(); + if let Some(i) = maybe_index { + return Ok(app + .config + .full_viewing_key + .ephemeral_address(OsRng, i.into()) + .0); + } + to_parse + .parse() + .map_err(|_| anyhow!("failed to parse address '{}'", to_parse)) + } + + pub async fn exec(&self, app: &mut App, gas_prices: GasPrices) -> anyhow::Result<()> { + let vote_meta = REGISTRY + .parse_denom(&self.vote) + .ok_or_else(|| anyhow!("failed to parse denom: '{}'", &self.vote))?; + let vote_denom = vote_meta.base_denom(); + + let epoch = fetch_epoch(app).await?; + let voting_notes = app.view().lqt_voting_notes(epoch.index, None).await?; + + let mut planner = Planner::new(OsRng); + + planner + .set_gas_prices(gas_prices) + .set_fee_tier(self.fee_tier); + + // First, tell the planner to make all the necessary votes. + planner.lqt_vote( + u16::try_from(epoch.index)?, + vote_denom, + self.rewards_addr(app)?, + &voting_notes, + ); + // We also want to go ahead and do the consolidation thing, + // to reduce the number of votes we need in the next epoch. + // To do so, we need to spend all of these notes, and produce one output per + // delegator token. + let mut totals: BTreeMap = Default::default(); + for note in voting_notes { + let value = note.note.value(); + planner.spend(note.note, note.position); + *totals.entry(value.asset_id).or_insert(Amount::zero()) += value.amount; + } + let change_addr = app + .config + .full_viewing_key + .ephemeral_address(OsRng, Default::default()) + .0; + planner.change_address(change_addr.clone()); + for (asset_id, amount) in totals { + planner.output(Value { asset_id, amount }, change_addr.clone()); + } + + let plan = planner.plan(app.view(), Default::default()).await?; + app.build_and_submit_transaction(plan).await?; + + Ok(()) } } From 3b73869e302f00f9cabb7b67b366dfea306166a7 Mon Sep 17 00:00:00 2001 From: Lucas Meier Date: Sat, 8 Feb 2025 00:16:45 -0800 Subject: [PATCH 12/13] lqt: add missing TryFrom section for action plan protos --- crates/core/transaction/src/plan/action.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/core/transaction/src/plan/action.rs b/crates/core/transaction/src/plan/action.rs index c2ad5eca4b..c0acf69ac0 100644 --- a/crates/core/transaction/src/plan/action.rs +++ b/crates/core/transaction/src/plan/action.rs @@ -649,8 +649,8 @@ impl TryFrom for ActionPlan { pb_t::action_plan::Action::Ics20Withdrawal(inner) => { Ok(ActionPlan::Ics20Withdrawal(inner.try_into()?)) } - pb_t::action_plan::Action::ActionLiquidityTournamentVotePlan(_) => { - unimplemented!() + pb_t::action_plan::Action::ActionLiquidityTournamentVotePlan(inner) => { + Ok(ActionPlan::ActionLiquidityTournamentVote(inner.try_into()?)) } } } From 6373effa18c6012af77b92448fee2d2b5a1885a1 Mon Sep 17 00:00:00 2001 From: Lucas Meier Date: Sat, 8 Feb 2025 00:52:25 -0800 Subject: [PATCH 13/13] lqt: augment AuthorizationData to allow signing lqt transactions Was it really a good design to not just have a bunch of randomizers in auth data? Probably not, but oh well. --- .../app/src/action_handler/actions/submit.rs | 1 + crates/core/transaction/src/auth_data.rs | 9 + crates/core/transaction/src/plan.rs | 11 + crates/core/transaction/src/plan/auth.rs | 7 + crates/core/transaction/src/plan/build.rs | 16 + crates/custody/src/threshold/sign.rs | 10 +- .../src/gen/penumbra.core.transaction.v1.rs | 5 + .../gen/penumbra.core.transaction.v1.serde.rs | 18 + crates/proto/src/gen/penumbra.view.v1.rs | 1906 +++++++++++------ .../proto/src/gen/proto_descriptor.bin.no_lfs | Bin 664864 -> 665114 bytes .../core/transaction/v1/transaction.proto | 2 + 11 files changed, 1352 insertions(+), 633 deletions(-) diff --git a/crates/core/app/src/action_handler/actions/submit.rs b/crates/core/app/src/action_handler/actions/submit.rs index 23b194a8f3..a0ded0339c 100644 --- a/crates/core/app/src/action_handler/actions/submit.rs +++ b/crates/core/app/src/action_handler/actions/submit.rs @@ -357,6 +357,7 @@ async fn build_community_pool_transaction( effect_hash: Some(effect_hash), spend_auths: Default::default(), delegator_vote_auths: Default::default(), + lqt_vote_auths: Default::default(), }, ) } diff --git a/crates/core/transaction/src/auth_data.rs b/crates/core/transaction/src/auth_data.rs index 9a6b00a856..3f45e83dbf 100644 --- a/crates/core/transaction/src/auth_data.rs +++ b/crates/core/transaction/src/auth_data.rs @@ -15,6 +15,9 @@ pub struct AuthorizationData { /// The required delegator vote authorization signatures, returned in the same order as the /// DelegatorVote actions in the original request. pub delegator_vote_auths: Vec>, + /// The required LQT vote authorization signatures, returned in the same order as the + /// actions in the original request + pub lqt_vote_auths: Vec>, } impl DomainType for AuthorizationData { @@ -31,6 +34,7 @@ impl From for pb::AuthorizationData { .into_iter() .map(Into::into) .collect(), + lqt_vote_auths: msg.lqt_vote_auths.into_iter().map(Into::into).collect(), } } } @@ -50,6 +54,11 @@ impl TryFrom for AuthorizationData { .into_iter() .map(TryInto::try_into) .collect::>()?, + lqt_vote_auths: value + .lqt_vote_auths + .into_iter() + .map(TryInto::try_into) + .collect::>()?, }) } } diff --git a/crates/core/transaction/src/plan.rs b/crates/core/transaction/src/plan.rs index 17280905b6..0f450e2cd5 100644 --- a/crates/core/transaction/src/plan.rs +++ b/crates/core/transaction/src/plan.rs @@ -10,6 +10,7 @@ use penumbra_sdk_dex::{ swap::SwapPlan, swap_claim::SwapClaimPlan, }; +use penumbra_sdk_funding::liquidity_tournament::ActionLiquidityTournamentVotePlan; use penumbra_sdk_governance::{ DelegatorVotePlan, ProposalDepositClaim, ProposalSubmit, ProposalWithdraw, ValidatorVote, }; @@ -213,6 +214,16 @@ impl TransactionPlan { }) } + pub fn lqt_vote_plans(&self) -> impl Iterator { + self.actions.iter().filter_map(|action| { + if let ActionPlan::ActionLiquidityTournamentVote(v) = action { + Some(v) + } else { + None + } + }) + } + pub fn validator_votes(&self) -> impl Iterator { self.actions.iter().filter_map(|action| { if let ActionPlan::ValidatorVote(v) = action { diff --git a/crates/core/transaction/src/plan/auth.rs b/crates/core/transaction/src/plan/auth.rs index 831d34f075..0d61dcafc5 100644 --- a/crates/core/transaction/src/plan/auth.rs +++ b/crates/core/transaction/src/plan/auth.rs @@ -17,6 +17,7 @@ impl TransactionPlan { let effect_hash = self.effect_hash(sk.full_viewing_key())?; let mut spend_auths = Vec::new(); let mut delegator_vote_auths = Vec::new(); + let mut lqt_vote_auths = Vec::new(); for spend_plan in self.spend_plans() { let rsk = sk.spend_auth_key().randomize(&spend_plan.randomizer); @@ -30,10 +31,16 @@ impl TransactionPlan { let auth_sig = rsk.sign(&mut rng, effect_hash.as_ref()); delegator_vote_auths.push(auth_sig); } + for lqt_vote_plan in self.lqt_vote_plans() { + let rsk = sk.spend_auth_key().randomize(&lqt_vote_plan.randomizer); + let auth_sig = rsk.sign(&mut rng, effect_hash.as_ref()); + lqt_vote_auths.push(auth_sig); + } Ok(AuthorizationData { effect_hash: Some(effect_hash), spend_auths, delegator_vote_auths, + lqt_vote_auths, }) } } diff --git a/crates/core/transaction/src/plan/build.rs b/crates/core/transaction/src/plan/build.rs index 1eb831a162..76a7e76055 100644 --- a/crates/core/transaction/src/plan/build.rs +++ b/crates/core/transaction/src/plan/build.rs @@ -100,6 +100,22 @@ impl TransactionPlan { delegator_vote.auth_sig = auth_sig; } + for (lqt_vote, auth_sig) in transaction + .transaction_body + .actions + .iter_mut() + .filter_map(|action| { + if let Action::ActionLiquidityTournamentVote(s) = action { + Some(s) + } else { + None + } + }) + .zip(auth_data.lqt_vote_auths.clone().into_iter()) + { + lqt_vote.auth_sig = auth_sig; + } + // Compute the binding signature and assemble the transaction. let binding_signing_key = rdsa::SigningKey::from(synthetic_blinding_factor); let auth_hash = transaction.transaction_body.auth_hash(); diff --git a/crates/custody/src/threshold/sign.rs b/crates/custody/src/threshold/sign.rs index fe0ac495c5..a52c7f3f02 100644 --- a/crates/custody/src/threshold/sign.rs +++ b/crates/custody/src/threshold/sign.rs @@ -321,7 +321,9 @@ impl DomainType for FollowerRound2 { fn required_signatures(request: &SigningRequest) -> usize { match request { SigningRequest::TransactionPlan(plan) => { - plan.spend_plans().count() + plan.delegator_vote_plans().count() + plan.spend_plans().count() + + plan.delegator_vote_plans().count() + + plan.lqt_vote_plans().count() } SigningRequest::ValidatorDefinition(_) => 1, SigningRequest::ValidatorVote(_) => 1, @@ -339,6 +341,7 @@ pub fn no_signature_response( effect_hash: Some(plan.effect_hash(fvk)?), spend_auths: Vec::new(), delegator_vote_auths: Vec::new(), + lqt_vote_auths: Vec::new(), }))) } _ => Ok(None), @@ -484,6 +487,7 @@ pub fn coordinator_round3( .spend_plans() .map(|x| x.randomizer) .chain(plan.delegator_vote_plans().map(|x| x.randomizer)) + .chain(plan.lqt_vote_plans().map(|x| x.randomizer)) .zip(share_maps.iter()) .zip(state.signing_packages.iter()) .map(|((randomizer, share_map), signing_package)| { @@ -495,7 +499,8 @@ pub fn coordinator_round3( ) }) .collect::, _>>()?; - let delegator_vote_auths = spend_auths.split_off(plan.spend_plans().count()); + let mut delegator_vote_auths = spend_auths.split_off(plan.spend_plans().count()); + let lqt_vote_auths = delegator_vote_auths.split_off(plan.spend_plans().count()); Ok(SigningResponse::Transaction(AuthorizationData { effect_hash: { let ToBeSigned::EffectHash(effect_hash) = state.to_be_signed else { @@ -505,6 +510,7 @@ pub fn coordinator_round3( }, spend_auths, delegator_vote_auths, + lqt_vote_auths, })) } SigningRequest::ValidatorDefinition(_) => { diff --git a/crates/proto/src/gen/penumbra.core.transaction.v1.rs b/crates/proto/src/gen/penumbra.core.transaction.v1.rs index e5f9796491..540d60ecac 100644 --- a/crates/proto/src/gen/penumbra.core.transaction.v1.rs +++ b/crates/proto/src/gen/penumbra.core.transaction.v1.rs @@ -587,6 +587,11 @@ pub struct AuthorizationData { pub delegator_vote_auths: ::prost::alloc::vec::Vec< super::super::super::crypto::decaf377_rdsa::v1::SpendAuthSignature, >, + /// The required LQT vote authorizations, in the same order as the original request. + #[prost(message, repeated, tag = "4")] + pub lqt_vote_auths: ::prost::alloc::vec::Vec< + super::super::super::crypto::decaf377_rdsa::v1::SpendAuthSignature, + >, } impl ::prost::Name for AuthorizationData { const NAME: &'static str = "AuthorizationData"; diff --git a/crates/proto/src/gen/penumbra.core.transaction.v1.serde.rs b/crates/proto/src/gen/penumbra.core.transaction.v1.serde.rs index 6e249462da..cb0c1f5840 100644 --- a/crates/proto/src/gen/penumbra.core.transaction.v1.serde.rs +++ b/crates/proto/src/gen/penumbra.core.transaction.v1.serde.rs @@ -1353,6 +1353,9 @@ impl serde::Serialize for AuthorizationData { if !self.delegator_vote_auths.is_empty() { len += 1; } + if !self.lqt_vote_auths.is_empty() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("penumbra.core.transaction.v1.AuthorizationData", len)?; if let Some(v) = self.effect_hash.as_ref() { struct_ser.serialize_field("effectHash", v)?; @@ -1363,6 +1366,9 @@ impl serde::Serialize for AuthorizationData { if !self.delegator_vote_auths.is_empty() { struct_ser.serialize_field("delegatorVoteAuths", &self.delegator_vote_auths)?; } + if !self.lqt_vote_auths.is_empty() { + struct_ser.serialize_field("lqtVoteAuths", &self.lqt_vote_auths)?; + } struct_ser.end() } } @@ -1379,6 +1385,8 @@ impl<'de> serde::Deserialize<'de> for AuthorizationData { "spendAuths", "delegator_vote_auths", "delegatorVoteAuths", + "lqt_vote_auths", + "lqtVoteAuths", ]; #[allow(clippy::enum_variant_names)] @@ -1386,6 +1394,7 @@ impl<'de> serde::Deserialize<'de> for AuthorizationData { EffectHash, SpendAuths, DelegatorVoteAuths, + LqtVoteAuths, __SkipField__, } impl<'de> serde::Deserialize<'de> for GeneratedField { @@ -1411,6 +1420,7 @@ impl<'de> serde::Deserialize<'de> for AuthorizationData { "effectHash" | "effect_hash" => Ok(GeneratedField::EffectHash), "spendAuths" | "spend_auths" => Ok(GeneratedField::SpendAuths), "delegatorVoteAuths" | "delegator_vote_auths" => Ok(GeneratedField::DelegatorVoteAuths), + "lqtVoteAuths" | "lqt_vote_auths" => Ok(GeneratedField::LqtVoteAuths), _ => Ok(GeneratedField::__SkipField__), } } @@ -1433,6 +1443,7 @@ impl<'de> serde::Deserialize<'de> for AuthorizationData { let mut effect_hash__ = None; let mut spend_auths__ = None; let mut delegator_vote_auths__ = None; + let mut lqt_vote_auths__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::EffectHash => { @@ -1453,6 +1464,12 @@ impl<'de> serde::Deserialize<'de> for AuthorizationData { } delegator_vote_auths__ = Some(map_.next_value()?); } + GeneratedField::LqtVoteAuths => { + if lqt_vote_auths__.is_some() { + return Err(serde::de::Error::duplicate_field("lqtVoteAuths")); + } + lqt_vote_auths__ = Some(map_.next_value()?); + } GeneratedField::__SkipField__ => { let _ = map_.next_value::()?; } @@ -1462,6 +1479,7 @@ impl<'de> serde::Deserialize<'de> for AuthorizationData { effect_hash: effect_hash__, spend_auths: spend_auths__.unwrap_or_default(), delegator_vote_auths: delegator_vote_auths__.unwrap_or_default(), + lqt_vote_auths: lqt_vote_auths__.unwrap_or_default(), }) } } diff --git a/crates/proto/src/gen/penumbra.view.v1.rs b/crates/proto/src/gen/penumbra.view.v1.rs index c7dfab2f0b..cdae31ef23 100644 --- a/crates/proto/src/gen/penumbra.view.v1.rs +++ b/crates/proto/src/gen/penumbra.view.v1.rs @@ -6,7 +6,9 @@ pub struct LqtVotingNotesRequest { pub epoch_index: u64, /// If present, filter balances to only include the account specified by the `AddressIndex`. #[prost(message, optional, tag = "2")] - pub account_filter: ::core::option::Option, + pub account_filter: ::core::option::Option< + super::super::core::keys::v1::AddressIndex, + >, } impl ::prost::Name for LqtVotingNotesRequest { const NAME: &'static str = "LqtVotingNotesRequest"; @@ -47,7 +49,9 @@ pub struct TournamentVotesRequest { pub block_height: u64, /// If present, filter balances to only include the account specified by the `AddressIndex`. #[prost(message, optional, tag = "3")] - pub account_filter: ::core::option::Option, + pub account_filter: ::core::option::Option< + super::super::core::keys::v1::AddressIndex, + >, } impl ::prost::Name for TournamentVotesRequest { const NAME: &'static str = "TournamentVotesRequest"; @@ -71,18 +75,22 @@ pub mod tournament_votes_response { pub struct Vote { /// The incentivized asset receiving this vote. #[prost(message, optional, tag = "1")] - pub incentivized_asset: - ::core::option::Option, + pub incentivized_asset: ::core::option::Option< + super::super::super::core::asset::v1::AssetId, + >, /// The amount of voting power that this specific vote contributed. #[prost(message, optional, tag = "2")] - pub vote_power: ::core::option::Option, + pub vote_power: ::core::option::Option< + super::super::super::core::num::v1::Amount, + >, /// The amount of rewards issued for votes on this asset. #[prost(message, optional, tag = "3")] pub reward: ::core::option::Option, /// The transaction ID for the vote. #[prost(message, optional, tag = "4")] - pub transaction: - ::core::option::Option, + pub transaction: ::core::option::Option< + super::super::super::core::txhash::v1::TransactionId, + >, } impl ::prost::Name for Vote { const NAME: &'static str = "Vote"; @@ -144,7 +152,9 @@ impl ::prost::Name for TransparentAddressResponse { pub struct AuctionsRequest { /// If present, filter balances to only include the account specified by the `AddressIndex`. #[prost(message, optional, tag = "1")] - pub account_filter: ::core::option::Option, + pub account_filter: ::core::option::Option< + super::super::core::keys::v1::AddressIndex, + >, /// If present, include inactive auctions as well as active ones. #[prost(bool, tag = "2")] pub include_inactive: bool, @@ -153,8 +163,9 @@ pub struct AuctionsRequest { pub query_latest_state: bool, /// If present, filter to only include auctions whose IDs are in this array. #[prost(message, repeated, tag = "4")] - pub auction_ids_filter: - ::prost::alloc::vec::Vec, + pub auction_ids_filter: ::prost::alloc::vec::Vec< + super::super::core::component::auction::v1::AuctionId, + >, } impl ::prost::Name for AuctionsRequest { const NAME: &'static str = "AuctionsRequest"; @@ -169,7 +180,9 @@ impl ::prost::Name for AuctionsRequest { #[derive(Clone, PartialEq, ::prost::Message)] pub struct AuctionsResponse { #[prost(message, optional, tag = "1")] - pub id: ::core::option::Option, + pub id: ::core::option::Option< + super::super::core::component::auction::v1::AuctionId, + >, /// The state of the returned auction. /// /// Only present when `query_latest_state` was provided. @@ -180,7 +193,9 @@ pub struct AuctionsResponse { /// Only present when `query_latest_state` was provided. /// Could be empty, depending on the auction state. #[prost(message, repeated, tag = "3")] - pub positions: ::prost::alloc::vec::Vec, + pub positions: ::prost::alloc::vec::Vec< + super::super::core::component::dex::v1::Position, + >, /// The note recording the auction NFT. #[prost(message, optional, tag = "4")] pub note_record: ::core::option::Option, @@ -210,8 +225,9 @@ impl ::prost::Name for AuctionsResponse { pub struct AuthorizeAndBuildRequest { /// The transaction plan to authorize and build. #[prost(message, optional, tag = "1")] - pub transaction_plan: - ::core::option::Option, + pub transaction_plan: ::core::option::Option< + super::super::core::transaction::v1::TransactionPlan, + >, } impl ::prost::Name for AuthorizeAndBuildRequest { const NAME: &'static str = "AuthorizeAndBuildRequest"; @@ -252,8 +268,9 @@ pub mod authorize_and_build_response { pub struct Complete { /// The finished transaction. #[prost(message, optional, tag = "1")] - pub transaction: - ::core::option::Option, + pub transaction: ::core::option::Option< + super::super::super::core::transaction::v1::Transaction, + >, } impl ::prost::Name for Complete { const NAME: &'static str = "Complete"; @@ -287,7 +304,9 @@ impl ::prost::Name for AuthorizeAndBuildResponse { pub struct BroadcastTransactionRequest { /// The transaction to broadcast. #[prost(message, optional, tag = "1")] - pub transaction: ::core::option::Option, + pub transaction: ::core::option::Option< + super::super::core::transaction::v1::Transaction, + >, /// If true, wait for the view service to detect the transaction during sync. #[prost(bool, tag = "2")] pub await_detection: bool, @@ -314,7 +333,9 @@ pub mod broadcast_transaction_response { pub struct BroadcastSuccess { /// The hash of the transaction that was broadcast. #[prost(message, optional, tag = "1")] - pub id: ::core::option::Option, + pub id: ::core::option::Option< + super::super::super::core::txhash::v1::TransactionId, + >, } impl ::prost::Name for BroadcastSuccess { const NAME: &'static str = "BroadcastSuccess"; @@ -333,7 +354,9 @@ pub mod broadcast_transaction_response { pub struct Confirmed { /// The hash of the transaction that was broadcast. #[prost(message, optional, tag = "1")] - pub id: ::core::option::Option, + pub id: ::core::option::Option< + super::super::super::core::txhash::v1::TransactionId, + >, /// The height in which the transaction was detected as included in the chain, if any. #[prost(uint64, tag = "2")] pub detection_height: u64, @@ -392,30 +415,45 @@ pub struct TransactionPlannerRequest { #[prost(message, repeated, tag = "50")] pub undelegations: ::prost::alloc::vec::Vec, #[prost(message, repeated, tag = "51")] - pub undelegation_claims: ::prost::alloc::vec::Vec, + pub undelegation_claims: ::prost::alloc::vec::Vec< + transaction_planner_request::UndelegateClaim, + >, #[prost(message, repeated, tag = "60")] - pub ibc_relay_actions: - ::prost::alloc::vec::Vec, + pub ibc_relay_actions: ::prost::alloc::vec::Vec< + super::super::core::component::ibc::v1::IbcRelay, + >, #[prost(message, repeated, tag = "61")] - pub ics20_withdrawals: - ::prost::alloc::vec::Vec, + pub ics20_withdrawals: ::prost::alloc::vec::Vec< + super::super::core::component::ibc::v1::Ics20Withdrawal, + >, #[prost(message, repeated, tag = "70")] - pub position_opens: ::prost::alloc::vec::Vec, + pub position_opens: ::prost::alloc::vec::Vec< + transaction_planner_request::PositionOpen, + >, #[prost(message, repeated, tag = "71")] - pub position_closes: ::prost::alloc::vec::Vec, + pub position_closes: ::prost::alloc::vec::Vec< + transaction_planner_request::PositionClose, + >, #[prost(message, repeated, tag = "72")] - pub position_withdraws: ::prost::alloc::vec::Vec, + pub position_withdraws: ::prost::alloc::vec::Vec< + transaction_planner_request::PositionWithdraw, + >, #[prost(message, repeated, tag = "73")] - pub dutch_auction_schedule_actions: - ::prost::alloc::vec::Vec, + pub dutch_auction_schedule_actions: ::prost::alloc::vec::Vec< + transaction_planner_request::ActionDutchAuctionSchedule, + >, #[prost(message, repeated, tag = "74")] - pub dutch_auction_end_actions: - ::prost::alloc::vec::Vec, + pub dutch_auction_end_actions: ::prost::alloc::vec::Vec< + transaction_planner_request::ActionDutchAuctionEnd, + >, #[prost(message, repeated, tag = "75")] - pub dutch_auction_withdraw_actions: - ::prost::alloc::vec::Vec, + pub dutch_auction_withdraw_actions: ::prost::alloc::vec::Vec< + transaction_planner_request::ActionDutchAuctionWithdraw, + >, #[prost(message, repeated, tag = "76")] - pub delegator_votes: ::prost::alloc::vec::Vec, + pub delegator_votes: ::prost::alloc::vec::Vec< + transaction_planner_request::DelegatorVote, + >, /// The epoch index of the transaction being planned. #[deprecated] #[prost(uint64, tag = "200")] @@ -437,7 +475,9 @@ pub mod transaction_planner_request { pub value: ::core::option::Option, /// The address to which Output will be sent. #[prost(message, optional, tag = "2")] - pub address: ::core::option::Option, + pub address: ::core::option::Option< + super::super::super::core::keys::v1::Address, + >, } impl ::prost::Name for Output { const NAME: &'static str = "Output"; @@ -456,7 +496,9 @@ pub mod transaction_planner_request { pub value: ::core::option::Option, /// The source address from which the Spend will be sent. #[prost(message, optional, tag = "2")] - pub address: ::core::option::Option, + pub address: ::core::option::Option< + super::super::super::core::keys::v1::Address, + >, } impl ::prost::Name for Spend { const NAME: &'static str = "Spend"; @@ -475,13 +517,19 @@ pub mod transaction_planner_request { pub value: ::core::option::Option, /// The denomination to be received as a Output of the Swap. #[prost(message, optional, tag = "2")] - pub target_asset: ::core::option::Option, + pub target_asset: ::core::option::Option< + super::super::super::core::asset::v1::AssetId, + >, /// The pre-paid fee to be paid for claiming the Swap outputs. #[prost(message, optional, tag = "3")] - pub fee: ::core::option::Option, + pub fee: ::core::option::Option< + super::super::super::core::component::fee::v1::Fee, + >, /// The address to which swap claim output will be sent. #[prost(message, optional, tag = "4")] - pub claim_address: ::core::option::Option, + pub claim_address: ::core::option::Option< + super::super::super::core::keys::v1::Address, + >, } impl ::prost::Name for Swap { const NAME: &'static str = "Swap"; @@ -499,8 +547,9 @@ pub mod transaction_planner_request { /// Use the commitment from the Swap message: /// penumbra.core.component.dex.v1.Swap.body.payload.commitment. #[prost(message, optional, tag = "1")] - pub swap_commitment: - ::core::option::Option, + pub swap_commitment: ::core::option::Option< + super::super::super::crypto::tct::v1::StateCommitment, + >, } impl ::prost::Name for SwapClaim { const NAME: &'static str = "SwapClaim"; @@ -517,8 +566,9 @@ pub mod transaction_planner_request { #[prost(message, optional, tag = "1")] pub amount: ::core::option::Option, #[prost(message, optional, tag = "3")] - pub rate_data: - ::core::option::Option, + pub rate_data: ::core::option::Option< + super::super::super::core::component::stake::v1::RateData, + >, } impl ::prost::Name for Delegate { const NAME: &'static str = "Delegate"; @@ -535,8 +585,9 @@ pub mod transaction_planner_request { #[prost(message, optional, tag = "1")] pub value: ::core::option::Option, #[prost(message, optional, tag = "2")] - pub rate_data: - ::core::option::Option, + pub rate_data: ::core::option::Option< + super::super::super::core::component::stake::v1::RateData, + >, } impl ::prost::Name for Undelegate { const NAME: &'static str = "Undelegate"; @@ -552,8 +603,9 @@ pub mod transaction_planner_request { pub struct UndelegateClaim { /// The identity key of the validator to finish undelegating from. #[prost(message, optional, tag = "1")] - pub validator_identity: - ::core::option::Option, + pub validator_identity: ::core::option::Option< + super::super::super::core::keys::v1::IdentityKey, + >, /// The epoch in which unbonding began, used to verify the penalty. #[deprecated] #[prost(uint64, tag = "2")] @@ -561,12 +613,15 @@ pub mod transaction_planner_request { /// The penalty applied to undelegation, in bps^2 (10e-8). /// In the happy path (no slashing), this is 0. #[prost(message, optional, tag = "3")] - pub penalty: - ::core::option::Option, + pub penalty: ::core::option::Option< + super::super::super::core::component::stake::v1::Penalty, + >, /// The amount of unbonding tokens to claim. /// This is a bare number because its denom is determined by the preceding data. #[prost(message, optional, tag = "4")] - pub unbonding_amount: ::core::option::Option, + pub unbonding_amount: ::core::option::Option< + super::super::super::core::num::v1::Amount, + >, /// The height at which unbonding began. #[prost(uint64, tag = "5")] pub unbonding_start_height: u64, @@ -588,8 +643,9 @@ pub mod transaction_planner_request { /// Positions are immutable, so the `PositionData` (and hence the `PositionId`) /// are unchanged over the entire lifetime of the position. #[prost(message, optional, tag = "1")] - pub position: - ::core::option::Option, + pub position: ::core::option::Option< + super::super::super::core::component::dex::v1::Position, + >, } impl ::prost::Name for PositionOpen { const NAME: &'static str = "PositionOpen"; @@ -605,8 +661,9 @@ pub mod transaction_planner_request { pub struct PositionClose { /// The position to close. #[prost(message, optional, tag = "1")] - pub position_id: - ::core::option::Option, + pub position_id: ::core::option::Option< + super::super::super::core::component::dex::v1::PositionId, + >, } impl ::prost::Name for PositionClose { const NAME: &'static str = "PositionClose"; @@ -622,16 +679,19 @@ pub mod transaction_planner_request { pub struct PositionWithdraw { /// The position to withdraw. #[prost(message, optional, tag = "1")] - pub position_id: - ::core::option::Option, + pub position_id: ::core::option::Option< + super::super::super::core::component::dex::v1::PositionId, + >, /// The position's final reserves. #[prost(message, optional, tag = "2")] - pub reserves: - ::core::option::Option, + pub reserves: ::core::option::Option< + super::super::super::core::component::dex::v1::Reserves, + >, /// The trading pair of the position. #[prost(message, optional, tag = "3")] - pub trading_pair: - ::core::option::Option, + pub trading_pair: ::core::option::Option< + super::super::super::core::component::dex::v1::TradingPair, + >, } impl ::prost::Name for PositionWithdraw { const NAME: &'static str = "PositionWithdraw"; @@ -655,18 +715,21 @@ pub mod transaction_planner_request { const NAME: &'static str = "ActionDutchAuctionSchedule"; const PACKAGE: &'static str = "penumbra.view.v1"; fn full_name() -> ::prost::alloc::string::String { - "penumbra.view.v1.TransactionPlannerRequest.ActionDutchAuctionSchedule".into() + "penumbra.view.v1.TransactionPlannerRequest.ActionDutchAuctionSchedule" + .into() } fn type_url() -> ::prost::alloc::string::String { - "/penumbra.view.v1.TransactionPlannerRequest.ActionDutchAuctionSchedule".into() + "/penumbra.view.v1.TransactionPlannerRequest.ActionDutchAuctionSchedule" + .into() } } #[derive(Clone, PartialEq, ::prost::Message)] pub struct ActionDutchAuctionEnd { /// The unique id of the auction to close. #[prost(message, optional, tag = "1")] - pub auction_id: - ::core::option::Option, + pub auction_id: ::core::option::Option< + super::super::super::core::component::auction::v1::AuctionId, + >, } impl ::prost::Name for ActionDutchAuctionEnd { const NAME: &'static str = "ActionDutchAuctionEnd"; @@ -682,8 +745,9 @@ pub mod transaction_planner_request { pub struct ActionDutchAuctionWithdraw { /// The auction to withdraw funds from. #[prost(message, optional, tag = "1")] - pub auction_id: - ::core::option::Option, + pub auction_id: ::core::option::Option< + super::super::super::core::component::auction::v1::AuctionId, + >, /// The sequence number of the withdrawal. #[prost(uint64, tag = "2")] pub seq: u64, @@ -692,10 +756,12 @@ pub mod transaction_planner_request { const NAME: &'static str = "ActionDutchAuctionWithdraw"; const PACKAGE: &'static str = "penumbra.view.v1"; fn full_name() -> ::prost::alloc::string::String { - "penumbra.view.v1.TransactionPlannerRequest.ActionDutchAuctionWithdraw".into() + "penumbra.view.v1.TransactionPlannerRequest.ActionDutchAuctionWithdraw" + .into() } fn type_url() -> ::prost::alloc::string::String { - "/penumbra.view.v1.TransactionPlannerRequest.ActionDutchAuctionWithdraw".into() + "/penumbra.view.v1.TransactionPlannerRequest.ActionDutchAuctionWithdraw" + .into() } } #[derive(Clone, PartialEq, ::prost::Message)] @@ -705,8 +771,9 @@ pub mod transaction_planner_request { pub proposal: u64, /// The vote. #[prost(message, optional, tag = "2")] - pub vote: - ::core::option::Option, + pub vote: ::core::option::Option< + super::super::super::core::component::governance::v1::Vote, + >, /// The block height at which the proposal started voting. #[prost(uint64, tag = "3")] pub start_block_height: u64, @@ -715,8 +782,9 @@ pub mod transaction_planner_request { pub start_position: u64, /// The validators rate data for the proposal. #[prost(message, repeated, tag = "5")] - pub rate_data: - ::prost::alloc::vec::Vec, + pub rate_data: ::prost::alloc::vec::Vec< + super::super::super::core::component::stake::v1::RateData, + >, } impl ::prost::Name for DelegatorVote { const NAME: &'static str = "DelegatorVote"; @@ -752,7 +820,9 @@ impl ::prost::Name for TransactionPlannerRequest { #[derive(Clone, PartialEq, ::prost::Message)] pub struct TransactionPlannerResponse { #[prost(message, optional, tag = "1")] - pub plan: ::core::option::Option, + pub plan: ::core::option::Option< + super::super::core::transaction::v1::TransactionPlan, + >, } impl ::prost::Name for TransactionPlannerResponse { const NAME: &'static str = "TransactionPlannerResponse"; @@ -767,7 +837,9 @@ impl ::prost::Name for TransactionPlannerResponse { #[derive(Clone, PartialEq, ::prost::Message)] pub struct AddressByIndexRequest { #[prost(message, optional, tag = "1")] - pub address_index: ::core::option::Option, + pub address_index: ::core::option::Option< + super::super::core::keys::v1::AddressIndex, + >, } impl ::prost::Name for AddressByIndexRequest { const NAME: &'static str = "AddressByIndexRequest"; @@ -840,7 +912,9 @@ impl ::prost::Name for IndexByAddressRequest { pub struct IndexByAddressResponse { /// Will be absent if given an address not viewable by this viewing service #[prost(message, optional, tag = "1")] - pub address_index: ::core::option::Option, + pub address_index: ::core::option::Option< + super::super::core::keys::v1::AddressIndex, + >, } impl ::prost::Name for IndexByAddressResponse { const NAME: &'static str = "IndexByAddressResponse"; @@ -855,7 +929,9 @@ impl ::prost::Name for IndexByAddressResponse { #[derive(Clone, PartialEq, ::prost::Message)] pub struct EphemeralAddressRequest { #[prost(message, optional, tag = "1")] - pub address_index: ::core::option::Option, + pub address_index: ::core::option::Option< + super::super::core::keys::v1::AddressIndex, + >, } impl ::prost::Name for EphemeralAddressRequest { const NAME: &'static str = "EphemeralAddressRequest"; @@ -886,7 +962,9 @@ impl ::prost::Name for EphemeralAddressResponse { pub struct BalancesRequest { /// If present, filter balances to only include the account specified by the `AddressIndex`. #[prost(message, optional, tag = "1")] - pub account_filter: ::core::option::Option, + pub account_filter: ::core::option::Option< + super::super::core::keys::v1::AddressIndex, + >, /// If present, filter balances to only include the specified asset ID. #[prost(message, optional, tag = "2")] pub asset_id_filter: ::core::option::Option, @@ -916,7 +994,9 @@ pub struct BalancesResponse { /// Note that the returned balance is for all funds sent to the account, /// not just funds sent to its default address. #[prost(message, optional, tag = "3")] - pub account_address: ::core::option::Option, + pub account_address: ::core::option::Option< + super::super::core::keys::v1::AddressView, + >, /// The account's balance, with metadata. #[prost(message, optional, tag = "4")] pub balance_view: ::core::option::Option, @@ -1017,7 +1097,9 @@ pub struct NotesRequest { pub asset_id: ::core::option::Option, /// If set, only return notes with the specified address incore.component.dex.v1. #[prost(message, optional, tag = "4")] - pub address_index: ::core::option::Option, + pub address_index: ::core::option::Option< + super::super::core::keys::v1::AddressIndex, + >, /// If set, stop returning notes once the total exceeds this amount. /// /// Ignored if `asset_id` is unset or if `include_spent` is set. @@ -1042,7 +1124,9 @@ pub struct NotesForVotingRequest { pub votable_at_height: u64, /// If set, only return notes with the specified asset id. #[prost(message, optional, tag = "3")] - pub address_index: ::core::option::Option, + pub address_index: ::core::option::Option< + super::super::core::keys::v1::AddressIndex, + >, } impl ::prost::Name for NotesForVotingRequest { const NAME: &'static str = "NotesForVotingRequest"; @@ -1058,8 +1142,9 @@ impl ::prost::Name for NotesForVotingRequest { pub struct WitnessRequest { /// The transaction plan to witness #[prost(message, optional, tag = "3")] - pub transaction_plan: - ::core::option::Option, + pub transaction_plan: ::core::option::Option< + super::super::core::transaction::v1::TransactionPlan, + >, } impl ::prost::Name for WitnessRequest { const NAME: &'static str = "WitnessRequest"; @@ -1074,7 +1159,9 @@ impl ::prost::Name for WitnessRequest { #[derive(Clone, PartialEq, ::prost::Message)] pub struct WitnessResponse { #[prost(message, optional, tag = "1")] - pub witness_data: ::core::option::Option, + pub witness_data: ::core::option::Option< + super::super::core::transaction::v1::WitnessData, + >, } impl ::prost::Name for WitnessResponse { const NAME: &'static str = "WitnessResponse"; @@ -1089,11 +1176,13 @@ impl ::prost::Name for WitnessResponse { #[derive(Clone, PartialEq, ::prost::Message)] pub struct WitnessAndBuildRequest { #[prost(message, optional, tag = "1")] - pub transaction_plan: - ::core::option::Option, + pub transaction_plan: ::core::option::Option< + super::super::core::transaction::v1::TransactionPlan, + >, #[prost(message, optional, tag = "2")] - pub authorization_data: - ::core::option::Option, + pub authorization_data: ::core::option::Option< + super::super::core::transaction::v1::AuthorizationData, + >, } impl ::prost::Name for WitnessAndBuildRequest { const NAME: &'static str = "WitnessAndBuildRequest"; @@ -1134,8 +1223,9 @@ pub mod witness_and_build_response { pub struct Complete { /// The finished transaction. #[prost(message, optional, tag = "1")] - pub transaction: - ::core::option::Option, + pub transaction: ::core::option::Option< + super::super::super::core::transaction::v1::Transaction, + >, } impl ::prost::Name for Complete { const NAME: &'static str = "Complete"; @@ -1174,8 +1264,9 @@ pub struct AssetsRequest { pub filtered: bool, /// Include these specific denominations in the response. #[prost(message, repeated, tag = "2")] - pub include_specific_denominations: - ::prost::alloc::vec::Vec, + pub include_specific_denominations: ::prost::alloc::vec::Vec< + super::super::core::asset::v1::Denom, + >, /// Include all delegation tokens, to any validator, in the response. #[prost(bool, tag = "3")] pub include_delegation_tokens: bool, @@ -1263,10 +1354,14 @@ impl ::prost::Name for GasPricesRequest { pub struct GasPricesResponse { /// The current gas prices, in the preferred (native) token. #[prost(message, optional, tag = "1")] - pub gas_prices: ::core::option::Option, + pub gas_prices: ::core::option::Option< + super::super::core::component::fee::v1::GasPrices, + >, /// Other gas prices for other accepted tokens. #[prost(message, repeated, tag = "2")] - pub alt_gas_prices: ::prost::alloc::vec::Vec, + pub alt_gas_prices: ::prost::alloc::vec::Vec< + super::super::core::component::fee::v1::GasPrices, + >, } impl ::prost::Name for GasPricesResponse { const NAME: &'static str = "GasPricesResponse"; @@ -1294,8 +1389,9 @@ impl ::prost::Name for FmdParametersRequest { #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct FmdParametersResponse { #[prost(message, optional, tag = "1")] - pub parameters: - ::core::option::Option, + pub parameters: ::core::option::Option< + super::super::core::component::shielded_pool::v1::FmdParameters, + >, } impl ::prost::Name for FmdParametersResponse { const NAME: &'static str = "FMDParametersResponse"; @@ -1310,7 +1406,9 @@ impl ::prost::Name for FmdParametersResponse { #[derive(Clone, PartialEq, ::prost::Message)] pub struct NoteByCommitmentRequest { #[prost(message, optional, tag = "2")] - pub note_commitment: ::core::option::Option, + pub note_commitment: ::core::option::Option< + super::super::crypto::tct::v1::StateCommitment, + >, /// If set to true, waits to return until the requested note is detected. #[prost(bool, tag = "3")] pub await_detection: bool, @@ -1343,7 +1441,9 @@ impl ::prost::Name for NoteByCommitmentResponse { #[derive(Clone, PartialEq, ::prost::Message)] pub struct SwapByCommitmentRequest { #[prost(message, optional, tag = "2")] - pub swap_commitment: ::core::option::Option, + pub swap_commitment: ::core::option::Option< + super::super::crypto::tct::v1::StateCommitment, + >, /// If set to true, waits to return until the requested swap is detected. #[prost(bool, tag = "3")] pub await_detection: bool, @@ -1403,7 +1503,9 @@ impl ::prost::Name for UnclaimedSwapsResponse { #[derive(Clone, PartialEq, ::prost::Message)] pub struct NullifierStatusRequest { #[prost(message, optional, tag = "2")] - pub nullifier: ::core::option::Option, + pub nullifier: ::core::option::Option< + super::super::core::component::sct::v1::Nullifier, + >, #[prost(bool, tag = "3")] pub await_detection: bool, } @@ -1477,14 +1579,19 @@ pub struct TransactionInfo { pub id: ::core::option::Option, /// The transaction data itself. #[prost(message, optional, tag = "3")] - pub transaction: ::core::option::Option, + pub transaction: ::core::option::Option< + super::super::core::transaction::v1::Transaction, + >, /// The transaction perspective, as seen by this view server. #[prost(message, optional, tag = "4")] - pub perspective: - ::core::option::Option, + pub perspective: ::core::option::Option< + super::super::core::transaction::v1::TransactionPerspective, + >, /// A precomputed transaction view of `transaction` from `perspective`, included for convenience of clients that don't have support for viewing transactions on their own. #[prost(message, optional, tag = "5")] - pub view: ::core::option::Option, + pub view: ::core::option::Option< + super::super::core::transaction::v1::TransactionView, + >, } impl ::prost::Name for TransactionInfo { const NAME: &'static str = "TransactionInfo"; @@ -1563,16 +1670,24 @@ impl ::prost::Name for NotesForVotingResponse { pub struct SpendableNoteRecord { /// The note commitment, identifying the note. #[prost(message, optional, tag = "1")] - pub note_commitment: ::core::option::Option, + pub note_commitment: ::core::option::Option< + super::super::crypto::tct::v1::StateCommitment, + >, /// The note plaintext itself. #[prost(message, optional, tag = "2")] - pub note: ::core::option::Option, + pub note: ::core::option::Option< + super::super::core::component::shielded_pool::v1::Note, + >, /// A precomputed decryption of the note's address incore.component.dex.v1. #[prost(message, optional, tag = "3")] - pub address_index: ::core::option::Option, + pub address_index: ::core::option::Option< + super::super::core::keys::v1::AddressIndex, + >, /// The note's nullifier. #[prost(message, optional, tag = "4")] - pub nullifier: ::core::option::Option, + pub nullifier: ::core::option::Option< + super::super::core::component::sct::v1::Nullifier, + >, /// The height at which the note was created. #[prost(uint64, tag = "5")] pub height_created: u64, @@ -1584,10 +1699,14 @@ pub struct SpendableNoteRecord { pub position: u64, /// The source of the note #[prost(message, optional, tag = "8")] - pub source: ::core::option::Option, + pub source: ::core::option::Option< + super::super::core::component::sct::v1::CommitmentSource, + >, /// The sender's return address, if known. #[prost(message, optional, tag = "9")] - pub return_address: ::core::option::Option, + pub return_address: ::core::option::Option< + super::super::core::keys::v1::AddressView, + >, } impl ::prost::Name for SpendableNoteRecord { const NAME: &'static str = "SpendableNoteRecord"; @@ -1602,20 +1721,29 @@ impl ::prost::Name for SpendableNoteRecord { #[derive(Clone, PartialEq, ::prost::Message)] pub struct SwapRecord { #[prost(message, optional, tag = "1")] - pub swap_commitment: ::core::option::Option, + pub swap_commitment: ::core::option::Option< + super::super::crypto::tct::v1::StateCommitment, + >, #[prost(message, optional, tag = "2")] - pub swap: ::core::option::Option, + pub swap: ::core::option::Option< + super::super::core::component::dex::v1::SwapPlaintext, + >, #[prost(uint64, tag = "3")] pub position: u64, #[prost(message, optional, tag = "4")] - pub nullifier: ::core::option::Option, + pub nullifier: ::core::option::Option< + super::super::core::component::sct::v1::Nullifier, + >, #[prost(message, optional, tag = "5")] - pub output_data: - ::core::option::Option, + pub output_data: ::core::option::Option< + super::super::core::component::dex::v1::BatchSwapOutputData, + >, #[prost(uint64, tag = "6")] pub height_claimed: u64, #[prost(message, optional, tag = "7")] - pub source: ::core::option::Option, + pub source: ::core::option::Option< + super::super::core::component::sct::v1::CommitmentSource, + >, } impl ::prost::Name for SwapRecord { const NAME: &'static str = "SwapRecord"; @@ -1631,11 +1759,14 @@ impl ::prost::Name for SwapRecord { pub struct OwnedPositionIdsRequest { /// If present, return only positions with this position state. #[prost(message, optional, tag = "1")] - pub position_state: - ::core::option::Option, + pub position_state: ::core::option::Option< + super::super::core::component::dex::v1::PositionState, + >, /// If present, return only positions for this trading pair. #[prost(message, optional, tag = "2")] - pub trading_pair: ::core::option::Option, + pub trading_pair: ::core::option::Option< + super::super::core::component::dex::v1::TradingPair, + >, /// If present, return only positions for this subaccount index. #[prost(message, optional, tag = "3")] pub subaccount: ::core::option::Option, @@ -1653,7 +1784,9 @@ impl ::prost::Name for OwnedPositionIdsRequest { #[derive(Clone, PartialEq, ::prost::Message)] pub struct OwnedPositionIdsResponse { #[prost(message, optional, tag = "1")] - pub position_id: ::core::option::Option, + pub position_id: ::core::option::Option< + super::super::core::component::dex::v1::PositionId, + >, /// The subaccount this position belongs to. #[prost(message, optional, tag = "2")] pub subaccount: ::core::option::Option, @@ -1710,16 +1843,25 @@ impl ::prost::Name for AssetMetadataByIdResponse { pub struct DelegationsByAddressIndexRequest { /// The address index to fetch delegation balances for. #[prost(message, optional, tag = "1")] - pub address_index: ::core::option::Option, - #[prost( - enumeration = "delegations_by_address_index_request::Filter", - tag = "2" - )] + pub address_index: ::core::option::Option< + super::super::core::keys::v1::AddressIndex, + >, + #[prost(enumeration = "delegations_by_address_index_request::Filter", tag = "2")] pub filter: i32, } /// Nested message and enum types in `DelegationsByAddressIndexRequest`. pub mod delegations_by_address_index_request { - #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] + #[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, + ::prost::Enumeration + )] #[repr(i32)] pub enum Filter { /// By default, returns delegations for all active validators. For validators @@ -1742,7 +1884,9 @@ pub mod delegations_by_address_index_request { pub fn as_str_name(&self) -> &'static str { match self { Self::Unspecified => "FILTER_UNSPECIFIED", - Self::AllActiveWithNonzeroBalances => "FILTER_ALL_ACTIVE_WITH_NONZERO_BALANCES", + Self::AllActiveWithNonzeroBalances => { + "FILTER_ALL_ACTIVE_WITH_NONZERO_BALANCES" + } Self::All => "FILTER_ALL", } } @@ -1798,11 +1942,23 @@ pub struct UnbondingTokensByAddressIndexRequest { pub filter: i32, /// The address index to fetch unbonding tokens for. #[prost(message, optional, tag = "2")] - pub address_index: ::core::option::Option, + pub address_index: ::core::option::Option< + super::super::core::keys::v1::AddressIndex, + >, } /// Nested message and enum types in `UnbondingTokensByAddressIndexRequest`. pub mod unbonding_tokens_by_address_index_request { - #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] + #[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, + ::prost::Enumeration + )] #[repr(i32)] pub enum Filter { /// Return all unbonding tokens, regardless of whether they're claimable @@ -1878,10 +2034,14 @@ impl ::prost::Name for UnbondingTokensByAddressIndexResponse { pub struct LatestSwapsRequest { /// If present, filter balances to only include the account specified by the `AddressIndex`. #[prost(message, optional, tag = "1")] - pub account_filter: ::core::option::Option, + pub account_filter: ::core::option::Option< + super::super::core::keys::v1::AddressIndex, + >, /// If present, filter balances to only include trading activity on the specified pair. #[prost(message, optional, tag = "2")] - pub pair: ::core::option::Option, + pub pair: ::core::option::Option< + super::super::core::component::dex::v1::DirectedTradingPair, + >, /// If present, limit the responses to activity that occured after this block height. #[prost(uint64, tag = "3")] pub after_height: u64, @@ -1903,7 +2063,9 @@ impl ::prost::Name for LatestSwapsRequest { pub struct LatestSwapsResponse { /// The trading pair involved in this swap. #[prost(message, optional, tag = "1")] - pub pair: ::core::option::Option, + pub pair: ::core::option::Option< + super::super::core::component::dex::v1::DirectedTradingPair, + >, /// The input value for the swap. #[prost(message, optional, tag = "2")] pub input: ::core::option::Option, @@ -1935,10 +2097,10 @@ pub mod view_service_client { dead_code, missing_docs, clippy::wildcard_imports, - clippy::let_unit_value + clippy::let_unit_value, )] - use tonic::codegen::http::Uri; use tonic::codegen::*; + use tonic::codegen::http::Uri; /// The view RPC is used by a view client, who wants to do some /// transaction-related actions, to request data from a view service, which is /// responsible for synchronizing and scanning the public chain state with one or @@ -1986,8 +2148,9 @@ pub mod view_service_client { >::ResponseBody, >, >, - >>::Error: - Into + std::marker::Send + std::marker::Sync, + , + >>::Error: Into + std::marker::Send + std::marker::Sync, { ViewServiceClient::new(InterceptedService::new(inner, interceptor)) } @@ -2027,11 +2190,18 @@ pub mod view_service_client { &mut self, request: impl tonic::IntoRequest, ) -> std::result::Result, tonic::Status> { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static("/penumbra.view.v1.ViewService/Status"); + let path = http::uri::PathAndQuery::from_static( + "/penumbra.view.v1.ViewService/Status", + ); let mut req = request.into_request(); req.extensions_mut() .insert(GrpcMethod::new("penumbra.view.v1.ViewService", "Status")); @@ -2046,17 +2216,21 @@ pub mod view_service_client { tonic::Response>, tonic::Status, > { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = - http::uri::PathAndQuery::from_static("/penumbra.view.v1.ViewService/StatusStream"); + let path = http::uri::PathAndQuery::from_static( + "/penumbra.view.v1.ViewService/StatusStream", + ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new( - "penumbra.view.v1.ViewService", - "StatusStream", - )); + req.extensions_mut() + .insert(GrpcMethod::new("penumbra.view.v1.ViewService", "StatusStream")); self.inner.server_streaming(req, path, codec).await } /// Queries for notes that have been accepted by the chain. @@ -2068,11 +2242,18 @@ pub mod view_service_client { tonic::Response>, tonic::Status, > { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static("/penumbra.view.v1.ViewService/Notes"); + let path = http::uri::PathAndQuery::from_static( + "/penumbra.view.v1.ViewService/Notes", + ); let mut req = request.into_request(); req.extensions_mut() .insert(GrpcMethod::new("penumbra.view.v1.ViewService", "Notes")); @@ -2086,18 +2267,23 @@ pub mod view_service_client { tonic::Response>, tonic::Status, > { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/NotesForVoting", ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new( - "penumbra.view.v1.ViewService", - "NotesForVoting", - )); + req.extensions_mut() + .insert( + GrpcMethod::new("penumbra.view.v1.ViewService", "NotesForVoting"), + ); self.inner.server_streaming(req, path, codec).await } /// Queries for metadata about known assets. @@ -2109,11 +2295,18 @@ pub mod view_service_client { tonic::Response>, tonic::Status, > { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static("/penumbra.view.v1.ViewService/Assets"); + let path = http::uri::PathAndQuery::from_static( + "/penumbra.view.v1.ViewService/Assets", + ); let mut req = request.into_request(); req.extensions_mut() .insert(GrpcMethod::new("penumbra.view.v1.ViewService", "Assets")); @@ -2127,52 +2320,76 @@ pub mod view_service_client { pub async fn asset_metadata_by_id( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result, tonic::Status> - { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/AssetMetadataById", ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new( - "penumbra.view.v1.ViewService", - "AssetMetadataById", - )); + req.extensions_mut() + .insert( + GrpcMethod::new("penumbra.view.v1.ViewService", "AssetMetadataById"), + ); self.inner.unary(req, path, codec).await } /// Query for the current app parameters. pub async fn app_parameters( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result, tonic::Status> - { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = - http::uri::PathAndQuery::from_static("/penumbra.view.v1.ViewService/AppParameters"); + let path = http::uri::PathAndQuery::from_static( + "/penumbra.view.v1.ViewService/AppParameters", + ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new( - "penumbra.view.v1.ViewService", - "AppParameters", - )); + req.extensions_mut() + .insert( + GrpcMethod::new("penumbra.view.v1.ViewService", "AppParameters"), + ); self.inner.unary(req, path, codec).await } /// Query for the current gas prices. pub async fn gas_prices( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result, tonic::Status> { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = - http::uri::PathAndQuery::from_static("/penumbra.view.v1.ViewService/GasPrices"); + let path = http::uri::PathAndQuery::from_static( + "/penumbra.view.v1.ViewService/GasPrices", + ); let mut req = request.into_request(); req.extensions_mut() .insert(GrpcMethod::new("penumbra.view.v1.ViewService", "GasPrices")); @@ -2182,72 +2399,103 @@ pub mod view_service_client { pub async fn fmd_parameters( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result, tonic::Status> - { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = - http::uri::PathAndQuery::from_static("/penumbra.view.v1.ViewService/FMDParameters"); + let path = http::uri::PathAndQuery::from_static( + "/penumbra.view.v1.ViewService/FMDParameters", + ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new( - "penumbra.view.v1.ViewService", - "FMDParameters", - )); + req.extensions_mut() + .insert( + GrpcMethod::new("penumbra.view.v1.ViewService", "FMDParameters"), + ); self.inner.unary(req, path, codec).await } /// Query for an address given an address index pub async fn address_by_index( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result, tonic::Status> - { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/AddressByIndex", ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new( - "penumbra.view.v1.ViewService", - "AddressByIndex", - )); + req.extensions_mut() + .insert( + GrpcMethod::new("penumbra.view.v1.ViewService", "AddressByIndex"), + ); self.inner.unary(req, path, codec).await } /// Returns the transparent address for the user's wallet. pub async fn transparent_address( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result, tonic::Status> - { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/TransparentAddress", ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new( - "penumbra.view.v1.ViewService", - "TransparentAddress", - )); + req.extensions_mut() + .insert( + GrpcMethod::new("penumbra.view.v1.ViewService", "TransparentAddress"), + ); self.inner.unary(req, path, codec).await } /// Query for wallet id pub async fn wallet_id( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result, tonic::Status> { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = - http::uri::PathAndQuery::from_static("/penumbra.view.v1.ViewService/WalletId"); + let path = http::uri::PathAndQuery::from_static( + "/penumbra.view.v1.ViewService/WalletId", + ); let mut req = request.into_request(); req.extensions_mut() .insert(GrpcMethod::new("penumbra.view.v1.ViewService", "WalletId")); @@ -2257,40 +2505,54 @@ pub mod view_service_client { pub async fn index_by_address( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result, tonic::Status> - { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/IndexByAddress", ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new( - "penumbra.view.v1.ViewService", - "IndexByAddress", - )); + req.extensions_mut() + .insert( + GrpcMethod::new("penumbra.view.v1.ViewService", "IndexByAddress"), + ); self.inner.unary(req, path, codec).await } /// Query for an ephemeral address pub async fn ephemeral_address( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result, tonic::Status> - { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/EphemeralAddress", ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new( - "penumbra.view.v1.ViewService", - "EphemeralAddress", - )); + req.extensions_mut() + .insert( + GrpcMethod::new("penumbra.view.v1.ViewService", "EphemeralAddress"), + ); self.inner.unary(req, path, codec).await } /// Query for balance of a given address. @@ -2302,12 +2564,18 @@ pub mod view_service_client { tonic::Response>, tonic::Status, > { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = - http::uri::PathAndQuery::from_static("/penumbra.view.v1.ViewService/Balances"); + let path = http::uri::PathAndQuery::from_static( + "/penumbra.view.v1.ViewService/Balances", + ); let mut req = request.into_request(); req.extensions_mut() .insert(GrpcMethod::new("penumbra.view.v1.ViewService", "Balances")); @@ -2317,40 +2585,54 @@ pub mod view_service_client { pub async fn note_by_commitment( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result, tonic::Status> - { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/NoteByCommitment", ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new( - "penumbra.view.v1.ViewService", - "NoteByCommitment", - )); + req.extensions_mut() + .insert( + GrpcMethod::new("penumbra.view.v1.ViewService", "NoteByCommitment"), + ); self.inner.unary(req, path, codec).await } /// Query for a swap by its swap commitment, optionally waiting until the swap is detected. pub async fn swap_by_commitment( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result, tonic::Status> - { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/SwapByCommitment", ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new( - "penumbra.view.v1.ViewService", - "SwapByCommitment", - )); + req.extensions_mut() + .insert( + GrpcMethod::new("penumbra.view.v1.ViewService", "SwapByCommitment"), + ); self.inner.unary(req, path, codec).await } /// Query for all unclaimed swaps. @@ -2361,58 +2643,80 @@ pub mod view_service_client { tonic::Response>, tonic::Status, > { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/UnclaimedSwaps", ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new( - "penumbra.view.v1.ViewService", - "UnclaimedSwaps", - )); + req.extensions_mut() + .insert( + GrpcMethod::new("penumbra.view.v1.ViewService", "UnclaimedSwaps"), + ); self.inner.server_streaming(req, path, codec).await } /// Query for whether a nullifier has been spent, optionally waiting until it is spent. pub async fn nullifier_status( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result, tonic::Status> - { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/NullifierStatus", ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new( - "penumbra.view.v1.ViewService", - "NullifierStatus", - )); + req.extensions_mut() + .insert( + GrpcMethod::new("penumbra.view.v1.ViewService", "NullifierStatus"), + ); self.inner.unary(req, path, codec).await } /// Query for a given transaction by its hash. pub async fn transaction_info_by_hash( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result, tonic::Status> - { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/TransactionInfoByHash", ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new( - "penumbra.view.v1.ViewService", - "TransactionInfoByHash", - )); + req.extensions_mut() + .insert( + GrpcMethod::new( + "penumbra.view.v1.ViewService", + "TransactionInfoByHash", + ), + ); self.inner.unary(req, path, codec).await } /// Query for the full transactions in the given range of blocks. @@ -2424,18 +2728,23 @@ pub mod view_service_client { tonic::Response>, tonic::Status, > { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/TransactionInfo", ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new( - "penumbra.view.v1.ViewService", - "TransactionInfo", - )); + req.extensions_mut() + .insert( + GrpcMethod::new("penumbra.view.v1.ViewService", "TransactionInfo"), + ); self.inner.server_streaming(req, path, codec).await } /// Query for owned position IDs for the given trading pair and in the given position state. @@ -2446,38 +2755,50 @@ pub mod view_service_client { tonic::Response>, tonic::Status, > { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/OwnedPositionIds", ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new( - "penumbra.view.v1.ViewService", - "OwnedPositionIds", - )); + req.extensions_mut() + .insert( + GrpcMethod::new("penumbra.view.v1.ViewService", "OwnedPositionIds"), + ); self.inner.server_streaming(req, path, codec).await } /// Translates a high-level intent ("send X funds to Y address") into a complete transaction plan. pub async fn transaction_planner( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result, tonic::Status> - { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/TransactionPlanner", ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new( - "penumbra.view.v1.ViewService", - "TransactionPlanner", - )); + req.extensions_mut() + .insert( + GrpcMethod::new("penumbra.view.v1.ViewService", "TransactionPlanner"), + ); self.inner.unary(req, path, codec).await } /// Returns authentication data for the given transaction plan. @@ -2489,13 +2810,22 @@ pub mod view_service_client { pub async fn witness( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result, tonic::Status> { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = - http::uri::PathAndQuery::from_static("/penumbra.view.v1.ViewService/Witness"); + let path = http::uri::PathAndQuery::from_static( + "/penumbra.view.v1.ViewService/Witness", + ); let mut req = request.into_request(); req.extensions_mut() .insert(GrpcMethod::new("penumbra.view.v1.ViewService", "Witness")); @@ -2515,18 +2845,23 @@ pub mod view_service_client { tonic::Response>, tonic::Status, > { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/WitnessAndBuild", ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new( - "penumbra.view.v1.ViewService", - "WitnessAndBuild", - )); + req.extensions_mut() + .insert( + GrpcMethod::new("penumbra.view.v1.ViewService", "WitnessAndBuild"), + ); self.inner.server_streaming(req, path, codec).await } /// Authorize a transaction plan and build the transaction. @@ -2547,18 +2882,23 @@ pub mod view_service_client { tonic::Response>, tonic::Status, > { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/AuthorizeAndBuild", ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new( - "penumbra.view.v1.ViewService", - "AuthorizeAndBuild", - )); + req.extensions_mut() + .insert( + GrpcMethod::new("penumbra.view.v1.ViewService", "AuthorizeAndBuild"), + ); self.inner.server_streaming(req, path, codec).await } /// Broadcast a transaction to the network, optionally waiting for full confirmation. @@ -2568,21 +2908,31 @@ pub mod view_service_client { &mut self, request: impl tonic::IntoRequest, ) -> std::result::Result< - tonic::Response>, + tonic::Response< + tonic::codec::Streaming, + >, tonic::Status, > { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/BroadcastTransaction", ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new( - "penumbra.view.v1.ViewService", - "BroadcastTransaction", - )); + req.extensions_mut() + .insert( + GrpcMethod::new( + "penumbra.view.v1.ViewService", + "BroadcastTransaction", + ), + ); self.inner.server_streaming(req, path, codec).await } /// Get delegation tokens for a given address index. Each delegation token will @@ -2593,21 +2943,31 @@ pub mod view_service_client { &mut self, request: impl tonic::IntoRequest, ) -> std::result::Result< - tonic::Response>, + tonic::Response< + tonic::codec::Streaming, + >, tonic::Status, > { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/DelegationsByAddressIndex", ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new( - "penumbra.view.v1.ViewService", - "DelegationsByAddressIndex", - )); + req.extensions_mut() + .insert( + GrpcMethod::new( + "penumbra.view.v1.ViewService", + "DelegationsByAddressIndex", + ), + ); self.inner.server_streaming(req, path, codec).await } /// Get unbonding tokens for the given address index, optionally filtered by @@ -2616,21 +2976,31 @@ pub mod view_service_client { &mut self, request: impl tonic::IntoRequest, ) -> std::result::Result< - tonic::Response>, + tonic::Response< + tonic::codec::Streaming, + >, tonic::Status, > { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/UnbondingTokensByAddressIndex", ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new( - "penumbra.view.v1.ViewService", - "UnbondingTokensByAddressIndex", - )); + req.extensions_mut() + .insert( + GrpcMethod::new( + "penumbra.view.v1.ViewService", + "UnbondingTokensByAddressIndex", + ), + ); self.inner.server_streaming(req, path, codec).await } /// Gets the auctions controlled by the user's wallet. @@ -2641,12 +3011,18 @@ pub mod view_service_client { tonic::Response>, tonic::Status, > { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = - http::uri::PathAndQuery::from_static("/penumbra.view.v1.ViewService/Auctions"); + let path = http::uri::PathAndQuery::from_static( + "/penumbra.view.v1.ViewService/Auctions", + ); let mut req = request.into_request(); req.extensions_mut() .insert(GrpcMethod::new("penumbra.view.v1.ViewService", "Auctions")); @@ -2660,37 +3036,48 @@ pub mod view_service_client { tonic::Response>, tonic::Status, > { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = - http::uri::PathAndQuery::from_static("/penumbra.view.v1.ViewService/LatestSwaps"); + let path = http::uri::PathAndQuery::from_static( + "/penumbra.view.v1.ViewService/LatestSwaps", + ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new( - "penumbra.view.v1.ViewService", - "LatestSwaps", - )); + req.extensions_mut() + .insert(GrpcMethod::new("penumbra.view.v1.ViewService", "LatestSwaps")); self.inner.server_streaming(req, path, codec).await } /// Gets details on the list votes cast in the current epoch for incentivized assets. pub async fn tournament_votes( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result, tonic::Status> - { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/TournamentVotes", ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new( - "penumbra.view.v1.ViewService", - "TournamentVotes", - )); + req.extensions_mut() + .insert( + GrpcMethod::new("penumbra.view.v1.ViewService", "TournamentVotes"), + ); self.inner.unary(req, path, codec).await } /// Gets the spendable note records that are eligible for voting in the current epoch. @@ -2701,18 +3088,23 @@ pub mod view_service_client { tonic::Response>, tonic::Status, > { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/penumbra.view.v1.ViewService/LqtVotingNotes", ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new( - "penumbra.view.v1.ViewService", - "LqtVotingNotes", - )); + req.extensions_mut() + .insert( + GrpcMethod::new("penumbra.view.v1.ViewService", "LqtVotingNotes"), + ); self.inner.server_streaming(req, path, codec).await } } @@ -2725,7 +3117,7 @@ pub mod view_service_server { dead_code, missing_docs, clippy::wildcard_imports, - clippy::let_unit_value + clippy::let_unit_value, )] use tonic::codegen::*; /// Generated trait containing gRPC methods that should be implemented for use with ViewServiceServer. @@ -2739,18 +3131,23 @@ pub mod view_service_server { /// Server streaming response type for the StatusStream method. type StatusStreamStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > + std::marker::Send + > + + std::marker::Send + 'static; /// Stream sync status updates until the view service has caught up with the chain. /// Returns a stream of `StatusStreamResponse`s. async fn status_stream( &self, request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Server streaming response type for the Notes method. type NotesStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > + std::marker::Send + > + + std::marker::Send + 'static; /// Queries for notes that have been accepted by the chain. /// Returns a stream of `NotesResponse`s. @@ -2761,17 +3158,22 @@ pub mod view_service_server { /// Server streaming response type for the NotesForVoting method. type NotesForVotingStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > + std::marker::Send + > + + std::marker::Send + 'static; /// Returns a stream of `NotesForVotingResponse`s. async fn notes_for_voting( &self, request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Server streaming response type for the Assets method. type AssetsStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > + std::marker::Send + > + + std::marker::Send + 'static; /// Queries for metadata about known assets. /// Returns a stream of `AssetsResponse`s. @@ -2787,51 +3189,79 @@ pub mod view_service_server { async fn asset_metadata_by_id( &self, request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Query for the current app parameters. async fn app_parameters( &self, request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Query for the current gas prices. async fn gas_prices( &self, request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Query for the current FMD parameters. async fn fmd_parameters( &self, request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Query for an address given an address index async fn address_by_index( &self, request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Returns the transparent address for the user's wallet. async fn transparent_address( &self, request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Query for wallet id async fn wallet_id( &self, request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Query for an address given an address index async fn index_by_address( &self, request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Query for an ephemeral address async fn ephemeral_address( &self, request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Server streaming response type for the Balances method. type BalancesStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > + std::marker::Send + > + + std::marker::Send + 'static; /// Query for balance of a given address. /// Returns a stream of `BalancesResponses`. @@ -2843,58 +3273,88 @@ pub mod view_service_server { async fn note_by_commitment( &self, request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Query for a swap by its swap commitment, optionally waiting until the swap is detected. async fn swap_by_commitment( &self, request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Server streaming response type for the UnclaimedSwaps method. type UnclaimedSwapsStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > + std::marker::Send + > + + std::marker::Send + 'static; /// Query for all unclaimed swaps. async fn unclaimed_swaps( &self, request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Query for whether a nullifier has been spent, optionally waiting until it is spent. async fn nullifier_status( &self, request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Query for a given transaction by its hash. async fn transaction_info_by_hash( &self, request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Server streaming response type for the TransactionInfo method. type TransactionInfoStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > + std::marker::Send + > + + std::marker::Send + 'static; /// Query for the full transactions in the given range of blocks. /// Returns a stream of `TransactionInfoResponse`s. async fn transaction_info( &self, request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Server streaming response type for the OwnedPositionIds method. type OwnedPositionIdsStream: tonic::codegen::tokio_stream::Stream< - Item = std::result::Result, - > + std::marker::Send + Item = std::result::Result< + super::OwnedPositionIdsResponse, + tonic::Status, + >, + > + + std::marker::Send + 'static; /// Query for owned position IDs for the given trading pair and in the given position state. async fn owned_position_ids( &self, request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Translates a high-level intent ("send X funds to Y address") into a complete transaction plan. async fn transaction_planner( &self, request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Returns authentication data for the given transaction plan. /// /// This method takes a complete transaction plan, so that the client can get a @@ -2908,7 +3368,8 @@ pub mod view_service_server { /// Server streaming response type for the WitnessAndBuild method. type WitnessAndBuildStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > + std::marker::Send + > + + std::marker::Send + 'static; /// Like `Witness`, but immediately uses the witness data to build (prove) the transaction. /// @@ -2920,11 +3381,18 @@ pub mod view_service_server { async fn witness_and_build( &self, request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Server streaming response type for the AuthorizeAndBuild method. type AuthorizeAndBuildStream: tonic::codegen::tokio_stream::Stream< - Item = std::result::Result, - > + std::marker::Send + Item = std::result::Result< + super::AuthorizeAndBuildResponse, + tonic::Status, + >, + > + + std::marker::Send + 'static; /// Authorize a transaction plan and build the transaction. /// @@ -2940,11 +3408,18 @@ pub mod view_service_server { async fn authorize_and_build( &self, request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Server streaming response type for the BroadcastTransaction method. type BroadcastTransactionStream: tonic::codegen::tokio_stream::Stream< - Item = std::result::Result, - > + std::marker::Send + Item = std::result::Result< + super::BroadcastTransactionResponse, + tonic::Status, + >, + > + + std::marker::Send + 'static; /// Broadcast a transaction to the network, optionally waiting for full confirmation. /// @@ -2952,11 +3427,18 @@ pub mod view_service_server { async fn broadcast_transaction( &self, request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Server streaming response type for the DelegationsByAddressIndex method. type DelegationsByAddressIndexStream: tonic::codegen::tokio_stream::Stream< - Item = std::result::Result, - > + std::marker::Send + Item = std::result::Result< + super::DelegationsByAddressIndexResponse, + tonic::Status, + >, + > + + std::marker::Send + 'static; /// Get delegation tokens for a given address index. Each delegation token will /// be represented by a `ValueView` with the given address index's balance of @@ -2975,7 +3457,8 @@ pub mod view_service_server { super::UnbondingTokensByAddressIndexResponse, tonic::Status, >, - > + std::marker::Send + > + + std::marker::Send + 'static; /// Get unbonding tokens for the given address index, optionally filtered by /// whether the tokens are currently claimable. @@ -2989,7 +3472,8 @@ pub mod view_service_server { /// Server streaming response type for the Auctions method. type AuctionsStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > + std::marker::Send + > + + std::marker::Send + 'static; /// Gets the auctions controlled by the user's wallet. async fn auctions( @@ -2999,28 +3483,39 @@ pub mod view_service_server { /// Server streaming response type for the LatestSwaps method. type LatestSwapsStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > + std::marker::Send + > + + std::marker::Send + 'static; /// Gets the latest swaps controlled by the user's wallet. async fn latest_swaps( &self, request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Gets details on the list votes cast in the current epoch for incentivized assets. async fn tournament_votes( &self, request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Server streaming response type for the LqtVotingNotes method. type LqtVotingNotesStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > + std::marker::Send + > + + std::marker::Send + 'static; /// Gets the spendable note records that are eligible for voting in the current epoch. async fn lqt_voting_notes( &self, request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; } /// The view RPC is used by a view client, who wants to do some /// transaction-related actions, to request data from a view service, which is @@ -3047,7 +3542,10 @@ pub mod view_service_server { max_encoding_message_size: None, } } - pub fn with_interceptor(inner: T, interceptor: F) -> InterceptedService + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> InterceptedService where F: tonic::service::Interceptor, { @@ -3102,16 +3600,23 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/Status" => { #[allow(non_camel_case_types)] struct StatusSvc(pub Arc); - impl tonic::server::UnaryService for StatusSvc { + impl< + T: ViewService, + > tonic::server::UnaryService + for StatusSvc { type Response = super::StatusResponse; - type Future = BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); - let fut = - async move { ::status(&inner, request).await }; + let fut = async move { + ::status(&inner, request).await + }; Box::pin(fut) } } @@ -3140,14 +3645,16 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/StatusStream" => { #[allow(non_camel_case_types)] struct StatusStreamSvc(pub Arc); - impl - tonic::server::ServerStreamingService - for StatusStreamSvc - { + impl< + T: ViewService, + > tonic::server::ServerStreamingService + for StatusStreamSvc { type Response = super::StatusStreamResponse; type ResponseStream = T::StatusStreamStream; - type Future = - BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, @@ -3184,18 +3691,24 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/Notes" => { #[allow(non_camel_case_types)] struct NotesSvc(pub Arc); - impl tonic::server::ServerStreamingService for NotesSvc { + impl< + T: ViewService, + > tonic::server::ServerStreamingService + for NotesSvc { type Response = super::NotesResponse; type ResponseStream = T::NotesStream; - type Future = - BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); - let fut = - async move { ::notes(&inner, request).await }; + let fut = async move { + ::notes(&inner, request).await + }; Box::pin(fut) } } @@ -3224,14 +3737,16 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/NotesForVoting" => { #[allow(non_camel_case_types)] struct NotesForVotingSvc(pub Arc); - impl - tonic::server::ServerStreamingService - for NotesForVotingSvc - { + impl< + T: ViewService, + > tonic::server::ServerStreamingService + for NotesForVotingSvc { type Response = super::NotesForVotingResponse; type ResponseStream = T::NotesForVotingStream; - type Future = - BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, @@ -3268,18 +3783,24 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/Assets" => { #[allow(non_camel_case_types)] struct AssetsSvc(pub Arc); - impl tonic::server::ServerStreamingService for AssetsSvc { + impl< + T: ViewService, + > tonic::server::ServerStreamingService + for AssetsSvc { type Response = super::AssetsResponse; type ResponseStream = T::AssetsStream; - type Future = - BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); - let fut = - async move { ::assets(&inner, request).await }; + let fut = async move { + ::assets(&inner, request).await + }; Box::pin(fut) } } @@ -3308,19 +3829,23 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/AssetMetadataById" => { #[allow(non_camel_case_types)] struct AssetMetadataByIdSvc(pub Arc); - impl - tonic::server::UnaryService - for AssetMetadataByIdSvc - { + impl< + T: ViewService, + > tonic::server::UnaryService + for AssetMetadataByIdSvc { type Response = super::AssetMetadataByIdResponse; - type Future = BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::asset_metadata_by_id(&inner, request).await + ::asset_metadata_by_id(&inner, request) + .await }; Box::pin(fut) } @@ -3350,11 +3875,15 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/AppParameters" => { #[allow(non_camel_case_types)] struct AppParametersSvc(pub Arc); - impl tonic::server::UnaryService - for AppParametersSvc - { + impl< + T: ViewService, + > tonic::server::UnaryService + for AppParametersSvc { type Response = super::AppParametersResponse; - type Future = BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, @@ -3391,9 +3920,15 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/GasPrices" => { #[allow(non_camel_case_types)] struct GasPricesSvc(pub Arc); - impl tonic::server::UnaryService for GasPricesSvc { + impl< + T: ViewService, + > tonic::server::UnaryService + for GasPricesSvc { type Response = super::GasPricesResponse; - type Future = BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, @@ -3430,11 +3965,15 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/FMDParameters" => { #[allow(non_camel_case_types)] struct FMDParametersSvc(pub Arc); - impl tonic::server::UnaryService - for FMDParametersSvc - { + impl< + T: ViewService, + > tonic::server::UnaryService + for FMDParametersSvc { type Response = super::FmdParametersResponse; - type Future = BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, @@ -3471,11 +4010,15 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/AddressByIndex" => { #[allow(non_camel_case_types)] struct AddressByIndexSvc(pub Arc); - impl tonic::server::UnaryService - for AddressByIndexSvc - { + impl< + T: ViewService, + > tonic::server::UnaryService + for AddressByIndexSvc { type Response = super::AddressByIndexResponse; - type Future = BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, @@ -3512,19 +4055,23 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/TransparentAddress" => { #[allow(non_camel_case_types)] struct TransparentAddressSvc(pub Arc); - impl - tonic::server::UnaryService - for TransparentAddressSvc - { + impl< + T: ViewService, + > tonic::server::UnaryService + for TransparentAddressSvc { type Response = super::TransparentAddressResponse; - type Future = BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::transparent_address(&inner, request).await + ::transparent_address(&inner, request) + .await }; Box::pin(fut) } @@ -3554,16 +4101,23 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/WalletId" => { #[allow(non_camel_case_types)] struct WalletIdSvc(pub Arc); - impl tonic::server::UnaryService for WalletIdSvc { + impl< + T: ViewService, + > tonic::server::UnaryService + for WalletIdSvc { type Response = super::WalletIdResponse; - type Future = BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); - let fut = - async move { ::wallet_id(&inner, request).await }; + let fut = async move { + ::wallet_id(&inner, request).await + }; Box::pin(fut) } } @@ -3592,11 +4146,15 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/IndexByAddress" => { #[allow(non_camel_case_types)] struct IndexByAddressSvc(pub Arc); - impl tonic::server::UnaryService - for IndexByAddressSvc - { + impl< + T: ViewService, + > tonic::server::UnaryService + for IndexByAddressSvc { type Response = super::IndexByAddressResponse; - type Future = BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, @@ -3633,11 +4191,15 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/EphemeralAddress" => { #[allow(non_camel_case_types)] struct EphemeralAddressSvc(pub Arc); - impl tonic::server::UnaryService - for EphemeralAddressSvc - { + impl< + T: ViewService, + > tonic::server::UnaryService + for EphemeralAddressSvc { type Response = super::EphemeralAddressResponse; - type Future = BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, @@ -3674,21 +4236,24 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/Balances" => { #[allow(non_camel_case_types)] struct BalancesSvc(pub Arc); - impl - tonic::server::ServerStreamingService - for BalancesSvc - { + impl< + T: ViewService, + > tonic::server::ServerStreamingService + for BalancesSvc { type Response = super::BalancesResponse; type ResponseStream = T::BalancesStream; - type Future = - BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); - let fut = - async move { ::balances(&inner, request).await }; + let fut = async move { + ::balances(&inner, request).await + }; Box::pin(fut) } } @@ -3717,18 +4282,23 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/NoteByCommitment" => { #[allow(non_camel_case_types)] struct NoteByCommitmentSvc(pub Arc); - impl tonic::server::UnaryService - for NoteByCommitmentSvc - { + impl< + T: ViewService, + > tonic::server::UnaryService + for NoteByCommitmentSvc { type Response = super::NoteByCommitmentResponse; - type Future = BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::note_by_commitment(&inner, request).await + ::note_by_commitment(&inner, request) + .await }; Box::pin(fut) } @@ -3758,18 +4328,23 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/SwapByCommitment" => { #[allow(non_camel_case_types)] struct SwapByCommitmentSvc(pub Arc); - impl tonic::server::UnaryService - for SwapByCommitmentSvc - { + impl< + T: ViewService, + > tonic::server::UnaryService + for SwapByCommitmentSvc { type Response = super::SwapByCommitmentResponse; - type Future = BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::swap_by_commitment(&inner, request).await + ::swap_by_commitment(&inner, request) + .await }; Box::pin(fut) } @@ -3799,14 +4374,16 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/UnclaimedSwaps" => { #[allow(non_camel_case_types)] struct UnclaimedSwapsSvc(pub Arc); - impl - tonic::server::ServerStreamingService - for UnclaimedSwapsSvc - { + impl< + T: ViewService, + > tonic::server::ServerStreamingService + for UnclaimedSwapsSvc { type Response = super::UnclaimedSwapsResponse; type ResponseStream = T::UnclaimedSwapsStream; - type Future = - BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, @@ -3843,11 +4420,15 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/NullifierStatus" => { #[allow(non_camel_case_types)] struct NullifierStatusSvc(pub Arc); - impl tonic::server::UnaryService - for NullifierStatusSvc - { + impl< + T: ViewService, + > tonic::server::UnaryService + for NullifierStatusSvc { type Response = super::NullifierStatusResponse; - type Future = BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, @@ -3884,19 +4465,26 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/TransactionInfoByHash" => { #[allow(non_camel_case_types)] struct TransactionInfoByHashSvc(pub Arc); - impl - tonic::server::UnaryService - for TransactionInfoByHashSvc - { + impl< + T: ViewService, + > tonic::server::UnaryService + for TransactionInfoByHashSvc { type Response = super::TransactionInfoByHashResponse; - type Future = BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::transaction_info_by_hash(&inner, request).await + ::transaction_info_by_hash( + &inner, + request, + ) + .await }; Box::pin(fut) } @@ -3926,14 +4514,17 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/TransactionInfo" => { #[allow(non_camel_case_types)] struct TransactionInfoSvc(pub Arc); - impl - tonic::server::ServerStreamingService - for TransactionInfoSvc - { + impl< + T: ViewService, + > tonic::server::ServerStreamingService< + super::TransactionInfoRequest, + > for TransactionInfoSvc { type Response = super::TransactionInfoResponse; type ResponseStream = T::TransactionInfoStream; - type Future = - BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, @@ -3970,21 +4561,25 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/OwnedPositionIds" => { #[allow(non_camel_case_types)] struct OwnedPositionIdsSvc(pub Arc); - impl - tonic::server::ServerStreamingService - for OwnedPositionIdsSvc - { + impl< + T: ViewService, + > tonic::server::ServerStreamingService< + super::OwnedPositionIdsRequest, + > for OwnedPositionIdsSvc { type Response = super::OwnedPositionIdsResponse; type ResponseStream = T::OwnedPositionIdsStream; - type Future = - BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::owned_position_ids(&inner, request).await + ::owned_position_ids(&inner, request) + .await }; Box::pin(fut) } @@ -4014,19 +4609,23 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/TransactionPlanner" => { #[allow(non_camel_case_types)] struct TransactionPlannerSvc(pub Arc); - impl - tonic::server::UnaryService - for TransactionPlannerSvc - { + impl< + T: ViewService, + > tonic::server::UnaryService + for TransactionPlannerSvc { type Response = super::TransactionPlannerResponse; - type Future = BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::transaction_planner(&inner, request).await + ::transaction_planner(&inner, request) + .await }; Box::pin(fut) } @@ -4056,16 +4655,23 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/Witness" => { #[allow(non_camel_case_types)] struct WitnessSvc(pub Arc); - impl tonic::server::UnaryService for WitnessSvc { + impl< + T: ViewService, + > tonic::server::UnaryService + for WitnessSvc { type Response = super::WitnessResponse; - type Future = BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); - let fut = - async move { ::witness(&inner, request).await }; + let fut = async move { + ::witness(&inner, request).await + }; Box::pin(fut) } } @@ -4094,14 +4700,17 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/WitnessAndBuild" => { #[allow(non_camel_case_types)] struct WitnessAndBuildSvc(pub Arc); - impl - tonic::server::ServerStreamingService - for WitnessAndBuildSvc - { + impl< + T: ViewService, + > tonic::server::ServerStreamingService< + super::WitnessAndBuildRequest, + > for WitnessAndBuildSvc { type Response = super::WitnessAndBuildResponse; type ResponseStream = T::WitnessAndBuildStream; - type Future = - BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, @@ -4138,21 +4747,25 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/AuthorizeAndBuild" => { #[allow(non_camel_case_types)] struct AuthorizeAndBuildSvc(pub Arc); - impl - tonic::server::ServerStreamingService - for AuthorizeAndBuildSvc - { + impl< + T: ViewService, + > tonic::server::ServerStreamingService< + super::AuthorizeAndBuildRequest, + > for AuthorizeAndBuildSvc { type Response = super::AuthorizeAndBuildResponse; type ResponseStream = T::AuthorizeAndBuildStream; - type Future = - BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::authorize_and_build(&inner, request).await + ::authorize_and_build(&inner, request) + .await }; Box::pin(fut) } @@ -4182,21 +4795,25 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/BroadcastTransaction" => { #[allow(non_camel_case_types)] struct BroadcastTransactionSvc(pub Arc); - impl - tonic::server::ServerStreamingService - for BroadcastTransactionSvc - { + impl< + T: ViewService, + > tonic::server::ServerStreamingService< + super::BroadcastTransactionRequest, + > for BroadcastTransactionSvc { type Response = super::BroadcastTransactionResponse; type ResponseStream = T::BroadcastTransactionStream; - type Future = - BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::broadcast_transaction(&inner, request).await + ::broadcast_transaction(&inner, request) + .await }; Box::pin(fut) } @@ -4226,22 +4843,29 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/DelegationsByAddressIndex" => { #[allow(non_camel_case_types)] struct DelegationsByAddressIndexSvc(pub Arc); - impl - tonic::server::ServerStreamingService< - super::DelegationsByAddressIndexRequest, - > for DelegationsByAddressIndexSvc - { + impl< + T: ViewService, + > tonic::server::ServerStreamingService< + super::DelegationsByAddressIndexRequest, + > for DelegationsByAddressIndexSvc { type Response = super::DelegationsByAddressIndexResponse; type ResponseStream = T::DelegationsByAddressIndexStream; - type Future = - BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, - request: tonic::Request, + request: tonic::Request< + super::DelegationsByAddressIndexRequest, + >, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::delegations_by_address_index(&inner, request) + ::delegations_by_address_index( + &inner, + request, + ) .await }; Box::pin(fut) @@ -4272,25 +4896,30 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/UnbondingTokensByAddressIndex" => { #[allow(non_camel_case_types)] struct UnbondingTokensByAddressIndexSvc(pub Arc); - impl - tonic::server::ServerStreamingService< - super::UnbondingTokensByAddressIndexRequest, - > for UnbondingTokensByAddressIndexSvc - { + impl< + T: ViewService, + > tonic::server::ServerStreamingService< + super::UnbondingTokensByAddressIndexRequest, + > for UnbondingTokensByAddressIndexSvc { type Response = super::UnbondingTokensByAddressIndexResponse; type ResponseStream = T::UnbondingTokensByAddressIndexStream; - type Future = - BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, - request: tonic::Request, + request: tonic::Request< + super::UnbondingTokensByAddressIndexRequest, + >, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { ::unbonding_tokens_by_address_index( - &inner, request, - ) - .await + &inner, + request, + ) + .await }; Box::pin(fut) } @@ -4320,21 +4949,24 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/Auctions" => { #[allow(non_camel_case_types)] struct AuctionsSvc(pub Arc); - impl - tonic::server::ServerStreamingService - for AuctionsSvc - { + impl< + T: ViewService, + > tonic::server::ServerStreamingService + for AuctionsSvc { type Response = super::AuctionsResponse; type ResponseStream = T::AuctionsStream; - type Future = - BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); - let fut = - async move { ::auctions(&inner, request).await }; + let fut = async move { + ::auctions(&inner, request).await + }; Box::pin(fut) } } @@ -4363,14 +4995,16 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/LatestSwaps" => { #[allow(non_camel_case_types)] struct LatestSwapsSvc(pub Arc); - impl - tonic::server::ServerStreamingService - for LatestSwapsSvc - { + impl< + T: ViewService, + > tonic::server::ServerStreamingService + for LatestSwapsSvc { type Response = super::LatestSwapsResponse; type ResponseStream = T::LatestSwapsStream; - type Future = - BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, @@ -4407,11 +5041,15 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/TournamentVotes" => { #[allow(non_camel_case_types)] struct TournamentVotesSvc(pub Arc); - impl tonic::server::UnaryService - for TournamentVotesSvc - { + impl< + T: ViewService, + > tonic::server::UnaryService + for TournamentVotesSvc { type Response = super::TournamentVotesResponse; - type Future = BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, @@ -4448,14 +5086,16 @@ pub mod view_service_server { "/penumbra.view.v1.ViewService/LqtVotingNotes" => { #[allow(non_camel_case_types)] struct LqtVotingNotesSvc(pub Arc); - impl - tonic::server::ServerStreamingService - for LqtVotingNotesSvc - { + impl< + T: ViewService, + > tonic::server::ServerStreamingService + for LqtVotingNotesSvc { type Response = super::LqtVotingNotesResponse; type ResponseStream = T::LqtVotingNotesStream; - type Future = - BoxFuture, tonic::Status>; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; fn call( &mut self, request: tonic::Request, @@ -4489,19 +5129,23 @@ pub mod view_service_server { }; Box::pin(fut) } - _ => Box::pin(async move { - let mut response = http::Response::new(empty_body()); - let headers = response.headers_mut(); - headers.insert( - tonic::Status::GRPC_STATUS, - (tonic::Code::Unimplemented as i32).into(), - ); - headers.insert( - http::header::CONTENT_TYPE, - tonic::metadata::GRPC_CONTENT_TYPE, - ); - Ok(response) - }), + _ => { + Box::pin(async move { + let mut response = http::Response::new(empty_body()); + let headers = response.headers_mut(); + headers + .insert( + tonic::Status::GRPC_STATUS, + (tonic::Code::Unimplemented as i32).into(), + ); + headers + .insert( + http::header::CONTENT_TYPE, + tonic::metadata::GRPC_CONTENT_TYPE, + ); + Ok(response) + }) + } } } } diff --git a/crates/proto/src/gen/proto_descriptor.bin.no_lfs b/crates/proto/src/gen/proto_descriptor.bin.no_lfs index 1ed6495312760625529d6461ff5f92fb933101d5..41b2afc5435f84b55202a712df13f07f10b08d36 100644 GIT binary patch delta 3441 zcmYM1Yiv}<6~}k~_jtXYwRf+_-t_}8%QFPxC(pzI0)_&4NJ#}KC8-kHS_&$OLuxAe zfi4L|1R8K~DqWRY$RZ8>l<;Vg%S#9(kU|R*paQBxN~lX(FwhcOMU@c!&%HC*5BuRi zXMX3LIcMh1Z2y@_JO4Ck!>0HqZ1R3DyVm30@Ie21xiukvf8hO(q%NM*D^z;*n(kMA z+ST3p%F4Cful=M}@?P+;rQ~rbr(vM)H?q!Gzgn+KbxADtOE37cKVCi1c2K$|#eD=AFnCD42 zRjCS9V!(uvsp(F}jhwN-$y$5TUU*IR1rfn9~bHsZ=1&RC7f^k zm#9C3xukVsCt@EBtpBSljc0ZuS)&%xbJ`@+7hJn0i#qz8XAaVHA5z)S6(v3QAvelN zdhSDhjQU>afyQ0H)cR-g&j$|<$=qP)A0#!?R4W~(NMns9O^Ulv+vFr2?Lupt>IfY{ zOMh_dOIg_14^-JXAkvTOu}%`{$ApP$YKTzn4!(a~rWbY>v-gPXMk-?w&rE`@Qst~e zMkhW-?6-)kl=39QnI9urN0Ug#)M5`XF65}#c*>~Sl&r}fq@uhiiS9vlgPoj>G0Gl{ z8LNIBXBb~6K0)kiF!67)v+xO$TBRAmPsViOQ{Z!WAx2FvpCXwK6Yxy}dm&RJV;GTg zl9Qaf7mr58<6H*ZYl>%b_f47hL85I*#bhZTHE6+DL-XVo>ncumAEr*TEDOIM@`yEp zEM?SfAI9^3G(-)cB)Z=;APP%$0Mcerb2up7T+@gH7&$K5p*~C}4xpt~JsGCV`W_7a zG9+_a4nihd7eeMBrp$Gc$U)3sV386n1CVLK)ghVLTEb{lF3}Q_188vdDIqz4)~RYl z7>sid1^fOkqY8(L!4gCcVagLWSc1qQ%${r4R;uMNBs$tYO6h^}F*~=E=wUR@agyj^ z%{=%qDRs6q_Yw| zin;SFs*_)69kPPyXxNE11Q$?XXB*IWUmJ3N}` zIZSbj*F?{m#W#e}sZ*^6e2MhnPkxfBfFlzib*@hh1latYI3u*u|zT*A`jHe8LC%f)at3`gk} zSwr+Pnq9OSqL+&YqE^cl$V=95Em6v7qcYQ4vR5!`nKP5Uf)`h)ny}P$S_Xr?x1_FV z5aK>Bbwmcy{;Ealhz#O~ooWUzj7pujhS*oZe{ae3%rzu^HIj}h&5dw9cw$%@8m|MD zA<02Hx(;3EBpqGH$WiL?5TS7>cz0OZ8;5{WJI7oALr7LQNn{9qrJ5KbyZ~+lw})j? z+YKOT=a>)w4U|Q9cV+nDzk&J@YChA|I&l-RyNK6M3;uUY8iLN-GWzA4CU4U!ZSo!l z8o1ZY`|8crD_6bI-MOy2DY{K*XE`|`x}zx>YZ!jCB1)z=Y*u7$d2JH86I{D3)0^(N z6>-pvBAE)ar6h6(>5TdT)2q^ndx-rf=(r;*Gxw0psU|wAGFjaZes@P&n(sSD9HgWB zt~8W%bl;TbMLMe1iEj|w;05}wEcd@bGOIo_N4MIzdJwF;D}QW!;2Oh0x_SVe4|AfV zs|Of2UQG`X8XpF4{!3;S9=a-5hs$_~vZyhXL>`*x=CP91iFdr%yI%BIF=yi)&puYN zCV`C}qC16(^`wkmY?Pe4(aS}jZ%TUI=shwiJQP_JXx-#NhiPUJ=dDT^^_?=b+Ked4 zZt`qKIi1+-@nIchWRBiuk3Bb!o1DkT&3hhx;YE)dYMS5kRAu2M%h90+IRMi&R@VyicHoXs+> z6NPOadcIB5taqEI%qmQXxJh%nNizyT%@7=LS#p5H_F|SCV2JHemMnyM<$d7cLl+@@ z<$d5KO;c$`?8jPmcv2gdpOWq=qm4{S=R3Ue=$%PP*E_sijb&-<^(1G}@E?FD(V@zP ho$K{d(Px5^Xz%9q*TP>3e+m9d`AZI@zb?~l{|CPz&`tmV delta 3309 zcmYM0U2Igx6~}k~_jtXYwY}Hl-L=h!V{9M}bPdLskUEC&;e@1(+De3`qz_FBZPQ9P zg{FO|(uI@+BEC#tE_IRR2=dZ|kBVB$hY(2i11(5^1V|8x5Z6#*K0;{}RkA?+&%HC* zhx_n9XMX3LIWu!-`p>lv{<%oyXeV)8U6JtL>jP=5#!I{SiSpUK8WeSorK;t5)j$~$QWp{>VB zM(D$e7u993mTH~YgV=|~-`$Xv@$?=f>r@XTSDRw`gKMA53*G%LGL4Mfk5o1cMajth z$W3*Uk^9j!P5mg0K<8cre>*DQ4-Srs%I^j0?8tcNt8a6X;9j)PQ_DgSS_XofqtcTf z0BY?R5E($G*-0V;m@!jzgb3AO@WX#eXJN2Ztw&@KskB8rGYGm?RdU{Go!E!iM~JJG z@+8fX`;cs)OC)XPz8`1_IVuTd)LlyUU_Vk(U6e%kBhzRHXJgE=AJdxEU*b&T>%_;1 zeHt{4Nq^yEB(4njKZShE!sMNFQb;4r6Y+dNwSX{XG&~x+#nDM zvllx_}AF~jYv6w#Ad*k#d5EvHJGu97Ha^vm*5N%Rz& z=h#SC4C;xudsHP(K#)bf?Ic_sc@!3SM2U>caLmXt@gc*`$i5=igqp=FN3Kk1h`%4Gcq%``zM~zNgN9<?SW4{lqC5 zb(8mGYj`-aDA4<^2OXA~MVyx^WwfZ2q1RSKN%mdOR+Q6;_dLFEql(NCe9z;`nzv2P zO2$y+@B;tOe2ZpMdI)1uWk1|nO$+NmW2vv2YEv^4)- zgK)rBkGGQ}%tMEUY{?Lg$URXqFvM1`xy4o)*NMV54?Dgo)6939r_3x&inu9ryD2kD zLCq92xGHHNvAt9!4NS2;s*;T`kG!28cDoGWBX6gdG>b|%Vg)U`JgE=cPs#9<(MG0Z z@LgVI^vtAW=v`i}&a!m&d6Khe_~7>>`Um8~mFx3T(LaEaXrGtKzL9uqeeZ92JJg>S esK&R}u6ujSl&^$e8NUR-a(>C;l&>ltxBnjlezK(i diff --git a/proto/penumbra/penumbra/core/transaction/v1/transaction.proto b/proto/penumbra/penumbra/core/transaction/v1/transaction.proto index f0ac40cc9b..8598863518 100644 --- a/proto/penumbra/penumbra/core/transaction/v1/transaction.proto +++ b/proto/penumbra/penumbra/core/transaction/v1/transaction.proto @@ -262,6 +262,8 @@ message AuthorizationData { // The required delegator vote authorizations, returned in the same order as the // DelegatorVote actions in the original request. repeated crypto.decaf377_rdsa.v1.SpendAuthSignature delegator_vote_auths = 3; + // The required LQT vote authorizations, in the same order as the original request. + repeated crypto.decaf377_rdsa.v1.SpendAuthSignature lqt_vote_auths = 4; } // The data required for proving when building a transaction from a plan.