add new address functions & comments

This commit is contained in:
akildemir 2022-12-15 13:56:13 +03:00
parent 461504ccbf
commit 5123c7f121
2 changed files with 79 additions and 19 deletions

View file

@ -182,6 +182,14 @@ impl<B: AddressBytes> ToString for Address<B> {
}
impl<B: AddressBytes> Address<B> {
/// Generates an Address type according to the specification provided in the meta.
///
/// WARNING: Specification on the meta are not "commands" and are
/// just "specifications" for the address. This function relies on the
/// caller to make sure all the passed parameters makes sense and assumes
/// specifications provided in the meta are correct and applicable for the passed in keys.
/// For example, passing `AddressType::Subaddress` type in the meta wont generate
/// a correct subaddress if the keys aren't already for a valid subaddress.
pub fn new(meta: AddressMeta<B>, spend: EdwardsPoint, view: EdwardsPoint) -> Self {
Address { meta, spend, view }
}

View file

@ -29,6 +29,8 @@ pub use send::{Fee, TransactionError, SignableTransaction, SignableTransactionBu
#[cfg(feature = "multisig")]
pub use send::TransactionMachine;
use self::address::MoneroAddressBytes;
fn key_image_sort(x: &EdwardsPoint, y: &EdwardsPoint) -> std::cmp::Ordering {
x.compress().to_bytes().cmp(&y.compress().to_bytes()).reverse()
}
@ -121,12 +123,19 @@ impl ViewPair {
.concat(),
))
}
/// returns the MoneroAddress type according to specifications in the meta
pub fn address(&self, meta: AddressMeta<MoneroAddressBytes>) -> MoneroAddress {
MoneroAddress::new(meta, self.spend, self.view.deref() * &ED25519_BASEPOINT_TABLE)
}
}
/// Transaction scanner.
/// This scanner is capable of generating subaddresses, additionally scanning for them once they've
/// been explicitly generated. If the burning bug is attempted, any secondary outputs will be
/// ignored.
/// - This scanner is capable of generating subaddresses, additionally scanning for
/// them once they've been explicitly generated by using `subaddress()` member function.
/// It wont be able to track the outputs for subaddresses that aren't generated this way.
/// - If the burning bug is attempted, any secondary outputs will be ignored.
/// or standard address type if none passed.
#[derive(Clone)]
pub struct Scanner {
pair: ViewPair,
@ -167,8 +176,13 @@ impl Scanner {
/// burning_bug is a HashSet of used keys, intended to prevent key reuse which would burn funds.
/// When an output is successfully scanned, the output key MUST be saved to disk.
/// When a new scanner is created, ALL saved output keys must be passed in to be secure.
/// If None is passed, a modified shared key derivation is used which is immune to the burning
/// bug (specifically the Guaranteed feature from Featured Addresses).
/// If None is passed, a modified shared key derivation is used to generate new addresses
/// through this scanner which is immune to the burning bug (specifically
/// the Guaranteed feature from Featured Addresses).
///
/// If you want to use guaranteed feature for both generating addresses and
/// decoding outputs with such addresses pass `None` to the `burning_bug`. if you
/// just wanna support standard monero addresses then pass `Some`.
// TODO: Should this take in a DB access handle to ensure output keys are saved?
pub fn from_view(
pair: ViewPair,
@ -180,23 +194,33 @@ impl Scanner {
Scanner { pair, network, subaddresses, burning_bug }
}
/// Return the main address for this view pair.
/// Returns the main address for this view pair.
pub fn address(&self) -> MoneroAddress {
MoneroAddress::new(
AddressMeta::new(
self.network,
if self.burning_bug.is_none() {
AddressType::Featured(false, None, true)
} else {
AddressType::Standard
},
),
self.pair.spend,
self.pair.view.deref() * &ED25519_BASEPOINT_TABLE,
)
let meta = AddressMeta::new(
self.network,
if self.burning_bug.is_none() {
AddressType::Featured(false, None, true)
} else {
AddressType::Standard
},
);
self.pair.address(meta)
}
/// Return the specified subaddress for this view pair.
/// Returns the integrated address for a given payment id.
pub fn integrated_address(&self, payment_id: [u8; 8]) -> MoneroAddress {
let meta = AddressMeta::new(
self.network,
if self.burning_bug.is_none() {
AddressType::Featured(false, Some(payment_id), true)
} else {
AddressType::Integrated(payment_id)
},
);
self.pair.address(meta)
}
/// Returns the specified subaddress for this view pair.
pub fn subaddress(&mut self, index: (u32, u32)) -> MoneroAddress {
if index == (0, 0) {
return self.address();
@ -218,4 +242,32 @@ impl Scanner {
self.pair.view.deref() * spend,
)
}
/// Returns a featured address.
///
/// if you created the scanner with `Some` value for `burning_bug` be aware that
/// even though you can pass `true` for the `guaranteed` parameter and generate
/// a guaranteed address, scanner wont be able decode incoming outputs for this address.
/// If you want to support guaranteed addresses please create a scanner with `None` value to
/// `burning_bug`. Reverse of the case also holds.
pub fn featured_address(
&mut self,
index: Option<(u32, u32)>,
payment_id: Option<[u8; 8]>,
guaranteed: bool,
) -> MoneroAddress {
let subaddress = index.is_some() && (index.unwrap() != (0, 0));
let mut spend = self.pair.spend;
let mut view: EdwardsPoint = self.pair.view.deref() * &ED25519_BASEPOINT_TABLE;
if subaddress {
spend = self.pair.spend + (&self.pair.subaddress(index.unwrap()) * &ED25519_BASEPOINT_TABLE);
self.subaddresses.insert(spend.compress(), index.unwrap());
view = self.pair.view.deref() * spend;
}
let meta =
AddressMeta::new(self.network, AddressType::Featured(subaddress, payment_id, guaranteed));
MoneroAddress::new(meta, spend, view)
}
}