Skip to content

Transaction broadcasts successfully with one mnemonic but fails with another (UTXO valid, mnemonic-address pair verified) #480

@mallcoffee123g01-bot

Description

@mallcoffee123g01-bot

When creating and signing a SegWit (Bech32) transaction on Bitcoin Testnet using bitcoinlib,
the transaction broadcast succeeds with one mnemonic phrase,
but fails with "bad-txns-inputs-missingorspent" when using another mnemonic —
even though the UTXO is valid and the derived SegWit address perfectly matches.

Code that works

from bitcoinlib.keys import HDKey
from bitcoinlib.transactions import Transaction

=== Create private key from mnemonic phrase ===

phrase = 'merit tattoo fish response jar churn pear ski weekend ugly feature public'
k = HDKey().from_passphrase(phrase, network='testnet4')

def create_native_segwit_offline_transaction(prev_txid, prev_output_index, prev_output_value,
from_privkey, to_address, send_value, network='testnet4'):
# 建立 segwit 交易
tx = Transaction(network=network, witness_type='segwit')

# 加入輸入 (UTXO)
tx.add_input(prev_txid, prev_output_index, keys=[from_privkey],
             value=prev_output_value, witness_type='segwit')

# 加入輸出 (要轉給誰)
tx.add_output(send_value, to_address)

# 簽名並更新交易
tx.sign_and_update()
tx.verify()

# 回傳原始交易 hex
return tx.as_hex()

=== 測試資料 ===

network = 'testnet4'
prev_txid = 'b759ffc1c3b85814ecb8f9333b6dc9329673db1cd02397612824a795a0022d18'
prev_output_index = 1
prev_output_value = 185046 # 0.00185046 BTC
to_address = '
'
send_value = 1000 # satoshis
from_privkey = k

=== 建立交易 ===

raw_tx_hex = create_native_segwit_offline_transaction(
prev_txid, prev_output_index, prev_output_value,
from_privkey, to_address, send_value, network
)

print("Raw transaction hex:")
print(raw_tx_hex)

Image

Code that fails

from bitcoinlib.keys import HDKey
from bitcoinlib.transactions import Transaction

=== Create private key from mnemonic phrase ===

phrase = 'apology ridge roof conduct orchard miss horse frequent damage shock jewel rescue'
k = HDKey().from_passphrase(phrase, network='testnet')

def create_native_segwit_offline_transaction(prev_txid, prev_output_index, prev_output_value,
from_privkey, to_address, send_value, network='testnet'):
# 建立 segwit 交易
tx = Transaction(network=network, witness_type='segwit')

# 加入輸入 (UTXO)
tx.add_input(prev_txid, prev_output_index, keys=[from_privkey],
             value=prev_output_value, witness_type='segwit')

# 加入輸出 (要轉給誰)
tx.add_output(send_value, to_address)

# 簽名並更新交易
tx.sign_and_update()
tx.verify()

# 回傳原始交易 hex
return tx.as_hex()

=== 測試資料 ===

network = 'testnet'
prev_txid = 'd3fe9e674593ed693af7b21cf6e3d4ab6c9ee6646b2ce70cd4349f72ee9ccb95'
prev_output_index = 1
prev_output_value = 156661 # 0.00156661BTC
to_address = 'tb1qnmk0wazls8khuf0tkl9enx32l5krcua94jhlf6'
send_value = 1000 # satoshis
from_privkey = k

=== 建立交易 ===

raw_tx_hex = create_native_segwit_offline_transaction(
prev_txid, prev_output_index, prev_output_value,
from_privkey, to_address, send_value, network
)

print("Raw transaction hex:")
print(raw_tx_hex)

Broadcast fails
Error:
Failed to broadcast transaction, reason: bad-txns-inputs-missingorspent

Verification
I confirmed that:
The UTXO d3fe9e674593ed693af7b21cf6e3d4ab6c9ee6646b2ce70cd4349f72ee9ccb95:0
is valid and unspent (confirmed balance 0.00156661 tBTC).

Image

The mnemonic-derived address is correct:
✅ Derived address: tb1q0kmuhh5f63vj5jw8cl7w0dg06a4fxujke7adfv
🔍 Blockchain address: tb1q0kmuhh5f63vj5jw8cl7w0dg06a4fxujke7adfv
🎉 Match confirmed

Mnemonic–Address Verification Code
from bip_utils import (
Bip39SeedGenerator,
Bip84,
Bip84Coins,
Bip39MnemonicValidator,
Bip39Languages,
Bip44Changes
)
import sys

=== Input: mnemonic phrase and address to verify ===

MNEMONIC = "apology ridge roof conduct orchard miss horse frequent damage shock jewel rescue"
ADDRESS_TO_VERIFY = "tb1q0kmuhh5f63vj5jw8cl7w0dg06a4fxujke7adfv"

=== Validate that the mnemonic is a valid BIP39 English phrase ===

if not Bip39MnemonicValidator(Bip39Languages.ENGLISH).IsValid(MNEMONIC):
print("❌ Invalid mnemonic! Please make sure it is a valid English BIP39 mnemonic.")
sys.exit(1)

=== Generate seed from mnemonic and create a BIP84 (SegWit) wallet for Bitcoin Testnet ===

seed_bytes = Bip39SeedGenerator(MNEMONIC).Generate()
bip84_ctx = Bip84.FromSeed(seed_bytes, Bip84Coins.BITCOIN_TESTNET)

=== Derive the first address (m/84'/1'/0'/0/0) ===

addr_obj = bip84_ctx.Purpose().Coin().Account(0).Change(Bip44Changes.CHAIN_EXT).AddressIndex(0)
derived_addr = addr_obj.PublicKey().ToAddress()

=== Compare the derived address with the one provided ===

print(f"✅ Derived SegWit address from mnemonic: {derived_addr}")
print(f"🔍 Address to verify: {ADDRESS_TO_VERIFY}")

if derived_addr == ADDRESS_TO_VERIFY:
print("\n🎉 Verification successful: the mnemonic and the SegWit Testnet address match perfectly!")
print("👉 This confirms that the given mnemonic correctly generates the specified Bitcoin Testnet address.")
else:
print("\n⚠️ Verification failed: the mnemonic does not match the given address.")
print("👉 Please double-check your mnemonic or the derivation path (e.g., m/84'/1'/0'/0/0).")

output
output like this if everything matches:
✅ Derived SegWit address from mnemonic: tb1q0kmuhh5f63vj5jw8cl7w0dg06a4fxujke7adfv
🔍 Address to verify: tb1q0kmuhh5f63vj5jw8cl7w0dg06a4fxujke7adfv

🎉 Verification successful: the mnemonic and the SegWit Testnet address match perfectly!
👉 This confirms that the given mnemonic correctly generates the specified Bitcoin Testnet address.

Question
How can I fix the issue where the transaction can be broadcast successfully with one mnemonic and address, but fails to broadcast when using a different mnemonic and address, even though:
the UTXO is correct,
and the mnemonic and address are verified to match (using the verification code above)?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions