Enforce newline after assignment / clause.
This leads to more consistent formatting across entire Aiken programs. Before that commit, only long expressions would be formatted on a newline, causing non-consistent formatting and additional reading barrier when looking at source code. Programs also now take more vertical space, which is better for more friendly diffing in version control systems (especially git).
This commit is contained in:
parent
bf9297efcf
commit
20f5baffa7
|
@ -17,6 +17,7 @@
|
|||
- **aiken-lang**: update todo warning to include type
|
||||
- **aiken-lang**: `|>` operator can now be formatted as a single (short) line or forced over multiline in a flexible manner
|
||||
- **aiken-lang**: the compiler now provides better feedback for type holes (i.e. `_`) in type annotations
|
||||
- **aiken-lang**: assignment and clause guard are now always formatted on a new line
|
||||
|
||||
## [v0.0.29] - 2023-MM-DD
|
||||
|
||||
|
|
|
@ -285,7 +285,11 @@ impl<'comments> Formatter<'comments> {
|
|||
None => head,
|
||||
Some(t) => head.append(": ").append(self.annotation(t)),
|
||||
};
|
||||
head.append(" = ").append(self.const_expr(value))
|
||||
head.append(" =")
|
||||
.append(line())
|
||||
.append(self.const_expr(value))
|
||||
.nest(INDENT)
|
||||
.group()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -602,16 +606,14 @@ impl<'comments> Formatter<'comments> {
|
|||
&mut self,
|
||||
pattern: &'a UntypedPattern,
|
||||
value: &'a UntypedExpr,
|
||||
then: Option<&'a UntypedExpr>,
|
||||
kind: Option<AssignmentKind>,
|
||||
kind: AssignmentKind,
|
||||
annotation: &'a Option<Annotation>,
|
||||
) -> Document<'a> {
|
||||
self.pop_empty_lines(pattern.location().end);
|
||||
|
||||
let keyword = match kind {
|
||||
Some(AssignmentKind::Let) => "let ",
|
||||
Some(AssignmentKind::Expect) => "expect ",
|
||||
None => "try ",
|
||||
AssignmentKind::Let => "let ",
|
||||
AssignmentKind::Expect => "expect ",
|
||||
};
|
||||
|
||||
let pattern = self.pattern(pattern);
|
||||
|
@ -620,25 +622,11 @@ impl<'comments> Formatter<'comments> {
|
|||
.as_ref()
|
||||
.map(|a| ": ".to_doc().append(self.annotation(a)));
|
||||
|
||||
let doc = if then.is_some() {
|
||||
keyword.to_doc().force_break()
|
||||
} else {
|
||||
keyword.to_doc()
|
||||
}
|
||||
.append(pattern.append(annotation).group())
|
||||
.append(" =")
|
||||
.append(self.assigned_value(value));
|
||||
|
||||
if let Some(then) = then {
|
||||
doc.append(if self.pop_empty_lines(then.start_byte_index()) {
|
||||
lines(2)
|
||||
} else {
|
||||
line()
|
||||
})
|
||||
.append(self.expr(then))
|
||||
} else {
|
||||
doc
|
||||
}
|
||||
keyword
|
||||
.to_doc()
|
||||
.append(pattern.append(annotation).group())
|
||||
.append(" =")
|
||||
.append(self.case_clause_value(value))
|
||||
}
|
||||
|
||||
pub fn bytearray<'a>(
|
||||
|
@ -733,7 +721,7 @@ impl<'comments> Formatter<'comments> {
|
|||
annotation,
|
||||
kind,
|
||||
..
|
||||
} => self.assignment(pattern, value, None, Some(*kind), annotation),
|
||||
} => self.assignment(pattern, value, *kind, annotation),
|
||||
|
||||
UntypedExpr::Trace {
|
||||
kind, text, then, ..
|
||||
|
@ -1448,19 +1436,12 @@ impl<'comments> Formatter<'comments> {
|
|||
.force_break(),
|
||||
|
||||
UntypedExpr::Fn { .. } | UntypedExpr::List { .. } => {
|
||||
" ".to_doc().append(self.expr(expr)).group()
|
||||
line().append(self.expr(expr)).nest(INDENT).group()
|
||||
}
|
||||
|
||||
UntypedExpr::When { .. } => line().append(self.expr(expr)).nest(INDENT).group(),
|
||||
|
||||
_ => break_("", " ").append(self.expr(expr)).nest(INDENT).group(),
|
||||
}
|
||||
}
|
||||
|
||||
fn assigned_value<'a>(&mut self, expr: &'a UntypedExpr) -> Document<'a> {
|
||||
match expr {
|
||||
UntypedExpr::When { .. } => " ".to_doc().append(self.expr(expr)).group(),
|
||||
_ => self.case_clause_value(expr),
|
||||
_ => line().append(self.expr(expr)).nest(INDENT).group(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -90,8 +90,10 @@ fn test_format_when() {
|
|||
let expected = indoc! {r#"
|
||||
pub fn foo(a) {
|
||||
when a is {
|
||||
True -> 14
|
||||
False -> 42
|
||||
True ->
|
||||
14
|
||||
False ->
|
||||
42
|
||||
}
|
||||
}
|
||||
"#};
|
||||
|
@ -134,8 +136,10 @@ fn test_format_nested_when_if() {
|
|||
xs
|
||||
} else {
|
||||
when xs is {
|
||||
[] -> []
|
||||
[_x, ..rest] -> drop(rest, n - 1)
|
||||
[] ->
|
||||
[]
|
||||
[_x, ..rest] ->
|
||||
drop(rest, n - 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -147,8 +151,10 @@ fn test_format_nested_when_if() {
|
|||
xs
|
||||
} else {
|
||||
when xs is {
|
||||
[] -> []
|
||||
[_x, ..rest] -> drop(rest, n - 1)
|
||||
[] ->
|
||||
[]
|
||||
[_x, ..rest] ->
|
||||
drop(rest, n - 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -177,14 +183,18 @@ fn test_format_nested_when() {
|
|||
let expected = indoc! {r#"
|
||||
fn foo() {
|
||||
when a is {
|
||||
None -> "foo"
|
||||
None ->
|
||||
"foo"
|
||||
Some(b) ->
|
||||
when b is {
|
||||
None -> "foo"
|
||||
None ->
|
||||
"foo"
|
||||
Some(c) ->
|
||||
when c is {
|
||||
None -> "foo"
|
||||
Some(_) -> "foo"
|
||||
None ->
|
||||
"foo"
|
||||
Some(_) ->
|
||||
"foo"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -343,8 +353,10 @@ fn test_nested_function_calls() {
|
|||
),
|
||||
),
|
||||
when output.datum is {
|
||||
InlineDatum(_) -> True
|
||||
_ -> error @"expected inline datum"
|
||||
InlineDatum(_) ->
|
||||
True
|
||||
_ ->
|
||||
error @"expected inline datum"
|
||||
},
|
||||
]
|
||||
|> list.and
|
||||
|
@ -393,8 +405,10 @@ fn format_trace_todo_error() {
|
|||
|
||||
fn foo_3() {
|
||||
when x is {
|
||||
Foo -> True
|
||||
_ -> error
|
||||
Foo ->
|
||||
True
|
||||
_ ->
|
||||
error
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -517,18 +531,24 @@ fn test_newline_module_comments() {
|
|||
#[test]
|
||||
fn test_bytearray_literals() {
|
||||
let src = indoc! {r#"
|
||||
const foo_const_array = #[102, 111, 111]
|
||||
const foo_const_array =
|
||||
#[102, 111, 111]
|
||||
|
||||
const foo_const_hex = #"666f6f"
|
||||
const foo_const_hex =
|
||||
#"666f6f"
|
||||
|
||||
const foo_const_utf8 = "foo"
|
||||
const foo_const_utf8 =
|
||||
"foo"
|
||||
|
||||
fn foo() {
|
||||
let foo_const_array = #[102, 111, 111]
|
||||
let foo_const_array =
|
||||
#[102, 111, 111]
|
||||
|
||||
let foo_const_hex = #"666f6f"
|
||||
let foo_const_hex =
|
||||
#"666f6f"
|
||||
|
||||
let foo_const_utf8 = "foo"
|
||||
let foo_const_utf8 =
|
||||
"foo"
|
||||
}
|
||||
"#};
|
||||
|
||||
|
@ -538,10 +558,12 @@ fn test_bytearray_literals() {
|
|||
#[test]
|
||||
fn test_string_literal() {
|
||||
let src = indoc! {r#"
|
||||
const foo_const: String = @"foo"
|
||||
const foo_const: String =
|
||||
@"foo"
|
||||
|
||||
fn foo() {
|
||||
let foo_var: String = @"foo"
|
||||
let foo_var: String =
|
||||
@"foo"
|
||||
}
|
||||
"#};
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
pub fn length(xs: List<a>) -> Int {
|
||||
when xs is {
|
||||
[] -> 0
|
||||
[_, ..rest] -> 1 + length(rest)
|
||||
[] ->
|
||||
0
|
||||
[_, ..rest] ->
|
||||
1 + length(rest)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
pub fn foldr(xs: List<a>, f: fn(a, b) -> b, zero: b) -> b {
|
||||
when xs is {
|
||||
[] -> zero
|
||||
[x, ..rest] -> f(x, foldr(rest, f, zero))
|
||||
[] ->
|
||||
zero
|
||||
[x, ..rest] ->
|
||||
f(x, foldr(rest, f, zero))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
pub fn foldr(xs: List<a>, f: fn(a, b) -> b, zero: b) -> b {
|
||||
when xs is {
|
||||
[] -> zero
|
||||
[x, ..rest] -> f(x, foldr(rest, f, zero))
|
||||
[] ->
|
||||
zero
|
||||
[x, ..rest] ->
|
||||
f(x, foldr(rest, f, zero))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,10 @@ use aiken/builtin.{head_list}
|
|||
|
||||
pub fn head(xs: List<a>) -> Option<a> {
|
||||
when xs is {
|
||||
[] -> None
|
||||
_ -> Some(head_list(xs))
|
||||
[] ->
|
||||
None
|
||||
_ ->
|
||||
Some(head_list(xs))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
pub fn unzip(xs: List<(a, b)>) -> (List<a>, List<b>) {
|
||||
when xs is {
|
||||
[] -> ([], [])
|
||||
[] ->
|
||||
([], [])
|
||||
[(a, b), ..rest] -> {
|
||||
let (a_tail, b_tail) = unzip(rest)
|
||||
let (a_tail, b_tail) =
|
||||
unzip(rest)
|
||||
([a, ..a_tail], [b, ..b_tail])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
pub fn map(opt: Option<a>, f: fn(a) -> b) -> Option<b> {
|
||||
when opt is {
|
||||
None -> None
|
||||
Some(a) -> Some(f(a))
|
||||
None ->
|
||||
None
|
||||
Some(a) ->
|
||||
Some(f(a))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
pub fn map(xs: List<a>, f: fn(a) -> result) -> List<result> {
|
||||
when xs is {
|
||||
[] -> []
|
||||
[x, ..rest] -> [f(x), ..map(rest, f)]
|
||||
[] ->
|
||||
[]
|
||||
[x, ..rest] ->
|
||||
[f(x), ..map(rest, f)]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,8 @@ use aiken/builtin
|
|||
|
||||
pub fn filter(xs: List<a>, f: fn(a) -> Bool) -> List<a> {
|
||||
when xs is {
|
||||
[] -> []
|
||||
[] ->
|
||||
[]
|
||||
[x, ..rest] ->
|
||||
if f(x) {
|
||||
[x, ..filter(rest, f)]
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
pub fn unzip(xs: List<(a, b)>) -> (List<a>, List<b>) {
|
||||
when xs is {
|
||||
[] -> ([], [])
|
||||
[] ->
|
||||
([], [])
|
||||
[(a, b), ..rest] -> {
|
||||
let (a_tail, b_tail) = unzip(rest)
|
||||
let (a_tail, b_tail) =
|
||||
unzip(rest)
|
||||
([a, ..a_tail], [b, ..b_tail])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ pub fn drop(bytes: ByteArray, n: Int) -> ByteArray {
|
|||
}
|
||||
|
||||
test drop_1() {
|
||||
let x = #"01020304050607"
|
||||
let x =
|
||||
#"01020304050607"
|
||||
drop(x, 2) == #"0304050607"
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
pub fn or_else(opt: Option<a>, default: a) -> a {
|
||||
when opt is {
|
||||
None -> default
|
||||
Some(a) -> a
|
||||
None ->
|
||||
default
|
||||
Some(a) ->
|
||||
a
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
pub fn map(opt: Option<a>, f: fn(a) -> result) -> Option<result> {
|
||||
when opt is {
|
||||
None -> None
|
||||
Some(a) -> Some(f(a))
|
||||
None ->
|
||||
None
|
||||
Some(a) ->
|
||||
Some(f(a))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
pub fn map(opt: Option<a>, f: fn(a) -> result) -> Option<result> {
|
||||
when opt is {
|
||||
None -> None
|
||||
Some(a) -> Some(f(a))
|
||||
None ->
|
||||
None
|
||||
Some(a) ->
|
||||
Some(f(a))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
pub fn foldr(xs: List<a>, f: fn(a, b) -> b, zero: b) -> b {
|
||||
when xs is {
|
||||
[] -> zero
|
||||
[x, ..rest] -> f(x, foldr(rest, f, zero))
|
||||
[] ->
|
||||
zero
|
||||
[x, ..rest] ->
|
||||
f(x, foldr(rest, f, zero))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,8 +12,10 @@ pub fn filter_map(xs: List<a>, f: fn(a) -> Option<b>) -> List<b> {
|
|||
xs,
|
||||
fn(x, ys) {
|
||||
when f(x) is {
|
||||
None -> ys
|
||||
Some(y) -> [y, ..ys]
|
||||
None ->
|
||||
ys
|
||||
Some(y) ->
|
||||
[y, ..ys]
|
||||
}
|
||||
},
|
||||
[],
|
||||
|
|
|
@ -20,7 +20,8 @@ pub fn insert(
|
|||
|
||||
fn do_insert(elems: List<(key, value)>, k: key, v: value) -> List<(key, value)> {
|
||||
when elems is {
|
||||
[] -> [(k, v)]
|
||||
[] ->
|
||||
[(k, v)]
|
||||
[(k2, v2), ..rest] ->
|
||||
if k == k2 {
|
||||
[(k, v), ..rest]
|
||||
|
@ -32,8 +33,8 @@ fn do_insert(elems: List<(key, value)>, k: key, v: value) -> List<(key, value)>
|
|||
|
||||
fn fixture_1() {
|
||||
new()
|
||||
|> insert("foo", 42)
|
||||
|> insert("bar", 14)
|
||||
|> insert("foo", 42)
|
||||
|> insert("bar", 14)
|
||||
}
|
||||
|
||||
test to_list_2() {
|
||||
|
|
|
@ -4,11 +4,14 @@ pub fn map2(
|
|||
f: fn(a, b) -> result,
|
||||
) -> Option<result> {
|
||||
when opt_a is {
|
||||
None -> None
|
||||
None ->
|
||||
None
|
||||
Some(a) ->
|
||||
when opt_b is {
|
||||
None -> None
|
||||
Some(b) -> Some(f(a, b))
|
||||
None ->
|
||||
None
|
||||
Some(b) ->
|
||||
Some(f(a, b))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
pub fn foldr(xs: List<a>, f: fn(a, b) -> b, zero: b) -> b {
|
||||
when xs is {
|
||||
[] -> zero
|
||||
[x, ..rest] -> f(x, foldr(rest, f, zero))
|
||||
[] ->
|
||||
zero
|
||||
[x, ..rest] ->
|
||||
f(x, foldr(rest, f, zero))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,8 +13,10 @@ pub fn concat(left: List<a>, right: List<a>) -> List<a> {
|
|||
|
||||
pub fn flat_map(xs: List<a>, f: fn(a) -> List<b>) -> List<b> {
|
||||
when xs is {
|
||||
[] -> []
|
||||
[x, ..rest] -> concat(f(x), flat_map(rest, f))
|
||||
[] ->
|
||||
[]
|
||||
[x, ..rest] ->
|
||||
concat(f(x), flat_map(rest, f))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
pub fn filter(xs: List<a>, f: fn(a) -> Bool) -> List<a> {
|
||||
when xs is {
|
||||
[] -> []
|
||||
[] ->
|
||||
[]
|
||||
[x, ..rest] ->
|
||||
if f(x) {
|
||||
[x, ..filter(rest, f)]
|
||||
|
@ -12,8 +13,10 @@ pub fn filter(xs: List<a>, f: fn(a) -> Bool) -> List<a> {
|
|||
|
||||
pub fn unique(xs: List<a>) -> List<a> {
|
||||
when xs is {
|
||||
[] -> []
|
||||
[x, ..rest] -> [x, ..unique(filter(rest, fn(y) { y != x }))]
|
||||
[] ->
|
||||
[]
|
||||
[x, ..rest] ->
|
||||
[x, ..unique(filter(rest, fn(y) { y != x }))]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,6 +25,7 @@ test unique_1() {
|
|||
}
|
||||
|
||||
test unique_2() {
|
||||
let xs = [1, 2, 3, 1]
|
||||
let xs =
|
||||
[1, 2, 3, 1]
|
||||
unique(xs) == [1, 2, 3]
|
||||
}
|
||||
|
|
|
@ -12,8 +12,10 @@ pub fn from_list(xs: List<(key, value)>) -> AssocList<key, value> {
|
|||
|
||||
fn do_from_list(xs: List<(key, value)>) -> List<(key, value)> {
|
||||
when xs is {
|
||||
[] -> []
|
||||
[(k, v), ..rest] -> do_insert(do_from_list(rest), k, v)
|
||||
[] ->
|
||||
[]
|
||||
[(k, v), ..rest] ->
|
||||
do_insert(do_from_list(rest), k, v)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,7 +29,8 @@ pub fn insert(
|
|||
|
||||
fn do_insert(elems: List<(key, value)>, k: key, v: value) -> List<(key, value)> {
|
||||
when elems is {
|
||||
[] -> [(k, v)]
|
||||
[] ->
|
||||
[(k, v)]
|
||||
[(k2, v2), ..rest] ->
|
||||
if k == k2 {
|
||||
[(k, v), ..rest]
|
||||
|
@ -49,15 +52,17 @@ fn do_union(
|
|||
right: List<(key, value)>,
|
||||
) -> List<(key, value)> {
|
||||
when left is {
|
||||
[] -> right
|
||||
[(k, v), ..rest] -> do_union(rest, do_insert(right, k, v))
|
||||
[] ->
|
||||
right
|
||||
[(k, v), ..rest] ->
|
||||
do_union(rest, do_insert(right, k, v))
|
||||
}
|
||||
}
|
||||
|
||||
fn fixture_1() {
|
||||
new()
|
||||
|> insert("foo", 42)
|
||||
|> insert("bar", 14)
|
||||
|> insert("foo", 42)
|
||||
|> insert("bar", 14)
|
||||
}
|
||||
|
||||
test union_1() {
|
||||
|
|
|
@ -5,7 +5,7 @@ fn concat(left: String, right: String) -> String {
|
|||
builtin.encode_utf8(left),
|
||||
builtin.encode_utf8(right),
|
||||
)
|
||||
|> builtin.decode_utf8
|
||||
|> builtin.decode_utf8
|
||||
}
|
||||
|
||||
fn is_negative(i: Int) -> Bool {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
test tuple_1() {
|
||||
let coordinates = (14, 42)
|
||||
let coordinates =
|
||||
(14, 42)
|
||||
coordinates.1st == 14 && coordinates.2nd == 42
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
pub fn foldr(self: List<a>, with: fn(a, b) -> b, zero: b) -> b {
|
||||
when self is {
|
||||
[] -> zero
|
||||
[x, ..xs] -> with(x, foldr(xs, with, zero))
|
||||
[] ->
|
||||
zero
|
||||
[x, ..xs] ->
|
||||
with(x, foldr(xs, with, zero))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,8 @@ fn do_union_with(
|
|||
with: fn(ByteArray, value, value) -> Option<value>,
|
||||
) -> List<(ByteArray, value)> {
|
||||
when left is {
|
||||
[] -> right
|
||||
[] ->
|
||||
right
|
||||
[(k, v), ..rest] ->
|
||||
do_union_with(rest, do_insert_with(right, k, v, with), with)
|
||||
}
|
||||
|
@ -50,12 +51,15 @@ fn do_insert_with(
|
|||
with: fn(ByteArray, value, value) -> Option<value>,
|
||||
) -> List<(ByteArray, value)> {
|
||||
when self is {
|
||||
[] -> [(k, v)]
|
||||
[] ->
|
||||
[(k, v)]
|
||||
[(k2, v2), ..rest] ->
|
||||
if k == k2 {
|
||||
when with(k, v, v2) is {
|
||||
Some(combined) -> [(k, combined), ..rest]
|
||||
None -> rest
|
||||
Some(combined) ->
|
||||
[(k, combined), ..rest]
|
||||
None ->
|
||||
rest
|
||||
}
|
||||
} else {
|
||||
[(k2, v2), ..do_insert_with(rest, k, v, with)]
|
||||
|
|
|
@ -16,9 +16,9 @@ pub fn from_asset(
|
|||
) -> Value {
|
||||
let asset =
|
||||
dict.new()
|
||||
|> dict.insert(asset_name, quantity)
|
||||
|> dict.insert(asset_name, quantity)
|
||||
dict.new()
|
||||
|> dict.insert(policy_id, asset)
|
||||
|> dict.insert(policy_id, asset)
|
||||
}
|
||||
|
||||
pub fn from_lovelace(quantity: Int) -> Value {
|
||||
|
@ -35,7 +35,8 @@ pub fn add(left v0: Value, right v1: Value) -> Value {
|
|||
a0,
|
||||
a1,
|
||||
fn(_, q0, q1) {
|
||||
let q = q0 + q1
|
||||
let q =
|
||||
q0 + q1
|
||||
if q == 0 {
|
||||
None
|
||||
} else {
|
||||
|
@ -45,15 +46,19 @@ pub fn add(left v0: Value, right v1: Value) -> Value {
|
|||
)
|
||||
|
||||
when dict.toList(asset) is {
|
||||
[] -> None
|
||||
_ -> Some(asset)
|
||||
[] ->
|
||||
None
|
||||
_ ->
|
||||
Some(asset)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
test add_1() {
|
||||
let v1 = from_lovelace(1)
|
||||
let v2 = from_lovelace(-1)
|
||||
let v1 =
|
||||
from_lovelace(1)
|
||||
let v2 =
|
||||
from_lovelace(-1)
|
||||
add(v1, v2) == dict.new()
|
||||
}
|
||||
|
|
|
@ -3,19 +3,20 @@ use aiken/list
|
|||
use aiken/transaction.{Output, OutputReference, ScriptContext}
|
||||
use aiken/transaction/value.{PolicyId}
|
||||
|
||||
const my_policy_id: PolicyId = #"0000000000"
|
||||
const my_policy_id: PolicyId =
|
||||
#"0000000000"
|
||||
|
||||
pub fn has_policy_id(self: Output, policy_id: PolicyId) -> Bool {
|
||||
self.value
|
||||
|> value.tokens(policy_id)
|
||||
|> dict.is_empty
|
||||
|> not
|
||||
|> value.tokens(policy_id)
|
||||
|> dict.is_empty
|
||||
|> not
|
||||
}
|
||||
|
||||
validator spend {
|
||||
fn(_datum: Data, _redeemer: Data, ctx: ScriptContext) -> Bool {
|
||||
ctx.transaction.outputs
|
||||
|> list.any(has_policy_id(_, my_policy_id))
|
||||
|> list.any(has_policy_id(_, my_policy_id))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,8 +28,10 @@ validator mint(output_reference: OutputReference) {
|
|||
fn(input) { input.output_reference == output_reference },
|
||||
)
|
||||
is {
|
||||
Some(_) -> True
|
||||
None -> False
|
||||
Some(_) ->
|
||||
True
|
||||
None ->
|
||||
False
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
pub fn and(self: List<Bool>) -> Bool {
|
||||
when self is {
|
||||
[] -> True
|
||||
[x, ..xs] -> x && and(xs)
|
||||
[] ->
|
||||
True
|
||||
[x, ..xs] ->
|
||||
x && and(xs)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,8 +13,10 @@ test and_1() {
|
|||
|
||||
pub fn or(self: List<Bool>) -> Bool {
|
||||
when self is {
|
||||
[] -> False
|
||||
[x, ..xs] -> x || or(xs)
|
||||
[] ->
|
||||
False
|
||||
[x, ..xs] ->
|
||||
x || or(xs)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,8 @@ test expect_ford1() {
|
|||
builtin.list_data([]),
|
||||
],
|
||||
)
|
||||
expect Ford { owner, wheels, truck_bed_limit, .. }: Car = initial_car
|
||||
expect Ford { owner, wheels, truck_bed_limit, .. }: Car =
|
||||
initial_car
|
||||
owner == #"" && wheels == 4 && truck_bed_limit == 10000
|
||||
}
|
||||
|
||||
|
@ -41,26 +42,32 @@ test expect_ford2() {
|
|||
truck_bed_limit: 15000,
|
||||
car_doors: [],
|
||||
}
|
||||
expect Ford { owner, wheels, remote_connect, .. } = initial_car
|
||||
expect Ford { owner, wheels, remote_connect, .. } =
|
||||
initial_car
|
||||
owner == #"2222222222" && wheels == 6 && remote_connect == #""
|
||||
}
|
||||
|
||||
test expect_list1() {
|
||||
let initial_car = [5, 6, 7]
|
||||
expect [a, b, c] = initial_car
|
||||
let initial_car =
|
||||
[5, 6, 7]
|
||||
expect [a, b, c] =
|
||||
initial_car
|
||||
a == 5 && b == 6 && c == 7
|
||||
}
|
||||
|
||||
test expect_list2() {
|
||||
let initial_car = [5, 6, 7]
|
||||
expect [a, ..d] = initial_car
|
||||
let initial_car =
|
||||
[5, 6, 7]
|
||||
expect [a, ..d] =
|
||||
initial_car
|
||||
a == 5 && d == [6, 7]
|
||||
}
|
||||
|
||||
test expect_list3() {
|
||||
let initial_car =
|
||||
builtin.list_data([builtin.i_data(5), builtin.i_data(6), builtin.i_data(7)])
|
||||
expect [a, ..d]: List<Int> = initial_car
|
||||
expect [a, ..d]: List<Int> =
|
||||
initial_car
|
||||
a == 5 && d == [6, 7]
|
||||
}
|
||||
|
||||
|
@ -69,16 +76,22 @@ type Redeemer {
|
|||
}
|
||||
|
||||
test single_field_expect() {
|
||||
let redeemer = CreateVoteBatch { id: #"" }
|
||||
expect CreateVoteBatch { id } = redeemer
|
||||
let redeemer =
|
||||
CreateVoteBatch { id: #"" }
|
||||
expect CreateVoteBatch { id } =
|
||||
redeemer
|
||||
id == #""
|
||||
}
|
||||
|
||||
test single_when() {
|
||||
let redeemer = CreateVoteBatch { id: #"" }
|
||||
let x = when redeemer is {
|
||||
CreateVoteBatch { id } -> id == #""
|
||||
_ -> False
|
||||
}
|
||||
let redeemer =
|
||||
CreateVoteBatch { id: #"" }
|
||||
let x =
|
||||
when redeemer is {
|
||||
CreateVoteBatch { id } ->
|
||||
id == #""
|
||||
_ ->
|
||||
False
|
||||
}
|
||||
x == True
|
||||
}
|
||||
|
|
|
@ -1,16 +1,23 @@
|
|||
test foo_1() {
|
||||
let a = False
|
||||
let a =
|
||||
False
|
||||
when a is {
|
||||
True -> False
|
||||
False -> True
|
||||
True ->
|
||||
False
|
||||
False ->
|
||||
True
|
||||
}
|
||||
}
|
||||
|
||||
test foo_2() {
|
||||
let a = False
|
||||
let b = when a is {
|
||||
True -> 14
|
||||
False -> 42
|
||||
}
|
||||
let a =
|
||||
False
|
||||
let b =
|
||||
when a is {
|
||||
True ->
|
||||
14
|
||||
False ->
|
||||
42
|
||||
}
|
||||
b == 42
|
||||
}
|
||||
|
|
|
@ -9,7 +9,9 @@ fn fibonnaci(n) {
|
|||
}
|
||||
|
||||
test foo() {
|
||||
let right = fn() { fibonnaci(15) == 610 }
|
||||
let left = False
|
||||
let right =
|
||||
fn() { fibonnaci(15) == 610 }
|
||||
let left =
|
||||
False
|
||||
left || right()
|
||||
}
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
test sort_by_1() {
|
||||
let xs = [[4, 3, 2, 1], [2, 3, 4, 5]]
|
||||
let xs =
|
||||
[[4, 3, 2, 1], [2, 3, 4, 5]]
|
||||
when xs is {
|
||||
[[], ys] -> False
|
||||
[xs, []] -> False
|
||||
[[x, ..xs2], [y, ..ys2]] -> True
|
||||
_ -> False
|
||||
[[], ys] ->
|
||||
False
|
||||
[xs, []] ->
|
||||
False
|
||||
[[x, ..xs2], [y, ..ys2]] ->
|
||||
True
|
||||
_ ->
|
||||
False
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,33 +1,47 @@
|
|||
test foo_1() {
|
||||
let a = False
|
||||
let a =
|
||||
False
|
||||
when a is {
|
||||
a if a -> False
|
||||
_ -> True
|
||||
a if a ->
|
||||
False
|
||||
_ ->
|
||||
True
|
||||
}
|
||||
}
|
||||
|
||||
test foo_2() {
|
||||
let point = (14, 42)
|
||||
let point =
|
||||
(14, 42)
|
||||
when point is {
|
||||
(x, _) if x > 100 -> False
|
||||
(x, _) if x > 10 -> True
|
||||
_ -> False
|
||||
(x, _) if x > 100 ->
|
||||
False
|
||||
(x, _) if x > 10 ->
|
||||
True
|
||||
_ ->
|
||||
False
|
||||
}
|
||||
}
|
||||
|
||||
test foo_3() {
|
||||
let point = (14, 42)
|
||||
let point =
|
||||
(14, 42)
|
||||
when point is {
|
||||
(x, y) if x == 14 && y <= 100 -> True
|
||||
_ -> False
|
||||
(x, y) if x == 14 && y <= 100 ->
|
||||
True
|
||||
_ ->
|
||||
False
|
||||
}
|
||||
}
|
||||
|
||||
test foo_4() {
|
||||
let a = False
|
||||
let point = (14, 42)
|
||||
let a =
|
||||
False
|
||||
let point =
|
||||
(14, 42)
|
||||
when point is {
|
||||
(x, y) if !a -> x + y == 56
|
||||
_ -> False
|
||||
(x, y) if !a ->
|
||||
x + y == 56
|
||||
_ ->
|
||||
False
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
fn when_tuple(a: (Int, Int)) -> Int {
|
||||
when a is {
|
||||
(a, b) -> a
|
||||
(a, b) ->
|
||||
a
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
pub fn when_tuple(a: (Int, Int)) -> Int {
|
||||
when a is {
|
||||
(a, b) -> a
|
||||
(a, b) ->
|
||||
a
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,46 +5,55 @@ pub type Thing {
|
|||
}
|
||||
|
||||
test let_1() {
|
||||
let x: Data = 1
|
||||
let x: Data =
|
||||
1
|
||||
|
||||
x == builtin.i_data(1)
|
||||
}
|
||||
|
||||
test let_2() {
|
||||
let x: Data = 1
|
||||
let x: Data =
|
||||
1
|
||||
|
||||
expect y: Int = x
|
||||
expect y: Int =
|
||||
x
|
||||
|
||||
y == 1
|
||||
}
|
||||
|
||||
test assert_1() {
|
||||
expect thing: Thing = builtin.constr_data(0, [builtin.i_data(1)])
|
||||
expect thing: Thing =
|
||||
builtin.constr_data(0, [builtin.i_data(1)])
|
||||
|
||||
thing.wow == 1
|
||||
}
|
||||
|
||||
fn cast_to_thing(x: Data) -> Thing {
|
||||
expect x: Thing = x
|
||||
expect x: Thing =
|
||||
x
|
||||
|
||||
x
|
||||
}
|
||||
|
||||
test assert_2() {
|
||||
let thing = Thing { wow: 1 }
|
||||
let thing =
|
||||
Thing { wow: 1 }
|
||||
|
||||
let still_thing = cast_to_thing(thing)
|
||||
let still_thing =
|
||||
cast_to_thing(thing)
|
||||
|
||||
still_thing.wow == 1
|
||||
}
|
||||
|
||||
test tuple_1() {
|
||||
let thing = (#"aa", #"bb", #"cc")
|
||||
let thing =
|
||||
(#"aa", #"bb", #"cc")
|
||||
thing.1st == #"aa"
|
||||
}
|
||||
|
||||
test pair_1() {
|
||||
let thing = (#"aa", #"bb")
|
||||
let thing =
|
||||
(#"aa", #"bb")
|
||||
thing.1st == #"aa"
|
||||
}
|
||||
// should not typecheck
|
||||
|
|
|
@ -3,15 +3,20 @@ type TransactionId {
|
|||
}
|
||||
|
||||
test pattern_match_let() {
|
||||
let x = TransactionId { inner: #"0000" }
|
||||
let TransactionId(y) = x
|
||||
let x =
|
||||
TransactionId { inner: #"0000" }
|
||||
let TransactionId(y) =
|
||||
x
|
||||
y == #"0000"
|
||||
}
|
||||
|
||||
test pattern_match_when() {
|
||||
let x = TransactionId { inner: #"0000" }
|
||||
let y = when x is {
|
||||
TransactionId(y) -> y
|
||||
}
|
||||
let x =
|
||||
TransactionId { inner: #"0000" }
|
||||
let y =
|
||||
when x is {
|
||||
TransactionId(y) ->
|
||||
y
|
||||
}
|
||||
y == #"0000"
|
||||
}
|
||||
|
|
|
@ -5,12 +5,15 @@ pub type LinkedList<a> {
|
|||
|
||||
pub fn size(t: LinkedList<alg>) -> Int {
|
||||
when t is {
|
||||
Empty -> 0
|
||||
Node(_, tail) -> 1 + size(tail)
|
||||
Empty ->
|
||||
0
|
||||
Node(_, tail) ->
|
||||
1 + size(tail)
|
||||
}
|
||||
}
|
||||
|
||||
test foo() {
|
||||
let xs = Node(0, Node(1, Node(2, Empty)))
|
||||
let xs =
|
||||
Node(0, Node(1, Node(2, Empty)))
|
||||
size(xs) == 3
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use aiken/transaction/value
|
||||
|
||||
test test_quantity_of_1() {
|
||||
let x = value.from_asset(#"000000", #"000020e05363726970744f776e6572", -1)
|
||||
let x =
|
||||
value.from_asset(#"000000", #"000020e05363726970744f776e6572", -1)
|
||||
value.quantity_of(x, #"000000", #"000020e05363726970744f776e6572") < 0
|
||||
}
|
||||
|
|
|
@ -15,9 +15,12 @@ pub type MerkleTree {
|
|||
|
||||
pub fn root_hash(t: MerkleTree) -> Hash<Sha2_256, ByteArray> {
|
||||
when t is {
|
||||
Empty -> #""
|
||||
Leaf { hash, .. } -> hash
|
||||
Node { hash, .. } -> hash
|
||||
Empty ->
|
||||
#""
|
||||
Leaf { hash, .. } ->
|
||||
hash
|
||||
Node { hash, .. } ->
|
||||
hash
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,9 +30,12 @@ pub fn is_equal(a: MerkleTree, b: MerkleTree) -> Bool {
|
|||
|
||||
pub fn size(t: MerkleTree) -> Int {
|
||||
when t is {
|
||||
Empty -> 0
|
||||
Leaf{..} -> 1
|
||||
Node { left, right, .. } -> size(left) + size(right)
|
||||
Empty ->
|
||||
0
|
||||
Leaf{..} ->
|
||||
1
|
||||
Node { left, right, .. } ->
|
||||
size(left) + size(right)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,27 +49,33 @@ pub fn from_list(items0: List<ByteArray>) -> MerkleTree {
|
|||
|
||||
fn do_from_list(items: List<ByteArray>, len: Int) -> MerkleTree {
|
||||
when items is {
|
||||
[] -> Empty
|
||||
[value] -> Leaf { hash: sha2_256(value), value }
|
||||
[] ->
|
||||
Empty
|
||||
[value] ->
|
||||
Leaf { hash: sha2_256(value), value }
|
||||
all -> {
|
||||
let cutoff: Int = len / 2
|
||||
let cutoff: Int =
|
||||
len / 2
|
||||
let left =
|
||||
all
|
||||
|> list.take(cutoff)
|
||||
|> do_from_list(cutoff)
|
||||
|> list.take(cutoff)
|
||||
|> do_from_list(cutoff)
|
||||
let right =
|
||||
all
|
||||
|> list.drop(cutoff)
|
||||
|> do_from_list(len - cutoff)
|
||||
let hash = combine_hash(root_hash(left), root_hash(right))
|
||||
|> list.drop(cutoff)
|
||||
|> do_from_list(len - cutoff)
|
||||
let hash =
|
||||
combine_hash(root_hash(left), root_hash(right))
|
||||
Node { hash, left, right }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test foo() {
|
||||
let items = [#"aa", #"bb", #"cc"]
|
||||
let mt = from_list(items)
|
||||
let items =
|
||||
[#"aa", #"bb", #"cc"]
|
||||
let mt =
|
||||
from_list(items)
|
||||
size(mt) == 3
|
||||
}
|
||||
|
||||
|
@ -72,20 +84,24 @@ test some_test1() {
|
|||
}
|
||||
|
||||
test intersection_3() {
|
||||
let iv1 = between(0, 1)
|
||||
let iv2 = strictly_between(1, 2)
|
||||
let iv1 =
|
||||
between(0, 1)
|
||||
let iv2 =
|
||||
strictly_between(1, 2)
|
||||
intersection(iv1, iv2)
|
||||
|> is_empty
|
||||
|> is_empty
|
||||
}
|
||||
|
||||
const fooz = #"666f6f"
|
||||
const fooz =
|
||||
#"666f6f"
|
||||
|
||||
const bar = #"626172"
|
||||
const bar =
|
||||
#"626172"
|
||||
|
||||
fn fixture_1() {
|
||||
dict.new()
|
||||
|> dict.insert(fooz, 42, bytearray.compare)
|
||||
|> dict.insert(bar, 14, bytearray.compare)
|
||||
|> dict.insert(fooz, 42, bytearray.compare)
|
||||
|> dict.insert(bar, 14, bytearray.compare)
|
||||
}
|
||||
|
||||
test union_1() {
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
// Could possibly be forbidden by the parser instead if we have no intent to support that.
|
||||
pub fn choice(self: List<Option<a>>) -> Option<a> {
|
||||
when self is {
|
||||
[] -> None
|
||||
[Some(_) as result, ..] -> result
|
||||
[None, ..others] -> choice(others)
|
||||
[] ->
|
||||
None
|
||||
[Some(_) as result, ..] ->
|
||||
result
|
||||
[None, ..others] ->
|
||||
choice(others)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
pub fn choice(self: List<Option<a>>) -> Option<a> {
|
||||
when self is {
|
||||
[] -> None
|
||||
[Some(x), ..] -> Some(x)
|
||||
[None, ..others] -> choice(others)
|
||||
[] ->
|
||||
None
|
||||
[Some(x), ..] ->
|
||||
Some(x)
|
||||
[None, ..others] ->
|
||||
choice(others)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
pub fn choice(self: List<Option<a>>) -> Option<a> {
|
||||
when self is {
|
||||
[] -> None
|
||||
[None, ..others] -> choice(others)
|
||||
[result, ..] -> result
|
||||
[] ->
|
||||
None
|
||||
[None, ..others] ->
|
||||
choice(others)
|
||||
[result, ..] ->
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
pub fn alt(left: Option<a>, right: Option<a>) -> Option<a> {
|
||||
when (left, right) is {
|
||||
(Some(a), Some(_)) -> Some(a)
|
||||
(None, Some(a)) -> Some(a)
|
||||
(Some(a), None) -> Some(a)
|
||||
(None, None) -> None
|
||||
(Some(a), Some(_)) ->
|
||||
Some(a)
|
||||
(None, Some(a)) ->
|
||||
Some(a)
|
||||
(Some(a), None) ->
|
||||
Some(a)
|
||||
(None, None) ->
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,17 +3,23 @@ fn whatever(_xs) {
|
|||
}
|
||||
|
||||
test foo() {
|
||||
let xs = [1, 2, 3]
|
||||
let xs =
|
||||
[1, 2, 3]
|
||||
when xs is {
|
||||
[x] -> x == 1
|
||||
_ -> whatever(xs)
|
||||
[x] ->
|
||||
x == 1
|
||||
_ ->
|
||||
whatever(xs)
|
||||
}
|
||||
}
|
||||
|
||||
test bar() {
|
||||
let xs = [1, 2, 3]
|
||||
let xs =
|
||||
[1, 2, 3]
|
||||
when xs is {
|
||||
[x] -> x == 1
|
||||
ys -> whatever(ys)
|
||||
[x] ->
|
||||
x == 1
|
||||
ys ->
|
||||
whatever(ys)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,24 @@
|
|||
test foo() {
|
||||
let xs = [[1, 2], [4, 5]]
|
||||
let xs =
|
||||
[[1, 2], [4, 5]]
|
||||
when xs is {
|
||||
[[_, _], [_, _]] -> True
|
||||
_ -> False
|
||||
[[_, _], [_, _]] ->
|
||||
True
|
||||
_ ->
|
||||
False
|
||||
}
|
||||
}
|
||||
|
||||
test sort_by_1() {
|
||||
let xs = [[4, 3], [2, 3]]
|
||||
let g = when xs is {
|
||||
[[x, xs2], [y, ys2]] -> True
|
||||
_ -> False
|
||||
}
|
||||
let xs =
|
||||
[[4, 3], [2, 3]]
|
||||
let g =
|
||||
when xs is {
|
||||
[[x, xs2], [y, ys2]] ->
|
||||
True
|
||||
_ ->
|
||||
False
|
||||
}
|
||||
|
||||
g == True
|
||||
}
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
const int_constant = 42
|
||||
const int_constant =
|
||||
42
|
||||
|
||||
test int() {
|
||||
int_constant == 42
|
||||
}
|
||||
|
||||
const bytearray_constant = #"abcd"
|
||||
const bytearray_constant =
|
||||
#"abcd"
|
||||
|
||||
test bytearray() {
|
||||
bytearray_constant == #"abcd"
|
||||
}
|
||||
|
||||
const string_constant = "FOO"
|
||||
const string_constant =
|
||||
"FOO"
|
||||
|
||||
test string() {
|
||||
string_constant == "FOO"
|
||||
|
|
|
@ -8,9 +8,11 @@ use aiken/transaction/credential.{
|
|||
}
|
||||
use aiken/transaction/value
|
||||
|
||||
const keyhash = #"010203040506"
|
||||
const keyhash =
|
||||
#"010203040506"
|
||||
|
||||
const scripthash = #"060504030201"
|
||||
const scripthash =
|
||||
#"060504030201"
|
||||
|
||||
pub fn keyhash_address(with_stake_credential: Option<StakeCredential>) {
|
||||
Address {
|
||||
|
@ -32,7 +34,8 @@ type SampleData {
|
|||
}
|
||||
|
||||
pub fn tx_1() -> Transaction {
|
||||
let sample_datum = SampleData { a: 1, b: #"01" }
|
||||
let sample_datum =
|
||||
SampleData { a: 1, b: #"01" }
|
||||
let tx =
|
||||
Transaction {
|
||||
inputs: [
|
||||
|
|
|
@ -4,7 +4,8 @@ fn must_be_signed(signatories) {
|
|||
trace @"no signatories"
|
||||
False
|
||||
}
|
||||
[sig, ..] -> (sig == "#ffff")?
|
||||
[sig, ..] ->
|
||||
(sig == "#ffff")?
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,14 +15,16 @@ test foo() {
|
|||
|
||||
fn map(list: List<a>, f: fn(a) -> b) -> List<b> {
|
||||
when list is {
|
||||
[] -> []
|
||||
[x, ..xs] -> [f(x), ..map(xs, f)]
|
||||
[] ->
|
||||
[]
|
||||
[x, ..xs] ->
|
||||
[f(x), ..map(xs, f)]
|
||||
}
|
||||
}
|
||||
|
||||
fn get_fields(data: Data) -> List<Int> {
|
||||
builtin.un_constr_data(data).2nd
|
||||
|> map(builtin.un_i_data)
|
||||
|> map(builtin.un_i_data)
|
||||
}
|
||||
|
||||
test bar() {
|
||||
|
|
|
@ -37,13 +37,13 @@ fn inspect_list(_data: Data) -> Data {
|
|||
fn inspect_integer(data: Data) -> Data {
|
||||
let result: Data =
|
||||
builtin.un_i_data(data)
|
||||
|> Integer
|
||||
|> Integer
|
||||
result
|
||||
}
|
||||
|
||||
fn inspect_bytearray(data: Data) -> Data {
|
||||
let result: Data =
|
||||
builtin.un_b_data(data)
|
||||
|> Bytes
|
||||
|> Bytes
|
||||
result
|
||||
}
|
||||
|
|
|
@ -33,20 +33,29 @@ pub type ProofItem {
|
|||
/// Deconstruct a 'MerkleTree' back to a list of elements.
|
||||
pub fn to_list(self: MerkleTree<a>) -> List<a> {
|
||||
when self is {
|
||||
Empty -> []
|
||||
Leaf { value, .. } -> [value]
|
||||
Node { left, right, .. } -> list.concat(to_list(left), to_list(right))
|
||||
Empty ->
|
||||
[]
|
||||
Leaf { value, .. } ->
|
||||
[value]
|
||||
Node { left, right, .. } ->
|
||||
list.concat(to_list(left), to_list(right))
|
||||
}
|
||||
}
|
||||
|
||||
test to_list_1() {
|
||||
let dog = "dog"
|
||||
let cat = "cat"
|
||||
let mouse = "mouse"
|
||||
let items = [dog, cat, mouse]
|
||||
let hash_fn = create_string_item_hash_fn()
|
||||
let dog =
|
||||
"dog"
|
||||
let cat =
|
||||
"cat"
|
||||
let mouse =
|
||||
"mouse"
|
||||
let items =
|
||||
[dog, cat, mouse]
|
||||
let hash_fn =
|
||||
create_string_item_hash_fn()
|
||||
|
||||
let mt = from_list(items, hash_fn)
|
||||
let mt =
|
||||
from_list(items, hash_fn)
|
||||
|
||||
items == to_list(mt)
|
||||
}
|
||||
|
@ -54,47 +63,68 @@ test to_list_1() {
|
|||
// Function returning a hash of a given Merkle Tree element
|
||||
pub fn root_hash(self: MerkleTree<a>) -> Hash<Sha2_256, ByteArray> {
|
||||
when self is {
|
||||
Empty -> ""
|
||||
Leaf { hash, .. } -> hash
|
||||
Node { hash, .. } -> hash
|
||||
Empty ->
|
||||
""
|
||||
Leaf { hash, .. } ->
|
||||
hash
|
||||
Node { hash, .. } ->
|
||||
hash
|
||||
}
|
||||
}
|
||||
|
||||
test root_hash_1() {
|
||||
let dog = "dog"
|
||||
let items = [dog]
|
||||
let hash_fn = create_string_item_hash_fn()
|
||||
let dog =
|
||||
"dog"
|
||||
let items =
|
||||
[dog]
|
||||
let hash_fn =
|
||||
create_string_item_hash_fn()
|
||||
|
||||
let mt = from_list(items, hash_fn)
|
||||
let mt =
|
||||
from_list(items, hash_fn)
|
||||
|
||||
let node_hash = hash_fn(dog)
|
||||
let node_hash =
|
||||
hash_fn(dog)
|
||||
|
||||
root_hash(mt) == node_hash
|
||||
}
|
||||
|
||||
test root_hash_3() {
|
||||
let dog = "dog"
|
||||
let cat = "cat"
|
||||
let mouse = "mouse"
|
||||
let items = [dog, cat, mouse]
|
||||
let hash_fn = create_string_item_hash_fn()
|
||||
let dog =
|
||||
"dog"
|
||||
let cat =
|
||||
"cat"
|
||||
let mouse =
|
||||
"mouse"
|
||||
let items =
|
||||
[dog, cat, mouse]
|
||||
let hash_fn =
|
||||
create_string_item_hash_fn()
|
||||
|
||||
let mt = from_list(items, hash_fn)
|
||||
let mt =
|
||||
from_list(items, hash_fn)
|
||||
|
||||
let node_hash = sha2_256(bytearray.concat(hash_fn(cat), hash_fn(mouse)))
|
||||
let rh = sha2_256(bytearray.concat(hash_fn(dog), node_hash))
|
||||
let node_hash =
|
||||
sha2_256(bytearray.concat(hash_fn(cat), hash_fn(mouse)))
|
||||
let rh =
|
||||
sha2_256(bytearray.concat(hash_fn(dog), node_hash))
|
||||
|
||||
expect Node { hash: root_hash, .. } = mt
|
||||
expect Node { hash: root_hash, .. } =
|
||||
mt
|
||||
|
||||
rh == root_hash
|
||||
}
|
||||
|
||||
test root_hash_2() {
|
||||
let items = []
|
||||
let hash_fn = create_string_item_hash_fn()
|
||||
let mt = from_list(items, hash_fn)
|
||||
let items =
|
||||
[]
|
||||
let hash_fn =
|
||||
create_string_item_hash_fn()
|
||||
let mt =
|
||||
from_list(items, hash_fn)
|
||||
|
||||
let node_hash = #""
|
||||
let node_hash =
|
||||
#""
|
||||
|
||||
root_hash(mt) == node_hash
|
||||
}
|
||||
|
@ -107,52 +137,78 @@ pub fn is_equal(left: MerkleTree<a>, right: MerkleTree<a>) -> Bool {
|
|||
/// Function returns a total numbers of leaves in the tree.
|
||||
pub fn size(self: MerkleTree<a>) -> Int {
|
||||
when self is {
|
||||
Empty -> 0
|
||||
Leaf{..} -> 1
|
||||
Node { left, right, .. } -> size(left) + size(right)
|
||||
Empty ->
|
||||
0
|
||||
Leaf{..} ->
|
||||
1
|
||||
Node { left, right, .. } ->
|
||||
size(left) + size(right)
|
||||
}
|
||||
}
|
||||
|
||||
test size_1() {
|
||||
let items = []
|
||||
let hash_fn = create_string_item_hash_fn()
|
||||
let mt = from_list(items, hash_fn)
|
||||
let items =
|
||||
[]
|
||||
let hash_fn =
|
||||
create_string_item_hash_fn()
|
||||
let mt =
|
||||
from_list(items, hash_fn)
|
||||
size(mt) == 0
|
||||
}
|
||||
|
||||
test size_2() {
|
||||
let dog = "dog"
|
||||
let cat = "cat"
|
||||
let mouse = "mouse"
|
||||
let hash_fn = create_string_item_hash_fn()
|
||||
let dog =
|
||||
"dog"
|
||||
let cat =
|
||||
"cat"
|
||||
let mouse =
|
||||
"mouse"
|
||||
let hash_fn =
|
||||
create_string_item_hash_fn()
|
||||
|
||||
let mt = from_list([dog, cat, mouse], hash_fn)
|
||||
let mt =
|
||||
from_list([dog, cat, mouse], hash_fn)
|
||||
size(mt) == 3
|
||||
}
|
||||
|
||||
test size_3() {
|
||||
let dog = "dog"
|
||||
let cat = "cat"
|
||||
let mouse = "mouse"
|
||||
let items = [dog, cat, mouse]
|
||||
let hash_fn = create_string_item_hash_fn()
|
||||
let dog =
|
||||
"dog"
|
||||
let cat =
|
||||
"cat"
|
||||
let mouse =
|
||||
"mouse"
|
||||
let items =
|
||||
[dog, cat, mouse]
|
||||
let hash_fn =
|
||||
create_string_item_hash_fn()
|
||||
|
||||
let mt = from_list(items, hash_fn)
|
||||
let mt =
|
||||
from_list(items, hash_fn)
|
||||
size(mt) == 3
|
||||
}
|
||||
|
||||
test size_4() {
|
||||
let dog = "dog"
|
||||
let cat = "cat"
|
||||
let mouse = "mouse"
|
||||
let horse = "horse"
|
||||
let pig = "pig"
|
||||
let bull = "bull"
|
||||
let dog =
|
||||
"dog"
|
||||
let cat =
|
||||
"cat"
|
||||
let mouse =
|
||||
"mouse"
|
||||
let horse =
|
||||
"horse"
|
||||
let pig =
|
||||
"pig"
|
||||
let bull =
|
||||
"bull"
|
||||
|
||||
let hash_fn = create_string_item_hash_fn()
|
||||
let items = [dog, cat, mouse, horse, pig, bull]
|
||||
let hash_fn =
|
||||
create_string_item_hash_fn()
|
||||
let items =
|
||||
[dog, cat, mouse, horse, pig, bull]
|
||||
|
||||
let mt = from_list(items, hash_fn)
|
||||
let mt =
|
||||
from_list(items, hash_fn)
|
||||
size(mt) == 6
|
||||
}
|
||||
|
||||
|
@ -166,22 +222,28 @@ fn combine_hash(
|
|||
/// Function that returns whether merkle tree has any elements
|
||||
pub fn is_empty(self: MerkleTree<a>) -> Bool {
|
||||
when self is {
|
||||
Empty -> True
|
||||
_ -> False
|
||||
Empty ->
|
||||
True
|
||||
_ ->
|
||||
False
|
||||
}
|
||||
}
|
||||
|
||||
test is_empty_1() {
|
||||
let mt = Empty
|
||||
let mt =
|
||||
Empty
|
||||
|
||||
is_empty(mt)
|
||||
}
|
||||
|
||||
test is_empty_2() {
|
||||
let dog = "dog"
|
||||
let hash = create_string_item_hash_fn()
|
||||
let dog =
|
||||
"dog"
|
||||
let hash =
|
||||
create_string_item_hash_fn()
|
||||
|
||||
let mt = Leaf { value: dog, hash: hash(dog) }
|
||||
let mt =
|
||||
Leaf { value: dog, hash: hash(dog) }
|
||||
|
||||
is_empty(mt) == False
|
||||
}
|
||||
|
@ -193,7 +255,8 @@ fn do_proof(
|
|||
hash_fn: fn(a) -> Hash<Sha2_256, a>,
|
||||
) -> Option<Proof> {
|
||||
when self is {
|
||||
Empty -> None
|
||||
Empty ->
|
||||
None
|
||||
Leaf { hash, .. } ->
|
||||
if hash == item_hash {
|
||||
Some(proof)
|
||||
|
@ -201,8 +264,10 @@ fn do_proof(
|
|||
None
|
||||
}
|
||||
Node { left, right, .. } -> {
|
||||
let rh = root_hash(right)
|
||||
let lh = root_hash(left)
|
||||
let rh =
|
||||
root_hash(right)
|
||||
let lh =
|
||||
root_hash(left)
|
||||
let go_left: Option<Proof> =
|
||||
do_proof(left, item_hash, list.push(proof, Right { hash: rh }), hash_fn)
|
||||
let go_right: Option<Proof> =
|
||||
|
@ -220,93 +285,137 @@ pub fn get_proof(
|
|||
item: a,
|
||||
hash_fn: fn(a) -> Hash<Sha2_256, a>,
|
||||
) -> Option<Proof> {
|
||||
let empty: Proof = []
|
||||
let empty: Proof =
|
||||
[]
|
||||
|
||||
do_proof(self, hash_fn(item), empty, hash_fn)
|
||||
}
|
||||
|
||||
test get_proof_1() {
|
||||
let dog = "dog"
|
||||
let cat = "cat"
|
||||
let mouse = "mouse"
|
||||
let horse = "horse"
|
||||
let pig = "pig"
|
||||
let bull = "bull"
|
||||
let dog =
|
||||
"dog"
|
||||
let cat =
|
||||
"cat"
|
||||
let mouse =
|
||||
"mouse"
|
||||
let horse =
|
||||
"horse"
|
||||
let pig =
|
||||
"pig"
|
||||
let bull =
|
||||
"bull"
|
||||
|
||||
let items = [dog, cat, mouse, horse, pig, bull]
|
||||
let hash_fn = create_string_item_hash_fn()
|
||||
let items =
|
||||
[dog, cat, mouse, horse, pig, bull]
|
||||
let hash_fn =
|
||||
create_string_item_hash_fn()
|
||||
|
||||
let mt = from_list(items, hash_fn)
|
||||
let hash_fn = create_string_item_hash_fn()
|
||||
let mt =
|
||||
from_list(items, hash_fn)
|
||||
let hash_fn =
|
||||
create_string_item_hash_fn()
|
||||
|
||||
let maybe_proof: Option<Proof> = get_proof(mt, "parrot", hash_fn)
|
||||
let maybe_proof: Option<Proof> =
|
||||
get_proof(mt, "parrot", hash_fn)
|
||||
|
||||
is_none(maybe_proof)
|
||||
}
|
||||
|
||||
test get_proof_2() {
|
||||
let dog = "dog"
|
||||
let dog =
|
||||
"dog"
|
||||
|
||||
let items = [dog]
|
||||
let hash_fn = create_string_item_hash_fn()
|
||||
let mt = from_list(items, hash_fn)
|
||||
let items =
|
||||
[dog]
|
||||
let hash_fn =
|
||||
create_string_item_hash_fn()
|
||||
let mt =
|
||||
from_list(items, hash_fn)
|
||||
|
||||
let maybe_proof: Option<Proof> = get_proof(mt, dog, hash_fn)
|
||||
let maybe_proof: Option<Proof> =
|
||||
get_proof(mt, dog, hash_fn)
|
||||
|
||||
expect Some(proof) = maybe_proof
|
||||
expect Some(proof) =
|
||||
maybe_proof
|
||||
|
||||
// when proof is empty list it actually means that root of the tree is in fact element
|
||||
proof == []
|
||||
}
|
||||
|
||||
test get_proof_3() {
|
||||
let dog = "dog"
|
||||
let cat = "cat"
|
||||
let mouse = "mouse"
|
||||
let dog =
|
||||
"dog"
|
||||
let cat =
|
||||
"cat"
|
||||
let mouse =
|
||||
"mouse"
|
||||
|
||||
let items = [dog, cat, mouse]
|
||||
let items =
|
||||
[dog, cat, mouse]
|
||||
|
||||
let hash_fn = create_string_item_hash_fn()
|
||||
let mt = from_list(items, hash_fn)
|
||||
let hash_fn =
|
||||
create_string_item_hash_fn()
|
||||
let mt =
|
||||
from_list(items, hash_fn)
|
||||
|
||||
let node_hash = sha2_256(bytearray.concat(hash_fn(cat), hash_fn(mouse)))
|
||||
let node_hash =
|
||||
sha2_256(bytearray.concat(hash_fn(cat), hash_fn(mouse)))
|
||||
|
||||
let maybe_proof: Option<Proof> = get_proof(mt, dog, hash_fn)
|
||||
let maybe_proof: Option<Proof> =
|
||||
get_proof(mt, dog, hash_fn)
|
||||
|
||||
expect Some(proof) = maybe_proof
|
||||
expect Some(proof) =
|
||||
maybe_proof
|
||||
|
||||
let size_match = list.length(proof) == 1
|
||||
let size_match =
|
||||
list.length(proof) == 1
|
||||
|
||||
expect Some(p1) = list.at(proof, 0)
|
||||
expect Some(p1) =
|
||||
list.at(proof, 0)
|
||||
|
||||
let h1: ByteArray = get_proof_item_value(p1)
|
||||
let h1: ByteArray =
|
||||
get_proof_item_value(p1)
|
||||
|
||||
size_match && h1 == node_hash
|
||||
}
|
||||
|
||||
test get_proof_4() {
|
||||
let dog = "dog"
|
||||
let cat = "cat"
|
||||
let mouse = "mouse"
|
||||
let horse = "horse"
|
||||
let dog =
|
||||
"dog"
|
||||
let cat =
|
||||
"cat"
|
||||
let mouse =
|
||||
"mouse"
|
||||
let horse =
|
||||
"horse"
|
||||
|
||||
let items = [dog, cat, mouse, horse]
|
||||
let hash_fn = create_string_item_hash_fn()
|
||||
let mt = from_list(items, hash_fn)
|
||||
let items =
|
||||
[dog, cat, mouse, horse]
|
||||
let hash_fn =
|
||||
create_string_item_hash_fn()
|
||||
let mt =
|
||||
from_list(items, hash_fn)
|
||||
|
||||
let right_node_hash =
|
||||
sha2_256(bytearray.concat(hash_fn(mouse), hash_fn(horse)))
|
||||
let maybe_proof: Option<Proof> = get_proof(mt, dog, hash_fn)
|
||||
let maybe_proof: Option<Proof> =
|
||||
get_proof(mt, dog, hash_fn)
|
||||
|
||||
expect Some(proof) = maybe_proof
|
||||
expect Some(proof) =
|
||||
maybe_proof
|
||||
|
||||
let size_match = list.length(proof) == 2
|
||||
let size_match =
|
||||
list.length(proof) == 2
|
||||
|
||||
expect Some(p1) = list.at(proof, 0)
|
||||
expect Some(p2) = list.at(proof, 1)
|
||||
expect Some(p1) =
|
||||
list.at(proof, 0)
|
||||
expect Some(p2) =
|
||||
list.at(proof, 1)
|
||||
|
||||
let h1: ByteArray = get_proof_item_value(p1)
|
||||
let h2: ByteArray = get_proof_item_value(p2)
|
||||
let h1: ByteArray =
|
||||
get_proof_item_value(p1)
|
||||
let h2: ByteArray =
|
||||
get_proof_item_value(p2)
|
||||
|
||||
size_match && h1 == hash_fn(cat) && h2 == right_node_hash
|
||||
}
|
||||
|
@ -317,22 +426,26 @@ fn do_from_list(
|
|||
hash_fn: fn(a) -> Hash<Sha2_256, a>,
|
||||
) -> MerkleTree<a> {
|
||||
when items is {
|
||||
[] -> Empty
|
||||
[] ->
|
||||
Empty
|
||||
[item] -> {
|
||||
let hashed_item = hash_fn(item)
|
||||
let hashed_item =
|
||||
hash_fn(item)
|
||||
Leaf { value: item, hash: hashed_item }
|
||||
}
|
||||
all -> {
|
||||
let cutoff: Int = len / 2
|
||||
let cutoff: Int =
|
||||
len / 2
|
||||
let left =
|
||||
all
|
||||
|> list.take(cutoff)
|
||||
|> do_from_list(cutoff, hash_fn)
|
||||
|> list.take(cutoff)
|
||||
|> do_from_list(cutoff, hash_fn)
|
||||
let right =
|
||||
all
|
||||
|> list.drop(cutoff)
|
||||
|> do_from_list(len - cutoff, hash_fn)
|
||||
let hash = combine_hash(root_hash(left), root_hash(right))
|
||||
|> list.drop(cutoff)
|
||||
|> do_from_list(len - cutoff, hash_fn)
|
||||
let hash =
|
||||
combine_hash(root_hash(left), root_hash(right))
|
||||
Node { hash, left, right }
|
||||
}
|
||||
}
|
||||
|
@ -349,32 +462,46 @@ pub fn from_list(
|
|||
}
|
||||
|
||||
test from_1() {
|
||||
let _a = -1
|
||||
let items = []
|
||||
let hash_fn = create_string_item_hash_fn()
|
||||
let mt = from_list(items, hash_fn)
|
||||
let _a =
|
||||
-1
|
||||
let items =
|
||||
[]
|
||||
let hash_fn =
|
||||
create_string_item_hash_fn()
|
||||
let mt =
|
||||
from_list(items, hash_fn)
|
||||
|
||||
Empty == mt
|
||||
}
|
||||
|
||||
test from_2() {
|
||||
let dog = "dog"
|
||||
let items = [dog]
|
||||
let hash_fn = create_string_item_hash_fn()
|
||||
let mt = from_list(items, hash_fn)
|
||||
let dog =
|
||||
"dog"
|
||||
let items =
|
||||
[dog]
|
||||
let hash_fn =
|
||||
create_string_item_hash_fn()
|
||||
let mt =
|
||||
from_list(items, hash_fn)
|
||||
|
||||
Leaf { value: dog, hash: hash_fn(dog) } == mt
|
||||
}
|
||||
|
||||
test from_3() {
|
||||
let dog = "dog"
|
||||
let cat = "cat"
|
||||
let items = [dog, cat]
|
||||
let dog =
|
||||
"dog"
|
||||
let cat =
|
||||
"cat"
|
||||
let items =
|
||||
[dog, cat]
|
||||
|
||||
let hash_fn = create_string_item_hash_fn()
|
||||
let mt = from_list(items, hash_fn)
|
||||
let hash_fn =
|
||||
create_string_item_hash_fn()
|
||||
let mt =
|
||||
from_list(items, hash_fn)
|
||||
|
||||
let root_hash = sha2_256(bytearray.concat(hash_fn(dog), hash_fn(cat)))
|
||||
let root_hash =
|
||||
sha2_256(bytearray.concat(hash_fn(dog), hash_fn(cat)))
|
||||
|
||||
Node {
|
||||
hash: root_hash,
|
||||
|
@ -384,17 +511,25 @@ test from_3() {
|
|||
}
|
||||
|
||||
test from_4() {
|
||||
let dog = "dog"
|
||||
let cat = "cat"
|
||||
let mouse = "mouse"
|
||||
let dog =
|
||||
"dog"
|
||||
let cat =
|
||||
"cat"
|
||||
let mouse =
|
||||
"mouse"
|
||||
|
||||
let items = [dog, cat, mouse]
|
||||
let hash_fn = create_string_item_hash_fn()
|
||||
let items =
|
||||
[dog, cat, mouse]
|
||||
let hash_fn =
|
||||
create_string_item_hash_fn()
|
||||
|
||||
let mt = from_list(items, hash_fn)
|
||||
let mt =
|
||||
from_list(items, hash_fn)
|
||||
|
||||
let node_hash = sha2_256(bytearray.concat(hash_fn(cat), hash_fn(mouse)))
|
||||
let root_hash = sha2_256(bytearray.concat(hash_fn(dog), node_hash))
|
||||
let node_hash =
|
||||
sha2_256(bytearray.concat(hash_fn(cat), hash_fn(mouse)))
|
||||
let root_hash =
|
||||
sha2_256(bytearray.concat(hash_fn(dog), node_hash))
|
||||
|
||||
Node {
|
||||
hash: root_hash,
|
||||
|
@ -408,21 +543,30 @@ test from_4() {
|
|||
}
|
||||
|
||||
test from_5() {
|
||||
let dog = "dog"
|
||||
let cat = "cat"
|
||||
let mouse = "mouse"
|
||||
let horse = "horse"
|
||||
let dog =
|
||||
"dog"
|
||||
let cat =
|
||||
"cat"
|
||||
let mouse =
|
||||
"mouse"
|
||||
let horse =
|
||||
"horse"
|
||||
|
||||
let hash_fn = create_string_item_hash_fn()
|
||||
let hash_fn =
|
||||
create_string_item_hash_fn()
|
||||
|
||||
let items = [dog, cat, mouse, horse]
|
||||
let mt = from_list(items, hash_fn)
|
||||
let items =
|
||||
[dog, cat, mouse, horse]
|
||||
let mt =
|
||||
from_list(items, hash_fn)
|
||||
|
||||
let left_node_hash = sha2_256(bytearray.concat(hash_fn(dog), hash_fn(cat)))
|
||||
let left_node_hash =
|
||||
sha2_256(bytearray.concat(hash_fn(dog), hash_fn(cat)))
|
||||
let right_node_hash =
|
||||
sha2_256(bytearray.concat(hash_fn(mouse), hash_fn(horse)))
|
||||
|
||||
let root_hash = sha2_256(bytearray.concat(left_node_hash, right_node_hash))
|
||||
let root_hash =
|
||||
sha2_256(bytearray.concat(left_node_hash, right_node_hash))
|
||||
|
||||
Node {
|
||||
hash: root_hash,
|
||||
|
@ -450,7 +594,8 @@ pub fn member_from_hash(
|
|||
hash_fn: fn(a) -> Hash<Sha2_256, a>,
|
||||
) -> Bool {
|
||||
when proof is {
|
||||
[] -> root_hash == item_hash
|
||||
[] ->
|
||||
root_hash == item_hash
|
||||
[head, ..tail] ->
|
||||
when head is {
|
||||
Left { hash: l } ->
|
||||
|
@ -469,113 +614,173 @@ pub fn member(
|
|||
proof: Proof,
|
||||
hash_fn: fn(a) -> Hash<Sha2_256, a>,
|
||||
) -> Bool {
|
||||
let item_hash = hash_fn(item)
|
||||
let item_hash =
|
||||
hash_fn(item)
|
||||
member_from_hash(item_hash, root_hash, proof, hash_fn)
|
||||
}
|
||||
|
||||
test member_1() {
|
||||
let dog = "dog"
|
||||
let items = [dog]
|
||||
let hash_fn = create_string_item_hash_fn()
|
||||
let mt = from_list(items, hash_fn)
|
||||
let dog =
|
||||
"dog"
|
||||
let items =
|
||||
[dog]
|
||||
let hash_fn =
|
||||
create_string_item_hash_fn()
|
||||
let mt =
|
||||
from_list(items, hash_fn)
|
||||
|
||||
let item = dog
|
||||
let rh = root_hash(mt)
|
||||
let item =
|
||||
dog
|
||||
let rh =
|
||||
root_hash(mt)
|
||||
|
||||
expect Some(proof) = get_proof(mt, item, hash_fn)
|
||||
expect Some(proof) =
|
||||
get_proof(mt, item, hash_fn)
|
||||
member(item: item, root_hash: rh, proof: proof, hash_fn: hash_fn)
|
||||
}
|
||||
|
||||
test member_2() {
|
||||
let dog = "dog"
|
||||
let cat = "cat"
|
||||
let mouse = "mouse"
|
||||
let horse = "horse"
|
||||
let dog =
|
||||
"dog"
|
||||
let cat =
|
||||
"cat"
|
||||
let mouse =
|
||||
"mouse"
|
||||
let horse =
|
||||
"horse"
|
||||
|
||||
let items = [dog, cat, mouse, horse]
|
||||
let hash_fn = create_string_item_hash_fn()
|
||||
let mt = from_list(items, hash_fn)
|
||||
let items =
|
||||
[dog, cat, mouse, horse]
|
||||
let hash_fn =
|
||||
create_string_item_hash_fn()
|
||||
let mt =
|
||||
from_list(items, hash_fn)
|
||||
|
||||
let item = cat
|
||||
let rh = root_hash(mt)
|
||||
let item =
|
||||
cat
|
||||
let rh =
|
||||
root_hash(mt)
|
||||
|
||||
expect Some(proof) = get_proof(mt, item, hash_fn)
|
||||
expect Some(proof) =
|
||||
get_proof(mt, item, hash_fn)
|
||||
member(item: item, root_hash: rh, proof: proof, hash_fn: hash_fn)
|
||||
}
|
||||
|
||||
test member_3() {
|
||||
let dog = "dog"
|
||||
let cat = "cat"
|
||||
let dog =
|
||||
"dog"
|
||||
let cat =
|
||||
"cat"
|
||||
|
||||
let items = [dog, cat]
|
||||
let hash_fn = create_string_item_hash_fn()
|
||||
let mt = from_list(items, hash_fn)
|
||||
let items =
|
||||
[dog, cat]
|
||||
let hash_fn =
|
||||
create_string_item_hash_fn()
|
||||
let mt =
|
||||
from_list(items, hash_fn)
|
||||
|
||||
let item = cat
|
||||
let rh = root_hash(mt)
|
||||
let item =
|
||||
cat
|
||||
let rh =
|
||||
root_hash(mt)
|
||||
|
||||
expect Some(proof) = get_proof(mt, item, hash_fn)
|
||||
expect Some(proof) =
|
||||
get_proof(mt, item, hash_fn)
|
||||
member(item: item, root_hash: rh, proof: proof, hash_fn: hash_fn)
|
||||
}
|
||||
|
||||
test member_4() {
|
||||
let dog = "dog"
|
||||
let cat = "cat"
|
||||
let mouse = "mouse"
|
||||
let dog =
|
||||
"dog"
|
||||
let cat =
|
||||
"cat"
|
||||
let mouse =
|
||||
"mouse"
|
||||
|
||||
let items = [dog, cat, mouse]
|
||||
let hash_fn = create_string_item_hash_fn()
|
||||
let mt = from_list(items, hash_fn)
|
||||
let items =
|
||||
[dog, cat, mouse]
|
||||
let hash_fn =
|
||||
create_string_item_hash_fn()
|
||||
let mt =
|
||||
from_list(items, hash_fn)
|
||||
|
||||
let item = mouse
|
||||
let rh = root_hash(mt)
|
||||
let item =
|
||||
mouse
|
||||
let rh =
|
||||
root_hash(mt)
|
||||
|
||||
expect Some(proof) = get_proof(mt, item, hash_fn)
|
||||
expect Some(proof) =
|
||||
get_proof(mt, item, hash_fn)
|
||||
member(item: item, root_hash: rh, proof: proof, hash_fn: hash_fn)
|
||||
}
|
||||
|
||||
test member_5() {
|
||||
let dog = "dog"
|
||||
let cat = "cat"
|
||||
let mouse = "mouse"
|
||||
let horse = "horse"
|
||||
let pig = "pig"
|
||||
let bull = "bull"
|
||||
let dog =
|
||||
"dog"
|
||||
let cat =
|
||||
"cat"
|
||||
let mouse =
|
||||
"mouse"
|
||||
let horse =
|
||||
"horse"
|
||||
let pig =
|
||||
"pig"
|
||||
let bull =
|
||||
"bull"
|
||||
|
||||
let items = [dog, cat, mouse, horse, pig, bull]
|
||||
let hash_fn = create_string_item_hash_fn()
|
||||
let mt = from_list(items, hash_fn)
|
||||
let items =
|
||||
[dog, cat, mouse, horse, pig, bull]
|
||||
let hash_fn =
|
||||
create_string_item_hash_fn()
|
||||
let mt =
|
||||
from_list(items, hash_fn)
|
||||
|
||||
let item = pig
|
||||
let rh = root_hash(mt)
|
||||
let item =
|
||||
pig
|
||||
let rh =
|
||||
root_hash(mt)
|
||||
|
||||
expect Some(proof) = get_proof(mt, item, hash_fn)
|
||||
expect Some(proof) =
|
||||
get_proof(mt, item, hash_fn)
|
||||
member(item: item, root_hash: rh, proof: proof, hash_fn: hash_fn)
|
||||
}
|
||||
|
||||
test member_6() {
|
||||
let dog = "dog"
|
||||
let cat = "cat"
|
||||
let mouse = "mouse"
|
||||
let horse = "horse"
|
||||
let pig = "pig"
|
||||
let bull = "bull"
|
||||
let dog =
|
||||
"dog"
|
||||
let cat =
|
||||
"cat"
|
||||
let mouse =
|
||||
"mouse"
|
||||
let horse =
|
||||
"horse"
|
||||
let pig =
|
||||
"pig"
|
||||
let bull =
|
||||
"bull"
|
||||
|
||||
let hash_fn = create_string_item_hash_fn()
|
||||
let hash_fn =
|
||||
create_string_item_hash_fn()
|
||||
|
||||
let items = [dog, cat, mouse, horse, pig, bull]
|
||||
let mt = from_list(items, hash_fn)
|
||||
let items =
|
||||
[dog, cat, mouse, horse, pig, bull]
|
||||
let mt =
|
||||
from_list(items, hash_fn)
|
||||
|
||||
let item = "parrot"
|
||||
let item =
|
||||
"parrot"
|
||||
|
||||
let proof = get_proof(mt, item, hash_fn)
|
||||
let proof =
|
||||
get_proof(mt, item, hash_fn)
|
||||
proof == None
|
||||
}
|
||||
|
||||
fn get_proof_item_value(proof_item: ProofItem) -> Hash<Sha2_256, ByteArray> {
|
||||
when proof_item is {
|
||||
Left(x) -> x
|
||||
Right(y) -> y
|
||||
Left(x) ->
|
||||
x
|
||||
Right(y) ->
|
||||
y
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,10 +24,10 @@ pub fn from_asset(
|
|||
) -> Value {
|
||||
let asset =
|
||||
dict.new()
|
||||
|> dict.insert(asset_name, quantity, bytearray.compare)
|
||||
|> dict.insert(asset_name, quantity, bytearray.compare)
|
||||
dict.new()
|
||||
|> dict.insert(policy_id, asset, bytearray.compare)
|
||||
|> Value
|
||||
|> dict.insert(policy_id, asset, bytearray.compare)
|
||||
|> Value
|
||||
}
|
||||
|
||||
pub fn add(left v0: Value, right v1: Value) -> Value {
|
||||
|
@ -40,7 +40,8 @@ pub fn add(left v0: Value, right v1: Value) -> Value {
|
|||
a0,
|
||||
a1,
|
||||
fn(_, q0, q1) {
|
||||
let q = q0 + q1
|
||||
let q =
|
||||
q0 + q1
|
||||
if q == 0 {
|
||||
None
|
||||
} else {
|
||||
|
@ -58,7 +59,7 @@ pub fn add(left v0: Value, right v1: Value) -> Value {
|
|||
},
|
||||
bytearray.compare,
|
||||
)
|
||||
|> Value
|
||||
|> Value
|
||||
}
|
||||
|
||||
/// Flatten a value as a list of results, possibly discarding some along the way.
|
||||
|
@ -75,8 +76,10 @@ pub fn flatten_with(
|
|||
asset,
|
||||
fn(asset_name, quantity, xs) {
|
||||
when transform(policy_id, asset_name, quantity) is {
|
||||
None -> xs
|
||||
Some(x) -> [x, ..xs]
|
||||
None ->
|
||||
xs
|
||||
Some(x) ->
|
||||
[x, ..xs]
|
||||
}
|
||||
},
|
||||
assets,
|
||||
|
@ -93,9 +96,9 @@ test flatten_with_1() {
|
|||
test flatten_with_2() {
|
||||
let v =
|
||||
zero()
|
||||
|> add(from_asset("a", "1", 14))
|
||||
|> add(from_asset("b", "", 42))
|
||||
|> add(from_asset("a", "2", 42))
|
||||
|> add(from_asset("a", "1", 14))
|
||||
|> add(from_asset("b", "", 42))
|
||||
|> add(from_asset("a", "2", 42))
|
||||
|
||||
flatten_with(
|
||||
v,
|
||||
|
|
|
@ -69,10 +69,13 @@ pub fn validate_pool_deposit(
|
|||
datum: PoolDatum,
|
||||
redeemer: PoolDepositRedeemer,
|
||||
) -> Bool {
|
||||
let validator_address = scripthash_address(#"ff")
|
||||
let validator_address =
|
||||
scripthash_address(#"ff")
|
||||
|
||||
expect Some(pool_output) = get_output(ctx, validator_address)
|
||||
expect Some(pool_input) = get_input(ctx, validator_address)
|
||||
expect Some(pool_output) =
|
||||
get_output(ctx, validator_address)
|
||||
expect Some(pool_input) =
|
||||
get_input(ctx, validator_address)
|
||||
|
||||
True
|
||||
}
|
||||
|
@ -83,28 +86,34 @@ pub fn validate_pool_borrow(
|
|||
datum: PoolDatum,
|
||||
redeemer: PoolBorrowRedeemer,
|
||||
) -> Bool {
|
||||
let validator_address = scripthash_address(#"ff")
|
||||
let validator_address =
|
||||
scripthash_address(#"ff")
|
||||
|
||||
expect Some(pool_output) = get_output(ctx, validator_address)
|
||||
expect Some(pool_input) = get_input(ctx, validator_address)
|
||||
expect Some(pool_output) =
|
||||
get_output(ctx, validator_address)
|
||||
expect Some(pool_input) =
|
||||
get_input(ctx, validator_address)
|
||||
True
|
||||
}
|
||||
|
||||
validator pool_contract {
|
||||
fn(datum: PoolDatum, redeemer: PoolRedeemer, ctx: ScriptContext) {
|
||||
when redeemer.action is {
|
||||
PoolWithdraw(_) -> True
|
||||
PoolWithdraw(_) ->
|
||||
True
|
||||
PoolDeposit(pool_deposit_redeemer) ->
|
||||
when ctx.purpose is {
|
||||
Spend(output_ref) ->
|
||||
validate_pool_deposit(ctx, output_ref, datum, pool_deposit_redeemer)
|
||||
_ -> False
|
||||
_ ->
|
||||
False
|
||||
}
|
||||
PoolBorrow(pool_borrow_redeemer) ->
|
||||
when ctx.purpose is {
|
||||
Spend(output_ref) ->
|
||||
validate_pool_borrow(ctx, output_ref, datum, pool_borrow_redeemer)
|
||||
_ -> False
|
||||
_ ->
|
||||
False
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,24 +30,34 @@ fn find_outbound_datum(possible_output: Option<Output>) -> Data {
|
|||
when possible_output is {
|
||||
Some(possible_output) ->
|
||||
when possible_output.datum is {
|
||||
InlineDatum(outbound_datum) -> outbound_datum
|
||||
_ -> error @"expected outbound inline datum"
|
||||
InlineDatum(outbound_datum) ->
|
||||
outbound_datum
|
||||
_ ->
|
||||
error @"expected outbound inline datum"
|
||||
}
|
||||
None -> error @"no outbound datum found"
|
||||
None ->
|
||||
error @"no outbound datum found"
|
||||
}
|
||||
}
|
||||
|
||||
fn datum_a_cont() -> OtherDatum {
|
||||
let owner: OwnerInfo = OwnerInfo { pkh: #"", sc: #"" }
|
||||
let have: TokenInfo = TokenInfo { pid: #"", tkn: #"", amt: 100 }
|
||||
let want: TokenInfo = TokenInfo { pid: #"acab", tkn: #"beef", amt: 50 }
|
||||
let info: SwapInfo = SwapInfo { slip: 40 }
|
||||
let owner: OwnerInfo =
|
||||
OwnerInfo { pkh: #"", sc: #"" }
|
||||
let have: TokenInfo =
|
||||
TokenInfo { pid: #"", tkn: #"", amt: 100 }
|
||||
let want: TokenInfo =
|
||||
TokenInfo { pid: #"acab", tkn: #"beef", amt: 50 }
|
||||
let info: SwapInfo =
|
||||
SwapInfo { slip: 40 }
|
||||
OtherDatum { owner, have, want, info }
|
||||
}
|
||||
|
||||
test foo() {
|
||||
let outbound_datum = InlineDatum(datum_a_cont())
|
||||
let outbound_output = Some(Output { datum: outbound_datum })
|
||||
expect outbound_datum: OtherDatum = find_outbound_datum(outbound_output)
|
||||
let outbound_datum =
|
||||
InlineDatum(datum_a_cont())
|
||||
let outbound_output =
|
||||
Some(Output { datum: outbound_datum })
|
||||
expect outbound_datum: OtherDatum =
|
||||
find_outbound_datum(outbound_output)
|
||||
outbound_datum == datum_a_cont()
|
||||
}
|
||||
|
|
|
@ -25,9 +25,12 @@ pub type ProofItem {
|
|||
// Function returning a hash of a given Merkle Tree element
|
||||
pub fn root_hash(self: MerkleTree<a>) -> Hash<Sha2_256, ByteArray> {
|
||||
when self is {
|
||||
Empty -> #""
|
||||
Leaf { hash } -> hash
|
||||
Node { hash, .. } -> hash
|
||||
Empty ->
|
||||
#""
|
||||
Leaf { hash } ->
|
||||
hash
|
||||
Node { hash, .. } ->
|
||||
hash
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,9 +42,12 @@ pub fn is_equal(left: MerkleTree<a>, right: MerkleTree<a>) -> Bool {
|
|||
/// Function returns a total numbers of leaves in the tree.
|
||||
pub fn size(self: MerkleTree<a>) -> Int {
|
||||
when self is {
|
||||
Empty -> 0
|
||||
Leaf{..} -> 1
|
||||
Node { left, right, .. } -> size(left) + size(right)
|
||||
Empty ->
|
||||
0
|
||||
Leaf{..} ->
|
||||
1
|
||||
Node { left, right, .. } ->
|
||||
size(left) + size(right)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,8 +61,10 @@ fn combine_hash(
|
|||
/// Function that returns whether merkle tree has any elements
|
||||
pub fn is_empty(self: MerkleTree<a>) -> Bool {
|
||||
when self is {
|
||||
Empty -> True
|
||||
_ -> False
|
||||
Empty ->
|
||||
True
|
||||
_ ->
|
||||
False
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,7 +75,8 @@ fn do_proof(
|
|||
serialise_fn: fn(a) -> ByteArray,
|
||||
) -> Option<Proof> {
|
||||
when self is {
|
||||
Empty -> None
|
||||
Empty ->
|
||||
None
|
||||
Leaf { hash } ->
|
||||
if hash == item_hash {
|
||||
Some(proof)
|
||||
|
@ -75,8 +84,10 @@ fn do_proof(
|
|||
None
|
||||
}
|
||||
Node { left, right, .. } -> {
|
||||
let rh = root_hash(right)
|
||||
let lh = root_hash(left)
|
||||
let rh =
|
||||
root_hash(right)
|
||||
let lh =
|
||||
root_hash(left)
|
||||
let go_left: Option<Proof> =
|
||||
do_proof(
|
||||
left,
|
||||
|
@ -104,7 +115,8 @@ pub fn get_proof(
|
|||
item: a,
|
||||
serialise_fn: fn(a) -> ByteArray,
|
||||
) -> Option<Proof> {
|
||||
let empty: Proof = []
|
||||
let empty: Proof =
|
||||
[]
|
||||
|
||||
do_proof(self, sha2_256(serialise_fn(item)), empty, serialise_fn)
|
||||
}
|
||||
|
@ -115,22 +127,26 @@ fn do_from_list(
|
|||
serialise_fn: fn(a) -> ByteArray,
|
||||
) -> MerkleTree<a> {
|
||||
when items is {
|
||||
[] -> Empty
|
||||
[] ->
|
||||
Empty
|
||||
[item] -> {
|
||||
let hashed_item = sha2_256(serialise_fn(item))
|
||||
let hashed_item =
|
||||
sha2_256(serialise_fn(item))
|
||||
Leaf { hash: hashed_item }
|
||||
}
|
||||
all -> {
|
||||
let cutoff: Int = len / 2
|
||||
let cutoff: Int =
|
||||
len / 2
|
||||
let left =
|
||||
all
|
||||
|> list.take(cutoff)
|
||||
|> do_from_list(cutoff, serialise_fn)
|
||||
|> list.take(cutoff)
|
||||
|> do_from_list(cutoff, serialise_fn)
|
||||
let right =
|
||||
all
|
||||
|> list.drop(cutoff)
|
||||
|> do_from_list(len - cutoff, serialise_fn)
|
||||
let hash = combine_hash(root_hash(left), root_hash(right))
|
||||
|> list.drop(cutoff)
|
||||
|> do_from_list(len - cutoff, serialise_fn)
|
||||
let hash =
|
||||
combine_hash(root_hash(left), root_hash(right))
|
||||
Node { hash, left, right }
|
||||
}
|
||||
}
|
||||
|
@ -151,19 +167,23 @@ fn do_from_hashes_list(
|
|||
len: Int,
|
||||
) -> MerkleTree<a> {
|
||||
when items is {
|
||||
[] -> Empty
|
||||
[hashed_item] -> Leaf { hash: hashed_item }
|
||||
[] ->
|
||||
Empty
|
||||
[hashed_item] ->
|
||||
Leaf { hash: hashed_item }
|
||||
all -> {
|
||||
let cutoff: Int = len / 2
|
||||
let cutoff: Int =
|
||||
len / 2
|
||||
let left =
|
||||
all
|
||||
|> list.take(cutoff)
|
||||
|> do_from_hashes_list(cutoff)
|
||||
|> list.take(cutoff)
|
||||
|> do_from_hashes_list(cutoff)
|
||||
let right =
|
||||
all
|
||||
|> list.drop(cutoff)
|
||||
|> do_from_hashes_list(len - cutoff)
|
||||
let hash = combine_hash(root_hash(left), root_hash(right))
|
||||
|> list.drop(cutoff)
|
||||
|> do_from_hashes_list(len - cutoff)
|
||||
let hash =
|
||||
combine_hash(root_hash(left), root_hash(right))
|
||||
Node { hash, left, right }
|
||||
}
|
||||
}
|
||||
|
@ -187,7 +207,8 @@ pub fn member_from_hash(
|
|||
serialise_fn: fn(a) -> ByteArray,
|
||||
) -> Bool {
|
||||
when proof is {
|
||||
[] -> root_hash == item_hash
|
||||
[] ->
|
||||
root_hash == item_hash
|
||||
[head, ..tail] ->
|
||||
when head is {
|
||||
Left { hash: l } ->
|
||||
|
@ -216,7 +237,8 @@ pub fn member(
|
|||
proof: Proof,
|
||||
serialise_fn: fn(a) -> ByteArray,
|
||||
) -> Bool {
|
||||
let item_hash = sha2_256(serialise_fn(item))
|
||||
let item_hash =
|
||||
sha2_256(serialise_fn(item))
|
||||
member_from_hash(item_hash, root_hash, proof, serialise_fn)
|
||||
}
|
||||
|
||||
|
@ -225,12 +247,16 @@ pub fn member_from_tree(
|
|||
item: a,
|
||||
serialise_fn: fn(a) -> ByteArray,
|
||||
) -> Bool {
|
||||
let proof: Option<Proof> = get_proof(tree, item, serialise_fn)
|
||||
let rh = root_hash(tree)
|
||||
let proof: Option<Proof> =
|
||||
get_proof(tree, item, serialise_fn)
|
||||
let rh =
|
||||
root_hash(tree)
|
||||
|
||||
when proof is {
|
||||
Some(p) -> member(item, rh, p, serialise_fn)
|
||||
None -> False
|
||||
Some(p) ->
|
||||
member(item, rh, p, serialise_fn)
|
||||
None ->
|
||||
False
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,17 +266,25 @@ fn create_string_item_serialise_fn() -> fn(String) -> ByteArray {
|
|||
}
|
||||
|
||||
test from_hashes_list_5() {
|
||||
let dog = @"dog"
|
||||
let cat = @"cat"
|
||||
let mouse = @"mouse"
|
||||
let horse = @"horse"
|
||||
let dog =
|
||||
@"dog"
|
||||
let cat =
|
||||
@"cat"
|
||||
let mouse =
|
||||
@"mouse"
|
||||
let horse =
|
||||
@"horse"
|
||||
|
||||
let serialise_fn = create_string_item_serialise_fn()
|
||||
let serialise_fn =
|
||||
create_string_item_serialise_fn()
|
||||
|
||||
let items = [dog, cat, mouse, horse]
|
||||
let hashes_items = list.map(items, fn(item) { sha2_256(serialise_fn(item)) })
|
||||
let items =
|
||||
[dog, cat, mouse, horse]
|
||||
let hashes_items =
|
||||
list.map(items, fn(item) { sha2_256(serialise_fn(item)) })
|
||||
|
||||
let mt = from_hashes_list(hashes_items)
|
||||
let mt =
|
||||
from_hashes_list(hashes_items)
|
||||
|
||||
let left_node_hash =
|
||||
sha2_256(
|
||||
|
@ -264,7 +298,8 @@ test from_hashes_list_5() {
|
|||
),
|
||||
)
|
||||
|
||||
let root_hash = sha2_256(bytearray.concat(left_node_hash, right_node_hash))
|
||||
let root_hash =
|
||||
sha2_256(bytearray.concat(left_node_hash, right_node_hash))
|
||||
|
||||
Node {
|
||||
hash: root_hash,
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
test expect_positive() {
|
||||
let val = 5
|
||||
expect True = val > 0
|
||||
let val =
|
||||
5
|
||||
expect True =
|
||||
val > 0
|
||||
True
|
||||
}
|
||||
|
|
|
@ -4,12 +4,15 @@ use aiken/transaction/value.{add, zero}
|
|||
|
||||
validator staking {
|
||||
fn(_datum: Void, _redeemer: Void, context: ScriptContext) -> Bool {
|
||||
expect Spend(ref) = context.purpose
|
||||
expect Spend(ref) =
|
||||
context.purpose
|
||||
|
||||
expect Some(i) =
|
||||
find(context.transaction.inputs, fn(x) { x.output_reference == ref })
|
||||
let Input { output, .. } = i
|
||||
let staking_addr = output.address
|
||||
let Input { output, .. } =
|
||||
i
|
||||
let staking_addr =
|
||||
output.address
|
||||
|
||||
let v_in =
|
||||
foldr(
|
||||
|
|
|
@ -3,13 +3,16 @@ use aiken/transaction.{Output, ScriptContext}
|
|||
|
||||
validator backtrace {
|
||||
fn(_datum: Void, _redeemer: Void, context: ScriptContext) -> Bool {
|
||||
expect Some(_) = list.find(context.transaction.outputs, fn(_) { True })
|
||||
let _ = find_stuff(context)
|
||||
expect Some(_) =
|
||||
list.find(context.transaction.outputs, fn(_) { True })
|
||||
let _ =
|
||||
find_stuff(context)
|
||||
True
|
||||
}
|
||||
}
|
||||
|
||||
fn find_stuff(context) -> Output {
|
||||
expect Some(stuff) = list.find(context.transaction.outputs, fn(_) { True })
|
||||
expect Some(stuff) =
|
||||
list.find(context.transaction.outputs, fn(_) { True })
|
||||
stuff
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue