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:
Pierre-Emmanuel Wulfman 2020-02-19 17:08:30 +00:00
commit 0b10b7188b
4 changed files with 204 additions and 38 deletions

View File

@ -148,6 +148,7 @@ module Simplify = struct
module Cameligo = struct
let constants = function
| "assert" -> ok C_ASSERTION
| "chain_id" -> ok C_CHAIN_ID
| "Current.balance" -> ok C_BALANCE
| "balance" -> ok C_BALANCE
| "Current.time" -> ok C_NOW

View 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)

View 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))
}

View File

@ -1,24 +1,27 @@
open Trace
open Test_helpers
let type_file f =
let%bind simplified = Ligo.Compile.Of_source.compile f (Syntax_name "pascaligo") in
let file = "./contracts/multisig.ligo"
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
ok @@ (typed,state)
let get_program =
let get_program f st =
let s = ref None in
fun () -> match !s with
| Some s -> ok s
| None -> (
let%bind program = type_file "./contracts/multisig.ligo" in
let%bind program = type_file f st in
s := Some program ;
ok program
)
let compile_main () =
let%bind simplified = Ligo.Compile.Of_source.compile "./contracts/multisig.ligo" (Syntax_name "pascaligo") in
let%bind typed_prg,_ = Ligo.Compile.Of_simplified.compile simplified in
let compile_main f s () =
let%bind typed_prg,_ = type_file f s 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 (_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
(* sign the message 'msg' with 'keys', if 'is_valid'=false the providid signature will be incorrect *)
let params counter msg keys is_validl =
let%bind program,_ = get_program () in
let params counter msg keys is_validl f s =
let%bind program,_ = get_program f s () in
let aux = fun acc (key,is_valid) ->
let (_,_pk,sk) = 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 *)
let not_enough_1_of_2 () =
let%bind program,_ = get_program () in
let not_enough_1_of_2 f s () =
let%bind program,_ = get_program f s () in
let exp_failwith = "Not enough signatures passed the check" 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
program "main" (e_pair test_params (init_storage 2 0 [keys;gen_keys()])) exp_failwith in
ok ()
let unmatching_counter () =
let%bind program,_ = get_program () in
let unmatching_counter f s () =
let%bind program,_ = get_program f s () in
let exp_failwith = "Counters does not match" 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
program "main" (e_pair test_params (init_storage 1 0 [keys])) exp_failwith in
ok ()
(* Provide one invalid signature (correct key but incorrect signature)
when the threshold is one of one key *)
let invalid_1_of_1 () =
let%bind program,_ = get_program () in
let invalid_1_of_1 f s () =
let%bind program,_ = get_program f s () in
let exp_failwith = "Invalid signature" 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
program "main" (e_pair test_params (init_storage 1 0 keys)) exp_failwith in
ok ()
(* Provide one valid signature when the threshold is one of one key *)
let valid_1_of_1 () =
let%bind program,_ = get_program () in
let valid_1_of_1 f s () =
let%bind program,_ = get_program f s () in
let keys = gen_keys () in
let%bind () = expect_eq_n_trace_aux [0;1;2] program "main"
(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])
)
(fun n ->
@ -117,13 +120,13 @@ let valid_1_of_1 () =
ok ()
(* Provive two valid signatures when the threshold is two of three keys *)
let valid_2_of_3 () =
let%bind program,_ = get_program () in
let valid_2_of_3 f s () =
let%bind program,_ = get_program f s () in
let param_keys = [gen_keys (); gen_keys ()] in
let st_keys = param_keys @ [gen_keys ()] in
let%bind () = expect_eq_n_trace_aux [0;1;2] program "main"
(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)
)
(fun n ->
@ -132,36 +135,52 @@ let valid_2_of_3 () =
ok ()
(* Provide one invalid signature and two valid signatures when the threshold is two of three keys *)
let invalid_3_of_3 () =
let%bind program,_ = get_program () in
let invalid_3_of_3 f s () =
let%bind program,_ = get_program f s () in
let valid_keys = [gen_keys() ; gen_keys()] in
let invalid_key = gen_keys () in
let param_keys = valid_keys @ [invalid_key] 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%bind () = expect_string_failwith
program "main" (e_pair test_params (init_storage 2 0 st_keys)) exp_failwith in
ok ()
(* Provide two valid signatures when the threshold is three of three keys *)
let not_enough_2_of_3 () =
let%bind program,_ = get_program () in
let not_enough_2_of_3 f s () =
let%bind program,_ = get_program f s() in
let valid_keys = [gen_keys() ; gen_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%bind () = expect_string_failwith
program "main" (e_pair test_params (init_storage 3 0 st_keys)) exp_failwith in
ok ()
let main = test_suite "Multisig" [
test "compile" compile_main ;
test "unmatching_counter" unmatching_counter ;
test "valid_1_of_1" valid_1_of_1 ;
test "invalid_1_of_1" invalid_1_of_1 ;
test "not_enough_signature" not_enough_1_of_2 ;
test "valid_2_of_3" valid_2_of_3 ;
test "invalid_3_of_3" invalid_3_of_3 ;
test "not_enough_2_of_3" not_enough_2_of_3 ;
test "compile" (compile_main file "pascaligo");
test "unmatching_counter" (unmatching_counter file "pascaligo");
test "valid_1_of_1" (valid_1_of_1 file "pascaligo");
test "invalid_1_of_1" (invalid_1_of_1 file "pascaligo");
test "not_enough_signature" (not_enough_1_of_2 file "pascaligo");
test "valid_2_of_3" (valid_2_of_3 file "pascaligo");
test "invalid_3_of_3" (invalid_3_of_3 file "pascaligo");
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");
]