use bitcoin::hashes::{sha256, Hash};
use bitcoin::util::bip32::ExtendedPubKey;
use secp256k1::{PublicKey, SECP256K1};
use crate::{DerivationAccount, DerivationSubpath, TerminalStep, XpubRef};
pub trait UnsatisfiableKey {
type Param;
fn unsatisfiable_key(_: Self::Param) -> Self;
}
impl UnsatisfiableKey for PublicKey {
type Param = ();
fn unsatisfiable_key(_: Self::Param) -> Self {
let unspendable_key = PublicKey::from_secret_key(SECP256K1, &secp256k1::ONE_KEY);
let hash = &sha256::Hash::hash(&unspendable_key.serialize());
let tweak =
secp256k1::Scalar::from_be_bytes(hash.into_inner()).expect("negligible probability");
unspendable_key
.add_exp_tweak(SECP256K1, &tweak)
.expect("negligible probability")
}
}
impl UnsatisfiableKey for ExtendedPubKey {
type Param = bool;
fn unsatisfiable_key(testnet: Self::Param) -> Self {
let unspendable_key = PublicKey::unsatisfiable_key(());
let mut buf = Vec::with_capacity(78);
buf.extend(if testnet {
[0x04u8, 0x35, 0x87, 0xCF]
} else {
[0x04u8, 0x88, 0xB2, 0x1E]
});
buf.extend([0u8; 5]); buf.extend([0u8; 4]); buf.extend(&unspendable_key.serialize()[1..]);
buf.extend(unspendable_key.serialize());
ExtendedPubKey::decode(&buf).expect("broken unspendable key construction")
}
}
impl UnsatisfiableKey for DerivationAccount {
type Param = (bool, DerivationSubpath<TerminalStep>);
fn unsatisfiable_key(param: Self::Param) -> Self {
let (testnet, terminal_path) = param;
DerivationAccount {
master: XpubRef::Unknown,
account_path: empty!(),
account_xpub: ExtendedPubKey::unsatisfiable_key(testnet),
revocation_seal: None,
terminal_path,
}
}
}