Fixing wineprefix directory cleanup
[electrum-nvc.git] / lib / bitcoin.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, ecdsa, 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 # pywallet openssl private key implementation
48
49 def i2d_ECPrivateKey(pkey, compressed=False):
50     if compressed:
51         key = '3081d30201010420' + \
52               '%064x' % pkey.secret + \
53               'a081a53081a2020101302c06072a8648ce3d0101022100' + \
54               '%064x' % _p + \
55               '3006040100040107042102' + \
56               '%064x' % _Gx + \
57               '022100' + \
58               '%064x' % _r + \
59               '020101a124032200'
60     else:
61         key = '308201130201010420' + \
62               '%064x' % pkey.secret + \
63               'a081a53081a2020101302c06072a8648ce3d0101022100' + \
64               '%064x' % _p + \
65               '3006040100040107044104' + \
66               '%064x' % _Gx + \
67               '%064x' % _Gy + \
68               '022100' + \
69               '%064x' % _r + \
70               '020101a144034200'
71         
72     return key.decode('hex') + i2o_ECPublicKey(pkey, compressed)
73     
74 def i2o_ECPublicKey(pkey, compressed=False):
75     # public keys are 65 bytes long (520 bits)
76     # 0x04 + 32-byte X-coordinate + 32-byte Y-coordinate
77     # 0x00 = point at infinity, 0x02 and 0x03 = compressed, 0x04 = uncompressed
78     # compressed keys: <sign> <x> where <sign> is 0x02 if y is even and 0x03 if y is odd
79     if compressed:
80         if pkey.pubkey.point.y() & 1:
81             key = '03' + '%064x' % pkey.pubkey.point.x()
82         else:
83             key = '02' + '%064x' % pkey.pubkey.point.x()
84     else:
85         key = '04' + \
86               '%064x' % pkey.pubkey.point.x() + \
87               '%064x' % pkey.pubkey.point.y()
88             
89     return key.decode('hex')
90             
91 # end pywallet openssl private key implementation
92
93                                                 
94             
95 ############ functions from pywallet ##################### 
96             
97 addrtype = 0
98
99 def hash_160(public_key):
100     try:
101         md = hashlib.new('ripemd160')
102         md.update(hashlib.sha256(public_key).digest())
103         return md.digest()
104     except:
105         import ripemd
106         md = ripemd.new(hashlib.sha256(public_key).digest())
107         return md.digest()
108
109
110 def public_key_to_bc_address(public_key):
111     h160 = hash_160(public_key)
112     return hash_160_to_bc_address(h160)
113
114 def hash_160_to_bc_address(h160):
115     vh160 = chr(addrtype) + h160
116     h = Hash(vh160)
117     addr = vh160 + h[0:4]
118     return b58encode(addr)
119
120 def bc_address_to_hash_160(addr):
121     bytes = b58decode(addr, 25)
122     return bytes[1:21]
123
124 def encode_point(pubkey, compressed=False):
125     order = generator_secp256k1.order()
126     p = pubkey.pubkey.point
127     x_str = ecdsa.util.number_to_string(p.x(), order)
128     y_str = ecdsa.util.number_to_string(p.y(), order)
129     if compressed:
130         return chr(2 + (p.y() & 1)) + x_str
131     else:
132         return chr(4) + pubkey.to_string() #x_str + y_str
133
134 __b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
135 __b58base = len(__b58chars)
136
137 def b58encode(v):
138     """ encode v, which is a string of bytes, to base58."""
139
140     long_value = 0L
141     for (i, c) in enumerate(v[::-1]):
142         long_value += (256**i) * ord(c)
143
144     result = ''
145     while long_value >= __b58base:
146         div, mod = divmod(long_value, __b58base)
147         result = __b58chars[mod] + result
148         long_value = div
149     result = __b58chars[long_value] + result
150
151     # Bitcoin does a little leading-zero-compression:
152     # leading 0-bytes in the input become leading-1s
153     nPad = 0
154     for c in v:
155         if c == '\0': nPad += 1
156         else: break
157
158     return (__b58chars[0]*nPad) + result
159
160 def b58decode(v, length):
161     """ decode v into a string of len bytes."""
162     long_value = 0L
163     for (i, c) in enumerate(v[::-1]):
164         long_value += __b58chars.find(c) * (__b58base**i)
165
166     result = ''
167     while long_value >= 256:
168         div, mod = divmod(long_value, 256)
169         result = chr(mod) + result
170         long_value = div
171     result = chr(long_value) + result
172
173     nPad = 0
174     for c in v:
175         if c == __b58chars[0]: nPad += 1
176         else: break
177
178     result = chr(0)*nPad + result
179     if length is not None and len(result) != length:
180         return None
181
182     return result
183
184
185 def EncodeBase58Check(vchIn):
186     hash = Hash(vchIn)
187     return b58encode(vchIn + hash[0:4])
188
189 def DecodeBase58Check(psz):
190     vchRet = b58decode(psz, None)
191     key = vchRet[0:-4]
192     csum = vchRet[-4:]
193     hash = Hash(key)
194     cs32 = hash[0:4]
195     if cs32 != csum:
196         return None
197     else:
198         return key
199
200 def PrivKeyToSecret(privkey):
201     return privkey[9:9+32]
202
203 def SecretToASecret(secret, compressed=False):
204     vchIn = chr((addrtype+128)&255) + secret
205     if compressed: vchIn += '\01'
206     return EncodeBase58Check(vchIn)
207
208 def ASecretToSecret(key):
209     vch = DecodeBase58Check(key)
210     if vch and vch[0] == chr((addrtype+128)&255):
211         return vch[1:]
212     else:
213         return False
214
215 def regenerate_key(sec):
216     b = ASecretToSecret(sec)
217     if not b:
218         return False
219     b = b[0:32]
220     secret = int('0x' + b.encode('hex'), 16)
221     return EC_KEY(secret)
222
223 def GetPubKey(pkey, compressed=False):
224     return i2o_ECPublicKey(pkey, compressed)
225
226 def GetPrivKey(pkey, compressed=False):
227     return i2d_ECPrivateKey(pkey, compressed)
228
229 def GetSecret(pkey):
230     return ('%064x' % pkey.secret).decode('hex')
231
232 def is_compressed(sec):
233     b = ASecretToSecret(sec)
234     return len(b) == 33
235
236 ########### end pywallet functions #######################
237
238 # secp256k1, http://www.oid-info.com/get/1.3.132.0.10
239 _p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2FL
240 _r = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141L
241 _b = 0x0000000000000000000000000000000000000000000000000000000000000007L
242 _a = 0x0000000000000000000000000000000000000000000000000000000000000000L
243 _Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798L
244 _Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8L
245 curve_secp256k1 = ecdsa.ellipticcurve.CurveFp( _p, _a, _b )
246 generator_secp256k1 = ecdsa.ellipticcurve.Point( curve_secp256k1, _Gx, _Gy, _r )
247 oid_secp256k1 = (1,3,132,0,10)
248 SECP256k1 = ecdsa.curves.Curve("SECP256k1", curve_secp256k1, generator_secp256k1, oid_secp256k1 ) 
249
250 class EC_KEY(object):
251     def __init__( self, secret ):
252         self.pubkey = ecdsa.ecdsa.Public_key( generator_secp256k1, generator_secp256k1 * secret )
253         self.privkey = ecdsa.ecdsa.Private_key( self.pubkey, secret )
254         self.secret = secret
255         
256
257
258 def filter(s): 
259     out = re.sub('( [^\n]*|)\n','',s)
260     out = out.replace(' ','')
261     out = out.replace('\n','')
262     return out
263
264 # https://en.bitcoin.it/wiki/Protocol_specification#Variable_length_integer
265 def raw_tx( inputs, outputs, for_sig = None ):
266     s  = int_to_hex(1,4)                                     +   '     version\n' 
267     s += var_int( len(inputs) )                              +   '     number of inputs\n'
268     for i in range(len(inputs)):
269         _, _, p_hash, p_index, p_script, pubkey, sig = inputs[i]
270         s += p_hash.decode('hex')[::-1].encode('hex')        +  '     prev hash\n'
271         s += int_to_hex(p_index,4)                           +  '     prev index\n'
272         if for_sig is None:
273             sig = sig + chr(1)                               # hashtype
274             script  = int_to_hex( len(sig))                  +  '     push %d bytes\n'%len(sig)
275             script += sig.encode('hex')                      +  '     sig\n'
276             script += int_to_hex( len(pubkey))               +  '     push %d bytes\n'%len(pubkey)
277             script += pubkey.encode('hex')                   +  '     pubkey\n'
278         elif for_sig==i:
279             script = p_script                                +  '     scriptsig \n'
280         else:
281             script=''
282         s += var_int( len(filter(script))/2 )                +  '     script length \n'
283         s += script
284         s += "ffffffff"                                      +  '     sequence\n'
285     s += var_int( len(outputs) )                             +  '     number of outputs\n'
286     for output in outputs:
287         addr, amount = output
288         s += int_to_hex( amount, 8)                          +  '     amount: %d\n'%amount 
289         script = '76a9'                                      # op_dup, op_hash_160
290         script += '14'                                       # push 0x14 bytes
291         script += bc_address_to_hash_160(addr).encode('hex')
292         script += '88ac'                                     # op_equalverify, op_checksig
293         s += var_int( len(filter(script))/2 )                +  '     script length \n'
294         s += script                                          +  '     script \n'
295     s += int_to_hex(0,4)                                     # lock time
296     if for_sig is not None: s += int_to_hex(1, 4)            # hash type
297     return s
298
299