1
1
import json
2
2
import random
3
3
import time
4
+ import itertools
4
5
5
6
import rlp
6
7
10
11
from ethereum .slogging import get_logger
11
12
from ethereum .state import State
12
13
from ethereum .state_transition import apply_block , initialize , \
13
- update_block_env_variables
14
+ pre_seal_finalize , post_seal_finalize , apply_transaction , mk_receipt_sha , \
15
+ mk_transaction_sha , calc_difficulty , Receipt , mk_receipt , \
16
+ update_block_env_variables , validate_uncles , validate_block_header
14
17
from ethereum .utils import encode_hex , parse_as_bin , big_endian_to_int
15
18
16
19
log = get_logger ('eth.chain' )
@@ -70,9 +73,9 @@ def __init__(self, genesis=None, env=None, coinbase=b'\x00' * 20, \
70
73
self .db .put ('GENESIS_HASH' , str (self .genesis .header .hash ))
71
74
self .db .put ('GENESIS_STATE' , json .dumps (self .state .to_snapshot ()))
72
75
self .db .put ('GENESIS_RLP' , rlp .encode (self .genesis ))
73
- self .db .put ('score:' + self .genesis .header .hash , "0" )
74
- self .db .put ('state:' + self .genesis .header .hash , self .state .trie .root_hash )
75
- self .db .put ('block:0' , self .genesis .header .hash )
76
+ self .db .put (b 'score:' + self .genesis .header .hash , "0" )
77
+ self .db .put (b 'state:' + self .genesis .header .hash , self .state .trie .root_hash )
78
+ self .db .put (b 'block:0' , self .genesis .header .hash )
76
79
self .db .put (self .head_hash , 'GENESIS' )
77
80
self .db .commit ()
78
81
else :
@@ -105,7 +108,7 @@ def mk_poststate_of_blockhash(self, blockhash, convert=False):
105
108
block = rlp .decode (block_rlp , Block )
106
109
107
110
state = State (env = self .env )
108
- state .trie .root_hash = block .header .state_root if convert else self .db .get ('state:' + blockhash )
111
+ state .trie .root_hash = block .header .state_root if convert else self .db .get (b 'state:'+ blockhash )
109
112
update_block_env_variables (state , block )
110
113
state .gas_used = block .header .gas_used
111
114
state .txindex = len (block .transactions )
@@ -158,18 +161,18 @@ def get_block(self, blockhash):
158
161
# parent hash and see that it is one of its children
159
162
def add_child (self , child ):
160
163
try :
161
- existing = self .db .get ('ci :' + child .header .prevhash )
164
+ existing = self .db .get (b'child :' + child .header .prevhash )
162
165
except :
163
- existing = ''
166
+ existing = b ''
164
167
existing_hashes = []
165
168
for i in range (0 , len (existing ), 32 ):
166
169
existing_hashes .append (existing [i : i + 32 ])
167
170
if child .header .hash not in existing_hashes :
168
- self .db .put ('ci :' + child .header .prevhash , existing + child .header .hash )
171
+ self .db .put (b'child :' + child .header .prevhash , existing + child .header .hash )
169
172
170
173
def get_blockhash_by_number (self , number ):
171
174
try :
172
- return self .db .get ('block:' + str (number ))
175
+ return self .db .get (b 'block:' + str (number ))
173
176
except :
174
177
return None
175
178
@@ -180,7 +183,7 @@ def get_block_by_number(self, number):
180
183
def get_child_hashes (self , blockhash ):
181
184
o = []
182
185
try :
183
- data = self .db .get ('child:' + blockhash )
186
+ data = self .db .get (b 'child:' + blockhash )
184
187
for i in range (0 , len (data ), 32 ):
185
188
o .append (data [i :i + 32 ])
186
189
return o
@@ -198,16 +201,16 @@ def get_children(self, block):
198
201
def get_score (self , block ):
199
202
if not block :
200
203
return 0
201
- key = 'score:' + block .header .hash
204
+ key = b 'score:' + block .header .hash
202
205
203
206
fills = []
204
207
while key not in self .db :
205
208
fills .insert (0 , (block .header .hash , block .difficulty ))
206
- key = 'score:' + block .header .prevhash
209
+ key = b 'score:' + block .header .prevhash
207
210
block = self .get_parent (block )
208
211
score = int (self .db .get (key ))
209
212
for h ,d in fills :
210
- key = 'score:' + h
213
+ key = b 'score:' + h
211
214
score = score + d + random .randrange (d // 10 ** 6 + 1 )
212
215
self .db .put (key , str (score ))
213
216
@@ -255,52 +258,52 @@ def add_block(self, block):
255
258
except (KeyError , ValueError ) as e : # FIXME add relevant exceptions here
256
259
log .info ('Block %s with parent %s invalid, reason: %s' % (encode_hex (block .header .hash ), encode_hex (block .header .prevhash ), e ))
257
260
return False
258
- self .db .put ('block:' + str (block .header .number ), block .header .hash )
259
- self .db .put ('state:' + block .header .hash , self .state .trie .root_hash )
261
+ self .db .put (b 'block:' + str (block .header .number ), block .header .hash )
262
+ self .db .put (b 'state:' + block .header .hash , self .state .trie .root_hash )
260
263
block_score = self .get_score (block ) # side effect: put 'score:' cache in db
261
264
self .head_hash = block .header .hash
262
265
for i , tx in enumerate (block .transactions ):
263
- self .db .put ('txindex:' + tx .hash , rlp .encode ([block .number , i ]))
266
+ self .db .put (b 'txindex:' + tx .hash , rlp .encode ([block .number , i ]))
264
267
elif block .header .prevhash in self .env .db :
265
268
log .info ('Receiving block not on head, adding to secondary post state' ,
266
269
prevhash = encode_hex (block .header .prevhash ))
267
270
temp_state = self .mk_poststate_of_blockhash (block .header .prevhash )
268
271
try :
269
272
apply_block (temp_state , block )
270
- except (KeyError , ValueError ), e : # FIXME add relevant exceptions here
273
+ except (KeyError , ValueError ) as e : # FIXME add relevant exceptions here
271
274
log .info ('Block %s with parent %s invalid, reason: %s' % (encode_hex (block .header .hash ), encode_hex (block .header .prevhash ), e ))
272
275
return False
273
- self .db .put ('state:' + block .header .hash , temp_state .trie .root_hash )
276
+ self .db .put (b 'state:' + block .header .hash , temp_state .trie .root_hash )
274
277
block_score = self .get_score (block )
275
278
# Replace the head
276
279
if block_score > self .get_score (self .head ):
277
280
b = block
278
281
new_chain = {}
279
282
while b .header .number >= int (self .db .get ('GENESIS_NUMBER' )):
280
283
new_chain [b .header .number ] = b
281
- key = 'block:' + str (b .header .number )
284
+ key = b 'block:' + str (b .header .number )
282
285
orig_at_height = self .db .get (key ) if key in self .db else None
283
286
if orig_at_height == b .header .hash :
284
287
break
285
288
if b .prevhash not in self .db or self .db .get (b .prevhash ) == 'GENESIS' :
286
289
break
287
290
b = self .get_parent (b )
288
291
replace_from = b .header .number
289
- for i in xrange (replace_from , 2 ** 63 - 1 ):
292
+ for i in itertools . count (replace_from ):
290
293
log .info ('Rewriting height %d' % i )
291
- key = 'block:' + str (i )
294
+ key = b 'block:' + str (i )
292
295
orig_at_height = self .db .get (key ) if key in self .db else None
293
296
if orig_at_height :
294
297
self .db .delete (key )
295
298
orig_block_at_height = self .get_block (orig_at_height )
296
299
for tx in orig_block_at_height .transactions :
297
- if 'txindex:' + tx .hash in self .db :
298
- self .db .delete ('txindex:' + tx .hash )
300
+ if b 'txindex:' + tx .hash in self .db :
301
+ self .db .delete (b 'txindex:' + tx .hash )
299
302
if i in new_chain :
300
303
new_block_at_height = new_chain [i ]
301
304
self .db .put (key , new_block_at_height .header .hash )
302
305
for i , tx in enumerate (new_block_at_height .transactions ):
303
- self .db .put ('txindex:' + tx .hash ,
306
+ self .db .put (b 'txindex:' + tx .hash ,
304
307
rlp .encode ([new_block_at_height .number , i ]))
305
308
if i not in new_chain and not orig_at_height :
306
309
break
@@ -346,7 +349,7 @@ def get_chain(self, frm=None, to=2**63 - 1):
346
349
if frm is None :
347
350
frm = int (self .db .get ('GENESIS_NUMBER' )) + 1
348
351
chain = []
349
- for i in xrange ( frm , to ):
352
+ for i in itertools . islice ( itertools . count (), frm , to ):
350
353
h = self .get_blockhash_by_number (i )
351
354
if not h :
352
355
return chain
@@ -356,8 +359,8 @@ def get_chain(self, frm=None, to=2**63 - 1):
356
359
def get_transaction (self , tx ):
357
360
if not isinstance (tx , (str , bytes )):
358
361
tx = tx .hash
359
- if 'txindex:' + tx in self .db :
360
- data = rlp .decode (self .db .get ('txindex:' + tx ))
362
+ if b 'txindex:' + tx in self .db :
363
+ data = rlp .decode (self .db .get (b 'txindex:' + tx ))
361
364
blk , index = self .get_block_by_number (
362
365
big_endian_to_int (data [0 ])), big_endian_to_int (data [1 ])
363
366
tx = blk .transactions [index ]
0 commit comments