Merge branch 'test-contract-religo' into 'dev'
Multisig contract test for Cameligo and ReasonLigo See merge request ligolang/ligo!421
This commit is contained in:
commit
0b10b7188b
@ -148,6 +148,7 @@ module Simplify = struct
|
|||||||
module Cameligo = struct
|
module Cameligo = struct
|
||||||
let constants = function
|
let constants = function
|
||||||
| "assert" -> ok C_ASSERTION
|
| "assert" -> ok C_ASSERTION
|
||||||
|
| "chain_id" -> ok C_CHAIN_ID
|
||||||
| "Current.balance" -> ok C_BALANCE
|
| "Current.balance" -> ok C_BALANCE
|
||||||
| "balance" -> ok C_BALANCE
|
| "balance" -> ok C_BALANCE
|
||||||
| "Current.time" -> ok C_NOW
|
| "Current.time" -> ok C_NOW
|
||||||
|
66
src/test/contracts/multisig.mligo
Normal file
66
src/test/contracts/multisig.mligo
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
// storage type
|
||||||
|
|
||||||
|
type counter = nat
|
||||||
|
type threshold = nat
|
||||||
|
type authorized_keys = (key) list
|
||||||
|
type id = string
|
||||||
|
|
||||||
|
type storage = {
|
||||||
|
id : id;
|
||||||
|
counter : counter;
|
||||||
|
threshold : threshold;
|
||||||
|
auth : authorized_keys
|
||||||
|
}
|
||||||
|
|
||||||
|
// I/O types
|
||||||
|
|
||||||
|
type message = unit -> (operation) list
|
||||||
|
|
||||||
|
type signatures = (key_hash*signature) list
|
||||||
|
type check_message_pt = {
|
||||||
|
counter : counter;
|
||||||
|
message : message;
|
||||||
|
signatures : signatures
|
||||||
|
}
|
||||||
|
|
||||||
|
type return = (operation) list * storage
|
||||||
|
|
||||||
|
type parameter = CheckMessage of check_message_pt
|
||||||
|
|
||||||
|
let check_message (param,s : check_message_pt * storage) : return =
|
||||||
|
let message : message = param.message in
|
||||||
|
let s =
|
||||||
|
if (param.counter <> s.counter) then
|
||||||
|
let coco = failwith ("Counters does not match") in s
|
||||||
|
else (
|
||||||
|
let packed_payload : bytes = Bytes.pack ((message, param.counter, s.id, chain_id)) in
|
||||||
|
let valid : nat = 0n in
|
||||||
|
let keys : authorized_keys = s.auth in
|
||||||
|
let aux = fun (vk, pkh_sig: (nat* authorized_keys) * (key_hash*signature)) ->
|
||||||
|
let (valid,keys) = vk in
|
||||||
|
match (keys) with
|
||||||
|
| [] -> (valid,keys)
|
||||||
|
| key::tl -> (
|
||||||
|
let keys = tl in
|
||||||
|
if (pkh_sig.0 = Crypto.hash_key (key)) then
|
||||||
|
let valid =
|
||||||
|
if (Crypto.check key pkh_sig.1 packed_payload) then valid + 1n
|
||||||
|
else let coco = failwith ("Invalid signature") in valid
|
||||||
|
in
|
||||||
|
(valid,keys)
|
||||||
|
else (valid,keys)
|
||||||
|
)
|
||||||
|
in
|
||||||
|
let (valid,keys) = List.fold aux param.signatures (valid,keys) in
|
||||||
|
if (valid < s.threshold) then
|
||||||
|
let coco = failwith ("Not enough signatures passed the check") in
|
||||||
|
s
|
||||||
|
else
|
||||||
|
{s with counter = s.counter + 1n}
|
||||||
|
)
|
||||||
|
in
|
||||||
|
(message(unit),s)
|
||||||
|
|
||||||
|
let main (param, s: parameter * storage) : return =
|
||||||
|
match (param) with
|
||||||
|
| CheckMessage (p) -> check_message (p,s)
|
80
src/test/contracts/multisig.religo
Normal file
80
src/test/contracts/multisig.religo
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
// storage type
|
||||||
|
|
||||||
|
type counter = nat;
|
||||||
|
type threshold = nat;
|
||||||
|
type authorized_keys = list (key);
|
||||||
|
type id = string;
|
||||||
|
|
||||||
|
type storage = {
|
||||||
|
id : id,
|
||||||
|
counter : counter,
|
||||||
|
threshold : threshold,
|
||||||
|
auth : authorized_keys
|
||||||
|
};
|
||||||
|
|
||||||
|
// I/O types
|
||||||
|
|
||||||
|
type message = unit => list (operation);
|
||||||
|
type dummy = (key_hash,signature);
|
||||||
|
type signatures = list (dummy);
|
||||||
|
|
||||||
|
type check_message_pt = {
|
||||||
|
counter : counter,
|
||||||
|
message : message,
|
||||||
|
signatures : signatures
|
||||||
|
};
|
||||||
|
|
||||||
|
type return = (list (operation),storage);
|
||||||
|
|
||||||
|
type parameter = CheckMessage (check_message_pt);
|
||||||
|
|
||||||
|
let check_message = ((param,s) : (check_message_pt, storage)) : return => {
|
||||||
|
let message : message = param.message;
|
||||||
|
let s =
|
||||||
|
if (param.counter != s.counter) {
|
||||||
|
let coco = failwith ("Counters does not match");
|
||||||
|
s;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let packed_payload : bytes = Bytes.pack ((message, param.counter, s.id, chain_id));
|
||||||
|
let valid : nat = 0n;
|
||||||
|
let keys : authorized_keys = s.auth;
|
||||||
|
let aux = ((vk,pkh_sig) : ((nat, authorized_keys),(key_hash,signature))):(nat,authorized_keys) => {
|
||||||
|
let (valid,keys) = vk;
|
||||||
|
switch(keys) {
|
||||||
|
| [] => (valid,keys);
|
||||||
|
| [key, ...tl] => {
|
||||||
|
let keys = tl;
|
||||||
|
if (pkh_sig[0] == Crypto.hash_key (key)){
|
||||||
|
let valid =
|
||||||
|
if (Crypto.check (key, pkh_sig[1], packed_payload)){
|
||||||
|
valid + 1n ;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let coco = failwith ("Invalid signature");
|
||||||
|
valid;
|
||||||
|
};
|
||||||
|
(valid,keys);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
(valid,keys);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
let (valid,keys) = List.fold (aux, param.signatures, (valid,keys));
|
||||||
|
if (valid < s.threshold) {
|
||||||
|
let coco = failwith ("Not enough signatures passed the check");
|
||||||
|
s;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
{...s,counter : s.counter + 1n};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
(message(unit),s)
|
||||||
|
};
|
||||||
|
|
||||||
|
let main = ((param, s) : (parameter,storage)) : return =>
|
||||||
|
switch(param) {
|
||||||
|
| CheckMessage (p) => check_message ((p,s))
|
||||||
|
}
|
@ -1,24 +1,27 @@
|
|||||||
open Trace
|
open Trace
|
||||||
open Test_helpers
|
open Test_helpers
|
||||||
|
|
||||||
let type_file f =
|
let file = "./contracts/multisig.ligo"
|
||||||
let%bind simplified = Ligo.Compile.Of_source.compile f (Syntax_name "pascaligo") in
|
let mfile = "./contracts/multisig.mligo"
|
||||||
|
let refile = "./contracts/multisig.religo"
|
||||||
|
|
||||||
|
let type_file f s =
|
||||||
|
let%bind simplified = Ligo.Compile.Of_source.compile f (Syntax_name s) in
|
||||||
let%bind typed,state = Ligo.Compile.Of_simplified.compile simplified in
|
let%bind typed,state = Ligo.Compile.Of_simplified.compile simplified in
|
||||||
ok @@ (typed,state)
|
ok @@ (typed,state)
|
||||||
|
|
||||||
let get_program =
|
let get_program f st =
|
||||||
let s = ref None in
|
let s = ref None in
|
||||||
fun () -> match !s with
|
fun () -> match !s with
|
||||||
| Some s -> ok s
|
| Some s -> ok s
|
||||||
| None -> (
|
| None -> (
|
||||||
let%bind program = type_file "./contracts/multisig.ligo" in
|
let%bind program = type_file f st in
|
||||||
s := Some program ;
|
s := Some program ;
|
||||||
ok program
|
ok program
|
||||||
)
|
)
|
||||||
|
|
||||||
let compile_main () =
|
let compile_main f s () =
|
||||||
let%bind simplified = Ligo.Compile.Of_source.compile "./contracts/multisig.ligo" (Syntax_name "pascaligo") in
|
let%bind typed_prg,_ = type_file f s in
|
||||||
let%bind typed_prg,_ = Ligo.Compile.Of_simplified.compile simplified in
|
|
||||||
let%bind mini_c_prg = Ligo.Compile.Of_typed.compile typed_prg in
|
let%bind mini_c_prg = Ligo.Compile.Of_typed.compile typed_prg in
|
||||||
let%bind michelson_prg = Ligo.Compile.Of_mini_c.aggregate_and_compile_contract mini_c_prg "main" in
|
let%bind michelson_prg = Ligo.Compile.Of_mini_c.aggregate_and_compile_contract mini_c_prg "main" in
|
||||||
let%bind (_contract: Tezos_utils.Michelson.michelson) =
|
let%bind (_contract: Tezos_utils.Michelson.michelson) =
|
||||||
@ -51,8 +54,8 @@ let chain_id_zero = e_chain_id @@ Tezos_crypto.Base58.simple_encode
|
|||||||
Tezos_base__TzPervasives.Chain_id.zero
|
Tezos_base__TzPervasives.Chain_id.zero
|
||||||
|
|
||||||
(* sign the message 'msg' with 'keys', if 'is_valid'=false the providid signature will be incorrect *)
|
(* sign the message 'msg' with 'keys', if 'is_valid'=false the providid signature will be incorrect *)
|
||||||
let params counter msg keys is_validl =
|
let params counter msg keys is_validl f s =
|
||||||
let%bind program,_ = get_program () in
|
let%bind program,_ = get_program f s () in
|
||||||
let aux = fun acc (key,is_valid) ->
|
let aux = fun acc (key,is_valid) ->
|
||||||
let (_,_pk,sk) = key in
|
let (_,_pk,sk) = key in
|
||||||
let (pkh,_,_) = str_keys key in
|
let (pkh,_,_) = str_keys key in
|
||||||
@ -73,42 +76,42 @@ let params counter msg keys is_validl =
|
|||||||
])
|
])
|
||||||
|
|
||||||
(* Provide one valid signature when the threshold is two of two keys *)
|
(* Provide one valid signature when the threshold is two of two keys *)
|
||||||
let not_enough_1_of_2 () =
|
let not_enough_1_of_2 f s () =
|
||||||
let%bind program,_ = get_program () in
|
let%bind program,_ = get_program f s () in
|
||||||
let exp_failwith = "Not enough signatures passed the check" in
|
let exp_failwith = "Not enough signatures passed the check" in
|
||||||
let keys = gen_keys () in
|
let keys = gen_keys () in
|
||||||
let%bind test_params = params 0 empty_message [keys] [true] in
|
let%bind test_params = params 0 empty_message [keys] [true] f s in
|
||||||
let%bind () = expect_string_failwith
|
let%bind () = expect_string_failwith
|
||||||
program "main" (e_pair test_params (init_storage 2 0 [keys;gen_keys()])) exp_failwith in
|
program "main" (e_pair test_params (init_storage 2 0 [keys;gen_keys()])) exp_failwith in
|
||||||
ok ()
|
ok ()
|
||||||
|
|
||||||
let unmatching_counter () =
|
let unmatching_counter f s () =
|
||||||
let%bind program,_ = get_program () in
|
let%bind program,_ = get_program f s () in
|
||||||
let exp_failwith = "Counters does not match" in
|
let exp_failwith = "Counters does not match" in
|
||||||
let keys = gen_keys () in
|
let keys = gen_keys () in
|
||||||
let%bind test_params = params 1 empty_message [keys] [true] in
|
let%bind test_params = params 1 empty_message [keys] [true] f s in
|
||||||
let%bind () = expect_string_failwith
|
let%bind () = expect_string_failwith
|
||||||
program "main" (e_pair test_params (init_storage 1 0 [keys])) exp_failwith in
|
program "main" (e_pair test_params (init_storage 1 0 [keys])) exp_failwith in
|
||||||
ok ()
|
ok ()
|
||||||
|
|
||||||
(* Provide one invalid signature (correct key but incorrect signature)
|
(* Provide one invalid signature (correct key but incorrect signature)
|
||||||
when the threshold is one of one key *)
|
when the threshold is one of one key *)
|
||||||
let invalid_1_of_1 () =
|
let invalid_1_of_1 f s () =
|
||||||
let%bind program,_ = get_program () in
|
let%bind program,_ = get_program f s () in
|
||||||
let exp_failwith = "Invalid signature" in
|
let exp_failwith = "Invalid signature" in
|
||||||
let keys = [gen_keys ()] in
|
let keys = [gen_keys ()] in
|
||||||
let%bind test_params = params 0 empty_message keys [false] in
|
let%bind test_params = params 0 empty_message keys [false] f s in
|
||||||
let%bind () = expect_string_failwith
|
let%bind () = expect_string_failwith
|
||||||
program "main" (e_pair test_params (init_storage 1 0 keys)) exp_failwith in
|
program "main" (e_pair test_params (init_storage 1 0 keys)) exp_failwith in
|
||||||
ok ()
|
ok ()
|
||||||
|
|
||||||
(* Provide one valid signature when the threshold is one of one key *)
|
(* Provide one valid signature when the threshold is one of one key *)
|
||||||
let valid_1_of_1 () =
|
let valid_1_of_1 f s () =
|
||||||
let%bind program,_ = get_program () in
|
let%bind program,_ = get_program f s () in
|
||||||
let keys = gen_keys () in
|
let keys = gen_keys () in
|
||||||
let%bind () = expect_eq_n_trace_aux [0;1;2] program "main"
|
let%bind () = expect_eq_n_trace_aux [0;1;2] program "main"
|
||||||
(fun n ->
|
(fun n ->
|
||||||
let%bind params = params n empty_message [keys] [true] in
|
let%bind params = params n empty_message [keys] [true] f s in
|
||||||
ok @@ e_pair params (init_storage 1 n [keys])
|
ok @@ e_pair params (init_storage 1 n [keys])
|
||||||
)
|
)
|
||||||
(fun n ->
|
(fun n ->
|
||||||
@ -117,13 +120,13 @@ let valid_1_of_1 () =
|
|||||||
ok ()
|
ok ()
|
||||||
|
|
||||||
(* Provive two valid signatures when the threshold is two of three keys *)
|
(* Provive two valid signatures when the threshold is two of three keys *)
|
||||||
let valid_2_of_3 () =
|
let valid_2_of_3 f s () =
|
||||||
let%bind program,_ = get_program () in
|
let%bind program,_ = get_program f s () in
|
||||||
let param_keys = [gen_keys (); gen_keys ()] in
|
let param_keys = [gen_keys (); gen_keys ()] in
|
||||||
let st_keys = param_keys @ [gen_keys ()] in
|
let st_keys = param_keys @ [gen_keys ()] in
|
||||||
let%bind () = expect_eq_n_trace_aux [0;1;2] program "main"
|
let%bind () = expect_eq_n_trace_aux [0;1;2] program "main"
|
||||||
(fun n ->
|
(fun n ->
|
||||||
let%bind params = params n empty_message param_keys [true;true] in
|
let%bind params = params n empty_message param_keys [true;true] f s in
|
||||||
ok @@ e_pair params (init_storage 2 n st_keys)
|
ok @@ e_pair params (init_storage 2 n st_keys)
|
||||||
)
|
)
|
||||||
(fun n ->
|
(fun n ->
|
||||||
@ -132,36 +135,52 @@ let valid_2_of_3 () =
|
|||||||
ok ()
|
ok ()
|
||||||
|
|
||||||
(* Provide one invalid signature and two valid signatures when the threshold is two of three keys *)
|
(* Provide one invalid signature and two valid signatures when the threshold is two of three keys *)
|
||||||
let invalid_3_of_3 () =
|
let invalid_3_of_3 f s () =
|
||||||
let%bind program,_ = get_program () in
|
let%bind program,_ = get_program f s () in
|
||||||
let valid_keys = [gen_keys() ; gen_keys()] in
|
let valid_keys = [gen_keys() ; gen_keys()] in
|
||||||
let invalid_key = gen_keys () in
|
let invalid_key = gen_keys () in
|
||||||
let param_keys = valid_keys @ [invalid_key] in
|
let param_keys = valid_keys @ [invalid_key] in
|
||||||
let st_keys = valid_keys @ [gen_keys ()] in
|
let st_keys = valid_keys @ [gen_keys ()] in
|
||||||
let%bind test_params = params 0 empty_message param_keys [false;true;true] in
|
let%bind test_params = params 0 empty_message param_keys [false;true;true] f s in
|
||||||
let exp_failwith = "Invalid signature" in
|
let exp_failwith = "Invalid signature" in
|
||||||
let%bind () = expect_string_failwith
|
let%bind () = expect_string_failwith
|
||||||
program "main" (e_pair test_params (init_storage 2 0 st_keys)) exp_failwith in
|
program "main" (e_pair test_params (init_storage 2 0 st_keys)) exp_failwith in
|
||||||
ok ()
|
ok ()
|
||||||
|
|
||||||
(* Provide two valid signatures when the threshold is three of three keys *)
|
(* Provide two valid signatures when the threshold is three of three keys *)
|
||||||
let not_enough_2_of_3 () =
|
let not_enough_2_of_3 f s () =
|
||||||
let%bind program,_ = get_program () in
|
let%bind program,_ = get_program f s() in
|
||||||
let valid_keys = [gen_keys() ; gen_keys()] in
|
let valid_keys = [gen_keys() ; gen_keys()] in
|
||||||
let st_keys = gen_keys () :: valid_keys in
|
let st_keys = gen_keys () :: valid_keys in
|
||||||
let%bind test_params = params 0 empty_message (valid_keys) [true;true] in
|
let%bind test_params = params 0 empty_message (valid_keys) [true;true] f s in
|
||||||
let exp_failwith = "Not enough signatures passed the check" in
|
let exp_failwith = "Not enough signatures passed the check" in
|
||||||
let%bind () = expect_string_failwith
|
let%bind () = expect_string_failwith
|
||||||
program "main" (e_pair test_params (init_storage 3 0 st_keys)) exp_failwith in
|
program "main" (e_pair test_params (init_storage 3 0 st_keys)) exp_failwith in
|
||||||
ok ()
|
ok ()
|
||||||
|
|
||||||
let main = test_suite "Multisig" [
|
let main = test_suite "Multisig" [
|
||||||
test "compile" compile_main ;
|
test "compile" (compile_main file "pascaligo");
|
||||||
test "unmatching_counter" unmatching_counter ;
|
test "unmatching_counter" (unmatching_counter file "pascaligo");
|
||||||
test "valid_1_of_1" valid_1_of_1 ;
|
test "valid_1_of_1" (valid_1_of_1 file "pascaligo");
|
||||||
test "invalid_1_of_1" invalid_1_of_1 ;
|
test "invalid_1_of_1" (invalid_1_of_1 file "pascaligo");
|
||||||
test "not_enough_signature" not_enough_1_of_2 ;
|
test "not_enough_signature" (not_enough_1_of_2 file "pascaligo");
|
||||||
test "valid_2_of_3" valid_2_of_3 ;
|
test "valid_2_of_3" (valid_2_of_3 file "pascaligo");
|
||||||
test "invalid_3_of_3" invalid_3_of_3 ;
|
test "invalid_3_of_3" (invalid_3_of_3 file "pascaligo");
|
||||||
test "not_enough_2_of_3" not_enough_2_of_3 ;
|
test "not_enough_2_of_3" (not_enough_2_of_3 file "pascaligo");
|
||||||
|
test "compile (mligo)" (compile_main mfile "cameligo");
|
||||||
|
test "unmatching_counter (mligo)" (unmatching_counter mfile "cameligo");
|
||||||
|
test "valid_1_of_1 (mligo)" (valid_1_of_1 mfile "cameligo");
|
||||||
|
test "invalid_1_of_1 (mligo)" (invalid_1_of_1 mfile "cameligo");
|
||||||
|
test "not_enough_signature (mligo)" (not_enough_1_of_2 mfile "cameligo");
|
||||||
|
test "valid_2_of_3 (mligo)" (valid_2_of_3 mfile "cameligo");
|
||||||
|
test "invalid_3_of_3 (mligo)" (invalid_3_of_3 mfile "cameligo");
|
||||||
|
test "not_enough_2_of_3 (mligo)" (not_enough_2_of_3 mfile "cameligo");
|
||||||
|
test "compile (religo)" (compile_main refile "reasonligo");
|
||||||
|
test "unmatching_counter (religo)" (unmatching_counter refile "reasonligo");
|
||||||
|
test "valid_1_of_1 (religo)" (valid_1_of_1 refile "reasonligo");
|
||||||
|
test "invalid_1_of_1 (religo)" (invalid_1_of_1 refile "reasonligo");
|
||||||
|
test "not_enough_signature (religo)" (not_enough_1_of_2 refile "reasonligo");
|
||||||
|
test "valid_2_of_3 (religo)" (valid_2_of_3 refile "reasonligo");
|
||||||
|
test "invalid_3_of_3 (religo)" (invalid_3_of_3 refile "reasonligo");
|
||||||
|
test "not_enough_2_of_3 (religo)" (not_enough_2_of_3 refile "reasonligo");
|
||||||
]
|
]
|
||||||
|
Loading…
Reference in New Issue
Block a user