mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-04-28 03:00:18 -04:00
Use the new keypair module throughout the codebase.
This commit is contained in:
@@ -7,7 +7,7 @@ use clap::clap_app;
|
||||
use easy_parallel::Parallel;
|
||||
use incrementalmerkletree::bridgetree::BridgeTree;
|
||||
use log::{debug, info};
|
||||
use pasta_curves::pallas;
|
||||
use rand::rngs::OsRng;
|
||||
use serde_json::{json, Value};
|
||||
|
||||
use drk::{
|
||||
@@ -15,7 +15,11 @@ use drk::{
|
||||
circuit::{MintContract, SpendContract},
|
||||
cli::{CashierdConfig, Config},
|
||||
client::Client,
|
||||
crypto::{merkle_node::MerkleNode, proof::VerifyingKey, schnorr},
|
||||
crypto::{
|
||||
keypair::{PublicKey, SecretKey},
|
||||
merkle_node::MerkleNode,
|
||||
proof::VerifyingKey,
|
||||
},
|
||||
rpc::{
|
||||
jsonrpc::{error as jsonerr, response as jsonresp, ErrorCode::*, JsonRequest, JsonResult},
|
||||
rpcserver::{listen_and_serve, RequestHandler, RpcServerConfig},
|
||||
@@ -25,7 +29,10 @@ use drk::{
|
||||
state::State,
|
||||
types::DrkTokenId,
|
||||
util::{expand_path, generate_id, join_config_path, parse::truncate, NetworkName},
|
||||
wallet::{cashierdb::TokenKey, CashierDb, WalletDb},
|
||||
wallet::{
|
||||
cashierdb::{CashierDb, TokenKey},
|
||||
walletdb::WalletDb,
|
||||
},
|
||||
Error, Result,
|
||||
};
|
||||
|
||||
@@ -103,7 +110,7 @@ impl Cashierd {
|
||||
async fn listen_for_receiving_coins(
|
||||
bridge: Arc<Bridge>,
|
||||
cashier_wallet: Arc<CashierDb>,
|
||||
recv_coin: async_channel::Receiver<(pallas::Point, u64)>,
|
||||
recv_coin: async_channel::Receiver<(PublicKey, u64)>,
|
||||
executor: Arc<Executor<'_>>,
|
||||
) -> Result<()> {
|
||||
// received drk coin
|
||||
@@ -208,7 +215,7 @@ impl Cashierd {
|
||||
mint_address = "";
|
||||
}
|
||||
let drk_pub_key = bs58::decode(&drk_pub_key).into_vec()?;
|
||||
let drk_pub_key: pallas::Point = deserialize(&drk_pub_key)?;
|
||||
let drk_pub_key: PublicKey = deserialize(&drk_pub_key)?;
|
||||
|
||||
// check if the drk public key already exist
|
||||
let check = self
|
||||
@@ -336,7 +343,7 @@ impl Cashierd {
|
||||
|
||||
let address = serialize(&address.to_string());
|
||||
|
||||
let cashier_public: pallas::Point;
|
||||
let cashier_public: PublicKey;
|
||||
|
||||
if let Some(addr) = self
|
||||
.cashier_wallet
|
||||
@@ -345,14 +352,14 @@ impl Cashierd {
|
||||
{
|
||||
cashier_public = addr.public;
|
||||
} else {
|
||||
let cashier_secret = schnorr::SecretKey::random();
|
||||
cashier_public = cashier_secret.public_key().inner();
|
||||
let cashier_secret = SecretKey::random(&mut OsRng);
|
||||
cashier_public = PublicKey::from_secret(cashier_secret);
|
||||
|
||||
self.cashier_wallet
|
||||
.put_withdraw_keys(
|
||||
&address,
|
||||
&cashier_public,
|
||||
&cashier_secret.inner(),
|
||||
&cashier_secret,
|
||||
&network,
|
||||
&token_id,
|
||||
mint_address.into(),
|
||||
@@ -601,7 +608,7 @@ impl Cashierd {
|
||||
|
||||
client.start().await?;
|
||||
|
||||
let (notify, recv_coin) = async_channel::unbounded::<(pallas::Point, u64)>();
|
||||
let (notify, recv_coin) = async_channel::unbounded::<(PublicKey, u64)>();
|
||||
|
||||
client
|
||||
.connect_to_subscriber_from_cashier(
|
||||
@@ -703,9 +710,9 @@ async fn start(
|
||||
tree: BridgeTree::<MerkleNode, 32>::new(100),
|
||||
merkle_roots,
|
||||
nullifiers,
|
||||
public_keys: cashier_public_keys,
|
||||
mint_vk,
|
||||
spend_vk,
|
||||
public_keys: cashier_public_keys,
|
||||
}));
|
||||
|
||||
if get_address_flag {
|
||||
|
||||
@@ -17,7 +17,7 @@ use drk::{
|
||||
circuit::{MintContract, SpendContract},
|
||||
cli::{Config, DarkfidConfig},
|
||||
client::Client,
|
||||
crypto::{merkle_node::MerkleNode, proof::VerifyingKey},
|
||||
crypto::{keypair::PublicKey, merkle_node::MerkleNode, proof::VerifyingKey},
|
||||
rpc::{
|
||||
jsonrpc::{
|
||||
error as jsonerr, request as jsonreq, response as jsonresp, send_raw_request,
|
||||
@@ -31,7 +31,7 @@ use drk::{
|
||||
assign_id, decode_base10, encode_base10, expand_path, join_config_path, DrkTokenList,
|
||||
NetworkName, TokenList,
|
||||
},
|
||||
wallet::WalletDb,
|
||||
wallet::walletdb::WalletDb,
|
||||
Error, Result,
|
||||
};
|
||||
|
||||
@@ -39,7 +39,7 @@ use drk::{
|
||||
pub struct Cashier {
|
||||
pub name: String,
|
||||
pub rpc_url: String,
|
||||
pub public_key: pallas::Point,
|
||||
pub public_key: PublicKey,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
@@ -424,7 +424,7 @@ impl Darkfid {
|
||||
let result: Result<()> = async {
|
||||
let cashier_public = cashier_public.result.as_str().unwrap();
|
||||
|
||||
let cashier_public: pallas::Point =
|
||||
let cashier_public: PublicKey =
|
||||
deserialize(&bs58::decode(cashier_public).into_vec()?)?;
|
||||
|
||||
self.client
|
||||
@@ -509,7 +509,7 @@ impl Darkfid {
|
||||
|
||||
let result: Result<()> = async {
|
||||
let drk_address = bs58::decode(&address).into_vec()?;
|
||||
let drk_address: pallas::Point = deserialize(&drk_address)?;
|
||||
let drk_address: PublicKey = deserialize(&drk_address)?;
|
||||
|
||||
let decimals: usize = 8;
|
||||
let amount = decode_base10(amount, decimals, true)?;
|
||||
@@ -546,7 +546,7 @@ async fn start(
|
||||
let mut cashier_keys = Vec::new();
|
||||
|
||||
if let Some(cpub) = local_cashier {
|
||||
let cashier_public: pallas::Point = deserialize(&bs58::decode(cpub).into_vec()?)?;
|
||||
let cashier_public: PublicKey = deserialize(&bs58::decode(cpub).into_vec()?)?;
|
||||
|
||||
cashiers.push(Cashier {
|
||||
name: "localCashier".into(),
|
||||
@@ -561,7 +561,7 @@ async fn start(
|
||||
return Err(Error::CashierKeysNotFound)
|
||||
}
|
||||
|
||||
let cashier_public: pallas::Point =
|
||||
let cashier_public: PublicKey =
|
||||
deserialize(&bs58::decode(cashier.public_key).into_vec()?)?;
|
||||
|
||||
cashiers.push(Cashier {
|
||||
|
||||
@@ -6,12 +6,11 @@ use drk::{
|
||||
circuit::{mint_contract::MintContract, spend_contract::SpendContract},
|
||||
crypto::{
|
||||
coin::Coin,
|
||||
keypair::Keypair,
|
||||
keypair::{Keypair, PublicKey, SecretKey},
|
||||
merkle_node::MerkleNode,
|
||||
note::{EncryptedNote, Note},
|
||||
nullifier::Nullifier,
|
||||
proof::VerifyingKey,
|
||||
schnorr,
|
||||
},
|
||||
state::{state_transition, ProgramState, StateUpdate},
|
||||
tx, Result,
|
||||
@@ -35,13 +34,13 @@ struct MemoryState {
|
||||
spend_vk: VerifyingKey,
|
||||
|
||||
// Public key of the cashier
|
||||
cashier_signature_public: schnorr::PublicKey,
|
||||
cashier_signature_public: PublicKey,
|
||||
// List of all our secret keys
|
||||
secrets: Vec<pallas::Base>,
|
||||
secrets: Vec<SecretKey>,
|
||||
}
|
||||
|
||||
impl ProgramState for MemoryState {
|
||||
fn is_valid_cashier_public_key(&self, public: &schnorr::PublicKey) -> bool {
|
||||
fn is_valid_cashier_public_key(&self, public: &PublicKey) -> bool {
|
||||
public == &self.cashier_signature_public
|
||||
}
|
||||
|
||||
@@ -73,7 +72,7 @@ impl MemoryState {
|
||||
let node = MerkleNode(coin.0);
|
||||
self.tree.append(&node);
|
||||
|
||||
//// Keep track of all merkle roots that have existed
|
||||
// Keep track of all merkle roots that have existed
|
||||
self.merkle_roots.push(self.tree.root());
|
||||
|
||||
if let Some((note, _secret)) = self.try_decrypt_note(enc_note) {
|
||||
@@ -83,7 +82,7 @@ impl MemoryState {
|
||||
}
|
||||
}
|
||||
|
||||
fn try_decrypt_note(&self, ciphertext: EncryptedNote) -> Option<(Note, pallas::Base)> {
|
||||
fn try_decrypt_note(&self, ciphertext: EncryptedNote) -> Option<(Note, SecretKey)> {
|
||||
// Loop through all our secret keys...
|
||||
for secret in &self.secrets {
|
||||
// ... attempt to decrypt the note ...
|
||||
@@ -98,8 +97,8 @@ impl MemoryState {
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let cashier_signature_secret = schnorr::SecretKey::random();
|
||||
let cashier_signature_public = cashier_signature_secret.public_key();
|
||||
let cashier_signature_secret = SecretKey::random(&mut OsRng);
|
||||
let cashier_signature_public = PublicKey::from_secret(cashier_signature_secret);
|
||||
|
||||
let keypair = Keypair::random(&mut OsRng);
|
||||
|
||||
@@ -115,7 +114,7 @@ fn main() -> Result<()> {
|
||||
mint_vk,
|
||||
spend_vk,
|
||||
cashier_signature_public,
|
||||
secrets: vec![keypair.secret.inner()],
|
||||
secrets: vec![keypair.secret],
|
||||
};
|
||||
|
||||
let token_id = pallas::Base::from(110);
|
||||
@@ -130,7 +129,7 @@ fn main() -> Result<()> {
|
||||
outputs: vec![tx::TransactionBuilderOutputInfo {
|
||||
value: 110,
|
||||
token_id,
|
||||
public: keypair.public.inner(),
|
||||
public: keypair.public,
|
||||
}],
|
||||
};
|
||||
|
||||
@@ -138,7 +137,7 @@ fn main() -> Result<()> {
|
||||
|
||||
tx.verify(&state.mint_vk, &state.spend_vk).expect("tx verify");
|
||||
|
||||
let _note = tx.outputs[0].enc_note.decrypt(&keypair.secret.inner())?;
|
||||
let _note = tx.outputs[0].enc_note.decrypt(&keypair.secret)?;
|
||||
|
||||
let update = state_transition(&state, tx)?;
|
||||
state.apply(update);
|
||||
@@ -153,13 +152,13 @@ fn main() -> Result<()> {
|
||||
inputs: vec![tx::TransactionBuilderInputInfo {
|
||||
leaf_position,
|
||||
merkle_path,
|
||||
secret: keypair.secret.inner(),
|
||||
secret: keypair.secret,
|
||||
note: note.clone(),
|
||||
}],
|
||||
outputs: vec![tx::TransactionBuilderOutputInfo {
|
||||
value: 110,
|
||||
token_id,
|
||||
public: keypair.public.inner(),
|
||||
public: keypair.public,
|
||||
}],
|
||||
};
|
||||
|
||||
|
||||
@@ -102,7 +102,8 @@ pub struct SpendContract {
|
||||
pub asset_blind: Option<pallas::Scalar>,
|
||||
pub leaf_pos: Option<u32>,
|
||||
pub merkle_path: Option<[pallas::Base; 32]>,
|
||||
pub sig_secret: Option<pallas::Scalar>,
|
||||
//pub sig_secret: Option<pallas::Scalar>,
|
||||
pub sig_secret: Option<pallas::Base>,
|
||||
}
|
||||
|
||||
impl UtilitiesInstructions<pallas::Base> for SpendContract {
|
||||
@@ -442,11 +443,16 @@ impl Circuit<pallas::Base> for SpendContract {
|
||||
// ========================
|
||||
// Signature key derivation
|
||||
// ========================
|
||||
let (sig_pub, _) = {
|
||||
let spend_auth_g = OrchardFixedBases::SpendAuthG;
|
||||
let spend_auth_g = FixedPoint::from_inner(ecc_chip, spend_auth_g);
|
||||
// TODO: Do we need to load sig_secret somewhere first?
|
||||
spend_auth_g.mul(layouter.namespace(|| "[x_s] SpendAuthG"), self.sig_secret)?
|
||||
let sig_secret = self.load_private(
|
||||
layouter.namespace(|| "load sig_secret"),
|
||||
config.advices[0],
|
||||
self.sig_secret,
|
||||
)?;
|
||||
|
||||
let sig_pub = {
|
||||
let nullifier_k = OrchardFixedBases::NullifierK;
|
||||
let nullifier_k = FixedPoint::from_inner(ecc_chip.clone(), nullifier_k);
|
||||
nullifier_k.mul_base_field(layouter.namespace(|| "[x_s] Nullifier"), sig_secret)?
|
||||
};
|
||||
|
||||
layouter.constrain_instance(
|
||||
|
||||
@@ -7,12 +7,20 @@ use url::Url;
|
||||
|
||||
use crate::{
|
||||
blockchain::{rocks::columns, Rocks, RocksColumn, Slab},
|
||||
crypto::{coin::Coin, merkle_node::MerkleNode, schnorr, util::mod_r_p, OwnCoin},
|
||||
crypto::{
|
||||
coin::Coin,
|
||||
keypair::{Keypair, PublicKey, SecretKey},
|
||||
merkle_node::MerkleNode,
|
||||
OwnCoin,
|
||||
},
|
||||
serial::{serialize, Decodable, Encodable},
|
||||
service::GatewayClient,
|
||||
state::{state_transition, State},
|
||||
tx,
|
||||
wallet::{walletdb::Balances, CashierDbPtr, Keypair, WalletPtr},
|
||||
wallet::{
|
||||
cashierdb::CashierDbPtr,
|
||||
walletdb::{Balances, WalletPtr},
|
||||
},
|
||||
Result,
|
||||
};
|
||||
|
||||
@@ -95,7 +103,7 @@ impl Client {
|
||||
|
||||
async fn build_slab_from_tx(
|
||||
&mut self,
|
||||
pubkey: pallas::Point,
|
||||
pubkey: PublicKey,
|
||||
value: u64,
|
||||
token_id: pallas::Base,
|
||||
clear_input: bool,
|
||||
@@ -109,8 +117,9 @@ impl Client {
|
||||
|
||||
if clear_input {
|
||||
// TODO: FIXME:
|
||||
let base_secret = self.main_keypair.secret;
|
||||
let signature_secret = schnorr::SecretKey(mod_r_p(base_secret));
|
||||
let signature_secret = self.main_keypair.clone().secret;
|
||||
let signature_public = PublicKey::from_secret(signature_secret);
|
||||
debug!("SIGNATURE PUBLIC: {:?}", signature_public);
|
||||
let input = tx::TransactionBuilderClearInputInfo { value, token_id, signature_secret };
|
||||
clear_inputs.push(input);
|
||||
} else {
|
||||
@@ -124,7 +133,7 @@ impl Client {
|
||||
break
|
||||
}
|
||||
|
||||
let node = MerkleNode(own_coin.coin.inner());
|
||||
let node = MerkleNode(own_coin.coin.0);
|
||||
let (leaf_position, merkle_path) = state_m.tree.authentication_path(&node).unwrap();
|
||||
// TODO: What is this counting? Is it everything or does it know to separate
|
||||
// different tokens?
|
||||
@@ -179,7 +188,7 @@ impl Client {
|
||||
|
||||
pub async fn send(
|
||||
&mut self,
|
||||
pubkey: pallas::Point,
|
||||
pubkey: PublicKey,
|
||||
amount: u64,
|
||||
token_id: pallas::Base,
|
||||
clear_input: bool,
|
||||
@@ -204,7 +213,7 @@ impl Client {
|
||||
pub async fn transfer(
|
||||
&mut self,
|
||||
token_id: pallas::Base,
|
||||
pubkey: pallas::Point,
|
||||
pubkey: PublicKey,
|
||||
amount: u64,
|
||||
state: Arc<Mutex<State>>,
|
||||
) -> ClientResult<()> {
|
||||
@@ -222,11 +231,11 @@ impl Client {
|
||||
}
|
||||
|
||||
async fn update_state(
|
||||
secret_keys: Vec<pallas::Base>,
|
||||
secret_keys: Vec<SecretKey>,
|
||||
slab: &Slab,
|
||||
state: Arc<Mutex<State>>,
|
||||
wallet: WalletPtr,
|
||||
notify: Option<async_channel::Sender<(pallas::Point, u64)>>,
|
||||
notify: Option<async_channel::Sender<(PublicKey, u64)>>,
|
||||
) -> Result<()> {
|
||||
debug!("Build tx from slab and update the state");
|
||||
let tx = tx::Transaction::decode(&slab.get_payload()[..])?;
|
||||
@@ -242,7 +251,7 @@ impl Client {
|
||||
&self,
|
||||
state: Arc<Mutex<State>>,
|
||||
cashier_wallet: CashierDbPtr,
|
||||
notify: async_channel::Sender<(pallas::Point, u64)>,
|
||||
notify: async_channel::Sender<(PublicKey, u64)>,
|
||||
executor: Arc<Executor<'_>>,
|
||||
) -> Result<()> {
|
||||
debug!("Start subscriber for cashier");
|
||||
@@ -251,13 +260,12 @@ impl Client {
|
||||
let secret_key = self.main_keypair.secret;
|
||||
let wallet = self.wallet.clone();
|
||||
|
||||
//let task: smol::Task<Result<()>> = executor.spawn(async move {
|
||||
let task: smol::Task<Result<()>> = executor.spawn(async move {
|
||||
loop {
|
||||
let slab = gateway_slabs_sub.recv().await?;
|
||||
debug!("Received new slab");
|
||||
|
||||
let mut secret_keys: Vec<pallas::Base> = vec![secret_key];
|
||||
let mut secret_keys = vec![secret_key];
|
||||
let mut withdraw_keys = cashier_wallet.get_withdraw_private_keys().await?;
|
||||
secret_keys.append(&mut withdraw_keys);
|
||||
|
||||
@@ -289,8 +297,7 @@ impl Client {
|
||||
debug!("Start subscriber for darkfid");
|
||||
let gateway_slabs_sub = self.gateway.start_subscriber(executor.clone()).await?;
|
||||
|
||||
let secret_key = self.main_keypair.secret;
|
||||
|
||||
let secret_key = self.main_keypair.secret.clone();
|
||||
let wallet = self.wallet.clone();
|
||||
|
||||
let task: smol::Task<Result<()>> = executor.spawn(async move {
|
||||
|
||||
@@ -18,10 +18,6 @@ impl Coin {
|
||||
pub fn to_bytes(self) -> [u8; 32] {
|
||||
self.0.to_bytes()
|
||||
}
|
||||
|
||||
pub(crate) fn inner(&self) -> pallas::Base {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for Coin {
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams};
|
||||
use pasta_curves as pasta;
|
||||
use pasta_curves::group::{cofactor::CofactorGroup, GroupEncoding};
|
||||
|
||||
use crate::crypto::{
|
||||
keypair::{PublicKey, SecretKey},
|
||||
util::mod_r_p,
|
||||
};
|
||||
|
||||
pub const KDF_SAPLING_PERSONALIZATION: &[u8; 16] = b"DarkFiSaplingKDF";
|
||||
|
||||
/// Functions used for encrypting the note in transaction outputs.
|
||||
@@ -9,7 +13,7 @@ pub const KDF_SAPLING_PERSONALIZATION: &[u8; 16] = b"DarkFiSaplingKDF";
|
||||
/// Sapling key agreement for note encryption.
|
||||
///
|
||||
/// Implements section 5.4.4.3 of the Zcash Protocol Specification.
|
||||
pub fn sapling_ka_agree(esk: &pasta::Fq, pk_d: &pasta::Ep) -> pasta::Ep {
|
||||
pub fn sapling_ka_agree(esk: &SecretKey, pk_d: &PublicKey) -> PublicKey {
|
||||
// [8 esk] pk_d
|
||||
// <ExtendedPoint as CofactorGroup>::clear_cofactor is implemented using
|
||||
// ExtendedPoint::mul_by_cofactor in the jubjub crate.
|
||||
@@ -19,19 +23,20 @@ pub fn sapling_ka_agree(esk: &pasta::Fq, pk_d: &pasta::Ep) -> pasta::Ep {
|
||||
// of bits instead of individual bits).
|
||||
// We want that to be fast because it's in the hot path for trial decryption of
|
||||
// notes on chain.
|
||||
let esk_s = mod_r_p(esk.0);
|
||||
let mut wnaf = group::Wnaf::new();
|
||||
wnaf.scalar(esk).base(*pk_d).clear_cofactor()
|
||||
PublicKey(wnaf.scalar(&esk_s).base(pk_d.0).clear_cofactor())
|
||||
}
|
||||
|
||||
/// Sapling KDF for note encryption.
|
||||
///
|
||||
/// Implements section 5.4.4.4 of the Zcash Protocol Specification.
|
||||
pub fn kdf_sapling(dhsecret: pasta::Ep, epk: &pasta::Ep) -> Blake2bHash {
|
||||
pub fn kdf_sapling(dhsecret: &PublicKey, epk: &PublicKey) -> Blake2bHash {
|
||||
Blake2bParams::new()
|
||||
.hash_length(32)
|
||||
.personal(KDF_SAPLING_PERSONALIZATION)
|
||||
.to_state()
|
||||
.update(&dhsecret.to_bytes())
|
||||
.update(&epk.to_bytes())
|
||||
.update(&dhsecret.0.to_bytes())
|
||||
.update(&epk.0.to_bytes())
|
||||
.finalize()
|
||||
}
|
||||
|
||||
@@ -1,22 +1,28 @@
|
||||
use std::io;
|
||||
|
||||
use halo2_gadgets::ecc::FixedPoints;
|
||||
use pasta_curves::{arithmetic::Field, pallas};
|
||||
use pasta_curves::{
|
||||
arithmetic::{Field, FieldExt},
|
||||
group::{Group, GroupEncoding},
|
||||
pallas,
|
||||
};
|
||||
use rand::RngCore;
|
||||
|
||||
use crate::crypto::{constants::OrchardFixedBases, util::mod_r_p};
|
||||
use crate::{
|
||||
crypto::{constants::OrchardFixedBases, util::mod_r_p},
|
||||
serial::{Decodable, Encodable, ReadExt, WriteExt},
|
||||
Error, Result,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Keypair {
|
||||
pub secret: SecretKey,
|
||||
pub public: PublicKey,
|
||||
}
|
||||
|
||||
impl Keypair {
|
||||
fn derive_public_key(s: SecretKey) -> PublicKey {
|
||||
PublicKey(OrchardFixedBases::NullifierK.generator() * mod_r_p(s.inner()))
|
||||
}
|
||||
|
||||
pub fn new(secret: SecretKey) -> Self {
|
||||
let public = Keypair::derive_public_key(secret.clone());
|
||||
let public = PublicKey::from_secret(secret.clone());
|
||||
Keypair { secret, public }
|
||||
}
|
||||
|
||||
@@ -26,25 +32,135 @@ impl Keypair {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SecretKey(pallas::Base);
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct SecretKey(pub pallas::Base);
|
||||
|
||||
impl SecretKey {
|
||||
pub fn inner(&self) -> pallas::Base {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn random(mut rng: impl RngCore) -> Self {
|
||||
let x = pallas::Base::random(&mut rng);
|
||||
SecretKey(x)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PublicKey(pallas::Point);
|
||||
|
||||
impl PublicKey {
|
||||
pub fn inner(&self) -> pallas::Point {
|
||||
self.0
|
||||
pub fn to_bytes(self) -> [u8; 32] {
|
||||
self.0.to_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
pub struct PublicKey(pub pallas::Point);
|
||||
|
||||
impl PublicKey {
|
||||
pub fn random(mut rng: impl RngCore) -> Self {
|
||||
let p = pallas::Point::random(&mut rng);
|
||||
PublicKey(p)
|
||||
}
|
||||
|
||||
pub fn from_secret(s: SecretKey) -> Self {
|
||||
let p = OrchardFixedBases::NullifierK.generator() * mod_r_p(s.0);
|
||||
PublicKey(p)
|
||||
}
|
||||
|
||||
pub fn to_bytes(self) -> [u8; 32] {
|
||||
self.0.to_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for pallas::Base {
|
||||
fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
|
||||
s.write_slice(&self.to_bytes()[..])?;
|
||||
Ok(32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for pallas::Base {
|
||||
fn decode<D: io::Read>(mut d: D) -> Result<Self> {
|
||||
let mut bytes = [0u8; 32];
|
||||
d.read_slice(&mut bytes)?;
|
||||
let result = pallas::Base::from_bytes(&bytes);
|
||||
if result.is_some().into() {
|
||||
Ok(result.unwrap())
|
||||
} else {
|
||||
Err(Error::BadOperationType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for pallas::Scalar {
|
||||
fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
|
||||
s.write_slice(&self.to_bytes()[..])?;
|
||||
Ok(32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for pallas::Scalar {
|
||||
fn decode<D: io::Read>(mut d: D) -> Result<Self> {
|
||||
let mut bytes = [0u8; 32];
|
||||
d.read_slice(&mut bytes)?;
|
||||
let result = pallas::Scalar::from_bytes(&bytes);
|
||||
if result.is_some().into() {
|
||||
Ok(result.unwrap())
|
||||
} else {
|
||||
Err(Error::BadOperationType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for pallas::Point {
|
||||
fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
|
||||
s.write_slice(&self.to_bytes()[..])?;
|
||||
Ok(32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for pallas::Point {
|
||||
fn decode<D: io::Read>(mut d: D) -> Result<Self> {
|
||||
let mut bytes = [0u8; 32];
|
||||
d.read_slice(&mut bytes)?;
|
||||
let result = Self::from_bytes(&bytes);
|
||||
if result.is_some().into() {
|
||||
Ok(result.unwrap())
|
||||
} else {
|
||||
Err(Error::BadOperationType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for SecretKey {
|
||||
fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
|
||||
s.write_slice(&self.0.to_bytes()[..])?;
|
||||
Ok(32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for SecretKey {
|
||||
fn decode<D: io::Read>(mut d: D) -> Result<Self> {
|
||||
let mut bytes = [0u8; 32];
|
||||
d.read_slice(&mut bytes)?;
|
||||
let result = pallas::Base::from_bytes(&bytes);
|
||||
if result.is_some().into() {
|
||||
Ok(SecretKey(result.unwrap()))
|
||||
} else {
|
||||
Err(Error::BadOperationType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for PublicKey {
|
||||
fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
|
||||
s.write_slice(&self.0.to_bytes()[..])?;
|
||||
Ok(32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for PublicKey {
|
||||
fn decode<D: io::Read>(mut d: D) -> Result<Self> {
|
||||
let mut bytes = [0u8; 32];
|
||||
d.read_slice(&mut bytes)?;
|
||||
let result = pallas::Point::from_bytes(&bytes);
|
||||
if result.is_some().into() {
|
||||
Ok(PublicKey(result.unwrap()))
|
||||
} else {
|
||||
Err(Error::BadOperationType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,15 +8,16 @@ use log::debug;
|
||||
use pasta_curves::{
|
||||
arithmetic::{CurveAffine, FieldExt},
|
||||
group::Curve,
|
||||
pallas,
|
||||
};
|
||||
|
||||
use super::{
|
||||
proof::{Proof, ProvingKey, VerifyingKey},
|
||||
util::{mod_r_p, pedersen_commitment_scalar, pedersen_commitment_u64},
|
||||
};
|
||||
use crate::{
|
||||
circuit::mint_contract::MintContract,
|
||||
crypto::{
|
||||
coin::Coin,
|
||||
keypair::PublicKey,
|
||||
proof::{Proof, ProvingKey, VerifyingKey},
|
||||
util::{mod_r_p, pedersen_commitment_scalar, pedersen_commitment_u64},
|
||||
},
|
||||
serial::{Decodable, Encodable},
|
||||
types::*,
|
||||
Result,
|
||||
@@ -42,8 +43,7 @@ impl MintProofKeys {
|
||||
pub struct MintRevealedValues {
|
||||
pub value_commit: DrkValueCommit,
|
||||
pub token_commit: DrkValueCommit,
|
||||
//pub coin: [u8; 32],
|
||||
pub coin: pallas::Base,
|
||||
pub coin: Coin,
|
||||
}
|
||||
|
||||
impl MintRevealedValues {
|
||||
@@ -54,26 +54,18 @@ impl MintRevealedValues {
|
||||
token_blind: DrkValueBlind,
|
||||
serial: DrkSerial,
|
||||
coin_blind: DrkCoinBlind,
|
||||
public_key: DrkPublicKey,
|
||||
public_key: PublicKey,
|
||||
) -> Self {
|
||||
let value_commit = pedersen_commitment_u64(value, value_blind);
|
||||
let token_commit = pedersen_commitment_scalar(mod_r_p(token_id), token_blind);
|
||||
|
||||
let coords = public_key.to_affine().coordinates().unwrap();
|
||||
let messages = [
|
||||
[*coords.x(), *coords.y()],
|
||||
[DrkValue::from_u64(value), token_id],
|
||||
[serial, coin_blind],
|
||||
];
|
||||
let coords = public_key.0.to_affine().coordinates().unwrap();
|
||||
let messages =
|
||||
[*coords.x(), *coords.y(), DrkValue::from_u64(value), token_id, serial, coin_blind];
|
||||
|
||||
let mut coin = DrkCoin::zero();
|
||||
for msg in messages.iter() {
|
||||
coin += primitives::poseidon::Hash::init(P128Pow5T3, ConstantLength::<2>).hash(*msg);
|
||||
}
|
||||
let coin = primitives::poseidon::Hash::init(P128Pow5T3, ConstantLength::<6>).hash(messages);
|
||||
|
||||
//let coin = hash.to_bytes();
|
||||
|
||||
MintRevealedValues { value_commit, token_commit, coin }
|
||||
MintRevealedValues { value_commit, token_commit, coin: Coin(coin) }
|
||||
}
|
||||
|
||||
fn make_outputs(&self) -> [DrkCircuitField; 5] {
|
||||
@@ -81,8 +73,7 @@ impl MintRevealedValues {
|
||||
let token_coords = self.token_commit.to_affine().coordinates().unwrap();
|
||||
|
||||
vec![
|
||||
//DrkCircuitField::from_bytes(&self.coin).unwrap(),
|
||||
self.coin,
|
||||
self.coin.0,
|
||||
*value_coords.x(),
|
||||
*value_coords.y(),
|
||||
*token_coords.x(),
|
||||
@@ -121,7 +112,7 @@ pub fn create_mint_proof(
|
||||
token_blind: DrkValueBlind,
|
||||
serial: DrkSerial,
|
||||
coin_blind: DrkCoinBlind,
|
||||
public_key: DrkPublicKey,
|
||||
public_key: PublicKey,
|
||||
) -> Result<(Proof, MintRevealedValues)> {
|
||||
const K: u32 = 11;
|
||||
|
||||
@@ -135,7 +126,7 @@ pub fn create_mint_proof(
|
||||
public_key,
|
||||
);
|
||||
|
||||
let coords = public_key.to_affine().coordinates().unwrap();
|
||||
let coords = public_key.0.to_affine().coordinates().unwrap();
|
||||
|
||||
let c = MintContract {
|
||||
pub_x: Some(*coords.x()),
|
||||
|
||||
@@ -7,7 +7,6 @@ pub mod merkle_node;
|
||||
pub mod mint_proof;
|
||||
pub mod note;
|
||||
pub mod nullifier;
|
||||
pub mod pasta_serial;
|
||||
pub mod proof;
|
||||
pub mod schnorr;
|
||||
pub mod spend_proof;
|
||||
@@ -17,13 +16,13 @@ pub(crate) use mint_proof::MintRevealedValues;
|
||||
pub(crate) use proof::Proof;
|
||||
pub(crate) use spend_proof::SpendRevealedValues;
|
||||
|
||||
use crate::types::DrkSecretKey;
|
||||
use keypair::SecretKey;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct OwnCoin {
|
||||
pub coin: coin::Coin,
|
||||
pub note: note::Note,
|
||||
pub secret: DrkSecretKey,
|
||||
pub secret: SecretKey,
|
||||
//pub witness: merkle::IncrementalWitness<merkle_node::MerkleNode>,
|
||||
//pub witness: BridgeFrontier<merkle::MerkleHash, 32>,
|
||||
pub nullifier: nullifier::Nullifier,
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
use std::io;
|
||||
|
||||
use crypto_api_chachapoly::ChachaPolyIetf;
|
||||
use pasta_curves::arithmetic::Field;
|
||||
use rand::rngs::OsRng;
|
||||
|
||||
use super::{
|
||||
diffie_hellman::{kdf_sapling, sapling_ka_agree},
|
||||
util::mod_r_p,
|
||||
};
|
||||
use crate::{
|
||||
crypto::{
|
||||
diffie_hellman::{kdf_sapling, sapling_ka_agree},
|
||||
keypair::{PublicKey, SecretKey},
|
||||
},
|
||||
serial::{Decodable, Encodable, ReadExt, WriteExt},
|
||||
types::*,
|
||||
Error, Result,
|
||||
@@ -56,11 +55,11 @@ impl Decodable for Note {
|
||||
}
|
||||
|
||||
impl Note {
|
||||
pub fn encrypt(&self, public: &DrkPublicKey) -> Result<EncryptedNote> {
|
||||
let ephem_secret = DrkSecretKey::random(&mut OsRng);
|
||||
let ephem_public = derive_public_key(ephem_secret);
|
||||
let shared_secret = sapling_ka_agree(&mod_r_p(ephem_secret), public);
|
||||
let key = kdf_sapling(shared_secret, &ephem_public);
|
||||
pub fn encrypt(&self, public: &PublicKey) -> Result<EncryptedNote> {
|
||||
let ephem_secret = SecretKey::random(&mut OsRng);
|
||||
let ephem_public = PublicKey::from_secret(ephem_secret);
|
||||
let shared_secret = sapling_ka_agree(&ephem_secret, public);
|
||||
let key = kdf_sapling(&shared_secret, &ephem_public);
|
||||
|
||||
let mut input = Vec::new();
|
||||
self.encode(&mut input)?;
|
||||
@@ -79,7 +78,7 @@ impl Note {
|
||||
|
||||
pub struct EncryptedNote {
|
||||
ciphertext: [u8; ENC_CIPHERTEXT_SIZE],
|
||||
ephem_public: DrkPublicKey,
|
||||
ephem_public: PublicKey,
|
||||
}
|
||||
|
||||
impl Encodable for EncryptedNote {
|
||||
@@ -101,9 +100,9 @@ impl Decodable for EncryptedNote {
|
||||
}
|
||||
|
||||
impl EncryptedNote {
|
||||
pub fn decrypt(&self, secret: &DrkSecretKey) -> Result<Note> {
|
||||
let shared_secret = sapling_ka_agree(&mod_r_p(*secret), &self.ephem_public);
|
||||
let key = kdf_sapling(shared_secret, &self.ephem_public);
|
||||
pub fn decrypt(&self, secret: &SecretKey) -> Result<Note> {
|
||||
let shared_secret = sapling_ka_agree(&secret, &self.ephem_public);
|
||||
let key = kdf_sapling(&shared_secret, &self.ephem_public);
|
||||
|
||||
let mut plaintext = [0; ENC_CIPHERTEXT_SIZE];
|
||||
assert_eq!(
|
||||
|
||||
@@ -7,6 +7,7 @@ use halo2_gadgets::primitives::{
|
||||
use pasta_curves::{arithmetic::FieldExt, pallas};
|
||||
|
||||
use crate::{
|
||||
crypto::keypair::SecretKey,
|
||||
serial::{Decodable, Encodable, ReadExt, WriteExt},
|
||||
Result,
|
||||
};
|
||||
@@ -15,8 +16,8 @@ use crate::{
|
||||
pub struct Nullifier(pub(crate) pallas::Base);
|
||||
|
||||
impl Nullifier {
|
||||
pub fn new(secret: pallas::Base, serial: pallas::Base) -> Self {
|
||||
let nullifier = [secret, serial];
|
||||
pub fn new(secret: SecretKey, serial: pallas::Base) -> Self {
|
||||
let nullifier = [secret.0, serial];
|
||||
let nullifier = poseidon::Hash::init(P128Pow5T3, ConstantLength::<2>).hash(nullifier);
|
||||
Nullifier(nullifier)
|
||||
}
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
use std::io;
|
||||
|
||||
use pasta_curves as pasta;
|
||||
use pasta_curves::{arithmetic::FieldExt, group::GroupEncoding};
|
||||
|
||||
use crate::{
|
||||
serial::{Decodable, Encodable, ReadExt, WriteExt},
|
||||
Error, Result,
|
||||
};
|
||||
|
||||
impl Encodable for pasta::Fp {
|
||||
fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
|
||||
s.write_slice(&self.to_bytes()[..])?;
|
||||
Ok(32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for pasta::Fp {
|
||||
fn decode<D: io::Read>(mut d: D) -> Result<Self> {
|
||||
let mut bytes = [0u8; 32];
|
||||
d.read_slice(&mut bytes)?;
|
||||
let result = Self::from_bytes(&bytes);
|
||||
if result.is_some().into() {
|
||||
Ok(result.unwrap())
|
||||
} else {
|
||||
Err(Error::BadOperationType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for pasta::Fq {
|
||||
fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
|
||||
s.write_slice(&self.to_bytes()[..])?;
|
||||
Ok(32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for pasta::Fq {
|
||||
fn decode<D: io::Read>(mut d: D) -> Result<Self> {
|
||||
let mut bytes = [0u8; 32];
|
||||
d.read_slice(&mut bytes)?;
|
||||
let result = Self::from_bytes(&bytes);
|
||||
if result.is_some().into() {
|
||||
Ok(result.unwrap())
|
||||
} else {
|
||||
Err(Error::BadOperationType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for pasta::Ep {
|
||||
fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
|
||||
s.write_slice(&self.to_bytes()[..])?;
|
||||
Ok(32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for pasta::Ep {
|
||||
fn decode<D: io::Read>(mut d: D) -> Result<Self> {
|
||||
let mut bytes = [0u8; 32];
|
||||
d.read_slice(&mut bytes)?;
|
||||
let result = Self::from_bytes(&bytes);
|
||||
if result.is_some().into() {
|
||||
Ok(result.unwrap())
|
||||
} else {
|
||||
Err(Error::BadOperationType)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,50 +4,47 @@ use halo2_gadgets::ecc::FixedPoints;
|
||||
use pasta_curves::{arithmetic::Field, group::GroupEncoding, pallas};
|
||||
use rand::rngs::OsRng;
|
||||
|
||||
use super::{
|
||||
constants::{OrchardFixedBases, DRK_SCHNORR_DOMAIN},
|
||||
util::hash_to_scalar,
|
||||
};
|
||||
use crate::{
|
||||
error::Result,
|
||||
crypto::{
|
||||
constants::{OrchardFixedBases, DRK_SCHNORR_DOMAIN},
|
||||
keypair::{PublicKey, SecretKey},
|
||||
util::{hash_to_scalar, mod_r_p},
|
||||
},
|
||||
serial::{Decodable, Encodable},
|
||||
types::{DrkPublicKey, DrkValueBlind, DrkValueCommit},
|
||||
Result,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SecretKey(pub pallas::Scalar);
|
||||
pub struct Signature {
|
||||
commit: pallas::Point,
|
||||
response: pallas::Scalar,
|
||||
}
|
||||
|
||||
impl SecretKey {
|
||||
pub fn random() -> Self {
|
||||
Self(pallas::Scalar::random(&mut OsRng))
|
||||
}
|
||||
pub trait SchnorrSecret {
|
||||
fn sign(&self, message: &[u8]) -> Signature;
|
||||
}
|
||||
|
||||
pub fn sign(&self, message: &[u8]) -> Signature {
|
||||
let mask = DrkValueBlind::random(&mut OsRng);
|
||||
let commit = OrchardFixedBases::SpendAuthG.generator() * mask;
|
||||
pub trait SchnorrPublic {
|
||||
fn verify(&self, message: &[u8], signature: &Signature) -> bool;
|
||||
}
|
||||
|
||||
impl SchnorrSecret for SecretKey {
|
||||
fn sign(&self, message: &[u8]) -> Signature {
|
||||
let mask = pallas::Scalar::random(&mut OsRng);
|
||||
let commit = OrchardFixedBases::NullifierK.generator() * mask;
|
||||
|
||||
let challenge = hash_to_scalar(DRK_SCHNORR_DOMAIN, &commit.to_bytes(), message);
|
||||
let response = mask + challenge * self.0;
|
||||
let response = mask + challenge * mod_r_p(self.0);
|
||||
|
||||
Signature { commit, response }
|
||||
}
|
||||
|
||||
pub fn public_key(&self) -> PublicKey {
|
||||
let public_key = OrchardFixedBases::SpendAuthG.generator() * self.0;
|
||||
PublicKey(public_key)
|
||||
}
|
||||
|
||||
pub fn inner(&self) -> pallas::Scalar {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub struct PublicKey(pub DrkPublicKey);
|
||||
|
||||
pub struct Signature {
|
||||
commit: DrkValueCommit,
|
||||
response: DrkValueBlind,
|
||||
impl SchnorrPublic for PublicKey {
|
||||
fn verify(&self, message: &[u8], signature: &Signature) -> bool {
|
||||
let challenge = hash_to_scalar(DRK_SCHNORR_DOMAIN, &signature.commit.to_bytes(), message);
|
||||
OrchardFixedBases::NullifierK.generator() * signature.response - self.0 * challenge ==
|
||||
signature.commit
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for Signature {
|
||||
@@ -65,35 +62,16 @@ impl Decodable for Signature {
|
||||
}
|
||||
}
|
||||
|
||||
impl PublicKey {
|
||||
pub fn verify(&self, message: &[u8], signature: &Signature) -> bool {
|
||||
let challenge = hash_to_scalar(DRK_SCHNORR_DOMAIN, &signature.commit.to_bytes(), message);
|
||||
OrchardFixedBases::SpendAuthG.generator() * signature.response - self.0 * challenge ==
|
||||
signature.commit
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
pub fn inner(&self) -> pallas::Point {
|
||||
self.0
|
||||
#[test]
|
||||
fn test_schnorr() {
|
||||
let secret = SecretKey::random();
|
||||
let message = b"Foo bar";
|
||||
let signature = secret.sign(&message[..]);
|
||||
let public = PublicKey::from_secret(secret);
|
||||
assert!(public.verify(&message[..], &signature));
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for PublicKey {
|
||||
fn encode<S: io::Write>(&self, s: S) -> Result<usize> {
|
||||
self.0.encode(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for PublicKey {
|
||||
fn decode<D: io::Read>(mut d: D) -> Result<Self> {
|
||||
Ok(Self(Decodable::decode(&mut d)?))
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_schnorr() {
|
||||
let secret = SecretKey::random();
|
||||
let message = b"Foo bar";
|
||||
let signature = secret.sign(&message[..]);
|
||||
let public = secret.public_key();
|
||||
assert!(public.verify(&message[..], &signature));
|
||||
}
|
||||
|
||||
@@ -19,7 +19,10 @@ use super::{
|
||||
};
|
||||
use crate::{
|
||||
circuit::spend_contract::SpendContract,
|
||||
crypto::{merkle_node::MerkleNode, schnorr},
|
||||
crypto::{
|
||||
keypair::{PublicKey, SecretKey},
|
||||
merkle_node::MerkleNode,
|
||||
},
|
||||
serial::{Decodable, Encodable},
|
||||
types::*,
|
||||
Result,
|
||||
@@ -47,7 +50,7 @@ pub struct SpendRevealedValues {
|
||||
pub token_commit: DrkValueCommit,
|
||||
pub nullifier: Nullifier,
|
||||
pub merkle_root: MerkleNode,
|
||||
pub signature_public: schnorr::PublicKey,
|
||||
pub signature_public: PublicKey,
|
||||
}
|
||||
|
||||
impl SpendRevealedValues {
|
||||
@@ -59,27 +62,22 @@ impl SpendRevealedValues {
|
||||
token_blind: DrkValueBlind,
|
||||
serial: DrkSerial,
|
||||
coin_blind: DrkCoinBlind,
|
||||
secret: DrkSecretKey,
|
||||
secret: SecretKey,
|
||||
leaf_position: incrementalmerkletree::Position,
|
||||
merkle_path: Vec<MerkleNode>,
|
||||
signature_secret: schnorr::SecretKey,
|
||||
signature_secret: SecretKey,
|
||||
) -> Self {
|
||||
let nullifier = [secret, serial];
|
||||
let nullifier = [secret.0, serial];
|
||||
let nullifier =
|
||||
primitives::poseidon::Hash::init(P128Pow5T3, ConstantLength::<2>).hash(nullifier);
|
||||
|
||||
let public_key = derive_public_key(secret);
|
||||
let coords = public_key.to_affine().coordinates().unwrap();
|
||||
let messages = [
|
||||
[*coords.x(), *coords.y()],
|
||||
[DrkValue::from_u64(value), token_id],
|
||||
[serial, coin_blind],
|
||||
];
|
||||
let public_key = PublicKey::from_secret(secret);
|
||||
let coords = public_key.0.to_affine().coordinates().unwrap();
|
||||
|
||||
let mut coin = DrkCoin::zero();
|
||||
for msg in messages.iter() {
|
||||
coin += primitives::poseidon::Hash::init(P128Pow5T3, ConstantLength::<2>).hash(*msg);
|
||||
}
|
||||
let messages =
|
||||
[*coords.x(), *coords.y(), DrkValue::from_u64(value), token_id, serial, coin_blind];
|
||||
|
||||
let coin = primitives::poseidon::Hash::init(P128Pow5T3, ConstantLength::<6>).hash(messages);
|
||||
|
||||
let merkle_root = {
|
||||
let position: u64 = leaf_position.into();
|
||||
@@ -103,7 +101,7 @@ impl SpendRevealedValues {
|
||||
token_commit,
|
||||
nullifier: Nullifier(nullifier),
|
||||
merkle_root,
|
||||
signature_public: signature_secret.public_key(),
|
||||
signature_public: PublicKey::from_secret(signature_secret),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,10 +158,10 @@ pub fn create_spend_proof(
|
||||
token_blind: DrkValueBlind,
|
||||
serial: DrkSerial,
|
||||
coin_blind: DrkCoinBlind,
|
||||
secret: DrkSecretKey,
|
||||
secret: SecretKey,
|
||||
leaf_position: incrementalmerkletree::Position,
|
||||
merkle_path: Vec<MerkleNode>,
|
||||
signature_secret: schnorr::SecretKey,
|
||||
signature_secret: SecretKey,
|
||||
) -> Result<(Proof, SpendRevealedValues)> {
|
||||
const K: u32 = 11;
|
||||
|
||||
@@ -184,7 +182,7 @@ pub fn create_spend_proof(
|
||||
let leaf_position: u64 = leaf_position.into();
|
||||
|
||||
let c = SpendContract {
|
||||
secret_key: Some(secret),
|
||||
secret_key: Some(secret.0),
|
||||
serial: Some(serial),
|
||||
value: Some(DrkValue::from_u64(value)),
|
||||
asset: Some(token_id),
|
||||
|
||||
@@ -6,7 +6,10 @@ use async_trait::async_trait;
|
||||
use futures::stream::{FuturesUnordered, StreamExt};
|
||||
use log::{debug, error};
|
||||
|
||||
use crate::{types::*, util::NetworkName, wallet::cashierdb::TokenKey, Error, Result};
|
||||
use crate::{
|
||||
crypto::keypair::PublicKey, types::*, util::NetworkName, wallet::cashierdb::TokenKey, Error,
|
||||
Result,
|
||||
};
|
||||
|
||||
pub struct BridgeRequests {
|
||||
pub network: NetworkName,
|
||||
@@ -53,7 +56,7 @@ pub struct TokenSubscribtion {
|
||||
pub struct TokenNotification {
|
||||
pub network: NetworkName,
|
||||
pub token_id: DrkTokenId,
|
||||
pub drk_pub_key: DrkPublicKey,
|
||||
pub drk_pub_key: PublicKey,
|
||||
pub received_balance: u64,
|
||||
pub decimals: u16,
|
||||
}
|
||||
@@ -109,7 +112,7 @@ impl Bridge {
|
||||
|
||||
pub async fn subscribe(
|
||||
self: Arc<Self>,
|
||||
drk_pub_key: DrkPublicKey,
|
||||
drk_pub_key: PublicKey,
|
||||
mint: Option<String>,
|
||||
executor: Arc<Executor<'_>>,
|
||||
) -> BridgeSubscribtion {
|
||||
@@ -128,7 +131,7 @@ impl Bridge {
|
||||
self: Arc<Self>,
|
||||
req: async_channel::Receiver<BridgeRequests>,
|
||||
rep: async_channel::Sender<BridgeResponse>,
|
||||
drk_pub_key: DrkPublicKey,
|
||||
drk_pub_key: PublicKey,
|
||||
mint: Option<String>,
|
||||
executor: Arc<Executor<'_>>,
|
||||
) -> Result<()> {
|
||||
@@ -232,7 +235,7 @@ impl Bridge {
|
||||
pub trait NetworkClient {
|
||||
async fn subscribe(
|
||||
self: Arc<Self>,
|
||||
drk_pub_key: DrkPublicKey,
|
||||
drk_pub_key: PublicKey,
|
||||
mint: Option<String>,
|
||||
executor: Arc<Executor<'_>>,
|
||||
) -> Result<TokenSubscribtion>;
|
||||
@@ -242,7 +245,7 @@ pub trait NetworkClient {
|
||||
self: Arc<Self>,
|
||||
private_key: Vec<u8>,
|
||||
public_key: Vec<u8>,
|
||||
drk_pub_key: DrkPublicKey,
|
||||
drk_pub_key: PublicKey,
|
||||
mint: Option<String>,
|
||||
executor: Arc<Executor<'_>>,
|
||||
) -> Result<String>;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// TODO: This module needs cleanup related to PublicKey/SecretKey types.
|
||||
|
||||
use std::{
|
||||
cmp::max,
|
||||
collections::BTreeMap,
|
||||
@@ -40,8 +42,8 @@ use secp256k1::{
|
||||
|
||||
use super::bridge::{NetworkClient, TokenNotification, TokenSubscribtion};
|
||||
use crate::{
|
||||
crypto::keypair::PublicKey as DrkPublicKey,
|
||||
serial::{deserialize, serialize, Decodable, Encodable},
|
||||
types::*,
|
||||
util::{generate_id, NetworkName},
|
||||
Error, Result,
|
||||
};
|
||||
|
||||
@@ -13,9 +13,9 @@ use serde_json::{json, Value};
|
||||
|
||||
use super::bridge::{NetworkClient, TokenNotification, TokenSubscribtion};
|
||||
use crate::{
|
||||
crypto::keypair::PublicKey,
|
||||
rpc::{jsonrpc, jsonrpc::JsonResult},
|
||||
serial::{deserialize, serialize, Decodable, Encodable},
|
||||
types::*,
|
||||
util::{generate_id, parse::truncate, NetworkName},
|
||||
Error, Result,
|
||||
};
|
||||
@@ -228,7 +228,7 @@ impl EthClient {
|
||||
async fn handle_subscribe_request(
|
||||
self: Arc<Self>,
|
||||
addr: String,
|
||||
drk_pub_key: DrkPublicKey,
|
||||
drk_pub_key: PublicKey,
|
||||
) -> Result<()> {
|
||||
if self.subscriptions.lock().await.contains(&addr) {
|
||||
return Ok(())
|
||||
@@ -381,7 +381,7 @@ impl EthClient {
|
||||
impl NetworkClient for EthClient {
|
||||
async fn subscribe(
|
||||
self: Arc<Self>,
|
||||
drk_pub_key: DrkPublicKey,
|
||||
drk_pub_key: PublicKey,
|
||||
_mint_address: Option<String>,
|
||||
executor: Arc<Executor<'_>>,
|
||||
) -> Result<TokenSubscribtion> {
|
||||
@@ -414,7 +414,7 @@ impl NetworkClient for EthClient {
|
||||
self: Arc<Self>,
|
||||
_private_key: Vec<u8>,
|
||||
public_key: Vec<u8>,
|
||||
drk_pub_key: DrkPublicKey,
|
||||
drk_pub_key: PublicKey,
|
||||
_mint_address: Option<String>,
|
||||
executor: Arc<Executor<'_>>,
|
||||
) -> Result<String> {
|
||||
|
||||
@@ -23,9 +23,9 @@ use tungstenite::Message;
|
||||
|
||||
use super::bridge::{NetworkClient, TokenNotification, TokenSubscribtion};
|
||||
use crate::{
|
||||
crypto::keypair::PublicKey,
|
||||
rpc::{jsonrpc, jsonrpc::JsonResult, websockets, websockets::WsStream},
|
||||
serial::{deserialize, serialize, Decodable, Encodable},
|
||||
types::*,
|
||||
util::{generate_id, parse::truncate, NetworkName},
|
||||
Error, Result,
|
||||
};
|
||||
@@ -85,7 +85,7 @@ impl SolClient {
|
||||
async fn handle_subscribe_request(
|
||||
self: Arc<Self>,
|
||||
keypair: Keypair,
|
||||
drk_pub_key: DrkPublicKey,
|
||||
drk_pub_key: PublicKey,
|
||||
mint: Option<Pubkey>,
|
||||
) -> SolResult<()> {
|
||||
debug!(target: "SOL BRIDGE", "handle_subscribe_request()");
|
||||
@@ -396,7 +396,7 @@ impl SolClient {
|
||||
impl NetworkClient for SolClient {
|
||||
async fn subscribe(
|
||||
self: Arc<Self>,
|
||||
drk_pub_key: DrkPublicKey,
|
||||
drk_pub_key: PublicKey,
|
||||
mint_address: Option<String>,
|
||||
executor: Arc<Executor<'_>>,
|
||||
) -> Result<TokenSubscribtion> {
|
||||
@@ -431,7 +431,7 @@ impl NetworkClient for SolClient {
|
||||
self: Arc<Self>,
|
||||
private_key: Vec<u8>,
|
||||
_public_key: Vec<u8>,
|
||||
drk_pub_key: DrkPublicKey,
|
||||
drk_pub_key: PublicKey,
|
||||
mint_address: Option<String>,
|
||||
executor: Arc<Executor<'_>>,
|
||||
) -> Result<String> {
|
||||
|
||||
37
src/state.rs
37
src/state.rs
@@ -1,28 +1,25 @@
|
||||
use halo2_gadgets::ecc::FixedPoints;
|
||||
use incrementalmerkletree::{bridgetree::BridgeTree, Frontier, Tree};
|
||||
use log::debug;
|
||||
use pasta_curves::pallas;
|
||||
|
||||
use crate::{
|
||||
blockchain::{rocks::columns, RocksColumn},
|
||||
crypto::{
|
||||
coin::Coin,
|
||||
constants::OrchardFixedBases,
|
||||
keypair::{PublicKey, SecretKey},
|
||||
merkle_node::MerkleNode,
|
||||
note::{EncryptedNote, Note},
|
||||
nullifier::Nullifier,
|
||||
proof::VerifyingKey,
|
||||
schnorr,
|
||||
util::mod_r_p,
|
||||
OwnCoin,
|
||||
},
|
||||
serial::serialize,
|
||||
tx::Transaction,
|
||||
wallet::WalletPtr,
|
||||
wallet::walletdb::WalletPtr,
|
||||
Result,
|
||||
};
|
||||
|
||||
pub trait ProgramState {
|
||||
fn is_valid_cashier_public_key(&self, public: &schnorr::PublicKey) -> bool;
|
||||
fn is_valid_cashier_public_key(&self, public: &PublicKey) -> bool;
|
||||
fn is_valid_merkle(&self, merkle: &MerkleNode) -> bool;
|
||||
fn nullifier_exists(&self, nullifier: &Nullifier) -> bool;
|
||||
fn mint_vk(&self) -> &VerifyingKey;
|
||||
@@ -61,15 +58,17 @@ pub enum VerifyFailed {
|
||||
|
||||
pub fn state_transition<S: ProgramState>(state: &S, tx: Transaction) -> VerifyResult<StateUpdate> {
|
||||
// Check deposits are legit
|
||||
|
||||
debug!(target: "STATE TRANSITION", "iterate clear_inputs");
|
||||
|
||||
for (i, input) in tx.clear_inputs.iter().enumerate() {
|
||||
// Check the public key in the clear inputs
|
||||
// It should be a valid public key for the cashier
|
||||
|
||||
if !state.is_valid_cashier_public_key(&input.signature_public) {
|
||||
log::error!(target: "STATE TRANSITION", "Not valid cashier public key");
|
||||
debug!(
|
||||
"CASHIER PUBLIC: {}",
|
||||
bs58::encode(serialize(&input.signature_public)).into_string()
|
||||
);
|
||||
log::error!(target: "STATE TRANSITION", "Invalid cashier public key");
|
||||
return Err(VerifyFailed::InvalidCashierKey(i))
|
||||
}
|
||||
}
|
||||
@@ -108,7 +107,7 @@ pub fn state_transition<S: ProgramState>(state: &S, tx: Transaction) -> VerifyRe
|
||||
let mut enc_notes = vec![];
|
||||
for output in tx.outputs {
|
||||
// Gather all the coins
|
||||
coins.push(Coin(output.revealed.coin));
|
||||
coins.push(output.revealed.coin);
|
||||
enc_notes.push(output.enc_note);
|
||||
}
|
||||
|
||||
@@ -124,7 +123,7 @@ pub struct State {
|
||||
/// Nullifiers prevent double-spending
|
||||
pub nullifiers: RocksColumn<columns::Nullifiers>,
|
||||
/// List of Cashier public keys
|
||||
pub public_keys: Vec<pallas::Point>,
|
||||
pub public_keys: Vec<PublicKey>,
|
||||
/// Verifying key for the Mint contract
|
||||
pub mint_vk: VerifyingKey,
|
||||
/// Verifying key for the Spend contract
|
||||
@@ -135,8 +134,8 @@ impl State {
|
||||
pub async fn apply(
|
||||
&mut self,
|
||||
update: StateUpdate,
|
||||
secret_keys: Vec<pallas::Base>,
|
||||
notify: Option<async_channel::Sender<(pallas::Point, u64)>>,
|
||||
secret_keys: Vec<SecretKey>,
|
||||
notify: Option<async_channel::Sender<(PublicKey, u64)>>,
|
||||
wallet: WalletPtr,
|
||||
) -> Result<()> {
|
||||
// Extend our list of nullifiers with the ones from the update.
|
||||
@@ -170,8 +169,7 @@ impl State {
|
||||
|
||||
wallet.put_own_coins(own_coin).await?;
|
||||
|
||||
// TODO: Place somewhere proper
|
||||
let pubkey = OrchardFixedBases::NullifierK.generator() * mod_r_p(*secret);
|
||||
let pubkey = PublicKey::from_secret(*secret);
|
||||
|
||||
debug!("Received a coin: amount {}", note.value);
|
||||
debug!("Send a notification");
|
||||
@@ -186,7 +184,7 @@ impl State {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn try_decrypt_note(ciphertext: &EncryptedNote, secret: pallas::Base) -> Option<Note> {
|
||||
fn try_decrypt_note(ciphertext: &EncryptedNote, secret: SecretKey) -> Option<Note> {
|
||||
match ciphertext.decrypt(&secret) {
|
||||
Ok(note) => Some(note),
|
||||
Err(_) => None,
|
||||
@@ -195,10 +193,9 @@ impl State {
|
||||
}
|
||||
|
||||
impl ProgramState for State {
|
||||
// TODO: Proper keypair type
|
||||
fn is_valid_cashier_public_key(&self, public: &schnorr::PublicKey) -> bool {
|
||||
fn is_valid_cashier_public_key(&self, public: &PublicKey) -> bool {
|
||||
debug!("Check if it is a valid cashier public key");
|
||||
self.public_keys.contains(&public.inner())
|
||||
self.public_keys.contains(&public)
|
||||
}
|
||||
|
||||
fn is_valid_merkle(&self, merkle_root: &MerkleNode) -> bool {
|
||||
|
||||
@@ -7,11 +7,15 @@ use super::{
|
||||
};
|
||||
use crate::{
|
||||
crypto::{
|
||||
merkle_node::MerkleNode, mint_proof::create_mint_proof, note::Note, schnorr,
|
||||
keypair::{PublicKey, SecretKey},
|
||||
merkle_node::MerkleNode,
|
||||
mint_proof::create_mint_proof,
|
||||
note::Note,
|
||||
schnorr::SchnorrSecret,
|
||||
spend_proof::create_spend_proof,
|
||||
},
|
||||
serial::Encodable,
|
||||
types::{DrkCoinBlind, DrkPublicKey, DrkSecretKey, DrkSerial, DrkTokenId, DrkValueBlind},
|
||||
types::{DrkCoinBlind, DrkSerial, DrkTokenId, DrkValueBlind},
|
||||
Result,
|
||||
};
|
||||
|
||||
@@ -24,20 +28,20 @@ pub struct TransactionBuilder {
|
||||
pub struct TransactionBuilderClearInputInfo {
|
||||
pub value: u64,
|
||||
pub token_id: DrkTokenId,
|
||||
pub signature_secret: schnorr::SecretKey,
|
||||
pub signature_secret: SecretKey,
|
||||
}
|
||||
|
||||
pub struct TransactionBuilderInputInfo {
|
||||
pub leaf_position: incrementalmerkletree::Position,
|
||||
pub merkle_path: Vec<MerkleNode>,
|
||||
pub secret: DrkSecretKey,
|
||||
pub secret: SecretKey,
|
||||
pub note: Note,
|
||||
}
|
||||
|
||||
pub struct TransactionBuilderOutputInfo {
|
||||
pub value: u64,
|
||||
pub token_id: DrkTokenId,
|
||||
pub public: DrkPublicKey,
|
||||
pub public: PublicKey,
|
||||
}
|
||||
|
||||
impl TransactionBuilder {
|
||||
@@ -63,11 +67,12 @@ impl TransactionBuilder {
|
||||
total
|
||||
}
|
||||
|
||||
// TODO: pass proving keys as args to this function
|
||||
pub fn build(self) -> Result<Transaction> {
|
||||
let mut clear_inputs = vec![];
|
||||
let token_blind = DrkValueBlind::random(&mut OsRng);
|
||||
for input in &self.clear_inputs {
|
||||
let signature_public = input.signature_secret.public_key();
|
||||
let signature_public = PublicKey::from_secret(input.signature_secret);
|
||||
let value_blind = DrkValueBlind::random(&mut OsRng);
|
||||
|
||||
let clear_input = PartialTransactionClearInput {
|
||||
@@ -86,7 +91,7 @@ impl TransactionBuilder {
|
||||
for input in self.inputs {
|
||||
input_blinds.push(input.note.value_blind);
|
||||
|
||||
let signature_secret = schnorr::SecretKey::random();
|
||||
let signature_secret = SecretKey::random(&mut OsRng);
|
||||
|
||||
let (proof, revealed) = create_spend_proof(
|
||||
input.note.value,
|
||||
|
||||
@@ -7,10 +7,12 @@ use pasta_curves::group::Group;
|
||||
|
||||
use crate::{
|
||||
crypto::{
|
||||
keypair::PublicKey,
|
||||
mint_proof::verify_mint_proof,
|
||||
note::EncryptedNote,
|
||||
proof::{Proof, VerifyingKey},
|
||||
schnorr,
|
||||
schnorr::SchnorrPublic,
|
||||
spend_proof::verify_spend_proof,
|
||||
util::{mod_r_p, pedersen_commitment_scalar, pedersen_commitment_u64},
|
||||
MintRevealedValues, SpendRevealedValues,
|
||||
@@ -38,7 +40,7 @@ pub struct TransactionClearInput {
|
||||
pub token_id: DrkTokenId,
|
||||
pub value_blind: DrkValueBlind,
|
||||
pub token_blind: DrkValueBlind,
|
||||
pub signature_public: schnorr::PublicKey,
|
||||
pub signature_public: PublicKey,
|
||||
pub signature: schnorr::Signature,
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::io;
|
||||
|
||||
use super::TransactionOutput;
|
||||
use crate::{
|
||||
crypto::{schnorr, spend_proof::SpendRevealedValues, Proof},
|
||||
crypto::{keypair::PublicKey, spend_proof::SpendRevealedValues, Proof},
|
||||
error::Result,
|
||||
impl_vec,
|
||||
serial::{Decodable, Encodable, VarInt},
|
||||
@@ -20,7 +20,7 @@ pub struct PartialTransactionClearInput {
|
||||
pub token_id: DrkTokenId,
|
||||
pub value_blind: DrkValueBlind,
|
||||
pub token_blind: DrkValueBlind,
|
||||
pub signature_public: schnorr::PublicKey,
|
||||
pub signature_public: PublicKey,
|
||||
}
|
||||
|
||||
pub struct PartialTransactionInput {
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
use crate::types::*;
|
||||
use group::GroupEncoding;
|
||||
use sha2::Digest;
|
||||
|
||||
use crate::crypto::keypair::PublicKey;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Address {
|
||||
pub raw: DrkPublicKey,
|
||||
pub raw: PublicKey,
|
||||
pub pkh: String,
|
||||
}
|
||||
|
||||
impl Address {
|
||||
pub fn new(raw: DrkPublicKey) -> Self {
|
||||
pub fn new(raw: PublicKey) -> Self {
|
||||
let pkh = Self::pkh_address(&raw);
|
||||
|
||||
Address { raw, pkh }
|
||||
}
|
||||
|
||||
fn get_hash(raw: &DrkPublicKey) -> Vec<u8> {
|
||||
fn get_hash(raw: &PublicKey) -> Vec<u8> {
|
||||
// sha256
|
||||
let mut hasher = sha2::Sha256::new();
|
||||
hasher.update(raw.to_bytes());
|
||||
@@ -28,7 +28,7 @@ impl Address {
|
||||
hash.to_vec()
|
||||
}
|
||||
|
||||
pub fn pkh_address(raw: &DrkPublicKey) -> String {
|
||||
pub fn pkh_address(raw: &PublicKey) -> String {
|
||||
let mut hash = Self::get_hash(raw);
|
||||
|
||||
// add version
|
||||
@@ -44,7 +44,7 @@ impl Address {
|
||||
|
||||
payload.append(&mut payload_hash[0..4].to_vec());
|
||||
|
||||
// base56 encoding
|
||||
// base58 encoding
|
||||
let address: String = bs58::encode(payload).into_string();
|
||||
|
||||
address
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use pasta_curves::pallas;
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::{
|
||||
types::DrkTokenId,
|
||||
util::{generate_id, NetworkName},
|
||||
Error, Result,
|
||||
};
|
||||
@@ -55,7 +55,7 @@ impl TokenList {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DrkTokenList {
|
||||
pub tokens: HashMap<NetworkName, HashMap<String, pallas::Base>>,
|
||||
pub tokens: HashMap<NetworkName, HashMap<String, DrkTokenId>>,
|
||||
}
|
||||
|
||||
impl DrkTokenList {
|
||||
@@ -64,28 +64,28 @@ impl DrkTokenList {
|
||||
let eth_symbols = eth_list.get_symbols()?;
|
||||
let btc_symbols = btc_list.get_symbols()?;
|
||||
|
||||
let sol_tokens: HashMap<String, pallas::Base> = sol_symbols
|
||||
let sol_tokens: HashMap<String, DrkTokenId> = sol_symbols
|
||||
.iter()
|
||||
.filter_map(|symbol| {
|
||||
Self::generate_hash_pair(sol_list, &NetworkName::Solana, symbol).ok()
|
||||
})
|
||||
.collect();
|
||||
|
||||
let eth_tokens: HashMap<String, pallas::Base> = eth_symbols
|
||||
let eth_tokens: HashMap<String, DrkTokenId> = eth_symbols
|
||||
.iter()
|
||||
.filter_map(|symbol| {
|
||||
Self::generate_hash_pair(eth_list, &NetworkName::Ethereum, symbol).ok()
|
||||
})
|
||||
.collect();
|
||||
|
||||
let btc_tokens: HashMap<String, pallas::Base> = btc_symbols
|
||||
let btc_tokens: HashMap<String, DrkTokenId> = btc_symbols
|
||||
.iter()
|
||||
.filter_map(|symbol| {
|
||||
Self::generate_hash_pair(btc_list, &NetworkName::Bitcoin, symbol).ok()
|
||||
})
|
||||
.collect();
|
||||
|
||||
let tokens: HashMap<NetworkName, HashMap<String, pallas::Base>> = HashMap::from([
|
||||
let tokens: HashMap<NetworkName, HashMap<String, DrkTokenId>> = HashMap::from([
|
||||
(NetworkName::Solana, sol_tokens),
|
||||
(NetworkName::Ethereum, eth_tokens),
|
||||
(NetworkName::Bitcoin, btc_tokens),
|
||||
@@ -98,7 +98,7 @@ impl DrkTokenList {
|
||||
token_list: &TokenList,
|
||||
network_name: &NetworkName,
|
||||
symbol: &str,
|
||||
) -> Result<(String, pallas::Base)> {
|
||||
) -> Result<(String, DrkTokenId)> {
|
||||
if let Some(token_id) = &token_list.search_id(symbol)? {
|
||||
return Ok((symbol.to_string(), generate_id(token_id, network_name)?))
|
||||
};
|
||||
@@ -106,7 +106,7 @@ impl DrkTokenList {
|
||||
Err(Error::NotSupportedToken)
|
||||
}
|
||||
|
||||
pub fn symbol_from_id(&self, id: &pallas::Base) -> Result<Option<(NetworkName, String)>> {
|
||||
pub fn symbol_from_id(&self, id: &DrkTokenId) -> Result<Option<(NetworkName, String)>> {
|
||||
for (network, tokens) in self.tokens.iter() {
|
||||
for (key, val) in tokens.iter() {
|
||||
if val == id {
|
||||
|
||||
@@ -2,14 +2,19 @@ use std::{path::Path, str::FromStr};
|
||||
|
||||
use async_std::sync::Arc;
|
||||
use log::{debug, error, info};
|
||||
use pasta_curves::pallas;
|
||||
use sqlx::{
|
||||
sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePoolOptions},
|
||||
Row, SqlitePool,
|
||||
};
|
||||
|
||||
use super::{Keypair, WalletApi};
|
||||
use crate::{client::ClientFailed, types::*, util::NetworkName, Error, Result};
|
||||
use super::wallet_api::WalletApi;
|
||||
use crate::{
|
||||
client::ClientFailed,
|
||||
crypto::keypair::{Keypair, PublicKey, SecretKey},
|
||||
types::DrkTokenId,
|
||||
util::NetworkName,
|
||||
Error, Result,
|
||||
};
|
||||
|
||||
pub type CashierDbPtr = Arc<CashierDb>;
|
||||
|
||||
@@ -27,7 +32,7 @@ pub struct WithdrawToken {
|
||||
}
|
||||
|
||||
pub struct DepositToken {
|
||||
pub drk_public_key: DrkPublicKey,
|
||||
pub drk_public_key: PublicKey,
|
||||
pub token_key: TokenKey,
|
||||
pub token_id: DrkTokenId,
|
||||
pub mint_address: String,
|
||||
@@ -64,11 +69,15 @@ impl CashierDb {
|
||||
let main_kps = include_str!("../../sql/cashier_main_keypairs.sql");
|
||||
let deposit_kps = include_str!("../../sql/cashier_deposit_keypairs.sql");
|
||||
let withdraw_kps = include_str!("../../sql/cashier_withdraw_keypairs.sql");
|
||||
|
||||
let mut conn = self.conn.acquire().await?;
|
||||
|
||||
debug!("Initializing main keypairs table");
|
||||
sqlx::query(main_kps).execute(&mut conn).await?;
|
||||
|
||||
debug!("Initializing deposit keypairs table");
|
||||
sqlx::query(deposit_kps).execute(&mut conn).await?;
|
||||
|
||||
debug!("Initializing withdraw keypairs table");
|
||||
sqlx::query(withdraw_kps).execute(&mut conn).await?;
|
||||
Ok(())
|
||||
@@ -130,8 +139,8 @@ impl CashierDb {
|
||||
pub async fn put_withdraw_keys(
|
||||
&self,
|
||||
token_key_public: &[u8],
|
||||
d_key_public: &pallas::Point,
|
||||
d_key_secret: &pallas::Scalar,
|
||||
d_key_public: &PublicKey,
|
||||
d_key_secret: &SecretKey,
|
||||
network: &NetworkName,
|
||||
token_id: &DrkTokenId,
|
||||
mint_address: String,
|
||||
@@ -167,7 +176,7 @@ impl CashierDb {
|
||||
|
||||
pub async fn put_deposit_keys(
|
||||
&self,
|
||||
d_key_public: &DrkPublicKey,
|
||||
d_key_public: &PublicKey,
|
||||
token_key_secret: &[u8],
|
||||
token_key_public: &[u8],
|
||||
network: &NetworkName,
|
||||
@@ -202,7 +211,7 @@ impl CashierDb {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn get_withdraw_private_keys(&self) -> Result<Vec<DrkSecretKey>> {
|
||||
pub async fn get_withdraw_private_keys(&self) -> Result<Vec<SecretKey>> {
|
||||
debug!("Getting withdraw private keys");
|
||||
let confirm = self.get_value_serialized(&false)?;
|
||||
|
||||
@@ -217,7 +226,7 @@ impl CashierDb {
|
||||
|
||||
let mut secret_keys = vec![];
|
||||
for row in rows {
|
||||
let key = self.get_value_deserialized(row.get("d_key_secret"))?;
|
||||
let key: SecretKey = self.get_value_deserialized(row.get("d_key_secret"))?;
|
||||
secret_keys.push(key);
|
||||
}
|
||||
|
||||
@@ -226,7 +235,7 @@ impl CashierDb {
|
||||
|
||||
pub async fn get_withdraw_token_public_key_by_dkey_public(
|
||||
&self,
|
||||
pubkey: &DrkPublicKey,
|
||||
pubkey: &PublicKey,
|
||||
) -> Result<Option<WithdrawToken>> {
|
||||
debug!("Get token address by pubkey");
|
||||
let d_key_public = self.get_value_serialized(pubkey)?;
|
||||
@@ -259,7 +268,7 @@ impl CashierDb {
|
||||
|
||||
pub async fn get_deposit_token_keys_by_dkey_public(
|
||||
&self,
|
||||
d_key_public: &DrkPublicKey,
|
||||
d_key_public: &PublicKey,
|
||||
network: &NetworkName,
|
||||
) -> Result<Vec<TokenKey>> {
|
||||
debug!("Checking for existing dkey");
|
||||
@@ -350,7 +359,7 @@ impl CashierDb {
|
||||
|
||||
pub async fn confirm_deposit_key_record(
|
||||
&self,
|
||||
d_key_public: &DrkPublicKey,
|
||||
d_key_public: &PublicKey,
|
||||
network: &NetworkName,
|
||||
) -> Result<()> {
|
||||
debug!("Confirm deposit keys");
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
pub mod cashierdb;
|
||||
pub mod wallet_api;
|
||||
pub mod walletdb;
|
||||
|
||||
pub use cashierdb::{CashierDb, CashierDbPtr};
|
||||
pub use wallet_api::WalletApi;
|
||||
pub use walletdb::{Keypair, WalletDb, WalletPtr};
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
use std::{path::Path, str::FromStr};
|
||||
|
||||
use async_std::sync::Arc;
|
||||
use halo2::arithmetic::Field;
|
||||
use halo2_gadgets::ecc::FixedPoints;
|
||||
use log::{debug, error, info};
|
||||
use pasta_curves::pallas;
|
||||
use rand::rngs::OsRng;
|
||||
use sqlx::{
|
||||
sqlite::{SqliteConnectOptions, SqliteJournalMode},
|
||||
@@ -14,25 +11,23 @@ use sqlx::{
|
||||
use crate::{
|
||||
client::ClientFailed,
|
||||
crypto::{
|
||||
coin::Coin, constants::OrchardFixedBases, note::Note, nullifier::Nullifier, util::mod_r_p,
|
||||
coin::Coin,
|
||||
keypair::{Keypair, PublicKey, SecretKey},
|
||||
note::Note,
|
||||
nullifier::Nullifier,
|
||||
OwnCoin, OwnCoins,
|
||||
},
|
||||
serial::serialize,
|
||||
wallet::WalletApi,
|
||||
types::DrkTokenId,
|
||||
wallet::wallet_api::WalletApi,
|
||||
Error, Result,
|
||||
};
|
||||
|
||||
pub type WalletPtr = Arc<WalletDb>;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Keypair {
|
||||
pub public: pallas::Point,
|
||||
pub secret: pallas::Base,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Balance {
|
||||
pub token_id: pallas::Base,
|
||||
pub token_id: DrkTokenId,
|
||||
pub value: u64,
|
||||
pub nullifier: Nullifier,
|
||||
}
|
||||
@@ -73,9 +68,12 @@ impl WalletDb {
|
||||
debug!("Initializing wallet database");
|
||||
let keys = include_str!("../../sql/keys.sql");
|
||||
let coins = include_str!("../../sql/coins.sql");
|
||||
|
||||
let mut conn = self.conn.acquire().await?;
|
||||
|
||||
debug!("Initializing keys table");
|
||||
sqlx::query(keys).execute(&mut conn).await?;
|
||||
|
||||
debug!("Initializing coins table");
|
||||
sqlx::query(coins).execute(&mut conn).await?;
|
||||
Ok(())
|
||||
@@ -92,23 +90,22 @@ impl WalletDb {
|
||||
Err(Error::from(ClientFailed::KeyExists))
|
||||
}
|
||||
Err(_) => {
|
||||
let secret = pallas::Base::random(&mut OsRng);
|
||||
let public = OrchardFixedBases::NullifierK.generator() * mod_r_p(secret);
|
||||
self.put_keypair(&public, &secret).await?;
|
||||
let keypair = Keypair::random(&mut OsRng);
|
||||
self.put_keypair(&keypair.public, &keypair.secret).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn put_keypair(&self, public: &pallas::Point, secret: &pallas::Base) -> Result<()> {
|
||||
pub async fn put_keypair(&self, public: &PublicKey, secret: &SecretKey) -> Result<()> {
|
||||
debug!("Writing keypair into the wallet database");
|
||||
let p = serialize(public);
|
||||
let s = serialize(secret);
|
||||
let pubkey = serialize(&public.0);
|
||||
let secret = serialize(&secret.0);
|
||||
|
||||
let mut conn = self.conn.acquire().await?;
|
||||
sqlx::query("INSERT INTO keys(public, secret) VALUES (?1, ?2)")
|
||||
.bind(p)
|
||||
.bind(s)
|
||||
.bind(pubkey)
|
||||
.bind(secret)
|
||||
.execute(&mut conn)
|
||||
.await?;
|
||||
|
||||
@@ -121,8 +118,8 @@ impl WalletDb {
|
||||
|
||||
// TODO: Think about multiple keys
|
||||
let row = sqlx::query("SELECT * FROM keys").fetch_one(&mut conn).await?;
|
||||
let public: pallas::Point = self.get_value_deserialized(row.get("public"))?;
|
||||
let secret: pallas::Base = self.get_value_deserialized(row.get("secret"))?;
|
||||
let public: PublicKey = self.get_value_deserialized(row.get("public"))?;
|
||||
let secret: SecretKey = self.get_value_deserialized(row.get("secret"))?;
|
||||
|
||||
Ok(vec![Keypair { public, secret }])
|
||||
}
|
||||
@@ -256,7 +253,7 @@ impl WalletDb {
|
||||
Ok(Balances { list })
|
||||
}
|
||||
|
||||
pub async fn get_token_id(&self) -> Result<Vec<pallas::Base>> {
|
||||
pub async fn get_token_id(&self) -> Result<Vec<DrkTokenId>> {
|
||||
debug!("Getting token ID");
|
||||
let is_spent = 0;
|
||||
|
||||
@@ -275,7 +272,7 @@ impl WalletDb {
|
||||
Ok(token_ids)
|
||||
}
|
||||
|
||||
pub async fn token_id_exists(&self, token_id: pallas::Base) -> Result<bool> {
|
||||
pub async fn token_id_exists(&self, token_id: DrkTokenId) -> Result<bool> {
|
||||
debug!("Checking if token ID exists");
|
||||
let is_spent = 0;
|
||||
let id = self.get_value_serialized(&token_id)?;
|
||||
|
||||
Reference in New Issue
Block a user