Skip to content

Bogus double spend code on reorg. #734

@evoskuil

Description

@evoskuil
    // Is any duplicated point in the block confirmed (generally empty).
    for (const auto& spender: cache.conflicts)
        if (is_strong_tx(spender))
            return system::error::confirmed_double_spend;

Assuming that the prevout cache is properly populated, there should be no way for a spending duplicate tx to be strong if its block has been disorganized, since this results in a pop to the disorg point which includes set_strong(false) for all txs in the block(s).

Download: upon dirty archive the duplicate table is populated with best-efforts-unique points where the point is duplicated in the point table. atomicity of the point table duplicate detection ensures none are missed.

Validate: set_prevouts() is called for the block after validation. all previous blocks exist at that time. If any duplicates exist at that time (if they are relevant they must already exist), the duplicates table is searched for points (hash:index) spent in the block. For all matches, the the tx.link of each point.hash is retrieved by point.hash search in the tx table and stored as additional data in the prevouts table. This will include both self and the full set of duplicate(s). Returns error if none found.

Confirm: prevout table conflicts are iterated under the total ordering. if any is found to be a strong tx then a double spend code is returned.

The flaw in the above implementation is that the point.hash is searched to find txs that may be duplicated. However this is the tx of the spent output, not the tx of the spenders of that output. This leads to false positives.

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions