def get_pubkey_on_address(public_address): #only sometimes works try: txs = get_txs_from_address(public_address) found = False pubkey = '' for tx in txs: if not found: for inp in tx['inputs']: if 'script' in inp: script = inp['script'] if len(script) > 130: potential_key = script[len(script) - 130:len(script)] hashed_key = pybitcointools.pubkey_to_address( potential_key) if hashed_key == public_address: found = True pubkey = potential_key potential_key2 = script[len(script) - 66:len(script)] #print potential_key2 hashed_key2 = pybitcointools.pubkey_to_address( potential_key2) if hashed_key2 == public_address: found = True pubkey = potential_key2 return pubkey, found except: print "cannot get pubkey on address" return '', False
def get_pubkey_on_address(public_address): #only sometimes works try: txs = get_txs_from_address(public_address) found=False pubkey='' for tx in txs: if not found: for inp in tx['inputs']: if 'script' in inp: script = inp['script'] if len(script)>130: potential_key = script[len(script)-130:len(script)] hashed_key = pybitcointools.pubkey_to_address(potential_key) if hashed_key == public_address: found=True pubkey=potential_key potential_key2= script[len(script)-66:len(script)] #print potential_key2 hashed_key2=pybitcointools.pubkey_to_address(potential_key2) if hashed_key2 == public_address: found=True pubkey = potential_key2 return pubkey, found except: print "cannot get pubkey on address" return '', False
def test_stealth_tx_outputs(self): nonce = int('deadbeef', 16) value = 10**8 outputs = bc.mk_stealth_tx_outputs(self.addr, value, self.ephem_priv, nonce) self.assertEqual(outputs[0]['value'], 0) self.assertEqual(outputs[0]['script'], '6a2606deadbeef' + self.ephem_pub) self.assertEqual(outputs[1]['address'], bc.pubkey_to_address(self.pay_pub)) self.assertEqual(outputs[1]['value'], value) outputs = bc.mk_stealth_tx_outputs(self.testnet_addr, value, self.ephem_priv, nonce, 'testnet') self.assertEqual(outputs[0]['value'], 0) self.assertEqual(outputs[0]['script'], '6a2606deadbeef' + self.ephem_pub) self.assertEqual(outputs[1]['address'], bc.pubkey_to_address(self.pay_pub, 111)) self.assertEqual(outputs[1]['value'], value) self.assertRaises(Exception, bc.mk_stealth_tx_outputs, self.testnet_addr, value, self.ephem_priv, nonce, 'btc') self.assertRaises(Exception, bc.mk_stealth_tx_outputs, self.addr, value, self.ephem_priv, nonce, 'testnet')
def get_user_address(step, basepub, steppub, magic=None): basepub = b58check_to_hex(basepub) steppub = b58check_to_hex(steppub) pubkey = multiply_pubkeys(basepub, steppub, step) address = pubkey_to_address( pubkey) if magic is None else pubkey_to_address(pubkey, magic) return address
def sender_payee_address_from_stealth(sender_prikey, receiver_pubkey): # sender - derive payee address ss1 = btc.multiply(receiver_pubkey, sender_prikey) ss2 = btc.sha256(btc.encode_pubkey((ss1), 'bin_compressed')) addr = btc.pubkey_to_address(btc.add_pubkeys( receiver_pubkey, btc.privtopub(ss2))) return addr
def create_invoice_user (email): BMMySQL().db.ping(True) cur = BMMySQL().db.cursor(MySQLdb.cursors.DictCursor) cur.execute ("SELECT bm, masterpubkey_btc, offset_btc, feeamount, feecurrency FROM user WHERE email = %s AND active = 1", (email)) result = False for row in cur.fetchall(): result = row if result: if result['masterpubkey_btc'][0:4] == "xpub": # BIP44 dpk1 = pybitcointools.bip32_ckd(result['masterpubkey_btc'], 0) dpk2 = pybitcointools.bip32_ckd(dpk1, result['offset_btc']) pubkey = pybitcointools.bip32_extract_key(dpk2) else: # Electrum 1.x pubkey = pybitcointools.electrum_pubkey(result['masterpubkey_btc'], result['offset_btc']) address = pybitcointools.pubkey_to_address(pubkey) cur.execute ("UPDATE user SET offset_btc = offset_btc + 1 WHERE email = %s AND active = 1 AND masterpubkey_btc = %s", (email, result['masterpubkey_btc'])) if result['feecurrency'] in ("USD", "GBP", "EUR"): result['feeamount'] /= decimal.Decimal(get_bitcoin_price(result['feecurrency'])) cur.execute ("INSERT INTO invoice (issuer, address, coin, amount, type, paid) VALUES (%s, %s, 'BTC', %s, 1, 0)", (result['bm'], address, result['feeamount'])) bitcoind_importaddress(address) cur.close() return address, result['feeamount']; cur.close() return False
def __init__(self, tx_type, form): #self.conn = getRPCconn() self.testnet = False self.magicbyte = 0 self.exodus_address = self.mainnet_exodus_address if 'testnet' in form and (form['testnet'] in ['true', 'True']): self.testnet = True self.magicbyte = 111 self.exodus_address = self.testnet_exodus_address try: if config.D_PUBKEY and ('donate' in form) and (form['donate'] in [ 'true', 'True' ]): print_debug( ("We're Donating to pubkey for: ", pybitcointools.pubkey_to_address(config.D_PUBKEY)), 4) self.pubkey = config.D_PUBKEY else: print_debug("not donating", 4) self.pubkey = form['pubkey'] except NameError, e: print_debug(e, 2) self.pubkey = form['pubkey']
def validate_ecdsa(self, obfuscated): invalid = True while invalid: ob_randbyte = obfuscated[:-2] + pad(randint(0, 255), 2).upper() potential_address = pybitcointools.pubkey_to_address(ob_randbyte) if bool(self.rpc_conn.validateaddress(potential_address).isvalid): pubkey = ob_randbyte invalid = False return pubkey
def parse_pay2pubkey(script): # First 2 bytes is num bytes to be pushed to the stack # Last 2 are OP_CHECKSIG, pubkey is in the middle pubkey = script[2:-2] # Create address from public key (HASH160 + B58_CHECK) address = pubkey_to_address( pubkey, magicbyte=constants.PAY_TO_PUBKEY_VERSION_PREFIX) return (pubkey, address)
def __init__(self, private, url=NETVEND_URL, seed=False): if seed: self._private = pybitcointools.sha256(private) else: try: self._private = pybitcointools.b58check_to_hex(private) except AssertionError: raise RuntimeError("Invalid private key. Did you mean to set seed=True?") self.address = pybitcointools.pubkey_to_address(pybitcointools.privtopub(self._private)) self.url = url
def __init__(self, private, url=NETVEND_URL, seed=False): if seed: self._private = pybitcointools.sha256(private) else: try: self._private = pybitcointools.b58check_to_hex(private) except AssertionError: raise RuntimeError( "Invalid private key. Did you mean to set seed=True?") self.address = pybitcointools.pubkey_to_address( pybitcointools.privtopub(self._private)) self.url = url
def gen_row(height, file, column_number, column_total, sheet_num, digits): rows=number_of_rows() keys=GenerateKeys(rows) width=width_between_circles() f=int2padded_string for i in range(rows): if True: # if i in [0]: draw_circle_line(file, keys[i], frame_top()+i*width, frame_side()+height) print('Sticker #{} of Row #{} of Sheet #{}.....................Done'.format(f(i + 1, digits), f(column_number + 1, digits), f(sheet_num+1, digits))) pubs=[] for i in keys: pubs.append(pt.pubkey_to_address(i['pub'])) return pubs
def generate_tx(tx_type): #update this to support more transactions supported_transactions = [50,51,54,55,56,0] if tx_type not in supported_transactions: return jsonify({ 'status': 400, 'data': 'Unsupported transaction type '+str(tx_type) }) expected_fields=['transaction_version', 'transaction_from','pubkey','fee'] print "Form ",request.form #might add tx 00, 53, etc later; if tx_type == 50: expected_fields+=['ecosystem', 'property_type', 'previous_property_id', 'property_category', 'property_subcategory', 'property_name', 'property_url', 'property_data', 'number_properties'] elif tx_type == 51: expected_fields+=['ecosystem', 'property_type', 'previous_property_id', 'property_category', 'property_subcategory', 'property_name', 'property_url', 'property_data', 'currency_identifier_desired', 'number_properties', 'deadline', 'earlybird_bonus', 'percentage_for_issuer'] elif tx_type == 54: expected_fields+=['ecosystem', 'property_type', 'previous_property_id', 'property_category', 'property_subcategory', 'property_name', 'property_url', 'property_data'] elif tx_type == 0: expected_fields+=['currency_identifier', 'amount_to_transfer', 'transaction_to'] elif tx_type in [55,56]: expected_fields+=['currency_identifier', 'number_properties'] for field in expected_fields: if field not in request.form: return jsonify({ 'status': 403, 'data': 'No field in request form '+field }) elif request.form[field] == '': return jsonify({ 'status': 403, 'data': 'Empty field in request form '+field }) if 'testnet' in request.form and ( request.form['testnet'] in ['true', 'True'] ): global testnet testnet =True global magicbyte magicbyte = 111 global exodus_address exodus_address=testnet_exodus_address try: if config.D_PUBKEY and ( 'donate' in request.form ) and ( request.form['donate'] in ['true', 'True'] ): print "We're Donating to pubkey for: "+pybitcointools.pubkey_to_address(config.D_PUBKEY) pubkey = config.D_PUBKEY else: print "not donating" pubkey = request.form['pubkey'] except NameError, e: print e pubkey = request.form['pubkey']
def __init__(self, private, url, privtype): if privtype is PRIVTYPE_SEED: self.private = pybitcointools.sha256(private) elif privtype is PRIVTYPE_B58CHECK: try: self.private = pybitcointools.b58check_to_hex(private) except AssertionError: raise ValueError("Invalid private key") elif privtype is PRIVTYPE_HEX: if len(private) == 64: self.private = private else: raise ValueError("Invalid private key") else: # Raise a ValueError, otherwise self.private would not be defined raise ValueError("Invalid privtype") self.address = pybitcointools.pubkey_to_address(pybitcointools.privtopub(self.private)) self.url = url
def gen_row(height, file, column_number, column_total, sheet_num, digits): rows = number_of_rows() keys = GenerateKeys(rows) width = width_between_circles() f = int2padded_string for i in range(rows): if True: # if i in [0]: draw_circle_line(file, keys[i], frame_top() + i * width, frame_side() + height) print( 'Sticker #{} of Row #{} of Sheet #{}.....................Done'. format(f(i + 1, digits), f(column_number + 1, digits), f(sheet_num + 1, digits))) pubs = [] for i in keys: pubs.append(pt.pubkey_to_address(i['pub'])) return pubs
def __init__(self,tx_type,form): self.conn = getRPCconn() self.testnet = False self.magicbyte = 0 self.exodus_address=self.mainnet_exodus_address if 'testnet' in form and ( form['testnet'] in ['true', 'True'] ): self.testnet =True self.magicbyte = 111 self.exodus_address=self.testnet_exodus_address try: if config.D_PUBKEY and ( 'donate' in form ) and ( form['donate'] in ['true', 'True'] ): print "We're Donating to pubkey for: "+pybitcointools.pubkey_to_address(config.D_PUBKEY) self.pubkey = config.D_PUBKEY else: print "not donating" self.pubkey = form['pubkey'] except NameError, e: print e self.pubkey = form['pubkey']
def create_invoice_domain (domain, payer): BMMySQL().db.ping(True) cur = BMMySQL().db.cursor(MySQLdb.cursors.DictCursor) filterwarnings('ignore', category = MySQLdb.Warning) cur.execute ("SELECT bm, masterpubkey_btc, offset_btc, feeamount, feecurrency FROM domain WHERE name = %s AND active = 1", (domain)) result = False for row in cur.fetchall(): result = row while result: if result['masterpubkey_btc'][0:4] == "xpub": # BIP44 dpk1 = pybitcointools.bip32_ckd(result['masterpubkey_btc'], 0) dpk2 = pybitcointools.bip32_ckd(dpk1, result['offset_btc']) pubkey = pybitcointools.bip32_extract_key(dpk2) else: # Electrum 1.x pubkey = pybitcointools.electrum_pubkey(result['masterpubkey_btc'], result['offset_btc']) address = pybitcointools.pubkey_to_address(pubkey) cur.execute ("UPDATE domain SET offset_btc = offset_btc + 1 WHERE name = %s AND active = 1 AND masterpubkey_btc = %s", (domain, result['masterpubkey_btc'])) if result['feecurrency'] in ("USD", "GBP", "EUR"): result['feeamount'] /= decimal.Decimal(get_bitcoin_price(result['feecurrency'])) cur.execute ("INSERT IGNORE INTO invoice (issuer, payer, address, coin, amount, type, paid) VALUES (%s, %s, %s, 'BTC', %s, 0, 0)", (result['bm'], payer, address, result['feeamount'])) # invoice already exists for that address, increment if cur.rowcount == 0: cur.execute ("SELECT bm, masterpubkey_btc, offset_btc, feeamount, feecurrency FROM domain WHERE name = %s AND active = 1", (domain)) result = False for row in cur.fetchall(): result = row continue bitcoind_importaddress(address) cur.close() return address, result['feeamount']; cur.close() return False
def construct_packets(byte_stream, total_bytes, from_address): import math total_packets = int(math.ceil(float(total_bytes) / 30)) #get # of packets total_outs = int(math.ceil(float(total_packets) / 2)) #get # of outs #construct packets packets = [] index = 0 for i in range(total_packets): # 2 multisig data addrs per out, 60 bytes per, 2 characters per byte so 60 characters per pass parsed_data = byte_stream[index:index + 60].ljust(60, "0") cleartext_packet = (hex(i + 1)[2:].rjust(2, "0") + parsed_data.ljust(60, "0")) index = index + 60 packets.append(cleartext_packet) #DEBUG print ['pax',cleartext_packet, parsed_data, total_packets, i] obfuscation_packets = [hashlib.sha256(from_address).hexdigest().upper() ] #add first sha of sender to packet list for i in range(total_packets - 1): #do rest for seqnums obfuscation_packets.append( hashlib.sha256(obfuscation_packets[i]).hexdigest().upper()) #DEBUG print [packets,obfuscation_packets, len(obfuscation_packets[0]), len(obfuscation_packets[1]), len(packets[0])] #obfuscate and prepare multisig outs pair_packets = [] for i in range(total_packets): obfuscation_packet = obfuscation_packets[i] pair_packets.append((packets[i], obfuscation_packet[:-2])) #encode the plaintext packets obfuscated_packets = [] for pair in pair_packets: plaintext = pair[0].upper() shaaddress = pair[1] #DEBUG print ['packets', plaintext, shaaddress, len(plaintext), len(shaaddress)] datapacket = '' for i in range(len(plaintext)): if plaintext[i] == '0': datapacket = datapacket + shaaddress[i] else: bin_plain = int('0x' + plaintext[i], 16) bin_sha = int('0x' + shaaddress[i], 16) #DEBUG print ['texts, plain & addr', plaintext[i], shaaddress[i],'bins, plain & addr', bin_plain, bin_sha ] xored = hex(bin_plain ^ bin_sha)[2:].upper() datapacket = datapacket + xored obfuscated_packets.append((datapacket, shaaddress)) #### Test that the obfuscated packets produce the same output as the plaintext packet inputs #### #decode the obfuscated packet plaintext_packets = [] for pair in obfuscated_packets: obpacket = pair[0].upper() shaaddress = pair[1] #DEBUG print [obpacket, len(obpacket), shaaddress, len(shaaddress)] datapacket = '' for i in range(len(obpacket)): if obpacket[i] == shaaddress[i]: datapacket = datapacket + '0' else: bin_ob = int('0x' + obpacket[i], 16) bin_sha = int('0x' + shaaddress[i], 16) xored = hex(bin_ob ^ bin_sha)[2:].upper() datapacket = datapacket + xored plaintext_packets.append(datapacket) #check the packet is formed correctly by comparing it to the input final_packets = [] for i in range(len(plaintext_packets)): orig = packets[i] if orig.upper() != plaintext_packets[i]: print['packet did not come out right', orig, plaintext_packets[i]] else: final_packets.append(obfuscated_packets[i][0]) #DEBUG print plaintext_packets, obfuscation_packets,final_packets #add key identifier and ecdsa byte to new mastercoin data key for i in range(len(final_packets)): obfuscated = '02' + final_packets[i] + "00" #DEBUG print [obfuscated, len(obfuscated)] invalid = True while invalid: obfuscated_randbyte = obfuscated[:-2] + hex(random.randint( 0, 255))[2:].rjust(2, "0").upper() #set the last byte to something random in case we generated an invalid pubkey potential_data_address = pybitcointools.pubkey_to_address( obfuscated_randbyte, magicbyte) if bool(conn.validateaddress(potential_data_address).isvalid): final_packets[i] = obfuscated_randbyte invalid = False #make sure the public key is valid using pybitcointools, if not, regenerate #the last byte of the key and try again #DEBUG print final_packets return [final_packets, total_packets, total_outs]
def draw_line(filename, nums, x, y): num=nums['pub'] addr=pt.pubkey_to_address(num) draw_num(filename, addr[:8], x , y)
def generate_tx(tx_type): #update this to support more transactions supported_transactions = [50, 51, 54, 55, 56, 0] if tx_type not in supported_transactions: return jsonify({ 'status': 400, 'data': 'Unsupported transaction type ' + str(tx_type) }) expected_fields = [ 'transaction_version', 'transaction_from', 'pubkey', 'fee' ] print "Form ", request.form #might add tx 00, 53, etc later; if tx_type == 50: expected_fields += [ 'ecosystem', 'property_type', 'previous_property_id', 'property_category', 'property_subcategory', 'property_name', 'property_url', 'property_data', 'number_properties' ] elif tx_type == 51: expected_fields += [ 'ecosystem', 'property_type', 'previous_property_id', 'property_category', 'property_subcategory', 'property_name', 'property_url', 'property_data', 'currency_identifier_desired', 'number_properties', 'deadline', 'earlybird_bonus', 'percentage_for_issuer' ] elif tx_type == 54: expected_fields += [ 'ecosystem', 'property_type', 'previous_property_id', 'property_category', 'property_subcategory', 'property_name', 'property_url', 'property_data' ] elif tx_type == 0: expected_fields += [ 'currency_identifier', 'amount_to_transfer', 'transaction_to' ] elif tx_type in [55, 56]: expected_fields += ['currency_identifier', 'number_properties'] for field in expected_fields: if field not in request.form: return jsonify({ 'status': 403, 'data': 'No field in request form ' + field }) elif request.form[field] == '': return jsonify({ 'status': 403, 'data': 'Empty field in request form ' + field }) if 'testnet' in request.form and (request.form['testnet'] in ['true', 'True']): global testnet testnet = True global magicbyte magicbyte = 111 global exodus_address exodus_address = testnet_exodus_address try: if config.D_PUBKEY and ('donate' in request.form) and (request.form['donate'] in ['true', 'True']): print "We're Donating to pubkey for: " + pybitcointools.pubkey_to_address( config.D_PUBKEY) pubkey = config.D_PUBKEY else: print "not donating" pubkey = request.form['pubkey'] except NameError, e: print e pubkey = request.form['pubkey']
#!/usr/bin/env python from ledgerblue.comm import getDongle from ledgerblue.commException import CommException from secp256k1 import PublicKey from pybitcointools import pubkey_to_address import json print " ##### ZeroNet Nano S Ledger demo ##### " print "Demo 1 : print pubKey and get btc address" try: dongle = getDongle(True) publicKey = dongle.exchange(bytes("8004000000".decode('hex'))) print "Address : " + pubkey_to_address(str(publicKey).encode('hex')) except CommException as comm: if comm.sw == 0x6985: print "Aborted by user" else: print "Invalid status " + str(comm.sw) print "Demo 2 : sign conten.json" with open('content.json') as json_content: content = json.load(json_content) textToSign = "%s:%s" % (content["signs_required"], content["address"]) try: offset = 0 while offset <> len(textToSign): if (len(textToSign) - offset) > 255: chunk = textToSign[offset:offset + 255]
def point_to_address(pt): public_key = point_to_key(pt) address = pybitcointools.pubkey_to_address(public_key) return address
map( lambda xor_target: hex(operator.xor(xor_target[0], xor_target[1]))[2:]. rjust(2, "0"), zip(cleartext_bytes, shathesender_bytes))).upper() #map operation that xor's the bytes from cleartext and shathesender together #to obfuscate the cleartext packet, for more see Appendix Class B: #https://github.com/faizkhan00/spec#class-b-transactions-also-known-as-the-multisig-method obfuscated = "02" + msc_data_key + "00" #add key identifier and ecdsa byte to new mastercoin data key invalid = True while invalid: obfuscated_randbyte = obfuscated[:-2] + hex(random.randint( 0, 255))[2:].rjust(2, "0").upper() #set the last byte to something random in case we generated an invalid pubkey potential_data_address = pybitcointools.pubkey_to_address( obfuscated_randbyte) if bool(commands.getoutput('sx validaddr ' + potential_data_address)): data_pubkey = obfuscated_randbyte invalid = False #make sure the public key is valid using pybitcointools, if not, regenerate #the last byte of the key and try again #### Build transaction #retrieve raw transaction data to spend it and add it to the input validnextinputs = "" input_counter = 0 for utxo in utxo_list: #prev_tx = json.loads(commands.getoutput('sx fetch-transaction '+utxo[0]+' | sx showtx -j')) try: prev_tx = json.loads( commands.getoutput('sx fetch-transaction ' + utxo['tx_hash'] +
def build_transaction(miner_fee_satoshis, pubkey,final_packets, total_packets, total_outs, from_address, to_address=None): print 'pubkey', request.form['pubkey'], len(request.form['pubkey']) if len(request.form['pubkey']) < 100: print "Compressed Key, using hexspace 21" HEXSPACE_FIRST='21' else: HEXSPACE_FIRST='41' #calculate fees miner_fee = Decimal(miner_fee_satoshis) / Decimal(1e8) if to_address==None or to_address==from_address: #change goes to sender/receiver print "Single extra fee calculation" fee_total = Decimal(miner_fee) + Decimal(0.00005757*total_packets+0.00005757*total_outs) + Decimal(0.00005757) #exodus output is last else: #need 1 extra output for exodus and 1 for receiver. print "Double extra fee calculation" fee_total = Decimal(miner_fee) + Decimal(0.00005757*total_packets+0.00005757*total_outs) + Decimal(2*0.00005757) #exodus output is last fee_total_satoshi = int( round( fee_total * Decimal(1e8) ) ) #clean sx output, initial version by achamely utxo_list = [] #round so we aren't under fee amount dirty_txes = get_utxo( from_address, fee_total_satoshi ).replace(" ", "") if (dirty_txes[:3]=='Ass') or (dirty_txes[0][:3]=='Not'): raise Exception({ "status": "NOT OK", "error": "Not enough funds, try again. Needed: " + str(fee_total) }) for line in dirty_txes.splitlines(): utxo_list.append(line.split(':')) z = 0 total_amount=0 unspent_tx = [] for item in utxo_list: # unspent tx: [0] - txid; [1] - vout; [2] - amount; if utxo_list[z][0] == "output": unspent_tx.append( [ utxo_list[z][1] , utxo_list[z][2] ] ) if utxo_list[z][0] == "value": unspent_tx[-1] += [ int( utxo_list[z][1] ) ] total_amount += int( utxo_list[z][1] ) z += 1 # calculate change : # (total input amount) - (broadcast fee) change = total_amount - fee_total_satoshi #DEBUG print [ "Debugging...", dirty_txes,"miner fee sats: ", miner_fee_satoshis,"miner fee: ", miner_fee, "change: ",change,"total_amt: ", total_amount,"fee tot sat: ", fee_total_satoshi,"utxo ", unspent_tx,"total pax ", total_packets, "total outs ",total_outs,"to ", to_address ] #source script is needed to sign on the client credit grazcoin hash160=bc_address_to_hash_160(from_address).encode('hex_codec') prevout_script='OP_DUP OP_HASH160 ' + hash160 + ' OP_EQUALVERIFY OP_CHECKSIG' validnextinputs = [] #get valid redeemable inputs for unspent in unspent_tx: #retrieve raw transaction to spend it prev_tx = getrawtransaction(unspent[0]) for output in prev_tx.vout: if output['scriptPubKey']['reqSigs'] == 1 and output['scriptPubKey']['type'] != 'multisig': for address in output['scriptPubKey']['addresses']: if address == from_address and int(output['n']) == int(unspent[1]): validnextinputs.append({ "txid": prev_tx.txid, "vout": output['n']}) break global exodus_address validnextoutputs = { exodus_address: 0.00005757 } if to_address != None: validnextoutputs[to_address]=0.00005757 #Add for simple send if change >= 5757: # send anything above dust to yourself validnextoutputs[ from_address ] = float( Decimal(change)/Decimal(1e8) ) unsigned_raw_tx = createrawtransaction(validnextinputs, validnextoutputs) #DEBUG print change,unsigned_raw_tx json_tx = decoderawtransaction(unsigned_raw_tx) #append data structure ordered_packets = [] for i in range(total_outs): ordered_packets.append([]) #append actual packet index = 0 for i in range(total_outs): while len(ordered_packets[i]) < 2 and index != len(final_packets): ordered_packets[i].append(final_packets[index]) index = index + 1 #DEBUG print ordered_packets global magicbyte for i in range(total_outs): hex_string = "51" + HEXSPACE_FIRST + pubkey asm_string = "1 " + pubkey addresses = [ pybitcointools.pubkey_to_address(pubkey, magicbyte)] n_count = len(validnextoutputs)+i total_sig_count = 1 #DEBUG print [i,'added string', ordered_packets[i]] for packet in ordered_packets[i]: hex_string = hex_string + HEXSPACE_SECOND + packet.lower() asm_string = asm_string + " " + packet.lower() addresses.append(pybitcointools.pubkey_to_address(packet, magicbyte)) total_sig_count = total_sig_count + 1 hex_string = hex_string + "5" + str(total_sig_count) + "ae" asm_string = asm_string + " " + str(total_sig_count) + " " + "OP_CHECKMULTISIG" #DEBUG print ["hex string, asm string, addrs, total_sigs, ", hex_string, asm_string, addresses,total_sig_count] #add multisig output to json object json_tx['vout'].append( { "scriptPubKey": { "hex": hex_string, "asm": asm_string, "reqSigs": 1, "type": "multisig", "addresses": addresses }, "value": 0.00005757*len(addresses), "n": n_count }) #DEBUG import pprint #DEBUG print pprint.pprint(json_tx) #construct byte arrays for transaction #assert to verify byte lengths are OK version = ['01', '00', '00', '00' ] assert len(version) == 4 num_inputs = [str(len(json_tx['vin'])).rjust(2,"0")] assert len(num_inputs) == 1 num_outputs = [str(len(json_tx['vout'])).rjust(2,"0")] assert len(num_outputs) == 1 sequence = ['FF', 'FF', 'FF', 'FF'] assert len(sequence) == 4 blocklocktime = ['00', '00', '00', '00'] assert len(blocklocktime) == 4 #prepare inputs data for byte packing inputsdata = [] for _input in json_tx['vin']: prior_input_txhash = _input['txid'].upper() prior_input_index = str(hex(_input['vout'])[2:]).rjust(2,"0").ljust(8,"0") input_raw_signature = _input['scriptSig']['hex'] prior_txhash_bytes = [prior_input_txhash[ start: start + 2 ] for start in range(0, len(prior_input_txhash), 2)][::-1] assert len(prior_txhash_bytes) == 32 prior_txindex_bytes = [prior_input_index[ start: start + 2 ] for start in range(0, len(prior_input_index), 2)] assert len(prior_txindex_bytes) == 4 len_scriptsig = ['%02x' % len(''.join([]).decode('hex').lower())] assert len(len_scriptsig) == 1 inputsdata.append([prior_txhash_bytes, prior_txindex_bytes, len_scriptsig]) #prepare outputs for byte packing output_hex = [] for output in json_tx['vout']: value_hex = hex(int(float(output['value'])*1e8))[2:] value_hex = value_hex.rjust(16,"0") value_bytes = [value_hex[ start: start + 2 ].upper() for start in range(0, len(value_hex), 2)][::-1] assert len(value_bytes) == 8 # print output scriptpubkey_hex = output['scriptPubKey']['hex'] scriptpubkey_bytes = [scriptpubkey_hex[start:start + 2].upper() for start in range(0, len(scriptpubkey_hex), 2)] len_scriptpubkey = ['%02x' % len(''.join(scriptpubkey_bytes).decode('hex').lower())] #assert len(scriptpubkey_bytes) == 25 or len(scriptpubkey_bytes) == 71 output_hex.append([value_bytes, len_scriptpubkey, scriptpubkey_bytes] ) #join parts into final byte array hex_transaction = version + num_inputs for _input in inputsdata: hex_transaction += (_input[0] + _input[1] + _input[2] + sequence) hex_transaction += num_outputs for output in output_hex: hex_transaction = hex_transaction + (output[0] + output[1] + output[2]) hex_transaction = hex_transaction + blocklocktime #verify that transaction is valid decoded_tx = decoderawtransaction(''.join(hex_transaction).lower()); if 'txid' not in decoded_tx: raise Exception({ "status": "NOT OK", "error": "Network byte mismatch: Please try again" }) #DEBUG print 'final hex ', ''.join(hex_transaction).lower() #DEBUG print pprint.pprint(decoderawtransaction(''.join(hex_transaction).lower())) unsigned_hex=''.join(hex_transaction).lower() return [unsigned_hex, prevout_script]
def pubkey_to_address(self): return pybitcointools.pubkey_to_address(self.to_btc_pubkey())
msc_data_key = ''.join(map(lambda xor_target: hex(operator.xor(xor_target[0],xor_target[1]))[2:].rjust(2,"0"),zip(cleartext_bytes,shathesender_bytes))).upper() #map operation that xor's the bytes from cleartext and shathesender together #to obfuscate the cleartext packet, for more see Appendix Class B: #https://github.com/faizkhan00/spec#class-b-transactions-also-known-as-the-multisig-method obfuscated = "02" + msc_data_key + "00" #add key identifier and ecdsa byte to new mastercoin data key if testnet: data_pubkey = obfuscated[:-2] + hex(random.randint(0,255))[2:].rjust(2,"0").upper() else: invalid = True while invalid: obfuscated_randbyte = obfuscated[:-2] + hex(random.randint(0,255))[2:].rjust(2,"0").upper() #set the last byte to something random in case we generated an invalid pubkey potential_data_address = pybitcointools.pubkey_to_address(obfuscated_randbyte) if bool(conn.validateaddress(potential_data_address).isvalid): data_pubkey = obfuscated_randbyte invalid = False #make sure the public key is valid using pybitcointools, if not, regenerate #the last byte of the key and try again #### Build transaction #retrieve raw transaction to spend it prev_tx = conn.getrawtransaction(smallest_spendable_input['txid']) validnextinputs = [] #get valid redeemable inputs for output in prev_tx.vout: if output['scriptPubKey']['reqSigs'] == 1 and output['scriptPubKey']['type'] != 'multisig': for address in output['scriptPubKey']['addresses']:
def get_addr_from_pub(pubkey): # Multisignature addresses have the same prefix as pay2pubkey addresses return pubkey_to_address( pubkey, magicbyte=constants.PAY_TO_PUBKEY_VERSION_PREFIX)
def draw_line(filename, nums, x, y): num = nums['pub'] addr = pt.pubkey_to_address(num) draw_num(filename, addr[:8], x, y)
# Generate a WIF format from the compressed private key (WIF-compressed) wif_compressed_private_key = pybitcointools.encode_privkey( pybitcointools.decode_privkey(compressed_private_key, 'hex'), 'wif_compressed') print("Private Key (WIF-Compressed) is: ", wif_compressed_private_key) # Multiply the EC generator point G with the private key to get a public key point public_key = pybitcointools.fast_multiply(pybitcointools.G, decoded_private_key) print("Public Key (x,y) coordinates is:", public_key) # Encode as hex, prefix 04 hex_encoded_public_key = pybitcointools.encode_pubkey(public_key, 'hex') print("Public Key (hex) is:", hex_encoded_public_key) # Compress public key, adjust prefix depending on whether y is even or odd (public_key_x, public_key_y) = public_key compressed_prefix = '02' if (public_key_y % 2) == 0 else '03' hex_compressed_public_key = compressed_prefix + (pybitcointools.encode( public_key_x, 16).zfill(64)) print("Compressed Public Key (hex) is:", hex_compressed_public_key) # Generate pybitcointools address from public key print("pybitcointools Address (b58check) is:", pybitcointools.pubkey_to_address(public_key)) # Generate compressed pybitcointools address from compressed public key print("Compressed pybitcointools Address (b58check) is:", pybitcointools.pubkey_to_address(hex_compressed_public_key))
def script_to_destination_address(script): return pybitcointools.pubkey_to_address(script_to_pubkey(script))
def build_transaction( miner_fee_satoshis, pubkey, final_packets, total_packets, total_outs, from_address, to_address=None ): print "pubkey", pubkey, len(pubkey) if len(pubkey) < 100: print "Compressed Key, using hexspace 21" HEXSPACE_FIRST = "21" else: HEXSPACE_FIRST = "41" # calculate fees miner_fee = Decimal(miner_fee_satoshis) / Decimal(1e8) if to_address == None or to_address == from_address: # change goes to sender/receiver print "Single extra fee calculation" fee_total = ( Decimal(miner_fee) + Decimal(0.00005757 * total_packets + 0.00005757 * total_outs) + Decimal(0.00005757) ) # exodus output is last else: # need 1 extra output for exodus and 1 for receiver. print "Double extra fee calculation" fee_total = ( Decimal(miner_fee) + Decimal(0.00005757 * total_packets + 0.00005757 * total_outs) + Decimal(2 * 0.00005757) ) # exodus output is last fee_total_satoshi = int(round(fee_total * Decimal(1e8))) # ------------------------------------------- New utxo calls dirty_txes = bc_getutxo(from_address, fee_total_satoshi) if dirty_txes["error"][:3] == "Con": raise Exception( {"status": "NOT OK", "error": "Couldn't get list of unspent tx's. Response Code: " + dirty_txes["code"]} ) if dirty_txes["error"][:3] == "Low": raise Exception( { "status": "NOT OK", "error": "Not enough funds, try again. Needed: " + str(fee_total) + " but Have: " + dirty_txes["avail"], } ) total_amount = dirty_txes["avail"] unspent_tx = dirty_txes["utxos"] # ------------------------------------------- Old utxo calls # clean sx output, initial version by achamely # utxo_list = [] # round so we aren't under fee amount # dirty_txes = get_utxo( from_address, fee_total_satoshi ).replace(" ", "") # if (dirty_txes[:3]=='Ass') or (dirty_txes[0][:3]=='Not'): # raise Exception({ "status": "NOT OK", "error": "Not enough funds, try again. Needed: " + str(fee_total) }) # for line in dirty_txes.splitlines(): # utxo_list.append(line.split(':')) # z = 0 # total_amount=0 # unspent_tx = [] # for item in utxo_list: # # unspent tx: [0] - txid; [1] - vout; [2] - amount; # if utxo_list[z][0] == "output": # unspent_tx.append( [ utxo_list[z][1] , utxo_list[z][2] ] ) # if utxo_list[z][0] == "value": # unspent_tx[-1] += [ int( utxo_list[z][1] ) ] # total_amount += int( utxo_list[z][1] ) # z += 1 # ------------------------------------------- end Old utxo calls # calculate change : # (total input amount) - (broadcast fee) change = total_amount - fee_total_satoshi # DEBUG print [ "Debugging...", dirty_txes, "miner fee sats: ", miner_fee_satoshis, "miner fee: ", miner_fee, "change: ", change, "total_amt: ", total_amount, "fee tot sat: ", fee_total_satoshi, "utxo ", unspent_tx, "total pax ", total_packets, "total outs ", total_outs, "to ", to_address, ] # source script is needed to sign on the client credit grazcoin hash160 = bc_address_to_hash_160(from_address).encode("hex_codec") prevout_script = "OP_DUP OP_HASH160 " + hash160 + " OP_EQUALVERIFY OP_CHECKSIG" validnextinputs = [] # get valid redeemable inputs for unspent in unspent_tx: # retrieve raw transaction to spend it prev_tx = conn.getrawtransaction(unspent[0]) for output in prev_tx.vout: if output["scriptPubKey"]["reqSigs"] == 1 and output["scriptPubKey"]["type"] != "multisig": for address in output["scriptPubKey"]["addresses"]: if address == from_address and int(output["n"]) == int(unspent[1]): validnextinputs.append({"txid": prev_tx.txid, "vout": output["n"]}) break validnextoutputs = {exodus_address: 0.00005757} if to_address != None: validnextoutputs[to_address] = 0.00005757 # Add for simple send if change >= 5757: # send anything above dust to yourself validnextoutputs[from_address] = float(Decimal(change) / Decimal(1e8)) unsigned_raw_tx = conn.createrawtransaction(validnextinputs, validnextoutputs) # DEBUG print change,unsigned_raw_tx json_tx = conn.decoderawtransaction(unsigned_raw_tx) # append data structure ordered_packets = [] for i in range(total_outs): ordered_packets.append([]) # append actual packet index = 0 for i in range(total_outs): while len(ordered_packets[i]) < 2 and index != len(final_packets): ordered_packets[i].append(final_packets[index]) index = index + 1 # DEBUG print ordered_packets for i in range(total_outs): hex_string = "51" + HEXSPACE_FIRST + pubkey asm_string = "1 " + pubkey addresses = [pybitcointools.pubkey_to_address(pubkey, magicbyte)] n_count = len(validnextoutputs) + i total_sig_count = 1 # DEBUG print [i,'added string', ordered_packets[i]] for packet in ordered_packets[i]: hex_string = hex_string + HEXSPACE_SECOND + packet.lower() asm_string = asm_string + " " + packet.lower() addresses.append(pybitcointools.pubkey_to_address(packet, magicbyte)) total_sig_count = total_sig_count + 1 hex_string = hex_string + "5" + str(total_sig_count) + "ae" asm_string = asm_string + " " + str(total_sig_count) + " " + "OP_CHECKMULTISIG" # DEBUG print ["hex string, asm string, addrs, total_sigs, ", hex_string, asm_string, addresses, total_sig_count] # add multisig output to json object json_tx["vout"].append( { "scriptPubKey": { "hex": hex_string, "asm": asm_string, "reqSigs": 1, "type": "multisig", "addresses": addresses, }, "value": 0.00005757 * len(addresses), "n": n_count, } ) # DEBUG import pprint # DEBUG print pprint.pprint(json_tx) # construct byte arrays for transaction # assert to verify byte lengths are OK version = ["01", "00", "00", "00"] assert len(version) == 4 num_inputs = [str(len(json_tx["vin"])).rjust(2, "0")] assert len(num_inputs) == 1 num_outputs = [str(len(json_tx["vout"])).rjust(2, "0")] assert len(num_outputs) == 1 sequence = ["FF", "FF", "FF", "FF"] assert len(sequence) == 4 blocklocktime = ["00", "00", "00", "00"] assert len(blocklocktime) == 4 # prepare inputs data for byte packing inputsdata = [] for _input in json_tx["vin"]: prior_input_txhash = _input["txid"].upper() ihex = str(hex(_input["vout"])[2:]).rjust(2, "0") lhex = len(ihex) if lhex in [1, 2]: prior_input_index = ihex.ljust(8, "0") elif lhex in [3, 4]: prior_input_index = ihex[-2:].rjust(2, "0") + ihex[:-2].rjust(2, "0").ljust(6, "0") elif lhex in [5, 6]: prior_input_index = ( ihex[-2:].rjust(2, "0") + ihex[-4:-2].rjust(2, "0") + ihex[:-4].rjust(2, "0").ljust(4, "0") ) elif lhex in [7, 8]: prior_input_index = ( ihex[-2:].rjust(2, "0") + ihex[-4:-2].rjust(2, "0") + ihex[-6:-4].rjust(2, "0") + ihex[:-6].rjust(2, "0").ljust(2, "0") ) input_raw_signature = _input["scriptSig"]["hex"] prior_txhash_bytes = [prior_input_txhash[start : start + 2] for start in range(0, len(prior_input_txhash), 2)][ ::-1 ] assert len(prior_txhash_bytes) == 32 prior_txindex_bytes = [prior_input_index[start : start + 2] for start in range(0, len(prior_input_index), 2)] assert len(prior_txindex_bytes) == 4 len_scriptsig = ["%02x" % len("".join([]).decode("hex").lower())] assert len(len_scriptsig) == 1 inputsdata.append([prior_txhash_bytes, prior_txindex_bytes, len_scriptsig]) # prepare outputs for byte packing output_hex = [] for output in json_tx["vout"]: value_hex = hex(int(float(output["value"]) * 1e8))[2:] value_hex = value_hex.rjust(16, "0") value_bytes = [value_hex[start : start + 2].upper() for start in range(0, len(value_hex), 2)][::-1] assert len(value_bytes) == 8 # print output scriptpubkey_hex = output["scriptPubKey"]["hex"] scriptpubkey_bytes = [ scriptpubkey_hex[start : start + 2].upper() for start in range(0, len(scriptpubkey_hex), 2) ] len_scriptpubkey = ["%02x" % len("".join(scriptpubkey_bytes).decode("hex").lower())] # assert len(scriptpubkey_bytes) == 25 or len(scriptpubkey_bytes) == 71 output_hex.append([value_bytes, len_scriptpubkey, scriptpubkey_bytes]) # join parts into final byte array hex_transaction = version + num_inputs for _input in inputsdata: hex_transaction += _input[0] + _input[1] + _input[2] + sequence hex_transaction += num_outputs for output in output_hex: hex_transaction = hex_transaction + (output[0] + output[1] + output[2]) hex_transaction = hex_transaction + blocklocktime # verify that transaction is valid decoded_tx = conn.decoderawtransaction("".join(hex_transaction).lower()) if "txid" not in decoded_tx: raise Exception({"status": "NOT OK", "error": "Network byte mismatch: Please try again"}) # DEBUG print "final hex ", "".join(hex_transaction).lower() # DEBUG print pprint.pprint(conn.decoderawtransaction(''.join(hex_transaction).lower())) unsigned_hex = "".join(hex_transaction).lower() return [unsigned_hex, prevout_script]
def build_transaction(miner_fee_satoshis, pubkey, final_packets, total_packets, total_outs, from_address, to_address=None): print 'pubkey', pubkey, len(pubkey) if len(pubkey) < 100: print "Compressed Key, using hexspace 21" HEXSPACE_FIRST = '21' else: HEXSPACE_FIRST = '41' #calculate fees miner_fee = Decimal(miner_fee_satoshis) / Decimal(1e8) if to_address == None or to_address == from_address: #change goes to sender/receiver print "Single extra fee calculation" fee_total = Decimal(miner_fee) + Decimal( 0.00005757 * total_packets + 0.00005757 * total_outs) + Decimal( 0.00005757) #exodus output is last else: #need 1 extra output for exodus and 1 for receiver. print "Double extra fee calculation" fee_total = Decimal(miner_fee) + Decimal( 0.00005757 * total_packets + 0.00005757 * total_outs) + Decimal( 2 * 0.00005757) #exodus output is last fee_total_satoshi = int(round(fee_total * Decimal(1e8))) #------------------------------------------- New utxo calls dirty_txes = bc_getutxo(from_address, fee_total_satoshi) if (dirty_txes['error'][:3] == 'Con'): raise Exception({ "status": "NOT OK", "error": "Couldn't get list of unspent tx's. Response Code: " + dirty_txes['code'] }) if (dirty_txes['error'][:3] == 'Low'): raise Exception({ "status": "NOT OK", "error": "Not enough funds, try again. Needed: " + str(fee_total) + " but Have: " + dirty_txes['avail'] }) total_amount = dirty_txes['avail'] unspent_tx = dirty_txes['utxos'] #------------------------------------------- Old utxo calls #clean sx output, initial version by achamely #utxo_list = [] #round so we aren't under fee amount #dirty_txes = get_utxo( from_address, fee_total_satoshi ).replace(" ", "") #if (dirty_txes[:3]=='Ass') or (dirty_txes[0][:3]=='Not'): # raise Exception({ "status": "NOT OK", "error": "Not enough funds, try again. Needed: " + str(fee_total) }) #for line in dirty_txes.splitlines(): # utxo_list.append(line.split(':')) #z = 0 #total_amount=0 #unspent_tx = [] #for item in utxo_list: # # unspent tx: [0] - txid; [1] - vout; [2] - amount; # if utxo_list[z][0] == "output": # unspent_tx.append( [ utxo_list[z][1] , utxo_list[z][2] ] ) # if utxo_list[z][0] == "value": # unspent_tx[-1] += [ int( utxo_list[z][1] ) ] # total_amount += int( utxo_list[z][1] ) # z += 1 #------------------------------------------- end Old utxo calls # calculate change : # (total input amount) - (broadcast fee) change = total_amount - fee_total_satoshi #DEBUG print[ "Debugging...", dirty_txes, "miner fee sats: ", miner_fee_satoshis, "miner fee: ", miner_fee, "change: ", change, "total_amt: ", total_amount, "fee tot sat: ", fee_total_satoshi, "utxo ", unspent_tx, "total pax ", total_packets, "total outs ", total_outs, "to ", to_address ] #source script is needed to sign on the client credit grazcoin hash160 = bc_address_to_hash_160(from_address).encode('hex_codec') prevout_script = 'OP_DUP OP_HASH160 ' + hash160 + ' OP_EQUALVERIFY OP_CHECKSIG' validnextinputs = [] #get valid redeemable inputs for unspent in unspent_tx: #retrieve raw transaction to spend it prev_tx = conn.getrawtransaction(unspent[0]) for output in prev_tx.vout: if output['scriptPubKey']['reqSigs'] == 1 and output[ 'scriptPubKey']['type'] != 'multisig': for address in output['scriptPubKey']['addresses']: if address == from_address and int(output['n']) == int( unspent[1]): validnextinputs.append({ "txid": prev_tx.txid, "vout": output['n'] }) break validnextoutputs = {exodus_address: 0.00005757} if to_address != None: validnextoutputs[to_address] = 0.00005757 #Add for simple send if change >= 5757: # send anything above dust to yourself validnextoutputs[from_address] = float(Decimal(change) / Decimal(1e8)) unsigned_raw_tx = conn.createrawtransaction(validnextinputs, validnextoutputs) #DEBUG print change,unsigned_raw_tx json_tx = conn.decoderawtransaction(unsigned_raw_tx) #append data structure ordered_packets = [] for i in range(total_outs): ordered_packets.append([]) #append actual packet index = 0 for i in range(total_outs): while len(ordered_packets[i]) < 2 and index != len(final_packets): ordered_packets[i].append(final_packets[index]) index = index + 1 #DEBUG print ordered_packets for i in range(total_outs): hex_string = "51" + HEXSPACE_FIRST + pubkey asm_string = "1 " + pubkey addresses = [pybitcointools.pubkey_to_address(pubkey, magicbyte)] n_count = len(validnextoutputs) + i total_sig_count = 1 #DEBUG print [i,'added string', ordered_packets[i]] for packet in ordered_packets[i]: hex_string = hex_string + HEXSPACE_SECOND + packet.lower() asm_string = asm_string + " " + packet.lower() addresses.append( pybitcointools.pubkey_to_address(packet, magicbyte)) total_sig_count = total_sig_count + 1 hex_string = hex_string + "5" + str(total_sig_count) + "ae" asm_string = asm_string + " " + str( total_sig_count) + " " + "OP_CHECKMULTISIG" #DEBUG print[ "hex string, asm string, addrs, total_sigs, ", hex_string, asm_string, addresses, total_sig_count ] #add multisig output to json object json_tx['vout'].append({ "scriptPubKey": { "hex": hex_string, "asm": asm_string, "reqSigs": 1, "type": "multisig", "addresses": addresses }, "value": 0.00005757 * len(addresses), "n": n_count }) #DEBUG import pprint #DEBUG print pprint.pprint(json_tx) #construct byte arrays for transaction #assert to verify byte lengths are OK version = ['01', '00', '00', '00'] assert len(version) == 4 num_inputs = [str(len(json_tx['vin'])).rjust(2, "0")] assert len(num_inputs) == 1 num_outputs = [str(len(json_tx['vout'])).rjust(2, "0")] assert len(num_outputs) == 1 sequence = ['FF', 'FF', 'FF', 'FF'] assert len(sequence) == 4 blocklocktime = ['00', '00', '00', '00'] assert len(blocklocktime) == 4 #prepare inputs data for byte packing inputsdata = [] for _input in json_tx['vin']: prior_input_txhash = _input['txid'].upper() ihex = str(hex(_input['vout'])[2:]).rjust(2, "0") lhex = len(ihex) if lhex in [1, 2]: prior_input_index = ihex.ljust(8, "0") elif lhex in [3, 4]: prior_input_index = ihex[-2:].rjust(2, "0") + ihex[:-2].rjust( 2, "0").ljust(6, "0") elif lhex in [5, 6]: prior_input_index = ihex[-2:].rjust(2, "0") + ihex[-4:-2].rjust( 2, "0") + ihex[:-4].rjust(2, "0").ljust(4, "0") elif lhex in [7, 8]: prior_input_index = ihex[-2:].rjust(2, "0") + ihex[-4:-2].rjust( 2, "0") + ihex[-6:-4].rjust(2, "0") + ihex[:-6].rjust( 2, "0").ljust(2, "0") input_raw_signature = _input['scriptSig']['hex'] prior_txhash_bytes = [ prior_input_txhash[start:start + 2] for start in range(0, len(prior_input_txhash), 2) ][::-1] assert len(prior_txhash_bytes) == 32 prior_txindex_bytes = [ prior_input_index[start:start + 2] for start in range(0, len(prior_input_index), 2) ] assert len(prior_txindex_bytes) == 4 len_scriptsig = ['%02x' % len(''.join([]).decode('hex').lower())] assert len(len_scriptsig) == 1 inputsdata.append( [prior_txhash_bytes, prior_txindex_bytes, len_scriptsig]) #prepare outputs for byte packing output_hex = [] for output in json_tx['vout']: value_hex = hex(int(float(output['value']) * 1e8))[2:] value_hex = value_hex.rjust(16, "0") value_bytes = [ value_hex[start:start + 2].upper() for start in range(0, len(value_hex), 2) ][::-1] assert len(value_bytes) == 8 # print output scriptpubkey_hex = output['scriptPubKey']['hex'] scriptpubkey_bytes = [ scriptpubkey_hex[start:start + 2].upper() for start in range(0, len(scriptpubkey_hex), 2) ] len_scriptpubkey = [ '%02x' % len(''.join(scriptpubkey_bytes).decode('hex').lower()) ] #assert len(scriptpubkey_bytes) == 25 or len(scriptpubkey_bytes) == 71 output_hex.append([value_bytes, len_scriptpubkey, scriptpubkey_bytes]) #join parts into final byte array hex_transaction = version + num_inputs for _input in inputsdata: hex_transaction += (_input[0] + _input[1] + _input[2] + sequence) hex_transaction += num_outputs for output in output_hex: hex_transaction = hex_transaction + (output[0] + output[1] + output[2]) hex_transaction = hex_transaction + blocklocktime #verify that transaction is valid decoded_tx = conn.decoderawtransaction(''.join(hex_transaction).lower()) if 'txid' not in decoded_tx: raise Exception({ "status": "NOT OK", "error": "Network byte mismatch: Please try again" }) #DEBUG print 'final hex ', ''.join(hex_transaction).lower() #DEBUG print pprint.pprint(conn.decoderawtransaction(''.join(hex_transaction).lower())) unsigned_hex = ''.join(hex_transaction).lower() return [unsigned_hex, prevout_script]
def construct_packets(byte_stream, total_bytes, from_address): total_packets = int(math.ceil(float(total_bytes)/30)) #get # of packets total_outs = int(math.ceil(float(total_packets)/2)) #get # of outs #construct packets packets = [] index = 0 for i in range(total_packets): # 2 multisig data addrs per out, 60 bytes per, 2 characters per byte so 60 characters per pass parsed_data = byte_stream[index:index+60].ljust(60,"0") cleartext_packet = (hex(i+1)[2:].rjust(2,"0") + parsed_data.ljust(60,"0")) index = index+60 packets.append(cleartext_packet) #DEBUG print ['pax',cleartext_packet, parsed_data, total_packets, i] obfuscation_packets = [hashlib.sha256(from_address).hexdigest().upper()] #add first sha of sender to packet list for i in range(total_packets-1): #do rest for seqnums obfuscation_packets.append(hashlib.sha256(obfuscation_packets[i]).hexdigest().upper()) #DEBUG print [packets,obfuscation_packets, len(obfuscation_packets[0]), len(obfuscation_packets[1]), len(packets[0])] #obfuscate and prepare multisig outs pair_packets = [] for i in range(total_packets): obfuscation_packet = obfuscation_packets[i] pair_packets.append((packets[i], obfuscation_packet[:-2])) #encode the plaintext packets obfuscated_packets = [] for pair in pair_packets: plaintext = pair[0].upper() shaaddress = pair[1] #DEBUG print ['packets', plaintext, shaaddress, len(plaintext), len(shaaddress)] datapacket = '' for i in range(len(plaintext)): if plaintext[i] == '0': datapacket = datapacket + shaaddress[i] else: bin_plain = int('0x' + plaintext[i], 16) bin_sha = int('0x' + shaaddress[i], 16) #DEBUG print ['texts, plain & addr', plaintext[i], shaaddress[i],'bins, plain & addr', bin_plain, bin_sha ] xored = hex(bin_plain ^ bin_sha)[2:].upper() datapacket = datapacket + xored obfuscated_packets.append(( datapacket, shaaddress)) #### Test that the obfuscated packets produce the same output as the plaintext packet inputs #### #decode the obfuscated packet plaintext_packets = [] for pair in obfuscated_packets: obpacket = pair[0].upper() shaaddress = pair[1] #DEBUG print [obpacket, len(obpacket), shaaddress, len(shaaddress)] datapacket = '' for i in range(len(obpacket)): if obpacket[i] == shaaddress[i]: datapacket = datapacket + '0' else: bin_ob = int('0x' + obpacket[i], 16) bin_sha = int('0x' + shaaddress[i], 16) xored = hex(bin_ob ^ bin_sha)[2:].upper() datapacket = datapacket + xored plaintext_packets.append(datapacket) #check the packet is formed correctly by comparing it to the input final_packets = [] for i in range(len(plaintext_packets)): orig = packets[i] if orig.upper() != plaintext_packets[i]: print ['packet did not come out right', orig, plaintext_packets[i] ] else: final_packets.append(obfuscated_packets[i][0]) #DEBUG print plaintext_packets, obfuscation_packets,final_packets #add key identifier and ecdsa byte to new mastercoin data key global magicbyte for i in range(len(final_packets)): obfuscated = '02' + final_packets[i] + "00" #DEBUG print [obfuscated, len(obfuscated)] invalid = True while invalid: obfuscated_randbyte = obfuscated[:-2] + hex(random.randint(0,255))[2:].rjust(2,"0").upper() #set the last byte to something random in case we generated an invalid pubkey potential_data_address = pybitcointools.pubkey_to_address(obfuscated_randbyte, magicbyte) if bool(validateaddress(potential_data_address)["isvalid"]): final_packets[i] = obfuscated_randbyte invalid = False #make sure the public key is valid using pybitcointools, if not, regenerate #the last byte of the key and try again #DEBUG print final_packets return [final_packets,total_packets,total_outs]
cleartext_bytes = map(ord,cleartext_packet.decode('hex')) #convert to bytes for xor shathesender_bytes = map(ord,sha_the_sender.decode('hex')) #convert to bytes for xor msc_data_key = ''.join(map(lambda xor_target: hex(operator.xor(xor_target[0],xor_target[1]))[2:].rjust(2,"0"),zip(cleartext_bytes,shathesender_bytes))).upper() #map operation that xor's the bytes from cleartext and shathesender together #to obfuscate the cleartext packet, for more see Appendix Class B: #https://github.com/faizkhan00/spec#class-b-transactions-also-known-as-the-multisig-method obfuscated = "02" + msc_data_key + "00" #add key identifier and ecdsa byte to new mastercoin data key invalid = True while invalid: obfuscated_randbyte = obfuscated[:-2] + hex(random.randint(0,255))[2:].rjust(2,"0").upper() #set the last byte to something random in case we generated an invalid pubkey potential_data_address = pybitcointools.pubkey_to_address(obfuscated_randbyte) if bool(commands.getoutput('sx validaddr '+potential_data_address)): data_pubkey = obfuscated_randbyte invalid = False #make sure the public key is valid using pybitcointools, if not, regenerate #the last byte of the key and try again #### Build transaction #retrieve raw transaction data to spend it and add it to the input validnextinputs="" input_counter=0 for utxo in utxo_list: #prev_tx = json.loads(commands.getoutput('sx fetch-transaction '+utxo[0]+' | sx showtx -j')) try: prev_tx = json.loads(commands.getoutput('sx fetch-transaction '+utxo['tx_hash']+' | sx showtx -j')) except ValueError:
def build_transaction(final_packets, total_packets, total_outs, from_address): # calculate fees fee_total = Decimal(0.0001) + Decimal(0.00005757 * total_packets + 0.00005757 * total_outs) + Decimal(0.00005757) fee_total_satoshi = int(round(fee_total * Decimal(1e8))) pubkey = get_pubkey(from_address) # clean sx output, initial version by achamely utxo_list = [] # round so we aren't under fee amount dirty_txes = get_utxo(from_address, fee_total_satoshi).replace(" ", "") if (dirty_txes[:3] == "Ass") or (dirty_txes[0][:3] == "Not"): raise Exception({"status": "NOT OK", "error": "Not enough funds, try again. Needed: " + str(fee_total)}) for line in dirty_txes.splitlines(): utxo_list.append(line.split(":")) z = 0 total_amount = 0 unspent_tx = [] for item in utxo_list: # unspent tx: [0] - txid; [1] - vout; [2] - amount; if utxo_list[z][0] == "output": unspent_tx.append([utxo_list[z][1], utxo_list[z][2]]) if utxo_list[z][0] == "value": unspent_tx[-1] += [int(utxo_list[z][1])] total_amount += int(utxo_list[z][1]) z += 1 # calculate change : # (total input amount) - (broadcast fee) change = total_amount - fee_total_satoshi # DEBUG print[dirty_txes, change, total_amount, fee_total_satoshi, unspent_tx] # source script is needed to sign on the client credit grazcoin hash160 = bc_address_to_hash_160(from_address).encode("hex_codec") prevout_script = "OP_DUP OP_HASH160 " + hash160 + " OP_EQUALVERIFY OP_CHECKSIG" validnextinputs = [] # get valid redeemable inputs for unspent in unspent_tx: # retrieve raw transaction to spend it prev_tx = conn.getrawtransaction(unspent[0]) for output in prev_tx.vout: if output["scriptPubKey"]["reqSigs"] == 1 and output["scriptPubKey"]["type"] != "multisig": for address in output["scriptPubKey"]["addresses"]: if address == from_address: validnextinputs.append({"txid": prev_tx.txid, "vout": output["n"]}) validnextoutputs = {"1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P": 0.00005757} if change > Decimal(0.00005757): # send anything above dust to yourself validnextoutputs[from_address] = float(Decimal(change) / Decimal(1e8)) unsigned_raw_tx = conn.createrawtransaction(validnextinputs, validnextoutputs) # DEBUG print change,unsigned_raw_tx json_tx = conn.decoderawtransaction(unsigned_raw_tx) # append data structure ordered_packets = [] for i in range(total_outs): ordered_packets.append([]) # append actual packet index = 0 for i in range(total_outs): while len(ordered_packets[i]) < 2 and index != len(final_packets): ordered_packets[i].append(final_packets[index]) index = index + 1 # DEBUG print ordered_packets for i in range(total_outs): hex_string = "51" + HEXSPACE + pubkey asm_string = "1 " + pubkey addresses = [pybitcointools.pubkey_to_address(pubkey)] n_count = len(validnextoutputs) + i total_sig_count = 1 # DEBUG print [i,'added string', ordered_packets[i]] for packet in ordered_packets[i]: hex_string = hex_string + HEXSPACE + packet.lower() asm_string = asm_string + " " + packet.lower() addresses.append(pybitcointools.pubkey_to_address(packet)) total_sig_count = total_sig_count + 1 hex_string = hex_string + "5" + str(total_sig_count) + "ae" asm_string = asm_string + " " + str(total_sig_count) + " " + "OP_CHECKMULTISIG" # DEBUG print [hex_string, asm_string, addresses,total_sig_count] # add multisig output to json object json_tx["vout"].append( { "scriptPubKey": { "hex": hex_string, "asm": asm_string, "reqSigs": 1, "type": "multisig", "addresses": addresses, }, "value": 0.00005757 * len(addresses), "n": n_count, } ) # DEBUG import pprint # DEBUG print pprint.pprint(json_tx) # construct byte arrays for transaction # assert to verify byte lengths are OK version = ["01", "00", "00", "00"] assert len(version) == 4 num_inputs = [str(len(json_tx["vin"])).rjust(2, "0")] assert len(num_inputs) == 1 num_outputs = [str(len(json_tx["vout"])).rjust(2, "0")] assert len(num_outputs) == 1 sequence = ["FF", "FF", "FF", "FF"] assert len(sequence) == 4 blocklocktime = ["00", "00", "00", "00"] assert len(blocklocktime) == 4 # prepare inputs data for byte packing inputsdata = [] for _input in json_tx["vin"]: prior_input_txhash = _input["txid"].upper() prior_input_index = str(_input["vout"]).rjust(2, "0").ljust(8, "0") input_raw_signature = _input["scriptSig"]["hex"] prior_txhash_bytes = [prior_input_txhash[start : start + 2] for start in range(0, len(prior_input_txhash), 2)][ ::-1 ] assert len(prior_txhash_bytes) == 32 prior_txindex_bytes = [prior_input_index[start : start + 2] for start in range(0, len(prior_input_index), 2)] assert len(prior_txindex_bytes) == 4 len_scriptsig = ["%02x" % len("".join([]).decode("hex").lower())] assert len(len_scriptsig) == 1 inputsdata.append([prior_txhash_bytes, prior_txindex_bytes, len_scriptsig]) # prepare outputs for byte packing output_hex = [] for output in json_tx["vout"]: value_hex = hex(int(float(output["value"]) * 1e8))[2:] value_hex = value_hex.rjust(16, "0") value_bytes = [value_hex[start : start + 2].upper() for start in range(0, len(value_hex), 2)][::-1] assert len(value_bytes) == 8 # print output scriptpubkey_hex = output["scriptPubKey"]["hex"] scriptpubkey_bytes = [ scriptpubkey_hex[start : start + 2].upper() for start in range(0, len(scriptpubkey_hex), 2) ] len_scriptpubkey = ["%02x" % len("".join(scriptpubkey_bytes).decode("hex").lower())] # assert len(scriptpubkey_bytes) == 25 or len(scriptpubkey_bytes) == 71 output_hex.append([value_bytes, len_scriptpubkey, scriptpubkey_bytes]) # join parts into final byte array hex_transaction = version + num_inputs for _input in inputsdata: hex_transaction += _input[0] + _input[1] + _input[2] + sequence hex_transaction += num_outputs for output in output_hex: hex_transaction = hex_transaction + (output[0] + output[1] + output[2]) hex_transaction = hex_transaction + blocklocktime # verify that transaction is valid decoded_tx = conn.decoderawtransaction("".join(hex_transaction).lower()) if "txid" not in decoded_tx: raise Exception({"status": "NOT OK", "error": "Network byte mismatch: Please try again"}) # DEBUG print ''.join(hex_transaction).lower() # DEBUG print pprint.pprint(conn.decoderawtransaction(''.join(hex_transaction).lower())) unsigned_hex = "".join(hex_transaction).lower() return [unsigned_hex, prevout_script]
if orig.upper() != plaintext_packets[i]: print ['packet did not come out right', orig, plaintext_packets[i] ] else: final_packets.append(obfuscated_packets[i][0]) #DEBUG print plaintext_packets, obfuscation_packets,final_packets #add key identifier and ecdsa byte to new mastercoin data key for i in range(len(final_packets)): obfuscated = '02' + final_packets[i] + "00" #DEBUG print [obfuscated, len(obfuscated)] invalid = True while invalid: obfuscated_randbyte = obfuscated[:-2] + hex(random.randint(0,255))[2:].rjust(2,"0").upper() #set the last byte to something random in case we generated an invalid pubkey potential_data_address = pybitcointools.pubkey_to_address(obfuscated_randbyte) if bool(conn.validateaddress(potential_data_address).isvalid): final_packets[i] = obfuscated_randbyte invalid = False #make sure the public key is valid using pybitcointools, if not, regenerate #the last byte of the key and try again #DEBUG print final_packets #### Build transaction #calculate fees fee_total = Decimal(0.0001) + Decimal(0.000055*total_packets+0.000055*total_outs) + Decimal(0.000055) change = largest_spendable_input['amount'] - fee_total # calculate change : # (total input amount) - (broadcast fee)
def generate_tx(tx_type): # update this to support more transactions supported_transactions = [50, 51, 54, 55, 56, 0] if tx_type not in supported_transactions: return jsonify({"status": 400, "data": "Unsupported transaction type " + str(tx_type)}) expected_fields = ["transaction_version", "transaction_from", "pubkey", "fee"] print "Form ", request.form # might add tx 00, 53, etc later; if tx_type == 50: expected_fields += [ "ecosystem", "property_type", "previous_property_id", "property_category", "property_subcategory", "property_name", "property_url", "property_data", "number_properties", ] elif tx_type == 51: expected_fields += [ "ecosystem", "property_type", "previous_property_id", "property_category", "property_subcategory", "property_name", "property_url", "property_data", "currency_identifier_desired", "number_properties", "deadline", "earlybird_bonus", "percentage_for_issuer", ] elif tx_type == 54: expected_fields += [ "ecosystem", "property_type", "previous_property_id", "property_category", "property_subcategory", "property_name", "property_url", "property_data", ] elif tx_type == 0: expected_fields += ["currency_identifier", "amount_to_transfer", "transaction_to"] elif tx_type in [55, 56]: expected_fields += ["currency_identifier", "number_properties"] for field in expected_fields: if field not in request.form: return jsonify({"status": 403, "data": "No field in request form " + field}) elif request.form[field] == "": return jsonify({"status": 403, "data": "Empty field in request form " + field}) if "testnet" in request.form and (request.form["testnet"] in ["true", "True"]): global testnet testnet = True global magicbyte magicbyte = 111 global exodus_address exodus_address = testnet_exodus_address try: if config.D_PUBKEY and ("donate" in request.form) and (request.form["donate"] in ["true", "True"]): print "We're Donating to pubkey for: " + pybitcointools.pubkey_to_address(config.D_PUBKEY) pubkey = config.D_PUBKEY else: print "not donating" pubkey = request.form["pubkey"] except NameError, e: print e pubkey = request.form["pubkey"]