use alloy::{
primitives::Address,
providers::Provider,
};
use crate::{
artifacts::Artifacts,
deploy::deploy_contract_from,
error::{
Error,
Result,
},
};
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Circuit {
BearerLink,
OidcGoogle,
}
impl Circuit {
pub const ALL: [Self; 2] = [Self::BearerLink, Self::OidcGoogle];
pub const fn name(self) -> &'static str {
match self {
Self::BearerLink => "bearer-link",
Self::OidcGoogle => "oidc-google",
}
}
pub const fn contract(self) -> &'static str {
match self {
Self::BearerLink => "BearerLinkHonkVerifier",
Self::OidcGoogle => "OidcGoogleHonkVerifier",
}
}
}
pub fn version(artifacts: &Artifacts) -> Result<String> {
let pin: serde_json::Value = artifacts.read_json("circuits.json")?;
pin["version"]
.as_str()
.map(str::to_owned)
.ok_or_else(|| Error::Artifact {
detail: "circuits.json has no version".into(),
})
}
pub async fn deploy_honk_verifier<P: Provider>(
provider: &P,
artifacts: &Artifacts,
circuit: Circuit,
sender: Option<Address>,
) -> Result<Address> {
deploy_contract_from(
provider,
artifacts.bytecode(circuit.contract())?,
&format!("{} ({} circuit)", circuit.contract(), circuit.name()),
sender,
)
.await
}
#[cfg(test)]
mod tests {
use super::*;
use crate::artifacts::COVERED;
#[test]
fn every_verifier_is_covered() {
for circuit in Circuit::ALL {
let contract = circuit.contract();
assert!(
COVERED.contains(&(contract, contract)),
"{contract} is not in COVERED"
);
}
}
#[test]
fn the_two_circuits_are_different_artifacts() {
let artifacts = Artifacts::embedded();
let [bearer, oidc] = Circuit::ALL;
assert_ne!(bearer.contract(), oidc.contract());
assert_ne!(
artifacts
.bytecode_hex(bearer.contract(), bearer.contract())
.unwrap(),
artifacts
.bytecode_hex(oidc.contract(), oidc.contract())
.unwrap()
);
}
#[test]
fn the_enum_matches_the_pin() {
let artifacts = Artifacts::embedded();
let pin: serde_json::Value = artifacts.read_json("circuits.json").unwrap();
let circuits = pin["circuits"].as_object().expect("circuits object");
assert_eq!(circuits.len(), Circuit::ALL.len());
for circuit in Circuit::ALL {
let entry = &circuits[circuit.name()];
assert_eq!(entry["contract"].as_str(), Some(circuit.contract()));
let digest = entry["sha256"].as_str().expect("sha256 string");
assert_eq!(digest.len(), 64, "{}: not a sha256", circuit.name());
}
let version = version(&artifacts).unwrap();
assert!(
version.split('.').count() == 3,
"circuits.json version '{version}' is not major.minor.patch"
);
}
}