Creating RawTX Bitcoin Transactions Using Bloom Filter in Python

20.03.2025
Creating RawTX Bitcoin Transactions Using Bloom Filter in Python

To create a raw Bitcoin transaction using Bloom filter in Python, we combine two key technologies: transaction formation and data filtering. Here is the implementation:

python

from bitcoinutils.setup import setup
from bitcoinutils.transactions import Transaction, TxInput, TxOutput
from bitcoinutils.keys import PrivateKey, P2pkhAddress
from pybloom import BloomFilter

def create_raw_tx():
# Инициализация сети Bitcoin
setup('mainnet')

# Инициализация Bloom filter с адресами кошелька
wallet_addresses = [
'1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa',
'1BitcoinEaterAddressDontSendf59kuE'
]

bloom = BloomFilter(
capacity=1000,
error_rate=0.001,
backend='bitarray'
)

for addr in wallet_addresses:
bloom.add(addr)

# Фильтрация UTXO (пример данных)
utxo_list = [
{
'txid': 'abc123...',
'vout': 0,
'amount': 0.01,
'address': '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa',
'privkey': 'L4gB7...'
}
]

# Выбор подходящих UTXO через Bloom filter
selected_utxo = [
utxo for utxo in utxo_list
if utxo['address'] in bloom
]

# Создание входов транзакции
inputs = []
for utxo in selected_utxo:
inputs.append(TxInput(utxo['txid'], utxo['vout']))

# Создание выходов
output = TxOutput(
0.009, # сумма с учетом комиссии
P2pkhAddress('recipient_address_here').to_script_pub_key()
)

# Сборка транзакции
tx = Transaction(inputs, [output])

# Подписание входов
for i, utxo in enumerate(selected_utxo):
priv_key = PrivateKey.from_wif(utxo['privkey'])
tx.sign_input(i, priv_key)

return tx.serialize()

# Выполнение
print("Raw transaction:", create_raw_tx())

Key components of the solution:

  1. Bloom Filter initialization
    Used to filter UTXOs belonging to wallet 6 . Parameters:
    • capacity— expected number of elements
    • error_rate— acceptable probability of false positives
  2. UTXO filtering mechanism
    Checking address ownership via operator in4 . Actual data should be obtained from:
    • Local UTXO base
    • External Blockchain APIs
    • Bitcoin Full Node
  3. Optimizing the
    Bloom filter speed reduces the UTXO lookup time from O(n) to O(1) 6 , which is critical for:
    • Wallets with a large transaction history
    • Real time systems
    • Mobile applications

Recommendations for improvement:

  1. Add change output processing
  2. Implement dynamic commission calculation
  3. Integrate Bitcoin node connection via JSON-RPC
  4. Add support for SegWit addresses

The script requires the following dependencies to work:

pip install bitcoinutils BloomFilterPy

Example output:

Raw transaction: 0200000001... [полный hex транзакции]

To create a raw Bitcoin transaction using BloomFilterPy, follow this step-by-step guide. The example implements optimized UTXO lookup and transaction assembly.

**1. Installing Dependencies**
```bash
pip install bitcoinutils BloomFilterPy
```

**2. Full example script**
```python
from bitcoinutils.setup import setup
from bitcoinutils.transactions import Transaction, TxInput, TxOutput
from bitcoinutils.keys import PrivateKey, P2pkhAddress
from pybloom import BloomFilter

def build_tx_with_bloom():
# Initialize the Bitcoin network
setup('mainnet')

# List of wallet addresses
wallet_addrs = [
'1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa',
'bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq'
]

# Initialize Bloom filter
bloom = BloomFilter(
capacity=500, # Expected number of elements
error_rate=0.01, # 1% probability of errors
mode='optimal' # Automatic selection of parameters
)

# Adding addresses to the filter
for addr in wallet_addrs:
bloom.add(addr.encode('utf-8')) # Be sure to convert to bytes

# Getting UTXO (sample data)
utxo_pool = [
{
'txid': 'a9d459...',
'vout': 0,
'amount': 0.005,
'address': '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa',
'privkey': 'L4gB7...'
}
]

# Filtering via Bloom
valid_utxo = [utxo for utxo in utxo_pool
if bloom.check(utxo['address'].encode('utf-8'))]

# Creating transaction inputs
tx_inputs = [TxInput(utxo['txid'], utxo['vout']) for utxo in valid_utxo]

# Calculate amount and fee
total_in = sum(utxo['amount'] for utxo in valid_utxo)
fee = 0.00015 # Fee example
send_amount = total_in - fee

# Create output
recipient = '1BoatSLRHtKNngkdXEeobR76b53LETtpyT'
tx_output = TxOutput(
send_amount,
P2pkhAddress(recipient).to_script_pub_key()
)

# Assemble and sign
tx = Transaction(tx_inputs, [tx_output])
for i, utxo in enumerate(valid_utxo):
tx.sign_input(i, PrivateKey.from_wif(utxo['privkey']))

return tx.serialize()

print(f"Raw TX:{build_tx_with_bloom()}")
```

**Key aspects of working with BloomFilterPy:**

| Parameter | Recommended value | Description |
|-------------------|-------------------------|-----------------------------------|
| `capacity` | N × 1.2 | N - expected number of elements |
| `error_rate` | 0.01-0.001 | Filtering accuracy |
| `hash_seeds` | Auto-select | Seeds for hash functions |
| `mode` | `optimal` | Automatic optimization |

**Performance optimizations:**
1. Use `bloom.check()` instead of `in` operator for checking
2. Convert strings to bytes before adding to filter
3. For large datasets, increase `capacity` by 20-30%

**Security recommendations:**
```python
# Additional check after filtering
from bitcoinutils.utils import is_valid_address

verified_utxo = []
for utxo in valid_utxo:
if is_valid_address(utxo['address']):
verified_utxo.append(utxo)
```

**Typical output:**
```
Raw TX: 0100000001... [full HEX of transaction]
```

For real use case you need to:
1. Integrate UTXO source (Electrum server, Blockstream API)
2. Implement dynamic fee calculation via mempool.space API
3. Add change address processing
4. Enable SegWit support (bech32 addresses)

Example of calculating Bloom filter parameters for 1000 addresses:
```python
BloomFilter(
capacity=1200,
error_rate=0.001,
mode='fast' # Speed ​​optimization
)
```






How to Integrate BloomFilterPy with Other Libraries to Create RawTX

To integrate BloomFilterPy with various Bitcoin transaction creation libraries, we will look at three popular frameworks. Each example demonstrates the key steps: UTXO filtering and transaction assembly.

1. Integration with bitcoinlib (HD wallets)

python

from bitcoinlib.transactions import Transaction
from bitcoinlib.keys import Key
from pybloom import BloomFilter

# Инициализация Bloom фильтра
bloom = BloomFilter(capacity=1000, error_rate=0.01)
wallet_addresses = ['1A1zP...', 'bc1q...']
[bloom.add(addr.encode()) for addr in wallet_addresses]

# Фильтрация UTXO через Electrum-сервер
from bitcoinlib.services.services import Service

service = Service(network='bitcoin')
utxos = service.getutxos(wallet_addresses[0])

filtered_utxos = [utxo for utxo in utxos
if bloom.check(utxo['address'].encode())]

# Создание транзакции
tx = Transaction(network='bitcoin')
for utxo in filtered_utxos:
tx.add_input(utxo['txid'], utxo['output_n'])

tx.add_output(0.01, 'recipient_address')

# Подписание
key = Key.from_passphrase('your_wallet_passphrase')
tx.sign(key)

print("Raw TX:", tx.raw_hex())

Peculiarities:

  • Built-in work with Electrum servers
  • BIP32 HD wallet support
  • Automatic calculation of commissions via.fee_per_kb

2. Integration with pycoin (advanced functionality)

from pycoin.tx.Tx import Tx
from pycoin.tx.tx_utils import create_tx
from pycoin.ui import standard_tx_out_script
from pybloom import BloomFilter

# Конфигурация Bloom
bloom = BloomFilter(capacity=500, error_rate=0.001)
known_hashes = {b'addr1_hash', b'addr2_hash'}
[bloom.add(h) for h in known_hashes]

# Получение UTXO через собственный узел
def get_filtered_utxos(node):
return [utxo for utxo in node.getutxos()
if bloom.check(hash(utxo.address))]

# Сборка транзакции
tx = create_tx(
inputs=get_filtered_utxos(my_node),
outputs=[(recipient_addr, 0.01)],
fee=0.0001,
network='BTC'
)

print("Raw TX:", tx.as_hex())

Optimizations:

  • Using address hashes instead of strings
  • Batch check viabloom.batch_check()
  • PSBT support for multi-signatures

3. Integration with bit (simple library)

pythonfrom bit import Key, NetworkAPI
from bit.transaction import prepare_transaction
from pybloom import BloomFilter

# Инициализация фильтра
bloom = BloomFilter(100, 0.01)
key = Key()
bloom.add(key.address.encode())

# Фильтрация UTXO
utxos = NetworkAPI.get_unspent(key.address)
inputs = [utxo for utxo in utxos 
         if bloom.check(utxo['address'].encode())]

# Сборка транзакции
outputs = [('1BoatSLRHtKNngkdXEeobR76b53LETtpyT', 0.01, 'btc')]
raw_tx = prepare_transaction(
    inputs=inputs,
    outputs=outputs,
    leftover=key.address  # Автоматический change-адрес
)

print("Raw TX:", raw_tx)

Comparison of approaches

LibraryAdvantagesRestrictions
bitcoinlibBIP39/44 support, multi-networkComplex setup
pycoinFlexible signature scriptsManual assembly required
bitSimple API, automatic commissionsBasic scenarios only

General recommendations

  1. Optimizing Bloom parameters pythonbloom = BloomFilter( capacity=len(addresses) * 1.3, # 30% запас error_rate=0.001, mode='fast' )
  2. Safe UTXO handling pythondef verify_utxo(utxo): return ( bloom.check(utxo.address) and validate_signature(utxo) and check_double_spend(utxo) )
  3. Integration with Bitcoin Core python nodefrom bitcoin.rpc import RawProxy proxy = RawProxy() raw_utxos = proxy.listunspent(0)
  4. python batch processingaddresses_batch = [addr.encode() for addr in 1000_addresses] bloom.batch_add(addresses_batch)

For industrial use it is recommended:

  • Use C extensions likepybloomfiltermmap3
  • Implement filter caching
  • Add false positive monitoring

Citations:

  1. https://github.com/Bit-Wasp/bitcoin-php/issues/238
  2. https://pypi.org/project/python-bitcoin-tools/
  3. https://pypi.org/project/BloomFilterPy/
  4. https://pypi.org/project/bloom-filter/
  5. https://bitcoinops.org/en/topics/transaction-bloom-filtering/
  6. https://hackernoon.com/enhancing-bitcoins-transaction-privacy-with-bloom-filters-2m5q33ta
  7. https://gist.github.com/haidoan/26d76320e411887cdada18fec86bb333
  8. https://bitcoin.stackexchange.com/questions/92957/how-to-parse-transaction-script-to-address-the-correct-way
  9. https://pypi.org/project/btctxstore/0.1.0/
  10. https://bitcoin.stackexchange.com/questions/38480/are-there-any-python-modules-that-decode-raw-transaction-data
  11. https://bitcoin.stackexchange.com/questions/115263/bitcoin-rpc-createrawtransaction-parse-error
  12. https://bitcoin.stackexchange.com/questions/30550/is-it-possible-to-create-a-transaction-in-pure-python-without-needing-to-run-bit
  13. https://www.youtube.com/watch?v=qZNJTh2NEiU
  14. https://python.land/bloom-filter
  15. https://pypi.org/project/shaped-bloom-filter/
  16. https://gist.github.com/marcan/23e1ec416bf884dcd7f0e635ce5f2724
  17. https://llimllib.github.io/bloomfilter-tutorial/
  18. https://bitcoin.stackexchange.com/questions/37124/is-there-a-way-to-index-transactions-so-that-filterload-commands-can-be-answered
  19. https://ethz.ch/content/dam/ethz/special-interest/infk/inst-infsec/system-security-group-dam/research/publications/pub2014/acsac_gervais.pdf
  20. https://developer.bitcoin.org/examples/p2p_networking.html?highlight=bloom+filter
  21. https://www.npmjs.com/package/@synonymdev/raw-transaction-decoder

Source code

Telegram: https://t.me/cryptodeeptech

Video: https://youtu.be/i9KYih_ffr8

Video tutorial: https://dzen.ru/video/watch/6784be61b09e46422395c236

Source: https://cryptodeeptech.ru/discrete-logarithm


Useful information for enthusiasts:


Discrete Logarithm mathematical methods and tools for recovering cryptocurrency wallets Bitcoin