1
1
use bech32:: { self , FromBase32 } ;
2
- use chain_addr:: { Address , Kind } ;
2
+ use chain_addr:: { Address , AddressReadable , Kind } ;
3
3
use chain_crypto:: { Ed25519 , PublicKey } ;
4
4
use chain_impl_mockchain:: account;
5
5
@@ -10,15 +10,21 @@ use chain_impl_mockchain::{
10
10
block:: Block , chaintypes:: HeaderId , fragment:: Fragment , transaction:: InputEnum ,
11
11
} ;
12
12
13
- use tracing:: error;
13
+ use tracing:: { error, info } ;
14
14
15
15
use jormungandr_lib:: interfaces:: AccountIdentifier ;
16
16
17
17
const MAIN_TAG : & str = "HEAD" ;
18
18
19
- use std:: path:: Path ;
19
+ use std:: {
20
+ collections:: { HashMap , HashSet } ,
21
+ error,
22
+ fs:: { read_to_string, File } ,
23
+ io:: BufWriter ,
24
+ path:: { Path , PathBuf } ,
25
+ } ;
20
26
21
- use crate :: offline:: Vote ;
27
+ use crate :: offline:: { extract_fragments_from_storage , Vote } ;
22
28
23
29
#[ derive( Debug , thiserror:: Error ) ]
24
30
pub enum Error {
@@ -177,15 +183,147 @@ pub fn find_vote(jormungandr_database: &Path, voting_key: String) -> Result<Vec<
177
183
Ok ( votes)
178
184
}
179
185
186
+ /// Collect all voting keys in ca and 0x format and write to files
187
+ pub fn all_voters (
188
+ jormungandr_database : & Path ,
189
+ ) -> Result < ( HashSet < std:: string:: String > , HashSet < std:: string:: String > ) , Box < dyn error:: Error > > {
190
+ let fragments = extract_fragments_from_storage ( jormungandr_database) ?;
191
+
192
+ let mut unique_voters_ca = HashSet :: new ( ) ;
193
+ let mut unique_voters_0x = HashSet :: new ( ) ;
194
+
195
+ for fragment in fragments {
196
+ if let Fragment :: VoteCast ( tx) = fragment. clone ( ) {
197
+ let input = tx. as_slice ( ) . inputs ( ) . iter ( ) . next ( ) . unwrap ( ) . to_enum ( ) ;
198
+ let caster = if let InputEnum :: AccountInput ( account_id, _value) = input {
199
+ AccountIdentifier :: from ( account_id) . into_address ( Discrimination :: Production , "ca" )
200
+ } else {
201
+ error ! ( "Corrupted fragment {:?}" , fragment) ;
202
+ continue ;
203
+ } ;
204
+
205
+ unique_voters_ca. insert ( caster. to_string ( ) . clone ( ) ) ;
206
+
207
+ let voting_key_61824_format = AddressReadable :: from_string ( "ca" , & caster. to_string ( ) )
208
+ . expect ( "infallible" )
209
+ . to_address ( ) ;
210
+
211
+ let voting_key = voting_key_61824_format
212
+ . public_key ( )
213
+ . expect ( "infallible" )
214
+ . to_string ( ) ;
215
+ unique_voters_0x. insert ( voting_key) ;
216
+ }
217
+ }
218
+
219
+ info ! ( "unique voters ca {:?}" , unique_voters_ca. len( ) ) ;
220
+ info ! ( "unique voters 0x {:?}" , unique_voters_0x. len( ) ) ;
221
+
222
+ Ok ( ( unique_voters_ca, unique_voters_0x) )
223
+ }
224
+
225
+ /// convert keys from ca to 0x and vice versa
226
+ pub fn convert_key_formats ( voting_key : String ) -> Result < String , Box < dyn error:: Error > > {
227
+ if voting_key. starts_with ( "ca" ) {
228
+ let voting_key_61824_format = AddressReadable :: from_string ( "ca" , & voting_key) ?. to_address ( ) ;
229
+
230
+ let voting_key = voting_key_61824_format
231
+ . public_key ( )
232
+ . expect ( "addr to pub key is infallible" )
233
+ . to_string ( ) ;
234
+
235
+ Ok ( voting_key)
236
+ } else {
237
+ // we need to convert this to our internal key representation
238
+ let decoded_voting_key = hex:: decode ( voting_key) ?;
239
+ let voting_key: PublicKey < Ed25519 > = PublicKey :: from_binary ( & decoded_voting_key) ?;
240
+ let addr = Address ( Discrimination :: Production , Kind :: Single ( voting_key. clone ( ) ) ) ;
241
+ let addr_readable = AddressReadable :: from_address ( "ca" , & addr) ;
242
+
243
+ Ok ( addr_readable. to_string ( ) )
244
+ }
245
+ }
246
+
247
+ /// read voter keys from file
248
+ pub fn read_lines ( filename : & str ) -> Result < Vec < String > , Box < dyn error:: Error > > {
249
+ let mut result = Vec :: new ( ) ;
250
+
251
+ for line in read_to_string ( filename) ?. lines ( ) {
252
+ result. push ( line. to_string ( ) )
253
+ }
254
+
255
+ Ok ( result)
256
+ }
257
+
258
+ /// check key history of multiple keys and write metadata to file
259
+ pub fn batch_key_check (
260
+ jormungandr_database : & Path ,
261
+ key_file : String ,
262
+ ) -> Result < ( ) , Box < dyn error:: Error > > {
263
+ let mut flagged_keys = HashMap :: new ( ) ;
264
+
265
+ let keys = read_lines ( & key_file) ?;
266
+
267
+ for key in keys {
268
+ let voting_key_61824_format = AddressReadable :: from_string ( "ca" , & key)
269
+ . expect ( "infallible" )
270
+ . to_address ( ) ;
271
+
272
+ let voting_key = voting_key_61824_format
273
+ . public_key ( )
274
+ . expect ( "infallible" )
275
+ . to_string ( ) ;
276
+
277
+ let votes = find_vote ( jormungandr_database, voting_key) ?;
278
+
279
+ flagged_keys. insert ( key. clone ( ) , votes. clone ( ) ) ;
280
+
281
+ info ! ( "Inserted: key: {} vote: {:?}" , key, votes) ;
282
+ }
283
+
284
+ let flagged_file = PathBuf :: from ( "/tmp/inspect" ) . with_extension ( "flag_keys.json" ) ;
285
+
286
+ let file = File :: options ( )
287
+ . write ( true )
288
+ . create ( true )
289
+ . truncate ( true )
290
+ . open ( flagged_file. clone ( ) ) ?;
291
+ let writer = BufWriter :: new ( file) ;
292
+
293
+ serde_json:: to_writer_pretty ( writer, & flagged_keys) ?;
294
+
295
+ info ! ( "flagged keys and metadata saved here {:?}" , flagged_file) ;
296
+
297
+ Ok ( ( ) )
298
+ }
299
+
180
300
#[ cfg( test) ]
181
301
mod tests {
302
+
182
303
use std:: path:: PathBuf ;
183
304
184
305
use chain_addr:: { Address , AddressReadable , Discrimination , Kind } ;
185
306
use chain_crypto:: { Ed25519 , PublicKey } ;
186
307
187
308
use crate :: find:: find_vote;
188
309
310
+ use super :: convert_key_formats;
311
+
312
+ #[ test]
313
+ fn test_key_conversion ( ) {
314
+ let voting_key_0x =
315
+ "f895a6a7f44dd15f7700c60456c93793b1241fdd1c77bbb6cd3fc8a4d24c8c1b" . to_string ( ) ;
316
+
317
+ let converted_key = convert_key_formats ( voting_key_0x. clone ( ) ) . unwrap ( ) ;
318
+
319
+ let voting_key_ca =
320
+ "ca1q0uftf4873xazhmhqrrqg4kfx7fmzfqlm5w80wake5lu3fxjfjxpk6wv3f7" . to_string ( ) ;
321
+
322
+ assert_eq ! ( converted_key, voting_key_ca, ) ;
323
+
324
+ assert_eq ! ( convert_key_formats( voting_key_ca) . unwrap( ) , voting_key_0x) ;
325
+ }
326
+
189
327
#[ test]
190
328
#[ ignore]
191
329
fn test_account_parser ( ) {
0 commit comments