spark_rust/signer/traits/
derivation_path.rs

1//! # Key derivation path handling for Spark wallet
2//!
3//! This module implements the key derivation scheme for the Spark wallet, following
4//! BIP43 conventions with a custom purpose identifier. The scheme is structured as:
5//!
6//! - Identity key: m/8797555'/account'/0'
7//! - Base signing key: m/8797555'/account'/1'
8//! - Temporary signing key: m/8797555'/account'/2'
9//!
10//! For leaf keys, an additional index is derived from the leaf ID:
11//! - Leaf key: m/8797555'/account'/1'/hash(leaf_id)'
12//!
13//! The purpose value 8797555 is derived as the last 3 bytes of sha256("spark") in decimal (863d73).
14//!
15//! All indices use hardened derivation (denoted by the apostrophe) for enhanced security.
16//! Account indices should start from 0.
17//!
18//! ## Security and Compatibility
19//!
20//! This derivation path scheme is **critical** for compatibility with other Spark wallets.
21//! All Spark wallets must follow this exact scheme to ensure interoperability and proper
22//! handling of funds within the Spark ecosystem.
23//!
24//! # WARNING
25//!
26//! Implementing this trait with non-standard derivation paths will make your wallet
27//! incompatible with the Spark ecosystem. Only implement this trait if you fully understand
28//! the consequences and are intentionally creating a non-standard wallet.
29
30use crate::error::SparkSdkError;
31
32use bitcoin::{key::Keypair, secp256k1::PublicKey, Network};
33use spark_cryptography::derivation_path::{SparkDerivationPath, SparkKeyType};
34
35/// Trait for key derivation operations in the Spark wallet.
36///
37/// This trait defines the methods required to derive keys according to the
38/// Spark-specific derivation path scheme. Implementors must ensure they
39/// follow the exact derivation path structure to maintain compatibility
40/// with the Spark ecosystem.
41///
42/// The Spark derivation scheme follows:
43/// - m/8797555'/account'/key_type' for main keys
44/// - m/8797555'/account'/1'/hash(leaf_id)' for leaf-specific keys
45///
46/// Where:
47/// - 8797555' is the purpose value (derived from "spark")
48/// - account' is the account index (starting from 0)
49/// - key_type' is the key type (0' for identity, 1' for base signing, 2' for temporary)
50/// - hash(leaf_id)' is a hardened index derived from the leaf ID
51pub trait SparkSignerDerivationPath {
52    /// Derives the deposit signing key for the user.
53    ///
54    /// In Spark, users always have a single deposit key derived deterministically
55    /// from their seed. This method returns the public key corresponding to the
56    /// derived deposit signing key.
57    ///
58    /// The deposit signing key uses the `TemporarySigning` key type (path index 2')
59    /// in the derivation path.
60    ///
61    /// # Arguments
62    /// * `network` - The Bitcoin network to use for the key derivation
63    ///
64    /// # Returns
65    /// The public key for deposit operations or an error if derivation fails
66    fn get_deposit_signing_key(&self, network: Network) -> Result<PublicKey, SparkSdkError>;
67
68    /// Derives a Spark key for the specified key type, account, and optionally leaf ID.
69    ///
70    /// This is a core method for the Spark derivation path system. It handles the
71    /// derivation of all types of keys used in the Spark wallet, including identity
72    /// keys, base signing keys, temporary signing keys, and leaf-specific keys.
73    ///
74    /// # Arguments
75    /// * `leaf_id` - Optional leaf ID for leaf-specific keys. If provided, the key
76    ///   will be derived using the leaf-specific path: m/8797555'/account'/1'/hash(leaf_id)'
77    /// * `account` - Account index to use in the derivation path
78    /// * `key_type` - The type of key to derive (Identity, BaseSigning, or TemporarySigning)
79    /// * `network` - The Bitcoin network to use for the key derivation
80    ///
81    /// # Returns
82    /// The derived secret key or an error if derivation fails
83    fn derive_spark_key(
84        &self,
85        leaf_id: String,
86        account: u32,
87        key_type: SparkKeyType,
88        network: Network,
89    ) -> Result<Keypair, SparkSdkError>;
90
91    /// Returns the derivation path for the identity key.
92    ///
93    /// The identity key has the path: m/8797555'/account'/0'
94    /// This method constructs and returns this path for the specified account.
95    ///
96    /// # Arguments
97    /// * `account_index` - The account index to use in the derivation path
98    ///
99    /// # Returns
100    /// A `SparkDerivationPath` containing the identity key path components
101    /// or an error if path construction fails
102    fn get_identity_derivation_path(
103        account_index: u32,
104    ) -> Result<SparkDerivationPath, SparkSdkError>;
105}