cob: Parametrize `Change` with single signature
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
This commit is contained in:
parent
2230c8ddc4
commit
1a5b68c2b3
|
|
@ -64,6 +64,10 @@ pub mod error {
|
|||
NoChange(Oid),
|
||||
#[error("the 'change' found at '{0}' was not a blob")]
|
||||
ChangeNotBlob(Oid),
|
||||
#[error("the 'change' found at '{0}' was not signed")]
|
||||
ChangeNotSigned(Oid),
|
||||
#[error("the 'change' found at '{0}' has more than one signature")]
|
||||
TooManySignatures(Oid),
|
||||
#[error(transparent)]
|
||||
AuthorTrailer(#[from] trailers::error::InvalidAuthorTrailer),
|
||||
#[error(transparent)]
|
||||
|
|
@ -82,7 +86,7 @@ impl change::Storage for git2::Repository {
|
|||
type ObjectId = Oid;
|
||||
type Author = Oid;
|
||||
type Resource = Oid;
|
||||
type Signatures = Signatures;
|
||||
type Signatures = Signature;
|
||||
|
||||
fn create<Signer>(
|
||||
&self,
|
||||
|
|
@ -127,7 +131,7 @@ impl change::Storage for git2::Repository {
|
|||
Ok(Change {
|
||||
id,
|
||||
revision: revision.into(),
|
||||
signatures: signature.into(),
|
||||
signature,
|
||||
author,
|
||||
resource,
|
||||
manifest,
|
||||
|
|
@ -138,7 +142,15 @@ impl change::Storage for git2::Repository {
|
|||
fn load(&self, id: Self::ObjectId) -> Result<Change, Self::LoadError> {
|
||||
let commit = Commit::read(self, id.into())?;
|
||||
let (author, resource) = parse_trailers(commit.trailers())?;
|
||||
let signatures = Signatures::try_from(&commit)?;
|
||||
let mut signatures = Signatures::try_from(&commit)?
|
||||
.into_iter()
|
||||
.collect::<Vec<_>>();
|
||||
let Some(signature) = signatures.pop() else {
|
||||
return Err(error::Load::ChangeNotSigned(id));
|
||||
};
|
||||
if !signatures.is_empty() {
|
||||
return Err(error::Load::TooManySignatures(id));
|
||||
}
|
||||
|
||||
let tree = self.find_tree(commit.tree())?;
|
||||
let manifest = load_manifest(self, &tree)?;
|
||||
|
|
@ -147,7 +159,7 @@ impl change::Storage for git2::Repository {
|
|||
Ok(Change {
|
||||
id,
|
||||
revision: tree.id().into(),
|
||||
signatures,
|
||||
signature: signature.into(),
|
||||
author,
|
||||
resource,
|
||||
manifest,
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ use git_ext::Oid;
|
|||
pub mod store;
|
||||
pub use store::{Create, Storage};
|
||||
|
||||
use crate::signatures::Signatures;
|
||||
use crate::signatures::Signature;
|
||||
|
||||
/// A single change in the change graph. The layout of changes in the repository
|
||||
/// is specified in the RFC (docs/rfc/0662-collaborative-objects.adoc)
|
||||
/// under "Change Commits".
|
||||
pub type Change = store::Change<Oid, Oid, Oid, Signatures>;
|
||||
pub type Change = store::Change<Oid, Oid, Oid, Signature>;
|
||||
|
|
|
|||
|
|
@ -54,14 +54,14 @@ pub struct Create<Id> {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Change<Author, Resource, Id, Signatures> {
|
||||
pub struct Change<Author, Resource, Id, Signature> {
|
||||
/// The content address of the `Change` itself.
|
||||
pub id: Id,
|
||||
/// The content address of the tree of the `Change`.
|
||||
pub revision: Id,
|
||||
/// The cryptographic signatures and their public keys of the
|
||||
/// The cryptographic signature(s) and their public keys of the
|
||||
/// authors.
|
||||
pub signatures: Signatures,
|
||||
pub signature: Signature,
|
||||
/// The author of this change. The `Author` is expected to be a
|
||||
/// content address to look up the identity of the author.
|
||||
pub author: Option<Author>,
|
||||
|
|
@ -111,12 +111,21 @@ where
|
|||
Id: AsRef<[u8]>,
|
||||
{
|
||||
pub fn valid_signatures(&self) -> bool {
|
||||
self.signatures
|
||||
self.signature
|
||||
.iter()
|
||||
.all(|(key, sig)| key.verify(self.revision.as_ref(), sig).is_ok())
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, R, Id> Change<A, R, Id, signatures::Signature>
|
||||
where
|
||||
Id: AsRef<[u8]>,
|
||||
{
|
||||
pub fn valid_signatures(&self) -> bool {
|
||||
self.signature.verify(self.revision.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Manifest {
|
||||
/// The name given to the type of collaborative object.
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ use petgraph::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
change, object, signatures::Signatures, Change, CollaborativeObject, ObjectId, TypeName,
|
||||
change, object, signatures::Signature, Change, CollaborativeObject, ObjectId, TypeName,
|
||||
};
|
||||
|
||||
mod evaluation;
|
||||
|
|
@ -37,7 +37,7 @@ impl ChangeGraph {
|
|||
oid: &ObjectId,
|
||||
) -> Option<ChangeGraph>
|
||||
where
|
||||
S: change::Storage<ObjectId = Oid, Author = Oid, Resource = Oid, Signatures = Signatures>,
|
||||
S: change::Storage<ObjectId = Oid, Author = Oid, Resource = Oid, Signatures = Signature>,
|
||||
{
|
||||
log::info!("loading object '{}' '{}'", typename, oid);
|
||||
let mut builder = GraphBuilder::default();
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ pub use history::{Contents, Entry, History, HistoryType};
|
|||
mod pruning_fold;
|
||||
|
||||
pub mod signatures;
|
||||
use signatures::Signatures;
|
||||
use signatures::Signature;
|
||||
|
||||
pub mod type_name;
|
||||
pub use type_name::TypeName;
|
||||
|
|
@ -134,7 +134,7 @@ where
|
|||
ObjectId = git_ext::Oid,
|
||||
Author = git_ext::Oid,
|
||||
Resource = git_ext::Oid,
|
||||
Signatures = Signatures,
|
||||
Signatures = Signature,
|
||||
>,
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,12 @@ pub struct Signature {
|
|||
sig: crypto::Signature,
|
||||
}
|
||||
|
||||
impl Signature {
|
||||
pub fn verify(&self, payload: &[u8]) -> bool {
|
||||
self.key.verify(payload, &self.sig).is_ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Signature> for ExtendedSignature {
|
||||
fn from(sig: Signature) -> Self {
|
||||
Self::new(sig.key, sig.sig)
|
||||
|
|
|
|||
Loading…
Reference in New Issue