@@ -50,6 +50,8 @@ pub struct GenesisStakingSettings {
5050
5151#[ derive( thiserror:: Error , Debug , Clone , PartialEq , Eq ) ]
5252pub enum GenesisStakingSettingsInputErrors {
53+ #[ error( "Duplicate staking setting {0}" ) ]
54+ DupicateStakingSetting ( String ) ,
5355 #[ error( "Hex decoding failed {0}" ) ]
5456 HexDecodingFailed ( String ) ,
5557 #[ error( "Invalid pool Id {0}" ) ]
@@ -113,18 +115,29 @@ impl FromStr for GenesisStakingSettings {
113115 . split ( ',' )
114116 . filter_map ( |s| s. split_once ( ':' ) . or ( if s. is_empty ( ) { None } else { Some ( ( s, "" ) ) } ) )
115117 . map ( |( k, v) | ( k. trim ( ) , v. trim ( ) ) )
116- . collect :: < HashMap < & str , & str > > ( ) ;
118+ . collect :: < Vec < ( & str , & str ) > > ( ) ;
119+
120+ let mut settings_parts_uniq = HashMap :: new ( ) ;
121+
122+ for ( key, value) in settings_parts {
123+ if settings_parts_uniq. insert ( key, value) . is_some ( ) {
124+ return Err ( GenesisStakingSettingsInputErrors :: DupicateStakingSetting (
125+ key. into ( ) ,
126+ ) ) ;
127+ }
128+ }
117129
118130 let pool_id = {
119- let pool_id = settings_parts . remove ( "pool_id" ) . unwrap_or ( GENESIS_POOL_ID ) ;
131+ let pool_id = settings_parts_uniq . remove ( "pool_id" ) . unwrap_or ( GENESIS_POOL_ID ) ;
120132
121133 decode_hex :: < PoolId > ( pool_id)
122134 . map_err ( |_| GenesisStakingSettingsInputErrors :: InvalidPoolId ( pool_id. into ( ) ) ) ?
123135 } ;
124136
125137 let stake_private_key = {
126- let stake_private_key =
127- settings_parts. remove ( "stake_private_key" ) . unwrap_or ( GENESIS_STAKE_PRIVATE_KEY ) ;
138+ let stake_private_key = settings_parts_uniq
139+ . remove ( "stake_private_key" )
140+ . unwrap_or ( GENESIS_STAKE_PRIVATE_KEY ) ;
128141
129142 decode_hex :: < PrivateKey > ( stake_private_key) . map_err ( |_| {
130143 GenesisStakingSettingsInputErrors :: InvalidStakingPrivateKey (
@@ -135,18 +148,24 @@ impl FromStr for GenesisStakingSettings {
135148
136149 let vrf_private_key = {
137150 let vrf_private_key =
138- settings_parts . remove ( "vrf_private_key" ) . unwrap_or ( GENESIS_VRF_PRIVATE_KEY ) ;
151+ settings_parts_uniq . remove ( "vrf_private_key" ) . unwrap_or ( GENESIS_VRF_PRIVATE_KEY ) ;
139152
140153 decode_hex :: < VRFPrivateKey > ( vrf_private_key) . map_err ( |_| {
141154 GenesisStakingSettingsInputErrors :: InvalidVRFPrivateKey ( vrf_private_key. into ( ) )
142155 } ) ?
143156 } ;
144157
145- if !settings_parts . is_empty ( ) {
158+ if !settings_parts_uniq . is_empty ( ) {
146159 return Err ( GenesisStakingSettingsInputErrors :: UnknownParameter (
147- settings_parts
160+ settings_parts_uniq
148161 . drain ( )
149- . map ( |( k, v) | format ! ( "{}:{}" , k, v) )
162+ . map ( |( k, v) | {
163+ if v. is_empty ( ) {
164+ k. to_string ( )
165+ } else {
166+ [ k, v] . join ( ":" )
167+ }
168+ } )
150169 . collect :: < Vec < String > > ( )
151170 . join ( "," ) ,
152171 ) ) ;
@@ -301,6 +320,19 @@ mod test {
301320 ) ;
302321 }
303322
323+ #[ test]
324+ fn duplicate_key ( ) {
325+ let result = GenesisStakingSettings :: from_str ( "key:value1,key:value2" ) ;
326+
327+ assert_eq ! (
328+ result,
329+ Err ( GenesisStakingSettingsInputErrors :: DupicateStakingSetting (
330+ "key" . to_string( )
331+ ) ) ,
332+ "Duplicate key was valid"
333+ ) ;
334+ }
335+
304336 #[ test]
305337 fn invalid_pool_id ( ) {
306338 let result = GenesisStakingSettings :: from_str ( "pool_id:invalid_value" ) ;
0 commit comments