* Multisig

** Action Inputs

The contract is an N/M groups multisig, where each group has its own threshold (P/Q). The contract has four "action entrypoints" represented as a Michelson =or= type, plus an entrypoint that triggers vesting, which is handled separately. The action entrypoints are written below as an OCaml type with the Michelson type written above:

#+BEGIN_SRC ocaml

type action_input =

(* Left (Left (pair @transfer (contract @dest unit) (mutez @transfer_amount))) *)

| Transfer of { contract : unit contract ; amount : tez ; }

(* Left (Right (option (pair (contract unit) key))) *)

| Set_pour of (unit contract * key) option

(* Right (Left (pair (list (pair (list key) nat)) nat)) *)

| Set_keys of { key_groups : (key list * nat) list ; overall_threshold: nat }

(* Right (Right (option key_hash)) *)

| Set_delegate of key_hash option

In Michelson, the type encoding the actions is as follows:

#+BEGIN_SRC michelson

** Signatures

All action inputs require a list of signatures. To simplify the Michelson code, the signatures are optional types and must be in the order of the keys, with omitted signatures represented as =None=. The size of these groups and the required thresholds are set in the contract's storage. Below is an example of the contract's storage, with two signing groups. The thresholds are the second element of the tuple. In this example, both groups must pass their threshold, though this is also configurable. The first group requires 2/3 signatures and the second group requires 1/1.

#+BEGIN_SRC ocaml

([ ([ k1 ; k2 ; k3 ], 2) ; ([ k4 ], 1) ], 2)

The lengths of the lists must match the lengths of the lists in the contract's storage:

Here are several possible inputs to the above contract (sig1 is some piece of data signed with k1 and so on):

- =[ [ Some sig1 ; Some sig2 ; Some sig3 ] ; [ Some sig4 ] ]= -- passes

- =[ [ None ; Some sig2 ; Some sig3 ] ; [ Some sig4 ] ]= -- passes

- =[ [ Some sig1 ; None ; Some sig3 ] ; [ Some sig4 ] ]= -- passes

- =[ [ Some sig1 ; Some sig2 ; None ] ; [ Some sig4 ] ]= -- passes

- =[ [ Some sig1 ; Some sig2 ; None ] ; [ None ] ]= -- fails (second group does not equal or surpass threshold)

- =[ [ None ; Some sig2 ; None ] ; [ Some sig4 ] ]= -- fails (first group does not equal or surpass threshold)

- =[ [ Some sig2 ; Some sig1 ; None ] ; [ Some sig4 ] ]= -- fails (order is incorrect)

- =[ [ Some sig4 ] ; [ Some sig1 ; Some sig2 ; Some sig3 ] ]= -- fails (order is incorrect)

Users sign a pair consisting of the variant case and a second pair of the contract's address and a natural number. This number increases on every successful run of the contract to prevent replay attacks. The address is included to prevent replays across multiple instances of the contract.

** Full =parameter= type

In addition to executing one of the actions described above, the contract needs to vest at predefined intervals. The vesting operation requires no signatures and can be triggered by anyone, provided the timing criteria have been met. When the vest action occurs, an amount of Tez, specified in the storage, is added to the available balance and the next vesting date is pushed forward by the =vesting_interval= (also specified in the storage). The next vesting date is not necessarily greater than the current timestamp, and multiple, separate vesting operations may be necessary to redeem all of the Tez that are available at the current timestamp.

The contract also supports a pour operation. This operation allows a single approver to sign transactions to a single, agreed upon contract. This feature can be toggled by the signers.

To support these features, the contract has an outer =or= type. The =Left= variant includes action entrypoints and signatures. The =Right= variant includes the =pour= and =vest= entrypoints. A =pour= is encoded as =Right (option (pair signature mutez))=. The signature consists of the "pour contract" in the storage, the amount to be transferred, the address of the current contract, and the replay counter value (=(pair (pair (contract unit) mutez) (pair address nat))=). If no pour data is set in the storage, the operation fails. A =vest= call consists of =Right (Right None)=.

The full parameter type is:

#+BEGIN_SRC michelson

** The storage type

A number of values are configurable in the storage:

- The =replay_prevention= variable (should be initialized to =0=)

- The key information:

- The key group list -- At least N of the M groups must have P of Q valid signatures (where P and Q are set on a per-group basis)

- The overall threshold

- The vesting balance information:

- The vesting amount (the amount added each vesting interval), set to be a string if the contract is not activated

- The current balance (though only the initial balance is settable in the storage)

- The vesting schedule:

- The timestamp of the next payout (should be set to one vesting interval after the genesis block)

- The payout rate, which is the frequency of vests in seconds

- The pour information (can be set to =None=, which disables pours entirely)

- The destination contract that will receive the funds from a valid pour operation

- The authorizer key, which can trigger a pour operation by signing the appropriate data

The full storage type is:

#+BEGIN_SRC michelson

** Transfers

Transfers are possible to any contract that accepts the =unit= value as its parameter. If you want to call a contract that does not have this type, an intermediate call to another contract is required. The transfer specifies an amount of tez (in =mutez=) to transfer. If the amount to be transferred exceeds the available balance, the transfer fails.

** Setting keys

In the event that one or more keys are compromised, the entire list of keys can be replaced. There is no way to disable only a single key. All keys, or none must be replaced at once. This also allows new thresholds to be set.

** Setting the delegate

A delegate or no delegate can be set from the contract. This is done by providing an optional key hash.

** Pour operation

If a pour address is set, a pour operation may be executed. This operation includes a one-party signature of the data, as specified above. This operation increments the replay counter. The operation fails if the signature is incorrect, the pour data is set to =None= in the storage, or the amount to be transferred exceeds the available balance.

** Activate operation