Compare commits

..

10 Commits

Author SHA1 Message Date
waalge c03d12b98c initial thoughts 2024-02-06 11:12:44 +00:00
microproofs 982eff449e chore: Release 2024-01-31 13:48:20 -05:00
rvcas b46206bfe2
chore: update changelog 2024-01-31 13:47:07 -05:00
microproofs bcc2a0fd12 update changelog 2024-01-31 13:44:11 -05:00
microproofs 258c224e21 update changelog 2024-01-31 13:42:46 -05:00
microproofs d8cdeba6fd chore: lastest acceptance test lock and plutus.json files 2024-01-31 00:07:43 -05:00
microproofs 551941392e fix: assert had one minor edge case due to final clauses with lists 2024-01-31 00:05:09 -05:00
microproofs 444bccf19c fix: change list_access_to_uplc to properly handle list discards 2024-01-30 23:53:33 -05:00
microproofs a83220c8d9 fix: module_name was being overrided by the moduleselect field 2024-01-30 23:52:50 -05:00
rvcas 3a534271e7
chore: update changelog 2024-01-30 12:35:50 -05:00
50 changed files with 635 additions and 189 deletions

View File

@ -1,5 +1,18 @@
# Changelog
## v1.0.24-alpha - 2024-01-31
### Added
- **aiken**: New aliases for `check` (aiken c) and `build` (aiken b) commands. @Kuly14
### Fixed
- **aiken-lang**: Fixed an issue with expects on lists that used discards. This fixes
the validator issues being seen for previously succeeding validators on 1.0.21-alpha. @MicroProofs
- **aiken-lang**: Out of Span issue is now solved. This also fixes incorrectly selected
traces from the wrong module, which in some cases lead to the out of span issue. @MicroProofs
## v1.0.23-alpha - 2024-01-24
### Fixed
@ -18,7 +31,6 @@
compact & verbose. @MicroProofs @KtorZ
- **aiken**: New `--filter-traces` option for the `check` and `build` commands
to enable restricting traces with more granularity between user-defined
traces, compiler-generated traces or both. @MicroProofs @KtorZ.
- **aiken-lang**: Most builtin errors are now caught and instead catched trace
errors are thrown. The exception is BLS primitives.
@ -45,11 +57,12 @@
`--no-traces` (on the `check` command) have been removed; superseded by the
new options. @MicroProofs @KtorZ
> ![TIP]
> - If you've been using `aiken check --no-traces`, you can recover the old
> behavior by doing `aiken check --trace-level silent`.
> - If you've been using `aiken build --keep-traces`, you can recover the old
> behavior by doing `aiken build --trace-level verbose`.
> [!TIP]
>
> - If you've been using `aiken check --no-traces`, you can recover the old
> behavior by doing `aiken check --trace-level silent`.
> - If you've been using `aiken build --keep-traces`, you can recover the old
> behavior by doing `aiken build --trace-level verbose`.
## v1.0.21-alpha - 2023-12-04

10
Cargo.lock generated vendored
View File

@ -51,7 +51,7 @@ dependencies = [
[[package]]
name = "aiken"
version = "1.0.23-alpha"
version = "1.0.24-alpha"
dependencies = [
"aiken-lang",
"aiken-lsp",
@ -75,7 +75,7 @@ dependencies = [
[[package]]
name = "aiken-lang"
version = "1.0.23-alpha"
version = "1.0.24-alpha"
dependencies = [
"blst",
"chumsky",
@ -98,7 +98,7 @@ dependencies = [
[[package]]
name = "aiken-lsp"
version = "1.0.23-alpha"
version = "1.0.24-alpha"
dependencies = [
"aiken-lang",
"aiken-project",
@ -119,7 +119,7 @@ dependencies = [
[[package]]
name = "aiken-project"
version = "1.0.23-alpha"
version = "1.0.24-alpha"
dependencies = [
"aiken-lang",
"askama",
@ -3441,7 +3441,7 @@ checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
[[package]]
name = "uplc"
version = "1.0.23-alpha"
version = "1.0.24-alpha"
dependencies = [
"blst",
"cryptoxide",

View File

@ -1,7 +1,7 @@
[package]
name = "aiken-lang"
description = "The Aiken compiler"
version = "1.0.23-alpha"
version = "1.0.24-alpha"
edition = "2021"
repository = "https://github.com/aiken-lang/aiken"
homepage = "https://github.com/aiken-lang/aiken"
@ -24,7 +24,7 @@ owo-colors = { version = "3.5.0", features = ["supports-colors"] }
strum = "0.24.1"
thiserror = "1.0.39"
vec1 = "1.10.1"
uplc = { path = '../uplc', version = "1.0.23-alpha" }
uplc = { path = '../uplc', version = "1.0.24-alpha" }
num-bigint = "0.4.3"
petgraph = "0.6.3"
blst = "0.3.11"

View File

@ -236,7 +236,7 @@ impl<'a> CodeGenerator<'a> {
program
}
fn build(&mut self, body: &TypedExpr, module_name: &String) -> AirTree {
fn build(&mut self, body: &TypedExpr, module_build_name: &String) -> AirTree {
match body {
TypedExpr::UInt { value, .. } => AirTree::int(value),
TypedExpr::String { value, .. } => AirTree::string(value),
@ -251,11 +251,11 @@ impl<'a> CodeGenerator<'a> {
let mut last_exp = self.build(
&expressions.pop().unwrap_or_else(|| unreachable!()),
module_name,
module_build_name,
);
while let Some(expression) = expressions.pop() {
let exp_tree = self.build(&expression, module_name);
let exp_tree = self.build(&expression, module_build_name);
last_exp = exp_tree.hoist_over(last_exp);
}
@ -273,7 +273,7 @@ impl<'a> CodeGenerator<'a> {
args.iter()
.map(|arg| arg.arg_name.get_variable_name().unwrap_or("_").to_string())
.collect_vec(),
self.build(body, module_name),
self.build(body, module_build_name),
),
TypedExpr::List {
@ -284,10 +284,11 @@ impl<'a> CodeGenerator<'a> {
} => AirTree::list(
elements
.iter()
.map(|elem| self.build(elem, module_name))
.map(|elem| self.build(elem, module_build_name))
.collect_vec(),
tipo.clone(),
tail.as_ref().map(|tail| self.build(tail, module_name)),
tail.as_ref()
.map(|tail| self.build(tail, module_build_name)),
),
TypedExpr::Call {
@ -330,11 +331,11 @@ impl<'a> CodeGenerator<'a> {
.map(|(arg, tipo)| {
if tipo.is_data() {
AirTree::cast_to_data(
self.build(&arg.value, module_name),
self.build(&arg.value, module_build_name),
arg.value.tipo(),
)
} else {
self.build(&arg.value, module_name)
self.build(&arg.value, module_build_name)
}
})
.collect_vec();
@ -361,7 +362,7 @@ impl<'a> CodeGenerator<'a> {
.iter()
.zip(fun_arg_types)
.map(|(arg, arg_tipo)| {
let mut arg_val = self.build(&arg.value, module_name);
let mut arg_val = self.build(&arg.value, module_build_name);
if arg_tipo.is_data() && !arg.value.tipo().is_data() {
arg_val = AirTree::cast_to_data(arg_val, arg.value.tipo())
@ -374,7 +375,7 @@ impl<'a> CodeGenerator<'a> {
AirTree::builtin(*func, tipo.clone(), func_args)
} else {
AirTree::call(
self.build(fun.as_ref(), module_name),
self.build(fun.as_ref(), module_build_name),
tipo.clone(),
func_args,
)
@ -404,7 +405,7 @@ impl<'a> CodeGenerator<'a> {
.iter()
.zip(fun_arg_types)
.map(|(arg, arg_tipo)| {
let mut arg_val = self.build(&arg.value, module_name);
let mut arg_val = self.build(&arg.value, module_build_name);
if arg_tipo.is_data() && !arg.value.tipo().is_data() {
arg_val = AirTree::cast_to_data(arg_val, arg.value.tipo())
@ -417,7 +418,7 @@ impl<'a> CodeGenerator<'a> {
AirTree::builtin(*func, tipo.clone(), func_args)
} else {
AirTree::call(
self.build(fun.as_ref(), module_name),
self.build(fun.as_ref(), module_build_name),
tipo.clone(),
func_args,
)
@ -435,7 +436,7 @@ impl<'a> CodeGenerator<'a> {
.iter()
.zip(fun_arg_types)
.map(|(arg, arg_tipo)| {
let mut arg_val = self.build(&arg.value, module_name);
let mut arg_val = self.build(&arg.value, module_build_name);
if arg_tipo.is_data() && !arg.value.tipo().is_data() {
arg_val = AirTree::cast_to_data(arg_val, arg.value.tipo())
@ -445,7 +446,7 @@ impl<'a> CodeGenerator<'a> {
.collect_vec();
AirTree::call(
self.build(fun.as_ref(), module_name),
self.build(fun.as_ref(), module_build_name),
tipo.clone(),
func_args,
)
@ -460,8 +461,8 @@ impl<'a> CodeGenerator<'a> {
} => AirTree::binop(
*name,
tipo.clone(),
self.build(left, module_name),
self.build(right, module_name),
self.build(left, module_build_name),
self.build(right, module_build_name),
left.tipo(),
),
@ -475,7 +476,7 @@ impl<'a> CodeGenerator<'a> {
} => {
let replaced_type = convert_opaque_type(tipo, &self.data_types);
let air_value = self.build(value, module_name);
let air_value = self.build(value, module_build_name);
let msg_func = match self.tracing {
TraceLevel::Silent => None,
@ -484,14 +485,16 @@ impl<'a> CodeGenerator<'a> {
let msg = match self.tracing {
TraceLevel::Silent => unreachable!("excluded from pattern guards"),
TraceLevel::Compact => get_line_columns_by_span(
module_name,
module_build_name,
location,
&self.module_src,
)
.to_string(),
TraceLevel::Verbose => {
get_src_code_by_span(module_name, location, &self.module_src)
}
TraceLevel::Verbose => get_src_code_by_span(
module_build_name,
location,
&self.module_src,
),
};
let msg_func_name = msg.split_whitespace().join("");
@ -526,9 +529,9 @@ impl<'a> CodeGenerator<'a> {
TypedExpr::Trace {
tipo, then, text, ..
} => AirTree::trace(
self.build(text, module_name),
self.build(text, module_build_name),
tipo.clone(),
self.build(then, module_name),
self.build(then, module_build_name),
),
TypedExpr::When {
@ -544,11 +547,11 @@ impl<'a> CodeGenerator<'a> {
} else if clauses.len() == 1 {
let last_clause = clauses.pop().unwrap();
let clause_then = self.build(&last_clause.then, module_name);
let clause_then = self.build(&last_clause.then, module_build_name);
let subject_type = subject.tipo();
let subject_val = self.build(subject, module_name);
let subject_val = self.build(subject, module_build_name);
let assignment = self.assignment(
&last_clause.pattern,
@ -594,11 +597,13 @@ impl<'a> CodeGenerator<'a> {
constr_var.clone(),
subject_name.clone(),
),
module_name,
module_build_name,
);
let constr_assign =
AirTree::let_assignment(&constr_var, self.build(subject, module_name));
let constr_assign = AirTree::let_assignment(
&constr_var,
self.build(subject, module_build_name),
);
let when_assign = AirTree::when(
subject_name,
@ -622,13 +627,13 @@ impl<'a> CodeGenerator<'a> {
.iter()
.map(|branch| {
(
self.build(&branch.condition, module_name),
self.build(&branch.body, module_name),
self.build(&branch.condition, module_build_name),
self.build(&branch.body, module_build_name),
)
})
.collect_vec(),
tipo.clone(),
self.build(final_else, module_name),
self.build(final_else, module_build_name),
),
TypedExpr::RecordAccess {
@ -638,7 +643,7 @@ impl<'a> CodeGenerator<'a> {
..
} => {
if check_replaceable_opaque_type(&record.tipo(), &self.data_types) {
self.build(record, module_name)
self.build(record, module_build_name)
} else {
let function_name = format!("__access_index_{}", *index);
@ -668,7 +673,7 @@ impl<'a> CodeGenerator<'a> {
self.special_functions
.use_function_tree(CONSTR_FIELDS_EXPOSER.to_string()),
list(data()),
vec![self.build(record, module_name)],
vec![self.build(record, module_build_name)],
);
AirTree::index_access(function_name, tipo.clone(), list_of_fields)
@ -741,7 +746,7 @@ impl<'a> CodeGenerator<'a> {
TypedExpr::Tuple { tipo, elems, .. } => AirTree::tuple(
elems
.iter()
.map(|elem| self.build(elem, module_name))
.map(|elem| self.build(elem, module_build_name))
.collect_vec(),
tipo.clone(),
),
@ -750,7 +755,7 @@ impl<'a> CodeGenerator<'a> {
index, tuple, tipo, ..
} => {
if tuple.tipo().is_2_tuple() {
AirTree::pair_index(*index, tipo.clone(), self.build(tuple, module_name))
AirTree::pair_index(*index, tipo.clone(), self.build(tuple, module_build_name))
} else {
let function_name = format!("__access_index_{}", *index);
@ -779,7 +784,7 @@ impl<'a> CodeGenerator<'a> {
AirTree::index_access(
function_name,
tipo.clone(),
self.build(tuple, module_name),
self.build(tuple, module_build_name),
)
}
}
@ -798,7 +803,7 @@ impl<'a> CodeGenerator<'a> {
.iter()
.sorted_by(|arg1, arg2| arg1.index.cmp(&arg2.index))
{
let arg_val = self.build(&arg.value, module_name);
let arg_val = self.build(&arg.value, module_build_name);
if arg.index > highest_index {
highest_index = arg.index;
@ -812,12 +817,14 @@ impl<'a> CodeGenerator<'a> {
index_types,
highest_index,
tipo.clone(),
self.build(spread, module_name),
self.build(spread, module_build_name),
update_args,
)
}
TypedExpr::UnOp { value, op, .. } => AirTree::unop(*op, self.build(value, module_name)),
TypedExpr::UnOp { value, op, .. } => {
AirTree::unop(*op, self.build(value, module_build_name))
}
TypedExpr::CurvePoint { point, .. } => AirTree::curve(*point.as_ref()),
}
}

View File

@ -1,7 +1,7 @@
use std::{collections::HashMap, ops::Deref, rc::Rc};
use indexmap::{IndexMap, IndexSet};
use itertools::Itertools;
use itertools::{Itertools, Position};
use uplc::{
ast::{Constant as UplcConstant, Name, Term, Type as UplcType},
builder::{CONSTR_FIELDS_EXPOSER, CONSTR_INDEX_EXPOSER},
@ -1530,127 +1530,152 @@ pub fn list_access_to_uplc(
error_term: Term<Name>,
) -> Term<Name> {
let names_len = names_types_ids.len();
// Should never be expect level none on a list without a tail
assert!(!(matches!(expect_level, ExpectLevel::None) && is_list_accessor && !tail_present));
let mut no_tailing_discards = names_types_ids
.iter()
.rev()
.skip_while(|(name, _, _)| name == "_")
.with_position()
.skip_while(|pos| match pos {
// Items are reversed order
Position::Last((name, _, _)) | Position::Middle((name, _, _)) => {
name == "_" && matches!(expect_level, ExpectLevel::None)
}
Position::First((name, _, _)) | Position::Only((name, _, _)) => {
name == "_" && (tail_present || matches!(expect_level, ExpectLevel::None))
}
})
.map(|position| match position {
Position::First(a) | Position::Middle(a) | Position::Last(a) | Position::Only(a) => a,
})
.collect_vec();
// If the the is just discards and check_last_item then we check for empty list
// If is just discards and check_last_item then we check for empty list
if no_tailing_discards.is_empty() {
if !tail_present && matches!(expect_level, ExpectLevel::Full | ExpectLevel::Items) {
if tail_present || matches!(expect_level, ExpectLevel::None) {
return term.lambda("_");
} else {
return Term::var("empty_list")
.delayed_choose_list(term, error_term)
.lambda("empty_list");
} else {
return term.lambda("_");
}
}
// reverse back to original order
no_tailing_discards.reverse();
let no_tailing_len = no_tailing_discards.len();
// If we cut off at least one element then that was tail and possibly some heads
let tail_wasnt_cutoff = tail_present && no_tailing_discards.len() == names_len;
no_tailing_discards.into_iter().enumerate().rev().fold(
term,
|acc, (index, (name, tipo, id))| {
let tail_name = format!("tail_index_{}_{}", index, id);
let tail_name = |id| format!("tail_id_{}", id);
let head_list =
if matches!(tipo.get_uplc_type(), UplcType::Pair(_, _)) && is_list_accessor {
Term::head_list().apply(Term::var(tail_name.to_string()))
} else if matches!(expect_level, ExpectLevel::Full) && error_term != Term::Error {
convert_data_to_type_debug(
Term::head_list().apply(Term::var(tail_name.to_string())),
&tipo.to_owned(),
error_term.clone(),
)
} else {
convert_data_to_type(
Term::head_list().apply(Term::var(tail_name.to_string())),
&tipo.to_owned(),
)
};
let head_item = |name, tipo: &Rc<Type>, tail_name: &str| {
if name == "_" {
Term::unit()
} else if matches!(tipo.get_uplc_type(), UplcType::Pair(_, _)) && is_list_accessor {
Term::head_list().apply(Term::var(tail_name.to_string()))
} else if matches!(expect_level, ExpectLevel::Full) && error_term != Term::Error {
convert_data_to_type_debug(
Term::head_list().apply(Term::var(tail_name.to_string())),
&tipo.to_owned(),
error_term.clone(),
)
} else {
convert_data_to_type(
Term::head_list().apply(Term::var(tail_name.to_string())),
&tipo.to_owned(),
)
}
};
// handle tail case
// name is guaranteed to not be discard at this point
if index == no_tailing_len - 1 && tail_wasnt_cutoff {
// simply lambda for tail name
acc.lambda(name)
} else if index == no_tailing_len - 1 {
// case for no tail
// name is guaranteed to not be discard at this point
// Remember we reverse here so the First or Only is the last item
no_tailing_discards
.into_iter()
.rev()
.with_position()
.fold(term, |acc, position| {
match position {
Position::First((name, _, _)) | Position::Only((name, _, _))
if tail_wasnt_cutoff =>
{
// case for tail as the last item
acc.lambda(name)
}
match expect_level {
ExpectLevel::None => acc.lambda(name).apply(head_list).lambda(tail_name),
ExpectLevel::Full | ExpectLevel::Items => {
if error_term == Term::Error && tail_present {
acc.lambda(name).apply(head_list).lambda(tail_name)
} else if tail_present {
// Custom error instead of trying to do head_list on a possibly empty list.
Term::var(tail_name.to_string())
.delayed_choose_list(
error_term.clone(),
acc.lambda(name).apply(head_list),
)
.lambda(tail_name)
} else if error_term == Term::Error {
// Check head is last item in this list
Term::tail_list()
.apply(Term::var(tail_name.to_string()))
.delayed_choose_list(acc, error_term.clone())
.lambda(name)
.apply(head_list)
.lambda(tail_name)
} else {
// Custom error if list is not empty after this head
Term::var(tail_name.to_string())
.delayed_choose_list(
error_term.clone(),
Term::tail_list()
.apply(Term::var(tail_name.to_string()))
.delayed_choose_list(acc, error_term.clone())
.lambda(name)
.apply(head_list),
)
.lambda(tail_name)
Position::First((name, tipo, id)) | Position::Only((name, tipo, id)) => {
// case for no tail, but last item
let tail_name = tail_name(id);
let head_item = head_item(name, tipo, &tail_name);
match expect_level {
ExpectLevel::None => acc.lambda(name).apply(head_item).lambda(tail_name),
ExpectLevel::Full | ExpectLevel::Items => {
if error_term == Term::Error && tail_present {
// No need to check last item if tail was present
acc.lambda(name).apply(head_item).lambda(tail_name)
} else if tail_present {
// Custom error instead of trying to do head_item on a possibly empty list.
Term::var(tail_name.to_string())
.delayed_choose_list(
error_term.clone(),
acc.lambda(name).apply(head_item),
)
.lambda(tail_name)
} else if error_term == Term::Error {
// Check head is last item in this list
Term::tail_list()
.apply(Term::var(tail_name.to_string()))
.delayed_choose_list(acc, error_term.clone())
.lambda(name)
.apply(head_item)
.lambda(tail_name)
} else {
// Custom error if list is not empty after this head
Term::var(tail_name.to_string())
.delayed_choose_list(
error_term.clone(),
Term::tail_list()
.apply(Term::var(tail_name.to_string()))
.delayed_choose_list(acc, error_term.clone())
.lambda(name)
.apply(head_item),
)
.lambda(tail_name)
}
}
}
}
} else if name == "_" {
if matches!(expect_level, ExpectLevel::None) || error_term == Term::Error {
acc.apply(Term::tail_list().apply(Term::var(tail_name.to_string())))
.lambda(tail_name)
} else {
Term::var(tail_name.to_string())
.delayed_choose_list(
error_term.clone(),
acc.apply(Term::tail_list().apply(Term::var(tail_name.to_string()))),
)
.lambda(tail_name)
}
} else if matches!(expect_level, ExpectLevel::None) || error_term == Term::Error {
acc.apply(Term::tail_list().apply(Term::var(tail_name.to_string())))
.lambda(name)
.apply(head_list)
.lambda(tail_name)
} else {
Term::var(tail_name.to_string())
.delayed_choose_list(
error_term.clone(),
Position::Middle((name, tipo, id)) | Position::Last((name, tipo, id)) => {
// case for every item except the last item
let tail_name = tail_name(id);
let head_item = head_item(name, tipo, &tail_name);
if matches!(expect_level, ExpectLevel::None) || error_term == Term::Error {
acc.apply(Term::tail_list().apply(Term::var(tail_name.to_string())))
.lambda(name)
.apply(head_list),
)
.lambda(tail_name)
.apply(head_item)
.lambda(tail_name)
} else {
// case for a custom error if the list is empty at this point
Term::var(tail_name.to_string())
.delayed_choose_list(
error_term.clone(),
acc.apply(
Term::tail_list().apply(Term::var(tail_name.to_string())),
)
.lambda(name)
.apply(head_item),
)
.lambda(tail_name)
}
}
}
},
)
})
}
pub fn apply_builtin_forces(mut term: Term<Name>, force_count: u32) -> Term<Name> {

View File

@ -3,7 +3,7 @@ use chumsky::prelude::*;
use crate::{
ast,
expr::UntypedExpr,
parser::{error::ParseError, expr, token::Token},
parser::{error::ParseError, expr, token::Token, definition::function::param},
};
pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError> {
@ -13,7 +13,15 @@ pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError
.or_not()
.then_ignore(just(Token::Test))
.then(select! {Token::Name {name} => name})
.then(
param(false)
.separated_by(just(Token::Comma))
.allow_trailing()
.delimited_by(just(Token::LeftParen), just(Token::RightParen))
.map_with_span(|arguments, span| (arguments, span)),
)
.then_ignore(just(Token::LeftParen))
.then_ignore(just(Token::RightParen))
.then(just(Token::Fail).ignored().or_not())
.map_with_span(|name, span| (name, span))

View File

@ -1,6 +1,6 @@
[package]
name = "aiken-lsp"
version = "1.0.23-alpha"
version = "1.0.24-alpha"
edition = "2021"
description = "Cardano smart contract language and toolchain"
repository = "https://github.com/aiken-lang/aiken"
@ -24,5 +24,5 @@ tracing = "0.1.37"
url = "2.3.1"
urlencoding = "2.1.2"
aiken-lang = { path = '../aiken-lang', version = "1.0.23-alpha" }
aiken-project = { path = '../aiken-project', version = "1.0.23-alpha" }
aiken-lang = { path = '../aiken-lang', version = "1.0.24-alpha" }
aiken-project = { path = '../aiken-project', version = "1.0.24-alpha" }

View File

@ -1,7 +1,7 @@
[package]
name = "aiken-project"
description = "Aiken project utilities"
version = "1.0.23-alpha"
version = "1.0.24-alpha"
edition = "2021"
repository = "https://github.com/aiken-lang/aiken/crates/project"
homepage = "https://github.com/aiken-lang/aiken"
@ -41,8 +41,8 @@ toml = "0.7.2"
walkdir.workspace = true
zip = "0.6.4"
aiken-lang = { path = "../aiken-lang", version = "1.0.23-alpha" }
uplc = { path = '../uplc', version = "1.0.23-alpha" }
aiken-lang = { path = "../aiken-lang", version = "1.0.24-alpha" }
uplc = { path = '../uplc', version = "1.0.24-alpha" }
[dev-dependencies]
indoc = "2.0.1"

View File

@ -1,7 +1,7 @@
[package]
name = "aiken"
description = "Cardano smart contract language and toolchain"
version = "1.0.23-alpha"
version = "1.0.24-alpha"
edition = "2021"
repository = "https://github.com/aiken-lang/aiken"
homepage = "https://github.com/aiken-lang/aiken"
@ -30,10 +30,10 @@ regex = "1.7.1"
serde_json = "1.0.94"
thiserror = "1.0.39"
aiken-lang = { path = "../aiken-lang", version = "1.0.23-alpha" }
aiken-lsp = { path = "../aiken-lsp", version = "1.0.23-alpha" }
aiken-project = { path = '../aiken-project', version = "1.0.23-alpha" }
uplc = { path = '../uplc', version = "1.0.23-alpha" }
aiken-lang = { path = "../aiken-lang", version = "1.0.24-alpha" }
aiken-lsp = { path = "../aiken-lsp", version = "1.0.24-alpha" }
aiken-project = { path = '../aiken-project', version = "1.0.24-alpha" }
uplc = { path = '../uplc', version = "1.0.24-alpha" }
clap_complete = "4.3.2"
inquire = "0.6.2"
num-bigint = "0.4.3"

View File

@ -1,7 +1,7 @@
[package]
name = "uplc"
description = "Utilities for working with Untyped Plutus Core"
version = "1.0.23-alpha"
version = "1.0.24-alpha"
edition = "2021"
repository = "https://github.com/aiken-lang/aiken/crates/uplc"
homepage = "https://github.com/aiken-lang/aiken"

View File

@ -13,4 +13,4 @@ requirements = []
source = "github"
[etags]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1705743641, nanos_since_epoch = 8357000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1706676848, nanos_since_epoch = 220859000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]

View File

@ -5,7 +5,7 @@
"plutusVersion": "v2",
"compiler": {
"name": "Aiken",
"version": "v1.0.21-alpha+bf96c3a"
"version": "v1.0.23-alpha+3a53427"
}
},
"validators": [

View File

@ -5,7 +5,7 @@
"plutusVersion": "v2",
"compiler": {
"name": "Aiken",
"version": "v1.0.21-alpha+bf96c3a"
"version": "v1.0.23-alpha+3a53427"
}
},
"validators": [

View File

@ -13,4 +13,4 @@ requirements = []
source = "github"
[etags]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1705743640, nanos_since_epoch = 944875000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1706676846, nanos_since_epoch = 18640000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]

View File

@ -13,4 +13,4 @@ requirements = []
source = "github"
[etags]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1705743642, nanos_since_epoch = 21373000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1706676848, nanos_since_epoch = 314005000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]

View File

@ -13,4 +13,4 @@ requirements = []
source = "github"
[etags]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1705743643, nanos_since_epoch = 126963000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1706676863, nanos_since_epoch = 448060000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]

View File

@ -13,4 +13,4 @@ requirements = []
source = "github"
[etags]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1705743642, nanos_since_epoch = 40391000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1706676848, nanos_since_epoch = 251934000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]

View File

@ -13,4 +13,4 @@ requirements = []
source = "github"
[etags]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1705743643, nanos_since_epoch = 283477000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1706676868, nanos_since_epoch = 575072000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]

View File

@ -13,4 +13,4 @@ requirements = []
source = "github"
[etags]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1705743643, nanos_since_epoch = 186230000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1706676866, nanos_since_epoch = 190875000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]

View File

@ -13,4 +13,4 @@ requirements = []
source = "github"
[etags]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1705743643, nanos_since_epoch = 242458000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1706676867, nanos_since_epoch = 381950000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]

View File

@ -0,0 +1,16 @@
# This file was generated by Aiken
# You typically do not need to edit this file
[[requirements]]
name = "aiken-lang/stdlib"
version = "main"
source = "github"
[[packages]]
name = "aiken-lang/stdlib"
version = "main"
requirements = []
source = "github"
[etags]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1706674613, nanos_since_epoch = 871553000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]

View File

@ -0,0 +1,8 @@
name = "aiken-lang/acceptance_test_070"
version = '0.0.0'
description = ''
[[dependencies]]
name = 'aiken-lang/stdlib'
version = 'main'
source = 'github'

View File

@ -0,0 +1,47 @@
use aiken/list
use aiken/transaction.{InlineDatum, Input, OutputReference, TransactionId}
type OtherInput {
output_reference: OutputReference,
other: Data,
}
type MyDatum<a> {
Constructor1(a)
Constructor2
}
test discard_partitions() {
let all_inputs =
[
OtherInput(OutputReference(TransactionId(#"aabb"), 2), 3),
OtherInput(OutputReference(TransactionId(#"aabbcc"), 3), 3),
]
let own_out_ref = OutputReference(TransactionId(#"aabb"), 2)
expect ([_], other_inputs) =
list.partition(
all_inputs,
fn(input) { input.output_reference == own_out_ref },
)
let inputs: List<Input> =
[]
list.all(
inputs,
fn(input) {
expect dat: MyDatum<Int> =
when input.output.datum is {
InlineDatum(d) -> d
_ -> fail @"Not an inline datum"
}
when dat is {
Constructor1 { .. } -> True
_ -> False
}
},
)
}

View File

@ -13,4 +13,4 @@ requirements = []
source = "github"
[etags]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1705743640, nanos_since_epoch = 944756000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1706676838, nanos_since_epoch = 531311000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]

View File

@ -5,7 +5,7 @@
"plutusVersion": "v2",
"compiler": {
"name": "Aiken",
"version": "v1.0.21-alpha+bf96c3a"
"version": "v1.0.23-alpha+3a53427"
}
},
"validators": [

View File

@ -13,4 +13,4 @@ requirements = []
source = "github"
[etags]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1705743642, nanos_since_epoch = 736511000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1706676857, nanos_since_epoch = 453030000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]

View File

@ -13,4 +13,4 @@ requirements = []
source = "github"
[etags]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1705743642, nanos_since_epoch = 350520000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1706676854, nanos_since_epoch = 654421000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]

View File

@ -13,4 +13,4 @@ requirements = []
source = "github"
[etags]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1705743640, nanos_since_epoch = 940487000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1706676837, nanos_since_epoch = 179902000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]

View File

@ -5,7 +5,7 @@
"plutusVersion": "v2",
"compiler": {
"name": "Aiken",
"version": "v1.0.21-alpha+bf96c3a"
"version": "v1.0.23-alpha+3a53427"
}
},
"validators": [

View File

@ -5,7 +5,7 @@
"plutusVersion": "v2",
"compiler": {
"name": "Aiken",
"version": "v1.0.21-alpha+bf96c3a"
"version": "v1.0.23-alpha+3a53427"
}
},
"validators": [

View File

@ -13,4 +13,4 @@ requirements = []
source = "github"
[etags]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1705743640, nanos_since_epoch = 972182000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1706676839, nanos_since_epoch = 823823000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]

View File

@ -13,4 +13,4 @@ requirements = []
source = "github"
[etags]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1705743640, nanos_since_epoch = 966665000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1706676837, nanos_since_epoch = 181741000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]

View File

@ -13,4 +13,4 @@ requirements = []
source = "github"
[etags]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1705743640, nanos_since_epoch = 968996000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1706676837, nanos_since_epoch = 181596000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]

View File

@ -13,4 +13,4 @@ requirements = []
source = "github"
[etags]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1705743640, nanos_since_epoch = 975570000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1706676838, nanos_since_epoch = 486267000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]

View File

@ -13,4 +13,4 @@ requirements = []
source = "github"
[etags]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1705743642, nanos_since_epoch = 725442000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1706676857, nanos_since_epoch = 437022000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]

View File

@ -5,7 +5,7 @@
"plutusVersion": "v2",
"compiler": {
"name": "Aiken",
"version": "v1.0.21-alpha+bf96c3a"
"version": "v1.0.23-alpha+3a53427"
}
},
"validators": [

View File

@ -13,4 +13,4 @@ requirements = []
source = "github"
[etags]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1705743642, nanos_since_epoch = 191574000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1706676854, nanos_since_epoch = 655166000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]

View File

@ -13,4 +13,4 @@ requirements = []
source = "github"
[etags]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1705743642, nanos_since_epoch = 768373000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1706676858, nanos_since_epoch = 638040000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]

View File

@ -13,4 +13,4 @@ requirements = []
source = "github"
[etags]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1706210606, nanos_since_epoch = 598159000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1706676853, nanos_since_epoch = 345400000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]

View File

@ -0,0 +1,89 @@
{
"preamble": {
"title": "aiken-lang/acceptance_test_089",
"version": "0.0.0",
"plutusVersion": "v2",
"compiler": {
"name": "Aiken",
"version": "v1.0.23-alpha+3a53427"
}
},
"validators": [
{
"title": "test2.simple_oneshot",
"redeemer": {
"title": "_r",
"schema": {
"$ref": "#/definitions/Void"
}
},
"parameters": [
{
"title": "utxo_ref",
"schema": {
"$ref": "#/definitions/aiken~1transaction~1OutputReference"
}
}
],
"compiledCode": "58d40100003232323232323232322225333006323232323232533300c3370e900018058018991919299980799b8748000c0380044c8c94ccc044cdc3a40000022944528180780099801002119baf3004300e00100d163300100323375e6006601a00201844646600200200644a6660280022980103d87a8000132325333013300500213374a90001980b80125eb804cc010010004c060008c0580048c04800458dd61808000980400198070009807001180600098020008a4c26cac4600a6ea80048c00cdd5000ab9a5573aaae7955cfaba05742ae89",
"hash": "dd850cc95e173d7dbb3357a4a021afc350f405a3cc2e85ace58bfe8d"
}
],
"definitions": {
"ByteArray": {
"dataType": "bytes"
},
"Int": {
"dataType": "integer"
},
"Void": {
"title": "Unit",
"description": "The nullary constructor.",
"anyOf": [
{
"dataType": "constructor",
"index": 0,
"fields": []
}
]
},
"aiken/transaction/OutputReference": {
"title": "OutputReference",
"description": "An `OutputReference` is a unique reference to an output on-chain. The `output_index`\n corresponds to the position in the output list of the transaction (identified by its id)\n that produced that output",
"anyOf": [
{
"title": "OutputReference",
"dataType": "constructor",
"index": 0,
"fields": [
{
"title": "transaction_id",
"$ref": "#/definitions/aiken~1transaction~1TransactionId"
},
{
"title": "output_index",
"$ref": "#/definitions/Int"
}
]
}
]
},
"aiken/transaction/TransactionId": {
"title": "TransactionId",
"description": "A unique transaction identifier, as the hash of a transaction body. Note that the transaction id\n isn't a direct hash of the `Transaction` as visible on-chain. Rather, they correspond to hash\n digests of transaction body as they are serialized on the network.",
"anyOf": [
{
"title": "TransactionId",
"dataType": "constructor",
"index": 0,
"fields": [
{
"title": "hash",
"$ref": "#/definitions/ByteArray"
}
]
}
]
}
}
}

View File

@ -5,7 +5,7 @@
"plutusVersion": "v2",
"compiler": {
"name": "Aiken",
"version": "v1.0.21-alpha+bf96c3a"
"version": "v1.0.23-alpha+3a53427"
}
},
"validators": [

View File

@ -13,4 +13,4 @@ requirements = []
source = "github"
[etags]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1705181303, nanos_since_epoch = 777227000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1706677006, nanos_since_epoch = 304401000 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]

View File

@ -5,7 +5,7 @@
"plutusVersion": "v2",
"compiler": {
"name": "Aiken",
"version": "v1.0.21-alpha+0161cf6"
"version": "v1.0.23-alpha+3a53427"
}
},
"validators": [

1
examples/moonrat/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
build

114
examples/moonrat/README.md Normal file
View File

@ -0,0 +1,114 @@
# Moonrat
> Hedgehog's spineless cousin
## Aims
Property based testing for aiken inspired by hedgehog and elm-test.
Aims:
- Default gen and shrinking auto derived for any types
- Support custom gen/shrinking
- Friendly output (progress, sensible feedback such as diffs on large data)
- Reasonably speedy
Non-aims:
- e2e testing.
This is intended for functions rather than testing full txs against validators.
Although it should still be possible, it is not our aim here to make writing and testing txs ergonomic.
## Interface
An aiken file
```aiken
// my_tests.ak
type T0 {
f0 : Int,
...
}
fn gen_t0(seed : Int, complexity : Int) -> T0 {
...
}
fn shrink_t0(x : T0) -> List<T0> {
// TODO : what should the signature of this be?!
...
}
type T1 {
f0 : Int,
...
}
test prop_x (
a0 : T0 via (gen_t0(0), shrink_t0),
a1 : T0 via (gen_t0(1), shrink_t0),
a2 : T0,
a2 : T1,
) {
todo!
}
```
Comments on the sample.
`prop_x` is our test - now supporting arguments.
There is new syntax `via`.
We have a custom generator and shrinker for `T0` which we may or may not use.
In the absence of a specified gen/shrink pair, the default, autoderived one is used.
Run 100 times
```
aiken check -m "my_lib/my_test.{prop_x}"
```
Run 1000 cases with a specified seed and shrink limit
```
aiken check --repeat 1000 --seed 123212123 --shrink-limit 5
```
Reporting:
```sample
Testing ...
my_test
prop_x PASS [100/100]
```
```sample
Testing ...
my_test
prop_x FAIL (after 16 tests and 5 shrinks):
a0 = T0 { f0 : 120201, ... }
a1 = T0 { ... }
...
RHS = True
LHS = False
seed = 123212123
Rerun with
aiken check -m "my_lib/my_test.{prop_x}" --args " [ T0 { }] ... "
```
## Functionality
Aiken compiler finds all tests.
Any tests with args are assumed subject to property based testing.
[Property config](https://hackage.haskell.org/package/hedgehog-1.4/docs/Hedgehog-Internal-Property.html#t:PropertyConfig) is global, rather than local.
The test is compiled as if it were a parametrized validator.
Separate gen and shrink functions are also compiled.
To evaluate the test, the generator(s) are run to generate input for the test.
Then the args are applied, and the code evaluated.
On success this is repeated until `repeat` number of successes.
On failure, the shrinker is employed to seek a simpler failure case.

View File

@ -0,0 +1,16 @@
# This file was generated by Aiken
# You typically do not need to edit this file
[[requirements]]
name = "aiken-lang/stdlib"
version = "main"
source = "github"
[[packages]]
name = "aiken-lang/stdlib"
version = "main"
requirements = []
source = "github"
[etags]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1707160390, nanos_since_epoch = 895305443 }, "cf946239d3dd481ed41f20e56bf24910b5229ea35aa171a708edc2a47fc20a7b"]

View File

@ -0,0 +1,8 @@
name = "aiken-lang/moonrat"
version = "0.0.0"
description = ""
[[dependencies]]
name = 'aiken-lang/stdlib'
version = 'main'
source = 'github'

View File

@ -0,0 +1,4 @@
test test_with_arg(x : Int) {
x - x == 0
}

View File

@ -0,0 +1,89 @@
{
"preamble": {
"title": "aiken-lang/acceptance_test_089",
"version": "0.0.0",
"plutusVersion": "v2",
"compiler": {
"name": "Aiken",
"version": "v1.0.24-alpha+982eff4"
}
},
"validators": [
{
"title": "test2.simple_oneshot",
"redeemer": {
"title": "_r",
"schema": {
"$ref": "#/definitions/Void"
}
},
"parameters": [
{
"title": "utxo_ref",
"schema": {
"$ref": "#/definitions/aiken~1transaction~1OutputReference"
}
}
],
"compiledCode": "58d40100003232323232323232322225333006323232323232533300c3370e900018058018991919299980799b8748000c0380044c8c94ccc044cdc3a40000022944528180780099801002119baf3004300e00100d163300100323375e6006601a00201844646600200200644a6660280022980103d87a8000132325333013300500213374a90001980b80125eb804cc010010004c060008c0580048c04800458dd61808000980400198070009807001180600098020008a4c26cac4600a6ea80048c00cdd5000ab9a5573aaae7955cfaba05742ae89",
"hash": "dd850cc95e173d7dbb3357a4a021afc350f405a3cc2e85ace58bfe8d"
}
],
"definitions": {
"ByteArray": {
"dataType": "bytes"
},
"Int": {
"dataType": "integer"
},
"Void": {
"title": "Unit",
"description": "The nullary constructor.",
"anyOf": [
{
"dataType": "constructor",
"index": 0,
"fields": []
}
]
},
"aiken/transaction/OutputReference": {
"title": "OutputReference",
"description": "An `OutputReference` is a unique reference to an output on-chain. The `output_index`\n corresponds to the position in the output list of the transaction (identified by its id)\n that produced that output",
"anyOf": [
{
"title": "OutputReference",
"dataType": "constructor",
"index": 0,
"fields": [
{
"title": "transaction_id",
"$ref": "#/definitions/aiken~1transaction~1TransactionId"
},
{
"title": "output_index",
"$ref": "#/definitions/Int"
}
]
}
]
},
"aiken/transaction/TransactionId": {
"title": "TransactionId",
"description": "A unique transaction identifier, as the hash of a transaction body. Note that the transaction id\n isn't a direct hash of the `Transaction` as visible on-chain. Rather, they correspond to hash\n digests of transaction body as they are serialized on the network.",
"anyOf": [
{
"title": "TransactionId",
"dataType": "constructor",
"index": 0,
"fields": [
{
"title": "hash",
"$ref": "#/definitions/ByteArray"
}
]
}
]
}
}
}

View File

@ -79,8 +79,9 @@
cargo-insta
(pkgs.rust-bin.stable.latest.default.override {
extensions = [ "rust-src" "clippy" "rustfmt" ];
extensions = [ "rust-src" "clippy" "rustfmt" "rust-analyzer" ];
})
] ++ osxDependencies;