Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wp/ updated delete file to use pk as filename #33

Open
wants to merge 54 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 48 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
25eef4c
WP/skip files if exists on write
Mar 13, 2023
61b2edc
WP/check_catalog_exists [test]
Mar 14, 2023
eddf0d5
WP/block write_read [test] temporarily
Mar 14, 2023
07e5283
WP/delete-file-blake3hash-http-route
rustchain64 Mar 14, 2023
227ed37
WP/delete-file-format-update
rustchain64 Mar 14, 2023
7d85f6b
WP/delete-file-fix-clippy-issues
rustchain64 Mar 14, 2023
e148dd9
WP/18-slices-blake3_hash-slice_index-slice_range
rustchain64 Mar 15, 2023
8f30773
WP/18-slice-blake3_hash-slice-prototype
rustchain64 Apr 5, 2023
767156c
WP/18-slice-implement-http-get-slice
rustchain64 Apr 5, 2023
f02bc40
WP/18-slice-blake3_hash-slice-dev
rustchain64 Apr 6, 2023
ab317e4
WP/18-slice-blacke3-hash-slice-test-error-file-108
rustchain64 Apr 8, 2023
908e39d
WP/18-slice-black3-hash-Encoded
rustchain64 Apr 8, 2023
5f6c4c2
WP/18-slice-black3-hash-debug-stage
rustchain64 Apr 10, 2023
ba92b5d
WP/18-slice-black3-HT-to-debug
rustchain64 Apr 10, 2023
684bb7c
WP/18-slicke-blake3_hash-stash
rustchain64 Apr 11, 2023
fc8634e
WP/18-slice-blake3_hash-analyze-test
rustchain64 Apr 12, 2023
29a31b4
WP/18-slice-blake3-resolve-cargo-toml
rustchain64 Apr 12, 2023
e50a2d5
WP/18-slice-blake3-clippy
rustchain64 Apr 12, 2023
6b77b22
WP/18-slice-blake3-read_slices
rustchain64 Apr 12, 2023
657c120
WP/18-slice-blake3-test-update
rustchain64 Apr 12, 2023
50dc264
WP/18-slice-blake3-unneeded-return
rustchain64 Apr 12, 2023
dedb85d
WP/18-slice-blake3-http-get-slice
rustchain64 Apr 12, 2023
13134f7
WP/upload-get-last-hash
rustchain64 Apr 19, 2023
2f2e403
WP/upload-get-last-hash-debug
rustchain64 Apr 21, 2023
cbf7e9b
WP/upload-get-last-hash-cleanup
rustchain64 Apr 25, 2023
990420d
WP/upload-get-last-hash-test-to-pass
rustchain64 Apr 25, 2023
eff5232
WP/upload-get-last-hash-file-read-test
rustchain64 Apr 25, 2023
d32eeca
WP/upload-get-last-hash-implement-catalog-exists
rustchain64 Apr 25, 2023
5b9a950
WP/upload-get-last-hash-revert-tests
rustchain64 Apr 25, 2023
91ae1b9
WP/upload-get-last-hash-remove-file-write-local
rustchain64 Apr 25, 2023
30f7878
WP/upload-get-last-hash-clippy
rustchain64 Apr 25, 2023
a7fc00a
WP/upload-get-last-hash-path-exists
rustchain64 Apr 26, 2023
01ba0f7
WP/upload-get-last-debug-binary-files
rustchain64 Apr 29, 2023
8e88ead
WP/upload-get-last-point-cargo-toml
rustchain64 Apr 29, 2023
9e3a446
WP/upload-get-hash-clippy
rustchain64 Apr 29, 2023
8849101
Implement HTTP body streaming version of post_file.
cryptoquick Apr 30, 2023
ea0c994
Refactor streaming interface format. Fix tests.
cryptoquick Apr 30, 2023
4629aa2
Reduce number of files created in test by increasing chunk size to 1MB.
cryptoquick Apr 30, 2023
3e9949d
Fix check catalog_exists test. Cleanup unused libraries.
cryptoquick Apr 30, 2023
d1f9216
Log node public key in config. Correct Error Message in fs backend. R…
rustchain64 May 1, 2023
961f663
WP/upload-last-hash-merger-with-stream-post-file
rustchain64 May 2, 2023
730f208
upload-get-lash-hash fixes. (#38)
cryptoquick May 4, 2023
7188500
Merge main.
cryptoquick May 4, 2023
7db7d4d
temp stash
rustchain64 May 4, 2023
4e21025
update delete
rustchain64 May 4, 2023
642acb4
delete across volumes
rustchain64 May 4, 2023
8637f02
deleted files counter
rustchain64 May 5, 2023
04d53bf
comments
rustchain64 May 5, 2023
04ef77f
handle HT comments
rustchain64 May 8, 2023
dd5fa8c
updated delete file for file_name
rustchain64 May 8, 2023
c675bd0
remove slice function
rustchain64 May 8, 2023
18fc5df
fix clippy error
rustchain64 May 8, 2023
f651742
read_slices backup
rustchain64 May 8, 2023
c4329ad
backup only
rustchain64 May 9, 2023
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
Binary file modified .DS_Store
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not add this file

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file still needs to be removed. You need to add that to your global gitignore (no need to add it to the project gitignore.)

Copy link
Collaborator Author

@rustchain64 rustchain64 May 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added the (global) .gitignore for Mac

Copy link
Collaborator Author

@rustchain64 rustchain64 May 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ran
sudo find / -name ".DS_Store" -depth -exec rm {} ;
ran cargo test, no .DS_Store present

Binary file not shown.
313 changes: 179 additions & 134 deletions Cargo.lock

Large diffs are not rendered by default.

Binary file added file/body_test.png
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not add this file, please remove

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file does not appear to be used, and besides, it's in the wrong place. Please remove this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed, not used for testing at this anymore

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion src/backend.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
pub mod fs;
// pub mod task;
127 changes: 60 additions & 67 deletions src/backend/fs.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::{
fs::{self, OpenOptions},
io::{self, Read, Seek, Write},
path::{Path, PathBuf},
io::{Read, Seek, Write},
pin::Pin,
str::FromStr,
sync::Arc,
};

Expand Down Expand Up @@ -134,6 +134,7 @@ pub fn write_segment(sk: &[u8], pk: &[u8], encoded: &Encoded) -> Result<BaoHash>

pub fn write_catalog(file_hash: &Blake3Hash, segment_hashes: &[BaoHash]) -> Result<()> {
debug!("Write catalog");

let contents: Vec<u8> = segment_hashes
.iter()
.flat_map(|bao_hash| bao_hash.to_bytes())
Expand Down Expand Up @@ -255,73 +256,65 @@ pub fn read_catalog(file_hash: &Blake3Hash) -> Result<Vec<BaoHash>> {
Ok(bao_hashes)
}

#[allow(unused_variables)]
pub fn delete_file(pk: Secp256k1PubKey, file_bytes: &[u8]) -> Result<()> {
let pk_bytes = pk.to_bytes();
let (x_only_pk, _) = pk.into_inner().x_only_public_key();

let file_hash = Blake3Hash(blake3::keyed_hash(&x_only_pk.serialize(), file_bytes));
trace!(">>>>>file_hash:: {}", file_hash);

for vol in &SYS_CFG.volumes {
let seg_file = &vol.path.join(SEGMENT_DIR).join(file_hash.to_string());
let seg_dir = &vol.path.join(SEGMENT_DIR);
remove_dir_contents(seg_dir, seg_file.to_path_buf()).unwrap();
}

for vol in &SYS_CFG.volumes {
let cat_path = &vol.path.join(CATALOG_DIR).join(file_hash.to_string());
let cat = &vol.path.join(CATALOG_DIR);
remove_dir_catalogs(cat.to_path_buf(), cat_path.to_path_buf()).unwrap();
}
Ok(())
pub async fn read_slices(
//hash: bao::Hash, // from Blake3
file_bytes: &[u8],
//slice_start: u64, //let slice_start = 65536;
//slice_len: u16, // let slice_len = 8192;
) -> Result<Vec<u8>> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes no sense to provide the entire file to this method. This is supposed to be for retrieving just a slice of the file. It needs to return the range of the raw bytes on disk. It can make the disk IO calls by reading the catalog and then the appropriate segment.

I've updated the issue so hopefully the task is more clear:
#18

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

those values where for initial testing only.
actual slice data comes from the params.

use std::io::prelude::*;

// Start by encoding some input.
let (encoded_input, hash) = bao::encode::encode(file_bytes);
debug!(">>> encoded INPUT LENGTH:: {:?}", &encoded_input.len());
debug!(">>> fs hash hash:: {:?}", &hash);

// Slice the encoding. These parameters are multiples of the chunk size, which avoids
// unnecessary overhead.
let slice_start = 65536;
let slice_len = 8192;
let encoded_cursor = std::io::Cursor::new(&encoded_input);
let mut extractor = bao::encode::SliceExtractor::new(encoded_cursor, slice_start, slice_len);
let mut slice = Vec::new();
extractor.read_to_end(&mut slice)?;

// Decode the slice. The result should be the same as the part of the input that the slice
// represents. Note that we're using the same hash that encoding produced, which is
// independent of the slice parameters. That's the whole point; if we just wanted to re-encode
// a portion of the input and wind up with a different hash, we wouldn't need slicing.
let mut decoded = Vec::new();
let mut decoder = bao::decode::SliceDecoder::new(&*slice, &hash, slice_start, slice_len);
decoder.read_to_end(&mut decoded)?;

debug!(
"usize vs length: {:?}",
&encoded_input[slice_start as usize..][..slice_len as usize].len()
);

// Like regular decoding, slice decoding will fail if the hash doesn't match.
// let mut bad_slice = slice.clone();
// debug!("BAD SLICE");
// let last_index = bad_slice.len() - 1;
// bad_slice[last_index] ^= 1;
// let mut decoder = bao::decode::SliceDecoder::new(&*bad_slice, &hash, slice_start, slice_len);
// let err = decoder.read_to_end(&mut Vec::new()).unwrap_err();
// assert_eq!(std::io::ErrorKind::InvalidData, err.kind());

Ok(decoded)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None of this makes any sense. Do not submit this code again.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reworking slices by reading catalog, not files as you stated.

}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this code here? Can't we just use extract_slice from carbonado core?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing this section, as I was using it for A/B testing on the results.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have not yet removed it. Only request my review once everything has been addressed.


#[allow(unused_variables)]
fn remove_dir_contents<P: AsRef<Path>>(path: P, seg_file: PathBuf) -> io::Result<()> {
trace!(">>> remove_Segment_contents");
for entry in fs::read_dir(path)? {
trace!("Delete Segment File at {:?}", entry);
fs::remove_file(entry?.path())?;
}
Ok(())
}

#[allow(unused_variables)]
fn remove_dir_catalogs(path: PathBuf, file: PathBuf) -> io::Result<()> {
for entry in fs::read_dir(path)? {
trace!("Delete CATALOG File at {:?}", entry);
fs::remove_file(entry?.path())?;
pub async fn delete_file(hash: &String) -> Result<()> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should pass &str, not &String, this is not a pattern we use.

let blake3_hash = &Blake3Hash(blake3::Hash::from_str(hash)?);
let catalog = read_catalog(blake3_hash)?;
for vol in &SYS_CFG.volumes {
for cat in &catalog {
let seg_file = &vol.path.join(SEGMENT_DIR).join(cat.to_string() + ".c15");
let is_removed = fs::remove_file(seg_file).is_ok();
trace!("SEG: {:?} REMOVED: {:?}", &seg_file, is_removed);
}
let cat_path = &vol.path.join(CATALOG_DIR).join(hash);
let is_removed = fs::remove_file(cat_path).is_ok();
trace!("CAT: {:?}: REMOVED: {:?}", &cat_path, is_removed);
}
Ok(())
}

// fn remove_dir_segements<P: AsRef<Path>>(path: P, seg_file: PathBuf) -> io::Result<()> {
// trace!(">>> remove_Segment_contents");
// for entry in fs::read_dir(path)? {
// let entry = entry?;
// trace!("ENTRY Delete SEGMENT File at {:?}", entry);

// match &entry {
// seg_file => {
// fs::remove_file(seg_file.path())?;
// trace!("Delete Segment File at {:?}", seg_file);
// }
// }
// }
// Ok(())
// }

// fn remove_dir_catalogs(path: PathBuf, file: PathBuf) -> io::Result<()> {
// for entry in fs::read_dir(path)? {
// let entry = entry?;
// trace!("ENTRY Delete CATALOG File at {:?}", entry);
// match &entry {
// file => {
// fs::remove_file(file.path())?;
// trace!("FILE MATCH Delete CATALOG File at {:?}", file);
// }
// }
// }
// Ok(())
// }
cryptoquick marked this conversation as resolved.
Show resolved Hide resolved
10 changes: 4 additions & 6 deletions src/frontend/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,8 @@ async fn get_file(
}

#[axum_macros::debug_handler]
async fn remove_file(
Path((pk, blake3_hash)): Path<(String, String)>,
) -> Result<impl IntoResponse, AppError> {
let pk = Secp256k1PubKey::try_from(pk.as_str())?;
delete_file(pk, blake3_hash.as_bytes())?;
async fn remove_file(Path(blake3_hash): Path<String>) -> Result<impl IntoResponse, AppError> {
delete_file(&blake3_hash).await?;
Ok((StatusCode::OK, blake3_hash))
}

Expand All @@ -89,9 +86,10 @@ async fn key(Path(pk): Path<String>) -> Result<impl IntoResponse, AppError> {

pub async fn start() -> Result<()> {
let app = Router::new()
.route("/remove/:pk/:blake3_hash", delete(remove_file))
.route("/remove/:blake3_hash", delete(remove_file))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You removed the pk... We'll need this to be passed for the changes I'm making in #39. I've trimmed that PR down so we can get that merged and you can use that to make sure file deletion is namespaced by pk.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, your changes address that.

.route("/store/:pk", post(post_file))
.route("/retrieve/:pk/:blake3_hash", get(get_file))
// .route("/slice/", get(get_slice))
.route("/key/:pk", get(key))
// .route("/catalog/:blake3_hash", get(get_catalog))
// .route("/raw/:bao_hash", get(get_raw))
Expand Down
10 changes: 10 additions & 0 deletions src/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ impl fmt::Display for Blake3Hash {
}
}

impl TryFrom<&[u8]> for Blake3Hash {
type Error = Error;

fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
let mut hash = [0_u8; 32];
hash.copy_from_slice(&value[0..32]);
Ok(Self(blake3::Hash::try_from(hash)?))
}
}

pub struct BaoHash(pub bao::Hash);

impl BaoHash {
Expand Down
128 changes: 57 additions & 71 deletions tests/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ use std::fs;
use anyhow::Result;
use axum::body::Bytes;
use carbonado_node::{
backend::fs::{read_file, write_file, FileStream},
config::node_shared_secret,
prelude::SEGMENT_SIZE,
backend::fs::{delete_file, read_file, write_file, FileStream},
config::{node_shared_secret, SYS_CFG},
prelude::{CATALOG_DIR, SEGMENT_DIR, SEGMENT_SIZE},
structs::Secp256k1PubKey,
};
use futures_util::{stream, StreamExt};
Expand Down Expand Up @@ -63,100 +63,86 @@ async fn write_read() -> Result<()> {
"Original keyed blake3 hash and streamed hash match",
);

// TODO: This is not how you delete files
// let new_file_bytes = delete_file(Secp256k1PubKey(write_pk), &file_bytes).is_err();
// debug!("Write Delete:: deleted file:: {:?}", new_file_bytes);
// Delete file with hash across all volumes in config
let new_file_bytes = delete_file(&blake3_hash.to_string()).await.is_ok();
debug!("Write/Read Deleted file:: {:?}", new_file_bytes);

info!("Write/Delete test finished successfully!");
info!("Write/Read test finished successfully!");

Ok(())
}

#[tokio::test]
async fn check_catalog_exists() -> Result<()> {
async fn read_write_delete_file() -> Result<()> {
carbonado::utils::init_logging(RUST_LOG);

// write file to test delete
let (_sk, pk) = generate_keypair(&mut thread_rng());

info!("Reading file bytes");
let file_bytes = fs::read("tests/samples/cat.gif")?;
debug!("{} bytes read", file_bytes.len());

let file_stream = stream::iter(file_bytes)
.chunks(1024 * 1024)
.map(|chunk| Ok(Bytes::from(chunk)))
.boxed();

info!("Writing file if not exists");
let is_ok = write_file(&Secp256k1PubKey(pk), file_stream).await.is_ok();
debug!("Skip writing file as File hash exists: {is_ok}");
assert!(is_ok);

let file_bytes = fs::read("tests/samples/cat.gif")?;
let file_stream = stream::iter(file_bytes)
.chunks(1024 * 1024)
.map(|chunk| Ok(Bytes::from(chunk)))
.boxed();

info!("Writing file if not exists");
let is_err = write_file(&Secp256k1PubKey(pk), file_stream).await.is_err();
debug!("Skip writing file as File hash exists: {is_err}");
assert!(is_err);

Ok(())
}

#[tokio::test]
async fn read_write_delete_file() -> Result<()> {
carbonado::utils::init_logging(RUST_LOG);

info!("Write Delete:: Reading file bytes");
let file_bytes = fs::read("tests/samples/cat.gif")?;
debug!("{} Write Delete:: bytes read", file_bytes.len());

let file_stream = stream::iter(file_bytes.clone())
let file_stream = stream::iter(file_bytes)
.chunks(1024 * 1024)
.map(|chunk| Ok(Bytes::from(chunk)))
.boxed();

// first file to write
let (_sk, pk) = generate_keypair(&mut thread_rng());
info!("Write Delete:: Writing file if not exists in order to test delete");
let final_blake3_hash = write_file(&Secp256k1PubKey(pk), file_stream).await?;

// info!("Write Delete:: Writing file if not exists in order to test delete");
let file_did_write = write_file(&Secp256k1PubKey(pk), file_stream).await.is_ok();
info!(
"File To Delete as blake3_hash:: {} ",
final_blake3_hash.to_string()
);

if file_did_write {
info!(
"Write File Group One to Delete File as blake3_hash:: {} ",
file_did_write.to_string()
// Check number of catalog files
let mut current_volume = -1; // start for volume 0
for vol in &SYS_CFG.volumes {
current_volume += 1;
let seg_file = &vol.path.join(CATALOG_DIR);

let paths = fs::read_dir(seg_file).unwrap();
let mut counter = -1;
for path in paths {
counter += 1;
debug!(
"Catalog count: {:?} :: path: {}",
counter,
path.unwrap().path().display()
)
}
debug!(
"For Volume: {}, total catalogs deleted: {:?}",
current_volume, counter
);
}

// second file to write
let (_sk, pk) = generate_keypair(&mut thread_rng());

let file_stream = stream::iter(file_bytes)
.chunks(1024 * 1024)
.map(|chunk| Ok(Bytes::from(chunk)))
.boxed();

info!("Write Delete:: Writing file if not exists in order to test delete");
let blake3_hash = write_file(&Secp256k1PubKey(pk), file_stream).await.is_ok();

if blake3_hash {
info!(
"Write File in Group Two to Delete File as blake3_hash:: {} ",
blake3_hash.to_string()
// Check number of segment files
let mut current_volume = -1; // start for volume 0
for vol in &SYS_CFG.volumes {
current_volume += 1;
let seg_file = &vol.path.join(SEGMENT_DIR);

let paths = fs::read_dir(seg_file).unwrap();
let mut counter = -1; // account for .DS_store in dir .../segments/.DS_Store
for path in paths {
counter += 1;
debug!(
"Segment count: {:?} :: path: {}",
counter,
path.unwrap().path().display()
)
}
debug!(
"For Volume: {}, total segments deleted: {:?}",
current_volume, counter
);
}

// TODO: This is not how you delete files
// let new_file_bytes = delete_file(Secp256k1PubKey(pk), &file_bytes).is_err();
// debug!("Write Delete:: deleted file:: {:?}", new_file_bytes);

// TODO: Check number of files
// Delete Files for blake3_hash
let new_file_bytes = delete_file(&final_blake3_hash.to_string()).await.is_ok();
debug!("Deleted files success:: {:?}", new_file_bytes);

debug!(" >>>> Public Key Generated :: {:?} :: {}", _sk, pk);
info!("Write/Delete test finished successfully!");

Ok(())
Expand Down