Fix validator selection for apply, address and policy command
Before this commit, we would require those target a specific handler, whereas they are in fact global to the entire validator. So now, we recover the behaviour from before where we default to the only available validator when there's no ambiguity. Note that this also solves the need for repeatedly applying parameters to each handler of a parameterized validator. The command now rightfully apply parameters to each corresponding handler.
This commit is contained in:
parent
a51f7285c1
commit
5960065a03
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
- **aiken**: Fix validator selection for `apply`, `address` and `policy` commands. Parameters are also now correctly applied to all handlers of a given validator, instead of needing to be manually targetted one-by-one. @KtorZ
|
||||||
- **aiken**: Add more flexibility around the management of Plutus blueprint files for `build`, `address`, `policy` and `apply` commands. See [#1055](https://github.com/aiken-lang/aiken/issues/1055). @KtorZ
|
- **aiken**: Add more flexibility around the management of Plutus blueprint files for `build`, `address`, `policy` and `apply` commands. See [#1055](https://github.com/aiken-lang/aiken/issues/1055). @KtorZ
|
||||||
- **aiken**: Rename `--filter_traces` to `--trace_filter` for more consistency with `--trace_level`. An alias for `--filter_traces` still exists for backward compatibility. @KtorZ
|
- **aiken**: Rename `--filter_traces` to `--trace_filter` for more consistency with `--trace_level`. An alias for `--filter_traces` still exists for backward compatibility. @KtorZ
|
||||||
- **aiken-project**: Fix `aiken docs` wrongly formatting list constants as tuples. See [#1048](https://github.com/aiken-lang/aiken/issues/1048). @KtorZ
|
- **aiken-project**: Fix `aiken docs` wrongly formatting list constants as tuples. See [#1048](https://github.com/aiken-lang/aiken/issues/1048). @KtorZ
|
||||||
|
|
|
@ -52,7 +52,7 @@ pub struct Compiler {
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum LookupResult<'a, T> {
|
pub enum LookupResult<'a, T> {
|
||||||
One(&'a T),
|
One(String, &'a T),
|
||||||
Many,
|
Many,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,17 +91,48 @@ impl Blueprint {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Blueprint {
|
impl Blueprint {
|
||||||
pub fn lookup(&self, title: Option<&String>) -> Option<LookupResult<Validator>> {
|
pub fn lookup(
|
||||||
|
&self,
|
||||||
|
want_module_name: Option<&str>,
|
||||||
|
want_validator_name: Option<&str>,
|
||||||
|
) -> Option<LookupResult<Validator>> {
|
||||||
let mut validator = None;
|
let mut validator = None;
|
||||||
|
|
||||||
for v in self.validators.iter() {
|
for v in self.validators.iter() {
|
||||||
let match_title = Some(&v.title) == title.or(Some(&v.title));
|
let mut split = v.title.split('.');
|
||||||
if match_title {
|
|
||||||
validator = Some(if validator.is_none() {
|
let known_module_name = split
|
||||||
LookupResult::One(v)
|
.next()
|
||||||
} else {
|
.expect("validator's name must have two dot-separated components.");
|
||||||
LookupResult::Many
|
|
||||||
})
|
let known_validator_name = split
|
||||||
|
.next()
|
||||||
|
.expect("validator's name must have two dot-separated components.");
|
||||||
|
|
||||||
|
let is_target = match (want_module_name, want_validator_name) {
|
||||||
|
(None, None) => true,
|
||||||
|
(Some(want_module_name), None) => want_module_name == known_module_name,
|
||||||
|
(None, Some(want_validator_name)) => want_validator_name == known_validator_name,
|
||||||
|
(Some(want_module_name), Some(want_validator_name)) => {
|
||||||
|
want_module_name == known_module_name
|
||||||
|
&& want_validator_name == known_validator_name
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let title = format!("{known_module_name}.{known_validator_name}");
|
||||||
|
|
||||||
|
if is_target {
|
||||||
|
match validator {
|
||||||
|
Some(LookupResult::Many) => (),
|
||||||
|
None => {
|
||||||
|
validator = Some(LookupResult::One(title, v));
|
||||||
|
}
|
||||||
|
Some(LookupResult::One(ref known_title, _)) => {
|
||||||
|
if title.as_str() != known_title {
|
||||||
|
validator = Some(LookupResult::Many)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,16 +141,17 @@ impl Blueprint {
|
||||||
|
|
||||||
pub fn with_validator<F, A, E>(
|
pub fn with_validator<F, A, E>(
|
||||||
&self,
|
&self,
|
||||||
title: Option<&String>,
|
module_name: Option<&str>,
|
||||||
|
validator_name: Option<&str>,
|
||||||
when_too_many: fn(Vec<String>) -> E,
|
when_too_many: fn(Vec<String>) -> E,
|
||||||
when_missing: fn(Vec<String>) -> E,
|
when_missing: fn(Vec<String>) -> E,
|
||||||
action: F,
|
action: F,
|
||||||
) -> Result<A, E>
|
) -> Result<A, E>
|
||||||
where
|
where
|
||||||
F: Fn(Validator) -> Result<A, E>,
|
F: Fn(&Validator) -> Result<A, E>,
|
||||||
{
|
{
|
||||||
match self.lookup(title) {
|
match self.lookup(module_name, validator_name) {
|
||||||
Some(LookupResult::One(validator)) => action(validator.to_owned()),
|
Some(LookupResult::One(_, validator)) => action(validator),
|
||||||
Some(LookupResult::Many) => Err(when_too_many(
|
Some(LookupResult::Many) => Err(when_too_many(
|
||||||
self.validators.iter().map(|v| v.title.clone()).collect(),
|
self.validators.iter().map(|v| v.title.clone()).collect(),
|
||||||
)),
|
)),
|
||||||
|
|
|
@ -448,8 +448,9 @@ where
|
||||||
|
|
||||||
pub fn address(
|
pub fn address(
|
||||||
&self,
|
&self,
|
||||||
title: Option<&String>,
|
module_name: Option<&str>,
|
||||||
stake_address: Option<&String>,
|
validator_name: Option<&str>,
|
||||||
|
stake_address: Option<&str>,
|
||||||
blueprint_path: &Path,
|
blueprint_path: &Path,
|
||||||
mainnet: bool,
|
mainnet: bool,
|
||||||
) -> Result<ShelleyAddress, Error> {
|
) -> Result<ShelleyAddress, Error> {
|
||||||
|
@ -481,35 +482,39 @@ where
|
||||||
|known_validators| Error::MoreThanOneValidatorFound { known_validators };
|
|known_validators| Error::MoreThanOneValidatorFound { known_validators };
|
||||||
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(
|
||||||
// Make sure we're not calculating the address for a minting validator
|
module_name,
|
||||||
if let Some(title) = title {
|
validator_name,
|
||||||
if !title.ends_with("else") && !title.ends_with("spend") {
|
when_too_many,
|
||||||
return Err(blueprint::error::Error::UnexpectedMintingValidator.into());
|
when_missing,
|
||||||
}
|
|validator| {
|
||||||
}
|
let n = validator.parameters.len();
|
||||||
|
|
||||||
let n = validator.parameters.len();
|
if n > 0 {
|
||||||
|
Err(blueprint::error::Error::ParameterizedValidator { n }.into())
|
||||||
if n > 0 {
|
|
||||||
Err(blueprint::error::Error::ParameterizedValidator { n }.into())
|
|
||||||
} else {
|
|
||||||
let network = if mainnet {
|
|
||||||
Network::Mainnet
|
|
||||||
} else {
|
} else {
|
||||||
Network::Testnet
|
let network = if mainnet {
|
||||||
};
|
Network::Mainnet
|
||||||
|
} else {
|
||||||
|
Network::Testnet
|
||||||
|
};
|
||||||
|
|
||||||
Ok(validator.program.inner().address(
|
Ok(validator.program.inner().address(
|
||||||
network,
|
network,
|
||||||
delegation_part.to_owned(),
|
delegation_part.to_owned(),
|
||||||
&self.config.plutus.into(),
|
&self.config.plutus.into(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn policy(&self, title: Option<&String>, blueprint_path: &Path) -> Result<PolicyId, Error> {
|
pub fn policy(
|
||||||
|
&self,
|
||||||
|
module_name: Option<&str>,
|
||||||
|
validator_name: Option<&str>,
|
||||||
|
blueprint_path: &Path,
|
||||||
|
) -> Result<PolicyId, Error> {
|
||||||
// Read blueprint
|
// Read blueprint
|
||||||
let blueprint = File::open(blueprint_path)
|
let blueprint = File::open(blueprint_path)
|
||||||
.map_err(|_| blueprint::error::Error::InvalidOrMissingFile)?;
|
.map_err(|_| blueprint::error::Error::InvalidOrMissingFile)?;
|
||||||
|
@ -520,19 +525,20 @@ where
|
||||||
|known_validators| Error::MoreThanOneValidatorFound { known_validators };
|
|known_validators| Error::MoreThanOneValidatorFound { known_validators };
|
||||||
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(
|
||||||
// Make sure we're not calculating the policy for a spending validator
|
module_name,
|
||||||
if validator.datum.is_some() {
|
validator_name,
|
||||||
return Err(blueprint::error::Error::UnexpectedSpendingValidator.into());
|
when_too_many,
|
||||||
}
|
when_missing,
|
||||||
|
|validator| {
|
||||||
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())
|
||||||
} else {
|
} else {
|
||||||
Ok(validator.program.compiled_code_and_hash().1)
|
Ok(validator.program.compiled_code_and_hash().1)
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn export(&self, module: &str, name: &str, tracing: Tracing) -> Result<Export, Error> {
|
pub fn export(&self, module: &str, name: &str, tracing: Tracing) -> Result<Export, Error> {
|
||||||
|
@ -571,7 +577,8 @@ where
|
||||||
|
|
||||||
pub fn construct_parameter_incrementally<F>(
|
pub fn construct_parameter_incrementally<F>(
|
||||||
&self,
|
&self,
|
||||||
title: Option<&String>,
|
module_name: Option<&str>,
|
||||||
|
validator_name: Option<&str>,
|
||||||
blueprint_path: &Path,
|
blueprint_path: &Path,
|
||||||
ask: F,
|
ask: F,
|
||||||
) -> Result<PlutusData, Error>
|
) -> Result<PlutusData, Error>
|
||||||
|
@ -591,18 +598,25 @@ where
|
||||||
|known_validators| Error::MoreThanOneValidatorFound { known_validators };
|
|known_validators| Error::MoreThanOneValidatorFound { known_validators };
|
||||||
let when_missing = |known_validators| Error::NoValidatorNotFound { known_validators };
|
let when_missing = |known_validators| Error::NoValidatorNotFound { known_validators };
|
||||||
|
|
||||||
let data = blueprint.with_validator(title, when_too_many, when_missing, |validator| {
|
let data = blueprint.with_validator(
|
||||||
validator
|
module_name,
|
||||||
.ask_next_parameter(&blueprint.definitions, &ask)
|
validator_name,
|
||||||
.map_err(|e| e.into())
|
when_too_many,
|
||||||
})?;
|
when_missing,
|
||||||
|
|validator| {
|
||||||
|
validator
|
||||||
|
.ask_next_parameter(&blueprint.definitions, &ask)
|
||||||
|
.map_err(|e| e.into())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
Ok(data)
|
Ok(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_parameter(
|
pub fn apply_parameter(
|
||||||
&self,
|
&self,
|
||||||
title: Option<&String>,
|
module_name: Option<&str>,
|
||||||
|
validator_name: Option<&str>,
|
||||||
blueprint_path: &Path,
|
blueprint_path: &Path,
|
||||||
param: &PlutusData,
|
param: &PlutusData,
|
||||||
) -> Result<Blueprint, Error> {
|
) -> Result<Blueprint, Error> {
|
||||||
|
@ -616,21 +630,28 @@ where
|
||||||
|known_validators| Error::MoreThanOneValidatorFound { known_validators };
|
|known_validators| Error::MoreThanOneValidatorFound { known_validators };
|
||||||
let when_missing = |known_validators| Error::NoValidatorNotFound { known_validators };
|
let when_missing = |known_validators| Error::NoValidatorNotFound { known_validators };
|
||||||
|
|
||||||
let applied_validator =
|
let applied_validator = blueprint.with_validator(
|
||||||
blueprint.with_validator(title, when_too_many, when_missing, |validator| {
|
module_name,
|
||||||
|
validator_name,
|
||||||
|
when_too_many,
|
||||||
|
when_missing,
|
||||||
|
|validator| {
|
||||||
validator
|
validator
|
||||||
|
.clone()
|
||||||
.apply(&blueprint.definitions, param)
|
.apply(&blueprint.definitions, param)
|
||||||
.map_err(|e| e.into())
|
.map_err(|e| e.into())
|
||||||
})?;
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let prefix = |v: &str| v.split('.').take(2).collect::<Vec<&str>>().join(".");
|
||||||
|
|
||||||
// Overwrite validator
|
// Overwrite validator
|
||||||
blueprint.validators = blueprint
|
blueprint.validators = blueprint
|
||||||
.validators
|
.validators
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|validator| {
|
.map(|validator| {
|
||||||
let same_title = validator.title == applied_validator.title;
|
if prefix(&applied_validator.title) == prefix(&validator.title) {
|
||||||
if same_title {
|
applied_validator.clone()
|
||||||
applied_validator.to_owned()
|
|
||||||
} else {
|
} else {
|
||||||
validator
|
validator
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,14 +143,16 @@ where
|
||||||
return Err(ExitFailure::into_report());
|
return Err(ExitFailure::into_report());
|
||||||
}
|
}
|
||||||
|
|
||||||
eprintln!(
|
if project.checks_count.unwrap_or_default() + warning_count > 0 {
|
||||||
"{}",
|
eprintln!(
|
||||||
Summary {
|
"{}",
|
||||||
check_count: project.checks_count,
|
Summary {
|
||||||
error_count: 0,
|
check_count: project.checks_count,
|
||||||
warning_count
|
error_count: 0,
|
||||||
}
|
warning_count
|
||||||
);
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if warning_count > 0 && deny {
|
if warning_count > 0 && deny {
|
||||||
|
|
|
@ -47,21 +47,10 @@ pub fn exec(
|
||||||
}: Args,
|
}: Args,
|
||||||
) -> miette::Result<()> {
|
) -> miette::Result<()> {
|
||||||
with_project(directory.as_deref(), false, false, |p| {
|
with_project(directory.as_deref(), false, false, |p| {
|
||||||
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 address = p.address(
|
let address = p.address(
|
||||||
title,
|
module.as_deref(),
|
||||||
delegated_to.as_ref(),
|
validator.as_deref(),
|
||||||
|
delegated_to.as_deref(),
|
||||||
p.blueprint_path(input.as_deref()).as_path(),
|
p.blueprint_path(input.as_deref()).as_path(),
|
||||||
mainnet,
|
mainnet,
|
||||||
)?;
|
)?;
|
||||||
|
|
|
@ -63,18 +63,6 @@ pub fn exec(
|
||||||
}: Args,
|
}: Args,
|
||||||
) -> miette::Result<()> {
|
) -> miette::Result<()> {
|
||||||
with_project(None, false, false, |p| {
|
with_project(None, false, false, |p| {
|
||||||
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());
|
|
||||||
|
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"{} blueprint",
|
"{} blueprint",
|
||||||
" Analyzing"
|
" Analyzing"
|
||||||
|
@ -120,9 +108,12 @@ pub fn exec(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
None => {
|
None => p.construct_parameter_incrementally(
|
||||||
p.construct_parameter_incrementally(title, &blueprint_input_path, ask_schema)?
|
module.as_deref(),
|
||||||
}
|
validator.as_deref(),
|
||||||
|
&blueprint_input_path,
|
||||||
|
ask_schema,
|
||||||
|
)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
eprintln!(
|
eprintln!(
|
||||||
|
@ -136,7 +127,12 @@ pub fn exec(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
let blueprint = p.apply_parameter(title, &blueprint_input_path, &data)?;
|
let blueprint = p.apply_parameter(
|
||||||
|
module.as_deref(),
|
||||||
|
validator.as_deref(),
|
||||||
|
&blueprint_input_path,
|
||||||
|
&data,
|
||||||
|
)?;
|
||||||
|
|
||||||
let json = serde_json::to_string_pretty(&blueprint).unwrap();
|
let json = serde_json::to_string_pretty(&blueprint).unwrap();
|
||||||
|
|
||||||
|
|
|
@ -40,18 +40,6 @@ pub fn exec(
|
||||||
to,
|
to,
|
||||||
}: Args,
|
}: Args,
|
||||||
) -> miette::Result<()> {
|
) -> miette::Result<()> {
|
||||||
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 project_path = if let Some(d) = directory {
|
let project_path = if let Some(d) = directory {
|
||||||
d
|
d
|
||||||
} else {
|
} else {
|
||||||
|
@ -80,8 +68,12 @@ pub fn exec(
|
||||||
|known_validators| ProjectError::MoreThanOneValidatorFound { known_validators };
|
|known_validators| ProjectError::MoreThanOneValidatorFound { known_validators };
|
||||||
let when_missing = |known_validators| ProjectError::NoValidatorNotFound { known_validators };
|
let when_missing = |known_validators| ProjectError::NoValidatorNotFound { known_validators };
|
||||||
|
|
||||||
let result =
|
let result = blueprint.with_validator(
|
||||||
blueprint.with_validator(title, when_too_many, when_missing, |validator| match to {
|
module.as_deref(),
|
||||||
|
validator.as_deref(),
|
||||||
|
when_too_many,
|
||||||
|
when_missing,
|
||||||
|
|validator| match to {
|
||||||
Format::CardanoCli => {
|
Format::CardanoCli => {
|
||||||
let cbor_bytes = validator.program.inner().to_cbor().unwrap();
|
let cbor_bytes = validator.program.inner().to_cbor().unwrap();
|
||||||
|
|
||||||
|
@ -99,7 +91,8 @@ pub fn exec(
|
||||||
"cborHex": cbor_hex
|
"cborHex": cbor_hex
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(value) => {
|
Ok(value) => {
|
||||||
|
|
|
@ -37,20 +37,9 @@ pub fn exec(
|
||||||
}: Args,
|
}: Args,
|
||||||
) -> miette::Result<()> {
|
) -> miette::Result<()> {
|
||||||
with_project(directory.as_deref(), false, false, |p| {
|
with_project(directory.as_deref(), false, false, |p| {
|
||||||
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 address = p.address(
|
let address = p.address(
|
||||||
title,
|
module.as_deref(),
|
||||||
|
validator.as_deref(),
|
||||||
None,
|
None,
|
||||||
p.blueprint_path(input.as_deref()).as_path(),
|
p.blueprint_path(input.as_deref()).as_path(),
|
||||||
false,
|
false,
|
||||||
|
|
|
@ -37,19 +37,11 @@ pub fn exec(
|
||||||
}: Args,
|
}: Args,
|
||||||
) -> miette::Result<()> {
|
) -> miette::Result<()> {
|
||||||
with_project(directory.as_deref(), false, false, |p| {
|
with_project(directory.as_deref(), false, false, |p| {
|
||||||
let title = module.as_ref().map(|m| {
|
let policy = p.policy(
|
||||||
format!(
|
module.as_deref(),
|
||||||
"{m}{}",
|
validator.as_deref(),
|
||||||
validator
|
p.blueprint_path(input.as_deref()).as_path(),
|
||||||
.as_ref()
|
)?;
|
||||||
.map(|v| format!(".{v}"))
|
|
||||||
.unwrap_or_default()
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
let title = title.as_ref().or(validator.as_ref());
|
|
||||||
|
|
||||||
let policy = p.policy(title, p.blueprint_path(input.as_deref()).as_path())?;
|
|
||||||
|
|
||||||
println!("{}", policy);
|
println!("{}", policy);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue