//! # PSBT Serialization //! //! Defines traits used for (de)serializing PSBT values into/from raw //! bytes in PSBT key-value pairs. use std::io::{self, Cursor}; use blockdata::script::Script; use blockdata::transaction::Transaction; use consensus::encode::{self, serialize, Decodable}; use util::bip32::{ChildNumber, DerivationPath, Fingerprint}; use util::key::PublicKey; use util::psbt; /// A trait for serializing a value as raw data for insertion into PSBT /// key-value pairs. pub trait Serialize { /// Serialize a value as raw data. fn serialize(&self) -> Vec; } /// A trait for deserializing a value from raw data in PSBT key-value pairs. pub trait Deserialize: Sized { /// Deserialize a value from raw data. fn deserialize(bytes: &[u8]) -> Result; } impl_psbt_de_serialize!(Transaction); impl Serialize for Script { fn serialize(&self) -> Vec { self.to_bytes() } } impl Deserialize for Script { fn deserialize(bytes: &[u8]) -> Result { Ok(Self::from(bytes.to_vec())) } } impl Serialize for PublicKey { fn serialize(&self) -> Vec { let mut buf = Vec::new(); self.write_into(&mut buf); buf } } impl Deserialize for PublicKey { fn deserialize(bytes: &[u8]) -> Result { PublicKey::from_slice(bytes) .map_err(|_| encode::Error::ParseFailed("invalid public key")) } } impl Serialize for (Fingerprint, DerivationPath) { fn serialize(&self) -> Vec { let mut rv: Vec = Vec::with_capacity(4 + 4 * (self.1).as_ref().len()); rv.append(&mut self.0.to_bytes().to_vec()); for cnum in self.1.into_iter() { rv.append(&mut serialize(&u32::from(*cnum))) } rv } } impl Deserialize for (Fingerprint, DerivationPath) { fn deserialize(bytes: &[u8]) -> Result { if bytes.len() < 4 { return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()) } let fprint: Fingerprint = Fingerprint::from(&bytes[0..4]); let mut dpath: Vec = Default::default(); let d = &mut Cursor::new(&bytes[4..]); loop { match Decodable::consensus_decode(d) { Ok(index) => { dpath.push(>::from(index)); if d.position() == (bytes.len() - 4) as u64 { break; } }, Err(e) => return Err(e), } } Ok((fprint, dpath.into())) } }