Add a blueprint policy command
Computes the policy ID of a minting policy; added guards for blueprint address to check that it's not a minting policy; Wasn't 100% sure where the errors should live, so I'm happy to move them if there's objections
This commit is contained in:
parent
42544af799
commit
4a8cb72708
|
@ -49,6 +49,26 @@ pub enum Error {
|
||||||
))]
|
))]
|
||||||
ParameterizedValidator { n: usize },
|
ParameterizedValidator { n: usize },
|
||||||
|
|
||||||
|
#[error(
|
||||||
|
"I couldn't compute the address of the given validator because it's actually a minting policy!",
|
||||||
|
)]
|
||||||
|
#[diagnostic(code("aiken::blueprint::address::minting_validator"))]
|
||||||
|
#[diagnostic(help(
|
||||||
|
"I can only compute addresses for spending validators. Did you mean to call {blueprint_policy_command} instead?",
|
||||||
|
blueprint_policy_command = "blueprint policy".if_supports_color(Stdout, |s| s.purple()),
|
||||||
|
))]
|
||||||
|
UnexpectedMintingValidator,
|
||||||
|
|
||||||
|
#[error(
|
||||||
|
"I couldn't compute the policyId of the given validator because it's actually a spending policy!",
|
||||||
|
)]
|
||||||
|
#[diagnostic(code("aiken::blueprint::address::spending_validator"))]
|
||||||
|
#[diagnostic(help(
|
||||||
|
"I can only compute policyIds for minting validators. Did you mean to call {blueprint_address_command} instead?",
|
||||||
|
blueprint_address_command = "blueprint address".if_supports_color(Stdout, |s| s.purple()),
|
||||||
|
))]
|
||||||
|
UnexpectedSpendingValidator,
|
||||||
|
|
||||||
#[error("I stumble upon something else than a constant when I expected one.")]
|
#[error("I stumble upon something else than a constant when I expected one.")]
|
||||||
#[diagnostic(code("aiken:blueprint::apply::malformed::argument"))]
|
#[diagnostic(code("aiken:blueprint::apply::malformed::argument"))]
|
||||||
#[diagnostic(help(
|
#[diagnostic(help(
|
||||||
|
|
|
@ -27,9 +27,10 @@ use indexmap::IndexMap;
|
||||||
use miette::NamedSource;
|
use miette::NamedSource;
|
||||||
use options::{CodeGenMode, Options};
|
use options::{CodeGenMode, Options};
|
||||||
use package_name::PackageName;
|
use package_name::PackageName;
|
||||||
use pallas::ledger::addresses::{
|
use pallas::ledger::{addresses::{
|
||||||
Address, Network, ShelleyAddress, ShelleyDelegationPart, StakePayload,
|
Address, Network, ShelleyAddress, ShelleyDelegationPart, StakePayload,
|
||||||
};
|
}, primitives::babbage::{self as cardano, PolicyId}};
|
||||||
|
use pallas_traverse::ComputeHash;
|
||||||
use script::{EvalHint, EvalInfo, Script};
|
use script::{EvalHint, EvalInfo, Script};
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
|
@ -369,6 +370,11 @@ where
|
||||||
let when_missing = |known_validators| Error::NoValidatorNotFound { known_validators };
|
let when_missing = |known_validators| Error::NoValidatorNotFound { known_validators };
|
||||||
|
|
||||||
blueprint.with_validator(title, when_too_many, when_missing, |validator| {
|
blueprint.with_validator(title, when_too_many, when_missing, |validator| {
|
||||||
|
// Make sure we're not calculating the address for a minting validator
|
||||||
|
if validator.datum.is_none() {
|
||||||
|
return Err(blueprint::error::Error::UnexpectedMintingValidator.into());
|
||||||
|
}
|
||||||
|
|
||||||
let n = validator.parameters.len();
|
let n = validator.parameters.len();
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
Err(blueprint::error::Error::ParameterizedValidator { n }.into())
|
Err(blueprint::error::Error::ParameterizedValidator { n }.into())
|
||||||
|
@ -380,6 +386,37 @@ where
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn policy(
|
||||||
|
&self,
|
||||||
|
title: Option<&String>
|
||||||
|
) -> Result<PolicyId, Error> {
|
||||||
|
// Read blueprint
|
||||||
|
let blueprint = File::open(self.blueprint_path())
|
||||||
|
.map_err(|_| blueprint::error::Error::InvalidOrMissingFile)?;
|
||||||
|
let blueprint: Blueprint = serde_json::from_reader(BufReader::new(blueprint))?;
|
||||||
|
|
||||||
|
// Error handlers for ambiguous / missing validators
|
||||||
|
let when_too_many =
|
||||||
|
|known_validators| Error::MoreThanOneValidatorFound { known_validators };
|
||||||
|
let when_missing = |known_validators| Error::NoValidatorNotFound { known_validators };
|
||||||
|
|
||||||
|
blueprint.with_validator(title, when_too_many, when_missing, |validator| {
|
||||||
|
// Make sure we're not calculating the policy for a spending validator
|
||||||
|
if validator.datum.is_some() {
|
||||||
|
return Err(blueprint::error::Error::UnexpectedSpendingValidator.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let n = validator.parameters.len();
|
||||||
|
if n > 0 {
|
||||||
|
Err(blueprint::error::Error::ParameterizedValidator { n }.into())
|
||||||
|
} else {
|
||||||
|
let cbor = validator.program.to_cbor().unwrap();
|
||||||
|
let validator_hash = cardano::PlutusV2Script(cbor.into()).compute_hash();
|
||||||
|
Ok(validator_hash)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn apply_parameter(
|
pub fn apply_parameter(
|
||||||
&self,
|
&self,
|
||||||
title: Option<&String>,
|
title: Option<&String>,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
pub mod address;
|
pub mod address;
|
||||||
|
pub mod policy;
|
||||||
pub mod apply;
|
pub mod apply;
|
||||||
pub mod convert;
|
pub mod convert;
|
||||||
|
|
||||||
|
@ -8,6 +9,7 @@ use clap::Subcommand;
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
pub enum Cmd {
|
pub enum Cmd {
|
||||||
Address(address::Args),
|
Address(address::Args),
|
||||||
|
Policy(policy::Args),
|
||||||
Apply(apply::Args),
|
Apply(apply::Args),
|
||||||
Convert(convert::Args),
|
Convert(convert::Args),
|
||||||
}
|
}
|
||||||
|
@ -15,6 +17,7 @@ pub enum Cmd {
|
||||||
pub fn exec(cmd: Cmd) -> miette::Result<()> {
|
pub fn exec(cmd: Cmd) -> miette::Result<()> {
|
||||||
match cmd {
|
match cmd {
|
||||||
Cmd::Address(args) => address::exec(args),
|
Cmd::Address(args) => address::exec(args),
|
||||||
|
Cmd::Policy(args) => policy::exec(args),
|
||||||
Cmd::Apply(args) => apply::exec(args),
|
Cmd::Apply(args) => apply::exec(args),
|
||||||
Cmd::Convert(args) => convert::exec(args),
|
Cmd::Convert(args) => convert::exec(args),
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
use crate::with_project;
|
||||||
|
use aiken_lang::ast::Tracing;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
/// Compute a validator's address.
|
||||||
|
#[derive(clap::Args)]
|
||||||
|
pub struct Args {
|
||||||
|
/// Path to project
|
||||||
|
directory: Option<PathBuf>,
|
||||||
|
|
||||||
|
/// Name of the validator's module within the project. Optional if there's only one validator
|
||||||
|
#[clap(short, long)]
|
||||||
|
module: Option<String>,
|
||||||
|
|
||||||
|
/// Name of the validator within the module. Optional if there's only one validator
|
||||||
|
#[clap(short, long)]
|
||||||
|
validator: Option<String>,
|
||||||
|
|
||||||
|
/// Force the project to be rebuilt, otherwise relies on existing artifacts (i.e. plutus.json)
|
||||||
|
#[clap(long)]
|
||||||
|
rebuild: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn exec(
|
||||||
|
Args {
|
||||||
|
directory,
|
||||||
|
module,
|
||||||
|
validator,
|
||||||
|
rebuild,
|
||||||
|
}: Args,
|
||||||
|
) -> miette::Result<()> {
|
||||||
|
with_project(directory, |p| {
|
||||||
|
if rebuild {
|
||||||
|
p.build(false, Tracing::NoTraces)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let title = module.as_ref().map(|m| {
|
||||||
|
format!(
|
||||||
|
"{m}{}",
|
||||||
|
validator
|
||||||
|
.as_ref()
|
||||||
|
.map(|v| format!(".{v}"))
|
||||||
|
.unwrap_or_default()
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
let title = title.as_ref().or(validator.as_ref());
|
||||||
|
|
||||||
|
let policy = p.policy(title)?;
|
||||||
|
|
||||||
|
println!("{}", policy);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in New Issue