bridge: pass mint_address when subscribe

This commit is contained in:
ghassmo
2021-09-30 16:44:56 +03:00
parent 2ee620ddcf
commit ff8c900ec2
5 changed files with 90 additions and 60 deletions

View File

@@ -90,7 +90,8 @@ impl Cashierd {
expand_path(&config.spend_params_path.clone())?,
),
client_wallet.clone(),
).await?;
)
.await?;
let client = Arc::new(Mutex::new(client));
@@ -119,14 +120,19 @@ impl Cashierd {
for (network, _) in features.iter() {
let keypairs_to_watch = cashier_wallet.get_deposit_token_keys_by_network(&network)?;
for keypair in keypairs_to_watch {
for (private_key, public_key, _token_id, mint_address) in keypairs_to_watch {
let bridge = bridge.clone();
let bridge_subscribtion = bridge.subscribe().await;
let bridge_subscribtion = bridge.subscribe(Some(mint_address)).await;
bridge_subscribtion
.sender
.send(bridge::BridgeRequests {
network: network.clone(),
payload: bridge::BridgeRequestsPayload::Watch(Some((keypair.0, keypair.1))),
payload: bridge::BridgeRequestsPayload::Watch(Some((
private_key,
public_key,
))),
})
.await?;
}
@@ -139,20 +145,21 @@ impl Cashierd {
cashier_wallet: Arc<CashierDb>,
recv_coin: async_channel::Receiver<(jubjub::SubgroupPoint, u64)>,
) -> Result<()> {
let bridge_subscribtion = bridge.subscribe().await;
// received drk coin
let (drk_pub_key, amount) = recv_coin.recv().await?;
debug!(target: "CASHIER DAEMON", "Receive coin with following address and amount: {}, {}"
, drk_pub_key, amount);
// get public key, and asset_id of the token
// get public key, and token_id of the token
let token = cashier_wallet.get_withdraw_token_public_key_by_dkey_public(&drk_pub_key)?;
// send a request to bridge to send equivalent amount of
// received drk coin to token publickey
if let Some((addr, network, _asset_id)) = token {
if let Some((addr, network, _token_id, mint_address)) = token {
let bridge_subscribtion = bridge.subscribe(Some(mint_address)).await;
bridge_subscribtion
.sender
.send(bridge::BridgeRequests {
@@ -191,7 +198,7 @@ impl Cashierd {
}
let network = NetworkName::from_str(args[0].as_str().unwrap()).unwrap();
let token_id = &args[1].as_str().unwrap();
let mut mint_address: String = args[1].as_str().unwrap().to_string();
let drk_pub_key = &args[2].as_str().unwrap();
if !self.features.contains_key(&network.clone()) {
@@ -203,9 +210,13 @@ impl Cashierd {
}
let result: Result<String> = async {
Self::check_token_id(&network, token_id)?;
let token_id = generate_id(&mint_address)?;
let asset_id = generate_id(token_id)?;
let mint_address_opt = Self::check_token_id(&network, &mint_address)?;
if mint_address_opt.is_none() {
mint_address = String::new();
}
let drk_pub_key = bs58::decode(&drk_pub_key).into_vec()?;
let drk_pub_key: jubjub::SubgroupPoint = deserialize(&drk_pub_key)?;
@@ -216,7 +227,7 @@ impl Cashierd {
.get_deposit_token_keys_by_dkey_public(&drk_pub_key, &network)?;
let bridge = self.bridge.clone();
let bridge_subscribtion = bridge.subscribe().await;
let bridge_subscribtion = bridge.subscribe(mint_address_opt).await;
if check.is_empty() {
bridge_subscribtion
@@ -253,7 +264,8 @@ impl Cashierd {
&token_priv,
&serialize(&token_pub),
&network,
&asset_id,
&token_id,
&mint_address,
)?;
return Ok(token_pub);
@@ -284,7 +296,7 @@ impl Cashierd {
}
let network = NetworkName::from_str(args[0].as_str().unwrap()).unwrap();
let token = &args[1].as_str().unwrap();
let mut mint_address: String = args[1].as_str().unwrap().to_string();
let address = &args[2].as_str().unwrap();
let _amount = &args[3];
@@ -297,9 +309,15 @@ impl Cashierd {
}
let result: Result<String> = async {
Self::check_token_id(&network, token)?;
let token_id = generate_id(&mint_address)?;
let mint_address_opt = Self::check_token_id(&network, &mint_address)?;
if mint_address_opt.is_none() {
// empty string
mint_address = String::new();
}
let asset_id = generate_id(&token)?;
let address = serialize(&address.to_string());
let cashier_public: jubjub::SubgroupPoint;
@@ -319,7 +337,8 @@ impl Cashierd {
&cashier_public,
&cashier_secret,
&network,
&asset_id,
&token_id,
&mint_address,
)?;
}
@@ -345,37 +364,21 @@ impl Cashierd {
))
}
fn check_token_id(network: &NetworkName, token_id: &str) -> Result<()> {
fn check_token_id(network: &NetworkName, token_id: &str) -> Result<Option<String>> {
match network {
#[cfg(feature = "sol")]
NetworkName::Solana => {
if token_id != "So11111111111111111111111111111111111111112" {
// This is supposed to be a token mint account now
use drk::service::sol::account_is_initialized_mint;
use drk::service::sol::SolFailed::BadSolAddress;
use solana_client::rpc_client::RpcClient;
use solana_sdk::pubkey::Pubkey;
let pubkey = match Pubkey::from_str(token_id) {
Ok(v) => v,
Err(e) => return Err(Error::from(BadSolAddress(e.to_string()))),
};
// FIXME: Use network name from variable
let rpc = RpcClient::new("https://api.devnet.solana.com".to_string());
if !account_is_initialized_mint(&rpc, &pubkey) {
return Err(Error::CashierInvalidTokenId(
"Given address is not a valid token mint".into(),
));
}
return Ok(Some(token_id.to_string()));
}
return Ok(None);
}
#[cfg(feature = "btc")]
NetworkName::Bitcoin => {
// Handle bitcoin address here if needed
Ok(None)
}
}
Ok(())
}
async fn start(&self, executor: Arc<Executor<'static>>) -> Result<()> {

View File

@@ -32,7 +32,7 @@ async fn run() -> Result<()> {
.await?;
let bridge2 = bridge.clone();
let bridge_subscribtion = bridge2.subscribe().await;
let bridge_subscribtion = bridge2.subscribe(None).await;
bridge_subscribtion
.sender
@@ -51,7 +51,7 @@ async fn run() -> Result<()> {
_ => {}
}
let bridge_subscribtion = bridge.subscribe().await;
let bridge_subscribtion = bridge.subscribe(None).await;
bridge_subscribtion
.sender

View File

@@ -93,12 +93,12 @@ impl Bridge {
.map(|o| o.map_err(Error::from))
}
pub async fn subscribe(self: Arc<Self>) -> BridgeSubscribtion {
pub async fn subscribe(self: Arc<Self>, mint: Option<String>) -> BridgeSubscribtion {
debug!(target: "BRIDGE", "Start new subscription");
let (sender, req) = async_channel::unbounded();
let (rep, receiver) = async_channel::unbounded();
smol::spawn(self.listen_for_new_subscription(req, rep)).detach();
smol::spawn(self.listen_for_new_subscription(req, rep, mint)).detach();
BridgeSubscribtion { sender, receiver }
}
@@ -107,6 +107,7 @@ impl Bridge {
self: Arc<Self>,
req: async_channel::Receiver<BridgeRequests>,
rep: async_channel::Sender<BridgeResponse>,
mint: Option<String>,
) -> Result<()> {
debug!(target: "BRIDGE", "Listen for new subscription");
let req = req.recv().await?;
@@ -122,6 +123,14 @@ impl Bridge {
return Ok(());
}
let mut mint_address: Option<String> = mint.clone();
if mint.is_some() {
if mint.unwrap().is_empty() {
mint_address = None;
}
}
let client: Arc<dyn NetworkClient + Send + Sync>;
// avoid deadlock
{
@@ -133,7 +142,7 @@ impl Bridge {
BridgeRequestsPayload::Watch(val) => match val {
Some((private_key, public_key)) => {
let pub_key = client
.subscribe_with_keypair(private_key, public_key)
.subscribe_with_keypair(private_key, public_key, mint_address)
.await?;
let res = BridgeResponse {
error: BridgeResponseError::NoError,
@@ -142,7 +151,7 @@ impl Bridge {
rep.send(res).await?;
}
None => {
let sub = client.subscribe().await?;
let sub = client.subscribe(mint_address).await?;
let res = BridgeResponse {
error: BridgeResponseError::NoError,
payload: BridgeResponsePayload::Watch(sub.secret_key, sub.public_key),
@@ -166,13 +175,14 @@ impl Bridge {
#[async_trait]
pub trait NetworkClient {
async fn subscribe(self: Arc<Self>) -> Result<TokenSubscribtion>;
async fn subscribe(self: Arc<Self>, mint: Option<String>) -> Result<TokenSubscribtion>;
// should check if the keypair in not already subscribed
async fn subscribe_with_keypair(
self: Arc<Self>,
private_key: Vec<u8>,
public_key: Vec<u8>,
mint: Option<String>,
) -> Result<String>;
async fn get_notifier(self: Arc<Self>) -> Result<async_channel::Receiver<TokenNotification>>;

View File

@@ -149,7 +149,7 @@ impl BtcClient {
#[async_trait]
impl NetworkClient for BtcClient {
async fn subscribe(self: Arc<Self>) -> Result<TokenSubscribtion> {
async fn subscribe(self: Arc<Self>, _mint: Option<String>) -> Result<TokenSubscribtion> {
// Generate bitcoin keys
let btc_keys = BitcoinKeys::new(self.network)?;
let btc_privkey = btc_keys.clone();
@@ -174,6 +174,7 @@ impl NetworkClient for BtcClient {
self: Arc<Self>,
_private_key: Vec<u8>,
_public_key: Vec<u8>,
_mint: Option<String>,
) -> Result<String> {
// TODO this not implemented yet
Ok(String::new())

View File

@@ -223,10 +223,6 @@ impl SolClient {
debug!(target: "SOL BRIDGE", "Sending {} {:?} tokens to main wallet",
amount / u64::pow(10, decimals as u32), mint);
if !account_is_initialized_mint(rpc, mint) {
return Err(SolFailed::MintIsNotValid(mint.to_string()));
}
// The token account from our main wallet
let main_tok_pk = get_associated_token_address(&self.main_keypair.pubkey(), mint);
// The token account from the deposit wallet
@@ -302,27 +298,46 @@ impl SolClient {
) -> SolResult<Signature> {
debug!(target: "SOL BRIDGE", "Sending {} SOL to main wallet", lamports_to_sol(amount));
let ix = system_instruction::transfer(&keypair.pubkey(), &self.main_keypair.pubkey(), amount);
let ix =
system_instruction::transfer(&keypair.pubkey(), &self.main_keypair.pubkey(), amount);
let tx = Transaction::new_with_payer(&[ix], Some(&self.main_keypair.pubkey()));
let signature = sign_and_send_transaction(&rpc, tx, vec![&self.main_keypair, keypair])?;
debug!(target: "SOL BRIDGE", "Sent SOL to main wallet: {}", signature);
Ok(signature)
}
fn check_mint_address(&self, mint_address: Option<String>) -> SolResult<Option<Pubkey>> {
if let Some(mint_addr) = mint_address {
let pubkey = match Pubkey::from_str(&mint_addr) {
Ok(v) => v,
Err(e) => return Err(SolFailed::BadSolAddress(e.to_string())),
};
let rpc = RpcClient::new(self.rpc_server.to_string());
if !account_is_initialized_mint(&rpc, &pubkey) {
return Err(SolFailed::MintIsNotValid(mint_addr.to_string()));
}
return Ok(Some(pubkey));
} else {
return Ok(None);
}
}
}
#[async_trait]
impl NetworkClient for SolClient {
async fn subscribe(self: Arc<Self>) -> Result<TokenSubscribtion> {
async fn subscribe(self: Arc<Self>, mint_address: Option<String>) -> Result<TokenSubscribtion> {
let keypair = Keypair::generate(&mut OsRng);
let public_key = keypair.pubkey().to_string();
let secret_key = serialize(&keypair);
// TODO: Option<Pubkey> for 2nd arg representing Token Mint account
let mint = Pubkey::from_str("F4wkXLN5n1ckejfnJoahGpgW3ffRsrvS9GGVME6ckxS9").unwrap();
smol::spawn(self.handle_subscribe_request(keypair, Some(mint))).detach();
//smol::spawn(self.handle_subscribe_request(keypair, None)).detach();
let mint = self.check_mint_address(mint_address)?;
smol::spawn(self.handle_subscribe_request(keypair, mint)).detach();
Ok(TokenSubscribtion {
secret_key,
@@ -335,15 +350,15 @@ impl NetworkClient for SolClient {
self: Arc<Self>,
private_key: Vec<u8>,
_public_key: Vec<u8>,
mint_address: Option<String>,
) -> Result<String> {
let keypair: Keypair = deserialize(&private_key)?;
let public_key = keypair.pubkey().to_string();
// TODO: Option<Pubkey> for 2nd arg representing Token Mint account
let mint = Pubkey::from_str("F4wkXLN5n1ckejfnJoahGpgW3ffRsrvS9GGVME6ckxS9").unwrap();
smol::spawn(self.handle_subscribe_request(keypair, Some(mint))).detach();
//smol::spawn(self.handle_subscribe_request(keypair, None)).detach();
let mint = self.check_mint_address(mint_address)?;
smol::spawn(self.handle_subscribe_request(keypair, mint)).detach();
Ok(public_key)
}
@@ -355,7 +370,8 @@ impl NetworkClient for SolClient {
async fn send(self: Arc<Self>, address: Vec<u8>, amount: u64) -> Result<()> {
let rpc = RpcClient::new(self.rpc_server.to_string());
let address: Pubkey = deserialize(&address)?;
let instruction = system_instruction::transfer(&self.main_keypair.pubkey(), &address, amount);
let instruction =
system_instruction::transfer(&self.main_keypair.pubkey(), &address, amount);
let mut tx = Transaction::new_with_payer(&[instruction], Some(&self.main_keypair.pubkey()));
let bhq = BlockhashQuery::default();