You are trying to capture all exchanged transactions. Bitcon Core has been adhered to trace Enable and listen mempool:replaced As suggested in this question.
This method works as expected and can retrieve exchanged transactions. However, in some cases (about 20% of all transactions I capture), TracePoint warns that the transaction is being exchanged, but it’s not capturing the exchange of that transaction.
We can consider two reasons why this is happening:
- It’s possible that some of the alternatives won’t be included in my members. But in that case, how does TracePoint know that transactions are being exchanged? It’s also strange that this happens in so many transactions (20% as mentioned above).
- The second option is that the script that handles the transaction does not take into account some cases. This means losing the transaction. The script is a modified version of this example. I changed it so that the children of exchanged transactions can also be captured. The data collected with this script will be saved later in a PKL file, so there is a sharing list.
I’m not sure why I’m losing so many deals, so I was wondering if anyone could help me see what I’m doing wrong.
Here is the modified function:
def handle_replaced(_, data, size):
# Establish a new RPC connection for this event
rpc_connection_replaced = connection()
event = bpf("replaced_events").event(data)
hash_replaced = bytes(event.replaced_hash)(::-1).hex()
hash_new = bytes(event.replacement_hash)(::-1).hex()
tx_time = get_timestamp()
hex_tx = rpc_connection_replaced.getrawtransaction(hash_new)
new_tx = rpc_connection_replaced.decoderawtransaction(hex_tx)
new_tx('hex') = hex_tx
# Determine parent transactions that are still in the mempool and are not the transaction itself
parents = set((x('txid') for x in new_tx('vin') if x('txid') in mempool.keys() and x('txid') != new_tx('txid')))
# Retrieve the old transaction info from the mempool
old = mempool.get(hash_replaced, None)
if old is not None: # Some transactions may be missing initially
mempool.pop(hash_replaced, None)
# Share the replaced event details via list_shared queue
list_shared.put((old, (new_tx, tx_time, parents)))
# Find all child transactions that reference the new transaction as a parent
childs = (i(0)('txid') for i in mempool.values() if new_tx('txid') in i(2))
# Recursive function to collect child transaction IDs
def child(ll):
if len(ll) == 0:
return ()
new_childs = (i(0)('txid') for i in mempool.values() if ll - i(2) != ll)
return list(ll) + new_childs + child(set(new_childs))
if len(childs) > 0:
childs = child(set(childs))
# Share the connection between the new transaction and the first child
list_shared.put(((new_tx, tx_time, parents), mempool(childs(0))))
# Share connections between subsequent child transactions
for i in range(len(childs)-1):
list_shared.put((mempool(childs(i)), mempool(childs(i+1))))
# Add the new transaction to the mempool with its timestamp and parent set
mempool(new_tx('txid')) = (new_tx, tx_time, parents)
logger.info('-----------')
logger.info('New RBF!')
def handle_added(_, data, size):
rpc_connection_added = connection()
event = bpf("added_events").event(data)
hash_new = bytes(event.hash)(::-1).hex()
hex_tx = rpc_connection_added.getrawtransaction(hash_new)
tx_raw = rpc_connection_added.decoderawtransaction(hex_tx)
tx_raw('hex') = hex_tx
parents = set((x('txid') for x in tx_raw('vin') if x('txid') in mempool.keys()))
mempool(tx_raw('txid')) = (tx_raw, get_timestamp(), parents)
def handle_removed(_, data, size):
event = bpf("removed_events").event(data)
if event.reason != b'replaced':
txid_rem = bytes(event.hash)(::-1).hex()
keys = mempool.keys()
if txid_rem in keys:
mempool.pop(txid_rem)
logger.info('-----------')
logger.info(f'Removed. Reason:{event.reason}')
Discover more from Earlybirds Invest
Subscribe to get the latest posts sent to your email.

