mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-11 13:39:25 +00:00
Monero Planner
Finishes the Monero processor.
This commit is contained in:
@@ -41,3 +41,149 @@ async fn main() {
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
/*
|
||||
#[async_trait]
|
||||
impl TransactionTrait<Monero> for Transaction {
|
||||
#[cfg(test)]
|
||||
async fn fee(&self, _: &Monero) -> u64 {
|
||||
match self {
|
||||
Transaction::V1 { .. } => panic!("v1 TX in test-only function"),
|
||||
Transaction::V2 { ref proofs, .. } => proofs.as_ref().unwrap().base.fee,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Monero {
|
||||
async fn median_fee(&self, block: &Block) -> Result<FeeRate, NetworkError> {
|
||||
let mut fees = vec![];
|
||||
for tx_hash in &block.transactions {
|
||||
let tx =
|
||||
self.rpc.get_transaction(*tx_hash).await.map_err(|_| NetworkError::ConnectionError)?;
|
||||
// Only consider fees from RCT transactions, else the fee property read wouldn't be accurate
|
||||
let fee = match &tx {
|
||||
Transaction::V2 { proofs: Some(proofs), .. } => proofs.base.fee,
|
||||
_ => continue,
|
||||
};
|
||||
fees.push(fee / u64::try_from(tx.weight()).unwrap());
|
||||
}
|
||||
fees.sort();
|
||||
let fee = fees.get(fees.len() / 2).copied().unwrap_or(0);
|
||||
|
||||
// TODO: Set a sane minimum fee
|
||||
const MINIMUM_FEE: u64 = 1_500_000;
|
||||
Ok(FeeRate::new(fee.max(MINIMUM_FEE), 10000).unwrap())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn test_view_pair() -> ViewPair {
|
||||
ViewPair::new(*EdwardsPoint::generator(), Zeroizing::new(Scalar::ONE.0)).unwrap()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn test_scanner() -> Scanner {
|
||||
Scanner::new(Self::test_view_pair())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn test_address() -> Address {
|
||||
Address::new(Self::test_view_pair().legacy_address(MoneroNetwork::Mainnet)).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Network for Monero {
|
||||
#[cfg(test)]
|
||||
async fn get_block_number(&self, id: &[u8; 32]) -> usize {
|
||||
self.rpc.get_block(*id).await.unwrap().number().unwrap()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
async fn get_transaction_by_eventuality(
|
||||
&self,
|
||||
block: usize,
|
||||
eventuality: &Eventuality,
|
||||
) -> Transaction {
|
||||
let block = self.rpc.get_block_by_number(block).await.unwrap();
|
||||
for tx in &block.transactions {
|
||||
let tx = self.rpc.get_transaction(*tx).await.unwrap();
|
||||
if eventuality.matches(&tx.clone().into()) {
|
||||
return tx;
|
||||
}
|
||||
}
|
||||
panic!("block didn't have a transaction for this eventuality")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
async fn mine_block(&self) {
|
||||
// https://github.com/serai-dex/serai/issues/198
|
||||
sleep(std::time::Duration::from_millis(100)).await;
|
||||
self.rpc.generate_blocks(&Self::test_address().into(), 1).await.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
async fn test_send(&self, address: Address) -> Block {
|
||||
use zeroize::Zeroizing;
|
||||
use rand_core::{RngCore, OsRng};
|
||||
use monero_wallet::rpc::FeePriority;
|
||||
|
||||
let new_block = self.get_latest_block_number().await.unwrap() + 1;
|
||||
for _ in 0 .. 80 {
|
||||
self.mine_block().await;
|
||||
}
|
||||
|
||||
let new_block = self.rpc.get_block_by_number(new_block).await.unwrap();
|
||||
let mut outputs = Self::test_scanner()
|
||||
.scan(self.rpc.get_scannable_block(new_block.clone()).await.unwrap())
|
||||
.unwrap()
|
||||
.ignore_additional_timelock();
|
||||
let output = outputs.swap_remove(0);
|
||||
|
||||
let amount = output.commitment().amount;
|
||||
// The dust should always be sufficient for the fee
|
||||
let fee = Monero::DUST;
|
||||
|
||||
let rct_type = match new_block.header.hardfork_version {
|
||||
14 => RctType::ClsagBulletproof,
|
||||
15 | 16 => RctType::ClsagBulletproofPlus,
|
||||
_ => panic!("Monero hard forked and the processor wasn't updated for it"),
|
||||
};
|
||||
|
||||
let output = OutputWithDecoys::fingerprintable_deterministic_new(
|
||||
&mut OsRng,
|
||||
&self.rpc,
|
||||
match rct_type {
|
||||
RctType::ClsagBulletproof => 11,
|
||||
RctType::ClsagBulletproofPlus => 16,
|
||||
_ => panic!("selecting decoys for an unsupported RctType"),
|
||||
},
|
||||
self.rpc.get_height().await.unwrap(),
|
||||
output,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let mut outgoing_view_key = Zeroizing::new([0; 32]);
|
||||
OsRng.fill_bytes(outgoing_view_key.as_mut());
|
||||
let tx = MSignableTransaction::new(
|
||||
rct_type,
|
||||
outgoing_view_key,
|
||||
vec![output],
|
||||
vec![(address.into(), amount - fee)],
|
||||
Change::fingerprintable(Some(Self::test_address().into())),
|
||||
vec![],
|
||||
self.rpc.get_fee_rate(FeePriority::Unimportant).await.unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
.sign(&mut OsRng, &Zeroizing::new(Scalar::ONE.0))
|
||||
.unwrap();
|
||||
|
||||
let block = self.get_latest_block_number().await.unwrap() + 1;
|
||||
self.rpc.publish_transaction(&tx).await.unwrap();
|
||||
for _ in 0 .. 10 {
|
||||
self.mine_block().await;
|
||||
}
|
||||
self.get_block(block).await.unwrap()
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user