xmr-btc-swap/monero-wallet/src/lib.rs
2021-05-11 11:47:20 +10:00

109 lines
3.5 KiB
Rust

use anyhow::{Context, Result};
use monero::consensus::encode::VarInt;
use monero::cryptonote::hash::Hashable;
use monero_rpc::monerod;
use monero_rpc::monerod::{GetBlockResponse, MonerodRpc as _};
use rand::{CryptoRng, RngCore};
pub struct Wallet {
key: monero::KeyPair,
}
impl Wallet {
pub fn new_random<R: CryptoRng + RngCore>(rng: &mut R) -> Self {
Self {
key: monero::KeyPair {
view: monero::PrivateKey::from_scalar(curve25519_dalek::scalar::Scalar::random(
rng,
)),
spend: monero::PrivateKey::from_scalar(curve25519_dalek::scalar::Scalar::random(
rng,
)),
},
}
}
pub fn get_address(&self, network: monero::Network) -> monero::Address {
monero::Address::from_keypair(network, &self.key)
}
}
#[async_trait::async_trait]
pub trait MonerodClientExt {
async fn calculate_key_offset_boundaries(&self) -> Result<(VarInt, VarInt)>;
}
#[async_trait::async_trait]
impl MonerodClientExt for monerod::Client {
/// Chooses 10 random key offsets for use within a new confidential
/// transactions.
///
/// Choosing these offsets randomly is not ideal for privacy, instead they
/// should be chosen in a way that mimics a real spending pattern as much as
/// possible.
async fn calculate_key_offset_boundaries(&self) -> Result<(VarInt, VarInt)> {
let latest_block = self.get_block_count().await?;
let latest_spendable_block = latest_block.count - 50;
let block: GetBlockResponse = self.get_block(latest_spendable_block).await?;
let tx_hash = block
.blob
.tx_hashes
.first()
.copied()
.unwrap_or_else(|| block.blob.miner_tx.hash());
let indices = self.get_o_indexes(tx_hash).await?;
let last_index = indices
.o_indexes
.into_iter()
.max()
.context("Expected at least one output index")?;
// let oldest_index = last_index - (last_index / 100) * 40; // oldest index must be within last 40% TODO: CONFIRM THIS
Ok((VarInt(0), VarInt(last_index)))
}
}
#[cfg(test)]
mod tests {
use super::*;
use monero_harness::image::Monerod;
use monero_rpc::monerod::Client;
use testcontainers::clients::Cli;
use testcontainers::Docker;
#[tokio::test]
async fn get_outs_for_key_offsets() {
let cli = Cli::default();
let container = cli.run(Monerod::default());
let rpc_client = Client::localhost(container.get_host_port(18081).unwrap()).unwrap();
rpc_client.generateblocks(150, "498AVruCDWgP9Az9LjMm89VWjrBrSZ2W2K3HFBiyzzrRjUJWUcCVxvY1iitfuKoek2FdX6MKGAD9Qb1G1P8QgR5jPmmt3Vj".to_owned()).await.unwrap();
// let wallet = Wallet {
// client: rpc_client.clone(),
// key: todo!(),
// };
//
// let (lower, upper) = wallet.calculate_key_offset_boundaries().await.unwrap();
todo!("fix");
// let result = rpc_client
// .get_outs(
// key_offsets
// .to_vec()
// .into_iter()
// .map(|varint| GetOutputsOut {
// amount: 0,
// index: varint.0,
// })
// .collect(),
// )
// .await
// .unwrap();
// assert_eq!(result.outs.len(), 10);
}
}