@@ -35,6 +35,7 @@ def __init__(self, genesis=None, env=None, \
35
35
# Initialize the state
36
36
if 'head_hash' in self .db : # new head tag
37
37
self .state = self .mk_poststate_of_blockhash (self .db .get ('head_hash' ))
38
+ self .state .executing_on_head = True
38
39
print ('Initializing chain from saved head, #%d (%s)' % \
39
40
(self .state .prev_headers [0 ].number , encode_hex (self .state .prev_headers [0 ].hash )))
40
41
elif genesis is None :
@@ -47,11 +48,11 @@ def __init__(self, genesis=None, env=None, \
47
48
reset_genesis = True
48
49
elif "extraData" in genesis :
49
50
self .state = state_from_genesis_declaration (
50
- genesis , self .env )
51
+ genesis , self .env , executing_on_head = True )
51
52
reset_genesis = True
52
53
print ('Initializing chain from provided genesis declaration' )
53
54
elif "prev_headers" in genesis :
54
- self .state = State .from_snapshot (genesis , self .env )
55
+ self .state = State .from_snapshot (genesis , self .env , executing_on_head = True )
55
56
reset_genesis = True
56
57
print ('Initializing chain from provided state snapshot, %d (%s)' % \
57
58
(self .state .block_number , encode_hex (self .state .prev_headers [0 ].hash [:8 ])))
@@ -248,9 +249,10 @@ def add_block(self, block):
248
249
(now , block .header .timestamp , block .header .timestamp - now ))
249
250
return False
250
251
# Is the block being added to the head?
251
- self .state .deletes = []
252
252
if block .header .prevhash == self .head_hash :
253
253
log .info ('Adding to head' , head = encode_hex (block .header .prevhash ))
254
+ self .state .deletes = []
255
+ self .state .changed = {}
254
256
try :
255
257
apply_block (self .state , block )
256
258
except (AssertionError , KeyError , ValueError , InvalidTransaction , VerificationFailed ) as e :
@@ -264,10 +266,11 @@ def add_block(self, block):
264
266
self .db .put (b'txindex:' + tx .hash , rlp .encode ([block .number , i ]))
265
267
assert self .get_blockhash_by_number (block .header .number ) == block .header .hash
266
268
deletes = self .state .deletes
269
+ changed = self .state .changed
267
270
# Or is the block being added to a chain that is not currently the head?
268
271
elif block .header .prevhash in self .env .db :
269
- log .info ('Receiving block not on head, adding to secondary post state' ,
270
- prevhash = encode_hex (block .header .prevhash ))
272
+ log .info ('Receiving block not on head (%s) , adding to secondary post state %s' %
273
+ ( encode_hex (self . head_hash ), encode_hex ( block .header .prevhash ) ))
271
274
temp_state = self .mk_poststate_of_blockhash (block .header .prevhash )
272
275
try :
273
276
apply_block (temp_state , block )
@@ -277,6 +280,7 @@ def add_block(self, block):
277
280
return False
278
281
deletes = temp_state .deletes
279
282
block_score = self .get_score (block )
283
+ changed = temp_state .changed
280
284
# If the block should be the new head, replace the head
281
285
if block_score > self .get_score (self .head ):
282
286
b = block
@@ -291,7 +295,8 @@ def add_block(self, block):
291
295
if b .prevhash not in self .db or self .db .get (b .prevhash ) == 'GENESIS' :
292
296
break
293
297
b = self .get_parent (b )
294
- # Replace block index and tx indices
298
+ # Replace block index and tx indices, and edit the state cache
299
+ changed_accts = {}
295
300
replace_from = b .header .number
296
301
for i in itertools .count (replace_from ):
297
302
log .info ('Rewriting height %d' % i )
@@ -300,19 +305,40 @@ def add_block(self, block):
300
305
if orig_at_height :
301
306
self .db .delete (key )
302
307
orig_block_at_height = self .get_block (orig_at_height )
308
+ log .info ('%s no longer in main chain' % encode_hex (orig_block_at_height .header .hash ))
303
309
for tx in orig_block_at_height .transactions :
304
310
if b'txindex:' + tx .hash in self .db :
305
311
self .db .delete (b'txindex:' + tx .hash )
312
+ acct_list = self .db .get (b'changed:' + orig_block_at_height .hash )
313
+ for j in range (0 , len (acct_list ), 20 ):
314
+ changed_accts [acct_list [j : j + 20 ]] = True
306
315
if i in new_chain :
307
316
new_block_at_height = new_chain [i ]
317
+ log .info ('%s now in main chain' % encode_hex (new_block_at_height .header .hash ))
308
318
self .db .put (key , new_block_at_height .header .hash )
309
319
for i , tx in enumerate (new_block_at_height .transactions ):
310
320
self .db .put (b'txindex:' + tx .hash ,
311
321
rlp .encode ([new_block_at_height .number , i ]))
322
+ if i < b .number :
323
+ acct_list = self .db .get (b'changed:' + new_block_at_height .hash )
324
+ for j in range (0 , len (acct_list ), 20 ):
325
+ changed_accts [acct_list [j : j + 20 ]] = True
312
326
if i not in new_chain and not orig_at_height :
313
327
break
328
+ for c in changed .keys ():
329
+ changed_accts [c ] = True
330
+ for addr in changed_accts .keys ():
331
+ data = temp_state .trie .get (addr )
332
+ if data :
333
+ self .state .db .put (b'address:' + addr , data )
334
+ else :
335
+ try :
336
+ self .state .db .delete (b'address:' + addr )
337
+ except KeyError :
338
+ pass
314
339
self .head_hash = block .header .hash
315
340
self .state = temp_state
341
+ self .state .executing_on_head = True
316
342
# Block has no parent yet
317
343
else :
318
344
if block .header .prevhash not in self .parent_queue :
@@ -324,6 +350,8 @@ def add_block(self, block):
324
350
self .add_child (block )
325
351
self .db .put ('head_hash' , self .head_hash )
326
352
self .db .put (block .hash , rlp .encode (block ))
353
+ self .db .put (b'changed:' + block .hash , b'' .join (list (changed .keys ())))
354
+ print ('Saved %d address change logs' % len (changed .keys ()))
327
355
self .db .put (b'deletes:' + block .hash , b'' .join (deletes ))
328
356
print ('Saved %d trie node deletes for block %d (%s)' % (len (deletes ), block .number , utils .encode_hex (block .hash )))
329
357
# Delete old junk data
@@ -336,6 +364,7 @@ def add_block(self, block):
336
364
for i in range (0 , len (deletes ), 32 ):
337
365
rdb .delete (deletes [i : i + 32 ])
338
366
self .db .delete (b'deletes:' + old_block_hash )
367
+ self .db .delete (b'changed:' + old_block_hash )
339
368
except KeyError as e :
340
369
print (e )
341
370
pass
0 commit comments