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.

    Conflicts

    No conflicts as of last run.

  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
  13. achow101 commented at 7:54 pm on December 5, 2024: member

    cdaa3a58dc16d6a27248dc4cdec2dd1909eee7fe “wallet: bugfix, stop treating multisig consensus-invalid/unspendable scripts as ours” modifies legacy IsMine(), ostensibly to mix issues in migration. However, I don’t think doing that makes sense that this point as legacy IsMine is going to be removed from migration with #30328, and any changes to it may result in incompatibilities with legacy wallets and migrated wallets.

    I think that fixes to migration should be limited to the migration only code. Perhaps it would be easier to cherry pick the tests and migration specific fixes into #30328?

  14. DrahtBot added the label CI failed on Dec 6, 2024
  15. furszy commented at 4:05 pm on December 6, 2024: member

    cdaa3a5 “wallet: bugfix, stop treating multisig consensus-invalid/unspendable scripts as ours” modifies legacy IsMine(), ostensibly to mix issues in migration. However, I don’t think doing that makes sense that this point as legacy IsMine is going to be removed from migration with #30328, and any changes to it may result in incompatibilities with legacy wallets and migrated wallets.

    I’m not going too strong over this point but.. it’s hard for me to see the incompatibilities when the changes block two consensus-invalid scripts and a +10 year-old non-standard script that is already blocked in other parts of the legacy wallet. Arguably, this could also be labeled as a legacy wallet bugfix.

    I think that fixes to migration should be limited to the migration only code. Perhaps it would be easier to cherry pick the tests and migration specific fixes into #30328?

    I was aiming to keep #30328 purely as a refactoring without mixing in bug fixes. Reviewing the PR’s matching functionality has been challenging in its current state, so I think that it would be good if we don’t expand it more than strictly necessary.

    Note: If, after this comment, the general consensus is still to leave IsMine untouched, maybe postponing this PR until after #30328 would be the path that satisfies everyone?

  16. achow101 commented at 4:36 pm on December 6, 2024: member

    Note: If, after this comment, the general consensus is still to leave IsMine untouched, maybe postponing this PR until after #30328 would be the path that satisfies everyone?

    Then let’s do it afterwards.


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-18 21:12 UTC

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