Diversify ViewPair/Scanner into ViewPair/GuaranteedViewPair and Scanner/GuaranteedScanner

Also cleans the Scanner impl.
This commit is contained in:
Luke Parker
2024-07-03 13:35:19 -04:00
parent 64e74c52ec
commit daa0f8f7d5
32 changed files with 1458 additions and 1233 deletions

View File

@@ -47,7 +47,7 @@ impl BlockHeader {
w.write_all(&self.nonce.to_le_bytes())
}
/// Serialize the BlockHeader to a Vec<u8>.
/// Serialize the BlockHeader to a `Vec<u8>`.
pub fn serialize(&self) -> Vec<u8> {
let mut serialized = vec![];
self.write(&mut serialized).unwrap();
@@ -72,9 +72,9 @@ pub struct Block {
/// The block's header.
pub header: BlockHeader,
/// The miner's transaction.
pub miner_tx: Transaction,
pub miner_transaction: Transaction,
/// The transactions within this block.
pub txs: Vec<[u8; 32]>,
pub transactions: Vec<[u8; 32]>,
}
impl Block {
@@ -83,7 +83,7 @@ impl Block {
/// This information comes from the Block's miner transaction. If the miner transaction isn't
/// structed as expected, this will return None.
pub fn number(&self) -> Option<u64> {
match &self.miner_tx {
match &self.miner_transaction {
Transaction::V1 { prefix, .. } | Transaction::V2 { prefix, .. } => {
match prefix.inputs.first() {
Some(Input::Gen(number)) => Some(*number),
@@ -96,15 +96,15 @@ impl Block {
/// Write the Block.
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
self.header.write(w)?;
self.miner_tx.write(w)?;
write_varint(&self.txs.len(), w)?;
for tx in &self.txs {
self.miner_transaction.write(w)?;
write_varint(&self.transactions.len(), w)?;
for tx in &self.transactions {
w.write_all(tx)?;
}
Ok(())
}
/// Serialize the Block to a Vec<u8>.
/// Serialize the Block to a `Vec<u8>`.
pub fn serialize(&self) -> Vec<u8> {
let mut serialized = vec![];
self.write(&mut serialized).unwrap();
@@ -117,8 +117,8 @@ impl Block {
/// use the [`Block::hash`] function.
pub fn serialize_pow_hash(&self) -> Vec<u8> {
let mut blob = self.header.serialize();
blob.extend_from_slice(&merkle_root(self.miner_tx.hash(), &self.txs));
write_varint(&(1 + u64::try_from(self.txs.len()).unwrap()), &mut blob).unwrap();
blob.extend_from_slice(&merkle_root(self.miner_transaction.hash(), &self.transactions));
write_varint(&(1 + u64::try_from(self.transactions.len()).unwrap()), &mut blob).unwrap();
blob
}
@@ -142,8 +142,10 @@ impl Block {
pub fn read<R: Read>(r: &mut R) -> io::Result<Block> {
Ok(Block {
header: BlockHeader::read(r)?,
miner_tx: Transaction::read(r)?,
txs: (0_usize .. read_varint(r)?).map(|_| read_bytes(r)).collect::<Result<_, _>>()?,
miner_transaction: Transaction::read(r)?,
transactions: (0_usize .. read_varint(r)?)
.map(|_| read_bytes(r))
.collect::<Result<_, _>>()?,
})
}
}

View File

@@ -322,7 +322,7 @@ impl RctPrunable {
}
}
/// Serialize the RctPrunable to a Vec<u8>.
/// Serialize the RctPrunable to a `Vec<u8>`.
pub fn serialize(&self, rct_type: RctType) -> Vec<u8> {
let mut serialized = vec![];
self.write(&mut serialized, rct_type).unwrap();
@@ -437,7 +437,7 @@ impl RctProofs {
self.prunable.write(w, rct_type)
}
/// Serialize the RctProofs to a Vec<u8>.
/// Serialize the RctProofs to a `Vec<u8>`.
pub fn serialize(&self) -> Vec<u8> {
let mut serialized = vec![];
self.write(&mut serialized).unwrap();

View File

@@ -49,7 +49,7 @@ impl Input {
}
}
/// Serialize the Input to a Vec<u8>.
/// Serialize the Input to a `Vec<u8>`.
pub fn serialize(&self) -> Vec<u8> {
let mut res = vec![];
self.write(&mut res).unwrap();
@@ -102,7 +102,7 @@ impl Output {
Ok(())
}
/// Write the Output to a Vec<u8>.
/// Write the Output to a `Vec<u8>`.
pub fn serialize(&self) -> Vec<u8> {
let mut res = Vec::with_capacity(8 + 1 + 32);
self.write(&mut res).unwrap();
@@ -150,27 +150,33 @@ pub enum Timelock {
}
impl Timelock {
fn from_raw(raw: u64) -> Timelock {
if raw == 0 {
Timelock::None
} else if raw < 500_000_000 {
// TODO: This is trivial to have panic
Timelock::Block(usize::try_from(raw).unwrap())
} else {
Timelock::Time(raw)
/// Write the Timelock.
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
match self {
Timelock::None => write_varint(&0u8, w),
Timelock::Block(block) => write_varint(block, w),
Timelock::Time(time) => write_varint(time, w),
}
}
fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
write_varint(
&match self {
Timelock::None => 0,
// TODO: Check this unwrap
Timelock::Block(block) => (*block).try_into().unwrap(),
Timelock::Time(time) => *time,
},
w,
)
/// Serialize the Timelock to a `Vec<u8>`.
pub fn serialize(&self) -> Vec<u8> {
let mut res = Vec::with_capacity(1);
self.write(&mut res).unwrap();
res
}
/// Read a Timelock.
pub fn read<R: Read>(r: &mut R) -> io::Result<Self> {
let raw = read_varint::<_, u64>(r)?;
Ok(if raw == 0 {
Timelock::None
} else if raw < u64::from(500_000_000u32) {
// TODO: const-assert 32 or 64 bits
Timelock::Block(usize::try_from(raw).expect("timelock (<32 bits) overflowed usize"))
} else {
Timelock::Time(raw)
})
}
}
@@ -194,6 +200,7 @@ impl PartialOrd for Timelock {
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct TransactionPrefix {
/// The timelock this transaction uses.
// TODO: Rename to additional timelock?
pub timelock: Timelock,
/// The inputs for this transaction.
pub inputs: Vec<Input>,
@@ -223,7 +230,7 @@ impl TransactionPrefix {
/// This is distinct from Monero in that it won't read the version. The version must be passed
/// in.
pub fn read<R: Read>(r: &mut R, version: u64) -> io::Result<TransactionPrefix> {
let timelock = Timelock::from_raw(read_varint(r)?);
let timelock = Timelock::read(r)?;
let inputs = read_vec(|r| Input::read(r), r)?;
if inputs.is_empty() {
@@ -316,7 +323,7 @@ impl Transaction {
Ok(())
}
/// Write the Transaction to a Vec<u8>.
/// Write the Transaction to a `Vec<u8>`.
pub fn serialize(&self) -> Vec<u8> {
let mut res = Vec::with_capacity(2048);
self.write(&mut res).unwrap();