ligo/src/test/contracts/multisig.mligo
2020-03-02 18:01:56 +01:00

65 lines
1.8 KiB
Plaintext

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