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_solution_count(), 1) self.assertEqual(tx2.id(), ids[i - 1]) hash160_lookup = build_hash160_lookup( (key.secret_exponent() for key in keys[i - 1:i]), [secp256k1_generator]) tx2.sign(hash160_lookup=hash160_lookup) self.assertEqual(tx2.id(), ids[i]) self.assertEqual(tx2.bad_solution_count(), 0)
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 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 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(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)
def multisig_M_of_N_individually(self, M, N): keys = [Key(secret_exponent=i, generator=secp256k1_generator) for i in range(1, N+2)] tx_in = Tx.TxIn.coinbase_tx_in(script=b'') script = script_for_multisig(m=M, sec_keys=[key.sec() for key in keys[:N]]) tx_out = Tx.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()], [secp256k1_generator]) tx2.sign(hash160_lookup=hash160_lookup) self.assertEqual(tx2.bad_signature_count(), 0)
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)
def multisig_M_of_N_individually(self, M, N): keys = [Key(secret_exponent=i) for i in range(1, N + 2)] tx_in = Tx.TxIn.coinbase_tx_in(script=b'') script = script_for_multisig(m=M, sec_keys=[key.sec() for key in keys[:N]]) tx_out = Tx.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_solution_count(), 1) hash160_lookup = build_hash160_lookup([key.secret_exponent()], [secp256k1_generator]) tx2.sign(hash160_lookup=hash160_lookup) self.assertEqual(tx2.bad_solution_count(), 0)
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_solution_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_solution_count(), 0)
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_solution_count(), 0)
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((key.secret_exponent() for key in keys[i-1:i]), [secp256k1_generator]) tx2.sign(hash160_lookup=hash160_lookup) self.assertEqual(tx2.id(), ids[i]) self.assertEqual(tx2.bad_signature_count(), 0)
def _generate_transaction(self, spendables: List[Spendable], ins: List[InputTransaction], payables: List[Tuple]): tx = create_tx(spendables, payables, network=self._network, fee=0) priv_key = ins[0].priv_key sign_tx(tx, [priv_key.wif(False), priv_key.wif(True)], network=self._network) if len(ins) > 1: for q in range(1, len(ins)): priv_key = ins[q].priv_key sign_tx(tx, [priv_key.wif(False), priv_key.wif(True)], network=self._network) s = io.BytesIO() tx.stream(s) tx_as_hex = b2h(s.getvalue()) return tx_as_hex
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 = network.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 my_create_tx(*args, **kwargs): return create_tx(network, *args, **kwargs)