-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathMerklePatricia.py
90 lines (77 loc) · 2.22 KB
/
MerklePatricia.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import hashlib
import rlp
class MerklePatricia(object):
def __init__(self):
self.db = dict()
@staticmethod
def hash(text):
return hashlib.sha256(text).hexdigest()
@staticmethod
def compact_encode(hexarray):
term = 1 if hexarray[-1] == 16 else 0
if term:
hexarray = hexarray[:-1]
oddlen = len(hexarray) % 2
flags = 2 * term + oddlen
if oddlen:
hexarray = [flags] + hexarray
else:
hexarray = [flags, 0] + hexarray
o = ''
for i in xrange(0, len(hexarray), 2):
o += chr(16 * hexarray[i] + hexarray[i + 1])
return o
def update(self, node_hash, path, value):
if path == '':
curnode = self.db.get(node_hash) if node else [None] * 17
newnode = curnode.copy()
newnode[-1] = value
else:
curnode = self.db.get(node_hash) if node else [None] * 17
newnode = curnode.copy()
newindex = self.update(curnode[path[0]], path[1:], value)
newnode[path[0]] = newindex
self.db.put(MerklePatricia.hash(newnode), newnode)
return MerklePatricia.hash(newnode)
def delete(self, node_hash, path):
if node_hash is None:
return None
else:
curnode = self.db.get(node_hash)
newnode = curnode.copy()
if path == '':
newnode[-1] = None
else:
newindex = self.delete(curnode[path[0]], path[1:])
newnode[path[0]] = newindex
if len(filter(lambda x: x is not None, newnode)) == 0:
return None
else:
self.db.put(MerklePatricia.hash(newnode), newnode)
return MerklePatricia.hash(newnode)
def get_helper(self, node, path):
if not path:
return node
if node == '':
return ''
curnode = rlp.decode(node if len(node) < 32 else self.db.get(node))
if len(curnode) == 2:
(k2, v2) = curnode
k2 = MerklePatricia.compact_encode(k2)
if k2 == path[:len(k2)]:
return self.get_helper(v2, path[len(k2):])
else:
return ''
elif len(curnode) == 17:
return self.get_helper(curnode[path[0]], path[1:])
def get(self, node, path):
path2 = []
for i in xrange(len(path)):
path2.append(int(ord(path[i]) / 16))
path2.append(ord(path[i] % 16))
path2.append(16)
return self.get_helper(node, path2)
mp = MerklePatricia()
print MerklePatricia.hash('Nobody inspects the spammish repetition')
print MerklePatricia.hash(123)
print MerklePatricia.hash(MerklePatricia())