Skip to main content

miden_node_proto/domain/
block.rs

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