wallet: fix crash during migration due to invalid multisig descriptors #31378

pull furszy wants to merge 3 commits into bitcoin:master from furszy:2024_wallet_migration_multisig_crash changing 5 files +51 −8
  1. furszy commented at 11:16 pm on November 26, 2024: member

    Ensure legacy wallet migration skips the never standard bare multisig with +3 keys and consensus-invalid multisig scripts. Treating them as valid causes migration to crash because we are enforcing this rules within the descriptors parsing logic.

    Testing Notes: This can be verified by cherry-picking and running the test commit on master. It will crash there but pass on this branch.

  2. DrahtBot commented at 11:16 pm on November 26, 2024: contributor

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/31378.

    Reviews

    See the guideline for information on the review process. A summary of reviews will appear here.

  3. DrahtBot added the label Wallet on Nov 26, 2024
  4. darosior commented at 11:33 pm on November 26, 2024: member
    Ruling out consensus-invalid scripts makes sense, but discarding non-standard scripts is a much bigger leap. Also it would be a wack-a-mole: does the migration crash on any non-standard script? How much of that do you want to cover? Is it not possible to make the migration not crash on valid but not standard scripts instead of changing IsMine for those?
  5. furszy commented at 4:30 pm on November 27, 2024: member

    Ruling out consensus-invalid scripts makes sense, but discarding non-standard scripts is a much bigger leap. Also it would be a wack-a-mole: does the migration crash on any non-standard script? How much of that do you want to cover?

    Ok, I might have made the PR/commit description too broad when the actual changes are very specific. Migration does not crash on all non-standard scripts, it only crashes on scripts that fail to be parsed by the descriptors’ logic. The specific non-standard crash this PR addresses is a bare multisig with +3 keys. And I don’t think we want to cover all non-standard rules; we just need to handle the ones also applied by the current descriptors parsing logic.

    Ultimately, we’re preserving/freezing the legacy wallet’s existing behavior ahead of its removal. We shouldn’t allow spendability or migration (even though it’s not possible anyway) of scripts that were not functional during the lifetime of the legacy wallet anyway.

    Is it not possible to make the migration not crash on valid but not standard scripts instead of changing IsMine for those?

    It’s possible, but it would mean duplicating more code. Still, at least for this case, I don’t think it matters much. #30328 inlines the IsMine() logic into the migration code, so the entire legacy wallet support can be removed by the next release. In other words, duplicating code now won’t change the outcome; if #30328 proceeds, the code will end up been consolidated into the same migration function anyway.

    I’ll update the PR description to reflect the actual scope of this fix. it’s not as broad as I initially described.

  6. furszy force-pushed on Nov 27, 2024
  7. refactor: replace hardcoded number, introduce 'MAX_BARE_MULTISIG_PUBKEYS_NUM' e22aa8b22d
  8. in src/wallet/scriptpubkeyman.cpp:208 in d641931427 outdated
    203+            return IsMineResult::INVALID;
    204+        }
    205+
    206+        // Never treat bare multisig outputs as ours (they can still be made watchonly-though)
    207+        if (sigversion == IsMineSigVersion::TOP) {
    208+            if (keys.size() > 3) return IsMineResult::INVALID; // These are standard wise non-spendable
    


    brunoerg commented at 2:25 pm on December 3, 2024:
    nit: Maybe we should have a constant for this number (3)? Then we can use here and in IsStandard.

    furszy commented at 2:36 pm on December 3, 2024:
    yeah, thats also something that popped-up in #31404 (review) too. Will bring the commit here as well.
  9. wallet: bugfix, stop treating multisig consensus-invalid/unspendable scripts as ours
    Ensure legacy wallet migration skips the never standard bare multisig with +3 keys
    and consensus-invalid multisig scripts. Treating them as valid causes migration to
    crash because we are enforcing this rules within the descriptors parsing logic.
    cdaa3a58dc
  10. test: migration, add coverage for consensus-invalid/unspendable multisig scripts 74fa29e12e
  11. in test/functional/wallet_migration.py:324 in d641931427 outdated
    319+        # Now migrate it and verify we don't crash due to a non-allowed descriptor migration
    320+        wallet.migratewallet()
    321+        wallet.unloadwallet()
    322+
    323+        ##############################################################
    324+        # Import a consensus-wise invalid p2sh multisig with 20 keys #
    


    brunoerg commented at 2:38 pm on December 3, 2024:
    In d64193142792e68636bf61ef4b083dfb8c1d20d7: A p2sh multisig with 20 keys is invalid? I thought 20 keys are the limit, but still valid.

    furszy commented at 2:47 pm on December 3, 2024:

    In d641931: A p2sh multisig with 20 keys is invalid? I thought 20 keys are the limit, but still valid.

    Yes, they are. The limit is not based on the number of keys, it is on the size of the redeem script. Which can go up to 520 bytes max (which limits the number of keys inside a p2sh to 15).

  12. furszy force-pushed on Dec 3, 2024

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-12-03 21:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me