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:
KtorZ 2023-03-16 19:42:57 +01:00
parent bf9297efcf
commit 20f5baffa7
No known key found for this signature in database
GPG Key ID: 33173CB6F77F4277
60 changed files with 998 additions and 548 deletions

View File

@ -17,6 +17,7 @@
- **aiken-lang**: update todo warning to include type - **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**: `|>` 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**: 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 ## [v0.0.29] - 2023-MM-DD

View File

@ -285,7 +285,11 @@ impl<'comments> Formatter<'comments> {
None => head, None => head,
Some(t) => head.append(": ").append(self.annotation(t)), 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, &mut self,
pattern: &'a UntypedPattern, pattern: &'a UntypedPattern,
value: &'a UntypedExpr, value: &'a UntypedExpr,
then: Option<&'a UntypedExpr>, kind: AssignmentKind,
kind: Option<AssignmentKind>,
annotation: &'a Option<Annotation>, annotation: &'a Option<Annotation>,
) -> Document<'a> { ) -> Document<'a> {
self.pop_empty_lines(pattern.location().end); self.pop_empty_lines(pattern.location().end);
let keyword = match kind { let keyword = match kind {
Some(AssignmentKind::Let) => "let ", AssignmentKind::Let => "let ",
Some(AssignmentKind::Expect) => "expect ", AssignmentKind::Expect => "expect ",
None => "try ",
}; };
let pattern = self.pattern(pattern); let pattern = self.pattern(pattern);
@ -620,25 +622,11 @@ impl<'comments> Formatter<'comments> {
.as_ref() .as_ref()
.map(|a| ": ".to_doc().append(self.annotation(a))); .map(|a| ": ".to_doc().append(self.annotation(a)));
let doc = if then.is_some() { keyword
keyword.to_doc().force_break() .to_doc()
} else { .append(pattern.append(annotation).group())
keyword.to_doc() .append(" =")
} .append(self.case_clause_value(value))
.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
}
} }
pub fn bytearray<'a>( pub fn bytearray<'a>(
@ -733,7 +721,7 @@ impl<'comments> Formatter<'comments> {
annotation, annotation,
kind, kind,
.. ..
} => self.assignment(pattern, value, None, Some(*kind), annotation), } => self.assignment(pattern, value, *kind, annotation),
UntypedExpr::Trace { UntypedExpr::Trace {
kind, text, then, .. kind, text, then, ..
@ -1448,19 +1436,12 @@ impl<'comments> Formatter<'comments> {
.force_break(), .force_break(),
UntypedExpr::Fn { .. } | UntypedExpr::List { .. } => { 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(), UntypedExpr::When { .. } => line().append(self.expr(expr)).nest(INDENT).group(),
_ => break_("", " ").append(self.expr(expr)).nest(INDENT).group(), _ => line().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),
} }
} }

View File

@ -90,8 +90,10 @@ fn test_format_when() {
let expected = indoc! {r#" let expected = indoc! {r#"
pub fn foo(a) { pub fn foo(a) {
when a is { when a is {
True -> 14 True ->
False -> 42 14
False ->
42
} }
} }
"#}; "#};
@ -134,8 +136,10 @@ fn test_format_nested_when_if() {
xs xs
} else { } else {
when xs is { 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 xs
} else { } else {
when xs is { 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#" let expected = indoc! {r#"
fn foo() { fn foo() {
when a is { when a is {
None -> "foo" None ->
"foo"
Some(b) -> Some(b) ->
when b is { when b is {
None -> "foo" None ->
"foo"
Some(c) -> Some(c) ->
when c is { when c is {
None -> "foo" None ->
Some(_) -> "foo" "foo"
Some(_) ->
"foo"
} }
} }
} }
@ -343,8 +353,10 @@ fn test_nested_function_calls() {
), ),
), ),
when output.datum is { when output.datum is {
InlineDatum(_) -> True InlineDatum(_) ->
_ -> error @"expected inline datum" True
_ ->
error @"expected inline datum"
}, },
] ]
|> list.and |> list.and
@ -393,8 +405,10 @@ fn format_trace_todo_error() {
fn foo_3() { fn foo_3() {
when x is { when x is {
Foo -> True Foo ->
_ -> error True
_ ->
error
} }
} }
@ -517,18 +531,24 @@ fn test_newline_module_comments() {
#[test] #[test]
fn test_bytearray_literals() { fn test_bytearray_literals() {
let src = indoc! {r#" 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() { 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] #[test]
fn test_string_literal() { fn test_string_literal() {
let src = indoc! {r#" let src = indoc! {r#"
const foo_const: String = @"foo" const foo_const: String =
@"foo"
fn foo() { fn foo() {
let foo_var: String = @"foo" let foo_var: String =
@"foo"
} }
"#}; "#};

View File

@ -1,7 +1,9 @@
pub fn length(xs: List<a>) -> Int { pub fn length(xs: List<a>) -> Int {
when xs is { when xs is {
[] -> 0 [] ->
[_, ..rest] -> 1 + length(rest) 0
[_, ..rest] ->
1 + length(rest)
} }
} }

View File

@ -1,7 +1,9 @@
pub fn foldr(xs: List<a>, f: fn(a, b) -> b, zero: b) -> b { pub fn foldr(xs: List<a>, f: fn(a, b) -> b, zero: b) -> b {
when xs is { when xs is {
[] -> zero [] ->
[x, ..rest] -> f(x, foldr(rest, f, zero)) zero
[x, ..rest] ->
f(x, foldr(rest, f, zero))
} }
} }

View File

@ -1,7 +1,9 @@
pub fn foldr(xs: List<a>, f: fn(a, b) -> b, zero: b) -> b { pub fn foldr(xs: List<a>, f: fn(a, b) -> b, zero: b) -> b {
when xs is { when xs is {
[] -> zero [] ->
[x, ..rest] -> f(x, foldr(rest, f, zero)) zero
[x, ..rest] ->
f(x, foldr(rest, f, zero))
} }
} }

View File

@ -2,8 +2,10 @@ use aiken/builtin.{head_list}
pub fn head(xs: List<a>) -> Option<a> { pub fn head(xs: List<a>) -> Option<a> {
when xs is { when xs is {
[] -> None [] ->
_ -> Some(head_list(xs)) None
_ ->
Some(head_list(xs))
} }
} }

View File

@ -1,8 +1,10 @@
pub fn unzip(xs: List<(a, b)>) -> (List<a>, List<b>) { pub fn unzip(xs: List<(a, b)>) -> (List<a>, List<b>) {
when xs is { when xs is {
[] -> ([], []) [] ->
([], [])
[(a, b), ..rest] -> { [(a, b), ..rest] -> {
let (a_tail, b_tail) = unzip(rest) let (a_tail, b_tail) =
unzip(rest)
([a, ..a_tail], [b, ..b_tail]) ([a, ..a_tail], [b, ..b_tail])
} }
} }

View File

@ -1,7 +1,9 @@
pub fn map(opt: Option<a>, f: fn(a) -> b) -> Option<b> { pub fn map(opt: Option<a>, f: fn(a) -> b) -> Option<b> {
when opt is { when opt is {
None -> None None ->
Some(a) -> Some(f(a)) None
Some(a) ->
Some(f(a))
} }
} }

View File

@ -1,7 +1,9 @@
pub fn map(xs: List<a>, f: fn(a) -> result) -> List<result> { pub fn map(xs: List<a>, f: fn(a) -> result) -> List<result> {
when xs is { when xs is {
[] -> [] [] ->
[x, ..rest] -> [f(x), ..map(rest, f)] []
[x, ..rest] ->
[f(x), ..map(rest, f)]
} }
} }

View File

@ -2,7 +2,8 @@ use aiken/builtin
pub fn filter(xs: List<a>, f: fn(a) -> Bool) -> List<a> { pub fn filter(xs: List<a>, f: fn(a) -> Bool) -> List<a> {
when xs is { when xs is {
[] -> [] [] ->
[]
[x, ..rest] -> [x, ..rest] ->
if f(x) { if f(x) {
[x, ..filter(rest, f)] [x, ..filter(rest, f)]

View File

@ -1,8 +1,10 @@
pub fn unzip(xs: List<(a, b)>) -> (List<a>, List<b>) { pub fn unzip(xs: List<(a, b)>) -> (List<a>, List<b>) {
when xs is { when xs is {
[] -> ([], []) [] ->
([], [])
[(a, b), ..rest] -> { [(a, b), ..rest] -> {
let (a_tail, b_tail) = unzip(rest) let (a_tail, b_tail) =
unzip(rest)
([a, ..a_tail], [b, ..b_tail]) ([a, ..a_tail], [b, ..b_tail])
} }
} }

View File

@ -13,6 +13,7 @@ pub fn drop(bytes: ByteArray, n: Int) -> ByteArray {
} }
test drop_1() { test drop_1() {
let x = #"01020304050607" let x =
#"01020304050607"
drop(x, 2) == #"0304050607" drop(x, 2) == #"0304050607"
} }

View File

@ -1,7 +1,9 @@
pub fn or_else(opt: Option<a>, default: a) -> a { pub fn or_else(opt: Option<a>, default: a) -> a {
when opt is { when opt is {
None -> default None ->
Some(a) -> a default
Some(a) ->
a
} }
} }

View File

@ -1,7 +1,9 @@
pub fn map(opt: Option<a>, f: fn(a) -> result) -> Option<result> { pub fn map(opt: Option<a>, f: fn(a) -> result) -> Option<result> {
when opt is { when opt is {
None -> None None ->
Some(a) -> Some(f(a)) None
Some(a) ->
Some(f(a))
} }
} }

View File

@ -1,7 +1,9 @@
pub fn map(opt: Option<a>, f: fn(a) -> result) -> Option<result> { pub fn map(opt: Option<a>, f: fn(a) -> result) -> Option<result> {
when opt is { when opt is {
None -> None None ->
Some(a) -> Some(f(a)) None
Some(a) ->
Some(f(a))
} }
} }

View File

@ -1,7 +1,9 @@
pub fn foldr(xs: List<a>, f: fn(a, b) -> b, zero: b) -> b { pub fn foldr(xs: List<a>, f: fn(a, b) -> b, zero: b) -> b {
when xs is { 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, xs,
fn(x, ys) { fn(x, ys) {
when f(x) is { when f(x) is {
None -> ys None ->
Some(y) -> [y, ..ys] ys
Some(y) ->
[y, ..ys]
} }
}, },
[], [],

View File

@ -20,7 +20,8 @@ pub fn insert(
fn do_insert(elems: List<(key, value)>, k: key, v: value) -> List<(key, value)> { fn do_insert(elems: List<(key, value)>, k: key, v: value) -> List<(key, value)> {
when elems is { when elems is {
[] -> [(k, v)] [] ->
[(k, v)]
[(k2, v2), ..rest] -> [(k2, v2), ..rest] ->
if k == k2 { if k == k2 {
[(k, v), ..rest] [(k, v), ..rest]
@ -32,8 +33,8 @@ fn do_insert(elems: List<(key, value)>, k: key, v: value) -> List<(key, value)>
fn fixture_1() { fn fixture_1() {
new() new()
|> insert("foo", 42) |> insert("foo", 42)
|> insert("bar", 14) |> insert("bar", 14)
} }
test to_list_2() { test to_list_2() {

View File

@ -4,11 +4,14 @@ pub fn map2(
f: fn(a, b) -> result, f: fn(a, b) -> result,
) -> Option<result> { ) -> Option<result> {
when opt_a is { when opt_a is {
None -> None None ->
None
Some(a) -> Some(a) ->
when opt_b is { when opt_b is {
None -> None None ->
Some(b) -> Some(f(a, b)) None
Some(b) ->
Some(f(a, b))
} }
} }
} }

View File

@ -1,7 +1,9 @@
pub fn foldr(xs: List<a>, f: fn(a, b) -> b, zero: b) -> b { pub fn foldr(xs: List<a>, f: fn(a, b) -> b, zero: b) -> b {
when xs is { 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> { pub fn flat_map(xs: List<a>, f: fn(a) -> List<b>) -> List<b> {
when xs is { when xs is {
[] -> [] [] ->
[x, ..rest] -> concat(f(x), flat_map(rest, f)) []
[x, ..rest] ->
concat(f(x), flat_map(rest, f))
} }
} }

View File

@ -1,6 +1,7 @@
pub fn filter(xs: List<a>, f: fn(a) -> Bool) -> List<a> { pub fn filter(xs: List<a>, f: fn(a) -> Bool) -> List<a> {
when xs is { when xs is {
[] -> [] [] ->
[]
[x, ..rest] -> [x, ..rest] ->
if f(x) { if f(x) {
[x, ..filter(rest, f)] [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> { pub fn unique(xs: List<a>) -> List<a> {
when xs is { 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() { test unique_2() {
let xs = [1, 2, 3, 1] let xs =
[1, 2, 3, 1]
unique(xs) == [1, 2, 3] unique(xs) == [1, 2, 3]
} }

View File

@ -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)> { fn do_from_list(xs: List<(key, value)>) -> List<(key, value)> {
when xs is { 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)> { fn do_insert(elems: List<(key, value)>, k: key, v: value) -> List<(key, value)> {
when elems is { when elems is {
[] -> [(k, v)] [] ->
[(k, v)]
[(k2, v2), ..rest] -> [(k2, v2), ..rest] ->
if k == k2 { if k == k2 {
[(k, v), ..rest] [(k, v), ..rest]
@ -49,15 +52,17 @@ fn do_union(
right: List<(key, value)>, right: List<(key, value)>,
) -> List<(key, value)> { ) -> List<(key, value)> {
when left is { 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() { fn fixture_1() {
new() new()
|> insert("foo", 42) |> insert("foo", 42)
|> insert("bar", 14) |> insert("bar", 14)
} }
test union_1() { test union_1() {

View File

@ -5,7 +5,7 @@ fn concat(left: String, right: String) -> String {
builtin.encode_utf8(left), builtin.encode_utf8(left),
builtin.encode_utf8(right), builtin.encode_utf8(right),
) )
|> builtin.decode_utf8 |> builtin.decode_utf8
} }
fn is_negative(i: Int) -> Bool { fn is_negative(i: Int) -> Bool {

View File

@ -1,4 +1,5 @@
test tuple_1() { test tuple_1() {
let coordinates = (14, 42) let coordinates =
(14, 42)
coordinates.1st == 14 && coordinates.2nd == 42 coordinates.1st == 14 && coordinates.2nd == 42
} }

View File

@ -1,7 +1,9 @@
pub fn foldr(self: List<a>, with: fn(a, b) -> b, zero: b) -> b { pub fn foldr(self: List<a>, with: fn(a, b) -> b, zero: b) -> b {
when self is { when self is {
[] -> zero [] ->
[x, ..xs] -> with(x, foldr(xs, with, zero)) zero
[x, ..xs] ->
with(x, foldr(xs, with, zero))
} }
} }

View File

@ -37,7 +37,8 @@ fn do_union_with(
with: fn(ByteArray, value, value) -> Option<value>, with: fn(ByteArray, value, value) -> Option<value>,
) -> List<(ByteArray, value)> { ) -> List<(ByteArray, value)> {
when left is { when left is {
[] -> right [] ->
right
[(k, v), ..rest] -> [(k, v), ..rest] ->
do_union_with(rest, do_insert_with(right, k, v, with), with) 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>, with: fn(ByteArray, value, value) -> Option<value>,
) -> List<(ByteArray, value)> { ) -> List<(ByteArray, value)> {
when self is { when self is {
[] -> [(k, v)] [] ->
[(k, v)]
[(k2, v2), ..rest] -> [(k2, v2), ..rest] ->
if k == k2 { if k == k2 {
when with(k, v, v2) is { when with(k, v, v2) is {
Some(combined) -> [(k, combined), ..rest] Some(combined) ->
None -> rest [(k, combined), ..rest]
None ->
rest
} }
} else { } else {
[(k2, v2), ..do_insert_with(rest, k, v, with)] [(k2, v2), ..do_insert_with(rest, k, v, with)]

View File

@ -16,9 +16,9 @@ pub fn from_asset(
) -> Value { ) -> Value {
let asset = let asset =
dict.new() dict.new()
|> dict.insert(asset_name, quantity) |> dict.insert(asset_name, quantity)
dict.new() dict.new()
|> dict.insert(policy_id, asset) |> dict.insert(policy_id, asset)
} }
pub fn from_lovelace(quantity: Int) -> Value { pub fn from_lovelace(quantity: Int) -> Value {
@ -35,7 +35,8 @@ pub fn add(left v0: Value, right v1: Value) -> Value {
a0, a0,
a1, a1,
fn(_, q0, q1) { fn(_, q0, q1) {
let q = q0 + q1 let q =
q0 + q1
if q == 0 { if q == 0 {
None None
} else { } else {
@ -45,15 +46,19 @@ pub fn add(left v0: Value, right v1: Value) -> Value {
) )
when dict.toList(asset) is { when dict.toList(asset) is {
[] -> None [] ->
_ -> Some(asset) None
_ ->
Some(asset)
} }
}, },
) )
} }
test add_1() { test add_1() {
let v1 = from_lovelace(1) let v1 =
let v2 = from_lovelace(-1) from_lovelace(1)
let v2 =
from_lovelace(-1)
add(v1, v2) == dict.new() add(v1, v2) == dict.new()
} }

View File

@ -3,19 +3,20 @@ use aiken/list
use aiken/transaction.{Output, OutputReference, ScriptContext} use aiken/transaction.{Output, OutputReference, ScriptContext}
use aiken/transaction/value.{PolicyId} 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 { pub fn has_policy_id(self: Output, policy_id: PolicyId) -> Bool {
self.value self.value
|> value.tokens(policy_id) |> value.tokens(policy_id)
|> dict.is_empty |> dict.is_empty
|> not |> not
} }
validator spend { validator spend {
fn(_datum: Data, _redeemer: Data, ctx: ScriptContext) -> Bool { fn(_datum: Data, _redeemer: Data, ctx: ScriptContext) -> Bool {
ctx.transaction.outputs 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 }, fn(input) { input.output_reference == output_reference },
) )
is { is {
Some(_) -> True Some(_) ->
None -> False True
None ->
False
} }
} }
} }

View File

@ -1,7 +1,9 @@
pub fn and(self: List<Bool>) -> Bool { pub fn and(self: List<Bool>) -> Bool {
when self is { 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 { pub fn or(self: List<Bool>) -> Bool {
when self is { when self is {
[] -> False [] ->
[x, ..xs] -> x || or(xs) False
[x, ..xs] ->
x || or(xs)
} }
} }

View File

@ -28,7 +28,8 @@ test expect_ford1() {
builtin.list_data([]), 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 owner == #"" && wheels == 4 && truck_bed_limit == 10000
} }
@ -41,26 +42,32 @@ test expect_ford2() {
truck_bed_limit: 15000, truck_bed_limit: 15000,
car_doors: [], car_doors: [],
} }
expect Ford { owner, wheels, remote_connect, .. } = initial_car expect Ford { owner, wheels, remote_connect, .. } =
initial_car
owner == #"2222222222" && wheels == 6 && remote_connect == #"" owner == #"2222222222" && wheels == 6 && remote_connect == #""
} }
test expect_list1() { test expect_list1() {
let initial_car = [5, 6, 7] let initial_car =
expect [a, b, c] = initial_car [5, 6, 7]
expect [a, b, c] =
initial_car
a == 5 && b == 6 && c == 7 a == 5 && b == 6 && c == 7
} }
test expect_list2() { test expect_list2() {
let initial_car = [5, 6, 7] let initial_car =
expect [a, ..d] = initial_car [5, 6, 7]
expect [a, ..d] =
initial_car
a == 5 && d == [6, 7] a == 5 && d == [6, 7]
} }
test expect_list3() { test expect_list3() {
let initial_car = let initial_car =
builtin.list_data([builtin.i_data(5), builtin.i_data(6), builtin.i_data(7)]) 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] a == 5 && d == [6, 7]
} }
@ -69,16 +76,22 @@ type Redeemer {
} }
test single_field_expect() { test single_field_expect() {
let redeemer = CreateVoteBatch { id: #"" } let redeemer =
expect CreateVoteBatch { id } = redeemer CreateVoteBatch { id: #"" }
expect CreateVoteBatch { id } =
redeemer
id == #"" id == #""
} }
test single_when() { test single_when() {
let redeemer = CreateVoteBatch { id: #"" } let redeemer =
let x = when redeemer is { CreateVoteBatch { id: #"" }
CreateVoteBatch { id } -> id == #"" let x =
_ -> False when redeemer is {
} CreateVoteBatch { id } ->
id == #""
_ ->
False
}
x == True x == True
} }

View File

@ -1,16 +1,23 @@
test foo_1() { test foo_1() {
let a = False let a =
False
when a is { when a is {
True -> False True ->
False -> True False
False ->
True
} }
} }
test foo_2() { test foo_2() {
let a = False let a =
let b = when a is { False
True -> 14 let b =
False -> 42 when a is {
} True ->
14
False ->
42
}
b == 42 b == 42
} }

View File

@ -9,7 +9,9 @@ fn fibonnaci(n) {
} }
test foo() { test foo() {
let right = fn() { fibonnaci(15) == 610 } let right =
let left = False fn() { fibonnaci(15) == 610 }
let left =
False
left || right() left || right()
} }

View File

@ -1,9 +1,14 @@
test sort_by_1() { 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 { when xs is {
[[], ys] -> False [[], ys] ->
[xs, []] -> False False
[[x, ..xs2], [y, ..ys2]] -> True [xs, []] ->
_ -> False False
[[x, ..xs2], [y, ..ys2]] ->
True
_ ->
False
} }
} }

View File

@ -1,33 +1,47 @@
test foo_1() { test foo_1() {
let a = False let a =
False
when a is { when a is {
a if a -> False a if a ->
_ -> True False
_ ->
True
} }
} }
test foo_2() { test foo_2() {
let point = (14, 42) let point =
(14, 42)
when point is { when point is {
(x, _) if x > 100 -> False (x, _) if x > 100 ->
(x, _) if x > 10 -> True False
_ -> False (x, _) if x > 10 ->
True
_ ->
False
} }
} }
test foo_3() { test foo_3() {
let point = (14, 42) let point =
(14, 42)
when point is { when point is {
(x, y) if x == 14 && y <= 100 -> True (x, y) if x == 14 && y <= 100 ->
_ -> False True
_ ->
False
} }
} }
test foo_4() { test foo_4() {
let a = False let a =
let point = (14, 42) False
let point =
(14, 42)
when point is { when point is {
(x, y) if !a -> x + y == 56 (x, y) if !a ->
_ -> False x + y == 56
_ ->
False
} }
} }

View File

@ -1,6 +1,7 @@
fn when_tuple(a: (Int, Int)) -> Int { fn when_tuple(a: (Int, Int)) -> Int {
when a is { when a is {
(a, b) -> a (a, b) ->
a
} }
} }

View File

@ -1,6 +1,7 @@
pub fn when_tuple(a: (Int, Int)) -> Int { pub fn when_tuple(a: (Int, Int)) -> Int {
when a is { when a is {
(a, b) -> a (a, b) ->
a
} }
} }

View File

@ -5,46 +5,55 @@ pub type Thing {
} }
test let_1() { test let_1() {
let x: Data = 1 let x: Data =
1
x == builtin.i_data(1) x == builtin.i_data(1)
} }
test let_2() { test let_2() {
let x: Data = 1 let x: Data =
1
expect y: Int = x expect y: Int =
x
y == 1 y == 1
} }
test assert_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 thing.wow == 1
} }
fn cast_to_thing(x: Data) -> Thing { fn cast_to_thing(x: Data) -> Thing {
expect x: Thing = x expect x: Thing =
x
x x
} }
test assert_2() { 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 still_thing.wow == 1
} }
test tuple_1() { test tuple_1() {
let thing = (#"aa", #"bb", #"cc") let thing =
(#"aa", #"bb", #"cc")
thing.1st == #"aa" thing.1st == #"aa"
} }
test pair_1() { test pair_1() {
let thing = (#"aa", #"bb") let thing =
(#"aa", #"bb")
thing.1st == #"aa" thing.1st == #"aa"
} }
// should not typecheck // should not typecheck

View File

@ -3,15 +3,20 @@ type TransactionId {
} }
test pattern_match_let() { test pattern_match_let() {
let x = TransactionId { inner: #"0000" } let x =
let TransactionId(y) = x TransactionId { inner: #"0000" }
let TransactionId(y) =
x
y == #"0000" y == #"0000"
} }
test pattern_match_when() { test pattern_match_when() {
let x = TransactionId { inner: #"0000" } let x =
let y = when x is { TransactionId { inner: #"0000" }
TransactionId(y) -> y let y =
} when x is {
TransactionId(y) ->
y
}
y == #"0000" y == #"0000"
} }

View File

@ -5,12 +5,15 @@ pub type LinkedList<a> {
pub fn size(t: LinkedList<alg>) -> Int { pub fn size(t: LinkedList<alg>) -> Int {
when t is { when t is {
Empty -> 0 Empty ->
Node(_, tail) -> 1 + size(tail) 0
Node(_, tail) ->
1 + size(tail)
} }
} }
test foo() { test foo() {
let xs = Node(0, Node(1, Node(2, Empty))) let xs =
Node(0, Node(1, Node(2, Empty)))
size(xs) == 3 size(xs) == 3
} }

View File

@ -1,6 +1,7 @@
use aiken/transaction/value use aiken/transaction/value
test test_quantity_of_1() { 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 value.quantity_of(x, #"000000", #"000020e05363726970744f776e6572") < 0
} }

View File

@ -15,9 +15,12 @@ pub type MerkleTree {
pub fn root_hash(t: MerkleTree) -> Hash<Sha2_256, ByteArray> { pub fn root_hash(t: MerkleTree) -> Hash<Sha2_256, ByteArray> {
when t is { when t is {
Empty -> #"" Empty ->
Leaf { hash, .. } -> hash #""
Node { hash, .. } -> hash 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 { pub fn size(t: MerkleTree) -> Int {
when t is { when t is {
Empty -> 0 Empty ->
Leaf{..} -> 1 0
Node { left, right, .. } -> size(left) + size(right) 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 { fn do_from_list(items: List<ByteArray>, len: Int) -> MerkleTree {
when items is { when items is {
[] -> Empty [] ->
[value] -> Leaf { hash: sha2_256(value), value } Empty
[value] ->
Leaf { hash: sha2_256(value), value }
all -> { all -> {
let cutoff: Int = len / 2 let cutoff: Int =
len / 2
let left = let left =
all all
|> list.take(cutoff) |> list.take(cutoff)
|> do_from_list(cutoff) |> do_from_list(cutoff)
let right = let right =
all all
|> list.drop(cutoff) |> list.drop(cutoff)
|> do_from_list(len - cutoff) |> do_from_list(len - cutoff)
let hash = combine_hash(root_hash(left), root_hash(right)) let hash =
combine_hash(root_hash(left), root_hash(right))
Node { hash, left, right } Node { hash, left, right }
} }
} }
} }
test foo() { test foo() {
let items = [#"aa", #"bb", #"cc"] let items =
let mt = from_list(items) [#"aa", #"bb", #"cc"]
let mt =
from_list(items)
size(mt) == 3 size(mt) == 3
} }
@ -72,20 +84,24 @@ test some_test1() {
} }
test intersection_3() { test intersection_3() {
let iv1 = between(0, 1) let iv1 =
let iv2 = strictly_between(1, 2) between(0, 1)
let iv2 =
strictly_between(1, 2)
intersection(iv1, iv2) intersection(iv1, iv2)
|> is_empty |> is_empty
} }
const fooz = #"666f6f" const fooz =
#"666f6f"
const bar = #"626172" const bar =
#"626172"
fn fixture_1() { fn fixture_1() {
dict.new() dict.new()
|> dict.insert(fooz, 42, bytearray.compare) |> dict.insert(fooz, 42, bytearray.compare)
|> dict.insert(bar, 14, bytearray.compare) |> dict.insert(bar, 14, bytearray.compare)
} }
test union_1() { test union_1() {

View File

@ -1,9 +1,12 @@
// Could possibly be forbidden by the parser instead if we have no intent to support that. // 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> { pub fn choice(self: List<Option<a>>) -> Option<a> {
when self is { when self is {
[] -> None [] ->
[Some(_) as result, ..] -> result None
[None, ..others] -> choice(others) [Some(_) as result, ..] ->
result
[None, ..others] ->
choice(others)
} }
} }

View File

@ -1,8 +1,11 @@
pub fn choice(self: List<Option<a>>) -> Option<a> { pub fn choice(self: List<Option<a>>) -> Option<a> {
when self is { when self is {
[] -> None [] ->
[Some(x), ..] -> Some(x) None
[None, ..others] -> choice(others) [Some(x), ..] ->
Some(x)
[None, ..others] ->
choice(others)
} }
} }

View File

@ -1,8 +1,11 @@
pub fn choice(self: List<Option<a>>) -> Option<a> { pub fn choice(self: List<Option<a>>) -> Option<a> {
when self is { when self is {
[] -> None [] ->
[None, ..others] -> choice(others) None
[result, ..] -> result [None, ..others] ->
choice(others)
[result, ..] ->
result
} }
} }

View File

@ -1,9 +1,13 @@
pub fn alt(left: Option<a>, right: Option<a>) -> Option<a> { pub fn alt(left: Option<a>, right: Option<a>) -> Option<a> {
when (left, right) is { when (left, right) is {
(Some(a), Some(_)) -> Some(a) (Some(a), Some(_)) ->
(None, Some(a)) -> Some(a) Some(a)
(Some(a), None) -> Some(a) (None, Some(a)) ->
(None, None) -> None Some(a)
(Some(a), None) ->
Some(a)
(None, None) ->
None
} }
} }

View File

@ -3,17 +3,23 @@ fn whatever(_xs) {
} }
test foo() { test foo() {
let xs = [1, 2, 3] let xs =
[1, 2, 3]
when xs is { when xs is {
[x] -> x == 1 [x] ->
_ -> whatever(xs) x == 1
_ ->
whatever(xs)
} }
} }
test bar() { test bar() {
let xs = [1, 2, 3] let xs =
[1, 2, 3]
when xs is { when xs is {
[x] -> x == 1 [x] ->
ys -> whatever(ys) x == 1
ys ->
whatever(ys)
} }
} }

View File

@ -1,17 +1,24 @@
test foo() { test foo() {
let xs = [[1, 2], [4, 5]] let xs =
[[1, 2], [4, 5]]
when xs is { when xs is {
[[_, _], [_, _]] -> True [[_, _], [_, _]] ->
_ -> False True
_ ->
False
} }
} }
test sort_by_1() { test sort_by_1() {
let xs = [[4, 3], [2, 3]] let xs =
let g = when xs is { [[4, 3], [2, 3]]
[[x, xs2], [y, ys2]] -> True let g =
_ -> False when xs is {
} [[x, xs2], [y, ys2]] ->
True
_ ->
False
}
g == True g == True
} }

View File

@ -1,16 +1,19 @@
const int_constant = 42 const int_constant =
42
test int() { test int() {
int_constant == 42 int_constant == 42
} }
const bytearray_constant = #"abcd" const bytearray_constant =
#"abcd"
test bytearray() { test bytearray() {
bytearray_constant == #"abcd" bytearray_constant == #"abcd"
} }
const string_constant = "FOO" const string_constant =
"FOO"
test string() { test string() {
string_constant == "FOO" string_constant == "FOO"

View File

@ -8,9 +8,11 @@ use aiken/transaction/credential.{
} }
use aiken/transaction/value 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>) { pub fn keyhash_address(with_stake_credential: Option<StakeCredential>) {
Address { Address {
@ -32,7 +34,8 @@ type SampleData {
} }
pub fn tx_1() -> Transaction { pub fn tx_1() -> Transaction {
let sample_datum = SampleData { a: 1, b: #"01" } let sample_datum =
SampleData { a: 1, b: #"01" }
let tx = let tx =
Transaction { Transaction {
inputs: [ inputs: [

View File

@ -4,7 +4,8 @@ fn must_be_signed(signatories) {
trace @"no signatories" trace @"no signatories"
False False
} }
[sig, ..] -> (sig == "#ffff")? [sig, ..] ->
(sig == "#ffff")?
} }
} }

View File

@ -15,14 +15,16 @@ test foo() {
fn map(list: List<a>, f: fn(a) -> b) -> List<b> { fn map(list: List<a>, f: fn(a) -> b) -> List<b> {
when list is { when list is {
[] -> [] [] ->
[x, ..xs] -> [f(x), ..map(xs, f)] []
[x, ..xs] ->
[f(x), ..map(xs, f)]
} }
} }
fn get_fields(data: Data) -> List<Int> { fn get_fields(data: Data) -> List<Int> {
builtin.un_constr_data(data).2nd builtin.un_constr_data(data).2nd
|> map(builtin.un_i_data) |> map(builtin.un_i_data)
} }
test bar() { test bar() {

View File

@ -37,13 +37,13 @@ fn inspect_list(_data: Data) -> Data {
fn inspect_integer(data: Data) -> Data { fn inspect_integer(data: Data) -> Data {
let result: Data = let result: Data =
builtin.un_i_data(data) builtin.un_i_data(data)
|> Integer |> Integer
result result
} }
fn inspect_bytearray(data: Data) -> Data { fn inspect_bytearray(data: Data) -> Data {
let result: Data = let result: Data =
builtin.un_b_data(data) builtin.un_b_data(data)
|> Bytes |> Bytes
result result
} }

View File

@ -33,20 +33,29 @@ pub type ProofItem {
/// Deconstruct a 'MerkleTree' back to a list of elements. /// Deconstruct a 'MerkleTree' back to a list of elements.
pub fn to_list(self: MerkleTree<a>) -> List<a> { pub fn to_list(self: MerkleTree<a>) -> List<a> {
when self is { when self is {
Empty -> [] Empty ->
Leaf { value, .. } -> [value] []
Node { left, right, .. } -> list.concat(to_list(left), to_list(right)) Leaf { value, .. } ->
[value]
Node { left, right, .. } ->
list.concat(to_list(left), to_list(right))
} }
} }
test to_list_1() { test to_list_1() {
let dog = "dog" let dog =
let cat = "cat" "dog"
let mouse = "mouse" let cat =
let items = [dog, cat, mouse] "cat"
let hash_fn = create_string_item_hash_fn() 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) items == to_list(mt)
} }
@ -54,47 +63,68 @@ test to_list_1() {
// Function returning a hash of a given Merkle Tree element // Function returning a hash of a given Merkle Tree element
pub fn root_hash(self: MerkleTree<a>) -> Hash<Sha2_256, ByteArray> { pub fn root_hash(self: MerkleTree<a>) -> Hash<Sha2_256, ByteArray> {
when self is { when self is {
Empty -> "" Empty ->
Leaf { hash, .. } -> hash ""
Node { hash, .. } -> hash Leaf { hash, .. } ->
hash
Node { hash, .. } ->
hash
} }
} }
test root_hash_1() { test root_hash_1() {
let dog = "dog" let dog =
let items = [dog] "dog"
let hash_fn = create_string_item_hash_fn() 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 root_hash(mt) == node_hash
} }
test root_hash_3() { test root_hash_3() {
let dog = "dog" let dog =
let cat = "cat" "dog"
let mouse = "mouse" let cat =
let items = [dog, cat, mouse] "cat"
let hash_fn = create_string_item_hash_fn() 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 node_hash =
let rh = sha2_256(bytearray.concat(hash_fn(dog), 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 rh == root_hash
} }
test root_hash_2() { test root_hash_2() {
let items = [] let items =
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 = #"" let node_hash =
#""
root_hash(mt) == 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. /// Function returns a total numbers of leaves in the tree.
pub fn size(self: MerkleTree<a>) -> Int { pub fn size(self: MerkleTree<a>) -> Int {
when self is { when self is {
Empty -> 0 Empty ->
Leaf{..} -> 1 0
Node { left, right, .. } -> size(left) + size(right) Leaf{..} ->
1
Node { left, right, .. } ->
size(left) + size(right)
} }
} }
test size_1() { test size_1() {
let items = [] let items =
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)
size(mt) == 0 size(mt) == 0
} }
test size_2() { test size_2() {
let dog = "dog" let dog =
let cat = "cat" "dog"
let mouse = "mouse" let cat =
let hash_fn = create_string_item_hash_fn() "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 size(mt) == 3
} }
test size_3() { test size_3() {
let dog = "dog" let dog =
let cat = "cat" "dog"
let mouse = "mouse" let cat =
let items = [dog, cat, mouse] "cat"
let hash_fn = create_string_item_hash_fn() 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 size(mt) == 3
} }
test size_4() { test size_4() {
let dog = "dog" let dog =
let cat = "cat" "dog"
let mouse = "mouse" let cat =
let horse = "horse" "cat"
let pig = "pig" let mouse =
let bull = "bull" "mouse"
let horse =
"horse"
let pig =
"pig"
let bull =
"bull"
let hash_fn = create_string_item_hash_fn() let hash_fn =
let items = [dog, cat, mouse, horse, pig, bull] 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 size(mt) == 6
} }
@ -166,22 +222,28 @@ fn combine_hash(
/// Function that returns whether merkle tree has any elements /// Function that returns whether merkle tree has any elements
pub fn is_empty(self: MerkleTree<a>) -> Bool { pub fn is_empty(self: MerkleTree<a>) -> Bool {
when self is { when self is {
Empty -> True Empty ->
_ -> False True
_ ->
False
} }
} }
test is_empty_1() { test is_empty_1() {
let mt = Empty let mt =
Empty
is_empty(mt) is_empty(mt)
} }
test is_empty_2() { test is_empty_2() {
let dog = "dog" let dog =
let hash = create_string_item_hash_fn() "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 is_empty(mt) == False
} }
@ -193,7 +255,8 @@ fn do_proof(
hash_fn: fn(a) -> Hash<Sha2_256, a>, hash_fn: fn(a) -> Hash<Sha2_256, a>,
) -> Option<Proof> { ) -> Option<Proof> {
when self is { when self is {
Empty -> None Empty ->
None
Leaf { hash, .. } -> Leaf { hash, .. } ->
if hash == item_hash { if hash == item_hash {
Some(proof) Some(proof)
@ -201,8 +264,10 @@ fn do_proof(
None None
} }
Node { left, right, .. } -> { Node { left, right, .. } -> {
let rh = root_hash(right) let rh =
let lh = root_hash(left) root_hash(right)
let lh =
root_hash(left)
let go_left: Option<Proof> = let go_left: Option<Proof> =
do_proof(left, item_hash, list.push(proof, Right { hash: rh }), hash_fn) do_proof(left, item_hash, list.push(proof, Right { hash: rh }), hash_fn)
let go_right: Option<Proof> = let go_right: Option<Proof> =
@ -220,93 +285,137 @@ pub fn get_proof(
item: a, item: a,
hash_fn: fn(a) -> Hash<Sha2_256, a>, hash_fn: fn(a) -> Hash<Sha2_256, a>,
) -> Option<Proof> { ) -> Option<Proof> {
let empty: Proof = [] let empty: Proof =
[]
do_proof(self, hash_fn(item), empty, hash_fn) do_proof(self, hash_fn(item), empty, hash_fn)
} }
test get_proof_1() { test get_proof_1() {
let dog = "dog" let dog =
let cat = "cat" "dog"
let mouse = "mouse" let cat =
let horse = "horse" "cat"
let pig = "pig" let mouse =
let bull = "bull" "mouse"
let horse =
"horse"
let pig =
"pig"
let bull =
"bull"
let items = [dog, cat, mouse, horse, pig, bull] let items =
let hash_fn = create_string_item_hash_fn() [dog, cat, mouse, horse, pig, bull]
let hash_fn =
create_string_item_hash_fn()
let mt = from_list(items, hash_fn) let mt =
let hash_fn = create_string_item_hash_fn() 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) is_none(maybe_proof)
} }
test get_proof_2() { test get_proof_2() {
let dog = "dog" let dog =
"dog"
let items = [dog] let items =
let hash_fn = create_string_item_hash_fn() [dog]
let mt = from_list(items, hash_fn) 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 // when proof is empty list it actually means that root of the tree is in fact element
proof == [] proof == []
} }
test get_proof_3() { test get_proof_3() {
let dog = "dog" let dog =
let cat = "cat" "dog"
let mouse = "mouse" 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 hash_fn =
let mt = from_list(items, 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 size_match && h1 == node_hash
} }
test get_proof_4() { test get_proof_4() {
let dog = "dog" let dog =
let cat = "cat" "dog"
let mouse = "mouse" let cat =
let horse = "horse" "cat"
let mouse =
"mouse"
let horse =
"horse"
let items = [dog, cat, mouse, horse] let items =
let hash_fn = create_string_item_hash_fn() [dog, cat, mouse, horse]
let mt = from_list(items, hash_fn) let hash_fn =
create_string_item_hash_fn()
let mt =
from_list(items, hash_fn)
let right_node_hash = let right_node_hash =
sha2_256(bytearray.concat(hash_fn(mouse), hash_fn(horse))) 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(p1) =
expect Some(p2) = list.at(proof, 1) list.at(proof, 0)
expect Some(p2) =
list.at(proof, 1)
let h1: ByteArray = get_proof_item_value(p1) let h1: ByteArray =
let h2: ByteArray = get_proof_item_value(p2) get_proof_item_value(p1)
let h2: ByteArray =
get_proof_item_value(p2)
size_match && h1 == hash_fn(cat) && h2 == right_node_hash 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>, hash_fn: fn(a) -> Hash<Sha2_256, a>,
) -> MerkleTree<a> { ) -> MerkleTree<a> {
when items is { when items is {
[] -> Empty [] ->
Empty
[item] -> { [item] -> {
let hashed_item = hash_fn(item) let hashed_item =
hash_fn(item)
Leaf { value: item, hash: hashed_item } Leaf { value: item, hash: hashed_item }
} }
all -> { all -> {
let cutoff: Int = len / 2 let cutoff: Int =
len / 2
let left = let left =
all all
|> list.take(cutoff) |> list.take(cutoff)
|> do_from_list(cutoff, hash_fn) |> do_from_list(cutoff, hash_fn)
let right = let right =
all all
|> list.drop(cutoff) |> list.drop(cutoff)
|> do_from_list(len - cutoff, hash_fn) |> do_from_list(len - cutoff, hash_fn)
let hash = combine_hash(root_hash(left), root_hash(right)) let hash =
combine_hash(root_hash(left), root_hash(right))
Node { hash, left, right } Node { hash, left, right }
} }
} }
@ -349,32 +462,46 @@ pub fn from_list(
} }
test from_1() { test from_1() {
let _a = -1 let _a =
let items = [] -1
let hash_fn = create_string_item_hash_fn() let items =
let mt = from_list(items, hash_fn) []
let hash_fn =
create_string_item_hash_fn()
let mt =
from_list(items, hash_fn)
Empty == mt Empty == mt
} }
test from_2() { test from_2() {
let dog = "dog" let dog =
let items = [dog] "dog"
let hash_fn = create_string_item_hash_fn() let items =
let mt = from_list(items, hash_fn) [dog]
let hash_fn =
create_string_item_hash_fn()
let mt =
from_list(items, hash_fn)
Leaf { value: dog, hash: hash_fn(dog) } == mt Leaf { value: dog, hash: hash_fn(dog) } == mt
} }
test from_3() { test from_3() {
let dog = "dog" let dog =
let cat = "cat" "dog"
let items = [dog, cat] let cat =
"cat"
let items =
[dog, cat]
let hash_fn = create_string_item_hash_fn() let hash_fn =
let mt = from_list(items, 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 { Node {
hash: root_hash, hash: root_hash,
@ -384,17 +511,25 @@ test from_3() {
} }
test from_4() { test from_4() {
let dog = "dog" let dog =
let cat = "cat" "dog"
let mouse = "mouse" let cat =
"cat"
let mouse =
"mouse"
let items = [dog, cat, mouse] let items =
let hash_fn = create_string_item_hash_fn() [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 node_hash =
let root_hash = sha2_256(bytearray.concat(hash_fn(dog), 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 { Node {
hash: root_hash, hash: root_hash,
@ -408,21 +543,30 @@ test from_4() {
} }
test from_5() { test from_5() {
let dog = "dog" let dog =
let cat = "cat" "dog"
let mouse = "mouse" let cat =
let horse = "horse" "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 items =
let mt = from_list(items, hash_fn) [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 = let right_node_hash =
sha2_256(bytearray.concat(hash_fn(mouse), hash_fn(horse))) 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 { Node {
hash: root_hash, hash: root_hash,
@ -450,7 +594,8 @@ pub fn member_from_hash(
hash_fn: fn(a) -> Hash<Sha2_256, a>, hash_fn: fn(a) -> Hash<Sha2_256, a>,
) -> Bool { ) -> Bool {
when proof is { when proof is {
[] -> root_hash == item_hash [] ->
root_hash == item_hash
[head, ..tail] -> [head, ..tail] ->
when head is { when head is {
Left { hash: l } -> Left { hash: l } ->
@ -469,113 +614,173 @@ pub fn member(
proof: Proof, proof: Proof,
hash_fn: fn(a) -> Hash<Sha2_256, a>, hash_fn: fn(a) -> Hash<Sha2_256, a>,
) -> Bool { ) -> Bool {
let item_hash = hash_fn(item) let item_hash =
hash_fn(item)
member_from_hash(item_hash, root_hash, proof, hash_fn) member_from_hash(item_hash, root_hash, proof, hash_fn)
} }
test member_1() { test member_1() {
let dog = "dog" let dog =
let items = [dog] "dog"
let hash_fn = create_string_item_hash_fn() let items =
let mt = from_list(items, hash_fn) [dog]
let hash_fn =
create_string_item_hash_fn()
let mt =
from_list(items, hash_fn)
let item = dog let item =
let rh = root_hash(mt) 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) member(item: item, root_hash: rh, proof: proof, hash_fn: hash_fn)
} }
test member_2() { test member_2() {
let dog = "dog" let dog =
let cat = "cat" "dog"
let mouse = "mouse" let cat =
let horse = "horse" "cat"
let mouse =
"mouse"
let horse =
"horse"
let items = [dog, cat, mouse, horse] let items =
let hash_fn = create_string_item_hash_fn() [dog, cat, mouse, horse]
let mt = from_list(items, hash_fn) let hash_fn =
create_string_item_hash_fn()
let mt =
from_list(items, hash_fn)
let item = cat let item =
let rh = root_hash(mt) 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) member(item: item, root_hash: rh, proof: proof, hash_fn: hash_fn)
} }
test member_3() { test member_3() {
let dog = "dog" let dog =
let cat = "cat" "dog"
let cat =
"cat"
let items = [dog, cat] let items =
let hash_fn = create_string_item_hash_fn() [dog, cat]
let mt = from_list(items, hash_fn) let hash_fn =
create_string_item_hash_fn()
let mt =
from_list(items, hash_fn)
let item = cat let item =
let rh = root_hash(mt) 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) member(item: item, root_hash: rh, proof: proof, hash_fn: hash_fn)
} }
test member_4() { test member_4() {
let dog = "dog" let dog =
let cat = "cat" "dog"
let mouse = "mouse" let cat =
"cat"
let mouse =
"mouse"
let items = [dog, cat, mouse] let items =
let hash_fn = create_string_item_hash_fn() [dog, cat, mouse]
let mt = from_list(items, hash_fn) let hash_fn =
create_string_item_hash_fn()
let mt =
from_list(items, hash_fn)
let item = mouse let item =
let rh = root_hash(mt) 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) member(item: item, root_hash: rh, proof: proof, hash_fn: hash_fn)
} }
test member_5() { test member_5() {
let dog = "dog" let dog =
let cat = "cat" "dog"
let mouse = "mouse" let cat =
let horse = "horse" "cat"
let pig = "pig" let mouse =
let bull = "bull" "mouse"
let horse =
"horse"
let pig =
"pig"
let bull =
"bull"
let items = [dog, cat, mouse, horse, pig, bull] let items =
let hash_fn = create_string_item_hash_fn() [dog, cat, mouse, horse, pig, bull]
let mt = from_list(items, hash_fn) let hash_fn =
create_string_item_hash_fn()
let mt =
from_list(items, hash_fn)
let item = pig let item =
let rh = root_hash(mt) 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) member(item: item, root_hash: rh, proof: proof, hash_fn: hash_fn)
} }
test member_6() { test member_6() {
let dog = "dog" let dog =
let cat = "cat" "dog"
let mouse = "mouse" let cat =
let horse = "horse" "cat"
let pig = "pig" let mouse =
let bull = "bull" "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 items =
let mt = from_list(items, hash_fn) [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 proof == None
} }
fn get_proof_item_value(proof_item: ProofItem) -> Hash<Sha2_256, ByteArray> { fn get_proof_item_value(proof_item: ProofItem) -> Hash<Sha2_256, ByteArray> {
when proof_item is { when proof_item is {
Left(x) -> x Left(x) ->
Right(y) -> y x
Right(y) ->
y
} }
} }

View File

@ -24,10 +24,10 @@ pub fn from_asset(
) -> Value { ) -> Value {
let asset = let asset =
dict.new() dict.new()
|> dict.insert(asset_name, quantity, bytearray.compare) |> dict.insert(asset_name, quantity, bytearray.compare)
dict.new() dict.new()
|> dict.insert(policy_id, asset, bytearray.compare) |> dict.insert(policy_id, asset, bytearray.compare)
|> Value |> Value
} }
pub fn add(left v0: Value, right v1: Value) -> 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, a0,
a1, a1,
fn(_, q0, q1) { fn(_, q0, q1) {
let q = q0 + q1 let q =
q0 + q1
if q == 0 { if q == 0 {
None None
} else { } else {
@ -58,7 +59,7 @@ pub fn add(left v0: Value, right v1: Value) -> Value {
}, },
bytearray.compare, bytearray.compare,
) )
|> Value |> Value
} }
/// Flatten a value as a list of results, possibly discarding some along the way. /// Flatten a value as a list of results, possibly discarding some along the way.
@ -75,8 +76,10 @@ pub fn flatten_with(
asset, asset,
fn(asset_name, quantity, xs) { fn(asset_name, quantity, xs) {
when transform(policy_id, asset_name, quantity) is { when transform(policy_id, asset_name, quantity) is {
None -> xs None ->
Some(x) -> [x, ..xs] xs
Some(x) ->
[x, ..xs]
} }
}, },
assets, assets,
@ -93,9 +96,9 @@ test flatten_with_1() {
test flatten_with_2() { test flatten_with_2() {
let v = let v =
zero() zero()
|> add(from_asset("a", "1", 14)) |> add(from_asset("a", "1", 14))
|> add(from_asset("b", "", 42)) |> add(from_asset("b", "", 42))
|> add(from_asset("a", "2", 42)) |> add(from_asset("a", "2", 42))
flatten_with( flatten_with(
v, v,

View File

@ -69,10 +69,13 @@ pub fn validate_pool_deposit(
datum: PoolDatum, datum: PoolDatum,
redeemer: PoolDepositRedeemer, redeemer: PoolDepositRedeemer,
) -> Bool { ) -> 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_output) =
expect Some(pool_input) = get_input(ctx, validator_address) get_output(ctx, validator_address)
expect Some(pool_input) =
get_input(ctx, validator_address)
True True
} }
@ -83,28 +86,34 @@ pub fn validate_pool_borrow(
datum: PoolDatum, datum: PoolDatum,
redeemer: PoolBorrowRedeemer, redeemer: PoolBorrowRedeemer,
) -> Bool { ) -> 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_output) =
expect Some(pool_input) = get_input(ctx, validator_address) get_output(ctx, validator_address)
expect Some(pool_input) =
get_input(ctx, validator_address)
True True
} }
validator pool_contract { validator pool_contract {
fn(datum: PoolDatum, redeemer: PoolRedeemer, ctx: ScriptContext) { fn(datum: PoolDatum, redeemer: PoolRedeemer, ctx: ScriptContext) {
when redeemer.action is { when redeemer.action is {
PoolWithdraw(_) -> True PoolWithdraw(_) ->
True
PoolDeposit(pool_deposit_redeemer) -> PoolDeposit(pool_deposit_redeemer) ->
when ctx.purpose is { when ctx.purpose is {
Spend(output_ref) -> Spend(output_ref) ->
validate_pool_deposit(ctx, output_ref, datum, pool_deposit_redeemer) validate_pool_deposit(ctx, output_ref, datum, pool_deposit_redeemer)
_ -> False _ ->
False
} }
PoolBorrow(pool_borrow_redeemer) -> PoolBorrow(pool_borrow_redeemer) ->
when ctx.purpose is { when ctx.purpose is {
Spend(output_ref) -> Spend(output_ref) ->
validate_pool_borrow(ctx, output_ref, datum, pool_borrow_redeemer) validate_pool_borrow(ctx, output_ref, datum, pool_borrow_redeemer)
_ -> False _ ->
False
} }
} }
} }

View File

@ -30,24 +30,34 @@ fn find_outbound_datum(possible_output: Option<Output>) -> Data {
when possible_output is { when possible_output is {
Some(possible_output) -> Some(possible_output) ->
when possible_output.datum is { when possible_output.datum is {
InlineDatum(outbound_datum) -> outbound_datum InlineDatum(outbound_datum) ->
_ -> error @"expected outbound inline 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 { fn datum_a_cont() -> OtherDatum {
let owner: OwnerInfo = OwnerInfo { pkh: #"", sc: #"" } let owner: OwnerInfo =
let have: TokenInfo = TokenInfo { pid: #"", tkn: #"", amt: 100 } OwnerInfo { pkh: #"", sc: #"" }
let want: TokenInfo = TokenInfo { pid: #"acab", tkn: #"beef", amt: 50 } let have: TokenInfo =
let info: SwapInfo = SwapInfo { slip: 40 } 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 } OtherDatum { owner, have, want, info }
} }
test foo() { test foo() {
let outbound_datum = InlineDatum(datum_a_cont()) let outbound_datum =
let outbound_output = Some(Output { datum: outbound_datum }) InlineDatum(datum_a_cont())
expect outbound_datum: OtherDatum = find_outbound_datum(outbound_output) let outbound_output =
Some(Output { datum: outbound_datum })
expect outbound_datum: OtherDatum =
find_outbound_datum(outbound_output)
outbound_datum == datum_a_cont() outbound_datum == datum_a_cont()
} }

View File

@ -25,9 +25,12 @@ pub type ProofItem {
// Function returning a hash of a given Merkle Tree element // Function returning a hash of a given Merkle Tree element
pub fn root_hash(self: MerkleTree<a>) -> Hash<Sha2_256, ByteArray> { pub fn root_hash(self: MerkleTree<a>) -> Hash<Sha2_256, ByteArray> {
when self is { when self is {
Empty -> #"" Empty ->
Leaf { hash } -> hash #""
Node { hash, .. } -> hash 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. /// Function returns a total numbers of leaves in the tree.
pub fn size(self: MerkleTree<a>) -> Int { pub fn size(self: MerkleTree<a>) -> Int {
when self is { when self is {
Empty -> 0 Empty ->
Leaf{..} -> 1 0
Node { left, right, .. } -> size(left) + size(right) 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 /// Function that returns whether merkle tree has any elements
pub fn is_empty(self: MerkleTree<a>) -> Bool { pub fn is_empty(self: MerkleTree<a>) -> Bool {
when self is { when self is {
Empty -> True Empty ->
_ -> False True
_ ->
False
} }
} }
@ -67,7 +75,8 @@ fn do_proof(
serialise_fn: fn(a) -> ByteArray, serialise_fn: fn(a) -> ByteArray,
) -> Option<Proof> { ) -> Option<Proof> {
when self is { when self is {
Empty -> None Empty ->
None
Leaf { hash } -> Leaf { hash } ->
if hash == item_hash { if hash == item_hash {
Some(proof) Some(proof)
@ -75,8 +84,10 @@ fn do_proof(
None None
} }
Node { left, right, .. } -> { Node { left, right, .. } -> {
let rh = root_hash(right) let rh =
let lh = root_hash(left) root_hash(right)
let lh =
root_hash(left)
let go_left: Option<Proof> = let go_left: Option<Proof> =
do_proof( do_proof(
left, left,
@ -104,7 +115,8 @@ pub fn get_proof(
item: a, item: a,
serialise_fn: fn(a) -> ByteArray, serialise_fn: fn(a) -> ByteArray,
) -> Option<Proof> { ) -> Option<Proof> {
let empty: Proof = [] let empty: Proof =
[]
do_proof(self, sha2_256(serialise_fn(item)), empty, serialise_fn) do_proof(self, sha2_256(serialise_fn(item)), empty, serialise_fn)
} }
@ -115,22 +127,26 @@ fn do_from_list(
serialise_fn: fn(a) -> ByteArray, serialise_fn: fn(a) -> ByteArray,
) -> MerkleTree<a> { ) -> MerkleTree<a> {
when items is { when items is {
[] -> Empty [] ->
Empty
[item] -> { [item] -> {
let hashed_item = sha2_256(serialise_fn(item)) let hashed_item =
sha2_256(serialise_fn(item))
Leaf { hash: hashed_item } Leaf { hash: hashed_item }
} }
all -> { all -> {
let cutoff: Int = len / 2 let cutoff: Int =
len / 2
let left = let left =
all all
|> list.take(cutoff) |> list.take(cutoff)
|> do_from_list(cutoff, serialise_fn) |> do_from_list(cutoff, serialise_fn)
let right = let right =
all all
|> list.drop(cutoff) |> list.drop(cutoff)
|> do_from_list(len - cutoff, serialise_fn) |> do_from_list(len - cutoff, serialise_fn)
let hash = combine_hash(root_hash(left), root_hash(right)) let hash =
combine_hash(root_hash(left), root_hash(right))
Node { hash, left, right } Node { hash, left, right }
} }
} }
@ -151,19 +167,23 @@ fn do_from_hashes_list(
len: Int, len: Int,
) -> MerkleTree<a> { ) -> MerkleTree<a> {
when items is { when items is {
[] -> Empty [] ->
[hashed_item] -> Leaf { hash: hashed_item } Empty
[hashed_item] ->
Leaf { hash: hashed_item }
all -> { all -> {
let cutoff: Int = len / 2 let cutoff: Int =
len / 2
let left = let left =
all all
|> list.take(cutoff) |> list.take(cutoff)
|> do_from_hashes_list(cutoff) |> do_from_hashes_list(cutoff)
let right = let right =
all all
|> list.drop(cutoff) |> list.drop(cutoff)
|> do_from_hashes_list(len - cutoff) |> do_from_hashes_list(len - cutoff)
let hash = combine_hash(root_hash(left), root_hash(right)) let hash =
combine_hash(root_hash(left), root_hash(right))
Node { hash, left, right } Node { hash, left, right }
} }
} }
@ -187,7 +207,8 @@ pub fn member_from_hash(
serialise_fn: fn(a) -> ByteArray, serialise_fn: fn(a) -> ByteArray,
) -> Bool { ) -> Bool {
when proof is { when proof is {
[] -> root_hash == item_hash [] ->
root_hash == item_hash
[head, ..tail] -> [head, ..tail] ->
when head is { when head is {
Left { hash: l } -> Left { hash: l } ->
@ -216,7 +237,8 @@ pub fn member(
proof: Proof, proof: Proof,
serialise_fn: fn(a) -> ByteArray, serialise_fn: fn(a) -> ByteArray,
) -> Bool { ) -> 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) member_from_hash(item_hash, root_hash, proof, serialise_fn)
} }
@ -225,12 +247,16 @@ pub fn member_from_tree(
item: a, item: a,
serialise_fn: fn(a) -> ByteArray, serialise_fn: fn(a) -> ByteArray,
) -> Bool { ) -> Bool {
let proof: Option<Proof> = get_proof(tree, item, serialise_fn) let proof: Option<Proof> =
let rh = root_hash(tree) get_proof(tree, item, serialise_fn)
let rh =
root_hash(tree)
when proof is { when proof is {
Some(p) -> member(item, rh, p, serialise_fn) Some(p) ->
None -> False 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() { test from_hashes_list_5() {
let dog = @"dog" let dog =
let cat = @"cat" @"dog"
let mouse = @"mouse" let cat =
let horse = @"horse" @"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 items =
let hashes_items = list.map(items, fn(item) { sha2_256(serialise_fn(item)) }) [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 = let left_node_hash =
sha2_256( 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 { Node {
hash: root_hash, hash: root_hash,

View File

@ -1,5 +1,7 @@
test expect_positive() { test expect_positive() {
let val = 5 let val =
expect True = val > 0 5
expect True =
val > 0
True True
} }

View File

@ -4,12 +4,15 @@ use aiken/transaction/value.{add, zero}
validator staking { validator staking {
fn(_datum: Void, _redeemer: Void, context: ScriptContext) -> Bool { fn(_datum: Void, _redeemer: Void, context: ScriptContext) -> Bool {
expect Spend(ref) = context.purpose expect Spend(ref) =
context.purpose
expect Some(i) = expect Some(i) =
find(context.transaction.inputs, fn(x) { x.output_reference == ref }) find(context.transaction.inputs, fn(x) { x.output_reference == ref })
let Input { output, .. } = i let Input { output, .. } =
let staking_addr = output.address i
let staking_addr =
output.address
let v_in = let v_in =
foldr( foldr(

View File

@ -3,13 +3,16 @@ use aiken/transaction.{Output, ScriptContext}
validator backtrace { validator backtrace {
fn(_datum: Void, _redeemer: Void, context: ScriptContext) -> Bool { fn(_datum: Void, _redeemer: Void, context: ScriptContext) -> Bool {
expect Some(_) = list.find(context.transaction.outputs, fn(_) { True }) expect Some(_) =
let _ = find_stuff(context) list.find(context.transaction.outputs, fn(_) { True })
let _ =
find_stuff(context)
True True
} }
} }
fn find_stuff(context) -> Output { 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 stuff
} }