Skip to content

Phase 1: descriptor-backed standard wallet address derivation (wpkh)#700

Draft
Copilot wants to merge 2 commits intomainfrom
copilot/migrate-standard-wallet-descriptors
Draft

Phase 1: descriptor-backed standard wallet address derivation (wpkh)#700
Copilot wants to merge 2 commits intomainfrom
copilot/migrate-standard-wallet-descriptors

Conversation

Copy link
Contributor

Copilot AI commented Mar 14, 2026

Migrates standard wallet receive/change address derivation to use BIP-84 wpkh descriptors internally, while keeping all existing interfaces, signing paths, and Angor custom scripts unchanged. Old wallets auto-migrate on first scan without any user action.

Model changes (AccountInfo)

Three new nullable fields alongside existing ExtPubKey/Path (additive – no breaking storage change):

  • ReceiveDescriptorwpkh([fp/84h/coinTypeh/0h]xpub/0/*)
  • ChangeDescriptorwpkh([fp/84h/coinTypeh/0h]xpub/1/*)
  • MasterFingerprint – first 4 bytes of HASH160(root pubkey), lowercase hex

New helper: StandardWalletDescriptors

Static class in Angor.Shared:

  • Build(xpub, fingerprint, coinType)(ReceiveDescriptor, ChangeDescriptor)
  • ExtractXPub(descriptor) → account-level xpub string
  • IsChangeBranch(descriptor) → bool
  • TryMigrate(accountInfo, coinType) → generates descriptors from legacy ExtPubKey when absent

WalletOperations changes

  • BuildAccountInfoForWalletWords now computes the master fingerprint and populates all three descriptor fields on creation.
  • UpdateAccountInfoWithNewAddressesAsync calls TryMigrate at entry (no-op if already migrated), then sources the scanning xpub from the descriptor rather than raw ExtPubKey:
// Before
var (index, items) = await FetchAddressesDataForPubKeyAsync(
    accountInfo.LastFetchIndex, accountInfo.ExtPubKey, network, false);

// After – xpub sourced from descriptor; falls back to ExtPubKey for unmigrated records
var receiveXPub = !string.IsNullOrEmpty(accountInfo.ReceiveDescriptor)
    ? StandardWalletDescriptors.ExtractXPub(accountInfo.ReceiveDescriptor)
    : accountInfo.ExtPubKey;
var (index, items) = await FetchAddressesDataForPubKeyAsync(
    accountInfo.LastFetchIndex, receiveXPub, network, false);

Migration behaviour

Descriptor derivation uses the same account xpub at m/84'/coinType'/0' as the legacy path, so all addresses are identical. Old wallets transparently gain descriptors in-memory on first UpdateAccountInfoWithNewAddressesAsync call; no manual migration or data loss.

Tests (WalletDescriptorTests – 23 cases)

  • Descriptor format correctness with/without fingerprint
  • ExtractXPub round-trip
  • BuildAccountInfoForWalletWords integration
  • Descriptor-derived addresses match legacy derivation for each index and branch
  • TryMigrate lifecycle: generates, is idempotent, skips when xpub absent

Not changed

Angor custom scripts, founder/investor derivation, Nostr paths, signing, all public service interfaces.

Recommended follow-up

  • Persist migrated descriptors to storage (currently in-memory per session)
  • Phase 2: Taproot (tr(…)) descriptor support

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Co-authored-by: dangershony <7487930+dangershony@users.noreply.github.com>
Copilot AI changed the title [WIP] Migrate standard wallet to descriptor-based wallets Phase 1: descriptor-backed standard wallet address derivation (wpkh) Mar 14, 2026
Copilot AI requested a review from dangershony March 14, 2026 20:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants