Skip to content
This repository was archived by the owner on May 23, 2023. It is now read-only.

Commit 81d37fc

Browse files
vubvub
authored andcommitted
Added tree split/merge and made next/prev work
1 parent 7828427 commit 81d37fc

File tree

4 files changed

+154
-14
lines changed

4 files changed

+154
-14
lines changed

ethereum/blocks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
# Difficulty adjustment algo
3939
def calc_difficulty(parent, timestamp):
4040
config = parent.config
41-
print 'cutoff', config['HOMESTEAD_FORK_BLKNUM']
4241
offset = parent.difficulty // config['BLOCK_DIFF_FACTOR']
4342
if parent.number >= (config['HOMESTEAD_FORK_BLKNUM'] - 1):
4443
sign = max(1 - ((timestamp - parent.timestamp) // config['HOMESTEAD_DIFF_ADJUSTMENT_CUTOFF']), -99)
@@ -51,6 +50,7 @@ def calc_difficulty(parent, timestamp):
5150
period_count = (parent.number + 1) // config['EXPDIFF_PERIOD']
5251
if period_count >= config['EXPDIFF_FREE_PERIODS']:
5352
o = max(o + 2**(period_count - config['EXPDIFF_FREE_PERIODS']), config['MIN_DIFF'])
53+
# print 'Calculating difficulty of block %d, timestamp difference %d, parent diff %d, child diff %d' % (parent.number + 1, timestamp - parent.timestamp, parent.difficulty, o)
5454
return o
5555

5656

ethereum/tests/test_blocks.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ def run_block_test(params, config_overrides = {}):
9191
assert b2.validate_uncles()
9292
blockmap[b2.hash] = b2
9393
env.db.put(b2.hash, rlp.encode(b2))
94+
print 'Block %d with state root %s' % (b2.number, b2.state.root_hash.encode('hex'))
9495
# blkdict = b.to_dict(False, True, False, True)
9596
# assert blk["blockHeader"] == \
9697
# translate_keys(blkdict["header"], translator_list, lambda y, x: x, [])

ethereum/trie.py

Lines changed: 151 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -460,84 +460,223 @@ def _update_kv_node(self, node, key, value):
460460
return new_node
461461

462462
def _getany(self, node, reverse=False, path=[]):
463+
# print 'getany', node, 'reverse=', reverse, path
463464
node_type = self._get_node_type(node)
464465
if node_type == NODE_TYPE_BLANK:
465466
return None
466467
if node_type == NODE_TYPE_BRANCH:
467-
if node[16]:
468+
if node[16] and not reverse:
469+
# print 'found!', [16], path
468470
return [16]
469471
scan_range = list(range(16))
470472
if reverse:
471473
scan_range.reverse()
472474
for i in scan_range:
473-
o = self._getany(self._decode_to_node(node[i]), path=path + [i])
474-
if o:
475+
o = self._getany(self._decode_to_node(node[i]), reverse=reverse, path=path + [i])
476+
if o is not None:
477+
# print 'found@', [i] + o, path
475478
return [i] + o
479+
if node[16] and reverse:
480+
# print 'found!', [16], path
481+
return [16]
476482
return None
477483
curr_key = without_terminator(unpack_to_nibbles(node[0]))
478484
if node_type == NODE_TYPE_LEAF:
485+
# print 'found#', curr_key, path
479486
return curr_key
480487

481488
if node_type == NODE_TYPE_EXTENSION:
482489
curr_key = without_terminator(unpack_to_nibbles(node[0]))
483490
sub_node = self._decode_to_node(node[1])
484-
return self._getany(sub_node, path=path + curr_key)
491+
return curr_key + self._getany(sub_node, reverse=reverse, path=path + curr_key)
492+
493+
def _split(self, node, key):
494+
node_type = self._get_node_type(node)
495+
if node_type == NODE_TYPE_BLANK:
496+
return BLANK_NODE, BLANK_NODE
497+
elif not key:
498+
return BLANK_NODE, node
499+
elif node_type == NODE_TYPE_BRANCH:
500+
b1 = node[:key[0]]
501+
b1 += [''] * (17 - len(b1))
502+
b2 = node[key[0]+1:]
503+
b2 = [''] * (17 - len(b2)) + b2
504+
b1[16], b2[16] = b2[16], b1[16]
505+
sub = self._decode_to_node(node[key[0]])
506+
sub1, sub2 = self._split(sub, key[1:])
507+
b1[key[0]] = self._encode_node(sub1) if sub1 else ''
508+
b2[key[0]] = self._encode_node(sub2) if sub2 else ''
509+
return self._normalize_branch_node(b1) if len([x for x in b1 if x]) else BLANK_NODE, \
510+
self._normalize_branch_node(b2) if len([x for x in b2 if x]) else BLANK_NODE
511+
512+
descend_key = without_terminator(unpack_to_nibbles(node[0]))
513+
if node_type == NODE_TYPE_LEAF:
514+
if descend_key < key:
515+
return node, BLANK_NODE
516+
else:
517+
return BLANK_NODE, node
518+
elif node_type == NODE_TYPE_EXTENSION:
519+
sub_node = self._decode_to_node(node[1])
520+
sub_key = key[len(descend_key):]
521+
if starts_with(key, descend_key):
522+
sub1, sub2 = self._split(sub_node, sub_key)
523+
subtype1 = self._get_node_type(sub1)
524+
subtype2 = self._get_node_type(sub2)
525+
if not sub1:
526+
o1 = BLANK_NODE
527+
elif subtype1 in (NODE_TYPE_LEAF, NODE_TYPE_EXTENSION):
528+
new_key = key[:len(descend_key)] + unpack_to_nibbles(sub1[0])
529+
o1 = [pack_nibbles(new_key), sub1[1]]
530+
else:
531+
o1 = [pack_nibbles(key[:len(descend_key)]), self._encode_node(sub1)]
532+
if not sub2:
533+
o2 = BLANK_NODE
534+
elif subtype2 in (NODE_TYPE_LEAF, NODE_TYPE_EXTENSION):
535+
new_key = key[:len(descend_key)] + unpack_to_nibbles(sub2[0])
536+
o2 = [pack_nibbles(new_key), sub2[1]]
537+
else:
538+
o2 = [pack_nibbles(key[:len(descend_key)]), self._encode_node(sub2)]
539+
return o1, o2
540+
elif descend_key < key[:len(descend_key)]:
541+
return node, BLANK_NODE
542+
elif descend_key > key[:len(descend_key)]:
543+
return BLANK_NODE, node
544+
else:
545+
return BLANK_NODE, BLANK_NODE
546+
547+
def split(self, key):
548+
key = bin_to_nibbles(key)
549+
r1, r2 = self._split(self.root_node, key)
550+
t1, t2 = Trie(self.db), Trie(self.db)
551+
t1.root_node, t2.root_node = r1, r2
552+
return t1, t2
553+
554+
def _merge(self, node1, node2):
555+
assert isinstance(node1, list) or not node1
556+
assert isinstance(node2, list) or not node2
557+
node_type1 = self._get_node_type(node1)
558+
node_type2 = self._get_node_type(node2)
559+
if not node1:
560+
return node2
561+
if not node2:
562+
return node1
563+
if node_type1 != NODE_TYPE_BRANCH and node_type2 != NODE_TYPE_BRANCH:
564+
descend_key1 = unpack_to_nibbles(node1[0])
565+
descend_key2 = unpack_to_nibbles(node2[0])
566+
# find longest common prefix
567+
prefix_length = 0
568+
for i in range(min(len(descend_key1), len(descend_key2))):
569+
if descend_key1[i] != descend_key2[i]:
570+
break
571+
prefix_length = i + 1
572+
if prefix_length:
573+
sub1 = self._decode_to_node(node1[1]) if node_type1 == NODE_TYPE_EXTENSION else node1[1]
574+
new_sub1 = [
575+
pack_nibbles(descend_key1[prefix_length:]),
576+
sub1
577+
] if descend_key1[prefix_length:] else sub1
578+
sub2 = self._decode_to_node(node2[1]) if node_type2 == NODE_TYPE_EXTENSION else node2[1]
579+
new_sub2 = [
580+
pack_nibbles(descend_key2[prefix_length:]),
581+
sub2
582+
] if descend_key2[prefix_length:] else sub2
583+
return [pack_nibbles(descend_key1[:prefix_length]),
584+
self._encode_node(self._merge(new_sub1, new_sub2))]
585+
586+
nodes = [[node1], [node2]]
587+
for (node, node_type) in zip(nodes, [node_type1, node_type2]):
588+
if node_type != NODE_TYPE_BRANCH:
589+
new_node = [BLANK_NODE] * 17
590+
curr_key = unpack_to_nibbles(node[0][0])
591+
new_node[curr_key[0]] = self._encode_node([
592+
pack_nibbles(curr_key[1:]),
593+
node[0][1]
594+
]) if curr_key[0] < 16 and curr_key[1:] else node[0][1]
595+
node[0] = new_node
596+
node1, node2 = nodes[0][0], nodes[1][0]
597+
assert len([i for i in range(17) if node1[i] and node2[i]]) <= 1
598+
new_node = [self._encode_node(self._merge(self._decode_to_node(node1[i]), self._decode_to_node(node2[i]))) if node1[i] and node2[i] else node1[i] or node2[i] for i in range(17)]
599+
return new_node
600+
601+
@classmethod
602+
def unsafe_merge(cls, trie1, trie2):
603+
t = Trie(trie1.db)
604+
t.root_node = t._merge(trie1.root_node, trie2.root_node)
605+
return t
485606

486607
def _iter(self, node, key, reverse=False, path=[]):
608+
# print 'iter', node, key, 'reverse =', reverse, 'path =', path
487609
node_type = self._get_node_type(node)
488610

489611
if node_type == NODE_TYPE_BLANK:
490612
return None
491613

492614
elif node_type == NODE_TYPE_BRANCH:
615+
# print 'b'
493616
if len(key):
494617
sub_node = self._decode_to_node(node[key[0]])
495618
o = self._iter(sub_node, key[1:], reverse, path + [key[0]])
496-
if o:
619+
if o is not None:
620+
# print 'returning', [key[0]] + o, path
497621
return [key[0]] + o
498622
if reverse:
499-
scan_range = list(range(key[0] if len(key) else 0))
623+
scan_range = reversed(list(range(key[0] if len(key) else 0)))
500624
else:
501625
scan_range = list(range(key[0] + 1 if len(key) else 0, 16))
502626
for i in scan_range:
503627
sub_node = self._decode_to_node(node[i])
628+
# print 'prelim getany', path+[i]
504629
o = self._getany(sub_node, reverse, path + [i])
505-
if o:
630+
if o is not None:
631+
# print 'returning', [i] + o, path
506632
return [i] + o
507-
if reverse and node[16]:
633+
if reverse and key and node[16]:
634+
# print 'o'
508635
return [16]
509636
return None
510637

511638
descend_key = without_terminator(unpack_to_nibbles(node[0]))
512639
if node_type == NODE_TYPE_LEAF:
513640
if reverse:
641+
# print 'L', descend_key, key, descend_key if descend_key < key else None, path
514642
return descend_key if descend_key < key else None
515643
else:
644+
# print 'L', descend_key, key, descend_key if descend_key > key else None, path
516645
return descend_key if descend_key > key else None
517646

518647
if node_type == NODE_TYPE_EXTENSION:
519648
# traverse child nodes
520649
sub_node = self._decode_to_node(node[1])
521650
sub_key = key[len(descend_key):]
651+
# print 'amhere', key, descend_key, descend_key > key[:len(descend_key)]
522652
if starts_with(key, descend_key):
523653
o = self._iter(sub_node, sub_key, reverse, path + descend_key)
524654
elif descend_key > key[:len(descend_key)] and not reverse:
525-
o = self._getany(sub_node, sub_key, False, path + descend_key)
655+
# print 1
656+
# print 'prelim getany', path+descend_key
657+
o = self._getany(sub_node, False, path + descend_key)
526658
elif descend_key < key[:len(descend_key)] and reverse:
527-
o = self._getany(sub_node, sub_key, True, path + descend_key)
659+
# print 2
660+
# print 'prelim getany', path+descend_key
661+
o = self._getany(sub_node, True, path + descend_key)
528662
else:
529663
o = None
664+
# print 'returning@', descend_key + o if o else None, path
530665
return descend_key + o if o else None
531666

532667
def next(self, key):
668+
# print 'nextting'
533669
key = bin_to_nibbles(key)
534670
o = self._iter(self.root_node, key)
535-
return nibbles_to_bin(o) if o else None
671+
# print 'answer', o
672+
return nibbles_to_bin(without_terminator(o)) if o else None
536673

537674
def prev(self, key):
675+
# print 'prevving'
538676
key = bin_to_nibbles(key)
539677
o = self._iter(self.root_node, key, reverse=True)
540-
return nibbles_to_bin(o) if o else None
678+
# print 'answer', o
679+
return nibbles_to_bin(without_terminator(o)) if o else None
541680

542681
def _delete_node_storage(self, node):
543682
'''delete storage

0 commit comments

Comments
 (0)