def sign_tx(private_key, hex_data): public_address = pubtoaddr(privtopub(private_key)) pubkey = privtopub(private_key) split_data = hex_data.split("00ffffffff") input_stubs = split_data[:-1] output_stub = split_data[-1] pre_sig_script = '1976a914'+b58check_to_hex(public_address)+'88acffffffff' sig_stubs = [] for i in range(len(input_stubs)): signing_message = '' for j in range(i): signing_message += input_stubs[j]+'00ffffffff' signing_message += input_stubs[i] + pre_sig_script for k in range(i+1, len(input_stubs)): signing_message += input_stubs[k]+'00ffffffff' signing_message += output_stub+'01000000' hashed_message = hashlib.sha256(hashlib.sha256(signing_message.decode('hex')).digest()).digest() signingkey = ecdsa.SigningKey.from_string(b58check_to_hex(private_key).decode('hex'), curve=ecdsa.SECP256k1) SIG = binascii.hexlify(signingkey.sign_digest(hashed_message, sigencode=ecdsa.util.sigencode_der_canonize)) ScriptSig = hex(len(SIG+'01')/2)[2:] + SIG + '01' + hex(len(pubkey)/2)[2:] + pubkey ScriptLength = hex(len(ScriptSig)/2)[2:] sig_stub = ScriptLength+ScriptSig+'ffffffff' sig_stubs.append(sig_stub) bytes_ = '' for q in range(len(sig_stubs)): bytes_ += input_stubs[q]+sig_stubs[q] bytes_ += output_stub return bytes_
def subscribe_address(self, address, callback): """ Listen for transactions on an address. Since we can't validate the transaction, we will only callback if a majority of our peers relay it. If less than a majority relay it, we will have to wait for block inclusion to callback. """ def on_peer_announce(tx): txhash = bitcoin.txhash(bitcoin.serialize(tx["tx"])) if txhash in self.subscriptions[address][0] and self.subscriptions[ address][0][txhash][0] != "complete": self.subscriptions[address][0][txhash][0] += 1 if self.subscriptions[address][0][txhash][ 0] >= self.subscriptions[address][0][txhash][1]: self.subscriptions[address][0][txhash][0] = "complete" self.subscriptions[address][1](tx["tx"]) elif txhash not in self.subscriptions[address][0]: self.subscriptions[address][0][txhash] = [ 1, len(self.peers) / 2 ] self.subscriptions[address] = [{}, callback] self.bloom_filter.insert(unhexlify(bitcoin.b58check_to_hex(address))) for peer in self.peers: peer.protocol.add_inv_callback(bitcoin.b58check_to_hex(address), on_peer_announce) peer.protocol.update_filter()
def add_order_confirmation( self, payout_address, comments=None, shipper=None, tracking_number=None, est_delivery=None, url=None, password=None, ): """ Add the vendor's order confirmation to the contract. """ if not self.testnet and not (payout_address[:1] == "1" or payout_address[:1] == "3"): raise Exception("Bitcoin address is not a mainnet address") elif self.testnet and not (payout_address[:1] == "n" or payout_address[:1] == "m" or payout_address[:1] == "2"): raise Exception("Bitcoin address is not a testnet address") try: bitcoin.b58check_to_hex(payout_address) except AssertionError: raise Exception("Invalid Bitcoin address") conf_json = { "vendor_order_confirmation": { "invoice": { "ref_hash": digest(json.dumps(self.contract, indent=4)).encode("hex"), "payout_address": payout_address, } } } if self.contract["vendor_offer"]["listing"]["metadata"]["category"] == "physical good": shipping = {"shipper": shipper, "tracking_number": tracking_number, "est_delivery": est_delivery} conf_json["vendor_order_confirmation"]["invoice"]["shipping"] = shipping elif self.contract["vendor_offer"]["listing"]["metadata"]["category"] == "digital good": content_source = {"url": url, "password": password} conf_json["vendor_order_confirmation"]["invoice"]["content_source"] = content_source if comments: conf_json["vendor_order_confirmation"]["invoice"]["comments"] = comments confirmation = json.dumps(conf_json["vendor_order_confirmation"]["invoice"], indent=4) conf_json["vendor_order_confirmation"]["signature"] = self.keychain.signing_key.sign( confirmation, encoder=nacl.encoding.HexEncoder )[:128] order_id = digest(json.dumps(self.contract, indent=4)).encode("hex") self.contract["vendor_order_confirmation"] = conf_json["vendor_order_confirmation"] self.db.Sales().update_status(order_id, 2) file_path = DATA_FOLDER + "store/listings/in progress/" + order_id + ".json" with open(file_path, "w") as outfile: outfile.write(json.dumps(self.contract, indent=4))
def list_purchases(obj): txs, heights = obj['txs'], obj['heights'] o = [] for h in txs: txhex = str(txs[h]) # print txhex txouts = b.deserialize(txhex)['outs'] if len(txouts) >= 2 and txouts[0]['value'] >= minimum - 30000: addr = b.script_to_address(txouts[0]['script']) if addr == exodus: v = txouts[0]['value'] + 30000 ht = heights[h] # We care about the timestamp of the previous # confirmed block before a transaction t = get_block_header_data(ht - 1)['timestamp'] o.append({ "tx": h, "addr": b.b58check_to_hex(b.script_to_address( txouts[1]['script'])), "value": v, "time": t }) if len(o) % 50 == 0: sys.stderr.write('Gathered outputs: %d\n' % len(o)) return o
def compose_tx_locking_script(dest_address, dash_newtork: str): """ Create a Locking script (ScriptPubKey) that will be assigned to a transaction output. :param dest_address: destination address in Base58Check format :return: sequence of opcodes and its arguments, defining logic of the locking script """ pubkey_hash = bytearray.fromhex(bitcoin.b58check_to_hex( dest_address)) # convert address to a public key hash if len(pubkey_hash) != 20: raise Exception('Invalid length of the public key hash: ' + str(len(pubkey_hash))) if dest_address[0] in get_chain_params( dash_newtork).B58_PREFIXES_PUBKEY_ADDRESS: # sequence of opcodes/arguments for p2pkh (pay-to-public-key-hash) scr = OP_DUP + \ OP_HASH160 + \ int.to_bytes(len(pubkey_hash), 1, byteorder='little') + \ pubkey_hash + \ OP_EQUALVERIFY + \ OP_CHECKSIG elif dest_address[0] in get_chain_params( dash_newtork).B58_PREFIXES_SCRIPT_ADDRESS: # sequence of opcodes/arguments for p2sh (pay-to-script-hash) scr = OP_HASH160 + \ int.to_bytes(len(pubkey_hash), 1, byteorder='little') + \ pubkey_hash + \ OP_EQUAL else: raise Exception('Invalid dest address prefix: ' + dest_address[0]) return scr
def compose_tx_locking_script(dest_address, isTestnet=False): """ Create a Locking script (ScriptPubKey) that will be assigned to a transaction output. :param dest_address: destination address in Base58Check format :return: sequence of opcodes and its arguments, defining logic of the locking script """ pubkey_hash = bytearray.fromhex( b58check_to_hex(dest_address)) # convert address to a public key hash if len(pubkey_hash) != 20: raise Exception('Invalid length of the public key hash: ' + str(len(pubkey_hash))) if (((not isTestnet) and (dest_address[0] in P2PKH_PREFIXES)) or (isTestnet and (dest_address[0] in P2PKH_PREFIXES_TNET))): # sequence of opcodes/arguments for p2pkh (pay-to-public-key-hash) scr = OP_DUP + \ OP_HASH160 + \ int.to_bytes(len(pubkey_hash), 1, byteorder='little') + \ pubkey_hash + \ OP_EQUALVERIFY + \ OP_CHECKSIG elif (((not isTestnet) and (dest_address[0] in P2SH_PREFIXES)) or (isTestnet and (dest_address[0] in P2SH_PREFIXES_TNET))): # sequence of opcodes/arguments for p2sh (pay-to-script-hash) scr = OP_HASH160 + \ int.to_bytes(len(pubkey_hash), 1, byteorder='little') + \ pubkey_hash + \ OP_EQUAL else: mess = 'Invalid dest address prefix: ' + dest_address[0] if isTestnet: mess += ' for testnet' raise Exception(mess) return scr
def cmdImportPrivs(args): for l in stdin: ls = l.split() for x in ls: try: privkey = bitcoin.b58check_to_hex(x) addr = bitcoin.privkey_to_address(privkey) tokenval.db["PRIVKEY_" + addr] = privkey except: pass
def subscribe_address(self, address, callback): """ Listen for transactions on an address. Since we can't validate the transaction, we will only callback if a majority of our peers relay it. If less than a majority relay it, we will have to wait for block inclusion to callback. """ def on_peer_announce(tx): txhash = bitcoin.txhash(bitcoin.serialize(tx["tx"])) if txhash in self.subscriptions[address][0] and self.subscriptions[address][0][txhash][0] != "complete": self.subscriptions[address][0][txhash][0] += 1 if self.subscriptions[address][0][txhash][0] >= self.subscriptions[address][0][txhash][1]: self.subscriptions[address][0][txhash][0] = "complete" self.subscriptions[address][1](tx["tx"]) elif txhash not in self.subscriptions[address][0]: self.subscriptions[address][0][txhash] = [1, len(self.peers)/2] self.subscriptions[address] = [{}, callback] self.bloom_filter.insert(unhexlify(bitcoin.b58check_to_hex(address))) for peer in self.peers: peer.protocol.add_inv_callback(bitcoin.b58check_to_hex(address), on_peer_announce) peer.protocol.update_filter()
def list_purchases(obj): txs, heights = obj['txs'], obj['heights'] process_queue = [] for h in txs: txhex = str(txs[h]) txouts = b.deserialize(txhex)['outs'] if len(txouts) >= 2 and txouts[0]['value'] >= minimum - 30000: addr = b.script_to_address(txouts[0]['script']) if addr == exodus: v = txouts[0]['value'] + 30000 process_queue.append({ "tx": h, "addr": b.b58check_to_hex(b.script_to_address( txouts[1]['script'])), "value": v, "height": heights[h] }) else: sys.stderr.write( "Non-purchase tx found (not to exodus): %s\n" % h) elif len(txouts) == 1: sys.stderr.write("Non-purchase tx found (single output): %s\n" % h) else: sys.stderr.write( "Non-purchase tx found (insufficient value): %s\n" % h) sys.stderr.write('Gathered outputs, collecting block timestamps\n') # Determine the timestamp for every block height. We care about # the timestamp of the previous confirmed block before a transaction. # Save the results as a dictionary of transaction data o = [] for i in range(0, len(process_queue), 20): subpq = process_queue[i:i + 20] t = get_block_timestamp([x['height'] - 1 for x in subpq]) assert len(t) == len(subpq), [x['height'] - 1 for x in subpq] o.extend([{ "tx": _a["tx"], "addr": _a["addr"], "value": _a["value"], "time": _b } for _a, _b in zip(subpq, t)]) sys.stderr.write('Collected timestamps: %d\n' % len(o)) return o
def list_purchases(obj): txs, heights = obj['txs'], obj['heights'] process_queue = [] for h in txs: txhex = str(txs[h]) txouts = b.deserialize(txhex)['outs'] if len(txouts) >= 2 and txouts[0]['value'] >= minimum - 30000: addr = b.script_to_address(txouts[0]['script']) if addr == exodus: v = txouts[0]['value'] + 30000 process_queue.append({ "tx": h, "addr": b.b58check_to_hex(b.script_to_address( txouts[1]['script'])), "value": v, "height": heights[h] }) else: sys.stderr.write("Non-purchase tx found (not to exodus): %s\n" % h) elif len(txouts) == 1: sys.stderr.write("Non-purchase tx found (single output): %s\n" % h) else: sys.stderr.write("Non-purchase tx found (insufficient value): %s\n" % h) sys.stderr.write('Gathered outputs, collecting block timestamps\n') # Determine the timestamp for every block height. We care about # the timestamp of the previous confirmed block before a transaction. # Save the results as a dictionary of transaction data o = [] for i in range(0, len(process_queue), 20): subpq = process_queue[i:i+20] t = get_block_timestamp([x['height'] - 1 for x in subpq]) assert len(t) == len(subpq), [x['height'] - 1 for x in subpq] o.extend([{ "tx": _a["tx"], "addr": _a["addr"], "value": _a["value"], "time": _b } for _a, _b in zip(subpq, t)]) sys.stderr.write('Collected timestamps: %d\n' % len(o)) return o
# This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. import sys from bitcoin import b58check_to_hex, hex_to_b58check if len(sys.argv) not in [2, 3]: print("Usage: convertAddress.py ADDRESS [TO-MAGIC-BYTE]") sys.exit(-1) addr = sys.argv[1] if len(sys.argv) >= 3: magic = int(sys.argv[2]) else: magic = 52 keyHex = b58check_to_hex(addr) newAddr = hex_to_b58check(keyHex, magic) print(newAddr)
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. import argparse import sys from bitcoin import b58check_to_hex, hex_to_b58check parser = argparse.ArgumentParser () parser.add_argument ("--address", required=True, help="the address to convert") parser.add_argument ("--magic-byte", dest="magic", default=52, type=int, help="the target 'magic' version byte") parser.add_argument ("--update-file", dest="updatefile", default="", help="if set, replace all occurances in the given file") args = parser.parse_args () keyHex = b58check_to_hex (args.address) newAddr = hex_to_b58check (keyHex, args.magic) print (newAddr) if args.updatefile != "": with open (args.updatefile, "r") as f: lines = f.readlines () with open (args.updatefile, "w") as f: for l in lines: f.write (str.replace (l, args.address, newAddr))
# Check that the wallet is unlocked. for rpc in [huc, xaya]: info = rpc.getwalletinfo () if 'unlocked_until' in info and info['unlocked_until'] < 1000000000: sys.exit ("The wallets must be unlocked") # Go through the snapshot data and look for addresses that are in the HUC # wallet we own. totalHuc = Decimal ('0.00000000') totalChi = Decimal ('0.00000000') privkeys = [] for entry in snapshot: info = huc.getaddressinfo (entry['address']['huc']) if info['ismine']: log.info ("Found address: %s" % entry['address']['huc']) totalHuc += Decimal (entry['amount']['huc']).quantize (PRECISION) totalChi += Decimal (entry['amount']['chi']).quantize (PRECISION) pkHuc = huc.dumpprivkey (entry['address']['huc']) keyHex = b58check_to_hex (pkHuc) pkChi = hex_to_b58check (keyHex, CHI_PRIVKEY_VERSION) privkeys.append (pkChi) log.info ("Total HUC amount eligible: %s" % totalHuc) log.info ("Total CHI amount claimed: %s" % totalChi) # Import the found addresses. for pk in privkeys: xaya.importprivkey (pk, LABEL, False) log.info ("Imported %d private keys. You need to manually rescan now." % len (privkeys))
import json from bitcoin import b58check_to_hex, hex_to_b58check CHI_ADDRESS_VERSION = 28 INPUT_FILE = 'snapshot-balances.json' PRECISION = Decimal('1.00000000') CHI_PER_HUC = Decimal('0.23338000') with open(INPUT_FILE) as f: hucBalances = json.load(f) output = [] totalChi = Decimal('0.00000000') for hucAddr, val in hucBalances['addresses'].items(): keyHex = b58check_to_hex(hucAddr) chiAddr = hex_to_b58check(keyHex, CHI_ADDRESS_VERSION) hucValue = Decimal(val).quantize(PRECISION) hucRounded = int(val) chiValue = hucRounded * CHI_PER_HUC obj = { "address": { "huc": hucAddr, "chi": chiAddr, }, "amount": { "huc": float(hucValue), "full_huc": hucRounded, "chi": float(chiValue),
def address_to_hex(address): version = get_version_byte(address) hex_value = b58check_to_hex(address) return "0x%02x%s" % (version, hex_value)
entries = [] members = [] for row in csv.reader(csv_file): try: member_idx =int(row[0]) nick = (row[1] .replace(" ", "_") # sorry ... ).replace(".", "_") # and sorry again .. joined = date2epoch(row[3]) app_text = row[4] addr = row[5].strip() bitcoin.b58check_to_hex(addr) last_vote = date2epoch(row[6]) last_action = max(joined, last_vote) print("Adding:", nick, addr, "?") while True: m = Member.by_name(nick) b = Member.by_address(addr) if m is not None: print("by name:", m.name, m.address) if b is not None: print("by address:", b.name, b.address)
def add_order_confirmation(self, payout_address, comments=None, shipper=None, tracking_number=None, est_delivery=None, url=None, password=None): """ Add the vendor's order confirmation to the contract. """ if not self.testnet and not (payout_address[:1] == "1" or payout_address[:1] == "3"): raise Exception("Bitcoin address is not a mainnet address") elif self.testnet and not \ (payout_address[:1] == "n" or payout_address[:1] == "m" or payout_address[:1] == "2"): raise Exception("Bitcoin address is not a testnet address") try: bitcoin.b58check_to_hex(payout_address) except AssertionError: raise Exception("Invalid Bitcoin address") conf_json = { "vendor_order_confirmation": { "invoice": { "ref_hash": digest(json.dumps(self.contract, indent=4)).encode("hex") } } } if self.contract["vendor_offer"]["listing"]["metadata"][ "category"] == "physical good": shipping = { "shipper": shipper, "tracking_number": tracking_number, "est_delivery": est_delivery } conf_json["vendor_order_confirmation"]["invoice"][ "shipping"] = shipping elif self.contract["vendor_offer"]["listing"]["metadata"][ "category"] == "digital good": content_source = {"url": url, "password": password} conf_json["vendor_order_confirmation"]["invoice"][ "content_source"] = content_source if comments: conf_json["vendor_order_confirmation"]["invoice"][ "comments"] = comments confirmation = json.dumps( conf_json["vendor_order_confirmation"]["invoice"], indent=4) conf_json["vendor_order_confirmation"]["signature"] = \ self.keychain.signing_key.sign(confirmation, encoder=nacl.encoding.HexEncoder)[:128] order_id = digest(json.dumps(self.contract, indent=4)).encode("hex") # apply signatures outpoints = pickle.loads(self.db.Sales().get_outpoint(order_id)) redeem_script = self.contract["buyer_order"]["order"]["payment"][ "redeem_script"] value = 0 for output in outpoints: value += output["value"] del output["value"] value -= TRANSACTION_FEE outs = [{'value': value, 'address': payout_address}] tx = bitcoin.mktx(outpoints, outs) signatures = [] chaincode = self.contract["buyer_order"]["order"]["payment"][ "chaincode"] masterkey_v = bitcoin.bip32_extract_key( self.keychain.bitcoin_master_privkey) vendor_priv = derive_childkey(masterkey_v, chaincode, bitcoin.MAINNET_PRIVATE) for index in range(0, len(outpoints)): sig = bitcoin.multisign(tx, index, redeem_script, vendor_priv) signatures.append({"input_index": index, "signature": sig}) conf_json["vendor_order_confirmation"]["invoice"]["payout"] = {} conf_json["vendor_order_confirmation"]["invoice"]["payout"][ "address"] = payout_address conf_json["vendor_order_confirmation"]["invoice"]["payout"][ "value"] = value conf_json["vendor_order_confirmation"]["invoice"]["payout"][ "signature(s)"] = signatures self.contract["vendor_order_confirmation"] = conf_json[ "vendor_order_confirmation"] self.db.Sales().update_status(order_id, 2) file_path = DATA_FOLDER + "store/listings/in progress/" + order_id + ".json" with open(file_path, 'w') as outfile: outfile.write(json.dumps(self.contract, indent=4))
def add_order_confirmation(self, payout_address, comments=None, shipper=None, tracking_number=None, est_delivery=None, url=None, password=None): """ Add the vendor's order confirmation to the contract. """ if not self.testnet and not (payout_address[:1] == "1" or payout_address[:1] == "3"): raise Exception("Bitcoin address is not a mainnet address") elif self.testnet and not \ (payout_address[:1] == "n" or payout_address[:1] == "m" or payout_address[:1] == "2"): raise Exception("Bitcoin address is not a testnet address") try: bitcoin.b58check_to_hex(payout_address) except AssertionError: raise Exception("Invalid Bitcoin address") conf_json = { "vendor_order_confirmation": { "invoice": { "ref_hash": digest(json.dumps(self.contract, indent=4)).encode("hex") } } } if self.contract["vendor_offer"]["listing"]["metadata"]["category"] == "physical good": shipping = {"shipper": shipper, "tracking_number": tracking_number, "est_delivery": est_delivery} conf_json["vendor_order_confirmation"]["invoice"]["shipping"] = shipping elif self.contract["vendor_offer"]["listing"]["metadata"]["category"] == "digital good": content_source = {"url": url, "password": password} conf_json["vendor_order_confirmation"]["invoice"]["content_source"] = content_source if comments: conf_json["vendor_order_confirmation"]["invoice"]["comments"] = comments confirmation = json.dumps(conf_json["vendor_order_confirmation"]["invoice"], indent=4) conf_json["vendor_order_confirmation"]["signature"] = \ self.keychain.signing_key.sign(confirmation, encoder=nacl.encoding.HexEncoder)[:128] order_id = digest(json.dumps(self.contract, indent=4)).encode("hex") # apply signatures outpoints = pickle.loads(self.db.Sales().get_outpoint(order_id)) redeem_script = self.contract["buyer_order"]["order"]["payment"]["redeem_script"] value = 0 for output in outpoints: value += output["value"] del output["value"] value -= TRANSACTION_FEE outs = [{'value': value, 'address': payout_address}] tx = bitcoin.mktx(outpoints, outs) signatures = [] chaincode = self.contract["buyer_order"]["order"]["payment"]["chaincode"] masterkey_v = bitcoin.bip32_extract_key(self.keychain.bitcoin_master_privkey) vendor_priv = derive_childkey(masterkey_v, chaincode, bitcoin.MAINNET_PRIVATE) for index in range(0, len(outpoints)): sig = bitcoin.multisign(tx, index, redeem_script, vendor_priv) signatures.append({"input_index": index, "signature": sig}) conf_json["vendor_order_confirmation"]["invoice"]["payout"] = {} conf_json["vendor_order_confirmation"]["invoice"]["payout"]["address"] = payout_address conf_json["vendor_order_confirmation"]["invoice"]["payout"]["value"] = value conf_json["vendor_order_confirmation"]["invoice"]["payout"]["signature(s)"] = signatures self.contract["vendor_order_confirmation"] = conf_json["vendor_order_confirmation"] self.db.Sales().update_status(order_id, 2) file_path = DATA_FOLDER + "store/listings/in progress/" + order_id + ".json" with open(file_path, 'w') as outfile: outfile.write(json.dumps(self.contract, indent=4))