From 873b1c7147e97664539d1836ccb28ab54a801d39 Mon Sep 17 00:00:00 2001 From: Lucas Meier Date: Thu, 18 Apr 2024 14:55:50 -0700 Subject: [PATCH] Make swap_claim check the exact epoch and block in circuit --- crates/bench/benches/swap_claim.rs | 1 + crates/bin/pcli/tests/proof.rs | 1 + .../dex/src/batch_swap_output_data.rs | 47 ++++++++++-------- .../src/component/circuit_breaker/value.rs | 12 ++++- .../core/component/dex/src/component/dex.rs | 2 +- .../src/component/router/route_and_fill.rs | 21 ++++---- .../dex/src/component/router/tests.rs | 23 ++++++++- .../core/component/dex/src/component/tests.rs | 24 ++++++++- .../component/dex/src/swap_claim/proof.rs | 31 ++++++++---- .../proof-params/src/gen/swapclaim_id.rs | 4 +- .../proof-params/src/gen/swapclaim_pk.bin | 4 +- .../proof-params/src/gen/swapclaim_vk.param | Bin 2888 -> 8840 bytes .../src/gen/penumbra.core.component.dex.v1.rs | 3 ++ .../penumbra.core.component.dex.v1.serde.rs | 21 ++++++++ .../proto/src/gen/proto_descriptor.bin.no_lfs | Bin 380322 -> 380506 bytes .../penumbra/core/component/dex/v1/dex.proto | 2 + 16 files changed, 144 insertions(+), 52 deletions(-) diff --git a/crates/bench/benches/swap_claim.rs b/crates/bench/benches/swap_claim.rs index 2ba03515bb..bbeb2ea233 100644 --- a/crates/bench/benches/swap_claim.rs +++ b/crates/bench/benches/swap_claim.rs @@ -71,6 +71,7 @@ fn swap_claim_proving_time(c: &mut Criterion) { height: height.into(), trading_pair: swap_plaintext.trading_pair, epoch_starting_height: (epoch_duration * position.epoch()).into(), + sct_position_prefix: position, }; let (lambda_1, lambda_2) = output_data.pro_rata_outputs((delta_1_i, delta_2_i)); diff --git a/crates/bin/pcli/tests/proof.rs b/crates/bin/pcli/tests/proof.rs index a3eacf3860..ead865959e 100644 --- a/crates/bin/pcli/tests/proof.rs +++ b/crates/bin/pcli/tests/proof.rs @@ -279,6 +279,7 @@ fn swap_claim_parameters_vs_current_swap_claim_circuit() { height: height.into(), trading_pair: swap_plaintext.trading_pair, epoch_starting_height: (epoch_duration * position.epoch()).into(), + sct_position_prefix: position, }; let (lambda_1, lambda_2) = output_data.pro_rata_outputs((delta_1_i, delta_2_i)); diff --git a/crates/core/component/dex/src/batch_swap_output_data.rs b/crates/core/component/dex/src/batch_swap_output_data.rs index f40a446b46..8b29b6b8ac 100644 --- a/crates/core/component/dex/src/batch_swap_output_data.rs +++ b/crates/core/component/dex/src/batch_swap_output_data.rs @@ -6,11 +6,12 @@ use ark_r1cs_std::{ select::CondSelectGadget, }; use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError}; -use decaf377::{r1cs::FqVar, Fq}; +use decaf377::Fq; use penumbra_proto::{penumbra::core::component::dex::v1 as pb, DomainType}; +use penumbra_tct::{r1cs::PositionVar, Position}; use serde::{Deserialize, Serialize}; -use penumbra_num::fixpoint::{bit_constrain, U128x128, U128x128Var}; +use penumbra_num::fixpoint::{U128x128, U128x128Var}; use penumbra_num::{Amount, AmountVar}; use crate::TradingPairVar; @@ -38,6 +39,8 @@ pub struct BatchSwapOutputData { pub trading_pair: TradingPair, /// The starting block height of the epoch for which the batch swap data is valid. pub epoch_starting_height: u64, + /// The position prefix where this batch swap occurred. The commitment index must be 0. + pub sct_position_prefix: Position, } impl BatchSwapOutputData { @@ -116,20 +119,15 @@ impl ToConstraintField for BatchSwapOutputData { .to_field_elements() .expect("U128x128 types are Bls12-377 field members"), ); - public_inputs.extend( - Fq::from(self.height) - .to_field_elements() - .expect("Fq types are Bls12-377 field members"), - ); public_inputs.extend( self.trading_pair .to_field_elements() .expect("trading_pair is a Bls12-377 field member"), ); public_inputs.extend( - Fq::from(self.epoch_starting_height) + self.sct_position_prefix .to_field_elements() - .expect("Fq types are Bls12-377 field members"), + .expect("Position types are Bls12-377 field members"), ); Some(public_inputs) } @@ -142,9 +140,8 @@ pub struct BatchSwapOutputDataVar { pub lambda_2: U128x128Var, pub unfilled_1: U128x128Var, pub unfilled_2: U128x128Var, - pub height: FqVar, pub trading_pair: TradingPairVar, - pub epoch_starting_height: FqVar, + pub sct_position_prefix: PositionVar, } impl AllocVar for BatchSwapOutputDataVar { @@ -168,18 +165,13 @@ impl AllocVar for BatchSwapOutputDataVar { let unfilled_1 = U128x128Var::new_variable(cs.clone(), || Ok(unfilled_1_fixpoint), mode)?; let unfilled_2_fixpoint: U128x128 = output_data.unfilled_2.into(); let unfilled_2 = U128x128Var::new_variable(cs.clone(), || Ok(unfilled_2_fixpoint), mode)?; - let height = FqVar::new_variable(cs.clone(), || Ok(Fq::from(output_data.height)), mode)?; - // Check the height is 64 bits - let _ = bit_constrain(height.clone(), 64); let trading_pair = TradingPairVar::new_variable_unchecked( cs.clone(), || Ok(output_data.trading_pair), mode, )?; - let epoch_starting_height = - FqVar::new_variable(cs, || Ok(Fq::from(output_data.epoch_starting_height)), mode)?; - // Check the epoch starting height is 64 bits - let _ = bit_constrain(epoch_starting_height.clone(), 64); + let sct_position_prefix = + PositionVar::new_variable(cs.clone(), || Ok(output_data.sct_position_prefix), mode)?; Ok(Self { delta_1, @@ -189,8 +181,7 @@ impl AllocVar for BatchSwapOutputDataVar { unfilled_1, unfilled_2, trading_pair, - height, - epoch_starting_height, + sct_position_prefix, }) } } @@ -211,6 +202,7 @@ impl From for pb::BatchSwapOutputData { height: s.height, epoch_starting_height: s.epoch_starting_height, trading_pair: Some(s.trading_pair.into()), + sct_position_prefix: s.sct_position_prefix.into(), } } } @@ -276,6 +268,14 @@ impl From for pb::BatchSwapOutputDataResponse { impl TryFrom for BatchSwapOutputData { type Error = anyhow::Error; fn try_from(s: pb::BatchSwapOutputData) -> Result { + let sct_position_prefix = { + let prefix = Position::from(s.sct_position_prefix); + anyhow::ensure!( + prefix.commitment() == 0, + "sct_position_prefix.commitment() != 0" + ); + prefix + }; Ok(Self { delta_1: s .delta_1 @@ -307,6 +307,7 @@ impl TryFrom for BatchSwapOutputData { .ok_or_else(|| anyhow!("Missing trading_pair"))? .try_into()?, epoch_starting_height: s.epoch_starting_height, + sct_position_prefix, }) } } @@ -421,9 +422,10 @@ mod tests { lambda_2: Amount::from(1u32), unfilled_1: Amount::from(1u32), unfilled_2: Amount::from(1u32), - height: 1, + height: 0, trading_pair, - epoch_starting_height: 1, + epoch_starting_height: 0, + sct_position_prefix: 0u64.into(), }, } } @@ -445,6 +447,7 @@ mod tests { height: 0u64, trading_pair, epoch_starting_height: 0u64, + sct_position_prefix: 0u64.into(), }; // Now suppose our user's contribution is: diff --git a/crates/core/component/dex/src/component/circuit_breaker/value.rs b/crates/core/component/dex/src/component/circuit_breaker/value.rs index ac76907569..5337549861 100644 --- a/crates/core/component/dex/src/component/circuit_breaker/value.rs +++ b/crates/core/component/dex/src/component/circuit_breaker/value.rs @@ -162,6 +162,7 @@ mod tests { height: 1, trading_pair: pair_1.into_directed_trading_pair().into(), epoch_starting_height: 0, + sct_position_prefix: Default::default(), }, None, None, @@ -252,7 +253,16 @@ mod tests { let routing_params = state.routing_params().await.unwrap(); // This call should panic due to the outflow of gn not being covered by the circuit breaker. state - .handle_batch_swaps(trading_pair, swap_flow, 0, 0, routing_params) + .handle_batch_swaps( + trading_pair, + swap_flow, + 0, + Epoch { + index: 0, + start_height: 0, + }, + routing_params, + ) .await .expect("unable to process batch swaps"); } diff --git a/crates/core/component/dex/src/component/dex.rs b/crates/core/component/dex/src/component/dex.rs index bdb9ada0c5..1bbaf4e41e 100644 --- a/crates/core/component/dex/src/component/dex.rs +++ b/crates/core/component/dex/src/component/dex.rs @@ -69,7 +69,7 @@ impl Component for Dex { .height .try_into() .expect("height is part of the end block data"), - current_epoch.start_height, + current_epoch, // Always include both ends of the target pair as fixed candidates. routing_params .clone() diff --git a/crates/core/component/dex/src/component/router/route_and_fill.rs b/crates/core/component/dex/src/component/router/route_and_fill.rs index b18a786200..47dfd997e3 100644 --- a/crates/core/component/dex/src/component/router/route_and_fill.rs +++ b/crates/core/component/dex/src/component/router/route_and_fill.rs @@ -5,6 +5,7 @@ use async_trait::async_trait; use cnidarium::StateWrite; use penumbra_asset::{asset, Value}; use penumbra_num::Amount; +use penumbra_sct::epoch::Epoch; use tracing::instrument; use crate::{ @@ -23,21 +24,14 @@ use super::fill_route::FillError; /// a block's batch swap flows. #[async_trait] pub trait HandleBatchSwaps: StateWrite + Sized { - #[instrument(skip( - self, - trading_pair, - batch_data, - block_height, - epoch_starting_height, - params - ))] + #[instrument(skip(self, trading_pair, batch_data, block_height, epoch, params))] async fn handle_batch_swaps( self: &mut Arc, trading_pair: TradingPair, batch_data: SwapFlow, // TODO: why not read these 2 from the state? block_height: u64, - epoch_starting_height: u64, + epoch: Epoch, params: RoutingParams, ) -> Result<()> where @@ -97,7 +91,7 @@ pub trait HandleBatchSwaps: StateWrite + Sized { }; let output_data = BatchSwapOutputData { height: block_height, - epoch_starting_height, + epoch_starting_height: epoch.start_height, trading_pair, delta_1, delta_2, @@ -105,6 +99,13 @@ pub trait HandleBatchSwaps: StateWrite + Sized { lambda_2, unfilled_1, unfilled_2, + sct_position_prefix: ( + u16::try_from(epoch.index).expect("epoch index should be small enough"), + u16::try_from(block_height - epoch.start_height) + .expect("block index should be small enough"), + 0, + ) + .into(), }; // Fetch the swap execution object that should have been modified during the routing and filling. diff --git a/crates/core/component/dex/src/component/router/tests.rs b/crates/core/component/dex/src/component/router/tests.rs index bd9c5f4de6..42048a30fd 100644 --- a/crates/core/component/dex/src/component/router/tests.rs +++ b/crates/core/component/dex/src/component/router/tests.rs @@ -5,6 +5,7 @@ use core::panic; use futures::StreamExt; use penumbra_asset::{asset, Value}; use penumbra_num::{fixpoint::U128x128, Amount}; +use penumbra_sct::epoch::Epoch; use rand_core::OsRng; use std::sync::Arc; @@ -1024,7 +1025,16 @@ async fn best_position_route_and_fill() -> anyhow::Result<()> { .unwrap(); let routing_params = state.routing_params().await.unwrap(); state - .handle_batch_swaps(trading_pair, swap_flow, 0u32.into(), 0, routing_params) + .handle_batch_swaps( + trading_pair, + swap_flow, + 0u32.into(), + Epoch { + index: 0, + start_height: 0, + }, + routing_params, + ) .await .expect("unable to process batch swaps"); @@ -1165,7 +1175,16 @@ async fn multi_hop_route_and_fill() -> anyhow::Result<()> { .unwrap(); let routing_params = state.routing_params().await.unwrap(); state - .handle_batch_swaps(trading_pair, swap_flow, 0u32.into(), 0, routing_params) + .handle_batch_swaps( + trading_pair, + swap_flow, + 0u32.into(), + Epoch { + index: 0, + start_height: 0, + }, + routing_params, + ) .await .expect("unable to process batch swaps"); diff --git a/crates/core/component/dex/src/component/tests.rs b/crates/core/component/dex/src/component/tests.rs index 69baee6c9b..72ecda092d 100644 --- a/crates/core/component/dex/src/component/tests.rs +++ b/crates/core/component/dex/src/component/tests.rs @@ -6,6 +6,7 @@ use cnidarium::{ArcStateDeltaExt, StateDelta, TempStorage}; use futures::StreamExt; use penumbra_asset::{asset, Value}; use penumbra_num::Amount; +use penumbra_sct::epoch::Epoch; use rand_core::OsRng; use crate::lp::action::PositionOpen; @@ -632,7 +633,16 @@ async fn swap_execution_tests() -> anyhow::Result<()> { .unwrap(); let routing_params = state.routing_params().await.unwrap(); state - .handle_batch_swaps(trading_pair, swap_flow, 0, 0, routing_params) + .handle_batch_swaps( + trading_pair, + swap_flow, + 0, + Epoch { + index: 0, + start_height: 0, + }, + routing_params, + ) .await .expect("unable to process batch swaps"); @@ -740,7 +750,16 @@ async fn swap_execution_tests() -> anyhow::Result<()> { .unwrap(); let routing_params = state.routing_params().await.unwrap(); state - .handle_batch_swaps(trading_pair, swap_flow, 0u32.into(), 0, routing_params) + .handle_batch_swaps( + trading_pair, + swap_flow, + 0u32.into(), + Epoch { + index: 0, + start_height: 0, + }, + routing_params, + ) .await .expect("unable to process batch swaps"); @@ -758,6 +777,7 @@ async fn swap_execution_tests() -> anyhow::Result<()> { height: 0, epoch_starting_height: 0, trading_pair, + sct_position_prefix: Default::default(), } ); diff --git a/crates/core/component/dex/src/swap_claim/proof.rs b/crates/core/component/dex/src/swap_claim/proof.rs index c8698d131c..7484e1d307 100644 --- a/crates/core/component/dex/src/swap_claim/proof.rs +++ b/crates/core/component/dex/src/swap_claim/proof.rs @@ -123,11 +123,16 @@ fn check_satisfaction( anyhow::bail!("claim fee did not match public input"); } - let block: u64 = private.state_commitment_proof.position().block().into(); - let note_commitment_block_height: u64 = public.output_data.epoch_starting_height + block; - if note_commitment_block_height != public.output_data.height { - anyhow::bail!("swap commitment height did not match public input"); - } + anyhow::ensure!( + private.state_commitment_proof.position().block() + == public.output_data.sct_position_prefix.block(), + "scm block did not match batch swap" + ); + anyhow::ensure!( + private.state_commitment_proof.position().epoch() + == public.output_data.sct_position_prefix.epoch(), + "scm epoch did not match batch swap" + ); if private.swap_plaintext.trading_pair != public.output_data.trading_pair { anyhow::bail!("trading pair did not match public input"); @@ -255,12 +260,14 @@ impl ConstraintSynthesizer for SwapClaimCircuit { claimed_fee_var.enforce_equal(&swap_plaintext_var.claim_fee)?; // Validate the swap commitment's height matches the output data's height (i.e. the clearing price height). - let block = position_var.block()?; - let note_commitment_block_height_var = - output_data_var.epoch_starting_height.clone() + block; output_data_var - .height - .enforce_equal(¬e_commitment_block_height_var)?; + .sct_position_prefix + .block()? + .enforce_equal(&position_var.block()?)?; + output_data_var + .sct_position_prefix + .epoch()? + .enforce_equal(&position_var.epoch()?)?; // Validate that the output data's trading pair matches the note commitment's trading pair. output_data_var @@ -360,6 +367,7 @@ impl DummyWitness for SwapClaimCircuit { height: 0, trading_pair: swap_plaintext.trading_pair, epoch_starting_height: 0, + sct_position_prefix: Default::default(), }; let note_blinding_1 = Fq::from(1); let note_blinding_2 = Fq::from(1); @@ -643,6 +651,7 @@ mod tests { height: height.into(), trading_pair: swap_plaintext.trading_pair, epoch_starting_height: (epoch_duration * position.epoch()).into(), + sct_position_prefix: Default::default(), }; let (lambda_1, lambda_2) = output_data.pro_rata_outputs((delta_1_i, delta_2_i)); @@ -775,6 +784,7 @@ mod tests { height: height.into(), trading_pair: swap_plaintext.trading_pair, epoch_starting_height: (epoch_duration * position.epoch()).into(), + sct_position_prefix: Default::default() }; let (lambda_1, lambda_2) = output_data.pro_rata_outputs((delta_1_i, delta_2_i)); @@ -875,6 +885,7 @@ mod tests { height: height.into(), trading_pair: swap_plaintext.trading_pair, epoch_starting_height: (epoch_duration * dummy_position.epoch()).into(), + sct_position_prefix: Default::default() }; let (lambda_1, lambda_2) = output_data.pro_rata_outputs((delta_1_i, delta_2_i)); diff --git a/crates/crypto/proof-params/src/gen/swapclaim_id.rs b/crates/crypto/proof-params/src/gen/swapclaim_id.rs index 0293098666..4745bf8515 100644 --- a/crates/crypto/proof-params/src/gen/swapclaim_id.rs +++ b/crates/crypto/proof-params/src/gen/swapclaim_id.rs @@ -1,3 +1,3 @@ -pub const PROVING_KEY_ID: &'static str = "groth16pk1vs60etmlvwfzmn2ve0ljz0vfkzjlrhjpue5svm5ry6l076qukjcsw566rp"; -pub const VERIFICATION_KEY_ID: &'static str = "groth16vk18qjn0kxmypk8gmfc6zhjukhyxk0agmunfnhpxmf3yxq266q6sgaqwe94rc"; +pub const PROVING_KEY_ID: &'static str = "groth16pk19hg2sshv5t4d3fhexjr4vhq4d8tuxr5nfsw7mkzucwxmsjcf2kxql9gdte"; +pub const VERIFICATION_KEY_ID: &'static str = "groth16vk18pt0t8685e8h7y4dz494a2pamunadu4x3rtrttsaf4cd37gdsnhqsqkqgv"; diff --git a/crates/crypto/proof-params/src/gen/swapclaim_pk.bin b/crates/crypto/proof-params/src/gen/swapclaim_pk.bin index 96b1d164b6..8ff04c4e53 100644 --- a/crates/crypto/proof-params/src/gen/swapclaim_pk.bin +++ b/crates/crypto/proof-params/src/gen/swapclaim_pk.bin @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8501f1dad9ac85d80c6421b17b838f8c6478431babfa836d3d33b5398fa6b6ad -size 26003952 +oid sha256:5331fa2cf2f005c969125a2b61d2cf8a41f8f52b81360ad4d157c28d08aeee8b +size 25972272 diff --git a/crates/crypto/proof-params/src/gen/swapclaim_vk.param b/crates/crypto/proof-params/src/gen/swapclaim_vk.param index 4bd2b584a5dd9a63a3f92eace8fdf9fb648339ac..efe58c0c56c3c4fb1bc6c67eb264ca8103fdff3b 100644 GIT binary patch delta 8725 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 delta 2726 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 serde::Deserialize<'de> for BatchSwapOutputData { "tradingPair", "epoch_starting_height", "epochStartingHeight", + "sct_position_prefix", + "sctPositionPrefix", ]; #[allow(clippy::enum_variant_names)] @@ -684,6 +693,7 @@ impl<'de> serde::Deserialize<'de> for BatchSwapOutputData { Height, TradingPair, EpochStartingHeight, + SctPositionPrefix, __SkipField__, } impl<'de> serde::Deserialize<'de> for GeneratedField { @@ -715,6 +725,7 @@ impl<'de> serde::Deserialize<'de> for BatchSwapOutputData { "height" => Ok(GeneratedField::Height), "tradingPair" | "trading_pair" => Ok(GeneratedField::TradingPair), "epochStartingHeight" | "epoch_starting_height" => Ok(GeneratedField::EpochStartingHeight), + "sctPositionPrefix" | "sct_position_prefix" => Ok(GeneratedField::SctPositionPrefix), _ => Ok(GeneratedField::__SkipField__), } } @@ -743,6 +754,7 @@ impl<'de> serde::Deserialize<'de> for BatchSwapOutputData { let mut height__ = None; let mut trading_pair__ = None; let mut epoch_starting_height__ = None; + let mut sct_position_prefix__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::Delta1 => { @@ -803,6 +815,14 @@ impl<'de> serde::Deserialize<'de> for BatchSwapOutputData { Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) ; } + GeneratedField::SctPositionPrefix => { + if sct_position_prefix__.is_some() { + return Err(serde::de::Error::duplicate_field("sctPositionPrefix")); + } + sct_position_prefix__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } GeneratedField::__SkipField__ => { let _ = map_.next_value::()?; } @@ -818,6 +838,7 @@ impl<'de> serde::Deserialize<'de> for BatchSwapOutputData { height: height__.unwrap_or_default(), trading_pair: trading_pair__, epoch_starting_height: epoch_starting_height__.unwrap_or_default(), + sct_position_prefix: sct_position_prefix__.unwrap_or_default(), }) } } diff --git a/crates/proto/src/gen/proto_descriptor.bin.no_lfs b/crates/proto/src/gen/proto_descriptor.bin.no_lfs index 8a26d29b046550f594d789bdc692d546f5431d8b..8f030d1fee28902f54fcb7b0fbca3040b720a132 100644 GIT binary patch delta 9374 zcmYjXX^>UbwLW_|hueptZ=Z%9Zci6znx^4)(-Yk^4H!TLLBOdhaY~esk|ZxsfMrs7 zFV_T>AuTfLmQjPKjDjFGGKi?bl!QEk1P3HQ=~JTE!3mH--naJP&5y3)TYG)qUTf{~ z?91xq`R}jD-*RES{NI1@aB=*%h3daAiTJj@8$OG(UE6YZci{u0>M(c4q?tdSHg(37 znNz0z>c`WjPyX4IUl)W)Rw-}HLDNLrGEp~dD|>lNW#@JOWMQYs_q;cJb;BB7rn>)? z=cyIGEZFwS$A2wlpR_;hvq^sXN1>G6cvd7oX1rHoZ1U!NCMQh?$;!#orcSzNK=STi zPM!3Ne#xmnOU|T5+gb9ydnQkx4AYbu$-D2GIq9C{jQj4ImYh0i(!JBCPyT6j7QB%t1yltJuOGS%Pp`&+ro#a+w_kpEK`_x)idH)1R|ge%J-^Wpgi*9gLT25>TLF z4+kOH!Sc!+gklHl)!S0h_;1GZZ6gB}u&aZ*wOiyMsQ+d?^1>&1$YU}d1?QM|xqV6( zR>rP9$6`fVGfv^0XFNx5D3^$`5TVPQD0q;2bJ|aJV{w*# zkjLUW@*Il%A#SSygeU+_6o8O?h{sJe03rDhM>S{+a;U%A87d_J=%|#y>m`&6H z2&PjM1%Kq;jt!3@@BOTEtOS${^yXQ9Tz^e})RQ zg!2O1jQ|zUO!4xF3vie4&bh8xd*|hcGjz8ylIpQsc5k)fJg_bj48=QjcMuH4^9#bh zs8?{>Zx2-k-eP9qA&%WTq@T}^=>Y!sb1+ah7m$5UB-YAT1gonpfcrBQqQzE zc4ybK>Swr}qOg*gXPMpsL3)OIuSDqU97!EM>&KOYtjl807_#4ZB!)7%&kNviCGnb{``!V=! z<~@6b^O<#oVJnmpzf;5VSibrykIn22Lxw^_yOk&x90e)uQ1kNHrCvL@?D@U6fa4Bc z-X|=v(iohbYHa~4OYh{e?0Y{6znvVLh|5Moa3?Qs3gcl+rzdI9ck(`i^bF}v>F?&e z)Ko`LWBG|K}}x7y_a2DmPg^7P!~$s zrwu3EdVvvIC){!Ygw_d;<#NA7X8BQYntL6bCB6{q`G4}f_Ua`2h>bfkpzU~ zStkhy$+IN6hjJ{S(Yv7D>CN^wT;SXsY%r3QmkiVc0SL|oUf&QtYB-o)-*KLoc!({& z>ZiqOZ9mpkeO1oxNyBOmk^;RWedi_sASAw{2~dPY3Zvi;!h2A#MAzh~$vChl-8EAm zx}8HI3(@xb(k9n{E@bi(Yuzj6T~$*P@I8y|#&Bv!=BN`fU?f(=PlZWw0d!dLS=|-O|0=?XcLKQ`U65bQ)=auY^v=TA18jC26$Avv{fDkvJ zNdpjqj|+R?03wFR1y&GMpon@~>INJLR6sM}fV$NVI3TD?-FRP9L>uWcVJ`?k-~yWS z6cF5H!d{mE!CfYB$`8`r0<933)0J*Y=cj3(d~ z&{df%C3;^aI-6ayh|`(5N+f#f!UIBK6%9MBhvFz$Exa}Azp7Yb!fFvK)1@e;Dn8|^ z2n0buQ$;`sKIN(i2*IbQicKL8Fi)Qq-s@Ok{T4s>OhTQhVg=dH3hZpS#|3(}u2cE_ z*&V5MBG3_%5!G8K5_-81gy1?c{MK;1rl7YC>QDXI#MA~6=#v3Hbl7bW-76_6f}m^= z^`pbv`OSvI0(unQG0bbO;dojsAU7#^wupR&?h`(>Db#M zdQ@2o-Cwqd#vu+8N3`A;-m4Wb7F*Tm6uYl=YbH)Q5VvOHq@md=>IYi|8jG!>WkNVu zE8s%BU0qDEA=hpffj(^zgAax6qOi_Vd?;)eLq|FYh3#V0o#8LE0vcZu{O-gZ$s6vS zJpDH+S;I=yvTAm9>Ln2rSxx}Omqc;1gOGShjQoiWqEjSysV+4LVwVW?mW3cXfwD`K zv{*_f^s`G`J=Q@e>=NUC9{x}V5sTy=!S796mkFYWda8!C4BaCF{kZ|f7!>!2ot`a$UdlfO$2&Lk`WTGVcW4B`XqWy^r;We;cN|9 z6dVxV-&CJkb~gKfh!uv7P+~N*52~s<)>M7ajS`GdI_O3T5K0GWHciD6DT#u=3-7Rc zq>lY6{dW=TrI$zv2^|vL+y#L!c7SHp0%Fo05?SUJ00_ZDBFeQ?G`=l(BgHLC^hN{N z+d^n}jEDGKi-Z86M2G951hFV6dM_rz2KqLxm5(R|wQI{wnWRJQ;%V^*GK=7eD z1Rz8NXd(jCtpoHllz^aqAcnN+M3Yf)TzDsKL`ira7qOBsO&fKRLOLP1UPOc-3)n~Z z0tn|5qQacLfRH^Qnwqt2&nWm%c>iZ*d&2WWci#6T)sI}FK*$r&Qpz#dOgTy$subCC9WM)ts6&$ps<#g6jL0$f-0ws z&bk@{p~irw#(?lW>uL-L)w8a~h??H+Mp;W;0 z4-!*_R$2vxGE3T(280X&O<@7yJ4@P?1_;$zQm-_k-ip=-q}?DZbYTHa5`enZ78VfP z2c+I0x$GMSv!yrBM${Lcvt_Jjcoib*OA*agX9lwo>ABKA3&04Uxw4a)yns-fEA=A; zzO195O?vaKS|vQ&q}{|TN$p|D_4zJ=kRM=D?<9cmeOUH1=>kIaVOiNv?z!vxGs>fa$UB5B)d@ZdaVNlS-@Tn!grzUUF{%b7s}c?En5`@OQiRhRjq>O5*af$ z^eR$))CF6`({7{FbvQt{#sHeT z9w0hdDm$A=4G8K|IiLy7X06s(ZmD%;BdxUP_~3SE)`)XPd2JP>37 zP3(a1UFl*6gz8EcdnyW^l-|=;H3iQnWvntBk%j4yBH7idsg;dNt(JD_!3d|-((WUG zkXtQrve4H_idM)PwYHVDrq{Un2qRf#RySP*Kv34;IZ)?SjXSOM*4YTE;rXnL(KL{< zngUqs@&ZC$fF>_M_^x$%0YY`H%c}-6XoK`NS=k!6Zjkm{y@q5rN_#~Bf-Io9A^^g7 zqqJ89K*(;C_KGkt3N}k`hgBU2&&@JsJ~alC>hqGfBr5fLwYqi~D^iz-vfLD`CT946 z^1SS6ZYO{ce_l2Z)*mYasd(Ge&|$2(YFmav#oLylQ1P}AWgIFrkaLw7&W5RD!_d!m zS8Yx+r*4dVjMcTL;%S-2qic*&L9(Ruh3B3utz1K=>Yz6$4x= zWDm%if#F0%R7ZUtRImSl-8lN7w67E}l2zuIZ)ZSI4obW@(iE$Yg14mio(-fPo^Q!m zPS_7>^%Te|4yzxt50AO0}H=aB4Xp6UUic8JEZucn~!uw48|N20aX{_In)YkFAP z=R-j46F1=iLf|lkV+2ssBP39&`j2E`>PUu1$sLj3^QfRlh*z#V26|WBJ(5+7ephny z`%k@oXn0p9&8rk3IZ3=qQRWSJr?&h@xVno|=Hl;d(x6MeU#7vy?UJw1vw)t$^xD9w`@ z3Z;3HDD<$>KOd6x$W9fZq^KFFZ z#}Z$V#gJ{Jd{3#lSF_U8DQTaFV1&;pX`hDxp>|5*IglntBZc`XO^$@>xSHiued_9j z7HV>J0tD|;C&Qi5Vttkq=mEHrsxsNu% z^IKZ(wTP{W)Gn%iqgj33MW+TMd@edQK&V|LHF{ZWqFP->IT9(g?>c@lpe?ux4-%phHHRRjd-N`?gVdmp_vsN^{O z^m0FuVK76`q=(@5z8yh8?T#L4;x^F;%<}*9MKEVPjQBEv)m)$f(fusnz6%0EVU};U zOxYX-5Bc7swuH^_e8|VQQZvMxsf2UXE!VM@)EwVVUl`#t$G6iL5NdOLl#nXWOqtG8 zyRT!Ts^|2`N`azY8Oy4x=4W`cZ0BcqRJr-Y8>73GYQebw=(ZxYAj71JE%4)JziZYNTj1lT zD#Ju|7pbCgrpHK)8OI81>8)*1M!<)_qKtr#t{0I2eYG{yiMB*_zMkDWdWmn(Qy4*6 z;^&#)l>k9m;wO9Ri9R?Al<%#wqcj+v%EzX91Jnl7C@oc+u4gw@Ep=)z!e^~nx1E%&j{84|YDm1^^NcFX9M843;f z$_$0ZW+hQ*dA8s>?t4$$s9WIqq>rs}I6`Qls8_3T6W9+@tKCe65k9MZ`>6*Awbed8 z^@eE*8rP_u6WCRCYg_;=I_5Qg+*~C9L0RMDD$#-fhD5U%G#O*gQn?5#e&@F?_F3jGBNeNa9A4Y?Ow0)UWv!6g6)xffglt<=|xl)&)Ri!K5f z$?8G}1m#5+dMky#gF*6qjh~mWrASnCX7C9^mUia~z ze9S2`44$vk;;V<+FiK{>+I}-@EZgr&10#I)yNw4BYWrtr-NNw4@h9*n+p})*m;UIe_j3!jU8wW!I@9Gbf0bS8UrDErm1d}!foH&%{$;us6l zBH#1g^3@ZgGDj6Y#m5Z2aq>zL`(k*n&wlP_f5}2FGos)$^Ug9B|A>{`u1d$VZ1vt4 z_HObti%ks2hEis5FOp{%FAv9sKA}Lv2@W!Xxy23&f|JWE6`fx*KGAkEPyxp|sC&mp z4ubkMn~)p!^N`16W)ytOysN{d<5)4f>01^n(3+X#&PB$vGz-YrFy$#WmXhC$i3ym{TVEiB_HImOzn9VdHxW$*#Lqhpm75bk`M7rlMO&fKE#m?szDZw z_i&0zi3D_1is0cCl_GeUs59V9S`-D3aBrh(&SKN&KjNH;$eA9_<2ngIPy{qd0EA)> zk4%vPq1eOo^20AVyot!0wZqS5vA<@?wVbC}4RT{GkD2nq2&AhQHRs%1CbDJU@PK zjXJbmPEdcyW=pEk5?FHy_6DAo;~>}@_{6+$Dsq<{1)I3{l)5vARb*`9u_#PHGn-P^ zr`G1Mn(96mJsKg@=b{IMP#;BqkW!XS0X{kWbq>3kRX@qOnXYK1W}a?F2L$O!8od&u z=S0Ca?(I{*$YoQ1wvERogyW%c`Wxi`RNWtb7B84Lq7 zl%*O_iveCSHN4L!>{j>Wv*P4#E{lJ(ld#*(v5mMGBm{T! z@|G|&jOm~xm3=p#(yZr54h8)R=S3zbdO8D|Ie|{tzQS|zT`$C5;gbr(O^h;1wRuhb zIiK~_yyi-SMr!5hW<>yk^BTtz?@2>#CPcv~_x>>acAPyTlA~01nyM4XjYFIl>VbeT zRRPUz1PIAPe4LrcfRH@I3np1AIuE-AGJ(?)2Q&)=Q1{ve0to71S|A6piI0=HQE-%d z$2p6?%G78HD^Qn;*g)n{9?J>8q8M|@u}{^D#q5;oyjzrwyLtlT%be?kcqg!F0fMYM^)2QHa}~nz(T3Pl0rMV*`s==vbtoCkYn`<(#;sO zM~o{-HDK5tG07}WZGnM%1QsVvf;j1{a!vwar2?8=7Z7Tz#F$L&Ga$59i7a!_143z) z7#A-H+qD#W*Qi@6S!ZI6;EqFKuMt_fR)VJV8j&9lJ2VAV>s7;*tgE^=MWH7A3ZeKyUA`p>t}x$f=~r2!gU*G<1hIYYIAds1Ikbg^3-wI#?U3 z&km7Y;UFkGMBVk_KWGZjb82yd{Zr?2BG893Wa;dBPE4q>6uO2yCz?7OB#!7@9R7<| zKtTpKRJ`{#T ze!ZpmP#6+ja~*`jkeGLO_%~Vsox_6vEWT7-SBn$j>lzkQi)+~RiD3~GSV{oFVKJ%I zK`0E1x%XHf(jvJ>9jIX)oqI%}cPsdi2Fe~$*lsCl7-o;Se!hcH*drGFGW<*JLoAXb zs-u=I=^7D%{zia83<@KnCXO!8^ixR~@Tk7c<@wvHY+JN{lA*LG@WZYpFiyih@Qc z9dtzjgwjEpJAaQ=Q5Xg93-7S{Ndx;;@_iATtXD)K35^PFE^R<46`;A&0b+`diga^u z143|AMA?>#&O?GXk>9dVZz+If4(i@=bC97I)I$OX*;x3JEQ*37!uwFLa7-v<5loMW znEB2sB9A_BvOvfv;B+ku2-^?D3?mB&*$duQlrCjmkISafviKueor3NvVc?cD1b2jR8*K_77((Zik4O_TN(u?g!jKzwiK2p+{s=_ zs-L+)fe=j66D{ z?rUauCeAoDG{WYLNH-r}fKWRlaJO8dDd;?_SPQ!=aW+LE2hNIgbH6Ur4xFWJA3H8a z!ICJ?m&5WK5i8P5rks4f;IasWECQM= z0>bu!%OW6DFSsn0^CWt|b!jZ8G!isf1k}AYi-6#M>n3nH1#!_$U?2<&XeKZqs25!@ zfS_J)Q z8tWPkVD;N(Y~y3vSiaiP#>$guGm*eTo7i#yf`83iW4NrqZB}{@O0#cN!18{H`9RC5 zg1lKK?Q#M_kbow)fUsRA?Q#Ny>N2U96H%9-_W@~l!3v#QK;sdh?zOoE1or`{cR?)kcgv|<>W@acL)K*CSJb>@qDCm*i zDyvor%N}WW>Pk|3RC0Y}OCZDtSfaNJK-fMiOHH_dP<>QZPSe}Pv?v*@mfl(`I}N6* zWvpDMZ5qk0k-S0c06`XTvV*W)Bg?8CgzOqwSFdHOqF|l${@top!E&99nG1Insjhd< zR`Dds0vm793*+_9TR_OJciv8qf{oI9%*sxO?ku}x>?35bV_E>D1FX(Ajkq5-vMFU=X?i* zYM=8x5e1J+@Ap*O2UhwD$lY$O4*s03d7!q`e0KLUusf zdq8az?3CUvt6B@ooib*=9BN7RdCA-3l_j_T;@%Rqc_yo_LW6M^-LQUMmYUlKAatLX zt!?_Vqn0!EyP2#~#b>eX#0x1BW$uL(i8A*Bkrp65wX{nPsU@@6EmcD<*=Pi1NT%z{ zHQ9hNB&Stbico(si_KJ-*Rky6%PA7Q=e(RE(Fe}UM54=2T@>t=-hbMl>tMNCVn?O- zusZq@-Xr;bY2L$t(Y;58S$HZ6s5=IOSESr4ef{aHTVV1EOp^M|3@wzo5gEjtg{}x1 z#-$oS8Ij{Bq#EGh2yH_2>_!qWcva$(OHWoBqo`=eNHu7S%+w$(35{1}VUg27EOH;- zIUGgDvQLhsr$0RiCFylM=lp0u)p=cxHP_2J3gb;zIv{ueXtqs2*uE)q_1#|riYN(O zWWMw2$o~Uw4g!G-XujwHb#I<|Uju~W2P7W+Xpz*>EO<+D^Cb@iDqy-^Yk;7>MfIRN zFCeIINqo7YuuElq6ud3HcWq_sVfwZ^o$4u?cO7%#TugEJ?Z_Ib)*57@5xwJI1OqI zk%6Lg{MI$vl!GQ(#9@WJ=}{BA4s&fId|5d932*4<$E0$u#Jf zgAZkid0qk}BZ=oFin{4CTzk0lalFpn7M zhV>^dbU^5SLZLTmGCGf`EAv=$;+S)#QHOp^mY9PR5R_xGxrM&ZFdjlbu9jZUS`x=o z6bkrwib4S&Ckj24G!imt7fSG zNyg&(H;`t^)dls-ZdTKM!Q~2#u({xJ1qihZlq*teiGuH>_keHip)Iidj#hddd}|@K z%j!foYe-ynYG{PbWv2!RwacVN4}>k0r>koAjd&ou>N1Z;YIT_h1m!BFfL_U3DD&5( zD!d8T=yMBLx*ENa6<1$#2}D2G*IWVt!M>Ja1O1@cbE|(yaVY6Oq&SrHABaQqvxOt) z%Y1cR6{}PGZel_AGT+{i(FNi%-#+L8g1F2#+oEiZf`@!>z0FlCEFbdmJ=6-#R?5|K zHEup@Pb~NCEJY)1miu;=0zz%Mk6cmUtrXWv_0RL!y!w^CUB76gR^M)2fS|1O;d!^F zAXhy;7Js`cy@^evd_}5f0n4kS`HCJhUt4v~dVD)y0in{9QUO|}?pnZZs$Z3&P|8-N zD3r2QM7dE9jFheRd3n6!$AN3A(BQ_Sw5|3t&F0ps)3(~j4@HLTtI-9lSp9~)z3*mL zm{^-)`e3e2F?|fXmYDQi)=E*WQ*YkPmUOT4?TLv-P}cdm=I0zhP}cb+rFuTMMZpH& z+hS|f2FndTw$59j)fT$}Z3*Sn&5NgWDiFKQ%pmUS@tA(sp6)uG1 zo1Eiqx=@?^OtYT>g15=X&B*Xjs6OJ|(cPD#P{sRF6sk%eQD`ByfYPtv+rJ?Qo?d3ZC}8o$7xUv9^q-eSA#N6~2SK*rs+YX3gsETUn6U zhIdcBAEF1NZS%9u9R?6;+k9MMx-<`+1FH8{HY+jU9O%#v4EUMm5)25+fL~UwS5pV= z3D2tgZ)1&(_%|lOvne7a@mW99jYUa(md0v@=bce7=zGKJ-o>mXW6;Mp9C_YJp1(+* zcP3tRPNNY*FFL0IA@rhix|2qEiJWe0z`xT|9Gg7}hiy^~zuMXtAZ?@Ccf zZkKZ!HlXaHv8eK0xGDSI>$dV;u-xP0i=-Z&cai5Kir>x}6C=L;@J1tSM*K8$cLRjl z2yIe$qXq??d)3cx$NTVJ-+ob|5h3jL$C#`El94~jOnN{l?4?Oh>$QtQ*rz_eoz3sw z=cXGPLD}baMnF*Zxt(!l6ujZ%Ked=sWF{=%pjFoZwV4#c0rhuxu%_YzE+J@y%>lRD Z07C7+iv4#m{BisV{K?_{cleur^M5#Kc$)wK diff --git a/proto/penumbra/penumbra/core/component/dex/v1/dex.proto b/proto/penumbra/penumbra/core/component/dex/v1/dex.proto index 4ba3cbb394..1076e03ecf 100644 --- a/proto/penumbra/penumbra/core/component/dex/v1/dex.proto +++ b/proto/penumbra/penumbra/core/component/dex/v1/dex.proto @@ -227,6 +227,8 @@ message BatchSwapOutputData { TradingPair trading_pair = 8; // The starting block height of the epoch for which the batch swap data is valid. uint64 epoch_starting_height = 9; + // The prefix (epoch, block) of the position where this batch swap occurred. + uint64 sct_position_prefix = 10; } // The trading function for a specific pair.