use super::*;
impl<N: Network, A: circuit::Aleo<Network = N>> RegistersCircuit<N, A> for Registers<N, A> {
#[inline]
fn signer_circuit(&self) -> Result<circuit::Address<A>> {
self.signer_circuit.clone().ok_or_else(|| anyhow!("Signer address (circuit) is not set in the registers."))
}
#[inline]
fn set_signer_circuit(&mut self, signer_circuit: circuit::Address<A>) {
self.signer_circuit = Some(signer_circuit);
}
#[inline]
fn root_tvk_circuit(&self) -> Result<circuit::Field<A>> {
self.root_tvk_circuit.clone().ok_or_else(|| anyhow!("Root tvk (circuit) is not set in the registers."))
}
#[inline]
fn set_root_tvk_circuit(&mut self, root_tvk_circuit: circuit::Field<A>) {
self.root_tvk_circuit = Some(root_tvk_circuit);
}
#[inline]
fn caller_circuit(&self) -> Result<circuit::Address<A>> {
self.caller_circuit.clone().ok_or_else(|| anyhow!("Caller address (circuit) is not set in the registers."))
}
#[inline]
fn set_caller_circuit(&mut self, caller_circuit: circuit::Address<A>) {
self.caller_circuit = Some(caller_circuit);
}
#[inline]
fn tvk_circuit(&self) -> Result<circuit::Field<A>> {
self.tvk_circuit.clone().ok_or_else(|| anyhow!("Transition view key (circuit) is not set in the registers."))
}
#[inline]
fn set_tvk_circuit(&mut self, tvk_circuit: circuit::Field<A>) {
self.tvk_circuit = Some(tvk_circuit);
}
fn load_circuit(&self, stack: &impl StackTrait<N>, operand: &Operand<N>) -> Result<circuit::Value<A>> {
use circuit::Inject;
let register = match operand {
Operand::Literal(literal) => {
return Ok(circuit::Value::Plaintext(circuit::Plaintext::from(circuit::Literal::constant(
literal.clone(),
))));
}
Operand::Register(register) => register,
Operand::ProgramID(program_id) => {
return Ok(circuit::Value::Plaintext(circuit::Plaintext::from(circuit::Literal::constant(
Literal::Address(program_id.to_address()?),
))));
}
Operand::Signer => {
return Ok(circuit::Value::Plaintext(circuit::Plaintext::from(circuit::Literal::Address(
self.signer_circuit()?,
))));
}
Operand::Caller => {
return Ok(circuit::Value::Plaintext(circuit::Plaintext::from(circuit::Literal::Address(
self.caller_circuit()?,
))));
}
Operand::BlockHeight => bail!("Cannot load the block height in a non-finalize context"),
Operand::NetworkID => bail!("Cannot load the network ID in a non-finalize context"),
Operand::Checksum(_) => bail!("Cannot load the checksum in a non-finalize context."),
Operand::Edition(_) => bail!("Cannot load the edition in a non-finalize context"),
Operand::ProgramOwner(_) => bail!("Cannot load the program owner in a non-finalize context"),
};
let circuit_value =
self.circuit_registers.get(®ister.locator()).ok_or_else(|| anyhow!("'{register}' does not exist"))?;
let circuit_value = match register {
Register::Locator(..) => circuit_value.clone(),
Register::Access(_, path) => {
let path = path.iter().map(|access| circuit::Access::constant(*access)).collect::<Vec<_>>();
match circuit_value {
circuit::Value::Plaintext(plaintext) => circuit::Value::Plaintext(plaintext.find(&path)?),
circuit::Value::Record(record) => match record.find(&path)? {
circuit::Entry::Constant(plaintext)
| circuit::Entry::Public(plaintext)
| circuit::Entry::Private(plaintext) => circuit::Value::Plaintext(plaintext),
},
circuit::Value::Future(future) => future.find(&path)?,
}
}
};
match self.register_types.get_type(stack, register) {
Ok(register_type) => {
stack.matches_register_type(&circuit::Eject::eject_value(&circuit_value), ®ister_type)?
}
Err(error) => bail!("Register '{register}' is not a member of the function: {error}"),
};
Ok(circuit_value)
}
fn store_circuit(
&mut self,
stack: &impl StackTrait<N>,
register: &Register<N>,
circuit_value: circuit::Value<A>,
) -> Result<()> {
match register {
Register::Locator(locator) => {
let expected_locator = self.circuit_registers.len() as u64;
ensure!(expected_locator == *locator, "Out-of-order write operation at '{register}'");
ensure!(
!self.circuit_registers.contains_key(locator),
"Cannot write to occupied register '{register}'"
);
match self.register_types.get_type(stack, register) {
Ok(register_type) => {
stack.matches_register_type(&circuit::Eject::eject_value(&circuit_value), ®ister_type)?
}
Err(error) => bail!("Register '{register}' is missing a type definition: {error}"),
};
match self.circuit_registers.insert(*locator, circuit_value) {
Some(..) => bail!("Attempted to write to register '{register}' again"),
None => Ok(()),
}
}
Register::Access(..) => bail!("Cannot store to a register access: '{register}'"),
}
}
}