Skip to content

Commit

Permalink
Added a ton of documentation, minor cleanup.
Browse files Browse the repository at this point in the history
  • Loading branch information
treyzania committed Sep 15, 2017
1 parent 736be1f commit 203f688
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 28 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
members = [
"dag",
"db",
"verification"
"validation"
]
32 changes: 32 additions & 0 deletions dag/src/comp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use DagComponent;
use DagNode;
use DecodeError;

/// Generic type for a "signed" version of `T`.
#[derive(Clone)]
pub struct Signed<T> where T: DagComponent {
signature: sig::Signature,
Expand All @@ -17,13 +18,15 @@ pub struct Signed<T> where T: DagComponent {

impl<T> Signed<T> where T: DagComponent {

/// Creates a new signed verison of the given `T`, signed with the specified keypair.
pub fn new(kp: sig::Keypair, body: T) -> Signed<T> {
Signed {
signature: kp.sign(body.get_hash()),
body: body
}
}

/// Unwraps the contained type into its unsigned form.
pub fn extract(self) -> T {
self.body
}
Expand Down Expand Up @@ -53,12 +56,27 @@ impl<T> DagComponent for Signed<T> where T: DagComponent {

}

/// Main type of node on the dag. Primary unit of time and validation.
///
/// Blocks have a header including their parent information. They also contain a set of segments
/// that represent the data actually stored in the blocks. Segments are for the actual mid-layer
/// validation logic. One type of segments are artifact segments, which carry actual payload data
/// in the content layer. Artifact contents have no bearing on validation, only total size.
#[derive(Clone)]
pub struct Block {

/// Version identifier. TODO Formalize this.
version: u32,

/// Millisecond UNIX time
timestamp: i64,

/// The addresses of the immediate parent blocks (`Signed<Block>`) to this block.
parents: Vec<Address>,

/// The segments contained within this block.
segments: Vec<Signed<Segment>>

}

impl DagComponent for Block {
Expand Down Expand Up @@ -135,6 +153,11 @@ impl DagNode for Signed<Block> {

}

/// Any kind of data that can be stored in a segment.
///
/// * IdentDecl - Used to declare identities on the network.
/// * Artifact - Actual on-chain artifact.
/// * ArtifactPointer - Pointer to an artifact container, off-chain.
#[derive(Clone)]
pub enum SegmentContent {
IdentDecl(sig::Hash),
Expand All @@ -143,6 +166,10 @@ pub enum SegmentContent {
}

impl SegmentContent {

/// Returns the speciier for the SegmentContent used for serialization.
///
/// TODO Make this make more sense.
fn specifier(&self) -> u8 {
use self::SegmentContent::*;
match self {
Expand Down Expand Up @@ -209,6 +236,8 @@ impl DagComponent for SegmentContent {

}

/// A segment itself, with a timestamp. See the documentation for Block for more information. You
/// probably want to use a `Signed<Segment>` if you're just working with them.
#[derive(Clone)]
pub struct Segment {
timestamp: i64,
Expand Down Expand Up @@ -274,6 +303,9 @@ impl DagComponent for ArtifactData {

}

/// The off-chain container. Usually you would want to use it as a `Signed<ArtifactContainer>`.
/// You can technically chain these infinitely as it's actually a segment container, so you could
/// just chain `ArtifactPointer`s indefinitely.
#[derive(Clone)]
pub struct ArtifactContainer {
version: u32,
Expand Down
27 changes: 24 additions & 3 deletions dag/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,62 @@ extern crate crypto;
pub mod comp;
pub mod sig;

/// Used to directly address something in the DAG. Just a SHA-256 hash of whatever it is that
/// it's addressing. Yay for content-addressed objects.
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Address(sig::Hash);

/// Simpler way to refer to the actual block on the chain, as they need to be signed.
pub type SignedBlock = comp::Signed<comp::Block>;

/// Simpler way to refer to artifacts stored off-chain, as they *still* need to be signed.
pub type SignedArtifactContainer = comp::Signed<comp::ArtifactContainer>;

/// Defines something that is used to make up the DAG. Does not have to be a standalone node
/// (see `DagNode`) but does have to be able to have a standard representation as bytes.
pub trait DagComponent where Self: Clone {

// <(the object, bytes consumed), error info>
/// Creates a component from a blob (a slice, actually) of bytes.
///
/// `<(the object, bytes consumed), error info>`
fn from_blob(blob: &[u8]) -> Result<(Self, usize), DecodeError>;

/// Converts the component into its byte representation. Should not be able to fail.
fn to_blob(&self) -> Vec<u8>;

fn get_hash(&self) -> sig::Hash {
/// Returns the hash of the component, used to create the address of it, if applicable.
fn get_hash(&self) -> sig::Hash { // TODO Rename to to_hash.
sig::Hash::from_blob(self.to_blob().as_slice())
}

/// Converts the component into the signed version of itself. This can be done repeatedly as
/// `Signed<T` is also a component, technically.
fn into_signed(self, kp: sig::Keypair) -> comp::Signed<Self> {
comp::Signed::new(kp, self)
}

}

/// Represents a standalone node on the DAG. Should always also be a `Signed<T>` something, but
/// this does not *need* to be true.
pub trait DagNode where Self: DagComponent {

/// Version identifier. TODO Formalize this.
fn version(&self) -> u32;

/// Millisecond UNIX time
fn timestamp(&self) -> i64;

}

impl Address {

/// Creates a new address, assuming the specified hash data.
pub fn new(hex: [u8; sig::SHA256_WIDTH]) -> Address {
Address(sig::Hash::new(hex))
}

/// Returns the address of the given blob, assuming that it's a node in a dag.
pub fn of(blob: &[u8]) -> Address {
Address(sig::Hash::from_blob(blob))
}
Expand Down Expand Up @@ -73,7 +94,7 @@ impl DagComponent for Address {

}


/// An error in decoding a DagComponent. Should propagate up the call stack.
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct DecodeError;

Expand Down
16 changes: 16 additions & 0 deletions dag/src/sig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use DecodeError;

pub const SHA256_WIDTH: usize = 32;

/// A SHA-256 hash.
#[derive(Copy, Eq, Ord, PartialOrd, Hash)]
pub struct Hash([u8; SHA256_WIDTH]);

Expand All @@ -22,10 +23,12 @@ impl PartialEq for Hash {

impl Hash {

/// Creates a new hash with the given contents.
pub fn new(hex: [u8; SHA256_WIDTH]) -> Hash {
Hash(hex)
}

/// Computes the SHA-256 hash of the given blob.
pub fn from_blob(blob: &[u8]) -> Hash {

let mut hasher = sha2::Sha256::new();
Expand All @@ -37,10 +40,12 @@ impl Hash {

}

/// Converts this hash into a `Fingerprint`, presumably used for creating a `Signature`.
pub fn into_fingerprint(self) -> Fingerprint {
Fingerprint(self)
}

/// (does what it says on the tin)
pub fn into_array(self) -> [u8; SHA256_WIDTH] {
let Hash(h) = self;
h
Expand All @@ -54,6 +59,7 @@ impl Clone for Hash {
}
}

/// The SHA-256 hash of an identity declaration artifact.
#[derive(Copy, Clone)]
pub struct Fingerprint(Hash);

Expand All @@ -73,13 +79,16 @@ impl Fingerprint {
}
}

/// A signature algorithm scheme. Only supports Ed25519 for now.
/// FIXME There is a better way to keep track of these in a modular manner.
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum Scheme {
Ed25519
}

impl Scheme {

/// Generates a new keypair using the scheme (ourselves) and the given seed,
pub fn generate(self, seed: &[u8]) -> Keypair {
match self {
Scheme::Ed25519 => {
Expand All @@ -89,13 +98,15 @@ impl Scheme {
}
}

/// Returns the specifier byte for this signature scheme.
fn to_specifier(&self) -> u8 {
use self::Scheme::*;
match self {
&Ed25519 => 0x00
}
}

/// Returns the signature scheme from the given specifier byte.
fn from_specifier(s: u8) -> Option<Scheme> {
use self::Scheme::*;
match s {
Expand All @@ -106,6 +117,7 @@ impl Scheme {

}

/// A keypair using some signature algorithm. Only support Ed25519 for now.
#[derive(Copy)]
pub enum Keypair {
Ed25519([u8; 64], [u8; 32])
Expand All @@ -119,6 +131,7 @@ impl Clone for Keypair {

impl Keypair {

/// Generates a signature for the given hash using this keypair.
pub fn sign(&self, hash: Hash) -> Signature {
match self {
&Keypair::Ed25519(kpriv, kpub) => {
Expand All @@ -130,6 +143,7 @@ impl Keypair {

}

/// The actual signature data (signed hash) of some blob and the fingerprint of the keypair used to create it. Supports multiple schemes.
#[derive(Copy)]
pub enum Signature {
Ed25519([u8; 64], Fingerprint)
Expand All @@ -143,13 +157,15 @@ impl Clone for Signature {

impl Signature {

/// Returns the signature scheme used for this signature.
fn scheme(&self) -> Scheme {
use self::Signature::*;
match self {
&Ed25519(_, _) => Scheme::Ed25519
}
}

/// Extracts the fingerprint of the public key of the signature.
pub fn into_fingerprint(self) -> Fingerprint {
match self {
Signature::Ed25519(_, f) => f,
Expand Down
10 changes: 10 additions & 0 deletions db/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,20 @@ use dag::Address;
use dag::DagComponent;
use BlobSource;

/// Stores blobs using some directory, with a root specified.
pub struct FsBlobSource {
root: PathBuf
}

impl FsBlobSource {

/// Creates a new `FsBlobSource` using the specified datastore root.
pub fn new(root: PathBuf) -> FsBlobSource {
FsBlobSource { root: root }
}

}

impl BlobSource for FsBlobSource {

fn get(&self, addr: Address) -> Option<Vec<u8>> {
Expand Down
11 changes: 11 additions & 0 deletions db/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,36 @@ pub mod fs;
use dag::Address;
use dag::DagNode;

/// Specifies a type that can be used to store and retrieve blobs, given addresses.
pub trait BlobSource {

/// Returns the blob (in `Vec` form) of the address for this source, if it exists.
fn get(&self, addr: Address) -> Option<Vec<u8>>;

/// Stores the blob in the storage, with the specified address, ignoring if the address matches up.
fn put(&self, addr: Address, blob: Vec<u8>) -> Result<(), ()>; // TODO Make something out of this.

}

/// Used to interact with a `BlobSource`, but converting to and from actual `DagNode`s.
pub struct NodeSource<S> where S: BlobSource {
source: S
}

/// Some kind of error in finding a node from the datastore.
pub enum NodeGetError {
NotFound,
DecodeError(dag::DecodeError)
}

impl<S> NodeSource<S> where S: BlobSource {

/// Creates a new `NodeSource` with the given backend.
pub fn new(src: S) -> NodeSource<S> {
NodeSource { source: src }
}

/// Returns the node with the given address, if possible.
pub fn get<N: DagNode>(&self, addr: Address) -> Result<N, NodeGetError> {
match self.source.get(addr) {
Some(b) => match N::from_blob(b.as_slice()) {
Expand All @@ -35,6 +45,7 @@ impl<S> NodeSource<S> where S: BlobSource {
}
}

/// Stores the node with the address derived from the node.
pub fn put<N: DagNode>(&self, node: N) -> Result<(), ()> { // FIXME Fix this when it's fixed.
let blob = node.to_blob();
self.source.put(dag::Address::of(blob.as_slice()), blob)
Expand Down
2 changes: 1 addition & 1 deletion verification/Cargo.toml → validation/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "libjiyunet-verification"
name = "libjiyunet-validation"
version = "0.1.0"
authors = ["treyzania <treyzania@gmail.com>"]

Expand Down
25 changes: 25 additions & 0 deletions validation/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
extern crate libjiyunet_dag as dag;
extern crate libjiyunet_db as db;

#[derive(Copy, Clone, Eq, PartialEq)]
pub enum ValidationError {
DecodeError(dag::Address), // Problem decoding data.
NodeNotFound(dag::Address), // Node not found in db, try again later?
ComponentTooLarge(dag::sig::Hash), // If something is too big to be allowed.
InsufficientCredits, // Identitiy doesn't have credits for some action.
}

type SignedBlock = dag::comp::Signed<dag::comp::Block>;
type SignedArtifactContainer = dag::comp::Signed<dag::comp::ArtifactContainer>;

enum Addable {
Block(SignedBlock),
ArtifactContainer(SignedArtifactContainer)
}

trait Validate {

fn new(genesis: dag::comp::Signed<dag::comp::Block>) -> Result<Box<Self>, ValidationError>;
fn include(self, added: Addable) -> Result<Box<Self>, (Box<Self>, ValidationError)>;

}
Loading

0 comments on commit 203f688

Please sign in to comment.