2023-12-14 15:39:16 +00:00
|
|
|
//! Version 1 ring signature verification.
|
|
|
|
//!
|
|
|
|
//! Some checks have to be done at deserialization or with data we don't have so we can't do them here, those checks are:
|
2024-02-10 00:08:39 +00:00
|
|
|
//! <https://monero-book.cuprate.org/consensus_rules/transactions/ring_signatures.html#signatures-must-be-canonical>
|
2023-12-14 15:39:16 +00:00
|
|
|
//! this happens at deserialization in monero-serai.
|
2024-02-10 00:08:39 +00:00
|
|
|
//! <https://monero-book.cuprate.org/consensus_rules/transactions/ring_signatures.html#amount-of-signatures-in-a-ring>
|
2023-12-14 15:39:16 +00:00
|
|
|
//! and this happens during ring signature verification in monero-serai.
|
|
|
|
//!
|
|
|
|
use monero_serai::{ring_signatures::RingSignature, transaction::Input};
|
|
|
|
|
|
|
|
#[cfg(feature = "rayon")]
|
|
|
|
use rayon::prelude::*;
|
|
|
|
|
2023-12-27 23:50:18 +00:00
|
|
|
use super::{Rings, TransactionError};
|
2023-12-16 23:03:02 +00:00
|
|
|
use crate::try_par_iter;
|
2023-12-14 15:39:16 +00:00
|
|
|
|
|
|
|
/// Verifies the ring signature.
|
|
|
|
///
|
2024-02-10 00:08:39 +00:00
|
|
|
/// ref: <https://monero-book.cuprate.org/consensus_rules/transactions/ring_signatures.html>
|
2024-09-21 00:32:03 +00:00
|
|
|
pub(crate) fn check_input_signatures(
|
2023-12-14 15:39:16 +00:00
|
|
|
inputs: &[Input],
|
|
|
|
signatures: &[RingSignature],
|
|
|
|
rings: &Rings,
|
|
|
|
tx_sig_hash: &[u8; 32],
|
2023-12-27 23:50:18 +00:00
|
|
|
) -> Result<(), TransactionError> {
|
2023-12-14 15:39:16 +00:00
|
|
|
match rings {
|
|
|
|
Rings::Legacy(rings) => {
|
2024-02-10 00:08:39 +00:00
|
|
|
// <https://monero-book.cuprate.org/consensus_rules/transactions/ring_signatures.html#amount-of-ring-signatures>
|
2023-12-14 15:39:16 +00:00
|
|
|
// rings.len() != inputs.len() can't happen but check any way.
|
|
|
|
if signatures.len() != inputs.len() || rings.len() != inputs.len() {
|
2023-12-27 23:50:18 +00:00
|
|
|
return Err(TransactionError::RingSignatureIncorrect);
|
2023-12-14 15:39:16 +00:00
|
|
|
}
|
|
|
|
|
2023-12-16 23:03:02 +00:00
|
|
|
try_par_iter(inputs)
|
2023-12-14 15:39:16 +00:00
|
|
|
.zip(rings)
|
|
|
|
.zip(signatures)
|
|
|
|
.try_for_each(|((input, ring), sig)| {
|
|
|
|
let Input::ToKey { key_image, .. } = input else {
|
|
|
|
panic!("How did we build a ring with no decoys?");
|
|
|
|
};
|
|
|
|
|
|
|
|
if !sig.verify(tx_sig_hash, ring, key_image) {
|
2023-12-27 23:50:18 +00:00
|
|
|
return Err(TransactionError::RingSignatureIncorrect);
|
2023-12-14 15:39:16 +00:00
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
})?;
|
|
|
|
}
|
2024-09-21 00:32:03 +00:00
|
|
|
Rings::RingCT(_) => panic!("tried to verify v1 tx with a non v1 ring"),
|
2023-12-14 15:39:16 +00:00
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|