mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 12:19:24 +00:00
Monero Planner
Finishes the Monero processor.
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
use core::{fmt::Debug, future::Future};
|
||||
|
||||
use serai_primitives::{Coin, Amount};
|
||||
use serai_primitives::Amount;
|
||||
|
||||
use primitives::{ReceivedOutput, Payment};
|
||||
use scanner::{ScannerFeed, KeyFor, AddressFor, OutputFor, EventualityFor, BlockFor};
|
||||
@@ -48,9 +48,6 @@ pub trait TransactionPlanner<S: ScannerFeed, A>: 'static + Send + Sync {
|
||||
/// resolve manual intervention/changing the arguments.
|
||||
type EphemeralError: Debug;
|
||||
|
||||
/// The type representing a fee rate to use for transactions.
|
||||
type FeeRate: Send + Clone + Copy;
|
||||
|
||||
/// The type representing a signable transaction.
|
||||
type SignableTransaction: SignableTransaction;
|
||||
|
||||
@@ -59,11 +56,6 @@ pub trait TransactionPlanner<S: ScannerFeed, A>: 'static + Send + Sync {
|
||||
/// The maximum amount of outputs allowed in a transaction, including the change output.
|
||||
const MAX_OUTPUTS: usize;
|
||||
|
||||
/// Obtain the fee rate to pay.
|
||||
///
|
||||
/// This must be constant to the block and coin.
|
||||
fn fee_rate(block: &BlockFor<S>, coin: Coin) -> Self::FeeRate;
|
||||
|
||||
/// The branch address for this key of Serai's.
|
||||
fn branch_address(key: KeyFor<S>) -> AddressFor<S>;
|
||||
/// The change address for this key of Serai's.
|
||||
@@ -76,11 +68,12 @@ pub trait TransactionPlanner<S: ScannerFeed, A>: 'static + Send + Sync {
|
||||
/// The fee rate, inputs, and payments, will all be for the same coin. The returned fee is
|
||||
/// denominated in this coin.
|
||||
fn calculate_fee(
|
||||
fee_rate: Self::FeeRate,
|
||||
&self,
|
||||
reference_block: &BlockFor<S>,
|
||||
inputs: Vec<OutputFor<S>>,
|
||||
payments: Vec<Payment<AddressFor<S>>>,
|
||||
change: Option<KeyFor<S>>,
|
||||
) -> Amount;
|
||||
) -> impl Send + Future<Output = Result<Amount, Self::EphemeralError>>;
|
||||
|
||||
/// Plan a transaction.
|
||||
///
|
||||
@@ -91,7 +84,7 @@ pub trait TransactionPlanner<S: ScannerFeed, A>: 'static + Send + Sync {
|
||||
/// output must be created.
|
||||
fn plan(
|
||||
&self,
|
||||
fee_rate: Self::FeeRate,
|
||||
reference_block: &BlockFor<S>,
|
||||
inputs: Vec<OutputFor<S>>,
|
||||
payments: Vec<Payment<AddressFor<S>>>,
|
||||
change: Option<KeyFor<S>>,
|
||||
@@ -112,7 +105,7 @@ pub trait TransactionPlanner<S: ScannerFeed, A>: 'static + Send + Sync {
|
||||
fn plan_transaction_with_fee_amortization(
|
||||
&self,
|
||||
operating_costs: &mut u64,
|
||||
fee_rate: Self::FeeRate,
|
||||
reference_block: &BlockFor<S>,
|
||||
inputs: Vec<OutputFor<S>>,
|
||||
mut payments: Vec<Payment<AddressFor<S>>>,
|
||||
mut change: Option<KeyFor<S>>,
|
||||
@@ -156,7 +149,8 @@ pub trait TransactionPlanner<S: ScannerFeed, A>: 'static + Send + Sync {
|
||||
// Sort payments from high amount to low amount
|
||||
payments.sort_by(|a, b| a.balance().amount.0.cmp(&b.balance().amount.0).reverse());
|
||||
|
||||
let mut fee = Self::calculate_fee(fee_rate, inputs.clone(), payments.clone(), change).0;
|
||||
let mut fee =
|
||||
self.calculate_fee(reference_block, inputs.clone(), payments.clone(), change).await?.0;
|
||||
let mut amortized = 0;
|
||||
while !payments.is_empty() {
|
||||
// We need to pay the fee, and any accrued operating costs, minus what we've already
|
||||
@@ -176,7 +170,10 @@ pub trait TransactionPlanner<S: ScannerFeed, A>: 'static + Send + Sync {
|
||||
if payments.last().unwrap().balance().amount.0 <= (per_payment_fee + S::dust(coin).0) {
|
||||
amortized += payments.pop().unwrap().balance().amount.0;
|
||||
// Recalculate the fee and try again
|
||||
fee = Self::calculate_fee(fee_rate, inputs.clone(), payments.clone(), change).0;
|
||||
fee = self
|
||||
.calculate_fee(reference_block, inputs.clone(), payments.clone(), change)
|
||||
.await?
|
||||
.0;
|
||||
continue;
|
||||
}
|
||||
// Break since all of these payments shouldn't be dropped
|
||||
@@ -237,7 +234,7 @@ pub trait TransactionPlanner<S: ScannerFeed, A>: 'static + Send + Sync {
|
||||
let has_change = change.is_some();
|
||||
|
||||
let PlannedTransaction { signable, eventuality, auxilliary } =
|
||||
self.plan(fee_rate, inputs, payments, change).await?;
|
||||
self.plan(reference_block, inputs, payments, change).await?;
|
||||
Ok(Some(AmortizePlannedTransaction {
|
||||
effected_payments,
|
||||
has_change,
|
||||
|
||||
@@ -56,7 +56,7 @@ impl<S: ScannerFeed, P: TransactionPlanner<S, ()>> Scheduler<S, P> {
|
||||
.planner
|
||||
.plan_transaction_with_fee_amortization(
|
||||
&mut operating_costs,
|
||||
P::fee_rate(block, coin),
|
||||
block,
|
||||
to_aggregate,
|
||||
vec![],
|
||||
Some(key_for_change),
|
||||
@@ -176,7 +176,7 @@ impl<S: ScannerFeed, P: TransactionPlanner<S, ()>> Scheduler<S, P> {
|
||||
.plan_transaction_with_fee_amortization(
|
||||
// Uses 0 as there's no operating costs to incur/amortize here
|
||||
&mut 0,
|
||||
P::fee_rate(block, coin),
|
||||
block,
|
||||
vec![output],
|
||||
payments,
|
||||
None,
|
||||
@@ -254,7 +254,7 @@ impl<S: ScannerFeed, P: TransactionPlanner<S, ()>> Scheduler<S, P> {
|
||||
.planner
|
||||
.plan_transaction_with_fee_amortization(
|
||||
&mut operating_costs,
|
||||
P::fee_rate(block, coin),
|
||||
block,
|
||||
outputs.clone(),
|
||||
tree[0]
|
||||
.payments::<S>(coin, &branch_address, tree[0].value())
|
||||
@@ -327,7 +327,7 @@ impl<S: ScannerFeed, P: TransactionPlanner<S, ()>> Scheduler<S, P> {
|
||||
.planner
|
||||
.plan_transaction_with_fee_amortization(
|
||||
&mut operating_costs,
|
||||
P::fee_rate(block, coin),
|
||||
block,
|
||||
outputs,
|
||||
vec![],
|
||||
Some(to),
|
||||
@@ -487,7 +487,7 @@ impl<S: ScannerFeed, P: TransactionPlanner<S, ()>> SchedulerTrait<S> for Schedul
|
||||
// This uses 0 for the operating costs as we don't incur any here
|
||||
// If the output can't pay for itself to be forwarded, we simply drop it
|
||||
&mut 0,
|
||||
P::fee_rate(block, forward.balance().coin),
|
||||
block,
|
||||
vec![forward.clone()],
|
||||
vec![Payment::new(P::forwarding_address(forward_to_key), forward.balance(), None)],
|
||||
None,
|
||||
@@ -508,7 +508,7 @@ impl<S: ScannerFeed, P: TransactionPlanner<S, ()>> SchedulerTrait<S> for Schedul
|
||||
// This uses 0 for the operating costs as we don't incur any here
|
||||
// If the output can't pay for itself to be returned, we simply drop it
|
||||
&mut 0,
|
||||
P::fee_rate(block, out_instruction.balance().coin),
|
||||
block,
|
||||
vec![to_return.output().clone()],
|
||||
vec![out_instruction],
|
||||
None,
|
||||
|
||||
@@ -86,7 +86,7 @@ impl<S: ScannerFeed, P: TransactionPlanner<S, EffectedReceivedOutputs<S>>> Sched
|
||||
.planner
|
||||
.plan_transaction_with_fee_amortization(
|
||||
&mut operating_costs,
|
||||
P::fee_rate(block, coin),
|
||||
block,
|
||||
to_aggregate,
|
||||
vec![],
|
||||
Some(key_for_change),
|
||||
@@ -229,7 +229,7 @@ impl<S: ScannerFeed, P: TransactionPlanner<S, EffectedReceivedOutputs<S>>> Sched
|
||||
.planner
|
||||
.plan_transaction_with_fee_amortization(
|
||||
&mut operating_costs,
|
||||
P::fee_rate(block, coin),
|
||||
block,
|
||||
outputs.clone(),
|
||||
tree[0]
|
||||
.payments::<S>(coin, &branch_address, tree[0].value())
|
||||
@@ -323,7 +323,7 @@ impl<S: ScannerFeed, P: TransactionPlanner<S, EffectedReceivedOutputs<S>>> Sched
|
||||
.plan_transaction_with_fee_amortization(
|
||||
// Uses 0 as there's no operating costs to incur/amortize here
|
||||
&mut 0,
|
||||
P::fee_rate(block, coin),
|
||||
block,
|
||||
vec![branch_output],
|
||||
payments,
|
||||
None,
|
||||
@@ -379,7 +379,7 @@ impl<S: ScannerFeed, P: TransactionPlanner<S, EffectedReceivedOutputs<S>>> Sched
|
||||
.planner
|
||||
.plan_transaction_with_fee_amortization(
|
||||
&mut operating_costs,
|
||||
P::fee_rate(block, coin),
|
||||
block,
|
||||
outputs,
|
||||
vec![],
|
||||
Some(to),
|
||||
@@ -505,7 +505,7 @@ impl<S: ScannerFeed, P: TransactionPlanner<S, EffectedReceivedOutputs<S>>> Sched
|
||||
// This uses 0 for the operating costs as we don't incur any here
|
||||
// If the output can't pay for itself to be forwarded, we simply drop it
|
||||
&mut 0,
|
||||
P::fee_rate(block, forward.balance().coin),
|
||||
block,
|
||||
vec![forward.clone()],
|
||||
vec![Payment::new(P::forwarding_address(forward_to_key), forward.balance(), None)],
|
||||
None,
|
||||
@@ -526,7 +526,7 @@ impl<S: ScannerFeed, P: TransactionPlanner<S, EffectedReceivedOutputs<S>>> Sched
|
||||
// This uses 0 for the operating costs as we don't incur any here
|
||||
// If the output can't pay for itself to be returned, we simply drop it
|
||||
&mut 0,
|
||||
P::fee_rate(block, out_instruction.balance().coin),
|
||||
block,
|
||||
vec![to_return.output().clone()],
|
||||
vec![out_instruction],
|
||||
None,
|
||||
|
||||
Reference in New Issue
Block a user