diff --git a/Cargo.toml b/Cargo.toml index 4420b7e..869df29 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "milagro-bls-binding" -version = "1.6.3" +version = "1.7.0" edition = "2018" authors = ["chihchengliang@gmail.com"] @@ -23,4 +23,5 @@ crate-type = ["cdylib"] [dependencies] pyo3 = { version = "0.13.0", features = ["extension-module"] } -milagro_bls = {git = "https://github.com/sigp/milagro_bls", tag= "v1.4.1" } +milagro_bls = {git = "https://github.com/sigp/milagro_bls", tag= "v1.4.2" } +rand = { version = "0.7.2", default-features = false } diff --git a/src/lib.rs b/src/lib.rs index d9d61c4..559ccb8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -150,6 +150,32 @@ fn AggregateVerify(_py: Python, PKs: &PyList, messages: &PyList, signature: &PyB agg_sig.aggregate_verify(&msgs_refs, &pks_ref) } +#[pyfunction] +fn VerifyMultipleAggregateSignatures(_py: Python, SignatureSets: &PyList) -> bool { + let mut signature_sets: Vec<(AggregateSignature, AggregatePublicKey, Vec)> = Vec::new(); + for set in SignatureSets { + let tuple: Vec> = match set.extract() { + Ok(_tuple) => _tuple, + Err(_) => return false, + }; + let aggsig = match AggregateSignature::from_bytes(&tuple[0]) { + Ok(_aggsig) => _aggsig, + Err(_) => return false, + }; + let aggkey = match PublicKey::from_bytes(&tuple[1]) { + Ok(_pubkey) => AggregatePublicKey::from_public_key(&_pubkey), + Err(_) => return false, + }; + signature_sets.push((aggsig, aggkey, tuple[2].clone())); + } + + let mut rng = &mut rand::thread_rng(); + AggregateSignature::verify_multiple_aggregate_signatures( + &mut rng, + signature_sets.iter().map(|x| (&x.0, &x.1, x.2.as_slice())), + ) +} + /// This module is a python module implemented in Rust. #[pymodule] fn milagro_bls_binding(_py: Python, m: &PyModule) -> PyResult<()> { @@ -161,5 +187,6 @@ fn milagro_bls_binding(_py: Python, m: &PyModule) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(_AggregatePKs))?; m.add_wrapped(wrap_pyfunction!(FastAggregateVerify))?; m.add_wrapped(wrap_pyfunction!(AggregateVerify))?; + m.add_wrapped(wrap_pyfunction!(VerifyMultipleAggregateSignatures))?; Ok(()) } diff --git a/test.py b/test.py index 44cd44c..70d1a9f 100644 --- a/test.py +++ b/test.py @@ -84,6 +84,24 @@ def test_fast_aggregate_verify(SKs, message): aggregate_signature = bls.Aggregate(signatures) assert bls.FastAggregateVerify(PKs, message, aggregate_signature) +@pytest.mark.parametrize( + 'SKs,messages', + [ + (bytes_range(range(1, 5)), bytes_range(range(55, 66))), + ] +) +def test_verify_multiple_aggregate_signatures(SKs, messages): + signature_set = [ + ( + bls.Aggregate( [bls.Sign(sk, msg) for sk in SKs]), + bls._AggregatePKs([bls.SkToPk(sk) for sk in SKs]), + msg + ) + for msg in messages + ] + assert bls.VerifyMultipleAggregateSignatures(signature_set) + bad_signature_set = [(aggsig, aggkey, msg + b'\xbadd') for aggsig, aggkey, msg in signature_set] + assert not bls.VerifyMultipleAggregateSignatures(bad_signature_set) def test_weird_cases(): Z1_PUBKEY = b'\xc0' + b'\x00' * 47