add multisig test for cameligo and reasonligo
This commit is contained in:
parent
dcb342e031
commit
e1606c4700
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 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");
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user