Skip to content

Commit b05ce60

Browse files
committed
Make signing an async operation
- to make an easier integration with Ledger in the future
1 parent 28ec848 commit b05ce60

File tree

17 files changed

+2085
-901
lines changed

17 files changed

+2085
-901
lines changed

Cargo.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

wallet/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ wallet-storage = { path = "./storage" }
2828
wallet-types = { path = "./types" }
2929
trezor-client = { git = "https://github.com/mintlayer/mintlayer-trezor-firmware", branch = "feature/mintlayer-pk", features = ["bitcoin", "mintlayer"], optional = true }
3030

31+
async-trait.workspace = true
3132
bip39 = { workspace = true, default-features = false, features = ["std", "zeroize"] }
33+
futures = { workspace = true, default-features = false }
3234
hex.workspace = true
3335
itertools.workspace = true
3436
parity-scale-codec.workspace = true
@@ -38,6 +40,7 @@ zeroize.workspace = true
3840

3941
[dev-dependencies]
4042
test-utils = { path = "../test-utils" }
43+
tokio = { workspace = true, default-features = false, features = ["io-util", "macros", "net", "rt", "sync"] }
4144

4245
rstest.workspace = true
4346
tempfile.workspace = true

wallet/src/account/mod.rs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ pub struct Account<K> {
120120
account_info: AccountInfo,
121121
}
122122

123-
impl<K: AccountKeyChains> Account<K> {
123+
impl<K: AccountKeyChains + Sync> Account<K> {
124124
/// Create a new account by providing a key chain
125125
pub fn new(
126126
chain_config: Arc<ChainConfig>,
@@ -654,7 +654,7 @@ impl<K: AccountKeyChains> Account<K> {
654654

655655
pub fn process_send_request_and_sign(
656656
&mut self,
657-
db_tx: &mut impl WalletStorageWriteUnlocked,
657+
db_tx: &mut impl WalletStorageWriteLocked,
658658
request: SendRequest,
659659
inputs: SelectedInputs,
660660
change_addresses: BTreeMap<Currency, Address<Destination>>,
@@ -676,7 +676,7 @@ impl<K: AccountKeyChains> Account<K> {
676676

677677
fn decommission_stake_pool_impl(
678678
&mut self,
679-
db_tx: &mut impl WalletStorageWriteUnlocked,
679+
db_tx: &mut impl WalletStorageWriteLocked,
680680
pool_id: PoolId,
681681
pool_balance: Amount,
682682
output_address: Option<Destination>,
@@ -739,7 +739,7 @@ impl<K: AccountKeyChains> Account<K> {
739739

740740
pub fn decommission_stake_pool(
741741
&mut self,
742-
db_tx: &mut impl WalletStorageWriteUnlocked,
742+
db_tx: &mut impl WalletStorageWriteLocked,
743743
pool_id: PoolId,
744744
pool_balance: Amount,
745745
output_address: Option<Destination>,
@@ -756,7 +756,7 @@ impl<K: AccountKeyChains> Account<K> {
756756

757757
pub fn decommission_stake_pool_request(
758758
&mut self,
759-
db_tx: &mut impl WalletStorageWriteUnlocked,
759+
db_tx: &mut impl WalletStorageWriteLocked,
760760
pool_id: PoolId,
761761
pool_balance: Amount,
762762
output_address: Option<Destination>,
@@ -900,7 +900,7 @@ impl<K: AccountKeyChains> Account<K> {
900900

901901
pub fn create_htlc_tx(
902902
&mut self,
903-
db_tx: &mut impl WalletStorageWriteUnlocked,
903+
db_tx: &mut impl WalletStorageWriteLocked,
904904
output_value: OutputValue,
905905
htlc: HashedTimelockContract,
906906
median_time: BlockTimestamp,
@@ -923,7 +923,7 @@ impl<K: AccountKeyChains> Account<K> {
923923

924924
pub fn create_order_tx(
925925
&mut self,
926-
db_tx: &mut impl WalletStorageWriteUnlocked,
926+
db_tx: &mut impl WalletStorageWriteLocked,
927927
ask_value: OutputValue,
928928
give_value: OutputValue,
929929
conclude_address: Address<Destination>,
@@ -949,7 +949,7 @@ impl<K: AccountKeyChains> Account<K> {
949949

950950
pub fn create_conclude_order_tx(
951951
&mut self,
952-
db_tx: &mut impl WalletStorageWriteUnlocked,
952+
db_tx: &mut impl WalletStorageWriteLocked,
953953
order_id: OrderId,
954954
order_info: RpcOrderInfo,
955955
output_address: Option<Destination>,
@@ -1002,7 +1002,7 @@ impl<K: AccountKeyChains> Account<K> {
10021002
#[allow(clippy::too_many_arguments)]
10031003
pub fn create_fill_order_tx(
10041004
&mut self,
1005-
db_tx: &mut impl WalletStorageWriteUnlocked,
1005+
db_tx: &mut impl WalletStorageWriteLocked,
10061006
order_id: OrderId,
10071007
order_info: RpcOrderInfo,
10081008
fill_amount_in_ask_currency: Amount,
@@ -1058,7 +1058,7 @@ impl<K: AccountKeyChains> Account<K> {
10581058

10591059
pub fn create_issue_nft_tx(
10601060
&mut self,
1061-
db_tx: &mut impl WalletStorageWriteUnlocked,
1061+
db_tx: &mut impl WalletStorageWriteLocked,
10621062
nft_issue_arguments: IssueNftArguments,
10631063
median_time: BlockTimestamp,
10641064
fee_rate: CurrentFeeRate,
@@ -1119,7 +1119,7 @@ impl<K: AccountKeyChains> Account<K> {
11191119

11201120
pub fn mint_tokens(
11211121
&mut self,
1122-
db_tx: &mut impl WalletStorageWriteUnlocked,
1122+
db_tx: &mut impl WalletStorageWriteLocked,
11231123
token_info: &UnconfirmedTokenInfo,
11241124
address: Address<Destination>,
11251125
amount: Amount,
@@ -1147,7 +1147,7 @@ impl<K: AccountKeyChains> Account<K> {
11471147

11481148
pub fn unmint_tokens(
11491149
&mut self,
1150-
db_tx: &mut impl WalletStorageWriteUnlocked,
1150+
db_tx: &mut impl WalletStorageWriteLocked,
11511151
token_info: &UnconfirmedTokenInfo,
11521152
amount: Amount,
11531153
median_time: BlockTimestamp,
@@ -1174,7 +1174,7 @@ impl<K: AccountKeyChains> Account<K> {
11741174

11751175
pub fn lock_token_supply(
11761176
&mut self,
1177-
db_tx: &mut impl WalletStorageWriteUnlocked,
1177+
db_tx: &mut impl WalletStorageWriteLocked,
11781178
token_info: &UnconfirmedTokenInfo,
11791179
median_time: BlockTimestamp,
11801180
fee_rate: CurrentFeeRate,
@@ -1198,7 +1198,7 @@ impl<K: AccountKeyChains> Account<K> {
11981198

11991199
pub fn freeze_token(
12001200
&mut self,
1201-
db_tx: &mut impl WalletStorageWriteUnlocked,
1201+
db_tx: &mut impl WalletStorageWriteLocked,
12021202
token_info: &UnconfirmedTokenInfo,
12031203
is_token_unfreezable: IsTokenUnfreezable,
12041204
median_time: BlockTimestamp,
@@ -1225,7 +1225,7 @@ impl<K: AccountKeyChains> Account<K> {
12251225

12261226
pub fn unfreeze_token(
12271227
&mut self,
1228-
db_tx: &mut impl WalletStorageWriteUnlocked,
1228+
db_tx: &mut impl WalletStorageWriteLocked,
12291229
token_info: &UnconfirmedTokenInfo,
12301230
median_time: BlockTimestamp,
12311231
fee_rate: CurrentFeeRate,
@@ -1249,7 +1249,7 @@ impl<K: AccountKeyChains> Account<K> {
12491249

12501250
pub fn change_token_authority(
12511251
&mut self,
1252-
db_tx: &mut impl WalletStorageWriteUnlocked,
1252+
db_tx: &mut impl WalletStorageWriteLocked,
12531253
token_info: &UnconfirmedTokenInfo,
12541254
address: Address<Destination>,
12551255
median_time: BlockTimestamp,
@@ -1276,7 +1276,7 @@ impl<K: AccountKeyChains> Account<K> {
12761276

12771277
pub fn change_token_metadata_uri(
12781278
&mut self,
1279-
db_tx: &mut impl WalletStorageWriteUnlocked,
1279+
db_tx: &mut impl WalletStorageWriteLocked,
12801280
token_info: &UnconfirmedTokenInfo,
12811281
metadata_uri: Vec<u8>,
12821282
median_time: BlockTimestamp,
@@ -1304,7 +1304,7 @@ impl<K: AccountKeyChains> Account<K> {
13041304
authority: Destination,
13051305
tx_input: TxInput,
13061306
outputs: Vec<TxOutput>,
1307-
db_tx: &mut impl WalletStorageWriteUnlocked,
1307+
db_tx: &mut impl WalletStorageWriteLocked,
13081308
median_time: BlockTimestamp,
13091309
fee_rate: CurrentFeeRate,
13101310
) -> Result<SendRequest, WalletError> {
@@ -2128,7 +2128,7 @@ struct PreselectedInputAmounts {
21282128
pub burn: Amount,
21292129
}
21302130

2131-
impl<K: AccountKeyChains + VRFAccountKeyChains> Account<K> {
2131+
impl<K: AccountKeyChains + VRFAccountKeyChains + Sync> Account<K> {
21322132
fn get_vrf_public_key(
21332133
&mut self,
21342134
db_tx: &mut impl WalletStorageWriteLocked,
@@ -2199,7 +2199,7 @@ impl<K: AccountKeyChains + VRFAccountKeyChains> Account<K> {
21992199

22002200
pub fn create_stake_pool_tx(
22012201
&mut self,
2202-
db_tx: &mut impl WalletStorageWriteUnlocked,
2202+
db_tx: &mut impl WalletStorageWriteLocked,
22032203
stake_pool_arguments: StakePoolDataArguments,
22042204
median_time: BlockTimestamp,
22052205
fee_rate: CurrentFeeRate,

wallet/src/signer/mod.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
use std::sync::Arc;
1717

18+
use async_trait::async_trait;
1819
use common::chain::{
1920
signature::{
2021
inputsig::{
@@ -86,32 +87,33 @@ type SignerResult<T> = Result<T, SignerError>;
8687

8788
/// Signer trait responsible for signing transactions or challenges using a software or hardware
8889
/// wallet
90+
#[async_trait]
8991
pub trait Signer {
9092
/// sign a partially signed transaction and return the before and after signature statuses
91-
fn sign_tx(
93+
async fn sign_tx(
9294
&mut self,
9395
tx: PartiallySignedTransaction,
94-
key_chain: &impl AccountKeyChains,
95-
db_tx: &impl WalletStorageReadUnlocked,
96+
key_chain: &(impl AccountKeyChains + Sync),
97+
db_tx: &(impl WalletStorageReadUnlocked + Sync),
9698
) -> SignerResult<(
9799
PartiallySignedTransaction,
98100
Vec<SignatureStatus>,
99101
Vec<SignatureStatus>,
100102
)>;
101103

102104
/// sign an arbitrary message for a destination known to this key chain
103-
fn sign_challenge(
105+
async fn sign_challenge(
104106
&mut self,
105107
message: Vec<u8>,
106108
destination: Destination,
107-
key_chain: &impl AccountKeyChains,
108-
db_tx: &impl WalletStorageReadUnlocked,
109+
key_chain: &(impl AccountKeyChains + Sync),
110+
db_tx: &(impl WalletStorageReadUnlocked + Sync),
109111
) -> SignerResult<ArbitraryMessageSignature>;
110112
}
111113

112114
pub trait SignerProvider {
113115
type S: Signer;
114-
type K: AccountKeyChains;
116+
type K: AccountKeyChains + Sync;
115117

116118
fn provide(&mut self, chain_config: Arc<ChainConfig>, account_index: U31) -> Self::S;
117119

wallet/src/signer/software_signer/mod.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
use std::sync::Arc;
1717

18+
use async_trait::async_trait;
1819
use common::chain::{
1920
htlc::HtlcSecret,
2021
signature::{
@@ -253,12 +254,13 @@ impl SoftwareSigner {
253254
}
254255
}
255256

257+
#[async_trait]
256258
impl Signer for SoftwareSigner {
257-
fn sign_tx(
259+
async fn sign_tx(
258260
&mut self,
259261
ptx: PartiallySignedTransaction,
260-
key_chain: &impl AccountKeyChains,
261-
db_tx: &impl WalletStorageReadUnlocked,
262+
key_chain: &(impl AccountKeyChains + Sync),
263+
db_tx: &(impl WalletStorageReadUnlocked + Sync),
262264
) -> SignerResult<(
263265
PartiallySignedTransaction,
264266
Vec<SignatureStatus>,
@@ -359,12 +361,12 @@ impl Signer for SoftwareSigner {
359361
Ok((ptx.with_witnesses(witnesses), prev_statuses, new_statuses))
360362
}
361363

362-
fn sign_challenge(
364+
async fn sign_challenge(
363365
&mut self,
364366
message: Vec<u8>,
365367
destination: Destination,
366-
key_chain: &impl AccountKeyChains,
367-
db_tx: &impl WalletStorageReadUnlocked,
368+
key_chain: &(impl AccountKeyChains + Sync),
369+
db_tx: &(impl WalletStorageReadUnlocked + Sync),
368370
) -> SignerResult<ArbitraryMessageSignature> {
369371
let private_key = self
370372
.get_private_key_for_destination(&destination, key_chain, db_tx)?

wallet/src/signer/software_signer/tests.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,10 @@ const MNEMONIC: &str =
5151
#[rstest]
5252
#[trace]
5353
#[case(Seed::from_entropy())]
54-
fn sign_message(#[case] seed: Seed) {
54+
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
55+
async fn sign_message(#[case] seed: Seed) {
56+
use wallet_storage::TransactionRwUnlocked;
57+
5558
let mut rng = make_seedable_rng(seed);
5659

5760
let config = Arc::new(create_regtest());
@@ -75,13 +78,16 @@ fn sign_message(#[case] seed: Seed) {
7578
let destination = account.get_new_address(&mut db_tx, ReceiveFunds).unwrap().1.into_object();
7679
let mut signer = SoftwareSigner::new(config.clone(), DEFAULT_ACCOUNT_INDEX);
7780
let message = vec![rng.gen::<u8>(), rng.gen::<u8>(), rng.gen::<u8>()];
81+
db_tx.commit().unwrap();
82+
let db_tx = db.local_rw_unlocked().read_only_store();
7883
let res = signer
7984
.sign_challenge(
8085
message.clone(),
8186
destination.clone(),
8287
account.key_chain(),
8388
&db_tx,
8489
)
90+
.await
8591
.unwrap();
8692

8793
let message_challenge = produce_message_challenge(&message);
@@ -91,7 +97,8 @@ fn sign_message(#[case] seed: Seed) {
9197
#[rstest]
9298
#[trace]
9399
#[case(Seed::from_entropy())]
94-
fn sign_transaction(#[case] seed: Seed) {
100+
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
101+
async fn sign_transaction(#[case] seed: Seed) {
95102
use std::num::NonZeroU8;
96103

97104
use common::{
@@ -110,6 +117,7 @@ fn sign_transaction(#[case] seed: Seed) {
110117
};
111118
use crypto::vrf::VRFPrivateKey;
112119
use serialization::extras::non_empty_vec::DataOrNoVec;
120+
use wallet_storage::TransactionRwUnlocked;
113121

114122
let mut rng = make_seedable_rng(seed);
115123

@@ -376,8 +384,10 @@ fn sign_transaction(#[case] seed: Seed) {
376384
let additional_info = BTreeMap::new();
377385
let ptx = req.into_partially_signed_tx(&additional_info).unwrap();
378386

387+
db_tx.commit().unwrap();
388+
let db_tx = db.local_rw_unlocked().read_only_store();
379389
let mut signer = SoftwareSigner::new(chain_config.clone(), DEFAULT_ACCOUNT_INDEX);
380-
let (ptx, _, _) = signer.sign_tx(ptx, account.key_chain(), &db_tx).unwrap();
390+
let (ptx, _, _) = signer.sign_tx(ptx, account.key_chain(), &db_tx).await.unwrap();
381391

382392
eprintln!("num inputs in tx: {} {:?}", inputs.len(), ptx.witnesses());
383393
assert!(ptx.all_signatures_available());

0 commit comments

Comments
 (0)