mirror of
https://github.com/serai-dex/serai.git
synced 2024-12-23 03:59:22 +00:00
Convert the FeaturedAddress tuple to a struct
Not only did we already have multiple booleans in it, yet it theoretically could expand in the future. Not only is this more explicit, it actually cleans some existing code.
This commit is contained in:
parent
7b0b8a20ec
commit
4be3290e40
5 changed files with 93 additions and 33 deletions
|
@ -83,13 +83,14 @@ fn featured() {
|
||||||
|
|
||||||
let subaddress = (features & SUBADDRESS_FEATURE_BIT) == SUBADDRESS_FEATURE_BIT;
|
let subaddress = (features & SUBADDRESS_FEATURE_BIT) == SUBADDRESS_FEATURE_BIT;
|
||||||
|
|
||||||
let mut id = [0; 8];
|
let mut payment_id = [0; 8];
|
||||||
OsRng.fill_bytes(&mut id);
|
OsRng.fill_bytes(&mut payment_id);
|
||||||
let id = Some(id).filter(|_| (features & INTEGRATED_FEATURE_BIT) == INTEGRATED_FEATURE_BIT);
|
let payment_id = Some(payment_id)
|
||||||
|
.filter(|_| (features & INTEGRATED_FEATURE_BIT) == INTEGRATED_FEATURE_BIT);
|
||||||
|
|
||||||
let guaranteed = (features & GUARANTEED_FEATURE_BIT) == GUARANTEED_FEATURE_BIT;
|
let guaranteed = (features & GUARANTEED_FEATURE_BIT) == GUARANTEED_FEATURE_BIT;
|
||||||
|
|
||||||
let kind = AddressType::Featured(subaddress, id, guaranteed);
|
let kind = AddressType::Featured { subaddress, payment_id, guaranteed };
|
||||||
let meta = AddressMeta::new(network, kind);
|
let meta = AddressMeta::new(network, kind);
|
||||||
let addr = MoneroAddress::new(meta, spend, view);
|
let addr = MoneroAddress::new(meta, spend, view);
|
||||||
|
|
||||||
|
@ -100,7 +101,7 @@ fn featured() {
|
||||||
assert_eq!(addr.view, view);
|
assert_eq!(addr.view, view);
|
||||||
|
|
||||||
assert_eq!(addr.subaddress(), subaddress);
|
assert_eq!(addr.subaddress(), subaddress);
|
||||||
assert_eq!(addr.payment_id(), id);
|
assert_eq!(addr.payment_id(), payment_id);
|
||||||
assert_eq!(addr.guaranteed(), guaranteed);
|
assert_eq!(addr.guaranteed(), guaranteed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,7 +160,11 @@ fn featured_vectors() {
|
||||||
MoneroAddress::new(
|
MoneroAddress::new(
|
||||||
AddressMeta::new(
|
AddressMeta::new(
|
||||||
network,
|
network,
|
||||||
AddressType::Featured(vector.subaddress, vector.payment_id, vector.guaranteed)
|
AddressType::Featured {
|
||||||
|
subaddress: vector.subaddress,
|
||||||
|
payment_id: vector.payment_id,
|
||||||
|
guaranteed: vector.guaranteed
|
||||||
|
}
|
||||||
),
|
),
|
||||||
spend,
|
spend,
|
||||||
view
|
view
|
||||||
|
|
|
@ -24,7 +24,7 @@ pub enum AddressType {
|
||||||
Standard,
|
Standard,
|
||||||
Integrated([u8; 8]),
|
Integrated([u8; 8]),
|
||||||
Subaddress,
|
Subaddress,
|
||||||
Featured(bool, Option<[u8; 8]>, bool),
|
Featured { subaddress: bool, payment_id: Option<[u8; 8]>, guaranteed: bool },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Zeroize)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Zeroize)]
|
||||||
|
@ -56,26 +56,27 @@ pub enum AddressSpec {
|
||||||
Standard,
|
Standard,
|
||||||
Integrated([u8; 8]),
|
Integrated([u8; 8]),
|
||||||
Subaddress(SubaddressIndex),
|
Subaddress(SubaddressIndex),
|
||||||
Featured(Option<SubaddressIndex>, Option<[u8; 8]>, bool),
|
Featured { subaddress: Option<SubaddressIndex>, payment_id: Option<[u8; 8]>, guaranteed: bool },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AddressType {
|
impl AddressType {
|
||||||
pub fn subaddress(&self) -> bool {
|
pub fn subaddress(&self) -> bool {
|
||||||
matches!(self, AddressType::Subaddress) || matches!(self, AddressType::Featured(true, ..))
|
matches!(self, AddressType::Subaddress) ||
|
||||||
|
matches!(self, AddressType::Featured { subaddress: true, .. })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn payment_id(&self) -> Option<[u8; 8]> {
|
pub fn payment_id(&self) -> Option<[u8; 8]> {
|
||||||
if let AddressType::Integrated(id) = self {
|
if let AddressType::Integrated(id) = self {
|
||||||
Some(*id)
|
Some(*id)
|
||||||
} else if let AddressType::Featured(_, id, _) = self {
|
} else if let AddressType::Featured { payment_id, .. } = self {
|
||||||
*id
|
*payment_id
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn guaranteed(&self) -> bool {
|
pub fn guaranteed(&self) -> bool {
|
||||||
matches!(self, AddressType::Featured(_, _, true))
|
matches!(self, AddressType::Featured { guaranteed: true, .. })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +138,7 @@ impl<B: AddressBytes> AddressMeta<B> {
|
||||||
AddressType::Standard => bytes.0,
|
AddressType::Standard => bytes.0,
|
||||||
AddressType::Integrated(_) => bytes.1,
|
AddressType::Integrated(_) => bytes.1,
|
||||||
AddressType::Subaddress => bytes.2,
|
AddressType::Subaddress => bytes.2,
|
||||||
AddressType::Featured(..) => bytes.3,
|
AddressType::Featured { .. } => bytes.3,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +147,7 @@ impl<B: AddressBytes> AddressMeta<B> {
|
||||||
AddressMeta { _bytes: PhantomData, network, kind }
|
AddressMeta { _bytes: PhantomData, network, kind }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns an incomplete type in the case of Integrated/Featured addresses
|
// Returns an incomplete instantiation in the case of Integrated/Featured addresses
|
||||||
fn from_byte(byte: u8) -> Result<Self, AddressError> {
|
fn from_byte(byte: u8) -> Result<Self, AddressError> {
|
||||||
let mut meta = None;
|
let mut meta = None;
|
||||||
for network in [Network::Mainnet, Network::Testnet, Network::Stagenet] {
|
for network in [Network::Mainnet, Network::Testnet, Network::Stagenet] {
|
||||||
|
@ -155,7 +156,9 @@ impl<B: AddressBytes> AddressMeta<B> {
|
||||||
_ if byte == standard => Some(AddressType::Standard),
|
_ if byte == standard => Some(AddressType::Standard),
|
||||||
_ if byte == integrated => Some(AddressType::Integrated([0; 8])),
|
_ if byte == integrated => Some(AddressType::Integrated([0; 8])),
|
||||||
_ if byte == subaddress => Some(AddressType::Subaddress),
|
_ if byte == subaddress => Some(AddressType::Subaddress),
|
||||||
_ if byte == featured => Some(AddressType::Featured(false, None, false)),
|
_ if byte == featured => {
|
||||||
|
Some(AddressType::Featured { subaddress: false, payment_id: None, guaranteed: false })
|
||||||
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
} {
|
} {
|
||||||
meta = Some(AddressMeta::new(network, kind));
|
meta = Some(AddressMeta::new(network, kind));
|
||||||
|
@ -200,7 +203,7 @@ impl<B: AddressBytes> ToString for Address<B> {
|
||||||
let mut data = vec![self.meta.to_byte()];
|
let mut data = vec![self.meta.to_byte()];
|
||||||
data.extend(self.spend.compress().to_bytes());
|
data.extend(self.spend.compress().to_bytes());
|
||||||
data.extend(self.view.compress().to_bytes());
|
data.extend(self.view.compress().to_bytes());
|
||||||
if let AddressType::Featured(subaddress, payment_id, guaranteed) = self.meta.kind {
|
if let AddressType::Featured { subaddress, payment_id, guaranteed } = self.meta.kind {
|
||||||
// Technically should be a VarInt, yet we don't have enough features it's needed
|
// Technically should be a VarInt, yet we don't have enough features it's needed
|
||||||
data.push(
|
data.push(
|
||||||
u8::from(subaddress) + (u8::from(payment_id.is_some()) << 1) + (u8::from(guaranteed) << 2),
|
u8::from(subaddress) + (u8::from(payment_id.is_some()) << 1) + (u8::from(guaranteed) << 2),
|
||||||
|
@ -233,7 +236,7 @@ impl<B: AddressBytes> Address<B> {
|
||||||
.ok_or(AddressError::InvalidKey)?;
|
.ok_or(AddressError::InvalidKey)?;
|
||||||
let mut read = 65;
|
let mut read = 65;
|
||||||
|
|
||||||
if matches!(meta.kind, AddressType::Featured(..)) {
|
if matches!(meta.kind, AddressType::Featured { .. }) {
|
||||||
if raw[read] >= (2 << 3) {
|
if raw[read] >= (2 << 3) {
|
||||||
Err(AddressError::UnknownFeatures)?;
|
Err(AddressError::UnknownFeatures)?;
|
||||||
}
|
}
|
||||||
|
@ -242,8 +245,11 @@ impl<B: AddressBytes> Address<B> {
|
||||||
let integrated = ((raw[read] >> 1) & 1) == 1;
|
let integrated = ((raw[read] >> 1) & 1) == 1;
|
||||||
let guaranteed = ((raw[read] >> 2) & 1) == 1;
|
let guaranteed = ((raw[read] >> 2) & 1) == 1;
|
||||||
|
|
||||||
meta.kind =
|
meta.kind = AddressType::Featured {
|
||||||
AddressType::Featured(subaddress, Some([0; 8]).filter(|_| integrated), guaranteed);
|
subaddress,
|
||||||
|
payment_id: Some([0; 8]).filter(|_| integrated),
|
||||||
|
guaranteed,
|
||||||
|
};
|
||||||
read += 1;
|
read += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,7 +264,7 @@ impl<B: AddressBytes> Address<B> {
|
||||||
if let AddressType::Integrated(ref mut id) = meta.kind {
|
if let AddressType::Integrated(ref mut id) = meta.kind {
|
||||||
id.copy_from_slice(&raw[(read - 8) .. read]);
|
id.copy_from_slice(&raw[(read - 8) .. read]);
|
||||||
}
|
}
|
||||||
if let AddressType::Featured(_, Some(ref mut id), _) = meta.kind {
|
if let AddressType::Featured { payment_id: Some(ref mut id), .. } = meta.kind {
|
||||||
id.copy_from_slice(&raw[(read - 8) .. read]);
|
id.copy_from_slice(&raw[(read - 8) .. read]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -140,13 +140,13 @@ impl ViewPair {
|
||||||
(spend, view) = self.subaddress_keys(index);
|
(spend, view) = self.subaddress_keys(index);
|
||||||
AddressMeta::new(network, AddressType::Subaddress)
|
AddressMeta::new(network, AddressType::Subaddress)
|
||||||
}
|
}
|
||||||
AddressSpec::Featured(subaddress, payment_id, guaranteed) => {
|
AddressSpec::Featured { subaddress, payment_id, guaranteed } => {
|
||||||
if let Some(index) = subaddress {
|
if let Some(index) = subaddress {
|
||||||
(spend, view) = self.subaddress_keys(index);
|
(spend, view) = self.subaddress_keys(index);
|
||||||
}
|
}
|
||||||
AddressMeta::new(
|
AddressMeta::new(
|
||||||
network,
|
network,
|
||||||
AddressType::Featured(subaddress.is_some(), payment_id, guaranteed),
|
AddressType::Featured { subaddress: subaddress.is_some(), payment_id, guaranteed },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -68,8 +68,13 @@ test!(
|
||||||
|_, mut builder: Builder, _| async move {
|
|_, mut builder: Builder, _| async move {
|
||||||
let view = runner::random_address().1;
|
let view = runner::random_address().1;
|
||||||
let scanner = Scanner::from_view(view.clone(), Some(HashSet::new()));
|
let scanner = Scanner::from_view(view.clone(), Some(HashSet::new()));
|
||||||
builder
|
builder.add_payment(
|
||||||
.add_payment(view.address(Network::Mainnet, AddressSpec::Featured(None, None, false)), 5);
|
view.address(
|
||||||
|
Network::Mainnet,
|
||||||
|
AddressSpec::Featured { subaddress: None, payment_id: None, guaranteed: false },
|
||||||
|
),
|
||||||
|
5,
|
||||||
|
);
|
||||||
(builder.build().unwrap(), scanner)
|
(builder.build().unwrap(), scanner)
|
||||||
},
|
},
|
||||||
|_, tx: Transaction, _, mut state: Scanner| async move {
|
|_, tx: Transaction, _, mut state: Scanner| async move {
|
||||||
|
@ -90,7 +95,14 @@ test!(
|
||||||
scanner.register_subaddress(subaddress);
|
scanner.register_subaddress(subaddress);
|
||||||
|
|
||||||
builder.add_payment(
|
builder.add_payment(
|
||||||
view.address(Network::Mainnet, AddressSpec::Featured(Some(subaddress), None, false)),
|
view.address(
|
||||||
|
Network::Mainnet,
|
||||||
|
AddressSpec::Featured {
|
||||||
|
subaddress: Some(subaddress),
|
||||||
|
payment_id: None,
|
||||||
|
guaranteed: false,
|
||||||
|
},
|
||||||
|
),
|
||||||
5,
|
5,
|
||||||
);
|
);
|
||||||
(builder.build().unwrap(), (scanner, subaddress))
|
(builder.build().unwrap(), (scanner, subaddress))
|
||||||
|
@ -113,7 +125,14 @@ test!(
|
||||||
OsRng.fill_bytes(&mut payment_id);
|
OsRng.fill_bytes(&mut payment_id);
|
||||||
|
|
||||||
builder.add_payment(
|
builder.add_payment(
|
||||||
view.address(Network::Mainnet, AddressSpec::Featured(None, Some(payment_id), false)),
|
view.address(
|
||||||
|
Network::Mainnet,
|
||||||
|
AddressSpec::Featured {
|
||||||
|
subaddress: None,
|
||||||
|
payment_id: Some(payment_id),
|
||||||
|
guaranteed: false,
|
||||||
|
},
|
||||||
|
),
|
||||||
5,
|
5,
|
||||||
);
|
);
|
||||||
(builder.build().unwrap(), (scanner, payment_id))
|
(builder.build().unwrap(), (scanner, payment_id))
|
||||||
|
@ -142,7 +161,11 @@ test!(
|
||||||
builder.add_payment(
|
builder.add_payment(
|
||||||
view.address(
|
view.address(
|
||||||
Network::Mainnet,
|
Network::Mainnet,
|
||||||
AddressSpec::Featured(Some(subaddress), Some(payment_id), false),
|
AddressSpec::Featured {
|
||||||
|
subaddress: Some(subaddress),
|
||||||
|
payment_id: Some(payment_id),
|
||||||
|
guaranteed: false,
|
||||||
|
},
|
||||||
),
|
),
|
||||||
5,
|
5,
|
||||||
);
|
);
|
||||||
|
@ -164,8 +187,13 @@ test!(
|
||||||
let view = runner::random_address().1;
|
let view = runner::random_address().1;
|
||||||
let scanner = Scanner::from_view(view.clone(), None);
|
let scanner = Scanner::from_view(view.clone(), None);
|
||||||
|
|
||||||
builder
|
builder.add_payment(
|
||||||
.add_payment(view.address(Network::Mainnet, AddressSpec::Featured(None, None, true)), 5);
|
view.address(
|
||||||
|
Network::Mainnet,
|
||||||
|
AddressSpec::Featured { subaddress: None, payment_id: None, guaranteed: true },
|
||||||
|
),
|
||||||
|
5,
|
||||||
|
);
|
||||||
(builder.build().unwrap(), scanner)
|
(builder.build().unwrap(), scanner)
|
||||||
},
|
},
|
||||||
|_, tx: Transaction, _, mut state: Scanner| async move {
|
|_, tx: Transaction, _, mut state: Scanner| async move {
|
||||||
|
@ -186,7 +214,14 @@ test!(
|
||||||
scanner.register_subaddress(subaddress);
|
scanner.register_subaddress(subaddress);
|
||||||
|
|
||||||
builder.add_payment(
|
builder.add_payment(
|
||||||
view.address(Network::Mainnet, AddressSpec::Featured(Some(subaddress), None, true)),
|
view.address(
|
||||||
|
Network::Mainnet,
|
||||||
|
AddressSpec::Featured {
|
||||||
|
subaddress: Some(subaddress),
|
||||||
|
payment_id: None,
|
||||||
|
guaranteed: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
5,
|
5,
|
||||||
);
|
);
|
||||||
(builder.build().unwrap(), (scanner, subaddress))
|
(builder.build().unwrap(), (scanner, subaddress))
|
||||||
|
@ -209,7 +244,14 @@ test!(
|
||||||
OsRng.fill_bytes(&mut payment_id);
|
OsRng.fill_bytes(&mut payment_id);
|
||||||
|
|
||||||
builder.add_payment(
|
builder.add_payment(
|
||||||
view.address(Network::Mainnet, AddressSpec::Featured(None, Some(payment_id), true)),
|
view.address(
|
||||||
|
Network::Mainnet,
|
||||||
|
AddressSpec::Featured {
|
||||||
|
subaddress: None,
|
||||||
|
payment_id: Some(payment_id),
|
||||||
|
guaranteed: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
5,
|
5,
|
||||||
);
|
);
|
||||||
(builder.build().unwrap(), (scanner, payment_id))
|
(builder.build().unwrap(), (scanner, payment_id))
|
||||||
|
@ -238,7 +280,11 @@ test!(
|
||||||
builder.add_payment(
|
builder.add_payment(
|
||||||
view.address(
|
view.address(
|
||||||
Network::Mainnet,
|
Network::Mainnet,
|
||||||
AddressSpec::Featured(Some(subaddress), Some(payment_id), true),
|
AddressSpec::Featured {
|
||||||
|
subaddress: Some(subaddress),
|
||||||
|
payment_id: Some(payment_id),
|
||||||
|
guaranteed: true,
|
||||||
|
},
|
||||||
),
|
),
|
||||||
5,
|
5,
|
||||||
);
|
);
|
||||||
|
|
|
@ -106,7 +106,10 @@ impl Monero {
|
||||||
spend: dfg::EdwardsPoint,
|
spend: dfg::EdwardsPoint,
|
||||||
subaddress: Option<SubaddressIndex>,
|
subaddress: Option<SubaddressIndex>,
|
||||||
) -> MoneroAddress {
|
) -> MoneroAddress {
|
||||||
self.view_pair(spend).address(Network::Mainnet, AddressSpec::Featured(subaddress, None, true))
|
self.view_pair(spend).address(
|
||||||
|
Network::Mainnet,
|
||||||
|
AddressSpec::Featured { subaddress, payment_id: None, guaranteed: true },
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scanner(&self, spend: dfg::EdwardsPoint) -> Scanner {
|
fn scanner(&self, spend: dfg::EdwardsPoint) -> Scanner {
|
||||||
|
|
Loading…
Reference in a new issue