Monero prepare_send

This commit is contained in:
Luke Parker
2022-06-05 15:10:50 -04:00
parent fdb1929ba4
commit 5313210526
6 changed files with 91 additions and 31 deletions

View File

@@ -37,11 +37,11 @@ pub struct TransactionMachine {
impl SignableTransaction { impl SignableTransaction {
pub async fn multisig<R: RngCore + CryptoRng>( pub async fn multisig<R: RngCore + CryptoRng>(
mut self, mut self,
mut transcript: Transcript,
rng: &mut R, rng: &mut R,
rpc: &Rpc, rpc: &Rpc,
height: usize,
keys: MultisigKeys<Ed25519>, keys: MultisigKeys<Ed25519>,
mut transcript: Transcript,
height: usize,
mut included: Vec<u16> mut included: Vec<u16>
) -> Result<TransactionMachine, TransactionError> { ) -> Result<TransactionMachine, TransactionError> {
let mut images = vec![]; let mut images = vec![];

View File

@@ -145,11 +145,11 @@ async fn send_core(test: usize, multisig: bool) {
machines.insert( machines.insert(
i, i,
signable.clone().multisig( signable.clone().multisig(
Transcript::new(b"Monero Serai Test Transaction"),
&mut OsRng, &mut OsRng,
&rpc, &rpc,
rpc.get_height().await.unwrap() - 10,
(*keys[&i]).clone(), (*keys[&i]).clone(),
Transcript::new(b"Monero Serai Test Transaction"),
rpc.get_height().await.unwrap() - 10,
(1 ..= THRESHOLD).collect::<Vec<_>>() (1 ..= THRESHOLD).collect::<Vec<_>>()
).await.unwrap() ).await.unwrap()
); );

View File

@@ -3,20 +3,24 @@ use std::sync::Arc;
use async_trait::async_trait; use async_trait::async_trait;
use rand_core::{RngCore, CryptoRng}; 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 dalek_ff_group as dfg;
use frost::MultisigKeys; use frost::MultisigKeys;
use monero::util::address::Address; use monero::{PublicKey, network::Network, util::address::Address};
use monero_serai::{ use monero_serai::{
frost::Ed25519, frost::Ed25519,
transaction::{Timelock, Transaction}, transaction::{Timelock, Transaction},
rpc::Rpc, 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)] #[derive(Clone)]
pub struct Output(SpendableOutput); pub struct Output(SpendableOutput);
@@ -49,16 +53,26 @@ impl From<SpendableOutput> for Output {
} }
} }
pub struct SignableTransaction(
Arc<MultisigKeys<Ed25519>>,
Transcript,
usize,
MSignableTransaction
);
pub struct Monero { pub struct Monero {
rpc: Rpc, rpc: Rpc,
view: Scalar view: Scalar,
view_pub: CompressedEdwardsY
} }
impl Monero { impl Monero {
pub fn new(url: String) -> Monero { pub fn new(url: String) -> Monero {
let view = view_key::<Monero>(0).0;
Monero { Monero {
rpc: Rpc::new(url), rpc: Rpc::new(url),
view: *view_key::<Monero>(0) view,
view_pub: (&view * &ED25519_BASEPOINT_TABLE).compress()
} }
} }
} }
@@ -109,21 +123,55 @@ impl Coin for Monero {
async fn prepare_send( async fn prepare_send(
&self, &self,
_keys: Arc<MultisigKeys<Ed25519>>, keys: Arc<MultisigKeys<Ed25519>>,
_label: Vec<u8>, transcript: Transcript,
_height: usize, height: usize,
_inputs: Vec<Output>, mut inputs: Vec<Output>,
_payments: &[(Address, u64)] payments: &[(Address, u64)]
) -> Result<SignableTransaction, CoinError> { ) -> Result<SignableTransaction, CoinError> {
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<R: RngCore + CryptoRng + std::marker::Send>( async fn attempt_send<R: RngCore + CryptoRng + std::marker::Send>(
&self, &self,
_rng: &mut R, rng: &mut R,
_transaction: SignableTransaction, transaction: SignableTransaction,
_included: &[u16] included: &[u16]
) -> Result<(Vec<u8>, Vec<<Self::Output as OutputTrait>::Id>), CoinError> { ) -> Result<(Vec<u8>, Vec<<Self::Output as OutputTrait>::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![]))
} }
} }

View File

@@ -6,6 +6,8 @@ use rand_core::{RngCore, CryptoRng};
use frost::{Curve, MultisigKeys}; use frost::{Curve, MultisigKeys};
pub(crate) use monero_serai::frost::Transcript;
mod coins; mod coins;
mod wallet; mod wallet;
@@ -54,7 +56,7 @@ pub trait Coin {
async fn prepare_send( async fn prepare_send(
&self, &self,
keys: Arc<MultisigKeys<Self::Curve>>, keys: Arc<MultisigKeys<Self::Curve>>,
label: Vec<u8>, transcript: Transcript,
height: usize, height: usize,
inputs: Vec<Self::Output>, inputs: Vec<Self::Output>,
payments: &[(Self::Address, u64)] payments: &[(Self::Address, u64)]

View File

@@ -1,4 +1,4 @@
use std::rc::Rc; use std::sync::Arc;
use rand::rngs::OsRng; use rand::rngs::OsRng;
@@ -11,6 +11,6 @@ async fn test() {
let mut keys = frost::tests::key_gen::<_, <Monero as Coin>::Curve>(&mut OsRng); let mut keys = frost::tests::key_gen::<_, <Monero as Coin>::Curve>(&mut OsRng);
let mut wallet = Wallet::new(MemCoinDb::new(), monero); let mut wallet = Wallet::new(MemCoinDb::new(), monero);
wallet.acknowledge_height(0, 0); 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); dbg!(0);
} }

View File

@@ -1,9 +1,10 @@
use std::{sync::Arc, collections::HashMap}; use std::{sync::Arc, collections::HashMap};
use transcript::{Transcript, DigestTranscript}; use transcript::Transcript as TranscriptTrait;
use frost::{Curve, MultisigKeys}; use frost::{Curve, MultisigKeys};
use crate::{CoinError, Output, Coin}; use crate::{Transcript, CoinError, Output, Coin};
pub struct WalletKeys<C: Curve> { pub struct WalletKeys<C: Curve> {
keys: MultisigKeys<C>, keys: MultisigKeys<C>,
@@ -25,7 +26,7 @@ impl<C: Curve> WalletKeys<C> {
// function as well, although that degree of influence means key gen is broken already // function as well, although that degree of influence means key gen is broken already
fn bind(&self, chain: &[u8]) -> MultisigKeys<C> { fn bind(&self, chain: &[u8]) -> MultisigKeys<C> {
const DST: &[u8] = b"Serai Processor Wallet Chain Bind"; const DST: &[u8] = b"Serai Processor Wallet Chain Bind";
let mut transcript = DigestTranscript::<blake2::Blake2b512>::new(DST); let mut transcript = Transcript::new(DST);
transcript.append_message(b"chain", chain); transcript.append_message(b"chain", chain);
transcript.append_message(b"curve", C::ID); transcript.append_message(b"curve", C::ID);
transcript.append_message(b"group_key", &C::G_to_bytes(&self.keys.group_key())); transcript.append_message(b"group_key", &C::G_to_bytes(&self.keys.group_key()));
@@ -223,13 +224,22 @@ impl<D: CoinDb, C: Coin> Wallet<D, C> {
let inputs = outputs.drain(.. inputs.len()).collect(); let inputs = outputs.drain(.. inputs.len()).collect();
let payments = payments.drain(.. these_payments.len()).collect::<Vec<_>>(); let payments = payments.drain(.. these_payments.len()).collect::<Vec<_>>();
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( let tx = self.coin.prepare_send(
keys.clone(), keys.clone(),
format!( transcript,
"Serai Processor Wallet Send (height {}, index {})",
canonical,
txs.len()
).as_bytes().to_vec(),
acknowledged_height, acknowledged_height,
inputs, inputs,
&payments &payments