From f6bec4c6c321e9335dc56e03bdaa090b351f3d77 Mon Sep 17 00:00:00 2001 From: zack Date: Fri, 27 Mar 2015 18:24:20 -0700 Subject: [PATCH 1/2] 0 in bitcoin opcodes is 0x00 not 0x50. 0x50 is reserved https://en.bitcoin.it/wiki/Script --- bitcoin.egg-info/PKG-INFO | 10 + bitcoin.egg-info/SOURCES.txt | 20 + bitcoin.egg-info/dependency_links.txt | 1 + bitcoin.egg-info/top_level.txt | 1 + bitcoin/transaction.py | 4 +- .../lib.linux-x86_64-2.7/bitcoin/__init__.py | 9 + build/lib.linux-x86_64-2.7/bitcoin/bci.py | 364 ++++++++++++ build/lib.linux-x86_64-2.7/bitcoin/blocks.py | 50 ++ .../lib.linux-x86_64-2.7/bitcoin/composite.py | 128 ++++ .../bitcoin/deterministic.py | 199 +++++++ build/lib.linux-x86_64-2.7/bitcoin/main.py | 550 ++++++++++++++++++ .../bitcoin/py2specials.py | 94 +++ .../bitcoin/py3specials.py | 119 ++++ build/lib.linux-x86_64-2.7/bitcoin/ripemd.py | 414 +++++++++++++ build/lib.linux-x86_64-2.7/bitcoin/stealth.py | 100 ++++ .../bitcoin/transaction.py | 484 +++++++++++++++ build/scripts-2.7/pybtctool | 36 ++ dist/bitcoin-1.1.26-py2.7.egg | Bin 0 -> 60618 bytes 18 files changed, 2582 insertions(+), 1 deletion(-) create mode 100644 bitcoin.egg-info/PKG-INFO create mode 100644 bitcoin.egg-info/SOURCES.txt create mode 100644 bitcoin.egg-info/dependency_links.txt create mode 100644 bitcoin.egg-info/top_level.txt create mode 100644 build/lib.linux-x86_64-2.7/bitcoin/__init__.py create mode 100644 build/lib.linux-x86_64-2.7/bitcoin/bci.py create mode 100644 build/lib.linux-x86_64-2.7/bitcoin/blocks.py create mode 100644 build/lib.linux-x86_64-2.7/bitcoin/composite.py create mode 100644 build/lib.linux-x86_64-2.7/bitcoin/deterministic.py create mode 100644 build/lib.linux-x86_64-2.7/bitcoin/main.py create mode 100644 build/lib.linux-x86_64-2.7/bitcoin/py2specials.py create mode 100644 build/lib.linux-x86_64-2.7/bitcoin/py3specials.py create mode 100644 build/lib.linux-x86_64-2.7/bitcoin/ripemd.py create mode 100644 build/lib.linux-x86_64-2.7/bitcoin/stealth.py create mode 100644 build/lib.linux-x86_64-2.7/bitcoin/transaction.py create mode 100755 build/scripts-2.7/pybtctool create mode 100644 dist/bitcoin-1.1.26-py2.7.egg diff --git a/bitcoin.egg-info/PKG-INFO b/bitcoin.egg-info/PKG-INFO new file mode 100644 index 00000000..0dc8cc30 --- /dev/null +++ b/bitcoin.egg-info/PKG-INFO @@ -0,0 +1,10 @@ +Metadata-Version: 1.0 +Name: bitcoin +Version: 1.1.26 +Summary: Python Bitcoin Tools +Home-page: http://github.com/vbuterin/pybitcointools +Author: Vitalik Buterin +Author-email: vbuterin@gmail.com +License: UNKNOWN +Description: UNKNOWN +Platform: UNKNOWN diff --git a/bitcoin.egg-info/SOURCES.txt b/bitcoin.egg-info/SOURCES.txt new file mode 100644 index 00000000..7f126fcd --- /dev/null +++ b/bitcoin.egg-info/SOURCES.txt @@ -0,0 +1,20 @@ +LICENSE +MANIFEST.in +README.txt +pybtctool +setup.py +bitcoin/__init__.py +bitcoin/bci.py +bitcoin/blocks.py +bitcoin/composite.py +bitcoin/deterministic.py +bitcoin/main.py +bitcoin/py2specials.py +bitcoin/py3specials.py +bitcoin/ripemd.py +bitcoin/stealth.py +bitcoin/transaction.py +bitcoin.egg-info/PKG-INFO +bitcoin.egg-info/SOURCES.txt +bitcoin.egg-info/dependency_links.txt +bitcoin.egg-info/top_level.txt \ No newline at end of file diff --git a/bitcoin.egg-info/dependency_links.txt b/bitcoin.egg-info/dependency_links.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/bitcoin.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/bitcoin.egg-info/top_level.txt b/bitcoin.egg-info/top_level.txt new file mode 100644 index 00000000..83c8dca4 --- /dev/null +++ b/bitcoin.egg-info/top_level.txt @@ -0,0 +1 @@ +bitcoin diff --git a/bitcoin/transaction.py b/bitcoin/transaction.py index e3728b8a..fd594900 100644 --- a/bitcoin/transaction.py +++ b/bitcoin/transaction.py @@ -272,7 +272,9 @@ def deserialize_script(script): def serialize_script_unit(unit): if isinstance(unit, int): - if unit < 16: + if unit == 0: + return from_int_to_byte(0) + elif unit < 16: return from_int_to_byte(unit + 80) else: return bytes([unit]) diff --git a/build/lib.linux-x86_64-2.7/bitcoin/__init__.py b/build/lib.linux-x86_64-2.7/bitcoin/__init__.py new file mode 100644 index 00000000..a772073f --- /dev/null +++ b/build/lib.linux-x86_64-2.7/bitcoin/__init__.py @@ -0,0 +1,9 @@ +from 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 * diff --git a/build/lib.linux-x86_64-2.7/bitcoin/bci.py b/build/lib.linux-x86_64-2.7/bitcoin/bci.py new file mode 100644 index 00000000..bfe53248 --- /dev/null +++ b/build/lib.linux-x86_64-2.7/bitcoin/bci.py @@ -0,0 +1,364 @@ +#!/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 parse_addr_args(*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 = 'btc' + addr_args = args + 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): + addr_args = addr_args[0] + + 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?address='+a) + except Exception as e: + if str(e) == 'No free outputs to spend': + continue + else: + raise Exception(e) + try: + jsonobj = json.loads(data) + 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 = 'https://tbtc.blockr.io/api/v1/address/unspent/' + elif network == 'btc': + blockr_url = 'https://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)['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): + network, addrs = 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)["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: + data = make_request( + 'https://blockchain.info/address/%s?format=json&offset=%s' % + (addr, offset)) + try: + jsonobj = json.loads(data) + 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['addr'] 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 inp["prev_out"]["addr"] 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 = 'https://tbtc.blockr.io/api/v1/tx/push' + elif network == 'btc': + blockr_url = 'https://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(): + data = make_request('https://blockchain.info/latestblock') + jsonobj = json.loads(data) + return jsonobj["height"] + + +# Gets a specific transaction +def bci_fetchtx(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 = 'https://tbtc.blockr.io/api/v1/tx/raw/' + elif network == 'btc': + blockr_url = 'https://btc.blockr.io/api/v1/tx/raw/' + else: + raise Exception( + 'Unsupported network {0} for blockr_fetchtx'.format(network)) + if not re.match('^[0-9a-fA-F]*$', txhash): + txhash = txhash.encode('hex') + jsondata = json.loads(make_request(blockr_url+txhash)) + return jsondata['data']['tx']['hex'] + + +def helloblock_fetchtx(txhash, network='btc'): + 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))["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")) + 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)) + + +def 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 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)) + return j['block_height'] diff --git a/build/lib.linux-x86_64-2.7/bitcoin/blocks.py b/build/lib.linux-x86_64-2.7/bitcoin/blocks.py new file mode 100644 index 00000000..e60dcfdd --- /dev/null +++ b/build/lib.linux-x86_64-2.7/bitcoin/blocks.py @@ -0,0 +1,50 @@ +from 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 + } diff --git a/build/lib.linux-x86_64-2.7/bitcoin/composite.py b/build/lib.linux-x86_64-2.7/bitcoin/composite.py new file mode 100644 index 00000000..cbceea93 --- /dev/null +++ b/build/lib.linux-x86_64-2.7/bitcoin/composite.py @@ -0,0 +1,128 @@ +from 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): + return sendmultitx(frm, to + ":" + str(value), fee) + + +# Takes privkey, "address1:value1,address2:value2" (satoshis), fee (satoshis) +def sendmultitx(frm, tovalues, fee=10000, **kwargs): + outs = [] + outvalue = 0 + tv = tovalues.split(",") + 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 + [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) diff --git a/build/lib.linux-x86_64-2.7/bitcoin/deterministic.py b/build/lib.linux-x86_64-2.7/bitcoin/deterministic.py new file mode 100644 index 00000000..200dc4a4 --- /dev/null +++ b/build/lib.linux-x86_64-2.7/bitcoin/deterministic.py @@ -0,0 +1,199 @@ +from 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: + 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) diff --git a/build/lib.linux-x86_64-2.7/bitcoin/main.py b/build/lib.linux-x86_64-2.7/bitcoin/main.py new file mode 100644 index 00000000..daa66bd9 --- /dev/null +++ b/build/lib.linux-x86_64-2.7/bitcoin/main.py @@ -0,0 +1,550 @@ +#!/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): + 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) + + +# Elliptic curve Jordan form functions +# P = (m, n, p, q) where m/n = x, p/q = y + +def isinf(p): + return p[0] == 0 and p[1] == 0 + + +def jordan_isinf(p): + return p[0][0] == 0 and p[1][0] == 0 + + +def mulcoords(c1, c2): + return (c1[0] * c2[0] % P, c1[1] * c2[1] % P) + + +def mul_by_const(c, v): + return (c[0] * v % P, c[1]) + + +def addcoords(c1, c2): + return ((c1[0] * c2[1] + c2[0] * c1[1]) % P, c1[1] * c2[1] % P) + + +def subcoords(c1, c2): + return ((c1[0] * c2[1] - c2[0] * c1[1]) % P, c1[1] * c2[1] % P) + + +def invcoords(c): + return (c[1], c[0]) + + +def jordan_add(a, b): + if jordan_isinf(a): + return b + if jordan_isinf(b): + return a + + if (a[0][0] * b[0][1] - b[0][0] * a[0][1]) % P == 0: + if (a[1][0] * b[1][1] - b[1][0] * a[1][1]) % P == 0: + return jordan_double(a) + else: + return ((0, 1), (0, 1)) + xdiff = subcoords(b[0], a[0]) + ydiff = subcoords(b[1], a[1]) + m = mulcoords(ydiff, invcoords(xdiff)) + x = subcoords(subcoords(mulcoords(m, m), a[0]), b[0]) + y = subcoords(mulcoords(m, subcoords(a[0], x)), a[1]) + return (x, y) + + +def jordan_double(a): + if jordan_isinf(a): + return ((0, 1), (0, 1)) + num = addcoords(mul_by_const(mulcoords(a[0], a[0]), 3), (A, 1)) + den = mul_by_const(a[1], 2) + m = mulcoords(num, invcoords(den)) + x = subcoords(mulcoords(m, m), mul_by_const(a[0], 2)) + y = subcoords(mulcoords(m, subcoords(a[0], x)), a[1]) + return (x, y) + + +def jordan_multiply(a, n): + if jordan_isinf(a) or n == 0: + return ((0, 0), (0, 0)) + if n == 1: + return a + if n < 0 or n >= N: + return jordan_multiply(a, n % N) + if (n % 2) == 0: + return jordan_double(jordan_multiply(a, n//2)) + if (n % 2) == 1: + return jordan_add(jordan_double(jordan_multiply(a, n//2)), a) + + +def to_jordan(p): + return ((p[0], 1), (p[1], 1)) + + +def from_jordan(p): + return (p[0][0] * inv(p[0][1], P) % P, p[1][0] * inv(p[1][1], P) % P) + return (p[0][0] * inv(p[0][1], P) % P, p[1][0] * inv(p[1][1], P) % P) + + +def fast_multiply(a, n): + return from_jordan(jordan_multiply(to_jordan(a), n)) + + +def fast_add(a, b): + return from_jordan(jordan_add(to_jordan(a), to_jordan(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 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 + +# 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 + + return 27+(y % 2), r, s + + +def ecdsa_sign(msg, priv): + return encode_sig(*ecdsa_raw_sign(electrum_sig_hash(msg), priv)) + + +def ecdsa_raw_verify(msghash, vrs, pub): + v, r, s = vrs + + 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 r == x + + +def ecdsa_verify(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 + + x = r + beta = pow(x*x*x+A*x+B, (P+1)//4, P) + y = beta if v % 2 ^ beta % 2 else (P - beta) + z = hash_to_int(msghash) + Gz = jordan_multiply(((Gx, 1), (Gy, 1)), (N - z) % N) + XY = jordan_multiply(((x, 1), (y, 1)), s) + Qr = jordan_add(Gz, XY) + Q = jordan_multiply(Qr, inv(r, N)) + Q = from_jordan(Q) + + if ecdsa_raw_verify(msghash, vrs, Q): + return Q + return False + + +def ecdsa_recover(msg, sig): + return encode_pubkey(ecdsa_raw_recover(electrum_sig_hash(msg), decode_sig(sig)), 'hex') diff --git a/build/lib.linux-x86_64-2.7/bitcoin/py2specials.py b/build/lib.linux-x86_64-2.7/bitcoin/py2specials.py new file mode 100644 index 00000000..9a08bb7e --- /dev/null +++ b/build/lib.linux-x86_64-2.7/bitcoin/py2specials.py @@ -0,0 +1,94 @@ +import 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): + inp_fmtd = chr(int(magicbyte)) + inp + leadingzbytes = len(re.match('^\x00*', inp_fmtd).group(0)) + checksum = bin_dbl_sha256(inp_fmtd)[:4] + return '1' * leadingzbytes + changebase(inp_fmtd+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_byes_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) diff --git a/build/lib.linux-x86_64-2.7/bitcoin/py3specials.py b/build/lib.linux-x86_64-2.7/bitcoin/py3specials.py new file mode 100644 index 00000000..be234722 --- /dev/null +++ b/build/lib.linux-x86_64-2.7/bitcoin/py3specials.py @@ -0,0 +1,119 @@ +import 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): + inp_fmtd = from_int_to_byte(int(magicbyte))+inp + + leadingzbytes = 0 + for x in inp_fmtd: + if x != 0: + break + leadingzbytes += 1 + + checksum = bin_dbl_sha256(inp_fmtd)[:4] + return '1' * leadingzbytes + changebase(inp_fmtd+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)) diff --git a/build/lib.linux-x86_64-2.7/bitcoin/ripemd.py b/build/lib.linux-x86_64-2.7/bitcoin/ripemd.py new file mode 100644 index 00000000..4b0c6045 --- /dev/null +++ b/build/lib.linux-x86_64-2.7/bitcoin/ripemd.py @@ -0,0 +1,414 @@ +## 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("= 2**255: + b1 = '00' + b1 + if s >= 2**255: + b2 = '00' + b2 + left = '02'+encode(len(b1)//2, 16, 2)+b1 + right = '02'+encode(len(b2)//2, 16, 2)+b2 + return '30'+encode(len(left+right)//2, 16, 2)+left+right + + +def der_decode_sig(sig): + leftlen = decode(sig[6:8], 16)*2 + left = sig[8:8+leftlen] + rightlen = decode(sig[10+leftlen:12+leftlen], 16)*2 + right = sig[12+leftlen:12+leftlen+rightlen] + return (None, decode(left, 16), decode(right, 16)) + + +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 + else: + scripthash_byte = 5 + # 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 == 0: + return from_int_to_byte(0) + elif unit < 16: + return from_int_to_byte(unit + 80) + else: + return bytes([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)]) + 'ae' + +# 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)) + + txobj = deserialize(tx) + txobj["ins"][i]["script"] = serialize_script([None]+sigs+[script]) + 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) diff --git a/build/scripts-2.7/pybtctool b/build/scripts-2.7/pybtctool new file mode 100755 index 00000000..2f6b3dcc --- /dev/null +++ b/build/scripts-2.7/pybtctool @@ -0,0 +1,36 @@ +#!/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 diff --git a/dist/bitcoin-1.1.26-py2.7.egg b/dist/bitcoin-1.1.26-py2.7.egg new file mode 100644 index 0000000000000000000000000000000000000000..91be6de6b7e2ac85a5e3db688e9183ac9a057890 GIT binary patch literal 60618 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 Date: Fri, 27 Mar 2015 18:26:52 -0700 Subject: [PATCH 2/2] removed polluting files --- bitcoin.egg-info/PKG-INFO | 10 - bitcoin.egg-info/SOURCES.txt | 20 - bitcoin.egg-info/dependency_links.txt | 1 - bitcoin.egg-info/top_level.txt | 1 - .../lib.linux-x86_64-2.7/bitcoin/__init__.py | 9 - build/lib.linux-x86_64-2.7/bitcoin/bci.py | 364 ------------ build/lib.linux-x86_64-2.7/bitcoin/blocks.py | 50 -- .../lib.linux-x86_64-2.7/bitcoin/composite.py | 128 ---- .../bitcoin/deterministic.py | 199 ------- build/lib.linux-x86_64-2.7/bitcoin/main.py | 550 ------------------ .../bitcoin/py2specials.py | 94 --- .../bitcoin/py3specials.py | 119 ---- build/lib.linux-x86_64-2.7/bitcoin/ripemd.py | 414 ------------- build/lib.linux-x86_64-2.7/bitcoin/stealth.py | 100 ---- .../bitcoin/transaction.py | 484 --------------- build/scripts-2.7/pybtctool | 36 -- dist/bitcoin-1.1.26-py2.7.egg | Bin 60618 -> 0 bytes 17 files changed, 2579 deletions(-) delete mode 100644 bitcoin.egg-info/PKG-INFO delete mode 100644 bitcoin.egg-info/SOURCES.txt delete mode 100644 bitcoin.egg-info/dependency_links.txt delete mode 100644 bitcoin.egg-info/top_level.txt delete mode 100644 build/lib.linux-x86_64-2.7/bitcoin/__init__.py delete mode 100644 build/lib.linux-x86_64-2.7/bitcoin/bci.py delete mode 100644 build/lib.linux-x86_64-2.7/bitcoin/blocks.py delete mode 100644 build/lib.linux-x86_64-2.7/bitcoin/composite.py delete mode 100644 build/lib.linux-x86_64-2.7/bitcoin/deterministic.py delete mode 100644 build/lib.linux-x86_64-2.7/bitcoin/main.py delete mode 100644 build/lib.linux-x86_64-2.7/bitcoin/py2specials.py delete mode 100644 build/lib.linux-x86_64-2.7/bitcoin/py3specials.py delete mode 100644 build/lib.linux-x86_64-2.7/bitcoin/ripemd.py delete mode 100644 build/lib.linux-x86_64-2.7/bitcoin/stealth.py delete mode 100644 build/lib.linux-x86_64-2.7/bitcoin/transaction.py delete mode 100755 build/scripts-2.7/pybtctool delete mode 100644 dist/bitcoin-1.1.26-py2.7.egg diff --git a/bitcoin.egg-info/PKG-INFO b/bitcoin.egg-info/PKG-INFO deleted file mode 100644 index 0dc8cc30..00000000 --- a/bitcoin.egg-info/PKG-INFO +++ /dev/null @@ -1,10 +0,0 @@ -Metadata-Version: 1.0 -Name: bitcoin -Version: 1.1.26 -Summary: Python Bitcoin Tools -Home-page: http://github.com/vbuterin/pybitcointools -Author: Vitalik Buterin -Author-email: vbuterin@gmail.com -License: UNKNOWN -Description: UNKNOWN -Platform: UNKNOWN diff --git a/bitcoin.egg-info/SOURCES.txt b/bitcoin.egg-info/SOURCES.txt deleted file mode 100644 index 7f126fcd..00000000 --- a/bitcoin.egg-info/SOURCES.txt +++ /dev/null @@ -1,20 +0,0 @@ -LICENSE -MANIFEST.in -README.txt -pybtctool -setup.py -bitcoin/__init__.py -bitcoin/bci.py -bitcoin/blocks.py -bitcoin/composite.py -bitcoin/deterministic.py -bitcoin/main.py -bitcoin/py2specials.py -bitcoin/py3specials.py -bitcoin/ripemd.py -bitcoin/stealth.py -bitcoin/transaction.py -bitcoin.egg-info/PKG-INFO -bitcoin.egg-info/SOURCES.txt -bitcoin.egg-info/dependency_links.txt -bitcoin.egg-info/top_level.txt \ No newline at end of file diff --git a/bitcoin.egg-info/dependency_links.txt b/bitcoin.egg-info/dependency_links.txt deleted file mode 100644 index 8b137891..00000000 --- a/bitcoin.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/bitcoin.egg-info/top_level.txt b/bitcoin.egg-info/top_level.txt deleted file mode 100644 index 83c8dca4..00000000 --- a/bitcoin.egg-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -bitcoin diff --git a/build/lib.linux-x86_64-2.7/bitcoin/__init__.py b/build/lib.linux-x86_64-2.7/bitcoin/__init__.py deleted file mode 100644 index a772073f..00000000 --- a/build/lib.linux-x86_64-2.7/bitcoin/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -from 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 * diff --git a/build/lib.linux-x86_64-2.7/bitcoin/bci.py b/build/lib.linux-x86_64-2.7/bitcoin/bci.py deleted file mode 100644 index bfe53248..00000000 --- a/build/lib.linux-x86_64-2.7/bitcoin/bci.py +++ /dev/null @@ -1,364 +0,0 @@ -#!/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 parse_addr_args(*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 = 'btc' - addr_args = args - 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): - addr_args = addr_args[0] - - 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?address='+a) - except Exception as e: - if str(e) == 'No free outputs to spend': - continue - else: - raise Exception(e) - try: - jsonobj = json.loads(data) - 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 = 'https://tbtc.blockr.io/api/v1/address/unspent/' - elif network == 'btc': - blockr_url = 'https://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)['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): - network, addrs = 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)["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: - data = make_request( - 'https://blockchain.info/address/%s?format=json&offset=%s' % - (addr, offset)) - try: - jsonobj = json.loads(data) - 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['addr'] 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 inp["prev_out"]["addr"] 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 = 'https://tbtc.blockr.io/api/v1/tx/push' - elif network == 'btc': - blockr_url = 'https://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(): - data = make_request('https://blockchain.info/latestblock') - jsonobj = json.loads(data) - return jsonobj["height"] - - -# Gets a specific transaction -def bci_fetchtx(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 = 'https://tbtc.blockr.io/api/v1/tx/raw/' - elif network == 'btc': - blockr_url = 'https://btc.blockr.io/api/v1/tx/raw/' - else: - raise Exception( - 'Unsupported network {0} for blockr_fetchtx'.format(network)) - if not re.match('^[0-9a-fA-F]*$', txhash): - txhash = txhash.encode('hex') - jsondata = json.loads(make_request(blockr_url+txhash)) - return jsondata['data']['tx']['hex'] - - -def helloblock_fetchtx(txhash, network='btc'): - 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))["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")) - 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)) - - -def 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 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)) - return j['block_height'] diff --git a/build/lib.linux-x86_64-2.7/bitcoin/blocks.py b/build/lib.linux-x86_64-2.7/bitcoin/blocks.py deleted file mode 100644 index e60dcfdd..00000000 --- a/build/lib.linux-x86_64-2.7/bitcoin/blocks.py +++ /dev/null @@ -1,50 +0,0 @@ -from 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 - } diff --git a/build/lib.linux-x86_64-2.7/bitcoin/composite.py b/build/lib.linux-x86_64-2.7/bitcoin/composite.py deleted file mode 100644 index cbceea93..00000000 --- a/build/lib.linux-x86_64-2.7/bitcoin/composite.py +++ /dev/null @@ -1,128 +0,0 @@ -from 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): - return sendmultitx(frm, to + ":" + str(value), fee) - - -# Takes privkey, "address1:value1,address2:value2" (satoshis), fee (satoshis) -def sendmultitx(frm, tovalues, fee=10000, **kwargs): - outs = [] - outvalue = 0 - tv = tovalues.split(",") - 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 + [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) diff --git a/build/lib.linux-x86_64-2.7/bitcoin/deterministic.py b/build/lib.linux-x86_64-2.7/bitcoin/deterministic.py deleted file mode 100644 index 200dc4a4..00000000 --- a/build/lib.linux-x86_64-2.7/bitcoin/deterministic.py +++ /dev/null @@ -1,199 +0,0 @@ -from 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: - 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) diff --git a/build/lib.linux-x86_64-2.7/bitcoin/main.py b/build/lib.linux-x86_64-2.7/bitcoin/main.py deleted file mode 100644 index daa66bd9..00000000 --- a/build/lib.linux-x86_64-2.7/bitcoin/main.py +++ /dev/null @@ -1,550 +0,0 @@ -#!/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): - 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) - - -# Elliptic curve Jordan form functions -# P = (m, n, p, q) where m/n = x, p/q = y - -def isinf(p): - return p[0] == 0 and p[1] == 0 - - -def jordan_isinf(p): - return p[0][0] == 0 and p[1][0] == 0 - - -def mulcoords(c1, c2): - return (c1[0] * c2[0] % P, c1[1] * c2[1] % P) - - -def mul_by_const(c, v): - return (c[0] * v % P, c[1]) - - -def addcoords(c1, c2): - return ((c1[0] * c2[1] + c2[0] * c1[1]) % P, c1[1] * c2[1] % P) - - -def subcoords(c1, c2): - return ((c1[0] * c2[1] - c2[0] * c1[1]) % P, c1[1] * c2[1] % P) - - -def invcoords(c): - return (c[1], c[0]) - - -def jordan_add(a, b): - if jordan_isinf(a): - return b - if jordan_isinf(b): - return a - - if (a[0][0] * b[0][1] - b[0][0] * a[0][1]) % P == 0: - if (a[1][0] * b[1][1] - b[1][0] * a[1][1]) % P == 0: - return jordan_double(a) - else: - return ((0, 1), (0, 1)) - xdiff = subcoords(b[0], a[0]) - ydiff = subcoords(b[1], a[1]) - m = mulcoords(ydiff, invcoords(xdiff)) - x = subcoords(subcoords(mulcoords(m, m), a[0]), b[0]) - y = subcoords(mulcoords(m, subcoords(a[0], x)), a[1]) - return (x, y) - - -def jordan_double(a): - if jordan_isinf(a): - return ((0, 1), (0, 1)) - num = addcoords(mul_by_const(mulcoords(a[0], a[0]), 3), (A, 1)) - den = mul_by_const(a[1], 2) - m = mulcoords(num, invcoords(den)) - x = subcoords(mulcoords(m, m), mul_by_const(a[0], 2)) - y = subcoords(mulcoords(m, subcoords(a[0], x)), a[1]) - return (x, y) - - -def jordan_multiply(a, n): - if jordan_isinf(a) or n == 0: - return ((0, 0), (0, 0)) - if n == 1: - return a - if n < 0 or n >= N: - return jordan_multiply(a, n % N) - if (n % 2) == 0: - return jordan_double(jordan_multiply(a, n//2)) - if (n % 2) == 1: - return jordan_add(jordan_double(jordan_multiply(a, n//2)), a) - - -def to_jordan(p): - return ((p[0], 1), (p[1], 1)) - - -def from_jordan(p): - return (p[0][0] * inv(p[0][1], P) % P, p[1][0] * inv(p[1][1], P) % P) - return (p[0][0] * inv(p[0][1], P) % P, p[1][0] * inv(p[1][1], P) % P) - - -def fast_multiply(a, n): - return from_jordan(jordan_multiply(to_jordan(a), n)) - - -def fast_add(a, b): - return from_jordan(jordan_add(to_jordan(a), to_jordan(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 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 - -# 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 - - return 27+(y % 2), r, s - - -def ecdsa_sign(msg, priv): - return encode_sig(*ecdsa_raw_sign(electrum_sig_hash(msg), priv)) - - -def ecdsa_raw_verify(msghash, vrs, pub): - v, r, s = vrs - - 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 r == x - - -def ecdsa_verify(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 - - x = r - beta = pow(x*x*x+A*x+B, (P+1)//4, P) - y = beta if v % 2 ^ beta % 2 else (P - beta) - z = hash_to_int(msghash) - Gz = jordan_multiply(((Gx, 1), (Gy, 1)), (N - z) % N) - XY = jordan_multiply(((x, 1), (y, 1)), s) - Qr = jordan_add(Gz, XY) - Q = jordan_multiply(Qr, inv(r, N)) - Q = from_jordan(Q) - - if ecdsa_raw_verify(msghash, vrs, Q): - return Q - return False - - -def ecdsa_recover(msg, sig): - return encode_pubkey(ecdsa_raw_recover(electrum_sig_hash(msg), decode_sig(sig)), 'hex') diff --git a/build/lib.linux-x86_64-2.7/bitcoin/py2specials.py b/build/lib.linux-x86_64-2.7/bitcoin/py2specials.py deleted file mode 100644 index 9a08bb7e..00000000 --- a/build/lib.linux-x86_64-2.7/bitcoin/py2specials.py +++ /dev/null @@ -1,94 +0,0 @@ -import 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): - inp_fmtd = chr(int(magicbyte)) + inp - leadingzbytes = len(re.match('^\x00*', inp_fmtd).group(0)) - checksum = bin_dbl_sha256(inp_fmtd)[:4] - return '1' * leadingzbytes + changebase(inp_fmtd+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_byes_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) diff --git a/build/lib.linux-x86_64-2.7/bitcoin/py3specials.py b/build/lib.linux-x86_64-2.7/bitcoin/py3specials.py deleted file mode 100644 index be234722..00000000 --- a/build/lib.linux-x86_64-2.7/bitcoin/py3specials.py +++ /dev/null @@ -1,119 +0,0 @@ -import 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): - inp_fmtd = from_int_to_byte(int(magicbyte))+inp - - leadingzbytes = 0 - for x in inp_fmtd: - if x != 0: - break - leadingzbytes += 1 - - checksum = bin_dbl_sha256(inp_fmtd)[:4] - return '1' * leadingzbytes + changebase(inp_fmtd+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)) diff --git a/build/lib.linux-x86_64-2.7/bitcoin/ripemd.py b/build/lib.linux-x86_64-2.7/bitcoin/ripemd.py deleted file mode 100644 index 4b0c6045..00000000 --- a/build/lib.linux-x86_64-2.7/bitcoin/ripemd.py +++ /dev/null @@ -1,414 +0,0 @@ -## 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("= 2**255: - b1 = '00' + b1 - if s >= 2**255: - b2 = '00' + b2 - left = '02'+encode(len(b1)//2, 16, 2)+b1 - right = '02'+encode(len(b2)//2, 16, 2)+b2 - return '30'+encode(len(left+right)//2, 16, 2)+left+right - - -def der_decode_sig(sig): - leftlen = decode(sig[6:8], 16)*2 - left = sig[8:8+leftlen] - rightlen = decode(sig[10+leftlen:12+leftlen], 16)*2 - right = sig[12+leftlen:12+leftlen+rightlen] - return (None, decode(left, 16), decode(right, 16)) - - -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 - else: - scripthash_byte = 5 - # 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 == 0: - return from_int_to_byte(0) - elif unit < 16: - return from_int_to_byte(unit + 80) - else: - return bytes([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)]) + 'ae' - -# 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)) - - txobj = deserialize(tx) - txobj["ins"][i]["script"] = serialize_script([None]+sigs+[script]) - 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) diff --git a/build/scripts-2.7/pybtctool b/build/scripts-2.7/pybtctool deleted file mode 100755 index 2f6b3dcc..00000000 --- a/build/scripts-2.7/pybtctool +++ /dev/null @@ -1,36 +0,0 @@ -#!/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 diff --git a/dist/bitcoin-1.1.26-py2.7.egg b/dist/bitcoin-1.1.26-py2.7.egg deleted file mode 100644 index 91be6de6b7e2ac85a5e3db688e9183ac9a057890..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 60618 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