mirror of https://github.com/vacp2p/pmtree.git
Merge pull request #7 from vacp2p/custom-errors
fix: custom error enums
This commit is contained in:
commit
183f378d32
12
README.md
12
README.md
|
@ -29,25 +29,25 @@ struct MemoryDBConfig;
|
|||
impl Database for MemoryDB {
|
||||
type Config = MemoryDBConfig;
|
||||
|
||||
fn new(_db_config: MemoryDBConfig) -> Result<Self> {
|
||||
fn new(_db_config: MemoryDBConfig) -> PmtreeResult<Self> {
|
||||
Ok(MemoryDB(HashMap::new()))
|
||||
}
|
||||
|
||||
fn load(_db_config: MemoryDBConfig) -> Result<Self> {
|
||||
Err(Box::new(Error("Cannot load in-memory DB".to_string())))
|
||||
fn load(_db_config: MemoryDBConfig) -> PmtreeResult<Self> {
|
||||
Err(DatabaseError(DatabaseErrorKind::CannotLoadDatabase))
|
||||
}
|
||||
|
||||
fn get(&self, key: DBKey) -> Result<Option<Value>> {
|
||||
fn get(&self, key: DBKey) -> PmtreeResult<Option<Value>> {
|
||||
Ok(self.0.get(&key).cloned())
|
||||
}
|
||||
|
||||
fn put(&mut self, key: DBKey, value: Value) -> Result<()> {
|
||||
fn put(&mut self, key: DBKey, value: Value) -> PmtreeResult<()> {
|
||||
self.0.insert(key, value);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn put_batch(&mut self, subtree: HashMap<DBKey, Value>) -> Result<()> {
|
||||
fn put_batch(&mut self, subtree: HashMap<DBKey, Value>) -> PmtreeResult<()> {
|
||||
self.0.extend(subtree.into_iter());
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -8,21 +8,21 @@ pub trait Database {
|
|||
type Config: Default;
|
||||
|
||||
/// Creates new instance of db
|
||||
fn new(config: Self::Config) -> Result<Self>
|
||||
fn new(config: Self::Config) -> PmtreeResult<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
/// Loades existing db (existence check required)
|
||||
fn load(config: Self::Config) -> Result<Self>
|
||||
fn load(config: Self::Config) -> PmtreeResult<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
/// Returns value from db by the key
|
||||
fn get(&self, key: DBKey) -> Result<Option<Value>>;
|
||||
fn get(&self, key: DBKey) -> PmtreeResult<Option<Value>>;
|
||||
|
||||
/// Puts the value to the db by the key
|
||||
fn put(&mut self, key: DBKey, value: Value) -> Result<()>;
|
||||
fn put(&mut self, key: DBKey, value: Value) -> PmtreeResult<()>;
|
||||
|
||||
/// Batc
|
||||
fn put_batch(&mut self, subtree: HashMap<DBKey, Value>) -> Result<()>;
|
||||
fn put_batch(&mut self, subtree: HashMap<DBKey, Value>) -> PmtreeResult<()>;
|
||||
}
|
||||
|
|
32
src/lib.rs
32
src/lib.rs
|
@ -20,17 +20,37 @@ pub type DBKey = [u8; 8];
|
|||
/// Denotes values in a database
|
||||
pub type Value = Vec<u8>;
|
||||
|
||||
/// Denotes `Error` type, for handling DB interaction errors
|
||||
#[derive(Debug)]
|
||||
pub struct Error(pub String);
|
||||
pub enum TreeErrorKind {
|
||||
MerkleTreeIsFull,
|
||||
InvalidKey,
|
||||
IndexOutOfBounds,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Error {
|
||||
#[derive(Debug)]
|
||||
pub enum DatabaseErrorKind {
|
||||
CannotLoadDatabase,
|
||||
DatabaseExists,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum PmtreeErrorKind {
|
||||
/// Error in database
|
||||
DatabaseError(DatabaseErrorKind),
|
||||
/// Error in tree
|
||||
TreeError(TreeErrorKind),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for PmtreeErrorKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
match self {
|
||||
PmtreeErrorKind::DatabaseError(e) => write!(f, "Database error: {e:?}"),
|
||||
PmtreeErrorKind::TreeError(e) => write!(f, "Tree error: {e:?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {}
|
||||
impl std::error::Error for PmtreeErrorKind {}
|
||||
|
||||
/// Custom `Result` type with custom `Error` type
|
||||
pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
||||
pub type PmtreeResult<T> = std::result::Result<T, PmtreeErrorKind>;
|
||||
|
|
34
src/tree.rs
34
src/tree.rs
|
@ -44,12 +44,12 @@ where
|
|||
H: Hasher,
|
||||
{
|
||||
/// Creates tree with specified depth and default "pmtree_db" dbpath.
|
||||
pub fn default(depth: usize) -> Result<Self> {
|
||||
pub fn default(depth: usize) -> PmtreeResult<Self> {
|
||||
Self::new(depth, D::Config::default())
|
||||
}
|
||||
|
||||
/// Creates new `MerkleTree` and store it to the specified path/db
|
||||
pub fn new(depth: usize, db_config: D::Config) -> Result<Self> {
|
||||
pub fn new(depth: usize, db_config: D::Config) -> PmtreeResult<Self> {
|
||||
// Create new db instance
|
||||
let mut db = D::new(db_config)?;
|
||||
|
||||
|
@ -85,7 +85,7 @@ where
|
|||
}
|
||||
|
||||
/// Loads existing Merkle Tree from the specified path/db
|
||||
pub fn load(db_config: D::Config) -> Result<Self> {
|
||||
pub fn load(db_config: D::Config) -> PmtreeResult<Self> {
|
||||
// Load existing db instance
|
||||
let db = D::load(db_config)?;
|
||||
|
||||
|
@ -116,9 +116,9 @@ where
|
|||
}
|
||||
|
||||
/// Sets a leaf at the specified tree index
|
||||
pub fn set(&mut self, key: usize, leaf: H::Fr) -> Result<()> {
|
||||
pub fn set(&mut self, key: usize, leaf: H::Fr) -> PmtreeResult<()> {
|
||||
if key >= self.capacity() {
|
||||
return Err(Box::new(Error("Merkle Tree is full!".to_string())));
|
||||
return Err(PmtreeErrorKind::TreeError(TreeErrorKind::IndexOutOfBounds));
|
||||
}
|
||||
|
||||
self.db
|
||||
|
@ -136,7 +136,7 @@ where
|
|||
}
|
||||
|
||||
// Recalculates `Merkle Tree` from the specified key
|
||||
fn recalculate_from(&mut self, key: usize) -> Result<()> {
|
||||
fn recalculate_from(&mut self, key: usize) -> PmtreeResult<()> {
|
||||
let mut depth = self.depth;
|
||||
let mut i = key;
|
||||
|
||||
|
@ -156,7 +156,7 @@ where
|
|||
}
|
||||
|
||||
// Hashes the correct couple for the key
|
||||
fn hash_couple(&self, depth: usize, key: usize) -> Result<H::Fr> {
|
||||
fn hash_couple(&self, depth: usize, key: usize) -> PmtreeResult<H::Fr> {
|
||||
let b = key & !1;
|
||||
Ok(H::hash(&[
|
||||
self.get_elem(Key(depth, b))?,
|
||||
|
@ -165,7 +165,7 @@ where
|
|||
}
|
||||
|
||||
// Returns elem by the key
|
||||
fn get_elem(&self, key: Key) -> Result<H::Fr> {
|
||||
fn get_elem(&self, key: Key) -> PmtreeResult<H::Fr> {
|
||||
let res = self
|
||||
.db
|
||||
.get(key.into())?
|
||||
|
@ -175,9 +175,9 @@ where
|
|||
}
|
||||
|
||||
/// Deletes a leaf at the `key` by setting it to its default value
|
||||
pub fn delete(&mut self, key: usize) -> Result<()> {
|
||||
pub fn delete(&mut self, key: usize) -> PmtreeResult<()> {
|
||||
if key >= self.next_index {
|
||||
return Err(Box::new(Error("The key doesn't exist!".to_string())));
|
||||
return Err(PmtreeErrorKind::TreeError(TreeErrorKind::InvalidKey));
|
||||
}
|
||||
|
||||
self.set(key, H::default_leaf())?;
|
||||
|
@ -186,20 +186,18 @@ where
|
|||
}
|
||||
|
||||
/// Inserts a leaf to the next available index
|
||||
pub fn update_next(&mut self, leaf: H::Fr) -> Result<()> {
|
||||
pub fn update_next(&mut self, leaf: H::Fr) -> PmtreeResult<()> {
|
||||
self.set(self.next_index, leaf)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Batch insertion, updates the tree in parallel.
|
||||
pub fn batch_insert(&mut self, leaves: &[H::Fr]) -> Result<()> {
|
||||
pub fn batch_insert(&mut self, leaves: &[H::Fr]) -> PmtreeResult<()> {
|
||||
let end = self.next_index + leaves.len();
|
||||
|
||||
if end > self.capacity() {
|
||||
return Err(Box::new(Error(
|
||||
"Not enough space to insert the leaves!".to_string(),
|
||||
)));
|
||||
return Err(PmtreeErrorKind::TreeError(TreeErrorKind::MerkleTreeIsFull));
|
||||
}
|
||||
|
||||
let mut subtree = HashMap::<Key, H::Fr>::new();
|
||||
|
@ -253,7 +251,7 @@ where
|
|||
subtree: &mut HashMap<Key, H::Fr>,
|
||||
leaves: &[H::Fr],
|
||||
from: usize,
|
||||
) -> Result<()> {
|
||||
) -> PmtreeResult<()> {
|
||||
if key.0 == self.depth {
|
||||
if key.1 >= from {
|
||||
subtree.insert(key, leaves[key.1 - from]);
|
||||
|
@ -309,9 +307,9 @@ where
|
|||
}
|
||||
|
||||
/// Computes a Merkle proof for the leaf at the specified index
|
||||
pub fn proof(&self, index: usize) -> Result<MerkleProof<H>> {
|
||||
pub fn proof(&self, index: usize) -> PmtreeResult<MerkleProof<H>> {
|
||||
if index >= self.capacity() {
|
||||
return Err(Box::new(Error("Index exceeds set size!".to_string())));
|
||||
return Err(PmtreeErrorKind::TreeError(TreeErrorKind::IndexOutOfBounds));
|
||||
}
|
||||
|
||||
let mut witness = Vec::with_capacity(self.depth);
|
||||
|
|
|
@ -12,25 +12,27 @@ struct MemoryDBConfig;
|
|||
impl Database for MemoryDB {
|
||||
type Config = MemoryDBConfig;
|
||||
|
||||
fn new(_db_config: MemoryDBConfig) -> Result<Self> {
|
||||
fn new(_db_config: MemoryDBConfig) -> PmtreeResult<Self> {
|
||||
Ok(MemoryDB(HashMap::new()))
|
||||
}
|
||||
|
||||
fn load(_db_config: MemoryDBConfig) -> Result<Self> {
|
||||
Err(Box::new(Error("Cannot load in-memory DB".to_string())))
|
||||
fn load(_db_config: MemoryDBConfig) -> PmtreeResult<Self> {
|
||||
Err(PmtreeErrorKind::DatabaseError(
|
||||
DatabaseErrorKind::CannotLoadDatabase,
|
||||
))
|
||||
}
|
||||
|
||||
fn get(&self, key: DBKey) -> Result<Option<Value>> {
|
||||
fn get(&self, key: DBKey) -> PmtreeResult<Option<Value>> {
|
||||
Ok(self.0.get(&key).cloned())
|
||||
}
|
||||
|
||||
fn put(&mut self, key: DBKey, value: Value) -> Result<()> {
|
||||
fn put(&mut self, key: DBKey, value: Value) -> PmtreeResult<()> {
|
||||
self.0.insert(key, value);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn put_batch(&mut self, subtree: HashMap<DBKey, Value>) -> Result<()> {
|
||||
fn put_batch(&mut self, subtree: HashMap<DBKey, Value>) -> PmtreeResult<()> {
|
||||
self.0.extend(subtree.into_iter());
|
||||
|
||||
Ok(())
|
||||
|
@ -64,7 +66,7 @@ impl Hasher for MyKeccak {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn insert_delete() -> Result<()> {
|
||||
fn insert_delete() -> PmtreeResult<()> {
|
||||
let mut mt = MerkleTree::<MemoryDB, MyKeccak>::new(2, MemoryDBConfig)?;
|
||||
|
||||
assert_eq!(mt.capacity(), 4);
|
||||
|
@ -110,7 +112,7 @@ fn insert_delete() -> Result<()> {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn batch_insertions() -> Result<()> {
|
||||
fn batch_insertions() -> PmtreeResult<()> {
|
||||
let mut mt = MerkleTree::<MemoryDB, MyKeccak>::new(2, MemoryDBConfig)?;
|
||||
|
||||
let leaves = [
|
||||
|
|
|
@ -49,25 +49,27 @@ struct MemoryDBConfig;
|
|||
impl Database for MemoryDB {
|
||||
type Config = MemoryDBConfig;
|
||||
|
||||
fn new(_db_config: MemoryDBConfig) -> Result<Self> {
|
||||
fn new(_db_config: MemoryDBConfig) -> PmtreeResult<Self> {
|
||||
Ok(MemoryDB(HashMap::new()))
|
||||
}
|
||||
|
||||
fn load(_db_config: MemoryDBConfig) -> Result<Self> {
|
||||
Err(Box::new(Error("Cannot load in-memory DB".to_string())))
|
||||
fn load(_db_config: MemoryDBConfig) -> PmtreeResult<Self> {
|
||||
Err(PmtreeErrorKind::DatabaseError(
|
||||
DatabaseErrorKind::CannotLoadDatabase,
|
||||
))
|
||||
}
|
||||
|
||||
fn get(&self, key: DBKey) -> Result<Option<Value>> {
|
||||
fn get(&self, key: DBKey) -> PmtreeResult<Option<Value>> {
|
||||
Ok(self.0.get(&key).cloned())
|
||||
}
|
||||
|
||||
fn put(&mut self, key: DBKey, value: Value) -> Result<()> {
|
||||
fn put(&mut self, key: DBKey, value: Value) -> PmtreeResult<()> {
|
||||
self.0.insert(key, value);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn put_batch(&mut self, subtree: HashMap<DBKey, Value>) -> Result<()> {
|
||||
fn put_batch(&mut self, subtree: HashMap<DBKey, Value>) -> PmtreeResult<()> {
|
||||
self.0.extend(subtree.into_iter());
|
||||
|
||||
Ok(())
|
||||
|
@ -82,33 +84,35 @@ struct SledConfig {
|
|||
impl Database for MySled {
|
||||
type Config = SledConfig;
|
||||
|
||||
fn new(db_config: SledConfig) -> Result<Self> {
|
||||
fn new(db_config: SledConfig) -> PmtreeResult<Self> {
|
||||
let db = sled::open(db_config.path).unwrap();
|
||||
if db.was_recovered() {
|
||||
return Err(Box::new(Error("Database exists, try load()!".to_string())));
|
||||
return Err(PmtreeErrorKind::DatabaseError(
|
||||
DatabaseErrorKind::DatabaseExists,
|
||||
));
|
||||
}
|
||||
|
||||
Ok(MySled(db))
|
||||
}
|
||||
|
||||
fn load(db_config: SledConfig) -> Result<Self> {
|
||||
fn load(db_config: SledConfig) -> PmtreeResult<Self> {
|
||||
let db = sled::open(&db_config.path).unwrap();
|
||||
|
||||
if !db.was_recovered() {
|
||||
fs::remove_dir_all(&db_config.path).expect("Error removing db");
|
||||
return Err(Box::new(Error(
|
||||
"Trying to load non-existing database!".to_string(),
|
||||
)));
|
||||
return Err(PmtreeErrorKind::DatabaseError(
|
||||
DatabaseErrorKind::CannotLoadDatabase,
|
||||
));
|
||||
}
|
||||
|
||||
Ok(MySled(db))
|
||||
}
|
||||
|
||||
fn get(&self, key: DBKey) -> Result<Option<Value>> {
|
||||
fn get(&self, key: DBKey) -> PmtreeResult<Option<Value>> {
|
||||
Ok(self.0.get(key).unwrap().map(|val| val.to_vec()))
|
||||
}
|
||||
|
||||
fn put(&mut self, key: DBKey, value: Value) -> Result<()> {
|
||||
fn put(&mut self, key: DBKey, value: Value) -> PmtreeResult<()> {
|
||||
self.0.insert(key, value).unwrap();
|
||||
|
||||
self.0.flush().unwrap();
|
||||
|
@ -116,7 +120,7 @@ impl Database for MySled {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn put_batch(&mut self, subtree: HashMap<DBKey, Value>) -> Result<()> {
|
||||
fn put_batch(&mut self, subtree: HashMap<DBKey, Value>) -> PmtreeResult<()> {
|
||||
let mut batch = sled::Batch::default();
|
||||
|
||||
for (key, value) in subtree {
|
||||
|
@ -130,7 +134,7 @@ impl Database for MySled {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn poseidon_memory() -> Result<()> {
|
||||
fn poseidon_memory() -> PmtreeResult<()> {
|
||||
let mut mt = MerkleTree::<MemoryDB, PoseidonHash>::new(TEST_TREE_HEIGHT, MemoryDBConfig)?;
|
||||
|
||||
let leaf_index = 3;
|
||||
|
@ -254,7 +258,7 @@ fn poseidon_memory() -> Result<()> {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn poseidon_sled() -> Result<()> {
|
||||
fn poseidon_sled() -> PmtreeResult<()> {
|
||||
let mut mt = MerkleTree::<MySled, PoseidonHash>::new(
|
||||
TEST_TREE_HEIGHT,
|
||||
SledConfig {
|
||||
|
|
|
@ -15,33 +15,35 @@ struct SledConfig {
|
|||
impl Database for MySled {
|
||||
type Config = SledConfig;
|
||||
|
||||
fn new(db_config: SledConfig) -> Result<Self> {
|
||||
fn new(db_config: SledConfig) -> PmtreeResult<Self> {
|
||||
let db = sled::open(db_config.path).unwrap();
|
||||
if db.was_recovered() {
|
||||
return Err(Box::new(Error("Database exists, try load()!".to_string())));
|
||||
return Err(PmtreeErrorKind::DatabaseError(
|
||||
DatabaseErrorKind::DatabaseExists,
|
||||
));
|
||||
}
|
||||
|
||||
Ok(MySled(db))
|
||||
}
|
||||
|
||||
fn load(db_config: SledConfig) -> Result<Self> {
|
||||
fn load(db_config: SledConfig) -> PmtreeResult<Self> {
|
||||
let db = sled::open(&db_config.path).unwrap();
|
||||
|
||||
if !db.was_recovered() {
|
||||
fs::remove_dir_all(&db_config.path).expect("Error removing db");
|
||||
return Err(Box::new(Error(
|
||||
"Trying to load non-existing database!".to_string(),
|
||||
)));
|
||||
return Err(PmtreeErrorKind::DatabaseError(
|
||||
DatabaseErrorKind::CannotLoadDatabase,
|
||||
));
|
||||
}
|
||||
|
||||
Ok(MySled(db))
|
||||
}
|
||||
|
||||
fn get(&self, key: DBKey) -> Result<Option<Value>> {
|
||||
fn get(&self, key: DBKey) -> PmtreeResult<Option<Value>> {
|
||||
Ok(self.0.get(key).unwrap().map(|val| val.to_vec()))
|
||||
}
|
||||
|
||||
fn put(&mut self, key: DBKey, value: Value) -> Result<()> {
|
||||
fn put(&mut self, key: DBKey, value: Value) -> PmtreeResult<()> {
|
||||
self.0.insert(key, value).unwrap();
|
||||
|
||||
self.0.flush().unwrap();
|
||||
|
@ -49,7 +51,7 @@ impl Database for MySled {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn put_batch(&mut self, subtree: HashMap<DBKey, Value>) -> Result<()> {
|
||||
fn put_batch(&mut self, subtree: HashMap<DBKey, Value>) -> PmtreeResult<()> {
|
||||
let mut batch = sled::Batch::default();
|
||||
|
||||
for (key, value) in subtree {
|
||||
|
@ -89,7 +91,7 @@ impl Hasher for MyKeccak {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn insert_delete() -> Result<()> {
|
||||
fn insert_delete() -> PmtreeResult<()> {
|
||||
let mut mt = MerkleTree::<MySled, MyKeccak>::new(
|
||||
2,
|
||||
SledConfig {
|
||||
|
@ -142,7 +144,7 @@ fn insert_delete() -> Result<()> {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn batch_insertions() -> Result<()> {
|
||||
fn batch_insertions() -> PmtreeResult<()> {
|
||||
let mut mt = MerkleTree::<MySled, MyKeccak>::new(
|
||||
2,
|
||||
SledConfig {
|
||||
|
|
Loading…
Reference in New Issue