From 304a66311aeb80122f711362c952c0dc34962c27 Mon Sep 17 00:00:00 2001 From: Lorenz Leutgeb Date: Mon, 16 Mar 2026 13:34:42 +0100 Subject: [PATCH] radicle: Remove generics for verification markers `SignedRefs` are now always verified. --- crates/radicle-fetch/src/sigrefs.rs | 2 +- crates/radicle-fetch/src/state.rs | 3 +- crates/radicle/src/rad.rs | 5 +- crates/radicle/src/storage.rs | 63 ++++++++----------- crates/radicle/src/storage/git.rs | 18 +++--- crates/radicle/src/storage/git/cob.rs | 10 +-- crates/radicle/src/storage/refs.rs | 25 +++----- crates/radicle/src/storage/refs/arbitrary.rs | 1 - .../radicle/src/storage/refs/sigrefs/write.rs | 2 - crates/radicle/src/test/fixtures.rs | 12 +--- crates/radicle/src/test/storage.rs | 9 ++- 11 files changed, 55 insertions(+), 95 deletions(-) diff --git a/crates/radicle-fetch/src/sigrefs.rs b/crates/radicle-fetch/src/sigrefs.rs index 77c7c15c..69d4bd8a 100644 --- a/crates/radicle-fetch/src/sigrefs.rs +++ b/crates/radicle-fetch/src/sigrefs.rs @@ -93,7 +93,7 @@ pub(crate) fn validate( repo: &impl ValidateRepository, SignedRefsAt { sigrefs, .. }: SignedRefsAt, ) -> Result, radicle::storage::Error> { - let remote = radicle::storage::Remote::::new(sigrefs); + let remote = radicle::storage::Remote::new(sigrefs); let validations = repo.validate_remote(&remote)?; Ok(validations.is_empty().not().then_some(validations)) } diff --git a/crates/radicle-fetch/src/state.rs b/crates/radicle-fetch/src/state.rs index fc75ef61..94f605bf 100644 --- a/crates/radicle-fetch/src/state.rs +++ b/crates/radicle-fetch/src/state.rs @@ -6,7 +6,6 @@ use radicle::crypto::PublicKey; use radicle::git::{fmt::Qualified, Oid}; use radicle::identity::{Did, Doc, DocError}; -use radicle::prelude::Verified; use radicle::storage; use radicle::storage::git::Repository; use radicle::storage::refs::RefsAt; @@ -709,7 +708,7 @@ where self.handle.repository().remote(remote) } - fn remotes(&self) -> Result, storage::refs::Error> { + fn remotes(&self) -> Result { self.state .sigrefs .keys() diff --git a/crates/radicle/src/rad.rs b/crates/radicle/src/rad.rs index fdc91be0..9e49c22d 100644 --- a/crates/radicle/src/rad.rs +++ b/crates/radicle/src/rad.rs @@ -7,7 +7,6 @@ use std::sync::LazyLock; use thiserror::Error; use crate::cob::ObjectId; -use crate::crypto::Verified; use crate::git; use crate::git::BranchName; use crate::identity::doc; @@ -56,7 +55,7 @@ pub fn init( visibility: Visibility, signer: &Device, storage: S, -) -> Result<(RepoId, identity::Doc, SignedRefs), InitError> +) -> Result<(RepoId, identity::Doc, SignedRefs), InitError> where G: crypto::signature::Signer, S: WriteStorage, @@ -103,7 +102,7 @@ fn init_configure( url: &git::Url, identity: git::Oid, signer: &Device, -) -> Result, InitError> +) -> Result where G: crypto::signature::Signer, { diff --git a/crates/radicle/src/storage.rs b/crates/radicle/src/storage.rs index e36498f1..8c7c50d5 100644 --- a/crates/radicle/src/storage.rs +++ b/crates/radicle/src/storage.rs @@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize}; use thiserror::Error; pub use crate::git::Oid; -use crypto::{PublicKey, Unverified, Verified}; +use crypto::PublicKey; pub use git::{Validation, Validations}; use crate::cob; @@ -313,46 +313,40 @@ impl fmt::Display for RefUpdate { } /// Project remotes. Tracks the git state of a project. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct Remotes(RandomMap>); +#[derive(Debug, Clone, PartialEq, Eq, Default)] +pub struct Remotes(RandomMap); -impl FromIterator<(RemoteId, Remote)> for Remotes { - fn from_iter)>>(iter: T) -> Self { +impl FromIterator<(RemoteId, Remote)> for Remotes { + fn from_iter>(iter: T) -> Self { Self(iter.into_iter().collect()) } } -impl Deref for Remotes { - type Target = RandomMap>; +impl Deref for Remotes { + type Target = RandomMap; fn deref(&self) -> &Self::Target { &self.0 } } -impl Remotes { - pub fn new(remotes: RandomMap>) -> Self { +impl Remotes { + pub fn new(remotes: RandomMap) -> Self { Self(remotes) } } -impl Default for Remotes { - fn default() -> Self { - Self(RandomMap::default()) - } -} - -impl IntoIterator for Remotes { - type Item = (RemoteId, Remote); - type IntoIter = hash_map::IntoIter>; +impl IntoIterator for Remotes { + type Item = (RemoteId, Remote); + type IntoIter = hash_map::IntoIter; fn into_iter(self) -> Self::IntoIter { self.0.into_iter() } } -impl From> for RandomMap { - fn from(other: Remotes) -> Self { +impl From for RandomMap { + fn from(other: Remotes) -> Self { let mut remotes = RandomMap::with_hasher(fastrand::Rng::new().into()); for (k, v) in other.into_iter() { @@ -364,22 +358,15 @@ impl From> for RandomMap { /// A project remote. #[derive(Debug, Clone, PartialEq, Eq, Serialize)] -pub struct Remote { +pub struct Remote { /// Git references published under this remote, and their hashes. #[serde(flatten)] - pub refs: SignedRefs, + pub refs: SignedRefs, } -impl Remote { - /// Create a new unverified remotes object. - pub fn new(refs: impl Into>) -> Self { - Self { refs: refs.into() } - } -} - -impl Remote { - /// Create a new unverified remotes object. - pub fn new(refs: impl Into>) -> Self { +impl Remote { + /// Create a new remotes object. + pub fn new(refs: impl Into) -> Self { Self { refs: refs.into() } } @@ -400,8 +387,8 @@ impl Remote { } } -impl Deref for Remote { - type Target = SignedRefs; +impl Deref for Remote { + type Target = SignedRefs; fn deref(&self) -> &Self::Target { &self.refs @@ -605,10 +592,10 @@ pub trait ReadRepository: Sized + ValidateRepository { /// Access the remotes of a repository. pub trait RemoteRepository { /// Get the given remote. - fn remote(&self, remote: &RemoteId) -> Result, refs::Error>; + fn remote(&self, remote: &RemoteId) -> Result; /// Get all remotes. - fn remotes(&self) -> Result, refs::Error>; + fn remotes(&self) -> Result; /// Get [`RefsAt`] of all remotes. fn remote_refs_at(&self) -> Result, refs::Error>; @@ -631,7 +618,7 @@ where /// /// Returns any ref found under that remote that isn't signed. /// If a signed ref is missing from the repository, an error is returned. - fn validate_remote(&self, remote: &Remote) -> Result; + fn validate_remote(&self, remote: &Remote) -> Result; } /// Allows read-write access to a repository. @@ -670,7 +657,7 @@ pub trait WriteRepository: ReadRepository + SignRepository { /// Allows signing refs. pub trait SignRepository { /// Sign the repository's refs under the `refs/rad/sigrefs` branch. - fn sign_refs(&self, signer: &Device) -> Result, RepositoryError> + fn sign_refs(&self, signer: &Device) -> Result where G: crypto::signature::Signer; } diff --git a/crates/radicle/src/storage/git.rs b/crates/radicle/src/storage/git.rs index b6b1d3cb..0bbf8113 100644 --- a/crates/radicle/src/storage/git.rs +++ b/crates/radicle/src/storage/git.rs @@ -11,8 +11,6 @@ use std::path::{Path, PathBuf}; use std::sync::LazyLock; use std::{fs, io}; -use crypto::Verified; - use crate::git::canonical::Quorum; use crate::git::raw::ErrorExt as _; use crate::identity::crefs::GetCanonicalRefs as _; @@ -590,10 +588,8 @@ impl Repository { pub fn remotes( &self, - ) -> Result< - impl Iterator), refs::Error>> + '_, - git::raw::Error, - > { + ) -> Result> + '_, git::raw::Error> + { let remotes = self.backend .references_glob(SIGREFS_GLOB.as_str())? @@ -610,7 +606,7 @@ impl Repository { } impl RemoteRepository for Repository { - fn remotes(&self) -> Result, refs::Error> { + fn remotes(&self) -> Result { let mut remotes = Vec::new(); for remote in Repository::remotes(self)? { remotes.push(remote?); @@ -618,9 +614,9 @@ impl RemoteRepository for Repository { Ok(Remotes::from_iter(remotes)) } - fn remote(&self, remote: &RemoteId) -> Result, refs::Error> { + fn remote(&self, remote: &RemoteId) -> Result { let refs = SignedRefs::load(*remote, self)?; - Ok(Remote::::new(refs)) + Ok(Remote::new(refs)) } fn remote_refs_at(&self) -> Result, refs::Error> { @@ -637,7 +633,7 @@ impl RemoteRepository for Repository { } impl ValidateRepository for Repository { - fn validate_remote(&self, remote: &Remote) -> Result { + fn validate_remote(&self, remote: &Remote) -> Result { // Contains a copy of the signed refs of this remote. let mut signed = BTreeMap::from((*remote.refs).clone()); let mut failures = Validations::default(); @@ -990,7 +986,7 @@ impl SignRepository for Repository { fn sign_refs>( &self, signer: &Device, - ) -> Result, RepositoryError> { + ) -> Result { let remote = signer.public_key(); // Ensure the root reference is set, which is checked during sigref verification. if self diff --git a/crates/radicle/src/storage/git/cob.rs b/crates/radicle/src/storage/git/cob.rs index 4676c315..39a29a7d 100644 --- a/crates/radicle/src/storage/git/cob.rs +++ b/crates/radicle/src/storage/git/cob.rs @@ -22,7 +22,7 @@ use crate::storage; use crate::storage::Error; use crate::storage::{ git::{Remote, Remotes, Validations}, - ReadRepository, Verified, + ReadRepository, }; use super::{RemoteId, Repository}; @@ -239,7 +239,7 @@ where fn sign_refs>( &self, signer: &Device, - ) -> Result, RepositoryError> { + ) -> Result { // Since this is a draft store, we do not actually want to sign the refs. // Instead, we just return the existing signed refs. let remote = self.repo.remote(signer.public_key())?; @@ -249,11 +249,11 @@ where } impl RemoteRepository for DraftStore<'_, R> { - fn remote(&self, id: &RemoteId) -> Result, storage::refs::Error> { + fn remote(&self, id: &RemoteId) -> Result { self.repo.remote(id) } - fn remotes(&self) -> Result, storage::refs::Error> { + fn remotes(&self) -> Result { RemoteRepository::remotes(self.repo) } @@ -263,7 +263,7 @@ impl RemoteRepository for DraftStore<'_, R> { } impl ValidateRepository for DraftStore<'_, R> { - fn validate_remote(&self, remote: &Remote) -> Result { + fn validate_remote(&self, remote: &Remote) -> Result { self.repo.validate_remote(remote) } } diff --git a/crates/radicle/src/storage/refs.rs b/crates/radicle/src/storage/refs.rs index c9ad6cd3..510fec79 100644 --- a/crates/radicle/src/storage/refs.rs +++ b/crates/radicle/src/storage/refs.rs @@ -7,12 +7,11 @@ use std::collections::BTreeMap; use std::fmt::Debug; use std::io; use std::io::{BufRead, BufReader}; -use std::marker::PhantomData; use std::ops::Deref; use std::str::FromStr; use crypto::signature; -use crypto::{PublicKey, Signature, Verified}; +use crypto::{PublicKey, Signature}; use radicle_core::NodeId; use serde::{Deserialize, Serialize}; use thiserror::Error; @@ -99,7 +98,6 @@ impl Refs { refs, signature, id: namespace, - _verified: PhantomData, }; Ok(SignedRefsAt { sigrefs, @@ -227,8 +225,8 @@ impl From for BTreeMap { } } -impl From> for Refs { - fn from(signed: SignedRefs) -> Self { +impl From for Refs { + fn from(signed: SignedRefs) -> Self { signed.refs } } @@ -249,10 +247,8 @@ where /// Combination of [`Refs`] and a [`Signature`]. The signature is a cryptographic /// signature over the refs. This allows us to easily verify if a set of refs /// came from a particular key. -/// -/// The type parameter keeps track of whether the signature was [`Verified`]. #[derive(Debug, Clone, PartialEq, Eq, Serialize)] -pub struct SignedRefs { +pub struct SignedRefs { /// The signed refs. refs: Refs, /// The signature of the signer over the refs. @@ -260,12 +256,9 @@ pub struct SignedRefs { signature: Signature, /// This is the remote under which these refs exist, and the public key of the signer. id: PublicKey, - - #[serde(skip)] - _verified: PhantomData, } -impl SignedRefs { +impl SignedRefs { /// Returns the [`NodeId`] of the [`SignedRefs`]. pub fn id(&self) -> NodeId { self.id @@ -290,7 +283,6 @@ impl SignedRefs { refs, signature, id: remote, - _verified: PhantomData, }) } @@ -312,12 +304,11 @@ impl SignedRefs { refs, signature, id: remote, - _verified: PhantomData, }) } } -impl Deref for SignedRefs { +impl Deref for SignedRefs { type Target = Refs; fn deref(&self) -> &Self::Target { @@ -379,7 +370,7 @@ impl std::fmt::Display for RefsAt { /// [`Oid`]. #[derive(Debug, Clone, PartialEq, Eq)] pub struct SignedRefsAt { - pub sigrefs: SignedRefs, + pub sigrefs: SignedRefs, pub at: Oid, } @@ -423,7 +414,7 @@ impl SignedRefsAt { } impl Deref for SignedRefsAt { - type Target = SignedRefs; + type Target = SignedRefs; fn deref(&self) -> &Self::Target { &self.sigrefs diff --git a/crates/radicle/src/storage/refs/arbitrary.rs b/crates/radicle/src/storage/refs/arbitrary.rs index a4a37be1..c5307ccb 100644 --- a/crates/radicle/src/storage/refs/arbitrary.rs +++ b/crates/radicle/src/storage/refs/arbitrary.rs @@ -23,7 +23,6 @@ where refs, signature, id: *signer.node_id(), - _verified: PhantomData, }; SignedRefsAt { sigrefs, diff --git a/crates/radicle/src/storage/refs/sigrefs/write.rs b/crates/radicle/src/storage/refs/sigrefs/write.rs index fae8d687..7ee27dc8 100644 --- a/crates/radicle/src/storage/refs/sigrefs/write.rs +++ b/crates/radicle/src/storage/refs/sigrefs/write.rs @@ -3,7 +3,6 @@ pub mod error; #[cfg(test)] mod test; -use std::marker::PhantomData; use std::path::Path; use crypto::signature::Signer; @@ -176,7 +175,6 @@ impl Commit { id, signature: self.signature, refs: self.refs, - _verified: PhantomData, }, } } diff --git a/crates/radicle/src/test/fixtures.rs b/crates/radicle/src/test/fixtures.rs index 33c930d8..bb80e6bc 100644 --- a/crates/radicle/src/test/fixtures.rs +++ b/crates/radicle/src/test/fixtures.rs @@ -1,7 +1,7 @@ use std::path::Path; use std::str::FromStr; -use crate::crypto::{PublicKey, Verified}; +use crate::crypto::PublicKey; use crate::git; use crate::identity::doc::Visibility; use crate::identity::RepoId; @@ -72,15 +72,7 @@ pub fn project( path: P, storage: &Storage, signer: &Device, -) -> Result< - ( - RepoId, - SignedRefs, - git::raw::Repository, - git::raw::Oid, - ), - rad::InitError, -> +) -> Result<(RepoId, SignedRefs, git::raw::Repository, git::raw::Oid), rad::InitError> where P: AsRef, G: crypto::signature::Signer, diff --git a/crates/radicle/src/test/storage.rs b/crates/radicle/src/test/storage.rs index c8ca919a..3364c434 100644 --- a/crates/radicle/src/test/storage.rs +++ b/crates/radicle/src/test/storage.rs @@ -9,7 +9,6 @@ use crypto::PublicKey; pub use crate::git; use crate::git::fmt; -use crate::crypto::Verified; use crate::identity::doc::{Doc, DocAt, DocError, RawDoc, RepoId}; use crate::node::device::Device; use crate::node::NodeId; @@ -179,7 +178,7 @@ impl self::refs::sigrefs::git::reference::Reader for MockRepository { } impl RemoteRepository for MockRepository { - fn remote(&self, id: &RemoteId) -> Result, refs::Error> { + fn remote(&self, id: &RemoteId) -> Result { self.remotes .get(id) .map(|refs| Remote { @@ -188,7 +187,7 @@ impl RemoteRepository for MockRepository { .ok_or(refs::Error::InvalidRef) } - fn remotes(&self) -> Result, refs::Error> { + fn remotes(&self) -> Result { Ok(self .remotes .iter() @@ -216,7 +215,7 @@ impl RemoteRepository for MockRepository { } impl ValidateRepository for MockRepository { - fn validate_remote(&self, _remote: &Remote) -> Result { + fn validate_remote(&self, _remote: &Remote) -> Result { Ok(Validations::default()) } } @@ -380,7 +379,7 @@ impl SignRepository for MockRepository { fn sign_refs>( &self, _signer: &Device, - ) -> Result, RepositoryError> { + ) -> Result { todo!() } }