Skip to content

Commit

Permalink
feat: Add Chain Data tables (#63)
Browse files Browse the repository at this point in the history
* add block headers & chain mmr nodes table

---------

Co-authored-by: Nacho <[email protected]>
Co-authored-by: igamigo <[email protected]>
  • Loading branch information
3 people authored Dec 29, 2023
1 parent 516e535 commit 653b3a9
Show file tree
Hide file tree
Showing 18 changed files with 546 additions and 160 deletions.
2 changes: 1 addition & 1 deletion src/cli/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ pub fn show_account(

println!(
"Storage: {}\n",
serde_json::to_string(&account_storage)
serde_json::to_string(&account_storage.slots())
.map_err(|_| "Error serializing account storage")?
);
}
Expand Down
3 changes: 2 additions & 1 deletion src/cli/input_notes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ use std::path::PathBuf;

use super::{Client, Parser};
use comfy_table::{presets, Attribute, Cell, ContentArrangement, Table};
use crypto::utils::{Deserializable, Serializable};
use miden_client::store::notes::InputNoteFilter;

use crypto::utils::{Deserializable, Serializable};
use objects::notes::RecordedNote;
use objects::Digest;

Expand Down
1 change: 1 addition & 0 deletions src/cli/transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use comfy_table::Attribute;
use comfy_table::Cell;
use comfy_table::ContentArrangement;
use comfy_table::Table;

use miden_client::client::transactions::PaymentTransactionData;
use miden_client::client::transactions::TransactionStub;
use miden_client::client::transactions::TransactionTemplate;
Expand Down
12 changes: 3 additions & 9 deletions src/client/accounts.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
use super::Client;

use std::collections::BTreeMap;

use crypto::{Felt, Word};
use crypto::Felt;
use miden_lib::{faucets, AuthScheme};
use objects::{
accounts::{Account, AccountId, AccountStub, AccountType},
accounts::{Account, AccountId, AccountStorage, AccountStub, AccountType},
assembly::ModuleAst,
assets::{Asset, TokenSymbol},
Digest,
Expand Down Expand Up @@ -188,10 +185,7 @@ impl Client {
}

/// Returns account storage data from a storage root.
pub fn get_account_storage(
&self,
storage_root: Digest,
) -> Result<BTreeMap<u64, Word>, ClientError> {
pub fn get_account_storage(&self, storage_root: Digest) -> Result<AccountStorage, ClientError> {
self.store
.get_account_storage(storage_root)
.map_err(|err| err.into())
Expand Down
24 changes: 24 additions & 0 deletions src/client/chain_data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use super::Client;

#[cfg(test)]
use crate::errors::ClientError;
#[cfg(test)]
use objects::BlockHeader;

impl Client {
#[cfg(test)]
pub fn get_block_headers(
&self,
start: u32,
finish: u32,
) -> Result<Vec<BlockHeader>, ClientError> {
let mut headers = Vec::new();
for block_number in start..=finish {
if let Ok(block_header) = self.store.get_block_header_by_num(block_number) {
headers.push(block_header)
}
}

Ok(headers)
}
}
29 changes: 17 additions & 12 deletions src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@ use crate::{
store::{mock_executor_data_store::MockDataStore, Store},
};

#[cfg(not(any(test, feature = "testing")))]
use crate::errors::RpcApiError;

use miden_tx::TransactionExecutor;

#[cfg(any(test, feature = "testing"))]
#[cfg(feature = "testing")]
use crate::mock::MockRpcApi;

pub mod accounts;
pub mod chain_data;
pub mod notes;
pub mod sync_state;
pub mod transactions;
Expand All @@ -37,11 +35,9 @@ pub const FILTER_ID_SHIFT: u8 = 48;
pub struct Client {
/// Local database containing information about the accounts managed by this client.
pub(crate) store: Store,
#[cfg(not(any(test, feature = "testing")))]
/// Api client for interacting with the Miden node.
rpc_api: miden_node_proto::rpc::api_client::ApiClient<tonic::transport::Channel>,
#[cfg(any(test, feature = "testing"))]
pub rpc_api: MockRpcApi,
#[cfg(any(test, feature = "testing"))]
pub(crate) tx_executor: TransactionExecutor<MockDataStore>,
}

Expand All @@ -54,17 +50,26 @@ impl Client {
/// # Errors
/// Returns an error if the client could not be instantiated.
pub async fn new(config: ClientConfig) -> Result<Self, ClientError> {
Ok(Self {
#[cfg(not(any(test, feature = "testing")))]
return Ok(Self {
store: Store::new((&config).into())?,
#[cfg(not(any(test, feature = "testing")))]
rpc_api: miden_node_proto::rpc::api_client::ApiClient::connect(
config.node_endpoint.to_string(),
)
.await
.map_err(|err| ClientError::RpcApiError(RpcApiError::ConnectionError(err)))?,
#[cfg(any(test, feature = "testing"))]
.map_err(|err| {
ClientError::RpcApiError(crate::errors::RpcApiError::ConnectionError(err))
})?,
tx_executor: TransactionExecutor::new(crate::store::data_store::SqliteDataStore::new(
Store::new((&config).into())?,
)),
});

#[cfg(any(test, feature = "testing"))]
return Ok(Self {
store: Store::new((&config).into())?,
rpc_api: Default::default(),
tx_executor: TransactionExecutor::new(MockDataStore::new()),
})
});
}
}
36 changes: 30 additions & 6 deletions src/client/sync_state.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use super::Client;

use crypto::StarkField;
use miden_node_proto::{
account_id::AccountId as ProtoAccountId, requests::SyncStateRequest,
Expand All @@ -9,6 +8,11 @@ use objects::{accounts::AccountId, Digest};

use crate::errors::{ClientError, RpcApiError};

pub enum SyncStatus {
SyncedToLastBlock(u32),
SyncedToBlock(u32),
}

// CONSTANTS
// ================================================================================================

Expand Down Expand Up @@ -47,16 +51,25 @@ impl Client {
///
/// Returns the block number the client has been synced to.
pub async fn sync_state(&mut self) -> Result<u32, ClientError> {
loop {
let response = self.single_sync_state().await?;
if let SyncStatus::SyncedToLastBlock(v) = response {
return Ok(v);
}
}
}

async fn single_sync_state(&mut self) -> Result<SyncStatus, ClientError> {
let block_num = self.store.get_latest_block_number()?;
let account_ids = self.store.get_account_ids()?;
let note_tags = self.store.get_note_tags()?;
let nullifiers = self.store.get_unspent_input_note_nullifiers()?; // breaks

let nullifiers = self.store.get_unspent_input_note_nullifiers()?;
let response = self
.sync_state_request(block_num, &account_ids, &note_tags, &nullifiers)
.await?;
let incoming_block_header = response.block_header.unwrap();

let new_block_num = response.chain_tip;
let new_block_num = incoming_block_header.block_num;
let new_nullifiers = response
.nullifiers
.into_iter()
Expand All @@ -71,10 +84,21 @@ impl Client {
.collect::<Vec<_>>();

self.store
.apply_state_sync(new_block_num, new_nullifiers)
.apply_state_sync(
incoming_block_header
.try_into()
.map_err(ClientError::RpcTypeConversionFailure)?,
new_nullifiers,
response.accounts,
response.mmr_delta,
)
.map_err(ClientError::StoreError)?;

Ok(new_block_num)
if response.chain_tip == new_block_num {
Ok(SyncStatus::SyncedToLastBlock(response.chain_tip))
} else {
Ok(SyncStatus::SyncedToBlock(new_block_num))
}
}

// HELPERS
Expand Down
13 changes: 6 additions & 7 deletions src/client/transactions.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
use crate::{
errors::{self, ClientError},
store::mock_executor_data_store::{self, MockDataStore},
};
use crypto::utils::Serializable;
use miden_lib::notes::{create_note, Script};
use miden_node_proto::{
Expand All @@ -14,11 +18,6 @@ use objects::{
};
use rand::Rng;

use crate::{
errors::{self, ClientError},
store::{self, mock_executor_data_store::MockDataStore},
};

use super::Client;

pub enum TransactionTemplate {
Expand Down Expand Up @@ -143,8 +142,8 @@ impl Client {
) -> Result<(TransactionResult, TransactionScript), ClientError> {
// Create assets
let (target_pub_key, target_sk_pk_felt) =
store::mock_executor_data_store::get_new_key_pair_with_advice_map();
let target_account = store::mock_executor_data_store::get_account_with_default_account_code(
mock_executor_data_store::get_new_key_pair_with_advice_map();
let target_account = mock_executor_data_store::get_account_with_default_account_code(
target_account_id,
target_pub_key,
None,
Expand Down
29 changes: 25 additions & 4 deletions src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use core::fmt;
use crypto::{
dsa::rpo_falcon512::FalconError,
utils::{DeserializationError, HexParseError},
};
use crypto::merkle::MmrError;
use crypto::utils::DeserializationError;
use crypto::{dsa::rpo_falcon512::FalconError, utils::HexParseError};
use miden_node_proto::error::ParseError;
use miden_tx::{TransactionExecutorError, TransactionProverError};
use objects::AssetError;
use objects::{accounts::AccountId, AccountError, Digest, NoteError, TransactionScriptError};
use tonic::{transport::Error as TransportError, Status as TonicStatus};

Expand All @@ -13,7 +14,9 @@ use tonic::{transport::Error as TransportError, Status as TonicStatus};
#[derive(Debug)]
pub enum ClientError {
AccountError(AccountError),
AssetError(AssetError),
AuthError(FalconError),
RpcTypeConversionFailure(ParseError),
NoteError(NoteError),
RpcApiError(RpcApiError),
StoreError(StoreError),
Expand All @@ -25,7 +28,11 @@ impl fmt::Display for ClientError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ClientError::AccountError(err) => write!(f, "account error: {err}"),
ClientError::AssetError(err) => write!(f, "asset error: {err}"),
ClientError::AuthError(err) => write!(f, "account auth error: {err}"),
ClientError::RpcTypeConversionFailure(err) => {
write!(f, "failed to convert data: {err}")
}
ClientError::NoteError(err) => write!(f, "note error: {err}"),
ClientError::RpcApiError(err) => write!(f, "rpc api error: {err}"),
ClientError::StoreError(err) => write!(f, "store error: {err}"),
Expand Down Expand Up @@ -56,7 +63,9 @@ pub enum StoreError {
AccountCodeDataNotFound(Digest),
AccountDataNotFound(AccountId),
AccountError(AccountError),
AccountHashMismatch(AccountId),
AccountStorageNotFound(Digest),
ChainMmrNodeNotFound(u64),
ColumnParsingError(rusqlite::Error),
ConnectionError(rusqlite::Error),
DataDeserializationError(DeserializationError),
Expand All @@ -65,9 +74,11 @@ pub enum StoreError {
InputSerializationError(serde_json::Error),
JsonDataDeserializationError(serde_json::Error),
MigrationError(rusqlite_migration::Error),
MmrError(MmrError),
NoteTagAlreadyTracked(u64),
QueryError(rusqlite::Error),
TransactionError(rusqlite::Error),
BlockHeaderNotFound(u32),
TransactionScriptError(TransactionScriptError),
VaultDataNotFound(Digest),
}
Expand All @@ -83,12 +94,18 @@ impl fmt::Display for StoreError {
write!(f, "Account data was not found for Account Id {account_id}")
}
AccountError(err) => write!(f, "error instantiating Account: {err}"),
AccountHashMismatch(account_id) => {
write!(f, "account hash mismatch for account {account_id}")
}
AccountStorageNotFound(root) => {
write!(f, "account storage data with root {} not found", root)
}
ColumnParsingError(err) => {
write!(f, "failed to parse data retrieved from the database: {err}")
}
ChainMmrNodeNotFound(node_index) => {
write!(f, "chain mmr node at index {} not found", node_index)
}
ConnectionError(err) => write!(f, "failed to connect to the database: {err}"),
DataDeserializationError(err) => {
write!(f, "error deserializing data from the store: {err}")
Expand All @@ -107,13 +124,17 @@ impl fmt::Display for StoreError {
)
}
MigrationError(err) => write!(f, "failed to update the database: {err}"),
MmrError(err) => write!(f, "error constructing mmr: {err}"),
NoteTagAlreadyTracked(tag) => write!(f, "note tag {} is already being tracked", tag),
QueryError(err) => write!(f, "failed to retrieve data from the database: {err}"),
TransactionError(err) => write!(f, "failed to instantiate a new transaction: {err}"),
TransactionScriptError(err) => {
write!(f, "error instantiating transaction script: {err}")
}
VaultDataNotFound(root) => write!(f, "account vault data for root {} not found", root),
BlockHeaderNotFound(block_num) => {
write!(f, "block header for block {} not found", block_num)
}
}
}
}
Expand Down
Loading

0 comments on commit 653b3a9

Please sign in to comment.