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