Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Added more tests for low coverage parts of the code [#861]
- Added MSRV, set to rust version `1.85` [#860]

### Changed
Expand Down Expand Up @@ -625,6 +626,7 @@ is necessary since `rkyv/validation` was required as a bound.
- Proof system module.

<!-- ISSUES -->
[#862]: https://github.com/dusk-network/plonk/issues/862
[#861]: https://github.com/dusk-network/plonk/issues/861
[#860]: https://github.com/dusk-network/plonk/issues/860
[#859]: https://github.com/dusk-network/plonk/issues/859
Expand Down
19 changes: 19 additions & 0 deletions src/commitment_scheme/kzg10/commitment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,23 @@ mod commitment_tests {
.expect("Error on the deserialization");
assert_eq!(commitment, obtained_comm);
}

#[test]
fn commitment_default_is_identity() {
let c = Commitment::default();
assert_eq!(c, Commitment(G1Affine::identity()));

let bytes = c.to_bytes();
let obtained = Commitment::from_slice(&bytes)
.expect("identity commitment should deserialize");
assert_eq!(c, obtained);
}

#[test]
fn commitment_from_projective_matches_affine() {
let projective = G1Projective::generator();
let from_proj: Commitment = projective.into();
let from_aff: Commitment = G1Affine::generator().into();
assert_eq!(from_proj, from_aff);
}
}
47 changes: 47 additions & 0 deletions src/commitment_scheme/kzg10/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,50 @@ pub(crate) mod alloc {
}
}
}

#[cfg(all(test, feature = "alloc"))]
mod tests {
use super::*;
use dusk_bls12_381::{G1Affine, G1Projective};

#[test]
fn aggregate_proof_flatten_is_linear_combination() {
// Build an aggregate proof with 3 parts.
let witness_commitment: Commitment = G1Affine::generator().into();
let mut agg = alloc::AggregateProof::with_witness(witness_commitment);

let c0: Commitment =
(G1Projective::generator() * BlsScalar::from(2u64)).into();
let c1: Commitment =
(G1Projective::generator() * BlsScalar::from(3u64)).into();
let c2: Commitment =
(G1Projective::generator() * BlsScalar::from(5u64)).into();

let e0 = BlsScalar::from(11u64);
let e1 = BlsScalar::from(13u64);
let e2 = BlsScalar::from(17u64);

agg.add_part((e0, c0));
agg.add_part((e1, c1));
agg.add_part((e2, c2));

let v = BlsScalar::from(7u64);

let proof = agg.flatten(&v);

// commitment_to_witness is left unchanged.
assert_eq!(proof.commitment_to_witness, witness_commitment);

let powers = crate::util::powers_of(&v, 2);
assert_eq!(powers.len(), 3);

let expected_eval = e0 * powers[0] + e1 * powers[1] + e2 * powers[2];
assert_eq!(proof.evaluated_point, expected_eval);

let expected_commitment_proj: G1Projective =
c0.0 * &powers[0] + c1.0 * &powers[1] + c2.0 * &powers[2];
let expected_commitment: Commitment = expected_commitment_proj.into();

assert_eq!(proof.commitment_to_polynomial, expected_commitment);
}
}
35 changes: 35 additions & 0 deletions src/composer/constraint_system/witness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,38 @@ impl Witness {

#[cfg(feature = "zeroize")]
impl zeroize::DefaultIsZeroes for Witness {}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn witness_constants_and_default_are_consistent() {
assert_eq!(Witness::ZERO.index(), 0);
assert_eq!(Witness::ONE.index(), 1);

// `Default` is implemented as `Witness::ZERO`.
assert_eq!(Witness::default(), Witness::ZERO);
}

#[test]
fn wire_data_variants_are_distinct_and_debuggable() {
let a = WireData::Left(0);
let b = WireData::Right(0);
let c = WireData::Output(0);
let d = WireData::Fourth(0);

assert_ne!(a, b);
assert_ne!(b, c);
assert_ne!(c, d);

// Debug fmt should not panic.
let _ = format!("{a:?}{b:?}{c:?}{d:?}");

// Pattern match to make sure we can extract indices.
match a {
WireData::Left(i) => assert_eq!(i, 0),
_ => panic!("expected Left"),
}
}
}
65 changes: 65 additions & 0 deletions src/composer/gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,68 @@ pub struct Gate {
/// Fourth wire witness.
pub(crate) d: Witness,
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn gate_is_copy_clone_and_eq() {
let gate = Gate {
q_m: BlsScalar::from(1u64),
q_l: BlsScalar::from(2u64),
q_r: BlsScalar::from(3u64),
q_o: BlsScalar::from(4u64),
q_f: BlsScalar::from(5u64),
q_c: BlsScalar::from(6u64),
q_arith: BlsScalar::one(),
q_range: BlsScalar::zero(),
q_logic: BlsScalar::zero(),
q_fixed_group_add: BlsScalar::zero(),
q_variable_group_add: BlsScalar::zero(),
a: Witness::ZERO,
b: Witness::ONE,
c: Witness::new(2),
d: Witness::new(3),
};

// Copy
let gate_copy = gate;
assert_eq!(gate, gate_copy);

// Clone
let gate_clone = gate_copy.clone();
assert_eq!(gate_copy, gate_clone);

// Debug fmt should not panic
let _ = format!("{gate_clone:?}");
}

#[test]
fn gate_partial_eq_compares_fields() {
let mut a = Gate {
q_m: BlsScalar::from(1u64),
q_l: BlsScalar::from(2u64),
q_r: BlsScalar::from(3u64),
q_o: BlsScalar::from(4u64),
q_f: BlsScalar::from(5u64),
q_c: BlsScalar::from(6u64),
q_arith: BlsScalar::one(),
q_range: BlsScalar::zero(),
q_logic: BlsScalar::zero(),
q_fixed_group_add: BlsScalar::zero(),
q_variable_group_add: BlsScalar::zero(),
a: Witness::ZERO,
b: Witness::ONE,
c: Witness::new(2),
d: Witness::new(3),
};

let mut b = a;
assert_eq!(a, b);

// Flip one field and ensure inequality.
b.q_c = BlsScalar::from(7u64);
assert_ne!(a, b);
}
}
67 changes: 67 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,3 +188,70 @@ impl From<DuskBytesError> for Error {

#[cfg(feature = "std")]
impl std::error::Error for Error {}

#[cfg(all(test, feature = "std"))]
mod tests {
use super::*;
use dusk_bls12_381::BlsScalar;
use dusk_bytes::{DeserializableSlice, Serializable};

#[test]
fn display_arms_are_exercised() {
let bogus = [0u8; BlsScalar::SIZE - 1];
let dusk_err = BlsScalar::from_slice(&bogus)
.expect_err("decoding from a short slice must fail");
let bytes_error: Error = dusk_err.into();
assert!(matches!(bytes_error, Error::BytesError(_)));

// Format each variant at least once so the `Display` impl gets covered.
let all_errors: [Error; 20] = [
Error::InvalidEvalDomainSize {
log_size_of_group: 32,
adacity: 28,
},
Error::ProofVerificationError,
Error::CircuitInputsNotFound,
Error::UninitializedPIGenerator,
Error::InvalidPublicInputBytes,
Error::CircuitAlreadyPreprocessed,
Error::InvalidCircuitSize(1, 2),
Error::MismatchedPolyLen,
Error::DegreeIsZero,
Error::TruncatedDegreeTooLarge,
Error::TruncatedDegreeIsZero,
Error::PolynomialDegreeTooLarge,
Error::PolynomialDegreeIsZero,
Error::PairingCheckFailure,
Error::NotEnoughBytes,
Error::PointMalformed,
Error::BlsScalarMalformed,
Error::JubJubScalarMalformed,
Error::UnsupportedWNAF2k,
Error::InvalidCompressedCircuit,
];

for e in all_errors {
let s = e.to_string();
assert!(!s.is_empty());
}

// Variants with payloads.
assert!(
Error::PublicInputNotFound { index: 7 }
.to_string()
.contains("index")
);
assert!(
Error::InconsistentPublicInputsLen {
expected: 1,
provided: 2
}
.to_string()
.contains("provided")
);

assert!(!bytes_error.to_string().is_empty());
let _as_std_error: &dyn std::error::Error =
&Error::ProofVerificationError;
}
}
Loading