Skip to main content

miden_node_proto/domain/
remote_prover.rs

1use miden_protobuf::{ConversionError, ConversionResultExt, Decoded, VerifyWith};
2use miden_protocol::batch::{ProposedBatch, ProvenBatch};
3use miden_protocol::vm::ExecutionProof;
4
5use crate::generated as proto;
6
7impl proto::miden::remote_prover::v1::DecodedProveResponse {
8    /// Extract the transaction fields without verifying the transaction.
9    pub fn into_transaction(
10        self,
11    ) -> Result<Decoded<proto::transaction::ProvenTransaction>, ConversionError> {
12        self.proof.into_transaction().context("proof")
13    }
14
15    /// Extract the batch fields without verifying the batch.
16    pub fn into_batch(self) -> Result<Decoded<proto::transaction::ProvenBatch>, ConversionError> {
17        self.proof.into_batch().context("proof")
18    }
19
20    /// Extract the block proof without verifying its statement.
21    pub fn into_block(self) -> Result<ExecutionProof, ConversionError> {
22        self.proof.into_block().context("proof")
23    }
24}
25
26impl VerifyWith<&ProposedBatch> for proto::miden::remote_prover::v1::DecodedProveResponse {
27    type Verified = ProvenBatch;
28    type Error = ConversionError;
29
30    /// Match the returned batch to the supplied proposal. The caller must verify the proposal
31    /// first. The caller must verify the execution proof separately.
32    fn verify_with(self, proposal: &ProposedBatch) -> Result<Self::Verified, Self::Error> {
33        self.into_batch()?.verify_with(proposal).context("proof.batch")
34    }
35}
36
37#[cfg(test)]
38mod tests {
39    use miden_protobuf::DecodeMessage;
40    use miden_protocol::testing::dummy_execution_proof;
41
42    use super::*;
43
44    fn block_response() -> proto::miden::remote_prover::v1::ProveResponse {
45        proto::miden::remote_prover::v1::ProveResponse {
46            proof: Some(proto::miden::remote_prover::v1::prove_response::Proof::Block(
47                dummy_execution_proof().into(),
48            )),
49        }
50    }
51
52    #[test]
53    fn missing_proof_is_rejected() {
54        let error = proto::miden::remote_prover::v1::ProveResponse { proof: None }
55            .decode_fields()
56            .unwrap_err();
57        assert!(error.to_string().contains("proof"));
58    }
59
60    #[test]
61    fn block_response_does_not_satisfy_transaction_or_batch_request() {
62        let error = block_response().decode_fields().unwrap().into_transaction().unwrap_err();
63        assert!(error.to_string().contains("expected oneof variant `transaction`, got `block`"));
64        let error = block_response().decode_fields().unwrap().into_batch().unwrap_err();
65        assert!(error.to_string().contains("expected oneof variant `batch`, got `block`"));
66    }
67
68    #[test]
69    fn block_response_preserves_proof() {
70        assert_eq!(
71            block_response().decode_fields().unwrap().into_block().unwrap(),
72            dummy_execution_proof()
73        );
74    }
75
76    #[test]
77    fn malformed_proof_retains_field_context() {
78        let response = proto::miden::remote_prover::v1::ProveResponse {
79            proof: Some(proto::miden::remote_prover::v1::prove_response::Proof::Transaction(
80                proto::transaction::ProvenTransaction::default(),
81            )),
82        };
83        let error = response.decode_fields().unwrap_err();
84        assert!(error.to_string().contains("proof.transaction"));
85    }
86}