mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-11 13:39:25 +00:00
Handle Monero fee logic properly in the processor
This commit is contained in:
@@ -181,7 +181,7 @@ async fn select_decoys<R: RngCore + CryptoRng>(
|
|||||||
|
|
||||||
// TODO: Create a TX with less than the target amount, as allowed by the protocol
|
// TODO: Create a TX with less than the target amount, as allowed by the protocol
|
||||||
let high = distribution[distribution.len() - DEFAULT_LOCK_WINDOW];
|
let high = distribution[distribution.len() - DEFAULT_LOCK_WINDOW];
|
||||||
if high.saturating_sub(COINBASE_LOCK_WINDOW as u64) <
|
if high.saturating_sub(u64::try_from(COINBASE_LOCK_WINDOW).unwrap()) <
|
||||||
u64::try_from(inputs.len() * ring_len).unwrap()
|
u64::try_from(inputs.len() * ring_len).unwrap()
|
||||||
{
|
{
|
||||||
Err(RpcError::InternalError("not enough coinbase candidates".to_string()))?;
|
Err(RpcError::InternalError("not enough coinbase candidates".to_string()))?;
|
||||||
|
|||||||
@@ -137,8 +137,8 @@ pub async fn rpc() -> SimpleRequestRpc {
|
|||||||
&Scalar::random(&mut OsRng) * ED25519_BASEPOINT_TABLE,
|
&Scalar::random(&mut OsRng) * ED25519_BASEPOINT_TABLE,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Mine 40 blocks to ensure decoy availability
|
// Mine 80 blocks to ensure decoy availability
|
||||||
rpc.generate_blocks(&addr, 40).await.unwrap();
|
rpc.generate_blocks(&addr, 80).await.unwrap();
|
||||||
|
|
||||||
rpc
|
rpc
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -244,6 +244,11 @@ fn map_rpc_err(err: RpcError) -> NetworkError {
|
|||||||
NetworkError::ConnectionError
|
NetworkError::ConnectionError
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum MakeSignableTransactionResult {
|
||||||
|
Fee(u64),
|
||||||
|
SignableTransaction(MSignableTransaction),
|
||||||
|
}
|
||||||
|
|
||||||
impl Monero {
|
impl Monero {
|
||||||
pub async fn new(url: String) -> Monero {
|
pub async fn new(url: String) -> Monero {
|
||||||
let mut res = SimpleRequestRpc::new(url.clone()).await;
|
let mut res = SimpleRequestRpc::new(url.clone()).await;
|
||||||
@@ -299,7 +304,7 @@ impl Monero {
|
|||||||
payments: &[Payment<Self>],
|
payments: &[Payment<Self>],
|
||||||
change: &Option<Address>,
|
change: &Option<Address>,
|
||||||
calculating_fee: bool,
|
calculating_fee: bool,
|
||||||
) -> Result<Option<MSignableTransaction>, NetworkError> {
|
) -> Result<Option<MakeSignableTransactionResult>, NetworkError> {
|
||||||
for payment in payments {
|
for payment in payments {
|
||||||
assert_eq!(payment.balance.coin, Coin::Monero);
|
assert_eq!(payment.balance.coin, Coin::Monero);
|
||||||
}
|
}
|
||||||
@@ -362,11 +367,7 @@ impl Monero {
|
|||||||
|
|
||||||
let payments = payments
|
let payments = payments
|
||||||
.into_iter()
|
.into_iter()
|
||||||
// If we're solely estimating the fee, don't actually specify an amount
|
.map(|payment| (payment.address.into(), payment.balance.amount.0))
|
||||||
// This won't affect the fee calculation yet will ensure we don't hit an out of funds error
|
|
||||||
.map(|payment| {
|
|
||||||
(payment.address.into(), if calculating_fee { 0 } else { payment.balance.amount.0 })
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
match MSignableTransaction::new(
|
match MSignableTransaction::new(
|
||||||
@@ -379,7 +380,13 @@ impl Monero {
|
|||||||
vec![],
|
vec![],
|
||||||
fee_rate,
|
fee_rate,
|
||||||
) {
|
) {
|
||||||
Ok(signable) => Ok(Some(signable)),
|
Ok(signable) => Ok(Some({
|
||||||
|
if calculating_fee {
|
||||||
|
MakeSignableTransactionResult::Fee(signable.fee())
|
||||||
|
} else {
|
||||||
|
MakeSignableTransactionResult::SignableTransaction(signable)
|
||||||
|
}
|
||||||
|
})),
|
||||||
Err(e) => match e {
|
Err(e) => match e {
|
||||||
SendError::UnsupportedRctType => {
|
SendError::UnsupportedRctType => {
|
||||||
panic!("trying to use an RctType unsupported by monero-wallet")
|
panic!("trying to use an RctType unsupported by monero-wallet")
|
||||||
@@ -403,8 +410,24 @@ impl Monero {
|
|||||||
inputs,
|
inputs,
|
||||||
outputs
|
outputs
|
||||||
);
|
);
|
||||||
|
match fee {
|
||||||
|
Some(fee) => {
|
||||||
|
// If we're solely calculating the fee, return the fee this TX will cost
|
||||||
|
if calculating_fee {
|
||||||
|
Ok(Some(MakeSignableTransactionResult::Fee(fee)))
|
||||||
|
} else {
|
||||||
|
// If we're actually trying to make the TX, return None
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// We didn't have enough funds to even cover the outputs
|
||||||
|
None => {
|
||||||
|
// Ensure we're not misinterpreting this
|
||||||
|
assert!(outputs > inputs);
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
SendError::MaliciousSerialization | SendError::ClsagError(_) | SendError::FrostError(_) => {
|
SendError::MaliciousSerialization | SendError::ClsagError(_) | SendError::FrostError(_) => {
|
||||||
panic!("supposedly unreachable (at this time) Monero error: {e}");
|
panic!("supposedly unreachable (at this time) Monero error: {e}");
|
||||||
}
|
}
|
||||||
@@ -594,12 +617,14 @@ impl Network for Monero {
|
|||||||
payments: &[Payment<Self>],
|
payments: &[Payment<Self>],
|
||||||
change: &Option<Address>,
|
change: &Option<Address>,
|
||||||
) -> Result<Option<u64>, NetworkError> {
|
) -> Result<Option<u64>, NetworkError> {
|
||||||
Ok(
|
let res = self
|
||||||
self
|
|
||||||
.make_signable_transaction(block_number, &[0; 32], inputs, payments, change, true)
|
.make_signable_transaction(block_number, &[0; 32], inputs, payments, change, true)
|
||||||
.await?
|
.await?;
|
||||||
.map(|signable| signable.fee()),
|
let Some(res) = res else { return Ok(None) };
|
||||||
)
|
let MakeSignableTransactionResult::Fee(fee) = res else {
|
||||||
|
panic!("told make_signable_transaction calculating_fee and got transaction")
|
||||||
|
};
|
||||||
|
Ok(Some(fee))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn signable_transaction(
|
async fn signable_transaction(
|
||||||
@@ -612,16 +637,17 @@ impl Network for Monero {
|
|||||||
change: &Option<Address>,
|
change: &Option<Address>,
|
||||||
(): &(),
|
(): &(),
|
||||||
) -> Result<Option<(Self::SignableTransaction, Self::Eventuality)>, NetworkError> {
|
) -> Result<Option<(Self::SignableTransaction, Self::Eventuality)>, NetworkError> {
|
||||||
Ok(
|
let res = self
|
||||||
self
|
|
||||||
.make_signable_transaction(block_number, plan_id, inputs, payments, change, false)
|
.make_signable_transaction(block_number, plan_id, inputs, payments, change, false)
|
||||||
.await?
|
.await?;
|
||||||
.map(|signable| {
|
let Some(res) = res else { return Ok(None) };
|
||||||
|
let MakeSignableTransactionResult::SignableTransaction(signable) = res else {
|
||||||
|
panic!("told make_signable_transaction not calculating_fee and got fee")
|
||||||
|
};
|
||||||
|
|
||||||
let signable = SignableTransaction(signable);
|
let signable = SignableTransaction(signable);
|
||||||
let eventuality = signable.0.clone().into();
|
let eventuality = signable.0.clone().into();
|
||||||
(signable, eventuality)
|
Ok(Some((signable, eventuality)))
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn attempt_sign(
|
async fn attempt_sign(
|
||||||
|
|||||||
Reference in New Issue
Block a user