diff --git a/bin/benchmark/src/inclusion.rs b/bin/benchmark/src/inclusion.rs index ab834d1b66..bc295349db 100644 --- a/bin/benchmark/src/inclusion.rs +++ b/bin/benchmark/src/inclusion.rs @@ -11,7 +11,7 @@ use std::collections::HashMap; use std::time::{Duration, SystemTime, UNIX_EPOCH}; use miden_node_proto::clients::RpcClient; -use miden_node_proto::generated::rpc::BlockHeaderByNumberRequest; +use miden_node_proto::generated::rpc::GetBlockHeaderByNumberRequest; use miden_node_proto::{DecodeMessageExt, generated as proto}; use miden_protocol::block::BlockHeader; use miden_protocol::transaction::TransactionId; @@ -110,7 +110,7 @@ pub(crate) async fn scan_with_drain( // Scan every unwatched block, capped at the max-bound target. let scan_to = tip.min(max_target); while next_block <= scan_to { - let request = proto::rpc::BlockRequest { + let request = proto::rpc::GetBlockByNumberRequest { block_num: next_block, include_proof: None, }; @@ -217,7 +217,7 @@ pub(crate) async fn scan_with_drain( pub(crate) async fn current_block_height(mut client: RpcClient) -> u32 { let response = client - .get_block_header_by_number(BlockHeaderByNumberRequest { + .get_block_header_by_number(GetBlockHeaderByNumberRequest { block_num: None, include_mmr_proof: None, include_protocol_config: None, diff --git a/bin/benchmark/src/main.rs b/bin/benchmark/src/main.rs index 1c8b925700..ce8d168e76 100644 --- a/bin/benchmark/src/main.rs +++ b/bin/benchmark/src/main.rs @@ -13,7 +13,7 @@ use miden_node_proto::domain::encryption::{ TransactionInputsSealer, TrustedTransactionEncryptionState, }; -use miden_node_proto::generated::rpc::BlockHeaderByNumberRequest; +use miden_node_proto::generated::rpc::GetBlockHeaderByNumberRequest; use miden_node_proto::{DecodeMessageExt, VerifyWith}; use miden_protocol::Word; use miden_protocol::block::{BlockHeader, BlockNumber}; @@ -222,10 +222,14 @@ pub(crate) async fn create_genesis_aware_rpc_client_pool( } let key = pool[0] .clone() - .get_transaction_encryption_key(()) + .get_transaction_encryption_key( + miden_node_proto::generated::rpc::GetTransactionEncryptionKeyRequest {}, + ) .await .context("Failed to fetch the transaction encryption key")? - .into_inner(); + .into_inner() + .key + .ok_or_else(|| tonic::Status::internal("missing transaction encryption key"))?; let trusted_keys = [trusted_validator_signing_key]; let verified = key .verify_with(TrustedTransactionEncryptionState::new(genesis, &trusted_keys)) @@ -234,8 +238,8 @@ pub(crate) async fn create_genesis_aware_rpc_client_pool( Ok((pool, TransactionInputsSealer::new(verified))) } -pub(crate) fn get_genesis_header_request() -> BlockHeaderByNumberRequest { - BlockHeaderByNumberRequest { +pub(crate) fn get_genesis_header_request() -> GetBlockHeaderByNumberRequest { + GetBlockHeaderByNumberRequest { block_num: Some(BlockNumber::GENESIS.as_u32()), include_mmr_proof: None, include_protocol_config: None, diff --git a/bin/benchmark/src/prover.rs b/bin/benchmark/src/prover.rs index c305819b07..2ec9bcd96b 100644 --- a/bin/benchmark/src/prover.rs +++ b/bin/benchmark/src/prover.rs @@ -16,8 +16,8 @@ use std::time::{Duration, Instant}; use anyhow::{Context, Result}; use miden_node_proto::clients::{Builder, RemoteProverClient}; use miden_node_proto::errors::ConversionError; -use miden_node_proto::generated::remote_prover::proof_request::Request; -use miden_node_proto::generated::remote_prover::{DecodedProof, ProofRequest}; +use miden_node_proto::generated::remote_prover::prove_request::Request; +use miden_node_proto::generated::remote_prover::{DecodedProveResponse, ProveRequest}; use miden_node_proto::{BuildUnchecked, DecodeMessage}; use miden_node_tracing::spawn::spawn_blocking_in_current_span; use miden_protocol::transaction::{ExecutedTransaction, ProvenTransaction, TransactionInputs}; @@ -200,7 +200,7 @@ impl RemoteTransactionProver { &self, tx_inputs: &TransactionInputs, ) -> Result { - let request = tonic::Request::new(ProofRequest { + let request = tonic::Request::new(ProveRequest { request: Some(Request::Transaction(tx_inputs.into())), }); @@ -211,7 +211,7 @@ impl RemoteTransactionProver { response .into_inner() .decode_fields() - .and_then(DecodedProof::into_transaction) + .and_then(DecodedProveResponse::into_transaction) // SAFETY: This benchmark trusts the configured prover to return a valid proof for the // requested transaction. .and_then(|transaction| transaction.build_unchecked().map_err(ConversionError::new)) diff --git a/bin/benchmark/src/submit.rs b/bin/benchmark/src/submit.rs index 0a514d83b0..9915ee2004 100644 --- a/bin/benchmark/src/submit.rs +++ b/bin/benchmark/src/submit.rs @@ -224,7 +224,10 @@ async fn submit_all( sealed_transaction_inputs: Some(sealed_inputs), }; let t0 = Instant::now(); - let outcome = match client.submit_proven_tx(request).await { + let outcome = match client + .submit_proven_tx(proto::rpc::SubmitProvenTxRequest { submission: Some(request) }) + .await + { Ok(_) => SubmitOutcome { index: i, result: Ok(t0.elapsed()), @@ -285,7 +288,10 @@ async fn submit_sequential( }; let t0 = Instant::now(); - let outcome = match client.submit_proven_tx(request).await { + let outcome = match client + .submit_proven_tx(proto::rpc::SubmitProvenTxRequest { submission: Some(request) }) + .await + { Ok(_) => SubmitOutcome { index: i, result: Ok(t0.elapsed()), diff --git a/bin/funding-service/src/node.rs b/bin/funding-service/src/node.rs index 5b0d21e1f4..79892e3608 100644 --- a/bin/funding-service/src/node.rs +++ b/bin/funding-service/src/node.rs @@ -14,13 +14,13 @@ use miden_node_proto::domain::encryption::{ TrustedTransactionEncryptionState, }; use miden_node_proto::domain::protocol_config::ensure_protocol_config_is_present_and_matches_header; -use miden_node_proto::generated::rpc::account_request::AccountDetailRequest; +use miden_node_proto::generated::rpc::get_account_request::AccountDetailRequest; use miden_node_proto::generated::rpc::{ - AccountRequest as ProtoAccountRequest, - BlockHeaderByNumberRequest, BlockRange, FinalityLevel, - NotesByIdRequest, + GetAccountRequest as ProtoAccountRequest, + GetBlockHeaderByNumberRequest, + GetNotesByIdRequest, SyncChainMmrRequest, SyncNotesRequest, SyncNullifiersRequest, @@ -248,7 +248,7 @@ impl RpcNodeClient { let response = self .rpc_client .clone() - .get_notes_by_id(NotesByIdRequest { note_ids }) + .get_notes_by_id(GetNotesByIdRequest { note_ids }) .await .context("failed to fetch notes from RPC")? .into_inner(); @@ -389,7 +389,7 @@ impl RpcNodeClient { let status = self .rpc_client .clone() - .status(()) + .status(miden_node_proto::generated::rpc::StatusRequest {}) .await .context("failed to fetch the node status")? .into_inner(); @@ -412,7 +412,13 @@ impl RpcNodeClient { transaction: Some(proven_tx.into()), sealed_transaction_inputs: Some(sealed), }; - let result = self.rpc_client.clone().submit_proven_tx(request).await; + let result = self + .rpc_client + .clone() + .submit_proven_tx(miden_node_proto::generated::rpc::SubmitProvenTxRequest { + submission: Some(request), + }) + .await; if result.is_err() { // The encryption key can be stale. Fetch it again for the next submission. @@ -434,10 +440,14 @@ impl RpcNodeClient { let key = self .rpc_client .clone() - .get_transaction_encryption_key(()) + .get_transaction_encryption_key( + miden_node_proto::generated::rpc::GetTransactionEncryptionKeyRequest {}, + ) .await .context("failed to fetch the transaction encryption key")? - .into_inner(); + .into_inner() + .key + .ok_or_else(|| tonic::Status::internal("missing transaction encryption key"))?; let verified = key .verify_with(TrustedTransactionEncryptionState::new( self.genesis_commitment, @@ -577,7 +587,7 @@ async fn fetch_block_header( rpc_client: &mut RpcClient, block_num: Option, ) -> Result { - let request = BlockHeaderByNumberRequest { + let request = GetBlockHeaderByNumberRequest { block_num: block_num.map(|block_num| block_num.as_u32()), include_mmr_proof: None, include_protocol_config: None, @@ -606,7 +616,7 @@ async fn fetch_genesis_header_and_config( rpc_client: &mut RpcClient, ) -> Result<(BlockHeader, ProtocolConfig)> { let response = rpc_client - .get_block_header_by_number(BlockHeaderByNumberRequest { + .get_block_header_by_number(GetBlockHeaderByNumberRequest { block_num: Some(BlockNumber::GENESIS.as_u32()), include_mmr_proof: None, include_protocol_config: Some(true), @@ -688,8 +698,8 @@ async fn fetch_public_account( account_id: AccountId, block_num: BlockNumber, ) -> Result<(Account, AccountWitness)> { - use miden_node_proto::generated::rpc::account_request::AccountDetailRequest; - use miden_node_proto::generated::rpc::account_request::account_detail_request::StorageRequest; + use miden_node_proto::generated::rpc::get_account_request::AccountDetailRequest; + use miden_node_proto::generated::rpc::get_account_request::account_detail_request::StorageRequest; // Dummy commitments force the server to include code and vault data in the response. let dummy: miden_node_proto::generated::primitives::Word = Word::default().into(); diff --git a/bin/funding-service/src/node/tests.rs b/bin/funding-service/src/node/tests.rs index d8b09a0fe3..2c1fe8ecbd 100644 --- a/bin/funding-service/src/node/tests.rs +++ b/bin/funding-service/src/node/tests.rs @@ -106,8 +106,8 @@ impl TestChain { } } - fn notes_by_id(&self, request: &NotesByIdRequest) -> rpc::NotesByIdResponse { - rpc::NotesByIdResponse { + fn notes_by_id(&self, request: &GetNotesByIdRequest) -> rpc::GetNotesByIdResponse { + rpc::GetNotesByIdResponse { notes: request .note_ids .iter() @@ -223,10 +223,12 @@ impl Service> for RpcFixture { return Box::pin(async { Ok(tonic::Status::unavailable("retry").into_http()) }); } match method { - "Status" => self.respond(request, |chain, _: &()| rpc::RpcStatus { - chain_tip: chain.tip, - ..Default::default() - }), + "Status" => { + self.respond(request, |chain, _: &rpc::StatusRequest| rpc::StatusResponse { + chain_tip: chain.tip, + ..Default::default() + }) + }, "SyncTransactions" => self.respond(request, TestChain::sync_transactions), "SyncNotes" => self.respond(request, TestChain::sync_notes), "GetNotesById" => self.respond(request, TestChain::notes_by_id), diff --git a/bin/funding-service/src/prover.rs b/bin/funding-service/src/prover.rs index 0dfc387323..d8a8e46f6a 100644 --- a/bin/funding-service/src/prover.rs +++ b/bin/funding-service/src/prover.rs @@ -4,8 +4,8 @@ use std::time::Duration; use anyhow::{Context, Result}; use miden_node_proto::clients::{Builder, RemoteProverClient}; -use miden_node_proto::generated::remote_prover::proof_request::Request as ProofRequestVariant; -use miden_node_proto::generated::remote_prover::{DecodedProof, ProofRequest}; +use miden_node_proto::generated::remote_prover::prove_request::Request as ProofRequestVariant; +use miden_node_proto::generated::remote_prover::{DecodedProveResponse, ProveRequest}; use miden_node_proto::{BuildUnchecked, DecodeMessage}; use miden_node_tracing::spawn::spawn_blocking_in_current_span; use miden_node_tracing::{ErrorReport, warn}; @@ -96,7 +96,7 @@ impl RemoteProver { /// Proves one transaction on the remote prover. async fn prove_remotely(&self, executed_tx: &ExecutedTransaction) -> Result { - let request = tonic::Request::new(ProofRequest { + let request = tonic::Request::new(ProveRequest { request: Some(ProofRequestVariant::Transaction(executed_tx.tx_inputs().into())), }); @@ -110,7 +110,7 @@ impl RemoteProver { response .into_inner() .decode_fields() - .and_then(DecodedProof::into_transaction) + .and_then(DecodedProveResponse::into_transaction) .context("failed to decode the response of the remote transaction prover")? .build_unchecked() .context("failed to build the response of the remote transaction prover") diff --git a/bin/large-account-benchmark/src/rpc.rs b/bin/large-account-benchmark/src/rpc.rs index 23864baa4b..bbb4c5cfd7 100644 --- a/bin/large-account-benchmark/src/rpc.rs +++ b/bin/large-account-benchmark/src/rpc.rs @@ -11,11 +11,11 @@ use miden_node_proto::domain::encryption::{ }; use miden_node_proto::domain::protocol_config::ensure_protocol_config_is_present_and_matches_header; use miden_node_proto::generated::account::account_storage_header::storage_slot::Content as SlotContent; -use miden_node_proto::generated::rpc::account_request::AccountDetailRequest; +use miden_node_proto::generated::rpc::get_account_request::AccountDetailRequest; use miden_node_proto::generated::rpc::{ - AccountRequest, - BlockHeaderByNumberRequest, - BlockHeaderByNumberResponse, + GetAccountRequest, + GetBlockHeaderByNumberRequest, + GetBlockHeaderByNumberResponse, }; use miden_node_proto::generated::submission::ProvenTransactionSubmission as ProtoProvenTransaction; use miden_node_proto::{DecodeMessageExt, VerifyWith}; @@ -136,7 +136,7 @@ impl SubmissionClient { let status = self .rpc .clone() - .status(()) + .status(miden_node_proto::generated::rpc::StatusRequest {}) .await .context("failed to read node status")? .into_inner(); @@ -151,7 +151,7 @@ impl SubmissionClient { /// this tool submitted, while the counter account's slot only advances when the ntx-builder has /// actually loaded the large account and consumed a network note. pub async fn slot_value(&self, account_id: AccountId, slot_name: &str) -> Result> { - let request = AccountRequest { + let request = GetAccountRequest { account_id: Some(account_id.into()), block_num: None, details: Some(AccountDetailRequest { @@ -214,7 +214,7 @@ impl SubmissionClient { account_id: AccountId, block_num: BlockNumber, ) -> Result { - let request = AccountRequest { + let request = GetAccountRequest { account_id: Some(account_id.into()), block_num: Some(block_num.into()), details: None, @@ -252,10 +252,14 @@ impl SubmissionClient { let key = self .rpc .clone() - .get_transaction_encryption_key(()) + .get_transaction_encryption_key( + miden_node_proto::generated::rpc::GetTransactionEncryptionKeyRequest {}, + ) .await .context("failed to fetch the transaction encryption key")? - .into_inner(); + .into_inner() + .key + .ok_or_else(|| tonic::Status::internal("missing transaction encryption key"))?; let verified = key .verify_with(TrustedTransactionEncryptionState::new( @@ -306,9 +310,11 @@ impl SubmissionClient { let response = self .rpc .clone() - .submit_proven_tx(ProtoProvenTransaction { - transaction: Some(proven_tx.into()), - sealed_transaction_inputs: Some(sealed), + .submit_proven_tx(miden_node_proto::generated::rpc::SubmitProvenTxRequest { + submission: Some(ProtoProvenTransaction { + transaction: Some(proven_tx.into()), + sealed_transaction_inputs: Some(sealed), + }), }) .await .context("failed to submit the proven transaction")?; @@ -330,7 +336,7 @@ async fn genesis_block_state(rpc: &mut RpcClient) -> Result<(BlockHeader, Protoc } fn decode_genesis_block_state( - response: BlockHeaderByNumberResponse, + response: GetBlockHeaderByNumberResponse, ) -> Result<(BlockHeader, ProtocolConfig)> { let header = response .block_header @@ -345,8 +351,8 @@ fn decode_genesis_block_state( Ok((header, protocol_config)) } -fn genesis_header_request() -> BlockHeaderByNumberRequest { - BlockHeaderByNumberRequest { +fn genesis_header_request() -> GetBlockHeaderByNumberRequest { + GetBlockHeaderByNumberRequest { block_num: Some(BlockNumber::GENESIS.as_u32()), include_mmr_proof: None, include_protocol_config: Some(true), @@ -364,7 +370,7 @@ fn is_stale_key(err: &anyhow::Error) -> bool { #[cfg(test)] mod tests { - use miden_node_proto::generated::rpc::BlockHeaderByNumberResponse; + use miden_node_proto::generated::rpc::GetBlockHeaderByNumberResponse; use miden_protocol::account::AccountId; use miden_protocol::testing::account_id::ACCOUNT_ID_PUBLIC_FUNGIBLE_FAUCET_1; use miden_testing::MockChain; @@ -381,7 +387,7 @@ mod tests { ) .build() .expect("chain should build"); - let response = BlockHeaderByNumberResponse { + let response = GetBlockHeaderByNumberResponse { block_header: Some(chain.genesis_block_header().into()), mmr_path: None, chain_length: None, diff --git a/bin/network-monitor/src/counter.rs b/bin/network-monitor/src/counter.rs index b8539c6ba7..b23c310026 100644 --- a/bin/network-monitor/src/counter.rs +++ b/bin/network-monitor/src/counter.rs @@ -1041,7 +1041,7 @@ async fn fetch_slot_value( fn build_account_request( account_id: AccountId, include_code_and_vault: bool, -) -> miden_node_proto::generated::rpc::AccountRequest { +) -> miden_node_proto::generated::rpc::GetAccountRequest { let account_id_proto: miden_node_proto::generated::account::AccountId = account_id.into(); let (code_commitment, asset_vault_commitment) = if include_code_and_vault { @@ -1051,14 +1051,16 @@ fn build_account_request( (None, None) }; - miden_node_proto::generated::rpc::AccountRequest { + miden_node_proto::generated::rpc::GetAccountRequest { account_id: Some(account_id_proto), block_num: None, - details: Some(miden_node_proto::generated::rpc::account_request::AccountDetailRequest { - code_commitment, - asset_vault_commitment, - storage_request: None, - }), + details: Some( + miden_node_proto::generated::rpc::get_account_request::AccountDetailRequest { + code_commitment, + asset_vault_commitment, + storage_request: None, + }, + ), } } @@ -1206,7 +1208,10 @@ fn create_network_note( /// Fetch the current chain tip height from RPC status. async fn fetch_chain_tip(rpc_client: &mut RpcClient) -> Result { - let status = rpc_client.status(()).await?.into_inner(); + let status = rpc_client + .status(miden_node_proto::generated::rpc::StatusRequest {}) + .await? + .into_inner(); if let Some(block_producer_status) = status.block_producer { Ok(block_producer_status.chain_tip) diff --git a/bin/network-monitor/src/deploy/mod.rs b/bin/network-monitor/src/deploy/mod.rs index 27740b63a1..a2f1168821 100644 --- a/bin/network-monitor/src/deploy/mod.rs +++ b/bin/network-monitor/src/deploy/mod.rs @@ -17,9 +17,9 @@ use miden_node_proto::domain::encryption::{ }; use miden_node_proto::domain::protocol_config::ensure_protocol_config_is_present_and_matches_header; use miden_node_proto::generated::rpc::{ - AccountRequest as ProtoAccountRequest, - BlockHeaderByNumberRequest, FinalityLevel, + GetAccountRequest as ProtoAccountRequest, + GetBlockHeaderByNumberRequest, SyncChainMmrRequest, SyncChainMmrResponse, }; @@ -155,10 +155,14 @@ impl TransactionSubmissionClient { let key = self .rpc_client .clone() - .get_transaction_encryption_key(()) + .get_transaction_encryption_key( + miden_node_proto::generated::rpc::GetTransactionEncryptionKeyRequest {}, + ) .await .context("Failed to fetch the transaction encryption key")? - .into_inner(); + .into_inner() + .key + .ok_or_else(|| tonic::Status::internal("missing transaction encryption key"))?; let verified = key .verify_with(TrustedTransactionEncryptionState::new( self.genesis_commitment, @@ -232,9 +236,11 @@ impl TransactionSubmissionClient { .context("Failed to seal the transaction inputs")?; self.rpc_client .clone() - .submit_proven_tx(ProtoProvenTransaction { - transaction: Some(transaction), - sealed_transaction_inputs: Some(sealed), + .submit_proven_tx(miden_node_proto::generated::rpc::SubmitProvenTxRequest { + submission: Some(ProtoProvenTransaction { + transaction: Some(transaction), + sealed_transaction_inputs: Some(sealed), + }), }) .await .context("Failed to submit proven transaction to RPC") @@ -313,7 +319,7 @@ pub async fn create_genesis_aware_rpc_client( .await .context("Failed to create RPC client for genesis discovery")?; - let block_header_request = BlockHeaderByNumberRequest { + let block_header_request = GetBlockHeaderByNumberRequest { block_num: Some(BlockNumber::GENESIS.as_u32()), include_mmr_proof: None, include_protocol_config: None, @@ -502,8 +508,8 @@ pub(crate) async fn fetch_foreign_account_inputs( account_id: AccountId, block_num: BlockNumber, ) -> Result<(Account, AccountWitness)> { - use miden_node_proto::generated::rpc::account_request::AccountDetailRequest; - use miden_node_proto::generated::rpc::account_request::account_detail_request::StorageRequest; + use miden_node_proto::generated::rpc::get_account_request::AccountDetailRequest; + use miden_node_proto::generated::rpc::get_account_request::account_detail_request::StorageRequest; // Dummy commitments force the server to include code and vault data in the response. let dummy: miden_node_proto::generated::primitives::Word = Word::default().into(); diff --git a/bin/network-monitor/src/remote_prover.rs b/bin/network-monitor/src/remote_prover.rs index 9e2b611e1f..0b013a9213 100644 --- a/bin/network-monitor/src/remote_prover.rs +++ b/bin/network-monitor/src/remote_prover.rs @@ -299,7 +299,11 @@ impl Service for ProverStatusService { ), )] async fn check(&mut self) -> ServiceStatus { - match self.client.status(()).await { + match self + .client + .status(miden_node_proto::generated::remote_prover::ProxyStatusRequest {}) + .await + { Ok(response) => { self.last_status = Some(RemoteProverStatusDetails::from_proxy_status( response.into_inner(), @@ -539,15 +543,17 @@ fn tonic_status_to_json(status: &tonic::Status) -> String { async fn generate_prover_test_payload( rpc_url: &Url, funding: Option<&FundingClient>, -) -> anyhow::Result { +) -> anyhow::Result { let tx_inputs = crate::deploy::build_probe_transaction_inputs(rpc_url, funding).await?; - Ok(proto::remote_prover::ProofRequest { - request: Some(proto::remote_prover::proof_request::Request::Transaction(tx_inputs.into())), + Ok(proto::remote_prover::ProveRequest { + request: Some(proto::remote_prover::prove_request::Request::Transaction(tx_inputs.into())), }) } -fn transaction_proof_size(response: proto::remote_prover::Proof) -> Result { - use proto::remote_prover::proof::Proof; +fn transaction_proof_size( + response: proto::remote_prover::ProveResponse, +) -> Result { + use proto::remote_prover::prove_response::Proof; match response.proof { Some(Proof::Transaction(proof)) => Ok(proof.encoded_len()), @@ -567,16 +573,16 @@ mod tests { #[test] fn missing_probe_response_variant_is_a_protocol_error() { - let error = - transaction_proof_size(proto::remote_prover::Proof { proof: None }).unwrap_err(); + let error = transaction_proof_size(proto::remote_prover::ProveResponse { proof: None }) + .unwrap_err(); assert_eq!(error.code(), tonic::Code::Internal); } #[test] fn mismatched_probe_response_variant_is_a_protocol_error() { - let response = proto::remote_prover::Proof { - proof: Some(proto::remote_prover::proof::Proof::Block( + let response = proto::remote_prover::ProveResponse { + proof: Some(proto::remote_prover::prove_response::Proof::Block( proto::primitives::ExecutionProof::default(), )), }; diff --git a/bin/network-monitor/src/service_status.rs b/bin/network-monitor/src/service_status.rs index 12062e51fa..4a0cd1abe6 100644 --- a/bin/network-monitor/src/service_status.rs +++ b/bin/network-monitor/src/service_status.rs @@ -7,7 +7,7 @@ use std::time::{Duration, SystemTime, UNIX_EPOCH}; use miden_node_proto::generated as proto; -use miden_node_proto::generated::rpc::{BlockProducerStatus, RpcStatus}; +use miden_node_proto::generated::rpc::{BlockProducerStatus, StatusResponse}; use miden_node_tracing::warn; use serde::{Deserialize, Serialize}; @@ -389,7 +389,10 @@ impl From for WorkerStatusDetails { } impl RemoteProverStatusDetails { - pub fn from_proxy_status(status: proto::remote_prover::ProxyStatus, url: String) -> Self { + pub fn from_proxy_status( + status: proto::remote_prover::ProxyStatusResponse, + url: String, + ) -> Self { // An out-of-range discriminant (e.g. from a newer prover version) degrades to Unknown // instead of panicking the checker task. let proof_type = proto::remote_prover::ProofType::try_from(status.supported_proof_type) @@ -418,8 +421,8 @@ impl RemoteProverStatusDetails { } impl RpcStatusDetails { - /// Creates `RpcStatusDetails` from a gRPC `RpcStatus` response and the configured URL. - pub fn from_rpc_status(status: RpcStatus, url: String) -> Self { + /// Creates `RpcStatusDetails` from a gRPC `StatusResponse` response and the configured URL. + pub fn from_rpc_status(status: StatusResponse, url: String) -> Self { Self { url, version: status.version, @@ -479,7 +482,7 @@ mod tests { #[test] fn proxy_status_with_unknown_proof_type_degrades_to_unknown() { - let proto_status = proto::remote_prover::ProxyStatus { + let proto_status = proto::remote_prover::ProxyStatusResponse { version: "1.0".to_string(), supported_proof_type: 99, workers: vec![proto::remote_prover::ProxyWorkerStatus { diff --git a/bin/network-monitor/src/status.rs b/bin/network-monitor/src/status.rs index 91750689c9..36e8d6f323 100644 --- a/bin/network-monitor/src/status.rs +++ b/bin/network-monitor/src/status.rs @@ -124,7 +124,7 @@ impl Service for RpcService { level = "info", )] async fn check(&mut self) -> ServiceStatus { - match self.rpc.status(()).await { + match self.rpc.status(miden_node_proto::generated::rpc::StatusRequest {}).await { Ok(response) => { let rpc_details = RpcStatusDetails::from_rpc_status(response.into_inner(), self.url.clone()); diff --git a/bin/network-monitor/src/validator.rs b/bin/network-monitor/src/validator.rs index d58e701be3..5202c48756 100644 --- a/bin/network-monitor/src/validator.rs +++ b/bin/network-monitor/src/validator.rs @@ -45,7 +45,11 @@ impl Service for ValidatorService { name = "check-status.validator", )] async fn check(&mut self) -> ServiceStatus { - match self.client.status(()).await { + match self + .client + .status(miden_node_proto::generated::validator::StatusRequest {}) + .await + { Ok(response) => { let status = response.into_inner(); ServiceStatus::healthy( diff --git a/bin/node/src/commands/recover.rs b/bin/node/src/commands/recover.rs index 37d11a195c..675b4e97d8 100644 --- a/bin/node/src/commands/recover.rs +++ b/bin/node/src/commands/recover.rs @@ -149,7 +149,7 @@ async fn recover_from_validators( for (url, validator) in &mut validators { let tip = BlockNumber::from( validator - .status(()) + .status(miden_node_proto::generated::validator::StatusRequest {}) .await .with_context(|| format!("failed to query status of validator {url}"))? .into_inner() diff --git a/bin/note-transport/src/server/note_root.rs b/bin/note-transport/src/server/note_root.rs index dfd32ed135..f580b56a7d 100644 --- a/bin/note-transport/src/server/note_root.rs +++ b/bin/note-transport/src/server/note_root.rs @@ -1,7 +1,10 @@ use std::time::Duration; use miden_node_proto::errors::ConversionResultExt; -use miden_node_proto::generated::rpc::{BlockHeaderByNumberRequest, BlockHeaderByNumberResponse}; +use miden_node_proto::generated::rpc::{ + GetBlockHeaderByNumberRequest, + GetBlockHeaderByNumberResponse, +}; use miden_node_proto::{BuildUnchecked, DecodeMessage}; use miden_node_tracing::{error, miden_instrument, miden_span_record}; use miden_protocol::Word; @@ -42,7 +45,7 @@ impl Server { async fn request_block_header( &self, block_num: BlockNumber, - ) -> tonic::Result { + ) -> tonic::Result { const MAX_ATTEMPTS: u32 = 3; // All attempts and backoff share one budget. Reserve the rest for validation and storage. @@ -56,7 +59,7 @@ impl Server { attempt += 1; let response = tokio::time::timeout( attempt_timeout, - rpc.get_block_header_by_number(BlockHeaderByNumberRequest { + rpc.get_block_header_by_number(GetBlockHeaderByNumberRequest { block_num: Some(block_num.as_u32()), include_mmr_proof: Some(false), include_protocol_config: Some(false), diff --git a/bin/note-transport/src/server/send_note_with_proof.rs b/bin/note-transport/src/server/send_note_with_proof.rs index 0e5bfd5fcf..e950d8faa9 100644 --- a/bin/note-transport/src/server/send_note_with_proof.rs +++ b/bin/note-transport/src/server/send_note_with_proof.rs @@ -1,5 +1,8 @@ use miden_node_proto::errors::ConversionError; -use miden_node_proto::generated::note_transport::{SendNoteResponse, SendNoteWithProofRequest}; +use miden_node_proto::generated::note_transport::{ + SendNoteWithProofRequest, + SendNoteWithProofResponse, +}; use miden_node_proto::server::note_transport_api::SendNoteWithProof; use miden_node_proto::{DecodeMessage, Verify}; use miden_node_tracing::{miden_instrument, miden_span_record}; @@ -35,8 +38,8 @@ impl SendNoteWithProof for Server { Ok((note, proof)) } - fn encode(_: ()) -> tonic::Result { - Ok(SendNoteResponse {}) + fn encode(_: ()) -> tonic::Result { + Ok(SendNoteWithProofResponse {}) } #[miden_instrument(target = COMPONENT, err)] diff --git a/bin/note-transport/src/server/tests/proofs.rs b/bin/note-transport/src/server/tests/proofs.rs index 0d3635bbd3..cf9fe41506 100644 --- a/bin/note-transport/src/server/tests/proofs.rs +++ b/bin/note-transport/src/server/tests/proofs.rs @@ -4,7 +4,10 @@ use std::sync::{Arc, Mutex}; use std::time::Duration; use miden_node_proto::generated::note_transport::SendNoteWithProofRequest; -use miden_node_proto::generated::rpc::{BlockHeaderByNumberRequest, BlockHeaderByNumberResponse}; +use miden_node_proto::generated::rpc::{ + GetBlockHeaderByNumberRequest, + GetBlockHeaderByNumberResponse, +}; use miden_node_proto::server::note_transport_api::SendNoteWithProof; use miden_protocol::block::{BlockHeader, BlockNoteIndex, BlockNoteTree}; use miden_protocol::note::NoteInclusionProof; @@ -12,7 +15,8 @@ use tonic::codegen::{BoxFuture, http}; use super::*; -type HeaderResponses = BTreeMap>>; +type HeaderResponses = + BTreeMap>>; #[derive(Clone)] struct NodeRpc { @@ -25,11 +29,11 @@ impl tonic::server::NamedService for NodeRpc { const NAME: &'static str = "rpc.Api"; } -impl tonic::server::UnaryService for NodeRpc { - type Response = BlockHeaderByNumberResponse; +impl tonic::server::UnaryService for NodeRpc { + type Response = GetBlockHeaderByNumberResponse; type Future = BoxFuture, tonic::Status>; - fn call(&mut self, request: Request) -> Self::Future { + fn call(&mut self, request: Request) -> Self::Future { let this = self.clone(); Box::pin(async move { // Return no header if the client asks for a different block or extra data. @@ -37,7 +41,7 @@ impl tonic::server::UnaryService for NodeRpc { if request.include_mmr_proof.unwrap_or(false) || request.include_protocol_config.unwrap_or(false) { - return Ok(tonic::Response::new(BlockHeaderByNumberResponse::default())); + return Ok(tonic::Response::new(GetBlockHeaderByNumberResponse::default())); } let block_num = request.block_num.unwrap(); this.requests.lock().unwrap().push(block_num); @@ -46,7 +50,7 @@ impl tonic::server::UnaryService for NodeRpc { match responses.get_mut(&block_num) { Some(responses) if responses.len() > 1 => responses.pop_front().unwrap(), Some(responses) => responses.front().unwrap().clone(), - None => Ok(BlockHeaderByNumberResponse::default()), + None => Ok(GetBlockHeaderByNumberResponse::default()), } }; tokio::time::sleep(this.delay).await; @@ -80,14 +84,14 @@ impl tower::Service> for NodeRpc { } async fn node_rpc( - response: Result, + response: Result, delay: Duration, ) -> (url::Url, tokio::task::JoinHandle<()>) { node_rpc_at_block(response, delay, 42).await } async fn node_rpc_at_block( - response: Result, + response: Result, delay: Duration, block_num: u32, ) -> (url::Url, tokio::task::JoinHandle<()>) { @@ -96,7 +100,7 @@ async fn node_rpc_at_block( } async fn node_rpc_responses( - responses: BTreeMap>, + responses: BTreeMap>, delay: Duration, ) -> (url::Url, tokio::task::JoinHandle<()>, Arc>>) { let responses = responses @@ -128,18 +132,18 @@ async fn node_rpc_script( (url, task, requests) } -fn fixture() -> (SendNoteWithProofRequest, BlockHeaderByNumberResponse) { +fn fixture() -> (SendNoteWithProofRequest, GetBlockHeaderByNumberResponse) { fixture_at_block(42) } -fn fixture_at_block(block_num: u32) -> (SendNoteWithProofRequest, BlockHeaderByNumberResponse) { +fn fixture_at_block(block_num: u32) -> (SendNoteWithProofRequest, GetBlockHeaderByNumberResponse) { fixture_for_note(block_num, note(1, 7)) } fn fixture_for_note( block_num: u32, note: TransportNote, -) -> (SendNoteWithProofRequest, BlockHeaderByNumberResponse) { +) -> (SendNoteWithProofRequest, GetBlockHeaderByNumberResponse) { let header = note.header.clone().unwrap().decode_fields().unwrap().verify().unwrap(); let index = BlockNoteIndex::new(3, 5).unwrap(); let tree = BlockNoteTree::with_entries([(index, &header)]).unwrap(); @@ -152,7 +156,7 @@ fn fixture_for_note( note: Some(note), inclusion_proof: Some((&header.id(), &proof).into()), }, - BlockHeaderByNumberResponse { + GetBlockHeaderByNumberResponse { block_header: Some(block.into()), ..Default::default() }, @@ -314,7 +318,7 @@ async fn lookup_failures_never_store_notes() { wrong_block.block_header = Some(BlockHeader::mock(43, None, None, &[]).into()); let cases = [ ( - Ok(BlockHeaderByNumberResponse::default()), + Ok(GetBlockHeaderByNumberResponse::default()), Duration::ZERO, tonic::Code::FailedPrecondition, ), @@ -466,7 +470,7 @@ async fn note_root_cache_evicts_the_least_recently_used_block() { let header = BlockHeader::mock(block_num, None, Some(root), &[]); ( block_num, - Ok(BlockHeaderByNumberResponse { + Ok(GetBlockHeaderByNumberResponse { block_header: Some(header.into()), ..Default::default() }), @@ -487,19 +491,19 @@ async fn note_root_cache_evicts_the_least_recently_used_block() { #[tokio::test] async fn note_root_cache_does_not_cache_failed_or_invalid_headers() { let cases = [ - (Ok(BlockHeaderByNumberResponse::default()), tonic::Code::FailedPrecondition), + (Ok(GetBlockHeaderByNumberResponse::default()), tonic::Code::FailedPrecondition), (Err(tonic::Status::not_found("missing")), tonic::Code::FailedPrecondition), (Err(tonic::Status::internal("upstream error")), tonic::Code::Unavailable), (Err(tonic::Status::deadline_exceeded("timeout")), tonic::Code::DeadlineExceeded), ( - Ok(BlockHeaderByNumberResponse { + Ok(GetBlockHeaderByNumberResponse { block_header: Some(miden_node_proto::generated::blockchain::BlockHeader::default()), ..Default::default() }), tonic::Code::Unavailable, ), ( - Ok(BlockHeaderByNumberResponse { + Ok(GetBlockHeaderByNumberResponse { block_header: Some(BlockHeader::mock(43, None, None, &[]).into()), ..Default::default() }), diff --git a/bin/ntx-builder/src/clients/prover.rs b/bin/ntx-builder/src/clients/prover.rs index 250198cd62..7fdd668df8 100644 --- a/bin/ntx-builder/src/clients/prover.rs +++ b/bin/ntx-builder/src/clients/prover.rs @@ -2,8 +2,8 @@ use std::time::Duration; use miden_node_proto::clients::{Builder, RemoteProverClient}; use miden_node_proto::errors::ConversionError; -use miden_node_proto::generated::remote_prover::proof_request::Request; -use miden_node_proto::generated::remote_prover::{DecodedProof, ProofRequest}; +use miden_node_proto::generated::remote_prover::prove_request::Request; +use miden_node_proto::generated::remote_prover::{DecodedProveResponse, ProveRequest}; use miden_node_proto::{BuildUnchecked, DecodeMessage}; use miden_protocol::transaction::{ProvenTransaction, TransactionInputs}; use miden_tx::TransactionProverError; @@ -37,7 +37,7 @@ impl RemoteTransactionProver { &self, tx_inputs: &TransactionInputs, ) -> Result { - let request = tonic::Request::new(ProofRequest { + let request = tonic::Request::new(ProveRequest { request: Some(Request::Transaction(tx_inputs.into())), }); @@ -48,7 +48,7 @@ impl RemoteTransactionProver { response .into_inner() .decode_fields() - .and_then(DecodedProof::into_transaction) + .and_then(DecodedProveResponse::into_transaction) // SAFETY: Construction checks transaction structure. The RPC checks the proof at // submission. // diff --git a/bin/ntx-builder/src/clients/rpc.rs b/bin/ntx-builder/src/clients/rpc.rs index 2d1b29cb94..4a3aefd2a2 100644 --- a/bin/ntx-builder/src/clients/rpc.rs +++ b/bin/ntx-builder/src/clients/rpc.rs @@ -12,7 +12,7 @@ use futures::{Stream, StreamExt}; use miden_node_proto::clients::{Builder, RpcClient as InnerRpcClient}; use miden_node_proto::VerifyWith; use miden_node_proto::domain::account::{ - AccountDetails, AccountResponse, AccountVaultDetails, StorageMapEntries + AccountDetails, GetAccountResponse, AccountVaultDetails, StorageMapEntries }; use miden_node_proto::domain::encryption::{ TransactionInputsSealer, @@ -20,11 +20,11 @@ use miden_node_proto::domain::encryption::{ }; use miden_node_proto::domain::protocol_config::ensure_protocol_config_is_present_and_matches_header; use miden_node_proto::errors::ConversionError; -use miden_node_proto::generated::rpc::account_request::account_detail_request::{StorageMapDetailRequest, StorageMapDetailRequests, StorageRequest, storage_map_detail_request}; -use miden_node_proto::generated::rpc::account_request::account_detail_request::storage_map_detail_request::MapKeys; +use miden_node_proto::generated::rpc::get_account_request::account_detail_request::{StorageMapDetailRequest, StorageMapDetailRequests, StorageRequest, storage_map_detail_request}; +use miden_node_proto::generated::rpc::get_account_request::account_detail_request::storage_map_detail_request::MapKeys; use miden_node_proto::generated::rpc::{ - BlockHeaderByNumberRequest, - BlockHeaderByNumberResponse, + GetBlockHeaderByNumberRequest, + GetBlockHeaderByNumberResponse, BlockSubscriptionRequest, }; use miden_node_proto::generated::{self as proto}; @@ -211,7 +211,14 @@ impl RpcClient { return Ok(sealer); } - let key = self.inner.clone().get_transaction_encryption_key(()).await?.into_inner(); + let key = self + .inner + .clone() + .get_transaction_encryption_key(proto::rpc::GetTransactionEncryptionKeyRequest {}) + .await? + .into_inner() + .key + .ok_or_else(|| tonic::Status::internal("missing transaction encryption key"))?; let verified = key .verify_with(TrustedTransactionEncryptionState::new( self.genesis_commitment, @@ -457,9 +464,11 @@ impl RpcClient { ) })?; client - .submit_proven_tx(proto::submission::ProvenTransactionSubmission { - transaction: Some(transaction), - sealed_transaction_inputs: Some(sealed), + .submit_proven_tx(proto::rpc::SubmitProvenTxRequest { + submission: Some(proto::submission::ProvenTransactionSubmission { + transaction: Some(transaction), + sealed_transaction_inputs: Some(sealed), + }), }) .await } @@ -480,8 +489,8 @@ impl RpcClient { } } -fn startup_header_request(block_num: BlockNumber) -> BlockHeaderByNumberRequest { - BlockHeaderByNumberRequest { +fn startup_header_request(block_num: BlockNumber) -> GetBlockHeaderByNumberRequest { + GetBlockHeaderByNumberRequest { block_num: Some(block_num.as_u32()), include_mmr_proof: None, include_protocol_config: Some(true), @@ -489,7 +498,7 @@ fn startup_header_request(block_num: BlockNumber) -> BlockHeaderByNumberRequest } fn decode_startup_header_response( - response: BlockHeaderByNumberResponse, + response: GetBlockHeaderByNumberResponse, expected_header: &miden_protocol::block::BlockHeader, ) -> Result { let header: miden_protocol::block::BlockHeader = response @@ -523,11 +532,11 @@ impl RpcClient { block_num: BlockNumber, ) -> Result { // Only request account code - let request = proto::rpc::AccountRequest { + let request = proto::rpc::GetAccountRequest { account_id: Some(account_id.into()), block_num: Some(block_num.into()), // TODO: should these commitments be cached on the NTX builder? - details: Some(proto::rpc::account_request::AccountDetailRequest { + details: Some(proto::rpc::get_account_request::AccountDetailRequest { code_commitment: Some(Word::default().into()), asset_vault_commitment: None, // storage_request: None, @@ -554,10 +563,10 @@ impl RpcClient { return Ok(Vec::new()); } - let request = proto::rpc::AccountRequest { + let request = proto::rpc::GetAccountRequest { account_id: Some(account_id.into()), block_num: block_num.map(Into::into), - details: Some(proto::rpc::account_request::AccountDetailRequest { + details: Some(proto::rpc::get_account_request::AccountDetailRequest { code_commitment: None, asset_vault_commitment: Some(Word::default().into()), storage_request: None, @@ -592,10 +601,10 @@ impl RpcClient { map_key: StorageMapKey, block_num: Option, ) -> Result { - let request = proto::rpc::AccountRequest { + let request = proto::rpc::GetAccountRequest { account_id: Some(account_id.into()), block_num: block_num.map(Into::into), - details: Some(proto::rpc::account_request::AccountDetailRequest { + details: Some(proto::rpc::get_account_request::AccountDetailRequest { code_commitment: None, asset_vault_commitment: None, storage_request: Some(StorageRequest::StorageMaps(StorageMapDetailRequests { @@ -657,7 +666,7 @@ impl RpcClient { &self, script_root: Word, ) -> Result, RpcError> { - let request = proto::rpc::NoteScriptByRootRequest { root: Some(script_root.into()) }; + let request = proto::rpc::GetNoteScriptByRootRequest { root: Some(script_root.into()) }; self.inner .clone() @@ -669,11 +678,12 @@ impl RpcClient { .map_err(RpcError::Conversion) } - /// Issues a `GetAccount` request and decodes the response into the domain [`AccountResponse`]. + /// Issues a `GetAccount` request and decodes the response into the domain + /// [`GetAccountResponse`]. async fn get_account( &self, - request: proto::rpc::AccountRequest, - ) -> Result { + request: proto::rpc::GetAccountRequest, + ) -> Result { let response = self .inner .clone() @@ -726,8 +736,8 @@ pub enum RpcError { mod protocol_config_tests { use miden_node_proto::generated::protocol_config::ProtocolConfig as ProtoProtocolConfig; use miden_node_proto::generated::rpc::{ - BlockHeaderByNumberResponse, BlockSubscriptionResponse, + GetBlockHeaderByNumberResponse, }; use miden_node_proto::{BuildUnchecked, DecodeMessage}; use miden_node_store::genesis::GenesisState; @@ -840,7 +850,7 @@ mod protocol_config_tests { fn startup_decoder_rejects_missing_protocol_config() { let config = test_protocol_config(); let header = header_for_config(42, &config); - let response = BlockHeaderByNumberResponse { + let response = GetBlockHeaderByNumberResponse { block_header: Some((&header).into()), chain_length: None, mmr_path: None, @@ -856,7 +866,7 @@ mod protocol_config_tests { let config = test_protocol_config(); let other = other_protocol_config(); let header = header_for_config(42, &config); - let response = BlockHeaderByNumberResponse { + let response = GetBlockHeaderByNumberResponse { block_header: Some((&header).into()), chain_length: None, mmr_path: None, @@ -872,7 +882,7 @@ mod protocol_config_tests { let config = test_protocol_config(); let local = header_for_config(42, &config); let remote = header_for_config(43, &config); - let response = BlockHeaderByNumberResponse { + let response = GetBlockHeaderByNumberResponse { block_header: Some((&remote).into()), chain_length: None, mmr_path: None, diff --git a/bin/ntx-builder/src/server/get_network_note_status.rs b/bin/ntx-builder/src/server/get_network_note_status.rs index f7527a5662..f69b90914e 100644 --- a/bin/ntx-builder/src/server/get_network_note_status.rs +++ b/bin/ntx-builder/src/server/get_network_note_status.rs @@ -8,10 +8,15 @@ use crate::{COMPONENT, LOG_TARGET}; #[tonic::async_trait] impl grpc::server::ntx_builder_api::GetNetworkNoteStatus for NtxBuilderRpcServer { type Input = miden_protocol::note::NoteId; - type Output = grpc::rpc::GetNetworkNoteStatusResponse; + type Output = grpc::ntx_builder::GetNetworkNoteStatusResponse; - fn decode(request: grpc::note::NoteId) -> tonic::Result { + fn decode( + request: grpc::ntx_builder::GetNetworkNoteStatusRequest, + ) -> tonic::Result { let note_id_digest: Word = request + .note_id + .as_ref() + .ok_or_else(|| tonic::Status::invalid_argument("missing note ID"))? .id .as_ref() .ok_or_else(|| tonic::Status::invalid_argument("missing note ID digest"))? @@ -60,7 +65,7 @@ impl grpc::server::ntx_builder_api::GetNetworkNoteStatus for NtxBuilderRpcServer let status = derive_status(row.committed_at.is_some(), attempt_count, self.max_note_attempts); - Ok(grpc::rpc::GetNetworkNoteStatusResponse { + Ok(grpc::ntx_builder::GetNetworkNoteStatusResponse { status: status.into(), last_error: row.last_error, attempt_count: response_attempt_count, @@ -68,7 +73,9 @@ impl grpc::server::ntx_builder_api::GetNetworkNoteStatus for NtxBuilderRpcServer }) } - fn encode(output: Self::Output) -> tonic::Result { + fn encode( + output: Self::Output, + ) -> tonic::Result { Ok(output) } } @@ -99,9 +106,31 @@ mod tests { use super::*; + #[test] + fn decode_rejects_missing_note_id() { + let error = NtxBuilderRpcServer::decode(grpc::ntx_builder::GetNetworkNoteStatusRequest { + note_id: None, + }) + .unwrap_err(); + assert_eq!(error.code(), tonic::Code::InvalidArgument); + } + + #[test] + fn decode_preserves_note_id() { + let note_id = miden_protocol::note::NoteId::from_raw(Word::from([1u32, 2, 3, 4])); + let decoded = NtxBuilderRpcServer::decode(grpc::ntx_builder::GetNetworkNoteStatusRequest { + note_id: Some(note_id.as_word().into()), + }) + .unwrap(); + assert_eq!(decoded, note_id); + } + #[test] fn decode_note_id_rejects_missing_digest() { - let err = NtxBuilderRpcServer::decode(NoteId { id: None }).unwrap_err(); + let err = NtxBuilderRpcServer::decode(grpc::ntx_builder::GetNetworkNoteStatusRequest { + note_id: Some(NoteId { id: None }), + }) + .unwrap_err(); assert_eq!(err.code(), tonic::Code::InvalidArgument); assert_eq!(err.message(), "missing note ID digest"); } diff --git a/bin/remote-prover/src/server/prove.rs b/bin/remote-prover/src/server/prove.rs index 01fc0d3a16..a49815651d 100644 --- a/bin/remote-prover/src/server/prove.rs +++ b/bin/remote-prover/src/server/prove.rs @@ -8,8 +8,8 @@ use crate::server::service::ProverService; #[tonic::async_trait] impl grpc::server::remote_prover_api::Prove for ProverService { - type Input = (ProofKind, grpc::remote_prover::ProofRequest); - type Output = grpc::remote_prover::Proof; + type Input = (ProofKind, grpc::remote_prover::ProveRequest); + type Output = grpc::remote_prover::ProveResponse; #[miden_instrument( target = COMPONENT, @@ -47,8 +47,8 @@ impl grpc::server::remote_prover_api::Prove for ProverService { .map_err(|e| tonic::Status::internal(e.as_report_context(task_panic_context)))? } - fn decode(request: grpc::remote_prover::ProofRequest) -> tonic::Result { - use grpc::remote_prover::proof_request::Request; + fn decode(request: grpc::remote_prover::ProveRequest) -> tonic::Result { + use grpc::remote_prover::prove_request::Request; let proof_kind = match request.request.as_ref() { Some(Request::Transaction(_)) => ProofKind::Transaction, @@ -60,7 +60,7 @@ impl grpc::server::remote_prover_api::Prove for ProverService { Ok((proof_kind, request)) } - fn encode(output: Self::Output) -> tonic::Result { + fn encode(output: Self::Output) -> tonic::Result { Ok(output) } } diff --git a/bin/remote-prover/src/server/prover.rs b/bin/remote-prover/src/server/prover.rs index cb33779ffc..771a0ed269 100644 --- a/bin/remote-prover/src/server/prover.rs +++ b/bin/remote-prover/src/server/prover.rs @@ -1,6 +1,6 @@ use miden_block_prover::{BlockExecutor, LocalBlockProver}; -use miden_node_proto::generated::remote_prover::proof::Proof as ProofVariant; -use miden_node_proto::generated::remote_prover::proof_request::DecodedRequest as Request; +use miden_node_proto::generated::remote_prover::prove_request::DecodedRequest as Request; +use miden_node_proto::generated::remote_prover::prove_response::Proof as ProofVariant; use miden_node_proto::generated::{block_proving, remote_prover as proto, transaction}; use miden_node_proto::{BlockProofRequest, BuildUnchecked, DecodeMessage, Decoded, VerifyWith}; use miden_node_tracing::{ErrorReport, miden_instrument}; @@ -36,7 +36,10 @@ impl Prover { name="prove", err, )] - pub fn prove(&self, request: proto::ProofRequest) -> Result { + pub fn prove( + &self, + request: proto::ProveRequest, + ) -> Result { let request = request .decode_fields() .map_err(miden_node_proto::errors::ConversionError::into_status)? @@ -51,7 +54,7 @@ impl Prover { _ => return Err(tonic::Status::invalid_argument("unsupported proof type")), }; - Ok(proto::Proof { proof: Some(proof) }) + Ok(proto::ProveResponse { proof: Some(proof) }) } /// Returns the context attached to failures of the blocking task running this prover. diff --git a/bin/remote-prover/src/server/status.rs b/bin/remote-prover/src/server/status.rs index b8e60c3c4f..6e63a3bbf2 100644 --- a/bin/remote-prover/src/server/status.rs +++ b/bin/remote-prover/src/server/status.rs @@ -15,7 +15,7 @@ impl StatusService { #[tonic::async_trait] impl grpc::server::remote_prover_worker_status_api::Status for StatusService { type Input = (); - type Output = grpc::remote_prover::WorkerStatus; + type Output = grpc::remote_prover::WorkerStatusResponse; async fn handle( &self, @@ -23,17 +23,17 @@ impl grpc::server::remote_prover_worker_status_api::Status for StatusService { _metadata: &tonic::metadata::MetadataMap, _extensions: &tonic::codegen::http::Extensions, ) -> tonic::Result { - Ok(grpc::remote_prover::WorkerStatus { + Ok(grpc::remote_prover::WorkerStatusResponse { version: env!("CARGO_PKG_VERSION").to_string(), supported_proof_type: self.kind as i32, }) } - fn decode(_request: ()) -> tonic::Result { + fn decode(_request: grpc::remote_prover::WorkerStatusRequest) -> tonic::Result { Ok(()) } - fn encode(output: Self::Output) -> tonic::Result { + fn encode(output: Self::Output) -> tonic::Result { Ok(output) } } diff --git a/bin/remote-prover/src/server/tests.rs b/bin/remote-prover/src/server/tests.rs index de3ec25591..161cad6861 100644 --- a/bin/remote-prover/src/server/tests.rs +++ b/bin/remote-prover/src/server/tests.rs @@ -5,9 +5,9 @@ use std::time::Duration; use assert_matches::assert_matches; use miden_node_proto::generated::remote_prover::api_client::ApiClient; -use miden_node_proto::generated::remote_prover::proof::Proof as ProofVariant; -use miden_node_proto::generated::remote_prover::proof_request::Request; -use miden_node_proto::generated::remote_prover::{Proof, ProofRequest}; +use miden_node_proto::generated::remote_prover::prove_request::Request; +use miden_node_proto::generated::remote_prover::prove_response::Proof as ProofVariant; +use miden_node_proto::generated::remote_prover::{ProveRequest, ProveResponse}; use miden_node_proto::{BlockProofRequest, BuildUnchecked, DecodeMessage, VerifyWith}; use miden_node_utils::shutdown::CancellationToken; use miden_protocol::MIN_PROOF_SECURITY_LEVEL; @@ -42,36 +42,39 @@ impl Client { Self { inner } } - async fn submit_request(&mut self, request: ProofRequest) -> Result { + async fn submit_request( + &mut self, + request: ProveRequest, + ) -> Result { self.inner.prove(request).await.map(tonic::Response::into_inner) } } trait ProofRequestExt { /// Generates a proof request for a transaction using [`MockChain`]. - fn from_tx(tx: &ExecutedTransaction) -> ProofRequest; - fn from_batch(batch: &ProposedBatch) -> ProofRequest; - fn for_empty_block() -> ProofRequest; + fn from_tx(tx: &ExecutedTransaction) -> ProveRequest; + fn from_batch(batch: &ProposedBatch) -> ProveRequest; + fn for_empty_block() -> ProveRequest; async fn mock_tx() -> ExecutedTransaction; async fn mock_batch() -> ProposedBatch; } -impl ProofRequestExt for ProofRequest { - fn from_tx(tx: &ExecutedTransaction) -> ProofRequest { +impl ProofRequestExt for ProveRequest { + fn from_tx(tx: &ExecutedTransaction) -> ProveRequest { let tx_inputs = tx.tx_inputs().clone(); - ProofRequest { + ProveRequest { request: Some(Request::Transaction(tx_inputs.into())), } } - fn from_batch(batch: &ProposedBatch) -> ProofRequest { - ProofRequest { + fn from_batch(batch: &ProposedBatch) -> ProveRequest { + ProveRequest { request: Some(Request::Batch(batch.into())), } } - fn for_empty_block() -> ProofRequest { + fn for_empty_block() -> ProveRequest { let partial_blockchain = PartialBlockchain::default(); let block_inputs = BlockInputs::new( BlockHeader::mock(0, Some(partial_blockchain.peaks().hash_peaks()), None, &[]), @@ -93,7 +96,7 @@ impl ProofRequestExt for ProofRequest { block_inputs, }; - ProofRequest { + ProveRequest { request: Some(Request::Block(request.into())), } } @@ -221,7 +224,7 @@ async fn legacy_behaviour_with_capacity_1() { .await .expect("server should spawn"); - let request = ProofRequest::from_tx(&ProofRequest::mock_tx().await); + let request = ProveRequest::from_tx(&ProveRequest::mock_tx().await); let mut client_a = Client::connect(port).await; let mut client_b = client_a.clone(); @@ -256,7 +259,7 @@ async fn capacity_is_respected() { .await .expect("server should spawn"); - let request = ProofRequest::from_tx(&ProofRequest::mock_tx().await); + let request = ProveRequest::from_tx(&ProveRequest::mock_tx().await); let mut client_a = Client::connect(port).await; let mut client_b = client_a.clone(); let mut client_c = client_a.clone(); @@ -294,7 +297,7 @@ async fn timeout_is_respected() { .await .expect("server should spawn"); - let request = ProofRequest::from_tx(&ProofRequest::mock_tx().await); + let request = ProveRequest::from_tx(&ProveRequest::mock_tx().await); let mut client_a = Client::connect(port).await; let mut client_b = Client::connect(port).await; @@ -324,7 +327,7 @@ async fn missing_request_variant_is_rejected() { .expect("server should spawn"); let mut client = Client::connect(port).await; - let response = client.submit_request(ProofRequest { request: None }).await; + let response = client.submit_request(ProveRequest { request: None }).await; let err = response.unwrap_err(); assert_eq!(err.code(), tonic::Code::InvalidArgument); @@ -341,7 +344,7 @@ async fn malformed_transaction_inputs_are_rejected() { .await .expect("server should spawn"); - let request = ProofRequest { + let request = ProveRequest { request: Some(Request::Transaction( miden_node_proto::generated::transaction::TransactionInputs::default(), )), @@ -363,7 +366,7 @@ async fn malformed_batch_inputs_are_rejected() { .await .expect("server should spawn"); - let request = ProofRequest { + let request = ProveRequest { request: Some(Request::Batch( miden_node_proto::generated::transaction::ProposedBatch::default(), )), @@ -385,7 +388,7 @@ async fn malformed_block_inputs_are_rejected() { .await .expect("server should spawn"); - let request = ProofRequest { + let request = ProveRequest { request: Some(Request::Block( miden_node_proto::generated::block_proving::BlockProofRequest::default(), )), @@ -410,7 +413,7 @@ async fn unsupported_proof_kind_is_rejected() { .await .expect("server should spawn"); - let request = ProofRequest::from_tx(&ProofRequest::mock_tx().await); + let request = ProveRequest::from_tx(&ProveRequest::mock_tx().await); let mut client = Client::connect(port).await; let response = client.submit_request(request).await; @@ -433,8 +436,8 @@ async fn transaction_proof_is_correct() { .await .expect("server should spawn"); - let tx = ProofRequest::mock_tx().await; - let request = ProofRequest::from_tx(&tx); + let tx = ProveRequest::mock_tx().await; + let request = ProveRequest::from_tx(&tx); let mut client = Client::connect(port).await; let response = client.submit_request(request).await.unwrap(); @@ -463,8 +466,8 @@ async fn batch_proof_is_correct() { .await .expect("server should spawn"); - let batch = ProofRequest::mock_batch().await; - let request = ProofRequest::from_batch(&batch); + let batch = ProveRequest::mock_batch().await; + let request = ProveRequest::from_batch(&batch); let mut client = Client::connect(port).await; let response = client.submit_request(request).await.unwrap(); @@ -488,7 +491,7 @@ async fn block_proof_is_canonical_execution_proof() { .await .expect("server should spawn"); - let request = ProofRequest::for_empty_block(); + let request = ProveRequest::for_empty_block(); let mut client = Client::connect(port).await; let response = client.submit_request(request).await.unwrap(); let proof = match response.proof.unwrap() { diff --git a/bin/stress-test/src/seeding/tests.rs b/bin/stress-test/src/seeding/tests.rs index 420b96de3c..0e45eb1bc9 100644 --- a/bin/stress-test/src/seeding/tests.rs +++ b/bin/stress-test/src/seeding/tests.rs @@ -156,8 +156,8 @@ fn private_account_storage_map_update_is_skipped() { async fn seed_store_persists_one_public_account_and_applies_one_map_update() { use miden_node_proto::domain::account::{ AccountDetailRequest, - AccountRequest, AccountStorageRequest, + GetAccountRequest, StorageMapEntries, }; @@ -173,7 +173,7 @@ async fn seed_store_persists_one_public_account_and_applies_one_map_update() { let (state, block_writer, writer_task) = load_state(data_directory).await; let response = state .view() - .get_account(AccountRequest { + .get_account(GetAccountRequest { account_id, block_num: None, details: Some(AccountDetailRequest { @@ -207,7 +207,7 @@ async fn seed_store_persists_one_public_account_and_applies_one_map_update() { #[tokio::test(flavor = "multi_thread")] async fn seed_store_handles_map_larger_than_transaction_account_update_limit() { - use miden_node_proto::domain::account::AccountRequest; + use miden_node_proto::domain::account::GetAccountRequest; let temp_dir = tempfile::tempdir().unwrap(); let data_directory = temp_dir.path().join("store"); @@ -221,7 +221,7 @@ async fn seed_store_handles_map_larger_than_transaction_account_update_limit() { let (state, block_writer, writer_task) = load_state(data_directory).await; let response = state .view() - .get_account(AccountRequest { + .get_account(GetAccountRequest { account_id, block_num: None, details: None, diff --git a/bin/stress-test/src/store/mod.rs b/bin/stress-test/src/store/mod.rs index 4271f103dc..4e0dc45bed 100644 --- a/bin/stress-test/src/store/mod.rs +++ b/bin/stress-test/src/store/mod.rs @@ -120,13 +120,13 @@ async fn get_account( account_id: AccountId, storage_map_slot: String, ) -> GetAccountRun { - use proto::rpc::account_storage_details::account_storage_map_details::Result; + use miden_node_proto::generated::rpc::account_storage_details::account_storage_map_details::Result; let request = get_account_request(account_id, storage_map_slot); let start = Instant::now(); let request = request.decode_and_verify().expect("request should be valid"); - let response: proto::rpc::AccountResponse = + let response: proto::rpc::GetAccountResponse = state.view().get_account(request).await.unwrap().into(); let duration = start.elapsed(); @@ -163,16 +163,16 @@ async fn get_account( fn get_account_request( account_id: AccountId, storage_map_slot: String, -) -> proto::rpc::AccountRequest { - use proto::rpc::account_request::AccountDetailRequest; - use proto::rpc::account_request::account_detail_request::storage_map_detail_request::SlotData; - use proto::rpc::account_request::account_detail_request::{ +) -> proto::rpc::GetAccountRequest { + use miden_node_proto::generated::rpc::get_account_request::AccountDetailRequest; + use miden_node_proto::generated::rpc::get_account_request::account_detail_request::storage_map_detail_request::SlotData; + use miden_node_proto::generated::rpc::get_account_request::account_detail_request::{ StorageMapDetailRequest, StorageMapDetailRequests, StorageRequest, }; - proto::rpc::AccountRequest { + proto::rpc::GetAccountRequest { account_id: Some(account_id.into()), block_num: None, details: Some(AccountDetailRequest { diff --git a/bin/validator/src/server/validator_service/get_transaction_encryption_key.rs b/bin/validator/src/server/validator_service/get_transaction_encryption_key.rs index 010a6bec7d..fc2c8ca235 100644 --- a/bin/validator/src/server/validator_service/get_transaction_encryption_key.rs +++ b/bin/validator/src/server/validator_service/get_transaction_encryption_key.rs @@ -9,12 +9,16 @@ impl grpc::server::validator_api::GetTransactionEncryptionKey for ValidatorServi type Input = (); type Output = grpc::submission::TransactionEncryptionKey; - fn decode(request: ()) -> tonic::Result { - Ok(request) + fn decode( + _request: grpc::validator::GetTransactionEncryptionKeyRequest, + ) -> tonic::Result { + Ok(()) } - fn encode(output: Self::Output) -> tonic::Result { - Ok(output) + fn encode( + output: Self::Output, + ) -> tonic::Result { + Ok(grpc::validator::GetTransactionEncryptionKeyResponse { key: Some(output) }) } #[miden_instrument( diff --git a/bin/validator/src/server/validator_service/status.rs b/bin/validator/src/server/validator_service/status.rs index c6d86ffe7d..44785ba062 100644 --- a/bin/validator/src/server/validator_service/status.rs +++ b/bin/validator/src/server/validator_service/status.rs @@ -11,8 +11,8 @@ impl grpc::server::validator_api::Status for ValidatorService { async fn full( &self, - _request: tonic::Request<()>, - ) -> tonic::Result { + _request: tonic::Request, + ) -> tonic::Result { // Unlike the other RPCs, status stays available during a backup so operators can observe // the validator. A failed read means a backup subscription holds the exclusive lock. let status = match self.serve_lock.try_read() { @@ -20,7 +20,7 @@ impl grpc::server::validator_api::Status for ValidatorService { Err(_) => "BACKUP", }; - Ok(grpc::validator::ValidatorStatus { + Ok(grpc::validator::StatusResponse { version: env!("CARGO_PKG_VERSION").to_string(), status: status.to_string(), chain_tip: self.committed_tip.borrow().as_u32(), @@ -38,11 +38,11 @@ impl grpc::server::validator_api::Status for ValidatorService { unimplemented!() } - fn decode(_request: ()) -> tonic::Result { + fn decode(_request: grpc::validator::StatusRequest) -> tonic::Result { unimplemented!() } - fn encode(_output: Self::Output) -> tonic::Result { + fn encode(_output: Self::Output) -> tonic::Result { unimplemented!() } } diff --git a/bin/validator/src/server/validator_service/submit_proven_transaction.rs b/bin/validator/src/server/validator_service/submit_proven_transaction.rs index c84fe8ba9e..17266e011d 100644 --- a/bin/validator/src/server/validator_service/submit_proven_transaction.rs +++ b/bin/validator/src/server/validator_service/submit_proven_transaction.rs @@ -102,8 +102,11 @@ impl grpc::server::validator_api::SubmitProvenTransaction for ValidatorService { } fn decode( - request: grpc::submission::ProvenTransactionSubmission, + request: grpc::validator::SubmitProvenTransactionRequest, ) -> tonic::Result { + let request = request + .submission + .ok_or_else(|| Status::invalid_argument("missing submission"))?; let submission = request // SAFETY: New transaction IDs pass proof verification and re-execution before storage. // Previously validated IDs use the handler's duplicate-submission shortcut. @@ -121,8 +124,8 @@ impl grpc::server::validator_api::SubmitProvenTransaction for ValidatorService { Ok(Self::Input { tx, sealed }) } - fn encode(output: Self::Output) -> tonic::Result<()> { - Ok(output) + fn encode((): Self::Output) -> tonic::Result { + Ok(grpc::validator::SubmitProvenTransactionResponse {}) } } diff --git a/bin/validator/src/server/validator_service/tests.rs b/bin/validator/src/server/validator_service/tests.rs index 6627e8851c..19de67319c 100644 --- a/bin/validator/src/server/validator_service/tests.rs +++ b/bin/validator/src/server/validator_service/tests.rs @@ -147,7 +147,14 @@ impl TestValidator { transaction: Some(tx.into()), sealed_transaction_inputs: Some(sealed), }); - validator_api::SubmitProvenTransaction::full(&self.server, request).await + validator_api::SubmitProvenTransaction::full( + &self.server, + request.map(|submission| proto::validator::SubmitProvenTransactionRequest { + submission: Some(submission), + }), + ) + .await + .map(|_| ()) } /// Seals `plaintext` exactly as a well-behaved client would: against the key this validator @@ -234,10 +241,13 @@ impl TestValidator { } /// Calls the `status` endpoint on the validator server. - async fn call_status(&self) -> proto::validator::ValidatorStatus { - validator_api::Status::full(&self.server, tonic::Request::new(())) - .await - .expect("status should always be available") + async fn call_status(&self) -> proto::validator::StatusResponse { + validator_api::Status::full( + &self.server, + tonic::Request::new(proto::validator::StatusRequest {}), + ) + .await + .expect("status should always be available") } /// Returns whether `tx_id` has a validated transaction marker. @@ -264,9 +274,14 @@ impl TestValidator { async fn call_get_transaction_encryption_key( &self, ) -> proto::submission::TransactionEncryptionKey { - validator_api::GetTransactionEncryptionKey::full(&self.server, tonic::Request::new(())) - .await - .expect("encryption key should always be available") + validator_api::GetTransactionEncryptionKey::full( + &self.server, + tonic::Request::new(proto::validator::GetTransactionEncryptionKeyRequest {}), + ) + .await + .expect("encryption key should always be available") + .key + .expect("transaction encryption key") } /// Asserts that opening a backup subscription is rejected with `resource_exhausted`. The @@ -1358,6 +1373,18 @@ async fn encryption_key_available_during_backup() { // SUBMIT PATH: TRANSACTION INPUT SEALING // ================================================================================================ +#[tokio::test] +async fn submit_rejects_missing_submission() { + let tv = TestValidator::new().await; + let request = + tonic::Request::new(proto::validator::SubmitProvenTransactionRequest { submission: None }); + let status = validator_api::SubmitProvenTransaction::full(&tv.server, request) + .await + .unwrap_err(); + assert_eq!(status.code(), tonic::Code::InvalidArgument); + assert_eq!(tv.validated_transaction_count().await, 0); +} + /// A submission with no encrypted inputs is rejected before validation. #[tokio::test] async fn submit_rejects_missing_encrypted_inputs() { @@ -1368,9 +1395,14 @@ async fn submit_rejects_missing_encrypted_inputs() { sealed_transaction_inputs: None, }); - let status = validator_api::SubmitProvenTransaction::full(&tv.server, request) - .await - .unwrap_err(); + let status = validator_api::SubmitProvenTransaction::full( + &tv.server, + request.map(|submission| proto::validator::SubmitProvenTransactionRequest { + submission: Some(submission), + }), + ) + .await + .unwrap_err(); assert_eq!(status.code(), tonic::Code::InvalidArgument); assert!(status.message().contains("sealed_transaction_inputs:"), "{}", status.message()); diff --git a/crates/block-producer/src/block_prover.rs b/crates/block-producer/src/block_prover.rs index 08d70c6615..a55291401b 100644 --- a/crates/block-producer/src/block_prover.rs +++ b/crates/block-producer/src/block_prover.rs @@ -4,8 +4,8 @@ use miden_block_prover::{ LocalBlockProver, }; use miden_node_proto::clients::{Builder, RemoteProverClient}; -use miden_node_proto::generated::remote_prover::proof_request::Request; -use miden_node_proto::generated::remote_prover::{DecodedProof, ProofRequest}; +use miden_node_proto::generated::remote_prover::prove_request::Request; +use miden_node_proto::generated::remote_prover::{DecodedProveResponse, ProveRequest}; use miden_node_proto::{BlockProofRequest, DecodeMessage}; use miden_node_tracing::miden_instrument; use miden_node_tracing::spawn::spawn_blocking_in_current_span; @@ -130,7 +130,7 @@ impl RemoteBlockProver { } async fn prove(&self, request: BlockProofRequest) -> Result { - let request = tonic::Request::new(ProofRequest { + let request = tonic::Request::new(ProveRequest { request: Some(Request::Block(request.into())), }); @@ -139,7 +139,7 @@ impl RemoteBlockProver { response .into_inner() .decode_fields() - .and_then(DecodedProof::into_block) + .and_then(DecodedProveResponse::into_block) .map_err(RemoteProverError::Conversion) } } diff --git a/crates/block-producer/src/fee_collector.rs b/crates/block-producer/src/fee_collector.rs index 8da73cb313..f1a07ed099 100644 --- a/crates/block-producer/src/fee_collector.rs +++ b/crates/block-producer/src/fee_collector.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use std::time::Duration; use anyhow::Context; -use miden_node_proto::domain::account::AccountRequest; +use miden_node_proto::domain::account::GetAccountRequest; use miden_node_store::state::{BlockWriter, ProofWriter, State}; use miden_node_tracing::spawn::spawn_blocking_in_current_span; use miden_node_tracing::{info, miden_instrument, miden_span_record}; @@ -148,7 +148,7 @@ pub(crate) async fn load_deployed_collector( async fn collector_is_deployed(state: &State, account: &Account) -> anyhow::Result { let response = state .view() - .get_account(AccountRequest { + .get_account(GetAccountRequest { account_id: account.id(), block_num: None, details: None, diff --git a/crates/block-producer/src/fee_collector/faucet.rs b/crates/block-producer/src/fee_collector/faucet.rs index 35f780db41..566df46bd2 100644 --- a/crates/block-producer/src/fee_collector/faucet.rs +++ b/crates/block-producer/src/fee_collector/faucet.rs @@ -1,8 +1,8 @@ use anyhow::Context; use miden_node_proto::domain::account::{ AccountDetailRequest, - AccountRequest, AccountStorageRequest, + GetAccountRequest, SlotData, StorageMapEntries, StorageMapRequest, @@ -41,7 +41,7 @@ impl FeeFaucet { .context("protocol configuration is missing")?; let id = config.fee_asset_id().faucet_id(); let response = view - .get_account(AccountRequest { + .get_account(GetAccountRequest { account_id: id, block_num: None, details: Some(AccountDetailRequest { @@ -62,7 +62,7 @@ impl FeeFaucet { block: BlockNumber, ) -> anyhow::Result { let response = view - .get_account(AccountRequest { + .get_account(GetAccountRequest { account_id: self.id, block_num: Some(block), details: Some(AccountDetailRequest { @@ -105,7 +105,7 @@ impl FeeFaucet { .name() .clone(); let response = view - .get_account(AccountRequest { + .get_account(GetAccountRequest { account_id: self.id, block_num: Some(block), details: Some(AccountDetailRequest { diff --git a/crates/block-producer/src/fee_collector/tests.rs b/crates/block-producer/src/fee_collector/tests.rs index 560f25ed93..30b259089f 100644 --- a/crates/block-producer/src/fee_collector/tests.rs +++ b/crates/block-producer/src/fee_collector/tests.rs @@ -179,12 +179,16 @@ impl validator_api::GetTransactionEncryptionKey for Validator { type Input = (); type Output = proto::submission::TransactionEncryptionKey; - fn decode(input: ()) -> tonic::Result { - Ok(input) + fn decode( + _request: proto::validator::GetTransactionEncryptionKeyRequest, + ) -> tonic::Result { + Ok(()) } - fn encode(output: Self::Output) -> tonic::Result { - Ok(output) + fn encode( + output: Self::Output, + ) -> tonic::Result { + Ok(proto::validator::GetTransactionEncryptionKeyResponse { key: Some(output) }) } async fn handle( @@ -219,12 +223,18 @@ impl validator_api::SubmitProvenTransaction for Validator { type Input = proto::submission::ProvenTransactionSubmission; type Output = (); - fn decode(input: Self::Input) -> tonic::Result { - Ok(input) + fn decode( + request: proto::validator::SubmitProvenTransactionRequest, + ) -> tonic::Result { + request + .submission + .ok_or_else(|| tonic::Status::invalid_argument("missing submission")) } - fn encode(output: Self::Output) -> tonic::Result { - Ok(output) + fn encode( + (): Self::Output, + ) -> tonic::Result { + Ok(proto::validator::SubmitProvenTransactionResponse {}) } async fn handle( @@ -305,10 +315,10 @@ impl validator_api::SignBlock for Validator { #[tonic::async_trait] impl validator_api::Status for Validator { type Input = (); - type Output = proto::validator::ValidatorStatus; + type Output = proto::validator::StatusResponse; - fn decode(input: ()) -> tonic::Result { - Ok(input) + fn decode(_request: proto::validator::StatusRequest) -> tonic::Result { + Ok(()) } fn encode(output: Self::Output) -> tonic::Result { diff --git a/crates/block-producer/src/rpc_sync.rs b/crates/block-producer/src/rpc_sync.rs index 787b921fae..8725aae939 100644 --- a/crates/block-producer/src/rpc_sync.rs +++ b/crates/block-producer/src/rpc_sync.rs @@ -207,8 +207,13 @@ impl BlockSync { let (parent, _) = self.state.view().get_block_header(Some(local_tip), false).await?; let mut parent = parent.context("local chain tip header not found")?; let mut client = self.source_rpc.clone(); - let upstream_tip = - BlockNumber::from(client.status(tonic::Request::new(())).await?.into_inner().chain_tip); + let upstream_tip = BlockNumber::from( + client + .status(tonic::Request::new(miden_node_proto::generated::rpc::StatusRequest {})) + .await? + .into_inner() + .chain_tip, + ); self.readiness.update(upstream_tip, local_tip).await; let block_from = local_tip.child().as_u32(); diff --git a/crates/block-producer/src/rpc_sync/block_tests.rs b/crates/block-producer/src/rpc_sync/block_tests.rs index 30fef81aef..1c925910e9 100644 --- a/crates/block-producer/src/rpc_sync/block_tests.rs +++ b/crates/block-producer/src/rpc_sync/block_tests.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; use miden_node_proto::clients::Builder; use miden_node_proto::generated as proto; -use miden_node_proto::generated::rpc::{BlockSubscriptionResponse, RpcStatus}; +use miden_node_proto::generated::rpc::{BlockSubscriptionResponse, StatusResponse}; use miden_node_proto::generated::server::rpc_api; use miden_node_store::GenesisState; use miden_node_utils::clap::StorageOptions; @@ -28,13 +28,13 @@ struct Upstream(Vec); #[tonic::async_trait] impl rpc_api::Status for Upstream { type Input = (); - type Output = RpcStatus; + type Output = StatusResponse; - fn decode(request: ()) -> tonic::Result { - Ok(request) + fn decode(_request: proto::rpc::StatusRequest) -> tonic::Result { + Ok(()) } - fn encode(output: Self::Output) -> tonic::Result { + fn encode(output: Self::Output) -> tonic::Result { Ok(output) } @@ -44,7 +44,7 @@ impl rpc_api::Status for Upstream { _metadata: &tonic::metadata::MetadataMap, _extensions: &tonic::codegen::http::Extensions, ) -> tonic::Result { - Ok(RpcStatus { + Ok(StatusResponse { chain_tip: self.0.last().unwrap().header().block_num().as_u32(), ..Default::default() }) @@ -235,30 +235,38 @@ macro_rules! unused_rpc { }; } -unused_rpc!(GetLimits, (), proto::rpc::RpcLimits); -unused_rpc!(GetAccount, proto::rpc::AccountRequest, proto::rpc::AccountResponse); -unused_rpc!(GetBlockByNumber, proto::rpc::BlockRequest, proto::rpc::MaybeBlock); +unused_rpc!(GetLimits, proto::rpc::GetLimitsRequest, proto::rpc::GetLimitsResponse); +unused_rpc!(GetAccount, proto::rpc::GetAccountRequest, proto::rpc::GetAccountResponse); +unused_rpc!( + GetBlockByNumber, + proto::rpc::GetBlockByNumberRequest, + proto::rpc::GetBlockByNumberResponse +); unused_rpc!( GetBlockHeaderByNumber, - proto::rpc::BlockHeaderByNumberRequest, - proto::rpc::BlockHeaderByNumberResponse + proto::rpc::GetBlockHeaderByNumberRequest, + proto::rpc::GetBlockHeaderByNumberResponse ); -unused_rpc!(GetNotesById, proto::rpc::NotesByIdRequest, proto::rpc::NotesByIdResponse); +unused_rpc!(GetNotesById, proto::rpc::GetNotesByIdRequest, proto::rpc::GetNotesByIdResponse); unused_rpc!( GetNoteScriptByRoot, - proto::rpc::NoteScriptByRootRequest, - proto::rpc::MaybeNoteScript + proto::rpc::GetNoteScriptByRootRequest, + proto::rpc::GetNoteScriptByRootResponse +); +unused_rpc!( + GetTransactionEncryptionKey, + proto::rpc::GetTransactionEncryptionKeyRequest, + proto::rpc::GetTransactionEncryptionKeyResponse ); -unused_rpc!(GetTransactionEncryptionKey, (), proto::submission::TransactionEncryptionKey); unused_rpc!( SubmitProvenTx, - proto::submission::ProvenTransactionSubmission, - proto::blockchain::BlockNumber + proto::rpc::SubmitProvenTxRequest, + proto::rpc::SubmitProvenTxResponse ); unused_rpc!( SubmitProvenTxBatch, - proto::submission::TransactionBatch, - proto::blockchain::BlockNumber + proto::rpc::SubmitProvenTxBatchRequest, + proto::rpc::SubmitProvenTxBatchResponse ); unused_rpc!( SyncTransactions, @@ -282,7 +290,11 @@ unused_rpc!( proto::rpc::SyncAccountStorageMapsResponse ); unused_rpc!(SyncChainMmr, proto::rpc::SyncChainMmrRequest, proto::rpc::SyncChainMmrResponse); -unused_rpc!(RegisterAccount, proto::rpc::RegisterAccountRequest, ()); +unused_rpc!( + RegisterAccount, + proto::rpc::RegisterAccountRequest, + proto::rpc::RegisterAccountResponse +); unused_rpc!( IsAccountAllowed, proto::rpc::IsAccountAllowedRequest, @@ -290,7 +302,7 @@ unused_rpc!( ); unused_rpc!( GetNetworkNoteStatus, - proto::note::NoteId, + proto::rpc::GetNetworkNoteStatusRequest, proto::rpc::GetNetworkNoteStatusResponse ); diff --git a/crates/block-producer/src/validator/mod.rs b/crates/block-producer/src/validator/mod.rs index 47fd3044cd..e9efb9e014 100644 --- a/crates/block-producer/src/validator/mod.rs +++ b/crates/block-producer/src/validator/mod.rs @@ -83,16 +83,25 @@ impl BlockProducerValidatorClient { validators: &ValidatorConfig, ) -> anyhow::Result<()> { let client = self.clients.first().context("transaction validation requires a validator")?; - let key = (|| async { client.clone().get_transaction_encryption_key(()).await }) - .retry(retry::exponential_bounded( - Duration::from_millis(100), - Duration::from_secs(2), - 10, - )) - .when(|error| error.code() == tonic::Code::Unavailable) - .await? - .into_inner() - .verify_with(TrustedTransactionEncryptionState::new(genesis, validators.keys()))?; + let key = (|| async { + client + .clone() + .get_transaction_encryption_key( + proto::validator::GetTransactionEncryptionKeyRequest {}, + ) + .await + }) + .retry(retry::exponential_bounded( + Duration::from_millis(100), + Duration::from_secs(2), + 10, + )) + .when(|error| error.code() == tonic::Code::Unavailable) + .await? + .into_inner() + .key + .ok_or_else(|| tonic::Status::internal("missing transaction encryption key"))? + .verify_with(TrustedTransactionEncryptionState::new(genesis, validators.keys()))?; let sealed = TransactionInputsSealer::new(key).seal(transaction.id(), &inputs.to_bytes())?; let request = proto::submission::ProvenTransactionSubmission { @@ -102,14 +111,23 @@ impl BlockProducerValidatorClient { futures::future::try_join_all(self.clients.iter().map(|client| { let request = request.clone(); async move { - (|| async { client.clone().submit_proven_transaction(request.clone()).await }) - .retry(retry::exponential_bounded( - Duration::from_millis(100), - Duration::from_secs(2), - 10, - )) - .when(|error| error.code() == tonic::Code::Unavailable) - .await + (|| async { + client + .clone() + .submit_proven_transaction( + proto::validator::SubmitProvenTransactionRequest { + submission: Some(request.clone()), + }, + ) + .await + }) + .retry(retry::exponential_bounded( + Duration::from_millis(100), + Duration::from_secs(2), + 10, + )) + .when(|error| error.code() == tonic::Code::Unavailable) + .await } })) .await?; diff --git a/crates/proto/build.rs b/crates/proto/build.rs index e3f91e15aa..1a77ae6f0e 100644 --- a/crates/proto/build.rs +++ b/crates/proto/build.rs @@ -88,7 +88,7 @@ fn generate_bindings(file_descriptors: &FileDescriptorSet, dst_dir: &Path) -> mi // Protobuf does not support the optional keyword on a oneof. Use a suffix match so the // attribute does not apply to the variants. prost_config.field_attribute( - "rpc.AccountRequest.AccountDetailRequest.storage_request", + "rpc.GetAccountRequest.AccountDetailRequest.storage_request", "#[proto_decode(optional)]", ); diff --git a/crates/proto/src/clients/mod.rs b/crates/proto/src/clients/mod.rs index 5c767e5de0..b1fe893297 100644 --- a/crates/proto/src/clients/mod.rs +++ b/crates/proto/src/clients/mod.rs @@ -679,7 +679,12 @@ impl ValidatorClient { transaction: Some(tx.as_ref().into()), sealed_transaction_inputs: Some(inputs.clone()), }; - self.submit_proven_transaction(proven_tx).await?; + self.submit_proven_transaction( + crate::generated::validator::SubmitProvenTransactionRequest { + submission: Some(proven_tx), + }, + ) + .await?; } Ok(()) } diff --git a/crates/proto/src/domain/account.rs b/crates/proto/src/domain/account.rs index 2f809cfced..288be9fa6e 100644 --- a/crates/proto/src/domain/account.rs +++ b/crates/proto/src/domain/account.rs @@ -129,15 +129,15 @@ impl Verify for proto::rpc::DecodedIsAccountAllowedRequest { /// Represents a request for an account proof. #[derive(Debug)] -pub struct AccountRequest { +pub struct GetAccountRequest { pub account_id: AccountId, // If not present, the latest account proof references the latest available pub block_num: Option, pub details: Option, } -impl Verify for proto::rpc::DecodedAccountRequest { - type Verified = AccountRequest; +impl Verify for proto::rpc::DecodedGetAccountRequest { + type Verified = GetAccountRequest; type Error = ConversionError; fn verify(self) -> Result { @@ -148,7 +148,7 @@ impl Verify for proto::rpc::DecodedAccountRequest { let details = details.verify()?; - Ok(AccountRequest { account_id, block_num, details }) + Ok(GetAccountRequest { account_id, block_num, details }) } } @@ -167,12 +167,12 @@ pub enum AccountStorageRequest { Explicit(Vec), } -impl Verify for proto::rpc::account_request::DecodedAccountDetailRequest { +impl Verify for proto::rpc::get_account_request::DecodedAccountDetailRequest { type Verified = AccountDetailRequest; type Error = ConversionError; fn verify(self) -> Result { - use proto::rpc::account_request::account_detail_request::DecodedStorageRequest as ProtoStorageRequest; + use proto::rpc::get_account_request::account_detail_request::DecodedStorageRequest as ProtoStorageRequest; let Self { code_commitment, @@ -210,7 +210,7 @@ pub struct StorageMapRequest { } impl Verify - for proto::rpc::account_request::account_detail_request::DecodedStorageMapDetailRequest + for proto::rpc::get_account_request::account_detail_request::DecodedStorageMapDetailRequest { type Verified = StorageMapRequest; type Error = ConversionError; @@ -232,12 +232,12 @@ pub enum SlotData { MapKeys(Vec), } -impl Verify for proto::rpc::account_request::account_detail_request::storage_map_detail_request::DecodedSlotData { +impl Verify for proto::rpc::get_account_request::account_detail_request::storage_map_detail_request::DecodedSlotData { type Verified = SlotData; type Error = ConversionError; fn verify(self) -> Result { - use proto::rpc::account_request::account_detail_request::storage_map_detail_request::DecodedSlotData as ProtoSlotData; + use proto::rpc::get_account_request::account_detail_request::storage_map_detail_request::DecodedSlotData as ProtoSlotData; Ok(match self { ProtoSlotData::AllEntries(true) => SlotData::All, @@ -652,14 +652,14 @@ impl From for proto::rpc::AccountStorageDetails { //================================================================================================ /// Represents the response to an account proof request. -pub struct AccountResponse { +pub struct GetAccountResponse { pub block_num: BlockNumber, pub witness: AccountWitness, pub details: Option, } -impl Verify for proto::rpc::DecodedAccountResponse { - type Verified = AccountResponse; +impl Verify for proto::rpc::DecodedGetAccountResponse { + type Verified = GetAccountResponse; type Error = ConversionError; /// Check that supplied details match the account witness. The caller must authenticate the @@ -684,13 +684,13 @@ impl Verify for proto::rpc::DecodedAccountResponse { } } - Ok(AccountResponse { block_num, witness, details }) + Ok(GetAccountResponse { block_num, witness, details }) } } -impl From for proto::rpc::AccountResponse { - fn from(value: AccountResponse) -> Self { - let AccountResponse { block_num, witness, details } = value; +impl From for proto::rpc::GetAccountResponse { + fn from(value: GetAccountResponse) -> Self { + let GetAccountResponse { block_num, witness, details } = value; Self { witness: Some(witness.into()), @@ -729,7 +729,7 @@ impl AccountDetails { } } -impl Verify for proto::rpc::account_response::DecodedAccountDetails { +impl Verify for proto::rpc::get_account_response::DecodedAccountDetails { type Verified = AccountDetails; type Error = ConversionError; @@ -771,7 +771,7 @@ impl Verify for proto::rpc::account_response::DecodedAccountDetails { } } -impl From for proto::rpc::account_response::AccountDetails { +impl From for proto::rpc::get_account_response::AccountDetails { fn from(value: AccountDetails) -> Self { let AccountDetails { account_header, diff --git a/crates/proto/src/domain/account/tests.rs b/crates/proto/src/domain/account/tests.rs index 519c67cf4f..a0ac661774 100644 --- a/crates/proto/src/domain/account/tests.rs +++ b/crates/proto/src/domain/account/tests.rs @@ -37,7 +37,7 @@ fn test_slot_name() -> StorageSlotName { StorageSlotName::new("miden::test::storage::slot").unwrap() } -fn account_response() -> proto::rpc::AccountResponse { +fn account_response() -> proto::rpc::GetAccountResponse { let id = AccountId::dummy( [7; 15], AccountIdVersion::Version1, @@ -59,7 +59,7 @@ fn account_response() -> proto::rpc::AccountResponse { code.commitment(), ); let witness = AccountTree::with_entries([(id, header.to_commitment())]).unwrap().open(id); - AccountResponse { + GetAccountResponse { block_num: BlockNumber::from(1), witness, details: Some(AccountDetails { @@ -87,7 +87,7 @@ fn account_response_accepts_matching_details_and_omitted_optional_data() { assert_eq!(details.account_header.to_commitment(), decoded.witness.state_commitment()); } - let message = proto::rpc::AccountResponse { details: None, ..response }; + let message = proto::rpc::GetAccountResponse { details: None, ..response }; assert!(message.decode_fields().and_then(Verify::verify).unwrap().details.is_none()); } @@ -277,9 +277,9 @@ fn account_storage_details_rejects_partial_map_root_mismatch() { #[test] fn account_detail_request_converts_all_storage_maps() { - use crate::generated::rpc::account_request::account_detail_request::StorageRequest; + use crate::generated::rpc::get_account_request::account_detail_request::StorageRequest; - let request = crate::generated::rpc::account_request::AccountDetailRequest { + let request = crate::generated::rpc::get_account_request::AccountDetailRequest { code_commitment: None, asset_vault_commitment: None, storage_request: Some(StorageRequest::AllStorageMaps(true)), @@ -292,9 +292,9 @@ fn account_detail_request_converts_all_storage_maps() { #[test] fn account_detail_request_rejects_false_all_storage_maps() { - use crate::generated::rpc::account_request::account_detail_request::StorageRequest; + use crate::generated::rpc::get_account_request::account_detail_request::StorageRequest; - let request = crate::generated::rpc::account_request::AccountDetailRequest { + let request = crate::generated::rpc::get_account_request::AccountDetailRequest { code_commitment: None, asset_vault_commitment: None, storage_request: Some(StorageRequest::AllStorageMaps(false)), @@ -307,14 +307,14 @@ fn account_detail_request_rejects_false_all_storage_maps() { #[test] fn account_detail_request_converts_explicit_storage_maps() { - use crate::generated::rpc::account_request::account_detail_request::{ + use crate::generated::rpc::get_account_request::account_detail_request::{ StorageMapDetailRequest, StorageMapDetailRequests, StorageRequest, storage_map_detail_request, }; - let request = crate::generated::rpc::account_request::AccountDetailRequest { + let request = crate::generated::rpc::get_account_request::AccountDetailRequest { code_commitment: None, asset_vault_commitment: None, storage_request: Some(StorageRequest::StorageMaps(StorageMapDetailRequests { @@ -335,16 +335,16 @@ fn account_detail_request_converts_explicit_storage_maps() { #[test] fn account_detail_request_rejects_duplicate_storage_map_keys() { - use crate::generated::rpc::account_request::account_detail_request::{ + use crate::generated::rpc::get_account_request::account_detail_request::{ StorageMapDetailRequest, StorageMapDetailRequests, StorageRequest, storage_map_detail_request, }; - use crate::generated::rpc::account_request::account_detail_request::storage_map_detail_request::MapKeys; + use crate::generated::rpc::get_account_request::account_detail_request::storage_map_detail_request::MapKeys; let map_key: crate::generated::primitives::Word = Word::from([1, 2, 3, 4u32]).into(); - let request = crate::generated::rpc::account_request::AccountDetailRequest { + let request = crate::generated::rpc::get_account_request::AccountDetailRequest { code_commitment: None, asset_vault_commitment: None, storage_request: Some(StorageRequest::StorageMaps(StorageMapDetailRequests { @@ -364,7 +364,7 @@ fn account_detail_request_rejects_duplicate_storage_map_keys() { #[test] fn account_detail_request_allows_no_storage_slot_data() { - let request = crate::generated::rpc::account_request::AccountDetailRequest { + let request = crate::generated::rpc::get_account_request::AccountDetailRequest { code_commitment: None, asset_vault_commitment: None, storage_request: None, diff --git a/crates/proto/src/domain/note.rs b/crates/proto/src/domain/note.rs index ab2e2fd7cc..267ad90455 100644 --- a/crates/proto/src/domain/note.rs +++ b/crates/proto/src/domain/note.rs @@ -3,7 +3,7 @@ use miden_protocol::note::NoteScript; use crate::generated as proto; -impl Verify for proto::rpc::DecodedMaybeNoteScript { +impl Verify for proto::rpc::DecodedGetNoteScriptByRootResponse { type Verified = Option; type Error = ConversionError; diff --git a/crates/proto/src/domain/remote_prover.rs b/crates/proto/src/domain/remote_prover.rs index 75fa62401e..2cecf31077 100644 --- a/crates/proto/src/domain/remote_prover.rs +++ b/crates/proto/src/domain/remote_prover.rs @@ -4,7 +4,7 @@ use miden_protocol::vm::ExecutionProof; use crate::generated as proto; -impl proto::remote_prover::DecodedProof { +impl proto::remote_prover::DecodedProveResponse { /// Extract the transaction fields without verifying the transaction. pub fn into_transaction( self, @@ -23,7 +23,7 @@ impl proto::remote_prover::DecodedProof { } } -impl VerifyWith<&ProposedBatch> for proto::remote_prover::DecodedProof { +impl VerifyWith<&ProposedBatch> for proto::remote_prover::DecodedProveResponse { type Verified = ProvenBatch; type Error = ConversionError; @@ -41,15 +41,18 @@ mod tests { use super::*; - fn block_response() -> proto::remote_prover::Proof { - proto::remote_prover::Proof { - proof: Some(proto::remote_prover::proof::Proof::Block(dummy_execution_proof().into())), + fn block_response() -> proto::remote_prover::ProveResponse { + proto::remote_prover::ProveResponse { + proof: Some(proto::remote_prover::prove_response::Proof::Block( + dummy_execution_proof().into(), + )), } } #[test] fn missing_proof_is_rejected() { - let error = proto::remote_prover::Proof { proof: None }.decode_fields().unwrap_err(); + let error = + proto::remote_prover::ProveResponse { proof: None }.decode_fields().unwrap_err(); assert!(error.to_string().contains("proof")); } @@ -71,8 +74,8 @@ mod tests { #[test] fn malformed_proof_retains_field_context() { - let response = proto::remote_prover::Proof { - proof: Some(proto::remote_prover::proof::Proof::Transaction( + let response = proto::remote_prover::ProveResponse { + proof: Some(proto::remote_prover::prove_response::Proof::Transaction( proto::transaction::ProvenTransaction::default(), )), }; diff --git a/crates/proto/tests/decoding.rs b/crates/proto/tests/decoding.rs index 0855b3b583..b6c1cb96fc 100644 --- a/crates/proto/tests/decoding.rs +++ b/crates/proto/tests/decoding.rs @@ -9,14 +9,14 @@ use miden_protocol::account::{AccountId, AccountIdVersion, AccountType, AssetCal use miden_protocol::utils::serde::DeserializationError; use prost::Message; -fn account_request() -> proto::rpc::AccountRequest { +fn get_account_request() -> proto::rpc::GetAccountRequest { let account_id = AccountId::dummy( [7; 15], AccountIdVersion::Version1, AccountType::Public, AssetCallbackFlag::Disabled, ); - proto::rpc::AccountRequest { + proto::rpc::GetAccountRequest { account_id: Some(account_id.into()), block_num: None, details: None, @@ -25,23 +25,23 @@ fn account_request() -> proto::rpc::AccountRequest { #[test] fn account_request_preserves_optional_fields_on_the_wire() { - let request = account_request(); - let decoded = proto::rpc::AccountRequest::decode(request.encode_to_vec().as_slice()) + let request = get_account_request(); + let decoded = proto::rpc::GetAccountRequest::decode(request.encode_to_vec().as_slice()) .unwrap() .decode_and_verify() .unwrap(); assert!(decoded.block_num.is_none()); assert!(decoded.details.is_none()); - let request = proto::rpc::AccountRequest { + let request = proto::rpc::GetAccountRequest { block_num: Some(miden_protocol::block::BlockNumber::GENESIS.into()), - details: Some(proto::rpc::account_request::AccountDetailRequest { + details: Some(proto::rpc::get_account_request::AccountDetailRequest { code_commitment: Some(Word::empty().into()), ..Default::default() }), - ..account_request() + ..get_account_request() }; - let decoded = proto::rpc::AccountRequest::decode(request.encode_to_vec().as_slice()) + let decoded = proto::rpc::GetAccountRequest::decode(request.encode_to_vec().as_slice()) .unwrap() .decode_and_verify() .unwrap(); @@ -54,7 +54,7 @@ fn account_request_preserves_optional_fields_on_the_wire() { #[test] fn missing_account_id_is_an_invalid_argument() { - let error = proto::rpc::AccountRequest::default().decode_and_verify().unwrap_err(); + let error = proto::rpc::GetAccountRequest::default().decode_and_verify().unwrap_err(); let status = error.into_status(); assert_eq!(status.code(), tonic::Code::InvalidArgument); assert!(status.message().starts_with("failed to decode: account_id:"), "{status}"); @@ -79,10 +79,10 @@ fn conversion_status_preserves_field_context_and_nested_causes() { #[test] fn nested_map_keys_report_the_field_index_and_original_error() { use detail::storage_map_detail_request::{MapKeys, SlotData}; - use proto::rpc::account_request::account_detail_request as detail; + use proto::rpc::get_account_request::account_detail_request as detail; - let request = proto::rpc::AccountRequest { - details: Some(proto::rpc::account_request::AccountDetailRequest { + let request = proto::rpc::GetAccountRequest { + details: Some(proto::rpc::get_account_request::AccountDetailRequest { storage_request: Some(detail::StorageRequest::StorageMaps( detail::StorageMapDetailRequests { storage_maps: vec![detail::StorageMapDetailRequest { @@ -98,7 +98,7 @@ fn nested_map_keys_report_the_field_index_and_original_error() { )), ..Default::default() }), - ..account_request() + ..get_account_request() }; let error = request.decode_fields().unwrap_err(); assert!(error.to_string().starts_with( @@ -109,7 +109,7 @@ fn nested_map_keys_report_the_field_index_and_original_error() { #[test] fn account_details_require_vault_data_but_allow_absent_code() { - let account_id = account_request().decode_fields().unwrap().verify().unwrap().account_id; + let account_id = get_account_request().decode_fields().unwrap().verify().unwrap().account_id; let storage = miden_protocol::account::AccountStorageHeader::new(Vec::new()).unwrap(); let header = miden_protocol::account::AccountHeader::new( account_id, @@ -118,7 +118,7 @@ fn account_details_require_vault_data_but_allow_absent_code() { storage.to_commitment(), Word::empty(), ); - let details = proto::rpc::account_response::AccountDetails { + let details = proto::rpc::get_account_response::AccountDetails { header: Some(header.into()), storage_details: Some(proto::rpc::AccountStorageDetails { header: Some(storage.into()), @@ -130,7 +130,7 @@ fn account_details_require_vault_data_but_allow_absent_code() { let decoded = details.clone().decode_fields().unwrap().verify().unwrap(); assert!(decoded.account_code.is_none()); - let error = proto::rpc::account_response::AccountDetails { vault_details: None, ..details } + let error = proto::rpc::get_account_response::AccountDetails { vault_details: None, ..details } .decode_fields() .unwrap_err(); assert!(error.to_string().starts_with("vault_details:"), "{error}"); @@ -138,11 +138,11 @@ fn account_details_require_vault_data_but_allow_absent_code() { #[test] fn absent_blocks_and_scripts_remain_optional() { - let block = proto::rpc::MaybeBlock::default().decode_fields().unwrap(); + let block = proto::rpc::GetBlockByNumberResponse::default().decode_fields().unwrap(); assert!(block.block.as_ref().is_none()); assert!(block.proof.as_ref().is_none()); assert!( - proto::rpc::MaybeNoteScript::default() + proto::rpc::GetNoteScriptByRootResponse::default() .decode_fields() .unwrap() .script @@ -153,20 +153,20 @@ fn absent_blocks_and_scripts_remain_optional() { #[test] fn prover_requires_a_request_variant() { - let error = proto::remote_prover::ProofRequest::default().decode_fields().unwrap_err(); + let error = proto::remote_prover::ProveRequest::default().decode_fields().unwrap_err(); assert!(error.to_string().starts_with("request:"), "{error}"); } #[test] fn rpc_limits_preserve_endpoint_and_parameter_names() { let parameters = HashMap::from([("max_items".to_string(), 10), ("max_bytes".to_string(), 0)]); - let message = proto::rpc::RpcLimits { + let message = proto::rpc::GetLimitsResponse { endpoints: HashMap::from([( "SyncNotes".to_string(), proto::rpc::EndpointLimits { parameters: parameters.clone() }, )]), }; - let decoded = proto::rpc::RpcLimits::decode(message.encode_to_vec().as_slice()) + let decoded = proto::rpc::GetLimitsResponse::decode(message.encode_to_vec().as_slice()) .unwrap() .decode_fields() .unwrap(); @@ -176,9 +176,9 @@ fn rpc_limits_preserve_endpoint_and_parameter_names() { #[test] fn rpc_limits_preserve_empty_maps() { - let decoded = proto::rpc::RpcLimits::default().decode_fields().unwrap(); + let decoded = proto::rpc::GetLimitsResponse::default().decode_fields().unwrap(); assert!(decoded.endpoints.as_ref().is_empty()); - let message = proto::rpc::RpcLimits { + let message = proto::rpc::GetLimitsResponse { endpoints: HashMap::from([( "SyncNotes".to_string(), proto::rpc::EndpointLimits::default(), diff --git a/crates/proto/tests/node_conversions.rs b/crates/proto/tests/node_conversions.rs index 9769c60d57..aab2a3e614 100644 --- a/crates/proto/tests/node_conversions.rs +++ b/crates/proto/tests/node_conversions.rs @@ -416,8 +416,8 @@ fn batch_submission_rejects_proof_that_does_not_match_proposal() { #[test] fn batch_proof_response_preserves_batch_and_rejects_other_requested_kinds() { let batch = nonempty_block_request().tx_batches.as_slice()[0].clone(); - let response = generated::remote_prover::Proof { - proof: Some(generated::remote_prover::proof::Proof::Batch((&batch).into())), + let response = generated::remote_prover::ProveResponse { + proof: Some(generated::remote_prover::prove_response::Proof::Batch((&batch).into())), }; assert!(response.clone().decode_fields().unwrap().into_transaction().is_err()); assert!(response.clone().decode_fields().unwrap().into_block().is_err()); diff --git a/crates/rpc/src/server/api.rs b/crates/rpc/src/server/api.rs index 59e04b49e5..9007275bb4 100644 --- a/crates/rpc/src/server/api.rs +++ b/crates/rpc/src/server/api.rs @@ -47,7 +47,13 @@ pub(crate) async fn submit_tx_to_validators( futures::future::try_join_all(validators.iter().map(|validator| { let mut validator = validator.clone(); let request = request.clone(); - async move { validator.submit_proven_transaction(request).await } + async move { + validator + .submit_proven_transaction(proto::validator::SubmitProvenTransactionRequest { + submission: Some(request), + }) + .await + } })) .await?; Ok(()) @@ -310,7 +316,7 @@ fn endpoint_limits(params: &[(&str, usize)]) -> proto::rpc::EndpointLimits { } /// Cached RPC query parameter limits. -static RPC_LIMITS: LazyLock = LazyLock::new(|| { +static RPC_LIMITS: LazyLock = LazyLock::new(|| { use QueryParamAccountIdLimit as AccountId; use QueryParamNoteIdLimit as NoteId; use QueryParamNoteTagLimit as NoteTag; @@ -318,7 +324,7 @@ static RPC_LIMITS: LazyLock = LazyLock::new(|| { use QueryParamStorageMapKeyTotalLimit as StorageMapKeyTotal; use QueryParamStorageMapSlotLimit as StorageMapSlot; - proto::rpc::RpcLimits { + proto::rpc::GetLimitsResponse { endpoints: std::collections::HashMap::from([ ( "SyncNullifiers".into(), @@ -348,8 +354,39 @@ mod tests { use super::*; #[test] - fn get_limits_decodes_unit_request() { - assert_eq!(RpcService::decode(()).unwrap(), ()); + fn get_limits_decodes_empty_request() { + assert_eq!(RpcService::decode(proto::rpc::GetLimitsRequest {}).unwrap(), ()); + } + + #[test] + fn endpoint_requests_reject_missing_payloads() { + use proto::server::{rpc_api, sequencer_api}; + + let errors = [ + ::decode(proto::rpc::SubmitProvenTxRequest { + submission: None, + }) + .expect_err("submission is required"), + ::decode( + proto::rpc::SubmitProvenTxBatchRequest { submission: None }, + ) + .expect_err("submission is required"), + ::decode( + proto::sequencer::SubmitAuthenticatedTxRequest { transaction: None }, + ) + .expect_err("transaction is required"), + ::decode( + proto::sequencer::SubmitAuthenticatedTxBatchRequest { batch: None }, + ) + .expect_err("batch is required"), + ::decode( + proto::rpc::GetNetworkNoteStatusRequest { note_id: None }, + ) + .expect_err("note ID is required"), + ]; + for error in errors { + assert_eq!(error.code(), tonic::Code::InvalidArgument); + } } #[test] diff --git a/crates/rpc/src/server/api/get_account.rs b/crates/rpc/src/server/api/get_account.rs index 0e521022ce..71f966c649 100644 --- a/crates/rpc/src/server/api/get_account.rs +++ b/crates/rpc/src/server/api/get_account.rs @@ -1,9 +1,9 @@ use std::collections::HashSet; use miden_node_proto::domain::account::{ - AccountRequest, - AccountResponse, AccountStorageRequest, + GetAccountRequest, + GetAccountResponse, SlotData, }; use miden_node_proto::{DecodeMessageExt, generated as proto}; @@ -18,16 +18,16 @@ use crate::{COMPONENT, LOG_TARGET}; #[tonic::async_trait] impl proto::server::rpc_api::GetAccount for RpcService { - type Input = AccountRequest; - type Output = AccountResponse; + type Input = GetAccountRequest; + type Output = GetAccountResponse; - fn decode(request: proto::rpc::AccountRequest) -> tonic::Result { + fn decode(request: proto::rpc::GetAccountRequest) -> tonic::Result { request .decode_and_verify() .map_err(|err| GetAccountErrorCode::DeserializationFailed.invalid_argument(err)) } - fn encode(output: Self::Output) -> tonic::Result { + fn encode(output: Self::Output) -> tonic::Result { Ok(output.into()) } diff --git a/crates/rpc/src/server/api/get_block_by_number.rs b/crates/rpc/src/server/api/get_block_by_number.rs index 6aee59cdbe..be852d01d3 100644 --- a/crates/rpc/src/server/api/get_block_by_number.rs +++ b/crates/rpc/src/server/api/get_block_by_number.rs @@ -9,14 +9,14 @@ use crate::{COMPONENT, LOG_TARGET}; #[tonic::async_trait] impl proto::server::rpc_api::GetBlockByNumber for RpcService { - type Input = proto::rpc::BlockRequest; - type Output = proto::rpc::MaybeBlock; + type Input = proto::rpc::GetBlockByNumberRequest; + type Output = proto::rpc::GetBlockByNumberResponse; - fn decode(request: proto::rpc::BlockRequest) -> tonic::Result { + fn decode(request: proto::rpc::GetBlockByNumberRequest) -> tonic::Result { Ok(request) } - fn encode(output: Self::Output) -> tonic::Result { + fn encode(output: Self::Output) -> tonic::Result { Ok(output) } @@ -77,6 +77,6 @@ impl proto::server::rpc_api::GetBlockByNumber for RpcService { None }; - Ok(proto::rpc::MaybeBlock { block, proof }) + Ok(proto::rpc::GetBlockByNumberResponse { block, proof }) } } diff --git a/crates/rpc/src/server/api/get_block_header_by_number.rs b/crates/rpc/src/server/api/get_block_header_by_number.rs index ac32a6a45b..f3c9afeccf 100644 --- a/crates/rpc/src/server/api/get_block_header_by_number.rs +++ b/crates/rpc/src/server/api/get_block_header_by_number.rs @@ -7,14 +7,14 @@ use crate::LOG_TARGET; #[tonic::async_trait] impl proto::server::rpc_api::GetBlockHeaderByNumber for RpcService { - type Input = proto::rpc::BlockHeaderByNumberRequest; - type Output = proto::rpc::BlockHeaderByNumberResponse; + type Input = proto::rpc::GetBlockHeaderByNumberRequest; + type Output = proto::rpc::GetBlockHeaderByNumberResponse; - fn decode(request: proto::rpc::BlockHeaderByNumberRequest) -> tonic::Result { + fn decode(request: proto::rpc::GetBlockHeaderByNumberRequest) -> tonic::Result { Ok(request) } - fn encode(output: Self::Output) -> tonic::Result { + fn encode(output: Self::Output) -> tonic::Result { Ok(output) } @@ -54,7 +54,7 @@ impl proto::server::rpc_api::GetBlockHeaderByNumber for RpcService { _ => None, }; - Ok(proto::rpc::BlockHeaderByNumberResponse { + Ok(proto::rpc::GetBlockHeaderByNumberResponse { protocol_config, block_header: block_header.map(Into::into), chain_length: mmr_proof.as_ref().map(|p| p.forest().num_leaves() as u32), diff --git a/crates/rpc/src/server/api/get_limits.rs b/crates/rpc/src/server/api/get_limits.rs index 7be0cb11e7..36f6668939 100644 --- a/crates/rpc/src/server/api/get_limits.rs +++ b/crates/rpc/src/server/api/get_limits.rs @@ -7,13 +7,13 @@ use crate::{COMPONENT, LOG_TARGET}; #[tonic::async_trait] impl proto::server::rpc_api::GetLimits for RpcService { type Input = (); - type Output = proto::rpc::RpcLimits; + type Output = proto::rpc::GetLimitsResponse; - fn decode(request: ()) -> tonic::Result { - Ok(request) + fn decode(_request: proto::rpc::GetLimitsRequest) -> tonic::Result { + Ok(()) } - fn encode(output: Self::Output) -> tonic::Result { + fn encode(output: Self::Output) -> tonic::Result { Ok(output) } diff --git a/crates/rpc/src/server/api/get_network_note_status.rs b/crates/rpc/src/server/api/get_network_note_status.rs index 66a89ee4db..8f0590fd7a 100644 --- a/crates/rpc/src/server/api/get_network_note_status.rs +++ b/crates/rpc/src/server/api/get_network_note_status.rs @@ -11,8 +11,11 @@ impl proto::server::rpc_api::GetNetworkNoteStatus for RpcService { type Input = miden_protocol::note::NoteId; type Output = proto::rpc::GetNetworkNoteStatusResponse; - fn decode(request: proto::note::NoteId) -> tonic::Result { + fn decode(request: proto::rpc::GetNetworkNoteStatusRequest) -> tonic::Result { let note_id_digest: Word = request + .note_id + .as_ref() + .ok_or_else(|| tonic::Status::invalid_argument("missing note ID"))? .id .as_ref() .ok_or_else(|| tonic::Status::invalid_argument("missing note ID digest"))? @@ -47,7 +50,7 @@ impl proto::server::rpc_api::GetNetworkNoteStatus for RpcService { note.id = note_id ); - let mut forwarded_request = Request::new(note_id.as_word().into()); + let mut forwarded_request = Request::new(proto::note::NoteId::from(note_id.as_word())); if let Some(accept) = original_accept_header { forwarded_request.metadata_mut().insert(http::header::ACCEPT.as_str(), accept); } @@ -60,16 +63,26 @@ impl proto::server::rpc_api::GetNetworkNoteStatus for RpcService { )); }; - ntx_builder + let response = ntx_builder .clone() - .get_network_note_status(forwarded_request) + .get_network_note_status(forwarded_request.map(|note_id| { + proto::ntx_builder::GetNetworkNoteStatusRequest { note_id: Some(note_id) } + })) .await? - .into_inner() + .into_inner(); + proto::rpc::GetNetworkNoteStatusResponse { + status: response.status, + last_error: response.last_error, + attempt_count: response.attempt_count, + last_attempt_block_num: response.last_attempt_block_num, + } }, RpcBackend::FullNode { source_rpc, .. } => source_rpc .as_ref() .clone() - .get_network_note_status(forwarded_request) + .get_network_note_status(forwarded_request.map(|note_id| { + proto::rpc::GetNetworkNoteStatusRequest { note_id: Some(note_id) } + })) .await? .into_inner(), }; diff --git a/crates/rpc/src/server/api/get_note_script_by_root.rs b/crates/rpc/src/server/api/get_note_script_by_root.rs index 291f90c398..7341ab9ed6 100644 --- a/crates/rpc/src/server/api/get_note_script_by_root.rs +++ b/crates/rpc/src/server/api/get_note_script_by_root.rs @@ -12,7 +12,7 @@ impl proto::server::rpc_api::GetNoteScriptByRoot for RpcService { type Input = Word; type Output = Option; - fn decode(request: proto::rpc::NoteScriptByRootRequest) -> tonic::Result { + fn decode(request: proto::rpc::GetNoteScriptByRootRequest) -> tonic::Result { Ok(request .decode_fields() .map_err(|err| { @@ -21,8 +21,8 @@ impl proto::server::rpc_api::GetNoteScriptByRoot for RpcService { .root) } - fn encode(output: Self::Output) -> tonic::Result { - Ok(proto::rpc::MaybeNoteScript { script: output.map(Into::into) }) + fn encode(output: Self::Output) -> tonic::Result { + Ok(proto::rpc::GetNoteScriptByRootResponse { script: output.map(Into::into) }) } #[miden_instrument( diff --git a/crates/rpc/src/server/api/get_notes_by_id.rs b/crates/rpc/src/server/api/get_notes_by_id.rs index 22200e0b23..1d7adc8d4b 100644 --- a/crates/rpc/src/server/api/get_notes_by_id.rs +++ b/crates/rpc/src/server/api/get_notes_by_id.rs @@ -11,18 +11,18 @@ use crate::{COMPONENT, LOG_TARGET}; #[tonic::async_trait] impl proto::server::rpc_api::GetNotesById for RpcService { - type Input = proto::rpc::DecodedNotesByIdRequest; + type Input = proto::rpc::DecodedGetNotesByIdRequest; type Output = Vec; - fn decode(request: proto::rpc::NotesByIdRequest) -> tonic::Result { + fn decode(request: proto::rpc::GetNotesByIdRequest) -> tonic::Result { check::(request.note_ids.len())?; request .decode_fields() .map_err(|err| GetNotesByIdErrorCode::DeserializationFailed.invalid_argument(err)) } - fn encode(notes: Self::Output) -> tonic::Result { - Ok(proto::rpc::NotesByIdResponse { notes }) + fn encode(notes: Self::Output) -> tonic::Result { + Ok(proto::rpc::GetNotesByIdResponse { notes }) } #[miden_instrument( diff --git a/crates/rpc/src/server/api/get_transaction_encryption_key.rs b/crates/rpc/src/server/api/get_transaction_encryption_key.rs index 31957dfb20..ba869cfd58 100644 --- a/crates/rpc/src/server/api/get_transaction_encryption_key.rs +++ b/crates/rpc/src/server/api/get_transaction_encryption_key.rs @@ -9,12 +9,16 @@ impl proto::server::rpc_api::GetTransactionEncryptionKey for RpcService { type Input = (); type Output = proto::submission::TransactionEncryptionKey; - fn decode(request: ()) -> tonic::Result { - Ok(request) + fn decode( + _request: proto::rpc::GetTransactionEncryptionKeyRequest, + ) -> tonic::Result { + Ok(()) } - fn encode(output: Self::Output) -> tonic::Result { - Ok(output) + fn encode( + output: Self::Output, + ) -> tonic::Result { + Ok(proto::rpc::GetTransactionEncryptionKeyResponse { key: Some(output) }) } #[miden_instrument( @@ -46,15 +50,29 @@ impl proto::server::rpc_api::GetTransactionEncryptionKey for RpcService { return source_rpc .as_ref() .clone() - .get_transaction_encryption_key(forwarded_request) + .get_transaction_encryption_key( + forwarded_request + .map(|()| proto::rpc::GetTransactionEncryptionKeyRequest {}), + ) .await - .map(tonic::Response::into_inner); + .and_then(|response| { + response.into_inner().key.ok_or_else(|| { + tonic::Status::internal("missing transaction encryption key") + }) + }); }, }; validator .clone() - .get_transaction_encryption_key(forwarded_request) + .get_transaction_encryption_key( + forwarded_request.map(|()| proto::validator::GetTransactionEncryptionKeyRequest {}), + ) .await - .map(tonic::Response::into_inner) + .and_then(|response| { + response + .into_inner() + .key + .ok_or_else(|| tonic::Status::internal("missing transaction encryption key")) + }) } } diff --git a/crates/rpc/src/server/api/register_account.rs b/crates/rpc/src/server/api/register_account.rs index 183ec8906e..9482835209 100644 --- a/crates/rpc/src/server/api/register_account.rs +++ b/crates/rpc/src/server/api/register_account.rs @@ -17,8 +17,8 @@ impl proto::server::rpc_api::RegisterAccount for RpcService { request.decode_and_verify().map_err(ConversionError::into_status) } - fn encode((): Self::Output) -> tonic::Result<()> { - Ok(()) + fn encode((): Self::Output) -> tonic::Result { + Ok(proto::rpc::RegisterAccountResponse {}) } #[miden_instrument(target = COMPONENT, name = "register_account", err)] diff --git a/crates/rpc/src/server/api/status.rs b/crates/rpc/src/server/api/status.rs index b8e2f45a3b..5da7dd662a 100644 --- a/crates/rpc/src/server/api/status.rs +++ b/crates/rpc/src/server/api/status.rs @@ -8,13 +8,13 @@ use crate::{COMPONENT, LOG_TARGET}; #[tonic::async_trait] impl proto::server::rpc_api::Status for RpcService { type Input = (); - type Output = proto::rpc::RpcStatus; + type Output = proto::rpc::StatusResponse; - fn decode(request: ()) -> tonic::Result { - Ok(request) + fn decode(_request: proto::rpc::StatusRequest) -> tonic::Result { + Ok(()) } - fn encode(output: Self::Output) -> tonic::Result { + fn encode(output: Self::Output) -> tonic::Result { Ok(output) } @@ -36,7 +36,7 @@ impl proto::server::rpc_api::Status for RpcService { RpcBackend::FullNode { source_rpc, .. } => source_rpc .as_ref() .clone() - .status(Request::new(())) + .status(Request::new(proto::rpc::StatusRequest {})) .await .ok() .and_then(|response| response.into_inner().block_producer), @@ -44,7 +44,7 @@ impl proto::server::rpc_api::Status for RpcService { debug!(target: LOG_TARGET, "Getting status"); - Ok(proto::rpc::RpcStatus { + Ok(proto::rpc::StatusResponse { version: env!("CARGO_PKG_VERSION").to_string(), chain_tip: self.state.committed_tip().as_u32(), block_producer: block_producer_status.or(Some(proto::rpc::BlockProducerStatus { diff --git a/crates/rpc/src/server/api/submit_auth_tx.rs b/crates/rpc/src/server/api/submit_auth_tx.rs index 5c6d77005f..b2d5293b28 100644 --- a/crates/rpc/src/server/api/submit_auth_tx.rs +++ b/crates/rpc/src/server/api/submit_auth_tx.rs @@ -12,7 +12,12 @@ impl sequencer_api::SubmitAuthenticatedTx for SequencerInternalService { type Input = AuthenticatedTransaction; type Output = proto::blockchain::BlockNumber; - fn decode(request: proto::sequencer::AuthenticatedTransaction) -> tonic::Result { + fn decode( + request: proto::sequencer::SubmitAuthenticatedTxRequest, + ) -> tonic::Result { + let request = request + .transaction + .ok_or_else(|| tonic::Status::invalid_argument("missing transaction"))?; request // SAFETY: Network isolation must restrict this endpoint to trusted full nodes. The // sender supplies proof and store validation. The handler checks the reference block @@ -23,8 +28,10 @@ impl sequencer_api::SubmitAuthenticatedTx for SequencerInternalService { }) } - fn encode(output: Self::Output) -> tonic::Result { - Ok(output) + fn encode( + output: Self::Output, + ) -> tonic::Result { + Ok(proto::sequencer::SubmitAuthenticatedTxResponse { block_num: output.block_num }) } async fn handle( diff --git a/crates/rpc/src/server/api/submit_auth_tx_batch.rs b/crates/rpc/src/server/api/submit_auth_tx_batch.rs index 7f240cefa2..f6b5a1af2d 100644 --- a/crates/rpc/src/server/api/submit_auth_tx_batch.rs +++ b/crates/rpc/src/server/api/submit_auth_tx_batch.rs @@ -11,13 +11,15 @@ impl sequencer_api::SubmitAuthenticatedTxBatch for SequencerInternalService { type Output = proto::blockchain::BlockNumber; fn decode( - request: proto::sequencer::AuthenticatedTransactionBatch, + request: proto::sequencer::SubmitAuthenticatedTxBatchRequest, ) -> tonic::Result { - Ok(request) + request.batch.ok_or_else(|| tonic::Status::invalid_argument("missing batch")) } - fn encode(output: Self::Output) -> tonic::Result { - Ok(output) + fn encode( + output: Self::Output, + ) -> tonic::Result { + Ok(proto::sequencer::SubmitAuthenticatedTxBatchResponse { block_num: output.block_num }) } async fn handle( diff --git a/crates/rpc/src/server/api/submit_proven_tx.rs b/crates/rpc/src/server/api/submit_proven_tx.rs index c056e58eb9..d43a10e5fb 100644 --- a/crates/rpc/src/server/api/submit_proven_tx.rs +++ b/crates/rpc/src/server/api/submit_proven_tx.rs @@ -23,9 +23,10 @@ impl proto::server::rpc_api::SubmitProvenTx for RpcService { type Input = miden_node_proto::ProvenTransactionSubmission; type Output = proto::blockchain::BlockNumber; - fn decode( - request: proto::submission::ProvenTransactionSubmission, - ) -> tonic::Result { + fn decode(request: proto::rpc::SubmitProvenTxRequest) -> tonic::Result { + let request = request + .submission + .ok_or_else(|| tonic::Status::invalid_argument("missing submission"))?; request // SAFETY: The handler checks the reference block and proof before forwarding. Decoding // does not authenticate the transaction against current chain state. @@ -37,8 +38,8 @@ impl proto::server::rpc_api::SubmitProvenTx for RpcService { .map_err(miden_node_proto::errors::ConversionError::into_status) } - fn encode(output: Self::Output) -> tonic::Result { - Ok(output) + fn encode(output: Self::Output) -> tonic::Result { + Ok(proto::rpc::SubmitProvenTxResponse { block_num: output.block_num }) } #[miden_instrument( @@ -169,9 +170,13 @@ impl proto::server::rpc_api::SubmitProvenTx for RpcService { source_rpc .as_ref() .clone() - .submit_proven_tx(forwarded_request) + .submit_proven_tx(forwarded_request.map(|payload| { + proto::rpc::SubmitProvenTxRequest { submission: Some(payload) } + })) .await - .map(tonic::Response::into_inner) + .map(|response| proto::blockchain::BlockNumber { + block_num: response.into_inner().block_num, + }) }, } } @@ -204,11 +209,15 @@ impl RpcService { // Submit to sequencer. let mut sequencer = sequencer; sequencer - .submit_authenticated_tx(proto::sequencer::AuthenticatedTransaction::from( - authenticated_tx, - )) + .submit_authenticated_tx(proto::sequencer::SubmitAuthenticatedTxRequest { + transaction: Some(proto::sequencer::AuthenticatedTransaction::from( + authenticated_tx, + )), + }) .await - .map(tonic::Response::into_inner) + .map(|response| proto::blockchain::BlockNumber { + block_num: response.into_inner().block_num, + }) } } diff --git a/crates/rpc/src/server/api/submit_proven_tx_batch.rs b/crates/rpc/src/server/api/submit_proven_tx_batch.rs index dce5d3b950..3dc21728aa 100644 --- a/crates/rpc/src/server/api/submit_proven_tx_batch.rs +++ b/crates/rpc/src/server/api/submit_proven_tx_batch.rs @@ -16,12 +16,14 @@ impl proto::server::rpc_api::SubmitProvenTxBatch for RpcService { type Input = proto::submission::TransactionBatch; type Output = proto::blockchain::BlockNumber; - fn decode(request: proto::submission::TransactionBatch) -> tonic::Result { - Ok(request) + fn decode(request: proto::rpc::SubmitProvenTxBatchRequest) -> tonic::Result { + request + .submission + .ok_or_else(|| tonic::Status::invalid_argument("missing submission")) } - fn encode(output: Self::Output) -> tonic::Result { - Ok(output) + fn encode(output: Self::Output) -> tonic::Result { + Ok(proto::rpc::SubmitProvenTxBatchResponse { block_num: output.block_num }) } #[miden_instrument( @@ -138,9 +140,13 @@ impl proto::server::rpc_api::SubmitProvenTxBatch for RpcService { source_rpc .as_ref() .clone() - .submit_proven_tx_batch(forwarded_request) + .submit_proven_tx_batch(forwarded_request.map(|payload| { + proto::rpc::SubmitProvenTxBatchRequest { submission: Some(payload) } + })) .await - .map(tonic::Response::into_inner) + .map(|response| proto::blockchain::BlockNumber { + block_num: response.into_inner().block_num, + }) }, } } @@ -176,9 +182,13 @@ impl RpcService { batch_proof: Some((&proven_batch).into()), }; sequencer - .submit_authenticated_tx_batch(authenticated_batch) + .submit_authenticated_tx_batch(proto::sequencer::SubmitAuthenticatedTxBatchRequest { + batch: Some(authenticated_batch), + }) .await - .map(tonic::Response::into_inner) + .map(|response| proto::blockchain::BlockNumber { + block_num: response.into_inner().block_num, + }) } } diff --git a/crates/rpc/src/tests.rs b/crates/rpc/src/tests.rs index b14cd7b3ca..16851f8c91 100644 --- a/crates/rpc/src/tests.rs +++ b/crates/rpc/src/tests.rs @@ -504,7 +504,7 @@ async fn rpc_server_accepts_requests_without_accept_header() { }; // Send any request to the RPC. - let request = proto::rpc::BlockHeaderByNumberRequest { + let request = proto::rpc::GetBlockHeaderByNumberRequest { block_num: Some(0), include_mmr_proof: None, include_protocol_config: None, @@ -639,7 +639,9 @@ async fn rpc_server_rejects_proven_transactions_with_invalid_commitment() { sealed_transaction_inputs: Some(test_sealed_transaction_inputs()), }; - let response = rpc_client.submit_proven_tx(request).await; + let response = rpc_client + .submit_proven_tx(proto::rpc::SubmitProvenTxRequest { submission: Some(request) }) + .await; // Assert that the server rejected our request. assert!(response.is_err()); @@ -684,7 +686,12 @@ async fn rpc_server_checks_transaction_fee_notes( None, ); - let status = service.submit_proven_tx(Request::new(request)).await.unwrap_err(); + let status = service + .submit_proven_tx(Request::new(proto::rpc::SubmitProvenTxRequest { + submission: Some(request), + })) + .await + .unwrap_err(); assert_eq!(status.code(), tonic::Code::InvalidArgument); assert_eq!(status.details(), expected_details); assert!( @@ -732,7 +739,9 @@ async fn sequencer_authenticated_rpc_rejects_transactions_without_native_fees( }; let status = service - .submit_authenticated_tx(Request::new(proto::sequencer::AuthenticatedTransaction::from(tx))) + .submit_authenticated_tx(Request::new(proto::sequencer::SubmitAuthenticatedTxRequest { + transaction: Some(proto::sequencer::AuthenticatedTransaction::from(tx)), + })) .await .unwrap_err(); @@ -772,7 +781,9 @@ async fn sequencer_authenticated_rpc_accepts_transactions_without_notes_when_fee }; service - .submit_authenticated_tx(Request::new(proto::sequencer::AuthenticatedTransaction::from(tx))) + .submit_authenticated_tx(Request::new(proto::sequencer::SubmitAuthenticatedTxRequest { + transaction: Some(proto::sequencer::AuthenticatedTransaction::from(tx)), + })) .await .expect("zero-fee transactions do not require output notes"); } @@ -801,7 +812,12 @@ async fn rpc_server_rejects_invalid_deferred_transaction_proofs() { None, ); - let status = service.submit_proven_tx(Request::new(request)).await.unwrap_err(); + let status = service + .submit_proven_tx(Request::new(proto::rpc::SubmitProvenTxRequest { + submission: Some(request), + })) + .await + .unwrap_err(); assert_eq!(status.code(), tonic::Code::InvalidArgument); assert!(status.message().contains("Invalid proof for transaction")); } @@ -843,7 +859,12 @@ async fn rpc_server_forwards_valid_deferred_proofs_and_rejects_missing_witnesses transaction: Some((&fixture.transaction).into()), sealed_transaction_inputs: Some(test_sealed_transaction_inputs()), }; - let status = service.submit_proven_tx(Request::new(request)).await.unwrap_err(); + let status = service + .submit_proven_tx(Request::new(proto::rpc::SubmitProvenTxRequest { + submission: Some(request), + })) + .await + .unwrap_err(); // The stub rejects submissions after it records them. assert_eq!(status.code(), tonic::Code::Unimplemented, "{status}"); { @@ -873,7 +894,12 @@ async fn rpc_server_forwards_valid_deferred_proofs_and_rejects_missing_witnesses transaction: Some((&invalid_tx).into()), sealed_transaction_inputs: Some(test_sealed_transaction_inputs()), }; - let status = service.submit_proven_tx(Request::new(request)).await.unwrap_err(); + let status = service + .submit_proven_tx(Request::new(proto::rpc::SubmitProvenTxRequest { + submission: Some(request), + })) + .await + .unwrap_err(); assert_eq!(status.code(), tonic::Code::InvalidArgument); assert!(status.message().contains("Invalid proof for transaction"), "{status}"); assert_eq!(submissions.lock().unwrap().len(), 1); @@ -905,7 +931,9 @@ async fn rpc_server_rejects_proven_transactions_with_invalid_reference_block() { sealed_transaction_inputs: Some(test_sealed_transaction_inputs()), }; - let response = rpc_client.submit_proven_tx(request).await; + let response = rpc_client + .submit_proven_tx(proto::rpc::SubmitProvenTxRequest { submission: Some(request) }) + .await; // Assert that the server rejected our request. assert!(response.is_err()); @@ -957,7 +985,11 @@ async fn rpc_rejects_post_deployment_network_account_tx() { None, ); - let response = service.submit_proven_tx(Request::new(request)).await; + let response = service + .submit_proven_tx(Request::new(proto::rpc::SubmitProvenTxRequest { + submission: Some(request), + })) + .await; assert!(response.is_err()); let err = response.as_ref().unwrap_err().message(); assert!( @@ -978,6 +1010,7 @@ fn source_rpc_client() -> RpcClient { #[derive(Clone)] struct FixedNtxBuilder { + expected_note_id: proto::note::NoteId, response: proto::rpc::GetNetworkNoteStatusResponse, call_count: Arc, last_accept: Arc>>, @@ -988,20 +1021,32 @@ impl ntx_builder_api::GetNetworkNoteStatus for FixedNtxBuilder { type Input = proto::note::NoteId; type Output = proto::rpc::GetNetworkNoteStatusResponse; - fn decode(request: proto::note::NoteId) -> tonic::Result { - Ok(request) + fn decode( + request: proto::ntx_builder::GetNetworkNoteStatusRequest, + ) -> tonic::Result { + request + .note_id + .ok_or_else(|| tonic::Status::invalid_argument("missing note ID")) } - fn encode(output: Self::Output) -> tonic::Result { - Ok(output) + fn encode( + output: Self::Output, + ) -> tonic::Result { + Ok(proto::ntx_builder::GetNetworkNoteStatusResponse { + status: output.status, + last_error: output.last_error, + attempt_count: output.attempt_count, + last_attempt_block_num: output.last_attempt_block_num, + }) } async fn handle( &self, - _input: Self::Input, + input: Self::Input, metadata: &MetadataMap, _extensions: &Extensions, ) -> tonic::Result { + assert_eq!(input, self.expected_note_id); self.call_count.fetch_add(1, Ordering::SeqCst); let accept = metadata .get(ACCEPT.as_str()) @@ -1014,6 +1059,7 @@ impl ntx_builder_api::GetNetworkNoteStatus for FixedNtxBuilder { } async fn start_ntx_builder( + expected_note_id: proto::note::NoteId, response: proto::rpc::GetNetworkNoteStatusResponse, ) -> ( NtxBuilderClient, @@ -1026,6 +1072,7 @@ async fn start_ntx_builder( let call_count = Arc::new(AtomicUsize::new(0)); let last_accept = Arc::new(std::sync::Mutex::new(None)); let service = FixedNtxBuilder { + expected_note_id, response, call_count: Arc::clone(&call_count), last_accept: Arc::clone(&last_accept), @@ -1164,12 +1211,16 @@ impl validator_api::GetTransactionEncryptionKey for FixedValidator { type Input = (); type Output = proto::submission::TransactionEncryptionKey; - fn decode(request: ()) -> tonic::Result { - Ok(request) + fn decode( + _request: proto::validator::GetTransactionEncryptionKeyRequest, + ) -> tonic::Result { + Ok(()) } - fn encode(output: Self::Output) -> tonic::Result { - Ok(output) + fn encode( + output: Self::Output, + ) -> tonic::Result { + Ok(proto::validator::GetTransactionEncryptionKeyResponse { key: Some(output) }) } async fn handle( @@ -1192,13 +1243,13 @@ impl validator_api::GetTransactionEncryptionKey for FixedValidator { #[tonic::async_trait] impl validator_api::Status for FixedValidator { type Input = (); - type Output = proto::validator::ValidatorStatus; + type Output = proto::validator::StatusResponse; - fn decode(request: ()) -> tonic::Result { - Ok(request) + fn decode(_request: proto::validator::StatusRequest) -> tonic::Result { + Ok(()) } - fn encode(output: Self::Output) -> tonic::Result { + fn encode(output: Self::Output) -> tonic::Result { Ok(output) } @@ -1218,13 +1269,17 @@ impl validator_api::SubmitProvenTransaction for FixedValidator { type Output = (); fn decode( - request: proto::submission::ProvenTransactionSubmission, + request: proto::validator::SubmitProvenTransactionRequest, ) -> tonic::Result { - Ok(request) + request + .submission + .ok_or_else(|| tonic::Status::invalid_argument("missing submission")) } - fn encode(output: Self::Output) -> tonic::Result<()> { - Ok(output) + fn encode( + (): Self::Output, + ) -> tonic::Result { + Ok(proto::validator::SubmitProvenTransactionResponse {}) } async fn handle( @@ -1384,16 +1439,22 @@ async fn full_node_with_validator_forwards_get_transaction_encryption_key() { ); let response = full_node - .get_transaction_encryption_key(Request::new(())) + .get_transaction_encryption_key(Request::new( + proto::rpc::GetTransactionEncryptionKeyRequest {}, + )) .await .expect("full-node RPC should forward the encryption key request to its validator") - .into_inner(); + .into_inner() + .key + .expect("transaction encryption key"); assert_eq!(response, expected); assert_eq!(validator_call_count.load(Ordering::SeqCst), 1); full_node - .get_transaction_encryption_key(Request::new(())) + .get_transaction_encryption_key(Request::new( + proto::rpc::GetTransactionEncryptionKeyRequest {}, + )) .await .expect("each encryption key request should reach the validator"); assert_eq!( @@ -1420,10 +1481,14 @@ async fn full_node_forwards_get_transaction_encryption_key_to_source_rpc() { ); let response = full_node - .get_transaction_encryption_key(Request::new(())) + .get_transaction_encryption_key(Request::new( + proto::rpc::GetTransactionEncryptionKeyRequest {}, + )) .await .expect("full-node RPC should forward the encryption key request to its source") - .into_inner(); + .into_inner() + .key + .expect("transaction encryption key"); assert_eq!(response, expected); assert_eq!(validator_call_count.load(Ordering::SeqCst), 1); @@ -1450,14 +1515,16 @@ async fn full_node_preserves_original_accept_metadata_when_forwarding_encryption env!("CARGO_PKG_VERSION"), source_store.genesis_commitment().to_hex(), ); - let mut request = Request::new(()); + let mut request = Request::new(proto::rpc::GetTransactionEncryptionKeyRequest {}); request.metadata_mut().insert(ACCEPT.as_str(), original_accept.parse().unwrap()); let response = full_node .get_transaction_encryption_key(request) .await .expect("full-node RPC should forward the encryption key request") - .into_inner(); + .into_inner() + .key + .expect("transaction encryption key"); assert_eq!(response, expected); assert_eq!( @@ -1468,6 +1535,7 @@ async fn full_node_preserves_original_accept_metadata_when_forwarding_encryption #[tokio::test] async fn full_node_forwards_get_network_note_status_to_source_rpc() { + let note_id = Word::from([1u32, 2, 3, 4]); let expected = proto::rpc::GetNetworkNoteStatusResponse { status: proto::rpc::NetworkNoteStatus::Discarded.into(), last_error: Some("execution failed".to_string()), @@ -1475,7 +1543,7 @@ async fn full_node_forwards_get_network_note_status_to_source_rpc() { last_attempt_block_num: Some(42), }; let (ntx_builder, ntx_builder_call_count, _last_accept, _ntx_builder_server) = - start_ntx_builder(expected.clone()).await; + start_ntx_builder(note_id.into(), expected.clone()).await; let (source_rpc, _source_store, _source_server) = start_source_rpc(ntx_builder, dummy_client::()).await; let local_store = TestStore::start().await; @@ -1488,7 +1556,9 @@ async fn full_node_forwards_get_network_note_status_to_source_rpc() { ); let response = full_node - .get_network_note_status(Request::new(Word::empty().into())) + .get_network_note_status(Request::new(proto::rpc::GetNetworkNoteStatusRequest { + note_id: Some(note_id.into()), + })) .await .expect("full-node RPC should forward network note status request") .into_inner(); @@ -1499,6 +1569,7 @@ async fn full_node_forwards_get_network_note_status_to_source_rpc() { #[tokio::test] async fn full_node_preserves_original_accept_metadata_when_forwarding() { + let note_id = Word::from([1u32, 2, 3, 4]); let expected = proto::rpc::GetNetworkNoteStatusResponse { status: proto::rpc::NetworkNoteStatus::Discarded.into(), last_error: Some("execution failed".to_string()), @@ -1506,7 +1577,7 @@ async fn full_node_preserves_original_accept_metadata_when_forwarding() { last_attempt_block_num: Some(42), }; let (ntx_builder, _ntx_builder_call_count, last_accept, _ntx_builder_server) = - start_ntx_builder(expected.clone()).await; + start_ntx_builder(note_id.into(), expected.clone()).await; let (source_rpc, source_store, _source_server) = start_source_rpc(ntx_builder, dummy_client::()).await; let local_store = TestStore::start().await; @@ -1523,7 +1594,8 @@ async fn full_node_preserves_original_accept_metadata_when_forwarding() { env!("CARGO_PKG_VERSION"), source_store.genesis_commitment().to_hex(), ); - let mut request = Request::new(Word::empty().into()); + let mut request = + Request::new(proto::rpc::GetNetworkNoteStatusRequest { note_id: Some(note_id.into()) }); request.metadata_mut().insert(ACCEPT.as_str(), original_accept.parse().unwrap()); let response = full_node @@ -1566,14 +1638,18 @@ async fn full_node_forwards_complete_transaction_batch_to_source_rpc(#[case] inc let mut malformed = fixture.request.clone(); malformed.sealed_transaction_inputs.clear(); let error = full_node - .submit_proven_tx_batch(Request::new(malformed)) + .submit_proven_tx_batch(Request::new(proto::rpc::SubmitProvenTxBatchRequest { + submission: Some(malformed), + })) .await .expect_err("batch submission must require one sealed input per transaction"); assert_eq!(error.code(), tonic::Code::InvalidArgument); assert!(error.message().contains("sealed transaction input count"), "{error}"); let response = full_node - .submit_proven_tx_batch(Request::new(fixture.request)) + .submit_proven_tx_batch(Request::new(proto::rpc::SubmitProvenTxBatchRequest { + submission: Some(fixture.request), + })) .await .expect("full-node RPC should forward both structured batch fields to its source") .into_inner(); @@ -1609,7 +1685,9 @@ async fn sequencer_authenticated_rpc_accepts_user_batch_without_fee_notes() { }; let response = service - .submit_authenticated_tx_batch(Request::new(request)) + .submit_authenticated_tx_batch(Request::new( + proto::sequencer::SubmitAuthenticatedTxBatchRequest { batch: Some(request) }, + )) .await .expect("the sequencer should accept a user batch without fee output notes") .into_inner(); @@ -1624,11 +1702,10 @@ async fn authenticated_batch_defers_validation_to_async_handler() { auth_inputs: Vec::new(), batch_proof: None, }; - let input = - ::decode(request) - .expect( - "wire decoding should defer proof-bearing batch conversion to the async handler", - ); + let input = ::decode( + proto::sequencer::SubmitAuthenticatedTxBatchRequest { batch: Some(request) }, + ) + .expect("wire decoding should defer proof-bearing batch conversion to the async handler"); let store = TestStore::start().await; let shutdown = CancellationToken::new(); @@ -1686,7 +1763,9 @@ async fn rpc_server_rejects_tx_submissions_without_genesis() { sealed_transaction_inputs: Some(test_sealed_transaction_inputs()), }; - let response = rpc_client.submit_proven_tx(request).await; + let response = rpc_client + .submit_proven_tx(proto::rpc::SubmitProvenTxRequest { submission: Some(request) }) + .await; // Assert that the server rejected our request. assert!(response.is_err()); @@ -1704,8 +1783,9 @@ async fn rpc_server_rejects_tx_submissions_without_genesis() { /// Sends an arbitrary / irrelevant request to the RPC. async fn send_request( rpc_client: &mut RpcClient, -) -> std::result::Result, tonic::Status> { - let request = proto::rpc::BlockHeaderByNumberRequest { +) -> std::result::Result, tonic::Status> +{ + let request = proto::rpc::GetBlockHeaderByNumberRequest { block_num: Some(0), include_mmr_proof: None, include_protocol_config: None, @@ -2078,7 +2158,10 @@ async fn get_limits_endpoint() { let (mut rpc_client, _rpc_addr, _store, _server) = start_rpc().await; // Call the get_limits endpoint - let response = rpc_client.get_limits(()).await.expect("get_limits should succeed"); + let response = rpc_client + .get_limits(proto::rpc::GetLimitsRequest {}) + .await + .expect("get_limits should succeed"); let limits = response.into_inner(); // Verify the response contains expected endpoints and limits @@ -2260,7 +2343,7 @@ async fn header_protocol_config_is_opt_in() { let (mut client, _, _store, _server) = start_rpc().await; for include in [None, Some(false), Some(true)] { let response = client - .get_block_header_by_number(proto::rpc::BlockHeaderByNumberRequest { + .get_block_header_by_number(proto::rpc::GetBlockHeaderByNumberRequest { block_num: Some(0), include_mmr_proof: Some(true), include_protocol_config: include, @@ -2283,7 +2366,7 @@ async fn header_protocol_config_is_opt_in() { } } let response = client - .get_block_header_by_number(proto::rpc::BlockHeaderByNumberRequest { + .get_block_header_by_number(proto::rpc::GetBlockHeaderByNumberRequest { block_num: Some(1), include_mmr_proof: None, include_protocol_config: Some(true), diff --git a/crates/rpc/src/tests/allowlist.rs b/crates/rpc/src/tests/allowlist.rs index ad964b079b..de71f3a7aa 100644 --- a/crates/rpc/src/tests/allowlist.rs +++ b/crates/rpc/src/tests/allowlist.rs @@ -496,22 +496,38 @@ async fn submission_endpoints_reject_unregistered_creation_without_partial_batch for result in [ public - .submit_proven_tx(Request::new(proto::submission::ProvenTransactionSubmission { - transaction: Some(transactions[1].as_ref().into()), - sealed_transaction_inputs: Some(test_sealed_transaction_inputs()), + .submit_proven_tx(Request::new(proto::rpc::SubmitProvenTxRequest { + submission: Some(proto::submission::ProvenTransactionSubmission { + transaction: Some(transactions[1].as_ref().into()), + sealed_transaction_inputs: Some(test_sealed_transaction_inputs()), + }), })) - .await, + .await + .map(|_| ()), public - .submit_proven_tx_batch(Request::new(proto::submission::TransactionBatch { - batch: Some((&proven_batch).into()), - proposed_batch: Some((&batch).into()), - sealed_transaction_inputs: vec![test_sealed_transaction_inputs(); 2], + .submit_proven_tx_batch(Request::new(proto::rpc::SubmitProvenTxBatchRequest { + submission: Some(proto::submission::TransactionBatch { + batch: Some((&proven_batch).into()), + proposed_batch: Some((&batch).into()), + sealed_transaction_inputs: vec![test_sealed_transaction_inputs(); 2], + }), })) - .await, - internal.submit_authenticated_tx(Request::new(tx)).await, + .await + .map(|_| ()), internal - .submit_authenticated_tx_batch(Request::new(authenticated_batch.clone())) - .await, + .submit_authenticated_tx(Request::new(proto::sequencer::SubmitAuthenticatedTxRequest { + transaction: Some(tx), + })) + .await + .map(|_| ()), + internal + .submit_authenticated_tx_batch(Request::new( + proto::sequencer::SubmitAuthenticatedTxBatchRequest { + batch: Some(authenticated_batch.clone()), + }, + )) + .await + .map(|_| ()), ] { let status = result.unwrap_err(); assert_eq!(status.code(), tonic::Code::PermissionDenied, "{status}"); @@ -521,7 +537,11 @@ async fn submission_endpoints_reject_unregistered_creation_without_partial_batch // The retry must not conflict with a partially admitted transaction from the rejected batch. allowlist.add_account(transactions[1].account_id()).await.unwrap(); internal - .submit_authenticated_tx_batch(Request::new(authenticated_batch)) + .submit_authenticated_tx_batch(Request::new( + proto::sequencer::SubmitAuthenticatedTxBatchRequest { + batch: Some(authenticated_batch), + }, + )) .await .unwrap(); } diff --git a/crates/rpc/src/tests/error_details.rs b/crates/rpc/src/tests/error_details.rs index 584bc8f40d..a23493fd75 100644 --- a/crates/rpc/src/tests/error_details.rs +++ b/crates/rpc/src/tests/error_details.rs @@ -14,10 +14,13 @@ async fn malformed_read_requests_return_method_specific_codes() { let (mut client, _, _store, _server) = start_rpc().await; let errors = [ - (client.get_account(proto::rpc::AccountRequest::default()).await.unwrap_err(), 1), + ( + client.get_account(proto::rpc::GetAccountRequest::default()).await.unwrap_err(), + 1, + ), ( client - .get_notes_by_id(proto::rpc::NotesByIdRequest { + .get_notes_by_id(proto::rpc::GetNotesByIdRequest { note_ids: vec![proto::note::NoteId::default()], }) .await @@ -26,7 +29,7 @@ async fn malformed_read_requests_return_method_specific_codes() { ), ( client - .get_note_script_by_root(proto::rpc::NoteScriptByRootRequest::default()) + .get_note_script_by_root(proto::rpc::GetNoteScriptByRootRequest::default()) .await .unwrap_err(), 1, @@ -163,10 +166,10 @@ async fn account_lookup_returns_distinct_error_codes() { (public_id, Some(BlockNumber::from(1).into()), 4), ] { let error = client - .get_account(proto::rpc::AccountRequest { + .get_account(proto::rpc::GetAccountRequest { account_id: Some(account_id.into()), block_num, - details: Some(proto::rpc::account_request::AccountDetailRequest::default()), + details: Some(proto::rpc::get_account_request::AccountDetailRequest::default()), }) .await .unwrap_err(); diff --git a/crates/store/src/state/view/account/mod.rs b/crates/store/src/state/view/account/mod.rs index ea1a75ea56..33b9982a52 100644 --- a/crates/store/src/state/view/account/mod.rs +++ b/crates/store/src/state/view/account/mod.rs @@ -3,12 +3,12 @@ use std::collections::HashSet; use miden_node_proto::domain::account::{ AccountDetailRequest, AccountDetails, - AccountRequest, - AccountResponse, AccountStorageDetails, AccountStorageMapDetails, AccountStorageRequest, AccountVaultDetails, + GetAccountRequest, + GetAccountResponse, SlotData, StorageMapEntries, StorageMapRequest, @@ -38,9 +38,9 @@ impl StateView { )] pub async fn get_account( &self, - account_request: AccountRequest, - ) -> Result { - let AccountRequest { block_num, account_id, details } = account_request; + get_account_request: GetAccountRequest, + ) -> Result { + let GetAccountRequest { block_num, account_id, details } = get_account_request; if details.is_some() && !account_id.is_public() { return Err(GetAccountError::AccountNotPublic(account_id)); @@ -57,7 +57,7 @@ impl StateView { None }; - Ok(AccountResponse { + Ok(GetAccountResponse { block_num: *scoped_block, witness, details, diff --git a/crates/store/src/state/view/account/response_budget.rs b/crates/store/src/state/view/account/response_budget.rs index fee5f7c876..1f467de6eb 100644 --- a/crates/store/src/state/view/account/response_budget.rs +++ b/crates/store/src/state/view/account/response_budget.rs @@ -7,10 +7,10 @@ use miden_node_proto::domain::account::{ AccountDetails, - AccountResponse, AccountStorageDetails, AccountStorageMapDetails, AccountVaultDetails, + GetAccountResponse, StorageMapEntries, }; use miden_node_proto::generated as proto; @@ -79,7 +79,7 @@ pub(super) fn apply_all_storage_maps_response_budget( ) -> AccountDetails { let mut accepted_map_details = Vec::with_capacity(ordered_map_details.len()); let base_response_size_without_map_details = - proto::rpc::AccountResponse::from(AccountResponse { + proto::rpc::GetAccountResponse::from(GetAccountResponse { block_num, witness: witness.clone(), details: Some(AccountDetails { @@ -130,11 +130,11 @@ pub(super) fn apply_all_storage_maps_response_budget( mod tests { use miden_node_proto::domain::account::{ AccountDetails, - AccountResponse, AccountStorageDetails, AccountStorageMapDetails, AccountStorageRequest, AccountVaultDetails, + GetAccountResponse, SlotData, StorageMapEntries, StorageMapRequest, @@ -283,7 +283,7 @@ mod tests { let storage_header = storage_header(); let slot_1 = StorageSlotName::mock(1); let slot_2 = StorageSlotName::mock(2); - let marker_only_budget = super::proto::rpc::AccountResponse::from(AccountResponse { + let marker_only_budget = super::proto::rpc::GetAccountResponse::from(GetAccountResponse { block_num: BlockNumber::GENESIS, witness: witness.clone(), details: Some(AccountDetails { @@ -347,24 +347,25 @@ mod tests { .collect(), ) .unwrap(); - let marker_only_hard_cap = super::proto::rpc::AccountResponse::from(AccountResponse { - block_num: BlockNumber::GENESIS, - witness: witness.clone(), - details: Some(AccountDetails { - account_header: header.clone(), - account_code: None, - vault_details: AccountVaultDetails::empty(), - storage_details: AccountStorageDetails { - header: storage_header.clone(), - map_details: slot_names - .iter() - .cloned() - .map(AccountStorageMapDetails::limit_exceeded) - .collect(), - }, - }), - }) - .encoded_len(); + let marker_only_hard_cap = + super::proto::rpc::GetAccountResponse::from(GetAccountResponse { + block_num: BlockNumber::GENESIS, + witness: witness.clone(), + details: Some(AccountDetails { + account_header: header.clone(), + account_code: None, + vault_details: AccountVaultDetails::empty(), + storage_details: AccountStorageDetails { + header: storage_header.clone(), + map_details: slot_names + .iter() + .cloned() + .map(AccountStorageMapDetails::limit_exceeded) + .collect(), + }, + }), + }) + .encoded_len(); let details = apply_all_storage_maps_response_budget( BlockNumber::GENESIS, @@ -391,7 +392,7 @@ mod tests { .all(|details| details.entries == StorageMapEntries::LimitExceeded) ); assert!( - super::proto::rpc::AccountResponse::from(AccountResponse { + super::proto::rpc::GetAccountResponse::from(GetAccountResponse { block_num: BlockNumber::GENESIS, witness, details: Some(details), diff --git a/proto/proto/README.md b/proto/proto/README.md index 2e7fe42f03..c126072ef5 100644 --- a/proto/proto/README.md +++ b/proto/proto/README.md @@ -31,4 +31,9 @@ Keep service-specific wrappers with their service. For example, `rpc.proto` owns messages. `internal/validator.proto` owns the signing request and signature response. Submission envelopes belong in `types/submission.proto`. Block proving requests belong in `types/block_proving.proto`. +Each method has a dedicated request message and a dedicated response message. Name these messages after the method, with +`Request` and `Response` suffixes. Add a service prefix when method names repeat within one package. Use dedicated empty +messages for methods that have no request fields or response fields. Do not share endpoint messages between methods or +services. Endpoint messages can contain shared payload types. + See the [migration guidance](../README.md#canonical-protobuf-migration) before updating an existing client. diff --git a/proto/proto/internal/ntx_builder.proto b/proto/proto/internal/ntx_builder.proto index 7d0ae3c91a..52bc4c41da 100644 --- a/proto/proto/internal/ntx_builder.proto +++ b/proto/proto/internal/ntx_builder.proto @@ -17,5 +17,20 @@ service Api { // many failed attempts. // // Returns `NOT_FOUND` if the note ID is not tracked by the network transaction builder. - rpc GetNetworkNoteStatus(note.NoteId) returns (rpc.GetNetworkNoteStatusResponse) {} + rpc GetNetworkNoteStatus(GetNetworkNoteStatusRequest) returns (GetNetworkNoteStatusResponse) {} +} + +message GetNetworkNoteStatusRequest { + note.NoteId note_id = 1; +} + +message GetNetworkNoteStatusResponse { + // Current lifecycle status of the note. + rpc.NetworkNoteStatus status = 1; + // The latest error message from execution, if any. + optional string last_error = 2; + // Number of failed execution attempts. + uint32 attempt_count = 3; + // Block number of the last failed attempt, if any. + optional fixed32 last_attempt_block_num = 4; } diff --git a/proto/proto/internal/sequencer.proto b/proto/proto/internal/sequencer.proto index a05fc6e796..84e3d79fde 100644 --- a/proto/proto/internal/sequencer.proto +++ b/proto/proto/internal/sequencer.proto @@ -5,7 +5,6 @@ syntax = "proto3"; package sequencer; import "account.proto"; -import "block_number.proto"; import "primitives.proto"; import "transaction.proto"; import "batch.proto"; @@ -16,11 +15,11 @@ import "batch.proto"; service Api { // Submits an already-authenticated transaction directly to the mempool. Returns the node's // current block height. - rpc SubmitAuthenticatedTx(AuthenticatedTransaction) returns (blockchain.BlockNumber) {} + rpc SubmitAuthenticatedTx(SubmitAuthenticatedTxRequest) returns (SubmitAuthenticatedTxResponse) {} // Submits a batch of already-authenticated transactions directly to the mempool. Returns the // node's current block height. - rpc SubmitAuthenticatedTxBatch(AuthenticatedTransactionBatch) returns (blockchain.BlockNumber) {} + rpc SubmitAuthenticatedTxBatch(SubmitAuthenticatedTxBatchRequest) returns (SubmitAuthenticatedTxBatchResponse) {} } // MESSAGES @@ -87,3 +86,19 @@ message NullifierRecord { // The block number in which the nullifier was consumed; 0 if it is unspent. fixed32 block_num = 2; } + +message SubmitAuthenticatedTxRequest { + AuthenticatedTransaction transaction = 1; +} + +message SubmitAuthenticatedTxResponse { + fixed32 block_num = 1; +} + +message SubmitAuthenticatedTxBatchRequest { + AuthenticatedTransactionBatch batch = 1; +} + +message SubmitAuthenticatedTxBatchResponse { + fixed32 block_num = 1; +} diff --git a/proto/proto/internal/validator.proto b/proto/proto/internal/validator.proto index 95d979717f..63bc825eba 100644 --- a/proto/proto/internal/validator.proto +++ b/proto/proto/internal/validator.proto @@ -8,7 +8,6 @@ import "primitives.proto"; import "protocol_config.proto"; import "types/block_proving.proto"; import "types/submission.proto"; -import "google/protobuf/empty.proto"; // VALIDATOR API // ================================================================================================ @@ -16,10 +15,10 @@ import "google/protobuf/empty.proto"; // Validator API for the Validator component. service Api { // Returns the status info of the validator. - rpc Status(google.protobuf.Empty) returns (ValidatorStatus) {} + rpc Status(StatusRequest) returns (StatusResponse) {} // Submits a transaction to the validator. - rpc SubmitProvenTransaction(submission.ProvenTransactionSubmission) returns (google.protobuf.Empty) {} + rpc SubmitProvenTransaction(SubmitProvenTransactionRequest) returns (SubmitProvenTransactionResponse) {} // Validates and signs a proposed block. rpc SignBlock(SignBlockRequest) returns (SignBlockResponse) {} @@ -37,7 +36,7 @@ service Api { // The encryption key is shared across the whole validator set, so the returned public key is // identical regardless of which validator serves the request. The attestation carried in the // response is specific to this validator. - rpc GetTransactionEncryptionKey(google.protobuf.Empty) returns (submission.TransactionEncryptionKey) {} + rpc GetTransactionEncryptionKey(GetTransactionEncryptionKeyRequest) returns (GetTransactionEncryptionKeyResponse) {} } // SIGN BLOCK REQUEST AND RESPONSE @@ -91,8 +90,10 @@ message BlockSubscriptionResponse { // VALIDATOR STATUS // ================================================================================================ +message StatusRequest {} + // Represents the status of the validator. -message ValidatorStatus { +message StatusResponse { // The validator's running version. string version = 1; @@ -108,3 +109,15 @@ message ValidatorStatus { // The total number of blocks signed by this validator. fixed64 signed_blocks_count = 5; } + +message SubmitProvenTransactionRequest { + submission.ProvenTransactionSubmission submission = 1; +} + +message SubmitProvenTransactionResponse {} + +message GetTransactionEncryptionKeyRequest {} + +message GetTransactionEncryptionKeyResponse { + submission.TransactionEncryptionKey key = 1; +} diff --git a/proto/proto/note_transport.proto b/proto/proto/note_transport.proto index d3dff86f2c..28203e1dd3 100644 --- a/proto/proto/note_transport.proto +++ b/proto/proto/note_transport.proto @@ -12,7 +12,7 @@ service Api { // Verifies inclusion against the trusted node before storage, including on retries. // Accepts only private notes. Rejects non-private notes with INVALID_ARGUMENT. // A retry with the same note ID keeps the first envelope. - rpc SendNoteWithProof(SendNoteWithProofRequest) returns (SendNoteResponse) {} + rpc SendNoteWithProof(SendNoteWithProofRequest) returns (SendNoteWithProofResponse) {} // Returns notes after the cursor, ordered by their storage cursor. rpc FetchNotes(FetchNotesRequest) returns (FetchNotesResponse) {} } @@ -32,6 +32,8 @@ message SendNoteWithProofRequest { note.NoteInclusionProof inclusion_proof = 2; } +message SendNoteWithProofResponse {} + message TransportNote { note.NoteHeader header = 1; note.NoteDetails details = 2; diff --git a/proto/proto/remote_prover.proto b/proto/proto/remote_prover.proto index d0b1eb11c9..f852b4b24e 100644 --- a/proto/proto/remote_prover.proto +++ b/proto/proto/remote_prover.proto @@ -2,7 +2,6 @@ syntax = "proto3"; package remote_prover; -import "google/protobuf/empty.proto"; import "batch.proto"; import "primitives.proto"; import "transaction.proto"; @@ -14,7 +13,7 @@ import "types/block_proving.proto"; service Api { // Generates a proof for the requested payload. - rpc Prove(ProofRequest) returns (Proof) {} + rpc Prove(ProveRequest) returns (ProveResponse) {} } // Enumeration of supported proof types. @@ -30,7 +29,7 @@ enum ProofType { } // Request message for proof generation. -message ProofRequest { +message ProveRequest { oneof request { transaction.TransactionInputs transaction = 1; transaction.ProposedBatch batch = 2; @@ -39,7 +38,7 @@ message ProofRequest { } // Response message containing the generated proof. -message Proof { +message ProveResponse { oneof proof { transaction.ProvenTransaction transaction = 1; transaction.ProvenBatch batch = 2; @@ -52,7 +51,7 @@ message Proof { service ProxyStatusApi { // Returns the status of the proxy. - rpc Status(google.protobuf.Empty) returns (ProxyStatus) {} + rpc Status(ProxyStatusRequest) returns (ProxyStatusResponse) {} } // Status of an individual worker in the proxy. @@ -79,8 +78,10 @@ enum WorkerHealthStatus { UNHEALTHY = 2; } +message ProxyStatusRequest {} + // Response message containing the status of the proxy. -message ProxyStatus { +message ProxyStatusResponse { // The version of the proxy. string version = 1; // The proof type supported by this proxy. @@ -94,11 +95,13 @@ message ProxyStatus { service WorkerStatusApi { // Returns the status of the worker. - rpc Status(google.protobuf.Empty) returns (WorkerStatus) {} + rpc Status(WorkerStatusRequest) returns (WorkerStatusResponse) {} } +message WorkerStatusRequest {} + // Response message containing the status of the worker. -message WorkerStatus { +message WorkerStatusResponse { // The version of the worker. string version = 1; // The proof type supported by this worker. diff --git a/proto/proto/rpc.proto b/proto/proto/rpc.proto index 094e9c7ae0..3922ca41ab 100644 --- a/proto/proto/rpc.proto +++ b/proto/proto/rpc.proto @@ -2,7 +2,6 @@ syntax = "proto3"; package rpc; -import "google/protobuf/empty.proto"; import "account.proto"; import "asset.proto"; import "batch.proto"; @@ -20,17 +19,17 @@ import "types/submission.proto"; // RPC API for the RPC component service Api { // Returns the status info of the node. - rpc Status(google.protobuf.Empty) returns (RpcStatus) {} + rpc Status(StatusRequest) returns (StatusResponse) {} // Returns the query parameter limits configured for RPC methods. // // These define the maximum number of each parameter a method will accept. // Exceeding the limit will result in the request being rejected and you should instead send // multiple smaller requests. - rpc GetLimits(google.protobuf.Empty) returns (RpcLimits) {} + rpc GetLimits(GetLimitsRequest) returns (GetLimitsResponse) {} // Returns the latest details of the specified account. - rpc GetAccount(AccountRequest) returns (AccountResponse) {} + rpc GetAccount(GetAccountRequest) returns (GetAccountResponse) {} // Registers an account with an invitation code on the sequencer. // A retry with the same code and account succeeds without changes. @@ -42,23 +41,23 @@ service Api { // If registration funding is configured, waits for the funding note to commit. // Returns UNAVAILABLE if funding fails. The account remains registered and retries do not // request funding again. - rpc RegisterAccount(RegisterAccountRequest) returns (google.protobuf.Empty) {} + rpc RegisterAccount(RegisterAccountRequest) returns (RegisterAccountResponse) {} // Returns true if account allowlist enforcement is disabled or the account is allowlisted. rpc IsAccountAllowed(IsAccountAllowedRequest) returns (IsAccountAllowedResponse) {} // Returns block data for the specified block number, optionally including the block proof. - rpc GetBlockByNumber(BlockRequest) returns (MaybeBlock) {} + rpc GetBlockByNumber(GetBlockByNumberRequest) returns (GetBlockByNumberResponse) {} // Retrieves block header by given block number. Optionally, it also returns the MMR path // and current chain length to authenticate the block's inclusion. - rpc GetBlockHeaderByNumber(BlockHeaderByNumberRequest) returns (BlockHeaderByNumberResponse) {} + rpc GetBlockHeaderByNumber(GetBlockHeaderByNumberRequest) returns (GetBlockHeaderByNumberResponse) {} // Returns a list of notes matching the provided note IDs. - rpc GetNotesById(NotesByIdRequest) returns (NotesByIdResponse) {} + rpc GetNotesById(GetNotesByIdRequest) returns (GetNotesByIdResponse) {} // Returns the script for a note by its root. - rpc GetNoteScriptByRoot(NoteScriptByRootRequest) returns (MaybeNoteScript) {} + rpc GetNoteScriptByRoot(GetNoteScriptByRootRequest) returns (GetNoteScriptByRootResponse) {} // TRANSACTION SUBMISSION ENDPOINTS // -------------------------------------------------------------------------------------------- @@ -71,17 +70,17 @@ service Api { // validator attestations, currently containing a single one. Since all validators vouch for // the same key, an attestation verifiable against any chain-recognized validator signing key // is sufficient. - rpc GetTransactionEncryptionKey(google.protobuf.Empty) returns (submission.TransactionEncryptionKey) {} + rpc GetTransactionEncryptionKey(GetTransactionEncryptionKeyRequest) returns (GetTransactionEncryptionKeyResponse) {} // Submits proven transaction to the Miden network. Returns the node's current block height. - rpc SubmitProvenTx(submission.ProvenTransactionSubmission) returns (blockchain.BlockNumber) {} + rpc SubmitProvenTx(SubmitProvenTxRequest) returns (SubmitProvenTxResponse) {} // Submits a batch of transactions to the Miden network. // // All transactions in this batch will be considered atomic, and be committed together or not all. // // Returns the node's current block height. - rpc SubmitProvenTxBatch(submission.TransactionBatch) returns (blockchain.BlockNumber) {} + rpc SubmitProvenTxBatch(SubmitProvenTxBatchRequest) returns (SubmitProvenTxBatchResponse) {} // STATE SYNCHRONIZATION ENDPOINTS // -------------------------------------------------------------------------------------------- @@ -137,7 +136,7 @@ service Api { // many failed attempts. // // Returns `NOT_FOUND` if the note ID is not tracked by the network transaction builder. - rpc GetNetworkNoteStatus(note.NoteId) returns (GetNetworkNoteStatusResponse) {} + rpc GetNetworkNoteStatus(GetNetworkNoteStatusRequest) returns (GetNetworkNoteStatusResponse) {} } // REGISTER ACCOUNT @@ -152,6 +151,8 @@ message RegisterAccountRequest { account.AccountId account_id = 2; } +message RegisterAccountResponse {} + // IS ACCOUNT ALLOWED // ================================================================================================ @@ -209,8 +210,10 @@ message ProofSubscriptionResponse { // RPC STATUS // ================================================================================================ +message StatusRequest {} + // Represents the status of the node. -message RpcStatus { +message StatusResponse { // The rpc component's running version. string version = 1; @@ -267,7 +270,7 @@ message MempoolStats { // path and current forest which validate the block's inclusion in the chain. // // The Merkle path is an MMR proof for the block's leaf, based on the current chain length. -message BlockHeaderByNumberRequest { +message GetBlockHeaderByNumberRequest { // The target block height, defaults to latest if not provided. optional uint32 block_num = 1; // Whether or not to return authentication data for the block header. @@ -277,7 +280,7 @@ message BlockHeaderByNumberRequest { } // Represents the result of getting a block header by block number. -message BlockHeaderByNumberResponse { +message GetBlockHeaderByNumberResponse { // The requested block header. blockchain.BlockHeader block_header = 1; @@ -295,13 +298,13 @@ message BlockHeaderByNumberResponse { // ================================================================================================ // Request for a block, with an optional execution proof. -message BlockRequest { +message GetBlockByNumberRequest { fixed32 block_num = 1; optional bool include_proof = 2; } // A block and, when requested and available, its execution proof. -message MaybeBlock { +message GetBlockByNumberResponse { optional blockchain.SignedBlock block = 1; optional primitives.ExecutionProof proof = 2; } @@ -310,7 +313,7 @@ message MaybeBlock { // ================================================================================================ // A list of note IDs to retrieve. -message NotesByIdRequest { +message GetNotesByIdRequest { repeated note.NoteId note_ids = 1; } @@ -321,19 +324,19 @@ message CommittedNote { } // Notes returned from a note ID query. -message NotesByIdResponse { +message GetNotesByIdResponse { repeated CommittedNote notes = 1; } // GET NOTE SCRIPT BY ROOT // ================================================================================================ -message NoteScriptByRootRequest { +message GetNoteScriptByRootRequest { primitives.Word root = 1; } // Represents a note script or nothing. -message MaybeNoteScript { +message GetNoteScriptByRootResponse { // The script for a note by its root. optional note.NoteScript script = 1; } @@ -342,7 +345,7 @@ message MaybeNoteScript { // ================================================================================================ // Defines the request for account details. -message AccountRequest { +message GetAccountRequest { // Request the details for a public account. message AccountDetailRequest { // Represents a storage slot index and the associated map keys. @@ -411,7 +414,7 @@ message AccountRequest { } // Represents the result of getting account proof. -message AccountResponse { +message GetAccountResponse { message AccountDetails { // Account header. account.AccountHeader header = 1; @@ -437,7 +440,7 @@ message AccountResponse { optional AccountDetails details = 3; } -// Account vault details for AccountResponse +// Account vault details for GetAccountResponse message AccountVaultDetails { // A flag that is set to true if the account contains too many assets. This indicates // to the user that `SyncAccountVault` endpoint should be used to retrieve the @@ -449,7 +452,7 @@ message AccountVaultDetails { repeated asset.Asset assets = 2; } -// Account storage details for AccountResponse +// Account storage details for GetAccountResponse message AccountStorageDetails { message AccountStorageMapDetails { // Wrapper for repeated storage map entries (without proofs). @@ -857,6 +860,10 @@ enum NetworkNoteStatus { NETWORK_NOTE_STATUS_NULLIFIER_COMMITTED = 4; } +message GetNetworkNoteStatusRequest { + note.NoteId note_id = 1; +} + // Response containing the lifecycle status and latest execution error for a network note. message GetNetworkNoteStatusResponse { // Current lifecycle status of the note. @@ -872,8 +879,10 @@ message GetNetworkNoteStatusResponse { // RPC LIMITS // ================================================================================================ +message GetLimitsRequest {} + // Represents the query parameter limits for RPC endpoints. -message RpcLimits { +message GetLimitsResponse { // Maps RPC endpoint names to their parameter limits. // Key: endpoint name (e.g., "SyncNullifiers") // Value: map of parameter names to their limit values @@ -887,3 +896,25 @@ message EndpointLimits { // Value: limit value map parameters = 1; } + +message GetTransactionEncryptionKeyRequest {} + +message GetTransactionEncryptionKeyResponse { + submission.TransactionEncryptionKey key = 1; +} + +message SubmitProvenTxRequest { + submission.ProvenTransactionSubmission submission = 1; +} + +message SubmitProvenTxResponse { + fixed32 block_num = 1; +} + +message SubmitProvenTxBatchRequest { + submission.TransactionBatch submission = 1; +} + +message SubmitProvenTxBatchResponse { + fixed32 block_num = 1; +} diff --git a/proto/tests/descriptors.rs b/proto/tests/descriptors.rs index 024abfa22d..2ed05890a6 100644 --- a/proto/tests/descriptors.rs +++ b/proto/tests/descriptors.rs @@ -1,5 +1,74 @@ use std::collections::BTreeSet; +#[test] +fn methods_have_dedicated_request_and_response_messages() { + let descriptors = [ + miden_node_proto_build::rpc_api_descriptor(), + miden_node_proto_build::remote_prover_api_descriptor(), + miden_node_proto_build::note_transport_api_descriptor(), + #[cfg(feature = "internal")] + miden_node_proto_build::ntx_builder_api_descriptor(), + #[cfg(feature = "internal")] + miden_node_proto_build::sequencer_api_descriptor(), + #[cfg(feature = "internal")] + miden_node_proto_build::validator_api_descriptor(), + ]; + let mut services = BTreeSet::new(); + let mut messages = BTreeSet::new(); + + for descriptor in &descriptors { + for file in &descriptor.file { + for service in &file.service { + let service_name = format!("{}.{}", file.package(), service.name()); + if !services.insert(service_name.clone()) { + continue; + } + for method in &service.method { + for (message, suffix) in + [(method.input_type(), "Request"), (method.output_type(), "Response")] + { + let prefix = format!(".{}.", file.package()); + assert!( + message.starts_with(&prefix), + "{service_name}.{} must own its {suffix} message: {message}", + method.name(), + ); + assert!( + message.ends_with(&format!("{}{suffix}", method.name())), + "{service_name}.{} must name its {suffix} message after the method: {message}", + method.name(), + ); + assert!( + messages.insert(message.to_owned()), + "{service_name}.{} shares endpoint message {message}", + method.name(), + ); + } + } + } + } + } +} + +#[test] +fn public_descriptors_exclude_internal_services() { + for descriptor in [ + miden_node_proto_build::rpc_api_descriptor(), + miden_node_proto_build::remote_prover_api_descriptor(), + miden_node_proto_build::note_transport_api_descriptor(), + ] { + for file in &descriptor.file { + if !file.service.is_empty() { + assert!( + matches!(file.package(), "rpc" | "remote_prover" | "note_transport"), + "public reflection exposes {}", + file.package(), + ); + } + } + } +} + #[test] fn descriptors_embed_their_dependencies() { let descriptors = [