Source file tenderbrute.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
open Protocol
type delegate_selection =
(Raw_level_repr.t * (Round_repr.t * Signature.public_key_hash) list) list
module LevelRoundMap = Map.Make (struct
type t = Level_repr.t * Round_repr.t
let compare (l1, r1) (l2, r2) =
Stdlib.compare
(Raw_level_repr.to_int32 l1.Level_repr.level, Round_repr.to_int32 r1)
(Raw_level_repr.to_int32 l2.Level_repr.level, Round_repr.to_int32 r2)
end)
let _ = Client_keys.register_signer (module Tezos_signer_backends.Unencrypted)
let init_context ?constants_overrides_json ?bootstrap_accounts_json parameters =
let parameters =
Data_encoding.Binary.of_bytes_exn Mockup.M.parameters_encoding
@@ Data_encoding.Binary.to_bytes_exn
Mockup.Protocol_parameters.encoding
parameters
in
Mockup.M.init
~cctxt:Client_context.null_printer
~parameters
~constants_overrides_json
~bootstrap_accounts_json
>>=? fun mockup_init ->
let ctxt = mockup_init.rpc_context.context in
let timestamp = Time.Protocol.of_seconds 0L in
Raw_context.prepare ctxt ~level:1l ~predecessor_timestamp:timestamp ~timestamp
>|= Environment.wrap_tzresult
let change_seed ?initial_seed ctxt =
let preserved = Constants_storage.preserved_cycles ctxt in
List.fold_left_es
(fun (c, ctxt) seed ->
let cycle = Cycle_repr.of_int32_exn (Int32.of_int c) in
Storage.Seed.For_cycle.remove_existing ctxt cycle >>=? fun ctxt ->
Storage.Seed.For_cycle.init ctxt cycle seed >|=? fun ctxt -> (c + 1, ctxt))
(0, ctxt)
(Seed_repr.initial_seeds ?initial_seed (preserved + 2))
>|=? snd
let init ?constants_overrides_json ?bootstrap_accounts_json parameters =
init_context ?constants_overrides_json ?bootstrap_accounts_json parameters
>>=? fun ctxt ->
let blocks_per_cycle = Constants_storage.blocks_per_cycle ctxt in
let blocks_per_commitment = Constants_storage.blocks_per_commitment ctxt in
let cycle_eras =
[
Level_repr.
{
first_level = Raw_level_repr.of_int32_exn 0l;
first_cycle = Cycle_repr.root;
blocks_per_cycle;
blocks_per_commitment;
};
]
in
Level_repr.create_cycle_eras cycle_eras |> Environment.wrap_tzresult
>>?= fun cycle_eras -> return (ctxt, cycle_eras)
let check ctxt ~selection =
Lwt.catch
(fun () ->
LevelRoundMap.fold_es
(fun (level, round) delegate ctxt ->
Delegate_sampler.baking_rights_owner ctxt level ~round
>|= Environment.wrap_tzresult
>>=? fun (ctxt, _, pk) ->
if not (Signature.Public_key_hash.equal delegate pk.delegate) then
raise Exit
else return ctxt)
selection
ctxt
>>=? fun _ctxt -> return_true)
(function Exit -> return_false | e -> raise e)
let rnd_bytes32 () =
let b1 = Random.int64 Int64.max_int in
let b2 = Random.int64 Int64.max_int in
let b3 = Random.int64 Int64.max_int in
let b4 = Random.int64 Int64.max_int in
let b = Bytes.make 32 '\000' in
TzEndian.set_int64 b 0 b1 ;
TzEndian.set_int64 b 8 b2 ;
TzEndian.set_int64 b 16 b3 ;
TzEndian.set_int64 b 24 b4 ;
b
let mk_selection_map cycle_eras selection =
List.fold_left
(fun acc (level, round_delegates) ->
let level = Level_repr.level_from_raw ~cycle_eras level in
List.fold_left
(fun acc (round, delegate) ->
if LevelRoundMap.mem (level, round) acc then
Stdlib.failwith "Duplicate level/round" ;
LevelRoundMap.add (level, round) delegate acc)
acc
round_delegates)
LevelRoundMap.empty
selection
let bruteforce ?(show_progress = false) ?(random_seed = 0) ?max
?(parameters = Mockup.Protocol_parameters.default_value)
?constants_overrides_json ?bootstrap_accounts_json selection =
Random.init random_seed ;
init ?constants_overrides_json ?bootstrap_accounts_json parameters
>>=? fun (ctxt, cycle_eras) ->
let selection = mk_selection_map cycle_eras selection in
let last_nb_chars = ref 0 in
let frames =
[|
"( ● )";
"( ● )";
"( ● )";
"( ● )";
"( ●)";
"( ● )";
"( ● )";
"( ● )";
"( ● )";
"(● )";
|]
in
let nframes = Array.length frames in
let frame n = frames.(n mod nframes) in
let rec loop n =
if show_progress && n <> 0 && n mod 10_000 = 0 then (
Format.eprintf "%s" (String.make !last_nb_chars '\b') ;
let s = frame (n / 10_000) ^ " " ^ string_of_int n in
last_nb_chars := String.length s ;
Format.eprintf "%s%!" s) ;
match max with
| Some max when n > max -> failwith "Did not find seed nonce"
| _ -> (
let initial_seed =
if n = 0 then None
else Some (State_hash.of_bytes_exn (rnd_bytes32 ()))
in
change_seed ?initial_seed ctxt >|= Environment.wrap_tzresult
>>=? fun ctxt ->
check ctxt ~selection >>=? function
| true ->
Format.eprintf "%s%!" (String.make !last_nb_chars '\b') ;
return initial_seed
| false -> loop (n + 1))
in
loop 0
let check_seed ?(parameters = Mockup.Protocol_parameters.default_value)
?constants_overrides_json ?bootstrap_accounts_json ~seed selection =
init ?constants_overrides_json ?bootstrap_accounts_json parameters
>>=? fun (ctxt, cycle_eras) ->
let selection = mk_selection_map cycle_eras selection in
change_seed ?initial_seed:seed ctxt >|= Environment.wrap_tzresult
>>=? fun ctxt -> check ctxt ~selection