CrypteCipher/core/src/btc.rs
MoCipher 267d8f6edd
Some checks failed
CI / build (macos-latest, stable) (push) Has been cancelled
CI / build (ubuntu-latest, stable) (push) Has been cancelled
CI / build (windows-latest, stable) (push) Has been cancelled
Initial CrypteCipher scaffold and features
2026-02-12 00:02:00 +01:00

60 lines
2.2 KiB
Rust

use bitcoin::network::constants::Network;
use bitcoin::util::address::Address;
use bitcoin::util::key::PrivateKey;
use bitcoin::secp256k1::{Secp256k1, SecretKey, PublicKey};
use sha2::{Digest, Sha256};
/// Simple Bitcoin on-chain wallet helper (minimal, safe-by-default)
///
/// This implements a deterministic derivation of a single private key from the core seed
/// purely for demonstration and testing. In production use **BIP32/BIP39** HD derivation
/// and robust UTXO management (e.g., `bdk`).
pub struct BtcWallet {
secret_key: SecretKey,
network: Network,
}
impl BtcWallet {
/// Derive a secret key deterministically from a seed and domain tag
pub fn derive_from_seed(seed: &[u8; 32], network: Network, tag: &[u8]) -> Self {
// Use SHA256(seed || tag) as a simple DRBG to get 32 bytes -> SecretKey
let mut hasher = Sha256::new();
hasher.update(seed);
hasher.update(tag);
let hash = hasher.finalize();
let sk = SecretKey::from_slice(&hash).expect("hash must be a valid secret key");
Self { secret_key: sk, network }
}
/// Return the P2WPKH bech32 address for this key
pub fn get_address(&self) -> Address {
let secp = Secp256k1::new();
let pk = PublicKey::from_secret_key(&secp, &self.secret_key);
let compressed = PublicKey::new(pk.key);
let pk_hash = bitcoin::hashes::hash160::Hash::hash(&compressed.serialize());
Address::p2wpkh(&pk, self.network).expect("address creation")
}
/// Return the private key in WIF format (useful for tests/examples only)
pub fn wif(&self) -> String {
let pk = PrivateKey { key: self.secret_key, network: self.network, compressed: true };
pk.to_wif()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::WalletCore;
#[test]
fn derive_and_address() {
let core = WalletCore::new();
let seed = core.seed; // NOTE: demo access to seed (in real code seed would be private)
let wallet = BtcWallet::derive_from_seed(&seed, Network::Testnet, b"cryptec-btc");
let addr = wallet.get_address();
assert!(addr.to_string().starts_with("tb1") || addr.to_string().starts_with("2") );
let wif = wallet.wif();
assert!(!wif.is_empty());
}
}