Skip to main content

miden_node_utils/
genesis.rs

1use std::fmt;
2use std::path::Path;
3
4use anyhow::Context;
5use miden_protocol::block::SignedBlock;
6use miden_protocol::utils::serde::Deserializable;
7
8/// Official Miden networks with a hosted genesis block.
9#[derive(clap::ValueEnum, Clone, Copy, Debug, Eq, PartialEq)]
10pub enum OfficialNetwork {
11    Devnet,
12    Testnet,
13}
14
15impl OfficialNetwork {
16    pub const fn as_str(self) -> &'static str {
17        match self {
18            Self::Devnet => "devnet",
19            Self::Testnet => "testnet",
20        }
21    }
22
23    pub fn genesis_block_url(self) -> String {
24        format!("https://genesis.{}.miden.io", self.as_str())
25    }
26}
27
28impl fmt::Display for OfficialNetwork {
29    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30        f.write_str(self.as_str())
31    }
32}
33
34/// Reads a trusted, signed genesis block from disk.
35pub fn read_signed_genesis_block(path: &Path) -> anyhow::Result<SignedBlock> {
36    let bytes = fs_err::read(path).context("failed to read genesis block file")?;
37    deserialize_signed_genesis_block(&bytes)
38}
39
40/// Downloads a trusted, signed genesis block for an official Miden network.
41pub async fn fetch_signed_genesis_block(network: OfficialNetwork) -> anyhow::Result<SignedBlock> {
42    let url = network.genesis_block_url();
43    let response = reqwest::get(url.as_str())
44        .await
45        .with_context(|| format!("failed to fetch genesis block from {url}"))?
46        .error_for_status()
47        .with_context(|| format!("failed to fetch genesis block from {url}"))?;
48    let bytes = response
49        .bytes()
50        .await
51        .with_context(|| format!("failed to read genesis block response from {url}"))?;
52
53    deserialize_signed_genesis_block(&bytes)
54}
55
56fn deserialize_signed_genesis_block(bytes: &[u8]) -> anyhow::Result<SignedBlock> {
57    SignedBlock::read_from_bytes(bytes).context("failed to deserialize genesis block")
58}