1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
// Copyright (C) 2019-2023 Aleo Systems Inc.
// This file is part of the snarkVM library.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
mod bytes;
use super::*;
use crate::hash_to_polynomial;
use snarkvm_algorithms::fft::Evaluations as EvaluationsOnDomain;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct EpochChallenge<N: Network> {
/// The epoch number.
epoch_number: u32,
/// The epoch block hash, defined as the block hash right before the epoch updated.
epoch_block_hash: N::BlockHash,
/// The epoch polynomial.
epoch_polynomial: DensePolynomial<<N::PairingCurve as PairingEngine>::Fr>,
/// The evaluations of the epoch polynomial over the product domain.
epoch_polynomial_evaluations: EvaluationsOnDomain<<N::PairingCurve as PairingEngine>::Fr>,
}
impl<N: Network> EpochChallenge<N> {
/// Initializes a new epoch challenge.
pub fn new(epoch_number: u32, epoch_block_hash: N::BlockHash, degree: u32) -> Result<Self> {
// Construct the 'input' as '( epoch_number || epoch_block_hash )'
let mut input = vec![];
epoch_number.write_le(&mut input)?;
epoch_block_hash.write_le(&mut input)?;
let product_domain = CoinbasePuzzle::<N>::product_domain(degree)?;
let epoch_polynomial = hash_to_polynomial::<<N::PairingCurve as PairingEngine>::Fr>(&input, degree);
ensure!(u32::try_from(epoch_polynomial.degree()).is_ok(), "Degree is too large");
let epoch_polynomial_evaluations = epoch_polynomial.evaluate_over_domain_by_ref(product_domain);
// Returns the epoch challenge.
Ok(EpochChallenge { epoch_number, epoch_block_hash, epoch_polynomial, epoch_polynomial_evaluations })
}
/// Returns the epoch number for the solution.
pub const fn epoch_number(&self) -> u32 {
self.epoch_number
}
/// Returns the epoch block hash for the solution.
pub const fn epoch_block_hash(&self) -> N::BlockHash {
self.epoch_block_hash
}
/// Returns the epoch polynomial for the solution.
pub const fn epoch_polynomial(&self) -> &DensePolynomial<<N::PairingCurve as PairingEngine>::Fr> {
&self.epoch_polynomial
}
/// Returns the evaluations of the epoch polynomial over the product domain.
pub const fn epoch_polynomial_evaluations(&self) -> &EvaluationsOnDomain<<N::PairingCurve as PairingEngine>::Fr> {
&self.epoch_polynomial_evaluations
}
/// Returns the number of coefficients of the epoch polynomial.
pub fn degree(&self) -> u32 {
// Convert the degree into a u32.
// The `unwrap` is guaranteed to succeed as we check the degree is less
// than `u32::MAX` in `new`.
u32::try_from(self.epoch_polynomial.degree()).unwrap()
}
/// Returns the number of coefficients of the epoch polynomial.
pub fn num_coefficients(&self) -> Result<u32> {
let degree = self.degree();
degree.checked_add(1).ok_or_else(|| anyhow!("Epoch polynomial degree ({degree} + 1) overflows"))
}
}