Added testing code for RLP, hexarraykey encoding, tries

This commit is contained in:
Vitalik Buterin 2013-12-31 19:02:38 -05:00
parent 2992c04169
commit 9d47cacc47
3 changed files with 94 additions and 11 deletions

8
rlp.py
View File

@ -63,19 +63,19 @@ def encode(s):
raise Exception("can't handle negative ints")
elif s >= 0 and s < 24:
return chr(s)
elif s <= 2**256:
elif s < 2**256:
b = to_binary(s)
return chr(len(b) + 23) + b
else:
b = to_binary(s)
b2 = to_binary(len(b))
return chr(len(b2) + 55) + b2 + b
elif isinstance(s,str):
elif isinstance(s,(str,unicode)):
if len(s) < 56:
return chr(len(s) + 64) + s
return chr(len(s) + 64) + str(s)
else:
b2 = to_binary(len(s))
return chr(len(b2) + 119) + b2 + s
return chr(len(b2) + 119) + b2 + str(s)
elif isinstance(s,list):
if len(s) < 56:
return chr(len(s) + 128) + ''.join([encode(x) for x in s])

81
runtest.py Normal file
View File

@ -0,0 +1,81 @@
import json, sys, os
import rlp, trie
import random
testdir = sys.argv[1] if len(sys.argv) >= 2 else '../tests'
rlpdata = json.loads(open(os.path.join(testdir,'rlptest.txt')).read())
for x,y in rlpdata:
yprime = rlp.encode(x).encode('hex')
if yprime != y: print "RLPEncode Mismatch: ",x,y,yprime
xprime = rlp.decode(y.decode('hex'))
jx, jxprime = json.dumps(x), json.dumps(xprime)
if jx != jxprime: print "RLPDecode Mismatch: ",jx,jxprime,y
hexencodedata = json.loads(open(os.path.join(testdir,'hexencodetest.txt')).read())
for x,y in hexencodedata:
yprime = trie.hexarraykey_to_bin(x).encode('hex')
if yprime != y: print "HexEncode Mismatch: ",x,y,yprime
xprime = trie.bin_to_hexarraykey(y.decode('hex'))
jx,jxprime = json.dumps(x), json.dumps(xprime)
if jx != jxprime: print "HexDecode Mismatch: ",jx,jxprime,y
triedata = json.loads(open(os.path.join(testdir,'trietest.txt')).read())
for x,y in triedata:
t0 = trie.Trie('/tmp/trietest-'+str(random.randrange(1000000000000)))
for k in x:
t0.update(k,x[k])
if t0.root.encode('hex') != y:
print "Mismatch with adds only"
continue
t = trie.Trie('/tmp/trietest-'+str(random.randrange(1000000000000)))
dummies, reals = [], []
for k in x:
reals.append([k,x[k]])
dummies.append(k[:random.randrange(len(k)-1)])
dummies.append(k+random.choice(dummies))
dummies.append(k[:random.randrange(len(k)-1)]+random.choice(dummies))
dummies_to_pop = set([])
i = 0
ops = []
mp = {}
success = [True]
def update(k,v):
t.update(k,v)
if v == '' and k in mp: del mp[k]
else: mp[k] = v
ops.append([k,v,t.root.encode('hex')])
tn = trie.Trie('/tmp/trietest-'+str(random.randrange(1000000000000)))
for k in mp:
tn.update(k,mp[k])
if tn.root != t.root:
print "Mismatch: "
for op in ops: print op
success[0] = False
while i < len(reals):
s = random.randrange(3)
if s == 0:
update(reals[i][0],reals[i][1])
i += 1
elif s == 1:
k,v = random.choice(dummies), random.choice(dummies)
update(k,v)
dummies_to_pop.add(k)
elif s == 2:
if len(dummies_to_pop) > 0:
k = random.choice(list(dummies_to_pop))
update(k,'')
dummies_to_pop.remove(k)
if not success[0]:
break
if not success[0]:
continue
i = len(reals) * 2
while len(dummies_to_pop) > 0:
k = random.choice(list(dummies_to_pop))
update(k,'')
dummies_to_pop.remove(k)
if not success[0]:
break

16
trie.py
View File

@ -70,7 +70,7 @@ class Trie():
else: return self.__delete_state(node,key)
def __insert_state(self,node,key,value):
if self.debug: print 'ink', node.encode('hex'), key
if self.debug: print 'ins', node.encode('hex'), key
if len(key) == 0:
return value
else:
@ -141,12 +141,14 @@ class Trie():
if newnode[i]:
if onlynode == -1: onlynode = i
else: onlynode = -2
if onlynode >= 0:
if onlynode == 16:
newnode2 = [ hexarraykey_to_bin([16]), newnode[onlynode] ]
elif onlynode >= 0:
childnode = rlp.decode(self.db.get(newnode[onlynode]))
if not childnode:
raise Exception("?????")
if len(childnode) == 17:
newnode2 = [ key[0], newnode[onlynode] ]
newnode2 = [ hexarraykey_to_bin([onlynode]), newnode[onlynode] ]
elif len(childnode) == 2:
newkey = [onlynode] + bin_to_hexarraykey(childnode[0])
newnode2 = [ hexarraykey_to_bin(newkey), childnode[1] ]
@ -210,13 +212,13 @@ class Trie():
return o
def get(self,key):
key2 = ['0123456789abcdef'.find(x) for x in key.encode('hex')] + [16]
key2 = ['0123456789abcdef'.find(x) for x in str(key).encode('hex')] + [16]
return self.__get_state(self.root,key2)
def get_size(self): return self.__get_size(self.root)
def update(self,key,value):
if not isinstance(key,str) or not isinstance(value,str):
if not isinstance(key,(str,unicode)) or not isinstance(value,(str,unicode)):
raise Exception("Key and value must be strings")
key2 = ['0123456789abcdef'.find(x) for x in key.encode('hex')] + [16]
self.root = self.__update_state(self.root,key2,value)
key2 = ['0123456789abcdef'.find(x) for x in str(key).encode('hex')] + [16]
self.root = self.__update_state(self.root,key2,str(value))