Luke Parker 2022-08-22 08:57:36 -04:00
parent 5751204a98
commit 5a1f011db8
No known key found for this signature in database
GPG key ID: F9F1386DB1E119B6
4 changed files with 38 additions and 14 deletions

View file

@ -1,4 +1,4 @@
use std::collections::HashMap;
use std::collections::{HashSet, HashMap};
use zeroize::{Zeroize, ZeroizeOnDrop};
@ -124,19 +124,25 @@ impl ViewPair {
pub struct Scanner {
pair: ViewPair,
network: Network,
guaranteed: bool,
pub(crate) subaddresses: HashMap<CompressedEdwardsY, (u32, u32)>,
pub(crate) burning_bug: Option<HashSet<CompressedEdwardsY>>,
}
impl Zeroize for Scanner {
fn zeroize(&mut self) {
self.pair.zeroize();
self.network.zeroize();
self.guaranteed.zeroize();
// These may not be effective, unfortunately
for (mut key, mut value) in self.subaddresses.drain() {
key.zeroize();
value.zeroize();
}
if let Some(ref mut burning_bug) = self.burning_bug.take() {
for mut output in burning_bug.drain() {
output.zeroize();
}
}
}
}
@ -149,17 +155,23 @@ impl Drop for Scanner {
impl ZeroizeOnDrop for Scanner {}
impl Scanner {
pub fn from_view(pair: ViewPair, network: Network, guaranteed: bool) -> Scanner {
// For burning bug immune addresses (Featured Address w/ the Guaranteed feature), pass None
// For traditional Monero address, provide a HashSet of all historically scanned output keys
pub fn from_view(
pair: ViewPair,
network: Network,
burning_bug: Option<HashSet<CompressedEdwardsY>>,
) -> Scanner {
let mut subaddresses = HashMap::new();
subaddresses.insert(pair.spend.compress(), (0, 0));
Scanner { pair, network, guaranteed, subaddresses }
Scanner { pair, network, subaddresses, burning_bug }
}
pub fn address(&self) -> Address {
Address::new(
AddressMeta {
network: self.network,
kind: if self.guaranteed {
kind: if self.burning_bug.is_none() {
AddressType::Featured(false, None, true)
} else {
AddressType::Standard
@ -181,7 +193,7 @@ impl Scanner {
Address::new(
AddressMeta {
network: self.network,
kind: if self.guaranteed {
kind: if self.burning_bug.is_none() {
AddressType::Featured(true, None, true)
} else {
AddressType::Subaddress

View file

@ -95,7 +95,7 @@ impl SpendableOutput {
}
impl Scanner {
pub fn scan(&self, tx: &Transaction) -> Timelocked {
pub fn scan(&mut self, tx: &Transaction) -> Timelocked {
let extra = Extra::deserialize(&mut Cursor::new(&tx.prefix.extra));
let keys;
let extra = if let Ok(extra) = extra {
@ -108,9 +108,17 @@ impl Scanner {
let mut res = vec![];
for (o, output) in tx.prefix.outputs.iter().enumerate() {
// https://github.com/serai-dex/serai/issues/102
let output_key_compressed = output.key.compress();
if let Some(burning_bug) = self.burning_bug.as_ref() {
if burning_bug.contains(&output_key_compressed) {
continue;
}
}
for key in &keys {
let (view_tag, key_offset, payment_id_xor) = shared_key(
if self.guaranteed { Some(uniqueness(&tx.prefix.inputs)) } else { None },
if self.burning_bug.is_none() { Some(uniqueness(&tx.prefix.inputs)) } else { None },
&self.pair.view,
key,
o,
@ -173,6 +181,10 @@ impl Scanner {
subaddress: (0, 0),
payment_id,
});
if let Some(burning_bug) = self.burning_bug.as_mut() {
burning_bug.insert(output_key_compressed);
}
}
// Break to prevent public keys from being included multiple times, triggering multiple
// inclusions of the same output

View file

@ -1,4 +1,4 @@
use std::sync::Mutex;
use std::{sync::Mutex, collections::HashSet};
#[cfg(feature = "multisig")]
use std::collections::HashMap;
@ -75,7 +75,7 @@ async fn send_core(test: usize, multisig: bool) {
}
let view_pair = ViewPair::new(spend_pub, view);
let scanner = Scanner::from_view(view_pair, Network::Mainnet, false);
let mut scanner = Scanner::from_view(view_pair, Network::Mainnet, Some(HashSet::new()));
let addr = scanner.address();
let fee = rpc.get_fee().await.unwrap();

View file

@ -72,7 +72,7 @@ impl Monero {
}
fn scanner(&self, spend: dfg::EdwardsPoint) -> Scanner {
Scanner::from_view(ViewPair::new(spend.0, self.view), Network::Mainnet, true)
Scanner::from_view(ViewPair::new(spend.0, self.view), Network::Mainnet, None)
}
#[cfg(test)]
@ -81,7 +81,7 @@ impl Monero {
Scanner::from_view(
ViewPair::new(*dfg::EdwardsPoint::generator(), Scalar::one()),
Network::Mainnet,
false,
Some(std::collections::HashSet::new()),
)
}
@ -129,7 +129,7 @@ impl Coin for Monero {
}
async fn get_outputs(&self, block: &Self::Block, key: dfg::EdwardsPoint) -> Vec<Self::Output> {
let scanner = self.scanner(key);
let mut scanner = self.scanner(key);
block.iter().flat_map(|tx| scanner.scan(tx).not_locked()).map(Output::from).collect()
}