diff --git a/rlp.py b/rlp.py index 0abfffb4ae..e35f111941 100644 --- a/rlp.py +++ b/rlp.py @@ -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]) diff --git a/runtest.py b/runtest.py new file mode 100644 index 0000000000..5ef92f5d57 --- /dev/null +++ b/runtest.py @@ -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 diff --git a/trie.py b/trie.py index de2e27b8c3..d914f88d4a 100644 --- a/trie.py +++ b/trie.py @@ -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))