67 lines
1.6 KiB
Plaintext
67 lines
1.6 KiB
Plaintext
// storage type
|
|
|
|
type counter is nat
|
|
type threshold is nat
|
|
type authorized_keys is list (key)
|
|
type id is string
|
|
|
|
type storage is
|
|
record [
|
|
id : id;
|
|
counter : counter;
|
|
threshold : threshold;
|
|
auth : authorized_keys
|
|
]
|
|
|
|
// I/O types
|
|
|
|
type message is unit -> list (operation)
|
|
|
|
type signatures is list (key_hash * signature)
|
|
|
|
type check_message_pt is
|
|
record [
|
|
counter : counter;
|
|
message : message;
|
|
signatures : signatures
|
|
]
|
|
|
|
type return is list (operation) * storage
|
|
|
|
type parameter is CheckMessage of check_message_pt
|
|
|
|
function check_message (const param : check_message_pt;
|
|
const s : storage) : return is block {
|
|
var message : message := param.message;
|
|
|
|
if param.counter =/= s.counter then
|
|
failwith ("Counters does not match")
|
|
else {
|
|
const packed_payload : bytes =
|
|
Bytes.pack ((message, param.counter, s.id, Tezos.chain_id));
|
|
var valid : nat := 0n;
|
|
|
|
var keys : authorized_keys := 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
|
|
}
|
|
end
|
|
};
|
|
|
|
if valid < s.threshold then
|
|
failwith ("Not enough signatures passed the check")
|
|
else s.counter := s.counter + 1n
|
|
}
|
|
} with (message (unit), s)
|
|
|
|
function main (const param : parameter; const s : storage) : return is
|
|
case param of CheckMessage (p) -> check_message (p,s) end
|