@@ -12,6 +12,7 @@ use futures::{stream, StreamExt};
12
12
use nym_api_requests:: legacy:: { LegacyGatewayBondWithId , LegacyMixNodeDetailsWithLayer } ;
13
13
use nym_api_requests:: models:: { DescribedNodeType , NymNodeData , NymNodeDescription } ;
14
14
use nym_config:: defaults:: DEFAULT_NYM_NODE_HTTP_PORT ;
15
+ use nym_crypto:: asymmetric:: ed25519;
15
16
use nym_mixnet_contract_common:: { LegacyMixLayer , NodeId , NymNodeDetails } ;
16
17
use nym_node_requests:: api:: client:: { NymNodeApiClientError , NymNodeApiClientExt } ;
17
18
use nym_topology:: gateway:: GatewayConversionError ;
@@ -58,6 +59,13 @@ pub enum NodeDescribeCacheError {
58
59
#[ error( "could not verify signed host information for node {node_id}" ) ]
59
60
MissignedHostInformation { node_id : NodeId } ,
60
61
62
+ #[ error( "identity of node {node_id} does not match. expected {expected} but got {got}" ) ]
63
+ MismatchedIdentity {
64
+ node_id : NodeId ,
65
+ expected : String ,
66
+ got : String ,
67
+ } ,
68
+
61
69
#[ error( "node {node_id} is announcing an illegal ip address" ) ]
62
70
IllegalIpAddress { node_id : NodeId } ,
63
71
}
@@ -289,6 +297,15 @@ async fn try_get_description(
289
297
290
298
let host_info = client. get_host_information ( ) . await . map_err ( map_query_err) ?;
291
299
300
+ // check if the identity key matches the information provided during bonding
301
+ if data. expected_identity != host_info. keys . ed25519_identity {
302
+ return Err ( NodeDescribeCacheError :: MismatchedIdentity {
303
+ node_id : data. node_id ,
304
+ expected : data. expected_identity . to_base58_string ( ) ,
305
+ got : host_info. keys . ed25519_identity . to_base58_string ( ) ,
306
+ } ) ;
307
+ }
308
+
292
309
if !host_info. verify_host_information ( ) {
293
310
return Err ( NodeDescribeCacheError :: MissignedHostInformation {
294
311
node_id : data. node_id ,
@@ -315,54 +332,66 @@ async fn try_get_description(
315
332
pub ( crate ) struct RefreshData {
316
333
host : String ,
317
334
node_id : NodeId ,
335
+ expected_identity : ed25519:: PublicKey ,
318
336
node_type : DescribedNodeType ,
319
337
320
338
port : Option < u16 > ,
321
339
}
322
340
323
- impl < ' a > From < & ' a LegacyMixNodeDetailsWithLayer > for RefreshData {
324
- fn from ( node : & ' a LegacyMixNodeDetailsWithLayer ) -> Self {
325
- RefreshData :: new (
341
+ impl < ' a > TryFrom < & ' a LegacyMixNodeDetailsWithLayer > for RefreshData {
342
+ type Error = ed25519:: Ed25519RecoveryError ;
343
+
344
+ fn try_from ( node : & ' a LegacyMixNodeDetailsWithLayer ) -> Result < Self , Self :: Error > {
345
+ Ok ( RefreshData :: new (
326
346
& node. bond_information . mix_node . host ,
347
+ node. bond_information . identity ( ) . parse ( ) ?,
327
348
DescribedNodeType :: LegacyMixnode ,
328
349
node. mix_id ( ) ,
329
350
Some ( node. bond_information . mix_node . http_api_port ) ,
330
- )
351
+ ) )
331
352
}
332
353
}
333
354
334
- impl < ' a > From < & ' a LegacyGatewayBondWithId > for RefreshData {
335
- fn from ( node : & ' a LegacyGatewayBondWithId ) -> Self {
336
- RefreshData :: new (
355
+ impl < ' a > TryFrom < & ' a LegacyGatewayBondWithId > for RefreshData {
356
+ type Error = ed25519:: Ed25519RecoveryError ;
357
+
358
+ fn try_from ( node : & ' a LegacyGatewayBondWithId ) -> Result < Self , Self :: Error > {
359
+ Ok ( RefreshData :: new (
337
360
& node. bond . gateway . host ,
361
+ node. bond . identity ( ) . parse ( ) ?,
338
362
DescribedNodeType :: LegacyGateway ,
339
363
node. node_id ,
340
364
None ,
341
- )
365
+ ) )
342
366
}
343
367
}
344
368
345
- impl < ' a > From < & ' a NymNodeDetails > for RefreshData {
346
- fn from ( node : & ' a NymNodeDetails ) -> Self {
347
- RefreshData :: new (
369
+ impl < ' a > TryFrom < & ' a NymNodeDetails > for RefreshData {
370
+ type Error = ed25519:: Ed25519RecoveryError ;
371
+
372
+ fn try_from ( node : & ' a NymNodeDetails ) -> Result < Self , Self :: Error > {
373
+ Ok ( RefreshData :: new (
348
374
& node. bond_information . node . host ,
375
+ node. bond_information . identity ( ) . parse ( ) ?,
349
376
DescribedNodeType :: NymNode ,
350
377
node. node_id ( ) ,
351
378
node. bond_information . node . custom_http_port ,
352
- )
379
+ ) )
353
380
}
354
381
}
355
382
356
383
impl RefreshData {
357
384
pub fn new (
358
385
host : impl Into < String > ,
386
+ expected_identity : ed25519:: PublicKey ,
359
387
node_type : DescribedNodeType ,
360
388
node_id : NodeId ,
361
389
port : Option < u16 > ,
362
390
) -> Self {
363
391
RefreshData {
364
392
host : host. into ( ) ,
365
393
node_id,
394
+ expected_identity,
366
395
node_type,
367
396
port,
368
397
}
@@ -404,7 +433,9 @@ impl CacheItemProvider for NodeDescriptionProvider {
404
433
None => error ! ( "failed to obtain mixnodes information from the cache" ) ,
405
434
Some ( legacy_mixnodes) => {
406
435
for node in & * * legacy_mixnodes {
407
- nodes_to_query. push ( node. into ( ) )
436
+ if let Ok ( data) = node. try_into ( ) {
437
+ nodes_to_query. push ( data) ;
438
+ }
408
439
}
409
440
}
410
441
}
@@ -413,7 +444,9 @@ impl CacheItemProvider for NodeDescriptionProvider {
413
444
None => error ! ( "failed to obtain gateways information from the cache" ) ,
414
445
Some ( legacy_gateways) => {
415
446
for node in & * * legacy_gateways {
416
- nodes_to_query. push ( node. into ( ) )
447
+ if let Ok ( data) = node. try_into ( ) {
448
+ nodes_to_query. push ( data) ;
449
+ }
417
450
}
418
451
}
419
452
}
@@ -422,7 +455,9 @@ impl CacheItemProvider for NodeDescriptionProvider {
422
455
None => error ! ( "failed to obtain nym-nodes information from the cache" ) ,
423
456
Some ( nym_nodes) => {
424
457
for node in & * * nym_nodes {
425
- nodes_to_query. push ( node. into ( ) )
458
+ if let Ok ( data) = node. try_into ( ) {
459
+ nodes_to_query. push ( data) ;
460
+ }
426
461
}
427
462
}
428
463
}
0 commit comments