rename mod_r_p() -> fp_mod_fv(), and mod_p_r_unsafe() -> fv_mod_fp_unsafe()

This commit is contained in:
zero
2024-01-23 16:34:20 +01:00
parent bb3729db92
commit 7ada52b28b
16 changed files with 48 additions and 44 deletions

View File

@@ -36,7 +36,7 @@ DarkFi uses the elliptic curves Pallas and Vesta that form a 2-cycle.
We denote Pallas by $ₚ$ and Vesta by $ᵥ$. Set the following values:
$$ p = 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001 $$
$$ q = 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 $$
$$ v = 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 $$
We now construct the base field for each curve $Kₚ$ and $Kᵥ$ as
$Kₚ = 𝔽ₚ$ and $Kᵥ = 𝔽_q$.

View File

@@ -151,7 +151,7 @@ impl Circuit<pallas::Base> for EcipCircuit {
assign_free_advice(layouter.namespace(|| "Witness s1"), config.advices[0], self.s1)?;
let s1 =
ScalarVar::from_base(config.ecc_chip(), layouter.namespace(|| "mod_r_p(s1)"), &s1)?;
ScalarVar::from_base(config.ecc_chip(), layouter.namespace(|| "fp_mod_fv(s1)"), &s1)?;
let (r, _) = g1.mul(layouter.namespace(|| "g1 * s1"), s1)?;
@@ -168,7 +168,7 @@ impl Circuit<pallas::Base> for EcipCircuit {
#[cfg(test)]
mod tests {
use super::*;
use darkfi_sdk::crypto::{pasta_prelude::Group, util::mod_r_p};
use darkfi_sdk::crypto::{pasta_prelude::Group, util::fp_mod_fv};
use halo2_proofs::{
arithmetic::{CurveAffine, Field},
dev::MockProver,
@@ -184,7 +184,7 @@ mod tests {
let circuit = EcipCircuit { g1: Value::known(g1), s1: Value::known(s1) };
let g1s1 = g1 * mod_r_p(s1);
let g1s1 = g1 * fp_mod_fv(s1);
let g1s1_coords = g1s1.to_affine().coordinates().unwrap();
let public_inputs = vec![*g1s1_coords.x(), *g1s1_coords.y()];

View File

@@ -20,7 +20,7 @@ use darkfi_sdk::{
crypto::{
pedersen::{pedersen_commitment_base, pedersen_commitment_u64},
poseidon_hash,
util::mod_r_p,
util::fp_mod_fv,
MerkleNode, MerkleTree, SecretKey,
},
pasta::{arithmetic::CurveAffine, group::Curve, pallas},
@@ -484,7 +484,7 @@ impl LeadCoinSecrets {
let secret = if i == 0 {
pedersen_commitment_u64(1, pallas::Scalar::random(&mut OsRng))
} else {
pedersen_commitment_u64(1, mod_r_p(prev_sk.inner()))
pedersen_commitment_u64(1, fp_mod_fv(prev_sk.inner()))
};
let secret_coords = secret.to_affine().coordinates().unwrap();

View File

@@ -22,7 +22,7 @@ use darkfi_sdk::{
bridgetree::Hashable,
crypto::{
note::ElGamalEncryptedNote, pasta_prelude::*, pedersen_commitment_u64, poseidon_hash,
util::mod_p_r_unsafe, Keypair, MerkleNode, Nullifier, PublicKey, SecretKey,
util::fv_mod_fp_unsafe, Keypair, MerkleNode, Nullifier, PublicKey, SecretKey,
},
pasta::pallas,
};
@@ -85,7 +85,7 @@ impl DaoVoteCall {
// It's near zero chance it ever loops at all.
// P(random 𝔽ᵥ ∉ 𝔽ₚ) = (q - p)/q = 2.99 × 10⁻⁵¹
loop {
let av_blind = mod_p_r_unsafe(all_vote_blind + value_blind);
let av_blind = fv_mod_fp_unsafe(all_vote_blind + value_blind);
if av_blind.is_none().into() {
value_blind = pallas::Scalar::random(&mut OsRng);
@@ -193,7 +193,7 @@ impl DaoVoteCall {
// Create a random blind b ∈ 𝔽ᵥ, such that b ∈ 𝔽ₚ
let yes_vote_blind = loop {
let blind = pallas::Scalar::random(&mut OsRng);
if mod_p_r_unsafe(blind).is_some().into() {
if fv_mod_fp_unsafe(blind).is_some().into() {
break blind
}
};
@@ -206,8 +206,8 @@ impl DaoVoteCall {
// Convert blinds to 𝔽ₚ, which should work fine since we selected them
// to be convertable.
let yes_vote_blind = mod_p_r_unsafe(yes_vote_blind).unwrap();
let all_vote_blind = mod_p_r_unsafe(all_vote_blind).unwrap();
let yes_vote_blind = fv_mod_fp_unsafe(yes_vote_blind).unwrap();
let all_vote_blind = fv_mod_fp_unsafe(all_vote_blind).unwrap();
let vote_option = pallas::Base::from(vote_option);
let all_vote_value_fp = pallas::Base::from(all_vote_value);

View File

@@ -24,7 +24,7 @@ use darkfi_sdk::{
crypto::{
pasta_prelude::*,
pedersen_commitment_u64,
util::{fp_to_u64, mod_r_p},
util::{fp_mod_fv, fp_to_u64},
DAO_CONTRACT_ID, DARK_TOKEN_ID,
},
pasta::pallas,
@@ -283,9 +283,9 @@ fn integration_test() -> Result<()> {
// all_vote_blind,
// ]
let vote_option = fp_to_u64(note[0]).unwrap();
let yes_vote_blind = mod_r_p(note[1]);
let yes_vote_blind = fp_mod_fv(note[1]);
let all_vote_value = fp_to_u64(note[2]).unwrap();
let all_vote_blind = mod_r_p(note[3]);
let all_vote_blind = fp_mod_fv(note[3]);
assert!(vote_option == 0 || vote_option == 1);
total_yes_vote_blind += yes_vote_blind;

View File

@@ -291,8 +291,8 @@ pub fn nullifier_k() -> EpAffine {
#[pyfunction]
/// Convert Fp to Fq safely.
pub fn mod_r_p(x: &PyCell<Fp>) -> PyResult<Fq> {
Ok(Fq(util::mod_r_p(x.borrow().deref().0)))
pub fn fp_mod_fv(x: &PyCell<Fp>) -> PyResult<Fq> {
Ok(Fq(util::fp_mod_fv(x.borrow().deref().0)))
}
pub fn create_module(py: pyo3::Python<'_>) -> PyResult<&PyModule> {
@@ -306,7 +306,7 @@ pub fn create_module(py: pyo3::Python<'_>) -> PyResult<&PyModule> {
submod.add_class::<EqAffine>()?;
submod.add_function(wrap_pyfunction!(nullifier_k, submod)?)?;
submod.add_function(wrap_pyfunction!(mod_r_p, submod)?)?;
submod.add_function(wrap_pyfunction!(fp_mod_fv, submod)?)?;
Ok(submod)
}

View File

@@ -19,14 +19,14 @@
use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams};
use pasta_curves::group::{GroupEncoding, Wnaf};
use super::{util::mod_r_p, PublicKey, SecretKey};
use super::{util::fp_mod_fv, PublicKey, SecretKey};
pub const KDF_SAPLING_PERSONALIZATION: &[u8; 16] = b"DarkFiSaplingKDF";
/// Sapling key agreement for note encryption.
/// Implements section 5.4.4.3 of the Zcash Protocol Specification
pub fn sapling_ka_agree(esk: &SecretKey, pk_d: &PublicKey) -> PublicKey {
let esk_s = mod_r_p(esk.inner());
let esk_s = fp_mod_fv(esk.inner());
// Windowed multiplication is constant time. Hence that is used here vs naive EC mult.
// Decrypting notes is a an amortized operation, so you want successful rare-case note
// decryptions to be indistinguishable from the usual case.

View File

@@ -33,7 +33,7 @@ use pasta_curves::{
};
use rand_core::{CryptoRng, RngCore};
use super::{constants::NullifierK, util::mod_r_p, PublicKey, SecretKey};
use super::{constants::NullifierK, util::fp_mod_fv, PublicKey, SecretKey};
/// Prefix domain used for `hash_to_curve` calls
const VRF_DOMAIN: &str = "DarkFi_ECVRF";
@@ -57,7 +57,7 @@ impl VrfProof {
message.extend_from_slice(alpha_string);
let H = pallas::Point::hash_to_curve(VRF_DOMAIN)(&message);
let gamma = H * mod_r_p(x.inner());
let gamma = H * fp_mod_fv(x.inner());
let k = pallas::Scalar::random(rng);
let mut hasher = blake3::Hasher::new();
@@ -73,7 +73,7 @@ impl VrfProof {
c_scalar[..blake3::OUT_LEN].copy_from_slice(c.as_bytes());
let c_scalar = pallas::Scalar::from_uniform_bytes(&c_scalar);
let s = k + c_scalar * mod_r_p(x.inner());
let s = k + c_scalar * fp_mod_fv(x.inner());
Self { gamma, c, s }
}

View File

@@ -32,7 +32,7 @@ use pasta_curves::{
};
use rand_core::{CryptoRng, RngCore};
use super::{constants::NullifierK, util::mod_r_p};
use super::{constants::NullifierK, util::fp_mod_fv};
use crate::error::ContractError;
/// Keypair structure holding a `SecretKey` and its respective `PublicKey`
@@ -129,7 +129,7 @@ impl PublicKey {
/// Derive a new `PublicKey` object given a `SecretKey`
pub fn from_secret(s: SecretKey) -> Self {
let p = NullifierK.generator() * mod_r_p(s.inner());
let p = NullifierK.generator() * fp_mod_fv(s.inner());
Self(p)
}

View File

@@ -24,7 +24,7 @@ use rand_core::{CryptoRng, RngCore};
#[cfg(feature = "async")]
use darkfi_serial::async_trait;
use super::{diffie_hellman, poseidon_hash, util::mod_r_p, PublicKey, SecretKey};
use super::{diffie_hellman, poseidon_hash, util::fp_mod_fv, PublicKey, SecretKey};
use crate::error::ContractError;
/// AEAD tag length in bytes
@@ -96,7 +96,7 @@ impl<const N: usize> ElGamalEncryptedNote<N> {
) -> Self {
// Derive shared secret using DH
let ephem_public = PublicKey::from_secret(*ephem_secret);
let (ss_x, ss_y) = PublicKey::from(public.inner() * mod_r_p(ephem_secret.inner())).xy();
let (ss_x, ss_y) = PublicKey::from(public.inner() * fp_mod_fv(ephem_secret.inner())).xy();
let shared_secret = poseidon_hash([ss_x, ss_y]);
let mut blinds = [pallas::Base::ZERO; N];
@@ -115,7 +115,7 @@ impl<const N: usize> ElGamalEncryptedNote<N> {
pub fn decrypt(&self, secret: &SecretKey) -> [pallas::Base; N] {
// Derive shared secret using DH
let (ss_x, ss_y) =
PublicKey::from(self.ephem_public.inner() * mod_r_p(secret.inner())).xy();
PublicKey::from(self.ephem_public.inner() * fp_mod_fv(secret.inner())).xy();
let shared_secret = poseidon_hash([ss_x, ss_y]);
let mut blinds = [pallas::Base::ZERO; N];

View File

@@ -26,7 +26,7 @@ use super::{
},
NullifierK,
},
util::mod_r_p,
util::fp_mod_fv,
};
/// Pedersen commitment for a full-width base field element.
@@ -36,7 +36,7 @@ pub fn pedersen_commitment_base(value: pallas::Base, blind: pallas::Scalar) -> p
let V = NullifierK.generator();
let R = hasher(&VALUE_COMMITMENT_R_BYTES);
V * mod_r_p(value) + R * blind
V * fp_mod_fv(value) + R * blind
}
/// Pedersen commitment for a 64-bit value, in the base field.
@@ -46,5 +46,5 @@ pub fn pedersen_commitment_u64(value: u64, blind: pallas::Scalar) -> pallas::Poi
let V = hasher(&VALUE_COMMITMENT_V_BYTES);
let R = hasher(&VALUE_COMMITMENT_R_BYTES);
V * mod_r_p(pallas::Base::from(value)) + R * blind
V * fp_mod_fv(pallas::Base::from(value)) + R * blind
}

View File

@@ -28,7 +28,7 @@ use rand_core::{CryptoRng, RngCore};
use super::{
constants::{NullifierK, DRK_SCHNORR_DOMAIN},
util::{hash_to_scalar, mod_r_p},
util::{fp_mod_fv, hash_to_scalar},
PublicKey, SecretKey,
};
@@ -65,7 +65,7 @@ impl SchnorrSecret for SecretKey {
let commit = NullifierK.generator() * mask;
let challenge = hash_to_scalar(DRK_SCHNORR_DOMAIN, &commit.to_bytes(), message);
let response = mask + challenge * mod_r_p(self.inner());
let response = mask + challenge * fp_mod_fv(self.inner());
Signature { commit, response }
}

View File

@@ -39,16 +39,16 @@ pub fn hash_to_scalar(persona: &[u8], a: &[u8], b: &[u8]) -> pallas::Scalar {
///
/// This requires no modular reduction because Pallas' base field is smaller than its
/// scalar field.
pub fn mod_r_p(x: pallas::Base) -> pallas::Scalar {
pallas::Scalar::from_repr(x.to_repr()).unwrap()
pub fn fp_mod_fv(val: pallas::Base) -> pallas::Scalar {
pallas::Scalar::from_repr(val.to_repr()).unwrap()
}
/// Converts from pallas::Scalar to pallas::Base (aka $x \pmod{r_\mathbb{P}}$).
///
/// This call is unsafe and liable to fail. Use with caution.
/// The Pallas scalar field is bigger than the field we're converting to here.
pub fn mod_p_r_unsafe(x: pallas::Scalar) -> CtOption<pallas::Base> {
pallas::Base::from_repr(x.to_repr())
pub fn fv_mod_fp_unsafe(val: pallas::Scalar) -> CtOption<pallas::Base> {
pallas::Base::from_repr(val.to_repr())
}
/// Wrapper around poseidon in `halo2_gadgets`
@@ -62,18 +62,20 @@ pub fn poseidon_hash<const N: usize>(messages: [pallas::Base; N]) -> pallas::Bas
.hash(messages)
}
pub fn fp_to_u64(v: pallas::Base) -> Option<u64> {
let repr = v.to_repr();
pub fn fp_to_u64(value: pallas::Base) -> Option<u64> {
let repr = value.to_repr();
if !repr[8..].iter().all(|&b| b == 0u8) {
return None
}
let mut cur = Cursor::new(&repr[0..8]);
let val = ReadExt::read_u64(&mut cur).ok()?;
Some(val)
let uint = ReadExt::read_u64(&mut cur).ok()?;
Some(uint)
}
#[test]
fn test_fp_to_u64() {
use super::pasta_prelude::Field;
let fp = pallas::Base::from(u64::MAX);
assert_eq!(fp_to_u64(fp), Some(u64::MAX));
assert_eq!(fp_to_u64(fp + pallas::Base::ONE), None);

View File

@@ -18,7 +18,8 @@
use std::io::Cursor;
use darkfi_sdk::crypto::{
pedersen::pedersen_commitment_u64, util::mod_r_p, MerkleNode, MerkleTree, PublicKey, SecretKey,
pedersen::pedersen_commitment_u64, util::fp_mod_fv, MerkleNode, MerkleTree, PublicKey,
SecretKey,
};
use halo2_gadgets::poseidon::{
primitives as poseidon,
@@ -116,7 +117,7 @@ fn halo2_vk_ser() -> Result<()> {
let ephem_secret = SecretKey::random(&mut OsRng);
let pubkey = PublicKey::from_secret(ephem_secret).inner();
let (ephem_x, ephem_y) = PublicKey::from(pubkey * mod_r_p(ephem_secret.inner())).xy();
let (ephem_x, ephem_y) = PublicKey::from(pubkey * fp_mod_fv(ephem_secret.inner())).xy();
let prover_witnesses = vec![
Witness::Base(Value::known(pallas::Base::from(value))),
Witness::Scalar(Value::known(value_blind)),

View File

@@ -17,7 +17,8 @@
*/
use darkfi_sdk::crypto::{
pedersen::pedersen_commitment_u64, util::mod_r_p, MerkleNode, MerkleTree, PublicKey, SecretKey,
pedersen::pedersen_commitment_u64, util::fp_mod_fv, MerkleNode, MerkleTree, PublicKey,
SecretKey,
};
use halo2_gadgets::poseidon::{
primitives as poseidon,
@@ -78,7 +79,7 @@ fn zkvm_opcodes() -> Result<()> {
let ephem_secret = SecretKey::random(&mut OsRng);
let pubkey = PublicKey::from_secret(ephem_secret).inner();
let (ephem_x, ephem_y) = PublicKey::from(pubkey * mod_r_p(ephem_secret.inner())).xy();
let (ephem_x, ephem_y) = PublicKey::from(pubkey * fp_mod_fv(ephem_secret.inner())).xy();
let prover_witnesses = vec![
Witness::Base(Value::known(pallas::Base::from(value))),