diff --git a/monero-adaptor/tests/integration_test.rs b/monero-adaptor/tests/integration_test.rs index c5fa5538..b8993bf6 100644 --- a/monero-adaptor/tests/integration_test.rs +++ b/monero-adaptor/tests/integration_test.rs @@ -3,7 +3,9 @@ use monero::ViewPair; use monero_harness::Monero; use monero_rpc::monerod::MonerodRpc; -use monero_wallet::{ConfidentialTransactionBuilder, MonerodClientExt}; +use monero_wallet::{ + CalculateKeyOffsetBoundaries, ConfidentialTransactionBuilder, FetchDecoyInputs, +}; use rand::{Rng, SeedableRng}; use std::convert::TryInto; use testcontainers::clients::Cli; diff --git a/monero-wallet/src/lib.rs b/monero-wallet/src/lib.rs index 547bf83b..67d45ac5 100644 --- a/monero-wallet/src/lib.rs +++ b/monero-wallet/src/lib.rs @@ -1,3 +1,5 @@ +mod v2; + use anyhow::{Context, Result}; use curve25519_dalek::constants::ED25519_BASEPOINT_POINT; use curve25519_dalek::edwards::{CompressedEdwardsY, EdwardsPoint}; @@ -278,13 +280,17 @@ fn random_array(rng: impl FnMut() -> T) -> [T } #[async_trait::async_trait] -pub trait MonerodClientExt { +pub trait CalculateKeyOffsetBoundaries { async fn calculate_key_offset_boundaries(&self) -> Result<(VarInt, VarInt)>; +} + +#[async_trait::async_trait] +pub trait FetchDecoyInputs { async fn fetch_decoy_inputs(&self, indices: [u64; 10]) -> Result<[DecoyInput; 10]>; } #[async_trait::async_trait] -impl MonerodClientExt for monerod::Client { +impl CalculateKeyOffsetBoundaries for monerod::Client { /// Chooses 10 random key offsets for use within a new confidential /// transactions. /// @@ -315,7 +321,10 @@ impl MonerodClientExt for monerod::Client { Ok((VarInt(0), VarInt(last_index))) } +} +#[async_trait::async_trait] +impl FetchDecoyInputs for monerod::Client { async fn fetch_decoy_inputs(&self, indices: [u64; 10]) -> Result<[DecoyInput; 10]> { let response = self .get_outs( @@ -403,7 +412,7 @@ mod tests { // key: todo!(), // }; // - // let (lower, upper) = wallet.calculate_key_offset_boundaries().await.unwrap(); + // let (lower, upper) = wallet.CalculateKeyOffsetBoundaries().await.unwrap(); todo!("fix"); // let result = rpc_client diff --git a/monero-wallet/src/v2.rs b/monero-wallet/src/v2.rs new file mode 100644 index 00000000..5ecb07c5 --- /dev/null +++ b/monero-wallet/src/v2.rs @@ -0,0 +1,110 @@ +use crate::{CalculateKeyOffsetBoundaries, DecoyInput, FetchDecoyInputs}; +use curve25519_dalek::edwards::EdwardsPoint; +use curve25519_dalek::scalar::Scalar; +use monero::util::ringct::Clsag; +use monero::{Address, KeyPair, OwnedTxOut, Transaction}; +use rand::{CryptoRng, RngCore}; + +pub struct EmptyTransaction {} + +impl EmptyTransaction { + pub fn spend_from(input: OwnedTxOut<'_>, global_output_index: u64) -> InputAdded { + todo!() + } +} + +pub struct InputAdded {} + +impl InputAdded { + pub fn with_static_decoy_inputs(self, decoys: [DecoyInput; 10]) -> DecoyOffsetsAdded { + todo!() + } + + pub fn with_random_decoy_inputs( + self, + rng: &mut impl RngCore, + client: &(impl FetchDecoyInputs + CalculateKeyOffsetBoundaries), + ) -> DecoyOffsetsAdded { + todo!() + } + + pub fn with_decoys_from_indices( + self, + decoy_indices: [u64; 10], + client: &(impl FetchDecoyInputs), + ) -> DecoyOffsetsAdded { + todo!() + } +} + +pub struct DecoyOffsetsAdded {} + +impl DecoyOffsetsAdded { + pub fn add_output( + self, + to: Address, + amount: u64, + rng: &mut (impl RngCore + CryptoRng), + ) -> OutputsAdded { + todo!() + } +} + +pub struct OutputsAdded {} + +impl OutputsAdded { + pub fn add_output( + self, + to: Address, + amount: u64, + rng: &mut (impl RngCore + CryptoRng), + ) -> Self { + todo!() + } + + pub fn blind_outputs(self, rng: &mut (impl RngCore + CryptoRng)) -> OutputsBlinded { + todo!() + } +} + +pub struct OutputsBlinded {} + +impl OutputsBlinded { + pub fn signature_parameters(&self) -> SignatureParameters { + todo!() + } + + /// Signs the transaction. + /// + /// This function calls the CLSAG sign algorithm with a set of parameters that will work. This however, assumes the caller does not want to have control over these parameters. + pub fn sign(self, keys: KeyPair, rng: &mut (impl RngCore + CryptoRng)) -> Transaction { + // TODO: Do we want a sign_recommended API in monero::clsag? + + todo!() + } + + /// Use the given signature for the internal transaction. + /// + /// This function is useful if the caller wants to have full control over certain parameters such as responses, L, R or I. + /// The provided signature will be validated to make sure it is correct. + pub fn with_signature(self, sig: Clsag) -> Result { + todo!() + } +} + +pub struct InvalidSignature; + +// TODO: We can break the CLSAG fn signature down into two parts: +// 1. What we see below +// 2. What an adaptor sig wants to control (signing key, alpha, L, R & I) +pub struct SignatureParameters { + message: [u8; 32], + z: Scalar, + ring: [EdwardsPoint; 11], + commitment_ring: [EdwardsPoint; 11], + // TODO: Can the adaptor sig protocol control the signing key index? + // Do we even need to control it? + // We need to know the public key to know the index. + // signing_key_index: usize, + pseudo_output_commitment: EdwardsPoint, +}