aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bin/geniza-net.rs53
-rw-r--r--src/bin/geniza-sleep.rs79
-rw-r--r--src/lib.rs12
-rw-r--r--src/protocol.rs88
-rw-r--r--src/sleep_file.rs57
-rw-r--r--src/sleep_register.rs151
6 files changed, 228 insertions, 212 deletions
diff --git a/src/bin/geniza-net.rs b/src/bin/geniza-net.rs
index be4dba0..a3abc61 100644
--- a/src/bin/geniza-net.rs
+++ b/src/bin/geniza-net.rs
@@ -1,10 +1,10 @@
-// Free Software under GPL-3.0, see LICENSE
+// Free Software under GPL-3.0, see LICENSE
// Copyright 2017 Bryan Newbold
-#[macro_use]
-extern crate error_chain;
extern crate clap;
extern crate env_logger;
+#[macro_use]
+extern crate error_chain;
extern crate geniza;
// TODO: more careful import
@@ -12,19 +12,22 @@ use geniza::*;
use clap::{App, SubCommand};
fn run() -> Result<()> {
-
env_logger::init().unwrap();
-
+
let matches = App::new("geniza-net")
.version(env!("CARGO_PKG_VERSION"))
- .subcommand(SubCommand::with_name("connect")
- .about("Connects to a peer and exchanges handshake")
- .arg_from_usage("<host_port> 'peer host:port to connect to'")
- .arg_from_usage("<dat_key> 'dat key (public key) to register with'"))
- .subcommand(SubCommand::with_name("receive-all")
- .about("Connects to a peer, pulls all metadata and content")
- .arg_from_usage("<host_port> 'peer host:port to connect to'")
- .arg_from_usage("<dat_key> 'dat key (public key) to register with'"))
+ .subcommand(
+ SubCommand::with_name("connect")
+ .about("Connects to a peer and exchanges handshake")
+ .arg_from_usage("<host_port> 'peer host:port to connect to'")
+ .arg_from_usage("<dat_key> 'dat key (public key) to register with'"),
+ )
+ .subcommand(
+ SubCommand::with_name("receive-all")
+ .about("Connects to a peer, pulls all metadata and content")
+ .arg_from_usage("<host_port> 'peer host:port to connect to'")
+ .arg_from_usage("<dat_key> 'dat key (public key) to register with'"),
+ )
.get_matches();
@@ -32,51 +35,45 @@ fn run() -> Result<()> {
("connect", Some(subm)) => {
let host_port = subm.value_of("host_port").unwrap();
let dat_key = subm.value_of("dat_key").unwrap();
- if dat_key.len() != 32*2 {
+ if dat_key.len() != 32 * 2 {
bail!("dat key not correct length");
}
let mut key_bytes = vec![];
for i in 0..32 {
- let r = u8::from_str_radix(&dat_key[2*i .. 2*i+2], 16);
+ let r = u8::from_str_radix(&dat_key[2 * i..2 * i + 2], 16);
match r {
Ok(b) => key_bytes.push(b),
Err(e) => bail!("Problem with hex: {}", e),
};
}
- DatConnection::connect(
- host_port,
- &key_bytes,
- false)?;
+ DatConnection::connect(host_port, &key_bytes, false)?;
println!("Done!");
- },
+ }
("receive-all", Some(subm)) => {
let host_port = subm.value_of("host_port").unwrap();
let dat_key = subm.value_of("dat_key").unwrap();
- if dat_key.len() != 32*2 {
+ if dat_key.len() != 32 * 2 {
bail!("dat key not correct length");
}
let mut key_bytes = vec![];
for i in 0..32 {
- let r = u8::from_str_radix(&dat_key[2*i .. 2*i+2], 16);
+ let r = u8::from_str_radix(&dat_key[2 * i..2 * i + 2], 16);
match r {
Ok(b) => key_bytes.push(b),
Err(e) => bail!("Problem with hex: {}", e),
};
}
- let mut dc = DatConnection::connect(
- host_port,
- &key_bytes,
- false)?;
+ let mut dc = DatConnection::connect(host_port, &key_bytes, false)?;
// XXX: number here totally arbitrary
dc.receive_all(false, 10)?;
dc.receive_all(true, 10)?;
println!("Done!");
- },
+ }
_ => {
println!("Missing or unimplemented command!");
println!("{}", matches.usage());
::std::process::exit(-1);
- },
+ }
}
Ok(())
}
diff --git a/src/bin/geniza-sleep.rs b/src/bin/geniza-sleep.rs
index 461df0d..1a50d17 100644
--- a/src/bin/geniza-sleep.rs
+++ b/src/bin/geniza-sleep.rs
@@ -1,11 +1,11 @@
-// Free Software under GPL-3.0, see LICENSE
+// Free Software under GPL-3.0, see LICENSE
// Copyright 2017 Bryan Newbold
#[macro_use]
-extern crate error_chain;
-#[macro_use]
extern crate clap;
extern crate env_logger;
+#[macro_use]
+extern crate error_chain;
extern crate geniza;
// TODO: more careful import
@@ -14,31 +14,40 @@ use std::path::Path;
use clap::{App, SubCommand};
fn run() -> Result<()> {
-
env_logger::init().unwrap();
-
+
let matches = App::new("geniza-sleep")
.version(env!("CARGO_PKG_VERSION"))
- .subcommand(SubCommand::with_name("info")
- .about("Reads a SLEEP dir register and shows some basic metadata")
- .arg_from_usage("<DIR> 'directory containing files'")
- .arg_from_usage("<prefix> 'prefix for each data file'"))
- .subcommand(SubCommand::with_name("create")
- .about("Creates an SLEEP directory register (with header)")
- .arg_from_usage("<DIR> 'directory containing files'")
- .arg_from_usage("<prefix> 'prefix for each data file'"))
- .subcommand(SubCommand::with_name("file-info")
- .about("Reads a single SLEEP file and shows some basic metadata")
- .arg_from_usage("<FILE> 'SLEEP file to read'"))
- .subcommand(SubCommand::with_name("file-create")
- .about("Creates an empty single SLEEP file (with header)")
- .arg_from_usage("<FILE> 'SLEEP file to write (can't exist)'")
- .arg_from_usage("<magic> 'Magic word to use (eg, 0x5025700)'")
- .arg_from_usage("<entry_size> 'Size of each entry (bytes)'")
- .arg_from_usage("<algo_name> 'Name of algorithm (empty string for none)'"))
- .subcommand(SubCommand::with_name("read-all")
- .about("Reads a single SLEEP file, iterates through all entries, prints raw bytes")
- .arg_from_usage("<FILE> 'SLEEP file to read'"))
+ .subcommand(
+ SubCommand::with_name("info")
+ .about("Reads a SLEEP dir register and shows some basic metadata")
+ .arg_from_usage("<DIR> 'directory containing files'")
+ .arg_from_usage("<prefix> 'prefix for each data file'"),
+ )
+ .subcommand(
+ SubCommand::with_name("create")
+ .about("Creates an SLEEP directory register (with header)")
+ .arg_from_usage("<DIR> 'directory containing files'")
+ .arg_from_usage("<prefix> 'prefix for each data file'"),
+ )
+ .subcommand(
+ SubCommand::with_name("file-info")
+ .about("Reads a single SLEEP file and shows some basic metadata")
+ .arg_from_usage("<FILE> 'SLEEP file to read'"),
+ )
+ .subcommand(
+ SubCommand::with_name("file-create")
+ .about("Creates an empty single SLEEP file (with header)")
+ .arg_from_usage("<FILE> 'SLEEP file to write (can't exist)'")
+ .arg_from_usage("<magic> 'Magic word to use (eg, 0x5025700)'")
+ .arg_from_usage("<entry_size> 'Size of each entry (bytes)'")
+ .arg_from_usage("<algo_name> 'Name of algorithm (empty string for none)'"),
+ )
+ .subcommand(
+ SubCommand::with_name("read-all")
+ .about("Reads a single SLEEP file, iterates through all entries, prints raw bytes")
+ .arg_from_usage("<FILE> 'SLEEP file to read'"),
+ )
.get_matches();
@@ -50,22 +59,25 @@ fn run() -> Result<()> {
//debug!(println!("{:?}", sdr));
println!("Entry count: {}", sdr.len()?);
println!("Total size (bytes): {}", sdr.len_bytes()?);
- },
+ }
("create", Some(subm)) => {
let dir = Path::new(subm.value_of("DIR").unwrap());
let prefix = subm.value_of("prefix").unwrap();
SleepDirRegister::create(dir, prefix)?;
println!("Done!");
- },
+ }
("file-info", Some(subm)) => {
let path = Path::new(subm.value_of("FILE").unwrap());
let sf = SleepFile::open(path, false)?;
//debug!(println!("{:?}", sf));
println!("Magic: 0x{:X}", sf.get_magic());
- println!("Algorithm: '{}'", sf.get_algorithm().or(Some("".to_string())).unwrap());
+ println!(
+ "Algorithm: '{}'",
+ sf.get_algorithm().or(Some("".to_string())).unwrap()
+ );
println!("Entry Size (bytes): {}", sf.get_entry_size());
println!("Entry count: {}", sf.len()?);
- },
+ }
("file-create", Some(subm)) => {
let path = Path::new(subm.value_of("FILE").unwrap());
let algo_name = subm.value_of("algo_name").unwrap();
@@ -78,21 +90,22 @@ fn run() -> Result<()> {
path,
value_t_or_exit!(subm, "magic", u32),
value_t_or_exit!(subm, "entry_size", u16),
- algo_name)?;
+ algo_name,
+ )?;
println!("Done!");
- },
+ }
("file-read-all", Some(subm)) => {
let path = Path::new(subm.value_of("FILE").unwrap());
let mut sf = SleepFile::open(path, false)?;
for i in 0..sf.len()? {
println!("{}: {:?}", i, sf.read(i));
}
- },
+ }
_ => {
println!("Missing or unimplemented command!");
println!("{}", matches.usage());
::std::process::exit(-1);
- },
+ }
}
Ok(())
}
diff --git a/src/lib.rs b/src/lib.rs
index d106895..c09301b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,4 +1,4 @@
-// Free Software under GPL-3.0, see LICENSE
+// Free Software under GPL-3.0, see LICENSE
// Copyright 2017 Bryan Newbold
//! This is a hobby/learning implementation of the dat distributed data synchronization system.
@@ -13,16 +13,16 @@
//! Additional notes in the source code for this repo, under the 'notes' directory. Also, see
//! README.
+extern crate crypto;
+extern crate env_logger;
#[macro_use]
extern crate error_chain;
+extern crate integer_encoding;
#[macro_use]
extern crate log;
-extern crate env_logger;
-extern crate integer_encoding;
-extern crate crypto;
-extern crate sodiumoxide;
-extern crate rand;
extern crate protobuf;
+extern crate rand;
+extern crate sodiumoxide;
#[cfg(test)]
extern crate tempdir;
diff --git a/src/protocol.rs b/src/protocol.rs
index 7a64f88..aaad914 100644
--- a/src/protocol.rs
+++ b/src/protocol.rs
@@ -31,37 +31,36 @@ pub enum DatNetMessage {
fn msg_code(msg: &DatNetMessage) -> u8 {
match msg {
- &DatNetMessage::Register(_) => 0,
+ &DatNetMessage::Register(_) => 0,
&DatNetMessage::Handshake(_) => 1,
- &DatNetMessage::Status(_) => 2,
- &DatNetMessage::Have(_) => 3,
- &DatNetMessage::Unhave(_) => 4,
- &DatNetMessage::Want(_) => 5,
- &DatNetMessage::Unwant(_) => 6,
- &DatNetMessage::Request(_) => 7,
- &DatNetMessage::Cancel(_) => 8,
- &DatNetMessage::Data(_) => 9,
+ &DatNetMessage::Status(_) => 2,
+ &DatNetMessage::Have(_) => 3,
+ &DatNetMessage::Unhave(_) => 4,
+ &DatNetMessage::Want(_) => 5,
+ &DatNetMessage::Unwant(_) => 6,
+ &DatNetMessage::Request(_) => 7,
+ &DatNetMessage::Cancel(_) => 8,
+ &DatNetMessage::Data(_) => 9,
}
}
fn msg_sugar(msg: &DatNetMessage) -> &Message {
match msg {
- &DatNetMessage::Register(ref m) => m,
+ &DatNetMessage::Register(ref m) => m,
&DatNetMessage::Handshake(ref m) => m,
- &DatNetMessage::Status(ref m) => m,
- &DatNetMessage::Have(ref m) => m,
- &DatNetMessage::Unhave(ref m) => m,
- &DatNetMessage::Want(ref m) => m,
- &DatNetMessage::Unwant(ref m) => m,
- &DatNetMessage::Request(ref m) => m,
- &DatNetMessage::Cancel(ref m) => m,
- &DatNetMessage::Data(ref m) => m,
+ &DatNetMessage::Status(ref m) => m,
+ &DatNetMessage::Have(ref m) => m,
+ &DatNetMessage::Unhave(ref m) => m,
+ &DatNetMessage::Want(ref m) => m,
+ &DatNetMessage::Unwant(ref m) => m,
+ &DatNetMessage::Request(ref m) => m,
+ &DatNetMessage::Cancel(ref m) => m,
+ &DatNetMessage::Data(ref m) => m,
}
}
/// This helper is pretty slow/inefficient; lots of copying memory
fn bytewise_stream_xor_ic_inplace(buf: &mut [u8], byte_offset: u64, nonce: &Nonce, key: &Key) {
-
let mut offset = byte_offset;
// We may have a partial-64-byte-block to finish encrypting first
@@ -70,26 +69,25 @@ fn bytewise_stream_xor_ic_inplace(buf: &mut [u8], byte_offset: u64, nonce: &Nonc
if partial_len != 0 {
let mut partial = vec![0; 64];
for i in 0..partial_len {
- partial[partial_offset+i] = buf[i];
+ partial[partial_offset + i] = buf[i];
}
let partial_enc = stream_xor_ic(&partial, offset / 64, &nonce, &key);
offset += partial_len as u64;
for i in 0..partial_len {
- buf[i] = partial_enc[partial_offset+i];
+ buf[i] = partial_enc[partial_offset + i];
}
}
if buf.len() > partial_len {
let main_enc = stream_xor_ic(&buf[partial_len..], offset / 64, &nonce, &key);
//offset += main_enc.len() as u64;
for i in 0..main_enc.len() {
- buf[partial_len+i] = main_enc[i];
+ buf[partial_len + i] = main_enc[i];
}
}
}
#[test]
fn test_bsxii_short() {
-
let nonce = gen_nonce();
let key = gen_key();
@@ -110,7 +108,6 @@ fn test_bsxii_short() {
#[test]
fn test_bsxii_continued() {
-
let nonce = gen_nonce();
let key = gen_key();
@@ -161,7 +158,6 @@ pub struct DatConnection {
}
impl Read for DatConnection {
-
/// Encrypted TCP read (after connection initialized). Uses XOR of an XSalsa20 stream, using
/// block offsets.
fn read(&mut self, buf: &mut [u8]) -> ::std::io::Result<usize> {
@@ -174,10 +170,8 @@ impl Read for DatConnection {
}
impl Write for DatConnection {
-
/// Encrypted write to complement `read()`.
fn write(&mut self, buf: &[u8]) -> ::std::io::Result<usize> {
-
// Don't mutate what we've been passed
let mut enc = vec![0; buf.len()];
enc.copy_from_slice(buf);
@@ -194,9 +188,7 @@ impl Write for DatConnection {
}
impl DatConnection {
-
pub fn connect(host_port: &str, key: &[u8], live: bool) -> Result<DatConnection> {
-
let timeout = Duration::new(7, 0);
let tx_nonce = gen_nonce();
let mut local_id = [0; 32];
@@ -224,13 +216,12 @@ impl DatConnection {
data_discovery_key: [0; 32],
tx_nonce: tx_nonce,
tx_offset: 0,
- rx_nonce: gen_nonce(), // dummy
+ rx_nonce: gen_nonce(), // dummy
rx_offset: 0,
};
// Exchange register/feed
dc.tcp.set_nodelay(true)?; // Faster handshake
- // send register
let mut register_msg = Feed::new();
register_msg.set_discoveryKey(dc.discovery_key.to_vec());
register_msg.set_nonce((tx_nonce[0..24]).to_vec());
@@ -281,13 +272,17 @@ impl DatConnection {
}
fn send_msg(&mut self, dnm: &DatNetMessage, is_content: bool) -> Result<()> {
-
let header_int: u8 = (is_content as u8) << 4 | (msg_code(dnm) & 0x0F);
let msg: &Message = msg_sugar(dnm);
let total_message_size = (msg.compute_size() as usize) + 1;
- trace!("SEND total_len={} header={} is_content={} type={:?}",
- total_message_size, header_int, is_content, &dnm);
+ trace!(
+ "SEND total_len={} header={} is_content={} type={:?}",
+ total_message_size,
+ header_int,
+ is_content,
+ &dnm
+ );
// send both header varints, and data
self.write_varint(total_message_size as u64)?;
@@ -309,13 +304,17 @@ impl DatConnection {
}
fn recv_msg(&mut self) -> Result<(bool, DatNetMessage)> {
-
let total_len: u64 = self.read_varint()?;
let header: u8 = self.read_varint()?;
let is_content = (header & (1 << 4)) != 0;
- trace!("RECV total_len={} header={} is_content={}", total_len, header, is_content);
+ trace!(
+ "RECV total_len={} header={} is_content={}",
+ total_len,
+ header,
+ is_content
+ );
if header > 0x1F {
bail!("Invalid header received: {}", header);
@@ -351,8 +350,12 @@ impl DatConnection {
let header_int: u8 = 0;
let total_message_size = (reg.compute_size() as usize) + 1;
- trace!("SEND total_len={} header={} msg={:?}",
- total_message_size, header_int, reg);
+ trace!(
+ "SEND total_len={} header={} msg={:?}",
+ total_message_size,
+ header_int,
+ reg
+ );
self.tcp.write_varint(total_message_size as u64)?;
self.tcp.write_varint(header_int as u32)?;
@@ -383,7 +386,6 @@ impl DatConnection {
}
pub fn get_data_key(&mut self) -> Result<()> {
-
// Status: downloading, not uploading
let mut sm = Info::new();
sm.set_uploading(false);
@@ -419,7 +421,7 @@ impl DatConnection {
info!("Expected Have message, got: {:?}", &msg);
continue;
}
- };
+ }
// Request
let mut rm = Request::new();
@@ -443,7 +445,8 @@ impl DatConnection {
}
info!("Got data discovery key");
self.data_key.copy_from_slice(&data_key[0..32]);
- self.data_discovery_key.copy_from_slice(&make_discovery_key(data_key)[0..32]);
+ self.data_discovery_key
+ .copy_from_slice(&make_discovery_key(data_key)[0..32]);
return Ok(());
} else {
unimplemented!("non-hyperdrive Index type: {}", index_msg.get_field_type());
@@ -457,7 +460,6 @@ impl DatConnection {
}
pub fn receive_all(&mut self, is_content: bool, length: u64) -> Result<()> {
-
// Status: downloading, not uploading
let mut sm = Info::new();
sm.set_uploading(false);
@@ -488,7 +490,7 @@ impl DatConnection {
loop {
let (was_content, msg) = self.recv_msg()?;
- if was_content != is_content{
+ if was_content != is_content {
info!("Expected other message channel");
continue;
}
diff --git a/src/sleep_file.rs b/src/sleep_file.rs
index 36bf7a9..71e95ba 100644
--- a/src/sleep_file.rs
+++ b/src/sleep_file.rs
@@ -12,7 +12,6 @@ use errors::*;
///
/// Back-ends could be in RAM, on disk, remote HTTP, etc.
pub trait SleepStorage {
-
/// Returns the 32-bit "magic word", indicating the content type, in native format (aka, not
/// necessarily big-endian).
fn get_magic(&self) -> u32;
@@ -50,12 +49,10 @@ pub struct SleepFile {
}
impl SleepFile {
-
// TODO: 'from' pre-existing File
// Something here to allow paths as references or actual Path...
pub fn open(path: &Path, writable: bool) -> Result<SleepFile> {
-
let mut f = OpenOptions::new()
.read(true)
.write(writable)
@@ -71,8 +68,10 @@ impl SleepFile {
if algo_len > 24 {
bail!("Invalid SLEEP header: can't have algo_len > 24");
}
- let algorithm_name = if algo_len == 0 { None } else {
- Some(String::from_utf8_lossy(&header[8..(8+(algo_len as usize))]).into_owned())
+ let algorithm_name = if algo_len == 0 {
+ None
+ } else {
+ Some(String::from_utf8_lossy(&header[8..(8 + (algo_len as usize))]).into_owned())
};
let sf = SleepFile {
file: f,
@@ -86,8 +85,12 @@ impl SleepFile {
}
/// This function will *not* allow overwriting an existing file.
- pub fn create(path: &Path, magic: u32, entry_size: u16, algo: Option<String>) -> Result<SleepFile> {
-
+ pub fn create(
+ path: &Path,
+ magic: u32,
+ entry_size: u16,
+ algo: Option<String>,
+ ) -> Result<SleepFile> {
let mut header = [0; 32];
u32::to_be(magic).encode_fixed(&mut header[0..4]);
header[4] = 0; // version
@@ -99,7 +102,7 @@ impl SleepFile {
bail!("Algorithm name must be 24 bytes at most");
}
header[7] = algo_len as u8;
- header[8..(8+algo_len)].clone_from_slice(name);
+ header[8..(8 + algo_len)].clone_from_slice(name);
} else {
header[7] = 0;
};
@@ -120,10 +123,15 @@ impl SleepFile {
}
impl SleepStorage for SleepFile {
-
- fn get_magic(&self) -> u32 { self.magic }
- fn get_algorithm(&self) -> Option<String> { self.algorithm_name.clone() }
- fn get_entry_size(&self) -> u16 { self.entry_size }
+ fn get_magic(&self) -> u32 {
+ self.magic
+ }
+ fn get_algorithm(&self) -> Option<String> {
+ self.algorithm_name.clone()
+ }
+ fn get_entry_size(&self) -> u16 {
+ self.entry_size
+ }
fn read(&mut self, index: u64) -> Result<Vec<u8>> {
let entry_size = self.entry_size as usize;
@@ -131,7 +139,8 @@ impl SleepStorage for SleepFile {
bail!("Tried to read beyond end of SLEEP file");
}
let mut entry = vec![0; entry_size];
- self.file.seek(SeekFrom::Start(32 + (entry_size as u64) * index))?;
+ self.file
+ .seek(SeekFrom::Start(32 + (entry_size as u64) * index))?;
self.file.read_exact(&mut entry)?;
Ok(entry)
}
@@ -141,7 +150,8 @@ impl SleepStorage for SleepFile {
if data.len() != self.entry_size as usize {
bail!("Tried to write mis-sized data");
}
- self.file.seek(SeekFrom::Start(32 + (self.entry_size as u64) * index))?;
+ self.file
+ .seek(SeekFrom::Start(32 + (self.entry_size as u64) * index))?;
self.file.write_all(&data)?;
Ok(())
}
@@ -156,23 +166,20 @@ impl SleepStorage for SleepFile {
if length < 32 || (length - 32) % (self.entry_size as u64) != 0 {
bail!("Bad SLEEP file: missing header or not multiple of entry_size");
}
- return Ok((length - 32) / (self.entry_size as u64))
+ return Ok((length - 32) / (self.entry_size as u64));
}
}
#[test]
fn test_sleep_open() {
-
- let sf = SleepFile::open(
- Path::new("test-data/sleep/empty/empty.sleep"), false).unwrap();
+ let sf = SleepFile::open(Path::new("test-data/sleep/empty/empty.sleep"), false).unwrap();
assert_eq!(sf.len().unwrap(), 0);
assert_eq!(sf.get_magic(), 0x050257FF);
assert_eq!(sf.get_algorithm(), None);
assert_eq!(sf.get_entry_size(), 1);
- let sf = SleepFile::open(
- Path::new("test-data/dat/simple/.dat/metadata.tree"), false).unwrap();
+ let sf = SleepFile::open(Path::new("test-data/dat/simple/.dat/metadata.tree"), false).unwrap();
// Calculated from 'dat log'
assert_eq!(sf.len().unwrap(), 5);
@@ -183,15 +190,10 @@ fn test_sleep_open() {
#[test]
fn test_sleep_create() {
-
use tempdir::TempDir;
let tmp_dir = TempDir::new("geniza-test").unwrap();
- SleepFile::create(
- &tmp_dir.path().join("empty2.sleep"),
- 0x050257FF,
- 1,
- None).unwrap();
+ SleepFile::create(&tmp_dir.path().join("empty2.sleep"), 0x050257FF, 1, None).unwrap();
// TODO: binary diff against 'test-data/sleep/empty/empty.sleep'
@@ -199,5 +201,6 @@ fn test_sleep_create() {
&tmp_dir.path().join("simple_metadata.sleep"),
0x05025702,
40,
- Some("BLAKE2b".into())).unwrap();
+ Some("BLAKE2b".into()),
+ ).unwrap();
}
diff --git a/src/sleep_register.rs b/src/sleep_register.rs
index e798cad..fa8229d 100644
--- a/src/sleep_register.rs
+++ b/src/sleep_register.rs
@@ -8,14 +8,13 @@ use std::fs::OpenOptions;
use crypto::blake2b::Blake2b;
use crypto::digest::Digest;
use crypto::ed25519;
-use rand::{Rng, OsRng};
+use rand::{OsRng, Rng};
use errors::*;
use sleep_file::*;
/// Abstract access to Hypercore register
pub trait HyperRegister {
-
/// Whether the register store contains the given (data) entry
fn has(&self, index: u64) -> Result<bool>;
@@ -52,11 +51,9 @@ pub trait HyperRegister {
}
impl HyperRegister {
-
fn hash_leaf(data: &[u8]) -> [u8; 40] {
let mut buf = [0; 40];
- u64::to_be(data.len() as u64)
- .encode_fixed(&mut buf[32..40]);
+ u64::to_be(data.len() as u64).encode_fixed(&mut buf[32..40]);
let mut hash = Blake2b::new(32);
hash.input(&[0; 1]);
hash.input(&buf[32..40]);
@@ -68,10 +65,9 @@ impl HyperRegister {
fn hash_parent(lhash: &[u8], rhash: &[u8]) -> [u8; 40] {
let mut buf = [0; 40];
// TODO: check overflow
- let sum_size = u64::from_be(FixedInt::decode_fixed(&lhash[32..40])) +
- u64::from_be(FixedInt::decode_fixed(&rhash[32..40]));
- u64::to_be(sum_size as u64)
- .encode_fixed(&mut buf[32..40]);
+ let sum_size = u64::from_be(FixedInt::decode_fixed(&lhash[32..40]))
+ + u64::from_be(FixedInt::decode_fixed(&rhash[32..40]));
+ u64::to_be(sum_size as u64).encode_fixed(&mut buf[32..40]);
let mut hash = Blake2b::new(32);
hash.input(&[1; 1]);
@@ -96,7 +92,6 @@ impl HyperRegister {
}
hash.result(&mut buf[0..32]);
Ok(buf.to_vec())
-
}
fn tree_root_nodes(data_count: u64) -> Vec<u64> {
@@ -124,7 +119,7 @@ impl HyperRegister {
let mut roots = vec![];
for x in components {
roots.push(accum + (x - 1));
- accum += 2*x;
+ accum += 2 * x;
}
roots
}
@@ -134,7 +129,7 @@ impl HyperRegister {
// log(N) would go up previous parent nodes (eg, use root_nodes())
let mut sum: u64 = 0;
for i in 0..index {
- let leaf = reg.get_tree_entry(i*2)?;
+ let leaf = reg.get_tree_entry(i * 2)?;
sum += u64::from_be(FixedInt::decode_fixed(&leaf[32..40]));
}
Ok(sum)
@@ -147,14 +142,14 @@ impl HyperRegister {
// find lowest-significant zero bit
if (index & (1 << i)) == 0 {
// set that bit and clear next higher
- return ((index | (1 << i))) & !(1 << (i+1));
+ return ((index | (1 << i))) & !(1 << (i + 1));
}
}
panic!("Parent lookup overflowed, huge index!");
}
/// Calling this on a leaf node is an error, as is calling very high node numbers (> 2^62)
- fn tree_child_indices(index: u64) -> Result<(u64,u64)> {
+ fn tree_child_indices(index: u64) -> Result<(u64, u64)> {
if index % 2 == 0 {
bail!("Leaf tree nodes have no children");
}
@@ -162,9 +157,9 @@ impl HyperRegister {
// find lowest-significant zero bit...
if (index & (1 << i)) == 0 {
// larger child has this bit high, next lower bit cleared
- let right = ((index | (1 << i))) & !(1 << (i-1));
+ let right = ((index | (1 << i))) & !(1 << (i - 1));
// smaller child has next lower bit cleared
- let left = index & !(1 << (i-1));
+ let left = index & !(1 << (i - 1));
return Ok((left, right));
}
}
@@ -177,11 +172,11 @@ fn test_tree_root_nodes() {
assert_eq!(HyperRegister::tree_root_nodes(0), vec![]);
assert_eq!(HyperRegister::tree_root_nodes(1), vec![0]);
assert_eq!(HyperRegister::tree_root_nodes(2), vec![1]);
- assert_eq!(HyperRegister::tree_root_nodes(3), vec![1,4]);
+ assert_eq!(HyperRegister::tree_root_nodes(3), vec![1, 4]);
assert_eq!(HyperRegister::tree_root_nodes(4), vec![3]);
- assert_eq!(HyperRegister::tree_root_nodes(5), vec![3,8]);
- assert_eq!(HyperRegister::tree_root_nodes(6), vec![3,9]);
- assert_eq!(HyperRegister::tree_root_nodes(7), vec![3,9,12]);
+ assert_eq!(HyperRegister::tree_root_nodes(5), vec![3, 8]);
+ assert_eq!(HyperRegister::tree_root_nodes(6), vec![3, 9]);
+ assert_eq!(HyperRegister::tree_root_nodes(7), vec![3, 9, 12]);
assert_eq!(HyperRegister::tree_root_nodes(8), vec![7]);
}
@@ -205,12 +200,12 @@ fn test_tree_parent_index() {
fn test_tree_child_indices() {
assert!(HyperRegister::tree_child_indices(0).is_err());
assert!(HyperRegister::tree_child_indices(1024).is_err());
- assert_eq!(HyperRegister::tree_child_indices(1).unwrap(), (0, 2));
+ assert_eq!(HyperRegister::tree_child_indices(1).unwrap(), (0, 2));
- assert_eq!(HyperRegister::tree_child_indices(3).unwrap(), (1, 5));
- assert_eq!(HyperRegister::tree_child_indices(5).unwrap(), (4, 6));
- assert_eq!(HyperRegister::tree_child_indices(7).unwrap(), (3, 11));
- assert_eq!(HyperRegister::tree_child_indices(9).unwrap(), (8, 10));
+ assert_eq!(HyperRegister::tree_child_indices(3).unwrap(), (1, 5));
+ assert_eq!(HyperRegister::tree_child_indices(5).unwrap(), (4, 6));
+ assert_eq!(HyperRegister::tree_child_indices(7).unwrap(), (3, 11));
+ assert_eq!(HyperRegister::tree_child_indices(9).unwrap(), (8, 10));
assert_eq!(HyperRegister::tree_child_indices(11).unwrap(), (9, 13));
assert_eq!(HyperRegister::tree_child_indices(13).unwrap(), (12, 14));
assert_eq!(HyperRegister::tree_child_indices(15).unwrap(), (7, 23));
@@ -230,46 +225,49 @@ pub struct SleepDirRegister {
}
fn read_key_file(path: &Path, is_secret: bool) -> Result<Vec<u8>> {
-
let expected = if is_secret { 64 } else { 32 };
let mut key = vec![];
- let mut key_file = OpenOptions::new()
- .read(true)
- .write(false)
- .open(path)?;
+ let mut key_file = OpenOptions::new().read(true).write(false).open(path)?;
key_file.read_to_end(&mut key)?;
if key.len() != expected {
- bail!("Bad key file (len {} != {}): {:?}", key.len(), expected, path);
+ bail!(
+ "Bad key file (len {} != {}): {:?}",
+ key.len(),
+ expected,
+ path
+ );
}
Ok(key)
}
fn write_key_file(path: &Path, key: &[u8], is_secret: bool) -> Result<()> {
-
let expected = if is_secret { 64 } else { 32 };
if key.len() != expected {
- bail!("Bad key file (len {} != {}): {:?}", key.len(), expected, path);
+ bail!(
+ "Bad key file (len {} != {}): {:?}",
+ key.len(),
+ expected,
+ path
+ );
}
- let mut key_file = OpenOptions::new()
- .write(true)
- .create_new(true)
- .open(path)?;
+ let mut key_file = OpenOptions::new().write(true).create_new(true).open(path)?;
key_file.write_all(&key)?;
Ok(())
}
impl SleepDirRegister {
-
pub fn open(directory: &Path, prefix: &str, writable: bool) -> Result<SleepDirRegister> {
// read public key from disk
let pub_key: Vec<u8> = read_key_file(
&directory.join(Path::new(&(prefix.to_owned() + ".key"))),
- false)?;
+ false,
+ )?;
let mut secret_key = None;
if writable {
secret_key = Some(read_key_file(
&directory.join(Path::new(&(prefix.to_owned() + ".secret_key"))),
- true)?);
+ true,
+ )?);
}
let data_path = &(prefix.to_owned() + ".data");
let data_path = Path::new(data_path);
@@ -282,11 +280,17 @@ impl SleepDirRegister {
None
};
let tree_sleep = SleepFile::open(
- &directory.join(Path::new(&(prefix.to_owned() + ".tree"))), writable)?;
+ &directory.join(Path::new(&(prefix.to_owned() + ".tree"))),
+ writable,
+ )?;
let sign_sleep = SleepFile::open(
- &directory.join(Path::new(&(prefix.to_owned() + ".signatures"))), writable)?;
+ &directory.join(Path::new(&(prefix.to_owned() + ".signatures"))),
+ writable,
+ )?;
let bitfield_sleep = SleepFile::open(
- &directory.join(Path::new(&(prefix.to_owned() + ".bitfield"))), writable)?;
+ &directory.join(Path::new(&(prefix.to_owned() + ".bitfield"))),
+ writable,
+ )?;
let mut sf = SleepDirRegister {
tree_sleep,
sign_sleep,
@@ -308,11 +312,13 @@ impl SleepDirRegister {
write_key_file(
&directory.join(Path::new(&(prefix.to_owned() + ".key"))),
&pub_key,
- false)?;
+ false,
+ )?;
write_key_file(
&directory.join(Path::new(&(prefix.to_owned() + ".secret_key"))),
&secret_key,
- true)?;
+ true,
+ )?;
let data_file = OpenOptions::new()
.read(true)
.write(true)
@@ -322,17 +328,20 @@ impl SleepDirRegister {
&directory.join(Path::new(&(prefix.to_owned() + ".tree"))),
0x05025702,
40,
- Some("BLAKE2b".to_string()))?;
+ Some("BLAKE2b".to_string()),
+ )?;
let sign_sleep = SleepFile::create(
&directory.join(Path::new(&(prefix.to_owned() + ".signatures"))),
0x05025701,
64,
- Some("Ed25519".to_string()))?;
+ Some("Ed25519".to_string()),
+ )?;
let bitfield_sleep = SleepFile::create(
&directory.join(Path::new(&(prefix.to_owned() + ".bitfield"))),
0x05025700,
3328,
- None)?;
+ None,
+ )?;
let mut sf = SleepDirRegister {
tree_sleep,
sign_sleep,
@@ -347,7 +356,6 @@ impl SleepDirRegister {
}
impl HyperRegister for SleepDirRegister {
-
/// TODO: this version only works for "dense" registers: it just checks if the index is in the
/// total length, instead of using the bitfield.
fn has(&self, index: u64) -> Result<bool> {
@@ -370,7 +378,6 @@ impl HyperRegister for SleepDirRegister {
}
fn get_data_entry(&mut self, index: u64) -> Result<Vec<u8>> {
-
// Get metadata about chunk (offset and length)
let offset = HyperRegister::get_data_offset(self, index)?;
@@ -384,7 +391,7 @@ impl HyperRegister for SleepDirRegister {
} else {
bail!("No data file in this register");
};
- let leaf = self.tree_sleep.read(index*2)?;
+ let leaf = self.tree_sleep.read(index * 2)?;
let data_len = u64::from_be(FixedInt::decode_fixed(&leaf[32..40]));
// avoid foot-gun in development: cap at ~1 billion bytes
assert!(data_len < 2u64.pow(29));
@@ -403,7 +410,6 @@ impl HyperRegister for SleepDirRegister {
}
fn append(&mut self, data: &[u8]) -> Result<u64> {
-
if !self.data_file.is_some() {
bail!("No data file in this register");
};
@@ -420,22 +426,21 @@ impl HyperRegister for SleepDirRegister {
}
// 3. Add hash to tree file, update merkel tree
- self.tree_sleep.write(index*2, &leaf_hash)?;
- let mut parent = HyperRegister::tree_parent_index(index*2);
- while parent < index*2 {
+ self.tree_sleep.write(index * 2, &leaf_hash)?;
+ let mut parent = HyperRegister::tree_parent_index(index * 2);
+ while parent < index * 2 {
let (left, right) = HyperRegister::tree_child_indices(parent)?;
- let (left, right) = (self.tree_sleep.read(left)?,
- self.tree_sleep.read(right)?);
+ let (left, right) = (self.tree_sleep.read(left)?, self.tree_sleep.read(right)?);
let parent_hash = HyperRegister::hash_parent(&left[0..40], &right[0..40]);
self.tree_sleep.write(parent, &parent_hash[0..40])?;
parent = HyperRegister::tree_parent_index(parent);
}
-
+
// 4. Add signature to signature file
- let root_hash = HyperRegister::hash_roots(self, index+1)?;
+ let root_hash = HyperRegister::hash_roots(self, index + 1)?;
let root_sig = ed25519::signature(&root_hash, &self.secret_key.clone().unwrap());
self.sign_sleep.append(&root_sig)?;
-
+
// 5. Update bitfile
Ok(index)
}
@@ -457,7 +462,7 @@ impl HyperRegister for SleepDirRegister {
// log(N) would go up previous parent nodes (eg, use tree_root_nodes())
let mut sum: u64 = 0;
for i in 0..self.len()? {
- let leaf = self.get_tree_entry(i*2)?;
+ let leaf = self.get_tree_entry(i * 2)?;
sum += u64::from_be(FixedInt::decode_fixed(&leaf[32..40]));
}
Ok(sum)
@@ -471,7 +476,7 @@ impl HyperRegister for SleepDirRegister {
let sign_len = self.sign_sleep.len()?;
let tree_len = self.tree_sleep.len()?;
if (tree_len == 0) && (sign_len == 0) {
- return Ok(())
+ return Ok(());
}
if tree_len != (sign_len * 2) - 1 {
bail!("Inconsistent SLEEP signature/tree file sizes");
@@ -488,22 +493,21 @@ impl HyperRegister for SleepDirRegister {
/// Checks if we have the secret key (such that we can append to this register)
fn writable(&self) -> bool {
- return self.secret_key.is_some()
+ return self.secret_key.is_some();
}
}
#[test]
fn test_sdr_open() {
-
- let mut sdr = SleepDirRegister::open(
- Path::new("test-data/dat/simple/.dat/"), "metadata", false).unwrap();
+ let mut sdr =
+ SleepDirRegister::open(Path::new("test-data/dat/simple/.dat/"), "metadata", false).unwrap();
// Values from 'dat log'
assert_eq!(sdr.len().unwrap(), 3);
assert_eq!(sdr.len_bytes().unwrap(), 145);
- let mut sdr = SleepDirRegister::open(
- Path::new("test-data/dat/simple/.dat/"), "content", false).unwrap();
+ let mut sdr =
+ SleepDirRegister::open(Path::new("test-data/dat/simple/.dat/"), "content", false).unwrap();
// Values from 'dat log'
assert_eq!(sdr.len().unwrap(), 2);
@@ -512,7 +516,6 @@ fn test_sdr_open() {
#[test]
fn test_sdr_create() {
-
use tempdir::TempDir;
let tmp_dir = TempDir::new("geniza-test").unwrap();
let mut sdr = SleepDirRegister::create(tmp_dir.path(), "dummy").unwrap();
@@ -523,7 +526,6 @@ fn test_sdr_create() {
#[test]
fn test_sdr_append() {
-
use tempdir::TempDir;
let tmp_dir = TempDir::new("geniza-test").unwrap();
let mut sdr = SleepDirRegister::create(tmp_dir.path(), "dummy").unwrap();
@@ -532,18 +534,17 @@ fn test_sdr_append() {
sdr.check().unwrap();
assert_eq!(sdr.len().unwrap(), 1);
assert_eq!(sdr.len_bytes().unwrap(), 12);
- let count = 100; // TODO: make this >1000 when things are faster
+ let count = 100; // TODO: make this >1000 when things are faster
for _ in 0..count {
- sdr.append(&[1,2,3,4,5]).unwrap();
+ sdr.append(&[1, 2, 3, 4, 5]).unwrap();
}
sdr.check().unwrap();
- assert_eq!(sdr.len().unwrap(), 1+count);
- assert_eq!(sdr.len_bytes().unwrap(), 12 + (count*5));
+ assert_eq!(sdr.len().unwrap(), 1 + count);
+ assert_eq!(sdr.len_bytes().unwrap(), 12 + (count * 5));
}
#[test]
fn test_sdr_has() {
-
use tempdir::TempDir;
let tmp_dir = TempDir::new("geniza-test").unwrap();
let mut sdr = SleepDirRegister::create(tmp_dir.path(), "dummy").unwrap();