Source file vote_storage.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
let get_delegate_proposal_count ctxt proposer =
let open Lwt_result_syntax in
let+ value = Storage.Vote.Proposals_count.find ctxt proposer in
Option.value ~default:0 value
let set_delegate_proposal_count ctxt proposer count =
Storage.Vote.Proposals_count.add ctxt proposer count
let has_proposed ctxt proposer proposal =
Storage.Vote.Proposals.mem ctxt (proposal, proposer)
let add_proposal ctxt proposer proposal =
Storage.Vote.Proposals.add ctxt (proposal, proposer)
let get_proposals ctxt =
let open Lwt_result_syntax in
Storage.Vote.Proposals.fold
ctxt
~order:`Sorted
~init:(Ok Protocol_hash.Map.empty)
~f:(fun (proposal, delegate) acc ->
let* weight = Storage.Vote.Listings.get ctxt delegate in
let*? acc in
let previous =
match Protocol_hash.Map.find proposal acc with
| None -> 0L
| Some x -> x
in
return (Protocol_hash.Map.add proposal (Int64.add weight previous) acc))
let clear_proposals ctxt =
let open Lwt_syntax in
let* ctxt = Storage.Vote.Proposals_count.clear ctxt in
Storage.Vote.Proposals.clear ctxt
type ballots = {yay : int64; nay : int64; pass : int64}
let ballots_zero = {yay = 0L; nay = 0L; pass = 0L}
let ballots_encoding =
let open Data_encoding in
conv
(fun {yay; nay; pass} -> (yay, nay, pass))
(fun (yay, nay, pass) -> {yay; nay; pass})
@@ obj3 (req "yay" int64) (req "nay" int64) (req "pass" int64)
let equal_ballots b1 b2 =
Int64.(equal b1.yay b2.yay && equal b1.nay b2.nay && equal b1.pass b2.pass)
let pp_ballots ppf b =
Format.fprintf ppf "{ yay = %Ld; nay = %Ld; pass = %Ld }" b.yay b.nay b.pass
let has_recorded_ballot = Storage.Vote.Ballots.mem
let record_ballot = Storage.Vote.Ballots.init
let get_ballots ctxt =
let open Lwt_result_syntax in
Storage.Vote.Ballots.fold
ctxt
~order:`Sorted
~f:(fun delegate ballot (ballots : ballots tzresult) ->
let* weight = Storage.Vote.Listings.get ctxt delegate in
let count = Int64.add weight in
let*? ballots in
return
(match ballot with
| Yay -> {ballots with yay = count ballots.yay}
| Nay -> {ballots with nay = count ballots.nay}
| Pass -> {ballots with pass = count ballots.pass}))
~init:(Ok ballots_zero)
let get_ballot_list = Storage.Vote.Ballots.bindings
let clear_ballots = Storage.Vote.Ballots.clear
let listings_encoding =
Data_encoding.(
list
(obj2
(req "pkh" Signature.Public_key_hash.encoding)
(req "voting_power" int64)))
let get_current_voting_power_free ctxt delegate =
let open Lwt_result_syntax in
let* stake = Storage.Stake.Staking_balance.get ctxt delegate in
Lwt.return @@ Full_staking_balance_repr.voting_weight stake
let update_listings ctxt =
let open Lwt_result_syntax in
let*! ctxt = Storage.Vote.Listings.clear ctxt in
let* ctxt, total =
Stake_storage.fold_on_active_delegates_with_minimal_stake_es
ctxt
~init:(ctxt, 0L)
~order:`Sorted
~f:(fun delegate (ctxt, total) ->
let* weight = get_current_voting_power_free ctxt delegate in
let+ ctxt = Storage.Vote.Listings.init ctxt delegate weight in
(ctxt, Int64.add total weight))
in
let*! ctxt = Storage.Vote.Voting_power_in_listings.add ctxt total in
return ctxt
type delegate_info = {
voting_power : Int64.t option;
current_ballot : Vote_repr.ballot option;
current_proposals : Protocol_hash.t list;
remaining_proposals : int;
}
let pp_delegate_info ppf info =
match info.voting_power with
| None -> Format.fprintf ppf "Voting power: none"
| Some p -> (
Format.fprintf
ppf
"Voting power: %a"
Tez_repr.pp
(Tez_repr.of_mutez_exn p) ;
(match info.current_ballot with
| None -> ()
| Some ballot ->
Format.fprintf ppf "@,Current ballot: %a" Vote_repr.pp_ballot ballot) ;
match info.current_proposals with
| [] ->
if Compare.Int.(info.remaining_proposals <> 0) then
Format.fprintf
ppf
"@,Remaining proposals: %d"
info.remaining_proposals
| proposals ->
Format.fprintf ppf "@,@[<v 2>Current proposals:" ;
List.iter
(fun p -> Format.fprintf ppf "@,- %a" Protocol_hash.pp p)
proposals ;
Format.fprintf ppf "@]" ;
Format.fprintf
ppf
"@,Remaining proposals: %d"
info.remaining_proposals)
let delegate_info_encoding =
let open Data_encoding in
conv
(fun {voting_power; current_ballot; current_proposals; remaining_proposals} ->
(voting_power, current_ballot, current_proposals, remaining_proposals))
(fun (voting_power, current_ballot, current_proposals, remaining_proposals) ->
{voting_power; current_ballot; current_proposals; remaining_proposals})
(obj4
(opt "voting_power" int64)
(opt "current_ballot" Vote_repr.ballot_encoding)
(dft "current_proposals" (list Protocol_hash.encoding) [])
(dft "remaining_proposals" int31 0))
let in_listings = Storage.Vote.Listings.mem
let get_listings = Storage.Vote.Listings.bindings
let get_delegate_info ctxt delegate =
let open Lwt_result_syntax in
let* voting_power = Storage.Vote.Listings.find ctxt delegate in
match voting_power with
| None ->
return
{
voting_power;
current_proposals = [];
current_ballot = None;
remaining_proposals = 0;
}
| Some _ ->
let* period = Voting_period_storage.get_current_kind ctxt in
let* current_ballot =
match period with
| Exploration | Promotion -> Storage.Vote.Ballots.find ctxt delegate
| Proposal | Cooldown | Adoption -> return_none
in
let*! current_proposals =
match period with
| Exploration | Promotion | Cooldown | Adoption -> Lwt.return_nil
| Proposal ->
Storage.Vote.Proposals.fold
ctxt
~order:`Undefined
~init:[]
~f:(fun (h, d) acc ->
if Signature.Public_key_hash.equal d delegate then
Lwt.return (h :: acc)
else Lwt.return acc)
in
let remaining_proposals =
match period with
| Proposal ->
Constants_repr.max_proposals_per_delegate
- List.length current_proposals
| _ -> 0
in
return
{voting_power; current_ballot; current_proposals; remaining_proposals}
let get_voting_power_free ctxt owner =
let open Lwt_result_syntax in
let+ value = Storage.Vote.Listings.find ctxt owner in
Option.value ~default:0L value
let get_voting_power ctxt owner =
let open Lwt_result_syntax in
let open Raw_context in
let*? ctxt =
consume_gas ctxt (Storage_costs.read_access ~path_length:4 ~read_bytes:8)
in
let+ power_opt = Storage.Vote.Listings.find ctxt owner in
match power_opt with None -> (ctxt, 0L) | Some power -> (ctxt, power)
let get_total_voting_power_free = Storage.Vote.Voting_power_in_listings.get
let get_total_voting_power ctxt =
let open Lwt_result_syntax in
let open Raw_context in
let*? ctxt =
consume_gas ctxt (Storage_costs.read_access ~path_length:2 ~read_bytes:8)
in
let+ total_voting_power = get_total_voting_power_free ctxt in
(ctxt, total_voting_power)
let get_current_quorum ctxt =
let open Lwt_result_syntax in
let+ participation_ema = Storage.Vote.Participation_ema.get ctxt in
let quorum_min = Constants_storage.quorum_min ctxt in
let quorum_max = Constants_storage.quorum_max ctxt in
let quorum_diff = Int32.sub quorum_max quorum_min in
Int32.(add quorum_min (div (mul participation_ema quorum_diff) 100_00l))
let get_participation_ema = Storage.Vote.Participation_ema.get
let set_participation_ema = Storage.Vote.Participation_ema.update
let current_proposal_exists = Storage.Vote.Current_proposal.mem
let get_current_proposal = Storage.Vote.Current_proposal.get
let find_current_proposal = Storage.Vote.Current_proposal.find
let init_current_proposal = Storage.Vote.Current_proposal.init
let clear_current_proposal = Storage.Vote.Current_proposal.remove
let init ctxt ~start_position =
let open Lwt_result_syntax in
let participation_ema = Constants_storage.quorum_max ctxt in
let* ctxt = Storage.Vote.Participation_ema.init ctxt participation_ema in
Voting_period_storage.init_first_period ctxt ~start_position