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> { 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 { pub fn new(meta: AddressMeta<B>, spend: EdwardsPoint, view: EdwardsPoint) -> Self {
Address { meta, spend, view } Address { meta, spend, view }
} }

View file

@ -29,6 +29,8 @@ pub use send::{Fee, TransactionError, SignableTransaction, SignableTransactionBu
#[cfg(feature = "multisig")] #[cfg(feature = "multisig")]
pub use send::TransactionMachine; pub use send::TransactionMachine;
use self::address::MoneroAddressBytes;
fn key_image_sort(x: &EdwardsPoint, y: &EdwardsPoint) -> std::cmp::Ordering { fn key_image_sort(x: &EdwardsPoint, y: &EdwardsPoint) -> std::cmp::Ordering {
x.compress().to_bytes().cmp(&y.compress().to_bytes()).reverse() x.compress().to_bytes().cmp(&y.compress().to_bytes()).reverse()
} }
@ -121,12 +123,19 @@ impl ViewPair {
.concat(), .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. /// Transaction scanner.
/// This scanner is capable of generating subaddresses, additionally scanning for them once they've /// - This scanner is capable of generating subaddresses, additionally scanning for
/// been explicitly generated. If the burning bug is attempted, any secondary outputs will be /// them once they've been explicitly generated by using `subaddress()` member function.
/// ignored. /// 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)] #[derive(Clone)]
pub struct Scanner { pub struct Scanner {
pair: ViewPair, 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. /// 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 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. /// 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 /// If None is passed, a modified shared key derivation is used to generate new addresses
/// bug (specifically the Guaranteed feature from Featured 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? // TODO: Should this take in a DB access handle to ensure output keys are saved?
pub fn from_view( pub fn from_view(
pair: ViewPair, pair: ViewPair,
@ -180,23 +194,33 @@ impl Scanner {
Scanner { pair, network, subaddresses, burning_bug } 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 { pub fn address(&self) -> MoneroAddress {
MoneroAddress::new( let meta = AddressMeta::new(
AddressMeta::new(
self.network, self.network,
if self.burning_bug.is_none() { if self.burning_bug.is_none() {
AddressType::Featured(false, None, true) AddressType::Featured(false, None, true)
} else { } else {
AddressType::Standard AddressType::Standard
}, },
), );
self.pair.spend, self.pair.address(meta)
self.pair.view.deref() * &ED25519_BASEPOINT_TABLE,
)
} }
/// 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 { pub fn subaddress(&mut self, index: (u32, u32)) -> MoneroAddress {
if index == (0, 0) { if index == (0, 0) {
return self.address(); return self.address();
@ -218,4 +242,32 @@ impl Scanner {
self.pair.view.deref() * spend, 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)
}
} }