use core::convert::Infallible;
use crate::transaction::fees::zip317::P2PKH_STANDARD_INPUT_SIZE;
use transparent::{
address::Script,
bundle::{OutPoint, TxOut},
};
use zcash_protocol::value::Zatoshis;
use zcash_script::{script, solver};
#[cfg(feature = "transparent-inputs")]
use transparent::builder::TransparentInputInfo;
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum InputSize {
Known(usize),
Unknown(OutPoint),
}
impl InputSize {
pub const STANDARD_P2PKH: InputSize = InputSize::Known(P2PKH_STANDARD_INPUT_SIZE);
}
pub trait InputView: core::fmt::Debug {
fn outpoint(&self) -> &OutPoint;
fn coin(&self) -> &TxOut;
fn serialized_size(&self) -> InputSize {
match script::PubKey::parse(&self.coin().script_pubkey().0)
.ok()
.as_ref()
.and_then(solver::standard)
{
Some(solver::ScriptKind::PubKeyHash { .. }) => InputSize::STANDARD_P2PKH,
_ => InputSize::Unknown(self.outpoint().clone()),
}
}
}
#[cfg(feature = "transparent-inputs")]
impl InputView for TransparentInputInfo {
fn outpoint(&self) -> &OutPoint {
self.outpoint()
}
fn coin(&self) -> &TxOut {
self.coin()
}
fn serialized_size(&self) -> InputSize {
self.serialized_len().map_or(
InputSize::Unknown(self.outpoint().clone()),
InputSize::Known,
)
}
}
impl InputView for Infallible {
fn outpoint(&self) -> &OutPoint {
unreachable!()
}
fn coin(&self) -> &TxOut {
unreachable!()
}
}
pub trait OutputView: core::fmt::Debug {
fn value(&self) -> Zatoshis;
fn script_pubkey(&self) -> &Script;
fn serialized_size(&self) -> usize {
8 + self.script_pubkey().serialized_size()
}
}
impl OutputView for TxOut {
fn value(&self) -> Zatoshis {
self.value()
}
fn script_pubkey(&self) -> &Script {
self.script_pubkey()
}
}