Merge pull request #454 from aiken-lang/newline-assignment

Enforce newline after assignment / clause.
This commit is contained in:
Lucas 2023-03-16 15:32:11 -04:00 committed by GitHub
commit 4ed279b30d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
60 changed files with 997 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
- **aiken-lang**: unused let-bindings are now fully removed from generated code and discarded unused let-binding now raise a warning - **aiken-lang**: unused let-bindings are now fully removed from generated code and discarded unused let-binding now raise a warning
## [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,14 +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
} }