def validate(self, provider=None): if self.merkle_root != self.build_merkle_root(): raise ValueError("calculated merkle_root %s does not match stated merkle_root %s from header" % (self.build_merkle_root(), self.merkle_root)) self.total_out = 0 if provider is not None: print "Doing full, online validation." self.total_in = 0 self.total_fee = 0 else: print "Doing limited, offline validation." print "Validating %d transactions" % len(self.batchable_txs) for tx_index, tx in enumerate(self.batchable_txs): print "\n\nValidating tx#%d - %s" % (tx_index+1, tx.id()) print "- Total out", tx.total_out() self.total_out += tx.total_out() if provider: print "Fetching %d UTXO..." % len(tx.txs_in) for idx, tx_in in enumerate(tx.txs_in): unspent_tx = provider.get_tx(tx_in.previous_hash) tx.unspents.append(unspent_tx.txs_out[tx_in.previous_index]) print "- Total in", tx.total_in() self.total_in += tx.total_in() print "- Fee", tx.fee() self.total_fee += tx.fee() print "- Transaction Size", len(tx.as_hex()) // 2 print "- Recommended Fee for Size ", tx_fee.recommended_fee_for_tx(tx) if tx.fee() > 100000 and tx.fee() > 2 * tx_fee.recommended_fee_for_tx(tx): raise ValueError("Very high fee in transaction %s" % tx.id()) print "- Fee Percent", (tx.fee() * 100.00 / tx.total_out()) print "- Bad Signatures", tx.bad_signature_count(), "of", len(tx.txs_in)
def check_fees(tx): total_in, total_out = tx.total_in(), tx.total_out() actual_tx_fee = total_in - total_out recommended_tx_fee = tx_fee.recommended_fee_for_tx(tx) print( "warning: transaction fees recommendations casually calculated and estimates may be incorrect", file=sys.stderr) if actual_tx_fee > recommended_tx_fee: print( "warning: transaction fee of %s exceeds expected value of %s mBTC" % (satoshi_to_mbtc(actual_tx_fee), satoshi_to_mbtc(recommended_tx_fee)), file=sys.stderr) elif actual_tx_fee < 0: print("not enough source coins (%s mBTC) for destination (%s mBTC)." " Short %s mBTC" % (satoshi_to_mbtc(total_in), satoshi_to_mbtc(total_out), satoshi_to_mbtc(-actual_tx_fee)), file=sys.stderr) elif actual_tx_fee < recommended_tx_fee: print("warning: transaction fee lower than (casually calculated)" " expected value of %s mBTC, transaction might not propogate" % satoshi_to_mbtc(recommended_tx_fee), file=sys.stderr) return actual_tx_fee
def send(self, ddestination_address, dcolourid=None): self.colordata.update() coins_to = [] total_spent = 0 for daa in [ddestination_address]: address, amount = daa[0], daa[1] amount = btc_to_satoshi(amount) total_spent += amount coins_to.append((amount, address)) selected_utxos, total_value = self.selectUTXOs(self.getAllUTXOs(), dcolourid, total_spent) change = (total_value - total_spent) - 10000 if change >= 1: coins_to.append((change, self.addresses[0].pubkey)) coins_from = [utxo.get_pycoin_coin_source() for utxo in selected_utxos] secret_exponents = [encoding.wif_to_secret_exponent(address.privkey) for address in self.addresses] 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) print tx_hex URL = "http://blockchain.info/pushtx" urllib2.urlopen(URL, data=tx_hex)
def check_fees(unsigned_tx): total_value, total_spent = calculate_fees(unsigned_tx) actual_tx_fee = total_value - total_spent recommended_tx_fee = tx_fee.recommended_fee_for_tx(unsigned_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 < 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))) 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)) return actual_tx_fee
def check_fees(unsigned_tx): total_value, total_spent = calculate_fees(unsigned_tx) actual_tx_fee = total_value - total_spent recommended_tx_fee = tx_fee.recommended_fee_for_tx(unsigned_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 < 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))) 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)) return actual_tx_fee
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 check_fees(tx): total_in, total_out = tx.total_in(), tx.total_out() actual_tx_fee = total_in - total_out recommended_tx_fee = tx_fee.recommended_fee_for_tx(tx) print("warning: transaction fees recommendations casually calculated and estimates may be incorrect", file=sys.stderr) if actual_tx_fee > recommended_tx_fee: print("warning: transaction fee of %s exceeds expected value of %s mBTC" % (satoshi_to_mbtc(actual_tx_fee), satoshi_to_mbtc(recommended_tx_fee)), file=sys.stderr) elif actual_tx_fee < 0: print("not enough source coins (%s mBTC) for destination (%s mBTC)." " Short %s mBTC" % (satoshi_to_mbtc(total_in), satoshi_to_mbtc(total_out), satoshi_to_mbtc(-actual_tx_fee)), file=sys.stderr) elif actual_tx_fee < recommended_tx_fee: print("warning: transaction fee lower than (casually calculated)" " expected value of %s mBTC, transaction might not propogate" % satoshi_to_mbtc(recommended_tx_fee), file=sys.stderr) return actual_tx_fee
def send(self, ddestination_address, dcolourid=None): self.colordata.update() coins_to = [] total_spent = 0 for daa in [ddestination_address]: address, amount = daa[0], daa[1] amount = btc_to_satoshi(amount) total_spent += amount coins_to.append((amount, address)) selected_utxos, total_value = self.selectUTXOs(self.getAllUTXOs(), dcolourid, total_spent) change = (total_value - total_spent) - 10000 if change >= 1: coins_to.append((change, self.addresses[0].pubkey)) coins_from = [utxo.get_pycoin_coin_source() for utxo in selected_utxos] secret_exponents = [ encoding.wif_to_secret_exponent(address.privkey) for address in self.addresses ] 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) print tx_hex URL = "http://blockchain.info/pushtx" urllib2.urlopen(URL, data=tx_hex)
def build_psbt(ctx, xfp, addrs, pubkey=None, xpubs=None, redeem=None): locals().update(ctx.obj) payout_address = ctx.obj['payout_address'] out_psbt = ctx.obj['output_psbt'] if pubkey: assert len(addrs) == 1 # can only be single addr in that case assert len(pubkey) == 33 spending = [] total = 0 psbt = BasicPSBT() for path, addr in addrs: print(f"addr: {path} => {addr} ... ", end='') rr = explora('address', addr, 'utxo') if not rr: print('nada') continue here = 0 for u in rr: here += u['value'] tt = TxIn(h2b_rev(u['txid']), u['vout']) spending.append(tt) #print(rr) pin = BasicPSBTInput(idx=len(psbt.inputs)) psbt.inputs.append(pin) pubkey = pubkey or calc_pubkey(xpubs, path) pin.bip32_paths[pubkey] = str2path(xfp, path) # fetch the UTXO for witness signging td = explora('tx', u['txid'], 'hex', is_json=False) #print(f"txis {u['txid']}:\b{td!r}") outpt = Tx.from_hex(td.decode('ascii')).txs_out[u['vout']] with BytesIO() as b: outpt.stream(b) pin.witness_utxo = b.getvalue() if redeem: pin.redeem_script = redeem print('%.8f BTC' % (here / 1E8)) total += here if len(spending) > 15: print("Reached practical limit on # of inputs. " "You'll need to repeat this process again later.") break assert total, "Sorry! Didn't find any UTXO" print("Found total: %.8f BTC" % (total / 1E8)) if payout_address: print("Planning to send to: %s" % payout_address) dest_scr = BTC.contract.for_address(payout_address) txn = Tx(2, spending, [TxOut(total, dest_scr)]) else: print("Output section of PSBT will be empty. Change downstream") txn = Tx(2, spending, []) fee = tx_fee.recommended_fee_for_tx(txn) # placeholder, single output that isn't change pout = BasicPSBTOutput(idx=0) psbt.outputs.append(pout) print("Guestimate fee: %.8f BTC" % (fee / 1E8)) if txn.txs_out: txn.txs_out[0].coin_value -= fee # write txn into PSBT with BytesIO() as b: txn.stream(b) psbt.txn = b.getvalue() out_psbt.write(psbt.as_bytes()) print("PSBT to be signed:\n\n\t" + out_psbt.name, end='\n\n')