use crate::base::ser::{EpeeRead, EpeeWrite, MAX_VEC_LEN, Reader, write_vec};
use crate::base::types::{AccountPublicAddr, Value256};
use crate::base::variant::Variant;
use crate::base::varint::append_varint;
use crate::crypto::{Point, chacha8, chacha8_generate_key};
use crate::error::{Error, Result};
use crate::txdest::TxDest;
use crate::txsource::TxSource;
#[derive(Clone, Debug)]
pub struct FinalizeTxParam {
pub unlock_time: u64,
pub extra: Vec<Variant>,
pub attachments: Vec<Variant>,
pub crypt_address: AccountPublicAddr,
pub tx_outs_attr: u8,
pub shuffle: bool,
pub flags: u8,
pub multisig_id: Value256,
pub sources: Vec<TxSource>,
pub selected_transfers: Vec<u64>,
pub prepared_destinations: Vec<TxDest>,
pub expiration_time: u64,
pub spend_pub_key: Point,
pub tx_version: u64,
pub tx_hardfork_id: u64,
pub mode_separate_fee: u64,
}
impl EpeeWrite for FinalizeTxParam {
fn write_epee(&self, out: &mut Vec<u8>) {
self.unlock_time.write_epee(out);
write_vec(&self.extra, out);
write_vec(&self.attachments, out);
self.crypt_address.write_epee(out);
out.push(self.tx_outs_attr);
self.shuffle.write_epee(out);
out.push(self.flags);
self.multisig_id.write_epee(out);
write_vec(&self.sources, out);
append_varint(out, self.selected_transfers.len() as u64);
for t in &self.selected_transfers {
append_varint(out, *t);
}
write_vec(&self.prepared_destinations, out);
self.expiration_time.write_epee(out);
self.spend_pub_key.write_epee(out);
self.tx_version.write_epee(out);
self.tx_hardfork_id.write_epee(out);
self.mode_separate_fee.write_epee(out);
}
}
impl EpeeRead for FinalizeTxParam {
fn read_epee(r: &mut Reader<'_>) -> Result<Self> {
let unlock_time = u64::read_epee(r)?;
let extra = r.read_vec()?;
let attachments = r.read_vec()?;
let crypt_address = AccountPublicAddr::read_epee(r)?;
let tx_outs_attr = r.read_byte()?;
let shuffle = bool::read_epee(r)?;
let flags = r.read_byte()?;
let multisig_id = Value256::read_epee(r)?;
let sources = r.read_vec()?;
let n = r.read_varint()?;
if n > MAX_VEC_LEN {
return Err(crate::err!("selected_transfers too large: {n}"));
}
let mut selected_transfers = Vec::with_capacity(n as usize);
for _ in 0..n {
selected_transfers.push(r.read_varint()?);
}
Ok(FinalizeTxParam {
unlock_time,
extra,
attachments,
crypt_address,
tx_outs_attr,
shuffle,
flags,
multisig_id,
sources,
selected_transfers,
prepared_destinations: r.read_vec()?,
expiration_time: u64::read_epee(r)?,
spend_pub_key: Point::read_epee(r)?,
tx_version: u64::read_epee(r)?,
tx_hardfork_id: u64::read_epee(r)?,
mode_separate_fee: u64::read_epee(r)?,
})
}
}
impl FinalizeTxParam {
pub fn parse(buf: &[u8], view_secret_key: &[u8]) -> Result<FinalizeTxParam> {
let code = chacha8_generate_key(view_secret_key)?;
let plain = chacha8(&code, &[0u8; 8], buf)?;
let mut r = Reader::new(&plain);
let res = FinalizeTxParam::read_epee(&mut r)?;
if !r.is_empty() {
return Err(Error::msg("trailing data"));
}
Ok(res)
}
}