Implement block store.

This commit is contained in:
David Craven 2019-01-31 21:51:08 +01:00
parent 94db690a45
commit 7e91bbbb71
No known key found for this signature in database
GPG Key ID: DF438712EA50DBB1
3 changed files with 262 additions and 0 deletions

138
Cargo.lock generated Normal file
View File

@ -0,0 +1,138 @@
[[package]]
name = "arrayref"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "base-x"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "block-buffer"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "byte-tools"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cid"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"integer-encoding 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"multibase 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"multihash 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crunchy"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "digest"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fake-simd"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "generic-array"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "integer-encoding"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "multibase"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"base-x 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "multihash"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"sha1 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rust-ipfs"
version = "0.1.0"
dependencies = [
"cid 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"multibase 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"multihash 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "sha1"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "sha2"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
"fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tiny-keccak"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "typenum"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
"checksum base-x 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d55aa264e822dbafa12db4d54767aff17c6ba55ea2d8559b3e17392c7d000e5d"
"checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab"
"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40"
"checksum cid 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0e37fba0087d9f3f4e269827a55dc511abf3e440cc097a0c154ff4e6584f988"
"checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda"
"checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90"
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d"
"checksum integer-encoding 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "26746cbc2e680af687e88d717f20ff90079bd10fc984ad57d277cd0e37309fa5"
"checksum multibase 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b9c35dac080fd6e16a99924c8dfdef0af89d797dd851adab25feaffacf7850d6"
"checksum multihash 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c62469025f45dee2464ef9fc845f4683c543993792c1993e7d903c17a4546b74"
"checksum sha1 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "171698ce4ec7cbb93babeb3190021b4d72e96ccb98e33d277ae4ea959d6f2d9e"
"checksum sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0"
"checksum tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e9175261fbdb60781fcd388a4d6cc7e14764a2b629a7ad94abb439aed223a44f"
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"

View File

@ -5,3 +5,6 @@ authors = ["David Craven <david@craven.ch>"]
edition = "2018"
[dependencies]
cid = "*"
multibase = "*"
multihash = "*"

121
src/lib.rs Normal file
View File

@ -0,0 +1,121 @@
//! IPFS node implementation
#![deny(missing_docs)]
#![deny(warnings)]
use cid::Cid;
use std::collections::HashMap;
use std::sync::Arc;
/// Ipfs struct creates a new IPFS node and is the main entry point
/// for interacting with IPFS.
pub struct Ipfs {
blocks: HashMap<Vec<u8>, Block>,
}
impl Ipfs {
/// Creates a new ipfs node.
pub fn new() -> Self {
Ipfs {
blocks: HashMap::new(),
}
}
/// Puts a block into the ipfs repo.
pub fn put_block(&mut self, block: Block) -> Result<Cid, ()> {
let cid = block.cid();
self.blocks.insert(cid.to_bytes(), block);
Ok(cid)
}
/// Retrives a block from the ipfs repo.
pub fn get_block(&self, cid: &Cid) -> Result<Block, ()> {
self.blocks.get(&cid.to_bytes())
.map_or(Err(()), |block| Ok((*block).clone()))
}
}
#[derive(Clone, Debug, PartialEq)]
/// An immutable ipfs block.
pub struct Block {
content: Arc<Vec<u8>>,
}
impl Block {
/// Creates a new immutable ipfs block.
pub fn new(content: Vec<u8>) -> Self {
Block { content: Arc::new(content) }
}
/// Returns the size of the block in bytes.
pub fn size(&self) -> usize {
self.content.len()
}
/// Returns the content id of the block.
pub fn cid(&self) -> Cid {
let prefix = cid::Prefix {
version: cid::Version::V0,
codec: cid::Codec::DagProtobuf,
mh_type: multihash::Hash::SHA2256,
mh_len: 32,
};
Cid::new_from_prefix(&prefix, &self.content)
}
}
impl From<&str> for Block {
fn from(content: &str) -> Block {
Block::new(content.as_bytes().to_vec())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_raw_block_cid() {
let content = "hello\n".as_bytes();
let cid = "zb2rhcc1wJn2GHDLT2YkmPq5b69cXc2xfRZZmyufbjFUfBkxr";
let prefix = cid::Prefix {
version: cid::Version::V1,
codec: cid::Codec::Raw,
mh_type: multihash::Hash::SHA2256,
mh_len: 32,
};
let computed_cid = Cid::new_from_prefix(
&prefix,
&content,
).to_string();
assert_eq!(cid, computed_cid);
}
#[test]
fn test_dag_pb_block_cid() {
let content = "hello\n".as_bytes();
let cid = "QmUJPTFZnR2CPGAzmfdYPghgrFtYFB6pf1BqMvqfiPDam8";
let prefix = cid::Prefix {
version: cid::Version::V0,
codec: cid::Codec::DagProtobuf,
mh_type: multihash::Hash::SHA2256,
mh_len: 32,
};
let computed_cid = Cid::new_from_prefix(
&prefix,
&content,
).to_string();
assert_eq!(cid, computed_cid);
}
#[test]
fn test_put_and_get_block() {
let mut ipfs = Ipfs::new();
let block = Block::from("hello block\n");
assert_eq!(block.cid().to_string(),
"QmVNrZhKw9JwYa4YPEZVccQxfgQJq993yP78QEN28927vq");
assert_eq!(block.size(), 12);
let cid = ipfs.put_block(block.clone()).unwrap();
let new_block = ipfs.get_block(&cid).unwrap();
assert_eq!(block, new_block);
}
}