@@ -1195,3 +1195,338 @@ impl Session {
1195
1195
/// Get a mut pointer to the inner Session
1196
1196
pub fn as_mut_ptr ( & mut self ) -> * mut ffi:: MusigSession { & mut self . 0 }
1197
1197
}
1198
+
1199
+ #[ cfg( test) ]
1200
+ mod tests {
1201
+ use super :: * ;
1202
+ #[ cfg( feature = "std" ) ]
1203
+ #[ cfg( feature = "rand" ) ]
1204
+ use crate :: { Message , PublicKey , Secp256k1 , SecretKey } ;
1205
+
1206
+ #[ test]
1207
+ #[ cfg( feature = "std" ) ]
1208
+ #[ cfg( feature = "rand" ) ]
1209
+ fn session_secret_rand ( ) {
1210
+ let mut rng = rand:: rng ( ) ;
1211
+ let session_secrand = SessionSecretRand :: from_rng ( & mut rng) ;
1212
+ let session_secrand1 = SessionSecretRand :: from_rng ( & mut rng) ;
1213
+ assert_ne ! ( session_secrand. to_byte_array( ) , [ 0 ; 32 ] ) ; // with overwhelming probability
1214
+ assert_ne ! ( session_secrand, session_secrand1) ; // with overwhelming probability
1215
+ }
1216
+
1217
+ #[ test]
1218
+ fn session_secret_no_rand ( ) {
1219
+ let custom_bytes = [ 42u8 ; 32 ] ;
1220
+ let session_secrand = SessionSecretRand :: assume_unique_per_nonce_gen ( custom_bytes) ;
1221
+ assert_eq ! ( session_secrand. to_byte_array( ) , custom_bytes) ;
1222
+ assert_eq ! ( session_secrand. as_byte_array( ) , & custom_bytes) ;
1223
+ }
1224
+
1225
+ #[ test]
1226
+ #[ should_panic( expected = "session secrets may not be all zero" ) ]
1227
+ fn session_secret_rand_zero_panic ( ) {
1228
+ let zero_bytes = [ 0u8 ; 32 ] ;
1229
+ let _session_secrand = SessionSecretRand :: assume_unique_per_nonce_gen ( zero_bytes) ;
1230
+ }
1231
+
1232
+ #[ test]
1233
+ #[ cfg( not( secp256k1_fuzz) ) ]
1234
+ #[ cfg( feature = "std" ) ]
1235
+ #[ cfg( feature = "rand" ) ]
1236
+ fn key_agg_cache ( ) {
1237
+ let secp = Secp256k1 :: new ( ) ;
1238
+ let mut rng = rand:: rng ( ) ;
1239
+
1240
+ let ( _seckey1, pubkey1) = secp. generate_keypair ( & mut rng) ;
1241
+ let seckey2 = SecretKey :: new ( & mut rng) ;
1242
+ let pubkey2 = PublicKey :: from_secret_key ( & secp, & seckey2) ;
1243
+
1244
+ let pubkeys = [ & pubkey1, & pubkey2] ;
1245
+ let key_agg_cache = KeyAggCache :: new ( & secp, & pubkeys) ;
1246
+ let agg_pk = key_agg_cache. agg_pk ( ) ;
1247
+
1248
+ // Test agg_pk_full
1249
+ let agg_pk_full = key_agg_cache. agg_pk_full ( ) ;
1250
+ assert_eq ! ( agg_pk_full. x_only_public_key( ) . 0 , agg_pk) ;
1251
+ }
1252
+
1253
+ #[ test]
1254
+ #[ cfg( not( secp256k1_fuzz) ) ]
1255
+ #[ cfg( feature = "std" ) ]
1256
+ #[ cfg( feature = "rand" ) ]
1257
+ fn key_agg_cache_tweaking ( ) {
1258
+ let secp = Secp256k1 :: new ( ) ;
1259
+ let mut rng = rand:: rng ( ) ;
1260
+
1261
+ let ( _seckey1, pubkey1) = secp. generate_keypair ( & mut rng) ;
1262
+ let seckey2 = SecretKey :: new ( & mut rng) ;
1263
+ let pubkey2 = PublicKey :: from_secret_key ( & secp, & seckey2) ;
1264
+
1265
+ let mut key_agg_cache = KeyAggCache :: new ( & secp, & [ & pubkey1, & pubkey2] ) ;
1266
+ let key_agg_cache1 = KeyAggCache :: new ( & secp, & [ & pubkey2, & pubkey1] ) ;
1267
+ let key_agg_cache2 = KeyAggCache :: new ( & secp, & [ & pubkey1, & pubkey1] ) ;
1268
+ let key_agg_cache3 = KeyAggCache :: new ( & secp, & [ & pubkey1, & pubkey1, & pubkey2] ) ;
1269
+ assert_ne ! ( key_agg_cache, key_agg_cache1) ; // swapped keys DOES mean not equal
1270
+ assert_ne ! ( key_agg_cache, key_agg_cache2) ; // missing keys
1271
+ assert_ne ! ( key_agg_cache, key_agg_cache3) ; // repeated key
1272
+ let original_agg_pk = key_agg_cache. agg_pk ( ) ;
1273
+ assert_ne ! ( key_agg_cache. agg_pk( ) , key_agg_cache1. agg_pk( ) ) ; // swapped keys DOES mean not equal
1274
+ assert_ne ! ( key_agg_cache. agg_pk( ) , key_agg_cache2. agg_pk( ) ) ; // missing keys
1275
+ assert_ne ! ( key_agg_cache. agg_pk( ) , key_agg_cache3. agg_pk( ) ) ; // repeated key
1276
+
1277
+ // Test EC tweaking
1278
+ let plain_tweak: [ u8 ; 32 ] = * b"this could be a BIP32 tweak....\0 " ;
1279
+ let plain_tweak = Scalar :: from_be_bytes ( plain_tweak) . unwrap ( ) ;
1280
+ let tweaked_key = key_agg_cache. pubkey_ec_tweak_add ( & secp, & plain_tweak) . unwrap ( ) ;
1281
+ assert_ne ! ( key_agg_cache. agg_pk( ) , original_agg_pk) ;
1282
+ assert_eq ! ( key_agg_cache. agg_pk( ) , tweaked_key. x_only_public_key( ) . 0 ) ;
1283
+
1284
+ // Test xonly tweaking
1285
+ let xonly_tweak: [ u8 ; 32 ] = * b"this could be a Taproot tweak..\0 " ;
1286
+ let xonly_tweak = Scalar :: from_be_bytes ( xonly_tweak) . unwrap ( ) ;
1287
+ let tweaked_agg_pk = key_agg_cache. pubkey_xonly_tweak_add ( & secp, & xonly_tweak) . unwrap ( ) ;
1288
+ assert_eq ! ( key_agg_cache. agg_pk( ) , tweaked_agg_pk. x_only_public_key( ) . 0 ) ;
1289
+ }
1290
+
1291
+ #[ test]
1292
+ #[ cfg( feature = "std" ) ]
1293
+ #[ cfg( feature = "rand" ) ]
1294
+ #[ should_panic( expected = "Cannot aggregate an empty slice of pubkeys" ) ]
1295
+ fn key_agg_cache_empty_panic ( ) {
1296
+ let secp = Secp256k1 :: new ( ) ;
1297
+ let _ = KeyAggCache :: new ( & secp, & [ ] ) ;
1298
+ }
1299
+
1300
+ #[ test]
1301
+ #[ cfg( feature = "std" ) ]
1302
+ #[ cfg( feature = "rand" ) ]
1303
+ fn nonce_generation ( ) {
1304
+ let secp = Secp256k1 :: new ( ) ;
1305
+ let mut rng = rand:: rng ( ) ;
1306
+
1307
+ let ( _seckey1, pubkey1) = secp. generate_keypair ( & mut rng) ;
1308
+ let seckey2 = SecretKey :: new ( & mut rng) ;
1309
+ let pubkey2 = PublicKey :: from_secret_key ( & secp, & seckey2) ;
1310
+
1311
+ let key_agg_cache = KeyAggCache :: new ( & secp, & [ & pubkey1, & pubkey2] ) ;
1312
+
1313
+ let msg_bytes: [ u8 ; 32 ] = * b"this_could_be_the_hash_of_a_msg!" ;
1314
+ let msg = Message :: from_digest_slice ( & msg_bytes) . unwrap ( ) ;
1315
+
1316
+ // Test nonce generation with KeyAggCache
1317
+ let session_secrand1 = SessionSecretRand :: from_rng ( & mut rng) ;
1318
+ let ( _sec_nonce1, pub_nonce1) =
1319
+ key_agg_cache. nonce_gen ( & secp, session_secrand1, pubkey1, msg, None ) ;
1320
+
1321
+ // Test direct nonce generation
1322
+ let session_secrand2 = SessionSecretRand :: from_rng ( & mut rng) ;
1323
+ let extra_rand = Some ( [ 42u8 ; 32 ] ) ;
1324
+ let ( _sec_nonce2, _pub_nonce2) = new_nonce_pair (
1325
+ & secp,
1326
+ session_secrand2,
1327
+ Some ( & key_agg_cache) ,
1328
+ Some ( seckey2) ,
1329
+ pubkey2,
1330
+ Some ( msg) ,
1331
+ extra_rand,
1332
+ ) ;
1333
+
1334
+ // Test PublicNonce serialization/deserialization
1335
+ let serialized_nonce = pub_nonce1. serialize ( ) ;
1336
+ let deserialized_nonce = PublicNonce :: from_byte_array ( & serialized_nonce) . unwrap ( ) ;
1337
+ assert_eq ! ( pub_nonce1. serialize( ) , deserialized_nonce. serialize( ) ) ;
1338
+ }
1339
+
1340
+ #[ test]
1341
+ #[ cfg( feature = "std" ) ]
1342
+ #[ cfg( feature = "rand" ) ]
1343
+ fn aggregated_nonce ( ) {
1344
+ let secp = Secp256k1 :: new ( ) ;
1345
+ let mut rng = rand:: rng ( ) ;
1346
+
1347
+ let ( _seckey1, pubkey1) = secp. generate_keypair ( & mut rng) ;
1348
+ let seckey2 = SecretKey :: new ( & mut rng) ;
1349
+ let pubkey2 = PublicKey :: from_secret_key ( & secp, & seckey2) ;
1350
+
1351
+ let key_agg_cache = KeyAggCache :: new ( & secp, & [ & pubkey1, & pubkey2] ) ;
1352
+
1353
+ let msg_bytes: [ u8 ; 32 ] = * b"this_could_be_the_hash_of_a_msg!" ;
1354
+ let msg = Message :: from_digest_slice ( & msg_bytes) . unwrap ( ) ;
1355
+
1356
+ let session_secrand1 = SessionSecretRand :: from_rng ( & mut rng) ;
1357
+ let ( _, pub_nonce1) = key_agg_cache. nonce_gen ( & secp, session_secrand1, pubkey1, msg, None ) ;
1358
+
1359
+ let session_secrand2 = SessionSecretRand :: from_rng ( & mut rng) ;
1360
+ let ( _, pub_nonce2) = key_agg_cache. nonce_gen ( & secp, session_secrand2, pubkey2, msg, None ) ;
1361
+
1362
+ // Test AggregatedNonce creation
1363
+ let agg_nonce = AggregatedNonce :: new ( & secp, & [ & pub_nonce1, & pub_nonce2] ) ;
1364
+ let agg_nonce1 = AggregatedNonce :: new ( & secp, & [ & pub_nonce2, & pub_nonce1] ) ;
1365
+ let agg_nonce2 = AggregatedNonce :: new ( & secp, & [ & pub_nonce2, & pub_nonce2] ) ;
1366
+ let agg_nonce3 = AggregatedNonce :: new ( & secp, & [ & pub_nonce2, & pub_nonce2] ) ;
1367
+ assert_eq ! ( agg_nonce, agg_nonce1) ; // swapped nonces
1368
+ assert_ne ! ( agg_nonce, agg_nonce2) ; // repeated/different nonces
1369
+ assert_ne ! ( agg_nonce, agg_nonce3) ; // repeated nonce but still both nonces present
1370
+
1371
+ // Test AggregatedNonce serialization/deserialization
1372
+ let serialized_agg_nonce = agg_nonce. serialize ( ) ;
1373
+ let deserialized_agg_nonce =
1374
+ AggregatedNonce :: from_byte_array ( & serialized_agg_nonce) . unwrap ( ) ;
1375
+ assert_eq ! ( agg_nonce. serialize( ) , deserialized_agg_nonce. serialize( ) ) ;
1376
+ }
1377
+
1378
+ #[ test]
1379
+ #[ cfg( feature = "std" ) ]
1380
+ #[ cfg( feature = "rand" ) ]
1381
+ #[ should_panic( expected = "Cannot aggregate an empty slice of nonces" ) ]
1382
+ fn aggregated_nonce_empty_panic ( ) {
1383
+ let secp = Secp256k1 :: new ( ) ;
1384
+ let empty_nonces: Vec < & PublicNonce > = vec ! [ ] ;
1385
+ let _agg_nonce = AggregatedNonce :: new ( & secp, & empty_nonces) ;
1386
+ }
1387
+
1388
+ #[ test]
1389
+ #[ cfg( not( secp256k1_fuzz) ) ]
1390
+ #[ cfg( feature = "std" ) ]
1391
+ #[ cfg( feature = "rand" ) ]
1392
+ fn session_and_partial_signing ( ) {
1393
+ let secp = Secp256k1 :: new ( ) ;
1394
+ let mut rng = rand:: rng ( ) ;
1395
+
1396
+ let ( seckey1, pubkey1) = secp. generate_keypair ( & mut rng) ;
1397
+ let seckey2 = SecretKey :: new ( & mut rng) ;
1398
+ let pubkey2 = PublicKey :: from_secret_key ( & secp, & seckey2) ;
1399
+
1400
+ let pubkeys = [ & pubkey1, & pubkey2] ;
1401
+ let key_agg_cache = KeyAggCache :: new ( & secp, & pubkeys) ;
1402
+
1403
+ let msg_bytes: [ u8 ; 32 ] = * b"this_could_be_the_hash_of_a_msg!" ;
1404
+ let msg = Message :: from_digest_slice ( & msg_bytes) . unwrap ( ) ;
1405
+
1406
+ let session_secrand1 = SessionSecretRand :: from_rng ( & mut rng) ;
1407
+ let ( sec_nonce1, pub_nonce1) =
1408
+ key_agg_cache. nonce_gen ( & secp, session_secrand1, pubkey1, msg, None ) ;
1409
+
1410
+ let session_secrand2 = SessionSecretRand :: from_rng ( & mut rng) ;
1411
+ let ( sec_nonce2, pub_nonce2) =
1412
+ key_agg_cache. nonce_gen ( & secp, session_secrand2, pubkey2, msg, None ) ;
1413
+
1414
+ let nonces = [ & pub_nonce1, & pub_nonce2] ;
1415
+ let agg_nonce = AggregatedNonce :: new ( & secp, & nonces) ;
1416
+
1417
+ // Test Session creation
1418
+ let session = Session :: new ( & secp, & key_agg_cache, agg_nonce, msg) ;
1419
+
1420
+ // Test partial signing
1421
+ let keypair1 = Keypair :: from_secret_key ( & secp, & seckey1) ;
1422
+ let partial_sign1 = session. partial_sign ( & secp, sec_nonce1, & keypair1, & key_agg_cache) ;
1423
+
1424
+ let keypair2 = Keypair :: from_secret_key ( & secp, & seckey2) ;
1425
+ let partial_sign2 = session. partial_sign ( & secp, sec_nonce2, & keypair2, & key_agg_cache) ;
1426
+
1427
+ // Test partial signature verification
1428
+ assert ! ( session. partial_verify( & secp, & key_agg_cache, partial_sign1, pub_nonce1, pubkey1) ) ;
1429
+ assert ! ( session. partial_verify( & secp, & key_agg_cache, partial_sign2, pub_nonce2, pubkey2) ) ;
1430
+ // Test that they are invalid if you switch keys
1431
+ assert ! ( !session. partial_verify( & secp, & key_agg_cache, partial_sign2, pub_nonce2, pubkey1) ) ;
1432
+ assert ! ( !session. partial_verify( & secp, & key_agg_cache, partial_sign2, pub_nonce1, pubkey2) ) ;
1433
+ assert ! ( !session. partial_verify( & secp, & key_agg_cache, partial_sign2, pub_nonce1, pubkey1) ) ;
1434
+
1435
+ // Test PartialSignature serialization/deserialization
1436
+ let serialized_partial_sig = partial_sign1. serialize ( ) ;
1437
+ let deserialized_partial_sig =
1438
+ PartialSignature :: from_byte_array ( & serialized_partial_sig) . unwrap ( ) ;
1439
+ assert_eq ! ( partial_sign1. serialize( ) , deserialized_partial_sig. serialize( ) ) ;
1440
+ }
1441
+
1442
+ #[ test]
1443
+ #[ cfg( not( secp256k1_fuzz) ) ]
1444
+ #[ cfg( feature = "std" ) ]
1445
+ #[ cfg( feature = "rand" ) ]
1446
+ fn signature_aggregation_and_verification ( ) {
1447
+ let secp = Secp256k1 :: new ( ) ;
1448
+ let mut rng = rand:: rng ( ) ;
1449
+
1450
+ let ( seckey1, pubkey1) = secp. generate_keypair ( & mut rng) ;
1451
+ let seckey2 = SecretKey :: new ( & mut rng) ;
1452
+ let pubkey2 = PublicKey :: from_secret_key ( & secp, & seckey2) ;
1453
+
1454
+ let pubkeys = [ & pubkey1, & pubkey2] ;
1455
+ let key_agg_cache = KeyAggCache :: new ( & secp, & pubkeys) ;
1456
+
1457
+ let msg_bytes: [ u8 ; 32 ] = * b"this_could_be_the_hash_of_a_msg!" ;
1458
+ let msg = Message :: from_digest_slice ( & msg_bytes) . unwrap ( ) ;
1459
+
1460
+ let session_secrand1 = SessionSecretRand :: from_rng ( & mut rng) ;
1461
+ let ( sec_nonce1, pub_nonce1) =
1462
+ key_agg_cache. nonce_gen ( & secp, session_secrand1, pubkey1, msg, None ) ;
1463
+
1464
+ let session_secrand2 = SessionSecretRand :: from_rng ( & mut rng) ;
1465
+ let ( sec_nonce2, pub_nonce2) =
1466
+ key_agg_cache. nonce_gen ( & secp, session_secrand2, pubkey2, msg, None ) ;
1467
+
1468
+ let nonces = [ & pub_nonce1, & pub_nonce2] ;
1469
+ let agg_nonce = AggregatedNonce :: new ( & secp, & nonces) ;
1470
+ let session = Session :: new ( & secp, & key_agg_cache, agg_nonce, msg) ;
1471
+
1472
+ let keypair1 = Keypair :: from_secret_key ( & secp, & seckey1) ;
1473
+ let partial_sign1 = session. partial_sign ( & secp, sec_nonce1, & keypair1, & key_agg_cache) ;
1474
+
1475
+ let keypair2 = Keypair :: from_secret_key ( & secp, & seckey2) ;
1476
+ let partial_sign2 = session. partial_sign ( & secp, sec_nonce2, & keypair2, & key_agg_cache) ;
1477
+
1478
+ // Test signature verification
1479
+ let aggregated_signature = session. partial_sig_agg ( & [ & partial_sign1, & partial_sign2] ) ;
1480
+ let agg_pk = key_agg_cache. agg_pk ( ) ;
1481
+ aggregated_signature. verify ( & secp, & agg_pk, & msg_bytes) . unwrap ( ) ;
1482
+
1483
+ // Test assume_valid
1484
+ let schnorr_sig = aggregated_signature. assume_valid ( ) ;
1485
+ secp. verify_schnorr ( & schnorr_sig, & msg_bytes, & agg_pk) . unwrap ( ) ;
1486
+
1487
+ // Test with wrong aggregate (repeated sigs)
1488
+ let aggregated_signature = session. partial_sig_agg ( & [ & partial_sign1, & partial_sign1] ) ;
1489
+ aggregated_signature. verify ( & secp, & agg_pk, & msg_bytes) . unwrap_err ( ) ;
1490
+ let schnorr_sig = aggregated_signature. assume_valid ( ) ;
1491
+ secp. verify_schnorr ( & schnorr_sig, & msg_bytes, & agg_pk) . unwrap_err ( ) ;
1492
+
1493
+ // Test with swapped sigs -- this will work. Unlike keys, sigs are not ordered.
1494
+ let aggregated_signature = session. partial_sig_agg ( & [ & partial_sign2, & partial_sign1] ) ;
1495
+ aggregated_signature. verify ( & secp, & agg_pk, & msg_bytes) . unwrap ( ) ;
1496
+ let schnorr_sig = aggregated_signature. assume_valid ( ) ;
1497
+ secp. verify_schnorr ( & schnorr_sig, & msg_bytes, & agg_pk) . unwrap ( ) ;
1498
+ }
1499
+
1500
+ #[ test]
1501
+ #[ cfg( feature = "std" ) ]
1502
+ #[ cfg( feature = "rand" ) ]
1503
+ #[ should_panic( expected = "Cannot aggregate an empty slice of partial signatures" ) ]
1504
+ fn partial_sig_agg_empty_panic ( ) {
1505
+ let secp = Secp256k1 :: new ( ) ;
1506
+ let mut rng = rand:: rng ( ) ;
1507
+
1508
+ let ( _seckey1, pubkey1) = secp. generate_keypair ( & mut rng) ;
1509
+ let seckey2 = SecretKey :: new ( & mut rng) ;
1510
+ let pubkey2 = PublicKey :: from_secret_key ( & secp, & seckey2) ;
1511
+
1512
+ let pubkeys = [ pubkey1, pubkey2] ;
1513
+ let mut pubkeys_ref: Vec < & PublicKey > = pubkeys. iter ( ) . collect ( ) ;
1514
+ let pubkeys_ref = pubkeys_ref. as_mut_slice ( ) ;
1515
+
1516
+ let key_agg_cache = KeyAggCache :: new ( & secp, pubkeys_ref) ;
1517
+ let msg_bytes: [ u8 ; 32 ] = * b"this_could_be_the_hash_of_a_msg!" ;
1518
+ let msg = Message :: from_digest_slice ( & msg_bytes) . unwrap ( ) ;
1519
+
1520
+ let session_secrand1 = SessionSecretRand :: from_rng ( & mut rng) ;
1521
+ let ( _, pub_nonce1) = key_agg_cache. nonce_gen ( & secp, session_secrand1, pubkey1, msg, None ) ;
1522
+ let session_secrand2 = SessionSecretRand :: from_rng ( & mut rng) ;
1523
+ let ( _, pub_nonce2) = key_agg_cache. nonce_gen ( & secp, session_secrand2, pubkey2, msg, None ) ;
1524
+
1525
+ let nonces = [ pub_nonce1, pub_nonce2] ;
1526
+ let nonces_ref: Vec < & PublicNonce > = nonces. iter ( ) . collect ( ) ;
1527
+ let agg_nonce = AggregatedNonce :: new ( & secp, & nonces_ref) ;
1528
+ let session = Session :: new ( & secp, & key_agg_cache, agg_nonce, msg) ;
1529
+
1530
+ let _agg_sig = session. partial_sig_agg ( & [ ] ) ;
1531
+ }
1532
+ }
0 commit comments