@@ -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(),
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
Reference in New Issue
Block a user