multisig : non quadratic signature check
This commit is contained in:
parent
88a0f33fca
commit
17ecf12fa3
@ -12,10 +12,12 @@ type storage_t is record
|
||||
end
|
||||
|
||||
// I/O types
|
||||
type message_t is (unit -> list(operation))
|
||||
type signatures_t is list(key_hash * signature)
|
||||
type check_message_pt is record
|
||||
counter : counter_t ;
|
||||
message : (unit -> list(operation)) ;
|
||||
signatures : list(signature) ;
|
||||
message : message_t ;
|
||||
signatures : signatures_t ;
|
||||
end
|
||||
|
||||
type contract_return_t is (list(operation) * storage_t)
|
||||
@ -25,7 +27,7 @@ type entry_point_t is
|
||||
|
||||
function check_message (const param : check_message_pt;
|
||||
const s : storage_t) : contract_return_t is block {
|
||||
var message : (unit -> list(operation)) := param.message ;
|
||||
var message : message_t := param.message ;
|
||||
|
||||
if param.counter =/= s.counter then
|
||||
failwith ("Counters does not match")
|
||||
@ -34,17 +36,20 @@ function check_message (const param : check_message_pt;
|
||||
bytes_pack((message , param.counter , s.id , get_chain_id));
|
||||
var valid : nat := 0n ;
|
||||
|
||||
for sig in list param.signatures block {
|
||||
var is_valid : bool := False ;
|
||||
|
||||
for pk in list s.auth block {
|
||||
if crypto_check(pk,sig,packed_payload) then is_valid := True
|
||||
var keys : authorized_keys_t := s.auth ;
|
||||
for pkh_sig in list param.signatures block {
|
||||
case keys of
|
||||
| nil -> skip
|
||||
| key # tl -> block {
|
||||
keys := tl ;
|
||||
if pkh_sig.0 = crypto_hash_key(key) then
|
||||
if crypto_check(key,pkh_sig.1,packed_payload) then valid := valid + 1n ;
|
||||
else failwith ("Invalid signature")
|
||||
else skip;
|
||||
};
|
||||
|
||||
if is_valid then valid := valid + 1n
|
||||
else failwith ("Invalid signature")
|
||||
}
|
||||
end
|
||||
};
|
||||
|
||||
if valid < s.threshold then
|
||||
failwith ("Not enough signatures passed the check")
|
||||
else s.counter := s.counter + 1n ;
|
||||
|
@ -24,18 +24,18 @@ open Ast_simplified
|
||||
|
||||
let gen_keys = fun () ->
|
||||
let open Tezos_crypto in
|
||||
let (_,raw_pk,raw_sk) = Ed25519.generate_key () in
|
||||
(raw_pk,raw_sk)
|
||||
let (raw_pkh,raw_pk,raw_sk) = Signature.generate_key () in
|
||||
(raw_pkh,raw_pk,raw_sk)
|
||||
|
||||
let str_keys (raw_pk, raw_sk) =
|
||||
let str_keys (raw_pkh, raw_pk, raw_sk) =
|
||||
let open Tezos_crypto in
|
||||
let (pk_str:string) = Base58.simple_encode (Ed25519.Public_key.b58check_encoding) raw_pk in
|
||||
let (sk_str:string) = Base58.simple_encode (Ed25519.Secret_key.b58check_encoding) raw_sk in
|
||||
(pk_str,sk_str)
|
||||
let sk_str = Signature.Secret_key.to_b58check raw_sk in
|
||||
let pk_str = Signature.Public_key.to_b58check raw_pk in
|
||||
let pkh_str = Signature.Public_key_hash.to_b58check raw_pkh in
|
||||
(pkh_str,pk_str,sk_str)
|
||||
|
||||
let sign_message (payload : expression) raw_sk : string result =
|
||||
let sign_message (payload : expression) sk : string result =
|
||||
let open Tezos_crypto in
|
||||
let (sk : Signature.secret_key) = Signature.Ed25519 raw_sk in
|
||||
let%bind program,_ = get_program () in
|
||||
let%bind code =
|
||||
let env = Ast_typed.program_environment program in
|
||||
@ -50,7 +50,11 @@ let sign_message (payload : expression) raw_sk : string result =
|
||||
ok signature_str
|
||||
|
||||
let init_storage threshold counter pkeys =
|
||||
let keys = List.map (fun el -> e_key @@ fst @@ str_keys el) pkeys in
|
||||
let keys = List.map
|
||||
(fun el ->
|
||||
let (_,pk_str,_) = str_keys el in
|
||||
e_key @@ pk_str)
|
||||
pkeys in
|
||||
ez_e_record [
|
||||
("id" , e_string "MULTISIG" ) ;
|
||||
("counter" , e_nat counter ) ;
|
||||
@ -67,23 +71,25 @@ let chain_id_zero = e_chain_id @@ Tezos_crypto.Base58.simple_encode
|
||||
Tezos_base__TzPervasives.Chain_id.b58check_encoding
|
||||
Tezos_base__TzPervasives.Chain_id.zero
|
||||
|
||||
(* sign the same message 'msg' with the secret keys of 'keys' *)
|
||||
let params counter msg keys =
|
||||
let aux = fun acc sk ->
|
||||
(* sign the message 'msg' with 'keys', if 'is_valid'=false the providid signature will be incorrect *)
|
||||
let params counter msg keys is_validl =
|
||||
let aux = fun acc (key,is_valid) ->
|
||||
let (_,_pk,sk) = key in
|
||||
let (pkh,_,_) = str_keys key in
|
||||
let payload = e_tuple
|
||||
[ msg ;
|
||||
e_nat counter ;
|
||||
e_string "MULTISIG" ;
|
||||
e_string (if is_valid then "MULTISIG" else "XX") ;
|
||||
chain_id_zero ] in
|
||||
let%bind signature = sign_message payload (snd sk) in
|
||||
ok @@ (e_signature signature)::acc in
|
||||
let%bind signed_msgs = Trace.bind_fold_list aux [] keys in
|
||||
let%bind signature = sign_message payload sk in
|
||||
ok @@ (e_pair (e_key_hash pkh) (e_signature signature))::acc in
|
||||
let%bind signed_msgs = Trace.bind_fold_list aux [] (List.rev @@ List.combine keys is_validl) in
|
||||
ok @@ e_constructor
|
||||
"CheckMessage"
|
||||
(ez_e_record [
|
||||
("counter" , e_nat counter ) ;
|
||||
("message" , msg) ;
|
||||
("signatures" , e_typed_list signed_msgs t_signature ) ;
|
||||
("signatures" , e_typed_list signed_msgs (t_pair (t_key_hash,t_signature)) ) ;
|
||||
])
|
||||
|
||||
|
||||
@ -92,7 +98,7 @@ let not_enough_1_of_2 () =
|
||||
let%bind program,_ = get_program () 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] in
|
||||
let%bind test_params = params 0 empty_message [keys] [true] in
|
||||
let%bind () = expect_string_failwith
|
||||
program "main" (e_pair test_params (init_storage 2 0 [keys;gen_keys()])) exp_failwith in
|
||||
ok ()
|
||||
@ -101,20 +107,20 @@ let unmatching_counter () =
|
||||
let%bind program,_ = get_program () in
|
||||
let exp_failwith = "Counters does not match" in
|
||||
let keys = gen_keys () in
|
||||
let%bind test_params = params 1 empty_message [keys] in
|
||||
let%bind test_params = params 1 empty_message [keys] [true] 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 when the threshold is one of one key *)
|
||||
(* 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 exp_failwith = "Invalid signature" in
|
||||
let keys = gen_keys () in
|
||||
let invalid_keys = gen_keys () in
|
||||
let%bind test_params = params 0 empty_message [keys] in
|
||||
let keys = [gen_keys ()] in
|
||||
let%bind test_params = params 0 empty_message keys [false] in
|
||||
let%bind () = expect_string_failwith
|
||||
program "main" (e_pair test_params (init_storage 1 0 [invalid_keys])) exp_failwith in
|
||||
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 *)
|
||||
@ -123,7 +129,7 @@ let valid_1_of_1 () =
|
||||
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] in
|
||||
let%bind params = params n empty_message [keys] [true] in
|
||||
ok @@ e_pair params (init_storage 1 n [keys])
|
||||
)
|
||||
(fun n ->
|
||||
@ -134,11 +140,11 @@ let valid_1_of_1 () =
|
||||
(* Provive two valid signatures when the threshold is two of three keys *)
|
||||
let valid_2_of_3 () =
|
||||
let%bind program,_ = get_program () in
|
||||
let keys = [gen_keys (); gen_keys ()] in
|
||||
let st_keys = gen_keys() :: keys 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 keys in
|
||||
let%bind params = params n empty_message param_keys [true;true] in
|
||||
ok @@ e_pair params (init_storage 2 n st_keys)
|
||||
)
|
||||
(fun n ->
|
||||
@ -147,12 +153,13 @@ 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_2 () =
|
||||
let invalid_3_of_3 () =
|
||||
let%bind program,_ = get_program () in
|
||||
let valid_keys = [gen_keys() ; gen_keys()] in
|
||||
let invalid_key = gen_keys () in
|
||||
let st_keys = gen_keys () :: valid_keys in
|
||||
let%bind test_params = params 0 empty_message (invalid_key::valid_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 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
|
||||
@ -163,7 +170,7 @@ let not_enough_2_of_3 () =
|
||||
let%bind program,_ = get_program () 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) in
|
||||
let%bind test_params = params 0 empty_message (valid_keys) [true;true] 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
|
||||
@ -176,6 +183,6 @@ let main = test_suite "Multisig" [
|
||||
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_2 ;
|
||||
test "invalid_3_of_3" invalid_3_of_3 ;
|
||||
test "not_enough_2_of_3" not_enough_2_of_3 ;
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user