mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-11 21:49:26 +00:00
Update monero-wallet tests to compile
Some are _consistently_ failing due to the inputs we attempt to spend being too young. I'm unsure what's up with that. Most seem to pass _consistently_, implying it's not a random issue yet some configuration/env aspect.
This commit is contained in:
@@ -32,7 +32,7 @@ async fn select_n<'a, R: RngCore + CryptoRng>(
|
||||
fingerprintable_canonical: bool,
|
||||
) -> Result<Vec<(u64, [EdwardsPoint; 2])>, RpcError> {
|
||||
// TODO: consider removing this extra RPC and expect the caller to handle it
|
||||
if fingerprintable_canonical && height > rpc.get_height().await? {
|
||||
if fingerprintable_canonical && (height > rpc.get_height().await?) {
|
||||
// TODO: Don't use InternalError for the caller's failure
|
||||
Err(RpcError::InternalError("decoys being requested from too young blocks"))?;
|
||||
}
|
||||
|
||||
@@ -1,140 +0,0 @@
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop, Zeroizing};
|
||||
|
||||
use crate::{
|
||||
WalletProtocol, address::MoneroAddress, FeeRate, SpendableOutput, Change, Decoys, SignableTransaction,
|
||||
TransactionError, extra::MAX_ARBITRARY_DATA_SIZE,
|
||||
};
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Zeroize, ZeroizeOnDrop)]
|
||||
struct SignableTransactionBuilderInternal {
|
||||
protocol: WalletProtocol,
|
||||
fee_rate: FeeRate,
|
||||
r_seed: Option<Zeroizing<[u8; 32]>>,
|
||||
inputs: Vec<(SpendableOutput, Decoys)>,
|
||||
payments: Vec<(MoneroAddress, u64)>,
|
||||
change_address: Change,
|
||||
data: Vec<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl SignableTransactionBuilderInternal {
|
||||
// Takes in the change address so users don't miss that they have to manually set one
|
||||
// If they don't, all leftover funds will become part of the fee
|
||||
fn new(protocol: WalletProtocol, fee_rate: FeeRate, change_address: Change) -> Self {
|
||||
Self {
|
||||
protocol,
|
||||
fee_rate,
|
||||
r_seed: None,
|
||||
inputs: vec![],
|
||||
payments: vec![],
|
||||
change_address,
|
||||
data: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
fn set_r_seed(&mut self, r_seed: Zeroizing<[u8; 32]>) {
|
||||
self.r_seed = Some(r_seed);
|
||||
}
|
||||
|
||||
fn add_input(&mut self, input: (SpendableOutput, Decoys)) {
|
||||
self.inputs.push(input);
|
||||
}
|
||||
fn add_inputs(&mut self, inputs: &[(SpendableOutput, Decoys)]) {
|
||||
self.inputs.extend(inputs.iter().cloned());
|
||||
}
|
||||
|
||||
fn add_payment(&mut self, dest: MoneroAddress, amount: u64) {
|
||||
self.payments.push((dest, amount));
|
||||
}
|
||||
fn add_payments(&mut self, payments: &[(MoneroAddress, u64)]) {
|
||||
self.payments.extend(payments);
|
||||
}
|
||||
|
||||
fn add_data(&mut self, data: Vec<u8>) {
|
||||
self.data.push(data);
|
||||
}
|
||||
}
|
||||
|
||||
/// A Transaction Builder for Monero transactions.
|
||||
/// All methods provided will modify self while also returning a shallow copy, enabling efficient
|
||||
/// chaining with a clean API.
|
||||
/// In order to fork the builder at some point, clone will still return a deep copy.
|
||||
#[derive(Debug)]
|
||||
pub struct SignableTransactionBuilder(Arc<RwLock<SignableTransactionBuilderInternal>>);
|
||||
impl Clone for SignableTransactionBuilder {
|
||||
fn clone(&self) -> Self {
|
||||
Self(Arc::new(RwLock::new((*self.0.read().unwrap()).clone())))
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for SignableTransactionBuilder {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
*self.0.read().unwrap() == *other.0.read().unwrap()
|
||||
}
|
||||
}
|
||||
impl Eq for SignableTransactionBuilder {}
|
||||
|
||||
impl Zeroize for SignableTransactionBuilder {
|
||||
fn zeroize(&mut self) {
|
||||
self.0.write().unwrap().zeroize()
|
||||
}
|
||||
}
|
||||
|
||||
impl SignableTransactionBuilder {
|
||||
fn shallow_copy(&self) -> Self {
|
||||
Self(self.0.clone())
|
||||
}
|
||||
|
||||
pub fn new(protocol: WalletProtocol, fee_rate: FeeRate, change_address: Change) -> Self {
|
||||
Self(Arc::new(RwLock::new(SignableTransactionBuilderInternal::new(
|
||||
protocol,
|
||||
fee_rate,
|
||||
change_address,
|
||||
))))
|
||||
}
|
||||
|
||||
pub fn set_r_seed(&mut self, r_seed: Zeroizing<[u8; 32]>) -> Self {
|
||||
self.0.write().unwrap().set_r_seed(r_seed);
|
||||
self.shallow_copy()
|
||||
}
|
||||
|
||||
pub fn add_input(&mut self, input: (SpendableOutput, Decoys)) -> Self {
|
||||
self.0.write().unwrap().add_input(input);
|
||||
self.shallow_copy()
|
||||
}
|
||||
pub fn add_inputs(&mut self, inputs: &[(SpendableOutput, Decoys)]) -> Self {
|
||||
self.0.write().unwrap().add_inputs(inputs);
|
||||
self.shallow_copy()
|
||||
}
|
||||
|
||||
pub fn add_payment(&mut self, dest: MoneroAddress, amount: u64) -> Self {
|
||||
self.0.write().unwrap().add_payment(dest, amount);
|
||||
self.shallow_copy()
|
||||
}
|
||||
pub fn add_payments(&mut self, payments: &[(MoneroAddress, u64)]) -> Self {
|
||||
self.0.write().unwrap().add_payments(payments);
|
||||
self.shallow_copy()
|
||||
}
|
||||
|
||||
pub fn add_data(&mut self, data: Vec<u8>) -> Result<Self, TransactionError> {
|
||||
if data.len() > MAX_ARBITRARY_DATA_SIZE {
|
||||
Err(TransactionError::TooMuchData)?;
|
||||
}
|
||||
self.0.write().unwrap().add_data(data);
|
||||
Ok(self.shallow_copy())
|
||||
}
|
||||
|
||||
pub fn build(self) -> Result<SignableTransaction, TransactionError> {
|
||||
let read = self.0.read().unwrap();
|
||||
SignableTransaction::new(
|
||||
read.protocol,
|
||||
read.r_seed.clone(),
|
||||
read.inputs.clone(),
|
||||
read.payments.clone(),
|
||||
&read.change_address,
|
||||
read.data.clone(),
|
||||
read.fee_rate,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -321,11 +321,27 @@ impl SignableTransaction {
|
||||
}
|
||||
}
|
||||
|
||||
let res = SignableTransaction { rct_type, sender_view_key, inputs, payments, data, fee_rate };
|
||||
let mut res =
|
||||
SignableTransaction { rct_type, sender_view_key, inputs, payments, data, fee_rate };
|
||||
res.validate()?;
|
||||
|
||||
// Shuffle the payments
|
||||
{
|
||||
let mut rng = res.seeded_rng(b"shuffle_payments");
|
||||
res.payments.shuffle(&mut rng);
|
||||
}
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn fee_rate(&self) -> FeeRate {
|
||||
self.fee_rate
|
||||
}
|
||||
|
||||
pub fn fee(&self) -> u64 {
|
||||
self.weight_and_fee().1
|
||||
}
|
||||
|
||||
pub fn write<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
|
||||
fn write_input<W: io::Write>(input: &(SpendableOutput, Decoys), w: &mut W) -> io::Result<()> {
|
||||
input.0.write(w)?;
|
||||
@@ -424,12 +440,6 @@ impl SignableTransaction {
|
||||
key_images.push(key_image);
|
||||
}
|
||||
|
||||
// Shuffle the payments
|
||||
{
|
||||
let mut rng = self.seeded_rng(b"shuffle_payments");
|
||||
self.payments.shuffle(&mut rng);
|
||||
}
|
||||
|
||||
SignableTransactionWithKeyImages { intent: self, key_images }
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use monero_serai::transaction::Transaction;
|
||||
use monero_wallet::{rpc::Rpc, TransactionError, extra::MAX_ARBITRARY_DATA_SIZE};
|
||||
use monero_wallet::{rpc::Rpc, extra::MAX_ARBITRARY_DATA_SIZE, send::SendError};
|
||||
|
||||
mod runner;
|
||||
|
||||
@@ -56,7 +56,7 @@ test!(
|
||||
let mut data = vec![b'a'; MAX_ARBITRARY_DATA_SIZE + 1];
|
||||
|
||||
// Make sure we get an error if we try to add it to the TX
|
||||
assert_eq!(builder.add_data(data.clone()), Err(TransactionError::TooMuchData));
|
||||
assert_eq!(builder.add_data(data.clone()), Err(SendError::TooMuchData));
|
||||
|
||||
// Reduce data size and retry. The data will now be 255 bytes long (including the added
|
||||
// marker), exactly
|
||||
|
||||
@@ -3,7 +3,7 @@ use monero_wallet::{
|
||||
DEFAULT_LOCK_WINDOW,
|
||||
transaction::Transaction,
|
||||
rpc::{OutputResponse, Rpc},
|
||||
SpendableOutput,
|
||||
scan::SpendableOutput,
|
||||
};
|
||||
|
||||
mod runner;
|
||||
@@ -24,12 +24,12 @@ test!(
|
||||
),
|
||||
(
|
||||
// Then make a second tx1
|
||||
|protocol: Protocol, rpc: SimpleRequestRpc, mut builder: Builder, addr, state: _| async move {
|
||||
|rct_type: RctType, rpc: SimpleRequestRpc, mut builder: Builder, addr, state: _| async move {
|
||||
let output_tx0: SpendableOutput = state;
|
||||
let decoys = Decoys::fingerprintable_canonical_select(
|
||||
&mut OsRng,
|
||||
&rpc,
|
||||
protocol.ring_len(),
|
||||
ring_len(rct_type),
|
||||
rpc.get_height().await.unwrap(),
|
||||
&[output_tx0.clone()],
|
||||
)
|
||||
@@ -40,7 +40,7 @@ test!(
|
||||
builder.add_inputs(&inputs);
|
||||
builder.add_payment(addr, 1000000000000);
|
||||
|
||||
(builder.build().unwrap(), (protocol, output_tx0))
|
||||
(builder.build().unwrap(), (rct_type, output_tx0))
|
||||
},
|
||||
// Then make sure DSA selects freshly unlocked output from tx1 as a decoy
|
||||
|rpc: SimpleRequestRpc, tx: Transaction, mut scanner: Scanner, state: (_, _)| async move {
|
||||
@@ -61,14 +61,14 @@ test!(
|
||||
|
||||
// Select decoys using spendable output from tx0 as the real, and make sure DSA selects
|
||||
// the freshly unlocked output from tx1 as a decoy
|
||||
let (protocol, output_tx0): (Protocol, SpendableOutput) = state;
|
||||
let (rct_type, output_tx0): (RctType, SpendableOutput) = state;
|
||||
let mut selected_fresh_decoy = false;
|
||||
let mut attempts = 1000;
|
||||
while !selected_fresh_decoy && attempts > 0 {
|
||||
let decoys = Decoys::fingerprintable_canonical_select(
|
||||
&mut OsRng, // TODO: use a seeded RNG to consistently select the latest output
|
||||
&rpc,
|
||||
protocol.ring_len(),
|
||||
ring_len(rct_type),
|
||||
height,
|
||||
&[output_tx0.clone()],
|
||||
)
|
||||
@@ -101,12 +101,12 @@ test!(
|
||||
),
|
||||
(
|
||||
// Then make a second tx1
|
||||
|protocol: Protocol, rpc: SimpleRequestRpc, mut builder: Builder, addr, state: _| async move {
|
||||
|rct_type: RctType, rpc: SimpleRequestRpc, mut builder: Builder, addr, state: _| async move {
|
||||
let output_tx0: SpendableOutput = state;
|
||||
let decoys = Decoys::select(
|
||||
&mut OsRng,
|
||||
&rpc,
|
||||
protocol.ring_len(),
|
||||
ring_len(rct_type),
|
||||
rpc.get_height().await.unwrap(),
|
||||
&[output_tx0.clone()],
|
||||
)
|
||||
@@ -117,7 +117,7 @@ test!(
|
||||
builder.add_inputs(&inputs);
|
||||
builder.add_payment(addr, 1000000000000);
|
||||
|
||||
(builder.build().unwrap(), (protocol, output_tx0))
|
||||
(builder.build().unwrap(), (rct_type, output_tx0))
|
||||
},
|
||||
// Then make sure DSA selects freshly unlocked output from tx1 as a decoy
|
||||
|rpc: SimpleRequestRpc, tx: Transaction, mut scanner: Scanner, state: (_, _)| async move {
|
||||
@@ -138,14 +138,14 @@ test!(
|
||||
|
||||
// Select decoys using spendable output from tx0 as the real, and make sure DSA selects
|
||||
// the freshly unlocked output from tx1 as a decoy
|
||||
let (protocol, output_tx0): (Protocol, SpendableOutput) = state;
|
||||
let (rct_type, output_tx0): (RctType, SpendableOutput) = state;
|
||||
let mut selected_fresh_decoy = false;
|
||||
let mut attempts = 1000;
|
||||
while !selected_fresh_decoy && attempts > 0 {
|
||||
let decoys = Decoys::select(
|
||||
&mut OsRng, // TODO: use a seeded RNG to consistently select the latest output
|
||||
&rpc,
|
||||
protocol.ring_len(),
|
||||
ring_len(rct_type),
|
||||
height,
|
||||
&[output_tx0.clone()],
|
||||
)
|
||||
|
||||
@@ -3,8 +3,8 @@ use curve25519_dalek::constants::ED25519_BASEPOINT_POINT;
|
||||
use monero_serai::transaction::Transaction;
|
||||
use monero_wallet::{
|
||||
rpc::Rpc,
|
||||
Eventuality,
|
||||
address::{AddressType, AddressMeta, MoneroAddress},
|
||||
send::Eventuality,
|
||||
};
|
||||
|
||||
mod runner;
|
||||
@@ -50,9 +50,8 @@ test!(
|
||||
),
|
||||
4,
|
||||
);
|
||||
builder.set_r_seed(Zeroizing::new([0xbb; 32]));
|
||||
let tx = builder.build().unwrap();
|
||||
let eventuality = tx.eventuality().unwrap();
|
||||
let eventuality = Eventuality::from(tx.clone());
|
||||
assert_eq!(
|
||||
eventuality,
|
||||
Eventuality::read::<&[u8]>(&mut eventuality.serialize().as_ref()).unwrap()
|
||||
|
||||
85
coins/monero/wallet/tests/runner/builder.rs
Normal file
85
coins/monero/wallet/tests/runner/builder.rs
Normal file
@@ -0,0 +1,85 @@
|
||||
use zeroize::{Zeroize, Zeroizing};
|
||||
|
||||
use curve25519_dalek::Scalar;
|
||||
|
||||
use monero_wallet::{
|
||||
primitives::Decoys,
|
||||
ringct::RctType,
|
||||
rpc::FeeRate,
|
||||
address::MoneroAddress,
|
||||
scan::SpendableOutput,
|
||||
send::{Change, SendError, SignableTransaction},
|
||||
extra::MAX_ARBITRARY_DATA_SIZE,
|
||||
};
|
||||
|
||||
/// A builder for Monero transactions.
|
||||
#[derive(Clone, PartialEq, Eq, Zeroize, Debug)]
|
||||
pub struct SignableTransactionBuilder {
|
||||
rct_type: RctType,
|
||||
sender_view_key: Zeroizing<Scalar>,
|
||||
inputs: Vec<(SpendableOutput, Decoys)>,
|
||||
payments: Vec<(MoneroAddress, u64)>,
|
||||
change: Change,
|
||||
data: Vec<Vec<u8>>,
|
||||
fee_rate: FeeRate,
|
||||
}
|
||||
|
||||
impl SignableTransactionBuilder {
|
||||
pub fn new(
|
||||
rct_type: RctType,
|
||||
sender_view_key: Zeroizing<Scalar>,
|
||||
change: Change,
|
||||
fee_rate: FeeRate,
|
||||
) -> Self {
|
||||
Self {
|
||||
rct_type,
|
||||
sender_view_key,
|
||||
inputs: vec![],
|
||||
payments: vec![],
|
||||
change,
|
||||
data: vec![],
|
||||
fee_rate,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_input(&mut self, input: (SpendableOutput, Decoys)) -> &mut Self {
|
||||
self.inputs.push(input);
|
||||
self
|
||||
}
|
||||
#[allow(unused)]
|
||||
pub fn add_inputs(&mut self, inputs: &[(SpendableOutput, Decoys)]) -> &mut Self {
|
||||
self.inputs.extend(inputs.iter().cloned());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_payment(&mut self, dest: MoneroAddress, amount: u64) -> &mut Self {
|
||||
self.payments.push((dest, amount));
|
||||
self
|
||||
}
|
||||
#[allow(unused)]
|
||||
pub fn add_payments(&mut self, payments: &[(MoneroAddress, u64)]) -> &mut Self {
|
||||
self.payments.extend(payments);
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn add_data(&mut self, data: Vec<u8>) -> Result<&mut Self, SendError> {
|
||||
if data.len() > MAX_ARBITRARY_DATA_SIZE {
|
||||
Err(SendError::TooMuchData)?;
|
||||
}
|
||||
self.data.push(data);
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn build(self) -> Result<SignableTransaction, SendError> {
|
||||
SignableTransaction::new(
|
||||
self.rct_type,
|
||||
self.sender_view_key,
|
||||
self.inputs,
|
||||
self.payments,
|
||||
self.change,
|
||||
self.data,
|
||||
self.fee_rate,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -10,13 +10,25 @@ use tokio::sync::Mutex;
|
||||
|
||||
use monero_simple_request_rpc::SimpleRequestRpc;
|
||||
use monero_wallet::{
|
||||
ringct::RctType,
|
||||
transaction::Transaction,
|
||||
rpc::Rpc,
|
||||
ViewPair, Scanner,
|
||||
rpc::{Rpc, FeeRate},
|
||||
ViewPair,
|
||||
address::{Network, AddressType, AddressSpec, AddressMeta, MoneroAddress},
|
||||
SpendableOutput, FeeRate,
|
||||
scan::{SpendableOutput, Scanner},
|
||||
};
|
||||
|
||||
mod builder;
|
||||
pub use builder::SignableTransactionBuilder;
|
||||
|
||||
pub fn ring_len(rct_type: RctType) -> usize {
|
||||
match rct_type {
|
||||
RctType::ClsagBulletproof => 11,
|
||||
RctType::ClsagBulletproofPlus => 16,
|
||||
_ => panic!("ring size unknown for RctType"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn random_address() -> (Scalar, ViewPair, MoneroAddress) {
|
||||
let spend = Scalar::random(&mut OsRng);
|
||||
let spend_pub = &spend * ED25519_BASEPOINT_TABLE;
|
||||
@@ -56,7 +68,7 @@ pub async fn mine_until_unlocked(rpc: &SimpleRequestRpc, addr: &str, tx_hash: [u
|
||||
.await
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.all(|output| output.is_some())
|
||||
.any(|output| output.is_none())
|
||||
{
|
||||
height = rpc.generate_blocks(addr, 1).await.unwrap().1 + 1;
|
||||
}
|
||||
@@ -159,8 +171,6 @@ macro_rules! test {
|
||||
|
||||
use curve25519_dalek::{constants::ED25519_BASEPOINT_TABLE, scalar::Scalar};
|
||||
|
||||
#[cfg(feature = "multisig")]
|
||||
use transcript::{Transcript, RecommendedTranscript};
|
||||
#[cfg(feature = "multisig")]
|
||||
use frost::{
|
||||
curve::Ed25519,
|
||||
@@ -169,15 +179,19 @@ macro_rules! test {
|
||||
};
|
||||
|
||||
use monero_wallet::{
|
||||
Protocol,
|
||||
primitives::Decoys,
|
||||
ringct::RctType,
|
||||
rpc::FeePriority,
|
||||
address::{Network, AddressSpec},
|
||||
ViewPair, Scanner, Change, DecoySelection, Decoys, FeePriority,
|
||||
SignableTransaction, SignableTransactionBuilder,
|
||||
ViewPair,
|
||||
DecoySelection,
|
||||
scan::Scanner,
|
||||
send::{Change, SignableTransaction},
|
||||
};
|
||||
|
||||
use runner::{
|
||||
random_address, rpc, mine_until_unlocked, get_miner_tx_output,
|
||||
check_weight_and_fee,
|
||||
SignableTransactionBuilder, ring_len, random_address, rpc, mine_until_unlocked,
|
||||
get_miner_tx_output, check_weight_and_fee,
|
||||
};
|
||||
|
||||
type Builder = SignableTransactionBuilder;
|
||||
@@ -206,16 +220,21 @@ macro_rules! test {
|
||||
|
||||
let rpc = rpc().await;
|
||||
|
||||
let view = ViewPair::new(spend_pub, Zeroizing::new(Scalar::random(&mut OsRng)));
|
||||
let view_priv = Zeroizing::new(Scalar::random(&mut OsRng));
|
||||
let view = ViewPair::new(spend_pub, view_priv.clone());
|
||||
let addr = view.address(Network::Mainnet, AddressSpec::Standard);
|
||||
|
||||
let miner_tx = get_miner_tx_output(&rpc, &view).await;
|
||||
|
||||
let protocol = Protocol::try_from(rpc.get_protocol().await.unwrap()).unwrap();
|
||||
let rct_type = match rpc.get_hardfork_version().await.unwrap() {
|
||||
14 => RctType::ClsagBulletproof,
|
||||
15 | 16 => RctType::ClsagBulletproofPlus,
|
||||
_ => panic!("unrecognized hardfork version"),
|
||||
};
|
||||
|
||||
let builder = SignableTransactionBuilder::new(
|
||||
protocol,
|
||||
rpc.get_fee_rate(FeePriority::Unimportant).await.unwrap(),
|
||||
rct_type,
|
||||
view_priv,
|
||||
Change::new(
|
||||
&ViewPair::new(
|
||||
&Scalar::random(&mut OsRng) * ED25519_BASEPOINT_TABLE,
|
||||
@@ -223,6 +242,7 @@ macro_rules! test {
|
||||
),
|
||||
false
|
||||
),
|
||||
rpc.get_fee_rate(FeePriority::Unimportant).await.unwrap(),
|
||||
);
|
||||
|
||||
let sign = |tx: SignableTransaction| {
|
||||
@@ -239,16 +259,7 @@ macro_rules! test {
|
||||
{
|
||||
let mut machines = HashMap::new();
|
||||
for i in (1 ..= THRESHOLD).map(|i| Participant::new(i).unwrap()) {
|
||||
machines.insert(
|
||||
i,
|
||||
tx
|
||||
.clone()
|
||||
.multisig(
|
||||
&keys[&i],
|
||||
RecommendedTranscript::new(b"Monero Serai Test Transaction"),
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
machines.insert(i, tx.clone().multisig(&keys[&i]).unwrap());
|
||||
}
|
||||
|
||||
frost::tests::sign_without_caching(&mut OsRng, machines, &[])
|
||||
@@ -266,7 +277,7 @@ macro_rules! test {
|
||||
let decoys = Decoys::fingerprintable_canonical_select(
|
||||
&mut OsRng,
|
||||
&rpc,
|
||||
protocol.ring_len(),
|
||||
ring_len(rct_type),
|
||||
rpc.get_height().await.unwrap(),
|
||||
&[miner_tx.clone()],
|
||||
)
|
||||
@@ -290,7 +301,7 @@ macro_rules! test {
|
||||
|
||||
$(
|
||||
let (tx, state) = ($tx)(
|
||||
protocol,
|
||||
rct_type,
|
||||
rpc.clone(),
|
||||
builder.clone(),
|
||||
next_addr,
|
||||
|
||||
@@ -2,15 +2,22 @@ use rand_core::OsRng;
|
||||
|
||||
use monero_simple_request_rpc::SimpleRequestRpc;
|
||||
use monero_wallet::{
|
||||
transaction::Transaction, Protocol, rpc::Rpc, extra::Extra, address::SubaddressIndex,
|
||||
ReceivedOutput, SpendableOutput, DecoySelection, Decoys, SignableTransactionBuilder,
|
||||
primitives::Decoys,
|
||||
ringct::RctType,
|
||||
transaction::Transaction,
|
||||
rpc::Rpc,
|
||||
address::SubaddressIndex,
|
||||
extra::Extra,
|
||||
scan::{ReceivedOutput, SpendableOutput},
|
||||
DecoySelection,
|
||||
};
|
||||
|
||||
mod runner;
|
||||
use runner::{SignableTransactionBuilder, ring_len};
|
||||
|
||||
// Set up inputs, select decoys, then add them to the TX builder
|
||||
async fn add_inputs(
|
||||
protocol: Protocol,
|
||||
rct_type: RctType,
|
||||
rpc: &SimpleRequestRpc,
|
||||
outputs: Vec<ReceivedOutput>,
|
||||
builder: &mut SignableTransactionBuilder,
|
||||
@@ -23,7 +30,7 @@ async fn add_inputs(
|
||||
let decoys = Decoys::fingerprintable_canonical_select(
|
||||
&mut OsRng,
|
||||
rpc,
|
||||
protocol.ring_len(),
|
||||
ring_len(rct_type),
|
||||
rpc.get_height().await.unwrap(),
|
||||
&spendable_outputs,
|
||||
)
|
||||
@@ -66,8 +73,8 @@ test!(
|
||||
},
|
||||
),
|
||||
(
|
||||
|protocol: Protocol, rpc, mut builder: Builder, addr, outputs: Vec<ReceivedOutput>| async move {
|
||||
add_inputs(protocol, &rpc, outputs, &mut builder).await;
|
||||
|rct_type: RctType, rpc, mut builder: Builder, addr, outputs: Vec<ReceivedOutput>| async move {
|
||||
add_inputs(rct_type, &rpc, outputs, &mut builder).await;
|
||||
builder.add_payment(addr, 6);
|
||||
(builder.build().unwrap(), ())
|
||||
},
|
||||
@@ -96,20 +103,20 @@ test!(
|
||||
},
|
||||
),
|
||||
(
|
||||
|protocol, rpc: SimpleRequestRpc, _, _, outputs: Vec<ReceivedOutput>| async move {
|
||||
use monero_wallet::FeePriority;
|
||||
|rct_type, rpc: SimpleRequestRpc, _, _, outputs: Vec<ReceivedOutput>| async move {
|
||||
use monero_wallet::rpc::FeePriority;
|
||||
|
||||
let change_view = ViewPair::new(
|
||||
&Scalar::random(&mut OsRng) * ED25519_BASEPOINT_TABLE,
|
||||
Zeroizing::new(Scalar::random(&mut OsRng)),
|
||||
);
|
||||
let view_priv = Zeroizing::new(Scalar::random(&mut OsRng));
|
||||
let change_view =
|
||||
ViewPair::new(&Scalar::random(&mut OsRng) * ED25519_BASEPOINT_TABLE, view_priv.clone());
|
||||
|
||||
let mut builder = SignableTransactionBuilder::new(
|
||||
protocol,
|
||||
rpc.get_fee_rate(FeePriority::Unimportant).await.unwrap(),
|
||||
rct_type,
|
||||
view_priv,
|
||||
Change::new(&change_view, false),
|
||||
rpc.get_fee_rate(FeePriority::Unimportant).await.unwrap(),
|
||||
);
|
||||
add_inputs(protocol, &rpc, vec![outputs.first().unwrap().clone()], &mut builder).await;
|
||||
add_inputs(rct_type, &rpc, vec![outputs.first().unwrap().clone()], &mut builder).await;
|
||||
|
||||
// Send to a subaddress
|
||||
let sub_view = ViewPair::new(
|
||||
@@ -161,8 +168,8 @@ test!(
|
||||
},
|
||||
),
|
||||
(
|
||||
|protocol: Protocol, rpc, mut builder: Builder, addr, outputs: Vec<ReceivedOutput>| async move {
|
||||
add_inputs(protocol, &rpc, outputs, &mut builder).await;
|
||||
|rct_type: RctType, rpc, mut builder: Builder, addr, outputs: Vec<ReceivedOutput>| async move {
|
||||
add_inputs(rct_type, &rpc, outputs, &mut builder).await;
|
||||
builder.add_payment(addr, 2);
|
||||
(builder.build().unwrap(), ())
|
||||
},
|
||||
@@ -188,8 +195,8 @@ test!(
|
||||
},
|
||||
),
|
||||
(
|
||||
|protocol: Protocol, rpc, mut builder: Builder, addr, outputs: Vec<ReceivedOutput>| async move {
|
||||
add_inputs(protocol, &rpc, outputs, &mut builder).await;
|
||||
|rct_type: RctType, rpc, mut builder: Builder, addr, outputs: Vec<ReceivedOutput>| async move {
|
||||
add_inputs(rct_type, &rpc, outputs, &mut builder).await;
|
||||
|
||||
for i in 0 .. 15 {
|
||||
builder.add_payment(addr, i + 1);
|
||||
@@ -228,8 +235,8 @@ test!(
|
||||
},
|
||||
),
|
||||
(
|
||||
|protocol: Protocol, rpc, mut builder: Builder, _, outputs: Vec<ReceivedOutput>| async move {
|
||||
add_inputs(protocol, &rpc, outputs, &mut builder).await;
|
||||
|rct_type: RctType, rpc, mut builder: Builder, _, outputs: Vec<ReceivedOutput>| async move {
|
||||
add_inputs(rct_type, &rpc, outputs, &mut builder).await;
|
||||
|
||||
let view = runner::random_address().1;
|
||||
let mut scanner = Scanner::from_view(view.clone(), Some(HashSet::new()));
|
||||
@@ -285,15 +292,16 @@ test!(
|
||||
},
|
||||
),
|
||||
(
|
||||
|protocol, rpc: SimpleRequestRpc, _, addr, outputs: Vec<ReceivedOutput>| async move {
|
||||
use monero_wallet::FeePriority;
|
||||
|rct_type, rpc: SimpleRequestRpc, _, addr, outputs: Vec<ReceivedOutput>| async move {
|
||||
use monero_wallet::rpc::FeePriority;
|
||||
|
||||
let mut builder = SignableTransactionBuilder::new(
|
||||
protocol,
|
||||
rpc.get_fee_rate(FeePriority::Unimportant).await.unwrap(),
|
||||
rct_type,
|
||||
Zeroizing::new(Scalar::random(&mut OsRng)),
|
||||
Change::fingerprintable(None),
|
||||
rpc.get_fee_rate(FeePriority::Unimportant).await.unwrap(),
|
||||
);
|
||||
add_inputs(protocol, &rpc, vec![outputs.first().unwrap().clone()], &mut builder).await;
|
||||
add_inputs(rct_type, &rpc, vec![outputs.first().unwrap().clone()], &mut builder).await;
|
||||
builder.add_payment(addr, 10000);
|
||||
builder.add_payment(addr, 50000);
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ use monero_wallet::{
|
||||
rpc::Rpc,
|
||||
address::{Network, AddressSpec, SubaddressIndex, MoneroAddress},
|
||||
extra::{MAX_TX_EXTRA_NONCE_SIZE, Extra, PaymentId},
|
||||
Scanner,
|
||||
scan::Scanner,
|
||||
};
|
||||
|
||||
mod runner;
|
||||
|
||||
Reference in New Issue
Block a user