use crate::error::Result;
use async_trait::async_trait;
use tenzro_types::{Account, Address, Block, BlockHeight, Hash, Nonce};
#[async_trait]
pub trait StateStore: Send + Sync {
async fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>>;
async fn put(&mut self, key: &[u8], value: &[u8]) -> Result<()>;
async fn delete(&mut self, key: &[u8]) -> Result<()>;
async fn state_root(&self) -> Result<Hash>;
async fn commit(&mut self) -> Result<Hash>;
async fn rollback(&mut self) -> Result<()>;
async fn contains(&self, key: &[u8]) -> Result<bool> {
Ok(self.get(key).await?.is_some())
}
}
#[async_trait]
pub trait BlockStore: Send + Sync {
async fn get_block(&self, hash: &Hash) -> Result<Option<Block>>;
async fn get_block_by_height(&self, height: BlockHeight) -> Result<Option<Block>>;
async fn put_block(&mut self, block: &Block) -> Result<()>;
async fn latest_block(&self) -> Result<Option<Block>>;
async fn latest_height(&self) -> Result<Option<BlockHeight>>;
async fn blocks_by_height_range(
&self,
start: BlockHeight,
end: BlockHeight,
) -> Result<Vec<Block>>;
async fn has_block(&self, hash: &Hash) -> Result<bool> {
Ok(self.get_block(hash).await?.is_some())
}
async fn get_block_hash(&self, height: BlockHeight) -> Result<Option<Hash>>;
}
#[async_trait]
pub trait AccountStore: Send + Sync {
async fn get_account(&self, address: &Address) -> Result<Option<Account>>;
async fn put_account(&mut self, account: &Account) -> Result<()>;
async fn delete_account(&mut self, address: &Address) -> Result<()>;
async fn get_balance(&self, address: &Address) -> Result<u128> {
Ok(self
.get_account(address)
.await?
.map(|acc| acc.balance)
.unwrap_or(0))
}
async fn update_nonce(&mut self, address: &Address, nonce: Nonce) -> Result<()> {
if let Some(mut account) = self.get_account(address).await? {
account.nonce = nonce;
self.put_account(&account).await?;
}
Ok(())
}
async fn has_account(&self, address: &Address) -> Result<bool> {
Ok(self.get_account(address).await?.is_some())
}
async fn get_nonce(&self, address: &Address) -> Result<Nonce> {
Ok(self
.get_account(address)
.await?
.map(|acc| acc.nonce)
.unwrap_or_else(Nonce::initial))
}
}