Debugging presumed double spend

My wallet received tx 7f8dde66f4692776273b581cd1959ddc85a5bf205b3b7470b31c57423038cc29 on 08/03/23 23:41:59 (UTC time). The transaction was never included in a block so I have a suspicion that it might’ve been miner-assisted double spend or just pure luck (from the attackers’ side). It’s no longer possible to look it up through any BCH explorers. It was replaced by tx 2722acebd7e82811dd7abe8e9349418f59fd2179bd1005fbea6a0c368379fbdf that my wallet first seen on 09/03/23 00:17:35 and was included in a #783,096 at 09/03/23 00:17:40.

I’d like to get to the bottom of what happened but can’t find anything useful in my wallet & BCHD logs. Does anyone have any information about tx 7f8dde66f4692776273b581cd1959ddc85a5bf205b3b7470b31c57423038cc29? If someone is logging double spends or all transactions accepted to the mempool please check the logs for these 2 txs.


Edit: I did a little bit of investigating and found the following (all times are UTC):

08/03/23 22:24:19 - block #783,089 was mined
08/03/23 23:41:59 - tx 7f8dde66f4692776273b581cd1959ddc85a5bf205b3b7470b31c57423038cc29 was first seen by my wallet
09/03/23 00:02:45 - block #783,090 was mined
09/03/23 00:05:17 - block #783,091 was mined
09/03/23 00:05:21 - block #783,092 was mined
09/03/23 00:06:06 - block #783,093 was mined
09/03/23 00:09:22 - block #783,094 was mined
09/03/23 00:15:56 - block #783,095 was mined
09/03/23 00:17:35 - tx 2722acebd7e82811dd7abe8e9349418f59fd2179bd1005fbea6a0c368379fbdf (double-spend of 7f8dde66f4692776273b581cd1959ddc85a5bf205b3b7470b31c57423038cc29?) was first seen by my wallet
09/03/23 00:17:40 - block #783,096 was mined (it included 2722acebd7e82811dd7abe8e9349418f59fd2179bd1005fbea6a0c368379fbdf tx)

so my theory about it being miner-assisted double spent seems less likely since there were multiple blocks mined after my wallet first saw tx 7f8dde66f4692776273b581cd1959ddc85a5bf205b3b7470b31c57423038cc29


Edit2: Now that I think about it, the 2722acebd7e82811dd7abe8e9349418f59fd2179bd1005fbea6a0c368379fbdf tx didn’t replace 7f8dde66f4692776273b581cd1959ddc85a5bf205b3b7470b31c57423038cc29. It just happened to have 1 same output (same amount and same destination address as in the first tx). So I am still looking for the transaction that actually replaced 7f8dde66f4692776273b581cd1959ddc85a5bf205b3b7470b31c57423038cc29

1 Like

I looked for the 7f8dde… transaction in my debug log but unfortunately didn’t have enough transaction debugging enabled, so I don’t have a log of it.

You say your wallet detected both transactions. When you say ‘wallet’, what exactly?
It will be useful to distinguish between whether you mean a wallet application and a full node.
A wallet would normally only see transactions it is expecting.

So in that sense, the 2722ace… transaction must have been to some address that your wallet was monitoring.

How do you conclude that this later transaction wasn’t in fulfilment of the earlier payment address?
I assume you know this somehow through knowing which addresses you were expecting money on for the 7f88dde… transaction.

If you know these addresses, and if they are not the “shared” address to which 2722ace… also paid the same amount (!), then it’ll be hard to find out if a double spend occurred since we don’t have the transaction data for the earlier transaction right now, so we can’t know whether some of its outputs were respent by another transaction. Until we know that, we can maybe call this a “presumed double spend” but it’s not confirmed as such…

It’s conceivable (until we find someone who has the original tx data) that the original tx has just not been propagated well, maybe due to some technical error on the sending platform. However, since your wallet saw it somehow, it at least got to whatever’s feeding your wallet’s information.

So if anyone can get hold of a copy of 7f8dde…'s data, they could try rebroadcasting it or checking whether any of its inputs have since been spent in other transactions.

Since you mention receiving an identical amount “into the same destination address as in the first tx”, it sounds like whoever was trying to pay you, might have decided something went wrong with their original payment tx, and constructed another tx. How do you conclude that it was some kind of attack - are you in fact missing some payment that you were supposed to have received additionally through the first transaction, and which has since gone missing from your wallet?

2 Likes

You say your wallet detected both transactions. When you say ‘wallet’, what exactly?
It will be useful to distinguish between whether you mean a wallet application and a full node.
A wallet would normally only see transactions it is expecting.

By “my wallet” I mean a wallet application that communicates with the BCH network through a private BCHD node (GRPC interface).

So in that sense, the 2722ace… transaction must have been to some address that your wallet was monitoring.

Correct.

It’s conceivable (until we find someone who has the original tx data) that the original tx has just not been propagated well, maybe due to some technical error on the sending platform. However, since your wallet saw it somehow, it at least got to whatever’s feeding your wallet’s information.

I am not sure about BCHD internals but I’d assume when it accepts TX into the mempool it broadcasts it to the other nodes?

So if anyone can get hold of a copy of 7f8dde…'s data, they could try rebroadcasting it or checking whether any of its inputs have since been spent in other transactions.

That’s exactly what I want to check.

Since you mention receiving an identical amount “into the same destination address as in the first tx”, it sounds like whoever was trying to pay you, might have decided something went wrong with their original payment tx, and constructed another tx. How do you conclude that it was some kind of attack - are you in fact missing some payment that you were supposed to have received additionally through the first transaction, and which has since gone missing from your wallet?

The “attacker” got credited twice.


EDIT: Managed to find this transaction on blockchain.com. Doing further investigation…

7f8dde66f4692776273b581cd1959ddc85a5bf205b3b7470b31c57423038cc29.json
{
  "txid": "7f8dde66f4692776273b581cd1959ddc85a5bf205b3b7470b31c57423038cc29",
  "size": 226,
  "version": 2,
  "locktime": 0,
  "fee": 270,
  "inputs": [
    {
      "coinbase": false,
      "txid": "ae1b821f837be0cfef6685ac94a6dc4169cdf5344f0580fbb886edc42d2bba96",
      "output": 1,
      "sigscript": "483045022100b3b15ba47ca4222c65f1601cec2a6804f3ad9442bdacd8d555fbdbb410554cb902202540929ce0fd662fe9840bda0cf179382d97a4d722b947900a43b383e5d79f444121033b5e0c0709d5c6b6171994d73e12cad544cd1750b1bdb0acef2ed45f3c76e578",
      "sequence": 4294967295,
      "pkscript": "76a914a6ee04cb7728759a8dee6bed3a781317a3ce3d2e88ac",
      "value": 1775298764,
      "address": "bitcoincash:qznwupxtwu58tx5dae476wnczvt68n3a9cm4mr9ptm",
      "witness": []
    }
  ],
  "outputs": [
    {
      "address": "bitcoincash:qrq0a23fewzpa7r9vlfa348zqlum54hfe5e8vq8pzs",
      "pkscript": "76a914c0feaa29cb841ef86567d3d8d4e207f9ba56e9cd88ac",
      "value": 15965000,
      "spent": false,
      "spender": null
    },
    {
      "address": "bitcoincash:qznwupxtwu58tx5dae476wnczvt68n3a9cm4mr9ptm",
      "pkscript": "76a914a6ee04cb7728759a8dee6bed3a781317a3ce3d2e88ac",
      "value": 1759333494,
      "spent": false,
      "spender": null
    }
  ],
  "block": {
    "mempool": 1678318919
  },
  "deleted": true,
  "time": 1678318919,
  "rbf": false,
  "weight": 904
}

EDIT2: So seems like 7f8dde66f4692776273b581cd1959ddc85a5bf205b3b7470b31c57423038cc29 was double-spend in 60d7dbaed8d271b0ff750478e34f60d6ec16fca307e9330f85ccd1e7c8a2c4ed.

Which is worrying because according to blockchain.com the latter one (successful double-spend) was broadcasted 20 minutes after first one! So this confirms that this was indeed a miner-assisted double spend?

2 Likes

Yeah, looks like a double spend alright, with a block mined by rented hash (at least that’s the impression given by a /Nicehash/ tag in the coinbase tx of 783,090).

All over a payment of $17.48 (blockchain.com data).

Doesn’t make much sense to me, unless someone did this just to demonstrate that a miner-assisted double spend is possible.

1 Like

Thanks for posting the links.

This does seem like a double spend, doesn’t look very unusual as they go, though. I’m sorry to hear that may have caused you to lose funds. I suggest using a wallet (like Flowee Pay) that supports double spend proofs to get early notification of this in the future.

What the data shows is this;

at 22:24 block 783089 was mined.
at 23:41:59 the transaction you saw was added to the mempool.
We have no data on when the other transaction was seen, presumably it happened at the same time. Our timing tests show typically its within 3 seconds.

At 00:02 (next day) block 783090 was mined, deciding that the ‘other’ transaction was to be included.

1 Like

I think these 2 transactions originated from crypto.com wallet. Maybe a bug in their wallet implementation (created double-spend by mistake?) but what’s worrying me is that looks like the double-spending tx was first seen in a block mined by nicehash pool, not by getting relayed…

1 Like

Check these 2 links: Transaction: 7f8dde66f4692776273b581cd1959ddc85a5bf205b3b7470b31c57423038cc29 | Blockchain.com & Transaction: 60d7dbaed8d271b0ff750478e34f60d6ec16fca307e9330f85ccd1e7c8a2c4ed | Blockchain.com. They spend same inputs.

This is the basis behind what causes the double spend issue in the first place. Different players will have a different notion of “truth”.

An older video of mine goes into the details of what this means (at 2min 40 sec mark): https://vimeo.com/manage/videos/806883416

We have no data on when the other transaction was seen, presumably it happened at the same time. Our timing tests show typically its within 3 seconds.

According to blockchain.com, the second transaction was first seen included in block #783,090 which was ~20 minutes after first tx was broadcasted. Which makes it look like it was indeed miner-assisted double-spend, no?

No.

Please refer to my timeline here: Debugging presumed double spend - #5 by tom

Notice that the ‘mempool’ section in the json is missing for mined blocks.

This is the actual timeline (UTC time):
08/03/23 22:24:19 - block 783089 gets mined
08/03/23 23:41:59 - tx “first” is seen for the first time (my BCHD node accepted this UTXO into its mempool)
09/03/23 00:02:45 - block 783090 gets mined, including tx “second” which was never seen before (proof: according to blockchain.com tx “second” was first seen at the same time as block 783090) and reused inputs from tx “first” - double spending it.

How is that not a literal example of miner-assisted double-spend? :thinking:

1 Like

The ‘first-seen’ rule makes a single node that already has the other transaction reject this new one. It won’t get propagated and so most of the network doesn’t see more then one. So indeed the second one won’t be seen by this node until it arrives in a block.

Its not trivial to wrap ones head around, the problem is that what is true for one node is local truth. And your node and the miners node have a different view on truth.

So, it was most likely seen before by other nodes.

The evidence just shows multiple nodes disagreed. In an entirely predictable manner.

Really, there is no evidence of a miner assisted double spend.

Please consider making your wallet act on double spend proofs and you’ll get notifined of its existance the moment the second transaction is seen by the network.

1 Like

That makes sense. Thanks for explaining it!

Please consider making your wallet act on double spend proofs and you’ll get notifined of its existance the moment the second transaction is seen by the network.

Adding support for DS-proofs has been on my todo-list for some time, unfortunately, BCHD doesn’t support them as of yet. And my current wallet implementation works on top of BCHD.

Do you maybe log DS-proofs so you could check if this case was maybe caught by the DS-proofs mechanism?

1 Like

Well you can also just scan the blockchain for conflicting transactions with the same inputs and different outputs, which is supported by BCHD - probably.

But DSProofs are highly superior, so I would recommend maybe implementing them in BCHD yourself or convincing somebody else to do it, perhaps.

EDIT:

Precisely what I meant was “have a node that will watch the network and notice attempts of other nodes to insert a TX with the same inputs and different outputs”, which is how double-spend protection worked in ~2015 era.

Now we don’t need it any more, there are DSProofs.