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/// A predefined, insecure validator signing key for development purposes.
9///
10/// `miden-validator start` signs blocks with this key by default, and the default genesis
11/// configuration commits the corresponding public key as the sole genesis validator, so a locally
12/// bootstrapped chain works without any key configuration.
13pub const INSECURE_VALIDATOR_SIGNING_KEY_HEX: &str =
14    "0101010101010101010101010101010101010101010101010101010101010101";
15
16/// Official Miden networks with a hosted genesis block.
17#[derive(clap::ValueEnum, Clone, Copy, Debug, Eq, PartialEq)]
18pub enum OfficialNetwork {
19    Devnet,
20    Testnet,
21}
22
23impl OfficialNetwork {
24    pub const fn as_str(self) -> &'static str {
25        match self {
26            Self::Devnet => "devnet",
27            Self::Testnet => "testnet",
28        }
29    }
30
31    pub fn genesis_block_url(self) -> String {
32        format!("https://genesis.{}.miden.io", self.as_str())
33    }
34}
35
36impl fmt::Display for OfficialNetwork {
37    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38        f.write_str(self.as_str())
39    }
40}
41
42/// Reads a trusted genesis block from disk.
43pub fn read_genesis_block(path: &Path) -> anyhow::Result<SignedBlock> {
44    let bytes = fs_err::read(path).context("failed to read genesis block file")?;
45    deserialize_genesis_block(&bytes)
46}
47
48/// Downloads a trusted genesis block for an official Miden network.
49pub async fn fetch_genesis_block(network: OfficialNetwork) -> anyhow::Result<SignedBlock> {
50    let url = network.genesis_block_url();
51    let response = reqwest::get(url.as_str())
52        .await
53        .with_context(|| format!("failed to fetch genesis block from {url}"))?
54        .error_for_status()
55        .with_context(|| format!("failed to fetch genesis block from {url}"))?;
56    let bytes = response
57        .bytes()
58        .await
59        .with_context(|| format!("failed to read genesis block response from {url}"))?;
60
61    deserialize_genesis_block(&bytes)
62}
63
64fn deserialize_genesis_block(bytes: &[u8]) -> anyhow::Result<SignedBlock> {
65    SignedBlock::read_from_bytes(bytes).context("failed to deserialize genesis block")
66}