1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
// Descriptor wallet library extending bitcoin & miniscript functionality
// by LNP/BP Association (https://lnp-bp.org)
// Written in 2020-2021 by
// Dr. Maxim Orlovsky <orlovsky@pandoracore.com>
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the Apache-2.0 License
// along with this software.
// If not, see <https://opensource.org/licenses/Apache-2.0>.
use amplify::Slice32;
use bitcoin::secp256k1;
use crate::ProprietaryKey;
// TODO: Move this module to BP Core lib
pub const PSBT_DBC_PREFIX: &[u8] = b"DBC";
pub const PSBT_IN_DBC_P2C_TWEAK: u8 = 0;
/// Extension trait to work with deterministic bitcoin commitment P2C tweaks
/// applied to public keys in PSBT inputs.
pub trait InputP2cTweak {
/// Adds information about DBC P2C public key to PSBT input
fn set_dbc_p2c_tweak(&mut self, pubkey: secp256k1::PublicKey, tweak: Slice32);
/// Finds a tweak for the provided bitcoin public key, if is known
fn dbc_p2c_tweak(&self, pk: secp256k1::PublicKey) -> Option<Slice32>;
}
impl InputP2cTweak for crate::Input {
fn set_dbc_p2c_tweak(&mut self, pubkey: secp256k1::PublicKey, tweak: Slice32) {
let mut value = pubkey.serialize().to_vec();
value.extend(&tweak[..]);
self.proprietary.insert(
ProprietaryKey {
prefix: PSBT_DBC_PREFIX.to_vec(),
subtype: PSBT_IN_DBC_P2C_TWEAK,
key: vec![],
},
value,
);
}
fn dbc_p2c_tweak(&self, pk: secp256k1::PublicKey) -> Option<Slice32> {
self.proprietary.iter().find_map(
|(
ProprietaryKey {
prefix,
subtype,
key,
},
value,
)| {
if prefix.as_slice() == PSBT_DBC_PREFIX
&& *subtype == PSBT_IN_DBC_P2C_TWEAK
&& key == &Vec::<u8>::new()
&& value.len() == 33 + 32
{
secp256k1::PublicKey::from_slice(&value[..33])
.ok()
.and_then(|pubkey| {
if pk == pubkey {
Slice32::from_slice(&value[33..])
} else {
None
}
})
} else {
None
}
},
)
}
}