// 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); /* Waiting to be fixed */ 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) { (failwith ("Counters does not match") : storage); } 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) { | [] => vk; | [key, ...keys] => if (pkh_sig[0] == Crypto.hash_key (key)) { let valid = if (Crypto.check (key, pkh_sig[1], packed_payload)) { valid + 1n; } else { (failwith ("Invalid signature") : nat) }; (valid, keys); } else { (valid, keys); }; }; }; let (valid, keys) = List.fold (aux, param.signatures, (valid, keys)); if (valid < s.threshold) { (failwith ("Not enough signatures passed the check") : storage); } else { {...s,counter : s.counter + 1n}; }; }; (message (unit),s) }; let main = ((action, store) : (parameter,storage)) : return => switch (action) { | CheckMessage (p) => check_message ((p, store)) }