def bitcoin(public, private, address, amount): coins_from = [] coins_sources = blockchain_info.coin_sources_for_address(public) coins_from.extend(coins_sources) value = sum(cs[-1].coin_value for cs in coins_sources) secret_exponents = [encoding.wif_to_secret_exponent(private)] amount = btc_to_satoshi(amount) coins_to = [] coins_to.append((amount, address)) actual_tx_fee = value - amount if actual_tx_fee < 0: print( "not enough source coins (%s BTC) for destination (%s BTC). Short %s BTC" % (satoshi_to_btc(total_value), satoshi_to_btc(total_spent), satoshi_to_btc(-actual_tx_fee))) return None if actual_tx_fee > 0: coins_to.append((actual_tx_fee, public)) unsigned_tx = UnsignedTx.standard_tx(coins_from, coins_to) solver = SecretExponentSolver(secret_exponents) new_tx = unsigned_tx.sign(solver) s = io.BytesIO() new_tx.stream(s) tx_bytes = s.getvalue() tx_hex = binascii.hexlify(tx_bytes).decode("utf8") return tx_bytes
def bitcoin(public, private, address, amount): coins_from = [] coins_sources = blockchain_info.coin_sources_for_address(public) coins_from.extend(coins_sources) value = sum(cs[-1].coin_value for cs in coins_sources) secret_exponents = [encoding.wif_to_secret_exponent(private)] amount = btc_to_satoshi(amount) coins_to = [] coins_to.append((amount, address)) actual_tx_fee = value - amount if actual_tx_fee < 0: print("not enough source coins (%s BTC) for destination (%s BTC). Short %s BTC" % (satoshi_to_btc(total_value), satoshi_to_btc(total_spent), satoshi_to_btc(-actual_tx_fee))) return None; if actual_tx_fee > 0: coins_to.append((actual_tx_fee, public)) unsigned_tx = UnsignedTx.standard_tx(coins_from, coins_to) solver = SecretExponentSolver(secret_exponents) new_tx = unsigned_tx.sign(solver) s = io.BytesIO() new_tx.stream(s) tx_bytes = s.getvalue() tx_hex = binascii.hexlify(tx_bytes).decode("utf8") return tx_bytes
def main(): parser = argparse.ArgumentParser(description="Create a Bitcoin transaction.") parser.add_argument('-s', "--source-address", help='source Bitcoin address', required=True, nargs="+", metavar='source_address') parser.add_argument('-d', "--destination-address", help='destination Bitcoin address/amount', required=True, metavar='dest_address/amount_in_btc', nargs="+") parser.add_argument('-f', "--wif-file", help='WIF items for source Bitcoin addresses', required=True, metavar="path-to-WIF-values", type=argparse.FileType('r')) args = parser.parse_args() total_value = 0 coins_from = [] for bca in args.source_address: coins_sources = blockchain_info.coin_sources_for_address(bca) coins_from.extend(coins_sources) total_value += sum(cs[-1].coin_value for cs in coins_sources) secret_exponents = [] for l in args.wif_file: print l secret_exponents.append(encoding.wif_to_secret_exponent(l[:-1])) coins_to = [] total_spent = 0 for daa in args.destination_address: address, amount = daa.split("/") amount = btc_to_satoshi(amount) total_spent += amount coins_to.append((amount, address)) actual_tx_fee = total_value - total_spent if actual_tx_fee < 0: print("not enough source coins (%s BTC) for destination (%s BTC). Short %s BTC" % (satoshi_to_btc(total_value), satoshi_to_btc(total_spent), satoshi_to_btc(-actual_tx_fee))) sys.exit(1) print("transaction fee: %s BTC" % satoshi_to_btc(actual_tx_fee)) unsigned_tx = UnsignedTx.standard_tx(coins_from, coins_to) solver = SecretExponentSolver(secret_exponents) new_tx = unsigned_tx.sign(solver) s = io.BytesIO() new_tx.stream(s) tx_bytes = s.getvalue() tx_hex = binascii.hexlify(tx_bytes).decode("utf8") recommended_tx_fee = tx_fee.recommended_fee_for_tx(new_tx) if actual_tx_fee > recommended_tx_fee: print("warning: transaction fee of exceeds expected value of %s BTC" % satoshi_to_btc(recommended_tx_fee)) elif actual_tx_fee < recommended_tx_fee: print("warning: transaction fee lower than (casually calculated) expected value of %s BTC, transaction might not propogate" % satoshi_to_btc(recommended_tx_fee)) print("copy the following hex to http://blockchain.info/pushtx to put the transaction on the network:\n") print(tx_hex)
def construct_data_tx(data, _from): # inputs coins_from = blockchain_info.coin_sources_for_address(_from) min_coin_value, min_idx, min_h, min_script = max((tx_out.coin_value, idx, h, tx_out.script) for h, idx, tx_out in coins_from) unsigned_txs_out = [UnsignedTxOut(min_h, min_idx, min_coin_value, min_script)] # outputs if min_coin_value > TX_FEES * 2: return 'max output greater than twice the threshold, too big.' if min_coin_value < TX_FEES: return 'max output smaller than threshold, too small.' script_text = 'OP_RETURN %s' % data.encode('hex') script_bin = tools.compile(script_text) new_txs_out = [TxOut(0, script_bin)] version = 1 lock_time = 0 unsigned_tx = UnsignedTx(version, unsigned_txs_out, new_txs_out, lock_time) return unsigned_tx
def construct_data_tx(data, _from): # inputs coins_from = blockchain_info.coin_sources_for_address(_from) if len(coins_from) < 1: return "No free outputs to spend" max_coin_value, _, max_idx, max_h, max_script = max( (tx_out.coin_value, random(), idx, h, tx_out.script) for h, idx, tx_out in coins_from) unsigned_txs_out = [ UnsignedTxOut(max_h, max_idx, max_coin_value, max_script) ] # outputs if max_coin_value > TX_FEES * 2: return 'max output greater than twice the threshold, too big.' if max_coin_value < TX_FEES: return 'max output smaller than threshold, too small.' script_text = 'OP_RETURN %s' % data.encode('hex') script_bin = tools.compile(script_text) new_txs_out = [TxOut(0, script_bin)] version = 1 lock_time = 0 unsigned_tx = UnsignedTx(version, unsigned_txs_out, new_txs_out, lock_time) return unsigned_tx
satoshis = 0 coin_sources = [] secret_exponent = None bitcoin_address_compressed = None try: secret_exponent = encoding.wif_to_secret_exponent(options.funding_source) public_pair = ecdsa.public_pair_for_secret_exponent(secp256k1.generator_secp256k1, secret_exponent) bitcoin_address_compressed = encoding.public_pair_to_bitcoin_address(public_pair, compressed=True) except: print "Hrm something went wrong in trying to figure out BTC address from WIF %s" % (options.funding_source) sys.exit() try: if not options.forced_tx_source: coin_sources = blockchain_info.coin_sources_for_address(bitcoin_address_compressed) else: #forced args should combine all the info we need to run the code below ... so, value in satoshis, script, tx_hash and tx_output_n #value is in satoshis. tx_output_n does appear to start at zero after all. #u can find a tx outputs info by putting the tx in here: https://blockchain.info/rawtx/8684f9ea9f35953d0235cd4f5c73485dcf0eeb4cada6d2f657b63bea1e425178?scripts=true #eg args below ... wanted to redo something that used output # 0 of this tx as a source: 8684f9ea9f35953d0235cd4f5c73485dcf0eeb4cada6d2f657b63bea1e425178, soooo from the https://blockchain.info/rawtx/8684f9ea9f35953d0235cd4f5c73485dcf0eeb4cada6d2f657b63bea1e425178?scripts=true link we got: #8684f9ea9f35953d0235cd4f5c73485dcf0eeb4cada6d2f657b63bea1e425178,0,500000,76a91439d61ff876886683142acf9b0235ea0bcc3ecf8788ac hash, tx_output_n, s_value, script = options.forced_tx_source.split(',') #the hash we get from rawtx will be the reverse byte order of the tx_hash that the unspent outputs thing that the pycoin normally uses (http://blockchain.info/unspent?active=%s ) reports (why?? only Satoshi knows.) #so we'll just put it in the form that is expected for manipulations by pycon. tx_hash = "".join(reversed([hash[i:i+2] for i in range(0, len(hash), 2)])) tx_out = TxOut(int(s_value), binascii.unhexlify(script.encode())) coins_source = (binascii.unhexlify(tx_hash.encode()), int(tx_output_n), tx_out) coin_sources.append(coins_source) print "NOTE: Could not verify that this source address even has enough funds, but preparing a (possibly to be rejected by network) that will source from supplied info and send change back to BTC %s address from WIF" % (bitcoin_address_compressed)