From 098b4220e784148ac2abfbc5fcbbbc00fcbd30fa Mon Sep 17 00:00:00 2001 From: Tomas Date: Thu, 20 Feb 2025 17:59:32 -0300 Subject: [PATCH] feat: remove nullifiers from SyncState endpoint (#708) * feat: add block_num parameter to check_nullifiers_by_prefix * chore: update CHANGELOG * review: add `block_num` parameter as required * review: update CHANGELOG * review: update doc comment * feat: remove nullifiers from `SyncState` endpoint * chore: update doc comments * chore: update CHANGELOG * chore: update rpc README --- CHANGELOG.md | 1 + crates/proto/src/generated/requests.rs | 6 +- crates/proto/src/generated/responses.rs | 7 +- crates/proto/src/generated/rpc.rs | 473 ++++++++---------------- crates/rpc-proto/proto/requests.proto | 6 +- crates/rpc-proto/proto/responses.proto | 3 - crates/rpc-proto/proto/rpc.proto | 8 +- crates/rpc/README.md | 17 +- crates/store/src/db/mod.rs | 6 +- crates/store/src/db/sql/mod.rs | 57 --- crates/store/src/db/tests.rs | 128 ------- crates/store/src/server/api.rs | 17 +- crates/store/src/state.rs | 8 +- proto/requests.proto | 6 +- proto/responses.proto | 3 - proto/rpc.proto | 8 +- 16 files changed, 182 insertions(+), 572 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bf65cf4c..e51e27f17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - [BREAKING] Updated minimum Rust version to 1.84. - [BREAKING] `Endpoint` configuration simplified to a single string (#654). - [BREAKING] `CheckNullifiersByPrefix` now takes a starting block number (#707). +- [BREAKING] Removed nullifiers from `SyncState` endpoint (#708). ### Enhancements diff --git a/crates/proto/src/generated/requests.rs b/crates/proto/src/generated/requests.rs index dc1bd3e7b..9194e084f 100644 --- a/crates/proto/src/generated/requests.rs +++ b/crates/proto/src/generated/requests.rs @@ -45,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, @@ -63,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/proto/src/generated/responses.rs b/crates/proto/src/generated/responses.rs index c3a8f5f20..2f94457b1 100644 --- a/crates/proto/src/generated/responses.rs +++ b/crates/proto/src/generated/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)] @@ -124,9 +121,7 @@ pub struct GetBlockInputsResponse { pub nullifiers: ::prost::alloc::vec::Vec, /// 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, - >, + pub found_unauthenticated_notes: ::core::option::Option, } /// Represents the result of getting batch inputs. #[derive(Clone, PartialEq, ::prost::Message)] diff --git a/crates/proto/src/generated/rpc.rs b/crates/proto/src/generated/rpc.rs index cab7a3998..3b364daf3 100644 --- a/crates/proto/src/generated/rpc.rs +++ b/crates/proto/src/generated/rpc.rs @@ -6,10 +6,10 @@ pub mod api_client { dead_code, missing_docs, clippy::wildcard_imports, - clippy::let_unit_value, + clippy::let_unit_value )] - use tonic::codegen::*; use tonic::codegen::http::Uri; + use tonic::codegen::*; #[derive(Debug, Clone)] pub struct ApiClient { inner: tonic::client::Grpc, @@ -40,10 +40,7 @@ pub mod api_client { let inner = tonic::client::Grpc::with_origin(inner, origin); Self { inner } } - pub fn with_interceptor( - inner: T, - interceptor: F, - ) -> ApiClient> + pub fn with_interceptor(inner: T, interceptor: F) -> ApiClient> where F: tonic::service::Interceptor, T::ResponseBody: Default, @@ -53,9 +50,8 @@ pub mod api_client { >::ResponseBody, >, >, - , - >>::Error: Into + std::marker::Send + std::marker::Sync, + >>::Error: + Into + std::marker::Send + std::marker::Sync, { ApiClient::new(InterceptedService::new(inner, interceptor)) } @@ -93,21 +89,14 @@ pub mod api_client { /// Returns a nullifier proof for each of the requested nullifiers. pub async fn check_nullifiers( &mut self, - request: impl tonic::IntoRequest< - super::super::requests::CheckNullifiersRequest, - >, + request: impl tonic::IntoRequest, ) -> std::result::Result< tonic::Response, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static("/rpc.Api/CheckNullifiers"); let mut req = request.into_request(); @@ -119,25 +108,16 @@ pub mod api_client { /// Note that only 16-bit prefixes are supported at this time. pub async fn check_nullifiers_by_prefix( &mut self, - request: impl tonic::IntoRequest< - super::super::requests::CheckNullifiersByPrefixRequest, - >, + request: impl tonic::IntoRequest, ) -> std::result::Result< tonic::Response, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/rpc.Api/CheckNullifiersByPrefix", - ); + let path = http::uri::PathAndQuery::from_static("/rpc.Api/CheckNullifiersByPrefix"); let mut req = request.into_request(); req.extensions_mut() .insert(GrpcMethod::new("rpc.Api", "CheckNullifiersByPrefix")); @@ -146,25 +126,16 @@ pub mod api_client { /// Returns the latest state of an account with the specified ID. pub async fn get_account_details( &mut self, - request: impl tonic::IntoRequest< - super::super::requests::GetAccountDetailsRequest, - >, + request: impl tonic::IntoRequest, ) -> std::result::Result< tonic::Response, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/rpc.Api/GetAccountDetails", - ); + let path = http::uri::PathAndQuery::from_static("/rpc.Api/GetAccountDetails"); let mut req = request.into_request(); req.extensions_mut().insert(GrpcMethod::new("rpc.Api", "GetAccountDetails")); self.inner.unary(req, path, codec).await @@ -172,21 +143,14 @@ pub mod api_client { /// Returns the latest state proofs of the specified accounts. pub async fn get_account_proofs( &mut self, - request: impl tonic::IntoRequest< - super::super::requests::GetAccountProofsRequest, - >, + request: impl tonic::IntoRequest, ) -> std::result::Result< tonic::Response, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static("/rpc.Api/GetAccountProofs"); let mut req = request.into_request(); @@ -197,48 +161,31 @@ pub mod api_client { /// `to_block_num` (inclusive). pub async fn get_account_state_delta( &mut self, - request: impl tonic::IntoRequest< - super::super::requests::GetAccountStateDeltaRequest, - >, + request: impl tonic::IntoRequest, ) -> std::result::Result< tonic::Response, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/rpc.Api/GetAccountStateDelta", - ); + let path = http::uri::PathAndQuery::from_static("/rpc.Api/GetAccountStateDelta"); let mut req = request.into_request(); - req.extensions_mut() - .insert(GrpcMethod::new("rpc.Api", "GetAccountStateDelta")); + req.extensions_mut().insert(GrpcMethod::new("rpc.Api", "GetAccountStateDelta")); self.inner.unary(req, path, codec).await } /// Returns raw block data for the specified block number. pub async fn get_block_by_number( &mut self, - request: impl tonic::IntoRequest< - super::super::requests::GetBlockByNumberRequest, - >, + request: impl tonic::IntoRequest, ) -> std::result::Result< tonic::Response, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static("/rpc.Api/GetBlockByNumber"); let mut req = request.into_request(); @@ -249,25 +196,16 @@ pub mod api_client { /// and current chain length to authenticate the block's inclusion. pub async fn get_block_header_by_number( &mut self, - request: impl tonic::IntoRequest< - super::super::requests::GetBlockHeaderByNumberRequest, - >, + request: impl tonic::IntoRequest, ) -> std::result::Result< tonic::Response, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/rpc.Api/GetBlockHeaderByNumber", - ); + let path = http::uri::PathAndQuery::from_static("/rpc.Api/GetBlockHeaderByNumber"); let mut req = request.into_request(); req.extensions_mut() .insert(GrpcMethod::new("rpc.Api", "GetBlockHeaderByNumber")); @@ -281,14 +219,9 @@ pub mod api_client { tonic::Response, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static("/rpc.Api/GetNotesById"); let mut req = request.into_request(); @@ -298,25 +231,16 @@ pub mod api_client { /// Submits proven transaction to the Miden network. pub async fn submit_proven_transaction( &mut self, - request: impl tonic::IntoRequest< - super::super::requests::SubmitProvenTransactionRequest, - >, + request: impl tonic::IntoRequest, ) -> std::result::Result< tonic::Response, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static( - "/rpc.Api/SubmitProvenTransaction", - ); + let path = http::uri::PathAndQuery::from_static("/rpc.Api/SubmitProvenTransaction"); let mut req = request.into_request(); req.extensions_mut() .insert(GrpcMethod::new("rpc.Api", "SubmitProvenTransaction")); @@ -338,14 +262,9 @@ pub mod api_client { tonic::Response, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static("/rpc.Api/SyncNotes"); let mut req = request.into_request(); @@ -353,19 +272,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, @@ -374,14 +293,9 @@ pub mod api_client { tonic::Response, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static("/rpc.Api/SyncState"); let mut req = request.into_request(); @@ -397,7 +311,7 @@ pub mod api_server { dead_code, missing_docs, clippy::wildcard_imports, - clippy::let_unit_value, + clippy::let_unit_value )] use tonic::codegen::*; /// Generated trait containing gRPC methods that should be implemented for use with ApiServer. @@ -416,9 +330,7 @@ pub mod api_server { /// Note that only 16-bit prefixes are supported at this time. async fn check_nullifiers_by_prefix( &self, - request: tonic::Request< - super::super::requests::CheckNullifiersByPrefixRequest, - >, + request: tonic::Request, ) -> std::result::Result< tonic::Response, tonic::Status, @@ -460,9 +372,7 @@ pub mod api_server { /// and current chain length to authenticate the block's inclusion. async fn get_block_header_by_number( &self, - request: tonic::Request< - super::super::requests::GetBlockHeaderByNumberRequest, - >, + request: tonic::Request, ) -> std::result::Result< tonic::Response, tonic::Status, @@ -478,9 +388,7 @@ pub mod api_server { /// Submits proven transaction to the Miden network. async fn submit_proven_transaction( &self, - request: tonic::Request< - super::super::requests::SubmitProvenTransactionRequest, - >, + request: tonic::Request, ) -> std::result::Result< tonic::Response, tonic::Status, @@ -502,19 +410,19 @@ pub mod api_server { 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. + /// 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. async fn sync_state( &self, @@ -545,10 +453,7 @@ pub mod api_server { max_encoding_message_size: None, } } - pub fn with_interceptor( - inner: T, - interceptor: F, - ) -> InterceptedService + pub fn with_interceptor(inner: T, interceptor: F) -> InterceptedService where F: tonic::service::Interceptor, { @@ -603,26 +508,19 @@ pub mod api_server { "/rpc.Api/CheckNullifiers" => { #[allow(non_camel_case_types)] struct CheckNullifiersSvc(pub Arc); - impl< - T: Api, - > tonic::server::UnaryService< - super::super::requests::CheckNullifiersRequest, - > for CheckNullifiersSvc { + impl + tonic::server::UnaryService + for CheckNullifiersSvc + { type Response = super::super::responses::CheckNullifiersResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, - request: tonic::Request< - super::super::requests::CheckNullifiersRequest, - >, + request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); - let fut = async move { - ::check_nullifiers(&inner, request).await - }; + let fut = + async move { ::check_nullifiers(&inner, request).await }; Box::pin(fut) } } @@ -647,20 +545,17 @@ pub mod api_server { Ok(res) }; Box::pin(fut) - } + }, "/rpc.Api/CheckNullifiersByPrefix" => { #[allow(non_camel_case_types)] struct CheckNullifiersByPrefixSvc(pub Arc); - impl< - T: Api, - > tonic::server::UnaryService< - super::super::requests::CheckNullifiersByPrefixRequest, - > for CheckNullifiersByPrefixSvc { + impl + tonic::server::UnaryService< + super::super::requests::CheckNullifiersByPrefixRequest, + > for CheckNullifiersByPrefixSvc + { type Response = super::super::responses::CheckNullifiersByPrefixResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request< @@ -669,8 +564,7 @@ pub mod api_server { ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::check_nullifiers_by_prefix(&inner, request) - .await + ::check_nullifiers_by_prefix(&inner, request).await }; Box::pin(fut) } @@ -696,20 +590,17 @@ pub mod api_server { Ok(res) }; Box::pin(fut) - } + }, "/rpc.Api/GetAccountDetails" => { #[allow(non_camel_case_types)] struct GetAccountDetailsSvc(pub Arc); - impl< - T: Api, - > tonic::server::UnaryService< - super::super::requests::GetAccountDetailsRequest, - > for GetAccountDetailsSvc { + impl + tonic::server::UnaryService< + super::super::requests::GetAccountDetailsRequest, + > for GetAccountDetailsSvc + { type Response = super::super::responses::GetAccountDetailsResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request< @@ -744,20 +635,16 @@ pub mod api_server { Ok(res) }; Box::pin(fut) - } + }, "/rpc.Api/GetAccountProofs" => { #[allow(non_camel_case_types)] struct GetAccountProofsSvc(pub Arc); - impl< - T: Api, - > tonic::server::UnaryService< - super::super::requests::GetAccountProofsRequest, - > for GetAccountProofsSvc { + impl + tonic::server::UnaryService + for GetAccountProofsSvc + { type Response = super::super::responses::GetAccountProofsResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request< @@ -792,20 +679,17 @@ pub mod api_server { Ok(res) }; Box::pin(fut) - } + }, "/rpc.Api/GetAccountStateDelta" => { #[allow(non_camel_case_types)] struct GetAccountStateDeltaSvc(pub Arc); - impl< - T: Api, - > tonic::server::UnaryService< - super::super::requests::GetAccountStateDeltaRequest, - > for GetAccountStateDeltaSvc { + impl + tonic::server::UnaryService< + super::super::requests::GetAccountStateDeltaRequest, + > for GetAccountStateDeltaSvc + { type Response = super::super::responses::GetAccountStateDeltaResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request< @@ -840,20 +724,16 @@ pub mod api_server { Ok(res) }; Box::pin(fut) - } + }, "/rpc.Api/GetBlockByNumber" => { #[allow(non_camel_case_types)] struct GetBlockByNumberSvc(pub Arc); - impl< - T: Api, - > tonic::server::UnaryService< - super::super::requests::GetBlockByNumberRequest, - > for GetBlockByNumberSvc { + impl + tonic::server::UnaryService + for GetBlockByNumberSvc + { type Response = super::super::responses::GetBlockByNumberResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request< @@ -888,20 +768,17 @@ pub mod api_server { Ok(res) }; Box::pin(fut) - } + }, "/rpc.Api/GetBlockHeaderByNumber" => { #[allow(non_camel_case_types)] struct GetBlockHeaderByNumberSvc(pub Arc); - impl< - T: Api, - > tonic::server::UnaryService< - super::super::requests::GetBlockHeaderByNumberRequest, - > for GetBlockHeaderByNumberSvc { + impl + tonic::server::UnaryService< + super::super::requests::GetBlockHeaderByNumberRequest, + > for GetBlockHeaderByNumberSvc + { type Response = super::super::responses::GetBlockHeaderByNumberResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request< @@ -910,8 +787,7 @@ pub mod api_server { ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::get_block_header_by_number(&inner, request) - .await + ::get_block_header_by_number(&inner, request).await }; Box::pin(fut) } @@ -937,30 +813,23 @@ pub mod api_server { Ok(res) }; Box::pin(fut) - } + }, "/rpc.Api/GetNotesById" => { #[allow(non_camel_case_types)] struct GetNotesByIdSvc(pub Arc); - impl< - T: Api, - > tonic::server::UnaryService< - super::super::requests::GetNotesByIdRequest, - > for GetNotesByIdSvc { + impl + tonic::server::UnaryService + for GetNotesByIdSvc + { type Response = super::super::responses::GetNotesByIdResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, - request: tonic::Request< - super::super::requests::GetNotesByIdRequest, - >, + request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); - let fut = async move { - ::get_notes_by_id(&inner, request).await - }; + let fut = + async move { ::get_notes_by_id(&inner, request).await }; Box::pin(fut) } } @@ -985,20 +854,17 @@ pub mod api_server { Ok(res) }; Box::pin(fut) - } + }, "/rpc.Api/SubmitProvenTransaction" => { #[allow(non_camel_case_types)] struct SubmitProvenTransactionSvc(pub Arc); - impl< - T: Api, - > tonic::server::UnaryService< - super::super::requests::SubmitProvenTransactionRequest, - > for SubmitProvenTransactionSvc { + impl + tonic::server::UnaryService< + super::super::requests::SubmitProvenTransactionRequest, + > for SubmitProvenTransactionSvc + { type Response = super::super::responses::SubmitProvenTransactionResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request< @@ -1033,30 +899,22 @@ pub mod api_server { Ok(res) }; Box::pin(fut) - } + }, "/rpc.Api/SyncNotes" => { #[allow(non_camel_case_types)] struct SyncNotesSvc(pub Arc); - impl< - T: Api, - > tonic::server::UnaryService< - super::super::requests::SyncNoteRequest, - > for SyncNotesSvc { + impl + tonic::server::UnaryService + for SyncNotesSvc + { type Response = super::super::responses::SyncNoteResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, - request: tonic::Request< - super::super::requests::SyncNoteRequest, - >, + request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); - let fut = async move { - ::sync_notes(&inner, request).await - }; + let fut = async move { ::sync_notes(&inner, request).await }; Box::pin(fut) } } @@ -1081,30 +939,22 @@ pub mod api_server { Ok(res) }; Box::pin(fut) - } + }, "/rpc.Api/SyncState" => { #[allow(non_camel_case_types)] struct SyncStateSvc(pub Arc); - impl< - T: Api, - > tonic::server::UnaryService< - super::super::requests::SyncStateRequest, - > for SyncStateSvc { + impl + tonic::server::UnaryService + for SyncStateSvc + { type Response = super::super::responses::SyncStateResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, - request: tonic::Request< - super::super::requests::SyncStateRequest, - >, + request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); - let fut = async move { - ::sync_state(&inner, request).await - }; + let fut = async move { ::sync_state(&inner, request).await }; Box::pin(fut) } } @@ -1129,24 +979,17 @@ pub mod api_server { Ok(res) }; Box::pin(fut) - } - _ => { - Box::pin(async move { - let mut response = http::Response::new(empty_body()); - let headers = response.headers_mut(); - headers - .insert( - tonic::Status::GRPC_STATUS, - (tonic::Code::Unimplemented as i32).into(), - ); - headers - .insert( - http::header::CONTENT_TYPE, - tonic::metadata::GRPC_CONTENT_TYPE, - ); - Ok(response) - }) - } + }, + _ => Box::pin(async move { + let mut response = http::Response::new(empty_body()); + let headers = response.headers_mut(); + headers.insert( + tonic::Status::GRPC_STATUS, + (tonic::Code::Unimplemented as i32).into(), + ); + headers.insert(http::header::CONTENT_TYPE, tonic::metadata::GRPC_CONTENT_TYPE); + Ok(response) + }), } } } diff --git a/crates/rpc-proto/proto/requests.proto b/crates/rpc-proto/proto/requests.proto index cd0bb960d..bf9fd557a 100644 --- a/crates/rpc-proto/proto/requests.proto +++ b/crates/rpc-proto/proto/requests.proto @@ -43,7 +43,7 @@ message 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. message SyncStateRequest { // Last block known by the client. The response will contain data starting from the next block, // until the first block which contains a note of matching the requested tag, or the chain tip @@ -59,10 +59,6 @@ message SyncStateRequest { // Specifies the tags which the client is interested in. repeated fixed32 note_tags = 3; - - // Determines the nullifiers the client is interested in by specifying the 16high bits of the - // target nullifier. - repeated uint32 nullifiers = 4; } // Note synchronization request. diff --git a/crates/rpc-proto/proto/responses.proto b/crates/rpc-proto/proto/responses.proto index f1dfe5f90..ad1f353a5 100644 --- a/crates/rpc-proto/proto/responses.proto +++ b/crates/rpc-proto/proto/responses.proto @@ -66,9 +66,6 @@ message SyncStateResponse { // 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`. - repeated NullifierUpdate nullifiers = 8; } // Represents the result of syncing notes request. diff --git a/crates/rpc-proto/proto/rpc.proto b/crates/rpc-proto/proto/rpc.proto index 82da3e20c..a7ad531db 100644 --- a/crates/rpc-proto/proto/rpc.proto +++ b/crates/rpc-proto/proto/rpc.proto @@ -49,19 +49,19 @@ service Api { 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. + // 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. rpc SyncState(requests.SyncStateRequest) returns (responses.SyncStateResponse) {} } diff --git a/crates/rpc/README.md b/crates/rpc/README.md index 9dd4375cd..6f0f40048 100644 --- a/crates/rpc/README.md +++ b/crates/rpc/README.md @@ -102,18 +102,17 @@ the chain. ### SyncState -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. +Returns info which can be used by the client to sync up to the latest state of the chain 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. +This request returns a stream where multiple update responses will be pushed in order. Client is expected to read +the updates from the stream and apply them, and then it will be 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. +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 additional filtering of that data on its side. +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. --- diff --git a/crates/store/src/db/mod.rs b/crates/store/src/db/mod.rs index fc6bbc0ec..a00094f54 100644 --- a/crates/store/src/db/mod.rs +++ b/crates/store/src/db/mod.rs @@ -85,7 +85,6 @@ pub struct StateSyncUpdate { pub block_header: BlockHeader, pub account_updates: Vec, pub transactions: Vec, - pub nullifiers: Vec, } #[derive(Debug, PartialEq)] @@ -328,15 +327,12 @@ impl Db { block_num: BlockNumber, account_ids: Vec, note_tags: Vec, - nullifier_prefixes: Vec, ) -> Result { self.pool .get() .await .map_err(DatabaseError::MissingDbConnection)? - .interact(move |conn| { - sql::get_state_sync(conn, block_num, &account_ids, ¬e_tags, &nullifier_prefixes) - }) + .interact(move |conn| sql::get_state_sync(conn, block_num, &account_ids, ¬e_tags)) .await .map_err(|err| { DatabaseError::InteractError(format!("Get state sync task failed: {err}")) diff --git a/crates/store/src/db/sql/mod.rs b/crates/store/src/db/sql/mod.rs index 1a6742f04..87ff16c3d 100644 --- a/crates/store/src/db/sql/mod.rs +++ b/crates/store/src/db/sql/mod.rs @@ -617,54 +617,6 @@ pub fn select_all_nullifiers(conn: &mut Connection) -> Result Result> { - let nullifier_prefixes: Vec = - nullifier_prefixes.iter().copied().map(Into::into).collect(); - - let mut stmt = conn.prepare_cached( - " - SELECT - nullifier, - block_num - FROM - nullifiers - WHERE - block_num > ?1 AND - block_num <= ?2 AND - nullifier_prefix IN rarray(?3) - ORDER BY - block_num ASC - ", - )?; - - let mut rows = - stmt.query(params![block_start.as_u32(), block_end.as_u32(), Rc::new(nullifier_prefixes)])?; - - let mut result = Vec::new(); - while let Some(row) = rows.next()? { - let nullifier_data = row.get_ref(0)?.as_blob()?; - let nullifier = Nullifier::read_from_bytes(nullifier_data)?; - let block_num: u32 = row.get(1)?; - result.push(NullifierInfo { nullifier, block_num: block_num.into() }); - } - Ok(result) -} - /// Returns nullifiers filtered by prefix and block creation height. /// /// Each value of the `nullifier_prefixes` is only the `prefix_len` most significant bits @@ -1195,7 +1147,6 @@ pub fn get_state_sync( block_num: BlockNumber, account_ids: &[AccountId], note_tag_prefixes: &[u32], - nullifier_prefixes: &[u32], ) -> Result { let notes = select_notes_since_block_by_tag_and_sender( conn, @@ -1218,19 +1169,11 @@ pub fn get_state_sync( account_ids, )?; - let nullifiers = select_nullifiers_by_block_range( - conn, - block_num, - block_header.block_num(), - nullifier_prefixes, - )?; - Ok(StateSyncUpdate { notes, block_header, account_updates, transactions, - nullifiers, }) } diff --git a/crates/store/src/db/tests.rs b/crates/store/src/db/tests.rs index 4d89e1cf9..768d6b2ff 100644 --- a/crates/store/src/db/tests.rs +++ b/crates/store/src/db/tests.rs @@ -486,134 +486,6 @@ fn sql_public_account_details() { assert_eq!(read_delta, Some(delta2)); } -#[test] -fn sql_select_nullifiers_by_block_range() { - let mut conn = create_db(); - - // test empty table - let nullifiers = - sql::select_nullifiers_by_block_range(&mut conn, 0.into(), u32::MAX.into(), &[]).unwrap(); - assert!(nullifiers.is_empty()); - - // test single item - let nullifier1 = num_to_nullifier(1 << 48); - let block_number1 = 1.into(); - create_block(&mut conn, block_number1); - - let transaction = conn.transaction().unwrap(); - sql::insert_nullifiers_for_block(&transaction, &[nullifier1], block_number1).unwrap(); - transaction.commit().unwrap(); - - let nullifiers = sql::select_nullifiers_by_block_range( - &mut conn, - 0.into(), - u32::MAX.into(), - &[sql::utils::get_nullifier_prefix(&nullifier1)], - ) - .unwrap(); - assert_eq!( - nullifiers, - vec![NullifierInfo { - nullifier: nullifier1, - block_num: block_number1 - }] - ); - - // test two elements - let nullifier2 = num_to_nullifier(2 << 48); - let block_number2 = 2.into(); - create_block(&mut conn, block_number2); - - let transaction = conn.transaction().unwrap(); - sql::insert_nullifiers_for_block(&transaction, &[nullifier2], block_number2).unwrap(); - transaction.commit().unwrap(); - - let nullifiers = sql::select_all_nullifiers(&mut conn).unwrap(); - assert_eq!(nullifiers, vec![(nullifier1, block_number1), (nullifier2, block_number2)]); - - // only the nullifiers matching the prefix are included - let nullifiers = sql::select_nullifiers_by_block_range( - &mut conn, - 0.into(), - u32::MAX.into(), - &[sql::utils::get_nullifier_prefix(&nullifier1)], - ) - .unwrap(); - assert_eq!( - nullifiers, - vec![NullifierInfo { - nullifier: nullifier1, - block_num: block_number1 - }] - ); - let nullifiers = sql::select_nullifiers_by_block_range( - &mut conn, - 0.into(), - u32::MAX.into(), - &[sql::utils::get_nullifier_prefix(&nullifier2)], - ) - .unwrap(); - assert_eq!( - nullifiers, - vec![NullifierInfo { - nullifier: nullifier2, - block_num: block_number2 - }] - ); - - // Nullifiers created at block_end are included - let nullifiers = sql::select_nullifiers_by_block_range( - &mut conn, - 0.into(), - 1.into(), - &[ - sql::utils::get_nullifier_prefix(&nullifier1), - sql::utils::get_nullifier_prefix(&nullifier2), - ], - ) - .unwrap(); - assert_eq!( - nullifiers, - vec![NullifierInfo { - nullifier: nullifier1, - block_num: block_number1 - }] - ); - - // Nullifiers created at block_start are not included - let nullifiers = sql::select_nullifiers_by_block_range( - &mut conn, - 1.into(), - u32::MAX.into(), - &[ - sql::utils::get_nullifier_prefix(&nullifier1), - sql::utils::get_nullifier_prefix(&nullifier2), - ], - ) - .unwrap(); - assert_eq!( - nullifiers, - vec![NullifierInfo { - nullifier: nullifier2, - block_num: block_number2 - }] - ); - - // When block start and end are the same, no nullifiers should be returned. This case happens - // when the client requests a sync update, and it is already tracking the chain tip. - let nullifiers = sql::select_nullifiers_by_block_range( - &mut conn, - 2.into(), - 2.into(), - &[ - sql::utils::get_nullifier_prefix(&nullifier1), - sql::utils::get_nullifier_prefix(&nullifier2), - ], - ) - .unwrap(); - assert!(nullifiers.is_empty()); -} - #[test] fn select_nullifiers_by_prefix() { const PREFIX_LEN: u32 = 16; diff --git a/crates/store/src/server/api.rs b/crates/store/src/server/api.rs index 0af086426..be0ea560d 100644 --- a/crates/store/src/server/api.rs +++ b/crates/store/src/server/api.rs @@ -164,12 +164,7 @@ impl api_server::Api for StoreApi { let (state, delta) = self .state - .sync_state( - request.block_num.into(), - account_ids, - request.note_tags, - request.nullifiers, - ) + .sync_state(request.block_num.into(), account_ids, request.note_tags) .await .map_err(internal_error)?; @@ -195,15 +190,6 @@ impl api_server::Api for StoreApi { let notes = state.notes.into_iter().map(Into::into).collect(); - let nullifiers = state - .nullifiers - .into_iter() - .map(|nullifier_info| NullifierUpdate { - nullifier: Some(nullifier_info.nullifier.into()), - block_num: nullifier_info.block_num.as_u32(), - }) - .collect(); - Ok(Response::new(SyncStateResponse { chain_tip: self.state.latest_block_num().await.as_u32(), block_header: Some(state.block_header.into()), @@ -211,7 +197,6 @@ impl api_server::Api for StoreApi { accounts, transactions, notes, - nullifiers, })) } diff --git a/crates/store/src/state.rs b/crates/store/src/state.rs index b8eb13fed..e832c4078 100644 --- a/crates/store/src/state.rs +++ b/crates/store/src/state.rs @@ -709,22 +709,16 @@ impl State { /// range. /// - `note_tags`: The tags the client is interested in, result is restricted to the first block /// with any matches tags. - /// - `nullifier_prefixes`: Only the 16 high bits of the nullifiers the client is interested in, - /// results will include nullifiers matching prefixes produced in the given block range. #[instrument(target = COMPONENT, skip_all, ret(level = "debug"), err)] pub async fn sync_state( &self, block_num: BlockNumber, account_ids: Vec, note_tags: Vec, - nullifier_prefixes: Vec, ) -> Result<(StateSyncUpdate, MmrDelta), StateSyncError> { let inner = self.inner.read().await; - let state_sync = self - .db - .get_state_sync(block_num, account_ids, note_tags, nullifier_prefixes) - .await?; + let state_sync = self.db.get_state_sync(block_num, account_ids, note_tags).await?; let delta = if block_num == state_sync.block_header.block_num() { // The client is in sync with the chain tip. diff --git a/proto/requests.proto b/proto/requests.proto index cd0bb960d..bf9fd557a 100644 --- a/proto/requests.proto +++ b/proto/requests.proto @@ -43,7 +43,7 @@ message 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. message SyncStateRequest { // Last block known by the client. The response will contain data starting from the next block, // until the first block which contains a note of matching the requested tag, or the chain tip @@ -59,10 +59,6 @@ message SyncStateRequest { // Specifies the tags which the client is interested in. repeated fixed32 note_tags = 3; - - // Determines the nullifiers the client is interested in by specifying the 16high bits of the - // target nullifier. - repeated uint32 nullifiers = 4; } // Note synchronization request. diff --git a/proto/responses.proto b/proto/responses.proto index f1dfe5f90..ad1f353a5 100644 --- a/proto/responses.proto +++ b/proto/responses.proto @@ -66,9 +66,6 @@ message SyncStateResponse { // 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`. - repeated NullifierUpdate nullifiers = 8; } // Represents the result of syncing notes request. diff --git a/proto/rpc.proto b/proto/rpc.proto index 82da3e20c..a7ad531db 100644 --- a/proto/rpc.proto +++ b/proto/rpc.proto @@ -49,19 +49,19 @@ service Api { 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. + // 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. rpc SyncState(requests.SyncStateRequest) returns (responses.SyncStateResponse) {} }