You would have to modify Bitcoin Core to accept double spends since Bitcoin Core will not allow double spends into its mempool for obvious reasons.
- snip -
Even if you do that, it will still be very rare that you will see a double spend attempt. This is because nearly all of the nodes you will typically connect to will refuse to accept and refuse to relay any double-spend attempt. Therefore, you will not hear about the double-spend attempt from your connected peers.
To find double-spend attempts you'll need to do 3 things...
- Find or write software that will accept transactions from bitcoin nodes that are double-spend attempts
- Connect to as many nodes as possible so that you are more likely to be connected to one of the few nodes that is relaying the double-spend attempt
- Keep a permanent history of all transactions that have ever been received and not confirmed, even weeks, months, or years after most nodes would have dropped them from their memory pool
Even if you do all of that, you will still miss some double-spend attempts, but if you are connected to enough nodes you'll have a good chance at finding a significant percentage of them.
The problem is, as an attacker I could do the following:
- Connect directly to nodes run by a few of the largest mining pools
- Connect to a very large number of non-mining peer nodes
- Broadcast a transaction (TXN_A) to the non-mining peer nodes
- Simultaneously send a double-spend attempt (TXN_B) directly to the mining pool nodes
If I did that, then most of the network (including your double-spend monitor) would hear about TXN_A. Since most nodes won't relay the double-spend attempt, it is very likely that your double-spend monitor won't hear about TXN_B (unless you happen to be connected directly to the same mining pool nodes as me). Meanwhile the mining pools will refuse to accept TXN_A (since that will appear to be a double-spend attempt to them). Eventually TXN_B will be confirmed by one of the mining pools, and you'll receive the block with TXN_B in it. At that point, your node will remove TXN_A from its memory pool since it is no longer valid. Notice that TXN_B never made it into your memory pool. As far as your node was concerned, the TXN_B didn't exist, and then it was confirmed.