mirror of
https://github.com/serai-dex/serai.git
synced 2024-11-17 01:17:36 +00:00
update address public API design
This commit is contained in:
parent
d9fa88fa76
commit
3a319b229f
6 changed files with 97 additions and 101 deletions
|
@ -80,6 +80,15 @@ impl<B: AddressBytes> Zeroize for AddressMeta<B> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Specifies Address Properties
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Zeroize)]
|
||||||
|
pub enum AddressSpec {
|
||||||
|
Standard,
|
||||||
|
Integrated([u8; 8]),
|
||||||
|
Subaddress(u32, u32),
|
||||||
|
Featured(Option<(u32, u32)>, Option<[u8; 8]>, bool),
|
||||||
|
}
|
||||||
|
|
||||||
/// Error when decoding an address.
|
/// Error when decoding an address.
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Error)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Error)]
|
||||||
pub enum AddressError {
|
pub enum AddressError {
|
||||||
|
|
|
@ -16,7 +16,7 @@ pub(crate) use extra::{PaymentId, ExtraField, Extra};
|
||||||
|
|
||||||
/// Address encoding and decoding functionality.
|
/// Address encoding and decoding functionality.
|
||||||
pub mod address;
|
pub mod address;
|
||||||
use address::{Network, AddressType, AddressMeta, MoneroAddress};
|
use address::{Network, AddressType, AddressMeta, MoneroAddress, AddressSpec};
|
||||||
|
|
||||||
mod scan;
|
mod scan;
|
||||||
pub use scan::{ReceivedOutput, SpendableOutput};
|
pub use scan::{ReceivedOutput, SpendableOutput};
|
||||||
|
@ -29,8 +29,6 @@ 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()
|
||||||
}
|
}
|
||||||
|
@ -108,7 +106,7 @@ impl ViewPair {
|
||||||
ViewPair { spend, view }
|
ViewPair { spend, view }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn subaddress(&self, index: (u32, u32)) -> Scalar {
|
fn subaddress_keys(&self, index: (u32, u32)) -> Scalar {
|
||||||
if index == (0, 0) {
|
if index == (0, 0) {
|
||||||
return Scalar::zero();
|
return Scalar::zero();
|
||||||
}
|
}
|
||||||
|
@ -124,9 +122,45 @@ impl ViewPair {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an address with the provided metadata.
|
fn subaddress_derivation(&self, index: (u32, u32)) -> (EdwardsPoint, EdwardsPoint) {
|
||||||
pub fn address(&self, meta: AddressMeta<MoneroAddressBytes>) -> MoneroAddress {
|
let scalar = self.subaddress_keys(index);
|
||||||
MoneroAddress::new(meta, self.spend, self.view.deref() * &ED25519_BASEPOINT_TABLE)
|
let spend = self.spend + (&scalar * &ED25519_BASEPOINT_TABLE);
|
||||||
|
let view = self.view.deref() * spend;
|
||||||
|
(spend, view)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns an address with the provided specification.
|
||||||
|
pub fn address(&self, network: Network, spec: AddressSpec) -> MoneroAddress {
|
||||||
|
let mut spend = self.spend;
|
||||||
|
let mut view: EdwardsPoint = self.view.deref() * &ED25519_BASEPOINT_TABLE;
|
||||||
|
|
||||||
|
// construct the address meta
|
||||||
|
let meta = match spec {
|
||||||
|
AddressSpec::Standard => AddressMeta::new(network, AddressType::Standard),
|
||||||
|
AddressSpec::Integrated(payment_id) => {
|
||||||
|
AddressMeta::new(network, AddressType::Integrated(payment_id))
|
||||||
|
}
|
||||||
|
AddressSpec::Subaddress(i1, i2) => {
|
||||||
|
if i1 == 0 && i2 == 0 {
|
||||||
|
AddressMeta::new(network, AddressType::Standard)
|
||||||
|
} else {
|
||||||
|
(spend, view) = self.subaddress_derivation((i1, i2));
|
||||||
|
AddressMeta::new(network, AddressType::Subaddress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AddressSpec::Featured(subaddress, payment_id, guaranteed) => {
|
||||||
|
let mut is_subaddress = false;
|
||||||
|
if let Some(index) = subaddress {
|
||||||
|
if index != (0, 0) {
|
||||||
|
(spend, view) = self.subaddress_derivation(index);
|
||||||
|
is_subaddress = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AddressMeta::new(network, AddressType::Featured(is_subaddress, payment_id, guaranteed))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MoneroAddress::new(meta, spend, view)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,80 +221,22 @@ impl Scanner {
|
||||||
Scanner { pair, network, subaddresses, burning_bug }
|
Scanner { pair, network, subaddresses, burning_bug }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the main address for this view pair.
|
/// Returns the specified address.
|
||||||
pub fn address(&self) -> MoneroAddress {
|
|
||||||
let meta = AddressMeta::new(
|
|
||||||
self.network,
|
|
||||||
if self.burning_bug.is_none() {
|
|
||||||
AddressType::Featured(false, None, true)
|
|
||||||
} else {
|
|
||||||
AddressType::Standard
|
|
||||||
},
|
|
||||||
);
|
|
||||||
self.pair.address(meta)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
let spend = self.pair.spend + (&self.pair.subaddress(index) * &ED25519_BASEPOINT_TABLE);
|
|
||||||
self.subaddresses.insert(spend.compress(), index);
|
|
||||||
|
|
||||||
MoneroAddress::new(
|
|
||||||
AddressMeta::new(
|
|
||||||
self.network,
|
|
||||||
if self.burning_bug.is_none() {
|
|
||||||
AddressType::Featured(true, None, true)
|
|
||||||
} else {
|
|
||||||
AddressType::Subaddress
|
|
||||||
},
|
|
||||||
),
|
|
||||||
spend,
|
|
||||||
self.pair.view.deref() * spend,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a featured address.
|
|
||||||
///
|
///
|
||||||
/// A `Scanner` will fail to scan this address unless it is appropriate to the `Scanner`.
|
/// A `Scanner` will fail to scan this address unless it is appropriate to the `Scanner`.
|
||||||
/// If the `Scanner` was defined as not handling the burning bug, by passing `None` for
|
/// If the `Scanner` was defined as not handling the burning bug, by passing `None` for
|
||||||
/// `burning_bug` upon construction, this must be a guaranteed address
|
/// `burning_bug` upon construction, this must be a guaranteed address
|
||||||
/// in order to be scanned by it.
|
/// in order to be scanned by it.
|
||||||
pub fn featured_address(
|
pub fn address(&mut self, spec: AddressSpec) -> MoneroAddress {
|
||||||
&mut self,
|
let addr = self.pair.address(self.network, spec);
|
||||||
subaddress: Option<(u32, u32)>,
|
|
||||||
payment_id: Option<[u8; 8]>,
|
|
||||||
guaranteed: bool,
|
|
||||||
) -> MoneroAddress {
|
|
||||||
let is_subaddress = subaddress.is_some() && (subaddress.unwrap() != (0, 0));
|
|
||||||
|
|
||||||
let mut spend = self.pair.spend;
|
let mut index = (0, 0);
|
||||||
let mut view: EdwardsPoint = self.pair.view.deref() * &ED25519_BASEPOINT_TABLE;
|
if let AddressSpec::Subaddress(i1, i2) = spec {
|
||||||
if is_subaddress {
|
index = (i1, i2);
|
||||||
spend =
|
} else if let AddressSpec::Featured(Some(index_inner), _, _) = spec {
|
||||||
self.pair.spend + (&self.pair.subaddress(subaddress.unwrap()) * &ED25519_BASEPOINT_TABLE);
|
index = index_inner;
|
||||||
self.subaddresses.insert(spend.compress(), subaddress.unwrap());
|
|
||||||
view = self.pair.view.deref() * spend;
|
|
||||||
}
|
}
|
||||||
|
self.subaddresses.insert(addr.spend.compress(), index);
|
||||||
let meta =
|
addr
|
||||||
AddressMeta::new(self.network, AddressType::Featured(is_subaddress, payment_id, guaranteed));
|
|
||||||
MoneroAddress::new(meta, spend, view)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -293,7 +293,7 @@ impl Scanner {
|
||||||
// If we did though, it'd enable bypassing the included burning bug protection
|
// If we did though, it'd enable bypassing the included burning bug protection
|
||||||
debug_assert!(output_key.is_torsion_free());
|
debug_assert!(output_key.is_torsion_free());
|
||||||
|
|
||||||
let key_offset = shared_key + self.pair.subaddress(subaddress);
|
let key_offset = shared_key + self.pair.subaddress_keys(subaddress);
|
||||||
// Since we've found an output to us, get its amount
|
// Since we've found an output to us, get its amount
|
||||||
let mut commitment = Commitment::zero();
|
let mut commitment = Commitment::zero();
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ use monero_serai::{
|
||||||
Protocol, random_scalar,
|
Protocol, random_scalar,
|
||||||
wallet::{
|
wallet::{
|
||||||
ViewPair, Scanner,
|
ViewPair, Scanner,
|
||||||
address::{Network, AddressType, AddressMeta, MoneroAddress},
|
address::{Network, AddressType, AddressMeta, MoneroAddress, AddressSpec},
|
||||||
SpendableOutput,
|
SpendableOutput,
|
||||||
},
|
},
|
||||||
rpc::Rpc,
|
rpc::Rpc,
|
||||||
|
@ -64,7 +64,7 @@ pub async fn get_miner_tx_output(rpc: &Rpc, view: &ViewPair) -> SpendableOutput
|
||||||
|
|
||||||
// mine 60 blocks to unlock a miner tx
|
// mine 60 blocks to unlock a miner tx
|
||||||
let start = rpc.get_height().await.unwrap();
|
let start = rpc.get_height().await.unwrap();
|
||||||
rpc.generate_blocks(&scanner.address().to_string(), 60).await.unwrap();
|
rpc.generate_blocks(&scanner.address(AddressSpec::Standard).to_string(), 60).await.unwrap();
|
||||||
|
|
||||||
let block = rpc.get_block(start).await.unwrap();
|
let block = rpc.get_block(start).await.unwrap();
|
||||||
scanner.scan(rpc, &block).await.unwrap().swap_remove(0).ignore_timelock().swap_remove(0)
|
scanner.scan(rpc, &block).await.unwrap().swap_remove(0).ignore_timelock().swap_remove(0)
|
||||||
|
@ -151,7 +151,7 @@ macro_rules! test {
|
||||||
use monero_serai::{
|
use monero_serai::{
|
||||||
random_scalar,
|
random_scalar,
|
||||||
wallet::{
|
wallet::{
|
||||||
address::{Network, AddressMeta, AddressType}, ViewPair, Scanner, SignableTransaction,
|
address::{Network, AddressSpec}, ViewPair, Scanner, SignableTransaction,
|
||||||
SignableTransactionBuilder,
|
SignableTransactionBuilder,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -185,7 +185,7 @@ macro_rules! test {
|
||||||
let rpc = rpc().await;
|
let rpc = rpc().await;
|
||||||
|
|
||||||
let view = ViewPair::new(spend_pub, Zeroizing::new(random_scalar(&mut OsRng)));
|
let view = ViewPair::new(spend_pub, Zeroizing::new(random_scalar(&mut OsRng)));
|
||||||
let addr = view.address(AddressMeta::new(Network::Mainnet, AddressType::Standard));
|
let addr = view.address(Network::Mainnet, AddressSpec::Standard);
|
||||||
|
|
||||||
let miner_tx = get_miner_tx_output(&rpc, &view).await;
|
let miner_tx = get_miner_tx_output(&rpc, &view).await;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
|
|
||||||
use monero_serai::{transaction::Transaction};
|
use monero_serai::transaction::Transaction;
|
||||||
|
|
||||||
mod runner;
|
mod runner;
|
||||||
|
|
||||||
|
@ -8,9 +8,9 @@ test!(
|
||||||
scan_standard_address,
|
scan_standard_address,
|
||||||
(
|
(
|
||||||
|_, mut builder: Builder, _| async move {
|
|_, mut builder: Builder, _| async move {
|
||||||
let scanner =
|
let mut scanner =
|
||||||
Scanner::from_view(runner::random_address().1, Network::Mainnet, Some(HashSet::new()));
|
Scanner::from_view(runner::random_address().1, Network::Mainnet, Some(HashSet::new()));
|
||||||
builder.add_payment(scanner.address(), 5);
|
builder.add_payment(scanner.address(AddressSpec::Standard), 5);
|
||||||
(builder.build().unwrap(), (scanner,))
|
(builder.build().unwrap(), (scanner,))
|
||||||
},
|
},
|
||||||
|_, tx: Transaction, _, mut state: (Scanner,)| async move {
|
|_, tx: Transaction, _, mut state: (Scanner,)| async move {
|
||||||
|
@ -27,7 +27,10 @@ test!(
|
||||||
let mut scanner =
|
let mut scanner =
|
||||||
Scanner::from_view(runner::random_address().1, Network::Mainnet, Some(HashSet::new()));
|
Scanner::from_view(runner::random_address().1, Network::Mainnet, Some(HashSet::new()));
|
||||||
let subaddress_index = (0, 1);
|
let subaddress_index = (0, 1);
|
||||||
builder.add_payment(scanner.subaddress(subaddress_index), 5);
|
builder.add_payment(
|
||||||
|
scanner.address(AddressSpec::Subaddress(subaddress_index.0, subaddress_index.1)),
|
||||||
|
5,
|
||||||
|
);
|
||||||
(builder.build().unwrap(), (scanner, subaddress_index))
|
(builder.build().unwrap(), (scanner, subaddress_index))
|
||||||
},
|
},
|
||||||
|_, tx: Transaction, _, mut state: (Scanner, (u32, u32))| async move {
|
|_, tx: Transaction, _, mut state: (Scanner, (u32, u32))| async move {
|
||||||
|
@ -42,12 +45,12 @@ test!(
|
||||||
scan_integrated_address,
|
scan_integrated_address,
|
||||||
(
|
(
|
||||||
|_, mut builder: Builder, _| async move {
|
|_, mut builder: Builder, _| async move {
|
||||||
let scanner =
|
let mut scanner =
|
||||||
Scanner::from_view(runner::random_address().1, Network::Mainnet, Some(HashSet::new()));
|
Scanner::from_view(runner::random_address().1, Network::Mainnet, Some(HashSet::new()));
|
||||||
let mut payment_id = [0u8; 8];
|
let mut payment_id = [0u8; 8];
|
||||||
OsRng.fill_bytes(&mut payment_id);
|
OsRng.fill_bytes(&mut payment_id);
|
||||||
|
|
||||||
builder.add_payment(scanner.integrated_address(payment_id), 5);
|
builder.add_payment(scanner.address(AddressSpec::Integrated(payment_id)), 5);
|
||||||
(builder.build().unwrap(), (scanner, payment_id))
|
(builder.build().unwrap(), (scanner, payment_id))
|
||||||
},
|
},
|
||||||
|_, tx: Transaction, _, mut state: (Scanner, [u8; 8])| async move {
|
|_, tx: Transaction, _, mut state: (Scanner, [u8; 8])| async move {
|
||||||
|
@ -64,7 +67,7 @@ test!(
|
||||||
|_, mut builder: Builder, _| async move {
|
|_, mut builder: Builder, _| async move {
|
||||||
let mut scanner =
|
let mut scanner =
|
||||||
Scanner::from_view(runner::random_address().1, Network::Mainnet, Some(HashSet::new()));
|
Scanner::from_view(runner::random_address().1, Network::Mainnet, Some(HashSet::new()));
|
||||||
builder.add_payment(scanner.featured_address(None, None, false), 5);
|
builder.add_payment(scanner.address(AddressSpec::Featured(None, None, false)), 5);
|
||||||
(builder.build().unwrap(), (scanner,))
|
(builder.build().unwrap(), (scanner,))
|
||||||
},
|
},
|
||||||
|_, tx: Transaction, _, mut state: (Scanner,)| async move {
|
|_, tx: Transaction, _, mut state: (Scanner,)| async move {
|
||||||
|
@ -81,7 +84,10 @@ test!(
|
||||||
let mut scanner =
|
let mut scanner =
|
||||||
Scanner::from_view(runner::random_address().1, Network::Mainnet, Some(HashSet::new()));
|
Scanner::from_view(runner::random_address().1, Network::Mainnet, Some(HashSet::new()));
|
||||||
let subaddress_index = (0, 2);
|
let subaddress_index = (0, 2);
|
||||||
builder.add_payment(scanner.featured_address(Some(subaddress_index), None, false), 5);
|
builder.add_payment(
|
||||||
|
scanner.address(AddressSpec::Featured(Some(subaddress_index), None, false)),
|
||||||
|
5,
|
||||||
|
);
|
||||||
(builder.build().unwrap(), (scanner, subaddress_index))
|
(builder.build().unwrap(), (scanner, subaddress_index))
|
||||||
},
|
},
|
||||||
|_, tx: Transaction, _, mut state: (Scanner, (u32, u32))| async move {
|
|_, tx: Transaction, _, mut state: (Scanner, (u32, u32))| async move {
|
||||||
|
@ -101,7 +107,7 @@ test!(
|
||||||
let mut payment_id = [0u8; 8];
|
let mut payment_id = [0u8; 8];
|
||||||
OsRng.fill_bytes(&mut payment_id);
|
OsRng.fill_bytes(&mut payment_id);
|
||||||
|
|
||||||
builder.add_payment(scanner.featured_address(None, Some(payment_id), false), 5);
|
builder.add_payment(scanner.address(AddressSpec::Featured(None, Some(payment_id), false)), 5);
|
||||||
(builder.build().unwrap(), (scanner, payment_id))
|
(builder.build().unwrap(), (scanner, payment_id))
|
||||||
},
|
},
|
||||||
|_, tx: Transaction, _, mut state: (Scanner, [u8; 8])| async move {
|
|_, tx: Transaction, _, mut state: (Scanner, [u8; 8])| async move {
|
||||||
|
@ -123,8 +129,10 @@ test!(
|
||||||
let mut payment_id = [0u8; 8];
|
let mut payment_id = [0u8; 8];
|
||||||
OsRng.fill_bytes(&mut payment_id);
|
OsRng.fill_bytes(&mut payment_id);
|
||||||
|
|
||||||
builder
|
builder.add_payment(
|
||||||
.add_payment(scanner.featured_address(Some(subaddress_index), Some(payment_id), false), 5);
|
scanner.address(AddressSpec::Featured(Some(subaddress_index), Some(payment_id), false)),
|
||||||
|
5,
|
||||||
|
);
|
||||||
(builder.build().unwrap(), (scanner, payment_id, subaddress_index))
|
(builder.build().unwrap(), (scanner, payment_id, subaddress_index))
|
||||||
},
|
},
|
||||||
|_, tx: Transaction, _, mut state: (Scanner, [u8; 8], (u32, u32))| async move {
|
|_, tx: Transaction, _, mut state: (Scanner, [u8; 8], (u32, u32))| async move {
|
||||||
|
@ -140,9 +148,9 @@ test!(
|
||||||
scan_guaranteed_standard,
|
scan_guaranteed_standard,
|
||||||
(
|
(
|
||||||
|_, mut builder: Builder, _| async move {
|
|_, mut builder: Builder, _| async move {
|
||||||
let scanner = Scanner::from_view(runner::random_address().1, Network::Mainnet, None);
|
let mut scanner = Scanner::from_view(runner::random_address().1, Network::Mainnet, None);
|
||||||
|
|
||||||
builder.add_payment(scanner.address(), 5);
|
builder.add_payment(scanner.address(AddressSpec::Featured(None, None, true)), 5);
|
||||||
(builder.build().unwrap(), (scanner,))
|
(builder.build().unwrap(), (scanner,))
|
||||||
},
|
},
|
||||||
|_, tx: Transaction, _, mut state: (Scanner,)| async move {
|
|_, tx: Transaction, _, mut state: (Scanner,)| async move {
|
||||||
|
@ -159,7 +167,8 @@ test!(
|
||||||
let mut scanner = Scanner::from_view(runner::random_address().1, Network::Mainnet, None);
|
let mut scanner = Scanner::from_view(runner::random_address().1, Network::Mainnet, None);
|
||||||
let subaddress_index = (0, 1);
|
let subaddress_index = (0, 1);
|
||||||
|
|
||||||
builder.add_payment(scanner.subaddress(subaddress_index), 5);
|
builder
|
||||||
|
.add_payment(scanner.address(AddressSpec::Featured(Some(subaddress_index), None, true)), 5);
|
||||||
(builder.build().unwrap(), (scanner, subaddress_index))
|
(builder.build().unwrap(), (scanner, subaddress_index))
|
||||||
},
|
},
|
||||||
|_, tx: Transaction, _, mut state: (Scanner, (u32, u32))| async move {
|
|_, tx: Transaction, _, mut state: (Scanner, (u32, u32))| async move {
|
||||||
|
@ -174,11 +183,11 @@ test!(
|
||||||
scan_guaranteed_integrated,
|
scan_guaranteed_integrated,
|
||||||
(
|
(
|
||||||
|_, mut builder: Builder, _| async move {
|
|_, mut builder: Builder, _| async move {
|
||||||
let scanner = Scanner::from_view(runner::random_address().1, Network::Mainnet, None);
|
let mut scanner = Scanner::from_view(runner::random_address().1, Network::Mainnet, None);
|
||||||
let mut payment_id = [0u8; 8];
|
let mut payment_id = [0u8; 8];
|
||||||
OsRng.fill_bytes(&mut payment_id);
|
OsRng.fill_bytes(&mut payment_id);
|
||||||
|
|
||||||
builder.add_payment(scanner.integrated_address(payment_id), 5);
|
builder.add_payment(scanner.address(AddressSpec::Featured(None, Some(payment_id), true)), 5);
|
||||||
(builder.build().unwrap(), (scanner, payment_id))
|
(builder.build().unwrap(), (scanner, payment_id))
|
||||||
},
|
},
|
||||||
|_, tx: Transaction, _, mut state: (Scanner, [u8; 8])| async move {
|
|_, tx: Transaction, _, mut state: (Scanner, [u8; 8])| async move {
|
||||||
|
@ -199,8 +208,10 @@ test!(
|
||||||
let mut payment_id = [0u8; 8];
|
let mut payment_id = [0u8; 8];
|
||||||
OsRng.fill_bytes(&mut payment_id);
|
OsRng.fill_bytes(&mut payment_id);
|
||||||
|
|
||||||
builder
|
builder.add_payment(
|
||||||
.add_payment(scanner.featured_address(Some(subaddress_index), Some(payment_id), true), 5);
|
scanner.address(AddressSpec::Featured(Some(subaddress_index), Some(payment_id), true)),
|
||||||
|
5,
|
||||||
|
);
|
||||||
(builder.build().unwrap(), (scanner, payment_id, subaddress_index))
|
(builder.build().unwrap(), (scanner, payment_id, subaddress_index))
|
||||||
},
|
},
|
||||||
|_, tx: Transaction, _, mut state: (Scanner, [u8; 8], (u32, u32))| async move {
|
|_, tx: Transaction, _, mut state: (Scanner, [u8; 8], (u32, u32))| async move {
|
||||||
|
|
|
@ -14,7 +14,7 @@ use monero_serai::{
|
||||||
rpc::Rpc,
|
rpc::Rpc,
|
||||||
wallet::{
|
wallet::{
|
||||||
ViewPair, Scanner,
|
ViewPair, Scanner,
|
||||||
address::{Network, MoneroAddress},
|
address::{Network, MoneroAddress, AddressSpec},
|
||||||
Fee, SpendableOutput, SignableTransaction as MSignableTransaction, TransactionMachine,
|
Fee, SpendableOutput, SignableTransaction as MSignableTransaction, TransactionMachine,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -91,7 +91,7 @@ impl Monero {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn empty_address() -> MoneroAddress {
|
fn empty_address() -> MoneroAddress {
|
||||||
Self::empty_scanner().address()
|
Self::empty_scanner().address(AddressSpec::Standard)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ impl Coin for Monero {
|
||||||
const MAX_OUTPUTS: usize = 16;
|
const MAX_OUTPUTS: usize = 16;
|
||||||
|
|
||||||
fn address(&self, key: dfg::EdwardsPoint) -> Self::Address {
|
fn address(&self, key: dfg::EdwardsPoint) -> Self::Address {
|
||||||
self.scanner(key).address()
|
self.scanner(key).address(AddressSpec::Featured(None, None, true))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_latest_block_number(&self) -> Result<usize, CoinError> {
|
async fn get_latest_block_number(&self) -> Result<usize, CoinError> {
|
||||||
|
|
Loading…
Reference in a new issue