@@ -1171,6 +1171,17 @@ declare_builtin_function!(
1171
1171
use solana_zk_token_sdk:: curve25519:: {
1172
1172
curve_syscall_traits:: * , edwards, ristretto, scalar,
1173
1173
} ;
1174
+
1175
+ let restrict_msm_length = invoke_context
1176
+ . feature_set
1177
+ . is_active( & feature_set:: curve25519_restrict_msm_length:: id( ) ) ;
1178
+ #[ allow( clippy:: collapsible_if) ]
1179
+ if restrict_msm_length {
1180
+ if points_len > 512 {
1181
+ return Err ( Box :: new( SyscallError :: InvalidLength ) ) ;
1182
+ }
1183
+ }
1184
+
1174
1185
match curve_id {
1175
1186
CURVE25519_EDWARDS => {
1176
1187
let cost = invoke_context
@@ -3211,6 +3222,122 @@ mod tests {
3211
3222
assert_eq ! ( expected_product, result_point) ;
3212
3223
}
3213
3224
3225
+ #[ test]
3226
+ fn test_syscall_multiscalar_multiplication_maximum_length_exceeded ( ) {
3227
+ use solana_zk_token_sdk:: curve25519:: curve_syscall_traits:: {
3228
+ CURVE25519_EDWARDS , CURVE25519_RISTRETTO ,
3229
+ } ;
3230
+
3231
+ let config = Config :: default ( ) ;
3232
+ prepare_mockup ! ( invoke_context, program_id, bpf_loader:: id( ) ) ;
3233
+
3234
+ let scalar: [ u8 ; 32 ] = [
3235
+ 254 , 198 , 23 , 138 , 67 , 243 , 184 , 110 , 236 , 115 , 236 , 205 , 205 , 215 , 79 , 114 , 45 , 250 ,
3236
+ 78 , 137 , 3 , 107 , 136 , 237 , 49 , 126 , 117 , 223 , 37 , 191 , 88 , 6 ,
3237
+ ] ;
3238
+ let scalars = [ scalar; 513 ] ;
3239
+ let scalars_va = 0x100000000 ;
3240
+
3241
+ let edwards_point: [ u8 ; 32 ] = [
3242
+ 252 , 31 , 230 , 46 , 173 , 95 , 144 , 148 , 158 , 157 , 63 , 10 , 8 , 68 , 58 , 176 , 142 , 192 , 168 ,
3243
+ 53 , 61 , 105 , 194 , 166 , 43 , 56 , 246 , 236 , 28 , 146 , 114 , 133 ,
3244
+ ] ;
3245
+ let edwards_points = [ edwards_point; 513 ] ;
3246
+ let edwards_points_va = 0x200000000 ;
3247
+
3248
+ let ristretto_point: [ u8 ; 32 ] = [
3249
+ 130 , 35 , 97 , 25 , 18 , 199 , 33 , 239 , 85 , 143 , 119 , 111 , 49 , 51 , 224 , 40 , 167 , 185 , 240 ,
3250
+ 179 , 25 , 194 , 213 , 41 , 14 , 155 , 104 , 18 , 181 , 197 , 15 , 112 ,
3251
+ ] ;
3252
+ let ristretto_points = [ ristretto_point; 513 ] ;
3253
+ let ristretto_points_va = 0x300000000 ;
3254
+
3255
+ let mut result_point: [ u8 ; 32 ] = [ 0 ; 32 ] ;
3256
+ let result_point_va = 0x400000000 ;
3257
+
3258
+ let mut memory_mapping = MemoryMapping :: new (
3259
+ vec ! [
3260
+ MemoryRegion :: new_readonly( bytes_of_slice( & scalars) , scalars_va) ,
3261
+ MemoryRegion :: new_readonly( bytes_of_slice( & edwards_points) , edwards_points_va) ,
3262
+ MemoryRegion :: new_readonly( bytes_of_slice( & ristretto_points) , ristretto_points_va) ,
3263
+ MemoryRegion :: new_writable( bytes_of_slice_mut( & mut result_point) , result_point_va) ,
3264
+ ] ,
3265
+ & config,
3266
+ & SBPFVersion :: V2 ,
3267
+ )
3268
+ . unwrap ( ) ;
3269
+
3270
+ // test Edwards
3271
+ invoke_context. mock_set_remaining ( 500_000 ) ;
3272
+ let result = SyscallCurveMultiscalarMultiplication :: rust (
3273
+ & mut invoke_context,
3274
+ CURVE25519_EDWARDS ,
3275
+ scalars_va,
3276
+ edwards_points_va,
3277
+ 512 , // below maximum vector length
3278
+ result_point_va,
3279
+ & mut memory_mapping,
3280
+ ) ;
3281
+
3282
+ assert_eq ! ( 0 , result. unwrap( ) ) ;
3283
+ let expected_product = [
3284
+ 20 , 146 , 226 , 37 , 22 , 61 , 86 , 249 , 208 , 40 , 38 , 11 , 126 , 101 , 10 , 82 , 81 , 77 , 88 , 209 ,
3285
+ 15 , 76 , 82 , 251 , 180 , 133 , 84 , 243 , 162 , 0 , 11 , 145 ,
3286
+ ] ;
3287
+ assert_eq ! ( expected_product, result_point) ;
3288
+
3289
+ invoke_context. mock_set_remaining ( 500_000 ) ;
3290
+ let result = SyscallCurveMultiscalarMultiplication :: rust (
3291
+ & mut invoke_context,
3292
+ CURVE25519_EDWARDS ,
3293
+ scalars_va,
3294
+ edwards_points_va,
3295
+ 513 , // above maximum vector length
3296
+ result_point_va,
3297
+ & mut memory_mapping,
3298
+ )
3299
+ . unwrap_err ( )
3300
+ . downcast :: < SyscallError > ( )
3301
+ . unwrap ( ) ;
3302
+
3303
+ assert_eq ! ( * result, SyscallError :: InvalidLength ) ;
3304
+
3305
+ // test Ristretto
3306
+ invoke_context. mock_set_remaining ( 500_000 ) ;
3307
+ let result = SyscallCurveMultiscalarMultiplication :: rust (
3308
+ & mut invoke_context,
3309
+ CURVE25519_RISTRETTO ,
3310
+ scalars_va,
3311
+ ristretto_points_va,
3312
+ 512 , // below maximum vector length
3313
+ result_point_va,
3314
+ & mut memory_mapping,
3315
+ ) ;
3316
+
3317
+ assert_eq ! ( 0 , result. unwrap( ) ) ;
3318
+ let expected_product = [
3319
+ 146 , 224 , 127 , 193 , 252 , 64 , 196 , 181 , 246 , 104 , 27 , 116 , 183 , 52 , 200 , 239 , 2 , 108 ,
3320
+ 21 , 27 , 97 , 44 , 95 , 65 , 26 , 218 , 223 , 39 , 197 , 132 , 51 , 49 ,
3321
+ ] ;
3322
+ assert_eq ! ( expected_product, result_point) ;
3323
+
3324
+ invoke_context. mock_set_remaining ( 500_000 ) ;
3325
+ let result = SyscallCurveMultiscalarMultiplication :: rust (
3326
+ & mut invoke_context,
3327
+ CURVE25519_RISTRETTO ,
3328
+ scalars_va,
3329
+ ristretto_points_va,
3330
+ 513 , // above maximum vector length
3331
+ result_point_va,
3332
+ & mut memory_mapping,
3333
+ )
3334
+ . unwrap_err ( )
3335
+ . downcast :: < SyscallError > ( )
3336
+ . unwrap ( ) ;
3337
+
3338
+ assert_eq ! ( * result, SyscallError :: InvalidLength ) ;
3339
+ }
3340
+
3214
3341
fn create_filled_type < T : Default > ( zero_init : bool ) -> T {
3215
3342
let mut val = T :: default ( ) ;
3216
3343
let p = & mut val as * mut _ as * mut u8 ;
0 commit comments