@@ -50,6 +50,8 @@ pub struct GenesisStakingSettings {
50
50
51
51
#[ derive( thiserror:: Error , Debug , Clone , PartialEq , Eq ) ]
52
52
pub enum GenesisStakingSettingsInputErrors {
53
+ #[ error( "Duplicate staking setting {0}" ) ]
54
+ DupicateStakingSetting ( String ) ,
53
55
#[ error( "Hex decoding failed {0}" ) ]
54
56
HexDecodingFailed ( String ) ,
55
57
#[ error( "Invalid pool Id {0}" ) ]
@@ -113,18 +115,29 @@ impl FromStr for GenesisStakingSettings {
113
115
. split ( ',' )
114
116
. filter_map ( |s| s. split_once ( ':' ) . or ( if s. is_empty ( ) { None } else { Some ( ( s, "" ) ) } ) )
115
117
. 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
+ }
117
129
118
130
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 ) ;
120
132
121
133
decode_hex :: < PoolId > ( pool_id)
122
134
. map_err ( |_| GenesisStakingSettingsInputErrors :: InvalidPoolId ( pool_id. into ( ) ) ) ?
123
135
} ;
124
136
125
137
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 ) ;
128
141
129
142
decode_hex :: < PrivateKey > ( stake_private_key) . map_err ( |_| {
130
143
GenesisStakingSettingsInputErrors :: InvalidStakingPrivateKey (
@@ -135,18 +148,24 @@ impl FromStr for GenesisStakingSettings {
135
148
136
149
let vrf_private_key = {
137
150
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 ) ;
139
152
140
153
decode_hex :: < VRFPrivateKey > ( vrf_private_key) . map_err ( |_| {
141
154
GenesisStakingSettingsInputErrors :: InvalidVRFPrivateKey ( vrf_private_key. into ( ) )
142
155
} ) ?
143
156
} ;
144
157
145
- if !settings_parts . is_empty ( ) {
158
+ if !settings_parts_uniq . is_empty ( ) {
146
159
return Err ( GenesisStakingSettingsInputErrors :: UnknownParameter (
147
- settings_parts
160
+ settings_parts_uniq
148
161
. 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
+ } )
150
169
. collect :: < Vec < String > > ( )
151
170
. join ( "," ) ,
152
171
) ) ;
@@ -301,6 +320,19 @@ mod test {
301
320
) ;
302
321
}
303
322
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
+
304
336
#[ test]
305
337
fn invalid_pool_id ( ) {
306
338
let result = GenesisStakingSettings :: from_str ( "pool_id:invalid_value" ) ;
0 commit comments