From 4703258c03b9a21538a100ff947375d5ec7d88df Mon Sep 17 00:00:00 2001 From: Ignacio Amigo Date: Mon, 24 Feb 2025 14:57:56 -0300 Subject: [PATCH 1/7] feat: New check nullifiers parameter --- Cargo.lock | 93 ++++++++----------- Makefile | 2 +- .../src/rpc/generated/nostd/requests.rs | 9 +- .../src/rpc/generated/nostd/responses.rs | 3 - .../src/rpc/generated/nostd/rpc.rs | 8 +- .../src/rpc/generated/std/requests.rs | 9 +- .../src/rpc/generated/std/responses.rs | 3 - .../rust-client/src/rpc/generated/std/rpc.rs | 8 +- 8 files changed, 57 insertions(+), 78 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 995ff07a2..d83d9377e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -105,9 +105,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.95" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" +checksum = "6b964d184e89d9b6b67dd2715bc8e74cf3107fb2b529990c90cf517326150bf4" [[package]] name = "arrayref" @@ -363,9 +363,9 @@ checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" [[package]] name = "cc" -version = "1.2.14" +version = "1.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3d1b2e905a3a7b00a6141adb0e4c0bb941d11caf55349d863942a1cc44e3c9" +checksum = "c736e259eea577f443d5c86c304f9f4ae0295c43f3ba05c21f1d66b5f06001af" dependencies = [ "jobserver", "libc", @@ -394,9 +394,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.30" +version = "4.5.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92b7b18d71fad5313a1e320fa9897994228ce274b60faa4d694fe0ea89cd9e6d" +checksum = "027bb0d98429ae334a8698531da7077bdf906419543a35a55c2cb1b66437d767" dependencies = [ "clap_builder", "clap_derive", @@ -404,9 +404,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.30" +version = "4.5.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a35db2071778a7344791a4fb4f95308b5673d219dee3ae348b86642574ecc90c" +checksum = "5589e0cba072e0f3d23791efac0fd8627b49c829c196a492e88168e6a669d863" dependencies = [ "anstream", "anstyle", @@ -644,9 +644,9 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "either" -version = "1.13.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "b7914353092ddf589ad78f25c5c1c21b7f80b0ff8621e7c814c3485b5306da9d" [[package]] name = "ena" @@ -1188,9 +1188,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.169" +version = "0.2.170" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" [[package]] name = "libm" @@ -1237,9 +1237,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.25" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" +checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" [[package]] name = "logos" @@ -1481,7 +1481,7 @@ dependencies = [ [[package]] name = "miden-lib" version = "0.8.0" -source = "git+https://github.com/0xPolygonMiden/miden-base?branch=next#dca16fd814bc7f7ef53c57a6edf520720e8fdfdd" +source = "git+https://github.com/0xPolygonMiden/miden-base?branch=next#f2d50bfa4a83841875570d1301adccbe164ea111" dependencies = [ "miden-assembly", "miden-objects", @@ -1536,7 +1536,7 @@ dependencies = [ [[package]] name = "miden-objects" version = "0.8.0" -source = "git+https://github.com/0xPolygonMiden/miden-base?branch=next#dca16fd814bc7f7ef53c57a6edf520720e8fdfdd" +source = "git+https://github.com/0xPolygonMiden/miden-base?branch=next#f2d50bfa4a83841875570d1301adccbe164ea111" dependencies = [ "getrandom 0.2.15", "miden-assembly", @@ -1582,17 +1582,17 @@ dependencies = [ [[package]] name = "miden-proving-service-client" version = "0.8.0" -source = "git+https://github.com/0xPolygonMiden/miden-base?branch=next#dca16fd814bc7f7ef53c57a6edf520720e8fdfdd" +source = "git+https://github.com/0xPolygonMiden/miden-base?branch=next#f2d50bfa4a83841875570d1301adccbe164ea111" dependencies = [ "async-trait", "miden-objects", "miden-tx", - "miden-tx-batch-prover", "miette", "prost", "prost-build", "protox", "thiserror 2.0.11", + "tokio", "tonic", "tonic-build", "tonic-web-wasm-client", @@ -1601,7 +1601,7 @@ dependencies = [ [[package]] name = "miden-rpc-proto" version = "0.8.0" -source = "git+https://github.com/0xPolygonMiden/miden-node?branch=next#fea7a5947fdd543c83f2fe5d4c468638fa97a131" +source = "git+https://github.com/0xPolygonMiden/miden-node?branch=next#bea3138187a6fe7d0810c2ecd7cf5e06c29f7ab1" [[package]] name = "miden-stdlib" @@ -1615,7 +1615,7 @@ dependencies = [ [[package]] name = "miden-tx" version = "0.8.0" -source = "git+https://github.com/0xPolygonMiden/miden-base?branch=next#dca16fd814bc7f7ef53c57a6edf520720e8fdfdd" +source = "git+https://github.com/0xPolygonMiden/miden-base?branch=next#f2d50bfa4a83841875570d1301adccbe164ea111" dependencies = [ "async-trait", "miden-lib", @@ -1629,19 +1629,6 @@ dependencies = [ "winter-maybe-async", ] -[[package]] -name = "miden-tx-batch-prover" -version = "0.8.0" -source = "git+https://github.com/0xPolygonMiden/miden-base?branch=next#dca16fd814bc7f7ef53c57a6edf520720e8fdfdd" -dependencies = [ - "miden-core", - "miden-crypto", - "miden-objects", - "miden-processor", - "miden-tx", - "thiserror 2.0.11", -] - [[package]] name = "miden-verifier" version = "0.12.0" @@ -1694,9 +1681,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3b1c9bd4fe1f0f8b387f6eb9eb3b4a1aa26185e5750efb9140301703f62cd1b" +checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" dependencies = [ "adler2", ] @@ -1864,9 +1851,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "owo-colors" -version = "4.1.0" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb37767f6569cd834a413442455e0f066d0d522de8630436e2a1761d9726ba56" +checksum = "1036865bb9422d3300cf723f657c2851d0e9ab12567854b1f4eba3d77decf564" [[package]] name = "parking_lot" @@ -2226,9 +2213,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +checksum = "82b568323e98e49e2a0899dcee453dd679fae22d69adf9b11dd508d1549b7e2f" dependencies = [ "bitflags", ] @@ -2290,9 +2277,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "ring" -version = "0.17.9" +version = "0.17.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e75ec5e92c4d8aede845126adc388046234541629e76029599ed35a003c7ed24" +checksum = "da5349ae27d3887ca812fb375b45a4fbb36d8d12d2df394968cd86e35683fe73" dependencies = [ "cc", "cfg-if", @@ -2497,9 +2484,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.217" +version = "1.0.218" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" dependencies = [ "serde_derive", ] @@ -2517,9 +2504,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.217" +version = "1.0.218" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" dependencies = [ "proc-macro2", "quote", @@ -2528,9 +2515,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.138" +version = "1.0.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" +checksum = "44f86c3acccc9c65b153fe1b85a3be07fe5515274ec9f0653b4a0875731c72a6" dependencies = [ "itoa", "memchr", @@ -2688,9 +2675,9 @@ checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" [[package]] name = "target-triple" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42a4d50cdb458045afc8131fd91b64904da29548bcb63c7236e0844936c13078" +checksum = "1ac9aa371f599d22256307c24a9d748c041e548cbf599f35d890f9d365361790" [[package]] name = "tempfile" @@ -3183,9 +3170,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.13.2" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c1f41ffb7cf259f1ecc2876861a17e7142e63ead296f671f81f6ae85903e0d6" +checksum = "93d59ca99a559661b96bf898d8fce28ed87935fd2bea9f05983c1464dd6c71b1" dependencies = [ "getrandom 0.3.1", "serde", @@ -3611,9 +3598,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59690dea168f2198d1a3b0cac23b8063efcd11012f10ae4698f284808c8ef603" +checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1" dependencies = [ "memchr", ] diff --git a/Makefile b/Makefile index 94250ae82..42103df3d 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ WARNINGS=RUSTDOCFLAGS="-D warnings" NODE_DIR="miden-node" NODE_REPO="https://github.com/0xPolygonMiden/miden-node.git" -NODE_BRANCH="cf87d340f394d03bf376abff06a4b36149d63b24" +NODE_BRANCH="next" PROVER_DIR="miden-base" PROVER_REPO="https://github.com/0xPolygonMiden/miden-base.git" diff --git a/crates/rust-client/src/rpc/generated/nostd/requests.rs b/crates/rust-client/src/rpc/generated/nostd/requests.rs index c8e19bb29..9194e084f 100644 --- a/crates/rust-client/src/rpc/generated/nostd/requests.rs +++ b/crates/rust-client/src/rpc/generated/nostd/requests.rs @@ -17,6 +17,9 @@ pub struct CheckNullifiersByPrefixRequest { /// to `prefix_len`. #[prost(uint32, repeated, tag = "2")] pub nullifiers: ::prost::alloc::vec::Vec, + /// Block number from which the nullifiers are requested (inclusive). + #[prost(fixed32, tag = "3")] + pub block_num: u32, } /// Returns a nullifier proof for each of the requested nullifiers. #[derive(Clone, PartialEq, ::prost::Message)] @@ -42,7 +45,7 @@ pub struct GetBlockHeaderByNumberRequest { /// /// Specifies state updates the client is interested in. The server will return the first block which /// contains a note matching `note_tags` or the chain tip. And the corresponding updates to -/// `nullifiers` and `account_ids` for that block range. +/// `account_ids` for that block range. #[derive(Clone, PartialEq, ::prost::Message)] pub struct SyncStateRequest { /// Last block known by the client. The response will contain data starting from the next block, @@ -60,10 +63,6 @@ pub struct SyncStateRequest { /// Specifies the tags which the client is interested in. #[prost(fixed32, repeated, tag = "3")] pub note_tags: ::prost::alloc::vec::Vec, - /// Determines the nullifiers the client is interested in by specifying the 16high bits of the - /// target nullifier. - #[prost(uint32, repeated, tag = "4")] - pub nullifiers: ::prost::alloc::vec::Vec, } /// Note synchronization request. /// diff --git a/crates/rust-client/src/rpc/generated/nostd/responses.rs b/crates/rust-client/src/rpc/generated/nostd/responses.rs index c3a8f5f20..ac764735d 100644 --- a/crates/rust-client/src/rpc/generated/nostd/responses.rs +++ b/crates/rust-client/src/rpc/generated/nostd/responses.rs @@ -61,9 +61,6 @@ pub struct SyncStateResponse { /// 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`. - #[prost(message, repeated, tag = "8")] - pub nullifiers: ::prost::alloc::vec::Vec, } /// Represents the result of syncing notes request. #[derive(Clone, PartialEq, ::prost::Message)] diff --git a/crates/rust-client/src/rpc/generated/nostd/rpc.rs b/crates/rust-client/src/rpc/generated/nostd/rpc.rs index 52f8ab263..8b2b19fa5 100644 --- a/crates/rust-client/src/rpc/generated/nostd/rpc.rs +++ b/crates/rust-client/src/rpc/generated/nostd/rpc.rs @@ -342,19 +342,19 @@ pub mod api_client { 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. + /// for the objects (accounts and notes) 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 + /// Each update response also contains info about new notes, accounts 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 + /// For preserving some degree of privacy, note tags contain only high + /// part of hashes. Thus, returned data contains excessive notes, client can make /// additional filtering of that data on its side. pub async fn sync_state( &mut self, diff --git a/crates/rust-client/src/rpc/generated/std/requests.rs b/crates/rust-client/src/rpc/generated/std/requests.rs index c8e19bb29..9194e084f 100644 --- a/crates/rust-client/src/rpc/generated/std/requests.rs +++ b/crates/rust-client/src/rpc/generated/std/requests.rs @@ -17,6 +17,9 @@ pub struct CheckNullifiersByPrefixRequest { /// to `prefix_len`. #[prost(uint32, repeated, tag = "2")] pub nullifiers: ::prost::alloc::vec::Vec, + /// Block number from which the nullifiers are requested (inclusive). + #[prost(fixed32, tag = "3")] + pub block_num: u32, } /// Returns a nullifier proof for each of the requested nullifiers. #[derive(Clone, PartialEq, ::prost::Message)] @@ -42,7 +45,7 @@ pub struct GetBlockHeaderByNumberRequest { /// /// Specifies state updates the client is interested in. The server will return the first block which /// contains a note matching `note_tags` or the chain tip. And the corresponding updates to -/// `nullifiers` and `account_ids` for that block range. +/// `account_ids` for that block range. #[derive(Clone, PartialEq, ::prost::Message)] pub struct SyncStateRequest { /// Last block known by the client. The response will contain data starting from the next block, @@ -60,10 +63,6 @@ pub struct SyncStateRequest { /// Specifies the tags which the client is interested in. #[prost(fixed32, repeated, tag = "3")] pub note_tags: ::prost::alloc::vec::Vec, - /// Determines the nullifiers the client is interested in by specifying the 16high bits of the - /// target nullifier. - #[prost(uint32, repeated, tag = "4")] - pub nullifiers: ::prost::alloc::vec::Vec, } /// Note synchronization request. /// diff --git a/crates/rust-client/src/rpc/generated/std/responses.rs b/crates/rust-client/src/rpc/generated/std/responses.rs index c3a8f5f20..ac764735d 100644 --- a/crates/rust-client/src/rpc/generated/std/responses.rs +++ b/crates/rust-client/src/rpc/generated/std/responses.rs @@ -61,9 +61,6 @@ pub struct SyncStateResponse { /// 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`. - #[prost(message, repeated, tag = "8")] - pub nullifiers: ::prost::alloc::vec::Vec, } /// Represents the result of syncing notes request. #[derive(Clone, PartialEq, ::prost::Message)] diff --git a/crates/rust-client/src/rpc/generated/std/rpc.rs b/crates/rust-client/src/rpc/generated/std/rpc.rs index 60f359f30..ead9572b1 100644 --- a/crates/rust-client/src/rpc/generated/std/rpc.rs +++ b/crates/rust-client/src/rpc/generated/std/rpc.rs @@ -353,19 +353,19 @@ pub mod api_client { 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. + /// for the objects (accounts and notes) 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 + /// Each update response also contains info about new notes, accounts 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 + /// For preserving some degree of privacy, note tags contain only high + /// part of hashes. Thus, returned data contains excessive notes, client can make /// additional filtering of that data on its side. pub async fn sync_state( &mut self, From ab17d69e3933acccef8f77282e424bb8f9968af9 Mon Sep 17 00:00:00 2001 From: tomasarrachea Date: Fri, 21 Feb 2025 11:18:36 -0300 Subject: [PATCH 2/7] chore: Merge --- CHANGELOG.md | 1 + crates/rust-client/src/mock.rs | 14 ++--------- crates/rust-client/src/note/import.rs | 9 +++++-- crates/rust-client/src/rpc/domain/sync.rs | 25 +------------------ crates/rust-client/src/rpc/mod.rs | 12 +++++++-- .../rust-client/src/rpc/tonic_client/mod.rs | 7 +++--- .../src/rpc/web_tonic_client/mod.rs | 6 ++--- crates/rust-client/src/sync/mod.rs | 2 +- 8 files changed, 28 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f10ae5715..9edf19049 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ * [BREAKING] Refactored authentication out of the `Client` and added new separate authenticators (#718). * Re-exported RemoteTransactionProver in `rust-client` (#752). * Moved error handling to the `TransactionRequestBuilder::build()` (#750). +* [BREAKING] Added starting block number parameter to `CheckNullifiersByPrefix` (#749). ## 0.7.0 (2025-01-28) diff --git a/crates/rust-client/src/mock.rs b/crates/rust-client/src/mock.rs index d3cafbea4..cb51e01d2 100644 --- a/crates/rust-client/src/mock.rs +++ b/crates/rust-client/src/mock.rs @@ -39,7 +39,7 @@ use crate::{ generated::{ merkle::MerklePath, note::NoteSyncRecord, - responses::{NullifierUpdate, SyncNoteResponse, SyncStateResponse}, + responses::{SyncNoteResponse, SyncStateResponse}, }, NodeRpcClient, RpcError, }, @@ -164,16 +164,6 @@ impl MockRpcApi { // Collect notes that are in the next block let notes = self.get_notes_in_block(next_block_num).collect(); - // Collect nullifiers from the next block - let nullifiers = next_block - .created_nullifiers() - .iter() - .map(|n| NullifierUpdate { - nullifier: Some(n.inner().into()), - block_num: next_block_num.as_u32(), - }) - .collect(); - SyncStateResponse { chain_tip: self.get_chain_tip_block_num().as_u32(), block_header: Some(next_block.header().into()), @@ -181,7 +171,6 @@ impl MockRpcApi { accounts: vec![], transactions: vec![], notes, - nullifiers, } } @@ -303,6 +292,7 @@ impl NodeRpcClient for MockRpcApi { async fn check_nullifiers_by_prefix( &mut self, _prefix: &[u16], + _block_num: BlockNumber, ) -> Result, RpcError> { // Always return an empty list for now since it's only used when importing Ok(vec![]) diff --git a/crates/rust-client/src/note/import.rs b/crates/rust-client/src/note/import.rs index 248218966..d696de2fb 100644 --- a/crates/rust-client/src/note/import.rs +++ b/crates/rust-client/src/note/import.rs @@ -153,8 +153,13 @@ impl Client { .into(), )); - if let Some(block_height) = - self.rpc_api.get_nullifier_commit_height(¬e_record.nullifier()).await? + if let Some(block_height) = self + .rpc_api + .get_nullifier_commit_height( + ¬e_record.nullifier(), + inclusion_proof.location().block_num(), + ) + .await? { if note_record.consumed_externally(note_record.nullifier(), block_height)? { return Ok(Some(note_record)); diff --git a/crates/rust-client/src/rpc/domain/sync.rs b/crates/rust-client/src/rpc/domain/sync.rs index 5ae69680e..fc4855da5 100644 --- a/crates/rust-client/src/rpc/domain/sync.rs +++ b/crates/rust-client/src/rpc/domain/sync.rs @@ -9,7 +9,7 @@ use miden_objects::{ Digest, }; -use super::{note::CommittedNote, nullifier::NullifierUpdate, transaction::TransactionUpdate}; +use super::{note::CommittedNote, transaction::TransactionUpdate}; use crate::rpc::{generated::responses::SyncStateResponse, RpcError}; // STATE SYNC INFO @@ -27,9 +27,6 @@ pub struct StateSyncInfo { pub account_hash_updates: Vec<(AccountId, Digest)>, /// List of tuples of Note ID, Note Index and Merkle Path for all new notes. pub note_inclusions: Vec, - /// List of nullifiers that identify spent notes along with the block number at which they were - /// consumed. - pub nullifiers: Vec, /// List of transaction IDs of transaction that were included in (`request.block_num`, /// `response.block_num-1`) along with the account the tx was executed against and the block /// number the transaction was included in. @@ -101,25 +98,6 @@ impl TryFrom for StateSyncInfo { note_inclusions.push(committed_note); } - let nullifiers = value - .nullifiers - .iter() - .map(|nul_update| { - let nullifier_digest = nul_update - .nullifier - .ok_or(RpcError::ExpectedDataMissing("Nullifier".into()))?; - - let nullifier_digest = Digest::try_from(nullifier_digest)?; - - let nullifier_block_num = nul_update.block_num; - - Ok(NullifierUpdate { - nullifier: nullifier_digest.into(), - block_num: nullifier_block_num, - }) - }) - .collect::, RpcError>>()?; - let transactions = value .transactions .iter() @@ -150,7 +128,6 @@ impl TryFrom for StateSyncInfo { mmr_delta, account_hash_updates, note_inclusions, - nullifiers, transactions, }) } diff --git a/crates/rust-client/src/rpc/mod.rs b/crates/rust-client/src/rpc/mod.rs index a8b92a083..39867f827 100644 --- a/crates/rust-client/src/rpc/mod.rs +++ b/crates/rust-client/src/rpc/mod.rs @@ -161,9 +161,14 @@ pub trait NodeRpcClient { /// Fetches the nullifiers corresponding to a list of prefixes using the /// `/CheckNullifiersByPrefix` RPC endpoint. + /// + /// - `prefix` is a list of nullifiers prefixes to search for. + /// - `block_num` is the block number to start the search from. Nullifiers created in this block + /// or the following blocks will be included. async fn check_nullifiers_by_prefix( &mut self, prefix: &[u16], + block_num: BlockNumber, ) -> Result, RpcError>; /// Fetches the account data needed to perform a Foreign Procedure Invocation (FPI) on the @@ -180,14 +185,17 @@ pub trait NodeRpcClient { /// Fetches the commit height where the nullifier was consumed. If the nullifier isn't found, /// then `None` is returned. + /// The `block_num` parameter is the block number to start the search from. /// /// The default implementation of this method uses [NodeRpcClient::check_nullifiers_by_prefix]. async fn get_nullifier_commit_height( &mut self, nullifier: &Nullifier, + block_num: BlockNumber, ) -> Result, RpcError> { - let nullifiers = - self.check_nullifiers_by_prefix(&[get_nullifier_prefix(nullifier)]).await?; + let nullifiers = self + .check_nullifiers_by_prefix(&[get_nullifier_prefix(nullifier)], block_num) + .await?; Ok(nullifiers.iter().find(|(n, _)| n == nullifier).map(|(_, block_num)| *block_num)) } diff --git a/crates/rust-client/src/rpc/tonic_client/mod.rs b/crates/rust-client/src/rpc/tonic_client/mod.rs index 06e413ce3..11e336a87 100644 --- a/crates/rust-client/src/rpc/tonic_client/mod.rs +++ b/crates/rust-client/src/rpc/tonic_client/mod.rs @@ -203,19 +203,16 @@ impl NodeRpcClient for TonicRpcClient { block_num: BlockNumber, account_ids: &[AccountId], note_tags: &[NoteTag], - nullifiers_tags: &[u16], + _nullifiers_tags: &[u16], ) -> Result { let account_ids = account_ids.iter().map(|acc| (*acc).into()).collect(); - let nullifiers = nullifiers_tags.iter().map(|&nullifier| u32::from(nullifier)).collect(); - let note_tags = note_tags.iter().map(|¬e_tag| note_tag.into()).collect(); let request = SyncStateRequest { block_num: block_num.as_u32(), account_ids, note_tags, - nullifiers, }; let rpc_api = self.rpc_api().await?; @@ -395,10 +392,12 @@ impl NodeRpcClient for TonicRpcClient { async fn check_nullifiers_by_prefix( &mut self, prefixes: &[u16], + block_num: BlockNumber, ) -> Result, RpcError> { let request = CheckNullifiersByPrefixRequest { nullifiers: prefixes.iter().map(|&x| u32::from(x)).collect(), prefix_len: 16, + block_num: block_num.as_u32(), }; let rpc_api = self.rpc_api().await?; let response = rpc_api.check_nullifiers_by_prefix(request).await.map_err(|err| { diff --git a/crates/rust-client/src/rpc/web_tonic_client/mod.rs b/crates/rust-client/src/rpc/web_tonic_client/mod.rs index fcb808438..cba842380 100644 --- a/crates/rust-client/src/rpc/web_tonic_client/mod.rs +++ b/crates/rust-client/src/rpc/web_tonic_client/mod.rs @@ -181,19 +181,17 @@ impl NodeRpcClient for WebTonicRpcClient { block_num: BlockNumber, account_ids: &[AccountId], note_tags: &[NoteTag], - nullifiers_tags: &[u16], + _nullifiers_tags: &[u16], ) -> Result { let mut query_client = self.build_api_client(); let account_ids = account_ids.iter().map(|acc| (*acc).into()).collect(); - let nullifiers = nullifiers_tags.iter().map(|&nullifier| u32::from(nullifier)).collect(); let note_tags = note_tags.iter().map(|¬e_tag| note_tag.into()).collect(); let request = SyncStateRequest { block_num: block_num.as_u32(), account_ids, note_tags, - nullifiers, }; let response = query_client.sync_state(request).await.map_err(|err| { @@ -373,12 +371,14 @@ impl NodeRpcClient for WebTonicRpcClient { async fn check_nullifiers_by_prefix( &mut self, prefixes: &[u16], + block_num: BlockNumber, ) -> Result, RpcError> { let mut query_client = self.build_api_client(); let request = CheckNullifiersByPrefixRequest { nullifiers: prefixes.iter().map(|&x| u32::from(x)).collect(), prefix_len: 16, + block_num: block_num.as_u32(), }; let response = query_client.check_nullifiers_by_prefix(request).await.map_err(|err| { diff --git a/crates/rust-client/src/sync/mod.rs b/crates/rust-client/src/sync/mod.rs index 3e32bef85..bb99135be 100644 --- a/crates/rust-client/src/sync/mod.rs +++ b/crates/rust-client/src/sync/mod.rs @@ -291,7 +291,7 @@ impl Client { let transactions_to_commit = self.get_transactions_to_commit(response.transactions).await?; let (consumed_note_updates, transactions_to_discard) = - self.consumed_note_updates(response.nullifiers, &transactions_to_commit).await?; + self.consumed_note_updates(vec![], &transactions_to_commit).await?; let note_updates = committed_note_updates.combine_with(consumed_note_updates); From 624b92072a1e487ec111374e9cd5688b6a73de8d Mon Sep 17 00:00:00 2001 From: Ignacio Amigo Date: Mon, 24 Feb 2025 15:27:59 -0300 Subject: [PATCH 3/7] feat: Compatibilize new sync process (dumb approach for now) --- crates/rust-client/src/mock.rs | 6 ++---- crates/rust-client/src/rpc/mod.rs | 11 ++++------- crates/rust-client/src/rpc/tonic_client/mod.rs | 8 ++++---- .../rust-client/src/rpc/web_tonic_client/mod.rs | 10 ++++------ crates/rust-client/src/sync/mod.rs | 15 +++++++-------- 5 files changed, 21 insertions(+), 29 deletions(-) diff --git a/crates/rust-client/src/mock.rs b/crates/rust-client/src/mock.rs index cb51e01d2..8c57f4055 100644 --- a/crates/rust-client/src/mock.rs +++ b/crates/rust-client/src/mock.rs @@ -32,9 +32,7 @@ use crate::{ authenticator::{keystore::FilesystemKeyStore, ClientAuthenticator}, rpc::{ domain::{ - account::{AccountDetails, AccountProofs}, - note::{NetworkNote, NoteSyncInfo}, - sync::StateSyncInfo, + account::{AccountDetails, AccountProofs}, note::{NetworkNote, NoteSyncInfo}, nullifier::NullifierUpdate, sync::StateSyncInfo }, generated::{ merkle::MerklePath, @@ -293,7 +291,7 @@ impl NodeRpcClient for MockRpcApi { &mut self, _prefix: &[u16], _block_num: BlockNumber, - ) -> Result, RpcError> { + ) -> Result, RpcError> { // Always return an empty list for now since it's only used when importing Ok(vec![]) } diff --git a/crates/rust-client/src/rpc/mod.rs b/crates/rust-client/src/rpc/mod.rs index 39867f827..4f297a204 100644 --- a/crates/rust-client/src/rpc/mod.rs +++ b/crates/rust-client/src/rpc/mod.rs @@ -45,9 +45,7 @@ use core::fmt; use async_trait::async_trait; use domain::{ - account::{AccountDetails, AccountProofs}, - note::{NetworkNote, NoteSyncInfo}, - sync::StateSyncInfo, + account::{AccountDetails, AccountProofs}, note::{NetworkNote, NoteSyncInfo}, nullifier::NullifierUpdate, sync::StateSyncInfo }; use miden_objects::{ account::{Account, AccountCode, AccountHeader, AccountId}, @@ -84,7 +82,6 @@ pub use web_tonic_client::WebTonicRpcClient; use crate::{ store::{input_note_states::UnverifiedNoteState, InputNoteRecord}, - sync::get_nullifier_prefix, transaction::ForeignAccount, }; @@ -169,7 +166,7 @@ pub trait NodeRpcClient { &mut self, prefix: &[u16], block_num: BlockNumber, - ) -> Result, RpcError>; + ) -> Result, RpcError>; /// Fetches the account data needed to perform a Foreign Procedure Invocation (FPI) on the /// specified foreign accounts, using the `GetAccountProofs` endpoint. @@ -194,10 +191,10 @@ pub trait NodeRpcClient { block_num: BlockNumber, ) -> Result, RpcError> { let nullifiers = self - .check_nullifiers_by_prefix(&[get_nullifier_prefix(nullifier)], block_num) + .check_nullifiers_by_prefix(&[nullifier.prefix()], block_num) .await?; - Ok(nullifiers.iter().find(|(n, _)| n == nullifier).map(|(_, block_num)| *block_num)) + Ok(nullifiers.iter().find(|update| update.nullifier == *nullifier).map(|update| update.block_num)) } /// Fetches public note-related data for a list of [NoteId] and builds [InputNoteRecord]s with diff --git a/crates/rust-client/src/rpc/tonic_client/mod.rs b/crates/rust-client/src/rpc/tonic_client/mod.rs index 11e336a87..c10accf98 100644 --- a/crates/rust-client/src/rpc/tonic_client/mod.rs +++ b/crates/rust-client/src/rpc/tonic_client/mod.rs @@ -23,7 +23,7 @@ use tracing::info; use super::{ domain::{ account::{AccountProof, AccountProofs, AccountUpdateSummary}, - note::NetworkNote, + note::NetworkNote, nullifier::NullifierUpdate, }, generated::{ requests::{ @@ -393,7 +393,7 @@ impl NodeRpcClient for TonicRpcClient { &mut self, prefixes: &[u16], block_num: BlockNumber, - ) -> Result, RpcError> { + ) -> Result, RpcError> { let request = CheckNullifiersByPrefixRequest { nullifiers: prefixes.iter().map(|&x| u32::from(x)).collect(), prefix_len: 16, @@ -414,9 +414,9 @@ impl NodeRpcClient for TonicRpcClient { let nullifier = nul.nullifier.ok_or(RpcError::ExpectedDataMissing("Nullifier".to_string()))?; let nullifier = nullifier.try_into()?; - Ok((nullifier, nul.block_num)) + Ok(NullifierUpdate {nullifier,block_num: nul.block_num}) }) - .collect::, RpcError>>()?; + .collect::, RpcError>>()?; Ok(nullifiers) } } diff --git a/crates/rust-client/src/rpc/web_tonic_client/mod.rs b/crates/rust-client/src/rpc/web_tonic_client/mod.rs index cba842380..527561ad8 100644 --- a/crates/rust-client/src/rpc/web_tonic_client/mod.rs +++ b/crates/rust-client/src/rpc/web_tonic_client/mod.rs @@ -20,9 +20,7 @@ use tonic_web_wasm_client::Client; use super::{ domain::{ - account::{AccountDetails, AccountProof, AccountProofs, AccountUpdateSummary}, - note::{NetworkNote, NoteSyncInfo}, - sync::StateSyncInfo, + account::{AccountDetails, AccountProof, AccountProofs, AccountUpdateSummary}, note::{NetworkNote, NoteSyncInfo}, nullifier::NullifierUpdate, sync::StateSyncInfo }, generated::{ requests::{ @@ -372,7 +370,7 @@ impl NodeRpcClient for WebTonicRpcClient { &mut self, prefixes: &[u16], block_num: BlockNumber, - ) -> Result, RpcError> { + ) -> Result, RpcError> { let mut query_client = self.build_api_client(); let request = CheckNullifiersByPrefixRequest { @@ -397,9 +395,9 @@ impl NodeRpcClient for WebTonicRpcClient { "CheckNullifiersByPrefix response should have a `nullifier`".to_string(), ))?; let nullifier = nullifier.try_into()?; - Ok((nullifier, nul.block_num)) + Ok(NullifierUpdate {nullifier, block_num: nul.block_num}) }) - .collect::, RpcError>>()?; + .collect::, RpcError>>()?; Ok(nullifiers) } } diff --git a/crates/rust-client/src/sync/mod.rs b/crates/rust-client/src/sync/mod.rs index bb99135be..9ad50497f 100644 --- a/crates/rust-client/src/sync/mod.rs +++ b/crates/rust-client/src/sync/mod.rs @@ -56,7 +56,7 @@ //! processed and applied to the local store. use alloc::{collections::BTreeMap, vec::Vec}; -use core::cmp::max; +use core::{cmp::max, ptr::null}; use crypto::merkle::{InOrderIndex, MmrPeaks}; use miden_objects::{ @@ -229,6 +229,7 @@ impl Client { pub async fn sync_state(&mut self) -> Result { _ = self.ensure_genesis_in_place().await?; let mut total_sync_summary = SyncSummary::new_empty(0.into()); + let current_height = self.get_sync_height().await?; loop { let response = self.sync_state_once().await?; let is_last_block = matches!(response, SyncStatus::SyncedToLastBlock(_)); @@ -266,9 +267,11 @@ impl Client { .get_unspent_input_note_nullifiers() .await? .iter() - .map(get_nullifier_prefix) + .map(Nullifier::prefix) .collect(); + let nullifiers = self.rpc_api.check_nullifiers_by_prefix(&nullifiers_tags, current_block_num).await?; + // Send request let account_ids: Vec = accounts.iter().map(AccountHeader::id).collect(); let response = self @@ -291,7 +294,7 @@ impl Client { let transactions_to_commit = self.get_transactions_to_commit(response.transactions).await?; let (consumed_note_updates, transactions_to_discard) = - self.consumed_note_updates(vec![], &transactions_to_commit).await?; + self.consumed_note_updates(&nullifiers, &transactions_to_commit).await?; let note_updates = committed_note_updates.combine_with(consumed_note_updates); @@ -456,7 +459,7 @@ impl Client { /// transactions that were discarded. async fn consumed_note_updates( &mut self, - nullifiers: Vec, + nullifiers: &[NullifierUpdate], committed_transactions: &[TransactionUpdate], ) -> Result<(NoteUpdates, Vec), ClientError> { let nullifier_filter = NoteFilter::Nullifiers( @@ -662,7 +665,3 @@ impl Client { Ok(mismatched_accounts) } } - -pub(crate) fn get_nullifier_prefix(nullifier: &Nullifier) -> u16 { - (nullifier.inner()[3].as_int() >> FILTER_ID_SHIFT) as u16 -} From 5176cf799cb5df9d2b40c9107b93c65f227223a2 Mon Sep 17 00:00:00 2001 From: Ignacio Amigo Date: Mon, 24 Feb 2025 15:29:52 -0300 Subject: [PATCH 4/7] chore: Format --- crates/rust-client/src/mock.rs | 5 ++++- crates/rust-client/src/rpc/mod.rs | 14 +++++++++----- crates/rust-client/src/rpc/tonic_client/mod.rs | 7 ++++--- crates/rust-client/src/rpc/web_tonic_client/mod.rs | 9 ++++++--- crates/rust-client/src/sync/mod.rs | 11 +++++------ crates/rust-client/src/tests.rs | 9 ++++----- 6 files changed, 32 insertions(+), 23 deletions(-) diff --git a/crates/rust-client/src/mock.rs b/crates/rust-client/src/mock.rs index 8c57f4055..f09c7ea7a 100644 --- a/crates/rust-client/src/mock.rs +++ b/crates/rust-client/src/mock.rs @@ -32,7 +32,10 @@ use crate::{ authenticator::{keystore::FilesystemKeyStore, ClientAuthenticator}, rpc::{ domain::{ - account::{AccountDetails, AccountProofs}, note::{NetworkNote, NoteSyncInfo}, nullifier::NullifierUpdate, sync::StateSyncInfo + account::{AccountDetails, AccountProofs}, + note::{NetworkNote, NoteSyncInfo}, + nullifier::NullifierUpdate, + sync::StateSyncInfo, }, generated::{ merkle::MerklePath, diff --git a/crates/rust-client/src/rpc/mod.rs b/crates/rust-client/src/rpc/mod.rs index 4f297a204..eb81b59f4 100644 --- a/crates/rust-client/src/rpc/mod.rs +++ b/crates/rust-client/src/rpc/mod.rs @@ -45,7 +45,10 @@ use core::fmt; use async_trait::async_trait; use domain::{ - account::{AccountDetails, AccountProofs}, note::{NetworkNote, NoteSyncInfo}, nullifier::NullifierUpdate, sync::StateSyncInfo + account::{AccountDetails, AccountProofs}, + note::{NetworkNote, NoteSyncInfo}, + nullifier::NullifierUpdate, + sync::StateSyncInfo, }; use miden_objects::{ account::{Account, AccountCode, AccountHeader, AccountId}, @@ -190,11 +193,12 @@ pub trait NodeRpcClient { nullifier: &Nullifier, block_num: BlockNumber, ) -> Result, RpcError> { - let nullifiers = self - .check_nullifiers_by_prefix(&[nullifier.prefix()], block_num) - .await?; + let nullifiers = self.check_nullifiers_by_prefix(&[nullifier.prefix()], block_num).await?; - Ok(nullifiers.iter().find(|update| update.nullifier == *nullifier).map(|update| update.block_num)) + Ok(nullifiers + .iter() + .find(|update| update.nullifier == *nullifier) + .map(|update| update.block_num)) } /// Fetches public note-related data for a list of [NoteId] and builds [InputNoteRecord]s with diff --git a/crates/rust-client/src/rpc/tonic_client/mod.rs b/crates/rust-client/src/rpc/tonic_client/mod.rs index c10accf98..b8da37b31 100644 --- a/crates/rust-client/src/rpc/tonic_client/mod.rs +++ b/crates/rust-client/src/rpc/tonic_client/mod.rs @@ -11,7 +11,7 @@ use miden_objects::{ account::{Account, AccountCode, AccountId}, block::{BlockHeader, BlockNumber}, crypto::merkle::{MerklePath, MmrProof}, - note::{Note, NoteId, NoteInclusionProof, NoteTag, Nullifier}, + note::{Note, NoteId, NoteInclusionProof, NoteTag}, transaction::ProvenTransaction, utils::Deserializable, Digest, @@ -23,7 +23,8 @@ use tracing::info; use super::{ domain::{ account::{AccountProof, AccountProofs, AccountUpdateSummary}, - note::NetworkNote, nullifier::NullifierUpdate, + note::NetworkNote, + nullifier::NullifierUpdate, }, generated::{ requests::{ @@ -414,7 +415,7 @@ impl NodeRpcClient for TonicRpcClient { let nullifier = nul.nullifier.ok_or(RpcError::ExpectedDataMissing("Nullifier".to_string()))?; let nullifier = nullifier.try_into()?; - Ok(NullifierUpdate {nullifier,block_num: nul.block_num}) + Ok(NullifierUpdate { nullifier, block_num: nul.block_num }) }) .collect::, RpcError>>()?; Ok(nullifiers) diff --git a/crates/rust-client/src/rpc/web_tonic_client/mod.rs b/crates/rust-client/src/rpc/web_tonic_client/mod.rs index 527561ad8..64e03c181 100644 --- a/crates/rust-client/src/rpc/web_tonic_client/mod.rs +++ b/crates/rust-client/src/rpc/web_tonic_client/mod.rs @@ -10,7 +10,7 @@ use miden_objects::{ account::{Account, AccountCode, AccountId}, block::{BlockHeader, BlockNumber}, crypto::merkle::{MerklePath, MmrProof}, - note::{Note, NoteId, NoteInclusionProof, NoteTag, Nullifier}, + note::{Note, NoteId, NoteInclusionProof, NoteTag}, transaction::ProvenTransaction, utils::Deserializable, Digest, @@ -20,7 +20,10 @@ use tonic_web_wasm_client::Client; use super::{ domain::{ - account::{AccountDetails, AccountProof, AccountProofs, AccountUpdateSummary}, note::{NetworkNote, NoteSyncInfo}, nullifier::NullifierUpdate, sync::StateSyncInfo + account::{AccountDetails, AccountProof, AccountProofs, AccountUpdateSummary}, + note::{NetworkNote, NoteSyncInfo}, + nullifier::NullifierUpdate, + sync::StateSyncInfo, }, generated::{ requests::{ @@ -395,7 +398,7 @@ impl NodeRpcClient for WebTonicRpcClient { "CheckNullifiersByPrefix response should have a `nullifier`".to_string(), ))?; let nullifier = nullifier.try_into()?; - Ok(NullifierUpdate {nullifier, block_num: nul.block_num}) + Ok(NullifierUpdate { nullifier, block_num: nul.block_num }) }) .collect::, RpcError>>()?; Ok(nullifiers) diff --git a/crates/rust-client/src/sync/mod.rs b/crates/rust-client/src/sync/mod.rs index 9ad50497f..92801cc45 100644 --- a/crates/rust-client/src/sync/mod.rs +++ b/crates/rust-client/src/sync/mod.rs @@ -56,7 +56,7 @@ //! processed and applied to the local store. use alloc::{collections::BTreeMap, vec::Vec}; -use core::{cmp::max, ptr::null}; +use core::cmp::max; use crypto::merkle::{InOrderIndex, MmrPeaks}; use miden_objects::{ @@ -194,9 +194,6 @@ pub struct StateSyncUpdate { // CONSTANTS // ================================================================================================ -/// The number of bits to shift identifiers for in use of filters. -pub(crate) const FILTER_ID_SHIFT: u8 = 48; - /// Client syncronization methods. impl Client { // SYNC STATE @@ -229,7 +226,6 @@ impl Client { pub async fn sync_state(&mut self) -> Result { _ = self.ensure_genesis_in_place().await?; let mut total_sync_summary = SyncSummary::new_empty(0.into()); - let current_height = self.get_sync_height().await?; loop { let response = self.sync_state_once().await?; let is_last_block = matches!(response, SyncStatus::SyncedToLastBlock(_)); @@ -270,7 +266,10 @@ impl Client { .map(Nullifier::prefix) .collect(); - let nullifiers = self.rpc_api.check_nullifiers_by_prefix(&nullifiers_tags, current_block_num).await?; + let nullifiers = self + .rpc_api + .check_nullifiers_by_prefix(&nullifiers_tags, current_block_num) + .await?; // Send request let account_ids: Vec = accounts.iter().map(AccountHeader::id).collect(); diff --git a/crates/rust-client/src/tests.rs b/crates/rust-client/src/tests.rs index c2493ce96..f3a8a3eeb 100644 --- a/crates/rust-client/src/tests.rs +++ b/crates/rust-client/src/tests.rs @@ -312,11 +312,10 @@ async fn test_sync_state() { assert_eq!(sync_details.block_num, rpc_api.blocks.last().unwrap().header().block_num()); // verify that we now have one committed note after syncing state - assert_eq!(client.get_input_notes(NoteFilter::Committed).await.unwrap().len(), 1); - - // verify that we now have one consumed note after syncing state - assert_eq!(client.get_input_notes(NoteFilter::Consumed).await.unwrap().len(), 1); - assert_eq!(sync_details.consumed_notes.len(), 1); + // TODO: Review these next 3 asserts (see PR 758) + assert_eq!(client.get_input_notes(NoteFilter::Committed).await.unwrap().len(), 2); + assert_eq!(client.get_input_notes(NoteFilter::Consumed).await.unwrap().len(), 0); + assert_eq!(sync_details.consumed_notes.len(), 0); // verify that the latest block number has been updated assert_eq!( From b82918ebfb445ca79718d69495406cdd1f3b4383 Mon Sep 17 00:00:00 2001 From: tomyrd Date: Mon, 24 Feb 2025 17:17:53 -0300 Subject: [PATCH 5/7] feat: add generated > domain conversion for nullifier --- .../rust-client/src/rpc/domain/nullifier.rs | 19 ++++++++++++++++++- .../rust-client/src/rpc/tonic_client/mod.rs | 11 ++++------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/crates/rust-client/src/rpc/domain/nullifier.rs b/crates/rust-client/src/rpc/domain/nullifier.rs index 9834fbdb5..8934d30ba 100644 --- a/crates/rust-client/src/rpc/domain/nullifier.rs +++ b/crates/rust-client/src/rpc/domain/nullifier.rs @@ -1,6 +1,7 @@ use miden_objects::{crypto::hash::rpo::RpoDigest, note::Nullifier}; -use crate::rpc::{errors::RpcConversionError, generated::digest::Digest}; +use super::MissingFieldHelper; +use crate::rpc::{self, errors::RpcConversionError, generated::digest::Digest}; // NULLIFIER UPDATE // ================================================================================================ @@ -24,3 +25,19 @@ impl TryFrom for Nullifier { Ok(digest.into()) } } + +impl TryFrom<&rpc::generated::responses::NullifierUpdate> for NullifierUpdate { + type Error = RpcConversionError; + + fn try_from(value: &rpc::generated::responses::NullifierUpdate) -> Result { + Ok(Self { + nullifier: value + .nullifier + .ok_or(rpc::generated::responses::NullifierUpdate::missing_field("nullifier")) + .unwrap() + .try_into() + .unwrap(), + block_num: value.block_num, + }) + } +} diff --git a/crates/rust-client/src/rpc/tonic_client/mod.rs b/crates/rust-client/src/rpc/tonic_client/mod.rs index b8da37b31..3348600dc 100644 --- a/crates/rust-client/src/rpc/tonic_client/mod.rs +++ b/crates/rust-client/src/rpc/tonic_client/mod.rs @@ -411,13 +411,10 @@ impl NodeRpcClient for TonicRpcClient { let nullifiers = response .nullifiers .iter() - .map(|nul| { - let nullifier = - nul.nullifier.ok_or(RpcError::ExpectedDataMissing("Nullifier".to_string()))?; - let nullifier = nullifier.try_into()?; - Ok(NullifierUpdate { nullifier, block_num: nul.block_num }) - }) - .collect::, RpcError>>()?; + .map(TryFrom::try_from) + .collect::, _>>() + .map_err(|err| RpcError::InvalidResponse(err.to_string()))?; + Ok(nullifiers) } } From f33296e3d170457ceccbb4d508e6416f3ddc7409 Mon Sep 17 00:00:00 2001 From: tomyrd Date: Mon, 24 Feb 2025 18:11:48 -0300 Subject: [PATCH 6/7] feat: call nullifier endpoint once per sync --- crates/rust-client/src/mock.rs | 1 - crates/rust-client/src/rpc/mod.rs | 1 - .../rust-client/src/rpc/tonic_client/mod.rs | 1 - .../src/rpc/web_tonic_client/mod.rs | 1 - crates/rust-client/src/store/mod.rs | 8 ++ .../rust-client/src/store/sqlite_store/mod.rs | 13 +++ .../src/store/sqlite_store/sync.rs | 19 +++- crates/rust-client/src/store/web_store/mod.rs | 10 ++ .../src/store/web_store/sync/mod.rs | 10 ++ crates/rust-client/src/sync/mod.rs | 106 +++++++++++++----- 10 files changed, 134 insertions(+), 36 deletions(-) diff --git a/crates/rust-client/src/mock.rs b/crates/rust-client/src/mock.rs index f09c7ea7a..eb18aecbe 100644 --- a/crates/rust-client/src/mock.rs +++ b/crates/rust-client/src/mock.rs @@ -219,7 +219,6 @@ impl NodeRpcClient for MockRpcApi { block_num: BlockNumber, _account_ids: &[AccountId], _note_tags: &[NoteTag], - _nullifiers_tags: &[u16], ) -> Result { // Match request -> response through block_num let response = self.get_sync_state_request(block_num); diff --git a/crates/rust-client/src/rpc/mod.rs b/crates/rust-client/src/rpc/mod.rs index eb81b59f4..917b5a3bc 100644 --- a/crates/rust-client/src/rpc/mod.rs +++ b/crates/rust-client/src/rpc/mod.rs @@ -141,7 +141,6 @@ pub trait NodeRpcClient { block_num: BlockNumber, account_ids: &[AccountId], note_tags: &[NoteTag], - nullifiers_tags: &[u16], ) -> Result; /// Fetches the current state of an account from the node using the `/GetAccountDetails` RPC diff --git a/crates/rust-client/src/rpc/tonic_client/mod.rs b/crates/rust-client/src/rpc/tonic_client/mod.rs index 3348600dc..9a3f52b75 100644 --- a/crates/rust-client/src/rpc/tonic_client/mod.rs +++ b/crates/rust-client/src/rpc/tonic_client/mod.rs @@ -204,7 +204,6 @@ impl NodeRpcClient for TonicRpcClient { block_num: BlockNumber, account_ids: &[AccountId], note_tags: &[NoteTag], - _nullifiers_tags: &[u16], ) -> Result { let account_ids = account_ids.iter().map(|acc| (*acc).into()).collect(); diff --git a/crates/rust-client/src/rpc/web_tonic_client/mod.rs b/crates/rust-client/src/rpc/web_tonic_client/mod.rs index 64e03c181..1643b8a80 100644 --- a/crates/rust-client/src/rpc/web_tonic_client/mod.rs +++ b/crates/rust-client/src/rpc/web_tonic_client/mod.rs @@ -182,7 +182,6 @@ impl NodeRpcClient for WebTonicRpcClient { block_num: BlockNumber, account_ids: &[AccountId], note_tags: &[NoteTag], - _nullifiers_tags: &[u16], ) -> Result { let mut query_client = self.build_api_client(); diff --git a/crates/rust-client/src/store/mod.rs b/crates/rust-client/src/store/mod.rs index 2c2219153..4cb7e4aba 100644 --- a/crates/rust-client/src/store/mod.rs +++ b/crates/rust-client/src/store/mod.rs @@ -33,10 +33,12 @@ use miden_objects::{ block::{BlockHeader, BlockNumber}, crypto::merkle::{InOrderIndex, MmrPeaks}, note::{NoteId, NoteTag, Nullifier}, + transaction::TransactionId, Digest, Word, }; use crate::{ + note::NoteUpdates, sync::{NoteTagRecord, StateSyncUpdate}, transaction::{TransactionRecord, TransactionStoreUpdate}, }; @@ -309,6 +311,12 @@ pub trait Store: Send + Sync { /// - Storing new MMR authentication nodes. /// - Updating the tracked on-chain accounts. async fn apply_state_sync(&self, state_sync_update: StateSyncUpdate) -> Result<(), StoreError>; + + async fn apply_nullifiers( + &self, + note_updates: NoteUpdates, + transactions_to_discard: Vec, + ) -> Result<(), StoreError>; } // CHAIN MMR NODE FILTER diff --git a/crates/rust-client/src/store/sqlite_store/mod.rs b/crates/rust-client/src/store/sqlite_store/mod.rs index a77b623af..3d9252e3b 100644 --- a/crates/rust-client/src/store/sqlite_store/mod.rs +++ b/crates/rust-client/src/store/sqlite_store/mod.rs @@ -17,6 +17,7 @@ use miden_objects::{ block::{BlockHeader, BlockNumber}, crypto::merkle::{InOrderIndex, MmrPeaks}, note::{NoteTag, Nullifier}, + transaction::TransactionId, Digest, Word, }; use rusqlite::{types::Value, vtab::array, Connection}; @@ -27,6 +28,7 @@ use super::{ OutputNoteRecord, Store, TransactionFilter, }; use crate::{ + note::NoteUpdates, store::StoreError, sync::{NoteTagRecord, StateSyncUpdate}, transaction::{TransactionRecord, TransactionStoreUpdate}, @@ -326,6 +328,17 @@ impl Store for SqliteStore { self.interact_with_connection(SqliteStore::get_unspent_input_note_nullifiers) .await } + + async fn apply_nullifiers( + &self, + note_updates: NoteUpdates, + transactions_to_discard: Vec, + ) -> Result<(), StoreError> { + self.interact_with_connection(move |conn| { + SqliteStore::apply_nullifiers(conn, ¬e_updates, &transactions_to_discard) + }) + .await + } } // UTILS diff --git a/crates/rust-client/src/store/sqlite_store/sync.rs b/crates/rust-client/src/store/sqlite_store/sync.rs index 64df7c9c6..129b860a2 100644 --- a/crates/rust-client/src/store/sqlite_store/sync.rs +++ b/crates/rust-client/src/store/sqlite_store/sync.rs @@ -2,12 +2,13 @@ use alloc::{collections::BTreeSet, vec::Vec}; -use miden_objects::{block::BlockNumber, note::NoteTag}; +use miden_objects::{block::BlockNumber, note::NoteTag, transaction::TransactionId}; use miden_tx::utils::{Deserializable, Serializable}; use rusqlite::{params, Connection, Transaction}; use super::SqliteStore; use crate::{ + note::NoteUpdates, store::{ sqlite_store::{ account::{lock_account, update_account}, @@ -152,6 +153,22 @@ impl SqliteStore { Ok(()) } + + pub(super) fn apply_nullifiers( + conn: &mut Connection, + note_updates: &NoteUpdates, + transactions_to_discard: &[TransactionId], + ) -> Result<(), StoreError> { + let tx = conn.transaction()?; + + apply_note_updates_tx(&tx, note_updates)?; + + Self::mark_transactions_as_discarded(&tx, transactions_to_discard)?; + + tx.commit()?; + + Ok(()) + } } pub(super) fn add_note_tag_tx(tx: &Transaction<'_>, tag: &NoteTagRecord) -> Result<(), StoreError> { diff --git a/crates/rust-client/src/store/web_store/mod.rs b/crates/rust-client/src/store/web_store/mod.rs index b19c9b15a..7a433adb0 100644 --- a/crates/rust-client/src/store/web_store/mod.rs +++ b/crates/rust-client/src/store/web_store/mod.rs @@ -14,6 +14,7 @@ use miden_objects::{ block::{BlockHeader, BlockNumber}, crypto::merkle::{InOrderIndex, MmrPeaks}, note::Nullifier, + transaction::TransactionId, Digest, Word, }; use tonic::async_trait; @@ -25,6 +26,7 @@ use super::{ OutputNoteRecord, Store, StoreError, TransactionFilter, }; use crate::{ + note::NoteUpdates, sync::{NoteTagRecord, StateSyncUpdate}, transaction::{TransactionRecord, TransactionStoreUpdate}, }; @@ -83,6 +85,14 @@ impl Store for WebStore { self.apply_state_sync(state_sync_update).await } + async fn apply_nullifiers( + &self, + note_updates: NoteUpdates, + transactions_to_discard: Vec, + ) -> Result<(), StoreError> { + self.apply_nullifiers(note_updates, transactions_to_discard).await + } + // TRANSACTIONS // -------------------------------------------------------------------------------------------- diff --git a/crates/rust-client/src/store/web_store/sync/mod.rs b/crates/rust-client/src/store/web_store/sync/mod.rs index 91a4f9aa6..bf55a0ea7 100644 --- a/crates/rust-client/src/store/web_store/sync/mod.rs +++ b/crates/rust-client/src/store/web_store/sync/mod.rs @@ -7,6 +7,7 @@ use miden_objects::{ account::AccountId, block::BlockNumber, note::{NoteId, NoteTag}, + transaction::TransactionId, }; use miden_tx::utils::{Deserializable, Serializable}; use serde_wasm_bindgen::from_value; @@ -19,6 +20,7 @@ use super::{ WebStore, }; use crate::{ + note::NoteUpdates, store::StoreError, sync::{NoteTagRecord, NoteTagSource, StateSyncUpdate}, }; @@ -185,4 +187,12 @@ impl WebStore { Ok(()) } + + pub(super) async fn apply_nullifiers( + &self, + note_updates: NoteUpdates, + _transactions_to_discard: Vec, + ) -> Result<(), StoreError> { + apply_note_updates_tx(¬e_updates).await + } } diff --git a/crates/rust-client/src/sync/mod.rs b/crates/rust-client/src/sync/mod.rs index 92801cc45..9a3c70406 100644 --- a/crates/rust-client/src/sync/mod.rs +++ b/crates/rust-client/src/sync/mod.rs @@ -75,6 +75,7 @@ use crate::{ note::CommittedNote, nullifier::NullifierUpdate, transaction::TransactionUpdate, }, store::{AccountUpdates, InputNoteRecord, NoteFilter, OutputNoteRecord, TransactionFilter}, + transaction::TransactionStatus, Client, ClientError, }; @@ -224,6 +225,8 @@ impl Client { /// 7. The MMR is updated with the new peaks and authentication nodes. /// 8. All updates are applied to the store to be persisted. pub async fn sync_state(&mut self) -> Result { + let starting_block_num = self.get_sync_height().await?; + _ = self.ensure_genesis_in_place().await?; let mut total_sync_summary = SyncSummary::new_empty(0.into()); loop { @@ -236,6 +239,7 @@ impl Client { } } self.update_mmr_data().await?; + total_sync_summary.combine_with(self.apply_nullifiers(starting_block_num).await?); Ok(total_sync_summary) } @@ -254,49 +258,23 @@ impl Client { let note_tags: Vec = self.store.get_unique_note_tags().await?.into_iter().collect(); - // To receive information about added nullifiers, we reduce them to the higher 16 bits - // Note that besides filtering by nullifier prefixes, the node also filters by block number - // (it only returns nullifiers from current_block_num until - // response.block_header.block_num()) - let nullifiers_tags: Vec = self - .store - .get_unspent_input_note_nullifiers() - .await? - .iter() - .map(Nullifier::prefix) - .collect(); - - let nullifiers = self - .rpc_api - .check_nullifiers_by_prefix(&nullifiers_tags, current_block_num) - .await?; - // Send request let account_ids: Vec = accounts.iter().map(AccountHeader::id).collect(); - let response = self - .rpc_api - .sync_state(current_block_num, &account_ids, ¬e_tags, &nullifiers_tags) - .await?; + let response = self.rpc_api.sync_state(current_block_num, &account_ids, ¬e_tags).await?; // We don't need to continue if the chain has not advanced, there are no new changes if response.block_header.block_num() == current_block_num { return Ok(SyncStatus::SyncedToLastBlock(SyncSummary::new_empty(current_block_num))); } - let (committed_note_updates, tags_to_remove) = self + let (note_updates, tags_to_remove) = self .committed_note_updates(response.note_inclusions, &response.block_header) .await?; - let incoming_block_has_relevant_notes = - self.check_block_relevance(&committed_note_updates).await?; + let incoming_block_has_relevant_notes = self.check_block_relevance(¬e_updates).await?; let transactions_to_commit = self.get_transactions_to_commit(response.transactions).await?; - let (consumed_note_updates, transactions_to_discard) = - self.consumed_note_updates(&nullifiers, &transactions_to_commit).await?; - - let note_updates = committed_note_updates.combine_with(consumed_note_updates); - let (public_accounts, private_accounts): (Vec<_>, Vec<_>) = accounts.into_iter().partition(|account_header| account_header.id().is_public()); @@ -348,7 +326,7 @@ impl Client { mismatched_private_accounts, ), block_has_relevant_notes: incoming_block_has_relevant_notes, - transactions_to_discard, + transactions_to_discard: vec![], tags_to_remove, }; @@ -368,6 +346,73 @@ impl Client { // HELPERS // -------------------------------------------------------------------------------------------- + async fn apply_nullifiers( + &mut self, + starting_block_num: BlockNumber, + ) -> Result { + // To receive information about added nullifiers, we reduce them to the higher 16 bits + // Note that besides filtering by nullifier prefixes, the node also filters by block number + // (it only returns nullifiers from current_block_num until + // response.block_header.block_num()) + let nullifiers_tags: Vec = self + .store + .get_unspent_input_note_nullifiers() + .await? + .iter() + .map(Nullifier::prefix) + .collect(); + + let nullifiers = self + .rpc_api + .check_nullifiers_by_prefix(&nullifiers_tags, starting_block_num) + .await?; + + // Committed transactions + let committed_transactions = self + .store + .get_transactions(TransactionFilter::All) + .await? + .into_iter() + .filter_map(|tx| { + if let TransactionStatus::Committed(block_num) = tx.transaction_status { + Some(TransactionUpdate { + transaction_id: tx.id, + account_id: tx.account_id, + block_num: block_num.as_u32(), + }) + } else { + None + } + }) + .collect::>(); + + let (consumed_note_updates, transactions_to_discard) = + self.consumed_note_updates(&nullifiers, &committed_transactions).await?; + + // Store summary to return later + let sync_summary = SyncSummary::new( + 0.into(), + consumed_note_updates + .new_input_notes() + .iter() + .map(InputNoteRecord::id) + .collect(), + consumed_note_updates.committed_note_ids().into_iter().collect(), + consumed_note_updates.consumed_note_ids().into_iter().collect(), + vec![], + vec![], + vec![], + ); + + // Apply received and computed updates to the store + self.store + .apply_nullifiers(consumed_note_updates, transactions_to_discard) + .await + .map_err(ClientError::StoreError)?; + + Ok(sync_summary) + } + /// Returns the [`NoteUpdates`] containing new public note and committed input/output notes and /// a list or note tag records to be removed from the store. async fn committed_note_updates( @@ -490,7 +535,6 @@ impl Client { let mut consumed_tracked_input_notes = vec![]; let mut consumed_tracked_output_notes = vec![]; - // Committed transactions for transaction_update in committed_transactions { let transaction_nullifiers: Vec = consumed_input_notes .iter() From ac2c3349818c3d76550a171bc4cd27be5d9e4e5d Mon Sep 17 00:00:00 2001 From: Ignacio Amigo Date: Mon, 24 Feb 2025 23:28:53 -0300 Subject: [PATCH 7/7] chore: Remove unwraps --- CHANGELOG.md | 2 +- crates/rust-client/src/rpc/domain/nullifier.rs | 6 ++---- crates/rust-client/src/store/mod.rs | 4 ++++ crates/rust-client/src/sync/mod.rs | 5 +++-- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9edf19049..36a8a62cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ * [BREAKING] Refactored authentication out of the `Client` and added new separate authenticators (#718). * Re-exported RemoteTransactionProver in `rust-client` (#752). * Moved error handling to the `TransactionRequestBuilder::build()` (#750). -* [BREAKING] Added starting block number parameter to `CheckNullifiersByPrefix` (#749). +* [BREAKING] Added starting block number parameter to `CheckNullifiersByPrefix` and removed nullifiers from `SyncState` (#758). ## 0.7.0 (2025-01-28) diff --git a/crates/rust-client/src/rpc/domain/nullifier.rs b/crates/rust-client/src/rpc/domain/nullifier.rs index 8934d30ba..3b0dab6e8 100644 --- a/crates/rust-client/src/rpc/domain/nullifier.rs +++ b/crates/rust-client/src/rpc/domain/nullifier.rs @@ -33,10 +33,8 @@ impl TryFrom<&rpc::generated::responses::NullifierUpdate> for NullifierUpdate { Ok(Self { nullifier: value .nullifier - .ok_or(rpc::generated::responses::NullifierUpdate::missing_field("nullifier")) - .unwrap() - .try_into() - .unwrap(), + .ok_or(rpc::generated::responses::NullifierUpdate::missing_field("nullifier"))? + .try_into()?, block_num: value.block_num, }) } diff --git a/crates/rust-client/src/store/mod.rs b/crates/rust-client/src/store/mod.rs index 4cb7e4aba..ecec9c172 100644 --- a/crates/rust-client/src/store/mod.rs +++ b/crates/rust-client/src/store/mod.rs @@ -312,6 +312,10 @@ pub trait Store: Send + Sync { /// - Updating the tracked on-chain accounts. async fn apply_state_sync(&self, state_sync_update: StateSyncUpdate) -> Result<(), StoreError>; + /// Applies nullifier updates to database. + /// Nullifiers are retrieved after completing a `StateSync`. + /// + /// This operation is temporary, to be removed as part of miden-client/650. async fn apply_nullifiers( &self, note_updates: NoteUpdates, diff --git a/crates/rust-client/src/sync/mod.rs b/crates/rust-client/src/sync/mod.rs index 9a3c70406..bbefce14f 100644 --- a/crates/rust-client/src/sync/mod.rs +++ b/crates/rust-client/src/sync/mod.rs @@ -239,7 +239,8 @@ impl Client { } } self.update_mmr_data().await?; - total_sync_summary.combine_with(self.apply_nullifiers(starting_block_num).await?); + // Sync and apply nullifiers + total_sync_summary.combine_with(self.sync_nullifiers(starting_block_num).await?); Ok(total_sync_summary) } @@ -346,7 +347,7 @@ impl Client { // HELPERS // -------------------------------------------------------------------------------------------- - async fn apply_nullifiers( + async fn sync_nullifiers( &mut self, starting_block_num: BlockNumber, ) -> Result {