snarkvm_ledger_puzzle_epoch/synthesis/program/
mod.rsmod construct_inputs;
mod to_leaves;
mod to_r1cs;
use crate::synthesis::helpers::*;
use circuit::{Mode, environment::R1CS};
use console::{
account::PrivateKey,
network::Network,
prelude::{Itertools, ToBits as TBits, Uniform, Zero},
program::{Field, Identifier, Literal, LiteralType, Value},
};
use snarkvm_synthesizer_process::{CallStack, Process, Registers, Stack, StackProgramTypes};
use snarkvm_synthesizer_program::{Instruction, Program, RegistersStoreCircuit, StackProgram};
use aleo_std::prelude::{finish, lap, timer};
use anyhow::{Result, anyhow, bail, ensure};
use rand::Rng;
use rand_chacha::ChaChaRng;
use std::{
fmt::{self, Debug, Formatter},
ops::Deref,
str::FromStr,
};
const ARITY: u8 = 8;
#[derive(Clone)]
pub struct EpochProgram<N: Network> {
stack: Stack<N>,
register_table: RegisterTable,
epoch_hash: N::BlockHash,
}
impl<N: Network> Debug for EpochProgram<N> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("EpochProgram")
.field("epoch_hash", &self.epoch_hash)
.field("program", self.stack.program())
.finish()
}
}
impl<N: Network> PartialEq for EpochProgram<N> {
fn eq(&self, other: &Self) -> bool {
self.epoch_hash == other.epoch_hash && self.stack.program() == other.stack.program()
}
}
impl<N: Network> Eq for EpochProgram<N> {}
impl<N: Network> EpochProgram<N> {
pub fn new(epoch_hash: N::BlockHash) -> Result<Self> {
let mut register_table = RegisterTable::new();
let input_string = register_table.input_block().to_string();
let instructions = sample_instructions::<N>(epoch_hash, &mut register_table)?;
debug_assert!(!instructions.is_empty());
let mut instruction_string = String::new();
for instruction in &instructions {
instruction_string.push_str(&format!(" {instruction}\n"));
}
let program_string = format!(
r"program puzzle.aleo;
function synthesize:
{input_string}
{instruction_string}
"
);
let program = Program::from_str(&program_string)?;
let process = Process::<N>::load()?;
let stack = Stack::new(&process, &program)?;
Ok(Self { stack, register_table, epoch_hash })
}
}
impl<N: Network> EpochProgram<N> {
#[inline]
pub const fn stack(&self) -> &Stack<N> {
&self.stack
}
#[inline]
pub const fn register_table(&self) -> &RegisterTable {
&self.register_table
}
#[inline]
pub const fn epoch_hash(&self) -> N::BlockHash {
self.epoch_hash
}
#[inline]
pub fn instructions(&self) -> Result<&[Instruction<N>]> {
Ok(self.stack.program().get_function_ref(&Identifier::from_str("synthesize")?)?.instructions())
}
}
impl<N: Network> Deref for EpochProgram<N> {
type Target = Program<N>;
fn deref(&self) -> &Self::Target {
self.stack.program()
}
}
#[cfg(test)]
mod tests {
use super::*;
use console::prelude::TestRng;
type CurrentNetwork = console::network::MainnetV0;
#[test]
fn test_new_is_deterministic() {
let mut rng = TestRng::default();
let epoch_hash = rng.gen();
let epoch_program_0 = EpochProgram::<CurrentNetwork>::new(epoch_hash).unwrap();
let epoch_program_1 = EpochProgram::<CurrentNetwork>::new(epoch_hash).unwrap();
assert_eq!(epoch_program_0, epoch_program_1);
}
#[test]
fn test_instructions_succeeds() {
let mut rng = TestRng::default();
let epoch_hash = rng.gen();
let epoch_program = EpochProgram::<CurrentNetwork>::new(epoch_hash).unwrap();
let instructions = epoch_program.instructions().unwrap();
assert!(!instructions.is_empty());
}
}