use std::{
fs::{self, File},
io::Write,
path::Path,
};
use miden_lib::account::auth::RpoFalcon512;
use miden_node_proto_build::rpc_api_descriptor;
use miden_objects::{EMPTY_WORD, account::AccountComponent, crypto::dsa::rpo_falcon512::PublicKey};
use miette::IntoDiagnostic;
const STD_PROTO_OUT_DIR: &str = "src/rpc/generated/std";
const NO_STD_PROTO_OUT_DIR: &str = "src/rpc/generated/nostd";
const CODEGEN: bool = option_env!("CODEGEN").is_some();
fn main() -> miette::Result<()> {
println!("cargo::rerun-if-env-changed=CODEGEN");
if !CODEGEN {
return Ok(());
}
compile_tonic_client_proto()?;
replace_no_std_types();
generate_known_procedure_roots().into_diagnostic()
}
fn compile_tonic_client_proto() -> miette::Result<()> {
let file_descriptors = rpc_api_descriptor();
let mut prost_config = prost_build::Config::new();
prost_config.skip_debug(["AccountId", "Digest"]);
let mut web_tonic_prost_config = prost_build::Config::new();
web_tonic_prost_config.skip_debug(["AccountId", "Digest"]);
tonic_build::configure()
.build_transport(false)
.build_server(false)
.out_dir(NO_STD_PROTO_OUT_DIR)
.compile_fds_with_config(web_tonic_prost_config, file_descriptors.clone())
.into_diagnostic()?;
tonic_build::configure()
.build_server(false)
.out_dir(STD_PROTO_OUT_DIR)
.compile_fds_with_config(prost_config, file_descriptors)
.into_diagnostic()?;
Ok(())
}
fn replace_no_std_types() {
let path = NO_STD_PROTO_OUT_DIR.to_string() + "/rpc.rs";
let file_str = fs::read_to_string(&path).unwrap();
let new_file_str = file_str
.replace("std::result", "core::result")
.replace("std::marker", "core::marker");
let mut f = std::fs::OpenOptions::new().write(true).open(path).unwrap();
f.write_all(new_file_str.as_bytes()).unwrap();
}
fn generate_known_procedure_roots() -> std::io::Result<()> {
let out_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("src/account/procedure_roots.rs");
let mut f = File::create(&dest_path)?;
writeln!(f, "//! Well-known procedure roots.")?;
writeln!(f, "//! This file was generated by build.rs.\n")?;
let rpo_falcon_512_component: AccountComponent =
RpoFalcon512::new(PublicKey::new(EMPTY_WORD)).into();
let rpo_auth_proc_root = rpo_falcon_512_component
.library()
.mast_forest()
.procedure_digests()
.next()
.expect("RpoFalcon512 component should have one procedure root");
writeln!(f, "/// Procedure root of the `RpoFalcon512` authentication component.")?;
writeln!(f, "pub const RPO_FALCON_512_AUTH: &str =\n \"{rpo_auth_proc_root}\";")?;
Ok(())
}