Numerical Unanimity
Anchors a unanimity regarding a numerical value
The proof of unanimity is a transaction on the blockchain, emitted if and only if all declared signatories have signed a value close enough to the average signed value.
Let
• n be the number of signatories
• a be the average signed value
• d be the percentage of deviation toward a
• S be the set of signed values.
The unanimity is reached if:
$|S|=n \land \forall s \space in \space S, (1-\frac d 2)·a ≤ s ≤ (1+\frac d 2)·a$
For example, say 2 signatories must sign a value with an authorized deviation of 2%. Unanimity is reached only in situation 2 below:
The unanimity logic is encoded by a smart contract that manages as many unanimity processes as necessary.
• a unique consensus identifier
• the list of required signatories
A signatory signs with:
• the consensus id
• the value
A “unanimity” transaction is generated when all signatories haves signed a quasi-equal value.
Below is the archetype implementation:
1
archetype unanimity
2
3
variable admin : role = @tz1ZXf37ZNfVupt5GVyrPJ76q8kbjFuD2z7R
4
5
asset sig identified by id signatory {
6
id : string;
7
8
value : int;
9
}
10
11
asset sig_spec {
12
sid : string;
13
14
dev : int; /* deviation toward avg. in nb. of percent */
15
expiration : date;
16
signatures : partition<sig> = [];
17
} with {
18
s0 : 0 <= dev <= 100;
19
}
20
21
entry create_sig (i : string, s : list<address>, d : int) {
22
23
effect {
24
sig_spec.add({ sid = i; signatories = s; dev = d; expiration = (now + 1d) });
25
}
26
}
27
28
function get_signatures(spid : string) : list<address * int> {
29
var l : list<address * int> = [];
30
for s in sig_spec[spid].signatures do
31
l := prepend(l, (sig[s].signatory, sig[s].value));
32
done;
33
return l
34
}
35
36
function check_sig_data(spid : string) : bool {
37
var avg = sig_spec[spid].signatures.sum(value) / sig_spec[spid].signatures.count();
38
var min = (1 - sig_spec[spid].dev / 200) * avg;
39
var max = (1 + sig_spec[spid].dev / 200) * avg;
40
var check = true;
41
for s in sig_spec[spid].signatures do
42
check &= min <= sig[s].value <= max
43
done;
44
return check
45
}
46
47
entry unanimity (spid : string, l : list<address * int>, d : int) {
48
49
}
50
51
entry failed (spid : string, l : list<address * int>, d : int) {
52
53
}
54
55
entry sign (spid : string, v : int) {
56
require {
57
r0 : contains(sig_spec[spid].signatories, caller);
58
}
59
effect {
60
61
if sig_spec[spid].signatures.count() = length (sig_spec[spid].signatories) then (
62
var sigs = get_signatures(spid);
63
var d = sig_spec[spid].dev;
64
var selfentry = if check_sig_data (spid) then self.unanimity else self.failed;
65
transfer 0tz to entry selfentry((spid, sigs, d));
66
sig_spec.remove(spid);
67
);
68
}
69
}
70
71
entry clear_expired () {
72
73
effect {
74
sig_spec.select(the.expiration < now).clear();
75
}
76
}
77
Copied!