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

Remove generic parameters from Hypercore and Storage #139

Merged
merged 4 commits into from
Jul 4, 2024
Merged
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
5 changes: 2 additions & 3 deletions benches/disk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use std::time::{Duration, Instant};
use criterion::async_executor::AsyncStdExecutor;
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use hypercore::{Hypercore, HypercoreBuilder, HypercoreError, Storage};
use random_access_disk::RandomAccessDisk;
use tempfile::Builder as TempfileBuilder;

fn bench_create_disk(c: &mut Criterion) {
Expand All @@ -24,7 +23,7 @@ fn bench_create_disk(c: &mut Criterion) {
}

#[cfg(feature = "cache")]
async fn create_hypercore(name: &str) -> Result<Hypercore<RandomAccessDisk>, HypercoreError> {
async fn create_hypercore(name: &str) -> Result<Hypercore, HypercoreError> {
let dir = TempfileBuilder::new()
.prefix(name)
.tempdir()
Expand All @@ -38,7 +37,7 @@ async fn create_hypercore(name: &str) -> Result<Hypercore<RandomAccessDisk>, Hyp
}

#[cfg(not(feature = "cache"))]
async fn create_hypercore(name: &str) -> Result<Hypercore<RandomAccessDisk>, HypercoreError> {
async fn create_hypercore(name: &str) -> Result<Hypercore, HypercoreError> {
let dir = TempfileBuilder::new()
.prefix(name)
.tempdir()
Expand Down
24 changes: 16 additions & 8 deletions benches/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,15 @@ fn bench_create_memory(c: &mut Criterion) {
}

#[cfg(feature = "cache")]
async fn create_hypercore(
page_size: usize,
) -> Result<Hypercore<RandomAccessMemory>, HypercoreError> {
async fn create_hypercore(page_size: usize) -> Result<Hypercore, HypercoreError> {
use hypercore::StorageTraits;

let storage = Storage::open(
|_| Box::pin(async move { Ok(RandomAccessMemory::new(page_size)) }),
|_| {
Box::pin(async move {
Ok(Box::new(RandomAccessMemory::new(page_size)) as Box<dyn StorageTraits>)
})
},
false,
)
.await?;
Expand All @@ -34,11 +38,15 @@ async fn create_hypercore(
}

#[cfg(not(feature = "cache"))]
async fn create_hypercore(
page_size: usize,
) -> Result<Hypercore<RandomAccessMemory>, HypercoreError> {
async fn create_hypercore(page_size: usize) -> Result<Hypercore, HypercoreError> {
use hypercore::StorageTraits;

let storage = Storage::open(
|_| Box::pin(async move { Ok(RandomAccessMemory::new(page_size)) }),
|_| {
Box::pin(async move {
Ok(Box::new(RandomAccessMemory::new(page_size)) as Box<dyn StorageTraits>)
})
},
false,
)
.await?;
Expand Down
6 changes: 2 additions & 4 deletions examples/replication.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ use hypercore::{
Hypercore, HypercoreBuilder, HypercoreError, PartialKeypair, RequestBlock, RequestUpgrade,
Storage,
};
use random_access_disk::RandomAccessDisk;
use random_access_memory::RandomAccessMemory;
use tempfile::Builder;
#[cfg(feature = "tokio")]
use tokio::main as async_main;
Expand Down Expand Up @@ -73,8 +71,8 @@ async fn main() {
}

async fn replicate_index(
origin_hypercore: &mut Hypercore<RandomAccessDisk>,
replicated_hypercore: &mut Hypercore<RandomAccessMemory>,
origin_hypercore: &mut Hypercore,
replicated_hypercore: &mut Hypercore,
request_index: u64,
) {
let missing_nodes = origin_hypercore
Expand Down
17 changes: 5 additions & 12 deletions src/builder.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use random_access_storage::RandomAccess;
use std::fmt::Debug;
#[cfg(feature = "cache")]
use std::time::Duration;
Expand Down Expand Up @@ -53,20 +52,14 @@ impl CacheOptionsBuilder {

/// Build a Hypercore instance with options.
#[derive(Debug)]
pub struct HypercoreBuilder<T>
where
T: RandomAccess + Debug + Send,
{
storage: Storage<T>,
pub struct HypercoreBuilder {
storage: Storage,
options: HypercoreOptions,
}

impl<T> HypercoreBuilder<T>
where
T: RandomAccess + Debug + Send,
{
impl HypercoreBuilder {
/// Create a hypercore builder with a given storage
pub fn new(storage: Storage<T>) -> Self {
pub fn new(storage: Storage) -> Self {
Self {
storage,
options: HypercoreOptions::new(),
Expand Down Expand Up @@ -94,7 +87,7 @@ where

/// Build a new Hypercore.
#[instrument(err, skip_all)]
pub async fn build(self) -> Result<Hypercore<T>, HypercoreError> {
pub async fn build(self) -> Result<Hypercore, HypercoreError> {
Hypercore::new(self.storage, self.options).await
}
}
24 changes: 7 additions & 17 deletions src/core.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//! Hypercore's main abstraction. Exposes an append-only, secure log structure.
use ed25519_dalek::Signature;
use futures::future::Either;
use random_access_storage::RandomAccess;
use std::convert::TryFrom;
use std::fmt::Debug;
use tracing::instrument;
Expand Down Expand Up @@ -40,12 +39,9 @@ impl HypercoreOptions {

/// Hypercore is an append-only log structure.
#[derive(Debug)]
pub struct Hypercore<T>
where
T: RandomAccess + Debug,
{
pub struct Hypercore {
pub(crate) key_pair: PartialKeypair,
pub(crate) storage: Storage<T>,
pub(crate) storage: Storage,
pub(crate) oplog: Oplog,
pub(crate) tree: MerkleTree,
pub(crate) block_store: BlockStore,
Expand Down Expand Up @@ -79,15 +75,12 @@ pub struct Info {
pub writeable: bool,
}

impl<T> Hypercore<T>
where
T: RandomAccess + Debug + Send,
{
impl Hypercore {
/// Creates/opens new hypercore using given storage and options
pub(crate) async fn new(
mut storage: Storage<T>,
mut storage: Storage,
mut options: HypercoreOptions,
) -> Result<Hypercore<T>, HypercoreError> {
) -> Result<Hypercore, HypercoreError> {
let key_pair: Option<PartialKeypair> = if options.open {
if options.key_pair.is_some() {
return Err(HypercoreError::BadArgument {
Expand Down Expand Up @@ -734,7 +727,6 @@ fn update_contiguous_length(
#[cfg(test)]
mod tests {
use super::*;
use random_access_memory::RandomAccessMemory;

#[async_std::test]
async fn core_create_proof_block_only() -> Result<(), HypercoreError> {
Expand Down Expand Up @@ -1099,9 +1091,7 @@ mod tests {
Ok(())
}

async fn create_hypercore_with_data(
length: u64,
) -> Result<Hypercore<RandomAccessMemory>, HypercoreError> {
async fn create_hypercore_with_data(length: u64) -> Result<Hypercore, HypercoreError> {
let signing_key = generate_signing_key();
create_hypercore_with_data_and_key_pair(
length,
Expand All @@ -1116,7 +1106,7 @@ mod tests {
async fn create_hypercore_with_data_and_key_pair(
length: u64,
key_pair: PartialKeypair,
) -> Result<Hypercore<RandomAccessMemory>, HypercoreError> {
) -> Result<Hypercore, HypercoreError> {
let storage = Storage::new_memory().await?;
let mut hypercore = Hypercore::new(
storage,
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ pub use crate::common::{
};
pub use crate::core::{AppendOutcome, Hypercore, Info};
pub use crate::crypto::{generate_signing_key, sign, verify, PartialKeypair};
pub use crate::storage::Storage;
pub use crate::storage::{Storage, StorageTraits};
pub use ed25519_dalek::{
SecretKey, Signature, SigningKey, VerifyingKey, KEYPAIR_LENGTH, PUBLIC_KEY_LENGTH,
SECRET_KEY_LENGTH,
Expand Down
62 changes: 35 additions & 27 deletions src/storage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,17 @@ use crate::{
HypercoreError,
};

/// Supertrait for Storage
pub trait StorageTraits: RandomAccess + Debug {}
impl<T: RandomAccess + Debug> StorageTraits for T {}

/// Save data to a desired storage backend.
#[derive(Debug)]
pub struct Storage<T>
where
T: RandomAccess + Debug,
{
tree: T,
data: T,
bitfield: T,
oplog: T,
pub struct Storage {
tree: Box<dyn StorageTraits + Send>,
data: Box<dyn StorageTraits + Send>,
bitfield: Box<dyn StorageTraits + Send>,
oplog: Box<dyn StorageTraits + Send>,
}

pub(crate) fn map_random_access_err(err: RandomAccessError) -> HypercoreError {
Expand All @@ -51,17 +52,18 @@ pub(crate) fn map_random_access_err(err: RandomAccessError) -> HypercoreError {
}
}

impl<T> Storage<T>
where
T: RandomAccess + Debug + Send,
{
impl Storage {
/// Create a new instance. Takes a callback to create new storage instances and overwrite flag.
pub async fn open<Cb>(create: Cb, overwrite: bool) -> Result<Self, HypercoreError>
where
Cb: Fn(
Store,
) -> std::pin::Pin<
Box<dyn std::future::Future<Output = Result<T, RandomAccessError>> + Send>,
Box<
dyn std::future::Future<
Output = Result<Box<dyn StorageTraits + Send>, RandomAccessError>,
> + Send,
>,
>,
{
let mut tree = create(Store::Tree).await.map_err(map_random_access_err)?;
Expand Down Expand Up @@ -235,39 +237,45 @@ where
Ok(())
}

fn get_random_access(&mut self, store: &Store) -> &mut T {
fn get_random_access(&mut self, store: &Store) -> &mut Box<dyn StorageTraits + Send> {
match store {
Store::Tree => &mut self.tree,
Store::Data => &mut self.data,
Store::Bitfield => &mut self.bitfield,
Store::Oplog => &mut self.oplog,
}
}
}

impl Storage<RandomAccessMemory> {
/// New storage backed by a `RandomAccessMemory` instance.
#[instrument(err)]
pub async fn new_memory() -> Result<Self, HypercoreError> {
let create = |_| async { Ok(RandomAccessMemory::default()) }.boxed();
let create = |_| {
async { Ok(Box::new(RandomAccessMemory::default()) as Box<dyn StorageTraits + Send>) }
.boxed()
};
// No reason to overwrite, as this is a new memory segment
Self::open(create, false).await
}
}

#[cfg(not(target_arch = "wasm32"))]
impl Storage<RandomAccessDisk> {
/// New storage backed by a `RandomAccessDisk` instance.
#[cfg(not(target_arch = "wasm32"))]
#[instrument(err)]
pub async fn new_disk(dir: &PathBuf, overwrite: bool) -> Result<Self, HypercoreError> {
let storage = |store: Store| {
let name = match store {
Store::Tree => "tree",
Store::Data => "data",
Store::Bitfield => "bitfield",
Store::Oplog => "oplog",
};
RandomAccessDisk::open(dir.as_path().join(name)).boxed()
let dir = dir.clone();
async move {
let name = match store {
Store::Tree => "tree",
Store::Data => "data",
Store::Bitfield => "bitfield",
Store::Oplog => "oplog",
};
Ok(
Box::new(RandomAccessDisk::open(dir.as_path().join(name)).await?)
as Box<dyn StorageTraits + Send>,
)
}
.boxed()
};
Self::open(storage, overwrite).await
}
Expand Down
5 changes: 2 additions & 3 deletions tests/common/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use anyhow::Result;
use ed25519_dalek::{SigningKey, VerifyingKey, PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH};
use random_access_disk::RandomAccessDisk;
use sha2::{Digest, Sha256};
use std::io::prelude::*;
use std::path::Path;
Expand Down Expand Up @@ -35,7 +34,7 @@ pub fn get_test_key_pair() -> PartialKeypair {
PartialKeypair { public, secret }
}

pub async fn create_hypercore(work_dir: &str) -> Result<Hypercore<RandomAccessDisk>> {
pub async fn create_hypercore(work_dir: &str) -> Result<Hypercore> {
let path = Path::new(work_dir).to_owned();
let key_pair = get_test_key_pair();
let storage = Storage::new_disk(&path, true).await?;
Expand All @@ -45,7 +44,7 @@ pub async fn create_hypercore(work_dir: &str) -> Result<Hypercore<RandomAccessDi
.await?)
}

pub async fn open_hypercore(work_dir: &str) -> Result<Hypercore<RandomAccessDisk>> {
pub async fn open_hypercore(work_dir: &str) -> Result<Hypercore> {
let path = Path::new(work_dir).to_owned();
let storage = Storage::new_disk(&path, false).await?;
Ok(HypercoreBuilder::new(storage).open(true).build().await?)
Expand Down
Loading