|
@@ -1,16 +1,10 @@
|
|
|
use async_std::sync::{Arc, Mutex};
|
|
use async_std::sync::{Arc, Mutex};
|
|
|
-
|
|
|
|
|
use incrementalmerkletree::{bridgetree::BridgeTree, Tree};
|
|
use incrementalmerkletree::{bridgetree::BridgeTree, Tree};
|
|
|
-use log::{debug, info, warn};
|
|
|
|
|
-use smol::Executor;
|
|
|
|
|
-use url::Url;
|
|
|
|
|
|
|
+use lazy_init::Lazy;
|
|
|
|
|
+use log::{debug, error, info};
|
|
|
|
|
|
|
|
-use super::{
|
|
|
|
|
- service::GatewayClient,
|
|
|
|
|
- state::{state_transition, State, StateUpdate},
|
|
|
|
|
-};
|
|
|
|
|
|
|
+use super::state::{state_transition, State};
|
|
|
use crate::{
|
|
use crate::{
|
|
|
- blockchain::{rocks::columns, Rocks, RocksColumn, Slab},
|
|
|
|
|
crypto::{
|
|
crypto::{
|
|
|
address::Address,
|
|
address::Address,
|
|
|
coin::Coin,
|
|
coin::Coin,
|
|
@@ -20,149 +14,130 @@ use crate::{
|
|
|
types::DrkTokenId,
|
|
types::DrkTokenId,
|
|
|
OwnCoin,
|
|
OwnCoin,
|
|
|
},
|
|
},
|
|
|
- tx,
|
|
|
|
|
- util::serial::{Decodable, Encodable},
|
|
|
|
|
- wallet::{
|
|
|
|
|
- cashierdb::CashierDbPtr,
|
|
|
|
|
- walletdb::{Balances, WalletPtr},
|
|
|
|
|
|
|
+ tx::{
|
|
|
|
|
+ builder::{
|
|
|
|
|
+ TransactionBuilder, TransactionBuilderClearInputInfo, TransactionBuilderInputInfo,
|
|
|
|
|
+ TransactionBuilderOutputInfo,
|
|
|
|
|
+ },
|
|
|
|
|
+ Transaction,
|
|
|
},
|
|
},
|
|
|
- zk::circuit::{MintContract, SpendContract},
|
|
|
|
|
|
|
+ util::serial::Encodable,
|
|
|
|
|
+ wallet::walletdb::{Balances, WalletPtr},
|
|
|
|
|
+ zk::circuit::MintContract,
|
|
|
Result,
|
|
Result,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+pub type ClientResult<T> = std::result::Result<T, ClientFailed>;
|
|
|
|
|
+
|
|
|
#[derive(Debug, Clone, thiserror::Error)]
|
|
#[derive(Debug, Clone, thiserror::Error)]
|
|
|
pub enum ClientFailed {
|
|
pub enum ClientFailed {
|
|
|
- #[error("Here is not enough value {0}")]
|
|
|
|
|
|
|
+ #[error("Not enough value: {0}")]
|
|
|
NotEnoughValue(u64),
|
|
NotEnoughValue(u64),
|
|
|
- #[error("Invalid Address {0}")]
|
|
|
|
|
|
|
+
|
|
|
|
|
+ #[error("Invalid address: {0}")]
|
|
|
InvalidAddress(String),
|
|
InvalidAddress(String),
|
|
|
- #[error("Invalid Amount {0}")]
|
|
|
|
|
|
|
+
|
|
|
|
|
+ #[error("Invalid amount: {0}")]
|
|
|
InvalidAmount(u64),
|
|
InvalidAmount(u64),
|
|
|
- #[error("Unable to get deposit address")]
|
|
|
|
|
- UnableToGetDepositAddress,
|
|
|
|
|
- #[error("Unable to get withdraw address")]
|
|
|
|
|
- UnableToGetWithdrawAddress,
|
|
|
|
|
- #[error("Does not have cashier public key")]
|
|
|
|
|
- DoesNotHaveCashierPublicKey,
|
|
|
|
|
- #[error("Does not have keypair")]
|
|
|
|
|
- DoesNotHaveKeypair,
|
|
|
|
|
- #[error("Password is empty. Cannot create database")]
|
|
|
|
|
- EmptyPassword,
|
|
|
|
|
- #[error("Wallet already initialized")]
|
|
|
|
|
- WalletInitialized,
|
|
|
|
|
- #[error("Keypair already exists")]
|
|
|
|
|
- KeyExists,
|
|
|
|
|
- #[error("{0}")]
|
|
|
|
|
|
|
+
|
|
|
|
|
+ #[error("Client error: {0}")]
|
|
|
ClientError(String),
|
|
ClientError(String),
|
|
|
|
|
+
|
|
|
#[error("Verify error: {0}")]
|
|
#[error("Verify error: {0}")]
|
|
|
VerifyError(String),
|
|
VerifyError(String),
|
|
|
- #[error("Merkle tree already exists")]
|
|
|
|
|
- TreeExists,
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-pub type ClientResult<T> = std::result::Result<T, ClientFailed>;
|
|
|
|
|
-
|
|
|
|
|
impl From<crate::error::Error> for ClientFailed {
|
|
impl From<crate::error::Error> for ClientFailed {
|
|
|
- fn from(err: crate::error::Error) -> ClientFailed {
|
|
|
|
|
- ClientFailed::ClientError(err.to_string())
|
|
|
|
|
|
|
+ fn from(err: crate::error::Error) -> Self {
|
|
|
|
|
+ Self::ClientError(err.to_string())
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
impl From<super::state::VerifyFailed> for ClientFailed {
|
|
impl From<super::state::VerifyFailed> for ClientFailed {
|
|
|
- fn from(err: super::state::VerifyFailed) -> ClientFailed {
|
|
|
|
|
- ClientFailed::VerifyError(err.to_string())
|
|
|
|
|
|
|
+ fn from(err: super::state::VerifyFailed) -> Self {
|
|
|
|
|
+ Self::VerifyError(err.to_string())
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/// The Client structure, used for transaction operations.
|
|
|
|
|
+/// This includes, receiving, broadcasting, and building.
|
|
|
pub struct Client {
|
|
pub struct Client {
|
|
|
pub main_keypair: Keypair,
|
|
pub main_keypair: Keypair,
|
|
|
- gateway: GatewayClient,
|
|
|
|
|
wallet: WalletPtr,
|
|
wallet: WalletPtr,
|
|
|
- mint_pk: ProvingKey,
|
|
|
|
|
- spend_pk: ProvingKey,
|
|
|
|
|
|
|
+ mint_pk: Lazy<ProvingKey>,
|
|
|
|
|
+ burn_pk: Lazy<ProvingKey>,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
impl Client {
|
|
impl Client {
|
|
|
- pub async fn new(
|
|
|
|
|
- rocks: Arc<Rocks>,
|
|
|
|
|
- gateway_addrs: (Url, Url),
|
|
|
|
|
- wallet: WalletPtr,
|
|
|
|
|
- ) -> Result<Self> {
|
|
|
|
|
|
|
+ pub async fn new(wallet: WalletPtr) -> Result<Self> {
|
|
|
|
|
+ // Initialize or load the wallet
|
|
|
wallet.init_db().await?;
|
|
wallet.init_db().await?;
|
|
|
|
|
|
|
|
- // Check if there is a default keypair
|
|
|
|
|
|
|
+ // Check if there is a default keypair and generate one in
|
|
|
|
|
+ // case we don't have any.
|
|
|
if wallet.get_default_keypair().await.is_err() {
|
|
if wallet.get_default_keypair().await.is_err() {
|
|
|
- // Generate a new keypair if we don't have any.
|
|
|
|
|
|
|
+ // TODO: Clean this up with Option<T> to have less calls.
|
|
|
if wallet.get_keypairs().await?.is_empty() {
|
|
if wallet.get_keypairs().await?.is_empty() {
|
|
|
wallet.keygen().await?;
|
|
wallet.keygen().await?;
|
|
|
}
|
|
}
|
|
|
- // set the first keypair as the default one
|
|
|
|
|
- wallet.set_default_keypair(&wallet.get_keypairs().await?[0].public).await?;
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ wallet.set_default_keypair(&wallet.get_keypairs().await?[0].public).await?;
|
|
|
|
|
+
|
|
|
// Generate merkle tree if we don't have one.
|
|
// Generate merkle tree if we don't have one.
|
|
|
|
|
+ // TODO: See what to do about this
|
|
|
if wallet.get_tree().await.is_err() {
|
|
if wallet.get_tree().await.is_err() {
|
|
|
wallet.tree_gen().await?;
|
|
wallet.tree_gen().await?;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
let main_keypair = wallet.get_default_keypair().await?;
|
|
let main_keypair = wallet.get_default_keypair().await?;
|
|
|
- info!("Main keypair: {}", Address::from(main_keypair.public).to_string());
|
|
|
|
|
-
|
|
|
|
|
- debug!("Creating GatewayClient");
|
|
|
|
|
- let slabstore = RocksColumn::<columns::Slabs>::new(rocks);
|
|
|
|
|
- let gateway = GatewayClient::new(gateway_addrs.0, gateway_addrs.1, slabstore)?;
|
|
|
|
|
-
|
|
|
|
|
- // TODO: These should go to a better place.
|
|
|
|
|
- debug!("Building proving key for the mint contract...");
|
|
|
|
|
- let mint_pk = ProvingKey::build(11, &MintContract::default());
|
|
|
|
|
- debug!("Building proving key for the spend contract...");
|
|
|
|
|
- let spend_pk = ProvingKey::build(11, &SpendContract::default());
|
|
|
|
|
-
|
|
|
|
|
- let client = Client { main_keypair, gateway, wallet, mint_pk, spend_pk };
|
|
|
|
|
- Ok(client)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- pub async fn start(&mut self) -> Result<()> {
|
|
|
|
|
- self.gateway.start().await
|
|
|
|
|
|
|
+ info!(target: "client", "Main keypair: {}", Address::from(main_keypair.public));
|
|
|
|
|
+
|
|
|
|
|
+ Ok(Self {
|
|
|
|
|
+ //main_keypair: Mutex::new(main_keypair),
|
|
|
|
|
+ main_keypair,
|
|
|
|
|
+ wallet,
|
|
|
|
|
+ mint_pk: Lazy::new(),
|
|
|
|
|
+ burn_pk: Lazy::new(),
|
|
|
|
|
+ })
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
async fn build_slab_from_tx(
|
|
async fn build_slab_from_tx(
|
|
|
- &mut self,
|
|
|
|
|
|
|
+ &self,
|
|
|
pubkey: PublicKey,
|
|
pubkey: PublicKey,
|
|
|
value: u64,
|
|
value: u64,
|
|
|
token_id: DrkTokenId,
|
|
token_id: DrkTokenId,
|
|
|
clear_input: bool,
|
|
clear_input: bool,
|
|
|
state: Arc<Mutex<State>>,
|
|
state: Arc<Mutex<State>>,
|
|
|
) -> ClientResult<Vec<Coin>> {
|
|
) -> ClientResult<Vec<Coin>> {
|
|
|
- debug!("Begin building slab from tx");
|
|
|
|
|
- let mut clear_inputs: Vec<tx::TransactionBuilderClearInputInfo> = vec![];
|
|
|
|
|
- let mut inputs: Vec<tx::TransactionBuilderInputInfo> = vec![];
|
|
|
|
|
- let mut outputs: Vec<tx::TransactionBuilderOutputInfo> = vec![];
|
|
|
|
|
- let mut coins: Vec<Coin> = vec![];
|
|
|
|
|
|
|
+ debug!("build_slab_from_tx(): Begin building slab from tx");
|
|
|
|
|
+ let mut clear_inputs = vec![];
|
|
|
|
|
+ let mut inputs = vec![];
|
|
|
|
|
+ let mut outputs = vec![];
|
|
|
|
|
+ let mut coins = vec![];
|
|
|
|
|
|
|
|
if clear_input {
|
|
if clear_input {
|
|
|
- // TODO: FIXME:
|
|
|
|
|
|
|
+ debug!("build_slab_from_tx(): Building clear input");
|
|
|
let signature_secret = self.main_keypair.secret;
|
|
let signature_secret = self.main_keypair.secret;
|
|
|
- let input = tx::TransactionBuilderClearInputInfo { value, token_id, signature_secret };
|
|
|
|
|
|
|
+ let input = TransactionBuilderClearInputInfo { value, token_id, signature_secret };
|
|
|
clear_inputs.push(input);
|
|
clear_inputs.push(input);
|
|
|
} else {
|
|
} else {
|
|
|
- debug!("Start building tx inputs");
|
|
|
|
|
- let mut inputs_value = 0_u64;
|
|
|
|
|
|
|
+ debug!("build_slab_from_tx(): Building tx inputs");
|
|
|
|
|
+ let mut inputs_value = 0;
|
|
|
let state_m = state.lock().await;
|
|
let state_m = state.lock().await;
|
|
|
let own_coins = self.wallet.get_own_coins().await?;
|
|
let own_coins = self.wallet.get_own_coins().await?;
|
|
|
|
|
|
|
|
for own_coin in own_coins.iter() {
|
|
for own_coin in own_coins.iter() {
|
|
|
if inputs_value >= value {
|
|
if inputs_value >= value {
|
|
|
|
|
+ debug!("build_slab_from_tx(): inputs_value >= value");
|
|
|
break
|
|
break
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- 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?
|
|
|
|
|
|
|
+ let leaf_position = own_coin.leaf_position;
|
|
|
|
|
+ let merkle_path = state_m.tree.authentication_path(leaf_position).unwrap();
|
|
|
inputs_value += own_coin.note.value;
|
|
inputs_value += own_coin.note.value;
|
|
|
|
|
|
|
|
- let input = tx::TransactionBuilderInputInfo {
|
|
|
|
|
|
|
+ let input = TransactionBuilderInputInfo {
|
|
|
leaf_position,
|
|
leaf_position,
|
|
|
merkle_path,
|
|
merkle_path,
|
|
|
secret: own_coin.secret,
|
|
secret: own_coin.secret,
|
|
@@ -172,56 +147,60 @@ impl Client {
|
|
|
inputs.push(input);
|
|
inputs.push(input);
|
|
|
coins.push(own_coin.coin);
|
|
coins.push(own_coin.coin);
|
|
|
}
|
|
}
|
|
|
|
|
+ // Release state lock
|
|
|
|
|
+ drop(state_m);
|
|
|
|
|
|
|
|
if inputs_value < value {
|
|
if inputs_value < value {
|
|
|
|
|
+ error!("build_slab_from_tx(): Not enough value to build tx inputs");
|
|
|
return Err(ClientFailed::NotEnoughValue(inputs_value))
|
|
return Err(ClientFailed::NotEnoughValue(inputs_value))
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if inputs_value > value {
|
|
if inputs_value > value {
|
|
|
- let return_value: u64 = inputs_value - value;
|
|
|
|
|
-
|
|
|
|
|
- outputs.push(tx::TransactionBuilderOutputInfo {
|
|
|
|
|
|
|
+ let return_value = inputs_value - value;
|
|
|
|
|
+ outputs.push(TransactionBuilderOutputInfo {
|
|
|
value: return_value,
|
|
value: return_value,
|
|
|
token_id,
|
|
token_id,
|
|
|
public: self.main_keypair.public,
|
|
public: self.main_keypair.public,
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- debug!("Finish building inputs");
|
|
|
|
|
|
|
+ debug!("build_slab_from_tx(): Finished building inputs");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- outputs.push(tx::TransactionBuilderOutputInfo { value, token_id, public: pubkey });
|
|
|
|
|
-
|
|
|
|
|
- let builder = tx::TransactionBuilder { clear_inputs, inputs, outputs };
|
|
|
|
|
-
|
|
|
|
|
|
|
+ outputs.push(TransactionBuilderOutputInfo { value, token_id, public: pubkey });
|
|
|
|
|
+ let builder = TransactionBuilder { clear_inputs, inputs, outputs };
|
|
|
let mut tx_data = vec![];
|
|
let mut tx_data = vec![];
|
|
|
|
|
|
|
|
- let tx: tx::Transaction = builder.build(&self.mint_pk, &self.spend_pk)?;
|
|
|
|
|
- tx.encode(&mut tx_data).expect("encode tx");
|
|
|
|
|
-
|
|
|
|
|
- let slab = Slab::new(tx_data);
|
|
|
|
|
- debug!("Finish building slab from tx");
|
|
|
|
|
|
|
+ let mint_pk = self.mint_pk.get_or_create(Client::build_mint_pk);
|
|
|
|
|
+ let burn_pk = self.burn_pk.get_or_create(Client::build_burn_pk);
|
|
|
|
|
+ let tx = builder.build(mint_pk, burn_pk)?;
|
|
|
|
|
+ tx.encode(&mut tx_data)?;
|
|
|
|
|
|
|
|
- // Check if it's valid before sending to gateway
|
|
|
|
|
|
|
+ // Check if state transition is valid before broadcasting
|
|
|
|
|
+ debug!("build_slab_from_tx(): Checking if state transition is valid");
|
|
|
let state = &*state.lock().await;
|
|
let state = &*state.lock().await;
|
|
|
|
|
+ debug!("build_slab_from_tx(): Got state lock");
|
|
|
state_transition(state, tx)?;
|
|
state_transition(state, tx)?;
|
|
|
|
|
+ debug!("build_slab_from_tx(): Successful state transition");
|
|
|
|
|
+
|
|
|
|
|
+ debug!("build_slab_from_tx(): Broadcasting transaction");
|
|
|
|
|
+ // TODO: Send to some channel, let's not p2p here
|
|
|
|
|
+ //self.p2p.broadcast(Tx(Transaction)).await?;
|
|
|
|
|
+ debug!("build_slab_from_tx(): Broadcasted successfully");
|
|
|
|
|
|
|
|
- debug!("Sending slab to gateway");
|
|
|
|
|
- self.gateway.put_slab(slab).await?;
|
|
|
|
|
- debug!("Slab sent to gateway successfully");
|
|
|
|
|
Ok(coins)
|
|
Ok(coins)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
pub async fn send(
|
|
pub async fn send(
|
|
|
- &mut self,
|
|
|
|
|
|
|
+ &self,
|
|
|
pubkey: PublicKey,
|
|
pubkey: PublicKey,
|
|
|
amount: u64,
|
|
amount: u64,
|
|
|
token_id: DrkTokenId,
|
|
token_id: DrkTokenId,
|
|
|
clear_input: bool,
|
|
clear_input: bool,
|
|
|
state: Arc<Mutex<State>>,
|
|
state: Arc<Mutex<State>>,
|
|
|
) -> ClientResult<()> {
|
|
) -> ClientResult<()> {
|
|
|
- // TODO: TOKEN debug
|
|
|
|
|
- debug!("Sending {}", amount);
|
|
|
|
|
|
|
+ // TODO: Token id debug
|
|
|
|
|
+ debug!("send(): Sending {}", amount);
|
|
|
|
|
|
|
|
if amount == 0 {
|
|
if amount == 0 {
|
|
|
return Err(ClientFailed::InvalidAmount(0))
|
|
return Err(ClientFailed::InvalidAmount(0))
|
|
@@ -229,147 +208,57 @@ impl Client {
|
|
|
|
|
|
|
|
let coins = self.build_slab_from_tx(pubkey, amount, token_id, clear_input, state).await?;
|
|
let coins = self.build_slab_from_tx(pubkey, amount, token_id, clear_input, state).await?;
|
|
|
for coin in coins.iter() {
|
|
for coin in coins.iter() {
|
|
|
|
|
+ // TODO: This should be more robust. In case our transaction is denied,
|
|
|
|
|
+ // we want to revert to be able to send again.
|
|
|
self.wallet.confirm_spend_coin(coin).await?;
|
|
self.wallet.confirm_spend_coin(coin).await?;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- debug!("Sent {}", amount);
|
|
|
|
|
|
|
+ debug!("send(): Sent {}", amount);
|
|
|
Ok(())
|
|
Ok(())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
pub async fn transfer(
|
|
pub async fn transfer(
|
|
|
- &mut self,
|
|
|
|
|
|
|
+ &self,
|
|
|
token_id: DrkTokenId,
|
|
token_id: DrkTokenId,
|
|
|
pubkey: PublicKey,
|
|
pubkey: PublicKey,
|
|
|
amount: u64,
|
|
amount: u64,
|
|
|
state: Arc<Mutex<State>>,
|
|
state: Arc<Mutex<State>>,
|
|
|
) -> ClientResult<()> {
|
|
) -> ClientResult<()> {
|
|
|
- debug!("Start transfer {}", amount);
|
|
|
|
|
- let token_id_exists = self.wallet.token_id_exists(token_id).await?;
|
|
|
|
|
-
|
|
|
|
|
- if token_id_exists {
|
|
|
|
|
|
|
+ debug!("transfer(): Start transfer {}", amount);
|
|
|
|
|
+ if self.wallet.token_id_exists(token_id).await? {
|
|
|
self.send(pubkey, amount, token_id, false, state).await?;
|
|
self.send(pubkey, amount, token_id, false, state).await?;
|
|
|
- } else {
|
|
|
|
|
- return Err(ClientFailed::NotEnoughValue(amount))
|
|
|
|
|
|
|
+ debug!("transfer(): Finish transfer {}", amount);
|
|
|
|
|
+ return Ok(())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- debug!("Finish transfer {}", amount);
|
|
|
|
|
- Ok(())
|
|
|
|
|
|
|
+ Err(ClientFailed::NotEnoughValue(amount))
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // TODO: Should this function run on finalized blocks and iterate over its transactions?
|
|
|
async fn update_state(
|
|
async fn update_state(
|
|
|
secret_keys: Vec<SecretKey>,
|
|
secret_keys: Vec<SecretKey>,
|
|
|
- slab: &Slab,
|
|
|
|
|
|
|
+ tx: Transaction,
|
|
|
state: Arc<Mutex<State>>,
|
|
state: Arc<Mutex<State>>,
|
|
|
wallet: WalletPtr,
|
|
wallet: WalletPtr,
|
|
|
notify: Option<async_channel::Sender<(PublicKey, u64)>>,
|
|
notify: Option<async_channel::Sender<(PublicKey, u64)>>,
|
|
|
) -> Result<()> {
|
|
) -> Result<()> {
|
|
|
- debug!("Building tx from slab and updating the state");
|
|
|
|
|
- let payload = slab.get_payload();
|
|
|
|
|
- /*
|
|
|
|
|
- use std::io::Write;
|
|
|
|
|
- let mut file = std::fs::File::create("/tmp/payload.txt")?;
|
|
|
|
|
- file.write_all(&payload)?;
|
|
|
|
|
- */
|
|
|
|
|
- debug!("Decoding payload");
|
|
|
|
|
- let tx = tx::Transaction::decode(&payload[..])?;
|
|
|
|
|
-
|
|
|
|
|
- let update: StateUpdate;
|
|
|
|
|
-
|
|
|
|
|
- // This is separate because otherwise the mutex is never unlocked.
|
|
|
|
|
|
|
+ debug!("update_state(): Begin state update");
|
|
|
|
|
+ debug!("update_state(): Acquiring state lock");
|
|
|
|
|
+ let update;
|
|
|
{
|
|
{
|
|
|
- debug!("Acquiring state lock");
|
|
|
|
|
let state = &*state.lock().await;
|
|
let state = &*state.lock().await;
|
|
|
update = state_transition(state, tx)?;
|
|
update = state_transition(state, tx)?;
|
|
|
- debug!("Successfully passed state_transition");
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- debug!("Acquiring state lock");
|
|
|
|
|
|
|
+ debug!("update_state(): Trying to apply the new state");
|
|
|
let mut state = state.lock().await;
|
|
let mut state = state.lock().await;
|
|
|
- debug!("Trying to apply the new state");
|
|
|
|
|
state.apply(update, secret_keys, notify, wallet).await?;
|
|
state.apply(update, secret_keys, notify, wallet).await?;
|
|
|
- debug!("Successfully passed state.apply");
|
|
|
|
|
|
|
+ drop(state);
|
|
|
|
|
+ debug!("update_state(): Successfully updated state");
|
|
|
|
|
|
|
|
Ok(())
|
|
Ok(())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- pub async fn connect_to_subscriber_from_cashier(
|
|
|
|
|
- &self,
|
|
|
|
|
- state: Arc<Mutex<State>>,
|
|
|
|
|
- cashier_wallet: CashierDbPtr,
|
|
|
|
|
- notify: async_channel::Sender<(PublicKey, u64)>,
|
|
|
|
|
- executor: Arc<Executor<'_>>,
|
|
|
|
|
- ) -> Result<()> {
|
|
|
|
|
- debug!("Start subscriber for cashier");
|
|
|
|
|
- let gateway_slabs_sub = self.gateway.start_subscriber(executor.clone()).await?;
|
|
|
|
|
-
|
|
|
|
|
- let secret_key = self.main_keypair.secret;
|
|
|
|
|
- let wallet = self.wallet.clone();
|
|
|
|
|
-
|
|
|
|
|
- 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![secret_key];
|
|
|
|
|
- let mut withdraw_keys = cashier_wallet.get_withdraw_private_keys().await?;
|
|
|
|
|
- secret_keys.append(&mut withdraw_keys);
|
|
|
|
|
-
|
|
|
|
|
- let update_state = Self::update_state(
|
|
|
|
|
- secret_keys,
|
|
|
|
|
- &slab,
|
|
|
|
|
- state.clone(),
|
|
|
|
|
- wallet.clone(),
|
|
|
|
|
- Some(notify.clone()),
|
|
|
|
|
- )
|
|
|
|
|
- .await;
|
|
|
|
|
-
|
|
|
|
|
- if let Err(e) = update_state {
|
|
|
|
|
- warn!("Update state: {}", e);
|
|
|
|
|
- continue
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- task.detach();
|
|
|
|
|
- Ok(())
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- pub async fn connect_to_subscriber(
|
|
|
|
|
- &self,
|
|
|
|
|
- state: Arc<Mutex<State>>,
|
|
|
|
|
- executor: Arc<Executor<'_>>,
|
|
|
|
|
- ) -> Result<()> {
|
|
|
|
|
- debug!("Start subscriber for darkfid");
|
|
|
|
|
- let gateway_slabs_sub = self.gateway.start_subscriber(executor.clone()).await?;
|
|
|
|
|
-
|
|
|
|
|
- let secret_key = self.main_keypair.secret;
|
|
|
|
|
- let wallet = self.wallet.clone();
|
|
|
|
|
-
|
|
|
|
|
- let task: smol::Task<Result<()>> = executor.spawn(async move {
|
|
|
|
|
- loop {
|
|
|
|
|
- let slab = gateway_slabs_sub.recv().await?;
|
|
|
|
|
- debug!("Received new slab");
|
|
|
|
|
-
|
|
|
|
|
- let update_state = Self::update_state(
|
|
|
|
|
- vec![secret_key],
|
|
|
|
|
- &slab,
|
|
|
|
|
- state.clone(),
|
|
|
|
|
- wallet.clone(),
|
|
|
|
|
- None,
|
|
|
|
|
- )
|
|
|
|
|
- .await;
|
|
|
|
|
-
|
|
|
|
|
- if let Err(e) = update_state {
|
|
|
|
|
- warn!("Update state: {}", e);
|
|
|
|
|
- continue
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- task.detach();
|
|
|
|
|
- Ok(())
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
pub async fn init_db(&self) -> Result<()> {
|
|
pub async fn init_db(&self) -> Result<()> {
|
|
|
self.wallet.init_db().await
|
|
self.wallet.init_db().await
|
|
|
}
|
|
}
|
|
@@ -408,4 +297,12 @@ impl Client {
|
|
|
pub async fn get_tree(&self) -> Result<BridgeTree<MerkleNode, 32>> {
|
|
pub async fn get_tree(&self) -> Result<BridgeTree<MerkleNode, 32>> {
|
|
|
self.wallet.get_tree().await
|
|
self.wallet.get_tree().await
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ fn build_mint_pk() -> ProvingKey {
|
|
|
|
|
+ ProvingKey::build(11, &MintContract::default())
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ fn build_burn_pk() -> ProvingKey {
|
|
|
|
|
+ ProvingKey::build(11, &MintContract::default())
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|