Merge pull request #7 from vacp2p/custom-errors

fix: custom error enums
This commit is contained in:
Magamedrasul Ibragimov 2023-04-19 20:15:50 +04:00 committed by GitHub
commit 183f378d32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 97 additions and 71 deletions

View File

@ -29,25 +29,25 @@ struct MemoryDBConfig;
impl Database for MemoryDB { impl Database for MemoryDB {
type Config = MemoryDBConfig; type Config = MemoryDBConfig;
fn new(_db_config: MemoryDBConfig) -> Result<Self> { fn new(_db_config: MemoryDBConfig) -> PmtreeResult<Self> {
Ok(MemoryDB(HashMap::new())) Ok(MemoryDB(HashMap::new()))
} }
fn load(_db_config: MemoryDBConfig) -> Result<Self> { fn load(_db_config: MemoryDBConfig) -> PmtreeResult<Self> {
Err(Box::new(Error("Cannot load in-memory DB".to_string()))) 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()) 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); self.0.insert(key, value);
Ok(()) 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()); self.0.extend(subtree.into_iter());
Ok(()) Ok(())

View File

@ -8,21 +8,21 @@ pub trait Database {
type Config: Default; type Config: Default;
/// Creates new instance of db /// Creates new instance of db
fn new(config: Self::Config) -> Result<Self> fn new(config: Self::Config) -> PmtreeResult<Self>
where where
Self: Sized; Self: Sized;
/// Loades existing db (existence check required) /// Loades existing db (existence check required)
fn load(config: Self::Config) -> Result<Self> fn load(config: Self::Config) -> PmtreeResult<Self>
where where
Self: Sized; Self: Sized;
/// Returns value from db by the key /// 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 /// 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 /// Batc
fn put_batch(&mut self, subtree: HashMap<DBKey, Value>) -> Result<()>; fn put_batch(&mut self, subtree: HashMap<DBKey, Value>) -> PmtreeResult<()>;
} }

View File

@ -20,17 +20,37 @@ pub type DBKey = [u8; 8];
/// Denotes values in a database /// Denotes values in a database
pub type Value = Vec<u8>; pub type Value = Vec<u8>;
/// Denotes `Error` type, for handling DB interaction errors
#[derive(Debug)] #[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 { 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 /// 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>;

View File

@ -44,12 +44,12 @@ where
H: Hasher, H: Hasher,
{ {
/// Creates tree with specified depth and default "pmtree_db" dbpath. /// 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()) Self::new(depth, D::Config::default())
} }
/// Creates new `MerkleTree` and store it to the specified path/db /// 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 // Create new db instance
let mut db = D::new(db_config)?; let mut db = D::new(db_config)?;
@ -85,7 +85,7 @@ where
} }
/// Loads existing Merkle Tree from the specified path/db /// 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 // Load existing db instance
let db = D::load(db_config)?; let db = D::load(db_config)?;
@ -116,9 +116,9 @@ where
} }
/// Sets a leaf at the specified tree index /// 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() { if key >= self.capacity() {
return Err(Box::new(Error("Merkle Tree is full!".to_string()))); return Err(PmtreeErrorKind::TreeError(TreeErrorKind::IndexOutOfBounds));
} }
self.db self.db
@ -136,7 +136,7 @@ where
} }
// Recalculates `Merkle Tree` from the specified key // 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 depth = self.depth;
let mut i = key; let mut i = key;
@ -156,7 +156,7 @@ where
} }
// Hashes the correct couple for the key // 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; let b = key & !1;
Ok(H::hash(&[ Ok(H::hash(&[
self.get_elem(Key(depth, b))?, self.get_elem(Key(depth, b))?,
@ -165,7 +165,7 @@ where
} }
// Returns elem by the key // 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 let res = self
.db .db
.get(key.into())? .get(key.into())?
@ -175,9 +175,9 @@ where
} }
/// Deletes a leaf at the `key` by setting it to its default value /// 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 { 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())?; self.set(key, H::default_leaf())?;
@ -186,20 +186,18 @@ where
} }
/// Inserts a leaf to the next available index /// 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)?; self.set(self.next_index, leaf)?;
Ok(()) Ok(())
} }
/// Batch insertion, updates the tree in parallel. /// 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(); let end = self.next_index + leaves.len();
if end > self.capacity() { if end > self.capacity() {
return Err(Box::new(Error( return Err(PmtreeErrorKind::TreeError(TreeErrorKind::MerkleTreeIsFull));
"Not enough space to insert the leaves!".to_string(),
)));
} }
let mut subtree = HashMap::<Key, H::Fr>::new(); let mut subtree = HashMap::<Key, H::Fr>::new();
@ -253,7 +251,7 @@ where
subtree: &mut HashMap<Key, H::Fr>, subtree: &mut HashMap<Key, H::Fr>,
leaves: &[H::Fr], leaves: &[H::Fr],
from: usize, from: usize,
) -> Result<()> { ) -> PmtreeResult<()> {
if key.0 == self.depth { if key.0 == self.depth {
if key.1 >= from { if key.1 >= from {
subtree.insert(key, leaves[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 /// 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() { 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); let mut witness = Vec::with_capacity(self.depth);

View File

@ -12,25 +12,27 @@ struct MemoryDBConfig;
impl Database for MemoryDB { impl Database for MemoryDB {
type Config = MemoryDBConfig; type Config = MemoryDBConfig;
fn new(_db_config: MemoryDBConfig) -> Result<Self> { fn new(_db_config: MemoryDBConfig) -> PmtreeResult<Self> {
Ok(MemoryDB(HashMap::new())) Ok(MemoryDB(HashMap::new()))
} }
fn load(_db_config: MemoryDBConfig) -> Result<Self> { fn load(_db_config: MemoryDBConfig) -> PmtreeResult<Self> {
Err(Box::new(Error("Cannot load in-memory DB".to_string()))) 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()) 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); self.0.insert(key, value);
Ok(()) 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()); self.0.extend(subtree.into_iter());
Ok(()) Ok(())
@ -64,7 +66,7 @@ impl Hasher for MyKeccak {
} }
#[test] #[test]
fn insert_delete() -> Result<()> { fn insert_delete() -> PmtreeResult<()> {
let mut mt = MerkleTree::<MemoryDB, MyKeccak>::new(2, MemoryDBConfig)?; let mut mt = MerkleTree::<MemoryDB, MyKeccak>::new(2, MemoryDBConfig)?;
assert_eq!(mt.capacity(), 4); assert_eq!(mt.capacity(), 4);
@ -110,7 +112,7 @@ fn insert_delete() -> Result<()> {
} }
#[test] #[test]
fn batch_insertions() -> Result<()> { fn batch_insertions() -> PmtreeResult<()> {
let mut mt = MerkleTree::<MemoryDB, MyKeccak>::new(2, MemoryDBConfig)?; let mut mt = MerkleTree::<MemoryDB, MyKeccak>::new(2, MemoryDBConfig)?;
let leaves = [ let leaves = [

View File

@ -49,25 +49,27 @@ struct MemoryDBConfig;
impl Database for MemoryDB { impl Database for MemoryDB {
type Config = MemoryDBConfig; type Config = MemoryDBConfig;
fn new(_db_config: MemoryDBConfig) -> Result<Self> { fn new(_db_config: MemoryDBConfig) -> PmtreeResult<Self> {
Ok(MemoryDB(HashMap::new())) Ok(MemoryDB(HashMap::new()))
} }
fn load(_db_config: MemoryDBConfig) -> Result<Self> { fn load(_db_config: MemoryDBConfig) -> PmtreeResult<Self> {
Err(Box::new(Error("Cannot load in-memory DB".to_string()))) 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()) 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); self.0.insert(key, value);
Ok(()) 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()); self.0.extend(subtree.into_iter());
Ok(()) Ok(())
@ -82,33 +84,35 @@ struct SledConfig {
impl Database for MySled { impl Database for MySled {
type Config = SledConfig; 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(); let db = sled::open(db_config.path).unwrap();
if db.was_recovered() { if db.was_recovered() {
return Err(Box::new(Error("Database exists, try load()!".to_string()))); return Err(PmtreeErrorKind::DatabaseError(
DatabaseErrorKind::DatabaseExists,
));
} }
Ok(MySled(db)) 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(); let db = sled::open(&db_config.path).unwrap();
if !db.was_recovered() { if !db.was_recovered() {
fs::remove_dir_all(&db_config.path).expect("Error removing db"); fs::remove_dir_all(&db_config.path).expect("Error removing db");
return Err(Box::new(Error( return Err(PmtreeErrorKind::DatabaseError(
"Trying to load non-existing database!".to_string(), DatabaseErrorKind::CannotLoadDatabase,
))); ));
} }
Ok(MySled(db)) 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())) 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.insert(key, value).unwrap();
self.0.flush().unwrap(); self.0.flush().unwrap();
@ -116,7 +120,7 @@ impl Database for MySled {
Ok(()) 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(); let mut batch = sled::Batch::default();
for (key, value) in subtree { for (key, value) in subtree {
@ -130,7 +134,7 @@ impl Database for MySled {
} }
#[test] #[test]
fn poseidon_memory() -> Result<()> { fn poseidon_memory() -> PmtreeResult<()> {
let mut mt = MerkleTree::<MemoryDB, PoseidonHash>::new(TEST_TREE_HEIGHT, MemoryDBConfig)?; let mut mt = MerkleTree::<MemoryDB, PoseidonHash>::new(TEST_TREE_HEIGHT, MemoryDBConfig)?;
let leaf_index = 3; let leaf_index = 3;
@ -254,7 +258,7 @@ fn poseidon_memory() -> Result<()> {
} }
#[test] #[test]
fn poseidon_sled() -> Result<()> { fn poseidon_sled() -> PmtreeResult<()> {
let mut mt = MerkleTree::<MySled, PoseidonHash>::new( let mut mt = MerkleTree::<MySled, PoseidonHash>::new(
TEST_TREE_HEIGHT, TEST_TREE_HEIGHT,
SledConfig { SledConfig {

View File

@ -15,33 +15,35 @@ struct SledConfig {
impl Database for MySled { impl Database for MySled {
type Config = SledConfig; 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(); let db = sled::open(db_config.path).unwrap();
if db.was_recovered() { if db.was_recovered() {
return Err(Box::new(Error("Database exists, try load()!".to_string()))); return Err(PmtreeErrorKind::DatabaseError(
DatabaseErrorKind::DatabaseExists,
));
} }
Ok(MySled(db)) 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(); let db = sled::open(&db_config.path).unwrap();
if !db.was_recovered() { if !db.was_recovered() {
fs::remove_dir_all(&db_config.path).expect("Error removing db"); fs::remove_dir_all(&db_config.path).expect("Error removing db");
return Err(Box::new(Error( return Err(PmtreeErrorKind::DatabaseError(
"Trying to load non-existing database!".to_string(), DatabaseErrorKind::CannotLoadDatabase,
))); ));
} }
Ok(MySled(db)) 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())) 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.insert(key, value).unwrap();
self.0.flush().unwrap(); self.0.flush().unwrap();
@ -49,7 +51,7 @@ impl Database for MySled {
Ok(()) 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(); let mut batch = sled::Batch::default();
for (key, value) in subtree { for (key, value) in subtree {
@ -89,7 +91,7 @@ impl Hasher for MyKeccak {
} }
#[test] #[test]
fn insert_delete() -> Result<()> { fn insert_delete() -> PmtreeResult<()> {
let mut mt = MerkleTree::<MySled, MyKeccak>::new( let mut mt = MerkleTree::<MySled, MyKeccak>::new(
2, 2,
SledConfig { SledConfig {
@ -142,7 +144,7 @@ fn insert_delete() -> Result<()> {
} }
#[test] #[test]
fn batch_insertions() -> Result<()> { fn batch_insertions() -> PmtreeResult<()> {
let mut mt = MerkleTree::<MySled, MyKeccak>::new( let mut mt = MerkleTree::<MySled, MyKeccak>::new(
2, 2,
SledConfig { SledConfig {