use std::collections::BTreeMap;
use bitcoin::psbt::TapTree;
use bitcoin::util::bip32::KeySource;
use bitcoin::util::taproot::TapLeafHash;
use bitcoin::{secp256k1, TxOut, XOnlyPublicKey};
use bitcoin_scripts::{PubkeyScript, RedeemScript, WitnessScript};
#[cfg(feature = "serde")]
use serde_with::{hex::Hex, As, Same};
use crate::raw;
use crate::v0::OutputV0;
#[derive(Clone, Eq, PartialEq, Debug, Default)]
#[derive(StrictEncode, StrictDecode)]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
serde(crate = "serde_crate")
)]
pub struct Output {
pub(crate) index: usize,
pub amount: u64,
pub script: PubkeyScript,
pub redeem_script: Option<RedeemScript>,
pub witness_script: Option<WitnessScript>,
#[cfg_attr(feature = "serde", serde(with = "As::<BTreeMap<Same, Same>>"))]
pub bip32_derivation: BTreeMap<secp256k1::PublicKey, KeySource>,
pub tap_internal_key: Option<XOnlyPublicKey>,
pub tap_tree: Option<TapTree>,
#[cfg_attr(
feature = "serde",
serde(with = "As::<BTreeMap<Same, (Vec<Same>, Same)>>")
)]
pub tap_key_origins: BTreeMap<XOnlyPublicKey, (Vec<TapLeafHash>, KeySource)>,
#[cfg_attr(feature = "serde", serde(with = "As::<BTreeMap<Same, Hex>>"))]
pub proprietary: BTreeMap<raw::ProprietaryKey, Vec<u8>>,
#[cfg_attr(feature = "serde", serde(with = "As::<BTreeMap<Same, Hex>>"))]
pub unknown: BTreeMap<raw::Key, Vec<u8>>,
}
impl Output {
pub fn new(index: usize, txout: TxOut) -> Self {
Output {
index,
amount: txout.value,
script: txout.script_pubkey.into(),
..Output::default()
}
}
pub fn with(index: usize, v0: OutputV0, txout: TxOut) -> Self {
Output {
index,
amount: txout.value,
script: txout.script_pubkey.into(),
redeem_script: v0.redeem_script.map(Into::into),
witness_script: v0.witness_script.map(Into::into),
bip32_derivation: v0.bip32_derivation,
tap_internal_key: v0.tap_internal_key,
tap_tree: v0.tap_tree,
tap_key_origins: v0.tap_key_origins,
proprietary: v0.proprietary,
unknown: v0.unknown,
}
}
#[inline]
pub fn index(&self) -> usize { self.index }
pub fn to_txout(&self) -> TxOut {
TxOut {
value: self.amount,
script_pubkey: self.script.clone().into(),
}
}
pub fn into_txout(self) -> TxOut {
TxOut {
value: self.amount,
script_pubkey: self.script.into(),
}
}
pub fn split(self) -> (OutputV0, TxOut) {
(
OutputV0 {
redeem_script: self.redeem_script.map(Into::into),
witness_script: self.witness_script.map(Into::into),
bip32_derivation: self.bip32_derivation,
tap_internal_key: self.tap_internal_key,
tap_tree: self.tap_tree,
tap_key_origins: self.tap_key_origins,
proprietary: self.proprietary,
unknown: self.unknown,
},
TxOut {
value: self.amount,
script_pubkey: self.script.into(),
},
)
}
}
impl From<Output> for OutputV0 {
fn from(output: Output) -> Self {
OutputV0 {
redeem_script: output.redeem_script.map(Into::into),
witness_script: output.witness_script.map(Into::into),
bip32_derivation: output.bip32_derivation,
tap_internal_key: output.tap_internal_key,
tap_tree: output.tap_tree,
tap_key_origins: output.tap_key_origins,
proprietary: output.proprietary,
unknown: output.unknown,
}
}
}