From faeee9f3701869fa927f3dd8b9c3406690e46556 Mon Sep 17 00:00:00 2001 From: Lorenz Leutgeb Date: Thu, 9 Oct 2025 23:52:30 +0200 Subject: [PATCH] crypto: Optionally provide JSON Schema Providing the schema in `radicle-crypto` saves a lot of repetition in `radicle`, and can be done via an optional dependency. --- Cargo.lock | 1 + crates/radicle-crypto/Cargo.toml | 1 + crates/radicle-crypto/src/lib.rs | 14 ++++++++++ crates/radicle-schemars/src/main.rs | 5 +--- crates/radicle/Cargo.toml | 1 + crates/radicle/src/node.rs | 12 --------- crates/radicle/src/node/command.rs | 40 +++-------------------------- crates/radicle/src/schemars_ext.rs | 23 ----------------- crates/radicle/src/storage/refs.rs | 4 --- 9 files changed, 21 insertions(+), 80 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1adcab8e..fa9043f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2959,6 +2959,7 @@ dependencies = [ "qcheck", "qcheck-macros", "radicle-ssh", + "schemars", "serde", "signature 2.2.0", "sqlite", diff --git a/crates/radicle-crypto/Cargo.toml b/crates/radicle-crypto/Cargo.toml index 58f945e0..ed706d0f 100644 --- a/crates/radicle-crypto/Cargo.toml +++ b/crates/radicle-crypto/Cargo.toml @@ -25,6 +25,7 @@ multibase = { workspace = true } qcheck = { workspace = true, optional = true } git-ref-format-core = { workspace = true, optional = true } radicle-ssh = { workspace = true, optional = true } +schemars = { workspace = true, optional = true, features = ["derive", "std"] } serde = { workspace = true, features = ["derive", "std"] } signature = { workspace = true } sqlite = { workspace = true, features = ["bundled"], optional = true } diff --git a/crates/radicle-crypto/src/lib.rs b/crates/radicle-crypto/src/lib.rs index b0a28eff..7c7c43cb 100644 --- a/crates/radicle-crypto/src/lib.rs +++ b/crates/radicle-crypto/src/lib.rs @@ -158,6 +158,20 @@ impl TryFrom for Signature { /// The public/verification key. #[derive(Hash, Serialize, Deserialize, PartialEq, Eq, Copy, Clone)] #[serde(into = "String", try_from = "String")] +#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] +#[cfg_attr( + feature = "schemars", + schemars( + title = "Ed25519", + description = "An Ed25519 public key in multibase encoding.", + extend("examples" = [ + "z6MkrLMMsiPWUcNPHcRajuMi9mDfYckSoJyPwwnknocNYPm7", + "z6MkvUJtYD9dHDJfpevWRT98mzDDpdAtmUjwyDSkyqksUr7C", + "z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi", + "z6MkkfM3tPXNPrPevKr3uSiQtHPuwnNhu2yUVjgd2jXVsVz5", + ]), + ), +)] pub struct PublicKey(pub ed25519::PublicKey); #[cfg(feature = "cyphernet")] diff --git a/crates/radicle-schemars/src/main.rs b/crates/radicle-schemars/src/main.rs index 511e3c52..be51c7bd 100644 --- a/crates/radicle-schemars/src/main.rs +++ b/crates/radicle-schemars/src/main.rs @@ -83,10 +83,7 @@ fn print_schema() -> io::Result<()> { #[schemars(untagged)] #[allow(dead_code)] enum CommandResult { - Nid( - #[schemars(with = "radicle::schemars_ext::crypto::PublicKey")] - radicle::node::NodeId, - ), + Nid(radicle::node::NodeId), Config(Box), ListenAddrs(ListenAddrs), ConnectResult(radicle::node::ConnectResult), diff --git a/crates/radicle/Cargo.toml b/crates/radicle/Cargo.toml index d7dab007..b33f07ca 100644 --- a/crates/radicle/Cargo.toml +++ b/crates/radicle/Cargo.toml @@ -20,6 +20,7 @@ qcheck = [ schemars = [ "radicle-oid/schemars", "radicle-core/schemars", + "radicle-crypto/schemars", "radicle-localtime/schemars", "dep:schemars" ] diff --git a/crates/radicle/src/node.rs b/crates/radicle/src/node.rs index a4291f6d..c9623890 100644 --- a/crates/radicle/src/node.rs +++ b/crates/radicle/src/node.rs @@ -553,10 +553,6 @@ impl std::fmt::Display for Link { #[derive(Debug, Clone, Serialize, Deserialize)] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct Session { - #[cfg_attr( - feature = "schemars", - schemars(with = "crate::schemars_ext::crypto::PublicKey") - )] pub nid: NodeId, pub link: Link, pub addr: Address, @@ -576,10 +572,6 @@ impl Session { #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct Seed { /// The Node ID. - #[cfg_attr( - feature = "schemars", - schemars(with = "crate::schemars_ext::crypto::PublicKey") - )] pub nid: NodeId, /// Known addresses for this seed. pub addrs: Vec, @@ -700,10 +692,6 @@ impl From> for Seeds { pub enum FetchResult { Success { updated: Vec, - #[cfg_attr( - feature = "schemars", - schemars(with = "HashSet") - )] namespaces: HashSet, clone: bool, }, diff --git a/crates/radicle/src/node/command.rs b/crates/radicle/src/node/command.rs index 1999626b..55ace68b 100644 --- a/crates/radicle/src/node/command.rs +++ b/crates/radicle/src/node/command.rs @@ -40,10 +40,6 @@ pub enum Command { rid: RepoId, /// The namespaces for which references should be announced. - #[cfg_attr( - feature = "schemars", - schemars(with = "HashSet") - )] namespaces: HashSet, }, @@ -69,13 +65,7 @@ pub enum Command { /// Disconnect from a node. #[serde(rename_all = "camelCase")] - Disconnect { - #[cfg_attr( - feature = "schemars", - schemars(with = "crate::schemars_ext::crypto::PublicKey") - )] - nid: NodeId, - }, + Disconnect { nid: NodeId }, /// Look up seeds for the given repository in the routing table. #[serde(rename_all = "camelCase")] @@ -91,10 +81,6 @@ pub enum Command { rid: RepoId, /// The namespaces for which references should be announced. - #[cfg_attr( - feature = "schemars", - schemars(with = "HashSet") - )] namespaces: HashSet, }, @@ -102,22 +88,12 @@ pub enum Command { Sessions, /// Get a specific peer session. - Session { - #[cfg_attr( - feature = "schemars", - schemars(with = "crate::schemars_ext::crypto::PublicKey") - )] - nid: NodeId, - }, + Session { nid: NodeId }, /// Fetch the given repository from the network. #[serde(rename_all = "camelCase")] Fetch { rid: RepoId, - #[cfg_attr( - feature = "schemars", - schemars(with = "crate::schemars_ext::crypto::PublicKey") - )] nid: NodeId, timeout: time::Duration, }, @@ -136,23 +112,13 @@ pub enum Command { /// Follow the given node. #[serde(rename_all = "camelCase")] Follow { - #[cfg_attr( - feature = "schemars", - schemars(with = "crate::schemars_ext::crypto::PublicKey") - )] nid: NodeId, alias: Option, }, /// Unfollow the given node. #[serde(rename_all = "camelCase")] - Unfollow { - #[cfg_attr( - feature = "schemars", - schemars(with = "crate::schemars_ext::crypto::PublicKey") - )] - nid: NodeId, - }, + Unfollow { nid: NodeId }, /// Get the node's status. Status, diff --git a/crates/radicle/src/schemars_ext.rs b/crates/radicle/src/schemars_ext.rs index 5186fd23..dd68f149 100644 --- a/crates/radicle/src/schemars_ext.rs +++ b/crates/radicle/src/schemars_ext.rs @@ -4,29 +4,6 @@ use schemars::JsonSchema; -pub mod crypto { - use super::*; - /// See [`crate::node::NodeId`] - /// See [`crate::storage::RemoteId`] - /// See [`::crypto::PublicKey`] - /// - /// An Ed25519 public key in multibase encoding. - /// - /// `MULTIBASE(base58-btc, MULTICODEC(public-key-type, raw-public-key-bytes))` - #[derive(JsonSchema)] - #[schemars( - title = "NodeId", - description = "An Ed25519 public key in multibase encoding.", - extend("examples" = [ - "z6MkrLMMsiPWUcNPHcRajuMi9mDfYckSoJyPwwnknocNYPm7", - "z6MkvUJtYD9dHDJfpevWRT98mzDDpdAtmUjwyDSkyqksUr7C", - "z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi", - "z6MkkfM3tPXNPrPevKr3uSiQtHPuwnNhu2yUVjgd2jXVsVz5", - ]), -)] - pub struct PublicKey(String); -} - pub(crate) mod log { use super::*; diff --git a/crates/radicle/src/storage/refs.rs b/crates/radicle/src/storage/refs.rs index 6ab4626c..e5d2a1e0 100644 --- a/crates/radicle/src/storage/refs.rs +++ b/crates/radicle/src/storage/refs.rs @@ -376,10 +376,6 @@ impl Deref for SignedRefs { #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct RefsAt { /// The remote namespace of the `rad/sigrefs`. - #[cfg_attr( - feature = "schemars", - schemars(with = "crate::schemars_ext::crypto::PublicKey") - )] pub remote: RemoteId, /// The commit SHA that `rad/sigrefs` points to. pub at: Oid,