diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d320426e7..145eff3eb7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Fixed + +- **CI**: ensure that `cargo test --doc` works in each crate, fix + [#1555](https://github.com/o1-labs/mina-rust/issues/1555), see + [#1556](https://github.com/o1-labs/mina-rust/pull/1556) + ## [0.18.0] - 2025-11-04 ### OCaml node diff --git a/Cargo.lock b/Cargo.lock index 31144fe37a..b38ed09f3d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1688,7 +1688,7 @@ checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "cli" -version = "0.17.0" +version = "0.18.0" dependencies = [ "anyhow", "backtrace", @@ -3340,7 +3340,7 @@ dependencies = [ [[package]] name = "hash-tool" -version = "0.17.0" +version = "0.18.0" dependencies = [ "bs58 0.4.0", "hex", @@ -4247,7 +4247,7 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "ledger-tool" -version = "0.17.0" +version = "0.18.0" dependencies = [ "anyhow", "mina-curves", @@ -4583,7 +4583,7 @@ dependencies = [ [[package]] name = "libp2p-rpc-behaviour" -version = "0.17.0" +version = "0.18.0" dependencies = [ "libp2p", "log", @@ -4868,7 +4868,7 @@ dependencies = [ [[package]] name = "mina-archive-breadcrumb-compare" -version = "0.17.0" +version = "0.18.0" dependencies = [ "anyhow", "binprot", @@ -4883,7 +4883,7 @@ dependencies = [ [[package]] name = "mina-bootstrap-sandbox" -version = "0.17.0" +version = "0.18.0" dependencies = [ "base64 0.22.1", "binprot", @@ -4908,7 +4908,7 @@ dependencies = [ [[package]] name = "mina-core" -version = "0.17.0" +version = "0.18.0" dependencies = [ "argon2", "ark-ff", @@ -4962,7 +4962,7 @@ dependencies = [ [[package]] name = "mina-fuzzer" -version = "0.17.0" +version = "0.18.0" dependencies = [ "lazy_static", "rand", @@ -4973,7 +4973,7 @@ dependencies = [ [[package]] name = "mina-gossipsub-sandbox" -version = "0.17.0" +version = "0.18.0" dependencies = [ "bs58 0.4.0", "env_logger", @@ -5000,12 +5000,13 @@ dependencies = [ [[package]] name = "mina-macros" -version = "0.17.0" +version = "0.18.0" dependencies = [ "anyhow", "mina-core", "proc-macro2 1.0.95", "quote 1.0.35", + "redux", "rust-format", "syn 2.0.96", "tracing", @@ -5013,7 +5014,7 @@ dependencies = [ [[package]] name = "mina-node-account" -version = "0.17.0" +version = "0.18.0" dependencies = [ "anyhow", "bs58 0.4.0", @@ -5031,7 +5032,7 @@ dependencies = [ [[package]] name = "mina-node-common" -version = "0.17.0" +version = "0.18.0" dependencies = [ "anyhow", "ark-ff", @@ -5073,7 +5074,7 @@ dependencies = [ [[package]] name = "mina-node-invariants" -version = "0.17.0" +version = "0.18.0" dependencies = [ "documented", "lazy_static", @@ -5087,7 +5088,7 @@ dependencies = [ [[package]] name = "mina-node-native" -version = "0.17.0" +version = "0.18.0" dependencies = [ "anyhow", "bs58 0.4.0", @@ -5127,7 +5128,7 @@ dependencies = [ [[package]] name = "mina-node-testing" -version = "0.17.0" +version = "0.18.0" dependencies = [ "anyhow", "axum", @@ -5173,7 +5174,7 @@ dependencies = [ [[package]] name = "mina-node-web" -version = "0.17.0" +version = "0.18.0" dependencies = [ "anyhow", "bytes", @@ -5201,7 +5202,7 @@ dependencies = [ [[package]] name = "mina-p2p-messages" -version = "0.17.0" +version = "0.18.0" dependencies = [ "alloc-test", "anyhow", @@ -5282,7 +5283,7 @@ dependencies = [ [[package]] name = "mina-transport" -version = "0.17.0" +version = "0.18.0" dependencies = [ "blake2", "hex", @@ -5293,7 +5294,7 @@ dependencies = [ [[package]] name = "mina-tree" -version = "0.17.0" +version = "0.18.0" dependencies = [ "anyhow", "ark-ec", @@ -5655,7 +5656,7 @@ dependencies = [ [[package]] name = "node" -version = "0.17.0" +version = "0.18.0" dependencies = [ "anyhow", "ark-ff", @@ -6128,7 +6129,7 @@ dependencies = [ [[package]] name = "p2p" -version = "0.17.0" +version = "0.18.0" dependencies = [ "aes-gcm 0.10.3", "anyhow", @@ -6197,7 +6198,7 @@ dependencies = [ [[package]] name = "p2p-testing" -version = "0.17.0" +version = "0.18.0" dependencies = [ "derive_more", "futures", @@ -6674,7 +6675,7 @@ checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" [[package]] name = "poseidon" -version = "0.17.0" +version = "0.18.0" dependencies = [ "ark-ff", "ark-serialize", @@ -7205,7 +7206,7 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "replay_dynamic_effects" -version = "0.17.0" +version = "0.18.0" dependencies = [ "mina-node-invariants", "mina-node-native", @@ -7634,7 +7635,7 @@ checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "salsa-simple" -version = "0.17.0" +version = "0.18.0" dependencies = [ "generic-array", "hex", @@ -8079,7 +8080,7 @@ dependencies = [ [[package]] name = "snark" -version = "0.17.0" +version = "0.18.0" dependencies = [ "ark-ec", "ark-ff", @@ -8928,7 +8929,7 @@ dependencies = [ [[package]] name = "transaction_fuzzer" -version = "0.17.0" +version = "0.18.0" dependencies = [ "ark-ec", "ark-ff", @@ -9302,7 +9303,7 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" [[package]] name = "vrf" -version = "0.17.0" +version = "0.18.0" dependencies = [ "anyhow", "ark-ec", @@ -9715,7 +9716,7 @@ dependencies = [ [[package]] name = "webrtc-sniffer" -version = "0.17.0" +version = "0.18.0" dependencies = [ "aes 0.8.4", "aes-gcm 0.10.3", diff --git a/Makefile b/Makefile index 34c1d0cc7d..12d1eeeac1 100644 --- a/Makefile +++ b/Makefile @@ -305,6 +305,10 @@ setup: setup-taplo setup-wasm ## Setup development environment test: ## Run tests cargo test +.PHONY: test-doc +test-doc: ## Run documentation tests only + @cargo test --doc + .PHONY: test-ledger test-ledger: build-ledger ## Run ledger tests in release mode, requires nightly Rust @cd ledger && cargo +$(NIGHTLY_RUST_VERSION) test --release -- -Z unstable-options --report-time @@ -560,7 +564,7 @@ docs-serve-only: docs-install ## Serve the documentation website locally without @cd website && npm start -- --port $(DOCS_PORT) .PHONY: docs-rust -docs-rust: ## Generate Rust API documentation +docs-rust: test-doc ## Generate Rust API documentation @echo "Generating Rust API documentation..." # Using nightly with --enable-index-page to generate workspace index # See: https://github.com/rust-lang/cargo/issues/8229 diff --git a/cli/src/commands/node/mod.rs b/cli/src/commands/node/mod.rs index e0ccb695a2..d87b0cc670 100644 --- a/cli/src/commands/node/mod.rs +++ b/cli/src/commands/node/mod.rs @@ -116,17 +116,17 @@ pub struct Node { /// Multiaddresses follow the format: `/protocol/address/protocol/port/protocol/peer_id` /// /// **IPv4 Example:** - /// ``` + /// ```text /// /ip4/192.168.1.100/tcp/8302/p2p/12D3KooWABCDEF1234567890abcdef... /// ``` /// /// **IPv6 Example:** - /// ``` + /// ```text /// /ip6/2001:db8::1/tcp/8302/p2p/12D3KooWABCDEF1234567890abcdef... /// ``` /// /// **DNS Example:** - /// ``` + /// ```text /// /dns4/node.example.com/tcp/8302/p2p/12D3KooWABCDEF1234567890abcdef... /// ``` /// @@ -143,7 +143,7 @@ pub struct Node { /// Each line should contain a peer's multiaddr following the format described above. /// /// **Example file content:** - /// ``` + /// ```text /// /ip4/192.168.1.100/tcp/8302/p2p/12D3KooWABCDEF1234567890abcdef... /// /ip4/10.0.0.50/tcp/8302/p2p/12D3KooWXYZ9876543210fedcba... /// /dns4/bootstrap.example.com/tcp/8302/p2p/12D3KooW123ABC... @@ -160,7 +160,7 @@ pub struct Node { /// Useful for dynamic peer discovery from a central bootstrap service. /// /// **Example URL response:** - /// ``` + /// ```text /// /ip4/bootstrap1.example.com/tcp/8302/p2p/12D3KooW... /// /ip4/bootstrap2.example.com/tcp/8302/p2p/12D3KooX... /// ``` diff --git a/macros/Cargo.toml b/macros/Cargo.toml index 2c8462a1af..57bfb73a1e 100644 --- a/macros/Cargo.toml +++ b/macros/Cargo.toml @@ -15,6 +15,7 @@ syn = { workspace = true } [dev-dependencies] mina-core = { workspace = true } +redux = { workspace = true } tracing = { workspace = true } rust-format = { workspace = true, features = ["token_stream"] } anyhow = { workspace = true } diff --git a/macros/src/action_event.md b/macros/src/action_event.md index e679299205..c9d32969c3 100644 --- a/macros/src/action_event.md +++ b/macros/src/action_event.md @@ -6,6 +6,21 @@ For action containers, it simply delegates to inner actions. ```rust # use mina_core::ActionEvent; +# extern crate redux; +# struct DummyContext { +# time: String, +# node_id: String, +# } +# impl mina_core::log::EventContext for DummyContext { +# fn timestamp(&self) -> redux::Timestamp { mina_core::log::system_time() } +# fn time(&self) -> &dyn tracing::Value { &self.time } +# fn node_id(&self) -> &dyn tracing::Value { &self.node_id } +# fn log_node_id(&self) -> bool { false } +# } +# let context = DummyContext { +# time: "0".to_string(), +# node_id: "test".to_string(), +# }; # #[derive(ActionEvent)] enum ActionContainer { @@ -17,7 +32,7 @@ enum Action1 { Done, } -ActionContainer::SubAction1(Action1::Init).action_event(context); +ActionContainer::SubAction1(Action1::Init).action_event(&context); ``` ```rust @@ -156,6 +171,8 @@ a field's enum variant), logging can be delegated to a function implementing that logic. ```rust +# fn foo(_context: &T) {} +# fn bar(_context: &T, _f1: &bool) {} #[derive(mina_core::ActionEvent)] pub enum Action { #[action_event(expr(foo(context)))] diff --git a/node/testing/src/cluster/mod.rs b/node/testing/src/cluster/mod.rs index 143ef27907..9c7e316046 100644 --- a/node/testing/src/cluster/mod.rs +++ b/node/testing/src/cluster/mod.rs @@ -17,18 +17,6 @@ //! //! - [`Cluster::add_rust_node`] - Add Rust implementation nodes //! - [`Cluster::add_ocaml_node`] - Add OCaml implementation nodes -//! -//! # Example -//! -//! ```rust,no_run -//! let mut cluster = Cluster::new(ClusterConfig::default()); -//! -//! // Add Rust node with custom configuration -//! let rust_node = cluster.add_rust_node(RustNodeTestingConfig::default()); -//! -//! // Add OCaml node for cross-implementation testing -//! let ocaml_node = cluster.add_ocaml_node(OcamlNodeTestingConfig::default()); -//! ``` mod config; pub use config::{ClusterConfig, ProofKind}; diff --git a/node/testing/src/node/ocaml/config.rs b/node/testing/src/node/ocaml/config.rs index 3348957dbe..5e6ae4617d 100644 --- a/node/testing/src/node/ocaml/config.rs +++ b/node/testing/src/node/ocaml/config.rs @@ -96,22 +96,12 @@ pub enum OcamlNodeExecutable { /// /// # Arguments /// * `String` - Path to the mina executable - /// - /// # Example - /// ``` - /// OcamlNodeExecutable::Installed("/usr/local/bin/mina".to_string()) - /// ``` Installed(String), /// Use specific Docker image /// /// # Arguments /// * `String` - Docker image tag - /// - /// # Example - /// ``` - /// OcamlNodeExecutable::Docker("minaprotocol/mina-daemon:3.0.0".to_string()) - /// ``` Docker(String), /// Use default Docker image diff --git a/node/testing/src/scenarios/driver.rs b/node/testing/src/scenarios/driver.rs index 5b81cf83f9..82c0793490 100644 --- a/node/testing/src/scenarios/driver.rs +++ b/node/testing/src/scenarios/driver.rs @@ -206,9 +206,15 @@ impl<'cluster> Driver<'cluster> { /// # Example /// /// ```no_run + /// # use std::time::Duration; + /// # use mina_node_testing::scenarios::Driver; + /// # use node::event_source::Event; + /// # async fn example(driver: &mut Driver<'_>) -> anyhow::Result<()> { /// driver.wait_for(Duration::from_secs(5), |node_id, event, state| { - /// matches!(event, Event::BlockReceived { .. }) + /// matches!(event, Event::P2p(_)) /// }).await?; + /// # Ok(()) + /// # } /// ``` pub async fn wait_for( &mut self, diff --git a/p2p/src/webrtc/connection_auth.rs b/p2p/src/webrtc/connection_auth.rs index a6765e2480..0597bed608 100644 --- a/p2p/src/webrtc/connection_auth.rs +++ b/p2p/src/webrtc/connection_auth.rs @@ -88,10 +88,17 @@ use super::{Answer, Offer}; /// ## Usage /// /// ```rust -/// use mina_p2p::webrtc::{ConnectionAuth, Offer, Answer}; -/// +/// # use p2p::webrtc::{ConnectionAuth, Offer, Answer}; +/// # use p2p::identity::{SecretKey, PublicKey}; +/// # use rand::thread_rng; +/// # fn example(offer: &Offer, answer: &Answer, +/// # my_secret_key: &SecretKey, peer_public_key: &PublicKey) +/// # -> Option<()> { +/// # let mut rng = thread_rng(); /// let connection_auth = ConnectionAuth::new(&offer, &answer); -/// let encrypted_auth = connection_auth.encrypt(&my_secret_key, &peer_public_key, rng)?; +/// let encrypted_auth = connection_auth.encrypt(&my_secret_key, &peer_public_key, &mut rng)?; +/// # Some(()) +/// # } /// ``` #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct ConnectionAuth(Vec); @@ -124,9 +131,16 @@ pub struct ConnectionAuth(Vec); /// ## Example /// /// ```rust +/// # use p2p::webrtc::ConnectionAuthEncrypted; +/// # use p2p::identity::{SecretKey, PublicKey}; +/// # fn example(encrypted_auth: &ConnectionAuthEncrypted, +/// # my_secret_key: &SecretKey, peer_public_key: &PublicKey) +/// # -> Option<()> { /// // After receiving encrypted authentication data /// let decrypted_auth = encrypted_auth.decrypt(&my_secret_key, &peer_public_key)?; /// // Verify that the decrypted data matches expected values +/// # Some(()) +/// # } /// ``` #[derive(Debug, Clone)] pub struct ConnectionAuthEncrypted(Box<[u8; 92]>); @@ -158,10 +172,11 @@ impl ConnectionAuth { /// # Example /// /// ```rust - /// use mina_p2p::webrtc::ConnectionAuth; - /// + /// # use p2p::webrtc::{ConnectionAuth, Offer, Answer}; + /// # fn example(offer: &Offer, answer: &Answer) { /// let auth = ConnectionAuth::new(&offer, &answer); /// // Use auth for connection verification + /// # } /// ``` pub fn new(offer: &Offer, answer: &Answer) -> Self { Self([offer.sdp_hash(), answer.sdp_hash()].concat()) @@ -196,14 +211,18 @@ impl ConnectionAuth { /// # Example /// /// ```rust - /// use rand::thread_rng; - /// + /// # use p2p::webrtc::ConnectionAuth; + /// # use p2p::identity::{SecretKey, PublicKey}; + /// # use rand::thread_rng; + /// # fn example(connection_auth: &ConnectionAuth, + /// # my_secret_key: &SecretKey, peer_public_key: &PublicKey) { /// let mut rng = thread_rng(); /// let encrypted_auth = connection_auth.encrypt(&my_secret_key, &peer_public_key, &mut rng); /// /// if let Some(encrypted) = encrypted_auth { /// // Send encrypted authentication data to peer /// } + /// # } /// ``` pub fn encrypt( &self, @@ -254,6 +273,10 @@ impl ConnectionAuthEncrypted { /// # Example /// /// ```rust + /// # use p2p::webrtc::ConnectionAuthEncrypted; + /// # use p2p::identity::{SecretKey, PublicKey}; + /// # fn example(encrypted_auth: &ConnectionAuthEncrypted, + /// # my_secret_key: &SecretKey, peer_public_key: &PublicKey) { /// // After receiving encrypted authentication data from peer /// if let Some(decrypted_auth) = encrypted_auth.decrypt(&my_secret_key, &peer_public_key) { /// // Authentication successful, proceed with connection @@ -262,6 +285,7 @@ impl ConnectionAuthEncrypted { /// // Authentication failed, reject connection /// println!("Peer authentication failed"); /// } + /// # } /// ``` pub fn decrypt(&self, sec_key: &SecretKey, other_pk: &PublicKey) -> Option { sec_key diff --git a/p2p/src/webrtc/signaling_method/http.rs b/p2p/src/webrtc/signaling_method/http.rs index 65fa14f83a..67e9df8ab5 100644 --- a/p2p/src/webrtc/signaling_method/http.rs +++ b/p2p/src/webrtc/signaling_method/http.rs @@ -59,9 +59,8 @@ use super::SignalingMethodParseError; /// # Examples /// /// ``` -/// use mina::webrtc::Host; -/// use mina::signaling_method::HttpSignalingInfo; -/// +/// # use p2p::webrtc::{Host, HttpSignalingInfo}; +/// # fn example() -> Result<(), Box> { /// // IPv4 signaling server /// let info = HttpSignalingInfo { /// host: Host::Ipv4("192.168.1.100".parse()?), @@ -73,6 +72,8 @@ use super::SignalingMethodParseError; /// host: Host::Domain("signal.example.com".into()), /// port: 443, /// }; +/// # Ok(()) +/// # } /// ``` #[derive(BinProtWrite, BinProtRead, Eq, PartialEq, Ord, PartialOrd, Debug, Clone)] pub struct HttpSignalingInfo { @@ -119,6 +120,7 @@ impl From<([u8; 4], u16)> for HttpSignalingInfo { /// # Example /// /// ``` + /// # use p2p::webrtc::HttpSignalingInfo; /// let info = HttpSignalingInfo::from(([192, 168, 1, 100], 8080)); /// assert_eq!(info.port, 8080); /// ``` @@ -148,8 +150,8 @@ impl FromStr for HttpSignalingInfo { /// # Examples /// /// ``` - /// use mina::signaling_method::HttpSignalingInfo; - /// + /// # use p2p::webrtc::HttpSignalingInfo; + /// # fn example() -> Result<(), Box> { /// // Domain and port /// let info: HttpSignalingInfo = "signal.example.com/443".parse()?; /// @@ -158,6 +160,8 @@ impl FromStr for HttpSignalingInfo { /// /// // With leading slash /// let info: HttpSignalingInfo = "/localhost/8080".parse()?; + /// # Ok(()) + /// # } /// ``` /// /// # Errors diff --git a/p2p/src/webrtc/signaling_method/mod.rs b/p2p/src/webrtc/signaling_method/mod.rs index 32f1656e4d..e65d7fc430 100644 --- a/p2p/src/webrtc/signaling_method/mod.rs +++ b/p2p/src/webrtc/signaling_method/mod.rs @@ -80,11 +80,16 @@ use crate::PeerId; /// # Example /// /// ``` +/// # use p2p::webrtc::SignalingMethod; +/// # use p2p::PeerId; +/// # fn example(peer_id: PeerId) -> Result<(), Box> { /// // Direct HTTPS signaling /// let method = "/https/signal.example.com/443".parse::()?; /// /// // P2P relay through an existing peer /// let method = SignalingMethod::P2p { relay_peer_id: peer_id }; +/// # Ok(()) +/// # } /// ``` #[derive(BinProtWrite, BinProtRead, Eq, PartialEq, Ord, PartialOrd, Debug, Clone)] pub enum SignalingMethod { @@ -158,8 +163,15 @@ impl SignalingMethod { /// # Example /// /// ``` + /// # use p2p::webrtc::{SignalingMethod, HttpSignalingInfo, Host}; + /// # fn example() { + /// # let info = HttpSignalingInfo { + /// # host: Host::Domain("signal.example.com".into()), + /// # port: 443, + /// # }; /// let method = SignalingMethod::Https(info); /// let url = method.http_url(); // Some("https://signal.example.com:443/mina/webrtc/signal") + /// # } /// ``` pub fn http_url(&self) -> Option { let (http, info) = match self { @@ -305,8 +317,8 @@ impl FromStr for SignalingMethod { /// # Examples /// /// ``` - /// use mina::signaling_method::SignalingMethod; - /// + /// # use p2p::webrtc::SignalingMethod; + /// # fn example() -> Result<(), Box> { /// // HTTP signaling /// let method: SignalingMethod = "/http/localhost/8080".parse()?; /// @@ -315,6 +327,8 @@ impl FromStr for SignalingMethod { /// /// // HTTPS proxy with cluster ID /// let method: SignalingMethod = "/https_proxy/123/proxy.example.com/443".parse()?; + /// # Ok(()) + /// # } /// ``` /// /// # Errors diff --git a/p2p/testing/src/cluster.rs b/p2p/testing/src/cluster.rs index b17266b427..771e653453 100644 --- a/p2p/testing/src/cluster.rs +++ b/p2p/testing/src/cluster.rs @@ -229,19 +229,6 @@ impl Default for Ports { } /// Declares a shared storage for ports. -/// -/// ``` -/// ports_store!(GLOBAL_PORTS); -/// -/// #[tokio::test] -/// fn test1() { -/// let cluster = ClusterBuilder::default() -/// .ports(GLOBAL_PORTS.take(20).await.expect("enough ports")) -/// .start() -/// .await; -/// } -/// -/// ``` #[macro_export] macro_rules! ports_store { ($name:ident, $range:expr) => { diff --git a/snark/src/lib.rs b/snark/src/lib.rs index bf1e55c2c8..4650f5ec14 100644 --- a/snark/src/lib.rs +++ b/snark/src/lib.rs @@ -56,19 +56,6 @@ //! since Berkeley. //! - **Node**: Provides verification services to the main node //! -//! ## Example Usage -//! -//! ```rust,no_run -//! use snark::{SnarkConfig, SnarkState}; -//! -//! // Initialize SNARK state with configuration -//! let config = SnarkConfig { /* ... */ }; -//! let state = SnarkState::new(config); -//! -//! // The state machine handles verification requests through actions -//! // dispatched by the main node's Redux store -//! ``` -//! //! ## Performance Considerations //! //! - Verifier indices and SRS parameters are cached for reuse