forked from vbuterin/pyethereum
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrlp.py
86 lines (80 loc) · 2.51 KB
/
rlp.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
def binary_length(n):
if n == 0: return 0
else: return 1 + binary_length(n / 256)
def to_binary_array(n,L=None):
if L is None: L = binary_length(n)
if n == 0: return []
else:
x = to_binary_array(n / 256)
x.append(n % 256)
return x
def to_binary(n,L=None): return ''.join([chr(x) for x in to_binary_array(n,L)])
def from_binary(b):
if len(b) == 0: return 0
else: return from_binary(b[:-1]) * 256 + ord(b[-1])
def __decode(s,pos=0):
if not s:
return (None, 0)
else:
fchar = ord(s[pos])
if fchar < 24:
return (ord(s[pos]), pos+1)
elif fchar < 56:
b = ord(s[pos]) - 23
return (from_binary(s[pos+1:pos+1+b]), pos+1+b)
elif fchar < 64:
b = ord(s[pos]) - 55
b2 = from_binary(s[pos+1:pos+1+b])
return (from_binary(s[pos+1+b:pos+1+b+b2]), pos+1+b+b2)
elif fchar < 120:
b = ord(s[pos]) - 64
return (s[pos+1:pos+1+b], pos+1+b)
elif fchar < 128:
b = ord(s[pos]) - 119
b2 = from_binary(s[pos+1:pos+1+b])
return (s[pos+1+b:pos+1+b+b2], pos+1+b+b2)
elif fchar < 184:
b = ord(s[pos]) - 128
o, pos = [], pos+1
for i in range(b):
obj, pos = __decode(s,pos)
o.append(obj)
return (o,pos)
elif fchar < 192:
b = ord(s[pos]) - 183
b2 = from_binary(s[pos+1:pos+1+b])
o, pos = [], pos+1+b
for i in range(b):
obj, pos = __decode(s,pos)
o.append(obj)
return (o,pos)
else:
raise Exception("byte not supported: "+fchar)
def decode(s): return __decode(s)[0]
def encode(s):
if isinstance(s,(int,long)):
if s < 0:
raise Exception("can't handle negative ints")
elif s >= 0 and s < 24:
return chr(s)
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):
if len(s) < 56:
return chr(len(s) + 64) + s
else:
b2 = to_binary(len(s))
return chr(len(b2) + 119) + b2 + s
elif isinstance(s,list):
if len(s) < 56:
return chr(len(s) + 128) + ''.join([encode(x) for x in s])
else:
b2 = to_binary(len(s))
return chr(len(b2) + 183) + b2 + ''.join([encode(x) for x in s])
else:
raise Exception("Encoding for "+s+" not yet implemented")