Skip to content

test(wallet-core): Property-based derivation tests for SEP-0005 across randomized indices and mnemonic entropy #41

Description

@Emmyt24

Description

crates/wallet-core/src/derive.rs only asserts derivation against the single official SEP-0005 test vector plus a handful of hand-picked indices (0, 1, 2, 5). The hardened path m/44'/148'/index' is security-sensitive: a subtle off-by-one in the hardened-offset math or path encoding would silently derive the wrong keypair for some indices while passing every existing test. We need property-based coverage across the full u32 index space (mod hardened bit) and randomized mnemonics to catch that class of bug.

Requirements and Context

  • Add proptest as a dev-dependency of crates/wallet-core (workspace-pinned, dev-only).
  • Properties to hold for any valid 12-word mnemonic and any u32 index: derivation is deterministic (same input -> same output byte-for-byte), different indices from the same seed produce different secrets with overwhelming probability, and the derived public key always round-trips through stellar_strkey encode/decode.
  • Include the reserved boundary indices explicitly: 0, 1, u32::MAX, and HARDENED - 1 (0x7fffffff), since these exercise the hardened-offset OR-mask differently than mid-range values.
  • Do not weaken #![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic)] in crates/wallet-core/src/lib.rs — proptest cases run under #[cfg(test)], which already relaxes those lints.

Suggested Execution

Branch: test/wallet-core/sep0005-property-derivation

Implement Changes

  • Add proptest = "1" under [dev-dependencies] in crates/wallet-core/Cargo.toml.
  • In crates/wallet-core/src/derive.rs's #[cfg(test)] mod tests, add a proptest! block generating random mnemonics via bip39::Mnemonic::new seeded from proptest's Rng (or generate random 16-byte entropy and feed it through Mnemonic::from_entropy) and random u32 indices.
  • Assert determinism, distinctness across indices, and successful ed25519 keypair construction (ed25519_dalek::SigningKey::from_bytes) for every generated case.

Test and Commit

  • proptest case: derivation_is_deterministic_for_any_index (same seed+index twice -> identical secret).
  • proptest case: distinct_indices_yield_distinct_secrets (two different random indices from the same seed differ).
  • #[test] fn boundary_indices_derive_without_panic covering 0, 1, u32::MAX, HARDENED - 1.
  • Run cargo test -p octo-wallet-core locally before committing.

Example Commit Message

test(wallet-core): add property-based SEP-0005 derivation coverage

Adds proptest cases exercising the hardened derivation path across randomized
mnemonics and the full u32 index space, plus explicit boundary-index tests, to
catch off-by-one errors the fixed test vector alone can't surface.

Guidelines

  • Keep proptest case counts reasonable (the default 256 cases is fine) — this crate's CI budget is tight and ed25519 derivation is not free.
  • Do not introduce any unsafe code; #![forbid(unsafe_code)] is enforced crate-wide.
  • Reference this issue with Closes #<issue-number> in the PR description.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions