def recv_txio(self, nick, utxo_list, cj_pub, change_addr): if nick not in self.nonrespondants: debug('nick(' + nick + ') not in nonrespondants ' + str(self.nonrespondants)) return self.utxos[nick] = utxo_list order = self.db.execute('SELECT ordertype, txfee, cjfee FROM ' 'orderbook WHERE oid=? AND counterparty=?', (self.active_orders[nick], nick)).fetchone() utxo_data = common.bc_interface.query_utxo_set(self.utxos[nick]) if None in utxo_data: common.debug('ERROR outputs unconfirmed or already spent. utxo_data=' + pprint.pformat(utxo_data)) raise RuntimeError('killing taker, TODO handle this error') total_input = sum([d['value'] for d in utxo_data]) real_cjfee = calc_cj_fee(order['ordertype'], order['cjfee'], self.cj_amount) self.outputs.append({'address': change_addr, 'value': total_input - self.cj_amount - order['txfee'] + real_cjfee}) print 'fee breakdown for %s totalin=%d cjamount=%d txfee=%d realcjfee=%d' % (nick, total_input, self.cj_amount, order['txfee'], real_cjfee) cj_addr = btc.pubtoaddr(cj_pub, get_addr_vbyte()) self.outputs.append({'address': cj_addr, 'value': self.cj_amount}) self.cjfee_total += real_cjfee self.nonrespondants.remove(nick) if len(self.nonrespondants) > 0: debug('nonrespondants = ' + str(self.nonrespondants)) return debug('got all parts, enough to build a tx cjfeetotal=' + str(self.cjfee_total)) my_total_in = 0 for u, va in self.input_utxos.iteritems(): my_total_in += va['value'] #my_total_in = sum([va['value'] for u, va in self.input_utxos.iteritems()]) my_change_value = my_total_in - self.cj_amount - self.cjfee_total - self.my_txfee print 'fee breakdown for me totalin=%d txfee=%d cjfee_total=%d => changevalue=%d' % (my_total_in, self.my_txfee, self.cjfee_total, my_change_value) if self.my_change_addr == None: if my_change_value != 0 and abs(my_change_value) != 1: #seems you wont always get exactly zero because of integer rounding # so 1 satoshi extra or fewer being spent as miner fees is acceptable print 'WARNING CHANGE NOT BEING USED\nCHANGEVALUE = ' + str(my_change_value) else: self.outputs.append({'address': self.my_change_addr, 'value': my_change_value}) utxo_tx = [dict([('output', u)]) for u in sum(self.utxos.values(), [])] random.shuffle(utxo_tx) random.shuffle(self.outputs) tx = btc.mktx(utxo_tx, self.outputs) debug('obtained tx\n' + pprint.pformat(btc.deserialize(tx))) self.msgchan.send_tx(self.active_orders.keys(), tx) #now sign it ourselves here for index, ins in enumerate(btc.deserialize(tx)['ins']): utxo = ins['outpoint']['hash'] + ':' + str(ins['outpoint']['index']) if utxo not in self.input_utxos.keys(): continue addr = self.input_utxos[utxo]['address'] tx = btc.sign(tx, index, self.wallet.get_key_from_addr(addr)) self.latest_tx = btc.deserialize(tx)
def sign_tx(self, tx, i, priv): if self.my_cj_addr: return btc.sign(tx, i, priv) else: return btc.sign(tx, i, priv, usenonce=btc.safe_from_hex(self.sign_k))
def recv_tx(self, nick, txhex): try: self.tx = btc.deserialize(txhex) except IndexError as e: self.maker.msgchan.send_error(nick, 'malformed txhex. ' + repr(e)) log.debug('obtained tx\n' + pprint.pformat(self.tx)) goodtx, errmsg = self.verify_unsigned_tx(self.tx) if not goodtx: log.debug('not a good tx, reason=' + errmsg) self.maker.msgchan.send_error(nick, errmsg) # TODO: the above 3 errors should be encrypted, but it's a bit messy. log.debug('goodtx') sigs = [] for index, ins in enumerate(self.tx['ins']): utxo = ins['outpoint']['hash'] + ':' + str( ins['outpoint']['index']) if utxo not in self.utxos: continue addr = self.utxos[utxo]['address'] txs = btc.sign(txhex, index, self.maker.wallet.get_key_from_addr(addr)) sigs.append( base64.b64encode( btc.deserialize(txs)['ins'][index]['script'].decode( 'hex'))) # len(sigs) > 0 guarenteed since i did verify_unsigned_tx() jm_single().bc_interface.add_tx_notify(self.tx, self.unconfirm_callback, self.confirm_callback, self.cj_addr) log.debug('sending sigs ' + str(sigs)) self.maker.msgchan.send_sigs(nick, sigs) self.maker.active_orders[nick] = None
def tx_sign_input(blockstack_tx, idx, private_key_info, hashcode=bitcoin.SIGHASH_ALL): """ Sign a particular input in the given transaction. @private_key_info can either be a private key, or it can be a dict with 'redeem_script' and 'private_keys' defined """ if type(private_key_info) in [str, unicode]: # single private key return bitcoin.sign(blockstack_tx, idx, virtualchain.BitcoinPrivateKey( str(private_key_info)).to_hex(), hashcode=hashcode) else: assert type(private_key_info) in [dict] assert "redeem_script" in private_key_info assert "private_keys" in private_key_info redeem_script = private_key_info['redeem_script'] private_keys = private_key_info['private_keys'] assert type(redeem_script) in [str, unicode] redeem_script = str(redeem_script) # multisig return tx_sign_multisig(blockstack_tx, idx, str(redeem_script), private_keys, hashcode=bitcoin.SIGHASH_ALL)
def tx_serialize_and_sign_multi( inputs, outputs, private_keys ): """ Given a list of inputs, outputs, private keys, and optionally a partially-signed transaction: * make a transaction out of the inputs and outputs * sign input[i] with private_key[i] Return the signed tx on success """ if len(inputs) != len(private_keys): raise Exception("Must have the same number of private keys as inputs") private_key_objs = [] for pk in private_keys: if isinstance( pk, pybitcoin.BitcoinPrivateKey ): private_key_objs.append( pk ) else: private_key_objs.append( pybitcoin.BitcoinPrivateKey( pk ) ) # make the transaction unsigned_tx = pybitcoin.serialize_transaction( inputs, outputs ) # sign with the appropriate private keys for i in xrange(0, len(inputs)): signed_tx = bitcoin.sign( unsigned_tx, i, private_key_objs[i].to_hex() ) unsigned_tx = signed_tx return unsigned_tx
def make_sign_and_push( ins_full, wallet, amount, output_addr=None, change_addr=None, hashcode=btc.SIGHASH_ALL, estimate_fee=False ): """Utility function for easily building transactions from wallets """ total = sum(x["value"] for x in ins_full.values()) ins = ins_full.keys() # random output address and change addr output_addr = wallet.get_new_addr(1, 1) if not output_addr else output_addr change_addr = wallet.get_new_addr(1, 0) if not change_addr else change_addr fee_est = estimate_tx_fee(len(ins), 2) if estimate_fee else 10000 outs = [{"value": amount, "address": output_addr}, {"value": total - amount - fee_est, "address": change_addr}] tx = btc.mktx(ins, outs) de_tx = btc.deserialize(tx) for index, ins in enumerate(de_tx["ins"]): utxo = ins["outpoint"]["hash"] + ":" + str(ins["outpoint"]["index"]) addr = ins_full[utxo]["address"] priv = wallet.get_key_from_addr(addr) if index % 2: priv = binascii.unhexlify(priv) tx = btc.sign(tx, index, priv, hashcode=hashcode) # pushtx returns False on any error print btc.deserialize(tx) push_succeed = jm_single().bc_interface.pushtx(tx) if push_succeed: return btc.txhash(tx) else: return False
def build_raw_tx(prev_tx_id, prev_out_index, src_btc_addr, value, dest_btc_addr, scriptPubKey=None, scriptSig=None): assert len(prev_tx_id) == len(prev_out_index) == len(src_btc_addr) assert len(value) == len(dest_btc_addr) if scriptPubKey is None: scriptPubKey = [] for i in range(len(dest_btc_addr)): scriptPubKey.append(generate_std_scriptpubkey(dest_btc_addr[i])) else: assert len(scriptPubKey) == len(dest_btc_addr) tx = TX() if scriptSig is None: tx.build_p2pkh_std_tx(prev_tx_id, prev_out_index, value, scriptPubKey) raw_tx = tx.hex for i in range(len(src_btc_addr)): priv_key = src_btc_addr[i] + "/sk.pem" priv_key_hex = get_priv_key_hex(priv_key) raw_tx = sign(raw_tx, i, priv_key_hex) else: assert len(scriptPubKey) == len(src_btc_addr) tx.build_p2pkh_std_tx(prev_tx_id, prev_out_index, value, scriptPubKey, scriptSig) raw_tx = tx.hex return raw_tx
def make_tx_add_notify(): wallet_dict = make_wallets(1, [[1, 0, 0, 0, 0]], mean_amt=4, sdev_amt=0)[0] amount = 250000000 txfee = 10000 wallet = wallet_dict['wallet'] sync_wallet(wallet) inputs = wallet.select_utxos(0, amount) ins = inputs.keys() input_value = sum([i['value'] for i in inputs.values()]) output_addr = wallet.get_new_addr(1, 0) change_addr = wallet.get_new_addr(0, 1) outs = [{ 'value': amount, 'address': output_addr }, { 'value': input_value - amount - txfee, 'address': change_addr }] tx = btc.mktx(ins, outs) de_tx = btc.deserialize(tx) for index, ins in enumerate(de_tx['ins']): utxo = ins['outpoint']['hash'] + ':' + str(ins['outpoint']['index']) addr = inputs[utxo]['address'] priv = wallet.get_key_from_addr(addr) tx = btc.sign(tx, index, priv) unconfirm_called[0] = confirm_called[0] = False timeout_unconfirm_called[0] = timeout_confirm_called[0] = False jm_single().bc_interface.add_tx_notify(btc.deserialize(tx), unconfirm_callback, confirm_callback, output_addr, timeout_callback) return tx
def mk_spend_txids(wallet, dst, amount, h): l = len(h) outs = [{'value': int(amount), 'address': dst}] tx = b.mksend(h, outs, wallet["address"], fee) for i in range(l): tx = b.sign(tx, i, wallet["priv"]) return (tx)
def tx_serialize_and_sign_multi(inputs, outputs, private_keys): """ Given a list of inputs, outputs, private keys, and optionally a partially-signed transaction: * make a transaction out of the inputs and outputs * sign input[i] with private_key[i] Return the signed tx on success """ if len(inputs) != len(private_keys): raise Exception("Must have the same number of private keys as inputs") private_key_objs = [] for pk in private_keys: if isinstance(pk, pybitcoin.BitcoinPrivateKey): private_key_objs.append(pk) else: private_key_objs.append(pybitcoin.BitcoinPrivateKey(pk)) # make the transaction unsigned_tx = pybitcoin.serialize_transaction(inputs, outputs) # sign with the appropriate private keys for i in xrange(0, len(inputs)): signed_tx = bitcoin.sign(unsigned_tx, i, private_key_objs[i].to_hex()) unsigned_tx = signed_tx return unsigned_tx
def recv_tx(self, nick, txhex): try: self.tx = btc.deserialize(txhex) except IndexError as e: self.maker.msgchan.send_error(nick, 'malformed txhex. ' + repr(e)) log.info('obtained tx\n' + pprint.pformat(self.tx)) goodtx, errmsg = self.verify_unsigned_tx(self.tx) if not goodtx: log.info('not a good tx, reason=' + errmsg) self.maker.msgchan.send_error(nick, errmsg) # TODO: the above 3 errors should be encrypted, but it's a bit messy. log.info('goodtx') sigs = [] for index, ins in enumerate(self.tx['ins']): utxo = ins['outpoint']['hash'] + ':' + str(ins['outpoint']['index']) if utxo not in self.utxos: continue addr = self.utxos[utxo]['address'] txs = btc.sign(txhex, index, self.maker.wallet.get_key_from_addr(addr)) sigs.append(base64.b64encode(btc.deserialize(txs)['ins'][index][ 'script'].decode('hex'))) # len(sigs) > 0 guarenteed since i did verify_unsigned_tx() jm_single().bc_interface.add_tx_notify( self.tx, self.unconfirm_callback, self.confirm_callback, self.cj_addr) self.maker.msgchan.send_sigs(nick, sigs) self.maker.active_orders[nick] = None
def create_tx(self, from_account, to_addr, amount, fee=0): ''' Create a serialized transaction from funds under 'from_account' returns signed serialized tx ''' spendables = self.get_utxo(from_account, amount + fee) if not spendables: raise Exception("Account is empty or amount to send is 0") assert (fee >= 0 and amount > 0) keys = [] total = 0 for sp in spendables: keys.append( self.get_key(sp['key_info'][0], sp['key_info'][1], sp['key_info'][2])) total += sp['value'] del sp['key_info'] change_addr = self.new_address(from_account, change=1) payables = [{ 'value': amount, 'address': to_addr }, { 'value': total - fee - amount, 'address': change_addr }] tx = mktx(spendables, payables) for i, key in enumerate(keys): priv = key.get_private_key().hex() tx = sign(tx, i, priv) return tx
def build_tx(inputs, priv, addr, script, fee=0, send=False): """ Build a transaction to post/cancel a book sale Args: inputs (list): list of UTXOs to use. Obtained with bitcoin.unspent() priv (str): private key for wallet addr (str): address to post sale to script (str): script with encoded message of sale/cancelation fee (int): satoshis to pay to miners to write to the blockchain There is no reason to do this. send (bool): if True, send to mempool Returns: signed_tx (str): signed transaction to send to mempool also, sends transaction to mempool """ outputs = [{ 'value': 546, 'address': settings.MARKET_ADDRESS }, { 'value': 0, 'script': script }] fee = fee tx = bitcoin.mksend(inputs, outputs, addr, fee) signed_tx = bitcoin.sign(tx, 0, priv) if send: bitcoin.pushtx(signed_tx) return signed_tx
def segwit_sign(tx, i, priv, amount, hashcode=SIGHASH_ALL, script=None, separator_index=None): i = int(i) txobj = tx if isinstance(tx, dict) else deserialize(tx) if not isinstance(tx, dict) and ((not is_python2 and isinstance(re, bytes)) or not re.match('^[0-9a-fA-F]*$', tx)): return binascii.unhexlify(sign(binascii.hexlify(tx), i, priv)) if len(priv) <= 33: priv = binascii.hexlify(priv) pub = privkey_to_pubkey(priv) address = pubkey_to_address(pub) wscript = mk_pubkey_script(address) if not script else script stripped_script = segwit_strip_script_separator(wscript, separator_index) signing_tx = segwit_signature_form(tx, i, stripped_script, amount, hashcode=hashcode) rawsig = ecdsa_raw_sign( hashlib.sha256( hashlib.sha256( binascii.unhexlify(signing_tx)).digest()).hexdigest(), priv) sig = der_encode_sig(*rawsig) + encode(hashcode, 16, 2) txobj['ins'][i]['txinwitness'] = [sig, pub if not script else script] return serialize(txobj)
def mk_spend_txids(wallet, dst, amount, h): l=len(h) outs = [{'value': int(amount), 'address': dst}] tx = b.mksend(h,outs, wallet["address"], fee) for i in range(l): tx=b.sign(tx, i, wallet["priv"]) return(tx)
def make_sign_and_push(ins_full, wallet, amount, output_addr=None, change_addr=None, hashcode=btc.SIGHASH_ALL): total = sum(x['value'] for x in ins_full.values()) ins = ins_full.keys() #random output address and change addr output_addr = wallet.get_new_addr(1, 1) if not output_addr else output_addr change_addr = wallet.get_new_addr(1, 0) if not change_addr else change_addr outs = [{'value': amount, 'address': output_addr}, {'value': total - amount - 100000, 'address': change_addr}] tx = btc.mktx(ins, outs) de_tx = btc.deserialize(tx) for index, ins in enumerate(de_tx['ins']): utxo = ins['outpoint']['hash'] + ':' + str(ins['outpoint']['index']) addr = ins_full[utxo]['address'] priv = wallet.get_key_from_addr(addr) if index % 2: priv = binascii.unhexlify(priv) tx = btc.sign(tx, index, priv, hashcode=hashcode) #pushtx returns False on any error print btc.deserialize(tx) push_succeed = jm_single().bc_interface.pushtx(tx) if push_succeed: return btc.txhash(tx) else: return False
def tx_serialize_subsidized_tx(blockstore_tx, payer_privkey_hex, payer_utxo_inputs, payer_address, dust_fee, op_fee): """ Make a signed serialized transaction with the given operation and dust fees """ tx_inputs, tx_outputs, locktime, version = tx_deserialize(blockstore_tx) subsidy_output = tx_make_subsidization_output(payer_utxo_inputs, payer_address, op_fee, dust_fee) # add our inputs and output subsidized_tx = tx_extend(blockstore_tx, payer_utxo_inputs, [subsidy_output]) # sign each of our inputs with our key, but use SIGHASH_ANYONECANPAY so the client can sign its inputs for i in xrange(0, len(payer_utxo_inputs)): idx = i + len(tx_inputs) subsidized_tx = bitcoin.sign(subsidized_tx, idx, payer_privkey_hex, hashcode=bitcoin.SIGHASH_ANYONECANPAY) return subsidized_tx
def make_tx_add_notify(): wallet_dict = make_wallets(1, [[1, 0, 0, 0, 0]], mean_amt=4, sdev_amt=0)[0] amount = 250000000 txfee = 10000 wallet = wallet_dict['wallet'] sync_wallet(wallet) inputs = wallet.select_utxos(0, amount) ins = inputs.keys() input_value = sum([i['value'] for i in inputs.values()]) output_addr = wallet.get_new_addr(1, 0) change_addr = wallet.get_new_addr(0, 1) outs = [{'value': amount, 'address': output_addr}, {'value': input_value - amount - txfee, 'address': change_addr}] tx = btc.mktx(ins, outs) de_tx = btc.deserialize(tx) for index, ins in enumerate(de_tx['ins']): utxo = ins['outpoint']['hash'] + ':' + str(ins['outpoint']['index']) addr = inputs[utxo]['address'] priv = wallet.get_key_from_addr(addr) tx = btc.sign(tx, index, priv) unconfirm_called[0] = confirm_called[0] = False timeout_unconfirm_called[0] = timeout_confirm_called[0] = False jm_single().bc_interface.add_tx_notify( btc.deserialize(tx), unconfirm_callback, confirm_callback, output_addr, timeout_callback) return tx
def send_whole_wallet(fromprivkey, toaddr): transaction_fee = 20000 # .0002 BTC fromaddress = bitcoin.privtoaddr(fromprivkey) balance = sum(transaction['value'] for transaction in bitcoin.unspent(fromaddress)) assert balance >= transaction_fee tx = bitcoin.mktx(bitcoin.history(fromaddress), [{'value': balance - transaction_fee, 'address': toaddr}]) signed_tx = bitcoin.sign(tx, 0, fromprivkey) bitcoin.pushtx(signed_tx)
def send(fromprivkey, toaddr, value): transaction_fee = 20000 print "Sending:", fromprivkey, toaddr, value tx = bitcoin.mksend(bitcoin.history(bitcoin.privtoaddr(fromprivkey)), [toaddr + ":" + str(value)], bitcoin.privtoaddr(fromprivkey), transaction_fee) signed_tx = bitcoin.sign(tx, 0, fromprivkey) bitcoin.pushtx(signed_tx)
def sendtx(key_info, op_return=''): addr, privkey = key_info confirmed_balance, inputs, unconfirmed = getbalance(addr) amount = confirmed_balance if not confirmed_balance >= amount: msg = "Balance insuficiente" else: # Transformar valores a Chatoshis used_amount = int(amount * COIN) # Utilizar solo las unspent que se necesiten used_balance = 0 used_inputs = [] for i in inputs: used_balance += i['value'] used_inputs.append(i) if used_balance > used_amount: break used_fee = int((base_fee + fee_per_input * len(inputs)) * COIN) # Output outputs = [] # Receptor if used_balance == used_amount: outputs.append({ 'address': addr, 'value': (used_amount - used_fee) }) else: outputs.append({'address': addr, 'value': used_amount}) # Change if used_balance > used_amount + used_fee: outputs.append({ 'address': addr, 'value': int(used_balance - used_amount - used_fee) }) # OP_RETURN if len(op_return) > 0 and len(op_return) <= 255: payload = OP_RETURN_payload(op_return) script = '6a' + b2a_hex(payload).decode('utf-8', errors='ignore') outputs.append({'value': 0, 'script': script}) # Transacción tx = mktx(used_inputs, outputs) # Firma for i in range(len(used_inputs)): tx = sign(tx, i, privkey) msg = tx return msg
def send(fromprivkey, toaddr, value): transaction_fee = 20000 # .0002 BTC fromaddress = bitcoin.privtoaddr(fromprivkey) tx = bitcoin.mksend(bitcoin.history(fromaddress), [{ 'value': value, 'address': toaddr }], fromaddress, transaction_fee) signed_tx = bitcoin.sign(tx, 0, fromprivkey) bitcoin.pushtx(signed_tx)
def test_p2p_broadcast(setup_tx_notify): #listen up kids, dont do this to generate private #keys that hold real money, or else you'll be robbed src_privkey = random.getrandbits(256) src_privkey = btc.encode(src_privkey, 16, 64) + '01' src_addr = btc.privtoaddr(src_privkey, magicbyte=get_p2pk_vbyte()) dst_addr = btc.pubtoaddr('03' + btc.encode(random.getrandbits(256), 16), get_p2pk_vbyte()) jm_single().bc_interface.rpc('importaddress', [src_addr, "", False]) jm_single().bc_interface.rpc('importaddress', [dst_addr, "", False]) jm_single().bc_interface.rpc('generatetoaddress', [1, src_addr]) jm_single().bc_interface.rpc('generate', [101]) src_utxos = jm_single().bc_interface.rpc('listunspent', [0, 500, [src_addr]]) inputs = [{ 'output': src_utxos[0]['txid'] + ':' + str(src_utxos[0]['vout']) }] miner_fee = 10000 outs = [{ 'address': dst_addr, 'value': int(src_utxos[0]['amount'] * 1e8) - miner_fee }] tx = btc.mktx(inputs, outs) tx = btc.sign(tx, 0, src_privkey) bad_tx = random.getrandbits(len(tx) * 4) bad_tx = btc.encode(bad_tx, 16, len(tx)) utxo_before = jm_single().bc_interface.rpc('listunspent', [0, 500, [dst_addr]]) #jm_single().bc_interface.rpc('sendrawtransaction', [tx]) pushed = tor_broadcast_tx(tx, None, 'regtest', remote_hostport=('localhost', 18444)) assert pushed pushed = tor_broadcast_tx(tx, None, 'regtest', remote_hostport=('localhost', 18444)) assert not pushed #node should already have the same tx, reject pushed = tor_broadcast_tx(bad_tx, None, 'regtest', remote_hostport=('localhost', 18444)) assert not pushed #bad tx should be rejected jm_single().bc_interface.rpc('generate', [1]) utxo_after = jm_single().bc_interface.rpc('listunspent', [0, 500, [dst_addr]]) return len(utxo_after) - 1 == len(utxo_before)
def direct_send(wallet, amount, mixdepth, destaddr, answeryes=False): """Send coins directly from one mixdepth to one destination address; does not need IRC. Sweep as for normal sendpayment (set amount=0). """ #Sanity checks; note destaddr format is carefully checked in startup assert isinstance(mixdepth, int) assert mixdepth >= 0 assert isinstance(amount, int) assert amount >= 0 and amount < 10000000000 assert isinstance(wallet, Wallet) import bitcoin as btc from pprint import pformat if amount == 0: utxos = wallet.get_utxos_by_mixdepth()[mixdepth] if utxos == {}: log.error("There are no utxos in mixdepth: " + str(mixdepth) + ", quitting.") return total_inputs_val = sum([va['value'] for u, va in utxos.iteritems()]) fee_est = estimate_tx_fee(len(utxos), 1) outs = [{"address": destaddr, "value": total_inputs_val - fee_est}] else: initial_fee_est = estimate_tx_fee(8, 2) #8 inputs to be conservative utxos = wallet.select_utxos(mixdepth, amount + initial_fee_est) if len(utxos) < 8: fee_est = estimate_tx_fee(len(utxos), 2) else: fee_est = initial_fee_est total_inputs_val = sum([va['value'] for u, va in utxos.iteritems()]) changeval = total_inputs_val - fee_est - amount outs = [{"value": amount, "address": destaddr}] change_addr = wallet.get_internal_addr(mixdepth) outs.append({"value": changeval, "address": change_addr}) #Now ready to construct transaction log.info("Using a fee of : " + str(fee_est) + " satoshis.") if amount != 0: log.info("Using a change value of: " + str(changeval) + " satoshis.") tx = btc.mktx(utxos.keys(), outs) stx = btc.deserialize(tx) for index, ins in enumerate(stx['ins']): utxo = ins['outpoint']['hash'] + ':' + str(ins['outpoint']['index']) addr = utxos[utxo]['address'] tx = btc.sign(tx, index, wallet.get_key_from_addr(addr)) txsigned = btc.deserialize(tx) log.info("Got signed transaction:\n") log.info(tx + "\n") log.info(pformat(txsigned)) if not answeryes: if raw_input( 'Would you like to push to the network? (y/n):')[0] != 'y': log.info("You chose not to broadcast the transaction, quitting.") return jm_single().bc_interface.pushtx(tx) txid = btc.txhash(tx) log.info("Transaction sent: " + txid + ", shutting down")
def tx_sign_all_unsigned_inputs( tx_hex, privkey ): """ Sign a serialized transaction's unsigned inputs """ inputs, outputs, locktime, version = blockstore.tx_deserialize( tx_hex ) for i in xrange( 0, len(inputs)): if len(inputs[i]['script_sig']) == 0: tx_hex = bitcoin.sign( tx_hex, i, privkey ) return tx_hex
def tx_sign_all_unsigned_inputs(tx_hex, privkey): """ Sign a serialized transaction's unsigned inputs """ inputs, outputs, locktime, version = blockstore.tx_deserialize(tx_hex) for i in xrange(0, len(inputs)): if len(inputs[i]['script_sig']) == 0: tx_hex = bitcoin.sign(tx_hex, i, privkey) return tx_hex
def sign_tx(unsigned_raw_tx, privatekey): tx2 = unsigned_raw_tx detx = bitcoin.deserialize(tx2) input_length = len(detx['ins']) for i in range(0, input_length): tx2 = bitcoin.sign(tx2, i, privatekey) return tx2
def self_sign(self): #now sign it ourselves tx = btc.serialize(self.latest_tx) for index, ins in enumerate(self.latest_tx['ins']): utxo = ins['outpoint']['hash'] + ':' + str(ins['outpoint']['index']) if utxo not in self.input_utxos.keys(): continue addr = self.input_utxos[utxo]['address'] tx = btc.sign(tx, index, self.wallet.get_key_from_addr(addr)) self.latest_tx = btc.deserialize(tx)
def self_sign(self): #now sign it ourselves tx = btc.serialize(self.latest_tx) for index, ins in enumerate(self.latest_tx['ins']): utxo = ins['outpoint']['hash'] + ':' + str( ins['outpoint']['index']) if utxo not in self.input_utxos.keys(): continue addr = self.input_utxos[utxo]['address'] tx = btc.sign(tx, index, self.wallet.get_key_from_addr(addr)) self.latest_tx = btc.deserialize(tx)
def send_whole_wallet(fromprivkey, toaddr): transaction_fee = 20000 # .0002 BTC fromaddress = bitcoin.privtoaddr(fromprivkey) balance = sum(transaction['value'] for transaction in bitcoin.unspent(fromaddress)) assert balance >= transaction_fee tx = bitcoin.mktx(bitcoin.history(fromaddress), [{ 'value': balance - transaction_fee, 'address': toaddr }]) signed_tx = bitcoin.sign(tx, 0, fromprivkey) bitcoin.pushtx(signed_tx)
def create_tx(username, form, op_return=''): privkey, address = get_keychain(username) unspent = get_unspent(address) inputs = unspent['inputs'] balance = int(float(unspent['confirmed']) * 1e8) amount = int(float(form.amount.data) * 1e8) receptor = form.address.data if check_addr(receptor): return "Dirección inválida" elif amount > balance: return "Balance insuficiente" elif amount <= 0: return "Monto inválido" used_utxo = 0 used_inputs = [] for utxo in inputs: used_utxo += utxo['value'] used_inputs.append(utxo) if used_utxo >= amount: break outputs = [{'address': receptor, 'value': amount}] template_tx = mktx(used_inputs, outputs) # size = unsigned tx + (65 bytes * signature) size = len(a2b_hex(template_tx)) + 65 * len(used_inputs) # FEE = 0.01 CHA/kb fee = int((size / 1024) * 0.01 * 1e8) # MAX FEE = 0.1 CHA fee = 1e7 if fee > 1e7 else fee if used_utxo == amount: outputs[0] = {'address': receptor, 'value': int(amount - fee)} tx = mksend(used_inputs, outputs, address, fee) for i, _ in enumerate(used_inputs): tx = sign(tx, i, privkey) return tx
def tx_make_subsidizable(blockstack_tx, fee_cb, max_fee, subsidy_key, utxo_client): """ Given an unsigned serialized transaction from Blockstack, make it into a subsidized transaction for the client to go sign off on. * Add subsidization inputs/outputs * Make sure the subsidy does not exceed the maximum subsidy fee * Sign our inputs with SIGHASH_ANYONECANPAY """ # get subsidizer key info private_key_obj, payer_address, payer_utxo_inputs = analyze_private_key( subsidy_key, utxo_client) tx_inputs, tx_outputs, locktime, version = tx_deserialize(blockstack_tx) # what's the fee? does it exceed the subsidy? dust_fee, op_fee = fee_cb(tx_inputs, tx_outputs) if dust_fee is None or op_fee is None: log.error("Invalid fee structure") return None if dust_fee + op_fee > max_fee: log.error("Op fee (%s) + dust fee (%s) exceeds maximum subsidy %s" % (dust_fee, op_fee, max_fee)) return None else: log.debug( "%s will subsidize %s satoshi" % (pybitcoin.BitcoinPrivateKey(subsidy_key).public_key().address(), dust_fee + op_fee)) subsidy_output = tx_make_subsidization_output(payer_utxo_inputs, payer_address, op_fee, dust_fee) # add our inputs and output subsidized_tx = tx_extend(blockstack_tx, payer_utxo_inputs, [subsidy_output]) # sign each of our inputs with our key, but use SIGHASH_ANYONECANPAY so the client can sign its inputs for i in xrange(0, len(payer_utxo_inputs)): idx = i + len(tx_inputs) subsidized_tx = bitcoin.sign(subsidized_tx, idx, private_key_obj.to_hex(), hashcode=bitcoin.SIGHASH_ANYONECANPAY) return subsidized_tx
def get_hex(self, signed=True): """ Given all the data the user has given so far, make the hex using pybitcointools """ total_ins_satoshi = self.total_input_satoshis() if total_ins_satoshi == 0: raise ValueError("Can't make transaction, there are zero inputs") # Note: there can be zero outs (sweep or coalesc transactions) total_outs_satoshi = sum([x['value'] for x in self.outs]) if not self.fee_satoshi: self.fee() # use default of $0.02 change_satoshi = total_ins_satoshi - (total_outs_satoshi + self.fee_satoshi) if change_satoshi < 0: raise ValueError( "Input amount (%s) must be more than all output amounts (%s) plus fees (%s). You need more %s." % (total_ins_satoshi, total_outs_satoshi, self.fee_satoshi, self.crypto.upper())) ins = [x['input'] for x in self.ins] if change_satoshi > 0: if self.verbose: print("Adding change address of %s satoshis to %s" % (change_satoshi, self.change_address)) change = [{ 'value': change_satoshi, 'address': self.change_address }] else: change = [] # no change ?! if self.verbose: print("Inputs == Outputs, no change address needed.") tx = mktx(ins, self.outs + change) if signed: for i, input_data in enumerate(self.ins): if not input_data['private_key']: raise Exception( "Can't sign transaction, missing private key for input %s" % i) tx = sign(tx, i, input_data['private_key']) return tx
def segwit_sign(tx, i, priv, amount, hashcode=SIGHASH_ALL, script=None, separator_index=None): i = int(i) txobj = tx if isinstance(tx, dict) else deserialize(tx) if not isinstance(tx, dict) and ((not is_python2 and isinstance(re, bytes)) or not re.match('^[0-9a-fA-F]*$', tx)): return binascii.unhexlify(sign(binascii.hexlify(tx), i, priv)) if len(priv) <= 33: priv = binascii.hexlify(priv) pub = privkey_to_pubkey(priv) address = pubkey_to_address(pub) wscript = mk_pubkey_script(address) if not script else script stripped_script = segwit_strip_script_separator(wscript, separator_index) signing_tx = segwit_signature_form(tx, i, stripped_script, amount, hashcode=hashcode) rawsig = ecdsa_raw_sign(hashlib.sha256(hashlib.sha256(binascii.unhexlify(signing_tx)).digest()).hexdigest(), priv) sig = der_encode_sig(*rawsig)+encode(hashcode, 16, 2) txobj['ins'][i]['txinwitness'] = [sig, pub if not script else script] return serialize(txobj)
def tx_serialize_subsidized_tx( blockstore_tx, payer_privkey_hex, payer_utxo_inputs, payer_address, dust_fee, op_fee ): """ Make a signed serialized transaction with the given operation and dust fees """ tx_inputs, tx_outputs, locktime, version = tx_deserialize( blockstore_tx ) subsidy_output = tx_make_subsidization_output( payer_utxo_inputs, payer_address, op_fee, dust_fee ) # add our inputs and output subsidized_tx = tx_extend( blockstore_tx, payer_utxo_inputs, [subsidy_output] ) # sign each of our inputs with our key, but use SIGHASH_ANYONECANPAY so the client can sign its inputs for i in xrange( 0, len(payer_utxo_inputs)): idx = i + len(tx_inputs) subsidized_tx = bitcoin.sign( subsidized_tx, idx, payer_privkey_hex, hashcode=bitcoin.SIGHASH_ANYONECANPAY ) return subsidized_tx
def finishcallback(self, coinjointx): if coinjointx.all_responded: #now sign it ourselves tx = btc.serialize(coinjointx.latest_tx) for index, ins in enumerate(coinjointx.latest_tx['ins']): utxo = ins['outpoint']['hash'] + ':' + str(ins['outpoint']['index']) if utxo != self.taker.auth_utxo: continue addr = coinjointx.input_utxos[utxo]['address'] tx = btc.sign(tx, index, coinjointx.wallet.get_key_from_addr(addr)) print 'unsigned tx = \n\n' + tx + '\n' debug('created unsigned tx, ending') self.taker.msgchan.shutdown() return self.ignored_makers += coinjointx.nonrespondants debug('recreating the tx, ignored_makers=' + str(self.ignored_makers)) self.create_tx()
def self_sign_and_push(self): #now sign it ourselves tx = btc.serialize(self.latest_tx) for index, ins in enumerate(self.latest_tx['ins']): utxo = ins['outpoint']['hash'] + ':' + str(ins['outpoint']['index']) if utxo not in self.input_utxos.keys(): continue addr = self.input_utxos[utxo]['address'] tx = btc.sign(tx, index, self.wallet.get_key_from_addr(addr)) txhex = btc.serialize(self.latest_tx) debug('\n' + txhex) debug('txid = ' + btc.txhash(tx)) #TODO send to a random maker or push myself #TODO need to check whether the other party sent it #self.msgchan.push_tx(self.active_orders.keys()[0], txhex) self.txid = common.bc_interface.pushtx(tx) if self.txid == None: debug('unable to pushtx')
def build_raw_tx(prev_tx_id, prev_out_index, value, src_btc_addr, dest_btc_addr): #assert len(prev_tx_id) == len(prev_out_index) == len(value) == len(src_btc_addr) scriptPubKey = [] for i in range(len(dest_btc_addr)): scriptPubKey.append(aux.generate_std_scriptpubkey(dest_btc_addr[i])) tx = Transaction.TX() tx.build_default_tx(prev_tx_id, prev_out_index, value, scriptPubKey) signed_tx = tx.hex for i in range(len(prev_tx_id)): priv_key = "wallet/" + src_btc_addr + "/sk.pem" priv_key_hex = aux.get_priv_key_hex(priv_key) signed_tx = sign(signed_tx, i, priv_key_hex) return signed_tx
def finishcallback(self, coinjointx): if coinjointx.all_responded: #now sign it ourselves tx = btc.serialize(coinjointx.latest_tx) for index, ins in enumerate(coinjointx.latest_tx['ins']): utxo = ins['outpoint']['hash'] + ':' + str( ins['outpoint']['index']) if utxo != self.taker.auth_utxo: continue addr = coinjointx.input_utxos[utxo]['address'] tx = btc.sign(tx, index, coinjointx.wallet.get_key_from_addr(addr)) print 'unsigned tx = \n\n' + tx + '\n' debug('created unsigned tx, ending') self.taker.msgchan.shutdown() return self.ignored_makers += coinjointx.nonrespondants debug('recreating the tx, ignored_makers=' + str(self.ignored_makers)) self.create_tx()
def send_message(recipient_addr, scripts, fee=0, send=False): """ Send encoded message Args: recipient_addr (str): address of user to send message too scripts (list): list of strings, each element is a single encoded message. Multiple encodings are needed if the message is longer than 40 char. fee (int): Satoshis to pay in miner fees. Not actually required. send (bool): If True, send transactions to mempool. Returns: signed_txs (list): list of strings where each element is a signed transaction encoding a message Also sends transaction to the mempool. Notes: This is currently sending the message to blockchain.info, but this is trivially changed if needed. """ priv, pub, addr = books.read_wallet() signed_txs = [] for script in scripts: outputs = [{'value': 546, 'address': recipient_addr}] inputs = bitcoin.unspent(addr) for _input in inputs: if _input > 1092: input_tx = _input break outputs.append({'value': 0, 'script': script}) fee = fee tx = bitcoin.mksend(input_tx, outputs, addr, fee) signed_tx = bitcoin.sign(tx, 0, priv) if send: bitcoin.pushtx(signed_tx) signed_txs.append(signed_tx) if send: _write_message(recipient_addr, signed_txs) return signed_txs
def sendCustomTransaction(self, privkeys, inputs, outputs, fee=0): success = False totalInputValue = 0 UTXOs = [] for tx_input in inputs: if 'spend' not in tx_input: totalInputValue += tx_input['value'] UTXOs.append(tx_input) totalOutputValue = 0 for tx_output in outputs: totalOutputValue += tx_output['value'] diff = totalInputValue - totalOutputValue if fee != diff: pprint("Warning: Fee incorrect! aborting transaction") else: allKeysPresent = True allInputsConfirmed = True for tx_input in UTXOs: if tx_input['address'] not in privkeys: print 'not found:', tx_input['address'] allKeysPresent = False if tx_input['block_height'] == None: allInputsConfirmed = False if allKeysPresent == True and allInputsConfirmed == True: tx = bitcoin.mktx(UTXOs, outputs) for i in range(0, len(UTXOs)): tx = bitcoin.sign(tx, i, str(privkeys[UTXOs[i]['address']])) try: bitcoin.pushtx(tx) success = True except: e = sys.exc_info() print e success = False return success
def get_hex(self, signed=True): """ Given all the data the user has given so far, make the hex using pybitcointools """ total_ins_satoshi = self.total_input_satoshis() if total_ins_satoshi == 0: raise ValueError("Can't make transaction, there are zero inputs") # Note: there can be zero outs (sweep or coalesc transactions) total_outs_satoshi = sum([x['value'] for x in self.outs]) if not self.fee_satoshi: self.fee() # use default of $0.02 change_satoshi = total_ins_satoshi - (total_outs_satoshi + self.fee_satoshi) if change_satoshi < 0: raise ValueError( "Input amount (%s) must be more than all output amounts (%s) plus fees (%s). You need more %s." % (total_ins_satoshi, total_outs_satoshi, self.fee_satoshi, self.crypto.upper()) ) ins = [x['input'] for x in self.ins] if change_satoshi > 0: if self.verbose: print("Adding change address of %s satoshis to %s" % (change_satoshi, self.change_address)) change = [{'value': change_satoshi, 'address': self.change_address}] else: change = [] # no change ?! if self.verbose: print("Inputs == Outputs, no change address needed.") tx = mktx(ins, self.outs + change) if signed: for i, input_data in enumerate(self.ins): if not input_data['private_key']: raise Exception("Can't sign transaction, missing private key for input %s" % i) tx = sign(tx, i, input_data['private_key']) return tx
def tx_make_subsidizable( blockstack_tx, fee_cb, max_fee, subsidy_key, utxo_client, tx_fee=0 ): """ Given an unsigned serialized transaction from Blockstack, make it into a subsidized transaction for the client to go sign off on. * Add subsidization inputs/outputs * Make sure the subsidy does not exceed the maximum subsidy fee * Sign our inputs with SIGHASH_ANYONECANPAY Raise ValueError if there are not enough inputs to subsidize """ # get subsidizer key info private_key_obj, payer_address, payer_utxo_inputs = pybitcoin.analyze_private_key(subsidy_key, utxo_client) tx_inputs, tx_outputs, locktime, version = tx_deserialize( blockstack_tx ) # what's the fee? does it exceed the subsidy? dust_fee, op_fee = fee_cb( tx_inputs, tx_outputs ) if dust_fee is None or op_fee is None: log.error("Invalid fee structure") return None if dust_fee + op_fee + tx_fee > max_fee: log.error("Op fee (%s) + dust fee (%s) exceeds maximum subsidy %s" % (dust_fee, op_fee, max_fee)) return None else: log.debug("%s will subsidize %s satoshi" % (pybitcoin.BitcoinPrivateKey( subsidy_key ).public_key().address(), dust_fee + op_fee )) subsidy_output = tx_make_subsidization_output( payer_utxo_inputs, payer_address, op_fee, dust_fee + tx_fee ) # add our inputs and output subsidized_tx = tx_extend( blockstack_tx, payer_utxo_inputs, [subsidy_output] ) # sign each of our inputs with our key, but use SIGHASH_ANYONECANPAY so the client can sign its inputs for i in xrange( 0, len(payer_utxo_inputs)): idx = i + len(tx_inputs) subsidized_tx = bitcoin.sign( subsidized_tx, idx, private_key_obj.to_hex(), hashcode=bitcoin.SIGHASH_ANYONECANPAY ) return subsidized_tx
def sendCustomTransaction(self, privkeys, inputs, outputs, fee=0): success = False totalInputValue = 0 UTXOs = [] for tx_input in inputs: if 'spend' not in tx_input: totalInputValue += tx_input['value'] UTXOs.append(tx_input) totalOutputValue = 0 for tx_output in outputs: totalOutputValue += tx_output['value'] diff = totalInputValue - totalOutputValue if fee != diff: self.response.write( "<br>Warning: Fee incorrect! aborting transaction") logging.error("Warning: Fee incorrect! aborting transaction") else: allKeysPresent = True allInputsConfirmed = True for tx_input in UTXOs: if tx_input['address'] not in privkeys: allKeysPresent = False if tx_input['block_height'] == None: allInputsConfirmed = False if allKeysPresent == True and allInputsConfirmed == True: tx = bitcoin.mktx(UTXOs, outputs) for i in range(0, len(UTXOs)): tx = bitcoin.sign(tx, i, str(privkeys[UTXOs[i]['address']])) bitcoin.pushtx(tx) success = True return success
def sendCustomTransaction(self, privkeys, inputs, outputs, fee=0): success = False totalInputValue = 0 UTXOs = [] for tx_input in inputs: if 'spend' not in tx_input: totalInputValue += tx_input['value'] UTXOs.append(tx_input) totalOutputValue = 0 for tx_output in outputs: totalOutputValue += tx_output['value'] diff = totalInputValue - totalOutputValue if fee != diff: self.response.write("<br>Warning: Fee incorrect! aborting transaction") logging.error("Warning: Fee incorrect! aborting transaction") else: allKeysPresent = True allInputsConfirmed = True for tx_input in UTXOs: if tx_input['address'] not in privkeys: allKeysPresent = False if tx_input['block_height'] == None: allInputsConfirmed = False if allKeysPresent == True and allInputsConfirmed == True: tx = bitcoin.mktx(UTXOs, outputs) for i in range(0, len(UTXOs)): tx = bitcoin.sign(tx, i, str(privkeys[UTXOs[i]['address']])) bitcoin.pushtx(tx) success = True return success
def sign(utxo, priv, destaddrs): """Sign a tx sending the amount amt, from utxo utxo, equally to each of addresses in list destaddrs, after fees; the purpose is to create a large number of utxos. """ results = validate_utxo_data([(utxo, priv)], retrieve=True) if not results: return False assert results[0][0] == utxo amt = results[0][1] ins = [utxo] estfee = estimate_tx_fee(1, len(destaddrs)) outs = [] share = int((amt - estfee) / len(destaddrs)) fee = amt - share*len(destaddrs) assert fee >= estfee log.debug("Using fee: " + str(fee)) for i, addr in enumerate(destaddrs): outs.append({'address': addr, 'value': share}) unsigned_tx = btc.mktx(ins, outs) return btc.sign(unsigned_tx, 0, btc.from_wif_privkey( priv, vbyte=get_p2pk_vbyte()))
def sign_tx(self, tx, i, priv): if self.my_cj_addr: return btc.sign(tx, i, priv) else: return sign_donation_tx(tx, i, priv)
def commitTo(self, testnet, commit_address, private_key): """ Commit to some address on the blockchain """ # Check if we have the keys for the BM address public_key = highlevelcrypto.privToPub( private_key.encode('hex') ).decode('hex') fromAddress = self.getAddress( testnet, public_key ) result = self.getUnspentTransactions( testnet, [fromAddress] ) if not 'unspent' in result or len( result['unspent'] ) == 0: log_debug( "commitTo: No unspent TXs (%s)" % ( fromAddress ) ) return False unspent_txs = result['unspent'] # filter for those with an amount >= minimum amount unspent_txs = filter( lambda tx: float( tx['amount'] ) > BitcoinThread.BTC_UNSPENT_MIN_AVAILABLE, unspent_txs ) if len( unspent_txs ) == 0: log_debug( "commitTo: No unspent TXs >= %d (%s, %s)" % ( BitcoinThread.BTC_UNSPENT_MIN_AVAILABLE, fromAddress, result['unspent'] ) ) return False # Find random unspent with an amount >= 0.00010 mBTC random.shuffle( unspent_txs ) while len( unspent_txs ) > 0: tx = unspent_txs.pop( 0 ) log_debug( "Trying unspent tx: %s" % tx ) amount = float( tx['amount'] ) amount_satoshis = int( amount * 100000000 ) change_satoshis = amount_satoshis - BitcoinThread.SATOSHI_COMMITMENT_AMOUNT - BitcoinThread.SATOSHI_TRANSACTION_FEE # Code in bitcoin.mktx separates the input string into tx=input[:64] and n=input[65:] input_tx = "%s %d" % ( tx['tx'], tx['n'] ) commit_payable = { "address": commit_address, "value": BitcoinThread.SATOSHI_COMMITMENT_AMOUNT } change_payable = { "address": fromAddress, "value": change_satoshis } tx = bitcoin.mktx( [input_tx], [ commit_payable, change_payable ] ) signed_tx = bitcoin.sign(tx, 0, private_key ) log_debug( "Pushing tx: %s" % bitcoin.deserialize( tx ) ) if testnet: try: result = json.loads( bitcoin.blockr_pushtx(signed_tx, 'testnet') ) except Exception, e: # If we get {"status":"fail","data":"Could not push your transaction!","code":500,"message":"Did you sign your transaction?"} # in an exception here, it probably means that the referenced inputs in our transaction have been spent in the meantime. try: e_obj = json.loads( e.message ) if e_obj["data"] == "Could not push your transaction!": from debug import logger log_warn( "Couldn't push transaction. Sometimes this is because the referenced inputs have been spent in the meantime, %s" % e_obj ) # Continue to try the next unspent tx continue else: log_warn( e ) except: log_warn( e ) return 'status' in result and result['status'] == "success" else: # if not testnet # I had problems pushing non-testnet transactions to blockr.io, # so we're using blockchain.info for this, and that works fine. try: result = bitcoin.pushtx( signed_tx ) if result.lower() == "transaction submitted": log_debug( "Committed to %s" % commit_address ) return True else: log_warn( "Transaction push fail: %s" % ( result, ) ) except Exception, e: log_warn( "Transaction push exception: %s" % ( e, ) ) continue
def test_donation_address(setup_donations, amount): wallets = make_wallets(1, wallet_structures=[[1,1,1,0,0]], mean_amt=0.5) wallet = wallets[0]['wallet'] jm_single().bc_interface.sync_wallet(wallet) #make a rdp from a simple privkey rdp_priv = "\x01"*32 reusable_donation_pubkey = binascii.hexlify(secp256k1.PrivateKey( privkey=rdp_priv, raw=True, ctx=btc.ctx).pubkey.serialize()) dest_addr, sign_k = donation_address(reusable_donation_pubkey) print dest_addr jm_single().bc_interface.rpc('importaddress', [dest_addr, '', False]) ins_full = wallet.unspent total = sum(x['value'] for x in ins_full.values()) ins = ins_full.keys() output_addr = wallet.get_new_addr(1, 1) fee_est = 10000 outs = [{'value': amount, 'address': dest_addr}, {'value': total - amount - fee_est, 'address': output_addr}] tx = btc.mktx(ins, outs) de_tx = btc.deserialize(tx) for index, ins in enumerate(de_tx['ins']): utxo = ins['outpoint']['hash'] + ':' + str(ins['outpoint']['index']) addr = ins_full[utxo]['address'] priv = wallet.get_key_from_addr(addr) priv = binascii.unhexlify(priv) usenonce = binascii.unhexlify(sign_k) if index == 0 else None if index == 0: log.debug("Applying rdp to input: " + str(ins)) tx = btc.sign(tx, index, priv, usenonce=usenonce) #pushtx returns False on any error push_succeed = jm_single().bc_interface.pushtx(tx) if push_succeed: log.debug(btc.txhash(tx)) else: assert False #Role of receiver: regenerate the destination private key, #and address, from the nonce of the first input; check it has #received the coins. detx = btc.deserialize(tx) first_utxo_script = detx['ins'][0]['script'] sig, pub = btc.deserialize_script(first_utxo_script) log.debug(sig) sig = binascii.unhexlify(sig) kGlen = ord(sig[3]) kG = sig[4:4+kGlen] log.debug(binascii.hexlify(kG)) if kG[0] == "\x00": kG = kG[1:] #H(rdp private key * K) + rdp should be ==> dest addr #Open issue: re-introduce recovery without ECC shenanigans #Just cheat by trying both signs for pubkey coerced_kG_1 = "02" + binascii.hexlify(kG) coerced_kG_2 = "03" + binascii.hexlify(kG) for coerc in [coerced_kG_1, coerced_kG_2]: c = btc.sha256(btc.multiply(binascii.hexlify(rdp_priv), coerc, True)) pub_check = btc.add_pubkeys([reusable_donation_pubkey, btc.privtopub(c+'01', True)], True) addr_check = btc.pubtoaddr(pub_check, get_p2pk_vbyte()) log.debug("Found checked address: " + addr_check) if addr_check == dest_addr: time.sleep(3) received = jm_single().bc_interface.get_received_by_addr( [dest_addr], None)['data'][0]['balance'] assert received == amount return assert False
def sign_donation_tx(tx, i, priv): return btc.sign(tx, i, priv, usenonce=sign_k)
import bitcoin as b import hashlib priv = hashlib.sha256('correct horse battery staple').hexdigest() pub = b.privToPub(priv) c = b.encrypt('123',pub) d = b.decrypt(c,priv) assert d == '123' print "Encryption seems to work" s = b.sign('123',priv) assert b.verify('123',s,pub) print "Signing and verification seems to work"
def send(fromprivkey, toaddr, value): transaction_fee = 20000 print "Sending:", fromprivkey, toaddr, value tx = bitcoin.mksend(bitcoin.history(bitcoin.privtoaddr(fromprivkey)), [toaddr+":"+str(value)], bitcoin.privtoaddr(fromprivkey), transaction_fee) signed_tx = bitcoin.sign(tx, 0, fromprivkey) bitcoin.pushtx(signed_tx)
def send(fromprivkey, toaddr, value): transaction_fee = 20000 # .0002 BTC fromaddress = bitcoin.privtoaddr(fromprivkey) tx = bitcoin.mksend(bitcoin.history(fromaddress), [{'value': value, 'address': toaddr}], fromaddress, transaction_fee) signed_tx = bitcoin.sign(tx, 0, fromprivkey) bitcoin.pushtx(signed_tx)