1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// Copyright (c) 2022-2023 The MobileCoin Foundation

use std::time::Duration;

use futures::executor::block_on;
use log::debug;

use ledger_lib::Device;
use ledger_mob_apdu::key_image::{KeyImageReq, KeyImageResp};

use mc_core::keys::TxOutPublic;
use mc_crypto_ring_signature::KeyImage;
use mc_transaction_signer::traits::KeyImageComputer;

use crate::{tx::TransactionHandle, Error};

/// Sync [KeyImageComputer] implementation for [TransactionHandle]
///
/// Note: this MUST be called from a tokio context
impl<T: Device> KeyImageComputer for TransactionHandle<T> {
    type Error = Error;

    /// Compute key image for a given subaddress and tx_out_public_key
    fn compute_key_image(
        &self,
        subaddress_index: u64,
        tx_out_public_key: &TxOutPublic,
    ) -> Result<KeyImage, Self::Error> {
        tokio::task::block_in_place(|| {
            block_on(async { self.key_image(subaddress_index, tx_out_public_key).await })
        })
    }
}

impl<T: Device> TransactionHandle<T> {
    /// Asynchronously compute key image for a given subaddress and
    /// tx_out_public_key.
    ///
    /// See [KeyImageComputer] for the public blocking API
    pub async fn key_image(
        &self,
        subaddress_index: u64,
        tx_out_public_key: &TxOutPublic,
    ) -> Result<KeyImage, Error> {
        let mut buff = [0u8; 256];

        let mut t = self.t.lock().await;

        debug!(
            "Resolving key image for account: {} subaddress: {} tx_out_public: {}",
            self.info.account_index, subaddress_index, tx_out_public_key
        );
        let req = KeyImageReq::new(
            self.info.account_index,
            subaddress_index,
            tx_out_public_key.clone(),
        );
        let resp = t
            .request::<KeyImageResp>(req, &mut buff, Duration::from_secs(1))
            .await?;

        Ok(resp.key_image)
    }
}