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}