Skip to content

wallet::Balance::trusted_pending AND TxBuilder::only_spend_change are broken #16

@stevenroose

Description

@stevenroose

Describe the bug
TxGraph calculates balance and splits the unconfirmed txs into "trusted" and "untrusted" based on a trust_predicate (trust_predicate: impl FnMut(&OI, ScriptBuf) -> bool). Wallet then uses that method and fills this argument with

            |&(k, _), _| k == KeychainKind::Internal,

This is too naive. While the Internal keychain is intended for change that the wallet controls, there is no guarantee that external users don't pay to change addresses (for example by observing the chain and discovering our change addresses). Hence, utxos that are considered trusted by the Wallet::balance method, can still be maliciously double-spent by external parties.

Similarly, only_spend_change also only checks the keychainkind of the output which does not guarantee it was actually change from one of our own txs:

impl ChangeSpendPolicy {
    pub(crate) fn is_satisfied_by(&self, utxo: &LocalOutput) -> bool {
        match self {
            ChangeSpendPolicy::ChangeAllowed => true,
            ChangeSpendPolicy::OnlyChange => utxo.keychain == KeychainKind::Internal,
            ChangeSpendPolicy::ChangeForbidden => utxo.keychain == KeychainKind::External,
        }
    }
}

While this trust_predicate seems useful, I think a "trusted" notion is confusing. In effect, the intention is already to mean "change", so I would just drop the "trusted" in favor of "change" (or equivalent the internal/external naming) (pending_internal, pending_external) or so. BUT, "internal" does not merely mean from the internal keychain, but actually "originating from a tx that we ourselves have created".

Once that notion is fixed, and change it not just determined based on keychainkind.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    Status

    Discussion

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions