-
Notifications
You must be signed in to change notification settings - Fork 104
Expand file tree
/
Copy pathprover.rs
More file actions
130 lines (110 loc) · 4.92 KB
/
prover.rs
File metadata and controls
130 lines (110 loc) · 4.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
use miden_block_prover::LocalBlockProver;
use miden_node_proto::BlockProofRequest;
use miden_node_utils::ErrorReport;
use miden_node_utils::tracing::OpenTelemetrySpanExt;
use miden_protocol::MIN_PROOF_SECURITY_LEVEL;
use miden_protocol::batch::{ProposedBatch, ProvenBatch};
use miden_protocol::block::BlockProof;
use miden_protocol::transaction::{ProvenTransaction, TransactionInputs};
use miden_tx::LocalTransactionProver;
use miden_tx_batch_prover::LocalBatchProver;
use tracing::{Instrument, instrument};
use crate::COMPONENT;
use crate::generated::{self as proto};
use crate::server::proof_kind::ProofKind;
/// An enum representing the different types of provers available.
pub enum Prover {
Transaction(LocalTransactionProver),
Batch(LocalBatchProver),
Block(LocalBlockProver),
}
impl Prover {
/// Constructs a [`Prover`] of the specified [`ProofKind`].
pub fn new(proof_type: ProofKind) -> Self {
match proof_type {
ProofKind::Transaction => Self::Transaction(LocalTransactionProver::default()),
ProofKind::Batch => Self::Batch(LocalBatchProver::new(MIN_PROOF_SECURITY_LEVEL)),
ProofKind::Block => Self::Block(LocalBlockProver::new(MIN_PROOF_SECURITY_LEVEL)),
}
}
/// Proves a [`proto::ProofRequest`] using the appropriate prover implementation as specified
/// during construction.
pub async fn prove(&self, request: proto::ProofRequest) -> Result<proto::Proof, tonic::Status> {
match self {
Prover::Transaction(prover) => prover.prove_request(request).await,
Prover::Batch(prover) => prover.prove_request(request).await,
Prover::Block(prover) => prover.prove_request(request).await,
}
}
}
/// This trait abstracts over proof request handling by providing a common interface for our
/// different provers.
///
/// It standardizes the proving process by providing default implementations for the decoding of
/// requests, and encoding of response. Notably it also standardizes the instrumentation, though
/// implementations should still add attributes that can only be known post-decoding of the request.
///
/// Implementations of this trait only need to provide the input and outputs types, as well as the
/// proof implementation.
#[async_trait::async_trait]
trait ProveRequest: Send + Sync {
type Input: miden_protocol::utils::serde::Deserializable + Send;
type Output: miden_protocol::utils::serde::Serializable + Send;
async fn prove(&self, input: Self::Input) -> Result<Self::Output, tonic::Status>;
/// Entry-point to the proof request handling.
///
/// Decodes the request, proves it, and encodes the response.
async fn prove_request(
&self,
request: proto::ProofRequest,
) -> Result<proto::Proof, tonic::Status> {
let input = Self::decode_request(request)?;
let prove_span = tracing::info_span!("prove", target = COMPONENT);
let result = self.prove(input).instrument(prove_span).await;
if let Err(e) = &result {
tracing::Span::current().set_error(e);
}
result.map(|output| Self::encode_response(output))
}
#[instrument(target=COMPONENT, skip_all, err)]
fn decode_request(request: proto::ProofRequest) -> Result<Self::Input, tonic::Status> {
use miden_protocol::utils::serde::Deserializable;
Self::Input::read_from_bytes(&request.payload).map_err(|e| {
tonic::Status::invalid_argument(e.as_report_context("failed to decode request"))
})
}
#[instrument(target=COMPONENT, skip_all)]
fn encode_response(output: Self::Output) -> proto::Proof {
use miden_protocol::utils::serde::Serializable;
proto::Proof { payload: output.to_bytes() }
}
}
#[async_trait::async_trait]
impl ProveRequest for LocalTransactionProver {
type Input = TransactionInputs;
type Output = ProvenTransaction;
async fn prove(&self, input: Self::Input) -> Result<Self::Output, tonic::Status> {
LocalTransactionProver::prove(self, input).await.map_err(|e| {
tonic::Status::internal(e.as_report_context("failed to prove transaction"))
})
}
}
#[async_trait::async_trait]
impl ProveRequest for LocalBatchProver {
type Input = ProposedBatch;
type Output = ProvenBatch;
async fn prove(&self, input: Self::Input) -> Result<Self::Output, tonic::Status> {
self.prove(input)
.map_err(|e| tonic::Status::internal(e.as_report_context("failed to prove batch")))
}
}
#[async_trait::async_trait]
impl ProveRequest for LocalBlockProver {
type Input = BlockProofRequest;
type Output = BlockProof;
async fn prove(&self, input: Self::Input) -> Result<Self::Output, tonic::Status> {
let BlockProofRequest { tx_batches, block_header, block_inputs } = input;
self.prove(tx_batches, &block_header, block_inputs)
.map_err(|e| tonic::Status::internal(e.as_report_context("failed to prove block")))
}
}