Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/ci-pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
12 changes: 12 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
@@ -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
28 changes: 21 additions & 7 deletions zcash_local_net/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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>) -> 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]

10 changes: 9 additions & 1 deletion zcash_local_net/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand All @@ -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",
]
16 changes: 7 additions & 9 deletions zcash_local_net/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<PathBuf> {
Expand Down Expand Up @@ -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<PathBuf> {
Expand Down Expand Up @@ -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<PathBuf> {
let config_file_path = config_dir.join(ZAINOD_FILENAME);
Expand Down Expand Up @@ -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<PathBuf> {
Expand Down
6 changes: 2 additions & 4 deletions zcash_local_net/src/indexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,20 @@
//! 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<Port>);
fn set_listen_port(&mut self, indexer_listen_port: Option<u16>);
/// To receive a port to instruct an indexer to listen at.
fn setup_validator_connection<V: Validator>(&mut self, validator: &V);
}

/// Functionality for indexer/light-node processes.
pub trait Indexer: Process<Config: IndexerConfig> + std::fmt::Debug {
/// Indexer listen port
fn listen_port(&self) -> Port;
fn listen_port(&self) -> u16;
}

/// The Zainod executable support struct.
Expand Down
5 changes: 2 additions & 3 deletions zcash_local_net/src/indexer/empty.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use getset::{CopyGetters, Getters};
use portpicker::Port;
use tempfile::TempDir;

use crate::{
Expand All @@ -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<Port>) {
fn set_listen_port(&mut self, indexer_listen_port: Option<u16>) {
panic!("Empty validator cannot listen on port! {indexer_listen_port:?}");
}
}
Expand Down Expand Up @@ -78,7 +77,7 @@ impl Drop for Empty {
}

impl Indexer for Empty {
fn listen_port(&self) -> Port {
fn listen_port(&self) -> u16 {
0
}
}
9 changes: 4 additions & 5 deletions zcash_local_net/src/indexer/lightwalletd.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::{fs::File, path::PathBuf, process::Child};

use getset::{CopyGetters, Getters};
use portpicker::Port;
use tempfile::TempDir;

use crate::{
Expand All @@ -26,7 +25,7 @@ use crate::{
#[derive(Debug)]
pub struct LightwalletdConfig {
/// Listen RPC port
pub listen_port: Option<Port>,
pub listen_port: Option<u16>,
/// Zcashd configuration file location. Required even when running non-Zcashd validators.
pub zcashd_conf: PathBuf,
/// Enables darkside
Expand All @@ -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<Port>) {
fn set_listen_port(&mut self, indexer_listen_port: Option<u16>) {
self.listen_port = indexer_listen_port;
}
}
Expand All @@ -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
Expand Down Expand Up @@ -163,7 +162,7 @@ impl Process for Lightwalletd {
}

impl Indexer for Lightwalletd {
fn listen_port(&self) -> Port {
fn listen_port(&self) -> u16 {
self.port
}
}
Expand Down
11 changes: 5 additions & 6 deletions zcash_local_net/src/indexer/zainod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -33,9 +32,9 @@ use crate::{
#[derive(Debug)]
pub struct ZainodConfig {
/// Listen RPC port
pub listen_port: Option<Port>,
pub listen_port: Option<u16>,
/// Validator RPC port
pub validator_port: Port,
pub validator_port: u16,
/// Chain cache path
pub chain_cache: Option<PathBuf>,
/// Network type.
Expand All @@ -58,7 +57,7 @@ impl IndexerConfig for ZainodConfig {
self.validator_port = validator.get_port();
}

fn set_listen_port(&mut self, indexer_listen_port: Option<Port>) {
fn set_listen_port(&mut self, indexer_listen_port: Option<u16>) {
self.listen_port = indexer_listen_port;
}
}
Expand All @@ -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
Expand Down Expand Up @@ -154,7 +153,7 @@ impl Process for Zainod {
}

impl Indexer for Zainod {
fn listen_port(&self) -> Port {
fn listen_port(&self) -> u16 {
self.port
}
}
Expand Down
12 changes: 12 additions & 0 deletions zcash_local_net/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
12 changes: 1 addition & 11 deletions zcash_local_net/src/network.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,13 @@
//! 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>) -> Port {
pub fn pick_unused_port(fixed_port: Option<u16>) -> u16 {
if let Some(port) = fixed_port {
assert!(portpicker::is_free(port), "Fixed port is not free!");
port
} else {
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()
}
19 changes: 0 additions & 19 deletions zcash_local_net/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
// }
Loading