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

Commit f6bc14c

Browse files
committed
Some optimizations, and most of STATICCALL
1 parent 0b37104 commit f6bc14c

File tree

4 files changed

+58
-182
lines changed

4 files changed

+58
-182
lines changed

ethereum/trie.py

Lines changed: 17 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -47,61 +47,6 @@ def nibbles_to_bin(nibbles):
4747

4848

4949
NIBBLE_TERMINATOR = 16
50-
RECORDING = 1
51-
NONE = 0
52-
VERIFYING = -1
53-
54-
proving = False
55-
56-
57-
class ProofConstructor():
58-
59-
def __init__(self):
60-
self.mode = []
61-
self.nodes = []
62-
self.exempt = []
63-
64-
def push(self, mode, nodes=[]):
65-
global proving
66-
proving = True
67-
self.mode.append(mode)
68-
self.exempt.append(set())
69-
if mode == VERIFYING:
70-
self.nodes.append(set([rlp_encode(x) for x in nodes]))
71-
else:
72-
self.nodes.append(set())
73-
74-
def pop(self):
75-
global proving
76-
self.mode.pop()
77-
self.nodes.pop()
78-
self.exempt.pop()
79-
if not self.mode:
80-
proving = False
81-
82-
def get_nodelist(self):
83-
return list(map(rlp.decode, list(self.nodes[-1])))
84-
85-
def get_nodes(self):
86-
return self.nodes[-1]
87-
88-
def add_node(self, node):
89-
node = rlp_encode(node)
90-
if node not in self.exempt[-1]:
91-
self.nodes[-1].add(node)
92-
93-
def add_exempt(self, node):
94-
self.exempt[-1].add(rlp_encode(node))
95-
96-
def get_mode(self):
97-
return self.mode[-1]
98-
99-
proof = ProofConstructor()
100-
101-
102-
class InvalidSPVProof(Exception):
103-
pass
104-
10550

10651
def with_terminator(nibbles):
10752
nibbles = nibbles[:]
@@ -190,22 +135,16 @@ def is_key_value_type(node_type):
190135
BLANK_ROOT = utils.sha3rlp(b'')
191136

192137

193-
def transient_trie_exception(*args):
194-
raise Exception("Transient trie")
195-
196138

197139
class Trie(object):
198140

199-
def __init__(self, db, root_hash=BLANK_ROOT, transient=False):
141+
def __init__(self, db, root_hash=BLANK_ROOT):
200142
'''it also present a dictionary like interface
201143
202144
:param db key value database
203145
:root: blank or trie node in form of [key, value] or [v0,v1..v15,v]
204146
'''
205147
self.db = db # Pass in a database object directly
206-
self.transient = transient
207-
if self.transient:
208-
self.update = self.get = self.delete = transient_trie_exception
209148
self.set_root_hash(root_hash)
210149

211150
# def __init__(self, dbfile, root_hash=BLANK_ROOT):
@@ -221,45 +160,20 @@ def __init__(self, db, root_hash=BLANK_ROOT, transient=False):
221160
# self.db = dbfile # Pass in a database object directly
222161
# self.set_root_hash(root_hash)
223162

224-
# For SPV proof production/verification purposes
225-
def spv_grabbing(self, node):
226-
global proving
227-
if not proving:
228-
pass
229-
elif proof.get_mode() == RECORDING:
230-
proof.add_node(copy.copy(node))
231-
# print('recording %s' % encode_hex(utils.sha3(rlp_encode(node))))
232-
elif proof.get_mode() == VERIFYING:
233-
# print('verifying %s' % encode_hex(utils.sha3(rlp_encode(node))))
234-
if rlp_encode(node) not in proof.get_nodes():
235-
raise InvalidSPVProof("Proof invalid!")
236-
237-
def spv_storing(self, node):
238-
global proving
239-
if not proving:
240-
pass
241-
elif proof.get_mode() == RECORDING:
242-
proof.add_exempt(copy.copy(node))
243-
elif proof.get_mode() == VERIFYING:
244-
proof.add_node(copy.copy(node))
245-
246163
@property
247164
def root_hash(self):
248165
'''always empty or a 32 bytes string
249166
'''
250-
return self.get_root_hash()
167+
return self._root_hash
251168

252169
def get_root_hash(self):
253-
if self.transient:
254-
return self.transient_root_hash
255-
if self.root_node == BLANK_NODE:
256-
return BLANK_ROOT
257-
assert isinstance(self.root_node, list)
170+
return self._root_hash
171+
172+
def _update_root_hash(self):
258173
val = rlp_encode(self.root_node)
259174
key = utils.sha3(val)
260175
self.db.put(key, val)
261-
self.spv_grabbing(self.root_node)
262-
return key
176+
self._root_hash = key
263177

264178
@root_hash.setter
265179
def root_hash(self, value):
@@ -268,20 +182,20 @@ def root_hash(self, value):
268182
def set_root_hash(self, root_hash):
269183
assert is_string(root_hash)
270184
assert len(root_hash) in [0, 32]
271-
if self.transient:
272-
self.transient_root_hash = root_hash
273-
return
274185
if root_hash == BLANK_ROOT:
275186
self.root_node = BLANK_NODE
187+
self._root_hash = BLANK_ROOT
276188
return
277189
self.root_node = self._decode_to_node(root_hash)
190+
self._root_hash = root_hash
278191

279192
def clear(self):
280193
''' clear all tree data
281194
'''
282195
self._delete_child_storage(self.root_node)
283196
self._delete_node_storage(self.root_node)
284197
self.root_node = BLANK_NODE
198+
self._root_hash = BLANK_ROOT
285199

286200
def _delete_child_storage(self, node):
287201
node_type = self._get_node_type(node)
@@ -294,23 +208,21 @@ def _delete_child_storage(self, node):
294208
def _encode_node(self, node):
295209
if node == BLANK_NODE:
296210
return BLANK_NODE
297-
assert isinstance(node, list)
211+
# assert isinstance(node, list)
298212
rlpnode = rlp_encode(node)
299213
if len(rlpnode) < 32:
300214
return node
301215

302216
hashkey = utils.sha3(rlpnode)
303217
self.db.put(hashkey, rlpnode)
304-
self.spv_storing(node)
305218
return hashkey
306219

307220
def _decode_to_node(self, encoded):
308221
if encoded == BLANK_NODE:
309222
return BLANK_NODE
310-
if isinstance(encoded, list):
223+
# if isinstance(encoded, list):
311224
return encoded
312225
o = rlp.decode(self.db.get(encoded))
313-
self.spv_grabbing(o)
314226
return o
315227

316228
def _get_node_type(self, node):
@@ -552,8 +464,8 @@ def split(self, key):
552464
return t1, t2
553465

554466
def _merge(self, node1, node2):
555-
assert isinstance(node1, list) or not node1
556-
assert isinstance(node2, list) or not node2
467+
# assert isinstance(node1, list) or not node1
468+
# assert isinstance(node2, list) or not node2
557469
node_type1 = self._get_node_type(node1)
558470
node_type2 = self._get_node_type(node2)
559471
if not node1:
@@ -684,7 +596,7 @@ def _delete_node_storage(self, node):
684596
'''
685597
if node == BLANK_NODE:
686598
return
687-
assert isinstance(node, list)
599+
# assert isinstance(node, list)
688600
encoded = self._encode_node(node)
689601
if len(encoded) < 32:
690602
return
@@ -798,7 +710,7 @@ def _delete_kv_node(self, node, key):
798710
if new_sub_node == BLANK_NODE:
799711
return BLANK_NODE
800712

801-
assert isinstance(new_sub_node, list)
713+
# assert isinstance(new_sub_node, list)
802714

803715
# new sub node not blank, not value and has changed
804716
new_sub_node_type = self._get_node_type(new_sub_node)
@@ -828,7 +740,7 @@ def delete(self, key):
828740
self.root_node = self._delete_and_delete_storage(
829741
self.root_node,
830742
bin_to_nibbles(to_string(key)))
831-
self.get_root_hash()
743+
self._update_root_hash()
832744

833745
def _get_size(self, node):
834746
'''Get counts of (key, value) stored in this and the descendant nodes
@@ -991,39 +903,13 @@ def update(self, key, value):
991903
self.root_node,
992904
bin_to_nibbles(to_string(key)),
993905
to_string(value))
994-
self.get_root_hash()
906+
self._update_root_hash()
995907

996908
def root_hash_valid(self):
997909
if self.root_hash == BLANK_ROOT:
998910
return True
999911
return self.root_hash in self.db
1000912

1001-
def produce_spv_proof(self, key):
1002-
proof.push(RECORDING)
1003-
self.get(key)
1004-
o = proof.get_nodelist()
1005-
proof.pop()
1006-
return o
1007-
1008-
1009-
def verify_spv_proof(root, key, proof):
1010-
proof.push(VERIFYING, proof)
1011-
t = Trie(db.EphemDB())
1012-
1013-
for i, node in enumerate(proof):
1014-
R = rlp_encode(node)
1015-
H = utils.sha3(R)
1016-
t.db.put(H, R)
1017-
try:
1018-
t.root_hash = root
1019-
t.get(key)
1020-
proof.pop()
1021-
return True
1022-
except Exception as e:
1023-
print(e)
1024-
proof.pop()
1025-
return False
1026-
1027913

1028914
if __name__ == "__main__":
1029915
import sys

0 commit comments

Comments
 (0)