miden_node_proto/domain/
submission.rs1use miden_protobuf::{BuildUnchecked, ConversionResultExt, Verify, VerifyWith};
2use miden_protocol::MIN_PROOF_SECURITY_LEVEL;
3use miden_protocol::batch::{ProposedBatch, ProvenBatch};
4use miden_protocol::transaction::ProvenTransaction;
5
6use crate::errors::ConversionError;
7use crate::generated as proto;
8
9#[derive(Debug)]
11pub struct ProvenTransactionSubmission {
12 pub transaction: ProvenTransaction,
13 pub sealed_transaction_inputs: proto::submission::SealedTransactionInputs,
14}
15
16impl BuildUnchecked for proto::submission::DecodedProvenTransactionSubmission {
17 type Output = ProvenTransactionSubmission;
18 type Error = ConversionError;
19
20 fn build_unchecked(self) -> Result<Self::Output, Self::Error> {
25 let transaction = self.transaction.build_unchecked().context("transaction")?;
28 let sealed_transaction_inputs = self.sealed_transaction_inputs.into();
29 Ok(ProvenTransactionSubmission { transaction, sealed_transaction_inputs })
30 }
31}
32
33impl From<proto::submission::DecodedSealedTransactionInputs>
34 for proto::submission::SealedTransactionInputs
35{
36 fn from(value: proto::submission::DecodedSealedTransactionInputs) -> Self {
37 Self {
38 key_id: value.key_id,
39 ciphertext: value.ciphertext,
40 }
41 }
42}
43
44impl From<&ProvenTransactionSubmission> for proto::submission::ProvenTransactionSubmission {
45 fn from(value: &ProvenTransactionSubmission) -> Self {
46 Self {
47 transaction: Some((&value.transaction).into()),
48 sealed_transaction_inputs: Some(value.sealed_transaction_inputs.clone()),
49 }
50 }
51}
52
53#[derive(Debug)]
54pub struct TransactionBatchSubmission {
55 pub batch: ProvenBatch,
56 pub proposed_batch: ProposedBatch,
57 pub sealed_transaction_inputs: Vec<proto::submission::SealedTransactionInputs>,
58}
59
60impl Verify for proto::submission::DecodedTransactionBatch {
61 type Verified = TransactionBatchSubmission;
62 type Error = ConversionError;
63
64 fn verify(self) -> Result<Self::Verified, Self::Error> {
69 let batch_reference_num = self.batch.reference_block_num.block_num;
70 let proposed_reference_num = self.proposed_batch.reference_block_header.block_num.block_num;
71 if batch_reference_num != proposed_reference_num {
72 return Err(ConversionError::message(
73 "batch reference block number does not match proposal",
74 ));
75 }
76
77 let proposed_batch = self
78 .proposed_batch
79 .verify_with(MIN_PROOF_SECURITY_LEVEL)
80 .context("proposed_batch")?;
81 let batch = self.batch.verify_with(&proposed_batch).context("batch")?;
82
83 if self.sealed_transaction_inputs.as_slice().len() != proposed_batch.transactions().len() {
84 return Err(ConversionError::message(format!(
85 "sealed transaction input count {} does not match proposal transaction count {}",
86 self.sealed_transaction_inputs.as_slice().len(),
87 proposed_batch.transactions().len()
88 )));
89 }
90
91 Ok(TransactionBatchSubmission {
92 batch,
93 proposed_batch,
94 sealed_transaction_inputs: self.sealed_transaction_inputs.map(Into::into),
95 })
96 }
97}
98
99impl From<&TransactionBatchSubmission> for proto::submission::TransactionBatch {
100 fn from(value: &TransactionBatchSubmission) -> Self {
101 Self {
102 batch: Some((&value.batch).into()),
103 proposed_batch: Some((&value.proposed_batch).into()),
104 sealed_transaction_inputs: value.sealed_transaction_inputs.clone(),
105 }
106 }
107}