From 81bf4ed4ecc0ffad7623510346f997d9655ed493 Mon Sep 17 00:00:00 2001 From: jackjack-jj Date: Sun, 24 Jul 2011 06:05:43 -0700 Subject: [PATCH] Version 0.3.25 OK --- pywallet.py | 1716 +++++++++++++++++++++++++-------------------------- 1 file changed, 858 insertions(+), 858 deletions(-) diff --git a/pywallet.py b/pywallet.py index 0444890..b622806 100644 --- a/pywallet.py +++ b/pywallet.py @@ -1,861 +1,861 @@ #!/usr/bin/env python # pywallet.py 1.1 -# based on http://github.com/gavinandresen/bitcointools -# -# Usage: pywallet.py [options] -# -# Options: -# --version show program's version number and exit -# -h, --help show this help message and exit -# --dumpwallet dump wallet in json format -# --importprivkey=KEY import private key from vanitygen -# --datadir=DATADIR wallet directory (defaults to bitcoin default) -# --testnet use testnet subdirectory and address type - -from bsddb.db import * -import os, sys, time -import json -import logging -import struct -import StringIO -import traceback -import socket -import types -import string -import exceptions -import hashlib -import random - -max_version = 32400 -addrtype = 0 -json_db = {} -private_keys = [] - -def determine_db_dir(): - import os - import os.path - import platform - if platform.system() == "Darwin": - return os.path.expanduser("~/Library/Application Support/Bitcoin/") - elif platform.system() == "Windows": - return os.path.join(os.environ['APPDATA'], "Bitcoin") - return os.path.expanduser("~/.bitcoin") - -# secp256k1 - -_p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2FL -_r = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141L -_b = 0x0000000000000000000000000000000000000000000000000000000000000007L -_a = 0x0000000000000000000000000000000000000000000000000000000000000000L -_Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798L -_Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8L - -class CurveFp( object ): - def __init__( self, p, a, b ): - self.__p = p - self.__a = a - self.__b = b - - def p( self ): - return self.__p - - def a( self ): - return self.__a - - def b( self ): - return self.__b - - def contains_point( self, x, y ): - return ( y * y - ( x * x * x + self.__a * x + self.__b ) ) % self.__p == 0 - -class Point( object ): - def __init__( self, curve, x, y, order = None ): - self.__curve = curve - self.__x = x - self.__y = y - self.__order = order - if self.__curve: assert self.__curve.contains_point( x, y ) - if order: assert self * order == INFINITY - - def __add__( self, other ): - if other == INFINITY: return self - if self == INFINITY: return other - assert self.__curve == other.__curve - if self.__x == other.__x: - if ( self.__y + other.__y ) % self.__curve.p() == 0: - return INFINITY - else: - return self.double() - - p = self.__curve.p() - l = ( ( other.__y - self.__y ) * \ - inverse_mod( other.__x - self.__x, p ) ) % p - x3 = ( l * l - self.__x - other.__x ) % p - y3 = ( l * ( self.__x - x3 ) - self.__y ) % p - return Point( self.__curve, x3, y3 ) - - def __mul__( self, other ): - def leftmost_bit( x ): - assert x > 0 - result = 1L - while result <= x: result = 2 * result - return result / 2 - - e = other - if self.__order: e = e % self.__order - if e == 0: return INFINITY - if self == INFINITY: return INFINITY - assert e > 0 - e3 = 3 * e - negative_self = Point( self.__curve, self.__x, -self.__y, self.__order ) - i = leftmost_bit( e3 ) / 2 - result = self - while i > 1: - result = result.double() - if ( e3 & i ) != 0 and ( e & i ) == 0: result = result + self - if ( e3 & i ) == 0 and ( e & i ) != 0: result = result + negative_self - i = i / 2 - return result - - def __rmul__( self, other ): - return self * other - - def __str__( self ): - if self == INFINITY: return "infinity" - return "(%d,%d)" % ( self.__x, self.__y ) - - def double( self ): - if self == INFINITY: - return INFINITY - - p = self.__curve.p() - a = self.__curve.a() - l = ( ( 3 * self.__x * self.__x + a ) * \ - inverse_mod( 2 * self.__y, p ) ) % p - x3 = ( l * l - 2 * self.__x ) % p - y3 = ( l * ( self.__x - x3 ) - self.__y ) % p - return Point( self.__curve, x3, y3 ) - - def x( self ): - return self.__x - - def y( self ): - return self.__y - - def curve( self ): - return self.__curve - - def order( self ): - return self.__order - -INFINITY = Point( None, None, None ) - -def inverse_mod( a, m ): - if a < 0 or m <= a: a = a % m - c, d = a, m - uc, vc, ud, vd = 1, 0, 0, 1 - while c != 0: - q, c, d = divmod( d, c ) + ( c, ) - uc, vc, ud, vd = ud - q*uc, vd - q*vc, uc, vc - assert d == 1 - if ud > 0: return ud - else: return ud + m - -class Signature( object ): - def __init__( self, r, s ): - self.r = r - self.s = s - -class Public_key( object ): - def __init__( self, generator, point ): - self.curve = generator.curve() - self.generator = generator - self.point = point - n = generator.order() - if not n: - raise RuntimeError, "Generator point must have order." - if not n * point == INFINITY: - raise RuntimeError, "Generator point order is bad." - if point.x() < 0 or n <= point.x() or point.y() < 0 or n <= point.y(): - raise RuntimeError, "Generator point has x or y out of range." - - def verifies( self, hash, signature ): - G = self.generator - n = G.order() - r = signature.r - s = signature.s - if r < 1 or r > n-1: return False - if s < 1 or s > n-1: return False - c = inverse_mod( s, n ) - u1 = ( hash * c ) % n - u2 = ( r * c ) % n - xy = u1 * G + u2 * self.point - v = xy.x() % n - return v == r - -class Private_key( object ): - def __init__( self, public_key, secret_multiplier ): - self.public_key = public_key - self.secret_multiplier = secret_multiplier - - def der( self ): - hex_der_key = '06052b8104000a30740201010420' + \ - '%064x' % self.secret_multiplier + \ - 'a00706052b8104000aa14403420004' + \ - '%064x' % self.public_key.point.x() + \ - '%064x' % self.public_key.point.y() - return hex_der_key.decode('hex') - - def sign( self, hash, random_k ): - G = self.public_key.generator - n = G.order() - k = random_k % n - p1 = k * G - r = p1.x() - if r == 0: raise RuntimeError, "amazingly unlucky random number r" - s = ( inverse_mod( k, n ) * \ - ( hash + ( self.secret_multiplier * r ) % n ) ) % n - if s == 0: raise RuntimeError, "amazingly unlucky random number s" - return Signature( r, s ) - -class EC_KEY(object): - def __init__( self, secret ): - curve = CurveFp( _p, _a, _b ) - generator = Point( curve, _Gx, _Gy, _r ) - self.pubkey = Public_key( generator, generator * secret ) - self.privkey = Private_key( self.pubkey, secret ) - self.secret = secret - -def i2d_ECPrivateKey(pkey): - # private keys are 279 bytes long (see crypto/ec/cec_asn1.c) - # ASN1_SIMPLE(EC_PRIVATEKEY, version, LONG), - # ASN1_SIMPLE(EC_PRIVATEKEY, privateKey, ASN1_OCTET_STRING), - # ASN1_EXP_OPT(EC_PRIVATEKEY, parameters, ECPKPARAMETERS, 0), - # ASN1_EXP_OPT(EC_PRIVATEKEY, publicKey, ASN1_BIT_STRING, 1) - hex_i2d_key = '308201130201010420' + \ - '%064x' % pkey.secret + \ - 'a081a53081a2020101302c06072a8648ce3d0101022100' + \ - '%064x' % _p + \ - '3006040100040107044104' + \ - '%064x' % _Gx + \ - '%064x' % _Gy + \ - '022100' + \ - '%064x' % _r + \ - '020101a14403420004' + \ - '%064x' % pkey.pubkey.point.x() + \ - '%064x' % pkey.pubkey.point.y() - return hex_i2d_key.decode('hex') - -def i2o_ECPublicKey(pkey): - # public keys are 65 bytes long (520 bits) - # 0x04 + 32-byte X-coordinate + 32-byte Y-coordinate - hex_i2o_key = '04' + \ - '%064x' % pkey.pubkey.point.x() + \ - '%064x' % pkey.pubkey.point.y() - return hex_i2o_key.decode('hex') - -# hashes - -def hash_160(public_key): - md = hashlib.new('ripemd160') - md.update(hashlib.sha256(public_key).digest()) - return md.digest() - -def public_key_to_bc_address(public_key): - h160 = hash_160(public_key) - return hash_160_to_bc_address(h160) - -def hash_160_to_bc_address(h160): - vh160 = chr(addrtype) + h160 - h = Hash(vh160) - addr = vh160 + h[0:4] - return b58encode(addr) - -def bc_address_to_hash_160(addr): - bytes = b58decode(addr, 25) - return bytes[1:21] - -__b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' -__b58base = len(__b58chars) - -def b58encode(v): - """ encode v, which is a string of bytes, to base58. - """ - - long_value = 0L - for (i, c) in enumerate(v[::-1]): - long_value += (256**i) * ord(c) - - result = '' - while long_value >= __b58base: - div, mod = divmod(long_value, __b58base) - result = __b58chars[mod] + result - long_value = div - result = __b58chars[long_value] + result - - # Bitcoin does a little leading-zero-compression: - # leading 0-bytes in the input become leading-1s - nPad = 0 - for c in v: - if c == '\0': nPad += 1 - else: break - - return (__b58chars[0]*nPad) + result - -def b58decode(v, length): - """ decode v into a string of len bytes - """ - long_value = 0L - for (i, c) in enumerate(v[::-1]): - long_value += __b58chars.find(c) * (__b58base**i) - - result = '' - while long_value >= 256: - div, mod = divmod(long_value, 256) - result = chr(mod) + result - long_value = div - result = chr(long_value) + result - - nPad = 0 - for c in v: - if c == __b58chars[0]: nPad += 1 - else: break - - result = chr(0)*nPad + result - if length is not None and len(result) != length: - return None - - return result - -def long_hex(bytes): - return bytes.encode('hex_codec') - -def Hash(data): - return hashlib.sha256(hashlib.sha256(data).digest()).digest() - -def EncodeBase58Check(vchIn): - hash = Hash(vchIn) - return b58encode(vchIn + hash[0:4]) - -def DecodeBase58Check(psz): - vchRet = b58decode(psz, None) - key = vchRet[0:-4] - csum = vchRet[-4:] - hash = Hash(key) - cs32 = hash[0:4] - if cs32 != csum: - return None - else: - return key - -def str_to_long(b): - res = 0 - pos = 1 - for a in reversed(b): - res += ord(a) * pos - pos *= 256 - return res - -def PrivKeyToSecret(privkey): - return privkey[9:9+32] - -def SecretToASecret(secret): - vchIn = chr(addrtype+128) + secret - return EncodeBase58Check(vchIn) - -def ASecretToSecret(key): - vch = DecodeBase58Check(key) - if vch and vch[0] == chr(addrtype+128): - return vch[1:] - else: - return False - -def regenerate_key(sec): - b = ASecretToSecret(sec) - if not b: - return False - secret = str_to_long(b) - return EC_KEY(secret) - -def GetPubKey(pkey): - return i2o_ECPublicKey(pkey) - -def GetPrivKey(pkey): - return i2d_ECPrivateKey(pkey) - -def GetSecret(pkey): - return ('%064x' % pkey.secret).decode('hex') - -# parser - -def create_env(db_dir): - db_env = DBEnv(0) - r = db_env.open(db_dir, (DB_CREATE|DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_THREAD|DB_RECOVER)) - return db_env - -def parse_CAddress(vds): - d = {'ip':'0.0.0.0','port':0,'nTime': 0} - try: - d['nVersion'] = vds.read_int32() - d['nTime'] = vds.read_uint32() - d['nServices'] = vds.read_uint64() - d['pchReserved'] = vds.read_bytes(12) - d['ip'] = socket.inet_ntoa(vds.read_bytes(4)) - d['port'] = vds.read_uint16() - except: - pass - return d - -def deserialize_CAddress(d): - return d['ip']+":"+str(d['port']) - -def parse_BlockLocator(vds): - d = { 'hashes' : [] } - nHashes = vds.read_compact_size() - for i in xrange(nHashes): - d['hashes'].append(vds.read_bytes(32)) - return d - -def deserialize_BlockLocator(d): - result = "Block Locator top: "+d['hashes'][0][::-1].encode('hex_codec') - return result - -def parse_setting(setting, vds): - if setting[0] == "f": # flag (boolean) settings - return str(vds.read_boolean()) - elif setting[0:4] == "addr": # CAddress - d = parse_CAddress(vds) - return deserialize_CAddress(d) - elif setting == "nTransactionFee": - return vds.read_int64() - elif setting == "nLimitProcessors": - return vds.read_int32() - return 'unknown setting' - -class SerializationError(Exception): - """ Thrown when there's a problem deserializing or serializing """ - -class BCDataStream(object): - def __init__(self): - self.input = None - self.read_cursor = 0 - - def clear(self): - self.input = None - self.read_cursor = 0 - - def write(self, bytes): # Initialize with string of bytes - if self.input is None: - self.input = bytes - else: - self.input += bytes - - def map_file(self, file, start): # Initialize with bytes from file - self.input = mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ) - self.read_cursor = start - def seek_file(self, position): - self.read_cursor = position - def close_file(self): - self.input.close() - - def read_string(self): - # Strings are encoded depending on length: - # 0 to 252 : 1-byte-length followed by bytes (if any) - # 253 to 65,535 : byte'253' 2-byte-length followed by bytes - # 65,536 to 4,294,967,295 : byte '254' 4-byte-length followed by bytes - # ... and the Bitcoin client is coded to understand: - # greater than 4,294,967,295 : byte '255' 8-byte-length followed by bytes of string - # ... but I don't think it actually handles any strings that big. - if self.input is None: - raise SerializationError("call write(bytes) before trying to deserialize") - - try: - length = self.read_compact_size() - except IndexError: - raise SerializationError("attempt to read past end of buffer") - - return self.read_bytes(length) - - def write_string(self, string): - # Length-encoded as with read-string - self.write_compact_size(len(string)) - self.write(string) - - def read_bytes(self, length): - try: - result = self.input[self.read_cursor:self.read_cursor+length] - self.read_cursor += length - return result - except IndexError: - raise SerializationError("attempt to read past end of buffer") - - return '' - - def read_boolean(self): return self.read_bytes(1)[0] != chr(0) - def read_int16(self): return self._read_num(' max_version: - print "Version mismatch (must be <= %d)" % max_version - elif options.key in private_keys: - print "Already exists" - else: - db = open_wallet(db_env, writable=True) - - if importprivkey(db, options.key): - print "Imported successfully" - else: - print "Bad private key" - - db.close() - -if __name__ == '__main__': - main() +# based on http://github.com/gavinandresen/bitcointools +# +# Usage: pywallet.py [options] +# +# Options: +# --version show program's version number and exit +# -h, --help show this help message and exit +# --dumpwallet dump wallet in json format +# --importprivkey=KEY import private key from vanitygen +# --datadir=DATADIR wallet directory (defaults to bitcoin default) +# --testnet use testnet subdirectory and address type + +from bsddb.db import * +import os, sys, time +import json +import logging +import struct +import StringIO +import traceback +import socket +import types +import string +import exceptions +import hashlib +import random + +max_version = 32500 +addrtype = 0 +json_db = {} +private_keys = [] + +def determine_db_dir(): + import os + import os.path + import platform + if platform.system() == "Darwin": + return os.path.expanduser("~/Library/Application Support/Bitcoin/") + elif platform.system() == "Windows": + return os.path.join(os.environ['APPDATA'], "Bitcoin") + return os.path.expanduser("~/.bitcoin") + +# secp256k1 + +_p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2FL +_r = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141L +_b = 0x0000000000000000000000000000000000000000000000000000000000000007L +_a = 0x0000000000000000000000000000000000000000000000000000000000000000L +_Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798L +_Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8L + +class CurveFp( object ): + def __init__( self, p, a, b ): + self.__p = p + self.__a = a + self.__b = b + + def p( self ): + return self.__p + + def a( self ): + return self.__a + + def b( self ): + return self.__b + + def contains_point( self, x, y ): + return ( y * y - ( x * x * x + self.__a * x + self.__b ) ) % self.__p == 0 + +class Point( object ): + def __init__( self, curve, x, y, order = None ): + self.__curve = curve + self.__x = x + self.__y = y + self.__order = order + if self.__curve: assert self.__curve.contains_point( x, y ) + if order: assert self * order == INFINITY + + def __add__( self, other ): + if other == INFINITY: return self + if self == INFINITY: return other + assert self.__curve == other.__curve + if self.__x == other.__x: + if ( self.__y + other.__y ) % self.__curve.p() == 0: + return INFINITY + else: + return self.double() + + p = self.__curve.p() + l = ( ( other.__y - self.__y ) * \ + inverse_mod( other.__x - self.__x, p ) ) % p + x3 = ( l * l - self.__x - other.__x ) % p + y3 = ( l * ( self.__x - x3 ) - self.__y ) % p + return Point( self.__curve, x3, y3 ) + + def __mul__( self, other ): + def leftmost_bit( x ): + assert x > 0 + result = 1L + while result <= x: result = 2 * result + return result / 2 + + e = other + if self.__order: e = e % self.__order + if e == 0: return INFINITY + if self == INFINITY: return INFINITY + assert e > 0 + e3 = 3 * e + negative_self = Point( self.__curve, self.__x, -self.__y, self.__order ) + i = leftmost_bit( e3 ) / 2 + result = self + while i > 1: + result = result.double() + if ( e3 & i ) != 0 and ( e & i ) == 0: result = result + self + if ( e3 & i ) == 0 and ( e & i ) != 0: result = result + negative_self + i = i / 2 + return result + + def __rmul__( self, other ): + return self * other + + def __str__( self ): + if self == INFINITY: return "infinity" + return "(%d,%d)" % ( self.__x, self.__y ) + + def double( self ): + if self == INFINITY: + return INFINITY + + p = self.__curve.p() + a = self.__curve.a() + l = ( ( 3 * self.__x * self.__x + a ) * \ + inverse_mod( 2 * self.__y, p ) ) % p + x3 = ( l * l - 2 * self.__x ) % p + y3 = ( l * ( self.__x - x3 ) - self.__y ) % p + return Point( self.__curve, x3, y3 ) + + def x( self ): + return self.__x + + def y( self ): + return self.__y + + def curve( self ): + return self.__curve + + def order( self ): + return self.__order + +INFINITY = Point( None, None, None ) + +def inverse_mod( a, m ): + if a < 0 or m <= a: a = a % m + c, d = a, m + uc, vc, ud, vd = 1, 0, 0, 1 + while c != 0: + q, c, d = divmod( d, c ) + ( c, ) + uc, vc, ud, vd = ud - q*uc, vd - q*vc, uc, vc + assert d == 1 + if ud > 0: return ud + else: return ud + m + +class Signature( object ): + def __init__( self, r, s ): + self.r = r + self.s = s + +class Public_key( object ): + def __init__( self, generator, point ): + self.curve = generator.curve() + self.generator = generator + self.point = point + n = generator.order() + if not n: + raise RuntimeError, "Generator point must have order." + if not n * point == INFINITY: + raise RuntimeError, "Generator point order is bad." + if point.x() < 0 or n <= point.x() or point.y() < 0 or n <= point.y(): + raise RuntimeError, "Generator point has x or y out of range." + + def verifies( self, hash, signature ): + G = self.generator + n = G.order() + r = signature.r + s = signature.s + if r < 1 or r > n-1: return False + if s < 1 or s > n-1: return False + c = inverse_mod( s, n ) + u1 = ( hash * c ) % n + u2 = ( r * c ) % n + xy = u1 * G + u2 * self.point + v = xy.x() % n + return v == r + +class Private_key( object ): + def __init__( self, public_key, secret_multiplier ): + self.public_key = public_key + self.secret_multiplier = secret_multiplier + + def der( self ): + hex_der_key = '06052b8104000a30740201010420' + \ + '%064x' % self.secret_multiplier + \ + 'a00706052b8104000aa14403420004' + \ + '%064x' % self.public_key.point.x() + \ + '%064x' % self.public_key.point.y() + return hex_der_key.decode('hex') + + def sign( self, hash, random_k ): + G = self.public_key.generator + n = G.order() + k = random_k % n + p1 = k * G + r = p1.x() + if r == 0: raise RuntimeError, "amazingly unlucky random number r" + s = ( inverse_mod( k, n ) * \ + ( hash + ( self.secret_multiplier * r ) % n ) ) % n + if s == 0: raise RuntimeError, "amazingly unlucky random number s" + return Signature( r, s ) + +class EC_KEY(object): + def __init__( self, secret ): + curve = CurveFp( _p, _a, _b ) + generator = Point( curve, _Gx, _Gy, _r ) + self.pubkey = Public_key( generator, generator * secret ) + self.privkey = Private_key( self.pubkey, secret ) + self.secret = secret + +def i2d_ECPrivateKey(pkey): + # private keys are 279 bytes long (see crypto/ec/cec_asn1.c) + # ASN1_SIMPLE(EC_PRIVATEKEY, version, LONG), + # ASN1_SIMPLE(EC_PRIVATEKEY, privateKey, ASN1_OCTET_STRING), + # ASN1_EXP_OPT(EC_PRIVATEKEY, parameters, ECPKPARAMETERS, 0), + # ASN1_EXP_OPT(EC_PRIVATEKEY, publicKey, ASN1_BIT_STRING, 1) + hex_i2d_key = '308201130201010420' + \ + '%064x' % pkey.secret + \ + 'a081a53081a2020101302c06072a8648ce3d0101022100' + \ + '%064x' % _p + \ + '3006040100040107044104' + \ + '%064x' % _Gx + \ + '%064x' % _Gy + \ + '022100' + \ + '%064x' % _r + \ + '020101a14403420004' + \ + '%064x' % pkey.pubkey.point.x() + \ + '%064x' % pkey.pubkey.point.y() + return hex_i2d_key.decode('hex') + +def i2o_ECPublicKey(pkey): + # public keys are 65 bytes long (520 bits) + # 0x04 + 32-byte X-coordinate + 32-byte Y-coordinate + hex_i2o_key = '04' + \ + '%064x' % pkey.pubkey.point.x() + \ + '%064x' % pkey.pubkey.point.y() + return hex_i2o_key.decode('hex') + +# hashes + +def hash_160(public_key): + md = hashlib.new('ripemd160') + md.update(hashlib.sha256(public_key).digest()) + return md.digest() + +def public_key_to_bc_address(public_key): + h160 = hash_160(public_key) + return hash_160_to_bc_address(h160) + +def hash_160_to_bc_address(h160): + vh160 = chr(addrtype) + h160 + h = Hash(vh160) + addr = vh160 + h[0:4] + return b58encode(addr) + +def bc_address_to_hash_160(addr): + bytes = b58decode(addr, 25) + return bytes[1:21] + +__b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' +__b58base = len(__b58chars) + +def b58encode(v): + """ encode v, which is a string of bytes, to base58. + """ + + long_value = 0L + for (i, c) in enumerate(v[::-1]): + long_value += (256**i) * ord(c) + + result = '' + while long_value >= __b58base: + div, mod = divmod(long_value, __b58base) + result = __b58chars[mod] + result + long_value = div + result = __b58chars[long_value] + result + + # Bitcoin does a little leading-zero-compression: + # leading 0-bytes in the input become leading-1s + nPad = 0 + for c in v: + if c == '\0': nPad += 1 + else: break + + return (__b58chars[0]*nPad) + result + +def b58decode(v, length): + """ decode v into a string of len bytes + """ + long_value = 0L + for (i, c) in enumerate(v[::-1]): + long_value += __b58chars.find(c) * (__b58base**i) + + result = '' + while long_value >= 256: + div, mod = divmod(long_value, 256) + result = chr(mod) + result + long_value = div + result = chr(long_value) + result + + nPad = 0 + for c in v: + if c == __b58chars[0]: nPad += 1 + else: break + + result = chr(0)*nPad + result + if length is not None and len(result) != length: + return None + + return result + +def long_hex(bytes): + return bytes.encode('hex_codec') + +def Hash(data): + return hashlib.sha256(hashlib.sha256(data).digest()).digest() + +def EncodeBase58Check(vchIn): + hash = Hash(vchIn) + return b58encode(vchIn + hash[0:4]) + +def DecodeBase58Check(psz): + vchRet = b58decode(psz, None) + key = vchRet[0:-4] + csum = vchRet[-4:] + hash = Hash(key) + cs32 = hash[0:4] + if cs32 != csum: + return None + else: + return key + +def str_to_long(b): + res = 0 + pos = 1 + for a in reversed(b): + res += ord(a) * pos + pos *= 256 + return res + +def PrivKeyToSecret(privkey): + return privkey[9:9+32] + +def SecretToASecret(secret): + vchIn = chr(addrtype+128) + secret + return EncodeBase58Check(vchIn) + +def ASecretToSecret(key): + vch = DecodeBase58Check(key) + if vch and vch[0] == chr(addrtype+128): + return vch[1:] + else: + return False + +def regenerate_key(sec): + b = ASecretToSecret(sec) + if not b: + return False + secret = str_to_long(b) + return EC_KEY(secret) + +def GetPubKey(pkey): + return i2o_ECPublicKey(pkey) + +def GetPrivKey(pkey): + return i2d_ECPrivateKey(pkey) + +def GetSecret(pkey): + return ('%064x' % pkey.secret).decode('hex') + +# parser + +def create_env(db_dir): + db_env = DBEnv(0) + r = db_env.open(db_dir, (DB_CREATE|DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_THREAD|DB_RECOVER)) + return db_env + +def parse_CAddress(vds): + d = {'ip':'0.0.0.0','port':0,'nTime': 0} + try: + d['nVersion'] = vds.read_int32() + d['nTime'] = vds.read_uint32() + d['nServices'] = vds.read_uint64() + d['pchReserved'] = vds.read_bytes(12) + d['ip'] = socket.inet_ntoa(vds.read_bytes(4)) + d['port'] = vds.read_uint16() + except: + pass + return d + +def deserialize_CAddress(d): + return d['ip']+":"+str(d['port']) + +def parse_BlockLocator(vds): + d = { 'hashes' : [] } + nHashes = vds.read_compact_size() + for i in xrange(nHashes): + d['hashes'].append(vds.read_bytes(32)) + return d + +def deserialize_BlockLocator(d): + result = "Block Locator top: "+d['hashes'][0][::-1].encode('hex_codec') + return result + +def parse_setting(setting, vds): + if setting[0] == "f": # flag (boolean) settings + return str(vds.read_boolean()) + elif setting[0:4] == "addr": # CAddress + d = parse_CAddress(vds) + return deserialize_CAddress(d) + elif setting == "nTransactionFee": + return vds.read_int64() + elif setting == "nLimitProcessors": + return vds.read_int32() + return 'unknown setting' + +class SerializationError(Exception): + """ Thrown when there's a problem deserializing or serializing """ + +class BCDataStream(object): + def __init__(self): + self.input = None + self.read_cursor = 0 + + def clear(self): + self.input = None + self.read_cursor = 0 + + def write(self, bytes): # Initialize with string of bytes + if self.input is None: + self.input = bytes + else: + self.input += bytes + + def map_file(self, file, start): # Initialize with bytes from file + self.input = mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ) + self.read_cursor = start + def seek_file(self, position): + self.read_cursor = position + def close_file(self): + self.input.close() + + def read_string(self): + # Strings are encoded depending on length: + # 0 to 252 : 1-byte-length followed by bytes (if any) + # 253 to 65,535 : byte'253' 2-byte-length followed by bytes + # 65,536 to 4,294,967,295 : byte '254' 4-byte-length followed by bytes + # ... and the Bitcoin client is coded to understand: + # greater than 4,294,967,295 : byte '255' 8-byte-length followed by bytes of string + # ... but I don't think it actually handles any strings that big. + if self.input is None: + raise SerializationError("call write(bytes) before trying to deserialize") + + try: + length = self.read_compact_size() + except IndexError: + raise SerializationError("attempt to read past end of buffer") + + return self.read_bytes(length) + + def write_string(self, string): + # Length-encoded as with read-string + self.write_compact_size(len(string)) + self.write(string) + + def read_bytes(self, length): + try: + result = self.input[self.read_cursor:self.read_cursor+length] + self.read_cursor += length + return result + except IndexError: + raise SerializationError("attempt to read past end of buffer") + + return '' + + def read_boolean(self): return self.read_bytes(1)[0] != chr(0) + def read_int16(self): return self._read_num(' max_version: + print "Version mismatch (must be <= %d)" % max_version + elif options.key in private_keys: + print "Already exists" + else: + db = open_wallet(db_env, writable=True) + + if importprivkey(db, options.key): + print "Imported successfully" + else: + print "Bad private key" + + db.close() + +if __name__ == '__main__': + main()