use crate::bls12_381::{decode_g1, CryptoError};
use ark_serialize::CanonicalSerialize;
use sha2::{Digest, Sha256};
use sp_std::vec::Vec;
use ark_bls12_381::G1Affine;
use ark_ec::{
bls12::Bls12Config,
hashing::{curve_maps::wb::WBMap, map_to_curve_hasher::MapToCurveBasedHasher, HashToCurve},
pairing::Pairing,
};
use ark_ff::field_hashers::DefaultFieldHasher;
pub const QUICKNET_CTX: &[u8] = b"BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_";
type E = ark_bls12_381::Bls12_381;
type Config = ark_bls12_381::Config;
fn message(current_round: u64, prev_sig: &[u8]) -> Vec<u8> {
let mut hasher = Sha256::default();
hasher.update(prev_sig);
hasher.update(current_round.to_be_bytes());
hasher.finalize().to_vec()
}
pub fn compute_round_on_g1(round: u64) -> Result<G1Affine, CryptoError> {
let message = message(round, &[]);
let hasher = MapToCurveBasedHasher::<
<E as Pairing>::G1,
DefaultFieldHasher<Sha256, 128>,
WBMap<<Config as Bls12Config>::G1Config>,
>::new(QUICKNET_CTX)
.map_err(|_| CryptoError::HashToCurveFailure)?;
let message_hash = hasher.hash(&message).map_err(|_| CryptoError::InvalidBuffer)?;
let mut bytes = Vec::new();
message_hash
.serialize_compressed(&mut bytes)
.map_err(|_| CryptoError::DeserializeG1Failure)?;
decode_g1(&bytes)
}
#[cfg(test)]
pub mod tests {
use super::*;
use ark_ec::AffineRepr;
#[test]
fn test_message_deterministic() {
let round: u64 = 42;
let prev_sig = b"previous_signature";
let msg1 = message(round, prev_sig);
let msg2 = message(round, prev_sig);
assert_eq!(msg1, msg2, "Message function should be deterministic for the same inputs");
assert_eq!(msg1.len(), 32, "SHA256 digest must be 32 bytes long");
}
#[test]
fn test_message_different_rounds() {
let prev_sig = b"prev";
let msg1 = message(1, prev_sig);
let msg2 = message(2, prev_sig);
assert_ne!(msg1, msg2, "Different rounds should produce different messages");
}
#[test]
fn test_compute_round_on_g1() {
let round = 1;
let result = compute_round_on_g1(round);
assert!(result.is_ok(), "compute_round_on_g1 should succeed for a valid round");
let point = result.unwrap();
assert!(!point.is_zero(), "The computed round point should not be the identity element");
}
}