From 53132105262ca84e215b3a05d8f8a90edb236ecd Mon Sep 17 00:00:00 2001 From: Luke Parker Date: Sun, 5 Jun 2022 15:10:50 -0400 Subject: [PATCH] Monero prepare_send --- coins/monero/src/wallet/send/multisig.rs | 4 +- coins/monero/tests/send.rs | 4 +- processor/src/coins/monero.rs | 80 +++++++++++++++++++----- processor/src/lib.rs | 4 +- processor/src/tests/mod.rs | 4 +- processor/src/wallet.rs | 26 +++++--- 6 files changed, 91 insertions(+), 31 deletions(-) diff --git a/coins/monero/src/wallet/send/multisig.rs b/coins/monero/src/wallet/send/multisig.rs index e1ac0f10..02c3e4ff 100644 --- a/coins/monero/src/wallet/send/multisig.rs +++ b/coins/monero/src/wallet/send/multisig.rs @@ -37,11 +37,11 @@ pub struct TransactionMachine { impl SignableTransaction { pub async fn multisig( mut self, - mut transcript: Transcript, rng: &mut R, rpc: &Rpc, - height: usize, keys: MultisigKeys, + mut transcript: Transcript, + height: usize, mut included: Vec ) -> Result { let mut images = vec![]; diff --git a/coins/monero/tests/send.rs b/coins/monero/tests/send.rs index a50ffd33..dd95c5b4 100644 --- a/coins/monero/tests/send.rs +++ b/coins/monero/tests/send.rs @@ -145,11 +145,11 @@ async fn send_core(test: usize, multisig: bool) { machines.insert( i, signable.clone().multisig( - Transcript::new(b"Monero Serai Test Transaction"), &mut OsRng, &rpc, - rpc.get_height().await.unwrap() - 10, (*keys[&i]).clone(), + Transcript::new(b"Monero Serai Test Transaction"), + rpc.get_height().await.unwrap() - 10, (1 ..= THRESHOLD).collect::>() ).await.unwrap() ); diff --git a/processor/src/coins/monero.rs b/processor/src/coins/monero.rs index da5d6ac4..2b694984 100644 --- a/processor/src/coins/monero.rs +++ b/processor/src/coins/monero.rs @@ -3,20 +3,24 @@ use std::sync::Arc; use async_trait::async_trait; use rand_core::{RngCore, CryptoRng}; -use curve25519_dalek::{scalar::Scalar, edwards::CompressedEdwardsY}; +use curve25519_dalek::{ + constants::ED25519_BASEPOINT_TABLE, + scalar::Scalar, + edwards::CompressedEdwardsY +}; use dalek_ff_group as dfg; use frost::MultisigKeys; -use monero::util::address::Address; +use monero::{PublicKey, network::Network, util::address::Address}; use monero_serai::{ frost::Ed25519, transaction::{Timelock, Transaction}, rpc::Rpc, - wallet::{SpendableOutput, SignableTransaction} + wallet::{SpendableOutput, SignableTransaction as MSignableTransaction} }; -use crate::{Output as OutputTrait, CoinError, Coin, view_key}; +use crate::{Transcript, Output as OutputTrait, CoinError, Coin, view_key}; #[derive(Clone)] pub struct Output(SpendableOutput); @@ -49,16 +53,26 @@ impl From for Output { } } +pub struct SignableTransaction( + Arc>, + Transcript, + usize, + MSignableTransaction +); + pub struct Monero { rpc: Rpc, - view: Scalar + view: Scalar, + view_pub: CompressedEdwardsY } impl Monero { pub fn new(url: String) -> Monero { + let view = view_key::(0).0; Monero { rpc: Rpc::new(url), - view: *view_key::(0) + view, + view_pub: (&view * &ED25519_BASEPOINT_TABLE).compress() } } } @@ -109,21 +123,55 @@ impl Coin for Monero { async fn prepare_send( &self, - _keys: Arc>, - _label: Vec, - _height: usize, - _inputs: Vec, - _payments: &[(Address, u64)] + keys: Arc>, + transcript: Transcript, + height: usize, + mut inputs: Vec, + payments: &[(Address, u64)] ) -> Result { - todo!() + let spend = keys.group_key().0.compress(); + Ok( + SignableTransaction( + keys, + transcript, + height, + MSignableTransaction::new( + inputs.drain(..).map(|input| input.0).collect(), + payments.to_vec(), + Address::standard( + Network::Mainnet, + PublicKey { point: spend }, + PublicKey { point: self.view_pub } + ), + 100000000 + ).map_err(|_| CoinError::ConnectionError)? + ) + ) } async fn attempt_send( &self, - _rng: &mut R, - _transaction: SignableTransaction, - _included: &[u16] + rng: &mut R, + transaction: SignableTransaction, + included: &[u16] ) -> Result<(Vec, Vec<::Id>), CoinError> { - todo!() + let attempt = transaction.3.clone().multisig( + rng, + &self.rpc, + (*transaction.0).clone(), + transaction.1.clone(), + transaction.2, + included.to_vec() + ).await.map_err(|_| CoinError::ConnectionError)?; + + /* + let tx = None; + self.rpc.publish_transaction(tx).await.map_err(|_| CoinError::ConnectionError)?; + Ok( + tx.hash().to_vec(), + tx.outputs.iter().map(|output| output.key.compress().to_bytes().collect()) + ) + */ + Ok((vec![], vec![])) } } diff --git a/processor/src/lib.rs b/processor/src/lib.rs index 9357bd06..337a409f 100644 --- a/processor/src/lib.rs +++ b/processor/src/lib.rs @@ -6,6 +6,8 @@ use rand_core::{RngCore, CryptoRng}; use frost::{Curve, MultisigKeys}; +pub(crate) use monero_serai::frost::Transcript; + mod coins; mod wallet; @@ -54,7 +56,7 @@ pub trait Coin { async fn prepare_send( &self, keys: Arc>, - label: Vec, + transcript: Transcript, height: usize, inputs: Vec, payments: &[(Self::Address, u64)] diff --git a/processor/src/tests/mod.rs b/processor/src/tests/mod.rs index 02c8180d..abc338d3 100644 --- a/processor/src/tests/mod.rs +++ b/processor/src/tests/mod.rs @@ -1,4 +1,4 @@ -use std::rc::Rc; +use std::sync::Arc; use rand::rngs::OsRng; @@ -11,6 +11,6 @@ async fn test() { let mut keys = frost::tests::key_gen::<_, ::Curve>(&mut OsRng); let mut wallet = Wallet::new(MemCoinDb::new(), monero); wallet.acknowledge_height(0, 0); - wallet.add_keys(&WalletKeys::new(Rc::try_unwrap(keys.remove(&1).take().unwrap()).unwrap(), 0)); + wallet.add_keys(&WalletKeys::new(Arc::try_unwrap(keys.remove(&1).take().unwrap()).unwrap(), 0)); dbg!(0); } diff --git a/processor/src/wallet.rs b/processor/src/wallet.rs index 0c5b66a9..25514ce8 100644 --- a/processor/src/wallet.rs +++ b/processor/src/wallet.rs @@ -1,9 +1,10 @@ use std::{sync::Arc, collections::HashMap}; -use transcript::{Transcript, DigestTranscript}; +use transcript::Transcript as TranscriptTrait; + use frost::{Curve, MultisigKeys}; -use crate::{CoinError, Output, Coin}; +use crate::{Transcript, CoinError, Output, Coin}; pub struct WalletKeys { keys: MultisigKeys, @@ -25,7 +26,7 @@ impl WalletKeys { // function as well, although that degree of influence means key gen is broken already fn bind(&self, chain: &[u8]) -> MultisigKeys { const DST: &[u8] = b"Serai Processor Wallet Chain Bind"; - let mut transcript = DigestTranscript::::new(DST); + let mut transcript = Transcript::new(DST); transcript.append_message(b"chain", chain); transcript.append_message(b"curve", C::ID); transcript.append_message(b"group_key", &C::G_to_bytes(&self.keys.group_key())); @@ -223,13 +224,22 @@ impl Wallet { let inputs = outputs.drain(.. inputs.len()).collect(); let payments = payments.drain(.. these_payments.len()).collect::>(); + let mut transcript = Transcript::new(b"Serai Processor Wallet Send"); + transcript.append_message( + b"canonical_height", + &u64::try_from(canonical).unwrap().to_le_bytes() + ); + transcript.append_message( + b"acknowledged_height", + &u64::try_from(acknowledged_height).unwrap().to_le_bytes() + ); + transcript.append_message( + b"index", + &u64::try_from(txs.len()).unwrap().to_le_bytes() + ); let tx = self.coin.prepare_send( keys.clone(), - format!( - "Serai Processor Wallet Send (height {}, index {})", - canonical, - txs.len() - ).as_bytes().to_vec(), + transcript, acknowledged_height, inputs, &payments