diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 3b97b0d25..5c898fde8 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -68,6 +68,14 @@ jobs: - name: check rust versions run: ./scripts/check-rust-version.sh + unused_deps: + name: check for unused dependencies + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: machete + uses: bnjbvr/cargo-machete@main + proto: name: proto check runs-on: ubuntu-latest diff --git a/CHANGELOG.md b/CHANGELOG.md index e31162448..67f1afd47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Support Https in endpoint configuration (#556). - Upgrade `block-producer` from FIFO queue to mempool dependency graph (#562). - Support transaction expiration (#582). +- Improved RPC endpoints doc comments (#620). ### Changes diff --git a/Cargo.lock b/Cargo.lock index 62cd6afd4..ba0544214 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1485,7 +1485,6 @@ dependencies = [ "anyhow", "axum", "clap", - "figment", "http", "http-body-util", "miden-lib", @@ -1590,7 +1589,6 @@ dependencies = [ "tokio", "toml", "tracing", - "tracing-subscriber", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 7e83339b9..caa067022 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,3 +47,17 @@ tokio-stream = { version = "0.1" } tonic = { version = "0.12" } tracing = { version = "0.1" } tracing-subscriber = { version = "0.3", features = ["fmt", "json", "env-filter"] } + +# Lints are set to warn for development, which are promoted to errors in CI. +[workspace.lints.clippy] +# Pedantic lints are set to a lower priority which allows lints in the group to be selectively enabled. +pedantic = { level = "warn", priority = -1 } +cast_possible_truncation = "allow" # Overly many instances especially regarding indices. +ignored_unit_patterns = "allow" # Stylistic choice. +large_types_passed_by_value = "allow" # Triggered by BlockHeader being Copy + 334 bytes. +missing_errors_doc = "allow" # TODO: fixup and enable this. +missing_panics_doc = "allow" # TODO: fixup and enable this. +module_name_repetitions = "allow" # Many triggers, and is a stylistic choice. +must_use_candidate = "allow" # This marks many fn's which isn't helpful. +should_panic_without_expect = "allow" # We don't care about the specific panic message. +# End of pedantic lints. diff --git a/bin/faucet/Cargo.toml b/bin/faucet/Cargo.toml index 5d9d8a148..cce8844fd 100644 --- a/bin/faucet/Cargo.toml +++ b/bin/faucet/Cargo.toml @@ -11,11 +11,13 @@ authors.workspace = true homepage.workspace = true repository.workspace = true +[lints] +workspace = true + [dependencies] anyhow = "1.0" axum = { version = "0.7", features = ["tokio"] } clap = { version = "4.5", features = ["derive", "string"] } -figment = { version = "0.10", features = ["toml", "env"] } http = "1.1" http-body-util = "0.1" miden-lib = { workspace = true } diff --git a/bin/faucet/src/client.rs b/bin/faucet/src/client.rs index 8b05ddf4f..562ff483d 100644 --- a/bin/faucet/src/client.rs +++ b/bin/faucet/src/client.rs @@ -111,7 +111,7 @@ impl FaucetClient { let coin_seed: [u64; 4] = random(); let rng = RpoRandomCoin::new(coin_seed.map(Felt::new)); - Ok(Self { data_store, rpc_api, executor, id, rng }) + Ok(Self { rpc_api, executor, data_store, id, rng }) } /// Executes a mint transaction for the target account. @@ -137,7 +137,7 @@ impl FaucetClient { target_account_id, vec![asset.into()], note_type, - Default::default(), + Felt::default(), &mut self.rng, ) .context("Failed to create P2ID note")?; diff --git a/bin/faucet/src/handlers.rs b/bin/faucet/src/handlers.rs index e8d6e11bb..9037c2a24 100644 --- a/bin/faucet/src/handlers.rs +++ b/bin/faucet/src/handlers.rs @@ -86,7 +86,7 @@ pub async fn get_tokens( let block_height = client.prove_and_submit_transaction(executed_tx).await?; // Update data store with the new faucet state - client.data_store().update_faucet_state(faucet_account).await?; + client.data_store().update_faucet_state(faucet_account); let note_id: NoteId = created_note.id(); let note_details = diff --git a/bin/faucet/src/main.rs b/bin/faucet/src/main.rs index 06a3a5fe9..cb4053ead 100644 --- a/bin/faucet/src/main.rs +++ b/bin/faucet/src/main.rs @@ -203,7 +203,7 @@ mod static_resources { include!(concat!(env!("OUT_DIR"), "/generated.rs")); } -/// Generates [LongVersion] using the metadata generated by build.rs. +/// Generates [`LongVersion`] using the metadata generated by build.rs. fn long_version() -> LongVersion { // Use optional to allow for build script embedding failure. LongVersion { diff --git a/bin/faucet/src/state.rs b/bin/faucet/src/state.rs index fb6940812..6f70a0207 100644 --- a/bin/faucet/src/state.rs +++ b/bin/faucet/src/state.rs @@ -31,6 +31,6 @@ impl FaucetState { info!(target: COMPONENT, account_id = %id, "Faucet initialization successful"); - Ok(FaucetState { client, id, config, static_files }) + Ok(FaucetState { id, client, config, static_files }) } } diff --git a/bin/faucet/src/store.rs b/bin/faucet/src/store.rs index 02050765e..a4a3c831e 100644 --- a/bin/faucet/src/store.rs +++ b/bin/faucet/src/store.rs @@ -8,8 +8,6 @@ use miden_objects::{ }; use miden_tx::{DataStore, DataStoreError}; -use crate::errors::HandlerError; - pub struct FaucetDataStore { faucet_account: Mutex, /// Optional initial seed used for faucet account creation. @@ -42,10 +40,8 @@ impl FaucetDataStore { } /// Updates the stored faucet account with the new one. - pub async fn update_faucet_state(&self, new_faucet_state: Account) -> Result<(), HandlerError> { + pub fn update_faucet_state(&self, new_faucet_state: Account) { *self.faucet_account.lock().expect("Poisoned lock") = new_faucet_state; - - Ok(()) } } diff --git a/bin/node/Cargo.toml b/bin/node/Cargo.toml index 9e25829b7..37eda9a12 100644 --- a/bin/node/Cargo.toml +++ b/bin/node/Cargo.toml @@ -11,6 +11,9 @@ authors.workspace = true homepage.workspace = true repository.workspace = true +[lints] +workspace = true + [features] tracing-forest = ["miden-node-block-producer/tracing-forest"] @@ -29,7 +32,6 @@ serde = { version = "1.0", features = ["derive"] } tokio = { workspace = true, features = ["rt-multi-thread", "net", "macros"] } toml = { version = "0.8" } tracing = { workspace = true } -tracing-subscriber = { workspace = true } [dev-dependencies] figment = { version = "0.10", features = ["toml", "env", "test"] } diff --git a/bin/node/src/commands/genesis/inputs.rs b/bin/node/src/commands/genesis/inputs.rs index 2f93d1d60..c0f5a765e 100644 --- a/bin/node/src/commands/genesis/inputs.rs +++ b/bin/node/src/commands/genesis/inputs.rs @@ -47,7 +47,7 @@ impl Default for GenesisInput { auth_scheme: AuthSchemeInput::RpoFalcon512, token_symbol: "POL".to_string(), decimals: 12, - max_supply: 1000000, + max_supply: 1_000_000, storage_mode: "public".to_string(), })]), } diff --git a/bin/node/src/commands/genesis/mod.rs b/bin/node/src/commands/genesis/mod.rs index d3c00148f..1875bb940 100644 --- a/bin/node/src/commands/genesis/mod.rs +++ b/bin/node/src/commands/genesis/mod.rs @@ -38,7 +38,7 @@ const DEFAULT_ACCOUNTS_DIR: &str = "accounts/"; /// This function returns a `Result` type. On successful creation of the genesis file, it returns /// `Ok(())`. If it fails at any point, due to issues like file existence checks or read/write /// operations, it returns an `Err` with a detailed error message. -pub fn make_genesis(inputs_path: &PathBuf, output_path: &PathBuf, force: &bool) -> Result<()> { +pub fn make_genesis(inputs_path: &PathBuf, output_path: &PathBuf, force: bool) -> Result<()> { let inputs_path = Path::new(inputs_path); let output_path = Path::new(output_path); @@ -63,14 +63,8 @@ pub fn make_genesis(inputs_path: &PathBuf, output_path: &PathBuf, force: &bool) return Err(anyhow!("Failed to open {} file.", inputs_path.display())); } - let parent_path = match output_path.parent() { - Some(path) => path, - None => { - return Err(anyhow!( - "There has been an error processing output_path: {}", - output_path.display() - )) - }, + let Some(parent_path) = output_path.parent() else { + anyhow::bail!("There has been an error processing output_path: {}", output_path.display()); }; let genesis_input: GenesisInput = load_config(inputs_path).map_err(|err| { @@ -97,7 +91,7 @@ pub fn make_genesis(inputs_path: &PathBuf, output_path: &PathBuf, force: &bool) fn create_accounts( accounts: &[AccountInput], accounts_path: impl AsRef, - force: &bool, + force: bool, ) -> Result> { if accounts_path.as_ref().try_exists()? { if !force { @@ -120,7 +114,7 @@ fn create_accounts( let (mut account_data, name) = match account { AccountInput::BasicFungibleFaucet(inputs) => { info!("Creating fungible faucet account..."); - let (auth_scheme, auth_secret_key) = gen_auth_keys(inputs.auth_scheme, &mut rng)?; + let (auth_scheme, auth_secret_key) = gen_auth_keys(inputs.auth_scheme, &mut rng); let storage_mode = inputs.storage_mode.as_str().try_into()?; let (account, account_seed) = create_basic_fungible_faucet( @@ -166,15 +160,15 @@ fn create_accounts( fn gen_auth_keys( auth_scheme_input: AuthSchemeInput, rng: &mut ChaCha20Rng, -) -> Result<(AuthScheme, AuthSecretKey)> { +) -> (AuthScheme, AuthSecretKey) { match auth_scheme_input { AuthSchemeInput::RpoFalcon512 => { let secret = SecretKey::with_rng(&mut get_rpo_random_coin(rng)); - Ok(( + ( AuthScheme::RpoFalcon512 { pub_key: secret.public_key() }, AuthSecretKey::RpoFalcon512(secret), - )) + ) }, } } @@ -217,7 +211,7 @@ mod tests { let genesis_dat_file_path = PathBuf::from(DEFAULT_GENESIS_FILE_PATH); // run make_genesis to generate genesis.dat and accounts folder and files - super::make_genesis(&genesis_inputs_file_path, &genesis_dat_file_path, &true).unwrap(); + super::make_genesis(&genesis_inputs_file_path, &genesis_dat_file_path, true).unwrap(); let a0_file_path = PathBuf::from("accounts/faucet.mac"); @@ -235,7 +229,7 @@ mod tests { let genesis_state = GenesisState::read_from_bytes(&genesis_file_contents).unwrap(); // build supposed genesis_state - let supposed_genesis_state = GenesisState::new(vec![a0.account], 1, 1672531200); + let supposed_genesis_state = GenesisState::new(vec![a0.account], 1, 1_672_531_200); // assert that both genesis_state(s) are eq assert_eq!(genesis_state, supposed_genesis_state); diff --git a/bin/node/src/commands/init.rs b/bin/node/src/commands/init.rs index 13ea35c45..7b36a70ff 100644 --- a/bin/node/src/commands/init.rs +++ b/bin/node/src/commands/init.rs @@ -1,4 +1,4 @@ -use std::{fs::File, io::Write, path::PathBuf}; +use std::{fs::File, io::Write, path::Path}; use anyhow::{anyhow, Result}; @@ -7,27 +7,27 @@ use crate::{commands::genesis::GenesisInput, config::NodeConfig}; // INIT // =================================================================================================== -pub fn init_config_files(config_file_path: PathBuf, genesis_file_path: PathBuf) -> Result<()> { +pub fn init_config_files(config_file_path: &Path, genesis_file_path: &Path) -> Result<()> { let config = NodeConfig::default(); let config_as_toml_string = toml::to_string(&config) .map_err(|err| anyhow!("Failed to serialize default config: {}", err))?; - write_string_in_file(config_as_toml_string, &config_file_path)?; + write_string_in_file(&config_as_toml_string, config_file_path)?; - println!("Config file successfully created at: {:?}", config_file_path); + println!("Config file successfully created at: {config_file_path:?}"); let genesis = GenesisInput::default(); let genesis_as_toml_string = toml::to_string(&genesis) .map_err(|err| anyhow!("Failed to serialize default config: {}", err))?; - write_string_in_file(genesis_as_toml_string, &genesis_file_path)?; + write_string_in_file(&genesis_as_toml_string, genesis_file_path)?; - println!("Genesis config file successfully created at: {:?}", genesis_file_path); + println!("Genesis config file successfully created at: {genesis_file_path:?}"); Ok(()) } -fn write_string_in_file(content: String, path: &PathBuf) -> Result<()> { +fn write_string_in_file(content: &str, path: &Path) -> Result<()> { let mut file_handle = File::options() .write(true) .create_new(true) diff --git a/bin/node/src/config.rs b/bin/node/src/config.rs index 8e44ad064..21a018920 100644 --- a/bin/node/src/config.rs +++ b/bin/node/src/config.rs @@ -13,14 +13,14 @@ pub struct NodeConfig { store: StoreConfig, } -/// A specialized variant of [RpcConfig] with redundant fields within [NodeConfig] removed. +/// A specialized variant of [`RpcConfig`] with redundant fields within [`NodeConfig`] removed. #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Serialize, Deserialize)] #[serde(deny_unknown_fields)] struct NormalizedRpcConfig { endpoint: Endpoint, } -/// A specialized variant of [BlockProducerConfig] with redundant fields within [NodeConfig] +/// A specialized variant of [`BlockProducerConfig`] with redundant fields within [`NodeConfig`] /// removed. #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Serialize, Deserialize)] #[serde(deny_unknown_fields)] diff --git a/bin/node/src/main.rs b/bin/node/src/main.rs index 1839d7484..998b54461 100644 --- a/bin/node/src/main.rs +++ b/bin/node/src/main.rs @@ -121,7 +121,7 @@ async fn main() -> anyhow::Result<()> { }, }, Command::MakeGenesis { output_path, force, inputs_path } => { - commands::make_genesis(inputs_path, output_path, force) + commands::make_genesis(inputs_path, output_path, *force) }, Command::Init { config_path, genesis_path } => { let current_dir = std::env::current_dir() @@ -130,12 +130,12 @@ async fn main() -> anyhow::Result<()> { let config = current_dir.join(config_path); let genesis = current_dir.join(genesis_path); - init_config_files(config, genesis) + init_config_files(&config, &genesis) }, } } -/// Generates [LongVersion] using the metadata generated by build.rs. +/// Generates [`LongVersion`] using the metadata generated by build.rs. fn long_version() -> LongVersion { LongVersion { version: env!("CARGO_PKG_VERSION"), diff --git a/crates/block-producer/Cargo.toml b/crates/block-producer/Cargo.toml index c92a22e71..d9a0ef101 100644 --- a/crates/block-producer/Cargo.toml +++ b/crates/block-producer/Cargo.toml @@ -11,6 +11,9 @@ authors.workspace = true homepage.workspace = true repository.workspace = true +[lints] +workspace = true + [features] tracing-forest = ["miden-node-utils/tracing-forest"] testing = [] diff --git a/crates/block-producer/README.md b/crates/block-producer/README.md index 3de8f2085..cedb36b96 100644 --- a/crates/block-producer/README.md +++ b/crates/block-producer/README.md @@ -25,7 +25,7 @@ Submits proven transaction to the Miden network. **Parameters** -* `transaction`: `bytes` - transaction encoded using Miden's native format. +* `transaction`: `bytes` - transaction encoded using [winter_utils::Serializable](https://github.com/facebook/winterfell/blob/main/utils/core/src/serde/mod.rs#L26) implementation for [miden_objects::transaction::proven_tx::ProvenTransaction](https://github.com/0xPolygonMiden/miden-base/blob/main/objects/src/transaction/proven_tx.rs#L22). **Returns** diff --git a/crates/block-producer/src/batch_builder/batch.rs b/crates/block-producer/src/batch_builder/batch.rs index 7fc23e46a..b0e507ccf 100644 --- a/crates/block-producer/src/batch_builder/batch.rs +++ b/crates/block-producer/src/batch_builder/batch.rs @@ -21,7 +21,7 @@ use crate::{errors::BuildBatchError, COMPONENT}; // BATCH ID // ================================================================================================ -/// Uniquely identifies a [TransactionBatch]. +/// Uniquely identifies a [`TransactionBatch`]. #[derive(Debug, Copy, Clone, Eq, Ord, PartialEq, PartialOrd)] pub struct BatchId(Blake3Digest<32>); @@ -138,7 +138,7 @@ impl TransactionBatch { Entry::Occupied(occupied) => { occupied.into_mut().merge_tx(tx).map_err(|source| { BuildBatchError::AccountUpdateError { account_id: tx.account_id(), source } - })? + })?; }, }; @@ -181,7 +181,7 @@ impl TransactionBatch { }, None => input_note.clone(), }; - input_notes.push(input_note) + input_notes.push(input_note); } } @@ -210,7 +210,7 @@ impl TransactionBatch { self.id } - /// Returns an iterator over (account_id, init_state_hash) tuples for accounts that were + /// Returns an iterator over (`account_id`, `init_state_hash`) tuples for accounts that were /// modified in this transaction batch. #[cfg(any(test, feature = "testing"))] pub fn account_initial_states(&self) -> impl Iterator + '_ { @@ -219,8 +219,8 @@ impl TransactionBatch { .map(|(&account_id, update)| (account_id, update.init_state)) } - /// Returns an iterator over (account_id, details, new_state_hash) tuples for accounts that were - /// modified in this transaction batch. + /// Returns an iterator over (`account_id`, details, `new_state_hash`) tuples for accounts that + /// were modified in this transaction batch. pub fn updated_accounts(&self) -> impl Iterator + '_ { self.updated_accounts.iter() } @@ -330,7 +330,7 @@ mod tests { match OutputNoteTracker::new(txs.iter()) { Err(BuildBatchError::DuplicateOutputNote(note_id)) => { - assert_eq!(note_id, duplicate_output_note.id()) + assert_eq!(note_id, duplicate_output_note.id()); }, res => panic!("Unexpected result: {res:?}"), } @@ -364,9 +364,9 @@ mod tests { let mut txs = mock_proven_txs(); let duplicate_note = mock_note(5); txs.push(mock_proven_tx(4, vec![duplicate_note.clone()], vec![mock_output_note(9)])); - match TransactionBatch::new(&txs, Default::default()) { + match TransactionBatch::new(&txs, NoteAuthenticationInfo::default()) { Err(BuildBatchError::DuplicateUnauthenticatedNote(note_id)) => { - assert_eq!(note_id, duplicate_note.id()) + assert_eq!(note_id, duplicate_note.id()); }, res => panic!("Unexpected result: {res:?}"), } @@ -382,7 +382,7 @@ mod tests { vec![mock_output_note(9), mock_output_note(10)], )); - let batch = TransactionBatch::new(&txs, Default::default()).unwrap(); + let batch = TransactionBatch::new(&txs, NoteAuthenticationInfo::default()).unwrap(); // One of the unauthenticated notes must be removed from the batch due to the consumption // of the corresponding output note @@ -424,7 +424,7 @@ mod tests { )]); let found_unauthenticated_notes = NoteAuthenticationInfo { note_proofs: found_unauthenticated_notes, - block_proofs: Default::default(), + block_proofs: Vec::default(), }; let batch = TransactionBatch::new(&txs, found_unauthenticated_notes).unwrap(); diff --git a/crates/block-producer/src/batch_builder/mod.rs b/crates/block-producer/src/batch_builder/mod.rs index 5dc6f574c..a2f5f24a6 100644 --- a/crates/block-producer/src/batch_builder/mod.rs +++ b/crates/block-producer/src/batch_builder/mod.rs @@ -20,7 +20,7 @@ use crate::errors::BuildBatchError; // BATCH BUILDER // ================================================================================================ -/// Builds [TransactionBatch] from sets of transactions. +/// Builds [`TransactionBatch`] from sets of transactions. /// /// Transaction sets are pulled from the mempool at a configurable interval, and passed to /// a pool of provers for proof generation. Proving is currently unimplemented and is instead @@ -50,7 +50,7 @@ impl Default for BatchBuilder { } impl BatchBuilder { - /// Starts the [BatchBuilder], creating and proving batches at the configured interval. + /// Starts the [`BatchBuilder`], creating and proving batches at the configured interval. /// /// A pool of batch-proving workers is spawned, which are fed new batch jobs periodically. /// A batch is skipped if there are no available workers, or if there are no transactions @@ -109,7 +109,7 @@ type BatchResult = Result; /// Represents a pool of batch provers. /// -/// Effectively a wrapper around tokio's JoinSet that remains pending if the set is empty, +/// Effectively a wrapper around tokio's `JoinSet` that remains pending if the set is empty, /// instead of returning None. struct WorkerPool { in_progress: JoinSet, @@ -139,13 +139,13 @@ impl WorkerPool { capacity, store, in_progress: JoinSet::default(), - task_map: Default::default(), + task_map: Vec::default(), } } /// Returns the next batch proof result. /// - /// Will return pending if there are no jobs in progress (unlike tokio's [JoinSet::join_next] + /// Will return pending if there are no jobs in progress (unlike tokio's [`JoinSet::join_next`] /// which returns an option). async fn join_next(&mut self) -> BatchResult { if self.in_progress.is_empty() { @@ -193,7 +193,7 @@ impl WorkerPool { /// # Errors /// /// Returns an error if no workers are available which can be checked using - /// [has_capacity](Self::has_capacity). + /// [`has_capacity`](Self::has_capacity). fn spawn( &mut self, id: BatchId, @@ -221,7 +221,9 @@ impl WorkerPool { let inputs = store .get_batch_inputs( - transactions.iter().flat_map(|tx| tx.unauthenticated_notes()), + transactions + .iter() + .flat_map(AuthenticatedTransaction::unauthenticated_notes), ) .await .map_err(|err| (id, BuildBatchError::FetchBatchInputsFailed(err)))?; diff --git a/crates/block-producer/src/block_builder/mod.rs b/crates/block-producer/src/block_builder/mod.rs index 883fdc9cf..a0c0f63ad 100644 --- a/crates/block-producer/src/block_builder/mod.rs +++ b/crates/block-producer/src/block_builder/mod.rs @@ -5,7 +5,7 @@ use miden_objects::{ accounts::AccountId, block::Block, notes::{NoteHeader, Nullifier}, - transaction::InputNoteCommitment, + transaction::{InputNoteCommitment, OutputNote}, }; use rand::Rng; use tokio::time::Duration; @@ -48,7 +48,7 @@ impl BlockBuilder { store, } } - /// Starts the [BlockBuilder], infinitely producing blocks at the configured interval. + /// Starts the [`BlockBuilder`], infinitely producing blocks at the configured interval. /// /// Block production is sequential and consists of /// @@ -98,7 +98,7 @@ impl BlockBuilder { info!( target: COMPONENT, num_batches = batches.len(), - batches = %format_array(batches.iter().map(|batch| batch.id())), + batches = %format_array(batches.iter().map(TransactionBatch::id)), ); let updated_account_set: BTreeSet = batches @@ -114,10 +114,8 @@ impl BlockBuilder { batches.iter().flat_map(TransactionBatch::produced_nullifiers).collect(); // Populate set of output notes from all batches - let output_notes_set: BTreeSet<_> = output_notes - .iter() - .flat_map(|batch| batch.iter().map(|note| note.id())) - .collect(); + let output_notes_set: BTreeSet<_> = + output_notes.iter().flat_map(|batch| batch.iter().map(OutputNote::id)).collect(); // Build a set of unauthenticated input notes for this block which do not have a matching // output note produced in this block diff --git a/crates/block-producer/src/block_builder/prover/block_witness.rs b/crates/block-producer/src/block_builder/prover/block_witness.rs index 57205244c..b4ff493b0 100644 --- a/crates/block-producer/src/block_builder/prover/block_witness.rs +++ b/crates/block-producer/src/block_builder/prover/block_witness.rs @@ -11,7 +11,7 @@ use miden_objects::{ }; use crate::{ - batch_builder::{batch::AccountUpdate, TransactionBatch}, + batch_builder::batch::{AccountUpdate, TransactionBatch}, block::BlockInputs, errors::{BlockProverError, BuildBlockError}, }; @@ -23,7 +23,7 @@ use crate::{ #[derive(Debug, PartialEq)] pub struct BlockWitness { pub(super) updated_accounts: Vec<(AccountId, AccountUpdateWitness)>, - /// (batch_index, created_notes_root) for batches that contain notes + /// (`batch_index`, `created_notes_root`) for batches that contain notes pub(super) batch_created_notes_roots: BTreeMap, pub(super) produced_nullifiers: BTreeMap, pub(super) chain_peaks: MmrPeaks, @@ -162,7 +162,7 @@ impl BlockWitness { block_inputs.nullifiers.keys().copied().collect(); let produced_nullifiers_from_batches: BTreeSet = - batches.iter().flat_map(|batch| batch.produced_nullifiers()).collect(); + batches.iter().flat_map(TransactionBatch::produced_nullifiers).collect(); if produced_nullifiers_from_store == produced_nullifiers_from_batches { Ok(()) @@ -218,8 +218,7 @@ impl BlockWitness { let empty_root = EmptySubtreeRoots::entry(BLOCK_NOTE_TREE_DEPTH, 0); advice_stack.extend(*empty_root); - for (batch_index, batch_created_notes_root) in self.batch_created_notes_roots.iter() - { + for (batch_index, batch_created_notes_root) in &self.batch_created_notes_roots { advice_stack.extend(batch_created_notes_root.iter()); let batch_index = Felt::try_from(*batch_index as u64) diff --git a/crates/block-producer/src/block_builder/prover/tests.rs b/crates/block-producer/src/block_builder/prover/tests.rs index 927493975..d14ec2658 100644 --- a/crates/block-producer/src/block_builder/prover/tests.rs +++ b/crates/block-producer/src/block_builder/prover/tests.rs @@ -1,6 +1,7 @@ use std::{collections::BTreeMap, iter}; use assert_matches::assert_matches; +use miden_node_proto::domain::notes::NoteAuthenticationInfo; use miden_objects::{ accounts::{ delta::AccountUpdateDetails, AccountId, AccountIdVersion, AccountStorageMode, AccountType, @@ -20,7 +21,7 @@ use miden_objects::{ use self::block_witness::AccountUpdateWitness; use super::*; use crate::{ - batch_builder::TransactionBatch, + batch_builder::batch::TransactionBatch, block::{AccountWitness, BlockInputs}, test_utils::{ block::{build_actual_block_header, build_expected_block_header, MockBlockBuilder}, @@ -57,7 +58,7 @@ fn block_witness_validation_inconsistent_account_ids() { ); let block_inputs_from_store: BlockInputs = { - let block_header = BlockHeader::mock(0, None, None, &[], Default::default()); + let block_header = BlockHeader::mock(0, None, None, &[], Digest::default()); let chain_peaks = MmrPeaks::new(0, Vec::new()).unwrap(); let accounts = BTreeMap::from_iter(vec![ @@ -69,8 +70,8 @@ fn block_witness_validation_inconsistent_account_ids() { block_header, chain_peaks, accounts, - nullifiers: Default::default(), - found_unauthenticated_notes: Default::default(), + nullifiers: BTreeMap::default(), + found_unauthenticated_notes: NoteAuthenticationInfo::default(), } }; @@ -83,7 +84,7 @@ fn block_witness_validation_inconsistent_account_ids() { ) .build(); - TransactionBatch::new([&tx], Default::default()).unwrap() + TransactionBatch::new([&tx], NoteAuthenticationInfo::default()).unwrap() }; let batch_2 = { @@ -94,7 +95,7 @@ fn block_witness_validation_inconsistent_account_ids() { ) .build(); - TransactionBatch::new([&tx], Default::default()).unwrap() + TransactionBatch::new([&tx], NoteAuthenticationInfo::default()).unwrap() }; vec![batch_1, batch_2] @@ -121,7 +122,7 @@ fn block_witness_validation_inconsistent_account_hashes() { Digest::new([Felt::new(4u64), Felt::new(3u64), Felt::new(2u64), Felt::new(1u64)]); let block_inputs_from_store: BlockInputs = { - let block_header = BlockHeader::mock(0, None, None, &[], Default::default()); + let block_header = BlockHeader::mock(0, None, None, &[], Digest::default()); let chain_peaks = MmrPeaks::new(0, Vec::new()).unwrap(); let accounts = BTreeMap::from_iter(vec![ @@ -129,18 +130,18 @@ fn block_witness_validation_inconsistent_account_hashes() { account_id_1, AccountWitness { hash: account_1_hash_store, - proof: Default::default(), + proof: MerklePath::default(), }, ), - (account_id_2, Default::default()), + (account_id_2, AccountWitness::default()), ]); BlockInputs { block_header, chain_peaks, accounts, - nullifiers: Default::default(), - found_unauthenticated_notes: Default::default(), + nullifiers: BTreeMap::default(), + found_unauthenticated_notes: NoteAuthenticationInfo::default(), } }; @@ -152,7 +153,7 @@ fn block_witness_validation_inconsistent_account_hashes() { Digest::default(), ) .build()], - Default::default(), + NoteAuthenticationInfo::default(), ) .unwrap(); let batch_2 = TransactionBatch::new( @@ -162,7 +163,7 @@ fn block_witness_validation_inconsistent_account_hashes() { Digest::default(), ) .build()], - Default::default(), + NoteAuthenticationInfo::default(), ) .unwrap(); @@ -224,7 +225,7 @@ fn block_witness_multiple_batches_per_account() { )]); let block_inputs_from_store: BlockInputs = { - let block_header = BlockHeader::mock(0, None, None, &[], Default::default()); + let block_header = BlockHeader::mock(0, None, None, &[], Digest::default()); let chain_peaks = MmrPeaks::new(0, Vec::new()).unwrap(); let x_witness = AccountWitness { @@ -241,14 +242,18 @@ fn block_witness_multiple_batches_per_account() { block_header, chain_peaks, accounts, - nullifiers: Default::default(), - found_unauthenticated_notes: Default::default(), + nullifiers: BTreeMap::default(), + found_unauthenticated_notes: NoteAuthenticationInfo::default(), } }; let batches = { - let batch_1 = TransactionBatch::new([&x_txs[0], &y_txs[1]], Default::default()).unwrap(); - let batch_2 = TransactionBatch::new([&y_txs[0], &x_txs[1]], Default::default()).unwrap(); + let batch_1 = + TransactionBatch::new([&x_txs[0], &y_txs[1]], NoteAuthenticationInfo::default()) + .unwrap(); + let batch_2 = + TransactionBatch::new([&y_txs[0], &x_txs[1]], NoteAuthenticationInfo::default()) + .unwrap(); vec![batch_1, batch_2] }; @@ -369,8 +374,8 @@ async fn compute_account_root_success() { }) .collect(); - let batch_1 = TransactionBatch::new(&txs[..2], Default::default()).unwrap(); - let batch_2 = TransactionBatch::new(&txs[2..], Default::default()).unwrap(); + let batch_1 = TransactionBatch::new(&txs[..2], NoteAuthenticationInfo::default()).unwrap(); + let batch_2 = TransactionBatch::new(&txs[2..], NoteAuthenticationInfo::default()).unwrap(); vec![batch_1, batch_2] }; @@ -538,7 +543,7 @@ async fn compute_note_root_empty_notes_success() { .unwrap(); let batches: Vec = { - let batch = TransactionBatch::new(vec![], Default::default()).unwrap(); + let batch = TransactionBatch::new(vec![], NoteAuthenticationInfo::default()).unwrap(); vec![batch] }; @@ -627,8 +632,8 @@ async fn compute_note_root_success() { }) .collect(); - let batch_1 = TransactionBatch::new(&txs[..2], Default::default()).unwrap(); - let batch_2 = TransactionBatch::new(&txs[2..], Default::default()).unwrap(); + let batch_1 = TransactionBatch::new(&txs[..2], NoteAuthenticationInfo::default()).unwrap(); + let batch_2 = TransactionBatch::new(&txs[2..], NoteAuthenticationInfo::default()).unwrap(); vec![batch_1, batch_2] }; @@ -644,6 +649,7 @@ async fn compute_note_root_success() { // The current logic is hardcoded to a depth of 6 // Specifically, we assume the block has up to 2^6 batches, and each batch up to 2^10 created // notes, where each note is stored at depth 10 in the batch tree. + #[allow(clippy::items_after_statements, reason = "assert belongs to this section")] const _: () = assert!(BLOCK_NOTE_TREE_DEPTH - BATCH_NOTE_TREE_DEPTH == 6); // The first 2 txs were put in the first batch; the 3rd was put in the second @@ -684,13 +690,13 @@ fn block_witness_validation_inconsistent_nullifiers() { let batch_1 = { let tx = MockProvenTxBuilder::with_account_index(0).nullifiers_range(0..1).build(); - TransactionBatch::new([&tx], Default::default()).unwrap() + TransactionBatch::new([&tx], NoteAuthenticationInfo::default()).unwrap() }; let batch_2 = { let tx = MockProvenTxBuilder::with_account_index(1).nullifiers_range(1..2).build(); - TransactionBatch::new([&tx], Default::default()).unwrap() + TransactionBatch::new([&tx], NoteAuthenticationInfo::default()).unwrap() }; vec![batch_1, batch_2] @@ -702,12 +708,12 @@ fn block_witness_validation_inconsistent_nullifiers() { Nullifier::from([101_u32.into(), 102_u32.into(), 103_u32.into(), 104_u32.into()]); let block_inputs_from_store: BlockInputs = { - let block_header = BlockHeader::mock(0, None, None, &[], Default::default()); + let block_header = BlockHeader::mock(0, None, None, &[], Digest::default()); let chain_peaks = MmrPeaks::new(0, Vec::new()).unwrap(); let accounts = batches .iter() - .flat_map(|batch| batch.account_initial_states()) + .flat_map(TransactionBatch::account_initial_states) .map(|(account_id, hash)| { (account_id, AccountWitness { hash, proof: MerklePath::default() }) }) @@ -741,7 +747,7 @@ fn block_witness_validation_inconsistent_nullifiers() { chain_peaks, accounts, nullifiers, - found_unauthenticated_notes: Default::default(), + found_unauthenticated_notes: NoteAuthenticationInfo::default(), } }; @@ -763,13 +769,13 @@ async fn compute_nullifier_root_empty_success() { let batch_1 = { let tx = MockProvenTxBuilder::with_account_index(0).build(); - TransactionBatch::new([&tx], Default::default()).unwrap() + TransactionBatch::new([&tx], NoteAuthenticationInfo::default()).unwrap() }; let batch_2 = { let tx = MockProvenTxBuilder::with_account_index(1).build(); - TransactionBatch::new([&tx], Default::default()).unwrap() + TransactionBatch::new([&tx], NoteAuthenticationInfo::default()).unwrap() }; vec![batch_1, batch_2] @@ -777,7 +783,7 @@ async fn compute_nullifier_root_empty_success() { let account_ids: Vec = batches .iter() - .flat_map(|batch| batch.account_initial_states()) + .flat_map(TransactionBatch::account_initial_states) .map(|(account_id, _)| account_id) .collect(); @@ -817,13 +823,13 @@ async fn compute_nullifier_root_success() { let batch_1 = { let tx = MockProvenTxBuilder::with_account_index(0).nullifiers_range(0..1).build(); - TransactionBatch::new([&tx], Default::default()).unwrap() + TransactionBatch::new([&tx], NoteAuthenticationInfo::default()).unwrap() }; let batch_2 = { let tx = MockProvenTxBuilder::with_account_index(1).nullifiers_range(1..2).build(); - TransactionBatch::new([&tx], Default::default()).unwrap() + TransactionBatch::new([&tx], NoteAuthenticationInfo::default()).unwrap() }; vec![batch_1, batch_2] @@ -831,7 +837,7 @@ async fn compute_nullifier_root_success() { let account_ids: Vec = batches .iter() - .flat_map(|batch| batch.account_initial_states()) + .flat_map(TransactionBatch::account_initial_states) .map(|(account_id, _)| account_id) .collect(); diff --git a/crates/block-producer/src/domain/transaction.rs b/crates/block-producer/src/domain/transaction.rs index dccc0a592..84ee563ad 100644 --- a/crates/block-producer/src/domain/transaction.rs +++ b/crates/block-producer/src/domain/transaction.rs @@ -50,7 +50,7 @@ impl AuthenticatedTransaction { ) -> Result { let nullifiers_already_spent = tx .get_nullifiers() - .filter(|nullifier| inputs.nullifiers.get(nullifier).cloned().flatten().is_some()) + .filter(|nullifier| inputs.nullifiers.get(nullifier).copied().flatten().is_some()) .collect::>(); if !nullifiers_already_spent.is_empty() { return Err(VerifyTxError::InputNotesAlreadyConsumed(nullifiers_already_spent)); @@ -89,7 +89,7 @@ impl AuthenticatedTransaction { } pub fn output_notes(&self) -> impl Iterator + '_ { - self.inner.output_notes().iter().map(|note| note.id()) + self.inner.output_notes().iter().map(miden_objects::transaction::OutputNote::id) } pub fn output_note_count(&self) -> usize { @@ -105,7 +105,7 @@ impl AuthenticatedTransaction { pub fn unauthenticated_notes(&self) -> impl Iterator + '_ { self.inner .get_unauthenticated_notes() - .cloned() + .copied() .map(|header| header.id()) .filter(|note_id| !self.notes_authenticated_by_store.contains(note_id)) } @@ -134,8 +134,8 @@ impl AuthenticatedTransaction { account_id: inner.account_id(), account_hash: store_account_state, nullifiers: inner.get_nullifiers().map(|nullifier| (nullifier, None)).collect(), - found_unauthenticated_notes: Default::default(), - current_block_height: Default::default(), + found_unauthenticated_notes: BTreeSet::default(), + current_block_height: 0, }; // SAFETY: nullifiers were set to None aka are definitely unspent. Self::new(inner, inputs).unwrap() diff --git a/crates/block-producer/src/errors.rs b/crates/block-producer/src/errors.rs index 2dd8a4028..9e30d2e9c 100644 --- a/crates/block-producer/src/errors.rs +++ b/crates/block-producer/src/errors.rs @@ -102,20 +102,22 @@ pub enum AddTransactionError { impl From for tonic::Status { fn from(value: AddTransactionError) -> Self { - use AddTransactionError::*; match value { - VerificationFailed(VerifyTxError::InputNotesAlreadyConsumed(_)) - | VerificationFailed(VerifyTxError::UnauthenticatedNotesNotFound(_)) - | VerificationFailed(VerifyTxError::OutputNotesAlreadyExist(_)) - | VerificationFailed(VerifyTxError::IncorrectAccountInitialHash { .. }) - | VerificationFailed(VerifyTxError::InvalidTransactionProof(_)) - | Expired { .. } - | TransactionDeserializationFailed(_) => Self::invalid_argument(value.to_string()), + AddTransactionError::VerificationFailed( + VerifyTxError::InputNotesAlreadyConsumed(_) + | VerifyTxError::UnauthenticatedNotesNotFound(_) + | VerifyTxError::OutputNotesAlreadyExist(_) + | VerifyTxError::IncorrectAccountInitialHash { .. } + | VerifyTxError::InvalidTransactionProof(_), + ) + | AddTransactionError::Expired { .. } + | AddTransactionError::TransactionDeserializationFailed(_) => { + Self::invalid_argument(value.to_string()) + }, // Internal errors which should not be communicated to the user. - VerificationFailed(VerifyTxError::StoreConnectionFailed(_)) | StaleInputs { .. } => { - Self::internal("Internal error") - }, + AddTransactionError::VerificationFailed(VerifyTxError::StoreConnectionFailed(_)) + | AddTransactionError::StaleInputs { .. } => Self::internal("Internal error"), } } } @@ -207,7 +209,7 @@ pub enum BuildBlockError { // Store errors // ================================================================================================= -/// Errors returned by the [StoreClient](crate::store::StoreClient). +/// Errors returned by the [`StoreClient`](crate::store::StoreClient). #[derive(Debug, Error)] pub enum StoreError { #[error("gRPC client error")] diff --git a/crates/block-producer/src/mempool/batch_graph.rs b/crates/block-producer/src/mempool/batch_graph.rs index ef7822150..73948f46e 100644 --- a/crates/block-producer/src/mempool/batch_graph.rs +++ b/crates/block-producer/src/mempool/batch_graph.rs @@ -111,9 +111,9 @@ impl BatchGraph { // Reverse lookup parent batch IDs. Take care to allow for parent transactions within this // batch i.e. internal dependencies. - transactions.iter().for_each(|tx| { + for tx in &transactions { parents.remove(tx); - }); + } let parent_batches = parents .into_iter() .map(|tx| { @@ -175,7 +175,7 @@ impl BatchGraph { /// /// Returns all removed batches and their transactions. /// - /// Unlike [remove_batches](Self::remove_batches), this has no error condition as batches are + /// Unlike [`remove_batches`](Self::remove_batches), this has no error condition as batches are /// derived internally. pub fn remove_batches_with_transactions<'a>( &mut self, @@ -207,14 +207,14 @@ impl BatchGraph { /// The last point implies that batches should be removed in block order. pub fn prune_committed( &mut self, - batch_ids: BTreeSet, + batch_ids: &BTreeSet, ) -> Result, GraphError> { // This clone could be elided by moving this call to the end. This would lose the atomic // property of this method though its unclear what value (if any) that has. self.inner.prune_processed(batch_ids.clone())?; let mut transactions = Vec::new(); - for batch_id in &batch_ids { + for batch_id in batch_ids { transactions.extend(self.batches.remove(batch_id).into_iter().flatten()); } @@ -294,8 +294,8 @@ mod tests { let mut uut = BatchGraph::default(); - uut.insert(vec![tx_dup], Default::default()).unwrap(); - let err = uut.insert(vec![tx_dup, tx_non_dup], Default::default()).unwrap_err(); + uut.insert(vec![tx_dup], BTreeSet::default()).unwrap(); + let err = uut.insert(vec![tx_dup, tx_non_dup], BTreeSet::default()).unwrap_err(); let expected = BatchInsertError::DuplicateTransactions([tx_dup].into()); assert_eq!(err, expected); @@ -339,10 +339,10 @@ mod tests { let disjoint_batch_txs = (0..5).map(|_| rng.draw_tx_id()).collect(); let mut uut = BatchGraph::default(); - let parent_batch_id = uut.insert(parent_batch_txs.clone(), Default::default()).unwrap(); + let parent_batch_id = uut.insert(parent_batch_txs.clone(), BTreeSet::default()).unwrap(); let child_batch_id = uut.insert(child_batch_txs.clone(), [parent_batch_txs[0]].into()).unwrap(); - uut.insert(disjoint_batch_txs, Default::default()).unwrap(); + uut.insert(disjoint_batch_txs, BTreeSet::default()).unwrap(); let result = uut.remove_batches([parent_batch_id].into()).unwrap(); let expected = diff --git a/crates/block-producer/src/mempool/graph/mod.rs b/crates/block-producer/src/mempool/graph/mod.rs index 5b0921d49..55442deed 100644 --- a/crates/block-producer/src/mempool/graph/mod.rs +++ b/crates/block-producer/src/mempool/graph/mod.rs @@ -108,12 +108,12 @@ pub enum GraphError { impl Default for DependencyGraph { fn default() -> Self { Self { - vertices: Default::default(), - pending: Default::default(), - parents: Default::default(), - children: Default::default(), - roots: Default::default(), - processed: Default::default(), + vertices: BTreeMap::default(), + pending: BTreeSet::default(), + parents: BTreeMap::default(), + children: BTreeMap::default(), + roots: BTreeSet::default(), + processed: BTreeSet::default(), } } } @@ -146,7 +146,7 @@ impl DependencyGraph { } self.pending.insert(key); self.parents.insert(key, parents); - self.children.insert(key, Default::default()); + self.children.insert(key, BTreeSet::default()); Ok(()) } @@ -260,7 +260,7 @@ impl DependencyGraph { // No parent may be left dangling i.e. all parents must be part of this prune set. let dangling = keys .iter() - .flat_map(|key| self.parents.get(key)) + .filter_map(|key| self.parents.get(key)) .flatten() .filter(|parent| !keys.contains(parent)) .copied() diff --git a/crates/block-producer/src/mempool/graph/tests.rs b/crates/block-producer/src/mempool/graph/tests.rs index acee736f2..af8acdc18 100644 --- a/crates/block-producer/src/mempool/graph/tests.rs +++ b/crates/block-producer/src/mempool/graph/tests.rs @@ -10,7 +10,7 @@ type TestGraph = DependencyGraph; impl TestGraph { /// Alias for inserting a node with no parents. fn insert_with_no_parents(&mut self, node: u32) -> Result<(), GraphError> { - self.insert_with_parents(node, Default::default()) + self.insert_with_parents(node, BTreeSet::default()) } /// Alias for inserting a node with a single parent. @@ -41,7 +41,7 @@ impl TestGraph { self.promote(self.pending.clone()).unwrap(); } - /// Calls process_root until all nodes have been processed. + /// Calls `process_root` until all nodes have been processed. fn process_all(&mut self) { while let Some(root) = self.roots().first().copied() { // SAFETY: this is definitely a root since we just took it from there :) diff --git a/crates/block-producer/src/mempool/inflight_state/account_state.rs b/crates/block-producer/src/mempool/inflight_state/account_state.rs index dc79a339a..560241185 100644 --- a/crates/block-producer/src/mempool/inflight_state/account_state.rs +++ b/crates/block-producer/src/mempool/inflight_state/account_state.rs @@ -99,7 +99,7 @@ impl InflightAccountState { self.emptiness() } - /// This is essentially `is_empty` with the additional benefit that [AccountStatus] is marked + /// This is essentially `is_empty` with the additional benefit that [`AccountStatus`] is marked /// as `#[must_use]`, forcing callers to handle empty accounts (which should be pruned). fn emptiness(&self) -> AccountStatus { if self.states.is_empty() { @@ -115,21 +115,21 @@ impl InflightAccountState { } } -/// Describes the emptiness of an [InflightAccountState]. +/// Describes the emptiness of an [`InflightAccountState`]. /// /// Is marked as `#[must_use]` so that callers handle prune empty accounts. #[must_use] #[derive(Clone, Copy, PartialEq, Eq)] pub enum AccountStatus { - /// [InflightAccountState] contains no state and should be pruned. + /// [`InflightAccountState`] contains no state and should be pruned. Empty, - /// [InflightAccountState] contains state and should be kept. + /// [`InflightAccountState`] contains state and should be kept. NonEmpty, } impl AccountStatus { - pub fn is_empty(&self) -> bool { - *self == Self::Empty + pub fn is_empty(self) -> bool { + self == Self::Empty } } @@ -221,9 +221,9 @@ mod tests { #[test] fn reverted_txs_are_nonextant() { - let mut rng = Random::with_random_seed(); const N: usize = 5; const REVERT: usize = 2; + let mut rng = Random::with_random_seed(); let states = (0..N).map(|_| (rng.draw_digest(), rng.draw_tx_id())).collect::>(); @@ -243,9 +243,9 @@ mod tests { #[test] fn pruned_txs_are_nonextant() { - let mut rng = Random::with_random_seed(); const N: usize = 5; const PRUNE: usize = 2; + let mut rng = Random::with_random_seed(); let states = (0..N).map(|_| (rng.draw_digest(), rng.draw_tx_id())).collect::>(); @@ -266,8 +266,8 @@ mod tests { #[test] fn is_empty_after_full_commit_and_prune() { - let mut rng = Random::with_random_seed(); const N: usize = 5; + let mut rng = Random::with_random_seed(); let mut uut = InflightAccountState::default(); for _ in 0..N { uut.insert(rng.draw_digest(), rng.draw_tx_id()); @@ -276,7 +276,7 @@ mod tests { uut.commit(N); let _ = uut.prune_committed(N); - assert_eq!(uut, Default::default()); + assert_eq!(uut, InflightAccountState::default()); } #[test] @@ -290,14 +290,14 @@ mod tests { let _ = uut.revert(N); - assert_eq!(uut, Default::default()); + assert_eq!(uut, InflightAccountState::default()); } #[test] #[should_panic] fn revert_panics_on_out_of_bounds() { - let mut rng = Random::with_random_seed(); const N: usize = 5; + let mut rng = Random::with_random_seed(); let mut uut = InflightAccountState::default(); for _ in 0..N { uut.insert(rng.draw_digest(), rng.draw_tx_id()); @@ -310,8 +310,8 @@ mod tests { #[test] #[should_panic] fn commit_panics_on_out_of_bounds() { - let mut rng = Random::with_random_seed(); const N: usize = 5; + let mut rng = Random::with_random_seed(); let mut uut = InflightAccountState::default(); for _ in 0..N { uut.insert(rng.draw_digest(), rng.draw_tx_id()); diff --git a/crates/block-producer/src/mempool/inflight_state/mod.rs b/crates/block-producer/src/mempool/inflight_state/mod.rs index a68d4283b..865bac2cb 100644 --- a/crates/block-producer/src/mempool/inflight_state/mod.rs +++ b/crates/block-producer/src/mempool/inflight_state/mod.rs @@ -87,7 +87,7 @@ impl Delta { } impl InflightState { - /// Creates an [InflightState] which will retain committed state for the given + /// Creates an [`InflightState`] which will retain committed state for the given /// amount of blocks before pruning them. pub fn new( chain_tip: BlockNumber, @@ -98,11 +98,11 @@ impl InflightState { num_retained_blocks, chain_tip, expiration_slack, - accounts: Default::default(), - nullifiers: Default::default(), - output_notes: Default::default(), - transaction_deltas: Default::default(), - committed_blocks: Default::default(), + accounts: BTreeMap::default(), + nullifiers: BTreeSet::default(), + output_notes: BTreeMap::default(), + transaction_deltas: BTreeMap::default(), + committed_blocks: VecDeque::default(), } } @@ -283,7 +283,7 @@ impl InflightState { /// Panics if any transactions is not part of the uncommitted state. pub fn commit_block(&mut self, txs: impl IntoIterator) { let mut block_deltas = BTreeMap::new(); - for tx in txs.into_iter() { + for tx in txs { let delta = self.transaction_deltas.remove(&tx).expect("Transaction delta must exist"); // SAFETY: Since the delta exists, so must the account. diff --git a/crates/block-producer/src/mempool/mod.rs b/crates/block-producer/src/mempool/mod.rs index b16efcd31..22873c3fc 100644 --- a/crates/block-producer/src/mempool/mod.rs +++ b/crates/block-producer/src/mempool/mod.rs @@ -50,14 +50,13 @@ impl BlockNumber { Self(x) } - pub fn next(&self) -> Self { - let mut ret = *self; - ret.increment(); + pub fn next(mut self) -> Self { + self.increment(); - ret + self } - pub fn prev(&self) -> Option { + pub fn prev(self) -> Option { self.checked_sub(Self(1)) } @@ -65,7 +64,7 @@ impl BlockNumber { self.0 += 1; } - pub fn checked_sub(&self, rhs: Self) -> Option { + pub fn checked_sub(self, rhs: Self) -> Option { self.0.checked_sub(rhs.0).map(Self) } @@ -125,14 +124,14 @@ impl Default for BlockBudget { impl BatchBudget { /// Attempts to consume the transaction's resources from the budget. /// - /// Returns [BudgetStatus::Exceeded] if the transaction would exceed the remaining budget, - /// otherwise returns [BudgetStatus::Ok] and subtracts the resources from the budger. + /// Returns [`BudgetStatus::Exceeded`] if the transaction would exceed the remaining budget, + /// otherwise returns [`BudgetStatus::Ok`] and subtracts the resources from the budger. #[must_use] fn check_then_subtract(&mut self, tx: &AuthenticatedTransaction) -> BudgetStatus { // This type assertion reminds us to update the account check if we ever support multiple // account updates per tx. - let _: miden_objects::accounts::AccountId = tx.account_update().account_id(); const ACCOUNT_UPDATES_PER_TX: usize = 1; + let _: miden_objects::accounts::AccountId = tx.account_update().account_id(); let output_notes = tx.output_note_count(); let input_notes = tx.input_note_count(); @@ -157,8 +156,8 @@ impl BatchBudget { impl BlockBudget { /// Attempts to consume the batch's resources from the budget. /// - /// Returns [BudgetStatus::Exceeded] if the batch would exceed the remaining budget, - /// otherwise returns [BudgetStatus::Ok]. + /// Returns [`BudgetStatus::Exceeded`] if the batch would exceed the remaining budget, + /// otherwise returns [`BudgetStatus::Ok`]. #[must_use] fn check_then_subtract(&mut self, _batch: &TransactionBatch) -> BudgetStatus { if self.batches == 0 { @@ -206,7 +205,7 @@ pub struct Mempool { } impl Mempool { - /// Creates a new [SharedMempool] with the provided configuration. + /// Creates a new [`SharedMempool`] with the provided configuration. pub fn shared( chain_tip: BlockNumber, batch_budget: BatchBudget, @@ -235,10 +234,10 @@ impl Mempool { batch_budget, block_budget, state: InflightState::new(chain_tip, state_retention, expiration_slack), - block_in_progress: Default::default(), - transactions: Default::default(), - batches: Default::default(), - expirations: Default::default(), + block_in_progress: None, + transactions: TransactionGraph::default(), + batches: BatchGraph::default(), + expirations: TransactionExpirations::default(), } } @@ -353,7 +352,8 @@ impl Mempool { // Remove committed batches and transactions from graphs. let batches = self.block_in_progress.take().expect("No block in progress to commit"); - let transactions = self.batches.prune_committed(batches).expect("Batches failed to commit"); + let transactions = + self.batches.prune_committed(&batches).expect("Batches failed to commit"); self.transactions .commit_transactions(&transactions) .expect("Transaction graph malformed"); diff --git a/crates/block-producer/src/mempool/tests.rs b/crates/block-producer/src/mempool/tests.rs index 2646706a3..6a4ad8b91 100644 --- a/crates/block-producer/src/mempool/tests.rs +++ b/crates/block-producer/src/mempool/tests.rs @@ -1,3 +1,4 @@ +use miden_node_proto::domain::notes::NoteAuthenticationInfo; use pretty_assertions::assert_eq; use super::*; @@ -7,10 +8,10 @@ impl Mempool { fn for_tests() -> Self { Self::new( BlockNumber::new(0), - Default::default(), - Default::default(), + BatchBudget::default(), + BlockBudget::default(), 5, - Default::default(), + BlockNumber::default(), ) } } @@ -47,7 +48,8 @@ fn children_of_failed_batches_are_ignored() { assert_eq!(uut, reference); let proof = - TransactionBatch::new([txs[2].raw_proven_transaction()], Default::default()).unwrap(); + TransactionBatch::new([txs[2].raw_proven_transaction()], NoteAuthenticationInfo::default()) + .unwrap(); uut.batch_proved(proof); assert_eq!(uut, reference); } @@ -93,7 +95,11 @@ fn block_commit_reverts_expired_txns() { uut.add_transaction(tx_to_commit.clone()).unwrap(); uut.select_batch().unwrap(); uut.batch_proved( - TransactionBatch::new([tx_to_commit.raw_proven_transaction()], Default::default()).unwrap(), + TransactionBatch::new( + [tx_to_commit.raw_proven_transaction()], + NoteAuthenticationInfo::default(), + ) + .unwrap(), ); let (block, _) = uut.select_block(); // A reverted transaction behaves as if it never existed, the current state is the expected @@ -163,8 +169,11 @@ fn block_failure_reverts_its_transactions() { uut.add_transaction(reverted_txs[0].clone()).unwrap(); uut.select_batch().unwrap(); uut.batch_proved( - TransactionBatch::new([reverted_txs[0].raw_proven_transaction()], Default::default()) - .unwrap(), + TransactionBatch::new( + [reverted_txs[0].raw_proven_transaction()], + NoteAuthenticationInfo::default(), + ) + .unwrap(), ); // Block 1 will contain just the first batch. diff --git a/crates/block-producer/src/mempool/transaction_expiration.rs b/crates/block-producer/src/mempool/transaction_expiration.rs index 103e665f5..79dc450aa 100644 --- a/crates/block-producer/src/mempool/transaction_expiration.rs +++ b/crates/block-producer/src/mempool/transaction_expiration.rs @@ -65,7 +65,7 @@ mod tests { uut.insert(tx, block); uut.remove(std::iter::once(&tx)); - assert_eq!(uut, Default::default()); + assert_eq!(uut, TransactionExpirations::default()); } #[test] diff --git a/crates/block-producer/src/mempool/transaction_graph.rs b/crates/block-producer/src/mempool/transaction_graph.rs index 5709bfdeb..ab1eb43bf 100644 --- a/crates/block-producer/src/mempool/transaction_graph.rs +++ b/crates/block-producer/src/mempool/transaction_graph.rs @@ -53,7 +53,7 @@ impl TransactionGraph { /// /// # Errors /// - /// Follows the error conditions of [DependencyGraph::insert_pending]. + /// Follows the error conditions of [`DependencyGraph::insert_pending`]. pub fn insert( &mut self, transaction: AuthenticatedTransaction, @@ -73,8 +73,8 @@ impl TransactionGraph { /// Note: this may emit empty batches. /// /// See also: - /// - [Self::requeue_transactions] - /// - [Self::commit_transactions] + /// - [`Self::requeue_transactions`] + /// - [`Self::commit_transactions`] pub fn select_batch( &mut self, mut budget: BatchBudget, @@ -84,7 +84,7 @@ impl TransactionGraph { let mut batch = Vec::with_capacity(budget.transactions); let mut parents = BTreeSet::new(); - while let Some(root) = self.inner.roots().first().cloned() { + while let Some(root) = self.inner.roots().first().copied() { // SAFETY: Since it was a root batch, it must definitely have a processed batch // associated with it. let tx = self.inner.get(&root).unwrap().clone(); @@ -109,7 +109,7 @@ impl TransactionGraph { /// /// # Errors /// - /// Follows the error conditions of [DependencyGraph::revert_subgraphs]. + /// Follows the error conditions of [`DependencyGraph::revert_subgraphs`]. pub fn requeue_transactions( &mut self, transactions: BTreeSet, @@ -121,13 +121,13 @@ impl TransactionGraph { /// /// # Errors /// - /// Follows the error conditions of [DependencyGraph::prune_processed]. + /// Follows the error conditions of [`DependencyGraph::prune_processed`]. pub fn commit_transactions( &mut self, tx_ids: &[TransactionId], ) -> Result<(), GraphError> { // TODO: revisit this api. - let tx_ids = tx_ids.iter().cloned().collect(); + let tx_ids = tx_ids.iter().copied().collect(); self.inner.prune_processed(tx_ids)?; Ok(()) } @@ -138,7 +138,7 @@ impl TransactionGraph { /// /// # Errors /// - /// Follows the error conditions of [DependencyGraph::purge_subgraphs]. + /// Follows the error conditions of [`DependencyGraph::purge_subgraphs`]. pub fn remove_transactions( &mut self, transactions: Vec, diff --git a/crates/block-producer/src/server.rs b/crates/block-producer/src/server.rs index afd82c9e4..b0b445f2c 100644 --- a/crates/block-producer/src/server.rs +++ b/crates/block-producer/src/server.rs @@ -74,10 +74,10 @@ impl BlockProducer { info!(target: COMPONENT, "Server initialized"); Ok(Self { - batch_builder: Default::default(), + batch_builder: BatchBuilder::default(), block_builder: BlockBuilder::new(store.clone()), - batch_budget: Default::default(), - block_budget: Default::default(), + batch_budget: BatchBudget::default(), + block_budget: BlockBudget::default(), state_retention: SERVER_MEMPOOL_STATE_RETENTION, expiration_slack: SERVER_MEMPOOL_EXPIRATION_SLACK, store, diff --git a/crates/block-producer/src/store/mod.rs b/crates/block-producer/src/store/mod.rs index d5f7b55fe..9b3d50bda 100644 --- a/crates/block-producer/src/store/mod.rs +++ b/crates/block-producer/src/store/mod.rs @@ -11,8 +11,8 @@ use miden_node_proto::{ generated::{ digest, requests::{ - ApplyBlockRequest, GetBlockInputsRequest, GetNoteAuthenticationInfoRequest, - GetTransactionInputsRequest, + ApplyBlockRequest, GetBlockHeaderByNumberRequest, GetBlockInputsRequest, + GetNoteAuthenticationInfoRequest, GetTransactionInputsRequest, }, responses::{GetTransactionInputsResponse, NullifierTransactionInputRecord}, store::api_client as store_client, @@ -46,7 +46,7 @@ pub struct TransactionInputs { pub account_hash: Option, /// Maps each consumed notes' nullifier to block number, where the note is consumed. /// - /// We use NonZeroU32 as the wire format uses 0 to encode none. + /// We use `NonZeroU32` as the wire format uses 0 to encode none. pub nullifiers: BTreeMap>, /// Unauthenticated notes which are present in the store. /// @@ -67,7 +67,7 @@ impl Display for TransactionInputs { let nullifiers = if nullifiers.is_empty() { "None".to_owned() } else { - format!("{{ {} }}", nullifiers) + format!("{{ {nullifiers} }}") }; f.write_fmt(format_args!( @@ -112,8 +112,8 @@ impl TryFrom for TransactionInputs { account_id, account_hash, nullifiers, - current_block_height, found_unauthenticated_notes, + current_block_height, }) } } @@ -141,7 +141,9 @@ impl StoreClient { let response = self .inner .clone() - .get_block_header_by_number(tonic::Request::new(Default::default())) + .get_block_header_by_number(tonic::Request::new( + GetBlockHeaderByNumberRequest::default(), + )) .await? .into_inner() .block_header diff --git a/crates/block-producer/src/test_utils/account.rs b/crates/block-producer/src/test_utils/account.rs index c7511cd0c..fa7877404 100644 --- a/crates/block-producer/src/test_utils/account.rs +++ b/crates/block-producer/src/test_utils/account.rs @@ -82,5 +82,5 @@ impl From for MockPrivateAccount { } pub fn mock_account_id(num: u8) -> AccountId { - MockPrivateAccount::<3>::from(num as u32).id + MockPrivateAccount::<3>::from(u32::from(num)).id } diff --git a/crates/block-producer/src/test_utils/batch.rs b/crates/block-producer/src/test_utils/batch.rs index 53a572b9d..d27eb9e0b 100644 --- a/crates/block-producer/src/test_utils/batch.rs +++ b/crates/block-producer/src/test_utils/batch.rs @@ -1,3 +1,5 @@ +use miden_node_proto::domain::notes::NoteAuthenticationInfo; + use crate::{batch_builder::TransactionBatch, test_utils::MockProvenTxBuilder}; pub trait TransactionBatchConstructor { @@ -15,7 +17,7 @@ impl TransactionBatchConstructor for TransactionBatch { .iter() .enumerate() .map(|(index, &num_notes)| { - let starting_note_index = starting_account_index as u64 + index as u64; + let starting_note_index = u64::from(starting_account_index) + index as u64; MockProvenTxBuilder::with_account_index(starting_account_index + index as u32) .private_notes_created_range( starting_note_index..(starting_note_index + num_notes), @@ -24,7 +26,7 @@ impl TransactionBatchConstructor for TransactionBatch { }) .collect(); - Self::new(&txs, Default::default()).unwrap() + Self::new(&txs, NoteAuthenticationInfo::default()).unwrap() } fn from_txs(starting_account_index: u32, num_txs_in_batch: u64) -> Self { @@ -36,6 +38,6 @@ impl TransactionBatchConstructor for TransactionBatch { }) .collect(); - Self::new(&txs, Default::default()).unwrap() + Self::new(&txs, NoteAuthenticationInfo::default()).unwrap() } } diff --git a/crates/block-producer/src/test_utils/block.rs b/crates/block-producer/src/test_utils/block.rs index d81376caf..54fa67631 100644 --- a/crates/block-producer/src/test_utils/block.rs +++ b/crates/block-producer/src/test_utils/block.rs @@ -126,6 +126,7 @@ impl MockBlockBuilder { } } + #[must_use] pub fn account_updates(mut self, updated_accounts: Vec) -> Self { for update in &updated_accounts { self.store_accounts @@ -137,12 +138,14 @@ impl MockBlockBuilder { self } + #[must_use] pub fn created_notes(mut self, created_notes: Vec) -> Self { self.created_notes = Some(created_notes); self } + #[must_use] pub fn produced_nullifiers(mut self, produced_nullifiers: Vec) -> Self { self.produced_nullifiers = Some(produced_nullifiers); diff --git a/crates/block-producer/src/test_utils/proven_tx.rs b/crates/block-producer/src/test_utils/proven_tx.rs index 271466341..396e0c319 100644 --- a/crates/block-producer/src/test_utils/proven_tx.rs +++ b/crates/block-producer/src/test_utils/proven_tx.rs @@ -67,30 +67,35 @@ impl MockProvenTxBuilder { } } + #[must_use] pub fn unauthenticated_notes(mut self, notes: Vec) -> Self { self.input_notes = Some(notes.into_iter().map(InputNote::unauthenticated).collect()); self } + #[must_use] pub fn nullifiers(mut self, nullifiers: Vec) -> Self { self.nullifiers = Some(nullifiers); self } + #[must_use] pub fn expiration_block_num(mut self, expiration_block_num: u32) -> Self { self.expiration_block_num = expiration_block_num; self } + #[must_use] pub fn output_notes(mut self, notes: Vec) -> Self { self.output_notes = Some(notes); self } + #[must_use] pub fn nullifiers_range(self, range: Range) -> Self { let nullifiers = range .map(|index| { @@ -103,6 +108,7 @@ impl MockProvenTxBuilder { self.nullifiers(nullifiers) } + #[must_use] pub fn private_notes_created_range(self, range: Range) -> Self { let notes = range .map(|note_index| { diff --git a/crates/block-producer/src/test_utils/store.rs b/crates/block-producer/src/test_utils/store.rs index 76bf4f5ed..288494926 100644 --- a/crates/block-producer/src/test_utils/store.rs +++ b/crates/block-producer/src/test_utils/store.rs @@ -73,24 +73,28 @@ impl MockStoreSuccessBuilder { } } + #[must_use] pub fn initial_notes<'a>(mut self, notes: impl Iterator + Clone) -> Self { self.notes = Some(notes.cloned().collect()); self } + #[must_use] pub fn initial_nullifiers(mut self, nullifiers: BTreeSet) -> Self { self.produced_nullifiers = Some(nullifiers); self } + #[must_use] pub fn initial_chain_mmr(mut self, chain_mmr: Mmr) -> Self { self.chain_mmr = Some(chain_mmr); self } + #[must_use] pub fn initial_block_num(mut self, block_num: u32) -> Self { self.block_num = Some(block_num); @@ -152,7 +156,7 @@ impl MockStoreSuccessBuilder { initial_block_header.block_num(), initial_block_header, )]))), - num_apply_block_called: Default::default(), + num_apply_block_called: Arc::default(), notes: Arc::new(RwLock::new(notes)), } } diff --git a/crates/proto/Cargo.toml b/crates/proto/Cargo.toml index de58f3512..445a93a78 100644 --- a/crates/proto/Cargo.toml +++ b/crates/proto/Cargo.toml @@ -11,6 +11,9 @@ authors.workspace = true homepage.workspace = true repository.workspace = true +[lints] +workspace = true + [dependencies] hex = { version = "0.4" } miden-node-utils = { workspace = true } diff --git a/crates/proto/build.rs b/crates/proto/build.rs index b1382f2ca..3ea956b4b 100644 --- a/crates/proto/build.rs +++ b/crates/proto/build.rs @@ -8,8 +8,8 @@ use protox::prost::Message; /// Generates Rust protobuf bindings from .proto files in the root directory. /// -/// This is done only if BUILD_PROTO environment variable is set to `1` to avoid running the script -/// on crates.io where repo-level .proto files are not available. +/// This is done only if `BUILD_PROTO` environment variable is set to `1` to avoid running the +/// script on crates.io where repo-level .proto files are not available. fn main() -> anyhow::Result<()> { println!("cargo::rerun-if-changed=../../proto"); println!("cargo::rerun-if-env-changed=BUILD_PROTO"); @@ -91,9 +91,11 @@ fn generate_mod_rs(directory: impl AsRef) -> std::io::Result<()> { submodules.sort(); let contents = submodules.iter().map(|f| format!("pub mod {f};\n")); - let contents = std::iter::once("// Generated by build.rs\n\n".to_owned()) - .chain(contents) - .collect::(); + let contents = std::iter::once( + "#![allow(clippy::pedantic, reason = \"generated by build.rs and tonic\")]\n\n".to_string(), + ) + .chain(contents) + .collect::(); fs::write(mod_filepath, contents) } diff --git a/crates/proto/src/domain/accounts.rs b/crates/proto/src/domain/accounts.rs index cf358ab04..1283e193a 100644 --- a/crates/proto/src/domain/accounts.rs +++ b/crates/proto/src/domain/accounts.rs @@ -21,7 +21,7 @@ impl Display for proto::account::AccountId { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "0x")?; for byte in &self.id { - write!(f, "{:02x}", byte)?; + write!(f, "{byte:02x}")?; } Ok(()) } @@ -89,7 +89,7 @@ impl From<&AccountInfo> for proto::account::AccountInfo { fn from(AccountInfo { summary, details }: &AccountInfo) -> Self { Self { summary: Some(summary.into()), - details: details.as_ref().map(|account| account.to_bytes()), + details: details.as_ref().map(miden_objects::utils::Serializable::to_bytes), } } } diff --git a/crates/proto/src/domain/digest.rs b/crates/proto/src/domain/digest.rs index 811ee872d..b0bf19fac 100644 --- a/crates/proto/src/domain/digest.rs +++ b/crates/proto/src/domain/digest.rs @@ -159,19 +159,19 @@ impl TryFrom for [Felt; 4] { type Error = ConversionError; fn try_from(value: proto::Digest) -> Result { - if ![value.d0, value.d1, value.d2, value.d3] + if [value.d0, value.d1, value.d2, value.d3] .iter() - .all(|v| *v < ::MODULUS) + .any(|v| *v >= ::MODULUS) { - Err(ConversionError::NotAValidFelt) - } else { - Ok([ - Felt::new(value.d0), - Felt::new(value.d1), - Felt::new(value.d2), - Felt::new(value.d3), - ]) + return Err(ConversionError::NotAValidFelt); } + + Ok([ + Felt::new(value.d0), + Felt::new(value.d1), + Felt::new(value.d2), + Felt::new(value.d3), + ]) } } @@ -212,10 +212,10 @@ mod test { #[test] fn hex_digest() { let digest = proto::Digest { - d0: 3488802789098113751, - d1: 5271242459988994564, - d2: 17816570245237064784, - d3: 10910963388447438895, + d0: 0x306A_B7A6_F795_CAD7, + d1: 0x4927_3716_D099_AA04, + d2: 0xF741_2C3D_E726_4450, + d3: 0x976B_8764_9DB3_B82F, }; let encoded: String = ToHex::encode_hex(&digest); let round_trip: Result = FromHex::from_hex::<&[u8]>(encoded.as_ref()); diff --git a/crates/proto/src/domain/mod.rs b/crates/proto/src/domain/mod.rs index 43da3d479..b3e682664 100644 --- a/crates/proto/src/domain/mod.rs +++ b/crates/proto/src/domain/mod.rs @@ -15,7 +15,7 @@ where From: Into, R: FromIterator, { - from.into_iter().map(|e| e.into()).collect() + from.into_iter().map(Into::into).collect() } pub fn try_convert(from: T) -> Result @@ -24,5 +24,5 @@ where From: TryInto, R: FromIterator, { - from.into_iter().map(|e| e.try_into()).collect() + from.into_iter().map(TryInto::try_into).collect() } diff --git a/crates/proto/src/domain/notes.rs b/crates/proto/src/domain/notes.rs index 4dafb028f..4ea9e8652 100644 --- a/crates/proto/src/domain/notes.rs +++ b/crates/proto/src/domain/notes.rs @@ -21,7 +21,7 @@ impl TryFrom for NoteMetadata { .sender .ok_or_else(|| proto::NoteMetadata::missing_field(stringify!(sender)))? .try_into()?; - let note_type = NoteType::try_from(value.note_type as u64)?; + let note_type = NoteType::try_from(u64::from(value.note_type))?; let tag = NoteTag::from(value.tag); let execution_hint = NoteExecutionHint::try_from(value.execution_hint)?; diff --git a/crates/proto/src/generated/account.rs b/crates/proto/src/generated/account.rs index 85760632c..a2683eb0d 100644 --- a/crates/proto/src/generated/account.rs +++ b/crates/proto/src/generated/account.rs @@ -1,28 +1,41 @@ // This file is @generated by prost-build. +/// Uniquely identifies a specific account. +/// +/// A Miden account ID is a 120-bit value derived from the commitments to account code and storage, +/// and a random user-provided seed. #[derive(Clone, PartialEq, ::prost::Message)] #[prost(skip_debug)] pub struct AccountId { - /// A Miden account ID is a 120-bit value derived from the commitments to account code and - /// storage, and a random user-provided seed. + /// 15 bytes (120 bits) encoded using \[winter_utils::Serializable\] implementation for + /// \[miden_objects::accounts::account_id::AccountId\]. #[prost(bytes = "vec", tag = "1")] pub id: ::prost::alloc::vec::Vec, } +/// The state of an account at a specific block height. #[derive(Clone, PartialEq, ::prost::Message)] pub struct AccountSummary { + /// The account ID. #[prost(message, optional, tag = "1")] pub account_id: ::core::option::Option, + /// The current account hash or zero if the account does not exist. #[prost(message, optional, tag = "2")] pub account_hash: ::core::option::Option, + /// Block number at which the summary was made. #[prost(uint32, tag = "3")] pub block_num: u32, } +/// An account info. #[derive(Clone, PartialEq, ::prost::Message)] pub struct AccountInfo { + /// Account summary. #[prost(message, optional, tag = "1")] pub summary: ::core::option::Option, + /// Account details encoded using \[winter_utils::Serializable\] implementation for + /// \[miden_objects::accounts::Account\]. #[prost(bytes = "vec", optional, tag = "2")] pub details: ::core::option::Option<::prost::alloc::vec::Vec>, } +/// An account header. #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct AccountHeader { /// Vault root hash. diff --git a/crates/proto/src/generated/block.rs b/crates/proto/src/generated/block.rs index 2c0898b1f..915dce7ec 100644 --- a/crates/proto/src/generated/block.rs +++ b/crates/proto/src/generated/block.rs @@ -1,44 +1,48 @@ // This file is @generated by prost-build. +/// Represents a block header. #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct BlockHeader { - /// specifies the version of the protocol. + /// Specifies the version of the protocol. #[prost(uint32, tag = "1")] pub version: u32, - /// the hash of the previous blocks header. + /// The hash of the previous blocks header. #[prost(message, optional, tag = "2")] pub prev_hash: ::core::option::Option, - /// a unique sequential number of the current block. + /// A unique sequential number of the current block. #[prost(fixed32, tag = "3")] pub block_num: u32, - /// a commitment to an MMR of the entire chain where each block is a leaf. + /// A commitment to an MMR of the entire chain where each block is a leaf. #[prost(message, optional, tag = "4")] pub chain_root: ::core::option::Option, - /// a commitment to account database. + /// A commitment to account database. #[prost(message, optional, tag = "5")] pub account_root: ::core::option::Option, - /// a commitment to the nullifier database. + /// A commitment to the nullifier database. #[prost(message, optional, tag = "6")] pub nullifier_root: ::core::option::Option, - /// a commitment to all notes created in the current block. + /// A commitment to all notes created in the current block. #[prost(message, optional, tag = "7")] pub note_root: ::core::option::Option, - /// a commitment to a set of IDs of transactions which affected accounts in this block. + /// A commitment to a set of IDs of transactions which affected accounts in this block. #[prost(message, optional, tag = "8")] pub tx_hash: ::core::option::Option, - /// a hash of a STARK proof attesting to the correct state transition. + /// A hash of a STARK proof attesting to the correct state transition. #[prost(message, optional, tag = "9")] pub proof_hash: ::core::option::Option, - /// a commitment to all transaction kernels supported by this block. + /// A commitment to all transaction kernels supported by this block. #[prost(message, optional, tag = "10")] pub kernel_root: ::core::option::Option, - /// the time when the block was created. + /// The time when the block was created. #[prost(fixed32, tag = "11")] pub timestamp: u32, } +/// Represents a block inclusion proof. #[derive(Clone, PartialEq, ::prost::Message)] pub struct BlockInclusionProof { + /// Block header associated with the inclusion proof. #[prost(message, optional, tag = "1")] pub block_header: ::core::option::Option, + /// Merkle path associated with the inclusion proof. #[prost(message, optional, tag = "2")] pub mmr_path: ::core::option::Option, /// The chain length associated with `mmr_path`. diff --git a/crates/proto/src/generated/block_producer.rs b/crates/proto/src/generated/block_producer.rs index fefbd4351..c4e6ce35d 100644 --- a/crates/proto/src/generated/block_producer.rs +++ b/crates/proto/src/generated/block_producer.rs @@ -90,6 +90,7 @@ pub mod api_client { self.inner = self.inner.max_encoding_message_size(limit); self } + /// Submits proven transaction to the Miden network pub async fn submit_proven_transaction( &mut self, request: impl tonic::IntoRequest< @@ -133,6 +134,7 @@ pub mod api_server { /// Generated trait containing gRPC methods that should be implemented for use with ApiServer. #[async_trait] pub trait Api: std::marker::Send + std::marker::Sync + 'static { + /// Submits proven transaction to the Miden network async fn submit_proven_transaction( &self, request: tonic::Request< diff --git a/crates/proto/src/generated/merkle.rs b/crates/proto/src/generated/merkle.rs index 0aed4fbdc..e5c4a657a 100644 --- a/crates/proto/src/generated/merkle.rs +++ b/crates/proto/src/generated/merkle.rs @@ -1,6 +1,8 @@ // This file is @generated by prost-build. +/// Represents a Merkle path. #[derive(Clone, PartialEq, ::prost::Message)] pub struct MerklePath { + /// List of sibling node hashes, in order from the root to the leaf. #[prost(message, repeated, tag = "1")] pub siblings: ::prost::alloc::vec::Vec, } diff --git a/crates/proto/src/generated/mmr.rs b/crates/proto/src/generated/mmr.rs index f53ebe2d3..ca5591f71 100644 --- a/crates/proto/src/generated/mmr.rs +++ b/crates/proto/src/generated/mmr.rs @@ -1,8 +1,11 @@ // This file is @generated by prost-build. +/// Represents an MMR delta. #[derive(Clone, PartialEq, ::prost::Message)] pub struct MmrDelta { + /// The number of leaf nodes in the MMR. #[prost(uint64, tag = "1")] pub forest: u64, + /// New and changed MMR peaks. #[prost(message, repeated, tag = "2")] pub data: ::prost::alloc::vec::Vec, } diff --git a/crates/proto/src/generated/mod.rs b/crates/proto/src/generated/mod.rs index 13d511099..dc7675d92 100644 --- a/crates/proto/src/generated/mod.rs +++ b/crates/proto/src/generated/mod.rs @@ -1,4 +1,4 @@ -// Generated by build.rs +#![allow(clippy::pedantic, reason = "generated by build.rs and tonic")] pub mod account; pub mod block; diff --git a/crates/proto/src/generated/note.rs b/crates/proto/src/generated/note.rs index 3768961d0..b64565915 100644 --- a/crates/proto/src/generated/note.rs +++ b/crates/proto/src/generated/note.rs @@ -1,56 +1,84 @@ // This file is @generated by prost-build. +/// Represents a note's metadata. #[derive(Clone, PartialEq, ::prost::Message)] pub struct NoteMetadata { + /// The account which sent the note. #[prost(message, optional, tag = "1")] pub sender: ::core::option::Option, + /// The type of the note (0b01 = public, 0b10 = private, 0b11 = encrypted). #[prost(uint32, tag = "2")] pub note_type: u32, + /// A value which can be used by the recipient(s) to identify notes intended for them. + /// + /// See `miden_objects::notes::note_tag` for more info. #[prost(fixed32, tag = "3")] pub tag: u32, + /// Specifies when a note is ready to be consumed. + /// + /// See `miden_objects::notes::execution_hint` for more info. #[prost(fixed64, tag = "4")] pub execution_hint: u64, + /// An arbitrary user-defined value. #[prost(fixed64, tag = "5")] pub aux: u64, } +/// Represents a note. #[derive(Clone, PartialEq, ::prost::Message)] pub struct Note { + /// The block number in which the note was created. #[prost(fixed32, tag = "1")] pub block_num: u32, + /// The index of the note in the block. #[prost(uint32, tag = "2")] pub note_index: u32, + /// The ID of the note. #[prost(message, optional, tag = "3")] pub note_id: ::core::option::Option, + /// The note's metadata. #[prost(message, optional, tag = "4")] pub metadata: ::core::option::Option, + /// The note's inclusion proof in the block. #[prost(message, optional, tag = "5")] pub merkle_path: ::core::option::Option, - /// This field will be present when the note is public. - /// details contain the `Note` in a serialized format. + /// Serialized details of the public note (empty for private notes). #[prost(bytes = "vec", optional, tag = "6")] pub details: ::core::option::Option<::prost::alloc::vec::Vec>, } +/// Represents a proof of note's inclusion in a block. +/// +/// Does not include proof of the block's inclusion in the chain. #[derive(Clone, PartialEq, ::prost::Message)] pub struct NoteInclusionInBlockProof { + /// A unique identifier of the note which is a 32-byte commitment to the underlying note data. #[prost(message, optional, tag = "1")] pub note_id: ::core::option::Option, + /// The block number in which the note was created. #[prost(fixed32, tag = "2")] pub block_num: u32, + /// The index of the note in the block. #[prost(uint32, tag = "3")] pub note_index_in_block: u32, + /// The note's inclusion proof in the block. #[prost(message, optional, tag = "4")] pub merkle_path: ::core::option::Option, } +/// Represents proof of a note inclusion in the block. #[derive(Clone, PartialEq, ::prost::Message)] pub struct NoteSyncRecord { + /// The index of the note. #[prost(uint32, tag = "1")] pub note_index: u32, + /// A unique identifier of the note which is a 32-byte commitment to the underlying note data. #[prost(message, optional, tag = "2")] pub note_id: ::core::option::Option, + /// The note's metadata. #[prost(message, optional, tag = "3")] pub metadata: ::core::option::Option, + /// The note's inclusion proof in the block. #[prost(message, optional, tag = "4")] pub merkle_path: ::core::option::Option, } +/// Represents proof of notes inclusion in the block(s) and block(s) inclusion in the chain. #[derive(Clone, PartialEq, ::prost::Message)] pub struct NoteAuthenticationInfo { /// Proof of each note's inclusion in a block. diff --git a/crates/proto/src/generated/requests.rs b/crates/proto/src/generated/requests.rs index b28e0e3cf..6cdccab33 100644 --- a/crates/proto/src/generated/requests.rs +++ b/crates/proto/src/generated/requests.rs @@ -1,6 +1,9 @@ // This file is @generated by prost-build. +/// Applies changes of a new block to the DB and in-memory data structures. #[derive(Clone, PartialEq, ::prost::Message)] pub struct ApplyBlockRequest { + /// Block data encoded using \[winter_utils::Serializable\] implementation for + /// \[miden_objects::block::Block\]. #[prost(bytes = "vec", tag = "1")] pub block: ::prost::alloc::vec::Vec, } @@ -11,12 +14,14 @@ pub struct CheckNullifiersByPrefixRequest { #[prost(uint32, tag = "1")] pub prefix_len: u32, /// List of nullifiers to check. Each nullifier is specified by its prefix with length equal - /// to prefix_len + /// to `prefix_len`. #[prost(uint32, repeated, tag = "2")] pub nullifiers: ::prost::alloc::vec::Vec, } +/// Get a list of proofs for given nullifier hashes, each proof as a sparse Merkle Tree. #[derive(Clone, PartialEq, ::prost::Message)] pub struct CheckNullifiersRequest { + /// List of nullifiers to return proofs for. #[prost(message, repeated, tag = "1")] pub nullifiers: ::prost::alloc::vec::Vec, } @@ -26,9 +31,7 @@ pub struct CheckNullifiersRequest { /// The Merkle path is an MMR proof for the block's leaf, based on the current chain length. #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct GetBlockHeaderByNumberRequest { - /// The block number of the target block. - /// - /// If not provided, means latest known block. + /// The target block height, defaults to latest if not provided. #[prost(uint32, optional, tag = "1")] pub block_num: ::core::option::Option, /// Whether or not to return authentication data for the block header. @@ -76,42 +79,54 @@ pub struct SyncNoteRequest { #[prost(fixed32, repeated, tag = "2")] pub note_tags: ::prost::alloc::vec::Vec, } +/// Returns data required to prove the next block. #[derive(Clone, PartialEq, ::prost::Message)] pub struct GetBlockInputsRequest { /// ID of the account against which a transaction is executed. #[prost(message, repeated, tag = "1")] pub account_ids: ::prost::alloc::vec::Vec, - /// Array of nullifiers for all notes consumed by a transaction. + /// Set of nullifiers consumed by this transaction. #[prost(message, repeated, tag = "2")] pub nullifiers: ::prost::alloc::vec::Vec, /// Array of note IDs to be checked for existence in the database. #[prost(message, repeated, tag = "3")] pub unauthenticated_notes: ::prost::alloc::vec::Vec, } +/// Returns data required to validate a new transaction. #[derive(Clone, PartialEq, ::prost::Message)] pub struct GetTransactionInputsRequest { + /// ID of the account against which a transaction is executed. #[prost(message, optional, tag = "1")] pub account_id: ::core::option::Option, + /// Set of nullifiers consumed by this transaction. #[prost(message, repeated, tag = "2")] pub nullifiers: ::prost::alloc::vec::Vec, + /// Set of unauthenticated notes to check for existence on-chain. + /// + /// These are notes which were not on-chain at the state the transaction was proven, + /// but could by now be present. #[prost(message, repeated, tag = "3")] pub unauthenticated_notes: ::prost::alloc::vec::Vec, } +/// Submits proven transaction to the Miden network. #[derive(Clone, PartialEq, ::prost::Message)] pub struct SubmitProvenTransactionRequest { - /// Transaction encoded using miden's native format + /// Transaction encoded using \[winter_utils::Serializable\] implementation for + /// \[miden_objects::transaction::proven_tx::ProvenTransaction\]. #[prost(bytes = "vec", tag = "1")] pub transaction: ::prost::alloc::vec::Vec, } +/// Returns a list of notes matching the provided note IDs. #[derive(Clone, PartialEq, ::prost::Message)] pub struct GetNotesByIdRequest { - /// List of NoteId's to be queried from the database + /// List of notes to be queried from the database. #[prost(message, repeated, tag = "1")] pub note_ids: ::prost::alloc::vec::Vec, } +/// Returns a list of Note inclusion proofs for the specified Note IDs. #[derive(Clone, PartialEq, ::prost::Message)] pub struct GetNoteAuthenticationInfoRequest { - /// List of NoteId's to be queried from the database + /// List of notes to be queried from the database. #[prost(message, repeated, tag = "1")] pub note_ids: ::prost::alloc::vec::Vec, } @@ -122,6 +137,7 @@ pub struct GetAccountDetailsRequest { #[prost(message, optional, tag = "1")] pub account_id: ::core::option::Option, } +/// Retrieves block data by given block number. #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct GetBlockByNumberRequest { /// The block number of the target block. @@ -142,7 +158,7 @@ pub struct GetAccountStateDeltaRequest { #[prost(fixed32, tag = "3")] pub to_block_num: u32, } -/// Request message to get account proofs. +/// Returns the latest state proofs of the specified accounts. #[derive(Clone, PartialEq, ::prost::Message)] pub struct GetAccountProofsRequest { /// A list of account requests, including map keys + values. diff --git a/crates/proto/src/generated/responses.rs b/crates/proto/src/generated/responses.rs index 46ce0cd3d..ee222ce8e 100644 --- a/crates/proto/src/generated/responses.rs +++ b/crates/proto/src/generated/responses.rs @@ -1,68 +1,77 @@ // This file is @generated by prost-build. +/// Represents the result of applying a block. #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct ApplyBlockResponse {} +/// Represents the result of checking nullifiers. #[derive(Clone, PartialEq, ::prost::Message)] pub struct CheckNullifiersResponse { /// Each requested nullifier has its corresponding nullifier proof at the same position. #[prost(message, repeated, tag = "1")] pub proofs: ::prost::alloc::vec::Vec, } +/// Represents the result of checking nullifiers by prefix. #[derive(Clone, PartialEq, ::prost::Message)] pub struct CheckNullifiersByPrefixResponse { /// List of nullifiers matching the prefixes specified in the request. #[prost(message, repeated, tag = "1")] pub nullifiers: ::prost::alloc::vec::Vec, } +/// Represents the result of getting a block header by block number. #[derive(Clone, PartialEq, ::prost::Message)] pub struct GetBlockHeaderByNumberResponse { - /// The requested block header + /// The requested block header. #[prost(message, optional, tag = "1")] pub block_header: ::core::option::Option, - /// Merkle path to verify the block's inclusion in the MMR at the returned `chain_length` + /// Merkle path to verify the block's inclusion in the MMR at the returned `chain_length`. #[prost(message, optional, tag = "2")] pub mmr_path: ::core::option::Option, - /// Current chain length + /// Current chain length. #[prost(fixed32, optional, tag = "3")] pub chain_length: ::core::option::Option, } +/// Represents a single nullifier update. #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct NullifierUpdate { + /// Nullifier ID. #[prost(message, optional, tag = "1")] pub nullifier: ::core::option::Option, + /// Block number. #[prost(fixed32, tag = "2")] pub block_num: u32, } +/// Represents the result of syncing state request. #[derive(Clone, PartialEq, ::prost::Message)] pub struct SyncStateResponse { - /// Number of the latest block in the chain + /// Number of the latest block in the chain. #[prost(fixed32, tag = "1")] pub chain_tip: u32, - /// Block header of the block with the first note matching the specified criteria + /// Block header of the block with the first note matching the specified criteria. #[prost(message, optional, tag = "2")] pub block_header: ::core::option::Option, - /// Data needed to update the partial MMR from `request.block_num + 1` to `response.block_header.block_num` + /// Data needed to update the partial MMR from `request.block_num + 1` to `response.block_header.block_num`. #[prost(message, optional, tag = "3")] pub mmr_delta: ::core::option::Option, - /// List of account hashes updated after `request.block_num + 1` but not after `response.block_header.block_num` + /// List of account hashes updated after `request.block_num + 1` but not after `response.block_header.block_num`. #[prost(message, repeated, tag = "5")] pub accounts: ::prost::alloc::vec::Vec, /// List of transactions executed against requested accounts between `request.block_num + 1` and - /// `response.block_header.block_num` + /// `response.block_header.block_num`. #[prost(message, repeated, tag = "6")] pub transactions: ::prost::alloc::vec::Vec, - /// List of all notes together with the Merkle paths from `response.block_header.note_root` + /// List of all notes together with the Merkle paths from `response.block_header.note_root`. #[prost(message, repeated, tag = "7")] pub notes: ::prost::alloc::vec::Vec, - /// List of nullifiers created between `request.block_num + 1` and `response.block_header.block_num` + /// List of nullifiers created between `request.block_num + 1` and `response.block_header.block_num`. #[prost(message, repeated, tag = "8")] pub nullifiers: ::prost::alloc::vec::Vec, } +/// Represents the result of syncing notes request. #[derive(Clone, PartialEq, ::prost::Message)] pub struct SyncNoteResponse { - /// Number of the latest block in the chain + /// Number of the latest block in the chain. #[prost(fixed32, tag = "1")] pub chain_tip: u32, - /// Block header of the block with the first note matching the specified criteria + /// Block header of the block with the first note matching the specified criteria. #[prost(message, optional, tag = "2")] pub block_header: ::core::option::Option, /// Merkle path to verify the block's inclusion in the MMR at the returned `chain_tip`. @@ -71,112 +80,135 @@ pub struct SyncNoteResponse { /// an MMR of forest `chain_tip` with this path. #[prost(message, optional, tag = "3")] pub mmr_path: ::core::option::Option, - /// List of all notes together with the Merkle paths from `response.block_header.note_root` + /// List of all notes together with the Merkle paths from `response.block_header.note_root`. #[prost(message, repeated, tag = "4")] pub notes: ::prost::alloc::vec::Vec, } -/// An account returned as a response to the GetBlockInputs +/// An account returned as a response to the `GetBlockInputs`. #[derive(Clone, PartialEq, ::prost::Message)] pub struct AccountBlockInputRecord { + /// The account ID. #[prost(message, optional, tag = "1")] pub account_id: ::core::option::Option, + /// The latest account hash, zero hash if the account doesn't exist. #[prost(message, optional, tag = "2")] pub account_hash: ::core::option::Option, + /// Merkle path to verify the account's inclusion in the MMR. #[prost(message, optional, tag = "3")] pub proof: ::core::option::Option, } -/// A nullifier returned as a response to the GetBlockInputs +/// A nullifier returned as a response to the `GetBlockInputs`. #[derive(Clone, PartialEq, ::prost::Message)] pub struct NullifierBlockInputRecord { + /// The nullifier ID. #[prost(message, optional, tag = "1")] pub nullifier: ::core::option::Option, + /// Merkle path to verify the nullifier's inclusion in the MMR. #[prost(message, optional, tag = "2")] pub opening: ::core::option::Option, } +/// Represents the result of getting block inputs. #[derive(Clone, PartialEq, ::prost::Message)] pub struct GetBlockInputsResponse { - /// The latest block header + /// The latest block header. #[prost(message, optional, tag = "1")] pub block_header: ::core::option::Option, - /// Peaks of the above block's mmr, The `forest` value is equal to the block number + /// Peaks of the above block's mmr, The `forest` value is equal to the block number. #[prost(message, repeated, tag = "2")] pub mmr_peaks: ::prost::alloc::vec::Vec, - /// The hashes of the requested accounts and their authentication paths + /// The hashes of the requested accounts and their authentication paths. #[prost(message, repeated, tag = "3")] pub account_states: ::prost::alloc::vec::Vec, - /// The requested nullifiers and their authentication paths + /// The requested nullifiers and their authentication paths. #[prost(message, repeated, tag = "4")] pub nullifiers: ::prost::alloc::vec::Vec, - /// The list of requested notes which were found in the database + /// The list of requested notes which were found in the database. #[prost(message, optional, tag = "5")] pub found_unauthenticated_notes: ::core::option::Option< super::note::NoteAuthenticationInfo, >, } -/// An account returned as a response to the GetTransactionInputs +/// An account returned as a response to the `GetTransactionInputs`. #[derive(Clone, PartialEq, ::prost::Message)] pub struct AccountTransactionInputRecord { + /// The account ID. #[prost(message, optional, tag = "1")] pub account_id: ::core::option::Option, /// The latest account hash, zero hash if the account doesn't exist. #[prost(message, optional, tag = "2")] pub account_hash: ::core::option::Option, } -/// A nullifier returned as a response to the GetTransactionInputs +/// A nullifier returned as a response to the `GetTransactionInputs`. #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct NullifierTransactionInputRecord { + /// The nullifier ID. #[prost(message, optional, tag = "1")] pub nullifier: ::core::option::Option, /// The block at which the nullifier has been consumed, zero if not consumed. #[prost(fixed32, tag = "2")] pub block_num: u32, } +/// Represents the result of getting transaction inputs. #[derive(Clone, PartialEq, ::prost::Message)] pub struct GetTransactionInputsResponse { + /// Account state proof. #[prost(message, optional, tag = "1")] pub account_state: ::core::option::Option, + /// List of nullifiers that have been consumed. #[prost(message, repeated, tag = "2")] pub nullifiers: ::prost::alloc::vec::Vec, + /// List of unauthenticated notes that were not found in the database. #[prost(message, repeated, tag = "3")] pub found_unauthenticated_notes: ::prost::alloc::vec::Vec, + /// The node's current block height. #[prost(fixed32, tag = "4")] pub block_height: u32, } +/// Represents the result of submitting proven transaction. #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct SubmitProvenTransactionResponse { - /// The node's current block height + /// The node's current block height. #[prost(fixed32, tag = "1")] pub block_height: u32, } +/// Represents the result of getting notes by IDs. #[derive(Clone, PartialEq, ::prost::Message)] pub struct GetNotesByIdResponse { - /// Lists Note's returned by the database + /// Lists Note's returned by the database. #[prost(message, repeated, tag = "1")] pub notes: ::prost::alloc::vec::Vec, } +/// Represents the result of getting note authentication info. #[derive(Clone, PartialEq, ::prost::Message)] pub struct GetNoteAuthenticationInfoResponse { + /// Proofs of note inclusions in blocks and block inclusions in chain. #[prost(message, optional, tag = "1")] pub proofs: ::core::option::Option, } +/// Represents the result of getting account details. #[derive(Clone, PartialEq, ::prost::Message)] pub struct GetAccountDetailsResponse { - /// Account info (with details for public accounts) + /// Account info (with details for public accounts). #[prost(message, optional, tag = "1")] pub details: ::core::option::Option, } +/// Represents the result of getting block by number. #[derive(Clone, PartialEq, ::prost::Message)] pub struct GetBlockByNumberResponse { - /// The requested `Block` data encoded using miden native format + /// The requested block data encoded using \[winter_utils::Serializable\] implementation for + /// \[miden_objects::block::Block\]. #[prost(bytes = "vec", optional, tag = "1")] pub block: ::core::option::Option<::prost::alloc::vec::Vec>, } +/// Represents the result of getting account state delta. #[derive(Clone, PartialEq, ::prost::Message)] pub struct GetAccountStateDeltaResponse { - /// The calculated `AccountStateDelta` encoded using miden native format + /// The calculated account delta encoded using \[winter_utils::Serializable\] implementation + /// for \[miden_objects::accounts::delta::AccountDelta\]. #[prost(bytes = "vec", optional, tag = "1")] pub delta: ::core::option::Option<::prost::alloc::vec::Vec>, } +/// Represents the result of getting account proofs. #[derive(Clone, PartialEq, ::prost::Message)] pub struct GetAccountProofsResponse { /// Block number at which the state of the account was returned. @@ -186,6 +218,7 @@ pub struct GetAccountProofsResponse { #[prost(message, repeated, tag = "2")] pub account_proofs: ::prost::alloc::vec::Vec, } +/// A single account proof returned as a response to the `GetAccountProofs`. #[derive(Clone, PartialEq, ::prost::Message)] pub struct AccountProofsResponse { /// Account ID. @@ -201,6 +234,7 @@ pub struct AccountProofsResponse { #[prost(message, optional, tag = "4")] pub state_header: ::core::option::Option, } +/// State header for public accounts. #[derive(Clone, PartialEq, ::prost::Message)] pub struct AccountStateHeader { /// Account header. diff --git a/crates/proto/src/generated/rpc.rs b/crates/proto/src/generated/rpc.rs index c7181943c..f9af9ad7c 100644 --- a/crates/proto/src/generated/rpc.rs +++ b/crates/proto/src/generated/rpc.rs @@ -90,6 +90,7 @@ pub mod api_client { self.inner = self.inner.max_encoding_message_size(limit); self } + /// Gets a list of proofs for given nullifier hashes, each proof as a sparse Merkle Tree. pub async fn check_nullifiers( &mut self, request: impl tonic::IntoRequest< @@ -113,6 +114,7 @@ pub mod api_client { req.extensions_mut().insert(GrpcMethod::new("rpc.Api", "CheckNullifiers")); self.inner.unary(req, path, codec).await } + /// Returns a list of nullifiers that match the specified prefixes and are recorded in the node. pub async fn check_nullifiers_by_prefix( &mut self, request: impl tonic::IntoRequest< @@ -139,6 +141,7 @@ pub mod api_client { .insert(GrpcMethod::new("rpc.Api", "CheckNullifiersByPrefix")); self.inner.unary(req, path, codec).await } + /// Returns the latest state of an account with the specified ID. pub async fn get_account_details( &mut self, request: impl tonic::IntoRequest< @@ -164,6 +167,7 @@ pub mod api_client { req.extensions_mut().insert(GrpcMethod::new("rpc.Api", "GetAccountDetails")); self.inner.unary(req, path, codec).await } + /// Returns the latest state proofs of the specified accounts. pub async fn get_account_proofs( &mut self, request: impl tonic::IntoRequest< @@ -187,6 +191,8 @@ pub mod api_client { req.extensions_mut().insert(GrpcMethod::new("rpc.Api", "GetAccountProofs")); self.inner.unary(req, path, codec).await } + /// Returns delta of the account states in the range from `from_block_num` (exclusive) to + /// `to_block_num` (inclusive). pub async fn get_account_state_delta( &mut self, request: impl tonic::IntoRequest< @@ -213,6 +219,7 @@ pub mod api_client { .insert(GrpcMethod::new("rpc.Api", "GetAccountStateDelta")); self.inner.unary(req, path, codec).await } + /// Retrieves block data by given block number. pub async fn get_block_by_number( &mut self, request: impl tonic::IntoRequest< @@ -236,6 +243,8 @@ pub mod api_client { req.extensions_mut().insert(GrpcMethod::new("rpc.Api", "GetBlockByNumber")); self.inner.unary(req, path, codec).await } + /// Retrieves block header by given block number. Optionally, it also returns the MMR path + /// and current chain length to authenticate the block's inclusion. pub async fn get_block_header_by_number( &mut self, request: impl tonic::IntoRequest< @@ -262,6 +271,7 @@ pub mod api_client { .insert(GrpcMethod::new("rpc.Api", "GetBlockHeaderByNumber")); self.inner.unary(req, path, codec).await } + /// Returns a list of notes matching the provided note IDs. pub async fn get_notes_by_id( &mut self, request: impl tonic::IntoRequest, @@ -283,6 +293,7 @@ pub mod api_client { req.extensions_mut().insert(GrpcMethod::new("rpc.Api", "GetNotesById")); self.inner.unary(req, path, codec).await } + /// Submits proven transaction to the Miden network. pub async fn submit_proven_transaction( &mut self, request: impl tonic::IntoRequest< @@ -309,6 +320,10 @@ pub mod api_client { .insert(GrpcMethod::new("rpc.Api", "SubmitProvenTransaction")); self.inner.unary(req, path, codec).await } + /// Note synchronization request. + /// + /// Specifies note tags that client is interested in. The server will return the first block which + /// contains a note matching `note_tags` or the chain tip. pub async fn sync_notes( &mut self, request: impl tonic::IntoRequest, @@ -330,6 +345,21 @@ pub mod api_client { req.extensions_mut().insert(GrpcMethod::new("rpc.Api", "SyncNotes")); self.inner.unary(req, path, codec).await } + /// Returns info which can be used by the client to sync up to the latest state of the chain + /// for the objects (accounts, notes, nullifiers) the client is interested in. + /// + /// This request returns the next block containing requested data. It also returns `chain_tip` + /// which is the latest block number in the chain. Client is expected to repeat these requests + /// in a loop until `response.block_header.block_num == response.chain_tip`, at which point + /// the client is fully synchronized with the chain. + /// + /// Each request also returns info about new notes, nullifiers etc. created. It also returns + /// Chain MMR delta that can be used to update the state of Chain MMR. This includes both chain + /// MMR peaks and chain MMR nodes. + /// + /// For preserving some degree of privacy, note tags and nullifiers filters contain only high + /// part of hashes. Thus, returned data contains excessive notes and nullifiers, client can make + /// additional filtering of that data on its side. pub async fn sync_state( &mut self, request: impl tonic::IntoRequest, @@ -366,6 +396,7 @@ pub mod api_server { /// Generated trait containing gRPC methods that should be implemented for use with ApiServer. #[async_trait] pub trait Api: std::marker::Send + std::marker::Sync + 'static { + /// Gets a list of proofs for given nullifier hashes, each proof as a sparse Merkle Tree. async fn check_nullifiers( &self, request: tonic::Request, @@ -373,6 +404,7 @@ pub mod api_server { tonic::Response, tonic::Status, >; + /// Returns a list of nullifiers that match the specified prefixes and are recorded in the node. async fn check_nullifiers_by_prefix( &self, request: tonic::Request< @@ -382,6 +414,7 @@ pub mod api_server { tonic::Response, tonic::Status, >; + /// Returns the latest state of an account with the specified ID. async fn get_account_details( &self, request: tonic::Request, @@ -389,6 +422,7 @@ pub mod api_server { tonic::Response, tonic::Status, >; + /// Returns the latest state proofs of the specified accounts. async fn get_account_proofs( &self, request: tonic::Request, @@ -396,6 +430,8 @@ pub mod api_server { tonic::Response, tonic::Status, >; + /// Returns delta of the account states in the range from `from_block_num` (exclusive) to + /// `to_block_num` (inclusive). async fn get_account_state_delta( &self, request: tonic::Request, @@ -403,6 +439,7 @@ pub mod api_server { tonic::Response, tonic::Status, >; + /// Retrieves block data by given block number. async fn get_block_by_number( &self, request: tonic::Request, @@ -410,6 +447,8 @@ pub mod api_server { tonic::Response, tonic::Status, >; + /// Retrieves block header by given block number. Optionally, it also returns the MMR path + /// and current chain length to authenticate the block's inclusion. async fn get_block_header_by_number( &self, request: tonic::Request< @@ -419,6 +458,7 @@ pub mod api_server { tonic::Response, tonic::Status, >; + /// Returns a list of notes matching the provided note IDs. async fn get_notes_by_id( &self, request: tonic::Request, @@ -426,6 +466,7 @@ pub mod api_server { tonic::Response, tonic::Status, >; + /// Submits proven transaction to the Miden network. async fn submit_proven_transaction( &self, request: tonic::Request< @@ -435,6 +476,10 @@ pub mod api_server { tonic::Response, tonic::Status, >; + /// Note synchronization request. + /// + /// Specifies note tags that client is interested in. The server will return the first block which + /// contains a note matching `note_tags` or the chain tip. async fn sync_notes( &self, request: tonic::Request, @@ -442,6 +487,21 @@ pub mod api_server { tonic::Response, tonic::Status, >; + /// Returns info which can be used by the client to sync up to the latest state of the chain + /// for the objects (accounts, notes, nullifiers) the client is interested in. + /// + /// This request returns the next block containing requested data. It also returns `chain_tip` + /// which is the latest block number in the chain. Client is expected to repeat these requests + /// in a loop until `response.block_header.block_num == response.chain_tip`, at which point + /// the client is fully synchronized with the chain. + /// + /// Each request also returns info about new notes, nullifiers etc. created. It also returns + /// Chain MMR delta that can be used to update the state of Chain MMR. This includes both chain + /// MMR peaks and chain MMR nodes. + /// + /// For preserving some degree of privacy, note tags and nullifiers filters contain only high + /// part of hashes. Thus, returned data contains excessive notes and nullifiers, client can make + /// additional filtering of that data on its side. async fn sync_state( &self, request: tonic::Request, diff --git a/crates/proto/src/generated/smt.rs b/crates/proto/src/generated/smt.rs index c4aaf2d77..90e9394d3 100644 --- a/crates/proto/src/generated/smt.rs +++ b/crates/proto/src/generated/smt.rs @@ -1,14 +1,18 @@ // This file is @generated by prost-build. -/// An entry in a leaf. +/// Represents a single SMT leaf entry. #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct SmtLeafEntry { + /// The key of the entry. #[prost(message, optional, tag = "1")] pub key: ::core::option::Option, + /// The value of the entry. #[prost(message, optional, tag = "2")] pub value: ::core::option::Option, } +/// Represents multiple leaf entries in an SMT. #[derive(Clone, PartialEq, ::prost::Message)] pub struct SmtLeafEntries { + /// The entries list. #[prost(message, repeated, tag = "1")] pub entries: ::prost::alloc::vec::Vec, } @@ -22,10 +26,13 @@ pub struct SmtLeaf { pub mod smt_leaf { #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Leaf { + /// An empty leaf. #[prost(uint64, tag = "1")] Empty(u64), + /// A single leaf entry. #[prost(message, tag = "2")] Single(super::SmtLeafEntry), + /// Multiple leaf entries. #[prost(message, tag = "3")] Multiple(super::SmtLeafEntries), } @@ -33,8 +40,10 @@ pub mod smt_leaf { /// The opening of a leaf in an SMT. #[derive(Clone, PartialEq, ::prost::Message)] pub struct SmtOpening { + /// The merkle path to the leaf. #[prost(message, optional, tag = "1")] pub path: ::core::option::Option, + /// The leaf itself. #[prost(message, optional, tag = "2")] pub leaf: ::core::option::Option, } diff --git a/crates/proto/src/generated/store.rs b/crates/proto/src/generated/store.rs index 7d979f379..6b1aa2cee 100644 --- a/crates/proto/src/generated/store.rs +++ b/crates/proto/src/generated/store.rs @@ -90,6 +90,7 @@ pub mod api_client { self.inner = self.inner.max_encoding_message_size(limit); self } + /// Applies changes of a new block to the DB and in-memory data structures. pub async fn apply_block( &mut self, request: impl tonic::IntoRequest, @@ -111,6 +112,7 @@ pub mod api_client { req.extensions_mut().insert(GrpcMethod::new("store.Api", "ApplyBlock")); self.inner.unary(req, path, codec).await } + /// Gets a list of proofs for given nullifier hashes, each proof as a sparse Merkle Tree. pub async fn check_nullifiers( &mut self, request: impl tonic::IntoRequest< @@ -136,6 +138,7 @@ pub mod api_client { req.extensions_mut().insert(GrpcMethod::new("store.Api", "CheckNullifiers")); self.inner.unary(req, path, codec).await } + /// Returns a list of nullifiers that match the specified prefixes and are recorded in the node. pub async fn check_nullifiers_by_prefix( &mut self, request: impl tonic::IntoRequest< @@ -162,6 +165,7 @@ pub mod api_client { .insert(GrpcMethod::new("store.Api", "CheckNullifiersByPrefix")); self.inner.unary(req, path, codec).await } + /// Returns the latest state of an account with the specified ID. pub async fn get_account_details( &mut self, request: impl tonic::IntoRequest< @@ -188,6 +192,7 @@ pub mod api_client { .insert(GrpcMethod::new("store.Api", "GetAccountDetails")); self.inner.unary(req, path, codec).await } + /// Returns the latest state proofs of the specified accounts. pub async fn get_account_proofs( &mut self, request: impl tonic::IntoRequest< @@ -214,6 +219,8 @@ pub mod api_client { .insert(GrpcMethod::new("store.Api", "GetAccountProofs")); self.inner.unary(req, path, codec).await } + /// Returns delta of the account states in the range from `from_block_num` (exclusive) to + /// `to_block_num` (inclusive). pub async fn get_account_state_delta( &mut self, request: impl tonic::IntoRequest< @@ -240,6 +247,7 @@ pub mod api_client { .insert(GrpcMethod::new("store.Api", "GetAccountStateDelta")); self.inner.unary(req, path, codec).await } + /// Retrieves block data by given block number. pub async fn get_block_by_number( &mut self, request: impl tonic::IntoRequest< @@ -266,6 +274,8 @@ pub mod api_client { .insert(GrpcMethod::new("store.Api", "GetBlockByNumber")); self.inner.unary(req, path, codec).await } + /// Retrieves block header by given block number. Optionally, it also returns the MMR path + /// and current chain length to authenticate the block's inclusion. pub async fn get_block_header_by_number( &mut self, request: impl tonic::IntoRequest< @@ -292,6 +302,7 @@ pub mod api_client { .insert(GrpcMethod::new("store.Api", "GetBlockHeaderByNumber")); self.inner.unary(req, path, codec).await } + /// Returns data required to prove the next block. pub async fn get_block_inputs( &mut self, request: impl tonic::IntoRequest< @@ -315,6 +326,7 @@ pub mod api_client { req.extensions_mut().insert(GrpcMethod::new("store.Api", "GetBlockInputs")); self.inner.unary(req, path, codec).await } + /// Returns a list of Note inclusion proofs for the specified Note IDs. pub async fn get_note_authentication_info( &mut self, request: impl tonic::IntoRequest< @@ -341,6 +353,7 @@ pub mod api_client { .insert(GrpcMethod::new("store.Api", "GetNoteAuthenticationInfo")); self.inner.unary(req, path, codec).await } + /// Returns a list of notes matching the provided note IDs. pub async fn get_notes_by_id( &mut self, request: impl tonic::IntoRequest, @@ -362,6 +375,7 @@ pub mod api_client { req.extensions_mut().insert(GrpcMethod::new("store.Api", "GetNotesById")); self.inner.unary(req, path, codec).await } + /// Returns data required to validate a new transaction. pub async fn get_transaction_inputs( &mut self, request: impl tonic::IntoRequest< @@ -388,6 +402,10 @@ pub mod api_client { .insert(GrpcMethod::new("store.Api", "GetTransactionInputs")); self.inner.unary(req, path, codec).await } + /// Note synchronization request. + /// + /// Specifies note tags that client is interested in. The server will return the first block which + /// contains a note matching `note_tags` or the chain tip. pub async fn sync_notes( &mut self, request: impl tonic::IntoRequest, @@ -409,6 +427,21 @@ pub mod api_client { req.extensions_mut().insert(GrpcMethod::new("store.Api", "SyncNotes")); self.inner.unary(req, path, codec).await } + /// Returns info which can be used by the client to sync up to the latest state of the chain + /// for the objects (accounts, notes, nullifiers) the client is interested in. + /// + /// This request returns the next block containing requested data. It also returns `chain_tip` + /// which is the latest block number in the chain. Client is expected to repeat these requests + /// in a loop until `response.block_header.block_num == response.chain_tip`, at which point + /// the client is fully synchronized with the chain. + /// + /// Each request also returns info about new notes, nullifiers etc. created. It also returns + /// Chain MMR delta that can be used to update the state of Chain MMR. This includes both chain + /// MMR peaks and chain MMR nodes. + /// + /// For preserving some degree of privacy, note tags and nullifiers filters contain only high + /// part of hashes. Thus, returned data contains excessive notes and nullifiers, client can make + /// additional filtering of that data on its side. pub async fn sync_state( &mut self, request: impl tonic::IntoRequest, @@ -445,6 +478,7 @@ pub mod api_server { /// Generated trait containing gRPC methods that should be implemented for use with ApiServer. #[async_trait] pub trait Api: std::marker::Send + std::marker::Sync + 'static { + /// Applies changes of a new block to the DB and in-memory data structures. async fn apply_block( &self, request: tonic::Request, @@ -452,6 +486,7 @@ pub mod api_server { tonic::Response, tonic::Status, >; + /// Gets a list of proofs for given nullifier hashes, each proof as a sparse Merkle Tree. async fn check_nullifiers( &self, request: tonic::Request, @@ -459,6 +494,7 @@ pub mod api_server { tonic::Response, tonic::Status, >; + /// Returns a list of nullifiers that match the specified prefixes and are recorded in the node. async fn check_nullifiers_by_prefix( &self, request: tonic::Request< @@ -468,6 +504,7 @@ pub mod api_server { tonic::Response, tonic::Status, >; + /// Returns the latest state of an account with the specified ID. async fn get_account_details( &self, request: tonic::Request, @@ -475,6 +512,7 @@ pub mod api_server { tonic::Response, tonic::Status, >; + /// Returns the latest state proofs of the specified accounts. async fn get_account_proofs( &self, request: tonic::Request, @@ -482,6 +520,8 @@ pub mod api_server { tonic::Response, tonic::Status, >; + /// Returns delta of the account states in the range from `from_block_num` (exclusive) to + /// `to_block_num` (inclusive). async fn get_account_state_delta( &self, request: tonic::Request, @@ -489,6 +529,7 @@ pub mod api_server { tonic::Response, tonic::Status, >; + /// Retrieves block data by given block number. async fn get_block_by_number( &self, request: tonic::Request, @@ -496,6 +537,8 @@ pub mod api_server { tonic::Response, tonic::Status, >; + /// Retrieves block header by given block number. Optionally, it also returns the MMR path + /// and current chain length to authenticate the block's inclusion. async fn get_block_header_by_number( &self, request: tonic::Request< @@ -505,6 +548,7 @@ pub mod api_server { tonic::Response, tonic::Status, >; + /// Returns data required to prove the next block. async fn get_block_inputs( &self, request: tonic::Request, @@ -512,6 +556,7 @@ pub mod api_server { tonic::Response, tonic::Status, >; + /// Returns a list of Note inclusion proofs for the specified Note IDs. async fn get_note_authentication_info( &self, request: tonic::Request< @@ -521,6 +566,7 @@ pub mod api_server { tonic::Response, tonic::Status, >; + /// Returns a list of notes matching the provided note IDs. async fn get_notes_by_id( &self, request: tonic::Request, @@ -528,6 +574,7 @@ pub mod api_server { tonic::Response, tonic::Status, >; + /// Returns data required to validate a new transaction. async fn get_transaction_inputs( &self, request: tonic::Request, @@ -535,6 +582,10 @@ pub mod api_server { tonic::Response, tonic::Status, >; + /// Note synchronization request. + /// + /// Specifies note tags that client is interested in. The server will return the first block which + /// contains a note matching `note_tags` or the chain tip. async fn sync_notes( &self, request: tonic::Request, @@ -542,6 +593,21 @@ pub mod api_server { tonic::Response, tonic::Status, >; + /// Returns info which can be used by the client to sync up to the latest state of the chain + /// for the objects (accounts, notes, nullifiers) the client is interested in. + /// + /// This request returns the next block containing requested data. It also returns `chain_tip` + /// which is the latest block number in the chain. Client is expected to repeat these requests + /// in a loop until `response.block_header.block_num == response.chain_tip`, at which point + /// the client is fully synchronized with the chain. + /// + /// Each request also returns info about new notes, nullifiers etc. created. It also returns + /// Chain MMR delta that can be used to update the state of Chain MMR. This includes both chain + /// MMR peaks and chain MMR nodes. + /// + /// For preserving some degree of privacy, note tags and nullifiers filters contain only high + /// part of hashes. Thus, returned data contains excessive notes and nullifiers, client can make + /// additional filtering of that data on its side. async fn sync_state( &self, request: tonic::Request, diff --git a/crates/proto/src/generated/transaction.rs b/crates/proto/src/generated/transaction.rs index 7dca33a33..3439e78ea 100644 --- a/crates/proto/src/generated/transaction.rs +++ b/crates/proto/src/generated/transaction.rs @@ -1,15 +1,21 @@ // This file is @generated by prost-build. +/// Represents a transaction ID. #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct TransactionId { + /// The transaction ID. #[prost(message, optional, tag = "1")] pub id: ::core::option::Option, } +/// Represents a transaction summary. #[derive(Clone, PartialEq, ::prost::Message)] pub struct TransactionSummary { + /// A unique 32-byte identifier of a transaction. #[prost(message, optional, tag = "1")] pub transaction_id: ::core::option::Option, + /// The block number in which the transaction was executed. #[prost(fixed32, tag = "2")] pub block_num: u32, + /// The ID of the account affected by the transaction. #[prost(message, optional, tag = "3")] pub account_id: ::core::option::Option, } diff --git a/crates/rpc-proto/Cargo.toml b/crates/rpc-proto/Cargo.toml index 39da27233..a9015ed67 100644 --- a/crates/rpc-proto/Cargo.toml +++ b/crates/rpc-proto/Cargo.toml @@ -12,6 +12,9 @@ authors.workspace = true homepage.workspace = true repository.workspace = true +[lints] +workspace = true + [features] default = ["std"] std = [] diff --git a/crates/rpc-proto/build.rs b/crates/rpc-proto/build.rs index 4f6d911cc..48a3d6df2 100644 --- a/crates/rpc-proto/build.rs +++ b/crates/rpc-proto/build.rs @@ -15,10 +15,10 @@ const DOC_COMMENT: &str = // BUILD SCRIPT // ================================================================================================ -/// Copies .proto files to the local directory and re-builds src/proto_files.rs file. +/// Copies .proto files to the local directory and re-builds `src/proto_files.rs` file. /// -/// This is done only if BUILD_PROTO environment variable is set to `1` to avoid running the script -/// on crates.io where repo-level .proto files are not available. +/// This is done only if `BUILD_PROTO` environment variable is set to `1` to avoid running the +/// script on crates.io where repo-level .proto files are not available. fn main() -> io::Result<()> { println!("cargo::rerun-if-changed=../../proto"); println!("cargo::rerun-if-env-changed=BUILD_PROTO"); diff --git a/crates/rpc-proto/proto/account.proto b/crates/rpc-proto/proto/account.proto index 6614b7bc7..f2c1d6e50 100644 --- a/crates/rpc-proto/proto/account.proto +++ b/crates/rpc-proto/proto/account.proto @@ -3,30 +3,49 @@ package account; import "digest.proto"; +// Uniquely identifies a specific account. +// +// A Miden account ID is a 120-bit value derived from the commitments to account code and storage, +// and a random user-provided seed. message AccountId { - // A Miden account ID is a 120-bit value derived from the commitments to account code and - // storage, and a random user-provided seed. + // 15 bytes (120 bits) encoded using [winter_utils::Serializable] implementation for + // [miden_objects::accounts::account_id::AccountId]. bytes id = 1; } +// The state of an account at a specific block height. message AccountSummary { + // The account ID. AccountId account_id = 1; + + // The current account hash or zero if the account does not exist. digest.Digest account_hash = 2; + + // Block number at which the summary was made. uint32 block_num = 3; } +// An account info. message AccountInfo { + // Account summary. AccountSummary summary = 1; + + // Account details encoded using [winter_utils::Serializable] implementation for + // [miden_objects::accounts::Account]. optional bytes details = 2; } +// An account header. message AccountHeader { // Vault root hash. digest.Digest vault_root = 1; + // Storage root hash. digest.Digest storage_commitment = 2; + // Code root hash. digest.Digest code_commitment = 3; + // Account nonce. uint64 nonce = 4; } diff --git a/crates/rpc-proto/proto/block.proto b/crates/rpc-proto/proto/block.proto index 616f927b4..f9a41a99c 100644 --- a/crates/rpc-proto/proto/block.proto +++ b/crates/rpc-proto/proto/block.proto @@ -4,34 +4,50 @@ package block; import "digest.proto"; import "merkle.proto"; +// Represents a block header. message BlockHeader { - // specifies the version of the protocol. + // Specifies the version of the protocol. uint32 version = 1; - // the hash of the previous blocks header. + + // The hash of the previous blocks header. digest.Digest prev_hash = 2; - // a unique sequential number of the current block. + + // A unique sequential number of the current block. fixed32 block_num = 3; - // a commitment to an MMR of the entire chain where each block is a leaf. + + // A commitment to an MMR of the entire chain where each block is a leaf. digest.Digest chain_root = 4; - // a commitment to account database. + + // A commitment to account database. digest.Digest account_root = 5; - // a commitment to the nullifier database. + + // A commitment to the nullifier database. digest.Digest nullifier_root = 6; - // a commitment to all notes created in the current block. + + // A commitment to all notes created in the current block. digest.Digest note_root = 7; - // a commitment to a set of IDs of transactions which affected accounts in this block. + + // A commitment to a set of IDs of transactions which affected accounts in this block. digest.Digest tx_hash = 8; - // a hash of a STARK proof attesting to the correct state transition. + + // A hash of a STARK proof attesting to the correct state transition. digest.Digest proof_hash = 9; - // a commitment to all transaction kernels supported by this block. + + // A commitment to all transaction kernels supported by this block. digest.Digest kernel_root = 10; - // the time when the block was created. + + // The time when the block was created. fixed32 timestamp = 11; } +// Represents a block inclusion proof. message BlockInclusionProof { + // Block header associated with the inclusion proof. BlockHeader block_header = 1; + + // Merkle path associated with the inclusion proof. merkle.MerklePath mmr_path = 2; + // The chain length associated with `mmr_path`. fixed32 chain_length = 3; } diff --git a/crates/rpc-proto/proto/block_producer.proto b/crates/rpc-proto/proto/block_producer.proto index d4f2c0062..054c14912 100644 --- a/crates/rpc-proto/proto/block_producer.proto +++ b/crates/rpc-proto/proto/block_producer.proto @@ -6,6 +6,7 @@ import "requests.proto"; import "responses.proto"; service Api { + // Submits proven transaction to the Miden network rpc SubmitProvenTransaction(requests.SubmitProvenTransactionRequest) returns (responses.SubmitProvenTransactionResponse) {} } diff --git a/crates/rpc-proto/proto/merkle.proto b/crates/rpc-proto/proto/merkle.proto index abded7231..88336deda 100644 --- a/crates/rpc-proto/proto/merkle.proto +++ b/crates/rpc-proto/proto/merkle.proto @@ -3,6 +3,8 @@ package merkle; import "digest.proto"; +// Represents a Merkle path. message MerklePath { + // List of sibling node hashes, in order from the root to the leaf. repeated digest.Digest siblings = 1; } diff --git a/crates/rpc-proto/proto/mmr.proto b/crates/rpc-proto/proto/mmr.proto index baaced2c9..f5e60e570 100644 --- a/crates/rpc-proto/proto/mmr.proto +++ b/crates/rpc-proto/proto/mmr.proto @@ -3,7 +3,11 @@ package mmr; import "digest.proto"; +// Represents an MMR delta. message MmrDelta { + // The number of leaf nodes in the MMR. uint64 forest = 1; + + // New and changed MMR peaks. repeated digest.Digest data = 2; } diff --git a/crates/rpc-proto/proto/note.proto b/crates/rpc-proto/proto/note.proto index d424f696b..f65960d67 100644 --- a/crates/rpc-proto/proto/note.proto +++ b/crates/rpc-proto/proto/note.proto @@ -6,42 +6,86 @@ import "block.proto"; import "digest.proto"; import "merkle.proto"; +// Represents a note's metadata. message NoteMetadata { + // The account which sent the note. account.AccountId sender = 1; + + // The type of the note (0b01 = public, 0b10 = private, 0b11 = encrypted). uint32 note_type = 2; + + // A value which can be used by the recipient(s) to identify notes intended for them. + // + // See `miden_objects::notes::note_tag` for more info. fixed32 tag = 3; + + // Specifies when a note is ready to be consumed. + // + // See `miden_objects::notes::execution_hint` for more info. fixed64 execution_hint = 4; + + // An arbitrary user-defined value. fixed64 aux = 5; } +// Represents a note. message Note { + // The block number in which the note was created. fixed32 block_num = 1; + + // The index of the note in the block. uint32 note_index = 2; + + // The ID of the note. digest.Digest note_id = 3; + + // The note's metadata. NoteMetadata metadata = 4; + + // The note's inclusion proof in the block. merkle.MerklePath merkle_path = 5; - // This field will be present when the note is public. - // details contain the `Note` in a serialized format. + + // Serialized details of the public note (empty for private notes). optional bytes details = 6; } +// Represents a proof of note's inclusion in a block. +// +// Does not include proof of the block's inclusion in the chain. message NoteInclusionInBlockProof { + // A unique identifier of the note which is a 32-byte commitment to the underlying note data. digest.Digest note_id = 1; + + // The block number in which the note was created. fixed32 block_num = 2; + + // The index of the note in the block. uint32 note_index_in_block = 3; + + // The note's inclusion proof in the block. merkle.MerklePath merkle_path = 4; } +// Represents proof of a note inclusion in the block. message NoteSyncRecord { + // The index of the note. uint32 note_index = 1; + + // A unique identifier of the note which is a 32-byte commitment to the underlying note data. digest.Digest note_id = 2; + + // The note's metadata. NoteMetadata metadata = 3; + + // The note's inclusion proof in the block. merkle.MerklePath merkle_path = 4; } +// Represents proof of notes inclusion in the block(s) and block(s) inclusion in the chain. message NoteAuthenticationInfo { // Proof of each note's inclusion in a block. repeated note.NoteInclusionInBlockProof note_proofs = 1; + // Proof of each block's inclusion in the chain. repeated block.BlockInclusionProof block_proofs = 2; } diff --git a/crates/rpc-proto/proto/requests.proto b/crates/rpc-proto/proto/requests.proto index 62ec750a1..b8e2e0817 100644 --- a/crates/rpc-proto/proto/requests.proto +++ b/crates/rpc-proto/proto/requests.proto @@ -3,9 +3,11 @@ package requests; import "account.proto"; import "digest.proto"; -import "note.proto"; +// Applies changes of a new block to the DB and in-memory data structures. message ApplyBlockRequest { + // Block data encoded using [winter_utils::Serializable] implementation for + // [miden_objects::block::Block]. bytes block = 1; } @@ -14,11 +16,13 @@ message CheckNullifiersByPrefixRequest { // Number of bits used for nullifier prefix. Currently the only supported value is 16. uint32 prefix_len = 1; // List of nullifiers to check. Each nullifier is specified by its prefix with length equal - // to prefix_len + // to `prefix_len`. repeated uint32 nullifiers = 2; } +// Get a list of proofs for given nullifier hashes, each proof as a sparse Merkle Tree. message CheckNullifiersRequest { + // List of nullifiers to return proofs for. repeated digest.Digest nullifiers = 1; } @@ -27,9 +31,7 @@ message CheckNullifiersRequest { // // The Merkle path is an MMR proof for the block's leaf, based on the current chain length. message GetBlockHeaderByNumberRequest { - // The block number of the target block. - // - // If not provided, means latest known block. + // The target block height, defaults to latest if not provided. optional uint32 block_num = 1; // Whether or not to return authentication data for the block header. optional bool include_mmr_proof = 2; @@ -74,33 +76,45 @@ message SyncNoteRequest { repeated fixed32 note_tags = 2; } +// Returns data required to prove the next block. message GetBlockInputsRequest { // ID of the account against which a transaction is executed. repeated account.AccountId account_ids = 1; - // Array of nullifiers for all notes consumed by a transaction. + // Set of nullifiers consumed by this transaction. repeated digest.Digest nullifiers = 2; // Array of note IDs to be checked for existence in the database. repeated digest.Digest unauthenticated_notes = 3; } +// Returns data required to validate a new transaction. message GetTransactionInputsRequest { + // ID of the account against which a transaction is executed. account.AccountId account_id = 1; + // Set of nullifiers consumed by this transaction. repeated digest.Digest nullifiers = 2; + // Set of unauthenticated notes to check for existence on-chain. + // + // These are notes which were not on-chain at the state the transaction was proven, + // but could by now be present. repeated digest.Digest unauthenticated_notes = 3; } +// Submits proven transaction to the Miden network. message SubmitProvenTransactionRequest { - // Transaction encoded using miden's native format + // Transaction encoded using [winter_utils::Serializable] implementation for + // [miden_objects::transaction::proven_tx::ProvenTransaction]. bytes transaction = 1; } +// Returns a list of notes matching the provided note IDs. message GetNotesByIdRequest { - // List of NoteId's to be queried from the database + // List of notes to be queried from the database. repeated digest.Digest note_ids = 1; } +// Returns a list of Note inclusion proofs for the specified Note IDs. message GetNoteAuthenticationInfoRequest { - // List of NoteId's to be queried from the database + // List of notes to be queried from the database. repeated digest.Digest note_ids = 1; } @@ -110,6 +124,7 @@ message GetAccountDetailsRequest { account.AccountId account_id = 1; } +// Retrieves block data by given block number. message GetBlockByNumberRequest { // The block number of the target block. fixed32 block_num = 1; @@ -126,9 +141,9 @@ message GetAccountStateDeltaRequest { fixed32 to_block_num = 3; } -// Request message to get account proofs. +// Returns the latest state proofs of the specified accounts. message GetAccountProofsRequest { - // Represents per-account requests where each account ID has its own list of + // Represents per-account requests where each account ID has its own list of // (storage_slot_index, map_keys) pairs. message AccountRequest { // The account ID for this request. @@ -154,7 +169,7 @@ message GetAccountProofsRequest { // requests are also ignored. False by default. optional bool include_headers = 2; - // Account code commitments corresponding to the last-known `AccountCode` for requested + // Account code commitments corresponding to the last-known `AccountCode` for requested // accounts. Responses will include only the ones that are not known to the caller. // These are not associated with a specific account but rather, they will be matched against // all requested accounts. diff --git a/crates/rpc-proto/proto/responses.proto b/crates/rpc-proto/proto/responses.proto index 530a5dc18..860368e67 100644 --- a/crates/rpc-proto/proto/responses.proto +++ b/crates/rpc-proto/proto/responses.proto @@ -10,63 +10,73 @@ import "note.proto"; import "smt.proto"; import "transaction.proto"; +// Represents the result of applying a block. message ApplyBlockResponse {} +// Represents the result of checking nullifiers. message CheckNullifiersResponse { // Each requested nullifier has its corresponding nullifier proof at the same position. repeated smt.SmtOpening proofs = 1; } +// Represents the result of checking nullifiers by prefix. message CheckNullifiersByPrefixResponse { // List of nullifiers matching the prefixes specified in the request. repeated NullifierUpdate nullifiers = 1; } +// Represents the result of getting a block header by block number. message GetBlockHeaderByNumberResponse { - // The requested block header + // The requested block header. block.BlockHeader block_header = 1; - // Merkle path to verify the block's inclusion in the MMR at the returned `chain_length` + // Merkle path to verify the block's inclusion in the MMR at the returned `chain_length`. optional merkle.MerklePath mmr_path = 2; - // Current chain length + // Current chain length. optional fixed32 chain_length = 3; } +// Represents a single nullifier update. message NullifierUpdate { + // Nullifier ID. digest.Digest nullifier = 1; + + // Block number. fixed32 block_num = 2; } +// Represents the result of syncing state request. message SyncStateResponse { - // Number of the latest block in the chain + // Number of the latest block in the chain. fixed32 chain_tip = 1; - // Block header of the block with the first note matching the specified criteria + // Block header of the block with the first note matching the specified criteria. block.BlockHeader block_header = 2; - // Data needed to update the partial MMR from `request.block_num + 1` to `response.block_header.block_num` + // Data needed to update the partial MMR from `request.block_num + 1` to `response.block_header.block_num`. mmr.MmrDelta mmr_delta = 3; - // List of account hashes updated after `request.block_num + 1` but not after `response.block_header.block_num` + // List of account hashes updated after `request.block_num + 1` but not after `response.block_header.block_num`. repeated account.AccountSummary accounts = 5; // List of transactions executed against requested accounts between `request.block_num + 1` and - // `response.block_header.block_num` + // `response.block_header.block_num`. repeated transaction.TransactionSummary transactions = 6; - // List of all notes together with the Merkle paths from `response.block_header.note_root` + // List of all notes together with the Merkle paths from `response.block_header.note_root`. repeated note.NoteSyncRecord notes = 7; - // List of nullifiers created between `request.block_num + 1` and `response.block_header.block_num` + // List of nullifiers created between `request.block_num + 1` and `response.block_header.block_num`. repeated NullifierUpdate nullifiers = 8; } +// Represents the result of syncing notes request. message SyncNoteResponse { - // Number of the latest block in the chain + // Number of the latest block in the chain. fixed32 chain_tip = 1; - // Block header of the block with the first note matching the specified criteria + // Block header of the block with the first note matching the specified criteria. block.BlockHeader block_header = 2; // Merkle path to verify the block's inclusion in the MMR at the returned `chain_tip`. @@ -75,90 +85,121 @@ message SyncNoteResponse { // an MMR of forest `chain_tip` with this path. merkle.MerklePath mmr_path = 3; - // List of all notes together with the Merkle paths from `response.block_header.note_root` + // List of all notes together with the Merkle paths from `response.block_header.note_root`. repeated note.NoteSyncRecord notes = 4; } -// An account returned as a response to the GetBlockInputs +// An account returned as a response to the `GetBlockInputs`. message AccountBlockInputRecord { + // The account ID. account.AccountId account_id = 1; + + // The latest account hash, zero hash if the account doesn't exist. digest.Digest account_hash = 2; + + // Merkle path to verify the account's inclusion in the MMR. merkle.MerklePath proof = 3; } -// A nullifier returned as a response to the GetBlockInputs +// A nullifier returned as a response to the `GetBlockInputs`. message NullifierBlockInputRecord { + // The nullifier ID. digest.Digest nullifier = 1; + + // Merkle path to verify the nullifier's inclusion in the MMR. smt.SmtOpening opening = 2; } +// Represents the result of getting block inputs. message GetBlockInputsResponse { - // The latest block header + // The latest block header. block.BlockHeader block_header = 1; - // Peaks of the above block's mmr, The `forest` value is equal to the block number + // Peaks of the above block's mmr, The `forest` value is equal to the block number. repeated digest.Digest mmr_peaks = 2; - // The hashes of the requested accounts and their authentication paths + // The hashes of the requested accounts and their authentication paths. repeated AccountBlockInputRecord account_states = 3; - // The requested nullifiers and their authentication paths + // The requested nullifiers and their authentication paths. repeated NullifierBlockInputRecord nullifiers = 4; - // The list of requested notes which were found in the database + // The list of requested notes which were found in the database. note.NoteAuthenticationInfo found_unauthenticated_notes = 5; } -// An account returned as a response to the GetTransactionInputs +// An account returned as a response to the `GetTransactionInputs`. message AccountTransactionInputRecord { + // The account ID. account.AccountId account_id = 1; + // The latest account hash, zero hash if the account doesn't exist. digest.Digest account_hash = 2; } -// A nullifier returned as a response to the GetTransactionInputs +// A nullifier returned as a response to the `GetTransactionInputs`. message NullifierTransactionInputRecord { + // The nullifier ID. digest.Digest nullifier = 1; + // The block at which the nullifier has been consumed, zero if not consumed. fixed32 block_num = 2; } +// Represents the result of getting transaction inputs. message GetTransactionInputsResponse { + // Account state proof. AccountTransactionInputRecord account_state = 1; + + // List of nullifiers that have been consumed. repeated NullifierTransactionInputRecord nullifiers = 2; + + // List of unauthenticated notes that were not found in the database. repeated digest.Digest found_unauthenticated_notes = 3; + + // The node's current block height. fixed32 block_height = 4; } +// Represents the result of submitting proven transaction. message SubmitProvenTransactionResponse { - // The node's current block height + // The node's current block height. fixed32 block_height = 1; } +// Represents the result of getting notes by IDs. message GetNotesByIdResponse { - // Lists Note's returned by the database + // Lists Note's returned by the database. repeated note.Note notes = 1; } +// Represents the result of getting note authentication info. message GetNoteAuthenticationInfoResponse { + // Proofs of note inclusions in blocks and block inclusions in chain. note.NoteAuthenticationInfo proofs = 1; } +// Represents the result of getting account details. message GetAccountDetailsResponse { - // Account info (with details for public accounts) + // Account info (with details for public accounts). account.AccountInfo details = 1; } +// Represents the result of getting block by number. message GetBlockByNumberResponse { - // The requested `Block` data encoded using miden native format + // The requested block data encoded using [winter_utils::Serializable] implementation for + // [miden_objects::block::Block]. optional bytes block = 1; } +// Represents the result of getting account state delta. message GetAccountStateDeltaResponse { - // The calculated `AccountStateDelta` encoded using miden native format + // The calculated account delta encoded using [winter_utils::Serializable] implementation + // for [miden_objects::accounts::delta::AccountDelta]. optional bytes delta = 1; } +// Represents the result of getting account proofs. message GetAccountProofsResponse { // Block number at which the state of the account was returned. fixed32 block_num = 1; @@ -166,6 +207,7 @@ message GetAccountProofsResponse { repeated AccountProofsResponse account_proofs = 2; } +// A single account proof returned as a response to the `GetAccountProofs`. message AccountProofsResponse { // Account ID. account.AccountId account_id = 1; @@ -177,6 +219,7 @@ message AccountProofsResponse { optional AccountStateHeader state_header = 4; } +// State header for public accounts. message AccountStateHeader { // Account header. account.AccountHeader header = 1; diff --git a/crates/rpc-proto/proto/rpc.proto b/crates/rpc-proto/proto/rpc.proto index 13934b2c4..bd5d359ad 100644 --- a/crates/rpc-proto/proto/rpc.proto +++ b/crates/rpc-proto/proto/rpc.proto @@ -6,15 +6,55 @@ import "requests.proto"; import "responses.proto"; service Api { + // Gets a list of proofs for given nullifier hashes, each proof as a sparse Merkle Tree. rpc CheckNullifiers(requests.CheckNullifiersRequest) returns (responses.CheckNullifiersResponse) {} + + // Returns a list of nullifiers that match the specified prefixes and are recorded in the node. rpc CheckNullifiersByPrefix(requests.CheckNullifiersByPrefixRequest) returns (responses.CheckNullifiersByPrefixResponse) {} + + // Returns the latest state of an account with the specified ID. rpc GetAccountDetails(requests.GetAccountDetailsRequest) returns (responses.GetAccountDetailsResponse) {} + + // Returns the latest state proofs of the specified accounts. rpc GetAccountProofs(requests.GetAccountProofsRequest) returns (responses.GetAccountProofsResponse) {} + + // Returns delta of the account states in the range from `from_block_num` (exclusive) to + // `to_block_num` (inclusive). rpc GetAccountStateDelta(requests.GetAccountStateDeltaRequest) returns (responses.GetAccountStateDeltaResponse) {} + + // Retrieves block data by given block number. rpc GetBlockByNumber(requests.GetBlockByNumberRequest) returns (responses.GetBlockByNumberResponse) {} + + // Retrieves block header by given block number. Optionally, it also returns the MMR path + // and current chain length to authenticate the block's inclusion. rpc GetBlockHeaderByNumber(requests.GetBlockHeaderByNumberRequest) returns (responses.GetBlockHeaderByNumberResponse) {} + + // Returns a list of notes matching the provided note IDs. rpc GetNotesById(requests.GetNotesByIdRequest) returns (responses.GetNotesByIdResponse) {} + + // Submits proven transaction to the Miden network. rpc SubmitProvenTransaction(requests.SubmitProvenTransactionRequest) returns (responses.SubmitProvenTransactionResponse) {} + + // Note synchronization request. + // + // Specifies note tags that client is interested in. The server will return the first block which + // contains a note matching `note_tags` or the chain tip. rpc SyncNotes(requests.SyncNoteRequest) returns (responses.SyncNoteResponse) {} + + // Returns info which can be used by the client to sync up to the latest state of the chain + // for the objects (accounts, notes, nullifiers) the client is interested in. + // + // This request returns the next block containing requested data. It also returns `chain_tip` + // which is the latest block number in the chain. Client is expected to repeat these requests + // in a loop until `response.block_header.block_num == response.chain_tip`, at which point + // the client is fully synchronized with the chain. + // + // Each request also returns info about new notes, nullifiers etc. created. It also returns + // Chain MMR delta that can be used to update the state of Chain MMR. This includes both chain + // MMR peaks and chain MMR nodes. + // + // For preserving some degree of privacy, note tags and nullifiers filters contain only high + // part of hashes. Thus, returned data contains excessive notes and nullifiers, client can make + // additional filtering of that data on its side. rpc SyncState(requests.SyncStateRequest) returns (responses.SyncStateResponse) {} } diff --git a/crates/rpc-proto/proto/smt.proto b/crates/rpc-proto/proto/smt.proto index d62634dd4..484508b1b 100644 --- a/crates/rpc-proto/proto/smt.proto +++ b/crates/rpc-proto/proto/smt.proto @@ -1,4 +1,4 @@ -// Message definitions related to Sparse Merkle Trees (SMT). +// Message definitions related to Sparse Merkle Trees (SMT) syntax = "proto3"; package smt; @@ -6,27 +6,40 @@ package smt; import "digest.proto"; import "merkle.proto"; -// An entry in a leaf. +// Represents a single SMT leaf entry. message SmtLeafEntry { + // The key of the entry. digest.Digest key = 1; + + // The value of the entry. digest.Digest value = 2; } +// Represents multiple leaf entries in an SMT. message SmtLeafEntries { + // The entries list. repeated SmtLeafEntry entries = 1; } // A leaf in an SMT, sitting at depth 64. A leaf can contain 0, 1 or multiple leaf entries. message SmtLeaf { oneof leaf { + // An empty leaf. uint64 empty = 1; + + // A single leaf entry. SmtLeafEntry single = 2; + + // Multiple leaf entries. SmtLeafEntries multiple = 3; } } // The opening of a leaf in an SMT. message SmtOpening { + // The merkle path to the leaf. merkle.MerklePath path = 1; + + // The leaf itself. SmtLeaf leaf = 2; } diff --git a/crates/rpc-proto/proto/store.proto b/crates/rpc-proto/proto/store.proto index b51198b96..5ed980aba 100644 --- a/crates/rpc-proto/proto/store.proto +++ b/crates/rpc-proto/proto/store.proto @@ -8,18 +8,64 @@ import "requests.proto"; import "responses.proto"; service Api { + // Applies changes of a new block to the DB and in-memory data structures. rpc ApplyBlock(requests.ApplyBlockRequest) returns (responses.ApplyBlockResponse) {} + + // Gets a list of proofs for given nullifier hashes, each proof as a sparse Merkle Tree. rpc CheckNullifiers(requests.CheckNullifiersRequest) returns (responses.CheckNullifiersResponse) {} + + // Returns a list of nullifiers that match the specified prefixes and are recorded in the node. rpc CheckNullifiersByPrefix(requests.CheckNullifiersByPrefixRequest) returns (responses.CheckNullifiersByPrefixResponse) {} + + // Returns the latest state of an account with the specified ID. rpc GetAccountDetails(requests.GetAccountDetailsRequest) returns (responses.GetAccountDetailsResponse) {} + + // Returns the latest state proofs of the specified accounts. rpc GetAccountProofs(requests.GetAccountProofsRequest) returns (responses.GetAccountProofsResponse) {} + + // Returns delta of the account states in the range from `from_block_num` (exclusive) to + // `to_block_num` (inclusive). rpc GetAccountStateDelta(requests.GetAccountStateDeltaRequest) returns (responses.GetAccountStateDeltaResponse) {} + + // Retrieves block data by given block number. rpc GetBlockByNumber(requests.GetBlockByNumberRequest) returns (responses.GetBlockByNumberResponse) {} + + // Retrieves block header by given block number. Optionally, it also returns the MMR path + // and current chain length to authenticate the block's inclusion. rpc GetBlockHeaderByNumber(requests.GetBlockHeaderByNumberRequest) returns (responses.GetBlockHeaderByNumberResponse) {} + + // Returns data required to prove the next block. rpc GetBlockInputs(requests.GetBlockInputsRequest) returns (responses.GetBlockInputsResponse) {} + + // Returns a list of Note inclusion proofs for the specified Note IDs. rpc GetNoteAuthenticationInfo(requests.GetNoteAuthenticationInfoRequest) returns (responses.GetNoteAuthenticationInfoResponse) {} + + // Returns a list of notes matching the provided note IDs. rpc GetNotesById(requests.GetNotesByIdRequest) returns (responses.GetNotesByIdResponse) {} + + // Returns data required to validate a new transaction. rpc GetTransactionInputs(requests.GetTransactionInputsRequest) returns (responses.GetTransactionInputsResponse) {} + + // Note synchronization request. + // + // Specifies note tags that client is interested in. The server will return the first block which + // contains a note matching `note_tags` or the chain tip. rpc SyncNotes(requests.SyncNoteRequest) returns (responses.SyncNoteResponse) {} + + // Returns info which can be used by the client to sync up to the latest state of the chain + // for the objects (accounts, notes, nullifiers) the client is interested in. + // + // This request returns the next block containing requested data. It also returns `chain_tip` + // which is the latest block number in the chain. Client is expected to repeat these requests + // in a loop until `response.block_header.block_num == response.chain_tip`, at which point + // the client is fully synchronized with the chain. + // + // Each request also returns info about new notes, nullifiers etc. created. It also returns + // Chain MMR delta that can be used to update the state of Chain MMR. This includes both chain + // MMR peaks and chain MMR nodes. + // + // For preserving some degree of privacy, note tags and nullifiers filters contain only high + // part of hashes. Thus, returned data contains excessive notes and nullifiers, client can make + // additional filtering of that data on its side. rpc SyncState(requests.SyncStateRequest) returns (responses.SyncStateResponse) {} } diff --git a/crates/rpc-proto/proto/transaction.proto b/crates/rpc-proto/proto/transaction.proto index 996b15bc4..9a9520c61 100644 --- a/crates/rpc-proto/proto/transaction.proto +++ b/crates/rpc-proto/proto/transaction.proto @@ -4,13 +4,21 @@ package transaction; import "account.proto"; import "digest.proto"; +// Represents a transaction ID. message TransactionId { + // The transaction ID. digest.Digest id = 1; } +// Represents a transaction summary. message TransactionSummary { + // A unique 32-byte identifier of a transaction. TransactionId transaction_id = 1; + + // The block number in which the transaction was executed. fixed32 block_num = 2; + + // The ID of the account affected by the transaction. account.AccountId account_id = 3; } diff --git a/crates/rpc-proto/src/lib.rs b/crates/rpc-proto/src/lib.rs index 17711f2bc..d48a1afa9 100644 --- a/crates/rpc-proto/src/lib.rs +++ b/crates/rpc-proto/src/lib.rs @@ -17,8 +17,7 @@ pub fn write_proto(target_dir: &std::path::Path) -> Result<(), std::string::Stri }; if !target_dir.exists() { - fs::create_dir_all(target_dir) - .map_err(|err| format!("Error creating directory: {}", err))?; + fs::create_dir_all(target_dir).map_err(|err| format!("Error creating directory: {err}"))?; } else if !target_dir.is_dir() { return Err("The target path exists but is not a directory".to_string()); } @@ -26,10 +25,10 @@ pub fn write_proto(target_dir: &std::path::Path) -> Result<(), std::string::Stri for (file_name, file_content) in PROTO_FILES { let mut file_path = target_dir.to_path_buf(); file_path.push(file_name); - let mut file = File::create(&file_path) - .map_err(|err| format!("Error creating {}: {}", file_name, err))?; + let mut file = + File::create(&file_path).map_err(|err| format!("Error creating {file_name}: {err}"))?; file.write_all(file_content.as_bytes()) - .map_err(|err| format!("Error writing {}: {}", file_name, err))?; + .map_err(|err| format!("Error writing {file_name}: {err}"))?; } Ok(()) diff --git a/crates/rpc/Cargo.toml b/crates/rpc/Cargo.toml index c8e8ab167..3dfba5246 100644 --- a/crates/rpc/Cargo.toml +++ b/crates/rpc/Cargo.toml @@ -11,6 +11,9 @@ authors.workspace = true homepage.workspace = true repository.workspace = true +[lints] +workspace = true + [dependencies] miden-node-proto = { workspace = true } miden-node-utils = { workspace = true } diff --git a/crates/rpc/README.md b/crates/rpc/README.md index d069f4f57..500e56ebd 100644 --- a/crates/rpc/README.md +++ b/crates/rpc/README.md @@ -54,7 +54,7 @@ Retrieves block data by given block number. **Returns:** -- `block`: `Block` – block data encoded in Miden native format. +- `block`: `Block` – block data encoded using [winter_utils::Serializable](https://github.com/facebook/winterfell/blob/main/utils/core/src/serde/mod.rs#L26) implementation for [miden_objects::block::Block](https://github.com/0xPolygonMiden/miden-base/blob/main/objects/src/block/mod.rs#L43). ### GetNotesById @@ -119,7 +119,7 @@ Submits proven transaction to the Miden network. **Parameters** -- `transaction`: `bytes` - transaction encoded using Miden's native format. +- `transaction`: `bytes` - transaction encoded using [winter_utils::Serializable](https://github.com/facebook/winterfell/blob/main/utils/core/src/serde/mod.rs#L26) implementation for [miden_objects::transaction::proven_tx::ProvenTransaction](https://github.com/0xPolygonMiden/miden-base/blob/main/objects/src/transaction/proven_tx.rs#L22). **Returns** diff --git a/crates/rpc/src/server/api.rs b/crates/rpc/src/server/api.rs index 96bca8096..6afad672f 100644 --- a/crates/rpc/src/server/api.rs +++ b/crates/rpc/src/server/api.rs @@ -72,7 +72,7 @@ impl api_server::Api for RpcApi { debug!(target: COMPONENT, request = ?request.get_ref()); // validate all the nullifiers from the user request - for nullifier in request.get_ref().nullifiers.iter() { + for nullifier in &request.get_ref().nullifiers { let _: Digest = nullifier .try_into() .or(Err(Status::invalid_argument("Digest field is not in the modulus range")))?; @@ -162,7 +162,7 @@ impl api_server::Api for RpcApi { let note_ids = request.get_ref().note_ids.clone(); let _: Vec = try_convert(note_ids) - .map_err(|err| Status::invalid_argument(format!("Invalid NoteId: {}", err)))?; + .map_err(|err| Status::invalid_argument(format!("Invalid NoteId: {err}")))?; self.store.clone().get_notes_by_id(request).await } diff --git a/crates/store/Cargo.toml b/crates/store/Cargo.toml index 6ca51bb4b..8eec38f27 100644 --- a/crates/store/Cargo.toml +++ b/crates/store/Cargo.toml @@ -11,6 +11,9 @@ authors.workspace = true homepage.workspace = true repository.workspace = true +[lints] +workspace = true + [dependencies] deadpool-sqlite = { version = "0.9.0", features = ["rt_tokio_1"] } hex = { version = "0.4" } diff --git a/crates/store/README.md b/crates/store/README.md index a201956df..2932726ca 100644 --- a/crates/store/README.md +++ b/crates/store/README.md @@ -70,11 +70,11 @@ Retrieves block data by given block number. **Returns:** -- `block`: `Block` – block data encoded in Miden native format. +- `block`: `Block` – block data encoded using [winter_utils::Serializable](https://github.com/facebook/winterfell/blob/main/utils/core/src/serde/mod.rs#L26) implementation for [miden_objects::block::Block](https://github.com/0xPolygonMiden/miden-base/blob/main/objects/src/block/mod.rs#L43). ### GetBlockInputs -Returns data needed by the block producer to construct and prove the next block. +Returns data required to prove the next block. **Parameters** @@ -90,12 +90,12 @@ Returns data needed by the block producer to construct and prove the next block. ### GetTransactionInputs -Returns the data needed by the block producer to check validity of an incoming transaction. +Returns data required to validate a new transaction. **Parameters** - `account_id`: `AccountId` – ID of the account against which a transaction is executed. -- `nullifiers`: `[Digest]` – array of nullifiers for all notes consumed by a transaction. +- `nullifiers`: `[Digest]` – set of nullifiers consumed by this transaction. **Returns** diff --git a/crates/store/src/config.rs b/crates/store/src/config.rs index 447b5721d..3cac20a77 100644 --- a/crates/store/src/config.rs +++ b/crates/store/src/config.rs @@ -14,7 +14,7 @@ use serde::{Deserialize, Serialize}; pub struct StoreConfig { /// Defines the listening socket. pub endpoint: Endpoint, - /// SQLite database file + /// `SQLite` database file pub database_filepath: PathBuf, /// Genesis file pub genesis_filepath: PathBuf, diff --git a/crates/store/src/db/mod.rs b/crates/store/src/db/mod.rs index 64e0ebdb0..fc466d502 100644 --- a/crates/store/src/db/mod.rs +++ b/crates/store/src/db/mod.rs @@ -256,7 +256,7 @@ impl Db { self.pool .get() .await? - .interact(move |conn| sql::select_block_headers(conn, blocks)) + .interact(move |conn| sql::select_block_headers(conn, &blocks)) .await .map_err(|err| { DatabaseError::InteractError(format!( diff --git a/crates/store/src/db/sql/mod.rs b/crates/store/src/db/sql/mod.rs index fa93a26ec..a6539b7c8 100644 --- a/crates/store/src/db/sql/mod.rs +++ b/crates/store/src/db/sql/mod.rs @@ -66,7 +66,7 @@ pub fn select_all_accounts(conn: &mut Connection) -> Result> { let mut accounts = vec![]; while let Some(row) = rows.next()? { - accounts.push(account_info_from_row(row)?) + accounts.push(account_info_from_row(row)?); } Ok(accounts) } @@ -93,12 +93,12 @@ pub fn select_all_account_hashes(conn: &mut Connection) -> Result (None, None), @@ -571,9 +572,12 @@ pub fn insert_nullifiers_for_block( )?; let mut count = 0; - for nullifier in nullifiers.iter() { - count += - stmt.execute(params![nullifier.to_bytes(), get_nullifier_prefix(nullifier), block_num])? + for nullifier in nullifiers { + count += stmt.execute(params![ + nullifier.to_bytes(), + get_nullifier_prefix(nullifier), + block_num + ])?; } Ok(count) } @@ -606,7 +610,7 @@ pub fn select_all_nullifiers(conn: &mut Connection) -> Result Result> { metadata, details, merkle_path, - }) + }); } Ok(notes) } @@ -784,8 +788,8 @@ pub fn insert_notes(transaction: &Transaction, notes: &[NoteRecord]) -> Result Result< note_id: note_id.into(), metadata, merkle_path, - }) + }); } Ok(notes) } -/// Select note inclusion proofs matching the NoteId, using the given [Connection]. +/// Select note inclusion proofs matching the `NoteId`, using the given [Connection]. /// /// # Returns /// @@ -985,7 +989,7 @@ pub fn select_note_inclusion_proofs( // BLOCK CHAIN QUERIES // ================================================================================================ -/// Insert a [BlockHeader] to the DB using the given [Transaction]. +/// Insert a [`BlockHeader`] to the DB using the given [Transaction]. /// /// # Returns /// @@ -1001,7 +1005,7 @@ pub fn insert_block_header(transaction: &Transaction, block_header: &BlockHeader Ok(stmt.execute(params![block_header.block_num(), block_header.to_bytes()])?) } -/// Select a [BlockHeader] from the DB by its `block_num` using the given [Connection]. +/// Select a [`BlockHeader`] from the DB by its `block_num` using the given [Connection]. /// /// # Returns /// @@ -1012,18 +1016,15 @@ pub fn select_block_header_by_block_num( block_number: Option, ) -> Result> { let mut stmt; - let mut rows = match block_number { - Some(block_number) => { - stmt = - conn.prepare_cached("SELECT block_header FROM block_headers WHERE block_num = ?1")?; - stmt.query([block_number])? - }, - None => { - stmt = conn.prepare_cached( - "SELECT block_header FROM block_headers ORDER BY block_num DESC LIMIT 1", - )?; - stmt.query([])? - }, + let mut rows = if let Some(block_number) = block_number { + stmt = + conn.prepare_cached("SELECT block_header FROM block_headers WHERE block_num = ?1")?; + stmt.query([block_number])? + } else { + stmt = conn.prepare_cached( + "SELECT block_header FROM block_headers ORDER BY block_num DESC LIMIT 1", + )?; + stmt.query([])? }; match rows.next()? { @@ -1043,10 +1044,10 @@ pub fn select_block_header_by_block_num( /// /// # Returns /// -/// A vector of [BlockHeader] or an error. +/// A vector of [`BlockHeader`] or an error. pub fn select_block_headers( conn: &mut Connection, - blocks: Vec, + blocks: &[BlockNumber], ) -> Result> { let mut headers = Vec::with_capacity(blocks.len()); @@ -1068,7 +1069,7 @@ pub fn select_block_headers( /// /// # Returns /// -/// A vector of [BlockHeader] or an error. +/// A vector of [`BlockHeader`] or an error. pub fn select_all_block_headers(conn: &mut Connection) -> Result> { let mut stmt = conn.prepare_cached("SELECT block_header FROM block_headers ORDER BY block_num ASC;")?; @@ -1109,7 +1110,7 @@ pub fn insert_transactions( let account_id = update.account_id(); for transaction_id in update.transactions() { count += - stmt.execute(params![transaction_id.to_bytes(), account_id.to_bytes(), block_num])? + stmt.execute(params![transaction_id.to_bytes(), account_id.to_bytes(), block_num])?; } } Ok(count) @@ -1120,7 +1121,7 @@ pub fn insert_transactions( /// /// # Returns /// -/// The vector of [RpoDigest] with the transaction IDs. +/// The vector of [`RpoDigest`] with the transaction IDs. pub fn select_transactions_by_accounts_and_block_range( conn: &mut Connection, block_start: BlockNumber, diff --git a/crates/store/src/db/sql/utils.rs b/crates/store/src/db/sql/utils.rs index 03faf052c..0787acd28 100644 --- a/crates/store/src/db/sql/utils.rs +++ b/crates/store/src/db/sql/utils.rs @@ -50,7 +50,7 @@ macro_rules! subst { /// insert_sql!(users { id, first_name, last_name, age }); /// ``` /// which generates: -/// "INSERT INTO users (id, first_name, last_name, age) VALUES (?, ?, ?, ?)" +/// "INSERT INTO users (id, `first_name`, `last_name`, age) VALUES (?, ?, ?, ?)" macro_rules! insert_sql { ($table:ident { $first_field:ident $(, $($field:ident),+)? $(,)? }) => { concat!( @@ -71,6 +71,10 @@ macro_rules! insert_sql { /// Sqlite uses `i64` as its internal representation format. Note that the `as` operator performs a /// lossless conversion from `u64` to `i64`. pub fn u64_to_value(v: u64) -> Value { + #[allow( + clippy::cast_possible_wrap, + reason = "We store u64 as i64 as sqlite only allows the latter." + )] Value::Integer(v as i64) } @@ -83,6 +87,10 @@ pub fn column_value_as_u64( index: I, ) -> rusqlite::Result { let value: i64 = row.get(index)?; + #[allow( + clippy::cast_sign_loss, + reason = "We store u64 as i64 as sqlite only allows the latter." + )] Ok(value as u64) } diff --git a/crates/store/src/db/tests.rs b/crates/store/src/db/tests.rs index b931e850e..0ae53e9eb 100644 --- a/crates/store/src/db/tests.rs +++ b/crates/store/src/db/tests.rs @@ -1,3 +1,6 @@ +#![allow(clippy::similar_names, reason = "naming dummy test values is hard")] +#![allow(clippy::too_many_lines, reason = "test code can be long")] + use miden_lib::transaction::TransactionKernel; use miden_node_proto::domain::accounts::AccountSummary; use miden_objects::{ @@ -173,13 +176,13 @@ fn sql_select_notes() { let note = NoteRecord { block_num, note_index: BlockNoteIndex::new(0, i as usize).unwrap(), - note_id: num_to_rpo_digest(i as u64), + note_id: num_to_rpo_digest(u64::from(i)), metadata: NoteMetadata::new( ACCOUNT_ID_OFF_CHAIN_SENDER.try_into().unwrap(), NoteType::Public, i.into(), NoteExecutionHint::none(), - Default::default(), + Felt::default(), ) .unwrap(), details: Some(vec![1, 2, 3]), @@ -219,7 +222,7 @@ fn sql_select_notes_different_execution_hints() { NoteType::Public, 0.into(), NoteExecutionHint::none(), - Default::default(), + Felt::default(), ) .unwrap(), details: Some(vec![1, 2, 3]), @@ -243,7 +246,7 @@ fn sql_select_notes_different_execution_hints() { NoteType::Public, 1.into(), NoteExecutionHint::always(), - Default::default(), + Felt::default(), ) .unwrap(), details: Some(vec![1, 2, 3]), @@ -267,7 +270,7 @@ fn sql_select_notes_different_execution_hints() { NoteType::Public, 2.into(), NoteExecutionHint::after_block(12).unwrap(), - Default::default(), + Felt::default(), ) .unwrap(), details: Some(vec![1, 2, 3]), @@ -302,7 +305,7 @@ fn sql_select_accounts() { AccountType::RegularAccountImmutableCode, miden_objects::accounts::AccountStorageMode::Private, ); - let account_hash = num_to_rpo_digest(i as u64); + let account_hash = num_to_rpo_digest(u64::from(i)); state.push(AccountInfo { summary: AccountSummary { account_id, account_hash, block_num }, details: None, @@ -606,8 +609,8 @@ fn sql_select_nullifiers_by_block_range() { #[test] fn select_nullifiers_by_prefix() { - let mut conn = create_db(); const PREFIX_LEN: u32 = 16; + let mut conn = create_db(); // test empty table let nullifiers = sql::select_nullifiers_by_prefix(&mut conn, PREFIX_LEN, &[]).unwrap(); assert!(nullifiers.is_empty()); @@ -869,7 +872,7 @@ fn notes() { .unwrap(); let values = [(note_index, note_id.into(), note_metadata)]; - let notes_db = BlockNoteTree::with_entries(values.iter().cloned()).unwrap(); + let notes_db = BlockNoteTree::with_entries(values.iter().copied()).unwrap(); let details = Some(vec![1, 2, 3]); let merkle_path = notes_db.get_note_path(note_index); @@ -882,7 +885,7 @@ fn notes() { NoteType::Public, tag.into(), NoteExecutionHint::none(), - Default::default(), + Felt::default(), ) .unwrap(), details, @@ -948,7 +951,7 @@ fn notes() { let note_0 = res[0].clone(); let note_1 = res[1].clone(); assert_eq!(note_0.details, Some(vec![1, 2, 3])); - assert_eq!(note_1.details, None) + assert_eq!(note_1.details, None); } // UTILITIES diff --git a/crates/store/src/genesis.rs b/crates/store/src/genesis.rs index 98bf5379f..ada75543e 100644 --- a/crates/store/src/genesis.rs +++ b/crates/store/src/genesis.rs @@ -74,7 +74,7 @@ impl GenesisState { impl Serializable for GenesisState { fn write_into(&self, target: &mut W) { - assert!(self.accounts.len() <= u64::MAX as usize, "too many accounts in GenesisState"); + assert!(u64::try_from(self.accounts.len()).is_ok(), "too many accounts in GenesisState"); target.write_usize(self.accounts.len()); target.write_many(&self.accounts); diff --git a/crates/store/src/nullifier_tree.rs b/crates/store/src/nullifier_tree.rs index 282b27f44..81c197330 100644 --- a/crates/store/src/nullifier_tree.rs +++ b/crates/store/src/nullifier_tree.rs @@ -94,7 +94,7 @@ mod tests { let block_num = 123; let nullifier_value = NullifierTree::block_num_to_leaf_value(block_num); - assert_eq!(nullifier_value, [Felt::from(block_num), ZERO, ZERO, ZERO]) + assert_eq!(nullifier_value, [Felt::from(block_num), ZERO, ZERO, ZERO]); } #[test] diff --git a/crates/store/src/server/api.rs b/crates/store/src/server/api.rs index 1eb5f3627..efdd68438 100644 --- a/crates/store/src/server/api.rs +++ b/crates/store/src/server/api.rs @@ -259,7 +259,7 @@ impl api_server::Api for StoreApi { let note_ids = request.into_inner().note_ids; let note_ids: Vec = try_convert(note_ids) - .map_err(|err| Status::invalid_argument(format!("Invalid NoteId: {}", err)))?; + .map_err(|err| Status::invalid_argument(format!("Invalid NoteId: {err}")))?; let note_ids: Vec = note_ids.into_iter().map(From::from).collect(); @@ -274,7 +274,7 @@ impl api_server::Api for StoreApi { Ok(Response::new(GetNotesByIdResponse { notes })) } - /// Returns a list of Note inclusion proofs for the specified NoteId's. + /// Returns the inclusion proofs of the specified notes. #[instrument( target = COMPONENT, name = "store:get_note_inclusion_proofs", @@ -291,7 +291,7 @@ impl api_server::Api for StoreApi { let note_ids = request.into_inner().note_ids; let note_ids: Vec = try_convert(note_ids) - .map_err(|err| Status::invalid_argument(format!("Invalid NoteId: {}", err)))?; + .map_err(|err| Status::invalid_argument(format!("Invalid NoteId: {err}")))?; let note_ids = note_ids.into_iter().map(From::from).collect(); @@ -485,11 +485,11 @@ impl api_server::Api for StoreApi { let include_headers = include_headers.unwrap_or_default(); let request_code_commitments: BTreeSet = try_convert(code_commitments) - .map_err(|err| Status::invalid_argument(format!("Invalid code commitment: {}", err)))?; + .map_err(|err| Status::invalid_argument(format!("Invalid code commitment: {err}")))?; let account_requests: Vec = try_convert(account_requests).map_err(|err| { - Status::invalid_argument(format!("Invalid account proofs request: {}", err)) + Status::invalid_argument(format!("Invalid account proofs request: {err}")) })?; let (block_num, infos) = self @@ -545,7 +545,7 @@ fn invalid_argument(err: E) -> Status { fn read_account_id(id: Option) -> Result { id.ok_or(invalid_argument("missing account ID"))? .try_into() - .map_err(|err| invalid_argument(format!("invalid account ID: {}", err))) + .map_err(|err| invalid_argument(format!("invalid account ID: {err}"))) } #[instrument(target = COMPONENT, skip_all, err)] @@ -564,7 +564,7 @@ fn read_account_ids( fn validate_nullifiers(nullifiers: &[generated::digest::Digest]) -> Result, Status> { nullifiers .iter() - .cloned() + .copied() .map(TryInto::try_into) .collect::>() .map_err(|_| invalid_argument("Digest field is not in the modulus range")) diff --git a/crates/store/src/state.rs b/crates/store/src/state.rs index ab1e0045b..176d6cffd 100644 --- a/crates/store/src/state.rs +++ b/crates/store/src/state.rs @@ -233,7 +233,7 @@ impl State { .nullifiers() .iter() .filter(|&n| inner.nullifier_tree.get_block_num(n).is_some()) - .cloned() + .copied() .collect(); if !duplicate_nullifiers.is_empty() { return Err(InvalidBlockError::DuplicatedNullifiers(duplicate_nullifiers).into()); @@ -290,10 +290,10 @@ impl State { let details = match note { OutputNote::Full(note) => Some(note.to_bytes()), OutputNote::Header(_) => None, - note => { + note @ OutputNote::Partial(_) => { return Err(InvalidBlockError::InvalidOutputNoteType(Box::new( note.clone(), - ))) + ))); }, }; @@ -422,10 +422,10 @@ impl State { nullifiers.iter().map(|n| inner.nullifier_tree.open(n)).collect() } - /// Queries a list of [NoteRecord] from the database. + /// Queries a list of [`NoteRecord`] from the database. /// - /// If the provided list of [NoteId] given is empty or no [NoteRecord] matches the provided - /// [NoteId] an empty list is returned. + /// If the provided list of [`NoteId`] given is empty or no [`NoteRecord`] matches the provided + /// [`NoteId`] an empty list is returned. pub async fn get_notes_by_id( &self, note_ids: Vec, @@ -607,7 +607,7 @@ impl State { })?; let account_states = account_ids .iter() - .cloned() + .copied() .map(|account_id| { let ValuePath { value: account_hash, path: proof } = inner.account_tree.open(&LeafIndex::new_max_depth(account_id.prefix().into())); @@ -691,7 +691,7 @@ impl State { let account_ids: Vec = account_requests.iter().map(|req| req.account_id).collect(); - let state_headers = if !include_headers { + let state_headers = if include_headers.not() { BTreeMap::::default() } else { let infos = self.db.select_accounts_by_ids(account_ids.clone()).await?; @@ -724,7 +724,7 @@ impl State { let proof = storage_map.open(map_key); let slot_map_key = StorageSlotMapProof { - storage_slot: *storage_index as u32, + storage_slot: u32::from(*storage_index), smt_proof: proof.to_bytes(), }; storage_slot_map_keys.push(slot_map_key); diff --git a/crates/test-macro/Cargo.toml b/crates/test-macro/Cargo.toml index fdd7b06b0..4f1b3b15b 100644 --- a/crates/test-macro/Cargo.toml +++ b/crates/test-macro/Cargo.toml @@ -11,6 +11,9 @@ authors.workspace = true homepage.workspace = true repository.workspace = true +[lints] +workspace = true + [dependencies] quote = { version = "1.0" } syn = { version = "2.0" , features = ["full", "extra-traits"]} diff --git a/crates/utils/Cargo.toml b/crates/utils/Cargo.toml index 75f19675b..001f0d463 100644 --- a/crates/utils/Cargo.toml +++ b/crates/utils/Cargo.toml @@ -11,6 +11,9 @@ authors.workspace = true homepage.workspace = true repository.workspace = true +[lints] +workspace = true + [features] # Enables depedencies intended for build script generation of version metadata. vergen = ["dep:vergen", "dep:vergen-gitcl"] diff --git a/crates/utils/src/formatting.rs b/crates/utils/src/formatting.rs index 642eaf2ab..38e980b14 100644 --- a/crates/utils/src/formatting.rs +++ b/crates/utils/src/formatting.rs @@ -14,7 +14,7 @@ pub fn format_account_id(id: u64) -> String { } pub fn format_opt(opt: Option<&T>) -> String { - opt.map(ToString::to_string).unwrap_or("None".to_owned()) + opt.map_or("None".to_owned(), ToString::to_string) } pub fn format_input_notes(notes: &InputNotes) -> String { @@ -43,7 +43,7 @@ pub fn format_map<'a, K: Display + 'a, V: Display + 'a>( if map_str.is_empty() { "None".to_owned() } else { - format!("{{ {} }}", map_str) + format!("{{ {map_str} }}") } } @@ -52,7 +52,7 @@ pub fn format_array(list: impl IntoIterator) -> String { if comma_separated.is_empty() { "None".to_owned() } else { - format!("[{}]", comma_separated) + format!("[{comma_separated}]") } } diff --git a/crates/utils/src/version/mod.rs b/crates/utils/src/version/mod.rs index 18f2c5036..98f3c096c 100644 --- a/crates/utils/src/version/mod.rs +++ b/crates/utils/src/version/mod.rs @@ -6,7 +6,7 @@ pub use vergen::vergen; /// /// The build metadata can be embedded at compile time using the `vergen` function /// available from the `vergen` feature. See that functions description for a list -/// of the environment variables emitted which map nicely to [LongVersion]. +/// of the environment variables emitted which map nicely to [`LongVersion`]. /// /// Unfortunately these values must be transferred manually by the end user since the /// env variables are only available once the caller's build script has run - which is diff --git a/proto/account.proto b/proto/account.proto index 6614b7bc7..f2c1d6e50 100644 --- a/proto/account.proto +++ b/proto/account.proto @@ -3,30 +3,49 @@ package account; import "digest.proto"; +// Uniquely identifies a specific account. +// +// A Miden account ID is a 120-bit value derived from the commitments to account code and storage, +// and a random user-provided seed. message AccountId { - // A Miden account ID is a 120-bit value derived from the commitments to account code and - // storage, and a random user-provided seed. + // 15 bytes (120 bits) encoded using [winter_utils::Serializable] implementation for + // [miden_objects::accounts::account_id::AccountId]. bytes id = 1; } +// The state of an account at a specific block height. message AccountSummary { + // The account ID. AccountId account_id = 1; + + // The current account hash or zero if the account does not exist. digest.Digest account_hash = 2; + + // Block number at which the summary was made. uint32 block_num = 3; } +// An account info. message AccountInfo { + // Account summary. AccountSummary summary = 1; + + // Account details encoded using [winter_utils::Serializable] implementation for + // [miden_objects::accounts::Account]. optional bytes details = 2; } +// An account header. message AccountHeader { // Vault root hash. digest.Digest vault_root = 1; + // Storage root hash. digest.Digest storage_commitment = 2; + // Code root hash. digest.Digest code_commitment = 3; + // Account nonce. uint64 nonce = 4; } diff --git a/proto/block.proto b/proto/block.proto index 616f927b4..f9a41a99c 100644 --- a/proto/block.proto +++ b/proto/block.proto @@ -4,34 +4,50 @@ package block; import "digest.proto"; import "merkle.proto"; +// Represents a block header. message BlockHeader { - // specifies the version of the protocol. + // Specifies the version of the protocol. uint32 version = 1; - // the hash of the previous blocks header. + + // The hash of the previous blocks header. digest.Digest prev_hash = 2; - // a unique sequential number of the current block. + + // A unique sequential number of the current block. fixed32 block_num = 3; - // a commitment to an MMR of the entire chain where each block is a leaf. + + // A commitment to an MMR of the entire chain where each block is a leaf. digest.Digest chain_root = 4; - // a commitment to account database. + + // A commitment to account database. digest.Digest account_root = 5; - // a commitment to the nullifier database. + + // A commitment to the nullifier database. digest.Digest nullifier_root = 6; - // a commitment to all notes created in the current block. + + // A commitment to all notes created in the current block. digest.Digest note_root = 7; - // a commitment to a set of IDs of transactions which affected accounts in this block. + + // A commitment to a set of IDs of transactions which affected accounts in this block. digest.Digest tx_hash = 8; - // a hash of a STARK proof attesting to the correct state transition. + + // A hash of a STARK proof attesting to the correct state transition. digest.Digest proof_hash = 9; - // a commitment to all transaction kernels supported by this block. + + // A commitment to all transaction kernels supported by this block. digest.Digest kernel_root = 10; - // the time when the block was created. + + // The time when the block was created. fixed32 timestamp = 11; } +// Represents a block inclusion proof. message BlockInclusionProof { + // Block header associated with the inclusion proof. BlockHeader block_header = 1; + + // Merkle path associated with the inclusion proof. merkle.MerklePath mmr_path = 2; + // The chain length associated with `mmr_path`. fixed32 chain_length = 3; } diff --git a/proto/block_producer.proto b/proto/block_producer.proto index d4f2c0062..054c14912 100644 --- a/proto/block_producer.proto +++ b/proto/block_producer.proto @@ -6,6 +6,7 @@ import "requests.proto"; import "responses.proto"; service Api { + // Submits proven transaction to the Miden network rpc SubmitProvenTransaction(requests.SubmitProvenTransactionRequest) returns (responses.SubmitProvenTransactionResponse) {} } diff --git a/proto/merkle.proto b/proto/merkle.proto index abded7231..88336deda 100644 --- a/proto/merkle.proto +++ b/proto/merkle.proto @@ -3,6 +3,8 @@ package merkle; import "digest.proto"; +// Represents a Merkle path. message MerklePath { + // List of sibling node hashes, in order from the root to the leaf. repeated digest.Digest siblings = 1; } diff --git a/proto/mmr.proto b/proto/mmr.proto index baaced2c9..f5e60e570 100644 --- a/proto/mmr.proto +++ b/proto/mmr.proto @@ -3,7 +3,11 @@ package mmr; import "digest.proto"; +// Represents an MMR delta. message MmrDelta { + // The number of leaf nodes in the MMR. uint64 forest = 1; + + // New and changed MMR peaks. repeated digest.Digest data = 2; } diff --git a/proto/note.proto b/proto/note.proto index d424f696b..f65960d67 100644 --- a/proto/note.proto +++ b/proto/note.proto @@ -6,42 +6,86 @@ import "block.proto"; import "digest.proto"; import "merkle.proto"; +// Represents a note's metadata. message NoteMetadata { + // The account which sent the note. account.AccountId sender = 1; + + // The type of the note (0b01 = public, 0b10 = private, 0b11 = encrypted). uint32 note_type = 2; + + // A value which can be used by the recipient(s) to identify notes intended for them. + // + // See `miden_objects::notes::note_tag` for more info. fixed32 tag = 3; + + // Specifies when a note is ready to be consumed. + // + // See `miden_objects::notes::execution_hint` for more info. fixed64 execution_hint = 4; + + // An arbitrary user-defined value. fixed64 aux = 5; } +// Represents a note. message Note { + // The block number in which the note was created. fixed32 block_num = 1; + + // The index of the note in the block. uint32 note_index = 2; + + // The ID of the note. digest.Digest note_id = 3; + + // The note's metadata. NoteMetadata metadata = 4; + + // The note's inclusion proof in the block. merkle.MerklePath merkle_path = 5; - // This field will be present when the note is public. - // details contain the `Note` in a serialized format. + + // Serialized details of the public note (empty for private notes). optional bytes details = 6; } +// Represents a proof of note's inclusion in a block. +// +// Does not include proof of the block's inclusion in the chain. message NoteInclusionInBlockProof { + // A unique identifier of the note which is a 32-byte commitment to the underlying note data. digest.Digest note_id = 1; + + // The block number in which the note was created. fixed32 block_num = 2; + + // The index of the note in the block. uint32 note_index_in_block = 3; + + // The note's inclusion proof in the block. merkle.MerklePath merkle_path = 4; } +// Represents proof of a note inclusion in the block. message NoteSyncRecord { + // The index of the note. uint32 note_index = 1; + + // A unique identifier of the note which is a 32-byte commitment to the underlying note data. digest.Digest note_id = 2; + + // The note's metadata. NoteMetadata metadata = 3; + + // The note's inclusion proof in the block. merkle.MerklePath merkle_path = 4; } +// Represents proof of notes inclusion in the block(s) and block(s) inclusion in the chain. message NoteAuthenticationInfo { // Proof of each note's inclusion in a block. repeated note.NoteInclusionInBlockProof note_proofs = 1; + // Proof of each block's inclusion in the chain. repeated block.BlockInclusionProof block_proofs = 2; } diff --git a/proto/requests.proto b/proto/requests.proto index 62ec750a1..b8e2e0817 100644 --- a/proto/requests.proto +++ b/proto/requests.proto @@ -3,9 +3,11 @@ package requests; import "account.proto"; import "digest.proto"; -import "note.proto"; +// Applies changes of a new block to the DB and in-memory data structures. message ApplyBlockRequest { + // Block data encoded using [winter_utils::Serializable] implementation for + // [miden_objects::block::Block]. bytes block = 1; } @@ -14,11 +16,13 @@ message CheckNullifiersByPrefixRequest { // Number of bits used for nullifier prefix. Currently the only supported value is 16. uint32 prefix_len = 1; // List of nullifiers to check. Each nullifier is specified by its prefix with length equal - // to prefix_len + // to `prefix_len`. repeated uint32 nullifiers = 2; } +// Get a list of proofs for given nullifier hashes, each proof as a sparse Merkle Tree. message CheckNullifiersRequest { + // List of nullifiers to return proofs for. repeated digest.Digest nullifiers = 1; } @@ -27,9 +31,7 @@ message CheckNullifiersRequest { // // The Merkle path is an MMR proof for the block's leaf, based on the current chain length. message GetBlockHeaderByNumberRequest { - // The block number of the target block. - // - // If not provided, means latest known block. + // The target block height, defaults to latest if not provided. optional uint32 block_num = 1; // Whether or not to return authentication data for the block header. optional bool include_mmr_proof = 2; @@ -74,33 +76,45 @@ message SyncNoteRequest { repeated fixed32 note_tags = 2; } +// Returns data required to prove the next block. message GetBlockInputsRequest { // ID of the account against which a transaction is executed. repeated account.AccountId account_ids = 1; - // Array of nullifiers for all notes consumed by a transaction. + // Set of nullifiers consumed by this transaction. repeated digest.Digest nullifiers = 2; // Array of note IDs to be checked for existence in the database. repeated digest.Digest unauthenticated_notes = 3; } +// Returns data required to validate a new transaction. message GetTransactionInputsRequest { + // ID of the account against which a transaction is executed. account.AccountId account_id = 1; + // Set of nullifiers consumed by this transaction. repeated digest.Digest nullifiers = 2; + // Set of unauthenticated notes to check for existence on-chain. + // + // These are notes which were not on-chain at the state the transaction was proven, + // but could by now be present. repeated digest.Digest unauthenticated_notes = 3; } +// Submits proven transaction to the Miden network. message SubmitProvenTransactionRequest { - // Transaction encoded using miden's native format + // Transaction encoded using [winter_utils::Serializable] implementation for + // [miden_objects::transaction::proven_tx::ProvenTransaction]. bytes transaction = 1; } +// Returns a list of notes matching the provided note IDs. message GetNotesByIdRequest { - // List of NoteId's to be queried from the database + // List of notes to be queried from the database. repeated digest.Digest note_ids = 1; } +// Returns a list of Note inclusion proofs for the specified Note IDs. message GetNoteAuthenticationInfoRequest { - // List of NoteId's to be queried from the database + // List of notes to be queried from the database. repeated digest.Digest note_ids = 1; } @@ -110,6 +124,7 @@ message GetAccountDetailsRequest { account.AccountId account_id = 1; } +// Retrieves block data by given block number. message GetBlockByNumberRequest { // The block number of the target block. fixed32 block_num = 1; @@ -126,9 +141,9 @@ message GetAccountStateDeltaRequest { fixed32 to_block_num = 3; } -// Request message to get account proofs. +// Returns the latest state proofs of the specified accounts. message GetAccountProofsRequest { - // Represents per-account requests where each account ID has its own list of + // Represents per-account requests where each account ID has its own list of // (storage_slot_index, map_keys) pairs. message AccountRequest { // The account ID for this request. @@ -154,7 +169,7 @@ message GetAccountProofsRequest { // requests are also ignored. False by default. optional bool include_headers = 2; - // Account code commitments corresponding to the last-known `AccountCode` for requested + // Account code commitments corresponding to the last-known `AccountCode` for requested // accounts. Responses will include only the ones that are not known to the caller. // These are not associated with a specific account but rather, they will be matched against // all requested accounts. diff --git a/proto/responses.proto b/proto/responses.proto index 530a5dc18..860368e67 100644 --- a/proto/responses.proto +++ b/proto/responses.proto @@ -10,63 +10,73 @@ import "note.proto"; import "smt.proto"; import "transaction.proto"; +// Represents the result of applying a block. message ApplyBlockResponse {} +// Represents the result of checking nullifiers. message CheckNullifiersResponse { // Each requested nullifier has its corresponding nullifier proof at the same position. repeated smt.SmtOpening proofs = 1; } +// Represents the result of checking nullifiers by prefix. message CheckNullifiersByPrefixResponse { // List of nullifiers matching the prefixes specified in the request. repeated NullifierUpdate nullifiers = 1; } +// Represents the result of getting a block header by block number. message GetBlockHeaderByNumberResponse { - // The requested block header + // The requested block header. block.BlockHeader block_header = 1; - // Merkle path to verify the block's inclusion in the MMR at the returned `chain_length` + // Merkle path to verify the block's inclusion in the MMR at the returned `chain_length`. optional merkle.MerklePath mmr_path = 2; - // Current chain length + // Current chain length. optional fixed32 chain_length = 3; } +// Represents a single nullifier update. message NullifierUpdate { + // Nullifier ID. digest.Digest nullifier = 1; + + // Block number. fixed32 block_num = 2; } +// Represents the result of syncing state request. message SyncStateResponse { - // Number of the latest block in the chain + // Number of the latest block in the chain. fixed32 chain_tip = 1; - // Block header of the block with the first note matching the specified criteria + // Block header of the block with the first note matching the specified criteria. block.BlockHeader block_header = 2; - // Data needed to update the partial MMR from `request.block_num + 1` to `response.block_header.block_num` + // Data needed to update the partial MMR from `request.block_num + 1` to `response.block_header.block_num`. mmr.MmrDelta mmr_delta = 3; - // List of account hashes updated after `request.block_num + 1` but not after `response.block_header.block_num` + // List of account hashes updated after `request.block_num + 1` but not after `response.block_header.block_num`. repeated account.AccountSummary accounts = 5; // List of transactions executed against requested accounts between `request.block_num + 1` and - // `response.block_header.block_num` + // `response.block_header.block_num`. repeated transaction.TransactionSummary transactions = 6; - // List of all notes together with the Merkle paths from `response.block_header.note_root` + // List of all notes together with the Merkle paths from `response.block_header.note_root`. repeated note.NoteSyncRecord notes = 7; - // List of nullifiers created between `request.block_num + 1` and `response.block_header.block_num` + // List of nullifiers created between `request.block_num + 1` and `response.block_header.block_num`. repeated NullifierUpdate nullifiers = 8; } +// Represents the result of syncing notes request. message SyncNoteResponse { - // Number of the latest block in the chain + // Number of the latest block in the chain. fixed32 chain_tip = 1; - // Block header of the block with the first note matching the specified criteria + // Block header of the block with the first note matching the specified criteria. block.BlockHeader block_header = 2; // Merkle path to verify the block's inclusion in the MMR at the returned `chain_tip`. @@ -75,90 +85,121 @@ message SyncNoteResponse { // an MMR of forest `chain_tip` with this path. merkle.MerklePath mmr_path = 3; - // List of all notes together with the Merkle paths from `response.block_header.note_root` + // List of all notes together with the Merkle paths from `response.block_header.note_root`. repeated note.NoteSyncRecord notes = 4; } -// An account returned as a response to the GetBlockInputs +// An account returned as a response to the `GetBlockInputs`. message AccountBlockInputRecord { + // The account ID. account.AccountId account_id = 1; + + // The latest account hash, zero hash if the account doesn't exist. digest.Digest account_hash = 2; + + // Merkle path to verify the account's inclusion in the MMR. merkle.MerklePath proof = 3; } -// A nullifier returned as a response to the GetBlockInputs +// A nullifier returned as a response to the `GetBlockInputs`. message NullifierBlockInputRecord { + // The nullifier ID. digest.Digest nullifier = 1; + + // Merkle path to verify the nullifier's inclusion in the MMR. smt.SmtOpening opening = 2; } +// Represents the result of getting block inputs. message GetBlockInputsResponse { - // The latest block header + // The latest block header. block.BlockHeader block_header = 1; - // Peaks of the above block's mmr, The `forest` value is equal to the block number + // Peaks of the above block's mmr, The `forest` value is equal to the block number. repeated digest.Digest mmr_peaks = 2; - // The hashes of the requested accounts and their authentication paths + // The hashes of the requested accounts and their authentication paths. repeated AccountBlockInputRecord account_states = 3; - // The requested nullifiers and their authentication paths + // The requested nullifiers and their authentication paths. repeated NullifierBlockInputRecord nullifiers = 4; - // The list of requested notes which were found in the database + // The list of requested notes which were found in the database. note.NoteAuthenticationInfo found_unauthenticated_notes = 5; } -// An account returned as a response to the GetTransactionInputs +// An account returned as a response to the `GetTransactionInputs`. message AccountTransactionInputRecord { + // The account ID. account.AccountId account_id = 1; + // The latest account hash, zero hash if the account doesn't exist. digest.Digest account_hash = 2; } -// A nullifier returned as a response to the GetTransactionInputs +// A nullifier returned as a response to the `GetTransactionInputs`. message NullifierTransactionInputRecord { + // The nullifier ID. digest.Digest nullifier = 1; + // The block at which the nullifier has been consumed, zero if not consumed. fixed32 block_num = 2; } +// Represents the result of getting transaction inputs. message GetTransactionInputsResponse { + // Account state proof. AccountTransactionInputRecord account_state = 1; + + // List of nullifiers that have been consumed. repeated NullifierTransactionInputRecord nullifiers = 2; + + // List of unauthenticated notes that were not found in the database. repeated digest.Digest found_unauthenticated_notes = 3; + + // The node's current block height. fixed32 block_height = 4; } +// Represents the result of submitting proven transaction. message SubmitProvenTransactionResponse { - // The node's current block height + // The node's current block height. fixed32 block_height = 1; } +// Represents the result of getting notes by IDs. message GetNotesByIdResponse { - // Lists Note's returned by the database + // Lists Note's returned by the database. repeated note.Note notes = 1; } +// Represents the result of getting note authentication info. message GetNoteAuthenticationInfoResponse { + // Proofs of note inclusions in blocks and block inclusions in chain. note.NoteAuthenticationInfo proofs = 1; } +// Represents the result of getting account details. message GetAccountDetailsResponse { - // Account info (with details for public accounts) + // Account info (with details for public accounts). account.AccountInfo details = 1; } +// Represents the result of getting block by number. message GetBlockByNumberResponse { - // The requested `Block` data encoded using miden native format + // The requested block data encoded using [winter_utils::Serializable] implementation for + // [miden_objects::block::Block]. optional bytes block = 1; } +// Represents the result of getting account state delta. message GetAccountStateDeltaResponse { - // The calculated `AccountStateDelta` encoded using miden native format + // The calculated account delta encoded using [winter_utils::Serializable] implementation + // for [miden_objects::accounts::delta::AccountDelta]. optional bytes delta = 1; } +// Represents the result of getting account proofs. message GetAccountProofsResponse { // Block number at which the state of the account was returned. fixed32 block_num = 1; @@ -166,6 +207,7 @@ message GetAccountProofsResponse { repeated AccountProofsResponse account_proofs = 2; } +// A single account proof returned as a response to the `GetAccountProofs`. message AccountProofsResponse { // Account ID. account.AccountId account_id = 1; @@ -177,6 +219,7 @@ message AccountProofsResponse { optional AccountStateHeader state_header = 4; } +// State header for public accounts. message AccountStateHeader { // Account header. account.AccountHeader header = 1; diff --git a/proto/rpc.proto b/proto/rpc.proto index 13934b2c4..bd5d359ad 100644 --- a/proto/rpc.proto +++ b/proto/rpc.proto @@ -6,15 +6,55 @@ import "requests.proto"; import "responses.proto"; service Api { + // Gets a list of proofs for given nullifier hashes, each proof as a sparse Merkle Tree. rpc CheckNullifiers(requests.CheckNullifiersRequest) returns (responses.CheckNullifiersResponse) {} + + // Returns a list of nullifiers that match the specified prefixes and are recorded in the node. rpc CheckNullifiersByPrefix(requests.CheckNullifiersByPrefixRequest) returns (responses.CheckNullifiersByPrefixResponse) {} + + // Returns the latest state of an account with the specified ID. rpc GetAccountDetails(requests.GetAccountDetailsRequest) returns (responses.GetAccountDetailsResponse) {} + + // Returns the latest state proofs of the specified accounts. rpc GetAccountProofs(requests.GetAccountProofsRequest) returns (responses.GetAccountProofsResponse) {} + + // Returns delta of the account states in the range from `from_block_num` (exclusive) to + // `to_block_num` (inclusive). rpc GetAccountStateDelta(requests.GetAccountStateDeltaRequest) returns (responses.GetAccountStateDeltaResponse) {} + + // Retrieves block data by given block number. rpc GetBlockByNumber(requests.GetBlockByNumberRequest) returns (responses.GetBlockByNumberResponse) {} + + // Retrieves block header by given block number. Optionally, it also returns the MMR path + // and current chain length to authenticate the block's inclusion. rpc GetBlockHeaderByNumber(requests.GetBlockHeaderByNumberRequest) returns (responses.GetBlockHeaderByNumberResponse) {} + + // Returns a list of notes matching the provided note IDs. rpc GetNotesById(requests.GetNotesByIdRequest) returns (responses.GetNotesByIdResponse) {} + + // Submits proven transaction to the Miden network. rpc SubmitProvenTransaction(requests.SubmitProvenTransactionRequest) returns (responses.SubmitProvenTransactionResponse) {} + + // Note synchronization request. + // + // Specifies note tags that client is interested in. The server will return the first block which + // contains a note matching `note_tags` or the chain tip. rpc SyncNotes(requests.SyncNoteRequest) returns (responses.SyncNoteResponse) {} + + // Returns info which can be used by the client to sync up to the latest state of the chain + // for the objects (accounts, notes, nullifiers) the client is interested in. + // + // This request returns the next block containing requested data. It also returns `chain_tip` + // which is the latest block number in the chain. Client is expected to repeat these requests + // in a loop until `response.block_header.block_num == response.chain_tip`, at which point + // the client is fully synchronized with the chain. + // + // Each request also returns info about new notes, nullifiers etc. created. It also returns + // Chain MMR delta that can be used to update the state of Chain MMR. This includes both chain + // MMR peaks and chain MMR nodes. + // + // For preserving some degree of privacy, note tags and nullifiers filters contain only high + // part of hashes. Thus, returned data contains excessive notes and nullifiers, client can make + // additional filtering of that data on its side. rpc SyncState(requests.SyncStateRequest) returns (responses.SyncStateResponse) {} } diff --git a/proto/smt.proto b/proto/smt.proto index d62634dd4..484508b1b 100644 --- a/proto/smt.proto +++ b/proto/smt.proto @@ -1,4 +1,4 @@ -// Message definitions related to Sparse Merkle Trees (SMT). +// Message definitions related to Sparse Merkle Trees (SMT) syntax = "proto3"; package smt; @@ -6,27 +6,40 @@ package smt; import "digest.proto"; import "merkle.proto"; -// An entry in a leaf. +// Represents a single SMT leaf entry. message SmtLeafEntry { + // The key of the entry. digest.Digest key = 1; + + // The value of the entry. digest.Digest value = 2; } +// Represents multiple leaf entries in an SMT. message SmtLeafEntries { + // The entries list. repeated SmtLeafEntry entries = 1; } // A leaf in an SMT, sitting at depth 64. A leaf can contain 0, 1 or multiple leaf entries. message SmtLeaf { oneof leaf { + // An empty leaf. uint64 empty = 1; + + // A single leaf entry. SmtLeafEntry single = 2; + + // Multiple leaf entries. SmtLeafEntries multiple = 3; } } // The opening of a leaf in an SMT. message SmtOpening { + // The merkle path to the leaf. merkle.MerklePath path = 1; + + // The leaf itself. SmtLeaf leaf = 2; } diff --git a/proto/store.proto b/proto/store.proto index b51198b96..5ed980aba 100644 --- a/proto/store.proto +++ b/proto/store.proto @@ -8,18 +8,64 @@ import "requests.proto"; import "responses.proto"; service Api { + // Applies changes of a new block to the DB and in-memory data structures. rpc ApplyBlock(requests.ApplyBlockRequest) returns (responses.ApplyBlockResponse) {} + + // Gets a list of proofs for given nullifier hashes, each proof as a sparse Merkle Tree. rpc CheckNullifiers(requests.CheckNullifiersRequest) returns (responses.CheckNullifiersResponse) {} + + // Returns a list of nullifiers that match the specified prefixes and are recorded in the node. rpc CheckNullifiersByPrefix(requests.CheckNullifiersByPrefixRequest) returns (responses.CheckNullifiersByPrefixResponse) {} + + // Returns the latest state of an account with the specified ID. rpc GetAccountDetails(requests.GetAccountDetailsRequest) returns (responses.GetAccountDetailsResponse) {} + + // Returns the latest state proofs of the specified accounts. rpc GetAccountProofs(requests.GetAccountProofsRequest) returns (responses.GetAccountProofsResponse) {} + + // Returns delta of the account states in the range from `from_block_num` (exclusive) to + // `to_block_num` (inclusive). rpc GetAccountStateDelta(requests.GetAccountStateDeltaRequest) returns (responses.GetAccountStateDeltaResponse) {} + + // Retrieves block data by given block number. rpc GetBlockByNumber(requests.GetBlockByNumberRequest) returns (responses.GetBlockByNumberResponse) {} + + // Retrieves block header by given block number. Optionally, it also returns the MMR path + // and current chain length to authenticate the block's inclusion. rpc GetBlockHeaderByNumber(requests.GetBlockHeaderByNumberRequest) returns (responses.GetBlockHeaderByNumberResponse) {} + + // Returns data required to prove the next block. rpc GetBlockInputs(requests.GetBlockInputsRequest) returns (responses.GetBlockInputsResponse) {} + + // Returns a list of Note inclusion proofs for the specified Note IDs. rpc GetNoteAuthenticationInfo(requests.GetNoteAuthenticationInfoRequest) returns (responses.GetNoteAuthenticationInfoResponse) {} + + // Returns a list of notes matching the provided note IDs. rpc GetNotesById(requests.GetNotesByIdRequest) returns (responses.GetNotesByIdResponse) {} + + // Returns data required to validate a new transaction. rpc GetTransactionInputs(requests.GetTransactionInputsRequest) returns (responses.GetTransactionInputsResponse) {} + + // Note synchronization request. + // + // Specifies note tags that client is interested in. The server will return the first block which + // contains a note matching `note_tags` or the chain tip. rpc SyncNotes(requests.SyncNoteRequest) returns (responses.SyncNoteResponse) {} + + // Returns info which can be used by the client to sync up to the latest state of the chain + // for the objects (accounts, notes, nullifiers) the client is interested in. + // + // This request returns the next block containing requested data. It also returns `chain_tip` + // which is the latest block number in the chain. Client is expected to repeat these requests + // in a loop until `response.block_header.block_num == response.chain_tip`, at which point + // the client is fully synchronized with the chain. + // + // Each request also returns info about new notes, nullifiers etc. created. It also returns + // Chain MMR delta that can be used to update the state of Chain MMR. This includes both chain + // MMR peaks and chain MMR nodes. + // + // For preserving some degree of privacy, note tags and nullifiers filters contain only high + // part of hashes. Thus, returned data contains excessive notes and nullifiers, client can make + // additional filtering of that data on its side. rpc SyncState(requests.SyncStateRequest) returns (responses.SyncStateResponse) {} } diff --git a/proto/transaction.proto b/proto/transaction.proto index 996b15bc4..9a9520c61 100644 --- a/proto/transaction.proto +++ b/proto/transaction.proto @@ -4,13 +4,21 @@ package transaction; import "account.proto"; import "digest.proto"; +// Represents a transaction ID. message TransactionId { + // The transaction ID. digest.Digest id = 1; } +// Represents a transaction summary. message TransactionSummary { + // A unique 32-byte identifier of a transaction. TransactionId transaction_id = 1; + + // The block number in which the transaction was executed. fixed32 block_num = 2; + + // The ID of the account affected by the transaction. account.AccountId account_id = 3; }