def test_segwit_create_tx(self): from pycoin.tx.tx_utils import create_tx, sign_tx from pycoin.tx.Spendable import Spendable from pycoin.tx.pay_to.ScriptPayToAddress import ScriptPayToAddress from pycoin.tx.pay_to.ScriptPayToAddressWit import ScriptPayToAddressWit from pycoin.tx.pay_to.ScriptPayToScriptWit import ScriptPayToScriptWit from pycoin.ui import address_for_pay_to_script_wit, script_obj_from_address key1 = Key(1) coin_value = 5000000 script = ScriptPayToAddressWit(b'\0', key1.hash160()).script() tx_hash = b'\ee' * 32 tx_out_index = 0 spendable = Spendable(coin_value, script, tx_hash, tx_out_index) key2 = Key(2) tx = create_tx([spendable], [(key2.address(), coin_value)]) self.check_unsigned(tx) sign_tx(tx, [key1.wif()]) self.check_signed(tx) self.assertEqual(len(tx.txs_in[0].witness), 2) s1 = ScriptPayToAddress(key1.hash160()).script() address = address_for_pay_to_script_wit(s1) spendable.script = script_obj_from_address(address).script() tx = create_tx([spendable], [(key2.address(), coin_value)]) self.check_unsigned(tx) sign_tx(tx, [key1.wif()], p2sh_lookup=build_p2sh_lookup([s1])) self.check_signed(tx)
def create_stock_tx(user=PRIMARY, use_smallest_spendables=True, extra_payables=[]): address = get_address_for_key(user) spendables = spendables_for_address(address) if use_smallest_spendables: spendables = trim_spendables(spendables) tx = create_tx(spendables, [address] + extra_payables, fee=10000) return tx
def test_multisig_one_at_a_time(self): M = 3 N = 3 keys = [ Key(secret_exponent=i, generator=secp256k1_generator) for i in range(1, N + 2) ] tx_in = TxIn.coinbase_tx_in(script=b'') script = script_for_multisig(m=M, sec_keys=[key.sec() for key in keys[:N]]) tx_out = TxOut(1000000, script) tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out]) tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [keys[-1].address()]) ids = [ "403e5bfc59e097bb197bf77a692d158dd3a4f7affb4a1fa41072dafe7bec7058", "5931d9995e83721243dca24772d7012afcd4378996a8b953c458175f15a544db", "9bb4421088190bbbb5b42a9eaa9baed7ec7574a407c25f71992ba56ca43d9c44", "03a1dc2a63f93a5cf5a7cb668658eb3fc2eda88c06dc287b85ba3e6aff751771" ] for i in range(1, N + 1): self.assertEqual(tx2.bad_signature_count(), 1) self.assertEqual(tx2.id(), ids[i - 1]) hash160_lookup = build_hash160_lookup( [keys[i - 1].secret_exponent()], [secp256k1_generator]) tx2.sign(hash160_lookup=hash160_lookup) self.assertEqual(tx2.id(), ids[i]) t1 = sorted(who_signed_tx(tx2, 0, UI)) t2 = sorted(((key.address(), SIGHASH_ALL) for key in keys[:i])) self.assertEqual(t1, t2) self.assertEqual(tx2.bad_signature_count(), 0)
def wallet_create(path, args): sql_db = sqlite3.Connection(os.path.join(path, "wallet.db")) persistence = SQLite3Persistence(sql_db) bcv_json = persistence.get_global("blockchain_view") or "[]" blockchain_view = BlockChainView.from_json(bcv_json) last_block = blockchain_view.last_block_index() # how much are we sending? total_sending = 0 for p in args.payable: if len(p) == 2: total_sending += p[-1] if total_sending == 0: raise argparse.ArgumentTypeError( "you must choose a non-zero amount to send") total = 0 spendables = [] for spendable in persistence.unspent_spendables(last_block, confirmations=1): spendables.append(spendable) total += spendable.coin_value if total >= total_sending: break print("found %d coins which exceed %d" % (total, total_sending)) tx = create_tx(spendables, args.payable) with open(args.output, "wb") as f: tx.stream(f) tx.stream_unspents(f)
def wallet_create(path, args): sql_db = sqlite3.Connection(os.path.join(path, "wallet.db")) persistence = SQLite3Persistence(sql_db) bcv_json = persistence.get_global("blockchain_view") or "[]" blockchain_view = BlockChainView.from_json(bcv_json) last_block = blockchain_view.last_block_index() # how much are we sending? total_sending = 0 for p in args.payable: if len(p) == 2: total_sending += p[-1] if total_sending == 0: raise argparse.ArgumentTypeError("you must choose a non-zero amount to send") total = 0 spendables = [] for spendable in persistence.unspent_spendables(last_block, confirmations=1): spendables.append(spendable) total += spendable.coin_value if total >= total_sending: break print("found %d coins which exceed %d" % (total, total_sending)) tx = create_tx(spendables, args.payable) with open(args.output, "wb") as f: tx.stream(f) tx.stream_unspents(f)
def create_unsigned_send_tx(self, address, amount): total_input_value = 0 estimated_fee = TX_FEE_PER_THOUSAND_BYTES lbi = self.last_block_index() with self._lock: confirmations = 7 while confirmations > 0 and self.get_balance( confirmations=confirmations) < amount + estimated_fee: confirmations -= 1 spendables = [] for spendable in self.persistence.unspent_spendables( lbi, confirmations=1): spendables.append(spendable) total_input_value += spendable.coin_value if total_input_value >= amount + estimated_fee and len( spendables) > 1: break if total_input_value < amount + estimated_fee: raise ValueError("insufficient funds: only %d available" % total_input_value) payables = self.create_payables(address, amount) tx = create_tx(spendables, payables, fee=estimated_fee) # mark the given spendables as "unconfirmed_spent" for spendable in spendables: spendable.does_seem_spent = True self.persistence.save_spendable(spendable) self.persistence.commit() return tx
def wallet_create(path, args): sql_db = sqlite3.Connection(os.path.join(path, "wallet.db")) keychain = Keychain([]) persistence = SQLite3Persistence(sql_db) wallet = SQLite3Wallet(keychain, persistence, desired_spendable_count=20) bcv_json = persistence.get_global("blockchain_view") or "[]" blockchain_view = BlockChainView.from_json(bcv_json) last_block = blockchain_view.last_block_index() # how much are we sending? total_sending = 0 for p in args.payable: if len(p) == 2: total_sending += p[-1] if total_sending == 0: raise argparse.ArgumentTypeError("you must choose a non-zero amount to send") total = 0 spendables = [] for spendable in persistence.unspent_spendables(last_block, confirmations=1): spendables.append(spendable) total += spendable.coin_value if total >= total_sending: break tx = create_tx(spendables, args.payable) print(tx.as_hex())
def build_tx(signature, address, wif): prev = get_spendable(address) spend_tx = create_tx([prev], [address]) signature_script = ScriptNulldata(signature).script() signature_out = TxOut(0, signature_script) spend_tx.txs_out.append(signature_out) sign_tx(spend_tx, wifs=[wif]) return spend_tx
def send_funds(from_addr, payables, wif): '''from_addr is a simple address in a string. payables is a list of tuples of (address, amount in duffs) wif is the wallet import format version of the private key for from_addr''' bc = blockcypher.BlockcypherProvider(netcode='DASH', api_key=blockcypher_api_key) spendables = bc.spendables_for_address(from_addr) tx = tx_utils.create_tx(spendables, payables, fee=0) tx_utils.sign_tx(tx, [wif]) rtx = bc.broadcast_tx(tx) return tx
def create_prev_tx(self, win, in_keynum, sources_per_input, wout, out_keynum_satoshi, fees_satoshi): """ Creates and returns a supporting 'previous' tx of 100KB or less win - wallet to use for input addresses in_keynum - key nums from win sources_per_input - how many sources are used to fund each input wout - wallet to use for output addresses out_keynum_satoshi - list of key nums from wout and satoshis to spend in tuples of (num, satoshis) Returns a bytes object containing the previous tx. """ # Calculate the total output payables = [] total_spent = 0 for (out_key_id, out_satoshi) in out_keynum_satoshi: address = wout.subkey(out_key_id).bitcoin_address() payables.append((address, out_satoshi)) total_spent += out_satoshi # Split the total to spend across all of the inputs spendables = [] total_value = 0 satoshi_per_input = int(total_spent + fees_satoshi) / len(in_keynum) for keynum in in_keynum: # Grab the address for the current key num addr = win.subkey(keynum, as_private=True).bitcoin_address() # Generate fake sources for funding the input coin spendables.extend( self.fake_sources_for_address(addr, sources_per_input, satoshi_per_input)) total_value += satoshi_per_input # Calculate the fee tx_fee = total_value - total_spent assert tx_fee >= 0, "fee < 0: " + str(tx_fee) # Create and 'sign' the transaction unsigned_tx = create_tx(spendables, payables, tx_fee) signed_tx = self.__sign_fake(unsigned_tx) return self.get_tx_bytes(signed_tx)
def test_segwit_create_tx(self): key1 = Key(1, generator=secp256k1_generator) coin_value = 5000000 script = script_for_p2pkh_wit(key1.hash160()) tx_hash = b'\ee' * 32 tx_out_index = 0 spendable = Tx.Spendable(coin_value, script, tx_hash, tx_out_index) key2 = Key(2, generator=secp256k1_generator) tx = create_tx([spendable], [(key2.address(), coin_value)]) self.check_unsigned(tx) sign_tx(tx, [key1.wif()]) self.check_signed(tx) self.assertEqual(len(tx.txs_in[0].witness), 2) s1 = script_for_p2pkh(key1.hash160()) address = BitcoinMainnet.ui.address_for_p2s_wit(s1) spendable.script = BitcoinMainnet.ui.script_for_address(address) tx = create_tx([spendable], [(key2.address(), coin_value)]) self.check_unsigned(tx) sign_tx(tx, [key1.wif()], p2sh_lookup=build_p2sh_lookup([s1])) self.check_signed(tx)
def multisig_M_of_N_individually(self, M, N): keys = [Key(secret_exponent=i) for i in range(1, N+2)] tx_in = TxIn.coinbase_tx_in(script=b'') script = ScriptMultisig(n=M, sec_keys=[key.sec() for key in keys[:N]]).script() tx_out = TxOut(1000000, script) tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out]) for partial_key_list in itertools.permutations(keys[:N], M): tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [keys[-1].address()]) for key in partial_key_list: self.assertEqual(tx2.bad_signature_count(), 1) hash160_lookup = build_hash160_lookup([key.secret_exponent()]) tx2.sign(hash160_lookup=hash160_lookup) self.assertEqual(tx2.bad_signature_count(), 0)
def multisig_M_of_N(self, M, N, unsigned_id, signed_id): keys = [Key(secret_exponent=i) for i in range(1, N+2)] tx_in = TxIn.coinbase_tx_in(script=b'') script = ScriptMultisig(m=M, sec_keys=[key.sec() for key in keys[:N]]).script() tx_out = TxOut(1000000, script) tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out]) tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [keys[-1].address()]) self.assertEqual(tx2.id(), unsigned_id) self.assertEqual(tx2.bad_signature_count(), 1) hash160_lookup = build_hash160_lookup(key.secret_exponent() for key in keys) tx2.sign(hash160_lookup=hash160_lookup) self.assertEqual(tx2.id(), signed_id) self.assertEqual(tx2.bad_signature_count(), 0)
def multisig_N_of_M(self, N, M, unsigned_id, signed_id): keys = [Key(secret_exponent=i) for i in range(1, M+2)] tx_in = TxIn.coinbase_tx_in(script=b'') script = ScriptMultisig(n=N, sec_keys=[key.sec() for key in keys[:M]]).script() tx_out = TxOut(1000000, script) tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out]) tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [keys[-1].address()]) self.assertEqual(tx2.id(), unsigned_id) self.assertEqual(tx2.bad_signature_count(), 1) hash160_lookup = build_hash160_lookup(key.secret_exponent() for key in keys) tx2.sign(hash160_lookup=hash160_lookup) self.assertEqual(tx2.id(), signed_id) self.assertEqual(tx2.bad_signature_count(), 0)
def create_prev_tx(self, win, in_keynum, sources_per_input, wout, out_keynum_satoshi, fees_satoshi): """ Creates and returns a supporting 'previous' tx of 100KB or less win - wallet to use for input addresses in_keynum - key nums from win sources_per_input - how many sources are used to fund each input wout - wallet to use for output addresses out_keynum_satoshi - list of key nums from wout and satoshis to spend in tuples of (num, satoshis) Returns a bytes object containing the previous tx. """ # Calculate the total output payables = [] total_spent = 0 for (out_key_id, out_satoshi) in out_keynum_satoshi: address = wout.subkey(out_key_id).bitcoin_address() payables.append((address, out_satoshi)) total_spent += out_satoshi # Split the total to spend across all of the inputs spendables = [] total_value = 0 satoshi_per_input = int(total_spent + fees_satoshi) / len(in_keynum) for keynum in in_keynum: # Grab the address for the current key num addr = win.subkey(keynum, as_private = True).bitcoin_address(); # Generate fake sources for funding the input coin spendables.extend(self.fake_sources_for_address(addr, sources_per_input, satoshi_per_input)) total_value += satoshi_per_input # Calculate the fee tx_fee = total_value - total_spent assert tx_fee >= 0, "fee < 0: " + str(tx_fee) # Create and 'sign' the transaction unsigned_tx = create_tx(spendables, payables, tx_fee) signed_tx = self.__sign_fake(unsigned_tx) return self.get_tx_bytes(signed_tx)
def multisig_M_of_N_individually(self, M, N): keys = [Key(secret_exponent=i) for i in range(1, N + 2)] tx_in = TxIn.coinbase_tx_in(script=b'') script = ScriptMultisig(m=M, sec_keys=[key.sec() for key in keys[:N]]).script() tx_out = TxOut(1000000, script) tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out]) for partial_key_list in itertools.permutations(keys[:N], M): tx2 = create_tx(tx1.tx_outs_as_spendable(), [keys[-1].address()]) for key in partial_key_list: self.assertEqual(tx2.bad_signature_count(), 1) hash160_lookup = build_hash160_lookup([key.secret_exponent()]) tx2.sign(hash160_lookup=hash160_lookup) self.assertEqual(tx2.bad_signature_count(), 0)
def create_tx(sp, addrs, msg): addrs_wifs = get_wifs(addrs) addrs, wifs = zip(*addrs_wifs) fee = estimate_fee([sp], addrs[:1]) tx = tx_utils.create_tx([sp], [addrs[:1][0]], fee=fee, time=now) tx.txs_out[0].coin_value -= 2 * 10**4 tx.txs_out.append(format_msg(msg)) wifs=[wifs[0]] tx.sign(LazySecretExponentDB(wifs, {}, [b'\x34', b'\x44'])) for idx, tx_out in enumerate(tx.txs_in): if not tx.is_signature_ok(idx): print('failed to sign spendable for %s' % tx.unspents[idx].bitcoin_address(), file=sys.stderr) return tx
def test_sign_pay_to_script_multisig(self): M, N = 3, 3 keys = [Key(secret_exponent=i) for i in range(1, N+2)] tx_in = TxIn.coinbase_tx_in(script=b'') underlying_script = ScriptMultisig(m=M, sec_keys=[key.sec() for key in keys[:N]]).script() address = address_for_pay_to_script(underlying_script) self.assertEqual(address, "39qEwuwyb2cAX38MFtrNzvq3KV9hSNov3q") script = standard_tx_out_script(address) tx_out = TxOut(1000000, script) tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out]) tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [address]) hash160_lookup = build_hash160_lookup(key.secret_exponent() for key in keys[:N]) p2sh_lookup = build_p2sh_lookup([underlying_script]) tx2.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup) self.assertEqual(tx2.bad_signature_count(), 0)
def create_tx(sp, addrs, msg): addrs_wifs = get_wifs(addrs) addrs, wifs = zip(*addrs_wifs) fee = estimate_fee([sp], addrs[:1]) tx = tx_utils.create_tx([sp], [addrs[:1][0]], fee=fee, time=now) tx.txs_out[0].coin_value -= 2 * 10**4 tx.txs_out.append(format_msg(msg)) wifs = [wifs[0]] tx.sign(LazySecretExponentDB(wifs, {}, [b'\x34', b'\x44'])) for idx, tx_out in enumerate(tx.txs_in): if not tx.is_signature_ok(idx): print('failed to sign spendable for %s' % tx.unspents[idx].bitcoin_address(), file=sys.stderr) return tx
def test_sign_pay_to_script_multisig(self): N, M = 3, 3 keys = [Key(secret_exponent=i) for i in range(1, M+2)] tx_in = TxIn.coinbase_tx_in(script=b'') underlying_script = ScriptMultisig(n=N, sec_keys=[key.sec() for key in keys[:M]]).script() address = address_for_pay_to_script(underlying_script) self.assertEqual(address, "39qEwuwyb2cAX38MFtrNzvq3KV9hSNov3q") script = standard_tx_out_script(address) tx_out = TxOut(1000000, script) tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out]) tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [address]) hash160_lookup = build_hash160_lookup(key.secret_exponent() for key in keys[:M]) p2sh_lookup = build_p2sh_lookup([underlying_script]) tx2.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup) self.assertEqual(tx2.bad_signature_count(), 0)
def send_payment(self, rec_email, amount): """ Still in flux """ # TO DO: a database with emails and addresses would # be far better than this receive_address = get_address_for_account(rec_email) # create input from prior transaction tx_hex, index = self.utxo(amount) tx = Tx.from_hex(tx_hex) spendable = tx.tx_outs_as_spendable()[index] # create unsigned transaction tx = create_tx([spendable], [receive_address]) print("usigned %s" % tx.as_hex()) wallet = Wallet.Wallet.from_wallet_key(self.get_wallet_keys()[0]) sign_tx(tx, [wallet.wif()]) print("signed %s" % tx.as_hex())
def createTransaction(self, address, amount, keychain, fee="standard", confirms=0): unspents_result = yield self.unspents() spendables = [] p2sh = [] chain_paths = [] # Strip leading / keychain_path = keychain['path'][1:] for unspent in unspents_result["unspents"]: if unspent["confirmations"] < confirms: continue p2sh.append(h2b(unspent["redeemScript"])) spendable = Spendable(unspent["value"], h2b(unspent["script"]), h2b_rev(unspent["tx_hash"]), unspent["tx_output_n"]) spendables.append(spendable) chain_paths.append(keychain_path + unspent['chainPath']) p2sh_lookup = build_p2sh_lookup(p2sh) address_result = yield self.createAddress(1) change = address_result["address"] tx = tx_utils.create_tx(spendables, [(address, amount), change], fee) # address_keys = [BIP32Node.from_hwif(keychain["xprv"]).subkey_for_path("0/0/0/0"), # BIP32Node.from_hwif(keychain["xprv"]).subkey_for_path(address_result['path'])] spendable_keys = [ BIP32Node.from_hwif(keychain["xprv"]).subkey_for_path(path) for path in chain_paths ] # all_keys = address_keys + spendable_keys hash160_lookup = build_hash160_lookup( [key.secret_exponent() for key in spendable_keys]) pprint(tx) tx.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup) pprint(tx) returnValue({'tx': tx.as_hex(), 'fee': tx.fee()})
def genTx(fromAddress, toAddress, netcode): b = ChainSoProvider(netcode) spendables = b.spendables_for_address(fromAddress) if not spendables: print("{} no spenables tx.".format(fromAddress)) return print('FromAddress:', fromAddress) print('Spending:', spendables) for sp in spendables: print('\tsp:', sp.coin_value) print('ToAddress:', toAddress) tx = create_tx(spendables, [toAddress]) print('TxRaw :', tx.as_hex(include_unspents=True)) return tx.as_hex(include_unspents=True)
def create_unsigned_send_tx(self, address, amount): total_input_value = 0 estimated_fee = TX_FEE_PER_THOUSAND_BYTES with self._lock: confirmations = 7 while confirmations > 0 and self.get_balance( confirmations=confirmations) < amount + estimated_fee: confirmations -= 1 spendables = [] for spendable in self.persistence.unspent_spendables( self.last_block_index(), confirmations=1): spendables.append(spendable) total_input_value += spendable.coin_value if total_input_value >= amount + estimated_fee and len( spendables) > 1: break if total_input_value < amount + estimated_fee: raise ValueError("insufficient funds: only %d available" % total_input_value) # mark the given spendables as "unconfirmed_spent" for spendable in spendables: spendable.does_seem_spent = True self.persistence.save_spendable(spendable) payables = [(address, amount)] change_amount = total_input_value - estimated_fee - amount if change_amount > DUST: change_address = self.keychain.get_change_address() payables.append(change_address) if self._desired_spendable_count is not None: if self.persistence.unspent_spendable_count( ) < self._desired_spendable_count: desired_change_output_count = len(spendables) + 1 if change_amount > desired_change_output_count * DUST: for i in range(desired_change_output_count): change_address = self.keychain.get_change_address() payables.append(change_address) tx = create_tx(spendables, payables, fee=estimated_fee) self.persistence.commit() return tx
def test_multisig_one_at_a_time(self): N = 3 M = 3 keys = [Key(secret_exponent=i) for i in range(1, M+2)] tx_in = TxIn.coinbase_tx_in(script=b'') script = ScriptMultisig(n=N, sec_keys=[key.sec() for key in keys[:M]]).script() tx_out = TxOut(1000000, script) tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out]) tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [keys[-1].address()]) ids = ["403e5bfc59e097bb197bf77a692d158dd3a4f7affb4a1fa41072dafe7bec7058", "5931d9995e83721243dca24772d7012afcd4378996a8b953c458175f15a544db", "9bb4421088190bbbb5b42a9eaa9baed7ec7574a407c25f71992ba56ca43d9c44", "03a1dc2a63f93a5cf5a7cb668658eb3fc2eda88c06dc287b85ba3e6aff751771"] for i in range(1, M+1): self.assertEqual(tx2.bad_signature_count(), 1) self.assertEqual(tx2.id(), ids[i-1]) hash160_lookup = build_hash160_lookup(key.secret_exponent() for key in keys[i-1:i]) tx2.sign(hash160_lookup=hash160_lookup) self.assertEqual(tx2.id(), ids[i]) self.assertEqual(tx2.bad_signature_count(), 0)
[docs]def main(): if len(sys.argv) != 4: print("usage: %s incoming_tx_hex_filename tx_out_index new_address" % sys.argv[0]) sys.exit(-1) with open(sys.argv[1], "r") as f: tx_hex = f.readline().strip() # get the spendable from the prior transaction tx = Tx.from_hex(tx_hex) tx_out_index = int(sys.argv[2]) spendable = tx.tx_outs_as_spendable()[tx_out_index] # make sure the address is valid payable = sys.argv[3] assert is_address_valid(payable) # create the unsigned transaction tx = create_tx([spendable], [payable]) print("here is the transaction: %s" % tx.as_hex(include_unspents=True))
def createTransaction (self, outs, fee): # Create the signed transaction spendables = self._spendables (int (fee)) #print (spendables) if len (spendables) == 0: logger.error ('No spendables available') return None t = create_tx(spendables, [self.address], fee=int (fee)) for o in outs: t.txs_out.append (TxOut (0.0, tools.compile (o))) secret_exponent = wif_to_secret_exponent(self.wif, allowable_wif_prefixes=[wif_prefix_for_netcode (self.chain)]) d = {} d.update (build_hash160_lookup([secret_exponent])) t.sign (d) txhash = (t.as_hex ()) return txhash
def main(): if len(sys.argv) != 4: print("usage: %s incoming_tx_hex_filename tx_out_index new_address" % sys.argv[0]) sys.exit(-1) with open(sys.argv[1], "r") as f: tx_hex = f.readline().strip() # get the spendable from the prior transaction tx = Tx.from_hex(tx_hex) tx_out_index = int(sys.argv[2]) spendable = tx.tx_outs_as_spendable()[tx_out_index] # make sure the address is valid payable = sys.argv[3] assert is_address_valid(payable) # create the unsigned transaction tx = create_tx([spendable], [payable]) print("here is the transaction: %s" % tx.as_hex(include_unspents=True))
def create_unsigned_send_tx(self, address, amount): total_input_value = 0 estimated_fee = TX_FEE_PER_THOUSAND_BYTES with self._lock: confirmations = 7 while confirmations > 0 and self.get_balance(confirmations=confirmations) < amount + estimated_fee: confirmations -= 1 spendables = [] for spendable in self.persistence.unspent_spendables( self.last_block_index(), confirmations=1): spendables.append(spendable) total_input_value += spendable.coin_value if total_input_value >= amount + estimated_fee and len(spendables) > 1: break if total_input_value < amount + estimated_fee: raise ValueError("insufficient funds: only %d available" % total_input_value) # mark the given spendables as "unconfirmed_spent" for spendable in spendables: spendable.does_seem_spent = True self.persistence.save_spendable(spendable) payables = [(address, amount)] change_amount = total_input_value - estimated_fee - amount if change_amount > DUST: change_address = self.keychain.get_change_address() payables.append(change_address) if self._desired_spendable_count is not None: if self.persistence.unspent_spendable_count() < self._desired_spendable_count: desired_change_output_count = len(spendables) + 1 if change_amount > desired_change_output_count * DUST: for i in range(desired_change_output_count): change_address = self.keychain.get_change_address() payables.append(change_address) tx = create_tx(spendables, payables, fee=estimated_fee) self.persistence.commit() return tx
def createTransaction(self, address, amount, keychain, fee="standard", confirms=0): unspents_result = yield self.unspents() spendables = [] p2sh = [] chain_paths = [] # Strip leading / keychain_path = keychain['path'][1:] for unspent in unspents_result["unspents"]: if unspent["confirmations"] < confirms: continue p2sh.append(h2b(unspent["redeemScript"])) spendable = Spendable(unspent["value"], h2b(unspent["script"]), h2b_rev(unspent["tx_hash"]), unspent["tx_output_n"]) spendables.append(spendable) chain_paths.append(keychain_path + unspent['chainPath']) p2sh_lookup = build_p2sh_lookup(p2sh) address_result = yield self.createAddress(1) change = address_result["address"] tx = tx_utils.create_tx(spendables, [(address, amount), change], fee) # address_keys = [BIP32Node.from_hwif(keychain["xprv"]).subkey_for_path("0/0/0/0"), # BIP32Node.from_hwif(keychain["xprv"]).subkey_for_path(address_result['path'])] spendable_keys = [BIP32Node.from_hwif(keychain["xprv"]).subkey_for_path(path) for path in chain_paths] # all_keys = address_keys + spendable_keys hash160_lookup = build_hash160_lookup([key.secret_exponent() for key in spendable_keys]) pprint(tx) tx.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup) pprint(tx) returnValue({'tx': tx.as_hex(), 'fee': tx.fee()})
def multisig_M_of_N(self, M, N, unsigned_id, signed_id): keys = [ Key(secret_exponent=i, generator=secp256k1_generator) for i in range(1, N + 2) ] tx_in = TxIn.coinbase_tx_in(script=b'') script = script_for_multisig(m=M, sec_keys=[key.sec() for key in keys[:N]]) tx_out = TxOut(1000000, script) tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out]) tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [keys[-1].address()]) self.assertEqual(tx2.id(), unsigned_id) self.assertEqual(tx2.bad_signature_count(), 1) hash160_lookup = build_hash160_lookup( (key.secret_exponent() for key in keys[:M]), [secp256k1_generator]) tx2.sign(hash160_lookup=hash160_lookup) self.assertEqual(tx2.id(), signed_id) self.assertEqual(tx2.bad_signature_count(), 0) self.assertEqual( sorted(who_signed_tx(tx2, 0, UI)), sorted(((key.address(), SIGHASH_ALL) for key in keys[:M])))
def test_sign_pay_to_script_multisig(self): M, N = 3, 3 keys = [ Key(secret_exponent=i, generator=secp256k1_generator) for i in range(1, N + 2) ] tx_in = TxIn.coinbase_tx_in(script=b'') underlying_script = script_for_multisig( m=M, sec_keys=[key.sec() for key in keys[:N]]) address = address_for_p2s(underlying_script) self.assertEqual(address, "39qEwuwyb2cAX38MFtrNzvq3KV9hSNov3q") script = script_for_address(address) tx_out = TxOut(1000000, script) tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out]) tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [address]) hash160_lookup = build_hash160_lookup( (key.secret_exponent() for key in keys[:N]), [secp256k1_generator]) p2sh_lookup = build_p2sh_lookup([underlying_script]) tx2.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup) self.assertEqual(tx2.bad_signature_count(), 0) self.assertEqual( sorted(who_signed_tx(tx2, 0, UI)), sorted(((key.address(), SIGHASH_ALL) for key in keys[:M])))
# Very important part. When you move funds to a p2sh address you write a special scriptPubKey: # Instead of: OP_DUP OP_HASH160 <PubkeyHash> OP_EQUALVERIFY OP_CHECKSIG # your p2sh scriptPubKey will be: # OP_HASH160 <hash(redeemScript)> OP_EQUAL # standard_tx_out_script(address) gives the scriptPubKey for a given multisig address script = standard_tx_out_script(address) # Fake coinbase transaction to fill our p2sh address # It it is a coinbase transaction we put in a newly constructed block. tx_in = TxIn.coinbase_tx_in(script=b'') print("TxIn: %s" % tx_in.__str__()) tx_out = TxOut(1000000, script) print("TxOut: %s" % tx_out.__str__()) tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out]) tx1.as_hex() # we now have an UTXO redeemable by supplying the script and the required sigs. # tx_utils.create_tx() allows to spend all the UTXO from the preavious tx to an arbitrary address. tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [keys[-1].address()]) # to split the input in each of the generated addresses # tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [keys[i].address() for i in range(len(keys))]) print("unsigned transaction:") print("bad signatures: %s" % tx2.bad_signature_count()) print(tx2.as_hex()) for i in range(1, N+1): print("signining with key number: %s" % i) hash160_lookup = build_hash160_lookup([keys[i].secret_exponent()]) p2sh_lookup = build_p2sh_lookup([underlying_script]) tx2.sign(hash160_lookup=hash160_lookup,p2sh_lookup=p2sh_lookup) print(tx2.as_hex()) print("This transactions have now : %s signature of %t necessary" % (i, N)) print("bad signatures: %s" % tx2.bad_signature_count())
def send(self, wallet_id, passcode, address, amount, message='', fee=None, fan_unspend=10): """ Send bitcoins to address :param wallet_id: bitgo wallet id :param address: bitcoin address :param amount: btc amount in satoshis :param split: create new outputs if needed :return: boolean """ MINIMAL_FEE = 20000 MINIMAL_SPLIT = 10000000 MIN_UNSPENTS_FAN = 5 wallet = self.get_wallet(wallet_id) if not wallet['spendingAccount']: raise NotSpendableWallet() if not wallet['isActive']: raise NotActiveWallet() if amount < 10000: raise Exception('amount to small') if wallet['confirmedBalance'] < amount: raise NotEnoughFunds('Not enough funds: balance %s amount %s' % (wallet['confirmedBalance'], amount) ) change_address = self.create_address(wallet_id, chain=1) usableKeychain = False spendables = [] chain_paths = [] p2sh = [] payables = [(address, amount)] keychain_path = "" for keychain in wallet['private']['keychains']: keychain_path = keychain['path'][1:] keychain = self.get_keychain(keychain['xpub']) if 'encryptedXprv' not in keychain: continue usableKeychain = True break if not usableKeychain: raise BitGoError("didn't found a spendable keychain") data = json.loads(keychain['encryptedXprv']) #add base64 paddings for k in ['iv', 'salt', 'ct']: data[k] = data[k] + "==" cipher = sjcl.SJCL() xprv = cipher.decrypt(data, passcode) unspents = self.get_unspents(wallet_id)['unspents'] order_unspents = sorted(unspents, key=lambda k: k['confirmations'], reverse=True) total_value = 0 for d in order_unspents: path = keychain_path + d['chainPath'] chain_paths.append(path) p2sh.append(h2b(d["redeemScript"])) spendables.append(Spendable(d["value"], h2b(d["script"]), h2b_rev(d["tx_hash"]), d["tx_output_n"])) total_value += d['value'] if total_value > amount: break # make many outputs? if len(order_unspents) < MIN_UNSPENTS_FAN and (total_value > (amount + MINIMAL_SPLIT)) and fan_unspend > 0: fee = self.calculate_fee(len(spendables), fan_unspend) value = (total_value - amount - fee) / fan_unspend for i in range(fan_unspend): payables.append((change_address, value)) elif total_value > (amount + MINIMAL_FEE): # add a change address if fee is None: fee = self.calculate_fee(len(spendables), 2) value = total_value - amount - fee if value > 10000: #avoid dust payables.append((change_address, value)) p2sh_lookup = build_p2sh_lookup(p2sh) spendable_keys = [] priv_key = BIP32Node.from_hwif(xprv) spendable_keys = [priv_key.subkey_for_path(path) for path in chain_paths] hash160_lookup = build_hash160_lookup([key.secret_exponent() for key in spendable_keys]) tx = create_tx(spendables, payables) tx.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup) r = requests.post(self.url + '/tx/send', { 'tx': tx.as_hex(), 'message': message }, headers={ 'Authorization': 'Bearer %s' % self.access_token, }) return r.json()
def send(self, wallet_id, passcode, address, amount, message='', fee=10000): """ Send bitcoins to address :param wallet_id: bitgo wallet id :param address: bitcoin address :param amount: btc amount in satoshis :return: boolean """ wallet = self.get_wallet(wallet_id) if not wallet['spendingAccount']: raise NotSpendableWallet() if not wallet['isActive']: raise NotActiveWallet() if amount < 10000: raise Exception('amount to small') if wallet['confirmedBalance'] < amount: raise NotEnoughFunds('Not enough funds: balance %s amount %s' % (wallet['confirmedBalance'], amount)) change_address = self.create_address(wallet_id, chain=1) usableKeychain = False spendables = [] chain_paths = [] p2sh = [] payables = [(address, amount)] keychain_path = "" for keychain in wallet['private']['keychains']: keychain_path = keychain['path'][1:] keychain = self.get_keychain(keychain['xpub']) if 'encryptedXprv' not in keychain: continue usableKeychain = True break if not usableKeychain: raise BitGoError("didn't found a spendable keychain") data = json.loads(keychain['encryptedXprv']) #add base64 paddings for k in ['iv', 'salt', 'ct']: data[k] = data[k] + "==" cipher = sjcl.SJCL() xprv = cipher.decrypt(data, passcode) unspents = self.get_unspents(wallet_id) total_value = 0 for d in unspents['unspents'][::-1]: path = keychain_path + d['chainPath'] chain_paths.append(path) p2sh.append(h2b(d["redeemScript"])) spendables.append( Spendable(d["value"], h2b(d["script"]), h2b_rev(d["tx_hash"]), d["tx_output_n"])) total_value += d['value'] if total_value > amount: break if total_value > (amount + fee): #add a change address #TODO: create address payables.append(change_address) p2sh_lookup = build_p2sh_lookup(p2sh) spendable_keys = [] priv_key = BIP32Node.from_hwif(xprv) spendable_keys = [ priv_key.subkey_for_path(path) for path in chain_paths ] hash160_lookup = build_hash160_lookup( [key.secret_exponent() for key in spendable_keys]) tx = create_tx(spendables, payables) tx.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup) r = requests.post(self.url + '/tx/send', { 'tx': tx.as_hex(), 'message': message }, headers={ 'Authorization': 'Bearer %s' % self.access_token, }) return r.json()
script = ScriptMultisig(n=2, sec_keys=[key.sec() for key in keys]).script() print("script:") print(b2h(script)) address = address_for_pay_to_script(script) print(address) # Everything's ok until here """ tx_in = TxIn.coinbase_tx_in(script=b'') tx_out = TxOut(10000, script) # 0.1 mBits tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out]) """ spendables = blockr_io.spendables_for_address(address) #grab the spendables from an address tx = tx_utils.create_tx(spendables, [spk1.address()], fee="standard") # tx with the amount to the destination address. I take one key of which I have the secret key. hash160_lookup = build_hash160_lookup(key.secret_exponent() for key in keys[0:2]) # only the first two are private keys # build_hash160_lookup(key.secret_exponent() for key in keys[0:1]) # I sign only with the first one. # also build_hash160_lookup(Key.secret_exponent(keys[0])) tx2.sign(hash160_lookup=hash160_lookup) tx2.as_hex() #to be tested """ tx = create_tx( spendables_for_address("1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH"), [("1cMh228HTCiwS8ZsaakH8A8wze1JR5ZsP", 100)], fee=0) tx.sign_tx(wifs=["KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn"]) oppure tuuto d'un colpo: tx = create_signed_tx(
script = b2h(script_encoded) print("Script:") print(script) print("") address = address_for_pay_to_script(script_encoded) # 3Bi36w9RZHmibi1ip7ud9dvtpDt59ij7GC print("Address: %s" % address) print("") spendables = spendables_for_address(address) # UTXOs of address # The simplest transaction: all the UTXOs, less the fees, go to the address. tx = create_tx(spendables,["3977Lp7VNWY5L8hY5W2oaNjeR5r8FZ6ban"], fee="standard") # raw hex not-signed transaction tx.as_hex() # to sign the transaction I need the sub_private keys print("Transaction as Hex:") print(tx.as_hex(tx)) print("") # My Extended private subkeys subBip32PrivateNodes = [BIP32Node.subkey_for_path(Key.from_text(private_wallets[i]), chainPaths[i]) for i in range(len(private_wallets))] # subnodes print("Sub BIP32 private wallets:") for i in subBip32PrivateNodes: print(i)
def main(params=[]): """ Main function that deals with the information Args: ----- params: List of arguments received from the command line. """ banner = """ ____ _ _ _ _ ____ ____ ____ | __ )| | ___ ___| | _____| |__ __ _(_)_ __ / ___|___ \ / ___| | _ \| |/ _ \ / __| |/ / __| '_ \ / _` | | '_ \ | | __) | | | |_) | | (_) | (__| < (__| | | | (_| | | | | | | |___ / __/| |___ |____/|_|\___/ \___|_|\_\___|_| |_|\__,_|_|_| |_| \____|_____|\____| A PoC to push data to several blockchains by: - Yaiza Rubio (@yrubiosec) - Félix Brezo (@febrezo)""" print(banner) # Grabbing the parser parser = getParser() if params != None: args = parser.parse_args(params) else: args = parser.parse_args() # Getting the brain wallet network = raw_input( "\n> Choose type of network (BTC, XTN, LTC, XLT...) [XTN] ") or "XTN" while network not in VALID_NETWORKS: print("> The value provided '" + network + "' is not a possible option. Choose one of the following:\n" + json.dumps(VALID_NETWORKS.keys(), indent=2)) network = raw_input( "\n> Choose type of network (BTC, XTN, LTC, XLT...) [XTN] " ) or "XTN" print("\tNetwork: " + network) # Defining the target address admin_type = None while admin_type not in ["brain", "other"]: admin_type = raw_input( "\n> Set ADMIN address: 'brain' or 'other'? [brain] ") or "brain" if admin_type == "brain": brain = raw_input("\n> Say word for the ADMIN brainwallet: ") print("\tWe will generate the details for the target address:") priv = generatePrivateKey(brain) src_address = priv.address() elif admin_type == "other": print( "\tNote that you might not know the private key of this address so you can lose your balance:" ) src_WIF = raw_input( "\n> Set the admin private key in WIF format: ") #TODO: priv = Key.from_text(src_WIF) else: admin_type = raw_input( "\n> Set ADMIN address: 'brain' or 'other'? [brain] " ) or "brain" # Get the spendable outputs we are going to use to pay the fee print("\n> Choosing a provider!") provider = getProvider(network=network) spendables = provider.spendables_for_address(priv.address()) # Summing it up source_balance = sum(spendable.coin_value for spendable in spendables) print("\tBalance: " + str(source_balance)) if source_balance <= 0: print( "\n> No money in the account! You will need an account with some! Exiting!" ) sys.exit() # Defining the message to be send message_str = raw_input("\n> Set message to send: ") # No more than 80 caracters please! if (len(message_str) > 80): sys.exit("Message must be 80 characters or less") print("\tMessage (string): " + message_str) message_hex = hexlify(message_str.encode()).decode('utf8') print("\tMessage (hexadecimal): " + message_hex) # Defining the target address target_type = None while target_type not in ["brain", "other"]: target_type = raw_input( "\n> Set target address: 'brain' or 'other'? [brain] ") or "brain" if target_type == "brain": brain_dst = raw_input("\n> Say word for the TARGET brainwallet: ") print("\tWe will generate the details for the target address:") target = generatePrivateKey(brain_dst) dst_address = target.address() elif target_type == "other": print( "\tNote that you might not know the private key of this address so you can lose your balance:" ) dst_address = raw_input("\n> Set the target address: ") else: target_type = raw_input( "\n> Set target address: 'brain' or 'other'? [brain] " ) or "brain" # Defining the default fee try: fee = int(raw_input("\n> Set the fee [10000]: ")) except: fee = 10000 print("\tFee assigned: " + str(fee)) # Generating the transaction print( "\n> We'll try to create the transaction using all the spendables for " + priv.address()) # Creating the transaction tx = tx_utils.create_tx(spendables, [(dst_address, source_balance - fee)], fee=fee) print("\tTx:\n" + str(tx)) print("\n> We will create the OP_RETURN script for the message '" + message_str + "'.") # We need the hexadecimal representation of the message op_return_output_script = script.tools.compile("OP_RETURN %s" % message_hex) print("\tOP_RETURN script:\n" + str([str(op_return_output_script)])) print("\n> Appending the new OP_RETURN script to the transaction:") tx.txs_out.append(TxOut(0, op_return_output_script)) print("\tTx:\n" + str(tx)) print("\tNumber of outputs: " + str(len(tx.txs_out))) print("\tDisplaying the outputs:\n") for o in tx.txs_out: print("\t\t- " + str(o)) #print "\tDictionary representing the transaction:\n" + tx.__dict__ print("\n> Signing the transaction:") tx_utils.sign_tx(tx, netcode=network, wifs=[priv.wif()]) print("\tNow tx is a signed transaction:") print("\tTx:\n" + str(tx)) print("\n> Showing the hexadecimal information of the SIGNED transaction:") print(tx.as_hex()) if args.push: print("\n> We will try to push the signed transaction now:") pushTx(network=network, tx_hex=tx.as_hex()) else: print("\n> You can push this transaction manually using curl:") print("\tcurl -d 'tx_hex=" + tx.as_hex() + "' https://chain.so/api/v2/send_tx/" + VALID_NETWORKS[network]) print( "\n> You can also manually push this with the Web UI of BlockExplorer at <https://testnet.blockexplorer.com/tx/send>." ) print( "\n> You might want to do it using Tor Browser Bundle or torify to not let even a trace to know who you are in the provider." )
private_key = Key(secret_exponent=int.from_bytes(key_bytes, 'big')) address = private_key.address() print('Your Bitcoin address is...', address) print('Your --privkey-bytes', hexlify(key_bytes).decode()) try: spendables = spendables_for_address(address, None) print('Spending', spendables) except HTTPError as e: print( 'Blockchain throws a 500 error if there are no spendables. Try sending some coins to', address, 'and try again. Remeber to copy privkey-bytes.') sys.exit() tx = create_tx(spendables, [args.send_all_to]) print('TX created:', repr(tx)) sign_tx(tx, [private_key.wif(False), private_key.wif(True)]) print('Final TX:', tx) # print('TX Send Attempt:', send_tx(tx)) ''' tx_in = TxIn("<utxo hash in binary here>", <utxo position, usually between 0 and 5>) script = standard_tx_out_script(address) tx_out = TxOut(<btc amount to send - fee>, script) tx = Tx(1, [tx_in], [tx_out]) lookup = <this part you have to figure out> tx.sign(lookup) print tx.as_hex()
def send(self, wallet_id, passcode, address, amount, message='', fee=10000): """ Send bitcoins to address :param wallet_id: bitgo wallet id :param address: bitcoin address :param amount: btc amount in satoshis :return: boolean """ wallet = self.get_wallet(wallet_id) if not wallet['spendingAccount']: raise NotSpendableWallet() if not wallet['isActive']: raise NotActiveWallet() if amount < 10000: raise Exception('amount to small') if wallet['confirmedBalance'] < amount: raise NotEnoughFunds('Not enough funds: balance %s amount %s' % (wallet['confirmedBalance'], amount) ) change_address = self.create_address(wallet_id, chain=1) usableKeychain = False spendables = [] chain_paths = [] p2sh = [] payables = [(address, amount)] keychain_path = "" for keychain in wallet['private']['keychains']: keychain_path = keychain['path'][1:] keychain = self.get_keychain(keychain['xpub']) if 'encryptedXprv' not in keychain: continue usableKeychain = True break if not usableKeychain: raise BitGoError("didn't found a spendable keychain") data = json.loads(keychain['encryptedXprv']) #add base64 paddings for k in ['iv', 'salt', 'ct']: data[k] = data[k] + "==" cipher = sjcl.SJCL() xprv = cipher.decrypt(data, passcode) unspents = self.get_unspents(wallet_id) total_value = 0 for d in unspents['unspents'][::-1]: path = keychain_path + d['chainPath'] chain_paths.append(path) p2sh.append(h2b(d["redeemScript"])) spendables.append(Spendable(d["value"], h2b(d["script"]), h2b_rev(d["tx_hash"]), d["tx_output_n"])) total_value += d['value'] if total_value > amount: break if total_value > (amount + fee): #add a change address #TODO: create address payables.append(change_address) p2sh_lookup = build_p2sh_lookup(p2sh) spendable_keys = [] priv_key = BIP32Node.from_hwif(xprv) spendable_keys = [priv_key.subkey_for_path(path) for path in chain_paths] hash160_lookup = build_hash160_lookup([key.secret_exponent() for key in spendable_keys]) tx = create_tx(spendables, payables) tx.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup) r = requests.post(self.url + '/tx/send', { 'tx': tx.as_hex(), 'message': message }, headers={ 'Authorization': 'Bearer %s' % self.access_token, }) return r.json()