monero: added tx extra variants padding and mysterious minergate (#510)

* monero: read/write tx extra padding

* monero: read/write tx extra mysterious minergate variant

* Clippy

* monero: add tx extra test for minergate + pub key

* BufRead

---------

Co-authored-by: Luke Parker <lukeparker5132@gmail.com>
This commit is contained in:
Justin Berman
2024-02-19 18:22:00 -08:00
committed by GitHub
parent cda14ac8b9
commit 4f1f7984a6
4 changed files with 214 additions and 4 deletions

View File

@@ -1,7 +1,7 @@
use core::ops::BitXor;
use std_shims::{
vec::Vec,
io::{self, Read, Write},
io::{self, Read, BufRead, Write},
};
use zeroize::Zeroize;
@@ -13,6 +13,7 @@ use crate::serialize::{
write_point, write_vec,
};
pub const MAX_TX_EXTRA_PADDING_COUNT: usize = 255;
pub const MAX_TX_EXTRA_NONCE_SIZE: usize = 255;
pub const PAYMENT_ID_MARKER: u8 = 0;
@@ -70,15 +71,23 @@ impl PaymentId {
// Doesn't bother with padding nor MinerGate
#[derive(Clone, PartialEq, Eq, Debug, Zeroize)]
pub enum ExtraField {
Padding(usize),
PublicKey(EdwardsPoint),
Nonce(Vec<u8>),
MergeMining(usize, [u8; 32]),
PublicKeys(Vec<EdwardsPoint>),
MysteriousMinergate(Vec<u8>),
}
impl ExtraField {
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
match self {
ExtraField::Padding(size) => {
w.write_all(&[0])?;
for _ in 1 .. *size {
write_byte(&0u8, w)?;
}
}
ExtraField::PublicKey(key) => {
w.write_all(&[1])?;
w.write_all(&key.compress().to_bytes())?;
@@ -96,12 +105,39 @@ impl ExtraField {
w.write_all(&[4])?;
write_vec(write_point, keys, w)?;
}
ExtraField::MysteriousMinergate(data) => {
w.write_all(&[0xDE])?;
write_vec(write_byte, data, w)?;
}
}
Ok(())
}
pub fn read<R: Read>(r: &mut R) -> io::Result<ExtraField> {
pub fn read<R: BufRead>(r: &mut R) -> io::Result<ExtraField> {
Ok(match read_byte(r)? {
0 => ExtraField::Padding({
// Read until either non-zero, max padding count, or end of buffer
let mut size: usize = 1;
loop {
let buf = r.fill_buf()?;
let mut n_consume = 0;
for v in buf {
if *v != 0u8 {
Err(io::Error::other("non-zero value after padding"))?
}
n_consume += 1;
size += 1;
if size > MAX_TX_EXTRA_PADDING_COUNT {
Err(io::Error::other("padding exceeded max count"))?
}
}
if n_consume == 0 {
break;
}
r.consume(n_consume);
}
size
}),
1 => ExtraField::PublicKey(read_point(r)?),
2 => ExtraField::Nonce({
let nonce = read_vec(read_byte, r)?;
@@ -112,13 +148,14 @@ impl ExtraField {
}),
3 => ExtraField::MergeMining(read_varint(r)?, read_bytes(r)?),
4 => ExtraField::PublicKeys(read_vec(read_point, r)?),
0xDE => ExtraField::MysteriousMinergate(read_vec(read_byte, r)?),
_ => Err(io::Error::other("unknown extra field"))?,
})
}
}
#[derive(Clone, PartialEq, Eq, Debug, Zeroize)]
pub struct Extra(Vec<ExtraField>);
pub struct Extra(pub(crate) Vec<ExtraField>);
impl Extra {
pub fn keys(&self) -> Option<(Vec<EdwardsPoint>, Option<Vec<EdwardsPoint>>)> {
let mut keys = vec![];
@@ -204,7 +241,7 @@ impl Extra {
buf
}
pub fn read<R: Read>(r: &mut R) -> io::Result<Extra> {
pub fn read<R: BufRead>(r: &mut R) -> io::Result<Extra> {
let mut res = Extra(vec![]);
let mut field;
while {