feat: add plutus version to aiken.toml

relates to #907
This commit is contained in:
rvcas
2024-05-21 17:01:09 -04:00
parent 4ca73c4cdf
commit 3bc3792aa3
14 changed files with 366 additions and 81 deletions

View File

@@ -8,7 +8,7 @@ pub mod validator;
pub use error::Error;
use crate::{
config::{self, Config},
config::{self, Config, PlutusVersion},
module::CheckedModules,
};
use aiken_lang::gen_uplc::CodeGenerator;
@@ -44,13 +44,6 @@ pub struct Preamble {
pub license: Option<String>,
}
#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum PlutusVersion {
V1,
V2,
}
#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Compiler {
@@ -151,7 +144,7 @@ impl From<&Config> for Preamble {
name: "Aiken".to_string(),
version: config::compiler_version(true),
}),
plutus_version: PlutusVersion::V2,
plutus_version: config.plutus_version,
version: config.version.clone(),
license: config.license.clone(),
}

View File

@@ -1,13 +1,18 @@
use std::{fmt::Display, fs, io, path::Path};
use crate::{github::repo::LatestRelease, package_name::PackageName, paths, Error};
use aiken_lang::ast::Span;
use miette::NamedSource;
use serde::{Deserialize, Serialize};
use std::{fmt::Display, fs, io, path::Path};
pub use aiken_lang::plutus_version::PlutusVersion;
#[derive(Deserialize, Serialize, Clone)]
pub struct Config {
pub name: PackageName,
pub version: String,
pub plutus_version: PlutusVersion,
pub license: Option<String>,
#[serde(default)]
pub description: String,
@@ -53,6 +58,7 @@ impl Config {
Config {
name: name.clone(),
version: "0.0.0".to_string(),
plutus_version: PlutusVersion::default(),
license: Some("Apache-2.0".to_string()),
description: format!("Aiken contracts for project '{name}'"),
repository: Some(Repository {

View File

@@ -35,10 +35,11 @@ use aiken_lang::{
DataTypeKey, Definition, FunctionAccessKey, ModuleKind, Tracing, TypedDataType,
TypedFunction,
},
builtins::{self},
builtins,
expr::UntypedExpr,
gen_uplc::CodeGenerator,
line_numbers::LineNumbers,
plutus_version::PlutusVersion,
tipo::{Type, TypeInfo},
IdGenerator,
};
@@ -49,7 +50,7 @@ use options::{CodeGenMode, Options};
use package_name::PackageName;
use pallas::ledger::{
addresses::{Address, Network, ShelleyAddress, ShelleyDelegationPart, StakePayload},
primitives::babbage::{self as cardano, PolicyId},
primitives::conway::{self as cardano, PolicyId},
traverse::ComputeHash,
};
use std::{
@@ -141,6 +142,7 @@ where
pub fn new_generator(&'_ self, tracing: Tracing) -> CodeGenerator<'_> {
CodeGenerator::new(
self.config.plutus_version,
utils::indexmap::as_ref_values(&self.functions),
utils::indexmap::as_ref_values(&self.data_types),
utils::indexmap::as_str_ref_values(&self.module_types),
@@ -422,6 +424,7 @@ where
}
let n = validator.parameters.len();
if n > 0 {
Err(blueprint::error::Error::ParameterizedValidator { n }.into())
} else {
@@ -460,7 +463,13 @@ where
Err(blueprint::error::Error::ParameterizedValidator { n }.into())
} else {
let cbor = validator.program.to_cbor().unwrap();
let validator_hash = cardano::PlutusV2Script(cbor.into()).compute_hash();
let validator_hash = match self.config.plutus_version {
PlutusVersion::V1 => cardano::PlutusV1Script(cbor.into()).compute_hash(),
PlutusVersion::V2 => cardano::PlutusV2Script(cbor.into()).compute_hash(),
PlutusVersion::V3 => cardano::PlutusV3Script(cbor.into()).compute_hash(),
};
Ok(validator_hash)
}
})
@@ -842,11 +851,15 @@ where
let data_types = utils::indexmap::as_ref_values(&self.data_types);
let plutus_version = &self.config.plutus_version;
tests
.into_par_iter()
.map(|test| match test {
Test::UnitTest(unit_test) => unit_test.run(),
Test::PropertyTest(property_test) => property_test.run(seed, property_max_success),
Test::UnitTest(unit_test) => unit_test.run(plutus_version),
Test::PropertyTest(property_test) => {
property_test.run(seed, property_max_success, plutus_version)
}
})
.collect::<Vec<TestResult<(Constant, Rc<Type>), PlutusData>>>()
.into_iter()

View File

@@ -4,6 +4,7 @@ use aiken_lang::{
expr::{TypedExpr, UntypedExpr},
format::Formatter,
gen_uplc::CodeGenerator,
plutus_version::PlutusVersion,
tipo::{convert_opaque_type, Type},
};
use cryptoxide::{blake2b::Blake2b, digest::Digest};
@@ -171,10 +172,10 @@ pub struct UnitTest {
unsafe impl Send for UnitTest {}
impl UnitTest {
pub fn run<T>(self) -> TestResult<(Constant, Rc<Type>), T> {
pub fn run<T>(self, plutus_version: &PlutusVersion) -> TestResult<(Constant, Rc<Type>), T> {
let mut eval_result = Program::<NamedDeBruijn>::try_from(self.program.clone())
.unwrap()
.eval(ExBudget::max());
.eval_version(ExBudget::max(), &plutus_version.into());
let success = !eval_result.failed(self.can_error);
@@ -226,31 +227,40 @@ impl PropertyTest {
/// Run a property test from a given seed. The property is run at most DEFAULT_MAX_SUCCESS times. It
/// may stops earlier on failure; in which case a 'counterexample' is returned.
pub fn run<U>(self, seed: u32, n: usize) -> TestResult<U, PlutusData> {
pub fn run<U>(
self,
seed: u32,
n: usize,
plutus_version: &PlutusVersion,
) -> TestResult<U, PlutusData> {
let mut labels = BTreeMap::new();
let mut remaining = n;
let (traces, counterexample, iterations) =
match self.run_n_times(&mut remaining, Prng::from_seed(seed), &mut labels) {
Ok(None) => (Vec::new(), Ok(None), n),
Ok(Some(counterexample)) => (
self.eval(&counterexample.value)
.logs()
.into_iter()
.filter(|s| PropertyTest::extract_label(s).is_none())
.collect(),
Ok(Some(counterexample.value)),
n - remaining + 1,
),
Err(FuzzerError { traces, uplc_error }) => (
traces
.into_iter()
.filter(|s| PropertyTest::extract_label(s).is_none())
.collect(),
Err(uplc_error),
0,
),
};
let (traces, counterexample, iterations) = match self.run_n_times(
&mut remaining,
Prng::from_seed(seed),
&mut labels,
plutus_version,
) {
Ok(None) => (Vec::new(), Ok(None), n),
Ok(Some(counterexample)) => (
self.eval(&counterexample.value, plutus_version)
.logs()
.into_iter()
.filter(|s| PropertyTest::extract_label(s).is_none())
.collect(),
Ok(Some(counterexample.value)),
n - remaining + 1,
),
Err(FuzzerError { traces, uplc_error }) => (
traces
.into_iter()
.filter(|s| PropertyTest::extract_label(s).is_none())
.collect(),
Err(uplc_error),
0,
),
};
TestResult::PropertyTestResult(PropertyTestResult {
test: self,
@@ -266,28 +276,30 @@ impl PropertyTest {
remaining: &mut usize,
initial_prng: Prng,
labels: &mut BTreeMap<String, usize>,
plutus_version: &'a PlutusVersion,
) -> Result<Option<Counterexample<'a>>, FuzzerError> {
let mut prng = initial_prng;
let mut counterexample = None;
while *remaining > 0 && counterexample.is_none() {
(prng, counterexample) = self.run_once(prng, labels)?;
(prng, counterexample) = self.run_once(prng, labels, plutus_version)?;
*remaining -= 1;
}
Ok(counterexample)
}
fn run_once(
&self,
fn run_once<'a>(
&'a self,
prng: Prng,
labels: &mut BTreeMap<String, usize>,
) -> Result<(Prng, Option<Counterexample<'_>>), FuzzerError> {
plutus_version: &'a PlutusVersion,
) -> Result<(Prng, Option<Counterexample<'a>>), FuzzerError> {
let (next_prng, value) = prng
.sample(&self.fuzzer.program)?
.expect("A seeded PRNG returned 'None' which indicates a fuzzer is ill-formed and implemented wrongly; please contact library's authors.");
let mut result = self.eval(&value);
let mut result = self.eval(&value, plutus_version);
for s in result.logs() {
// NOTE: There may be other log outputs that interefere with labels. So *by
@@ -313,7 +325,7 @@ impl PropertyTest {
Err(..) => Status::Invalid,
Ok(None) => Status::Invalid,
Ok(Some((_, value))) => {
let result = self.eval(&value);
let result = self.eval(&value, plutus_version);
let is_failure = result.failed(self.can_error);
@@ -341,12 +353,12 @@ impl PropertyTest {
}
}
pub fn eval(&self, value: &PlutusData) -> EvalResult {
pub fn eval(&self, value: &PlutusData, plutus_version: &PlutusVersion) -> EvalResult {
let program = self.program.apply_data(value.clone());
Program::<NamedDeBruijn>::try_from(program)
.unwrap()
.eval(ExBudget::max())
.eval_version(ExBudget::max(), &plutus_version.into())
}
fn extract_label(s: &str) -> Option<String> {
@@ -1255,8 +1267,8 @@ mod test {
builtins,
format::Formatter,
line_numbers::LineNumbers,
parser,
parser::extra::ModuleExtra,
parser::{self, extra::ModuleExtra},
plutus_version::PlutusVersion,
IdGenerator,
};
use indoc::indoc;
@@ -1323,6 +1335,7 @@ mod test {
);
let mut generator = CodeGenerator::new(
PlutusVersion::default(),
utils::indexmap::as_ref_values(&functions),
utils::indexmap::as_ref_values(&data_types),
utils::indexmap::as_str_ref_values(&module_types),
@@ -1454,10 +1467,15 @@ mod test {
}
impl PropertyTest {
fn expect_failure(&self) -> Counterexample {
fn expect_failure<'a>(&'a self, plutus_version: &'a PlutusVersion) -> Counterexample<'a> {
let mut labels = BTreeMap::new();
let mut remaining = PropertyTest::DEFAULT_MAX_SUCCESS;
match self.run_n_times(&mut remaining, Prng::from_seed(42), &mut labels) {
match self.run_n_times(
&mut remaining,
Prng::from_seed(42),
&mut labels,
plutus_version,
) {
Ok(Some(counterexample)) => counterexample,
_ => panic!("expected property to fail but it didn't."),
}
@@ -1473,7 +1491,11 @@ mod test {
"#});
assert!(prop
.run::<()>(42, PropertyTest::DEFAULT_MAX_SUCCESS)
.run::<()>(
42,
PropertyTest::DEFAULT_MAX_SUCCESS,
&PlutusVersion::default()
)
.is_success());
}
@@ -1496,7 +1518,11 @@ mod test {
}
"#});
match prop.run::<()>(42, PropertyTest::DEFAULT_MAX_SUCCESS) {
match prop.run::<()>(
42,
PropertyTest::DEFAULT_MAX_SUCCESS,
&PlutusVersion::default(),
) {
TestResult::UnitTestResult(..) => unreachable!("property returned unit-test result ?!"),
TestResult::PropertyTestResult(result) => {
assert!(
@@ -1519,7 +1545,8 @@ mod test {
}
"#});
let mut counterexample = prop.expect_failure();
let plutus_version = PlutusVersion::default();
let mut counterexample = prop.expect_failure(&plutus_version);
counterexample.simplify();
@@ -1546,7 +1573,8 @@ mod test {
}
"#});
let mut counterexample = prop.expect_failure();
let plutus_version = PlutusVersion::default();
let mut counterexample = prop.expect_failure(&plutus_version);
counterexample.simplify();
@@ -1562,7 +1590,8 @@ mod test {
}
"#});
let mut counterexample = prop.expect_failure();
let plutus_version = PlutusVersion::default();
let mut counterexample = prop.expect_failure(&plutus_version);
counterexample.simplify();
@@ -1589,7 +1618,8 @@ mod test {
}
"#});
let mut counterexample = prop.expect_failure();
let plutus_version = PlutusVersion::default();
let mut counterexample = prop.expect_failure(&plutus_version);
counterexample.simplify();
@@ -1616,7 +1646,8 @@ mod test {
}
"#});
let mut counterexample = prop.expect_failure();
let plutus_version = PlutusVersion::default();
let mut counterexample = prop.expect_failure(&plutus_version);
counterexample.simplify();
@@ -1646,7 +1677,8 @@ mod test {
}
"#});
let mut counterexample = prop.expect_failure();
let plutus_version = PlutusVersion::default();
let mut counterexample = prop.expect_failure(&plutus_version);
counterexample.simplify();
@@ -1680,7 +1712,9 @@ mod test {
}
"#});
let mut counterexample = prop.expect_failure();
let plutus_version = PlutusVersion::default();
let mut counterexample = prop.expect_failure(&plutus_version);
counterexample.simplify();
@@ -1714,7 +1748,8 @@ mod test {
}
"#});
let mut counterexample = prop.expect_failure();
let plutus_version = PlutusVersion::default();
let mut counterexample = prop.expect_failure(&plutus_version);
counterexample.simplify();
@@ -1748,7 +1783,8 @@ mod test {
}
"#});
let mut counterexample = prop.expect_failure();
let plutus_version = PlutusVersion::default();
let mut counterexample = prop.expect_failure(&plutus_version);
counterexample.simplify();

View File

@@ -12,6 +12,7 @@ use aiken_lang::{
gen_uplc::CodeGenerator,
line_numbers::LineNumbers,
parser,
plutus_version::PlutusVersion,
tipo::TypeInfo,
IdGenerator,
};
@@ -60,6 +61,7 @@ impl TestProject {
pub fn new_generator(&'_ self, tracing: Tracing) -> CodeGenerator<'_> {
CodeGenerator::new(
PlutusVersion::default(),
utils::indexmap::as_ref_values(&self.functions),
utils::indexmap::as_ref_values(&self.data_types),
utils::indexmap::as_str_ref_values(&self.module_types),