mirror of https://github.com/zcash/halo2.git
commit
0ccb0101df
18
src/keys.rs
18
src/keys.rs
|
@ -8,6 +8,7 @@ use fpe::ff1::{BinaryNumeralString, FF1};
|
||||||
use group::GroupEncoding;
|
use group::GroupEncoding;
|
||||||
use halo2::arithmetic::FieldExt;
|
use halo2::arithmetic::FieldExt;
|
||||||
use pasta_curves::pallas;
|
use pasta_curves::pallas;
|
||||||
|
use rand::RngCore;
|
||||||
use subtle::CtOption;
|
use subtle::CtOption;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -28,6 +29,23 @@ use crate::{
|
||||||
pub struct SpendingKey([u8; 32]);
|
pub struct SpendingKey([u8; 32]);
|
||||||
|
|
||||||
impl SpendingKey {
|
impl SpendingKey {
|
||||||
|
/// Generates a random spending key.
|
||||||
|
///
|
||||||
|
/// This is only used when generating dummy notes. Real spending keys should be
|
||||||
|
/// derived according to [ZIP 32].
|
||||||
|
///
|
||||||
|
/// [ZIP 32]: https://zips.z.cash/zip-0032
|
||||||
|
pub(crate) fn random(rng: &mut impl RngCore) -> Self {
|
||||||
|
loop {
|
||||||
|
let mut bytes = [0; 32];
|
||||||
|
rng.fill_bytes(&mut bytes);
|
||||||
|
let sk = SpendingKey::from_bytes(bytes);
|
||||||
|
if sk.is_some().into() {
|
||||||
|
break sk.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Constructs an Orchard spending key from uniformly-random bytes.
|
/// Constructs an Orchard spending key from uniformly-random bytes.
|
||||||
///
|
///
|
||||||
/// Returns `None` if the bytes do not correspond to a valid Orchard spending key.
|
/// Returns `None` if the bytes do not correspond to a valid Orchard spending key.
|
||||||
|
|
28
src/note.rs
28
src/note.rs
|
@ -1,8 +1,9 @@
|
||||||
use group::GroupEncoding;
|
use group::GroupEncoding;
|
||||||
use pasta_curves::pallas;
|
use pasta_curves::pallas;
|
||||||
|
use rand::RngCore;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
keys::FullViewingKey,
|
keys::{FullViewingKey, SpendingKey},
|
||||||
spec::{prf_expand, to_base, to_scalar},
|
spec::{prf_expand, to_base, to_scalar},
|
||||||
value::NoteValue,
|
value::NoteValue,
|
||||||
Address,
|
Address,
|
||||||
|
@ -19,6 +20,12 @@ pub use self::nullifier::Nullifier;
|
||||||
struct RandomSeed([u8; 32]);
|
struct RandomSeed([u8; 32]);
|
||||||
|
|
||||||
impl RandomSeed {
|
impl RandomSeed {
|
||||||
|
pub(crate) fn random(rng: &mut impl RngCore) -> Self {
|
||||||
|
let mut bytes = [0; 32];
|
||||||
|
rng.fill_bytes(&mut bytes);
|
||||||
|
RandomSeed(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
/// Defined in [Zcash Protocol Spec § 4.7.3: Sending Notes (Orchard)][orchardsend].
|
/// Defined in [Zcash Protocol Spec § 4.7.3: Sending Notes (Orchard)][orchardsend].
|
||||||
///
|
///
|
||||||
/// [orchardsend]: https://zips.z.cash/protocol/nu5.pdf#orchardsend
|
/// [orchardsend]: https://zips.z.cash/protocol/nu5.pdf#orchardsend
|
||||||
|
@ -53,6 +60,25 @@ pub struct Note {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Note {
|
impl Note {
|
||||||
|
/// Generates a dummy spent note.
|
||||||
|
///
|
||||||
|
/// Defined in [Zcash Protocol Spec § 4.8.3: Dummy Notes (Orchard)][orcharddummynotes].
|
||||||
|
///
|
||||||
|
/// [orcharddummynotes]: https://zips.z.cash/protocol/nu5.pdf#orcharddummynotes
|
||||||
|
pub(crate) fn dummy(rng: &mut impl RngCore, rho: Option<Nullifier>) -> (FullViewingKey, Self) {
|
||||||
|
let fvk: FullViewingKey = (&SpendingKey::random(rng)).into();
|
||||||
|
let recipient = fvk.default_address();
|
||||||
|
|
||||||
|
let note = Note {
|
||||||
|
recipient,
|
||||||
|
value: NoteValue::zero(),
|
||||||
|
rho: rho.unwrap_or_else(|| Nullifier::dummy(rng)),
|
||||||
|
rseed: RandomSeed::random(rng),
|
||||||
|
};
|
||||||
|
|
||||||
|
(fvk, note)
|
||||||
|
}
|
||||||
|
|
||||||
/// Derives the commitment to this note.
|
/// Derives the commitment to this note.
|
||||||
///
|
///
|
||||||
/// Defined in [Zcash Protocol Spec § 3.2: Notes][notes].
|
/// Defined in [Zcash Protocol Spec § 3.2: Notes][notes].
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
use group::Group;
|
||||||
use halo2::arithmetic::CurveExt;
|
use halo2::arithmetic::CurveExt;
|
||||||
use pasta_curves::pallas;
|
use pasta_curves::pallas;
|
||||||
|
use rand::RngCore;
|
||||||
|
|
||||||
use super::NoteCommitment;
|
use super::NoteCommitment;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -12,6 +14,22 @@ use crate::{
|
||||||
pub struct Nullifier(pub(super) pallas::Base);
|
pub struct Nullifier(pub(super) pallas::Base);
|
||||||
|
|
||||||
impl Nullifier {
|
impl Nullifier {
|
||||||
|
/// Generates a dummy nullifier for use as $\rho$ in dummy spent notes.
|
||||||
|
///
|
||||||
|
/// Nullifiers are required by consensus to be unique. For dummy output notes, we get
|
||||||
|
/// this restriction as intended: the note's $\rho$ value is set to the nullifier of
|
||||||
|
/// the accompanying spent note within the action, which is constrained by consensus
|
||||||
|
/// to be unique. In the case of dummy spent notes, we get this restriction by
|
||||||
|
/// following the chain backwards: the nullifier of the dummy spent note will be
|
||||||
|
/// constrained by consensus to be unique, and the nullifier's uniqueness is derived
|
||||||
|
/// from the uniqueness of $\rho$.
|
||||||
|
///
|
||||||
|
/// Instead of explicitly sampling for a unique nullifier, we rely here on the size of
|
||||||
|
/// the base field to make the chance of sapling a colliding nullifier negligible.
|
||||||
|
pub(crate) fn dummy(rng: &mut impl RngCore) -> Self {
|
||||||
|
Nullifier(extract_p(&pallas::Point::random(rng)))
|
||||||
|
}
|
||||||
|
|
||||||
/// $DeriveNullifier$.
|
/// $DeriveNullifier$.
|
||||||
///
|
///
|
||||||
/// Defined in [Zcash Protocol Spec § 4.16: Note Commitments and Nullifiers][commitmentsandnullifiers].
|
/// Defined in [Zcash Protocol Spec § 4.16: Note Commitments and Nullifiers][commitmentsandnullifiers].
|
||||||
|
|
|
@ -47,6 +47,11 @@ impl std::error::Error for OverflowError {}
|
||||||
pub struct NoteValue(u64);
|
pub struct NoteValue(u64);
|
||||||
|
|
||||||
impl NoteValue {
|
impl NoteValue {
|
||||||
|
pub(crate) fn zero() -> Self {
|
||||||
|
// Default for u64 is zero.
|
||||||
|
Default::default()
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn to_le_bits(self) -> BitArray<Lsb0, [u8; 8]> {
|
pub(crate) fn to_le_bits(self) -> BitArray<Lsb0, [u8; 8]> {
|
||||||
BitArray::<Lsb0, _>::new(self.0.to_le_bytes())
|
BitArray::<Lsb0, _>::new(self.0.to_le_bytes())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue