pax_global_header00006660000000000000000000000064130147461070014515gustar00rootroot0000000000000052 comment=a82b00686b51677b047098e8968074a783e054a1 pybitcointools-1.1.42/000077500000000000000000000000001301474610700146635ustar00rootroot00000000000000pybitcointools-1.1.42/.gitignore000066400000000000000000000000141301474610700166460ustar00rootroot00000000000000*.pyc *.swp pybitcointools-1.1.42/LICENSE000066400000000000000000000024301301474610700156670ustar00rootroot00000000000000This code is public domain. Everyone has the right to do whatever they want with it for any purpose. In case your jurisdiction does not consider the above disclaimer valid or enforceable, here's an MIT license for you: The MIT License (MIT) Copyright (c) 2013 Vitalik Buterin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. pybitcointools-1.1.42/MANIFEST.in000066400000000000000000000000341301474610700164160ustar00rootroot00000000000000include bitcoin/english.txt pybitcointools-1.1.42/README.md000066400000000000000000000232551301474610700161510ustar00rootroot00000000000000# Pybitcointools, Python library for Bitcoin signatures and transactions ### Advantages: * Functions have a simple interface, inputting and outputting in standard formats * No classes * Many functions can be taken out and used individually * Supports binary, hex and base58 * Transaction deserialization format almost compatible with BitcoinJS * Electrum and BIP0032 support * Make and publish a transaction all in a single command line instruction * Includes non-bitcoin-specific conversion and JSON utilities ### Disadvantages: * Not a full node, has no idea what blocks are * Relies on centralized service (blockchain.info) for blockchain operations, although operations do have backups (eligius, blockr.io) ### Example usage (best way to learn :) ): > from bitcoin import * > priv = sha256('some big long brainwallet password') > priv '57c617d9b4e1f7af6ec97ca2ff57e94a28279a7eedd4d12a99fa11170e94f5a4' > pub = privtopub(priv) > pub '0420f34c2786b4bae593e22596631b025f3ff46e200fc1d4b52ef49bbdc2ed00b26c584b7e32523fb01be2294a1f8a5eb0cf71a203cc034ced46ea92a8df16c6e9' > addr = pubtoaddr(pub) > addr '1CQLd3bhw4EzaURHbKCwM5YZbUQfA4ReY6' > h = history(addr) > h [{'output': u'97f7c7d8ac85e40c255f8a763b6cd9a68f3a94d2e93e8bfa08f977b92e55465e:0', 'value': 50000, 'address': u'1CQLd3bhw4EzaURHbKCwM5YZbUQfA4ReY6'}, {'output': u'4cc806bb04f730c445c60b3e0f4f44b54769a1c196ca37d8d4002135e4abd171:1', 'value': 50000, 'address': u'1CQLd3bhw4EzaURHbKCwM5YZbUQfA4ReY6'}] > outs = [{'value': 90000, 'address': '16iw1MQ1sy1DtRPYw3ao1bCamoyBJtRB4t'}] > tx = mktx(h,outs) > tx '01000000025e46552eb977f908fa8b3ee9d2943a8fa6d96c3b768a5f250ce485acd8c7f7970000000000ffffffff71d1abe4352100d4d837ca96c1a16947b5444f0f3e0bc645c430f704bb06c84c0100000000ffffffff01905f0100000000001976a9143ec6c3ed8dfc3ceabcc1cbdb0c5aef4e2d02873c88ac00000000' > tx2 = sign(tx,0,priv) > tx2 '01000000025e46552eb977f908fa8b3ee9d2943a8fa6d96c3b768a5f250ce485acd8c7f797000000008b483045022100dd29d89a28451febb990fb1dafa21245b105140083ced315ebcdea187572b3990220713f2e554f384d29d7abfedf39f0eb92afba0ef46f374e49d43a728a0ff6046e01410420f34c2786b4bae593e22596631b025f3ff46e200fc1d4b52ef49bbdc2ed00b26c584b7e32523fb01be2294a1f8a5eb0cf71a203cc034ced46ea92a8df16c6e9ffffffff71d1abe4352100d4d837ca96c1a16947b5444f0f3e0bc645c430f704bb06c84c0100000000ffffffff01905f0100000000001976a9143ec6c3ed8dfc3ceabcc1cbdb0c5aef4e2d02873c88ac00000000' > tx3 = sign(tx2,1,priv) > tx3 '01000000025e46552eb977f908fa8b3ee9d2943a8fa6d96c3b768a5f250ce485acd8c7f797000000008b483045022100dd29d89a28451febb990fb1dafa21245b105140083ced315ebcdea187572b3990220713f2e554f384d29d7abfedf39f0eb92afba0ef46f374e49d43a728a0ff6046e01410420f34c2786b4bae593e22596631b025f3ff46e200fc1d4b52ef49bbdc2ed00b26c584b7e32523fb01be2294a1f8a5eb0cf71a203cc034ced46ea92a8df16c6e9ffffffff71d1abe4352100d4d837ca96c1a16947b5444f0f3e0bc645c430f704bb06c84c010000008c4930460221008bbaaaf172adfefc3a1315dc7312c88645832ff76d52e0029d127e65bbeeabe1022100fdeb89658d503cf2737cedb4049e5070f689c50a9b6c85997d49e0787938f93901410420f34c2786b4bae593e22596631b025f3ff46e200fc1d4b52ef49bbdc2ed00b26c584b7e32523fb01be2294a1f8a5eb0cf71a203cc034ced46ea92a8df16c6e9ffffffff01905f0100000000001976a9143ec6c3ed8dfc3ceabcc1cbdb0c5aef4e2d02873c88ac00000000' > pushtx(tx3) 'Transaction Submitted' Or using the pybtctool command line interface: @vub: pybtctool random_electrum_seed 484ccb566edb66c65dd0fd2e4d90ef65 @vub: pybtctool electrum_privkey 484ccb566edb66c65dd0fd2e4d90ef65 0 0 593240c2205e7b7b5d7c13393b7c9553497854b75c7470b76aeca50cd4a894d7 @vub: pybtctool electrum_mpk 484ccb566edb66c65dd0fd2e4d90ef65 484e42865b8e9a6ea8262fd1cde666b557393258ed598d842e563ad9e5e6c70a97e387eefdef123c1b8b4eb21fe210c6216ad7cc1e4186fbbba70f0e2c062c25 @vub: pybtctool bip32_master_key 21456t243rhgtucyadh3wgyrcubw3grydfbng xprv9s21ZrQH143K2napkeoHT48gWmoJa89KCQj4nqLfdGybyWHP9Z8jvCGzuEDv4ihCyoed7RFPNbc9NxoSF7cAvH9AaNSvepUaeqbSpJZ4rbT @vub: pybtctool bip32_ckd xprv9s21ZrQH143K2napkeoHT48gWmoJa89KCQj4nqLfdGybyWHP9Z8jvCGzuEDv4ihCyoed7RFPNbc9NxoSF7cAvH9AaNSvepUaeqbSpJZ4rbT 0 xprv9vfzYrpwo7QHFdtrcvsSCTrBESFPUf1g7NRvayy1QkEfUekpDKLfqvHjgypF5w3nAvnwPjtQUNkyywWNkLbiUS95khfHCzJXFkLEdwRepbw @vub: pybtctool bip32_privtopub xprv9s21ZrQH143K2napkeoHT48gWmoJa89KCQj4nqLfdGybyWHP9Z8jvCGzuEDv4ihCyoed7RFPNbc9NxoSF7cAvH9AaNSvepUaeqbSpJZ4rbT xpub661MyMwAqRbcFGfHrgLHpC5R4odnyasAZdefbDkHBcWarJcXh6SzTzbUkWuhnP142ZFdKdAJSuTSaiGDYjvm7bCLmA8DZqksYjJbYmcgrYF The -s option lets you read arguments from the command line @vub: pybtctool sha256 'some big long brainwallet password' | pybtctool -s privtoaddr | pybtctool -s history [{'output': u'97f7c7d8ac85e40c255f8a763b6cd9a68f3a94d2e93e8bfa08f977b92e55465e:0', 'value': 50000, 'address': u'1CQLd3bhw4EzaURHbKCwM5YZbUQfA4ReY6'}, {'output': u'4cc806bb04f730c445c60b3e0f4f44b54769a1c196ca37d8d4002135e4abd171:1', 'value': 50000, 'address': u'1CQLd3bhw4EzaURHbKCwM5YZbUQfA4ReY6'}] @vub: pybtctool random_electrum_seed | pybtctool -s electrum_privkey 0 0 593240c2205e7b7b5d7c13393b7c9553497854b75c7470b76aeca50cd4a894d7 The -b option lets you read binary data as an argument @vub: pybtctool sha256 123 | pybtctool -s changebase 16 256 | pybtctool -b changebase 256 16 a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae30a The -j option lets you read json from the command line (-J to split a json list into multiple arguments) @vub: pybtctool unspent 1FxkfJQLJTXpW6QmxGT6oF43ZH959ns8Cq | pybtctool -j select 200000001 | pybtctool -j mksend 1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P:20000 1FxkfJQLJTXpW6QmxGT6oF43ZH959ns8Cq 1000 | pybtctool -s signall 805cd74ca322633372b9bfb857f3be41db0b8de43a3c44353b238c0acff9d523 0100000003d5001aae8358ae98cb02c1b6f9859dc1ac3dbc1e9cc88632afeb7b7e3c510a49000000008b4830450221009e03bb6122437767e2ca785535824f4ed13d2ebbb9fa4f9becc6d6f4e1e217dc022064577353c08d8d974250143d920d3b963b463e43bbb90f3371060645c49266b90141048ef80f6bd6b073407a69299c2ba89de48adb59bb9689a5ab040befbbebcfbb15d01b006a6b825121a0d2c546c277acb60f0bd3203bd501b8d67c7dba91f27f47ffffffff1529d655dff6a0f6c9815ee835312fb3ca4df622fde21b6b9097666e9284087d010000008a473044022035dd67d18b575ebd339d05ca6ffa1d27d7549bd993aeaf430985795459fc139402201aaa162cc50181cee493870c9479b1148243a33923cb77be44a73ca554a4e5d60141048ef80f6bd6b073407a69299c2ba89de48adb59bb9689a5ab040befbbebcfbb15d01b006a6b825121a0d2c546c277acb60f0bd3203bd501b8d67c7dba91f27f47ffffffff23d5f9cf0a8c233b35443c3ae48d0bdb41bef357b8bfb972336322a34cd75c80010000008b483045022014daa5c5bbe9b3e5f2539a5cd8e22ce55bc84788f946c5b3643ecac85b4591a9022100a4062074a1df3fa0aea5ef67368d0b1f0eaac520bee6e417c682d83cd04330450141048ef80f6bd6b073407a69299c2ba89de48adb59bb9689a5ab040befbbebcfbb15d01b006a6b825121a0d2c546c277acb60f0bd3203bd501b8d67c7dba91f27f47ffffffff02204e0000000000001976a914946cb2e08075bcbaf157e47bcb67eb2b2339d24288ac5b3c4411000000001976a914a41d15ae657ad3bfd0846771a34d7584c37d54a288ac00000000 Fun stuff with json: @vub: pybtctool history 1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P | pybtctool -j multiaccess value | pybtctool -j sum 625216206372 @vub: pybtctool history 1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P | pybtctool -j count 6198 ### Listing of main commands: * privkey_to_pubkey : (privkey) -> pubkey * privtopub : (privkey) -> pubkey * pubkey_to_address : (pubkey) -> address * pubtoaddr : (pubkey) -> address * privkey_to_address : (privkey) -> address * privtoaddr : (privkey) -> address * add : (key1, key2) -> key1 + key2 (works on privkeys or pubkeys) * multiply : (pubkey, privkey) -> returns pubkey * privkey * ecdsa_sign : (message, privkey) -> sig * ecdsa_verify : (message, sig, pubkey) -> True/False * ecdsa_recover : (message, sig) -> pubkey * random_key : () -> privkey * random_electrum_seed : () -> electrum seed * electrum_stretch : (seed) -> secret exponent * electrum_privkey : (seed or secret exponent, i, type) -> privkey * electrum_mpk : (seed or secret exponent) -> master public key * electrum_pubkey : (seed or secexp or mpk) -> pubkey * bip32_master_key : (seed) -> bip32 master key * bip32_ckd : (private or public bip32 key, i) -> child key * bip32_privtopub : (private bip32 key) -> public bip32 key * bip32_extract_key : (private or public bip32_key) -> privkey or pubkey * deserialize : (hex or bin transaction) -> JSON tx * serialize : (JSON tx) -> hex or bin tx * mktx : (inputs, outputs) -> tx * mksend : (inputs, outputs, change_addr, fee) -> tx * sign : (tx, i, privkey) -> tx with index i signed with privkey * multisign : (tx, i, script, privkey) -> signature * apply_multisignatures: (tx, i, script, sigs) -> tx with index i signed with sigs * scriptaddr : (script) -> P2SH address * mk_multisig_script : (pubkeys, k, n) -> k-of-n multisig script from pubkeys * verify_tx_input : (tx, i, script, sig, pub) -> True/False * tx_hash : (hex or bin tx) -> hash * history : (address1, address2, etc) -> outputs to those addresses * unspent : (address1, address2, etc) -> unspent outputs to those addresses * fetchtx : (txash) -> tx if present * pushtx : (hex or bin tx) -> tries to push to blockchain.info/pushtx * access : (json list/object, prop) -> desired property of that json object * multiaccess : (json list, prop) -> like access, but mapped across each list element * slice : (json list, start, end) -> given slice of the list * count : (json list) -> number of elements * sum : (json list) -> sum of all values pybitcointools-1.1.42/bitcoin/000077500000000000000000000000001301474610700163125ustar00rootroot00000000000000pybitcointools-1.1.42/bitcoin/__init__.py000066400000000000000000000004711301474610700204250ustar00rootroot00000000000000from bitcoin.py2specials import * from bitcoin.py3specials import * from bitcoin.main import * from bitcoin.transaction import * from bitcoin.deterministic import * from bitcoin.bci import * from bitcoin.composite import * from bitcoin.stealth import * from bitcoin.blocks import * from bitcoin.mnemonic import * pybitcointools-1.1.42/bitcoin/bci.py000066400000000000000000000427651301474610700174370ustar00rootroot00000000000000#!/usr/bin/python import json, re import random import sys try: from urllib.request import build_opener except: from urllib2 import build_opener # Makes a request to a given URL (first arg) and optional params (second arg) def make_request(*args): opener = build_opener() opener.addheaders = [('User-agent', 'Mozilla/5.0'+str(random.randrange(1000000)))] try: return opener.open(*args).read().strip() except Exception as e: try: p = e.read().strip() except: p = e raise Exception(p) def is_testnet(inp): '''Checks if inp is a testnet address or if UTXO is a known testnet TxID''' if isinstance(inp, (list, tuple)) and len(inp) >= 1: return any([is_testnet(x) for x in inp]) elif not isinstance(inp, basestring): # sanity check raise TypeError("Input must be str/unicode, not type %s" % str(type(inp))) if not inp or (inp.lower() in ("btc", "testnet")): pass ## ADDRESSES if inp[0] in "123mn": if re.match("^[2mn][a-km-zA-HJ-NP-Z0-9]{26,33}$", inp): return True elif re.match("^[13][a-km-zA-HJ-NP-Z0-9]{26,33}$", inp): return False else: #sys.stderr.write("Bad address format %s") return None ## TXID elif re.match('^[0-9a-fA-F]{64}$', inp): base_url = "http://api.blockcypher.com/v1/btc/{network}/txs/{txid}?includesHex=false" try: # try testnet fetchtx make_request(base_url.format(network="test3", txid=inp.lower())) return True except: # try mainnet fetchtx make_request(base_url.format(network="main", txid=inp.lower())) return False sys.stderr.write("TxID %s has no match for testnet or mainnet (Bad TxID)") return None else: raise TypeError("{0} is unknown input".format(inp)) def set_network(*args): '''Decides if args for unspent/fetchtx/pushtx are mainnet or testnet''' r = [] for arg in args: if not arg: pass if isinstance(arg, basestring): r.append(is_testnet(arg)) elif isinstance(arg, (list, tuple)): return set_network(*arg) if any(r) and not all(r): raise Exception("Mixed Testnet/Mainnet queries") return "testnet" if any(r) else "btc" def parse_addr_args(*args): # Valid input formats: unspent([addr1, addr2, addr3]) # unspent([addr1, addr2, addr3], network) # unspent(addr1, addr2, addr3) # unspent(addr1, addr2, addr3, network) addr_args = args network = "btc" if len(args) == 0: return [], 'btc' if len(args) >= 1 and args[-1] in ('testnet', 'btc'): network = args[-1] addr_args = args[:-1] if len(addr_args) == 1 and isinstance(addr_args, list): network = set_network(*addr_args[0]) addr_args = addr_args[0] if addr_args and isinstance(addr_args, tuple) and isinstance(addr_args[0], list): addr_args = addr_args[0] network = set_network(addr_args) return network, addr_args # Gets the unspent outputs of one or more addresses def bci_unspent(*args): network, addrs = parse_addr_args(*args) u = [] for a in addrs: try: data = make_request('https://blockchain.info/unspent?active='+a) except Exception as e: if str(e) == 'No free outputs to spend': continue else: raise Exception(e) try: jsonobj = json.loads(data.decode("utf-8")) for o in jsonobj["unspent_outputs"]: h = o['tx_hash'].decode('hex')[::-1].encode('hex') u.append({ "output": h+':'+str(o['tx_output_n']), "value": o['value'] }) except: raise Exception("Failed to decode data: "+data) return u def blockr_unspent(*args): # Valid input formats: blockr_unspent([addr1, addr2,addr3]) # blockr_unspent(addr1, addr2, addr3) # blockr_unspent([addr1, addr2, addr3], network) # blockr_unspent(addr1, addr2, addr3, network) # Where network is 'btc' or 'testnet' network, addr_args = parse_addr_args(*args) if network == 'testnet': blockr_url = 'http://tbtc.blockr.io/api/v1/address/unspent/' elif network == 'btc': blockr_url = 'http://btc.blockr.io/api/v1/address/unspent/' else: raise Exception( 'Unsupported network {0} for blockr_unspent'.format(network)) if len(addr_args) == 0: return [] elif isinstance(addr_args[0], list): addrs = addr_args[0] else: addrs = addr_args res = make_request(blockr_url+','.join(addrs)) data = json.loads(res.decode("utf-8"))['data'] o = [] if 'unspent' in data: data = [data] for dat in data: for u in dat['unspent']: o.append({ "output": u['tx']+':'+str(u['n']), "value": int(u['amount'].replace('.', '')) }) return o def helloblock_unspent(*args): addrs, network = parse_addr_args(*args) if network == 'testnet': url = 'https://testnet.helloblock.io/v1/addresses/%s/unspents?limit=500&offset=%s' elif network == 'btc': url = 'https://mainnet.helloblock.io/v1/addresses/%s/unspents?limit=500&offset=%s' o = [] for addr in addrs: for offset in xrange(0, 10**9, 500): res = make_request(url % (addr, offset)) data = json.loads(res.decode("utf-8"))["data"] if not len(data["unspents"]): break elif offset: sys.stderr.write("Getting more unspents: %d\n" % offset) for dat in data["unspents"]: o.append({ "output": dat["txHash"]+':'+str(dat["index"]), "value": dat["value"], }) return o unspent_getters = { 'bci': bci_unspent, 'blockr': blockr_unspent, 'helloblock': helloblock_unspent } def unspent(*args, **kwargs): f = unspent_getters.get(kwargs.get('source', ''), bci_unspent) return f(*args) # Gets the transaction output history of a given set of addresses, # including whether or not they have been spent def history(*args): # Valid input formats: history([addr1, addr2,addr3]) # history(addr1, addr2, addr3) if len(args) == 0: return [] elif isinstance(args[0], list): addrs = args[0] else: addrs = args txs = [] for addr in addrs: offset = 0 while 1: gathered = False while not gathered: try: data = make_request( 'https://blockchain.info/address/%s?format=json&offset=%s' % (addr, offset)) gathered = True except Exception as e: try: sys.stderr.write(e.read().strip()) except: sys.stderr.write(str(e)) gathered = False try: jsonobj = json.loads(data.decode("utf-8")) except: raise Exception("Failed to decode data: "+data) txs.extend(jsonobj["txs"]) if len(jsonobj["txs"]) < 50: break offset += 50 sys.stderr.write("Fetching more transactions... "+str(offset)+'\n') outs = {} for tx in txs: for o in tx["out"]: if o.get('addr', None) in addrs: key = str(tx["tx_index"])+':'+str(o["n"]) outs[key] = { "address": o["addr"], "value": o["value"], "output": tx["hash"]+':'+str(o["n"]), "block_height": tx.get("block_height", None) } for tx in txs: for i, inp in enumerate(tx["inputs"]): if "prev_out" in inp: if inp["prev_out"].get("addr", None) in addrs: key = str(inp["prev_out"]["tx_index"]) + \ ':'+str(inp["prev_out"]["n"]) if outs.get(key): outs[key]["spend"] = tx["hash"]+':'+str(i) return [outs[k] for k in outs] # Pushes a transaction to the network using https://blockchain.info/pushtx def bci_pushtx(tx): if not re.match('^[0-9a-fA-F]*$', tx): tx = tx.encode('hex') return make_request('https://blockchain.info/pushtx', 'tx='+tx) def eligius_pushtx(tx): if not re.match('^[0-9a-fA-F]*$', tx): tx = tx.encode('hex') s = make_request( 'http://eligius.st/~wizkid057/newstats/pushtxn.php', 'transaction='+tx+'&send=Push') strings = re.findall('string[^"]*"[^"]*"', s) for string in strings: quote = re.findall('"[^"]*"', string)[0] if len(quote) >= 5: return quote[1:-1] def blockr_pushtx(tx, network='btc'): if network == 'testnet': blockr_url = 'http://tbtc.blockr.io/api/v1/tx/push' elif network == 'btc': blockr_url = 'http://btc.blockr.io/api/v1/tx/push' else: raise Exception( 'Unsupported network {0} for blockr_pushtx'.format(network)) if not re.match('^[0-9a-fA-F]*$', tx): tx = tx.encode('hex') return make_request(blockr_url, '{"hex":"%s"}' % tx) def helloblock_pushtx(tx): if not re.match('^[0-9a-fA-F]*$', tx): tx = tx.encode('hex') return make_request('https://mainnet.helloblock.io/v1/transactions', 'rawTxHex='+tx) pushtx_getters = { 'bci': bci_pushtx, 'blockr': blockr_pushtx, 'helloblock': helloblock_pushtx } def pushtx(*args, **kwargs): f = pushtx_getters.get(kwargs.get('source', ''), bci_pushtx) return f(*args) def last_block_height(network='btc'): if network == 'testnet': data = make_request('http://tbtc.blockr.io/api/v1/block/info/last') jsonobj = json.loads(data.decode("utf-8")) return jsonobj["data"]["nb"] data = make_request('https://blockchain.info/latestblock') jsonobj = json.loads(data.decode("utf-8")) return jsonobj["height"] # Gets a specific transaction def bci_fetchtx(txhash): if isinstance(txhash, list): return [bci_fetchtx(h) for h in txhash] if not re.match('^[0-9a-fA-F]*$', txhash): txhash = txhash.encode('hex') data = make_request('https://blockchain.info/rawtx/'+txhash+'?format=hex') return data def blockr_fetchtx(txhash, network='btc'): if network == 'testnet': blockr_url = 'http://tbtc.blockr.io/api/v1/tx/raw/' elif network == 'btc': blockr_url = 'http://btc.blockr.io/api/v1/tx/raw/' else: raise Exception( 'Unsupported network {0} for blockr_fetchtx'.format(network)) if isinstance(txhash, list): txhash = ','.join([x.encode('hex') if not re.match('^[0-9a-fA-F]*$', x) else x for x in txhash]) jsondata = json.loads(make_request(blockr_url+txhash).decode("utf-8")) return [d['tx']['hex'] for d in jsondata['data']] else: if not re.match('^[0-9a-fA-F]*$', txhash): txhash = txhash.encode('hex') jsondata = json.loads(make_request(blockr_url+txhash).decode("utf-8")) return jsondata['data']['tx']['hex'] def helloblock_fetchtx(txhash, network='btc'): if isinstance(txhash, list): return [helloblock_fetchtx(h) for h in txhash] if not re.match('^[0-9a-fA-F]*$', txhash): txhash = txhash.encode('hex') if network == 'testnet': url = 'https://testnet.helloblock.io/v1/transactions/' elif network == 'btc': url = 'https://mainnet.helloblock.io/v1/transactions/' else: raise Exception( 'Unsupported network {0} for helloblock_fetchtx'.format(network)) data = json.loads(make_request(url + txhash).decode("utf-8"))["data"]["transaction"] o = { "locktime": data["locktime"], "version": data["version"], "ins": [], "outs": [] } for inp in data["inputs"]: o["ins"].append({ "script": inp["scriptSig"], "outpoint": { "index": inp["prevTxoutIndex"], "hash": inp["prevTxHash"], }, "sequence": 4294967295 }) for outp in data["outputs"]: o["outs"].append({ "value": outp["value"], "script": outp["scriptPubKey"] }) from bitcoin.transaction import serialize from bitcoin.transaction import txhash as TXHASH tx = serialize(o) assert TXHASH(tx) == txhash return tx fetchtx_getters = { 'bci': bci_fetchtx, 'blockr': blockr_fetchtx, 'helloblock': helloblock_fetchtx } def fetchtx(*args, **kwargs): f = fetchtx_getters.get(kwargs.get('source', ''), bci_fetchtx) return f(*args) def firstbits(address): if len(address) >= 25: return make_request('https://blockchain.info/q/getfirstbits/'+address) else: return make_request( 'https://blockchain.info/q/resolvefirstbits/'+address) def get_block_at_height(height): j = json.loads(make_request("https://blockchain.info/block-height/" + str(height)+"?format=json").decode("utf-8")) for b in j['blocks']: if b['main_chain'] is True: return b raise Exception("Block at this height not found") def _get_block(inp): if len(str(inp)) < 64: return get_block_at_height(inp) else: return json.loads(make_request( 'https://blockchain.info/rawblock/'+inp).decode("utf-8")) def bci_get_block_header_data(inp): j = _get_block(inp) return { 'version': j['ver'], 'hash': j['hash'], 'prevhash': j['prev_block'], 'timestamp': j['time'], 'merkle_root': j['mrkl_root'], 'bits': j['bits'], 'nonce': j['nonce'], } def blockr_get_block_header_data(height, network='btc'): if network == 'testnet': blockr_url = "http://tbtc.blockr.io/api/v1/block/raw/" elif network == 'btc': blockr_url = "http://btc.blockr.io/api/v1/block/raw/" else: raise Exception( 'Unsupported network {0} for blockr_get_block_header_data'.format(network)) k = json.loads(make_request(blockr_url + str(height)).decode("utf-8")) j = k['data'] return { 'version': j['version'], 'hash': j['hash'], 'prevhash': j['previousblockhash'], 'timestamp': j['time'], 'merkle_root': j['merkleroot'], 'bits': int(j['bits'], 16), 'nonce': j['nonce'], } def get_block_timestamp(height, network='btc'): if network == 'testnet': blockr_url = "http://tbtc.blockr.io/api/v1/block/info/" elif network == 'btc': blockr_url = "http://btc.blockr.io/api/v1/block/info/" else: raise Exception( 'Unsupported network {0} for get_block_timestamp'.format(network)) import time, calendar if isinstance(height, list): k = json.loads(make_request(blockr_url + ','.join([str(x) for x in height])).decode("utf-8")) o = {x['nb']: calendar.timegm(time.strptime(x['time_utc'], "%Y-%m-%dT%H:%M:%SZ")) for x in k['data']} return [o[x] for x in height] else: k = json.loads(make_request(blockr_url + str(height)).decode("utf-8")) j = k['data']['time_utc'] return calendar.timegm(time.strptime(j, "%Y-%m-%dT%H:%M:%SZ")) block_header_data_getters = { 'bci': bci_get_block_header_data, 'blockr': blockr_get_block_header_data } def get_block_header_data(inp, **kwargs): f = block_header_data_getters.get(kwargs.get('source', ''), bci_get_block_header_data) return f(inp, **kwargs) def get_txs_in_block(inp): j = _get_block(inp) hashes = [t['hash'] for t in j['tx']] return hashes def get_block_height(txhash): j = json.loads(make_request('https://blockchain.info/rawtx/'+txhash).decode("utf-8")) return j['block_height'] # fromAddr, toAddr, 12345, changeAddress def get_tx_composite(inputs, outputs, output_value, change_address=None, network=None): """mktx using blockcypher API""" inputs = [inputs] if not isinstance(inputs, list) else inputs outputs = [outputs] if not isinstance(outputs, list) else outputs network = set_network(change_address or inputs) if not network else network.lower() url = "http://api.blockcypher.com/v1/btc/{network}/txs/new?includeToSignTx=true".format( network=('test3' if network=='testnet' else 'main')) is_address = lambda a: bool(re.match("^[123mn][a-km-zA-HJ-NP-Z0-9]{26,33}$", a)) if any([is_address(x) for x in inputs]): inputs_type = 'addresses' # also accepts UTXOs, only addresses supported presently if any([is_address(x) for x in outputs]): outputs_type = 'addresses' # TODO: add UTXO support data = { 'inputs': [{inputs_type: inputs}], 'confirmations': 0, 'preference': 'high', 'outputs': [{outputs_type: outputs, "value": output_value}] } if change_address: data["change_address"] = change_address # jdata = json.loads(make_request(url, data)) hash, txh = jdata.get("tosign")[0], jdata.get("tosign_tx")[0] assert bin_dbl_sha256(txh.decode('hex')).encode('hex') == hash, "checksum mismatch %s" % hash return txh.encode("utf-8") blockcypher_mktx = get_tx_composite pybitcointools-1.1.42/bitcoin/blocks.py000066400000000000000000000033701301474610700201440ustar00rootroot00000000000000from bitcoin.main import * def serialize_header(inp): o = encode(inp['version'], 256, 4)[::-1] + \ inp['prevhash'].decode('hex')[::-1] + \ inp['merkle_root'].decode('hex')[::-1] + \ encode(inp['timestamp'], 256, 4)[::-1] + \ encode(inp['bits'], 256, 4)[::-1] + \ encode(inp['nonce'], 256, 4)[::-1] h = bin_sha256(bin_sha256(o))[::-1].encode('hex') assert h == inp['hash'], (sha256(o), inp['hash']) return o.encode('hex') def deserialize_header(inp): inp = inp.decode('hex') return { "version": decode(inp[:4][::-1], 256), "prevhash": inp[4:36][::-1].encode('hex'), "merkle_root": inp[36:68][::-1].encode('hex'), "timestamp": decode(inp[68:72][::-1], 256), "bits": decode(inp[72:76][::-1], 256), "nonce": decode(inp[76:80][::-1], 256), "hash": bin_sha256(bin_sha256(inp))[::-1].encode('hex') } def mk_merkle_proof(header, hashes, index): nodes = [h.decode('hex')[::-1] for h in hashes] if len(nodes) % 2 and len(nodes) > 2: nodes.append(nodes[-1]) layers = [nodes] while len(nodes) > 1: newnodes = [] for i in range(0, len(nodes) - 1, 2): newnodes.append(bin_sha256(bin_sha256(nodes[i] + nodes[i+1]))) if len(newnodes) % 2 and len(newnodes) > 2: newnodes.append(newnodes[-1]) nodes = newnodes layers.append(nodes) # Sanity check, make sure merkle root is valid assert nodes[0][::-1].encode('hex') == header['merkle_root'] merkle_siblings = \ [layers[i][(index >> i) ^ 1] for i in range(len(layers)-1)] return { "hash": hashes[index], "siblings": [x[::-1].encode('hex') for x in merkle_siblings], "header": header } pybitcointools-1.1.42/bitcoin/composite.py000066400000000000000000000074341301474610700206760ustar00rootroot00000000000000from bitcoin.main import * from bitcoin.transaction import * from bitcoin.bci import * from bitcoin.deterministic import * from bitcoin.blocks import * # Takes privkey, address, value (satoshis), fee (satoshis) def send(frm, to, value, fee=10000, **kwargs): return sendmultitx(frm, to + ":" + str(value), fee, **kwargs) # Takes privkey, "address1:value1,address2:value2" (satoshis), fee (satoshis) def sendmultitx(frm, *args, **kwargs): tv, fee = args[:-1], int(args[-1]) outs = [] outvalue = 0 for a in tv: outs.append(a) outvalue += int(a.split(":")[1]) u = unspent(privtoaddr(frm), **kwargs) u2 = select(u, int(outvalue)+int(fee)) argz = u2 + outs + [privtoaddr(frm), fee] tx = mksend(*argz) tx2 = signall(tx, frm) return pushtx(tx2, **kwargs) # Takes address, address, value (satoshis), fee(satoshis) def preparetx(frm, to, value, fee=10000, **kwargs): tovalues = to + ":" + str(value) return preparemultitx(frm, tovalues, fee, **kwargs) # Takes address, address:value, address:value ... (satoshis), fee(satoshis) def preparemultitx(frm, *args, **kwargs): tv, fee = args[:-1], int(args[-1]) outs = [] outvalue = 0 for a in tv: outs.append(a) outvalue += int(a.split(":")[1]) u = unspent(frm, **kwargs) u2 = select(u, int(outvalue)+int(fee)) argz = u2 + outs + [frm, fee] return mksend(*argz) # BIP32 hierarchical deterministic multisig script def bip32_hdm_script(*args): if len(args) == 3: keys, req, path = args else: i, keys, path = 0, [], [] while len(args[i]) > 40: keys.append(args[i]) i += 1 req = int(args[i]) path = map(int, args[i+1:]) pubs = sorted(map(lambda x: bip32_descend(x, path), keys)) return mk_multisig_script(pubs, req) # BIP32 hierarchical deterministic multisig address def bip32_hdm_addr(*args): return scriptaddr(bip32_hdm_script(*args)) # Setup a coinvault transaction def setup_coinvault_tx(tx, script): txobj = deserialize(tx) N = deserialize_script(script)[-2] for inp in txobj["ins"]: inp["script"] = serialize_script([None] * (N+1) + [script]) return serialize(txobj) # Sign a coinvault transaction def sign_coinvault_tx(tx, priv): pub = privtopub(priv) txobj = deserialize(tx) subscript = deserialize_script(txobj['ins'][0]['script']) oscript = deserialize_script(subscript[-1]) k, pubs = oscript[0], oscript[1:-2] for j in range(len(txobj['ins'])): scr = deserialize_script(txobj['ins'][j]['script']) for i, p in enumerate(pubs): if p == pub: scr[i+1] = multisign(tx, j, subscript[-1], priv) if len(filter(lambda x: x, scr[1:-1])) >= k: scr = [None] + filter(lambda x: x, scr[1:-1])[:k] + [scr[-1]] txobj['ins'][j]['script'] = serialize_script(scr) return serialize(txobj) # Inspects a transaction def inspect(tx, **kwargs): d = deserialize(tx) isum = 0 ins = {} for _in in d['ins']: h = _in['outpoint']['hash'] i = _in['outpoint']['index'] prevout = deserialize(fetchtx(h, **kwargs))['outs'][i] isum += prevout['value'] a = script_to_address(prevout['script']) ins[a] = ins.get(a, 0) + prevout['value'] outs = [] osum = 0 for _out in d['outs']: outs.append({'address': script_to_address(_out['script']), 'value': _out['value']}) osum += _out['value'] return { 'fee': isum - osum, 'outs': outs, 'ins': ins } def merkle_prove(txhash): blocknum = str(get_block_height(txhash)) header = get_block_header_data(blocknum) hashes = get_txs_in_block(blocknum) i = hashes.index(txhash) return mk_merkle_proof(header, hashes, i) pybitcointools-1.1.42/bitcoin/deterministic.py000066400000000000000000000147261301474610700215410ustar00rootroot00000000000000from bitcoin.main import * import hmac import hashlib from binascii import hexlify # Electrum wallets def electrum_stretch(seed): return slowsha(seed) # Accepts seed or stretched seed, returns master public key def electrum_mpk(seed): if len(seed) == 32: seed = electrum_stretch(seed) return privkey_to_pubkey(seed)[2:] # Accepts (seed or stretched seed), index and secondary index # (conventionally 0 for ordinary addresses, 1 for change) , returns privkey def electrum_privkey(seed, n, for_change=0): if len(seed) == 32: seed = electrum_stretch(seed) mpk = electrum_mpk(seed) offset = dbl_sha256(from_int_representation_to_bytes(n)+b':'+from_int_representation_to_bytes(for_change)+b':'+binascii.unhexlify(mpk)) return add_privkeys(seed, offset) # Accepts (seed or stretched seed or master pubkey), index and secondary index # (conventionally 0 for ordinary addresses, 1 for change) , returns pubkey def electrum_pubkey(masterkey, n, for_change=0): if len(masterkey) == 32: mpk = electrum_mpk(electrum_stretch(masterkey)) elif len(masterkey) == 64: mpk = electrum_mpk(masterkey) else: mpk = masterkey bin_mpk = encode_pubkey(mpk, 'bin_electrum') offset = bin_dbl_sha256(from_int_representation_to_bytes(n)+b':'+from_int_representation_to_bytes(for_change)+b':'+bin_mpk) return add_pubkeys('04'+mpk, privtopub(offset)) # seed/stretched seed/pubkey -> address (convenience method) def electrum_address(masterkey, n, for_change=0, version=0): return pubkey_to_address(electrum_pubkey(masterkey, n, for_change), version) # Given a master public key, a private key from that wallet and its index, # cracks the secret exponent which can be used to generate all other private # keys in the wallet def crack_electrum_wallet(mpk, pk, n, for_change=0): bin_mpk = encode_pubkey(mpk, 'bin_electrum') offset = dbl_sha256(str(n)+':'+str(for_change)+':'+bin_mpk) return subtract_privkeys(pk, offset) # Below code ASSUMES binary inputs and compressed pubkeys MAINNET_PRIVATE = b'\x04\x88\xAD\xE4' MAINNET_PUBLIC = b'\x04\x88\xB2\x1E' TESTNET_PRIVATE = b'\x04\x35\x83\x94' TESTNET_PUBLIC = b'\x04\x35\x87\xCF' PRIVATE = [MAINNET_PRIVATE, TESTNET_PRIVATE] PUBLIC = [MAINNET_PUBLIC, TESTNET_PUBLIC] # BIP32 child key derivation def raw_bip32_ckd(rawtuple, i): vbytes, depth, fingerprint, oldi, chaincode, key = rawtuple i = int(i) if vbytes in PRIVATE: priv = key pub = privtopub(key) else: pub = key if i >= 2**31: if vbytes in PUBLIC: raise Exception("Can't do private derivation on public key!") I = hmac.new(chaincode, b'\x00'+priv[:32]+encode(i, 256, 4), hashlib.sha512).digest() else: I = hmac.new(chaincode, pub+encode(i, 256, 4), hashlib.sha512).digest() if vbytes in PRIVATE: newkey = add_privkeys(I[:32]+B'\x01', priv) fingerprint = bin_hash160(privtopub(key))[:4] if vbytes in PUBLIC: newkey = add_pubkeys(compress(privtopub(I[:32])), key) fingerprint = bin_hash160(key)[:4] return (vbytes, depth + 1, fingerprint, i, I[32:], newkey) def bip32_serialize(rawtuple): vbytes, depth, fingerprint, i, chaincode, key = rawtuple i = encode(i, 256, 4) chaincode = encode(hash_to_int(chaincode), 256, 32) keydata = b'\x00'+key[:-1] if vbytes in PRIVATE else key bindata = vbytes + from_int_to_byte(depth % 256) + fingerprint + i + chaincode + keydata return changebase(bindata+bin_dbl_sha256(bindata)[:4], 256, 58) def bip32_deserialize(data): dbin = changebase(data, 58, 256) if bin_dbl_sha256(dbin[:-4])[:4] != dbin[-4:]: raise Exception("Invalid checksum") vbytes = dbin[0:4] depth = from_byte_to_int(dbin[4]) fingerprint = dbin[5:9] i = decode(dbin[9:13], 256) chaincode = dbin[13:45] key = dbin[46:78]+b'\x01' if vbytes in PRIVATE else dbin[45:78] return (vbytes, depth, fingerprint, i, chaincode, key) def raw_bip32_privtopub(rawtuple): vbytes, depth, fingerprint, i, chaincode, key = rawtuple newvbytes = MAINNET_PUBLIC if vbytes == MAINNET_PRIVATE else TESTNET_PUBLIC return (newvbytes, depth, fingerprint, i, chaincode, privtopub(key)) def bip32_privtopub(data): return bip32_serialize(raw_bip32_privtopub(bip32_deserialize(data))) def bip32_ckd(data, i): return bip32_serialize(raw_bip32_ckd(bip32_deserialize(data), i)) def bip32_master_key(seed, vbytes=MAINNET_PRIVATE): I = hmac.new(from_string_to_bytes("Bitcoin seed"), seed, hashlib.sha512).digest() return bip32_serialize((vbytes, 0, b'\x00'*4, 0, I[32:], I[:32]+b'\x01')) def bip32_bin_extract_key(data): return bip32_deserialize(data)[-1] def bip32_extract_key(data): return safe_hexlify(bip32_deserialize(data)[-1]) # Exploits the same vulnerability as above in Electrum wallets # Takes a BIP32 pubkey and one of the child privkeys of its corresponding # privkey and returns the BIP32 privkey associated with that pubkey def raw_crack_bip32_privkey(parent_pub, priv): vbytes, depth, fingerprint, i, chaincode, key = priv pvbytes, pdepth, pfingerprint, pi, pchaincode, pkey = parent_pub i = int(i) if i >= 2**31: raise Exception("Can't crack private derivation!") I = hmac.new(pchaincode, pkey+encode(i, 256, 4), hashlib.sha512).digest() pprivkey = subtract_privkeys(key, I[:32]+b'\x01') newvbytes = MAINNET_PRIVATE if vbytes == MAINNET_PUBLIC else TESTNET_PRIVATE return (newvbytes, pdepth, pfingerprint, pi, pchaincode, pprivkey) def crack_bip32_privkey(parent_pub, priv): dsppub = bip32_deserialize(parent_pub) dspriv = bip32_deserialize(priv) return bip32_serialize(raw_crack_bip32_privkey(dsppub, dspriv)) def coinvault_pub_to_bip32(*args): if len(args) == 1: args = args[0].split(' ') vals = map(int, args[34:]) I1 = ''.join(map(chr, vals[:33])) I2 = ''.join(map(chr, vals[35:67])) return bip32_serialize((MAINNET_PUBLIC, 0, b'\x00'*4, 0, I2, I1)) def coinvault_priv_to_bip32(*args): if len(args) == 1: args = args[0].split(' ') vals = map(int, args[34:]) I2 = ''.join(map(chr, vals[35:67])) I3 = ''.join(map(chr, vals[72:104])) return bip32_serialize((MAINNET_PRIVATE, 0, b'\x00'*4, 0, I2, I3+b'\x01')) def bip32_descend(*args): if len(args) == 2 and isinstance(args[1], list): key, path = args else: key, path = args[0], map(int, args[1:]) for p in path: key = bip32_ckd(key, p) return bip32_extract_key(key) pybitcointools-1.1.42/bitcoin/english.txt000066400000000000000000000314741301474610700205150ustar00rootroot00000000000000abandon ability able about above absent absorb abstract absurd abuse access accident account accuse achieve acid acoustic acquire across act action actor actress actual adapt add addict address adjust admit adult advance advice aerobic affair afford afraid again age agent agree ahead aim air airport aisle alarm album alcohol alert alien all alley allow almost alone alpha already also alter always amateur amazing among amount amused analyst anchor ancient anger angle angry animal ankle announce annual another answer antenna antique anxiety any apart apology appear apple approve april arch arctic area arena argue arm armed armor army around arrange arrest arrive arrow art artefact artist artwork ask aspect assault asset assist assume asthma athlete atom attack attend attitude attract auction audit august aunt author auto autumn average avocado avoid awake aware away awesome awful awkward axis baby bachelor bacon badge bag balance balcony ball bamboo banana banner bar barely bargain barrel base basic basket battle beach bean beauty because become beef before begin behave behind believe below belt bench benefit best betray better between beyond bicycle bid bike bind biology bird birth bitter black blade blame blanket blast bleak bless blind blood blossom blouse blue blur blush board boat body boil bomb bone bonus book boost border boring borrow boss bottom bounce box boy bracket brain brand brass brave bread breeze brick bridge brief bright bring brisk broccoli broken bronze broom brother brown brush bubble buddy budget buffalo build bulb bulk bullet bundle bunker burden burger burst bus business busy butter buyer buzz cabbage cabin cable cactus cage cake call calm camera camp can canal cancel candy cannon canoe canvas canyon capable capital captain car carbon card cargo carpet carry cart case cash casino castle casual cat catalog catch category cattle caught cause caution cave ceiling celery cement census century cereal certain chair chalk champion change chaos chapter charge chase chat cheap check cheese chef cherry chest chicken chief child chimney choice choose chronic chuckle chunk churn cigar cinnamon circle citizen city civil claim clap clarify claw clay clean clerk clever click client cliff climb clinic clip clock clog close cloth cloud clown club clump cluster clutch coach coast coconut code coffee coil coin collect color column combine come comfort comic common company concert conduct confirm congress connect consider control convince cook cool copper copy coral core corn correct cost cotton couch country couple course cousin cover coyote crack cradle craft cram crane crash crater crawl crazy cream credit creek crew cricket crime crisp critic crop cross crouch crowd crucial cruel cruise crumble crunch crush cry crystal cube culture cup cupboard curious current curtain curve cushion custom cute cycle dad damage damp dance danger daring dash daughter dawn day deal debate debris decade december decide decline decorate decrease deer defense define defy degree delay deliver demand demise denial dentist deny depart depend deposit depth deputy derive describe desert design desk despair destroy detail detect develop device devote diagram dial diamond diary dice diesel diet differ digital dignity dilemma dinner dinosaur direct dirt disagree discover disease dish dismiss disorder display distance divert divide divorce dizzy doctor document dog doll dolphin domain donate donkey donor door dose double dove draft dragon drama drastic draw dream dress drift drill drink drip drive drop drum dry duck dumb dune during dust dutch duty dwarf dynamic eager eagle early earn earth easily east easy echo ecology economy edge edit educate effort egg eight either elbow elder electric elegant element elephant elevator elite else embark embody embrace emerge emotion employ empower empty enable enact end endless endorse enemy energy enforce engage engine enhance enjoy enlist enough enrich enroll ensure enter entire entry envelope episode equal equip era erase erode erosion error erupt escape essay essence estate eternal ethics evidence evil evoke evolve exact example excess exchange excite exclude excuse execute exercise exhaust exhibit exile exist exit exotic expand expect expire explain expose express extend extra eye eyebrow fabric face faculty fade faint faith fall false fame family famous fan fancy fantasy farm fashion fat fatal father fatigue fault favorite feature february federal fee feed feel female fence festival fetch fever few fiber fiction field figure file film filter final find fine finger finish fire firm first fiscal fish fit fitness fix flag flame flash flat flavor flee flight flip float flock floor flower fluid flush fly foam focus fog foil fold follow food foot force forest forget fork fortune forum forward fossil foster found fox fragile frame frequent fresh friend fringe frog front frost frown frozen fruit fuel fun funny furnace fury future gadget gain galaxy gallery game gap garage garbage garden garlic garment gas gasp gate gather gauge gaze general genius genre gentle genuine gesture ghost giant gift giggle ginger giraffe girl give glad glance glare glass glide glimpse globe gloom glory glove glow glue goat goddess gold good goose gorilla gospel gossip govern gown grab grace grain grant grape grass gravity great green grid grief grit grocery group grow grunt guard guess guide guilt guitar gun gym habit hair half hammer hamster hand happy harbor hard harsh harvest hat have hawk hazard head health heart heavy hedgehog height hello helmet help hen hero hidden high hill hint hip hire history hobby hockey hold hole holiday hollow home honey hood hope horn horror horse hospital host hotel hour hover hub huge human humble humor hundred hungry hunt hurdle hurry hurt husband hybrid ice icon idea identify idle ignore ill illegal illness image imitate immense immune impact impose improve impulse inch include income increase index indicate indoor industry infant inflict inform inhale inherit initial inject injury inmate inner innocent input inquiry insane insect inside inspire install intact interest into invest invite involve iron island isolate issue item ivory jacket jaguar jar jazz jealous jeans jelly jewel job join joke journey joy judge juice jump jungle junior junk just kangaroo keen keep ketchup key kick kid kidney kind kingdom kiss kit kitchen kite kitten kiwi knee knife knock know lab label labor ladder lady lake lamp language laptop large later latin laugh laundry lava law lawn lawsuit layer lazy leader leaf learn leave lecture left leg legal legend leisure lemon lend length lens leopard lesson letter level liar liberty library license life lift light like limb limit link lion liquid list little live lizard load loan lobster local lock logic lonely long loop lottery loud lounge love loyal lucky luggage lumber lunar lunch luxury lyrics machine mad magic magnet maid mail main major make mammal man manage mandate mango mansion manual maple marble march margin marine market marriage mask mass master match material math matrix matter maximum maze meadow mean measure meat mechanic medal media melody melt member memory mention menu mercy merge merit merry mesh message metal method middle midnight milk million mimic mind minimum minor minute miracle mirror misery miss mistake mix mixed mixture mobile model modify mom moment monitor monkey monster month moon moral more morning mosquito mother motion motor mountain mouse move movie much muffin mule multiply muscle museum mushroom music must mutual myself mystery myth naive name napkin narrow nasty nation nature near neck need negative neglect neither nephew nerve nest net network neutral never news next nice night noble noise nominee noodle normal north nose notable note nothing notice novel now nuclear number nurse nut oak obey object oblige obscure observe obtain obvious occur ocean october odor off offer office often oil okay old olive olympic omit once one onion online only open opera opinion oppose option orange orbit orchard order ordinary organ orient original orphan ostrich other outdoor outer output outside oval oven over own owner oxygen oyster ozone pact paddle page pair palace palm panda panel panic panther paper parade parent park parrot party pass patch path patient patrol pattern pause pave payment peace peanut pear peasant pelican pen penalty pencil people pepper perfect permit person pet phone photo phrase physical piano picnic picture piece pig pigeon pill pilot pink pioneer pipe pistol pitch pizza place planet plastic plate play please pledge pluck plug plunge poem poet point polar pole police pond pony pool popular portion position possible post potato pottery poverty powder power practice praise predict prefer prepare present pretty prevent price pride primary print priority prison private prize problem process produce profit program project promote proof property prosper protect proud provide public pudding pull pulp pulse pumpkin punch pupil puppy purchase purity purpose purse push put puzzle pyramid quality quantum quarter question quick quit quiz quote rabbit raccoon race rack radar radio rail rain raise rally ramp ranch random range rapid rare rate rather raven raw razor ready real reason rebel rebuild recall receive recipe record recycle reduce reflect reform refuse region regret regular reject relax release relief rely remain remember remind remove render renew rent reopen repair repeat replace report require rescue resemble resist resource response result retire retreat return reunion reveal review reward rhythm rib ribbon rice rich ride ridge rifle right rigid ring riot ripple risk ritual rival river road roast robot robust rocket romance roof rookie room rose rotate rough round route royal rubber rude rug rule run runway rural sad saddle sadness safe sail salad salmon salon salt salute same sample sand satisfy satoshi sauce sausage save say scale scan scare scatter scene scheme school science scissors scorpion scout scrap screen script scrub sea search season seat second secret section security seed seek segment select sell seminar senior sense sentence series service session settle setup seven shadow shaft shallow share shed shell sheriff shield shift shine ship shiver shock shoe shoot shop short shoulder shove shrimp shrug shuffle shy sibling sick side siege sight sign silent silk silly silver similar simple since sing siren sister situate six size skate sketch ski skill skin skirt skull slab slam sleep slender slice slide slight slim slogan slot slow slush small smart smile smoke smooth snack snake snap sniff snow soap soccer social sock soda soft solar soldier solid solution solve someone song soon sorry sort soul sound soup source south space spare spatial spawn speak special speed spell spend sphere spice spider spike spin spirit split spoil sponsor spoon sport spot spray spread spring spy square squeeze squirrel stable stadium staff stage stairs stamp stand start state stay steak steel stem step stereo stick still sting stock stomach stone stool story stove strategy street strike strong struggle student stuff stumble style subject submit subway success such sudden suffer sugar suggest suit summer sun sunny sunset super supply supreme sure surface surge surprise surround survey suspect sustain swallow swamp swap swarm swear sweet swift swim swing switch sword symbol symptom syrup system table tackle tag tail talent talk tank tape target task taste tattoo taxi teach team tell ten tenant tennis tent term test text thank that theme then theory there they thing this thought three thrive throw thumb thunder ticket tide tiger tilt timber time tiny tip tired tissue title toast tobacco today toddler toe together toilet token tomato tomorrow tone tongue tonight tool tooth top topic topple torch tornado tortoise toss total tourist toward tower town toy track trade traffic tragic train transfer trap trash travel tray treat tree trend trial tribe trick trigger trim trip trophy trouble truck true truly trumpet trust truth try tube tuition tumble tuna tunnel turkey turn turtle twelve twenty twice twin twist two type typical ugly umbrella unable unaware uncle uncover under undo unfair unfold unhappy uniform unique unit universe unknown unlock until unusual unveil update upgrade uphold upon upper upset urban urge usage use used useful useless usual utility vacant vacuum vague valid valley valve van vanish vapor various vast vault vehicle velvet vendor venture venue verb verify version very vessel veteran viable vibrant vicious victory video view village vintage violin virtual virus visa visit visual vital vivid vocal voice void volcano volume vote voyage wage wagon wait walk wall walnut want warfare warm warrior wash wasp waste water wave way wealth weapon wear weasel weather web wedding weekend weird welcome west wet whale what wheat wheel when where whip whisper wide width wife wild will win window wine wing wink winner winter wire wisdom wise wish witness wolf woman wonder wood wool word work world worry worth wrap wreck wrestle wrist write wrong yard year yellow you young youth zebra zero zone zoo pybitcointools-1.1.42/bitcoin/main.py000066400000000000000000000412221301474610700176110ustar00rootroot00000000000000#!/usr/bin/python from .py2specials import * from .py3specials import * import binascii import hashlib import re import sys import os import base64 import time import random import hmac from bitcoin.ripemd import * # Elliptic curve parameters (secp256k1) P = 2**256 - 2**32 - 977 N = 115792089237316195423570985008687907852837564279074904382605163141518161494337 A = 0 B = 7 Gx = 55066263022277343669578718895168534326250603453777594175500187360389116729240 Gy = 32670510020758816978083085130507043184471273380659243275938904335757337482424 G = (Gx, Gy) def change_curve(p, n, a, b, gx, gy): global P, N, A, B, Gx, Gy, G P, N, A, B, Gx, Gy = p, n, a, b, gx, gy G = (Gx, Gy) def getG(): return G # Extended Euclidean Algorithm def inv(a, n): if a == 0: return 0 lm, hm = 1, 0 low, high = a % n, n while low > 1: r = high//low nm, new = hm-lm*r, high-low*r lm, low, hm, high = nm, new, lm, low return lm % n # JSON access (for pybtctool convenience) def access(obj, prop): if isinstance(obj, dict): if prop in obj: return obj[prop] elif '.' in prop: return obj[float(prop)] else: return obj[int(prop)] else: return obj[int(prop)] def multiaccess(obj, prop): return [access(o, prop) for o in obj] def slice(obj, start=0, end=2**200): return obj[int(start):int(end)] def count(obj): return len(obj) _sum = sum def sum(obj): return _sum(obj) def isinf(p): return p[0] == 0 and p[1] == 0 def to_jacobian(p): o = (p[0], p[1], 1) return o def jacobian_double(p): if not p[1]: return (0, 0, 0) ysq = (p[1] ** 2) % P S = (4 * p[0] * ysq) % P M = (3 * p[0] ** 2 + A * p[2] ** 4) % P nx = (M**2 - 2 * S) % P ny = (M * (S - nx) - 8 * ysq ** 2) % P nz = (2 * p[1] * p[2]) % P return (nx, ny, nz) def jacobian_add(p, q): if not p[1]: return q if not q[1]: return p U1 = (p[0] * q[2] ** 2) % P U2 = (q[0] * p[2] ** 2) % P S1 = (p[1] * q[2] ** 3) % P S2 = (q[1] * p[2] ** 3) % P if U1 == U2: if S1 != S2: return (0, 0, 1) return jacobian_double(p) H = U2 - U1 R = S2 - S1 H2 = (H * H) % P H3 = (H * H2) % P U1H2 = (U1 * H2) % P nx = (R ** 2 - H3 - 2 * U1H2) % P ny = (R * (U1H2 - nx) - S1 * H3) % P nz = (H * p[2] * q[2]) % P return (nx, ny, nz) def from_jacobian(p): z = inv(p[2], P) return ((p[0] * z**2) % P, (p[1] * z**3) % P) def jacobian_multiply(a, n): if a[1] == 0 or n == 0: return (0, 0, 1) if n == 1: return a if n < 0 or n >= N: return jacobian_multiply(a, n % N) if (n % 2) == 0: return jacobian_double(jacobian_multiply(a, n//2)) if (n % 2) == 1: return jacobian_add(jacobian_double(jacobian_multiply(a, n//2)), a) def fast_multiply(a, n): return from_jacobian(jacobian_multiply(to_jacobian(a), n)) def fast_add(a, b): return from_jacobian(jacobian_add(to_jacobian(a), to_jacobian(b))) # Functions for handling pubkey and privkey formats def get_pubkey_format(pub): if is_python2: two = '\x02' three = '\x03' four = '\x04' else: two = 2 three = 3 four = 4 if isinstance(pub, (tuple, list)): return 'decimal' elif len(pub) == 65 and pub[0] == four: return 'bin' elif len(pub) == 130 and pub[0:2] == '04': return 'hex' elif len(pub) == 33 and pub[0] in [two, three]: return 'bin_compressed' elif len(pub) == 66 and pub[0:2] in ['02', '03']: return 'hex_compressed' elif len(pub) == 64: return 'bin_electrum' elif len(pub) == 128: return 'hex_electrum' else: raise Exception("Pubkey not in recognized format") def encode_pubkey(pub, formt): if not isinstance(pub, (tuple, list)): pub = decode_pubkey(pub) if formt == 'decimal': return pub elif formt == 'bin': return b'\x04' + encode(pub[0], 256, 32) + encode(pub[1], 256, 32) elif formt == 'bin_compressed': return from_int_to_byte(2+(pub[1] % 2)) + encode(pub[0], 256, 32) elif formt == 'hex': return '04' + encode(pub[0], 16, 64) + encode(pub[1], 16, 64) elif formt == 'hex_compressed': return '0'+str(2+(pub[1] % 2)) + encode(pub[0], 16, 64) elif formt == 'bin_electrum': return encode(pub[0], 256, 32) + encode(pub[1], 256, 32) elif formt == 'hex_electrum': return encode(pub[0], 16, 64) + encode(pub[1], 16, 64) else: raise Exception("Invalid format!") def decode_pubkey(pub, formt=None): if not formt: formt = get_pubkey_format(pub) if formt == 'decimal': return pub elif formt == 'bin': return (decode(pub[1:33], 256), decode(pub[33:65], 256)) elif formt == 'bin_compressed': x = decode(pub[1:33], 256) beta = pow(int(x*x*x+A*x+B), int((P+1)//4), int(P)) y = (P-beta) if ((beta + from_byte_to_int(pub[0])) % 2) else beta return (x, y) elif formt == 'hex': return (decode(pub[2:66], 16), decode(pub[66:130], 16)) elif formt == 'hex_compressed': return decode_pubkey(safe_from_hex(pub), 'bin_compressed') elif formt == 'bin_electrum': return (decode(pub[:32], 256), decode(pub[32:64], 256)) elif formt == 'hex_electrum': return (decode(pub[:64], 16), decode(pub[64:128], 16)) else: raise Exception("Invalid format!") def get_privkey_format(priv): if isinstance(priv, int_types): return 'decimal' elif len(priv) == 32: return 'bin' elif len(priv) == 33: return 'bin_compressed' elif len(priv) == 64: return 'hex' elif len(priv) == 66: return 'hex_compressed' else: bin_p = b58check_to_bin(priv) if len(bin_p) == 32: return 'wif' elif len(bin_p) == 33: return 'wif_compressed' else: raise Exception("WIF does not represent privkey") def encode_privkey(priv, formt, vbyte=0): if not isinstance(priv, int_types): return encode_privkey(decode_privkey(priv), formt, vbyte) if formt == 'decimal': return priv elif formt == 'bin': return encode(priv, 256, 32) elif formt == 'bin_compressed': return encode(priv, 256, 32)+b'\x01' elif formt == 'hex': return encode(priv, 16, 64) elif formt == 'hex_compressed': return encode(priv, 16, 64)+'01' elif formt == 'wif': return bin_to_b58check(encode(priv, 256, 32), 128+int(vbyte)) elif formt == 'wif_compressed': return bin_to_b58check(encode(priv, 256, 32)+b'\x01', 128+int(vbyte)) else: raise Exception("Invalid format!") def decode_privkey(priv,formt=None): if not formt: formt = get_privkey_format(priv) if formt == 'decimal': return priv elif formt == 'bin': return decode(priv, 256) elif formt == 'bin_compressed': return decode(priv[:32], 256) elif formt == 'hex': return decode(priv, 16) elif formt == 'hex_compressed': return decode(priv[:64], 16) elif formt == 'wif': return decode(b58check_to_bin(priv),256) elif formt == 'wif_compressed': return decode(b58check_to_bin(priv)[:32],256) else: raise Exception("WIF does not represent privkey") def add_pubkeys(p1, p2): f1, f2 = get_pubkey_format(p1), get_pubkey_format(p2) return encode_pubkey(fast_add(decode_pubkey(p1, f1), decode_pubkey(p2, f2)), f1) def add_privkeys(p1, p2): f1, f2 = get_privkey_format(p1), get_privkey_format(p2) return encode_privkey((decode_privkey(p1, f1) + decode_privkey(p2, f2)) % N, f1) def mul_privkeys(p1, p2): f1, f2 = get_privkey_format(p1), get_privkey_format(p2) return encode_privkey((decode_privkey(p1, f1) * decode_privkey(p2, f2)) % N, f1) def multiply(pubkey, privkey): f1, f2 = get_pubkey_format(pubkey), get_privkey_format(privkey) pubkey, privkey = decode_pubkey(pubkey, f1), decode_privkey(privkey, f2) # http://safecurves.cr.yp.to/twist.html if not isinf(pubkey) and (pubkey[0]**3+B-pubkey[1]*pubkey[1]) % P != 0: raise Exception("Point not on curve") return encode_pubkey(fast_multiply(pubkey, privkey), f1) def divide(pubkey, privkey): factor = inv(decode_privkey(privkey), N) return multiply(pubkey, factor) def compress(pubkey): f = get_pubkey_format(pubkey) if 'compressed' in f: return pubkey elif f == 'bin': return encode_pubkey(decode_pubkey(pubkey, f), 'bin_compressed') elif f == 'hex' or f == 'decimal': return encode_pubkey(decode_pubkey(pubkey, f), 'hex_compressed') def decompress(pubkey): f = get_pubkey_format(pubkey) if 'compressed' not in f: return pubkey elif f == 'bin_compressed': return encode_pubkey(decode_pubkey(pubkey, f), 'bin') elif f == 'hex_compressed' or f == 'decimal': return encode_pubkey(decode_pubkey(pubkey, f), 'hex') def privkey_to_pubkey(privkey): f = get_privkey_format(privkey) privkey = decode_privkey(privkey, f) if privkey >= N: raise Exception("Invalid privkey") if f in ['bin', 'bin_compressed', 'hex', 'hex_compressed', 'decimal']: return encode_pubkey(fast_multiply(G, privkey), f) else: return encode_pubkey(fast_multiply(G, privkey), f.replace('wif', 'hex')) privtopub = privkey_to_pubkey def privkey_to_address(priv, magicbyte=0): return pubkey_to_address(privkey_to_pubkey(priv), magicbyte) privtoaddr = privkey_to_address def neg_pubkey(pubkey): f = get_pubkey_format(pubkey) pubkey = decode_pubkey(pubkey, f) return encode_pubkey((pubkey[0], (P-pubkey[1]) % P), f) def neg_privkey(privkey): f = get_privkey_format(privkey) privkey = decode_privkey(privkey, f) return encode_privkey((N - privkey) % N, f) def subtract_pubkeys(p1, p2): f1, f2 = get_pubkey_format(p1), get_pubkey_format(p2) k2 = decode_pubkey(p2, f2) return encode_pubkey(fast_add(decode_pubkey(p1, f1), (k2[0], (P - k2[1]) % P)), f1) def subtract_privkeys(p1, p2): f1, f2 = get_privkey_format(p1), get_privkey_format(p2) k2 = decode_privkey(p2, f2) return encode_privkey((decode_privkey(p1, f1) - k2) % N, f1) # Hashes def bin_hash160(string): intermed = hashlib.sha256(string).digest() digest = '' try: digest = hashlib.new('ripemd160', intermed).digest() except: digest = RIPEMD160(intermed).digest() return digest def hash160(string): return safe_hexlify(bin_hash160(string)) def bin_sha256(string): binary_data = string if isinstance(string, bytes) else bytes(string, 'utf-8') return hashlib.sha256(binary_data).digest() def sha256(string): return bytes_to_hex_string(bin_sha256(string)) def bin_ripemd160(string): try: digest = hashlib.new('ripemd160', string).digest() except: digest = RIPEMD160(string).digest() return digest def ripemd160(string): return safe_hexlify(bin_ripemd160(string)) def bin_dbl_sha256(s): bytes_to_hash = from_string_to_bytes(s) return hashlib.sha256(hashlib.sha256(bytes_to_hash).digest()).digest() def dbl_sha256(string): return safe_hexlify(bin_dbl_sha256(string)) def bin_slowsha(string): string = from_string_to_bytes(string) orig_input = string for i in range(100000): string = hashlib.sha256(string + orig_input).digest() return string def slowsha(string): return safe_hexlify(bin_slowsha(string)) def hash_to_int(x): if len(x) in [40, 64]: return decode(x, 16) return decode(x, 256) def num_to_var_int(x): x = int(x) if x < 253: return from_int_to_byte(x) elif x < 65536: return from_int_to_byte(253)+encode(x, 256, 2)[::-1] elif x < 4294967296: return from_int_to_byte(254) + encode(x, 256, 4)[::-1] else: return from_int_to_byte(255) + encode(x, 256, 8)[::-1] # WTF, Electrum? def electrum_sig_hash(message): padded = b"\x18Bitcoin Signed Message:\n" + num_to_var_int(len(message)) + from_string_to_bytes(message) return bin_dbl_sha256(padded) def random_key(): # Gotta be secure after that java.SecureRandom fiasco... entropy = random_string(32) \ + str(random.randrange(2**256)) \ + str(int(time.time() * 1000000)) return sha256(entropy) def random_electrum_seed(): entropy = os.urandom(32) \ + str(random.randrange(2**256)) \ + str(int(time.time() * 1000000)) return sha256(entropy)[:32] # Encodings def b58check_to_bin(inp): leadingzbytes = len(re.match('^1*', inp).group(0)) data = b'\x00' * leadingzbytes + changebase(inp, 58, 256) assert bin_dbl_sha256(data[:-4])[:4] == data[-4:] return data[1:-4] def get_version_byte(inp): leadingzbytes = len(re.match('^1*', inp).group(0)) data = b'\x00' * leadingzbytes + changebase(inp, 58, 256) assert bin_dbl_sha256(data[:-4])[:4] == data[-4:] return ord(data[0]) def hex_to_b58check(inp, magicbyte=0): return bin_to_b58check(binascii.unhexlify(inp), magicbyte) def b58check_to_hex(inp): return safe_hexlify(b58check_to_bin(inp)) def pubkey_to_address(pubkey, magicbyte=0): if isinstance(pubkey, (list, tuple)): pubkey = encode_pubkey(pubkey, 'bin') if len(pubkey) in [66, 130]: return bin_to_b58check( bin_hash160(binascii.unhexlify(pubkey)), magicbyte) return bin_to_b58check(bin_hash160(pubkey), magicbyte) pubtoaddr = pubkey_to_address def is_privkey(priv): try: get_privkey_format(priv) return True except: return False def is_pubkey(pubkey): try: get_pubkey_format(pubkey) return True except: return False def is_address(addr): ADDR_RE = re.compile("^[123mn][a-km-zA-HJ-NP-Z0-9]{26,33}$") return bool(ADDR_RE.match(addr)) # EDCSA def encode_sig(v, r, s): vb, rb, sb = from_int_to_byte(v), encode(r, 256), encode(s, 256) result = base64.b64encode(vb+b'\x00'*(32-len(rb))+rb+b'\x00'*(32-len(sb))+sb) return result if is_python2 else str(result, 'utf-8') def decode_sig(sig): bytez = base64.b64decode(sig) return from_byte_to_int(bytez[0]), decode(bytez[1:33], 256), decode(bytez[33:], 256) # https://tools.ietf.org/html/rfc6979#section-3.2 def deterministic_generate_k(msghash, priv): v = b'\x01' * 32 k = b'\x00' * 32 priv = encode_privkey(priv, 'bin') msghash = encode(hash_to_int(msghash), 256, 32) k = hmac.new(k, v+b'\x00'+priv+msghash, hashlib.sha256).digest() v = hmac.new(k, v, hashlib.sha256).digest() k = hmac.new(k, v+b'\x01'+priv+msghash, hashlib.sha256).digest() v = hmac.new(k, v, hashlib.sha256).digest() return decode(hmac.new(k, v, hashlib.sha256).digest(), 256) def ecdsa_raw_sign(msghash, priv): z = hash_to_int(msghash) k = deterministic_generate_k(msghash, priv) r, y = fast_multiply(G, k) s = inv(k, N) * (z + r*decode_privkey(priv)) % N v, r, s = 27+((y % 2) ^ (0 if s * 2 < N else 1)), r, s if s * 2 < N else N - s if 'compressed' in get_privkey_format(priv): v += 4 return v, r, s def ecdsa_sign(msg, priv): v, r, s = ecdsa_raw_sign(electrum_sig_hash(msg), priv) sig = encode_sig(v, r, s) assert ecdsa_verify(msg, sig, privtopub(priv)), "Bad Sig!\t %s\nv = %d\n,r = %d\ns = %d" % (sig, v, r, s) return sig def ecdsa_raw_verify(msghash, vrs, pub): v, r, s = vrs if not (27 <= v <= 34): return False w = inv(s, N) z = hash_to_int(msghash) u1, u2 = z*w % N, r*w % N x, y = fast_add(fast_multiply(G, u1), fast_multiply(decode_pubkey(pub), u2)) return bool(r == x and (r % N) and (s % N)) # For BitcoinCore, (msg = addr or msg = "") be default def ecdsa_verify_addr(msg, sig, addr): assert is_address(addr) Q = ecdsa_recover(msg, sig) magic = get_version_byte(addr) return (addr == pubtoaddr(Q, int(magic))) or (addr == pubtoaddr(compress(Q), int(magic))) def ecdsa_verify(msg, sig, pub): if is_address(pub): return ecdsa_verify_addr(msg, sig, pub) return ecdsa_raw_verify(electrum_sig_hash(msg), decode_sig(sig), pub) def ecdsa_raw_recover(msghash, vrs): v, r, s = vrs if not (27 <= v <= 34): raise ValueError("%d must in range 27-31" % v) x = r xcubedaxb = (x*x*x+A*x+B) % P beta = pow(xcubedaxb, (P+1)//4, P) y = beta if v % 2 ^ beta % 2 else (P - beta) # If xcubedaxb is not a quadratic residue, then r cannot be the x coord # for a point on the curve, and so the sig is invalid if (xcubedaxb - y*y) % P != 0 or not (r % N) or not (s % N): return False z = hash_to_int(msghash) Gz = jacobian_multiply((Gx, Gy, 1), (N - z) % N) XY = jacobian_multiply((x, y, 1), s) Qr = jacobian_add(Gz, XY) Q = jacobian_multiply(Qr, inv(r, N)) Q = from_jacobian(Q) # if ecdsa_raw_verify(msghash, vrs, Q): return Q # return False def ecdsa_recover(msg, sig): v,r,s = decode_sig(sig) Q = ecdsa_raw_recover(electrum_sig_hash(msg), (v,r,s)) return encode_pubkey(Q, 'hex_compressed') if v >= 31 else encode_pubkey(Q, 'hex') pybitcointools-1.1.42/bitcoin/mnemonic.py000066400000000000000000000100751301474610700204740ustar00rootroot00000000000000import hashlib import os.path import binascii import random from bisect import bisect_left wordlist_english=list(open(os.path.join(os.path.dirname(os.path.realpath(__file__)),'english.txt'),'r')) def eint_to_bytes(entint,entbits): a=hex(entint)[2:].rstrip('L').zfill(32) print(a) return binascii.unhexlify(a) def mnemonic_int_to_words(mint,mint_num_words,wordlist=wordlist_english): backwords=[wordlist[(mint >> (11*x)) & 0x7FF].strip() for x in range(mint_num_words)] return backwords[::-1] def entropy_cs(entbytes): entropy_size=8*len(entbytes) checksum_size=entropy_size//32 hd=hashlib.sha256(entbytes).hexdigest() csint=int(hd,16) >> (256-checksum_size) return csint,checksum_size def entropy_to_words(entbytes,wordlist=wordlist_english): if(len(entbytes) < 4 or len(entbytes) % 4 != 0): raise ValueError("The size of the entropy must be a multiple of 4 bytes (multiple of 32 bits)") entropy_size=8*len(entbytes) csint,checksum_size = entropy_cs(entbytes) entint=int(binascii.hexlify(entbytes),16) mint=(entint << checksum_size) | csint mint_num_words=(entropy_size+checksum_size)//11 return mnemonic_int_to_words(mint,mint_num_words,wordlist) def words_bisect(word,wordlist=wordlist_english): lo=bisect_left(wordlist,word) hi=len(wordlist)-bisect_left(wordlist[:lo:-1],word) return lo,hi def words_split(wordstr,wordlist=wordlist_english): def popword(wordstr,wordlist): for fwl in range(1,9): w=wordstr[:fwl].strip() lo,hi=words_bisect(w,wordlist) if(hi-lo == 1): return w,wordstr[fwl:].lstrip() wordlist=wordlist[lo:hi] raise Exception("Wordstr %s not found in list" %(w)) words=[] tail=wordstr while(len(tail)): head,tail=popword(tail,wordlist) words.append(head) return words def words_to_mnemonic_int(words,wordlist=wordlist_english): if(isinstance(words,str)): words=words_split(words,wordlist) return sum([wordlist.index(w) << (11*x) for x,w in enumerate(words[::-1])]) def words_verify(words,wordlist=wordlist_english): if(isinstance(words,str)): words=words_split(words,wordlist) mint = words_to_mnemonic_int(words,wordlist) mint_bits=len(words)*11 cs_bits=mint_bits//32 entropy_bits=mint_bits-cs_bits eint=mint >> cs_bits csint=mint & ((1 << cs_bits)-1) ebytes=_eint_to_bytes(eint,entropy_bits) return csint == entropy_cs(ebytes) def mnemonic_to_seed(mnemonic_phrase,passphrase=b''): try: from hashlib import pbkdf2_hmac def pbkdf2_hmac_sha256(password,salt,iters=2048): return pbkdf2_hmac(hash_name='sha512',password=password,salt=salt,iterations=iters) except: try: from Crypto.Protocol.KDF import PBKDF2 from Crypto.Hash import SHA512,HMAC def pbkdf2_hmac_sha256(password,salt,iters=2048): return PBKDF2(password=password,salt=salt,dkLen=64,count=iters,prf=lambda p,s: HMAC.new(p,s,SHA512).digest()) except: try: from pbkdf2 import PBKDF2 import hmac def pbkdf2_hmac_sha256(password,salt,iters=2048): return PBKDF2(password,salt, iterations=iters, macmodule=hmac, digestmodule=hashlib.sha512).read(64) except: raise RuntimeError("No implementation of pbkdf2 was found!") return pbkdf2_hmac_sha256(password=mnemonic_phrase,salt=b'mnemonic'+passphrase) def words_mine(prefix,entbits,satisfunction,wordlist=wordlist_english,randombits=random.getrandbits): prefix_bits=len(prefix)*11 mine_bits=entbits-prefix_bits pint=words_to_mnemonic_int(prefix,wordlist) pint<<=mine_bits dint=randombits(mine_bits) count=0 while(not satisfunction(entropy_to_words(eint_to_bytes(pint+dint,entbits)))): dint=randombits(mine_bits) if((count & 0xFFFF) == 0): print("Searched %f percent of the space" % (float(count)/float(1 << mine_bits))) return entropy_to_words(eint_to_bytes(pint+dint,entbits)) if __name__=="__main__": import json testvectors=json.load(open('vectors.json','r')) passed=True for v in testvectors['english']: ebytes=binascii.unhexlify(v[0]) w=' '.join(entropy_to_words(ebytes)) seed=mnemonic_to_seed(w,passphrase='TREZOR') passed = passed and w==v[1] passed = passed and binascii.hexlify(seed)==v[2] print("Tests %s." % ("Passed" if passed else "Failed")) pybitcointools-1.1.42/bitcoin/py2specials.py000066400000000000000000000052211301474610700211220ustar00rootroot00000000000000import sys, re import binascii import os import hashlib if sys.version_info.major == 2: string_types = (str, unicode) string_or_bytes_types = string_types int_types = (int, float, long) # Base switching code_strings = { 2: '01', 10: '0123456789', 16: '0123456789abcdef', 32: 'abcdefghijklmnopqrstuvwxyz234567', 58: '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz', 256: ''.join([chr(x) for x in range(256)]) } def bin_dbl_sha256(s): bytes_to_hash = from_string_to_bytes(s) return hashlib.sha256(hashlib.sha256(bytes_to_hash).digest()).digest() def lpad(msg, symbol, length): if len(msg) >= length: return msg return symbol * (length - len(msg)) + msg def get_code_string(base): if base in code_strings: return code_strings[base] else: raise ValueError("Invalid base!") def changebase(string, frm, to, minlen=0): if frm == to: return lpad(string, get_code_string(frm)[0], minlen) return encode(decode(string, frm), to, minlen) def bin_to_b58check(inp, magicbyte=0): if magicbyte == 0: inp = '\x00' + inp while magicbyte > 0: inp = chr(int(magicbyte % 256)) + inp magicbyte //= 256 leadingzbytes = len(re.match('^\x00*', inp).group(0)) checksum = bin_dbl_sha256(inp)[:4] return '1' * leadingzbytes + changebase(inp+checksum, 256, 58) def bytes_to_hex_string(b): return b.encode('hex') def safe_from_hex(s): return s.decode('hex') def from_int_representation_to_bytes(a): return str(a) def from_int_to_byte(a): return chr(a) def from_byte_to_int(a): return ord(a) def from_bytes_to_string(s): return s def from_string_to_bytes(a): return a def safe_hexlify(a): return binascii.hexlify(a) def encode(val, base, minlen=0): base, minlen = int(base), int(minlen) code_string = get_code_string(base) result = "" while val > 0: result = code_string[val % base] + result val //= base return code_string[0] * max(minlen - len(result), 0) + result def decode(string, base): base = int(base) code_string = get_code_string(base) result = 0 if base == 16: string = string.lower() while len(string) > 0: result *= base result += code_string.find(string[0]) string = string[1:] return result def random_string(x): return os.urandom(x) pybitcointools-1.1.42/bitcoin/py3specials.py000066400000000000000000000067551301474610700211400ustar00rootroot00000000000000import sys, os import binascii import hashlib if sys.version_info.major == 3: string_types = (str) string_or_bytes_types = (str, bytes) int_types = (int, float) # Base switching code_strings = { 2: '01', 10: '0123456789', 16: '0123456789abcdef', 32: 'abcdefghijklmnopqrstuvwxyz234567', 58: '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz', 256: ''.join([chr(x) for x in range(256)]) } def bin_dbl_sha256(s): bytes_to_hash = from_string_to_bytes(s) return hashlib.sha256(hashlib.sha256(bytes_to_hash).digest()).digest() def lpad(msg, symbol, length): if len(msg) >= length: return msg return symbol * (length - len(msg)) + msg def get_code_string(base): if base in code_strings: return code_strings[base] else: raise ValueError("Invalid base!") def changebase(string, frm, to, minlen=0): if frm == to: return lpad(string, get_code_string(frm)[0], minlen) return encode(decode(string, frm), to, minlen) def bin_to_b58check(inp, magicbyte=0): if magicbyte == 0: inp = from_int_to_byte(0) + inp while magicbyte > 0: inp = from_int_to_byte(magicbyte % 256) + inp magicbyte //= 256 leadingzbytes = 0 for x in inp: if x != 0: break leadingzbytes += 1 checksum = bin_dbl_sha256(inp)[:4] return '1' * leadingzbytes + changebase(inp+checksum, 256, 58) def bytes_to_hex_string(b): if isinstance(b, str): return b return ''.join('{:02x}'.format(y) for y in b) def safe_from_hex(s): return bytes.fromhex(s) def from_int_representation_to_bytes(a): return bytes(str(a), 'utf-8') def from_int_to_byte(a): return bytes([a]) def from_byte_to_int(a): return a def from_string_to_bytes(a): return a if isinstance(a, bytes) else bytes(a, 'utf-8') def safe_hexlify(a): return str(binascii.hexlify(a), 'utf-8') def encode(val, base, minlen=0): base, minlen = int(base), int(minlen) code_string = get_code_string(base) result_bytes = bytes() while val > 0: curcode = code_string[val % base] result_bytes = bytes([ord(curcode)]) + result_bytes val //= base pad_size = minlen - len(result_bytes) padding_element = b'\x00' if base == 256 else b'1' \ if base == 58 else b'0' if (pad_size > 0): result_bytes = padding_element*pad_size + result_bytes result_string = ''.join([chr(y) for y in result_bytes]) result = result_bytes if base == 256 else result_string return result def decode(string, base): if base == 256 and isinstance(string, str): string = bytes(bytearray.fromhex(string)) base = int(base) code_string = get_code_string(base) result = 0 if base == 256: def extract(d, cs): return d else: def extract(d, cs): return cs.find(d if isinstance(d, str) else chr(d)) if base == 16: string = string.lower() while len(string) > 0: result *= base result += extract(string[0], code_string) string = string[1:] return result def random_string(x): return str(os.urandom(x)) pybitcointools-1.1.42/bitcoin/ripemd.py000066400000000000000000000354671301474610700201630ustar00rootroot00000000000000## ripemd.py - pure Python implementation of the RIPEMD-160 algorithm. ## Bjorn Edstrom 16 december 2007. ## ## Copyrights ## ========== ## ## This code is a derived from an implementation by Markus Friedl which is ## subject to the following license. This Python implementation is not ## subject to any other license. ## ##/* ## * Copyright (c) 2001 Markus Friedl. All rights reserved. ## * ## * Redistribution and use in source and binary forms, with or without ## * modification, are permitted provided that the following conditions ## * are met: ## * 1. Redistributions of source code must retain the above copyright ## * notice, this list of conditions and the following disclaimer. ## * 2. Redistributions in binary form must reproduce the above copyright ## * notice, this list of conditions and the following disclaimer in the ## * documentation and/or other materials provided with the distribution. ## * ## * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ## * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ## * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ## * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ## * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ## * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ## * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ## * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ## * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ## * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ## */ ##/* ## * Preneel, Bosselaers, Dobbertin, "The Cryptographic Hash Function RIPEMD-160", ## * RSA Laboratories, CryptoBytes, Volume 3, Number 2, Autumn 1997, ## * ftp://ftp.rsasecurity.com/pub/cryptobytes/crypto3n2.pdf ## */ try: import psyco psyco.full() except ImportError: pass import sys is_python2 = sys.version_info.major == 2 #block_size = 1 digest_size = 20 digestsize = 20 try: range = xrange except: pass class RIPEMD160: """Return a new RIPEMD160 object. An optional string argument may be provided; if present, this string will be automatically hashed.""" def __init__(self, arg=None): self.ctx = RMDContext() if arg: self.update(arg) self.dig = None def update(self, arg): """update(arg)""" RMD160Update(self.ctx, arg, len(arg)) self.dig = None def digest(self): """digest()""" if self.dig: return self.dig ctx = self.ctx.copy() self.dig = RMD160Final(self.ctx) self.ctx = ctx return self.dig def hexdigest(self): """hexdigest()""" dig = self.digest() hex_digest = '' for d in dig: if (is_python2): hex_digest += '%02x' % ord(d) else: hex_digest += '%02x' % d return hex_digest def copy(self): """copy()""" import copy return copy.deepcopy(self) def new(arg=None): """Return a new RIPEMD160 object. An optional string argument may be provided; if present, this string will be automatically hashed.""" return RIPEMD160(arg) # # Private. # class RMDContext: def __init__(self): self.state = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0] # uint32 self.count = 0 # uint64 self.buffer = [0]*64 # uchar def copy(self): ctx = RMDContext() ctx.state = self.state[:] ctx.count = self.count ctx.buffer = self.buffer[:] return ctx K0 = 0x00000000 K1 = 0x5A827999 K2 = 0x6ED9EBA1 K3 = 0x8F1BBCDC K4 = 0xA953FD4E KK0 = 0x50A28BE6 KK1 = 0x5C4DD124 KK2 = 0x6D703EF3 KK3 = 0x7A6D76E9 KK4 = 0x00000000 def ROL(n, x): return ((x << n) & 0xffffffff) | (x >> (32 - n)) def F0(x, y, z): return x ^ y ^ z def F1(x, y, z): return (x & y) | (((~x) % 0x100000000) & z) def F2(x, y, z): return (x | ((~y) % 0x100000000)) ^ z def F3(x, y, z): return (x & z) | (((~z) % 0x100000000) & y) def F4(x, y, z): return x ^ (y | ((~z) % 0x100000000)) def R(a, b, c, d, e, Fj, Kj, sj, rj, X): a = ROL(sj, (a + Fj(b, c, d) + X[rj] + Kj) % 0x100000000) + e c = ROL(10, c) return a % 0x100000000, c PADDING = [0x80] + [0]*63 import sys import struct def RMD160Transform(state, block): #uint32 state[5], uchar block[64] x = [0]*16 if sys.byteorder == 'little': if is_python2: x = struct.unpack('<16L', ''.join([chr(x) for x in block[0:64]])) else: x = struct.unpack('<16L', bytes(block[0:64])) else: raise "Error!!" a = state[0] b = state[1] c = state[2] d = state[3] e = state[4] #/* Round 1 */ a, c = R(a, b, c, d, e, F0, K0, 11, 0, x); e, b = R(e, a, b, c, d, F0, K0, 14, 1, x); d, a = R(d, e, a, b, c, F0, K0, 15, 2, x); c, e = R(c, d, e, a, b, F0, K0, 12, 3, x); b, d = R(b, c, d, e, a, F0, K0, 5, 4, x); a, c = R(a, b, c, d, e, F0, K0, 8, 5, x); e, b = R(e, a, b, c, d, F0, K0, 7, 6, x); d, a = R(d, e, a, b, c, F0, K0, 9, 7, x); c, e = R(c, d, e, a, b, F0, K0, 11, 8, x); b, d = R(b, c, d, e, a, F0, K0, 13, 9, x); a, c = R(a, b, c, d, e, F0, K0, 14, 10, x); e, b = R(e, a, b, c, d, F0, K0, 15, 11, x); d, a = R(d, e, a, b, c, F0, K0, 6, 12, x); c, e = R(c, d, e, a, b, F0, K0, 7, 13, x); b, d = R(b, c, d, e, a, F0, K0, 9, 14, x); a, c = R(a, b, c, d, e, F0, K0, 8, 15, x); #/* #15 */ #/* Round 2 */ e, b = R(e, a, b, c, d, F1, K1, 7, 7, x); d, a = R(d, e, a, b, c, F1, K1, 6, 4, x); c, e = R(c, d, e, a, b, F1, K1, 8, 13, x); b, d = R(b, c, d, e, a, F1, K1, 13, 1, x); a, c = R(a, b, c, d, e, F1, K1, 11, 10, x); e, b = R(e, a, b, c, d, F1, K1, 9, 6, x); d, a = R(d, e, a, b, c, F1, K1, 7, 15, x); c, e = R(c, d, e, a, b, F1, K1, 15, 3, x); b, d = R(b, c, d, e, a, F1, K1, 7, 12, x); a, c = R(a, b, c, d, e, F1, K1, 12, 0, x); e, b = R(e, a, b, c, d, F1, K1, 15, 9, x); d, a = R(d, e, a, b, c, F1, K1, 9, 5, x); c, e = R(c, d, e, a, b, F1, K1, 11, 2, x); b, d = R(b, c, d, e, a, F1, K1, 7, 14, x); a, c = R(a, b, c, d, e, F1, K1, 13, 11, x); e, b = R(e, a, b, c, d, F1, K1, 12, 8, x); #/* #31 */ #/* Round 3 */ d, a = R(d, e, a, b, c, F2, K2, 11, 3, x); c, e = R(c, d, e, a, b, F2, K2, 13, 10, x); b, d = R(b, c, d, e, a, F2, K2, 6, 14, x); a, c = R(a, b, c, d, e, F2, K2, 7, 4, x); e, b = R(e, a, b, c, d, F2, K2, 14, 9, x); d, a = R(d, e, a, b, c, F2, K2, 9, 15, x); c, e = R(c, d, e, a, b, F2, K2, 13, 8, x); b, d = R(b, c, d, e, a, F2, K2, 15, 1, x); a, c = R(a, b, c, d, e, F2, K2, 14, 2, x); e, b = R(e, a, b, c, d, F2, K2, 8, 7, x); d, a = R(d, e, a, b, c, F2, K2, 13, 0, x); c, e = R(c, d, e, a, b, F2, K2, 6, 6, x); b, d = R(b, c, d, e, a, F2, K2, 5, 13, x); a, c = R(a, b, c, d, e, F2, K2, 12, 11, x); e, b = R(e, a, b, c, d, F2, K2, 7, 5, x); d, a = R(d, e, a, b, c, F2, K2, 5, 12, x); #/* #47 */ #/* Round 4 */ c, e = R(c, d, e, a, b, F3, K3, 11, 1, x); b, d = R(b, c, d, e, a, F3, K3, 12, 9, x); a, c = R(a, b, c, d, e, F3, K3, 14, 11, x); e, b = R(e, a, b, c, d, F3, K3, 15, 10, x); d, a = R(d, e, a, b, c, F3, K3, 14, 0, x); c, e = R(c, d, e, a, b, F3, K3, 15, 8, x); b, d = R(b, c, d, e, a, F3, K3, 9, 12, x); a, c = R(a, b, c, d, e, F3, K3, 8, 4, x); e, b = R(e, a, b, c, d, F3, K3, 9, 13, x); d, a = R(d, e, a, b, c, F3, K3, 14, 3, x); c, e = R(c, d, e, a, b, F3, K3, 5, 7, x); b, d = R(b, c, d, e, a, F3, K3, 6, 15, x); a, c = R(a, b, c, d, e, F3, K3, 8, 14, x); e, b = R(e, a, b, c, d, F3, K3, 6, 5, x); d, a = R(d, e, a, b, c, F3, K3, 5, 6, x); c, e = R(c, d, e, a, b, F3, K3, 12, 2, x); #/* #63 */ #/* Round 5 */ b, d = R(b, c, d, e, a, F4, K4, 9, 4, x); a, c = R(a, b, c, d, e, F4, K4, 15, 0, x); e, b = R(e, a, b, c, d, F4, K4, 5, 5, x); d, a = R(d, e, a, b, c, F4, K4, 11, 9, x); c, e = R(c, d, e, a, b, F4, K4, 6, 7, x); b, d = R(b, c, d, e, a, F4, K4, 8, 12, x); a, c = R(a, b, c, d, e, F4, K4, 13, 2, x); e, b = R(e, a, b, c, d, F4, K4, 12, 10, x); d, a = R(d, e, a, b, c, F4, K4, 5, 14, x); c, e = R(c, d, e, a, b, F4, K4, 12, 1, x); b, d = R(b, c, d, e, a, F4, K4, 13, 3, x); a, c = R(a, b, c, d, e, F4, K4, 14, 8, x); e, b = R(e, a, b, c, d, F4, K4, 11, 11, x); d, a = R(d, e, a, b, c, F4, K4, 8, 6, x); c, e = R(c, d, e, a, b, F4, K4, 5, 15, x); b, d = R(b, c, d, e, a, F4, K4, 6, 13, x); #/* #79 */ aa = a; bb = b; cc = c; dd = d; ee = e; a = state[0] b = state[1] c = state[2] d = state[3] e = state[4] #/* Parallel round 1 */ a, c = R(a, b, c, d, e, F4, KK0, 8, 5, x) e, b = R(e, a, b, c, d, F4, KK0, 9, 14, x) d, a = R(d, e, a, b, c, F4, KK0, 9, 7, x) c, e = R(c, d, e, a, b, F4, KK0, 11, 0, x) b, d = R(b, c, d, e, a, F4, KK0, 13, 9, x) a, c = R(a, b, c, d, e, F4, KK0, 15, 2, x) e, b = R(e, a, b, c, d, F4, KK0, 15, 11, x) d, a = R(d, e, a, b, c, F4, KK0, 5, 4, x) c, e = R(c, d, e, a, b, F4, KK0, 7, 13, x) b, d = R(b, c, d, e, a, F4, KK0, 7, 6, x) a, c = R(a, b, c, d, e, F4, KK0, 8, 15, x) e, b = R(e, a, b, c, d, F4, KK0, 11, 8, x) d, a = R(d, e, a, b, c, F4, KK0, 14, 1, x) c, e = R(c, d, e, a, b, F4, KK0, 14, 10, x) b, d = R(b, c, d, e, a, F4, KK0, 12, 3, x) a, c = R(a, b, c, d, e, F4, KK0, 6, 12, x) #/* #15 */ #/* Parallel round 2 */ e, b = R(e, a, b, c, d, F3, KK1, 9, 6, x) d, a = R(d, e, a, b, c, F3, KK1, 13, 11, x) c, e = R(c, d, e, a, b, F3, KK1, 15, 3, x) b, d = R(b, c, d, e, a, F3, KK1, 7, 7, x) a, c = R(a, b, c, d, e, F3, KK1, 12, 0, x) e, b = R(e, a, b, c, d, F3, KK1, 8, 13, x) d, a = R(d, e, a, b, c, F3, KK1, 9, 5, x) c, e = R(c, d, e, a, b, F3, KK1, 11, 10, x) b, d = R(b, c, d, e, a, F3, KK1, 7, 14, x) a, c = R(a, b, c, d, e, F3, KK1, 7, 15, x) e, b = R(e, a, b, c, d, F3, KK1, 12, 8, x) d, a = R(d, e, a, b, c, F3, KK1, 7, 12, x) c, e = R(c, d, e, a, b, F3, KK1, 6, 4, x) b, d = R(b, c, d, e, a, F3, KK1, 15, 9, x) a, c = R(a, b, c, d, e, F3, KK1, 13, 1, x) e, b = R(e, a, b, c, d, F3, KK1, 11, 2, x) #/* #31 */ #/* Parallel round 3 */ d, a = R(d, e, a, b, c, F2, KK2, 9, 15, x) c, e = R(c, d, e, a, b, F2, KK2, 7, 5, x) b, d = R(b, c, d, e, a, F2, KK2, 15, 1, x) a, c = R(a, b, c, d, e, F2, KK2, 11, 3, x) e, b = R(e, a, b, c, d, F2, KK2, 8, 7, x) d, a = R(d, e, a, b, c, F2, KK2, 6, 14, x) c, e = R(c, d, e, a, b, F2, KK2, 6, 6, x) b, d = R(b, c, d, e, a, F2, KK2, 14, 9, x) a, c = R(a, b, c, d, e, F2, KK2, 12, 11, x) e, b = R(e, a, b, c, d, F2, KK2, 13, 8, x) d, a = R(d, e, a, b, c, F2, KK2, 5, 12, x) c, e = R(c, d, e, a, b, F2, KK2, 14, 2, x) b, d = R(b, c, d, e, a, F2, KK2, 13, 10, x) a, c = R(a, b, c, d, e, F2, KK2, 13, 0, x) e, b = R(e, a, b, c, d, F2, KK2, 7, 4, x) d, a = R(d, e, a, b, c, F2, KK2, 5, 13, x) #/* #47 */ #/* Parallel round 4 */ c, e = R(c, d, e, a, b, F1, KK3, 15, 8, x) b, d = R(b, c, d, e, a, F1, KK3, 5, 6, x) a, c = R(a, b, c, d, e, F1, KK3, 8, 4, x) e, b = R(e, a, b, c, d, F1, KK3, 11, 1, x) d, a = R(d, e, a, b, c, F1, KK3, 14, 3, x) c, e = R(c, d, e, a, b, F1, KK3, 14, 11, x) b, d = R(b, c, d, e, a, F1, KK3, 6, 15, x) a, c = R(a, b, c, d, e, F1, KK3, 14, 0, x) e, b = R(e, a, b, c, d, F1, KK3, 6, 5, x) d, a = R(d, e, a, b, c, F1, KK3, 9, 12, x) c, e = R(c, d, e, a, b, F1, KK3, 12, 2, x) b, d = R(b, c, d, e, a, F1, KK3, 9, 13, x) a, c = R(a, b, c, d, e, F1, KK3, 12, 9, x) e, b = R(e, a, b, c, d, F1, KK3, 5, 7, x) d, a = R(d, e, a, b, c, F1, KK3, 15, 10, x) c, e = R(c, d, e, a, b, F1, KK3, 8, 14, x) #/* #63 */ #/* Parallel round 5 */ b, d = R(b, c, d, e, a, F0, KK4, 8, 12, x) a, c = R(a, b, c, d, e, F0, KK4, 5, 15, x) e, b = R(e, a, b, c, d, F0, KK4, 12, 10, x) d, a = R(d, e, a, b, c, F0, KK4, 9, 4, x) c, e = R(c, d, e, a, b, F0, KK4, 12, 1, x) b, d = R(b, c, d, e, a, F0, KK4, 5, 5, x) a, c = R(a, b, c, d, e, F0, KK4, 14, 8, x) e, b = R(e, a, b, c, d, F0, KK4, 6, 7, x) d, a = R(d, e, a, b, c, F0, KK4, 8, 6, x) c, e = R(c, d, e, a, b, F0, KK4, 13, 2, x) b, d = R(b, c, d, e, a, F0, KK4, 6, 13, x) a, c = R(a, b, c, d, e, F0, KK4, 5, 14, x) e, b = R(e, a, b, c, d, F0, KK4, 15, 0, x) d, a = R(d, e, a, b, c, F0, KK4, 13, 3, x) c, e = R(c, d, e, a, b, F0, KK4, 11, 9, x) b, d = R(b, c, d, e, a, F0, KK4, 11, 11, x) #/* #79 */ t = (state[1] + cc + d) % 0x100000000; state[1] = (state[2] + dd + e) % 0x100000000; state[2] = (state[3] + ee + a) % 0x100000000; state[3] = (state[4] + aa + b) % 0x100000000; state[4] = (state[0] + bb + c) % 0x100000000; state[0] = t % 0x100000000; pass def RMD160Update(ctx, inp, inplen): if type(inp) == str: inp = [ord(i)&0xff for i in inp] have = int((ctx.count // 8) % 64) inplen = int(inplen) need = 64 - have ctx.count += 8 * inplen off = 0 if inplen >= need: if have: for i in range(need): ctx.buffer[have+i] = inp[i] RMD160Transform(ctx.state, ctx.buffer) off = need have = 0 while off + 64 <= inplen: RMD160Transform(ctx.state, inp[off:]) #<--- off += 64 if off < inplen: # memcpy(ctx->buffer + have, input+off, len-off); for i in range(inplen - off): ctx.buffer[have+i] = inp[off+i] def RMD160Final(ctx): size = struct.pack(" 73: return False if (sig[0] != 0x30): return False if (sig[1] != len(sig)-3): return False rlen = sig[3] if (5+rlen >= len(sig)): return False slen = sig[5+rlen] if (rlen + slen + 7 != len(sig)): return False if (sig[2] != 0x02): return False if (rlen == 0): return False if (sig[4] & 0x80): return False if (rlen > 1 and (sig[4] == 0x00) and not (sig[5] & 0x80)): return False if (sig[4+rlen] != 0x02): return False if (slen == 0): return False if (sig[rlen+6] & 0x80): return False if (slen > 1 and (sig[6+rlen] == 0x00) and not (sig[7+rlen] & 0x80)): return False return True def txhash(tx, hashcode=None): if isinstance(tx, str) and re.match('^[0-9a-fA-F]*$', tx): tx = changebase(tx, 16, 256) if hashcode: return dbl_sha256(from_string_to_bytes(tx) + encode(int(hashcode), 256, 4)[::-1]) else: return safe_hexlify(bin_dbl_sha256(tx)[::-1]) def bin_txhash(tx, hashcode=None): return binascii.unhexlify(txhash(tx, hashcode)) def ecdsa_tx_sign(tx, priv, hashcode=SIGHASH_ALL): rawsig = ecdsa_raw_sign(bin_txhash(tx, hashcode), priv) return der_encode_sig(*rawsig)+encode(hashcode, 16, 2) def ecdsa_tx_verify(tx, sig, pub, hashcode=SIGHASH_ALL): return ecdsa_raw_verify(bin_txhash(tx, hashcode), der_decode_sig(sig), pub) def ecdsa_tx_recover(tx, sig, hashcode=SIGHASH_ALL): z = bin_txhash(tx, hashcode) _, r, s = der_decode_sig(sig) left = ecdsa_raw_recover(z, (0, r, s)) right = ecdsa_raw_recover(z, (1, r, s)) return (encode_pubkey(left, 'hex'), encode_pubkey(right, 'hex')) # Scripts def mk_pubkey_script(addr): # Keep the auxiliary functions around for altcoins' sake return '76a914' + b58check_to_hex(addr) + '88ac' def mk_scripthash_script(addr): return 'a914' + b58check_to_hex(addr) + '87' # Address representation to output script def address_to_script(addr): if addr[0] == '3' or addr[0] == '2': return mk_scripthash_script(addr) else: return mk_pubkey_script(addr) # Output script to address representation def script_to_address(script, vbyte=0): if re.match('^[0-9a-fA-F]*$', script): script = binascii.unhexlify(script) if script[:3] == b'\x76\xa9\x14' and script[-2:] == b'\x88\xac' and len(script) == 25: return bin_to_b58check(script[3:-2], vbyte) # pubkey hash addresses else: if vbyte in [111, 196]: # Testnet scripthash_byte = 196 elif vbyte == 0: # Mainnet scripthash_byte = 5 else: scripthash_byte = vbyte # BIP0016 scripthash addresses return bin_to_b58check(script[2:-1], scripthash_byte) def p2sh_scriptaddr(script, magicbyte=5): if re.match('^[0-9a-fA-F]*$', script): script = binascii.unhexlify(script) return hex_to_b58check(hash160(script), magicbyte) scriptaddr = p2sh_scriptaddr def deserialize_script(script): if isinstance(script, str) and re.match('^[0-9a-fA-F]*$', script): return json_changebase(deserialize_script(binascii.unhexlify(script)), lambda x: safe_hexlify(x)) out, pos = [], 0 while pos < len(script): code = from_byte_to_int(script[pos]) if code == 0: out.append(None) pos += 1 elif code <= 75: out.append(script[pos+1:pos+1+code]) pos += 1 + code elif code <= 78: szsz = pow(2, code - 76) sz = decode(script[pos+szsz: pos:-1], 256) out.append(script[pos + 1 + szsz:pos + 1 + szsz + sz]) pos += 1 + szsz + sz elif code <= 96: out.append(code - 80) pos += 1 else: out.append(code) pos += 1 return out def serialize_script_unit(unit): if isinstance(unit, int): if unit < 16: return from_int_to_byte(unit + 80) else: return from_int_to_byte(unit) elif unit is None: return b'\x00' else: if len(unit) <= 75: return from_int_to_byte(len(unit))+unit elif len(unit) < 256: return from_int_to_byte(76)+from_int_to_byte(len(unit))+unit elif len(unit) < 65536: return from_int_to_byte(77)+encode(len(unit), 256, 2)[::-1]+unit else: return from_int_to_byte(78)+encode(len(unit), 256, 4)[::-1]+unit if is_python2: def serialize_script(script): if json_is_base(script, 16): return binascii.hexlify(serialize_script(json_changebase(script, lambda x: binascii.unhexlify(x)))) return ''.join(map(serialize_script_unit, script)) else: def serialize_script(script): if json_is_base(script, 16): return safe_hexlify(serialize_script(json_changebase(script, lambda x: binascii.unhexlify(x)))) result = bytes() for b in map(serialize_script_unit, script): result += b if isinstance(b, bytes) else bytes(b, 'utf-8') return result def mk_multisig_script(*args): # [pubs],k or pub1,pub2...pub[n],k if isinstance(args[0], list): pubs, k = args[0], int(args[1]) else: pubs = list(filter(lambda x: len(str(x)) >= 32, args)) k = int(args[len(pubs)]) return serialize_script([k]+pubs+[len(pubs)]+[0xae]) # Signing and verifying def verify_tx_input(tx, i, script, sig, pub): if re.match('^[0-9a-fA-F]*$', tx): tx = binascii.unhexlify(tx) if re.match('^[0-9a-fA-F]*$', script): script = binascii.unhexlify(script) if not re.match('^[0-9a-fA-F]*$', sig): sig = safe_hexlify(sig) hashcode = decode(sig[-2:], 16) modtx = signature_form(tx, int(i), script, hashcode) return ecdsa_tx_verify(modtx, sig, pub, hashcode) def sign(tx, i, priv, hashcode=SIGHASH_ALL): i = int(i) if (not is_python2 and isinstance(re, bytes)) or not re.match('^[0-9a-fA-F]*$', tx): return binascii.unhexlify(sign(safe_hexlify(tx), i, priv)) if len(priv) <= 33: priv = safe_hexlify(priv) pub = privkey_to_pubkey(priv) address = pubkey_to_address(pub) signing_tx = signature_form(tx, i, mk_pubkey_script(address), hashcode) sig = ecdsa_tx_sign(signing_tx, priv, hashcode) txobj = deserialize(tx) txobj["ins"][i]["script"] = serialize_script([sig, pub]) return serialize(txobj) def signall(tx, priv): # if priv is a dictionary, assume format is # { 'txinhash:txinidx' : privkey } if isinstance(priv, dict): for e, i in enumerate(deserialize(tx)["ins"]): k = priv["%s:%d" % (i["outpoint"]["hash"], i["outpoint"]["index"])] tx = sign(tx, e, k) else: for i in range(len(deserialize(tx)["ins"])): tx = sign(tx, i, priv) return tx def multisign(tx, i, script, pk, hashcode=SIGHASH_ALL): if re.match('^[0-9a-fA-F]*$', tx): tx = binascii.unhexlify(tx) if re.match('^[0-9a-fA-F]*$', script): script = binascii.unhexlify(script) modtx = signature_form(tx, i, script, hashcode) return ecdsa_tx_sign(modtx, pk, hashcode) def apply_multisignatures(*args): # tx,i,script,sigs OR tx,i,script,sig1,sig2...,sig[n] tx, i, script = args[0], int(args[1]), args[2] sigs = args[3] if isinstance(args[3], list) else list(args[3:]) if isinstance(script, str) and re.match('^[0-9a-fA-F]*$', script): script = binascii.unhexlify(script) sigs = [binascii.unhexlify(x) if x[:2] == '30' else x for x in sigs] if isinstance(tx, str) and re.match('^[0-9a-fA-F]*$', tx): return safe_hexlify(apply_multisignatures(binascii.unhexlify(tx), i, script, sigs)) # Not pushing empty elements on the top of the stack if passing no # script (in case of bare multisig inputs there is no script) script_blob = [] if script.__len__() == 0 else [script] txobj = deserialize(tx) txobj["ins"][i]["script"] = serialize_script([None]+sigs+script_blob) return serialize(txobj) def is_inp(arg): return len(arg) > 64 or "output" in arg or "outpoint" in arg def mktx(*args): # [in0, in1...],[out0, out1...] or in0, in1 ... out0 out1 ... ins, outs = [], [] for arg in args: if isinstance(arg, list): for a in arg: (ins if is_inp(a) else outs).append(a) else: (ins if is_inp(arg) else outs).append(arg) txobj = {"locktime": 0, "version": 1, "ins": [], "outs": []} for i in ins: if isinstance(i, dict) and "outpoint" in i: txobj["ins"].append(i) else: if isinstance(i, dict) and "output" in i: i = i["output"] txobj["ins"].append({ "outpoint": {"hash": i[:64], "index": int(i[65:])}, "script": "", "sequence": 4294967295 }) for o in outs: if isinstance(o, string_or_bytes_types): addr = o[:o.find(':')] val = int(o[o.find(':')+1:]) o = {} if re.match('^[0-9a-fA-F]*$', addr): o["script"] = addr else: o["address"] = addr o["value"] = val outobj = {} if "address" in o: outobj["script"] = address_to_script(o["address"]) elif "script" in o: outobj["script"] = o["script"] else: raise Exception("Could not find 'address' or 'script' in output.") outobj["value"] = o["value"] txobj["outs"].append(outobj) return serialize(txobj) def select(unspent, value): value = int(value) high = [u for u in unspent if u["value"] >= value] high.sort(key=lambda u: u["value"]) low = [u for u in unspent if u["value"] < value] low.sort(key=lambda u: -u["value"]) if len(high): return [high[0]] i, tv = 0, 0 while tv < value and i < len(low): tv += low[i]["value"] i += 1 if tv < value: raise Exception("Not enough funds") return low[:i] # Only takes inputs of the form { "output": blah, "value": foo } def mksend(*args): argz, change, fee = args[:-2], args[-2], int(args[-1]) ins, outs = [], [] for arg in argz: if isinstance(arg, list): for a in arg: (ins if is_inp(a) else outs).append(a) else: (ins if is_inp(arg) else outs).append(arg) isum = sum([i["value"] for i in ins]) osum, outputs2 = 0, [] for o in outs: if isinstance(o, string_types): o2 = { "address": o[:o.find(':')], "value": int(o[o.find(':')+1:]) } else: o2 = o outputs2.append(o2) osum += o2["value"] if isum < osum+fee: raise Exception("Not enough money") elif isum > osum+fee+5430: outputs2 += [{"address": change, "value": isum-osum-fee}] return mktx(ins, outputs2) pybitcointools-1.1.42/pybtctool000066400000000000000000000020251301474610700166240ustar00rootroot00000000000000#!/usr/bin/python import sys, json, re from bitcoin import * if len(sys.argv) == 1: print "pybtctool ..." else: cmdargs, preargs, kwargs = [], [], {} i = 2 # Process first arg tag if sys.argv[1] == '-s': preargs.extend(re.findall(r'\S\S*', sys.stdin.read())) elif sys.argv[1] == '-B': preargs.extend([sys.stdin.read()]) elif sys.argv[1] == '-b': preargs.extend([sys.stdin.read()[:-1]]) elif sys.argv[1] == '-j': preargs.extend([json.loads(sys.stdin.read())]) elif sys.argv[1] == '-J': preargs.extend(json.loads(sys.stdin.read())) else: i = 1 while i < len(sys.argv): if sys.argv[i][:2] == '--': kwargs[sys.argv[i][2:]] = sys.argv[i+1] i += 2 else: cmdargs.append(sys.argv[i]) i += 1 cmd = cmdargs[0] args = preargs + cmdargs[1:] o = vars()[cmd](*args, **kwargs) if isinstance(o, (list, dict)): print json.dumps(o) else: print o pybitcointools-1.1.42/setup.py000066400000000000000000000007741301474610700164050ustar00rootroot00000000000000#!/usr/bin/env python try: from setuptools import setup except ImportError: from distutils.core import setup setup(name='bitcoin', version='1.1.42', description='Python Bitcoin Tools', author='Vitalik Buterin', author_email='vbuterin@gmail.com', url='http://github.com/vbuterin/pybitcointools', packages=['bitcoin'], scripts=['pybtctool'], include_package_data=True, data_files=[("", ["LICENSE"]), ("bitcoin", ["bitcoin/english.txt"])], ) pybitcointools-1.1.42/test.py000066400000000000000000000553521301474610700162260ustar00rootroot00000000000000import json import os import random import unittest import bitcoin.ripemd as ripemd from bitcoin import * class TestECCArithmetic(unittest.TestCase): @classmethod def setUpClass(cls): print('Starting ECC arithmetic tests') def test_all(self): for i in range(8): print('### Round %d' % (i+1)) x, y = random.randrange(2**256), random.randrange(2**256) self.assertEqual( multiply(multiply(G, x), y)[0], multiply(multiply(G, y), x)[0] ) self.assertEqual( add_pubkeys(multiply(G, x), multiply(G, y))[0], multiply(G, add_privkeys(x, y))[0] ) hx, hy = encode(x % N, 16, 64), encode(y % N, 16, 64) self.assertEqual( multiply(multiply(G, hx), hy)[0], multiply(multiply(G, hy), hx)[0] ) self.assertEqual( add_pubkeys(multiply(G, hx), multiply(G, hy))[0], multiply(G, add_privkeys(hx, hy))[0] ) self.assertEqual( b58check_to_hex(pubtoaddr(privtopub(x))), b58check_to_hex(pubtoaddr(multiply(G, hx), 23)) ) p = privtopub(sha256(str(x))) if i % 2 == 1: p = changebase(p, 16, 256) self.assertEqual(p, decompress(compress(p))) self.assertEqual(G[0], multiply(divide(G, x), x)[0]) class TestBases(unittest.TestCase): @classmethod def setUpClass(cls): print('Starting base change tests') def test_all(self): data = [ [10, '65535', 16, 'ffff'], [16, 'deadbeef', 10, '3735928559'], [10, '0', 16, ''], [256, b'34567', 10, '219919234615'], [10, '444', 16, '1bc'], [256, b'\x03\x04\x05\x06\x07', 10, '12952339975'], [16, '3132333435', 256, b'12345'] ] for prebase, preval, postbase, postval in data: self.assertEqual(changebase(preval, prebase, postbase), postval) for i in range(100): x = random.randrange(1, 9999999999999999) frm = random.choice([2, 10, 16, 58, 256]) to = random.choice([2, 10, 16, 58, 256]) self.assertEqual(decode(encode(x, to), to), x) self.assertEqual(changebase(encode(x, frm), frm, to), encode(x, to)) self.assertEqual(decode(changebase(encode(x, frm), frm, to), to), x) class TestElectrumWalletInternalConsistency(unittest.TestCase): @classmethod def setUpClass(cls): print('Starting Electrum wallet internal consistency tests') def test_all(self): for i in range(3): seed = sha256(str(random.randrange(2**40)))[:32] mpk = electrum_mpk(seed) for i in range(5): pk = electrum_privkey(seed, i) pub = electrum_pubkey((mpk, seed)[i % 2], i) pub2 = privtopub(pk) self.assertEqual( pub, pub2, 'Does not match! Details:\nseed: %s\nmpk: %s\npriv: %s\npub: %s\npub2: %s' % ( seed, mpk, pk, pub, pub2 ) ) class TestRawSignRecover(unittest.TestCase): @classmethod def setUpClass(cls): print("Basic signing and recovery tests") def test_all(self): for i in range(20): k = sha256(str(i)) s = ecdsa_raw_sign('35' * 32, k) self.assertEqual( ecdsa_raw_recover('35' * 32, s), decode_pubkey(privtopub(k)) ) class TestTransactionSignVerify(unittest.TestCase): @classmethod def setUpClass(cls): print("Transaction-style signing and verification tests") def test_all(self): alphabet = "1234567890qwertyuiopasdfghjklzxcvbnm" for i in range(10): msg = ''.join([random.choice(alphabet) for i in range(random.randrange(20, 200))]) priv = sha256(str(random.randrange(2**256))) pub = privtopub(priv) sig = ecdsa_tx_sign(msg, priv) self.assertTrue( ecdsa_tx_verify(msg, sig, pub), "Verification error" ) self.assertIn( pub, ecdsa_tx_recover(msg, sig), "Recovery failed" ) class TestSerialize(unittest.TestCase): def test_serialize(self): tx = '0100000001239f932c780e517015842f3b02ff765fba97f9f63f9f1bc718b686a56ed9c73400000000fd5d010047304402200c40fa58d3f6d5537a343cf9c8d13bc7470baf1d13867e0de3e535cd6b4354c802200f2b48f67494835b060d0b2ff85657d2ba2d9ea4e697888c8cb580e8658183a801483045022056f488c59849a4259e7cef70fe5d6d53a4bd1c59a195b0577bd81cb76044beca022100a735b319fa66af7b178fc719b93f905961ef4d4446deca8757a90de2106dd98a014cc95241046c7d87fd72caeab48e937f2feca9e9a4bd77f0eff4ebb2dbbb9855c023e334e188d32aaec4632ea4cbc575c037d8101aec73d029236e7b1c2380f3e4ad7edced41046fd41cddf3bbda33a240b417a825cc46555949917c7ccf64c59f42fd8dfe95f34fae3b09ed279c8c5b3530510e8cca6230791102eef9961d895e8db54af0563c410488d618b988efd2511fc1f9c03f11c210808852b07fe46128c1a6b1155aa22cdf4b6802460ba593db2d11c7e6cbe19cedef76b7bcabd05d26fd97f4c5a59b225053aeffffffff0310270000000000001976a914a89733100315c37d228a529853af341a9d290a4588ac409c00000000000017a9142b56f9a4009d9ff99b8f97bea4455cd71135f5dd87409c00000000000017a9142b56f9a4009d9ff99b8f97bea4455cd71135f5dd8700000000' self.assertEqual( serialize(deserialize(tx)), tx, "Serialize roundtrip failed" ) def test_serialize_script(self): script = '47304402200c40fa58d3f6d5537a343cf9c8d13bc7470baf1d13867e0de3e535cd6b4354c802200f2b48f67494835b060d0b2ff85657d2ba2d9ea4e697888c8cb580e8658183a801483045022056f488c59849a4259e7cef70fe5d6d53a4bd1c59a195b0577bd81cb76044beca022100a735b319fa66af7b178fc719b93f905961ef4d4446deca8757a90de2106dd98a014cc95241046c7d87fd72caeab48e937f2feca9e9a4bd77f0eff4ebb2dbbb9855c023e334e188d32aaec4632ea4cbc575c037d8101aec73d029236e7b1c2380f3e4ad7edced41046fd41cddf3bbda33a240b417a825cc46555949917c7ccf64c59f42fd8dfe95f34fae3b09ed279c8c5b3530510e8cca6230791102eef9961d895e8db54af0563c410488d618b988efd2511fc1f9c03f11c210808852b07fe46128c1a6b1155aa22cdf4b6802460ba593db2d11c7e6cbe19cedef76b7bcabd05d26fd97f4c5a59b225053ae' self.assertEqual( serialize_script(deserialize_script(script)), script, "Script serialize roundtrip failed" ) class TestTransaction(unittest.TestCase): @classmethod def setUpClass(cls): print("Attempting transaction creation") # FIXME: I don't know how to write this as a unit test. # What should be asserted? def test_all(self): privs = [sha256(str(random.randrange(2**256))) for x in range(4)] pubs = [privtopub(priv) for priv in privs] addresses = [pubtoaddr(pub) for pub in pubs] mscript = mk_multisig_script(pubs[1:], 2, 3) msigaddr = p2sh_scriptaddr(mscript) tx = mktx(['01'*32+':1', '23'*32+':2'], [msigaddr+':20202', addresses[0]+':40404']) tx1 = sign(tx, 1, privs[0]) sig1 = multisign(tx, 0, mscript, privs[1]) self.assertTrue(verify_tx_input(tx1, 0, mscript, sig1, pubs[1]), "Verification Error") sig3 = multisign(tx, 0, mscript, privs[3]) self.assertTrue(verify_tx_input(tx1, 0, mscript, sig3, pubs[3]), "Verification Error") tx2 = apply_multisignatures(tx1, 0, mscript, [sig1, sig3]) print("Outputting transaction: ", tx2) # https://github.com/vbuterin/pybitcointools/issues/71 def test_multisig(self): script = mk_multisig_script(["0254236f7d1124fc07600ad3eec5ac47393bf963fbf0608bcce255e685580d16d9", "03560cad89031c412ad8619398bd43b3d673cb5bdcdac1afc46449382c6a8e0b2b"], 2) self.assertEqual(p2sh_scriptaddr(script), "33byJBaS5N45RHFcatTSt9ZjiGb6nK4iV3") self.assertEqual(p2sh_scriptaddr(script, 0x05), "33byJBaS5N45RHFcatTSt9ZjiGb6nK4iV3") self.assertEqual(p2sh_scriptaddr(script, 5), "33byJBaS5N45RHFcatTSt9ZjiGb6nK4iV3") self.assertEqual(p2sh_scriptaddr(script, 0xc4), "2MuABMvWTgpZRd4tAG25KW6YzvcoGVZDZYP") self.assertEqual(p2sh_scriptaddr(script, 196), "2MuABMvWTgpZRd4tAG25KW6YzvcoGVZDZYP") class TestDeterministicGenerate(unittest.TestCase): @classmethod def setUpClass(cls): print("Beginning RFC6979 deterministic signing tests") def test_all(self): # Created with python-ecdsa 0.9 # Code to make your own vectors: # class gen: # def order(self): return 115792089237316195423570985008687907852837564279074904382605163141518161494337 # dummy = gen() # for i in range(10): ecdsa.rfc6979.generate_k(dummy, i, hashlib.sha256, hashlib.sha256(str(i)).digest()) test_vectors = [ 32783320859482229023646250050688645858316445811207841524283044428614360139869, 109592113955144883013243055602231029997040992035200230706187150761552110229971, 65765393578006003630736298397268097590176526363988568884298609868706232621488, 85563144787585457107933685459469453513056530050186673491900346620874099325918, 99829559501561741463404068005537785834525504175465914981205926165214632019533, 7755945018790142325513649272940177083855222863968691658328003977498047013576, 81516639518483202269820502976089105897400159721845694286620077204726637043798, 52824159213002398817852821148973968315579759063230697131029801896913602807019, 44033460667645047622273556650595158811264350043302911918907282441675680538675, 32396602643737403620316035551493791485834117358805817054817536312402837398361 ] for i, ti in enumerate(test_vectors): mine = deterministic_generate_k(bin_sha256(str(i)), encode(i, 256, 32)) self.assertEqual( ti, mine, "Test vector does not match. Details:\n%s\n%s" % ( ti, mine ) ) class TestBIP0032(unittest.TestCase): """See: https://en.bitcoin.it/wiki/BIP_0032""" @classmethod def setUpClass(cls): print("Beginning BIP0032 tests") def _full_derive(self, key, chain): if len(chain) == 0: return key elif chain[0] == 'pub': return self._full_derive(bip32_privtopub(key), chain[1:]) else: return self._full_derive(bip32_ckd(key, chain[0]), chain[1:]) def test_all(self): test_vectors = [ [[], 'xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi'], [['pub'], 'xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8'], [[2**31], 'xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7'], [[2**31, 1], 'xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs'], [[2**31, 1, 2**31 + 2], 'xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM'], [[2**31, 1, 2**31 + 2, 'pub', 2, 1000000000], 'xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy'] ] mk = bip32_master_key(safe_from_hex('000102030405060708090a0b0c0d0e0f')) for tv in test_vectors: left, right = self._full_derive(mk, tv[0]), tv[1] self.assertEqual( left, right, "Test vector does not match. Details: \n%s\n%s\n\%s" % ( tv[0], [x.encode('hex') if isinstance(x, str) else x for x in bip32_deserialize(left)], [x.encode('hex') if isinstance(x, str) else x for x in bip32_deserialize(right)], ) ) def test_all_testnet(self): test_vectors = [ [[], 'tprv8ZgxMBicQKsPeDgjzdC36fs6bMjGApWDNLR9erAXMs5skhMv36j9MV5ecvfavji5khqjWaWSFhN3YcCUUdiKH6isR4Pwy3U5y5egddBr16m'], [['pub'], 'tpubD6NzVbkrYhZ4XgiXtGrdW5XDAPFCL9h7we1vwNCpn8tGbBcgfVYjXyhWo4E1xkh56hjod1RhGjxbaTLV3X4FyWuejifB9jusQ46QzG87VKp'], [[2**31], 'tprv8bxNLu25VazNnppTCP4fyhyCvBHcYtzE3wr3cwYeL4HA7yf6TLGEUdS4QC1vLT63TkjRssqJe4CvGNEC8DzW5AoPUw56D1Ayg6HY4oy8QZ9'], [[2**31, 1], 'tprv8e8VYgZxtHsSdGrtvdxYaSrryZGiYviWzGWtDDKTGh5NMXAEB8gYSCLHpFCywNs5uqV7ghRjimALQJkRFZnUrLHpzi2pGkwqLtbubgWuQ8q'], [[2**31, 1, 2**31 + 2], 'tprv8gjmbDPpbAirVSezBEMuwSu1Ci9EpUJWKokZTYccSZSomNMLytWyLdtDNHRbucNaRJWWHANf9AzEdWVAqahfyRjVMKbNRhBmxAM8EJr7R15'], [[2**31, 1, 2**31 + 2, 'pub', 2, 1000000000], 'tpubDHNy3kAG39ThyiwwsgoKY4iRenXDRtce8qdCFJZXPMCJg5dsCUHayp84raLTpvyiNA9sXPob5rgqkKvkN8S7MMyXbnEhGJMW64Cf4vFAoaF'] ] mk = bip32_master_key(safe_from_hex('000102030405060708090a0b0c0d0e0f'), TESTNET_PRIVATE) for tv in test_vectors: left, right = self._full_derive(mk, tv[0]), tv[1] self.assertEqual( left, right, "Test vector does not match. Details:\n%s\n%s\n%s\n\%s" % ( left, tv[0], [x.encode('hex') if isinstance(x, str) else x for x in bip32_deserialize(left)], [x.encode('hex') if isinstance(x, str) else x for x in bip32_deserialize(right)], ) ) def test_extra(self): master = bip32_master_key(safe_from_hex("000102030405060708090a0b0c0d0e0f")) # m/0 assert bip32_ckd(master, "0") == "xprv9uHRZZhbkedL37eZEnyrNsQPFZYRAvjy5rt6M1nbEkLSo378x1CQQLo2xxBvREwiK6kqf7GRNvsNEchwibzXaV6i5GcsgyjBeRguXhKsi4R" assert bip32_privtopub(bip32_ckd(master, "0")) == "xpub68Gmy5EVb2BdFbj2LpWrk1M7obNuaPTpT5oh9QCCo5sRfqSHVYWex97WpDZzszdzHzxXDAzPLVSwybe4uPYkSk4G3gnrPqqkV9RyNzAcNJ1" # m/1 assert bip32_ckd(master, "1") == "xprv9uHRZZhbkedL4yTpidDvuVfrdUkTbhDHviERRBkbzbNDZeMjWzqzKAdxWhzftGDSxDmBdakjqHiZJbkwiaTEXJdjZAaAjMZEE3PMbMrPJih" assert bip32_privtopub(bip32_ckd(master, "1")) == "xpub68Gmy5EVb2BdHTYHpekwGdcbBWax19w9HwA2DaADYvuCSSgt4YAErxxSN1KWSnmyqkwRNbnTj3XiUBKmHeC8rTjLRPjSULcDKQQgfgJDppq" # m/0/0 assert bip32_ckd(bip32_ckd(master, "0"), "0") == "xprv9ww7sMFLzJMzur2oEQDB642fbsMS4q6JRraMVTrM9bTWBq7NDS8ZpmsKVB4YF3mZecqax1fjnsPF19xnsJNfRp4RSyexacULXMKowSACTRc" assert bip32_privtopub(bip32_ckd(bip32_ckd(master, "0"), "0")) == "xpub6AvUGrnEpfvJ8L7GLRkBTByQ9uBvUHp9o5VxHrFxhvzV4dSWkySpNaBoLR9FpbnwRmTa69yLHF3QfcaxbWT7gWdwws5k4dpmJvqpEuMWwnj" # m/0' assert bip32_ckd(master, 2**31) == "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7" assert bip32_privtopub(bip32_ckd(master, 2**31)) == "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw" # m/1' assert bip32_ckd(master, 2**31 + 1) == "xprv9uHRZZhk6KAJFszJGW6LoUFq92uL7FvkBhmYiMurCWPHLJZkX2aGvNdRUBNnJu7nv36WnwCN59uNy6sxLDZvvNSgFz3TCCcKo7iutQzpg78" assert bip32_privtopub(bip32_ckd(master, 2**31 + 1)) == "xpub68Gmy5EdvgibUN4mNXdMAcCZh4jpWiebYvh9WkKTkqvGD6tu4ZtXUAwuKSyF5DFZVmotf9UHFTGqSXo9qyDBSn47RkaN6Aedt9JbL7zcgSL" # m/1' assert bip32_ckd(master, 1 + 2**31) == "xprv9uHRZZhk6KAJFszJGW6LoUFq92uL7FvkBhmYiMurCWPHLJZkX2aGvNdRUBNnJu7nv36WnwCN59uNy6sxLDZvvNSgFz3TCCcKo7iutQzpg78" assert bip32_privtopub(bip32_ckd(master, 1 + 2**31)) == "xpub68Gmy5EdvgibUN4mNXdMAcCZh4jpWiebYvh9WkKTkqvGD6tu4ZtXUAwuKSyF5DFZVmotf9UHFTGqSXo9qyDBSn47RkaN6Aedt9JbL7zcgSL" # m/0'/0 assert bip32_ckd(bip32_ckd(master, 2**31), "0") == "xprv9wTYmMFdV23N21MM6dLNavSQV7Sj7meSPXx6AV5eTdqqGLjycVjb115Ec5LgRAXscPZgy5G4jQ9csyyZLN3PZLxoM1h3BoPuEJzsgeypdKj" assert bip32_privtopub(bip32_ckd(bip32_ckd(master, 2**31), "0")) == "xpub6ASuArnXKPbfEVRpCesNx4P939HDXENHkksgxsVG1yNp9958A33qYoPiTN9QrJmWFa2jNLdK84bWmyqTSPGtApP8P7nHUYwxHPhqmzUyeFG" # m/0'/0' assert bip32_ckd(bip32_ckd(master, 2**31), 2**31) == "xprv9wTYmMFmpgaLB5Hge4YtaGqCKpsYPTD9vXWSsmdZrNU3Y2i4WoBykm6ZteeCLCCZpGxdHQuqEhM6Gdo2X6CVrQiTw6AAneF9WSkA9ewaxtS" assert bip32_privtopub(bip32_ckd(bip32_ckd(master, 2**31), 2**31)) == "xpub6ASuArnff48dPZN9k65twQmvsri2nuw1HkS3gA3BQi12Qq3D4LWEJZR3jwCAr1NhsFMcQcBkmevmub6SLP37bNq91SEShXtEGUbX3GhNaGk" # m/44'/0'/0'/0/0 assert bip32_ckd(bip32_ckd(bip32_ckd(bip32_ckd(bip32_ckd(master, 44 + 2**31), 2**31), 2**31), 0), 0) == "xprvA4A9CuBXhdBtCaLxwrw64Jaran4n1rgzeS5mjH47Ds8V67uZS8tTkG8jV3BZi83QqYXPcN4v8EjK2Aof4YcEeqLt688mV57gF4j6QZWdP9U" assert bip32_privtopub(bip32_ckd(bip32_ckd(bip32_ckd(bip32_ckd(bip32_ckd(master, 44 + 2**31), 2**31), 2**31), 0), 0)) == "xpub6H9VcQiRXzkBR4RS3tU6RSXb8ouGRKQr1f1NXfTinCfTxvEhygCiJ4TDLHz1dyQ6d2Vz8Ne7eezkrViwaPo2ZMsNjVtFwvzsQXCDV6HJ3cV" class TestStartingAddressAndScriptGenerationConsistency(unittest.TestCase): @classmethod def setUpClass(cls): print("Starting address and script generation consistency tests") def test_all(self): for i in range(5): a = privtoaddr(random_key()) self.assertEqual(a, script_to_address(address_to_script(a))) self.assertEqual(a, script_to_address(address_to_script(a), 0)) self.assertEqual(a, script_to_address(address_to_script(a), 0x00)) b = privtoaddr(random_key(), 5) self.assertEqual(b, script_to_address(address_to_script(b))) self.assertEqual(b, script_to_address(address_to_script(b), 0)) self.assertEqual(b, script_to_address(address_to_script(b), 0x00)) self.assertEqual(b, script_to_address(address_to_script(b), 5)) self.assertEqual(b, script_to_address(address_to_script(b), 0x05)) for i in range(5): a = privtoaddr(random_key(), 0x6f) self.assertEqual(a, script_to_address(address_to_script(a), 111)) self.assertEqual(a, script_to_address(address_to_script(a), 0x6f)) b = privtoaddr(random_key(), 0xc4) self.assertEqual(b, script_to_address(address_to_script(b), 111)) self.assertEqual(b, script_to_address(address_to_script(b), 0x6f)) self.assertEqual(b, script_to_address(address_to_script(b), 196)) self.assertEqual(b, script_to_address(address_to_script(b), 0xc4)) class TestRipeMD160PythonBackup(unittest.TestCase): @classmethod def setUpClass(cls): print('Testing the pure python backup for ripemd160') def test_all(self): strvec = [ '', 'The quick brown fox jumps over the lazy dog', 'The quick brown fox jumps over the lazy cog', 'Nobody inspects the spammish repetition' ] target = [ '9c1185a5c5e9fc54612808977ee8f548b2258d31', '37f332f68db77bd9d7edd4969571ad671cf9dd3b', '132072df690933835eb8b6ad0b77e7b6f14acad7', 'cc4a5ce1b3df48aec5d22d1f16b894a0b894eccc' ] hash160target = [ 'b472a266d0bd89c13706a4132ccfb16f7c3b9fcb', '0e3397b4abc7a382b3ea2365883c3c7ca5f07600', '53e0dacac5249e46114f65cb1f30d156b14e0bdc', '1c9b7b48049a8f98699bca22a5856c5ef571cd68' ] for i, s in enumerate(strvec): digest = ripemd.RIPEMD160(s).digest() hash160digest = ripemd.RIPEMD160(bin_sha256(s)).digest() self.assertEqual(bytes_to_hex_string(digest), target[i]) self.assertEqual(bytes_to_hex_string(hash160digest), hash160target[i]) self.assertEqual(bytes_to_hex_string(bin_hash160(from_string_to_bytes(s))), hash160target[i]) self.assertEqual(hash160(from_string_to_bytes(s)), hash160target[i]) class TestScriptVsAddressOutputs(unittest.TestCase): @classmethod def setUpClass(cls): print('Testing script vs address outputs') def test_all(self): addr0 = '1Lqgj1ThNfwLgHMp5qJUerYsuUEm8vHmVG' script0 = '76a914d99f84267d1f90f3e870a5e9d2399918140be61d88ac' addr1 = '31oSGBBNrpCiENH3XMZpiP6GTC4tad4bMy' script1 = 'a9140136d001619faba572df2ef3d193a57ad29122d987' inputs = [{ 'output': 'cd6219ea108119dc62fce09698b649efde56eca7ce223a3315e8b431f6280ce7:0', 'value': 158000 }] outputs = [ [{'address': addr0, 'value': 1000}, {'address': addr1, 'value': 2000}], [{'script': script0, 'value': 1000}, {'address': addr1, 'value': 2000}], [{'address': addr0, 'value': 1000}, {'script': script1, 'value': 2000}], [{'script': script0, 'value': 1000}, {'script': script1, 'value': 2000}], [addr0 + ':1000', addr1 + ':2000'], [script0 + ':1000', addr1 + ':2000'], [addr0 + ':1000', script1 + ':2000'], [script0 + ':1000', script1 + ':2000'] ] for outs in outputs: tx_struct = deserialize(mktx(inputs, outs)) self.assertEqual(tx_struct['outs'], outputs[3]) class TestConversions(unittest.TestCase): @classmethod def setUpClass(cls): cls.privkey_hex = ( "e9873d79c6d87dc0fb6a5778633389f4453213303da61f20bd67fc233aa33262" ) cls.privkey_bin = ( b"\xe9\x87=y\xc6\xd8}\xc0\xfbjWxc3\x89\xf4E2\x130=\xa6\x1f \xbdg\xfc#:\xa32b" ) cls.pubkey_hex = ( "04588d202afcc1ee4ab5254c7847ec25b9a135bbda0f2bc69ee1a714749fd77dc9f88ff2a00d7e752d44cbe16e1ebcf0890b76ec7c78886109dee76ccfc8445424" ) cls.pubkey_bin = ( b"\x04X\x8d *\xfc\xc1\xeeJ\xb5%LxG\xec%\xb9\xa15\xbb\xda\x0f+\xc6\x9e\xe1\xa7\x14t\x9f\xd7}\xc9\xf8\x8f\xf2\xa0\r~u-D\xcb\xe1n\x1e\xbc\xf0\x89\x0bv\xec|x\x88a\t\xde\xe7l\xcf\xc8DT$" ) def test_privkey_to_pubkey(self): pubkey_hex = privkey_to_pubkey(self.privkey_hex) self.assertEqual(pubkey_hex, self.pubkey_hex) def test_changebase(self): self.assertEqual( self.pubkey_bin, changebase( self.pubkey_hex, 16, 256, minlen=len(self.pubkey_bin) ) ) self.assertEqual( self.pubkey_hex, changebase( self.pubkey_bin, 256, 16, minlen=len(self.pubkey_hex) ) ) self.assertEqual( self.privkey_bin, changebase( self.privkey_hex, 16, 256, minlen=len(self.privkey_bin) ) ) self.assertEqual( self.privkey_hex, changebase( self.privkey_bin, 256, 16, minlen=len(self.privkey_hex) ) ) if __name__ == '__main__': unittest.main() pybitcointools-1.1.42/test_stealth.py000066400000000000000000000102621301474610700177410ustar00rootroot00000000000000import bitcoin as bc import sys import unittest class TestStealth(unittest.TestCase): def setUp(self): if sys.getrecursionlimit() < 1000: sys.setrecursionlimit(1000) self.addr = 'vJmtjxSDxNPXL4RNapp9ARdqKz3uJyf1EDGjr1Fgqs9c8mYsVH82h8wvnA4i5rtJ57mr3kor1EVJrd4e5upACJd588xe52yXtzumxj' self.scan_pub = '025e58a31122b38c86abc119b9379fe247410aee87a533f9c07b189aef6c3c1f52' self.scan_priv = '3e49e7257cb31db997edb1cf8299af0f37e2663e2260e4b8033e49d39a6d02f2' self.spend_pub = '03616562c98e7d7b74be409a787cec3a912122f3fb331a9bee9b0b73ce7b9f50af' self.spend_priv = 'aa3db0cfb3edc94de4d10f873f8190843f2a17484f6021a95a7742302c744748' self.ephem_pub = '03403d306ec35238384c7e340393335f9bc9bb4a2e574eb4e419452c4ea19f14b0' self.ephem_priv = '9e63abaf8dcd5ea3919e6de0b6c544e00bf51bf92496113a01d6e369944dc091' self.shared_secret = 'a4047ee231f4121e3a99a3a3378542e34a384b865a9917789920e1f13ffd91c6' self.pay_pub = '02726112ad39cb6bf848b1b1ef30b88e35286bf99f746c2be575f96c0e02a9357c' self.pay_priv = '4e422fb1e5e1db6c1f6ab32a7706d368ceb385e7fab098e633c5c5949c3b97cd' self.testnet_addr = 'waPUuLLykSnY3itzf1AyrQZm42F7KyB7SR5zpfqmnzPXWhx9kXLzV3EcyqzDdpTwngiyCCMUqztS9S1d7XJs3JMt3MsHPDpBCudvx9' def test_address_encoding(self): sc_pub, sp_pub = bc.basic_stealth_address_to_pubkeys(self.addr) self.assertEqual(sc_pub, self.scan_pub) self.assertEqual(sp_pub, self.spend_pub) stealth_addr2 = bc.pubkeys_to_basic_stealth_address(sc_pub, sp_pub) self.assertEqual(stealth_addr2, self.addr) magic_byte_testnet = 43 sc_pub, sp_pub = bc.basic_stealth_address_to_pubkeys(self.testnet_addr) self.assertEqual(sc_pub, self.scan_pub) self.assertEqual(sp_pub, self.spend_pub) stealth_addr2 = bc.pubkeys_to_basic_stealth_address(sc_pub, sp_pub, magic_byte_testnet) self.assertEqual(stealth_addr2, self.testnet_addr) def test_shared_secret(self): sh_sec = bc.shared_secret_sender(self.scan_pub, self.ephem_priv) self.assertEqual(sh_sec, self.shared_secret) sh_sec2 = bc.shared_secret_receiver(self.ephem_pub, self.scan_priv) self.assertEqual(sh_sec2, self.shared_secret) def test_uncover_pay_keys(self): pub = bc.uncover_pay_pubkey_sender(self.scan_pub, self.spend_pub, self.ephem_priv) pub2 = bc.uncover_pay_pubkey_receiver(self.scan_priv, self.spend_pub, self.ephem_pub) self.assertEqual(pub, self.pay_pub) self.assertEqual(pub2, self.pay_pub) priv = bc.uncover_pay_privkey(self.scan_priv, self.spend_priv, self.ephem_pub) self.assertEqual(priv, self.pay_priv) def test_stealth_metadata_script(self): nonce = int('deadbeef', 16) script = bc.mk_stealth_metadata_script(self.ephem_pub, nonce) self.assertEqual(script[6:], 'deadbeef' + self.ephem_pub) eph_pub = bc.ephem_pubkey_from_tx_script(script) self.assertEqual(eph_pub, self.ephem_pub) def test_stealth_tx_outputs(self): nonce = int('deadbeef', 16) value = 10**8 outputs = bc.mk_stealth_tx_outputs(self.addr, value, self.ephem_priv, nonce) self.assertEqual(outputs[0]['value'], 0) self.assertEqual(outputs[0]['script'], '6a2606deadbeef' + self.ephem_pub) self.assertEqual(outputs[1]['address'], bc.pubkey_to_address(self.pay_pub)) self.assertEqual(outputs[1]['value'], value) outputs = bc.mk_stealth_tx_outputs(self.testnet_addr, value, self.ephem_priv, nonce, 'testnet') self.assertEqual(outputs[0]['value'], 0) self.assertEqual(outputs[0]['script'], '6a2606deadbeef' + self.ephem_pub) self.assertEqual(outputs[1]['address'], bc.pubkey_to_address(self.pay_pub, 111)) self.assertEqual(outputs[1]['value'], value) self.assertRaises(Exception, bc.mk_stealth_tx_outputs, self.testnet_addr, value, self.ephem_priv, nonce, 'btc') self.assertRaises(Exception, bc.mk_stealth_tx_outputs, self.addr, value, self.ephem_priv, nonce, 'testnet') if __name__ == '__main__': unittest.main()