From 062e63635223da4ceecc15e53b9d1a5cd1774e9b Mon Sep 17 00:00:00 2001 From: Sam Stelfox Date: Mon, 12 Feb 2024 00:56:26 -0500 Subject: [PATCH] feat: that gets us as far as drive encoding --- Cargo.lock | 15 ++++++++ Cargo.toml | 1 + src/codec/content_payload/mod.rs | 18 ++++++++++ src/filesystem/mod.rs | 39 ++++++++++++++++---- src/main.rs | 62 +++++++++++++++++--------------- 5 files changed, 99 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6a2a45e..cf07b22 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -109,6 +109,7 @@ dependencies = [ "thiserror", "time", "tokio", + "tokio-util", "tracing", "tracing-appender", "tracing-subscriber", @@ -1225,6 +1226,20 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio-util" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +dependencies = [ + "bytes", + "futures-core", + "futures-io", + "futures-sink", + "pin-project-lite", + "tokio", +] + [[package]] name = "tracing" version = "0.1.40" diff --git a/Cargo.toml b/Cargo.toml index a97c02a..5216ff4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ crdts = { version = "^7", default-features = false, features = [ "num", ] } time = "^0.3" +tokio-util = { version = "^0.7", features = ["compat", "io"] } [[bin]] name = "banyanfs" diff --git a/src/codec/content_payload/mod.rs b/src/codec/content_payload/mod.rs index 20efdcc..b8ef9e4 100644 --- a/src/codec/content_payload/mod.rs +++ b/src/codec/content_payload/mod.rs @@ -8,11 +8,14 @@ pub use history_end::HistoryEnd; pub use history_start::HistoryStart; pub use key_access_settings::KeyAccessSettings; +use async_trait::async_trait; +use futures::AsyncWrite; use nom::error::{Error as NomError, ErrorKind}; use nom::number::streaming::le_u8; use nom::{Err, IResult}; use crate::codec::crypto::{AccessKey, AsymLockedAccessKey, SigningKey}; +use crate::codec::AsyncEncodable; pub enum ContentPayload { Private { access_key: AccessKey }, @@ -50,3 +53,18 @@ impl ContentPayload { Ok((input, ContentPayload::Public)) } } + +#[async_trait] +impl AsyncEncodable for ContentPayload { + async fn encode( + &self, + _writer: &mut W, + _pos: usize, + ) -> std::io::Result { + let _written_bytes = 0; + + todo!(); + + //Ok(written_bytes) + } +} diff --git a/src/filesystem/mod.rs b/src/filesystem/mod.rs index 3196fb9..232f271 100644 --- a/src/filesystem/mod.rs +++ b/src/filesystem/mod.rs @@ -9,9 +9,13 @@ pub use nodes::*; use std::collections::HashMap; use std::ops::{Deref, DerefMut}; -use crate::codec::content_payload::KeyAccessSettings; -use crate::codec::crypto::{SigningKey, VerifyingKey}; -use crate::codec::{ActorId, FilesystemId}; +use ecdsa::signature::rand_core::CryptoRngCore; +use futures::AsyncWrite; + +use crate::codec::content_payload::{ContentPayload, KeyAccessSettings}; +use crate::codec::crypto::{AccessKey, SigningKey, VerifyingKey}; +use crate::codec::header::{IdentityHeader, PublicSettings}; +use crate::codec::{ActorId, AsyncEncodable, FilesystemId}; pub struct Drive { filesystem_id: FilesystemId, @@ -34,13 +38,34 @@ impl Drive { } } + pub async fn encode_with_key( + &self, + writer: &mut W, + rng: &mut impl CryptoRngCore, + _signing_key: &SigningKey, + ) -> std::io::Result { + let mut written_bytes = 0; + + written_bytes += IdentityHeader::encode(&IdentityHeader, writer, 0).await?; + written_bytes += self.filesystem_id.encode(writer, 0).await?; + + // only doing private ones for now + written_bytes += PublicSettings::new(false, true).encode(writer, 0).await?; + + let content_payload = ContentPayload::Private { + access_key: AccessKey::generate(rng), + }; + + written_bytes += content_payload.encode(writer, 0).await?; + + Ok(written_bytes) + } + pub fn id(&self) -> FilesystemId { self.filesystem_id } - pub fn initialize_private(signing_key: &SigningKey) -> Self { - let mut rng = crate::utils::crypto_rng(); - + pub fn initialize_private(rng: &mut impl CryptoRngCore, signing_key: &SigningKey) -> Self { let verifying_key = signing_key.verifying_key(); let actor_id = signing_key.actor_id(); @@ -59,7 +84,7 @@ impl Drive { keys.insert(actor_id, (verifying_key, kas)); Self { - filesystem_id: FilesystemId::generate(&mut rng), + filesystem_id: FilesystemId::generate(rng), keys, root: Directory::new(actor_id), } diff --git a/src/main.rs b/src/main.rs index 5f1700b..916df72 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ fn main() -> BanyanFsResult<()> { #[tokio::main] async fn main() -> BanyanFsResult<()> { use banyanfs::codec::filesystem::DirectoryPermissions; + use tokio_util::compat::TokioAsyncReadCompatExt; use tracing::Level; use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; @@ -28,20 +29,9 @@ async fn main() -> BanyanFsResult<()> { tracing::debug!("running banyanfs {}", version()); let mut rng = banyanfs::utils::crypto_rng(); - - let header = FormatHeader { - ecc_present: false, - private: false, - filesystem_id: FilesystemId::generate(&mut rng), - }; - - let mut output_stream = Vec::new(); - header.encode(&mut output_stream, 0).await.unwrap(); - tracing::info!("output_stream: {:02x?}", output_stream); - let signing_key = SigningKey::generate(&mut rng); - let actor_id = signing_key.actor_id(); - let mut drive = Drive::initialize_private(&signing_key); + + let mut drive = Drive::initialize_private(&mut rng, &signing_key); if !drive.check_accessibility(&signing_key.verifying_key()) { tracing::error!("key doesn't have access to the drive"); @@ -49,23 +39,14 @@ async fn main() -> BanyanFsResult<()> { } if drive.is_writable(&signing_key) { + let actor_id = signing_key.actor_id(); let new_perms = DirectoryPermissions::default(); + if let Err(err) = drive.mkdir(actor_id, &["testing", "paths"], new_perms, true) { tracing::error!("failed to create directory: {}", err); return Ok(()); } - match drive.ls(&["testing"]) { - Ok(dir_contents) => { - let names: Vec = dir_contents.into_iter().map(|(name, _)| name).collect(); - tracing::info!("dir_contents: {names:?}"); - } - Err(err) => { - tracing::error!("failed to list directory: {err}"); - return Ok(()); - } - } - // let fh = drive.open("/root/testing/deep/paths/file.txt")?; // fh.write(b"hello world")?; // fh.close()?; @@ -84,12 +65,35 @@ async fn main() -> BanyanFsResult<()> { // drive.sync()?; } - //let dir_contents = drive.ls("/root/testing")?; - //tracing::info!("dir_contents: {dir_contents:?}"); + match drive.ls(&["testing"]) { + Ok(dir_contents) => { + let names: Vec = dir_contents.into_iter().map(|(name, _)| name).collect(); + tracing::info!("dir_contents: {names:?}"); + } + Err(err) => { + tracing::error!("failed to list directory: {err}"); + return Ok(()); + } + } - //let mut fh = tokio::fs::File::open("fixtures/minimal.bfs").await?; - //drive.encode_with_key(&mut fh, &signing_key).await?; - //fh.close().await?; + let mut file_opts = tokio::fs::OpenOptions::new(); + + file_opts.write(true); + file_opts.create(true); + file_opts.truncate(true); + + let mut fh = match file_opts.open("fixtures/minimal.bfs").await { + Ok(fh) => fh.compat(), + Err(err) => { + tracing::error!("failed to open file: {err}"); + return Ok(()); + } + }; + + drive + .encode_with_key(&mut fh, &mut rng, &signing_key) + .await + .unwrap(); //let mut fh = tokio::fs::File::open("fixtures/minimal.bfs").await?; //let loaded_drive = Drive::load_with_key(&mut fh, &signing_key).await?;