diff --git a/Cargo.lock b/Cargo.lock index e20260455c..caccf60f40 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4257,7 +4257,6 @@ dependencies = [ "penumbra-keys", "penumbra-num", "penumbra-proof-params", - "penumbra-proof-setup", "penumbra-proto", "penumbra-sct", "penumbra-shielded-pool", @@ -4512,6 +4511,7 @@ dependencies = [ "bitvec", "blake2b_simd 1.0.2", "camino", + "cfg-if", "cnidarium", "cnidarium-component", "decaf377", diff --git a/Cargo.toml b/Cargo.toml index d471f6fab0..fd2f40ffa8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,6 @@ [workspace] -# Set virtual workspace's resolver to v1, to support the "rust-docs" script. -resolver = "1" +resolver = "2" exclude = ["tools/proto-compiler", "tools/parameter-setup"] @@ -167,7 +166,7 @@ once_cell = { version = "1.8" } parking_lot = { version = "0.12.1" } pbjson = { version = "0.6" } pbjson-types = { version = "0.6.0" } -penumbra-app = { path = "crates/core/app" } +penumbra-app = { default-features = false, path = "crates/core/app" } penumbra-asset = { default-features = false, path = "crates/core/asset" } penumbra-community-pool = { default-features = false, path = "crates/core/component/community-pool" } penumbra-compact-block = { default-features = false, path = "crates/core/component/compact-block" } diff --git a/crates/bin/pcli/Cargo.toml b/crates/bin/pcli/Cargo.toml index 79bbdb9606..7c123ddff9 100644 --- a/crates/bin/pcli/Cargo.toml +++ b/crates/bin/pcli/Cargo.toml @@ -27,7 +27,6 @@ parallel = [ "penumbra-stake/parallel", "penumbra-transaction/parallel", "penumbra-wallet/parallel", - "penumbra-proof-setup/parallel", ] [dependencies] @@ -60,7 +59,7 @@ indicatif = {workspace = true} jmt = {workspace = true} ndarray = "0.15.6" once_cell = {workspace = true} -penumbra-app = {workspace = true} +penumbra-app = {workspace = true, default-features = false} penumbra-asset = {workspace = true, default-features = false} penumbra-community-pool = {workspace = true, default-features = false} penumbra-compact-block = {workspace = true, default-features = false} @@ -72,7 +71,6 @@ penumbra-governance = {workspace = true, default-features = false} penumbra-ibc = {workspace = true, default-features = false} penumbra-keys = {workspace = true, default-features = false} penumbra-num = {workspace = true, default-features = false} -penumbra-proof-setup = {workspace = true} penumbra-proof-params = { workspace = true, default-features = true } penumbra-proto = {workspace = true, features = ["rpc", "box-grpc"], default-features = true} penumbra-sct = {workspace = true, default-features = false} diff --git a/crates/bin/pcli/src/command.rs b/crates/bin/pcli/src/command.rs index 420964e6e6..025bc4d534 100644 --- a/crates/bin/pcli/src/command.rs +++ b/crates/bin/pcli/src/command.rs @@ -7,9 +7,8 @@ pub use tx::TxCmd; pub use validator::ValidatorCmd; pub use view::ViewCmd; -use self::{ceremony::CeremonyCmd, tx::TxCmdWithOptions}; +use self::tx::TxCmdWithOptions; -mod ceremony; mod debug; mod init; mod migrate; @@ -64,9 +63,6 @@ pub enum Command { /// Manage a validator. #[clap(subcommand, display_order = 900)] Validator(ValidatorCmd), - /// Contribute to the summoning ceremony. - #[clap(subcommand, display_order = 990)] - Ceremony(CeremonyCmd), /// Display information related to diagnosing problems running Penumbra #[clap(subcommand, display_order = 999)] Debug(DebugCmd), @@ -82,7 +78,6 @@ impl Command { Command::Validator(cmd) => cmd.offline(), Command::Query(cmd) => cmd.offline(), Command::Debug(cmd) => cmd.offline(), - Command::Ceremony(_) => false, Command::Threshold(cmd) => cmd.offline(), Command::Migrate(_) => false, } diff --git a/crates/bin/pcli/src/command/ceremony.rs b/crates/bin/pcli/src/command/ceremony.rs deleted file mode 100644 index f8095aed44..0000000000 --- a/crates/bin/pcli/src/command/ceremony.rs +++ /dev/null @@ -1,259 +0,0 @@ -use anyhow::{anyhow, Context, Result}; -use rand_core::OsRng; -use tokio::sync::mpsc; -use tokio_stream::wrappers::ReceiverStream; -use url::Url; - -use penumbra_asset::Value; -use penumbra_keys::{keys::AddressIndex, Address}; -use penumbra_num::Amount; -use penumbra_proof_setup::all::{ - Phase1CeremonyContribution, Phase1RawCeremonyCRS, Phase2CeremonyContribution, - Phase2RawCeremonyCRS, -}; -use penumbra_proof_setup::single::log::Hashable; -use penumbra_proto::{ - penumbra::tools::summoning::v1::ceremony_coordinator_service_client::CeremonyCoordinatorServiceClient, - tools::summoning::v1::{ - participate_request::{Identify, Msg as RequestMsg}, - participate_response::{Confirm, ContributeNow, Msg as ResponseMsg}, - ParticipateRequest, ParticipateResponse, - }, - view::v1::GasPricesRequest, -}; -use penumbra_view::Planner; - -use crate::App; - -fn max_message_size(phase: u8) -> usize { - match phase { - 1 => 200 * 1024 * 1024, - _ => 100 * 1024 * 1024, - } -} - -#[tracing::instrument(skip(app))] -async fn handle_bid(app: &mut App, to: Address, from: AddressIndex, bid: &str) -> Result<()> { - let gas_prices = app - .view - .as_mut() - .context("view service must be initialized")? - .gas_prices(GasPricesRequest {}) - .await? - .into_inner() - .gas_prices - .expect("gas prices must be available") - .try_into()?; - - let value = bid.parse::()?; - - // If the bid is 0, skip creating a transaction. For instance, this allows reconnecting - // without paying extra. - if value.amount == 0u64.into() { - return Ok(()); - } - - let mut planner = Planner::new(OsRng); - planner.set_gas_prices(gas_prices); - planner.output(value, to); - let plan = planner - .memo("E PLURIBUS UNUM".into()) - .memo_return_address(app.config.full_viewing_key.payment_address(from).0) - .plan( - app.view - .as_mut() - .context("view service must be initialized")?, - from, - ) - .await - .context("can't build send transaction")?; - app.build_and_submit_transaction(plan).await?; - Ok(()) -} - -#[derive(Debug, clap::Subcommand)] -pub enum CeremonyCmd { - /// Contribute to the ceremony - Contribute { - /// The phase of the summoning ceremony that's currently active. Must match that of the remote - /// coordinator. - #[clap(long, default_value = "2")] - phase: u8, - /// The URL for the public coordination server. - #[clap(long, default_value = "https://summoning.penumbra.zone")] - coordinator_url: Url, - /// The Penumbra wallet address of the coordination server. Bids will be sent to this - /// address, so the coordinator can compute the contributor's place in the queue. - #[clap( - long, - default_value = "penumbra1qvqr8cvqyf4pwrl6svw9kj8eypf3fuunrcs83m30zxh57y2ytk94gygmtq5k82cjdq9y3mlaa3fwctwpdjr6fxnwuzrsy4ezm0u2tqpzw0sed82shzcr42sju55en26mavjnw4" - )] - coordinator_address: Address, - /// Amount to spend during bid. Must be specified typed values, e.g. '50penumbra'. - /// Only the 'penumbra' token is accepted for contributions. Bids are additive, - /// so if you're disconnected, you can bid '0penumbra' and your previous bids - /// will be still be counted when computing your place in the queue. - #[clap(long)] - bid: String, - }, -} - -impl CeremonyCmd { - #[tracing::instrument(skip(self, app))] - pub async fn exec(&self, app: &mut App) -> Result<()> { - match self { - CeremonyCmd::Contribute { - phase, - coordinator_url, - coordinator_address, - bid, - } => { - println!("¸,ø¤º°` initiating summoning participation `°º¤ø,¸"); - - let index = match *phase { - 1 => AddressIndex { - account: 0, - randomizer: b"ceremnyaddr1" - .as_slice() - .try_into() - .expect("12 bytes long"), - }, - 2 => AddressIndex { - account: 0, - randomizer: b"ceremnyaddr2" - .as_slice() - .try_into() - .expect("12 bytes long"), - }, - _ => anyhow::bail!("phase must be 1 or 2."), - }; - let address = app.config.full_viewing_key.payment_address(index).0; - - println!( - "submitting bid {} for contribution slot from address {}", - bid, address - ); - - handle_bid(app, coordinator_address.clone(), index, bid).await?; - - println!("connecting to coordinator..."); - // After we bid, we need to wait a couple of seconds just for the transaction to be - // picked up by the coordinator. Else, there is a race wherein the coordinator will kick the - // client out of the queue because it doesn't see the transaction yet. - tokio::time::sleep(std::time::Duration::from_secs(2)).await; - - let (req_tx, req_rx) = mpsc::channel::(10); - tracing::debug!(?address, "participate request"); - req_tx - .send(ParticipateRequest { - msg: Some(RequestMsg::Identify(Identify { - address: Some(address.into()), - })), - }) - .await?; - let mut client = - CeremonyCoordinatorServiceClient::connect(coordinator_url.to_string()) - .await? - .max_decoding_message_size(max_message_size(*phase)) - .max_encoding_message_size(max_message_size(*phase)); - println!( - r#"connected to coordinator! -You may disconnect (CTRL+C) to increase your bid if you don't like your position in the queue. -Otherwise, please keep this window open. -"# - ); - use indicatif::{ProgressBar, ProgressDrawTarget, ProgressStyle}; - let progress_bar = ProgressBar::with_draw_target(1, ProgressDrawTarget::stdout()) - .with_style( - ProgressStyle::default_bar() - .template("[{elapsed}] {bar:50.blue/cyan} position {pos} out of {len} connected summoners\t{msg}"), - ); - progress_bar.set_position(0); - progress_bar.enable_steady_tick(1000); - - let mut response_rx = client - .participate(ReceiverStream::new(req_rx)) - .await? - .into_inner(); - let unparsed_parent = loop { - match response_rx.message().await? { - None => { - progress_bar.abandon(); - anyhow::bail!("Coordinator closed connection") - } - Some(ParticipateResponse { - msg: Some(ResponseMsg::Position(p)), - }) => { - tracing::debug!(?p); - let len = p.connected_participants; - // e.g. displaying 1 / 2 instead of 0 / 2 - let pos = p.position + 1; - progress_bar.set_length(len as u64); - progress_bar.set_position(pos as u64); - progress_bar.set_message(format!( - "(your bid: {}, most recent slot bid: {})", - Amount::try_from( - p.your_bid.ok_or(anyhow!("expected bid amount"))? - )?, - Amount::try_from( - p.last_slot_bid.ok_or(anyhow!("expected top bid amount"))? - )? - )); - progress_bar.tick(); - } - Some(ParticipateResponse { - msg: - Some(ResponseMsg::ContributeNow(ContributeNow { - parent: Some(parent), - })), - }) => { - progress_bar.finish(); - break parent; - } - m => { - progress_bar.abandon(); - anyhow::bail!("Received unexpected message from coordinator: {:?}", m) - } - } - }; - println!("preparing contribution... (please keep this window open)"); - let (contribution, hash) = if *phase == 1 { - let parent = Phase1RawCeremonyCRS::unchecked_from_protobuf(unparsed_parent)? - .assume_valid(); - let contribution = Phase1CeremonyContribution::make(&parent); - let hash = contribution.hash(); - (contribution.try_into()?, hash) - } else { - let parent = Phase2RawCeremonyCRS::unchecked_from_protobuf(unparsed_parent)? - .assume_valid(); - let contribution = Phase2CeremonyContribution::make(&parent); - let hash = contribution.hash(); - (contribution.try_into()?, hash) - }; - println!("submitting contribution..."); - - req_tx - .send(ParticipateRequest { - msg: Some(RequestMsg::Contribution(contribution)), - }) - .await?; - println!("coordinator is validating contribution..."); - match response_rx.message().await? { - None => anyhow::bail!("Coordinator closed connection"), - Some(ParticipateResponse { - msg: Some(ResponseMsg::Confirm(Confirm { slot })), - }) => { - println!("contribution confirmed at slot {slot}"); - println!("thank you for your help summoning penumbra <3"); - println!("here's your contribution receipt (save this to verify inclusion in the final transcript):\n{}", hex::encode_upper(hash.as_ref())); - } - m => { - anyhow::bail!("Received unexpected message from coordinator: {:?}", m) - } - } - - Ok(()) - } - } - } -} diff --git a/crates/bin/pcli/src/main.rs b/crates/bin/pcli/src/main.rs index 3f56af08c1..43be79b1bf 100644 --- a/crates/bin/pcli/src/main.rs +++ b/crates/bin/pcli/src/main.rs @@ -63,7 +63,6 @@ async fn main() -> Result<()> { Command::View(view_cmd) => view_cmd.exec(&mut app).await?, Command::Validator(cmd) => cmd.exec(&mut app).await?, Command::Query(cmd) => cmd.exec(&mut app).await?, - Command::Ceremony(cmd) => cmd.exec(&mut app).await?, Command::Threshold(cmd) => cmd.exec(&mut app).await?, Command::Migrate(cmd) => cmd.exec(&mut app).await?, } diff --git a/crates/bin/pclientd/Cargo.toml b/crates/bin/pclientd/Cargo.toml index ff7dfc4944..40c0906f8a 100644 --- a/crates/bin/pclientd/Cargo.toml +++ b/crates/bin/pclientd/Cargo.toml @@ -26,7 +26,7 @@ http = {workspace = true} http-body = {workspace = true} metrics = {workspace = true} parking_lot = {workspace = true} -penumbra-app = {workspace = true} +penumbra-app = {workspace = true, default-features = false} penumbra-asset = {workspace = true, default-features = true} penumbra-custody = {workspace = true} penumbra-keys = {workspace = true, default-features = true} diff --git a/crates/bin/pindexer/Cargo.toml b/crates/bin/pindexer/Cargo.toml index 2d6171b5c3..88e062b8ca 100644 --- a/crates/bin/pindexer/Cargo.toml +++ b/crates/bin/pindexer/Cargo.toml @@ -17,7 +17,7 @@ cometindex = {workspace = true} num-bigint = { version = "0.4" } penumbra-shielded-pool = {workspace = true, default-features = false} penumbra-stake = {workspace = true, default-features = false} -penumbra-app = {workspace = true} +penumbra-app = {workspace = true, default-features = false} penumbra-auction = {workspace = true, default-features = false} penumbra-dex = {workspace = true, default-features = false} penumbra-fee = {workspace = true, default-features = false} diff --git a/crates/core/app/Cargo.toml b/crates/core/app/Cargo.toml index f16d81a4e1..9013371d07 100644 --- a/crates/core/app/Cargo.toml +++ b/crates/core/app/Cargo.toml @@ -9,7 +9,28 @@ license = { workspace = true } publish = false [features] -default = ["std"] +component = [ + "dep:cnidarium", + "dep:cnidarium-component", + "penumbra-proto/cnidarium", + "penumbra-auction/component", + "penumbra-community-pool/component", + "penumbra-compact-block/component", + "penumbra-dex/component", + "penumbra-distributions/component", + "penumbra-fee/component", + "penumbra-funding/component", + "penumbra-governance/component", + "penumbra-ibc/component", + "penumbra-ibc/rpc", + "penumbra-sct/component", + "penumbra-shielded-pool/component", + "penumbra-stake/component", + "dep:tonic", + "dep:tonic-reflection", + "dep:tonic-web" +] +default = ["std", "component"] std = ["ark-ff/std", "ibc-types/std"] [dependencies] @@ -21,8 +42,9 @@ bech32 = { workspace = true } bincode = { workspace = true } bitvec = { workspace = true } blake2b_simd = { workspace = true } -cnidarium = { workspace = true, features = ["migration", "rpc"], default-features = true } -cnidarium-component = { workspace = true, default-features = true } +cfg-if = "1.0" +cnidarium = { workspace = true, optional = true, features = ["migration", "rpc"], default-features = true } +cnidarium-component = { workspace = true, optional = true, default-features = true } decaf377 = { workspace = true, default-features = true } decaf377-rdsa = { workspace = true } futures = { workspace = true } @@ -36,22 +58,22 @@ metrics = { workspace = true } once_cell = { workspace = true } parking_lot = { workspace = true } penumbra-asset = { workspace = true, default-features = true } -penumbra-auction = { workspace = true, default-features = true } -penumbra-community-pool = { workspace = true, default-features = true } -penumbra-compact-block = { workspace = true, default-features = true } -penumbra-dex = { workspace = true, default-features = true } -penumbra-distributions = { workspace = true, default-features = true } -penumbra-fee = { workspace = true, default-features = true } -penumbra-funding = { workspace = true, default-features = true } -penumbra-governance = { workspace = true, default-features = true } -penumbra-ibc = { workspace = true, features = ["component", "rpc"], default-features = true } +penumbra-auction = { workspace = true, default-features = false } +penumbra-community-pool = { workspace = true, default-features = false } +penumbra-compact-block = { workspace = true, default-features = false } +penumbra-dex = { workspace = true, default-features = false } +penumbra-distributions = { workspace = true, default-features = false } +penumbra-fee = { workspace = true, default-features = false } +penumbra-funding = { workspace = true, default-features = false } +penumbra-governance = { workspace = true, default-features = false } +penumbra-ibc = { workspace = true, default-features = false } penumbra-keys = { workspace = true, default-features = true } penumbra-num = { workspace = true, default-features = true } -penumbra-proof-params = { workspace = true, default-features = true } -penumbra-proto = { workspace = true, features = ["cnidarium"], default-features = true } -penumbra-sct = { workspace = true, default-features = true } -penumbra-shielded-pool = { workspace = true, features = ["component"], default-features = true } -penumbra-stake = { workspace = true, default-features = true } +penumbra-proof-params = { workspace = true, default-features = false } +penumbra-proto = { workspace = true, default-features = true } +penumbra-sct = { workspace = true, default-features = false } +penumbra-shielded-pool = { workspace = true, default-features = false } +penumbra-stake = { workspace = true, default-features = false } penumbra-tct = { workspace = true, default-features = true } penumbra-test-subscriber = { workspace = true } penumbra-tower-trace = { path = "../../util/tower-trace" } @@ -71,9 +93,9 @@ tendermint-light-client-verifier = { workspace = true } tendermint-proto = { workspace = true } tokio = { workspace = true, features = ["full", "tracing"] } tokio-util = { workspace = true } -tonic = { workspace = true } -tonic-reflection = { workspace = true } -tonic-web = { workspace = true } +tonic = { workspace = true, optional = true } +tonic-reflection = { workspace = true, optional = true } +tonic-web = { workspace = true, optional = true } tower = { workspace = true, features = ["full"] } tower-abci = "0.11" tower-actor = "0.1.0" diff --git a/crates/core/app/src/lib.rs b/crates/core/app/src/lib.rs index d915e9eaee..21e75bd50d 100644 --- a/crates/core/app/src/lib.rs +++ b/crates/core/app/src/lib.rs @@ -1,29 +1,8 @@ #![deny(clippy::unwrap_used)] #![cfg_attr(docsrs, feature(doc_auto_cfg))] -pub mod app; -pub mod genesis; -pub mod metrics; -pub mod params; -pub mod rpc; -pub mod server; - -mod action_handler; -mod community_pool_ext; -mod penumbra_host_chain; - -pub use crate::{ - action_handler::AppActionHandler, app::StateWriteExt, - community_pool_ext::CommunityPoolStateReadExt, metrics::register_metrics, - penumbra_host_chain::PenumbraHost, -}; - use once_cell::sync::Lazy; -/// Representation of the Penumbra application version. Notably, this is distinct -/// from the crate version(s). This number should only ever be incremented. -pub const APP_VERSION: u64 = 8; - pub static SUBSTORE_PREFIXES: Lazy> = Lazy::new(|| { vec![ penumbra_ibc::IBC_SUBSTORE_PREFIX.to_string(), @@ -34,5 +13,31 @@ pub static SUBSTORE_PREFIXES: Lazy> = Lazy::new(|| { /// The substore prefix used for storing historical CometBFT block data. pub static COMETBFT_SUBSTORE_PREFIX: &'static str = "cometbft-data"; -/// Temporary compat wrapper for duplicate trait impls -pub struct Compat<'a, T>(&'a T); +/// Representation of the Penumbra application version. Notably, this is distinct +/// from the crate version(s). This number should only ever be incremented. +pub const APP_VERSION: u64 = 8; + +pub mod genesis; +pub mod params; + +cfg_if::cfg_if! { + if #[cfg(feature="component")] { + pub mod app; + pub mod metrics; + pub mod rpc; + pub mod server; + + mod action_handler; + mod community_pool_ext; + mod penumbra_host_chain; + + pub use crate::{ + action_handler::AppActionHandler, app::StateWriteExt, + community_pool_ext::CommunityPoolStateReadExt, metrics::register_metrics, + penumbra_host_chain::PenumbraHost, + }; + + /// Temporary compat wrapper for duplicate trait impls + pub struct Compat<'a, T>(&'a T); + } +} diff --git a/crates/view/Cargo.toml b/crates/view/Cargo.toml index 4f43124d18..aebc7e6fa8 100644 --- a/crates/view/Cargo.toml +++ b/crates/view/Cargo.toml @@ -33,7 +33,7 @@ ibc-types = {workspace = true, default-features = false} metrics = {workspace = true} once_cell = {workspace = true} parking_lot = {workspace = true} -penumbra-app = {workspace = true} +penumbra-app = {workspace = true, default-features = false} penumbra-asset = {workspace = true, default-features = true} penumbra-community-pool = {workspace = true, default-features = false} penumbra-compact-block = {workspace = true, default-features = false} @@ -51,7 +51,7 @@ penumbra-shielded-pool = {workspace = true, default-features = false} penumbra-stake = {workspace = true, default-features = false} penumbra-tct = {workspace = true, default-features = true} penumbra-transaction = {workspace = true, default-features = true} -penumbra-auction = {workspace = true, default-features = true} +penumbra-auction = {workspace = true, default-features = false} prost = {workspace = true} r2d2 = {workspace = true} r2d2_sqlite = {workspace = true, features = ["bundled"]} diff --git a/crates/view/src/service.rs b/crates/view/src/service.rs index e0dccbeeff..d7f148206f 100644 --- a/crates/view/src/service.rs +++ b/crates/view/src/service.rs @@ -186,21 +186,8 @@ impl ViewServer { transaction: Transaction, await_detection: bool, ) -> BroadcastTransactionStream { - use penumbra_app::AppActionHandler; - let self2 = self.clone(); try_stream! { - // 1. Pre-check the transaction for (stateless) validity. - transaction - .check_stateless(()) - .await - .map_err(|e| { - tonic::Status::unavailable(format!( - "transaction pre-submission checks failed: {:#?}", - e - )) - })?; - // 2. Broadcast the transaction to the network. // Note that "synchronous" here means "wait for the tx to be accepted by // the fullnode", not "wait for the tx to be included on chain. diff --git a/crates/wallet/Cargo.toml b/crates/wallet/Cargo.toml index 30a645a3aa..6bce49542c 100644 --- a/crates/wallet/Cargo.toml +++ b/crates/wallet/Cargo.toml @@ -20,16 +20,16 @@ bincode = {workspace = true} bytes = {workspace = true} decaf377 = {workspace = true, default-features = true} hex = {workspace = true} -penumbra-app = {workspace = true} +penumbra-app = {workspace = true, default-features = false} penumbra-asset = {workspace = true, default-features = true} penumbra-custody = {workspace = true} -penumbra-dex = {workspace = true, default-features = true} -penumbra-fee = {workspace = true, default-features = true} -penumbra-governance = {workspace = true, default-features = true} +penumbra-dex = {workspace = true, default-features = false} +penumbra-fee = {workspace = true, default-features = false} +penumbra-governance = {workspace = true, default-features = false} penumbra-keys = {workspace = true, default-features = true} penumbra-num = {workspace = true, default-features = true} penumbra-proto = {workspace = true, default-features = true} -penumbra-stake = {workspace = true, default-features = true} +penumbra-stake = {workspace = true, default-features = false} penumbra-tct = {workspace = true, default-features = true} penumbra-sct = {workspace = true, default-features = false} penumbra-transaction = {workspace = true, default-features = true}