@@ -109,7 +109,7 @@ impl Default for LiquiditySourceConfig {
109
109
/// An error encountered during building a [`Node`].
110
110
///
111
111
/// [`Node`]: crate::Node
112
- #[ derive( Debug , Clone ) ]
112
+ #[ derive( Debug , Clone , PartialEq ) ]
113
113
pub enum BuildError {
114
114
/// The given seed bytes are invalid, e.g., have invalid length.
115
115
InvalidSeedBytes ,
@@ -139,6 +139,8 @@ pub enum BuildError {
139
139
WalletSetupFailed ,
140
140
/// We failed to setup the logger.
141
141
LoggerSetupFailed ,
142
+ /// The provided alias is invalid
143
+ InvalidNodeAlias ( String ) ,
142
144
}
143
145
144
146
impl fmt:: Display for BuildError {
@@ -159,6 +161,9 @@ impl fmt::Display for BuildError {
159
161
Self :: KVStoreSetupFailed => write ! ( f, "Failed to setup KVStore." ) ,
160
162
Self :: WalletSetupFailed => write ! ( f, "Failed to setup onchain wallet." ) ,
161
163
Self :: LoggerSetupFailed => write ! ( f, "Failed to setup the logger." ) ,
164
+ Self :: InvalidNodeAlias ( ref reason) => {
165
+ write ! ( f, "Given node alias is invalid: {}" , reason)
166
+ } ,
162
167
}
163
168
}
164
169
}
@@ -309,6 +314,17 @@ impl NodeBuilder {
309
314
self
310
315
}
311
316
317
+ /// Sets the alias the [`Node`] will use in its announcement. The provided
318
+ /// alias must be a valid UTF-8 string.
319
+ pub fn set_node_alias < T : Into < String > > (
320
+ & mut self , node_alias : T ,
321
+ ) -> Result < & mut Self , BuildError > {
322
+ let node_alias = sanitize_alias ( node_alias) . map_err ( |e| e) ?;
323
+
324
+ self . config . node_alias = Some ( node_alias) ;
325
+ Ok ( self )
326
+ }
327
+
312
328
/// Builds a [`Node`] instance with a [`SqliteStore`] backend and according to the options
313
329
/// previously configured.
314
330
pub fn build ( & self ) -> Result < Node , BuildError > {
@@ -1050,3 +1066,68 @@ fn seed_bytes_from_config(
1050
1066
} ,
1051
1067
}
1052
1068
}
1069
+
1070
+ /// Sanitize the user-provided node alias to ensure that it is a valid protocol-specified UTF-8 string.
1071
+ fn sanitize_alias < T : Into < String > > ( node_alias : T ) -> Result < String , BuildError > {
1072
+ // Alias is convertible into UTF-8 encoded string
1073
+ let node_alias: String = node_alias. into ( ) ;
1074
+ let alias = node_alias. trim ( ) ;
1075
+
1076
+ // Alias is non-empty
1077
+ if alias. is_empty ( ) {
1078
+ return Err ( BuildError :: InvalidNodeAlias ( "Node alias cannot be empty." . to_string ( ) ) ) ;
1079
+ }
1080
+
1081
+ // Alias valid up to first null byte
1082
+ let first_null = alias. as_bytes ( ) . iter ( ) . position ( |b| * b == 0 ) . unwrap_or ( alias. len ( ) ) ;
1083
+ let actual_alias = alias. split_at ( first_null) . 0 ;
1084
+
1085
+ // Alias must be 32-bytes long or less
1086
+ if actual_alias. as_bytes ( ) . len ( ) > 32 {
1087
+ return Err ( BuildError :: InvalidNodeAlias ( "Node alias cannot exceed 32 bytes." . to_string ( ) ) ) ;
1088
+ }
1089
+
1090
+ Ok ( actual_alias. to_string ( ) )
1091
+ }
1092
+
1093
+ #[ cfg( test) ]
1094
+ mod tests {
1095
+ use crate :: { BuildError , Node } ;
1096
+
1097
+ use super :: NodeBuilder ;
1098
+
1099
+ fn create_node_with_alias < T : Into < String > > ( alias : T ) -> Result < Node , BuildError > {
1100
+ NodeBuilder :: new ( ) . set_node_alias ( & alias. into ( ) ) ?. build ( )
1101
+ }
1102
+
1103
+ #[ test]
1104
+ fn empty_node_alias ( ) {
1105
+ // Empty node alias
1106
+ let alias = "" ;
1107
+ let node = create_node_with_alias ( alias) ;
1108
+ assert_eq ! (
1109
+ node. err( ) . unwrap( ) ,
1110
+ BuildError :: InvalidNodeAlias ( "Node alias cannot be empty." . to_string( ) )
1111
+ ) ;
1112
+ }
1113
+
1114
+ #[ test]
1115
+ fn node_alias_with_sandwiched_null ( ) {
1116
+ // Alias with emojis
1117
+ let expected_alias = "I\u{1F496} LDK-Node!" ;
1118
+ let user_provided_alias = "I\u{1F496} LDK-Node!\0 \u{26A1} " ;
1119
+ let node = create_node_with_alias ( user_provided_alias) . unwrap ( ) ;
1120
+
1121
+ assert_eq ! ( expected_alias, node. config( ) . node_alias. unwrap( ) ) ;
1122
+ }
1123
+
1124
+ #[ test]
1125
+ fn node_alias_longer_than_32_bytes ( ) {
1126
+ let alias = "This is a string longer than thirty-two bytes!" ; // 46 bytes
1127
+ let node = create_node_with_alias ( alias) ;
1128
+ assert_eq ! (
1129
+ node. err( ) . unwrap( ) ,
1130
+ BuildError :: InvalidNodeAlias ( "Node alias cannot exceed 32 bytes." . to_string( ) )
1131
+ ) ;
1132
+ }
1133
+ }
0 commit comments