Sketch initial type-level state machine for signing Monero transactions

This commit is contained in:
Thomas Eizinger 2021-05-17 19:08:26 +10:00
parent 702e1767c7
commit 25c4a5a9b9
No known key found for this signature in database
GPG Key ID: 651AC83A6C6C8B96
3 changed files with 125 additions and 4 deletions

View File

@ -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;

View File

@ -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<T: Default + Copy, const N: usize>(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

110
monero-wallet/src/v2.rs Normal file
View File

@ -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<Transaction, InvalidSignature> {
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,
}