@@ -59,23 +59,29 @@ use randomness::make_true_rng;
59
59
use serialization:: Encode ;
60
60
use tokio:: sync:: Mutex ;
61
61
use utils:: ensure;
62
- use wallet_storage:: { WalletStorageReadLocked , WalletStorageReadUnlocked } ;
62
+ use wallet_storage:: {
63
+ StoreLocalReadWriteUnlocked , WalletStorageReadLocked , WalletStorageReadUnlocked ,
64
+ } ;
63
65
use wallet_types:: {
64
- hw_data:: LedgerData , partially_signed_transaction:: PartiallySignedTransaction ,
66
+ account_info:: DEFAULT_ACCOUNT_INDEX ,
67
+ hw_data:: { HardwareWalletData , LedgerData } ,
68
+ partially_signed_transaction:: PartiallySignedTransaction ,
65
69
signature_status:: SignatureStatus ,
70
+ AccountId ,
66
71
} ;
67
72
68
73
use crate :: {
69
- key_chain:: { make_account_path, AccountKeyChains , FoundPubKey } ,
74
+ key_chain:: { make_account_path, AccountKeyChainImplHardware , AccountKeyChains , FoundPubKey } ,
70
75
signer:: {
71
76
ledger_signer:: ledger_messages:: {
72
77
check_current_app, get_app_name, get_extended_public_key, sign_challenge, sign_tx,
73
78
LedgerBip32Path , LedgerInputAddressPath , LedgerSignature , LedgerTxInput ,
74
79
LedgerTxInputCommitment , LedgerTxOutput ,
75
80
} ,
76
81
signer_utils:: { is_htlc_utxo, sign_input_with_standalone_key} ,
77
- Signer , SignerError , SignerResult ,
82
+ Signer , SignerError , SignerProvider , SignerResult ,
78
83
} ,
84
+ Account , WalletResult ,
79
85
} ;
80
86
81
87
/// Signer errors
@@ -122,7 +128,8 @@ pub trait LProvider {
122
128
123
129
async fn find_ledger_device_from_db (
124
130
& self ,
125
- db_tx : & impl WalletStorageReadLocked ,
131
+ db_tx : & ( impl WalletStorageReadLocked + Sync ) ,
132
+ chain_config : Arc < ChainConfig > ,
126
133
) -> SignerResult < ( Self :: L , LedgerData ) > ;
127
134
}
128
135
@@ -167,7 +174,7 @@ where
167
174
/// the function will attempt to reconnect to the Ledger device once before returning an error.
168
175
async fn check_session (
169
176
& mut self ,
170
- db_tx : & impl WalletStorageReadLocked ,
177
+ db_tx : & ( impl WalletStorageReadLocked + Sync ) ,
171
178
key_chain : & impl AccountKeyChains ,
172
179
) -> SignerResult < ( ) > {
173
180
let mut client = self . client . lock ( ) . await ;
@@ -184,13 +191,14 @@ where
184
191
| ledger_lib:: Error :: Tcp ( _)
185
192
| ledger_lib:: Error :: Ble ( _) ,
186
193
) => {
187
- let ( mut new_client, data) =
188
- self . provider . find_ledger_device_from_db ( db_tx) . await ?;
194
+ let ( mut new_client, _data) = self
195
+ . provider
196
+ . find_ledger_device_from_db ( db_tx, self . chain_config . clone ( ) )
197
+ . await ?;
189
198
190
199
check_public_keys_against_key_chain (
191
200
db_tx,
192
201
& mut new_client,
193
- & data,
194
202
key_chain,
195
203
& self . chain_config ,
196
204
)
@@ -215,7 +223,7 @@ where
215
223
async fn perform_ledger_operation < F , R > (
216
224
& mut self ,
217
225
operation : F ,
218
- db_tx : & impl WalletStorageReadLocked ,
226
+ db_tx : & ( impl WalletStorageReadLocked + Sync ) ,
219
227
key_chain : & impl AccountKeyChains ,
220
228
) -> SignerResult < R >
221
229
where
@@ -1007,7 +1015,6 @@ fn to_ledger_chain_type(chain_config: &ChainConfig) -> u8 {
1007
1015
}
1008
1016
}
1009
1017
1010
- #[ allow( dead_code) ]
1011
1018
async fn find_ledger_device ( ) -> SignerResult < ( LedgerHandle , LedgerData ) > {
1012
1019
let mut provider = LedgerProvider :: init ( ) . await ;
1013
1020
let mut devices = provider
@@ -1030,9 +1037,8 @@ async fn find_ledger_device() -> SignerResult<(LedgerHandle, LedgerData)> {
1030
1037
/// Check that the public keys in the provided key chain are the same as the ones from the
1031
1038
/// connected hardware wallet
1032
1039
async fn check_public_keys_against_key_chain < L : Exchange > (
1033
- db_tx : & impl WalletStorageReadLocked ,
1040
+ db_tx : & ( impl WalletStorageReadLocked + Sync ) ,
1034
1041
client : & mut L ,
1035
- _ledger_data : & LedgerData ,
1036
1042
key_chain : & impl AccountKeyChains ,
1037
1043
chain_config : & ChainConfig ,
1038
1044
) -> SignerResult < ( ) > {
@@ -1050,6 +1056,31 @@ async fn check_public_keys_against_key_chain<L: Exchange>(
1050
1056
Err ( LedgerError :: HardwareWalletDifferentFile ) ?
1051
1057
}
1052
1058
1059
+ /// Check that the public keys in the DB are the same as the ones from the connected hardware
1060
+ /// wallet
1061
+ async fn check_public_keys_against_db (
1062
+ db_tx : & ( impl WalletStorageReadLocked + Sync ) ,
1063
+ client : & mut LedgerHandle ,
1064
+ chain_config : Arc < ChainConfig > ,
1065
+ ) -> SignerResult < ( ) > {
1066
+ let ( id, first_acc) = db_tx
1067
+ . get_accounts_info ( ) ?
1068
+ . iter ( )
1069
+ . find_map ( |( id, info) | {
1070
+ ( info. account_index ( ) == DEFAULT_ACCOUNT_INDEX ) . then_some ( ( id. clone ( ) , info. clone ( ) ) )
1071
+ } )
1072
+ . ok_or ( SignerError :: WalletNotInitialized ) ?;
1073
+
1074
+ let loaded_acc = AccountKeyChainImplHardware :: load_from_database (
1075
+ chain_config. clone ( ) ,
1076
+ db_tx,
1077
+ & id,
1078
+ & first_acc,
1079
+ ) ?;
1080
+
1081
+ check_public_keys_against_key_chain ( db_tx, client, & loaded_acc, & chain_config) . await
1082
+ }
1083
+
1053
1084
async fn fetch_extended_pub_key < L : Exchange > (
1054
1085
client : & mut L ,
1055
1086
chain_config : & ChainConfig ,
@@ -1079,6 +1110,119 @@ fn single_signature(
1079
1110
}
1080
1111
}
1081
1112
1113
+ #[ derive( Clone ) ]
1114
+ pub struct LedgerSignerProvider {
1115
+ client : Arc < Mutex < LedgerHandle > > ,
1116
+ data : LedgerData ,
1117
+ }
1118
+
1119
+ impl std:: fmt:: Debug for LedgerSignerProvider {
1120
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
1121
+ f. write_str ( "LedgerSignerProvider" )
1122
+ }
1123
+ }
1124
+
1125
+ #[ async_trait]
1126
+ impl LProvider for LedgerSignerProvider {
1127
+ type L = LedgerHandle ;
1128
+
1129
+ async fn find_ledger_device_from_db (
1130
+ & self ,
1131
+ db_tx : & ( impl WalletStorageReadLocked + Sync ) ,
1132
+ chain_config : Arc < ChainConfig > ,
1133
+ ) -> SignerResult < ( Self :: L , LedgerData ) > {
1134
+ let ( mut client, data) = find_ledger_device ( ) . await ?;
1135
+
1136
+ check_public_keys_against_db ( db_tx, & mut client, chain_config) . await ?;
1137
+
1138
+ Ok ( ( client, data) )
1139
+ }
1140
+ }
1141
+
1142
+ impl LedgerSignerProvider {
1143
+ pub async fn new ( ) -> SignerResult < Self > {
1144
+ let ( client, data) = find_ledger_device ( ) . await ?;
1145
+
1146
+ Ok ( Self {
1147
+ client : Arc :: new ( Mutex :: new ( client) ) ,
1148
+ data,
1149
+ } )
1150
+ }
1151
+
1152
+ pub async fn load_from_database (
1153
+ chain_config : Arc < ChainConfig > ,
1154
+ db_tx : & ( impl WalletStorageReadLocked + Sync ) ,
1155
+ _device_id : Option < String > ,
1156
+ ) -> WalletResult < Self > {
1157
+ //let (client, data) = find_trezor_device_from_db(db_tx, device_id)?;
1158
+ let ( mut client, data) = find_ledger_device ( ) . await ?;
1159
+
1160
+ check_public_keys_against_db ( db_tx, & mut client, chain_config) . await ?;
1161
+
1162
+ let provider = Self {
1163
+ client : Arc :: new ( Mutex :: new ( client) ) ,
1164
+ data,
1165
+ } ;
1166
+
1167
+ Ok ( provider)
1168
+ }
1169
+
1170
+ async fn fetch_extended_pub_key (
1171
+ & self ,
1172
+ chain_config : & Arc < ChainConfig > ,
1173
+ account_index : U31 ,
1174
+ ) -> SignerResult < ExtendedPublicKey > {
1175
+ fetch_extended_pub_key ( & mut * self . client . lock ( ) . await , chain_config, account_index)
1176
+ . await
1177
+ . map_err ( SignerError :: LedgerError )
1178
+ }
1179
+ }
1180
+
1181
+ #[ async_trait]
1182
+ impl SignerProvider for LedgerSignerProvider {
1183
+ type S = LedgerSigner < LedgerHandle , LedgerSignerProvider > ;
1184
+ type K = AccountKeyChainImplHardware ;
1185
+
1186
+ fn provide ( & mut self , chain_config : Arc < ChainConfig > , _account_index : U31 ) -> Self :: S {
1187
+ LedgerSigner :: new ( chain_config, self . client . clone ( ) , self . clone ( ) )
1188
+ }
1189
+
1190
+ async fn make_new_account < B : storage:: Backend > (
1191
+ & mut self ,
1192
+ chain_config : Arc < ChainConfig > ,
1193
+ account_index : U31 ,
1194
+ name : Option < String > ,
1195
+ db_tx : & mut StoreLocalReadWriteUnlocked < B > ,
1196
+ ) -> WalletResult < Account < Self :: K > > {
1197
+ let account_pubkey = self . fetch_extended_pub_key ( & chain_config, account_index) . await ?;
1198
+
1199
+ let lookahead_size = db_tx. get_lookahead_size ( ) ?;
1200
+
1201
+ let key_chain = AccountKeyChainImplHardware :: new_from_hardware_key (
1202
+ chain_config. clone ( ) ,
1203
+ db_tx,
1204
+ account_pubkey,
1205
+ account_index,
1206
+ lookahead_size,
1207
+ ) ?;
1208
+
1209
+ Account :: new ( chain_config, db_tx, key_chain, name)
1210
+ }
1211
+
1212
+ fn load_account_from_database (
1213
+ & self ,
1214
+ chain_config : Arc < ChainConfig > ,
1215
+ db_tx : & impl WalletStorageReadLocked ,
1216
+ id : & AccountId ,
1217
+ ) -> WalletResult < Account < Self :: K > > {
1218
+ Account :: load_from_database ( chain_config, db_tx, id)
1219
+ }
1220
+
1221
+ fn get_hardware_wallet_data ( & self ) -> Option < HardwareWalletData > {
1222
+ Some ( HardwareWalletData :: Ledger ( self . data . clone ( ) ) )
1223
+ }
1224
+ }
1225
+
1082
1226
#[ cfg( feature = "enable-ledger-device-tests" ) ]
1083
1227
#[ cfg( test) ]
1084
1228
mod tests;
0 commit comments