parse black holes correctly
[electrum-server.git] / backends / bitcoind / util.py
1 #!/usr/bin/env python
2 #
3 # Electrum - lightweight Bitcoin client
4 # Copyright (C) 2011 thomasv@gitorious
5 #
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19
20 import hashlib, base64, re
21
22
23 def rev_hex(s):
24     return s.decode('hex')[::-1].encode('hex')
25
26 def int_to_hex(i, length=1):
27     s = hex(i)[2:].rstrip('L')
28     s = "0"*(2*length - len(s)) + s
29     return rev_hex(s)
30
31 def var_int(i):
32     if i<0xfd:
33         return int_to_hex(i)
34     elif i<=0xffff:
35         return "fd"+int_to_hex(i,2)
36     elif i<=0xffffffff:
37         return "fe"+int_to_hex(i,4)
38     else:
39         return "ff"+int_to_hex(i,8)
40
41
42 Hash = lambda x: hashlib.sha256(hashlib.sha256(x).digest()).digest()
43 hash_encode = lambda x: x[::-1].encode('hex')
44 hash_decode = lambda x: x.decode('hex')[::-1]
45
46
47 def header_to_string(res):
48     pbh = res.get('prev_block_hash')
49     if pbh is None: pbh = '0'*64
50     s = int_to_hex(res.get('version'),4) \
51         + rev_hex(pbh) \
52         + rev_hex(res.get('merkle_root')) \
53         + int_to_hex(int(res.get('timestamp')),4) \
54         + int_to_hex(int(res.get('bits')),4) \
55         + int_to_hex(int(res.get('nonce')),4)
56     return s
57
58 def header_from_string( s):
59     hex_to_int = lambda s: eval('0x' + s[::-1].encode('hex'))
60     h = {}
61     h['version'] = hex_to_int(s[0:4])
62     h['prev_block_hash'] = hash_encode(s[4:36])
63     h['merkle_root'] = hash_encode(s[36:68])
64     h['timestamp'] = hex_to_int(s[68:72])
65     h['bits'] = hex_to_int(s[72:76])
66     h['nonce'] = hex_to_int(s[76:80])
67     return h
68
69
70 ############ functions from pywallet ##################### 
71
72 addrtype = 0
73
74 def hash_160(public_key):
75     try:
76         md = hashlib.new('ripemd160')
77         md.update(hashlib.sha256(public_key).digest())
78         return md.digest()
79     except:
80         import ripemd
81         md = ripemd.new(hashlib.sha256(public_key).digest())
82         return md.digest()
83
84
85 def public_key_to_bc_address(public_key):
86     h160 = hash_160(public_key)
87     return hash_160_to_bc_address(h160)
88
89 def hash_160_to_bc_address(h160):
90     if h160 == 'None': return 'None'
91     vh160 = chr(addrtype) + h160
92     h = Hash(vh160)
93     addr = vh160 + h[0:4]
94     return b58encode(addr)
95
96 def bc_address_to_hash_160(addr):
97     if addr == 'None': return 'None'
98     bytes = b58decode(addr, 25)
99     return bytes[1:21]
100
101
102 __b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
103 __b58base = len(__b58chars)
104
105 def b58encode(v):
106     """ encode v, which is a string of bytes, to base58."""
107
108     long_value = 0L
109     for (i, c) in enumerate(v[::-1]):
110         long_value += (256**i) * ord(c)
111
112     result = ''
113     while long_value >= __b58base:
114         div, mod = divmod(long_value, __b58base)
115         result = __b58chars[mod] + result
116         long_value = div
117     result = __b58chars[long_value] + result
118
119     # Bitcoin does a little leading-zero-compression:
120     # leading 0-bytes in the input become leading-1s
121     nPad = 0
122     for c in v:
123         if c == '\0': nPad += 1
124         else: break
125
126     return (__b58chars[0]*nPad) + result
127
128 def b58decode(v, length):
129     """ decode v into a string of len bytes."""
130     long_value = 0L
131     for (i, c) in enumerate(v[::-1]):
132         long_value += __b58chars.find(c) * (__b58base**i)
133
134     result = ''
135     while long_value >= 256:
136         div, mod = divmod(long_value, 256)
137         result = chr(mod) + result
138         long_value = div
139     result = chr(long_value) + result
140
141     nPad = 0
142     for c in v:
143         if c == __b58chars[0]: nPad += 1
144         else: break
145
146     result = chr(0)*nPad + result
147     if length is not None and len(result) != length:
148         return None
149
150     return result
151
152
153 def EncodeBase58Check(vchIn):
154     hash = Hash(vchIn)
155     return b58encode(vchIn + hash[0:4])
156
157 def DecodeBase58Check(psz):
158     vchRet = b58decode(psz, None)
159     key = vchRet[0:-4]
160     csum = vchRet[-4:]
161     hash = Hash(key)
162     cs32 = hash[0:4]
163     if cs32 != csum:
164         return None
165     else:
166         return key
167
168 def PrivKeyToSecret(privkey):
169     return privkey[9:9+32]
170
171 def SecretToASecret(secret):
172     vchIn = chr(addrtype+128) + secret
173     return EncodeBase58Check(vchIn)
174
175 def ASecretToSecret(key):
176     vch = DecodeBase58Check(key)
177     if vch and vch[0] == chr(addrtype+128):
178         return vch[1:]
179     else:
180         return False
181
182 ########### end pywallet functions #######################
183