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