Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ This allows you to focus on implementing the important stuff, as well as getting

## Example

Simple creating, adding and verifying procedure based upon the typical `Chain` flow:

```rust
use onft::Chain;

Expand All @@ -25,7 +27,7 @@ let mut chain = Chain::default();
println!("Chain: {:?}", chain);

// add block
chain.push_data("Hello, world!").unwrap();
chain.push("Hello, world!").unwrap();
println!("Chain: {:?}", chain);

// verify
Expand Down
2 changes: 1 addition & 1 deletion examples/gamechain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fn handle_stream(chain: &mut Chain, mut stream: TcpStream) -> Result<GameReport,

// deserialize packet then add block
let game_report = GameReport::from_packet(packet)?;
chain.push_data(&packet[..]).map_err(|_| ())?;
chain.push(&packet[..]).map_err(|_| ())?;

Ok(game_report)
}
Expand Down
91 changes: 80 additions & 11 deletions src/chain.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Contains [Chain] and implementations

use crate::{error::Result, Block};
use crate::{error::Result, Block, Hash, Ownership};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

Expand All @@ -11,8 +11,8 @@ use serde::{Deserialize, Serialize};
/// You can, in high level terms, do the following directly to a blockchain:
///
/// - Create an initial blockchain: [Chain::default]
/// - Add some data inside a new block: [Chain::push_data]
/// - Extend multiple new pieces of data inside new blocks: [Chain::extend_data]
/// - Add some data inside a new block: [Chain::push]
/// - Extend multiple new pieces of data inside new blocks: [Chain::extend]
/// - Verify entire blockchain one-by-one: [Chain::verify]
///
/// # Example
Expand All @@ -25,7 +25,7 @@ use serde::{Deserialize, Serialize};
/// println!("Chain: {:?}", chain);
///
/// // add block
/// chain.push_data("Hello, world!").unwrap();
/// chain.push("Hello, world!").unwrap();
/// println!("Chain: {:?}", chain);
///
/// // verify
Expand All @@ -35,6 +35,16 @@ use serde::{Deserialize, Serialize};
/// eprintln!("Not verified")
/// }
/// ```
///
/// # Comparison to the [Vec] interface
///
/// This structure is based loosely of of the standard library's implementation
/// of [Vec] as this blockchain relies on it underneath. The two main differences
/// between this and the vector interface are:
///
/// - More item-level documentation; everything must be comprehensive
/// - Less methods here compared to vectors; unwise idea to [Vec::truncate] a
/// blockchain
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone)]
pub struct Chain(Vec<Block>);
Expand All @@ -52,7 +62,7 @@ impl Chain {
/// println!("Chain: {:?}", chain);
///
/// // add block
/// chain.push_data("Hello, world!").unwrap();
/// chain.push("Hello, world!").unwrap();
/// println!("Chain: {:?}", chain);
///
/// // verify
Expand Down Expand Up @@ -88,11 +98,11 @@ impl Chain {
/// use onft::prelude::*;
///
/// let mut chain = Chain::default();
/// chain.push_data("Hello, world!").unwrap();
/// chain.push("Hello, world!").unwrap();
///
/// println!("Chain: {:?}", chain);
/// ```
pub fn push_data(&mut self, data: impl Into<Vec<u8>>) -> Result<&mut Self> {
pub fn push(&mut self, data: impl Into<Vec<u8>>) -> Result<&mut Self> {
let previous_block = self.0.last().unwrap();
let new_block = Block::new(&previous_block.hash, data)?;
self.0.push(new_block);
Expand All @@ -113,25 +123,84 @@ impl Chain {
/// ];
///
/// let mut chain = Chain::default();
/// chain.extend_data(data_vec).unwrap();
/// chain.extend(data_vec).unwrap();
///
/// println!("Chain: {:?}", chain);
/// ```
pub fn extend_data(
pub fn extend(
&mut self,
data_iter: impl IntoIterator<Item = impl Into<Vec<u8>>>,
) -> Result<&mut Self> {
for data in data_iter.into_iter() {
Self::push_data(self, data)?;
Self::push(self, data)?;
}
Ok(self)
}

// TODO: more vec-like interface
/// TODO: document
///
/// # Example
///
/// ```none
/// TODO: example
/// ```
pub fn push_ext(&mut self, block: impl Into<Block>) -> &mut Self {
self.0.push(block.into());
self
}

/// TODO: document
///
/// # Example
///
/// ```none
/// TODO: example
/// ```
pub fn extend_ext(&mut self, blocks: impl IntoIterator<Item = impl Into<Block>>) -> &mut Self {
self.0.extend(blocks.into_iter().map(|block| block.into()));
self
}

/// TODO: document
///
/// # Example
///
/// ```none
/// TODO: example
/// ```
pub fn find(&self, query: ChainQuery) -> Option<&Block> {
match query {
ChainQuery::Hash(_) => todo!("query for hash"),
ChainQuery::Signature(_) => todo!("query for signature"),
ChainQuery::Owner(_) => todo!("query for owner"),
}
}

/// Clears the blockchain, removing all values. This method has no effect on
/// the allocated capacity of the block storage vector contained within.
///
/// # Example
///
/// ```none
/// TODO: example
/// ```
pub fn clear(&mut self) {
self.0.truncate(0)
}
}

impl Default for Chain {
fn default() -> Self {
Self(vec![Block::default()])
}
}

/// TODO: document
pub enum ChainQuery {
/// Queries for a block's hash, combining the `blockchain + data + ownership` values
Hash(Hash),
/// Queries for a block's signature combining the `data + ownership` values
Signature([u8; Hash::SIG_LEN]),
/// Queries for the ownership key, allowing for the `ownership` value
Owner(Ownership),
}
6 changes: 6 additions & 0 deletions src/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,12 @@ impl<'a> From<&'a Block> for &'a Hash {
}
}

impl From<[u8; 32]> for Hash {
fn from(inner: [u8; 32]) -> Self {
Self(inner)
}
}

fn gen_keypair() -> Result<PKey<Private>> {
PKey::generate_ed25519().map_err(Error::KeyGen)
}
Expand Down
4 changes: 3 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
//!
//! # Example
//!
//! Simple creating, adding and verifying procedure based upon the typical [Chain] flow:
//!
//! ```rust
//! use onft::prelude::*;
//!
Expand All @@ -16,7 +18,7 @@
//! println!("Chain: {:?}", chain);
//!
//! // add block
//! chain.push_data("Hello, world!").unwrap();
//! chain.push("Hello, world!").unwrap();
//! println!("Chain: {:?}", chain);
//!
//! // verify
Expand Down