diff --git a/.github/workflows/ci-pr.yaml b/.github/workflows/ci-pr.yaml index 812e36a..95e4cd6 100644 --- a/.github/workflows/ci-pr.yaml +++ b/.github/workflows/ci-pr.yaml @@ -29,6 +29,34 @@ jobs: with: command: check + external-types: + name: External Types (public API) + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v6 + + - name: Setup pinned nightly + uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: nightly-2025-10-18 + + - name: Cache cargo + uses: Swatinem/rust-cache@v2 + + - name: Install just + uses: extractions/setup-just@v2 + + - name: Install cargo-binstall + uses: taiki-e/install-action@v2 + with: + tool: cargo-binstall + + - name: Install cargo-check-external-types + run: cargo binstall cargo-check-external-types -y --force + + - name: Run checks + run: just check-external-types + reject-trailing-whitespace: uses: ./.github/workflows/trailing-whitespace.yaml diff --git a/Cargo.lock b/Cargo.lock index 1b8ff9b..c48b28b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4896,7 +4896,6 @@ version = "0.1.0" dependencies = [ "getset", "hex", - "http", "json", "portpicker", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index 1e23705..e3f298d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,6 @@ zebra-node-services = "3.0.0" zebra-rpc = "5.0.0" # other -http = "1.1.0" getset = "0.1.3" hex = "0.4.3" json = "0.12.4" diff --git a/justfile b/justfile new file mode 100644 index 0000000..0b6cecc --- /dev/null +++ b/justfile @@ -0,0 +1,12 @@ +# cargo-check-external-types requires this for now +PINNED_NIGHTLY := "nightly-2025-10-18" + +check-external-types-zcash-local-net: + cargo +{{PINNED_NIGHTLY}} check-external-types --manifest-path zcash_local_net/Cargo.toml + +check-external-types-zingo-test-vectors: + cargo +{{PINNED_NIGHTLY}} check-external-types --manifest-path zingo_test_vectors/Cargo.toml + +check-external-types: + just check-external-types-zcash-local-net + just check-external-types-zingo-test-vectors \ No newline at end of file diff --git a/zcash_local_net/CHANGELOG.md b/zcash_local_net/CHANGELOG.md index 04208fd..d8aae2d 100644 --- a/zcash_local_net/CHANGELOG.md +++ b/zcash_local_net/CHANGELOG.md @@ -10,25 +10,39 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Deprecated ### Added -- support for Zebra 4.1.0 -- support for Zebra 4 + +- Added `zcash_local_net::protocol` module to provide a stable, crate-owned path for protocol-related types exposed in the public API: + - Re-exported `PoolType`, `ActivationHeights`, `NetworkType`, and `RpcRequestClient`. +- Added `zcash_local_net::external` module to provide a stable, crate-owned path for external helper types exposed in the public API: + - Re-exported `TempDir` via `zcash_local_net::external::TempDir` (and `zcash_local_net::TempDir`). ### Changed + +- Replaced `portpicker::Port` with `u16` across the public API for listen/port-related accessors and configuration setters, reducing external type leakage and simplifying callers: + - `indexer::empty::Empty::listen_port() -> u16` + - `indexer::lightwalletd::{Lightwalletd::port(), Lightwalletd::listen_port(), LightwalletdConfig::listen_port, LightwalletdConfig::set_listen_port(..)}` + - `indexer::zainod::{Zainod::port(), Zainod::listen_port(), ZainodConfig::{listen_port, validator_port}, ZainodConfig::set_listen_port(..)}` + - `network::pick_unused_port(fixed_port: Option) -> u16` + - `validator::zcashd::{Zcashd::port(), Zcashd::get_port(), ZcashdConfig::rpc_listen_port}` + - `validator::zebrad::{Zebrad::{indexer_listen_port(), network_listen_port(), rpc_listen_port(), get_port()}, ZebradConfig::{indexer_listen_port, network_listen_port, rpc_listen_port}}` + - `validator::Validator::get_port() -> u16` + - `validator::Validator` trait: - `network`: now takes `ActivationHeights` instead of `ConfiguredActivationHeights`. - `load_chain`: now takes `NetworkType` instead of `NetworkKind`. - `validator::zcashd::ZcashdConfig`: changed `configured_activation_heights: ConfiguredActivationHeights` field to -`activation_heights: ActivationHeights`. Removing the zebra-chain type from the public API and replacing with new -zingo_common_components type. + `activation_heights: ActivationHeights`. Removing the zebra-chain type from the public API and replacing with new + zingo_common_components type. - `validator::zebrad::ZebradConfig`: - changed `network: NetworkKind` to `network_type: NetworkType`. Removing the -zebra-chain type from the public API and replacing with new zingo_common_components type. + zebra-chain type from the public API and replacing with new zingo_common_components type. - `with_regtest_enabled` method: now takes `ActivationHeights` instead of `ConfiguredActivationHeights`. - `set_test_parameters` method: now takes `ActivationHeights` instead of `ConfiguredActivationHeights`. ### Removed + +- Removed `network::localhost_uri(port: portpicker::Port) -> http::Uri` from the public API. (Callers should construct URIs using their own `u16` port value, or via a replacement helper if provided elsewhere.) - `validator::zebrad::ZebradConfig`: removed `configured_activation_heights: ConfiguredActivationHeights` field removing the -zebra-chain type from the public API. Replaced by new `network_type` field which includes activation heights. + zebra-chain type from the public API. Replaced by new `network_type` field which includes activation heights. ## [0.1.0] - diff --git a/zcash_local_net/Cargo.toml b/zcash_local_net/Cargo.toml index 1dbae03..338072d 100644 --- a/zcash_local_net/Cargo.toml +++ b/zcash_local_net/Cargo.toml @@ -24,7 +24,6 @@ zebra-chain = { workspace = true } # Community tempfile = { workspace = true } portpicker = { workspace = true } -http = { workspace = true } thiserror = { workspace = true } tracing = { workspace = true } getset = { workspace = true } @@ -39,3 +38,12 @@ tracing-subscriber = { workspace = true } [build-dependencies] hex = { workspace = true } tokio = { workspace = true, features = ["macros", "fs", "rt-multi-thread"] } + +[package.metadata.cargo_check_external_types] +allowed_external_types = [ + "tempfile::dir::TempDir", + "zcash_protocol::PoolType", + "zingo_common_components::protocol::ActivationHeights", + "zingo_common_components::protocol::NetworkType", + "zebra_node_services::rpc_client::RpcRequestClient", +] diff --git a/zcash_local_net/src/config.rs b/zcash_local_net/src/config.rs index b57e1fb..da4fef1 100644 --- a/zcash_local_net/src/config.rs +++ b/zcash_local_net/src/config.rs @@ -4,8 +4,6 @@ use std::fs::File; use std::io::{BufWriter, Write}; use std::path::{Path, PathBuf}; -use portpicker::Port; - use zingo_common_components::protocol::{ActivationHeights, NetworkType}; /// Convert `NetworkKind` to its config string representation @@ -27,7 +25,7 @@ pub(crate) const LIGHTWALLETD_FILENAME: &str = "lightwalletd.yml"; /// Returns the path to the config file. pub(crate) fn write_zcashd_config( config_dir: &Path, - rpc_port: Port, + rpc_port: u16, activation_heights: ActivationHeights, miner_address: Option<&str>, ) -> std::io::Result { @@ -120,9 +118,9 @@ minetolocalwallet=0 # This is set to false so that we can mine to a wallet, othe pub(crate) fn write_zebrad_config( output_config_dir: PathBuf, cache_dir: PathBuf, - network_listen_port: Port, - rpc_listen_port: Port, - indexer_listen_port: Port, + network_listen_port: u16, + rpc_listen_port: u16, + indexer_listen_port: u16, miner_address: &str, network: NetworkType, ) -> std::io::Result { @@ -234,8 +232,8 @@ NU6 = {nu6_activation_height} pub(crate) fn write_zainod_config( config_dir: &Path, validator_cache_dir: PathBuf, - listen_port: Port, - validator_port: Port, + listen_port: u16, + validator_port: u16, network: NetworkType, ) -> std::io::Result { let config_file_path = config_dir.join(ZAINOD_FILENAME); @@ -274,7 +272,7 @@ database.path = \"{chain_cache}\"" #[allow(dead_code)] pub(crate) fn write_lightwalletd_config( config_dir: &Path, - grpc_bind_addr_port: Port, + grpc_bind_addr_port: u16, log_file: PathBuf, zcashd_conf: PathBuf, ) -> std::io::Result { diff --git a/zcash_local_net/src/indexer.rs b/zcash_local_net/src/indexer.rs index 25b7f1f..0716e54 100644 --- a/zcash_local_net/src/indexer.rs +++ b/zcash_local_net/src/indexer.rs @@ -3,14 +3,12 @@ //! Processes which are not strictly indexers but have a similar role in serving light-clients/light-wallets //! (i.e. Lightwalletd) are also included in this category and are referred to as "light-nodes". -use portpicker::Port; - use crate::{process::Process, validator::Validator}; /// Can offer specific functionality shared across configuration for all indexers. pub trait IndexerConfig: Default + std::fmt::Debug { /// To receive a port to instruct an indexer to listen at. - fn set_listen_port(&mut self, indexer_listen_port: Option); + fn set_listen_port(&mut self, indexer_listen_port: Option); /// To receive a port to instruct an indexer to listen at. fn setup_validator_connection(&mut self, validator: &V); } @@ -18,7 +16,7 @@ pub trait IndexerConfig: Default + std::fmt::Debug { /// Functionality for indexer/light-node processes. pub trait Indexer: Process + std::fmt::Debug { /// Indexer listen port - fn listen_port(&self) -> Port; + fn listen_port(&self) -> u16; } /// The Zainod executable support struct. diff --git a/zcash_local_net/src/indexer/empty.rs b/zcash_local_net/src/indexer/empty.rs index 069a183..660e42b 100644 --- a/zcash_local_net/src/indexer/empty.rs +++ b/zcash_local_net/src/indexer/empty.rs @@ -1,5 +1,4 @@ use getset::{CopyGetters, Getters}; -use portpicker::Port; use tempfile::TempDir; use crate::{ @@ -21,7 +20,7 @@ impl IndexerConfig for EmptyConfig { tracing::info!("Empty Validator cannot accept a port!"); } - fn set_listen_port(&mut self, indexer_listen_port: Option) { + fn set_listen_port(&mut self, indexer_listen_port: Option) { panic!("Empty validator cannot listen on port! {indexer_listen_port:?}"); } } @@ -78,7 +77,7 @@ impl Drop for Empty { } impl Indexer for Empty { - fn listen_port(&self) -> Port { + fn listen_port(&self) -> u16 { 0 } } diff --git a/zcash_local_net/src/indexer/lightwalletd.rs b/zcash_local_net/src/indexer/lightwalletd.rs index 0f0dde4..db2869b 100644 --- a/zcash_local_net/src/indexer/lightwalletd.rs +++ b/zcash_local_net/src/indexer/lightwalletd.rs @@ -1,7 +1,6 @@ use std::{fs::File, path::PathBuf, process::Child}; use getset::{CopyGetters, Getters}; -use portpicker::Port; use tempfile::TempDir; use crate::{ @@ -26,7 +25,7 @@ use crate::{ #[derive(Debug)] pub struct LightwalletdConfig { /// Listen RPC port - pub listen_port: Option, + pub listen_port: Option, /// Zcashd configuration file location. Required even when running non-Zcashd validators. pub zcashd_conf: PathBuf, /// Enables darkside @@ -48,7 +47,7 @@ impl IndexerConfig for LightwalletdConfig { self.zcashd_conf = validator.get_zcashd_conf_path(); } - fn set_listen_port(&mut self, indexer_listen_port: Option) { + fn set_listen_port(&mut self, indexer_listen_port: Option) { self.listen_port = indexer_listen_port; } } @@ -61,7 +60,7 @@ pub struct Lightwalletd { /// RPC Port #[getset(skip)] #[getset(get_copy = "pub")] - port: Port, + port: u16, /// Data directory _data_dir: TempDir, /// Logs directory @@ -163,7 +162,7 @@ impl Process for Lightwalletd { } impl Indexer for Lightwalletd { - fn listen_port(&self) -> Port { + fn listen_port(&self) -> u16 { self.port } } diff --git a/zcash_local_net/src/indexer/zainod.rs b/zcash_local_net/src/indexer/zainod.rs index 7d42f0a..012eca2 100644 --- a/zcash_local_net/src/indexer/zainod.rs +++ b/zcash_local_net/src/indexer/zainod.rs @@ -3,7 +3,6 @@ use std::{path::PathBuf, process::Child}; use getset::{CopyGetters, Getters}; -use portpicker::Port; use tempfile::TempDir; use zingo_common_components::protocol::{ActivationHeights, NetworkType}; @@ -33,9 +32,9 @@ use crate::{ #[derive(Debug)] pub struct ZainodConfig { /// Listen RPC port - pub listen_port: Option, + pub listen_port: Option, /// Validator RPC port - pub validator_port: Port, + pub validator_port: u16, /// Chain cache path pub chain_cache: Option, /// Network type. @@ -58,7 +57,7 @@ impl IndexerConfig for ZainodConfig { self.validator_port = validator.get_port(); } - fn set_listen_port(&mut self, indexer_listen_port: Option) { + fn set_listen_port(&mut self, indexer_listen_port: Option) { self.listen_port = indexer_listen_port; } } @@ -72,7 +71,7 @@ pub struct Zainod { /// RPC port #[getset(skip)] #[getset(get_copy = "pub")] - port: Port, + port: u16, /// Logs directory logs_dir: TempDir, /// Config directory @@ -154,7 +153,7 @@ impl Process for Zainod { } impl Indexer for Zainod { - fn listen_port(&self) -> Port { + fn listen_port(&self) -> u16 { self.port } } diff --git a/zcash_local_net/src/lib.rs b/zcash_local_net/src/lib.rs index 471e292..e29c3e7 100644 --- a/zcash_local_net/src/lib.rs +++ b/zcash_local_net/src/lib.rs @@ -49,6 +49,18 @@ use crate::{ pub use zcash_protocol::PoolType; +/// External re-exported zcash types. +pub mod protocol { + pub use zcash_protocol::PoolType; + pub use zebra_node_services::rpc_client::RpcRequestClient; + pub use zingo_common_components::protocol::{ActivationHeights, NetworkType}; +} + +/// External re-exported types. +pub mod external { + pub use tempfile::TempDir; +} + /// All processes currently supported #[derive(Clone, Copy)] #[allow(missing_docs)] diff --git a/zcash_local_net/src/network.rs b/zcash_local_net/src/network.rs index 5ebead8..49de104 100644 --- a/zcash_local_net/src/network.rs +++ b/zcash_local_net/src/network.rs @@ -1,13 +1,9 @@ //! Structs and utility functions associated with local network configuration -use portpicker::Port; - -pub(crate) const LOCALHOST_IPV4: &str = "http://127.0.0.1"; - /// Checks `fixed_port` is not in use. /// If `fixed_port` is `None`, returns a random free port between `15_000` and `25_000`. #[must_use] -pub fn pick_unused_port(fixed_port: Option) -> Port { +pub fn pick_unused_port(fixed_port: Option) -> u16 { if let Some(port) = fixed_port { assert!(portpicker::is_free(port), "Fixed port is not free!"); port @@ -15,9 +11,3 @@ pub fn pick_unused_port(fixed_port: Option) -> Port { portpicker::pick_unused_port().expect("No ports free!") } } - -/// Constructs a URI with the localhost IPv4 address and the specified port. -#[must_use] -pub fn localhost_uri(port: Port) -> http::Uri { - format!("{LOCALHOST_IPV4}:{port}").try_into().unwrap() -} diff --git a/zcash_local_net/src/utils.rs b/zcash_local_net/src/utils.rs index d95680d..5e08a20 100644 --- a/zcash_local_net/src/utils.rs +++ b/zcash_local_net/src/utils.rs @@ -16,22 +16,3 @@ pub(crate) fn cargo_manifest_dir() -> PathBuf { pub fn chain_cache_dir() -> PathBuf { cargo_manifest_dir().join("chain_cache") } - -// // NOTE: this should be migrated to zingolib when LocalNet replaces regtest manager in zingoilb::testutils -// /// Builds faucet (miner) and recipient lightclients for local network integration testing -// pub fn build_lightclients( -// lightclient_dir: PathBuf, -// indexer_port: Port, -// ) -> (LightClient, LightClient) { -// let mut client_builder = -// ClientBuilder::new(network::localhost_uri(indexer_port), lightclient_dir); -// let faucet = client_builder.build_faucet(true, RegtestNetwork::all_upgrades_active()); -// let recipient = client_builder.build_client( -// seeds::HOSPITAL_MUSEUM_SEED.to_string(), -// 1, -// true, -// RegtestNetwork::all_upgrades_active(), -// ); - -// (faucet, recipient) -// } diff --git a/zcash_local_net/src/validator.rs b/zcash_local_net/src/validator.rs index d866312..88ef7ff 100644 --- a/zcash_local_net/src/validator.rs +++ b/zcash_local_net/src/validator.rs @@ -1,7 +1,6 @@ //! Module for the structs that represent and manage the validator/full-node processes i.e. Zebrad. use std::path::PathBuf; -use portpicker::Port; use tempfile::TempDir; use zcash_protocol::PoolType; use zingo_common_components::protocol::{ActivationHeights, NetworkType}; @@ -121,5 +120,5 @@ pub trait Validator: Process + std::fmt::Debug { ) -> PathBuf; /// To reveal a port. - fn get_port(&self) -> Port; + fn get_port(&self) -> u16; } diff --git a/zcash_local_net/src/validator/zcashd.rs b/zcash_local_net/src/validator/zcashd.rs index 90ded54..19a7be6 100644 --- a/zcash_local_net/src/validator/zcashd.rs +++ b/zcash_local_net/src/validator/zcashd.rs @@ -3,7 +3,6 @@ use std::{path::PathBuf, process::Child}; use getset::{CopyGetters, Getters}; -use portpicker::Port; use tempfile::TempDir; use zcash_protocol::PoolType; @@ -43,7 +42,7 @@ use crate::{ #[derive(Debug)] pub struct ZcashdConfig { /// Zcashd RPC listen port - pub rpc_listen_port: Option, + pub rpc_listen_port: Option, /// Local network upgrade activation heights pub activation_heights: ActivationHeights, /// Miner address @@ -89,7 +88,7 @@ pub struct Zcashd { /// RPC port #[getset(skip)] #[getset(get_copy = "pub")] - port: Port, + port: u16, /// Config directory config_dir: TempDir, /// Logs directory @@ -311,7 +310,7 @@ impl Validator for Zcashd { chain_cache } - fn get_port(&self) -> Port { + fn get_port(&self) -> u16 { self.port() } } diff --git a/zcash_local_net/src/validator/zebrad.rs b/zcash_local_net/src/validator/zebrad.rs index 7028809..fc339d3 100644 --- a/zcash_local_net/src/validator/zebrad.rs +++ b/zcash_local_net/src/validator/zebrad.rs @@ -25,7 +25,6 @@ use std::{ }; use getset::{CopyGetters, Getters}; -use portpicker::Port; use tempfile::TempDir; use zebra_chain::serialization::ZcashSerialize as _; use zebra_node_services::rpc_client::RpcRequestClient; @@ -52,11 +51,11 @@ use zebra_rpc::{ #[derive(Clone, Debug)] pub struct ZebradConfig { /// Zebrad network listen port - pub network_listen_port: Option, + pub network_listen_port: Option, /// Zebrad JSON-RPC listen port - pub rpc_listen_port: Option, + pub rpc_listen_port: Option, /// Zebrad gRPC listen port - pub indexer_listen_port: Option, + pub indexer_listen_port: Option, /// Miner address pub miner_address: String, /// Chain cache path @@ -114,15 +113,15 @@ pub struct Zebrad { /// network listen port #[getset(skip)] #[getset(get_copy = "pub")] - network_listen_port: Port, + network_listen_port: u16, /// json RPC listen port #[getset(skip)] #[getset(get_copy = "pub")] - rpc_listen_port: Port, + rpc_listen_port: u16, /// gRPC listen port #[getset(skip)] #[getset(get_copy = "pub")] - indexer_listen_port: Port, + indexer_listen_port: u16, /// Config directory config_dir: TempDir, /// Logs directory @@ -390,7 +389,7 @@ impl Validator for Zebrad { } } - fn get_port(&self) -> Port { + fn get_port(&self) -> u16 { self.rpc_listen_port() } }