Standardize serialization within the Monero lib

read for R: Read
write for W: Write
serialize for -> Vec<u8>

Also uses std::io::{self, Read, Write} consistently.
This commit is contained in:
Luke Parker
2023-01-07 05:18:35 -05:00
parent 7508106650
commit 7b0b8a20ec
12 changed files with 219 additions and 186 deletions

View File

@@ -32,7 +32,7 @@ impl BitXor<[u8; 8]> for PaymentId {
}
impl PaymentId {
pub(crate) fn serialize<W: Write>(&self, w: &mut W) -> io::Result<()> {
pub(crate) fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
match self {
PaymentId::Unencrypted(id) => {
w.write_all(&[0])?;
@@ -46,7 +46,7 @@ impl PaymentId {
Ok(())
}
fn deserialize<R: Read>(r: &mut R) -> io::Result<PaymentId> {
fn read<R: Read>(r: &mut R) -> io::Result<PaymentId> {
Ok(match read_byte(r)? {
0 => PaymentId::Unencrypted(read_bytes(r)?),
1 => PaymentId::Encrypted(read_bytes(r)?),
@@ -65,7 +65,7 @@ pub(crate) enum ExtraField {
}
impl ExtraField {
fn serialize<W: Write>(&self, w: &mut W) -> io::Result<()> {
fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
match self {
ExtraField::PublicKey(key) => {
w.write_all(&[1])?;
@@ -88,7 +88,7 @@ impl ExtraField {
Ok(())
}
fn deserialize<R: Read>(r: &mut R) -> io::Result<ExtraField> {
fn read<R: Read>(r: &mut R) -> io::Result<ExtraField> {
Ok(match read_byte(r)? {
1 => ExtraField::PublicKey(read_point(r)?),
2 => ExtraField::Nonce({
@@ -127,7 +127,7 @@ impl Extra {
pub(crate) fn payment_id(&self) -> Option<PaymentId> {
for field in &self.0 {
if let ExtraField::Nonce(data) = field {
return PaymentId::deserialize::<&[u8]>(&mut data.as_ref()).ok();
return PaymentId::read::<&[u8]>(&mut data.as_ref()).ok();
}
}
None
@@ -176,18 +176,18 @@ impl Extra {
data.iter().map(|v| 1 + varint_len(v.len()) + v.len()).sum::<usize>()
}
pub(crate) fn serialize<W: Write>(&self, w: &mut W) -> io::Result<()> {
pub(crate) fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
for field in &self.0 {
field.serialize(w)?;
field.write(w)?;
}
Ok(())
}
pub(crate) fn deserialize<R: Read>(r: &mut R) -> io::Result<Extra> {
pub(crate) fn read<R: Read>(r: &mut R) -> io::Result<Extra> {
let mut res = Extra(vec![]);
let mut field;
while {
field = ExtraField::deserialize(r);
field = ExtraField::read(r);
field.is_ok()
} {
res.0.push(field.unwrap());

View File

@@ -1,4 +1,4 @@
use std::io;
use std::io::{self, Read, Write};
use zeroize::{Zeroize, ZeroizeOnDrop};
@@ -24,14 +24,18 @@ pub struct AbsoluteId {
}
impl AbsoluteId {
pub fn serialize(&self) -> Vec<u8> {
let mut res = Vec::with_capacity(32 + 1);
res.extend(self.tx);
res.push(self.o);
res
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
w.write_all(&self.tx)?;
w.write_all(&[self.o])
}
pub fn read<R: io::Read>(r: &mut R) -> io::Result<AbsoluteId> {
pub fn serialize(&self) -> Vec<u8> {
let mut serialized = Vec::with_capacity(32 + 1);
self.write(&mut serialized).unwrap();
serialized
}
pub fn read<R: Read>(r: &mut R) -> io::Result<AbsoluteId> {
Ok(AbsoluteId { tx: read_bytes(r)?, o: read_byte(r)? })
}
}
@@ -46,16 +50,20 @@ pub struct OutputData {
}
impl OutputData {
pub fn serialize(&self) -> Vec<u8> {
let mut res = Vec::with_capacity(32 + 32 + 40);
res.extend(self.key.compress().to_bytes());
res.extend(self.key_offset.to_bytes());
res.extend(self.commitment.mask.to_bytes());
res.extend(self.commitment.amount.to_le_bytes());
res
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
w.write_all(&self.key.compress().to_bytes())?;
w.write_all(&self.key_offset.to_bytes())?;
w.write_all(&self.commitment.mask.to_bytes())?;
w.write_all(&self.commitment.amount.to_le_bytes())
}
pub fn read<R: io::Read>(r: &mut R) -> io::Result<OutputData> {
pub fn serialize(&self) -> Vec<u8> {
let mut serialized = Vec::with_capacity(32 + 32 + 32 + 8);
self.write(&mut serialized).unwrap();
serialized
}
pub fn read<R: Read>(r: &mut R) -> io::Result<OutputData> {
Ok(OutputData {
key: read_point(r)?,
key_offset: read_scalar(r)?,
@@ -79,26 +87,31 @@ pub struct Metadata {
}
impl Metadata {
pub fn serialize(&self) -> Vec<u8> {
let mut res = Vec::with_capacity(4 + 4 + 8 + 1);
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
if let Some(subaddress) = self.subaddress {
res.push(1);
res.extend(subaddress.account().to_le_bytes());
res.extend(subaddress.address().to_le_bytes());
w.write_all(&[1])?;
w.write_all(&subaddress.account().to_le_bytes())?;
w.write_all(&subaddress.address().to_le_bytes())?;
} else {
res.push(0);
w.write_all(&[0])?;
}
res.extend(self.payment_id);
w.write_all(&self.payment_id)?;
res.extend(u32::try_from(self.arbitrary_data.len()).unwrap().to_le_bytes());
w.write_all(&u32::try_from(self.arbitrary_data.len()).unwrap().to_le_bytes())?;
for part in &self.arbitrary_data {
res.extend([u8::try_from(part.len()).unwrap()]);
res.extend(part);
w.write_all(&[u8::try_from(part.len()).unwrap()])?;
w.write_all(part)?;
}
res
Ok(())
}
pub fn read<R: io::Read>(r: &mut R) -> io::Result<Metadata> {
pub fn serialize(&self) -> Vec<u8> {
let mut serialized = Vec::with_capacity(1 + 8 + 1);
self.write(&mut serialized).unwrap();
serialized
}
pub fn read<R: Read>(r: &mut R) -> io::Result<Metadata> {
let subaddress = if read_byte(r)? == 1 {
Some(
SubaddressIndex::new(read_u32(r)?, read_u32(r)?)
@@ -148,14 +161,19 @@ impl ReceivedOutput {
&self.metadata.arbitrary_data
}
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
self.absolute.write(w)?;
self.data.write(w)?;
self.metadata.write(w)
}
pub fn serialize(&self) -> Vec<u8> {
let mut serialized = self.absolute.serialize();
serialized.extend(&self.data.serialize());
serialized.extend(&self.metadata.serialize());
let mut serialized = vec![];
self.write(&mut serialized).unwrap();
serialized
}
pub fn deserialize<R: io::Read>(r: &mut R) -> io::Result<ReceivedOutput> {
pub fn read<R: Read>(r: &mut R) -> io::Result<ReceivedOutput> {
Ok(ReceivedOutput {
absolute: AbsoluteId::read(r)?,
data: OutputData::read(r)?,
@@ -200,14 +218,19 @@ impl SpendableOutput {
self.output.commitment()
}
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
self.output.write(w)?;
w.write_all(&self.global_index.to_le_bytes())
}
pub fn serialize(&self) -> Vec<u8> {
let mut serialized = self.output.serialize();
serialized.extend(self.global_index.to_le_bytes());
let mut serialized = vec![];
self.write(&mut serialized).unwrap();
serialized
}
pub fn read<R: io::Read>(r: &mut R) -> io::Result<SpendableOutput> {
Ok(SpendableOutput { output: ReceivedOutput::deserialize(r)?, global_index: read_u64(r)? })
pub fn read<R: Read>(r: &mut R) -> io::Result<SpendableOutput> {
Ok(SpendableOutput { output: ReceivedOutput::read(r)?, global_index: read_u64(r)? })
}
}
@@ -248,7 +271,7 @@ impl<O: Clone + Zeroize> Timelocked<O> {
impl Scanner {
/// Scan a transaction to discover the received outputs.
pub fn scan_transaction(&mut self, tx: &Transaction) -> Timelocked<ReceivedOutput> {
let extra = Extra::deserialize::<&[u8]>(&mut tx.prefix.extra.as_ref());
let extra = Extra::read::<&[u8]>(&mut tx.prefix.extra.as_ref());
let keys;
let extra = if let Ok(extra) = extra {
keys = extra.keys();

View File

@@ -311,7 +311,7 @@ impl SignableTransaction {
let mut extra = Extra::new(outputs.iter().map(|output| output.R).collect());
let mut id_vec = Vec::with_capacity(1 + 8);
PaymentId::Encrypted(id).serialize(&mut id_vec).unwrap();
PaymentId::Encrypted(id).write(&mut id_vec).unwrap();
extra.push(ExtraField::Nonce(id_vec));
// Include data if present
@@ -320,7 +320,7 @@ impl SignableTransaction {
}
let mut serialized = Vec::with_capacity(Extra::fee_weight(outputs.len(), self.data.as_ref()));
extra.serialize(&mut serialized).unwrap();
extra.write(&mut serialized).unwrap();
serialized
};