miden_node_proto/domain/
block.rs1use std::ops::RangeInclusive;
2
3use miden_protocol::block::{
4 BlockBody,
5 BlockHeader,
6 BlockNumber,
7 BlockSignatures,
8 FeeParameters,
9 SignedBlock,
10 ValidatorKeys,
11};
12use miden_protocol::crypto::dsa::ecdsa_k256_keccak::{PublicKey, Signature};
13use miden_protocol::utils::serde::Serializable;
14use thiserror::Error;
15
16use crate::decode::{ConversionResultExt, DecodeBytesExt, GrpcDecodeExt};
17use crate::errors::ConversionError;
18use crate::{decode, generated as proto};
19
20impl From<BlockNumber> for proto::blockchain::BlockNumber {
24 fn from(value: BlockNumber) -> Self {
25 proto::blockchain::BlockNumber { block_num: value.as_u32() }
26 }
27}
28
29impl From<proto::blockchain::BlockNumber> for BlockNumber {
30 fn from(value: proto::blockchain::BlockNumber) -> Self {
31 BlockNumber::from(value.block_num)
32 }
33}
34
35impl From<&BlockHeader> for proto::blockchain::BlockHeader {
39 fn from(header: &BlockHeader) -> Self {
40 Self {
41 version: header.version(),
42 prev_block_commitment: Some(header.prev_block_commitment().into()),
43 block_num: header.block_num().as_u32(),
44 chain_commitment: Some(header.chain_commitment().into()),
45 account_root: Some(header.account_root().into()),
46 nullifier_root: Some(header.nullifier_root().into()),
47 note_root: Some(header.note_root().into()),
48 tx_commitment: Some(header.tx_commitment().into()),
49 tx_kernel_commitment: Some(header.tx_kernel_commitment().into()),
50 validator_keys: header.validator_keys().as_keys().iter().map(Into::into).collect(),
51 timestamp: header.timestamp(),
52 fee_parameters: Some(header.fee_parameters().into()),
53 }
54 }
55}
56
57impl From<BlockHeader> for proto::blockchain::BlockHeader {
58 fn from(header: BlockHeader) -> Self {
59 (&header).into()
60 }
61}
62
63impl TryFrom<&proto::blockchain::BlockHeader> for BlockHeader {
64 type Error = ConversionError;
65
66 fn try_from(value: &proto::blockchain::BlockHeader) -> Result<Self, Self::Error> {
67 value.try_into()
68 }
69}
70
71impl TryFrom<proto::blockchain::BlockHeader> for BlockHeader {
72 type Error = ConversionError;
73
74 fn try_from(value: proto::blockchain::BlockHeader) -> Result<Self, Self::Error> {
75 let decoder = value.decoder();
76 let prev_block_commitment = decode!(decoder, value.prev_block_commitment)?;
77 let chain_commitment = decode!(decoder, value.chain_commitment)?;
78 let account_root = decode!(decoder, value.account_root)?;
79 let nullifier_root = decode!(decoder, value.nullifier_root)?;
80 let note_root = decode!(decoder, value.note_root)?;
81 let tx_commitment = decode!(decoder, value.tx_commitment)?;
82 let tx_kernel_commitment = decode!(decoder, value.tx_kernel_commitment)?;
83 let validator_keys = value
84 .validator_keys
85 .into_iter()
86 .map(PublicKey::try_from)
87 .collect::<Result<Vec<_>, _>>()
88 .context("validator_keys")?;
89 let validator_keys = ValidatorKeys::new(validator_keys)
90 .map_err(ConversionError::new)
91 .context("validator_keys")?;
92 let fee_parameters = decode!(decoder, value.fee_parameters)?;
93
94 Ok(BlockHeader::new(
95 value.version,
96 prev_block_commitment,
97 value.block_num.into(),
98 chain_commitment,
99 account_root,
100 nullifier_root,
101 note_root,
102 tx_commitment,
103 tx_kernel_commitment,
104 validator_keys,
105 fee_parameters,
106 value.timestamp,
107 ))
108 }
109}
110
111impl From<&BlockBody> for proto::blockchain::BlockBody {
115 fn from(body: &BlockBody) -> Self {
116 Self { block_body: body.to_bytes() }
117 }
118}
119
120impl From<BlockBody> for proto::blockchain::BlockBody {
121 fn from(body: BlockBody) -> Self {
122 (&body).into()
123 }
124}
125
126impl TryFrom<&proto::blockchain::BlockBody> for BlockBody {
127 type Error = ConversionError;
128
129 fn try_from(value: &proto::blockchain::BlockBody) -> Result<Self, Self::Error> {
130 value.try_into()
131 }
132}
133
134impl TryFrom<proto::blockchain::BlockBody> for BlockBody {
135 type Error = ConversionError;
136 fn try_from(value: proto::blockchain::BlockBody) -> Result<Self, Self::Error> {
137 BlockBody::decode_bytes(&value.block_body, "BlockBody")
138 }
139}
140
141impl From<&SignedBlock> for proto::blockchain::SignedBlock {
145 fn from(block: &SignedBlock) -> Self {
146 Self {
147 header: Some(block.header().into()),
148 body: Some(block.body().into()),
149 signatures: block.signatures().as_signatures().iter().map(Into::into).collect(),
150 }
151 }
152}
153
154impl From<SignedBlock> for proto::blockchain::SignedBlock {
155 fn from(block: SignedBlock) -> Self {
156 (&block).into()
157 }
158}
159
160impl TryFrom<&proto::blockchain::SignedBlock> for SignedBlock {
161 type Error = ConversionError;
162
163 fn try_from(value: &proto::blockchain::SignedBlock) -> Result<Self, Self::Error> {
164 value.try_into()
165 }
166}
167
168impl TryFrom<proto::blockchain::SignedBlock> for SignedBlock {
169 type Error = ConversionError;
170 fn try_from(value: proto::blockchain::SignedBlock) -> Result<Self, Self::Error> {
171 let decoder = value.decoder();
172 let header = decode!(decoder, value.header)?;
173 let body = decode!(decoder, value.body)?;
174 let signatures = value
175 .signatures
176 .into_iter()
177 .map(Signature::try_from)
178 .collect::<Result<Vec<_>, _>>()
179 .context("signatures")?;
180 let signatures = BlockSignatures::new(signatures)
181 .map_err(ConversionError::new)
182 .context("signatures")?;
183
184 Ok(SignedBlock::new_unchecked(header, body, signatures))
185 }
186}
187
188impl TryFrom<proto::blockchain::ValidatorPublicKey> for PublicKey {
192 type Error = ConversionError;
193 fn try_from(public_key: proto::blockchain::ValidatorPublicKey) -> Result<Self, Self::Error> {
194 PublicKey::decode_bytes(&public_key.validator_key, "PublicKey")
195 }
196}
197
198impl From<PublicKey> for proto::blockchain::ValidatorPublicKey {
199 fn from(value: PublicKey) -> Self {
200 Self::from(&value)
201 }
202}
203
204impl From<&PublicKey> for proto::blockchain::ValidatorPublicKey {
205 fn from(value: &PublicKey) -> Self {
206 Self { validator_key: value.to_bytes() }
207 }
208}
209
210impl TryFrom<proto::blockchain::BlockSignature> for Signature {
214 type Error = ConversionError;
215 fn try_from(signature: proto::blockchain::BlockSignature) -> Result<Self, Self::Error> {
216 Signature::decode_bytes(&signature.signature, "Signature")
217 }
218}
219
220impl From<Signature> for proto::blockchain::BlockSignature {
221 fn from(value: Signature) -> Self {
222 Self::from(&value)
223 }
224}
225
226impl From<&Signature> for proto::blockchain::BlockSignature {
227 fn from(value: &Signature) -> Self {
228 Self { signature: value.to_bytes() }
229 }
230}
231
232impl TryFrom<proto::blockchain::FeeParameters> for FeeParameters {
236 type Error = ConversionError;
237 fn try_from(fee_params: proto::blockchain::FeeParameters) -> Result<Self, Self::Error> {
238 let decoder = fee_params.decoder();
239 let native_asset_id = decode!(decoder, fee_params.native_asset_id)?;
240 Ok(FeeParameters::new(native_asset_id, fee_params.verification_base_fee))
241 }
242}
243
244impl From<FeeParameters> for proto::blockchain::FeeParameters {
245 fn from(value: FeeParameters) -> Self {
246 Self::from(&value)
247 }
248}
249
250impl From<&FeeParameters> for proto::blockchain::FeeParameters {
251 fn from(value: &FeeParameters) -> Self {
252 Self {
253 native_asset_id: Some(value.fee_faucet_id().into()),
254 verification_base_fee: value.verification_base_fee(),
255 }
256 }
257}
258
259#[derive(Debug, Clone, Error, PartialEq, Eq)]
263pub enum InvalidBlockRange {
264 #[error("start ({start}) greater than end ({end})")]
265 StartGreaterThanEnd { start: BlockNumber, end: BlockNumber },
266 #[error("empty range: start ({start})..end ({end})")]
267 EmptyRange { start: BlockNumber, end: BlockNumber },
268}
269
270impl proto::rpc::BlockRange {
271 pub fn into_inclusive_range<T: From<InvalidBlockRange>>(
273 self,
274 ) -> Result<RangeInclusive<BlockNumber>, T> {
275 let block_range = RangeInclusive::new(self.block_from.into(), self.block_to.into());
276
277 if block_range.start() > block_range.end() {
278 return Err(InvalidBlockRange::StartGreaterThanEnd {
279 start: *block_range.start(),
280 end: *block_range.end(),
281 }
282 .into());
283 }
284
285 if block_range.is_empty() {
286 return Err(InvalidBlockRange::EmptyRange {
287 start: *block_range.start(),
288 end: *block_range.end(),
289 }
290 .into());
291 }
292
293 Ok(block_range)
294 }
295}
296
297impl From<RangeInclusive<BlockNumber>> for proto::rpc::BlockRange {
298 fn from(range: RangeInclusive<BlockNumber>) -> Self {
299 Self {
300 block_from: range.start().as_u32(),
301 block_to: range.end().as_u32(),
302 }
303 }
304}