use std::collections::BTreeMap;
use blockdata::script::Script;
use blockdata::transaction::{SigHashType, Transaction, TxOut};
use consensus::encode;
use util::bip32::{DerivationPath, Fingerprint};
use util::key::PublicKey;
use util::psbt;
use util::psbt::map::Map;
use util::psbt::raw;
use util::psbt::Error;
#[derive(Clone, Default, Debug, PartialEq)]
pub struct Input {
pub non_witness_utxo: Option<Transaction>,
pub witness_utxo: Option<TxOut>,
pub partial_sigs: BTreeMap<PublicKey, Vec<u8>>,
pub sighash_type: Option<SigHashType>,
pub redeem_script: Option<Script>,
pub witness_script: Option<Script>,
pub hd_keypaths: BTreeMap<PublicKey, (Fingerprint, DerivationPath)>,
pub final_script_sig: Option<Script>,
pub final_script_witness: Option<Vec<Vec<u8>>>,
pub unknown: BTreeMap<raw::Key, Vec<u8>>,
}
impl Map for Input {
fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), encode::Error> {
let raw::Pair {
key: raw_key,
value: raw_value,
} = pair;
match raw_key.type_value {
0u8 => {
impl_psbt_insert_pair! {
self.non_witness_utxo <= <raw_key: _>|<raw_value: Transaction>
}
}
1u8 => {
impl_psbt_insert_pair! {
self.witness_utxo <= <raw_key: _>|<raw_value: TxOut>
}
}
3u8 => {
impl_psbt_insert_pair! {
self.sighash_type <= <raw_key: _>|<raw_value: SigHashType>
}
}
4u8 => {
impl_psbt_insert_pair! {
self.redeem_script <= <raw_key: _>|<raw_value: Script>
}
}
5u8 => {
impl_psbt_insert_pair! {
self.witness_script <= <raw_key: _>|<raw_value: Script>
}
}
7u8 => {
impl_psbt_insert_pair! {
self.final_script_sig <= <raw_key: _>|<raw_value: Script>
}
}
8u8 => {
impl_psbt_insert_pair! {
self.final_script_witness <= <raw_key: _>|<raw_value: Vec<Vec<u8>>>
}
}
2u8 => {
impl_psbt_insert_pair! {
self.partial_sigs <= <raw_key: PublicKey>|<raw_value: Vec<u8>>
}
}
6u8 => {
impl_psbt_insert_pair! {
self.hd_keypaths <= <raw_key: PublicKey>|<raw_value: (Fingerprint, DerivationPath)>
}
}
_ => {
if self.unknown.contains_key(&raw_key) {
return Err(Error::DuplicateKey(raw_key).into());
} else {
self.unknown.insert(raw_key, raw_value);
}
}
}
Ok(())
}
fn get_pairs(&self) -> Result<Vec<raw::Pair>, encode::Error> {
let mut rv: Vec<raw::Pair> = Default::default();
impl_psbt_get_pair! {
rv.push(self.non_witness_utxo as <0u8, _>|<Transaction>)
}
impl_psbt_get_pair! {
rv.push(self.witness_utxo as <1u8, _>|<TxOut>)
}
impl_psbt_get_pair! {
rv.push(self.partial_sigs as <2u8, PublicKey>|<Vec<u8>>)
}
impl_psbt_get_pair! {
rv.push(self.sighash_type as <3u8, _>|<SigHashType>)
}
impl_psbt_get_pair! {
rv.push(self.redeem_script as <4u8, _>|<Script>)
}
impl_psbt_get_pair! {
rv.push(self.witness_script as <5u8, _>|<Script>)
}
impl_psbt_get_pair! {
rv.push(self.hd_keypaths as <6u8, PublicKey>|<(Fingerprint, DerivationPath)>)
}
impl_psbt_get_pair! {
rv.push(self.final_script_sig as <7u8, _>|<Script>)
}
impl_psbt_get_pair! {
rv.push(self.final_script_witness as <8u8, _>|<Script>)
}
for (key, value) in self.unknown.iter() {
rv.push(raw::Pair {
key: key.clone(),
value: value.clone(),
});
}
Ok(rv)
}
fn merge(&mut self, other: Self) -> Result<(), psbt::Error> {
merge!(non_witness_utxo, self, other);
if let (&None, Some(witness_utxo)) = (&self.witness_utxo, other.witness_utxo) {
self.witness_utxo = Some(witness_utxo);
self.non_witness_utxo = None; }
self.partial_sigs.extend(other.partial_sigs);
self.hd_keypaths.extend(other.hd_keypaths);
self.unknown.extend(other.unknown);
merge!(redeem_script, self, other);
merge!(witness_script, self, other);
merge!(final_script_sig, self, other);
merge!(final_script_witness, self, other);
Ok(())
}
}
impl_psbtmap_consensus_enc_dec_oding!(Input);