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 {
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(())

View File

@ -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<()>;
}

View File

@ -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>;

View File

@ -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);

View File

@ -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 = [

View File

@ -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 {

View File

@ -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 {