The site is finding pairs of transactions for stale blocks that it thinks are conflicting. However in reality for several of these the transaction doesn't actually exist in the shortest branch. E.g. for the stale block at height 788686 transaction b4b995e6a3a7daceab20519ddd34530a997379f29ee1319609a90ea716f7b536 does not exist in either block 000000000000000000032e2236a4c96c9dfc0f9f7993be6675fefb8fb6200b4b or 000000000000000000015221d97f2a108ae4bfea27639592f6cf17a2effc5fa6.
I found a bug that may or may not be at the root of this issue. In any case it makes the result unreliable.
We incorrectly assume a Transaction is associated with one block:
This means that the Block method block_and_descendant_transactions returns an incomplete set.
We use the result from that method in get_spent_coins_with_tx to contruct a list of outpoints that are being spent on each side. This list is incomplete.
We then pass that list into get_double_spent_inputs, where we loop through all outpoints spent in the shortest branch. We then find coins that are spent with a different tx in the longest chain.
|
def get_double_spent_inputs(spent_coins_with_tx) |
|
return nil if spent_coins_with_tx.nil? |
|
|
|
(shortest_spent_coins_with_tx, longest_spent_coins_with_tx) = spent_coins_with_tx |
|
|
|
# Filter coins that are spent with a different tx in the longest chain |
|
# unique is used because a transaction may doublespend multiple inputs |
|
shortest_spent_coins_with_tx.filter do |txout, tx| |
|
longest_spent_coins_with_tx.key?(txout) && tx.tx_id != longest_spent_coins_with_tx[txout].tx_id |
|
end.collect { |txout, tx| [tx, longest_spent_coins_with_tx[txout]] }.uniq.transpose |
|
end |
This however doesn't explain why we end up with transactions that don't occur on the shortest chain at all. So there's probably another bug.
The site is finding pairs of transactions for stale blocks that it thinks are conflicting. However in reality for several of these the transaction doesn't actually exist in the shortest branch. E.g. for the stale block at height 788686 transaction b4b995e6a3a7daceab20519ddd34530a997379f29ee1319609a90ea716f7b536 does not exist in either block 000000000000000000032e2236a4c96c9dfc0f9f7993be6675fefb8fb6200b4b or 000000000000000000015221d97f2a108ae4bfea27639592f6cf17a2effc5fa6.
I found a bug that may or may not be at the root of this issue. In any case it makes the result unreliable.
We incorrectly assume a Transaction is associated with one block:
forkmonitor/app/models/transaction.rb
Line 4 in d6a8704
This means that the Block method
block_and_descendant_transactionsreturns an incomplete set.We use the result from that method in
get_spent_coins_with_txto contruct a list of outpoints that are being spent on each side. This list is incomplete.We then pass that list into
get_double_spent_inputs, where we loop through all outpoints spent in the shortest branch. We then find coins that are spent with a different tx in the longest chain.forkmonitor/app/models/stale_candidate.rb
Lines 140 to 150 in d6a8704
This however doesn't explain why we end up with transactions that don't occur on the shortest chain at all. So there's probably another bug.