Skip to content

Commit 7aec98d

Browse files
authored
Merge pull request #4289 from anoma/grarco/multisig-tests
More multisig tests
2 parents b242675 + aa3dfae commit 7aec98d

File tree

2 files changed

+156
-3
lines changed

2 files changed

+156
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- Added more test cases for multisig verification
2+
([\#4289](https://github.com/anoma/namada/pull/4289))

crates/tx/src/types.rs

+154-3
Original file line numberDiff line numberDiff line change
@@ -1244,6 +1244,8 @@ mod test {
12441244
let pks_map =
12451245
AccountPublicKeysMap::from_iter(vec![pk1.clone(), pk2.clone()]);
12461246
let threshold = 2_u8;
1247+
let est_address =
1248+
namada_core::address::testing::established_address_1();
12471249

12481250
let tx = Tx::default();
12491251

@@ -1327,9 +1329,13 @@ mod test {
13271329
// Sign the tx with two keys but one of them incorrect - sk3
13281330
{
13291331
let mut tx = tx.clone();
1330-
let pks_map_wrong = AccountPublicKeysMap::from_iter(vec![pk1, pk3]);
1331-
let signatures =
1332-
tx.compute_section_signature(&[sk1, sk3], &pks_map_wrong, None);
1332+
let pks_map_wrong =
1333+
AccountPublicKeysMap::from_iter(vec![pk1.clone(), pk3]);
1334+
let signatures = tx.compute_section_signature(
1335+
&[sk1.clone(), sk3],
1336+
&pks_map_wrong,
1337+
None,
1338+
);
13331339
assert_eq!(signatures.len(), 2);
13341340
tx.add_signatures(signatures);
13351341

@@ -1345,6 +1351,151 @@ mod test {
13451351
Err(VerifySigError::InvalidSectionSignature(_))
13461352
);
13471353
}
1354+
1355+
// Sign the tx with one key but duplicate the signature to try
1356+
// maliciously making it through the threshold check
1357+
{
1358+
let mut tx = tx.clone();
1359+
let pks_map_wrong =
1360+
AccountPublicKeysMap::from_iter(vec![pk1.clone()]);
1361+
let signatures = tx.compute_section_signature(
1362+
&[sk1.clone()],
1363+
&pks_map_wrong,
1364+
None,
1365+
);
1366+
assert_eq!(signatures.len(), 1);
1367+
let sig = signatures.first().unwrap().to_owned();
1368+
1369+
// Attach the duplicated signatures with the provided function
1370+
let signatures = vec![sig.clone(), sig.clone()];
1371+
tx.add_signatures(signatures);
1372+
1373+
// Should be rejected
1374+
assert_matches!(
1375+
tx.verify_signatures(
1376+
&HashSet::from_iter([tx.header_hash()]),
1377+
pks_map.clone(),
1378+
&None,
1379+
threshold,
1380+
|| Ok(()),
1381+
),
1382+
Err(VerifySigError::InvalidSectionSignature(_))
1383+
);
1384+
}
1385+
1386+
// Sign the tx with one key but duplicate the signature to try
1387+
// maliciously making it through the threshold check. This time avoid
1388+
// using the provided constructor and attach the signatures manually
1389+
{
1390+
let mut tx = tx.clone();
1391+
let pks_map_wrong =
1392+
AccountPublicKeysMap::from_iter(vec![pk1.clone()]);
1393+
let signatures = tx.compute_section_signature(
1394+
&[sk1.clone()],
1395+
&pks_map_wrong,
1396+
None,
1397+
);
1398+
assert_eq!(signatures.len(), 1);
1399+
let sig = signatures.first().unwrap().to_owned();
1400+
1401+
let auth = Authorization {
1402+
targets: vec![tx.header_hash()],
1403+
signatures: [(0, sig.signature)].into(),
1404+
signer: Signer::PubKeys(vec![pk1.clone()]),
1405+
};
1406+
tx.add_section(Section::Authorization(auth.clone()));
1407+
tx.add_section(Section::Authorization(auth));
1408+
1409+
// Should be rejected
1410+
assert_matches!(
1411+
tx.verify_signatures(
1412+
&HashSet::from_iter([tx.header_hash()]),
1413+
pks_map.clone(),
1414+
&None,
1415+
threshold,
1416+
|| Ok(()),
1417+
),
1418+
Err(VerifySigError::InvalidSectionSignature(_))
1419+
);
1420+
}
1421+
1422+
// Sign the tx with one key but duplicate the signature to try
1423+
// maliciously making it through the threshold check. This time avoid
1424+
// using the provided constructor and attach the signatures manually,
1425+
// also disguise the duplicated signature to avoid the protocol check on
1426+
// duplicated sections
1427+
{
1428+
let mut tx = tx.clone();
1429+
let pks_map_wrong =
1430+
AccountPublicKeysMap::from_iter(vec![pk1.clone()]);
1431+
let signatures = tx.compute_section_signature(
1432+
&[sk1.clone()],
1433+
&pks_map_wrong,
1434+
None,
1435+
);
1436+
assert_eq!(signatures.len(), 1);
1437+
let sig = signatures.first().unwrap().to_owned();
1438+
1439+
let auth = Authorization {
1440+
targets: vec![tx.header_hash()],
1441+
signatures: [(0, sig.signature)].into(),
1442+
signer: Signer::PubKeys(vec![pk1.clone()]),
1443+
};
1444+
let mut auth2 = auth.clone();
1445+
auth2.signer = Signer::Address(est_address.clone());
1446+
tx.add_section(Section::Authorization(auth));
1447+
tx.add_section(Section::Authorization(auth2));
1448+
1449+
// Should be rejected
1450+
assert_matches!(
1451+
tx.verify_signatures(
1452+
&HashSet::from_iter([tx.header_hash()]),
1453+
pks_map.clone(),
1454+
&None,
1455+
threshold,
1456+
|| Ok(()),
1457+
),
1458+
Err(VerifySigError::InvalidSectionSignature(_))
1459+
);
1460+
}
1461+
1462+
// Sign the tx with one key but duplicate the signature to try
1463+
// maliciously making it through the threshold check. This time avoid
1464+
// using the provided constructor and attach the signatures manually,
1465+
// also disguise the duplicated signature to avoid the protocol check on
1466+
// duplicated sections and change the signature index
1467+
{
1468+
let mut tx = tx.clone();
1469+
let pks_map_wrong =
1470+
AccountPublicKeysMap::from_iter(vec![pk1.clone()]);
1471+
let signatures =
1472+
tx.compute_section_signature(&[sk1], &pks_map_wrong, None);
1473+
assert_eq!(signatures.len(), 1);
1474+
let sig = signatures.first().unwrap().to_owned();
1475+
1476+
let auth = Authorization {
1477+
targets: vec![tx.header_hash()],
1478+
signatures: [(0, sig.signature.clone())].into(),
1479+
signer: Signer::PubKeys(vec![pk1]),
1480+
};
1481+
let mut auth2 = auth.clone();
1482+
auth2.signer = Signer::Address(est_address);
1483+
auth2.signatures = [(1, sig.signature)].into();
1484+
tx.add_section(Section::Authorization(auth));
1485+
tx.add_section(Section::Authorization(auth2));
1486+
1487+
// Should be rejected
1488+
assert_matches!(
1489+
tx.verify_signatures(
1490+
&HashSet::from_iter([tx.header_hash()]),
1491+
pks_map.clone(),
1492+
&None,
1493+
threshold,
1494+
|| Ok(()),
1495+
),
1496+
Err(VerifySigError::InvalidSectionSignature(_))
1497+
);
1498+
}
13481499
}
13491500

13501501
#[test]

0 commit comments

Comments
 (0)