1
- #!/usr/bin/env python
1
+ #!/usr/bin/env python3
2
2
#
3
3
# linearize-data.py: Construct a linear, no-fork version of the chain.
4
4
#
8
8
#
9
9
10
10
from __future__ import print_function , division
11
+ try : # Python 3
12
+ import http .client as httplib
13
+ except ImportError : # Python 2
14
+ import httplib
11
15
import json
12
16
import struct
13
17
import re
14
18
import os
15
19
import os .path
16
20
import base64
17
- import httplib
18
21
import sys
19
22
import hashlib
20
23
import datetime
21
24
import time
22
25
from collections import namedtuple
26
+ from binascii import hexlify , unhexlify
23
27
24
28
settings = {}
25
29
30
+ ##### Switch endian-ness #####
31
+ def hex_switchEndian (s ):
32
+ """ Switches the endianness of a hex string (in pairs of hex chars) """
33
+ pairList = [s [i :i + 2 ].encode () for i in range (0 , len (s ), 2 )]
34
+ return b'' .join (pairList [::- 1 ]).decode ()
35
+
26
36
def uint32 (x ):
27
- return x & 0xffffffffL
37
+ return x & 0xffffffff
28
38
29
39
def bytereverse (x ):
30
40
return uint32 (( ((x ) << 24 ) | (((x ) << 8 ) & 0x00ff0000 ) |
@@ -35,14 +45,14 @@ def bufreverse(in_buf):
35
45
for i in range (0 , len (in_buf ), 4 ):
36
46
word = struct .unpack ('@I' , in_buf [i :i + 4 ])[0 ]
37
47
out_words .append (struct .pack ('@I' , bytereverse (word )))
38
- return '' .join (out_words )
48
+ return b '' .join (out_words )
39
49
40
50
def wordreverse (in_buf ):
41
51
out_words = []
42
52
for i in range (0 , len (in_buf ), 4 ):
43
53
out_words .append (in_buf [i :i + 4 ])
44
54
out_words .reverse ()
45
- return '' .join (out_words )
55
+ return b '' .join (out_words )
46
56
47
57
def calc_hdr_hash (blk_hdr ):
48
58
hash1 = hashlib .sha256 ()
@@ -59,7 +69,7 @@ def calc_hash_str(blk_hdr):
59
69
hash = calc_hdr_hash (blk_hdr )
60
70
hash = bufreverse (hash )
61
71
hash = wordreverse (hash )
62
- hash_str = hash . encode ( 'hex ' )
72
+ hash_str = hexlify ( hash ). decode ( 'utf-8 ' )
63
73
return hash_str
64
74
65
75
def get_blk_dt (blk_hdr ):
@@ -69,17 +79,21 @@ def get_blk_dt(blk_hdr):
69
79
dt_ym = datetime .datetime (dt .year , dt .month , 1 )
70
80
return (dt_ym , nTime )
71
81
82
+ # When getting the list of block hashes, undo any byte reversals.
72
83
def get_block_hashes (settings ):
73
84
blkindex = []
74
85
f = open (settings ['hashlist' ], "r" )
75
86
for line in f :
76
87
line = line .rstrip ()
88
+ if settings ['rev_hash_bytes' ] == 'true' :
89
+ line = hex_switchEndian (line )
77
90
blkindex .append (line )
78
91
79
92
print ("Read " + str (len (blkindex )) + " hashes" )
80
93
81
94
return blkindex
82
95
96
+ # The block map shouldn't give or receive byte-reversed hashes.
83
97
def mkblockmap (blkindex ):
84
98
blkmap = {}
85
99
for height ,hash in enumerate (blkindex ):
@@ -207,7 +221,7 @@ def run(self):
207
221
208
222
inMagic = inhdr [:4 ]
209
223
if (inMagic != self .settings ['netmagic' ]):
210
- print ("Invalid magic: " + inMagic . encode ( 'hex ' ))
224
+ print ("Invalid magic: " + hexlify ( inMagic ). decode ( 'utf-8 ' ))
211
225
return
212
226
inLenLE = inhdr [4 :]
213
227
su = struct .unpack ("<I" , inLenLE )
@@ -265,6 +279,12 @@ def run(self):
265
279
settings [m .group (1 )] = m .group (2 )
266
280
f .close ()
267
281
282
+ # Force hash byte format setting to be lowercase to make comparisons easier.
283
+ # Also place upfront in case any settings need to know about it.
284
+ if 'rev_hash_bytes' not in settings :
285
+ settings ['rev_hash_bytes' ] = 'false'
286
+ settings ['rev_hash_bytes' ] = settings ['rev_hash_bytes' ].lower ()
287
+
268
288
if 'netmagic' not in settings :
269
289
settings ['netmagic' ] = 'f9beb4d9'
270
290
if 'genesis' not in settings :
@@ -278,14 +298,14 @@ def run(self):
278
298
if 'split_timestamp' not in settings :
279
299
settings ['split_timestamp' ] = 0
280
300
if 'max_out_sz' not in settings :
281
- settings ['max_out_sz' ] = 1000L * 1000 * 1000
301
+ settings ['max_out_sz' ] = 1000 * 1000 * 1000
282
302
if 'out_of_order_cache_sz' not in settings :
283
303
settings ['out_of_order_cache_sz' ] = 100 * 1000 * 1000
284
304
285
- settings ['max_out_sz' ] = long (settings ['max_out_sz' ])
305
+ settings ['max_out_sz' ] = int (settings ['max_out_sz' ])
286
306
settings ['split_timestamp' ] = int (settings ['split_timestamp' ])
287
307
settings ['file_timestamp' ] = int (settings ['file_timestamp' ])
288
- settings ['netmagic' ] = settings ['netmagic' ].decode ( 'hex' )
308
+ settings ['netmagic' ] = unhexlify ( settings ['netmagic' ].encode ( 'utf-8' ) )
289
309
settings ['out_of_order_cache_sz' ] = int (settings ['out_of_order_cache_sz' ])
290
310
291
311
if 'output_file' not in settings and 'output' not in settings :
@@ -295,9 +315,8 @@ def run(self):
295
315
blkindex = get_block_hashes (settings )
296
316
blkmap = mkblockmap (blkindex )
297
317
318
+ # Block hash map won't be byte-reversed. Neither should the genesis hash.
298
319
if not settings ['genesis' ] in blkmap :
299
320
print ("Genesis block not found in hashlist" )
300
321
else :
301
322
BlockDataCopier (settings , blkindex , blkmap ).run ()
302
-
303
-
0 commit comments