@@ -530,39 +530,80 @@ impl TryFrom<HrnTomlConfig> for HumanReadableNamesConfig {
530530 type Error = io:: Error ;
531531
532532 fn try_from ( value : HrnTomlConfig ) -> Result < Self , Self :: Error > {
533- let mut config = HumanReadableNamesConfig :: default ( ) ;
534-
535- match value. mode . as_deref ( ) {
536- None | Some ( "dns" ) => { } ,
533+ let HrnTomlConfig { mode, dns_server_address, enable_resolution_service } = value;
534+
535+ let resolution_config = match mode. as_deref ( ) {
536+ None | Some ( "dns" ) => {
537+ // Start from LDK Node's DNS defaults so we don't have to hardcode them, but fall
538+ // back to explicit values if the upstream default ever stops being `Dns`.
539+ let ( mut dns_server_address_val, mut enable_hrn_resolution_service) =
540+ if let HRNResolverConfig :: Dns {
541+ dns_server_address,
542+ enable_hrn_resolution_service,
543+ } = HumanReadableNamesConfig :: default ( ) . resolution_config
544+ {
545+ ( dns_server_address, enable_hrn_resolution_service)
546+ } else {
547+ (
548+ SocketAddress :: from_str ( "8.8.8.8:53" )
549+ . expect ( "`8.8.8.8:53` is a valid socket address" ) ,
550+ false ,
551+ )
552+ } ;
553+
554+ if let Some ( addr) = dns_server_address. as_deref ( ) {
555+ dns_server_address_val = parse_dns_server_address ( addr) ?;
556+ }
557+ if let Some ( enable) = enable_resolution_service {
558+ enable_hrn_resolution_service = enable;
559+ }
560+
561+ HRNResolverConfig :: Dns {
562+ dns_server_address : dns_server_address_val,
563+ enable_hrn_resolution_service,
564+ }
565+ } ,
537566 Some ( "blip32" ) => {
538- config. resolution_config = HRNResolverConfig :: Blip32 ;
567+ if dns_server_address. is_some ( ) {
568+ return Err ( io:: Error :: new (
569+ io:: ErrorKind :: InvalidInput ,
570+ "`hrn.dns_server_address` only applies when `hrn.mode = \" dns\" `"
571+ . to_string ( ) ,
572+ ) ) ;
573+ }
574+ if enable_resolution_service. is_some ( ) {
575+ return Err ( io:: Error :: new (
576+ io:: ErrorKind :: InvalidInput ,
577+ "`hrn.enable_resolution_service` only applies when `hrn.mode = \" dns\" `"
578+ . to_string ( ) ,
579+ ) ) ;
580+ }
581+ HRNResolverConfig :: Blip32
539582 } ,
540583 Some ( other) => {
541584 return Err ( io:: Error :: new (
542585 io:: ErrorKind :: InvalidInput ,
543586 format ! ( "Invalid HRN mode '{}' configured; expected 'dns' or 'blip32'" , other) ,
544587 ) )
545588 } ,
546- }
589+ } ;
547590
548- if let HRNResolverConfig :: Dns { dns_server_address, enable_hrn_resolution_service } =
549- & mut config. resolution_config
550- {
551- if let Some ( addr) = value. dns_server_address . as_deref ( ) {
552- * dns_server_address = SocketAddress :: from_str ( addr) . map_err ( |e| {
553- io:: Error :: new (
554- io:: ErrorKind :: InvalidInput ,
555- format ! ( "Invalid HRN DNS server address configured: {}" , e) ,
556- )
557- } ) ?;
558- }
559- if let Some ( enable) = value. enable_resolution_service {
560- * enable_hrn_resolution_service = enable;
561- }
562- }
591+ Ok ( HumanReadableNamesConfig { resolution_config } )
592+ }
593+ }
563594
564- Ok ( config)
595+ /// Parses a DNS server address, falling back to port 53 if the user omitted the port.
596+ fn parse_dns_server_address ( addr : & str ) -> io:: Result < SocketAddress > {
597+ if let Ok ( sa) = SocketAddress :: from_str ( addr) {
598+ return Ok ( sa) ;
565599 }
600+ let with_default_port = format ! ( "{}:53" , addr) ;
601+ SocketAddress :: from_str ( & with_default_port) . map_err ( |e| {
602+ io:: Error :: new (
603+ io:: ErrorKind :: InvalidInput ,
604+ format ! ( "Invalid HRN DNS server address configured: {}" , e) ,
605+ )
606+ } )
566607}
567608
568609#[ derive( Deserialize , Serialize ) ]
@@ -1634,11 +1675,43 @@ mod tests {
16341675 let err = load_config ( & args_config) . unwrap_err ( ) ;
16351676 assert_eq ! ( err. kind( ) , io:: ErrorKind :: InvalidInput ) ;
16361677
1637- // Invalid DNS server address is rejected.
1678+ // Invalid DNS server address is rejected (contains chars disallowed in hostnames, so
1679+ // neither the as-is parse nor the `:53` fallback can accept it).
16381680 let toml_config =
1639- format ! ( "{}\n [hrn]\n dns_server_address = \" not-a-socket-address\" \n " , base_config) ;
1681+ format ! ( "{}\n [hrn]\n dns_server_address = \" invalid@address\" \n " , base_config) ;
1682+ fs:: write ( storage_path. join ( config_file_name) , & toml_config) . unwrap ( ) ;
1683+ let err = load_config ( & args_config) . unwrap_err ( ) ;
1684+ assert_eq ! ( err. kind( ) , io:: ErrorKind :: InvalidInput ) ;
1685+
1686+ // DNS server address without an explicit port defaults to port 53.
1687+ let toml_config = format ! ( "{}\n [hrn]\n dns_server_address = \" 1.1.1.1\" \n " , base_config) ;
1688+ fs:: write ( storage_path. join ( config_file_name) , & toml_config) . unwrap ( ) ;
1689+ let config = load_config ( & args_config) . unwrap ( ) ;
1690+ match config. hrn_config . resolution_config {
1691+ HRNResolverConfig :: Dns { dns_server_address, .. } => {
1692+ assert_eq ! ( dns_server_address, SocketAddress :: from_str( "1.1.1.1:53" ) . unwrap( ) ) ;
1693+ } ,
1694+ other => panic ! ( "unexpected HRN resolver config: {:?}" , other) ,
1695+ }
1696+
1697+ // `blip32` mode combined with DNS-only settings is rejected so users aren't confused
1698+ // by settings that would silently have no effect.
1699+ let toml_config = format ! (
1700+ "{}\n [hrn]\n mode = \" blip32\" \n dns_server_address = \" 1.1.1.1:53\" \n " ,
1701+ base_config
1702+ ) ;
1703+ fs:: write ( storage_path. join ( config_file_name) , & toml_config) . unwrap ( ) ;
1704+ let err = load_config ( & args_config) . unwrap_err ( ) ;
1705+ assert_eq ! ( err. kind( ) , io:: ErrorKind :: InvalidInput ) ;
1706+ assert ! ( err. to_string( ) . contains( "dns_server_address" ) ) ;
1707+
1708+ let toml_config = format ! (
1709+ "{}\n [hrn]\n mode = \" blip32\" \n enable_resolution_service = true\n " ,
1710+ base_config
1711+ ) ;
16401712 fs:: write ( storage_path. join ( config_file_name) , & toml_config) . unwrap ( ) ;
16411713 let err = load_config ( & args_config) . unwrap_err ( ) ;
16421714 assert_eq ! ( err. kind( ) , io:: ErrorKind :: InvalidInput ) ;
1715+ assert ! ( err. to_string( ) . contains( "enable_resolution_service" ) ) ;
16431716 }
16441717}
0 commit comments