2022-05-28 23:56:59 +00:00
|
|
|
use std::marker::Send;
|
|
|
|
|
2022-05-26 08:36:19 +00:00
|
|
|
use async_trait::async_trait;
|
|
|
|
use thiserror::Error;
|
2022-05-28 23:56:59 +00:00
|
|
|
use rand_core::{RngCore, CryptoRng};
|
|
|
|
|
|
|
|
use blake2::{digest::{Digest, Update}, Blake2b512};
|
|
|
|
|
|
|
|
use frost::{Curve, MultisigKeys};
|
2022-05-26 08:36:19 +00:00
|
|
|
|
2022-05-28 23:56:59 +00:00
|
|
|
mod coins;
|
|
|
|
mod wallet;
|
2022-05-26 08:36:19 +00:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests;
|
|
|
|
|
2022-06-01 07:30:57 +00:00
|
|
|
pub trait Output: Sized {
|
2022-05-26 08:36:19 +00:00
|
|
|
type Id;
|
|
|
|
|
|
|
|
fn id(&self) -> Self::Id;
|
|
|
|
fn amount(&self) -> u64;
|
|
|
|
|
|
|
|
fn serialize(&self) -> Vec<u8>;
|
|
|
|
fn deserialize<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self>;
|
|
|
|
}
|
|
|
|
|
2022-05-28 23:56:59 +00:00
|
|
|
#[derive(Clone, Error, Debug)]
|
2022-06-01 07:30:57 +00:00
|
|
|
pub enum CoinError {
|
2022-05-26 08:36:19 +00:00
|
|
|
#[error("failed to connect to coin daemon")]
|
|
|
|
ConnectionError
|
|
|
|
}
|
|
|
|
|
|
|
|
#[async_trait]
|
2022-06-01 07:30:57 +00:00
|
|
|
pub trait Coin {
|
2022-05-28 23:56:59 +00:00
|
|
|
type Curve: Curve;
|
|
|
|
|
2022-05-26 08:36:19 +00:00
|
|
|
type Output: Output;
|
2022-06-01 07:30:57 +00:00
|
|
|
type Block;
|
2022-05-28 23:56:59 +00:00
|
|
|
type SignableTransaction;
|
|
|
|
|
|
|
|
type Address: Send;
|
2022-05-26 08:36:19 +00:00
|
|
|
|
2022-05-28 23:56:59 +00:00
|
|
|
fn id() -> &'static [u8];
|
2022-06-01 07:30:57 +00:00
|
|
|
fn confirmations() -> usize;
|
|
|
|
fn max_inputs() -> usize;
|
|
|
|
fn max_outputs() -> usize;
|
2022-05-26 08:36:19 +00:00
|
|
|
|
|
|
|
async fn get_height(&self) -> Result<usize, CoinError>;
|
2022-06-01 07:30:57 +00:00
|
|
|
async fn get_block(&self, height: usize) -> Result<Self::Block, CoinError>;
|
|
|
|
async fn get_outputs(
|
2022-05-26 08:36:19 +00:00
|
|
|
&self,
|
2022-06-01 07:30:57 +00:00
|
|
|
block: &Self::Block,
|
2022-05-28 23:56:59 +00:00
|
|
|
key: <Self::Curve as Curve>::G
|
2022-06-01 07:30:57 +00:00
|
|
|
) -> Vec<Self::Output>;
|
2022-05-28 23:56:59 +00:00
|
|
|
|
|
|
|
async fn prepare_send<R: RngCore + CryptoRng>(
|
|
|
|
&self,
|
|
|
|
keys: MultisigKeys<Self::Curve>,
|
|
|
|
label: Vec<u8>,
|
|
|
|
height: usize,
|
|
|
|
inputs: Vec<Self::Output>,
|
2022-05-26 08:36:19 +00:00
|
|
|
payments: &[(Self::Address, u64)]
|
2022-05-28 23:56:59 +00:00
|
|
|
) -> Result<Self::SignableTransaction, CoinError>;
|
|
|
|
|
|
|
|
async fn attempt_send<R: RngCore + CryptoRng + Send>(
|
|
|
|
&self,
|
|
|
|
rng: &mut R,
|
|
|
|
transaction: Self::SignableTransaction,
|
|
|
|
included: &[u16]
|
|
|
|
) -> Result<(Vec<u8>, Vec<<Self::Output as Output>::Id>), CoinError>;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generate a view key for a given chain in a globally consistent manner regardless of the current
|
|
|
|
// group key
|
|
|
|
// Takes an index, k, for more modern privacy protocols which use multiple view keys
|
|
|
|
// Doesn't run Curve::hash_to_F, instead returning the hash object, due to hash_to_F being a FROST
|
|
|
|
// definition instead of a wide reduction from a hash object
|
2022-06-01 07:30:57 +00:00
|
|
|
pub fn view_key<C: Coin>(k: u64) -> Blake2b512 {
|
2022-05-28 23:56:59 +00:00
|
|
|
Blake2b512::new().chain(b"Serai DEX View Key").chain(C::id()).chain(k.to_le_bytes())
|
2022-05-26 08:36:19 +00:00
|
|
|
}
|