Skip to content

feat: use deterministic derivation path for platform address funding#512

Closed
pauldelucia wants to merge 1 commit intov1.0-devfrom
feat/platform-address-funding-derivation-path
Closed

feat: use deterministic derivation path for platform address funding#512
pauldelucia wants to merge 1 commit intov1.0-devfrom
feat/platform-address-funding-derivation-path

Conversation

@pauldelucia
Copy link
Copy Markdown
Member

@pauldelucia pauldelucia commented Feb 2, 2026

Replace random one-time keys with deterministic keys derived from wallet seed for platform address funding asset locks.

Uses DIP-17 path structure with key_class=2 for funding: m/9'/coin_type'/17'/0'/2'/index

This is a local workaround until dash-sdk adds native support for platform_address_funding_path().

Changes:

  • Add DerivationPathReference::PlatformAddressFunding variant
  • Add PLATFORM_KEY_CLASS_FUNDING constant (key_class=2)
  • Add platform_address_funding_ecdsa_private_key() method
  • Add next_platform_address_funding_index() to track used indices
  • Update generic_asset_lock_transaction() to use derived keys

Summary by CodeRabbit

  • Security Improvements

    • Wallet now uses deterministic key derivation from the seed for asset lock transactions, replacing random key generation for enhanced security and recoverability.
  • Infrastructure Updates

    • Introduced platform address funding support with deterministic index tracking to improve wallet functionality and consistency.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 2, 2026

Warning

Rate limit exceeded

@pauldelucia has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 42 minutes and 0 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📝 Walkthrough

Walkthrough

This PR introduces deterministic key derivation for platform address funding by adding DIP-17 support to the wallet's key derivation system. It replaces random key generation in asset lock transactions with seed-derived keys indexed through a new platform address funding key class, and adds tracking of the next available funding index.

Changes

Cohort / File(s) Summary
Platform Address Funding Infrastructure
src/model/wallet/mod.rs
Introduces DIP-17 key class variant PlatformAddressFunding with value 17, adds constants PLATFORM_KEY_CLASS_PAYMENT and PLATFORM_KEY_CLASS_FUNDING, and implements two new public methods: platform_address_funding_ecdsa_private_key() for deriving private keys from wallet seed, and next_platform_address_funding_index() for computing the next available funding index by scanning watched addresses.
Asset Lock Transaction Determinism
src/model/wallet/asset_lock_transaction.rs
Replaces random one-time key generation with deterministic key derivation from wallet seed. Adds funding_index parameter to generic_asset_lock_transaction() signature and adds a new Address return value (asset_lock_address) as the third tuple element, shifting existing return values.
Wallet Funding Integration
src/backend_task/wallet/fund_platform_address_from_wallet_utxos.rs
Obtains next funding index via wallet.next_platform_address_funding_index() and passes it to generic_asset_lock_transaction() in both initial and retry code paths to enable deterministic key derivation during asset lock creation.

Sequence Diagram

sequenceDiagram
    participant FundTask as Fund Platform Address Task
    participant Wallet as Wallet
    participant AssetLock as Asset Lock Transaction
    participant Derivation as Key Derivation (DIP-17)

    FundTask->>Wallet: next_platform_address_funding_index(network)
    Wallet->>Wallet: Scan watched addresses for key_class=2
    Wallet-->>FundTask: Return next available index

    FundTask->>AssetLock: generic_asset_lock_transaction(network, amount, ..., funding_index)
    AssetLock->>Derivation: platform_address_funding_ecdsa_private_key(network, funding_index)
    Derivation->>Derivation: Derive from wallet seed using DIP-17 path
    Derivation-->>AssetLock: Return PrivateKey
    AssetLock->>AssetLock: Compute public_key and asset_lock_address
    AssetLock->>AssetLock: Create asset lock transaction
    AssetLock-->>FundTask: Return (Transaction, PrivateKey, Address, ...)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 No more dice rolls in the funding lane,
With DIP-17, our keys now follow a chain,
Each index precise, derived with care,
Deterministic magic floating through the air!
From wallet seeds, the addresses bloom,
Replacing randomness that sealed their doom. 🌱

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: implementing deterministic derivation paths for platform address funding instead of random one-time keys.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/platform-address-funding-derivation-path

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Replace random one-time keys with deterministic keys derived from wallet
seed for platform address funding asset locks.

Uses DIP-17 path structure with key_class=2 for funding:
m/9'/coin_type'/17'/0'/2'/index

This is a local workaround until dash-sdk adds native support for
platform_address_funding_path().

Changes:
- Add DerivationPathReference::PlatformAddressFunding variant
- Add PLATFORM_KEY_CLASS_FUNDING constant (key_class=2)
- Add platform_address_funding_ecdsa_private_key() method
- Add next_platform_address_funding_index() to track used indices
- Update generic_asset_lock_transaction() to use derived keys

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@pauldelucia pauldelucia force-pushed the feat/platform-address-funding-derivation-path branch from 4a71c00 to 2fa3a34 Compare February 2, 2026 08:09
Comment thread src/model/wallet/mod.rs
};

let max_existing = self
.watched_addresses
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you have two computers with DET, there is no guarantee that watched_addresses will be the same on both. It means there is a potential index reuse weakness, leading to private key reuse.

I would rather derive the index from some identity metadata - I think we have identity index, don't we? So maybe we can use the identity index here instead?

@PastaPastaPasta
Copy link
Copy Markdown
Member

This is a local workaround until dash-sdk adds native support for platform_address_funding_path().

can we just make this happen is dash-sdk?

Copy link
Copy Markdown
Collaborator

@thepastaclaw thepastaclaw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

Clean implementation of deterministic HD-derived keys for platform address funding. Derivation path follows DIP-17 conventions and concurrency is correctly handled within the wallet lock scope. However, the new funding path (key_class=2) is misclassified by is_platform_payment() which only checks the DIP-17 prefix without filtering on key_class.

Reviewed commit: 2fa3a34

🔴 1 blocking

1 additional finding

🔴 blocking: key_class=2 funding paths misclassified as Platform payment addresses

src/model/wallet/mod.rs (line 174)

is_platform_payment() only checks m/9'/coin_type'/17'/... and ignores the key_class component, so the new funding path m/9'/coin_type'/17'/0'/2'/index matches the payment predicate too. This leaks funding keys into payment-only flows:

  • platform_receive_address() and new-address index selection
  • platform_addresses() listing
  • get_platform_address_private_key()
  • Core refresh skips these Core P2PKH funding addresses as if they were Platform-only

The helper needs to require key_class == 0 for payments, or callers need to filter on DerivationPathReference::PlatformPayment instead of the broad DIP-17 prefix.

🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.

In `src/model/wallet/mod.rs`:
- [BLOCKING] line 174: key_class=2 funding paths misclassified as Platform payment addresses
  `is_platform_payment()` only checks `m/9'/coin_type'/17'/...` and ignores the `key_class` component, so the new funding path `m/9'/coin_type'/17'/0'/2'/index` matches the payment predicate too. This leaks funding keys into payment-only flows:
- `platform_receive_address()` and new-address index selection
- `platform_addresses()` listing
- `get_platform_address_private_key()`
- Core refresh skips these Core P2PKH funding addresses as if they were Platform-only

The helper needs to require `key_class == 0` for payments, or callers need to filter on `DerivationPathReference::PlatformPayment` instead of the broad DIP-17 prefix.

@lklimek
Copy link
Copy Markdown
Contributor

lklimek commented Apr 1, 2026

Closing — superseded by #790, which takes a more complete approach to the same problem (deterministic HD keys for asset lock transactions). PR #790 uses m/9'/coin_type'/15'/index derivation with pre-registered funding addresses and full recovery support, replacing this earlier workaround.

🤖 Co-authored by Claudius the Magnificent AI Agent

@lklimek lklimek closed this Apr 1, 2026
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.

4 participants