use super::*;
impl<N: Network, A: circuit::Aleo<Network = N>> RegistersSigner<N> for Registers<N, A> {
#[inline]
fn signer(&self) -> Result<Address<N>> {
self.signer.ok_or_else(|| anyhow!("Signer address (console) is not set in the registers."))
}
#[inline]
fn set_signer(&mut self, signer: Address<N>) {
self.signer = Some(signer);
}
#[inline]
fn root_tvk(&self) -> Result<Field<N>> {
self.root_tvk.ok_or_else(|| anyhow!("Root tvk (console) is not set in the registers."))
}
#[inline]
fn set_root_tvk(&mut self, root_tvk: Field<N>) {
self.root_tvk = Some(root_tvk);
}
#[inline]
fn caller(&self) -> Result<Address<N>> {
self.caller.ok_or_else(|| anyhow!("Caller address (console) is not set in the registers."))
}
#[inline]
fn set_caller(&mut self, caller: Address<N>) {
self.caller = Some(caller);
}
#[inline]
fn tvk(&self) -> Result<Field<N>> {
self.tvk.ok_or_else(|| anyhow!("Transition view key (console) is not set in the registers."))
}
#[inline]
fn set_tvk(&mut self, tvk: Field<N>) {
self.tvk = Some(tvk);
}
#[inline]
fn request(&self) -> Result<&crate::Request<N>> {
self.request.as_ref().ok_or_else(|| anyhow!("Caller request is not set in the registers."))
}
#[inline]
fn set_request(&mut self, request: crate::Request<N>) {
self.request = Some(request);
}
}
impl<N: Network, A: circuit::Aleo<Network = N>> RegistersTrait<N> for Registers<N, A> {
fn load(&self, stack: &impl StackTrait<N>, operand: &Operand<N>) -> Result<Value<N>> {
let register = match operand {
Operand::Literal(literal) => return Ok(Value::Plaintext(Plaintext::from(literal))),
Operand::Register(register) => register,
Operand::ProgramID(program_id) => {
return Ok(Value::Plaintext(Plaintext::from(Literal::Address(program_id.to_address()?))));
}
Operand::Signer => return Ok(Value::Plaintext(Plaintext::from(Literal::Address(self.signer()?)))),
Operand::Caller => return Ok(Value::Plaintext(Plaintext::from(Literal::Address(self.caller()?)))),
Operand::AleoGenerator => {
return N::g_powers()
.first()
.map(|element| Value::Plaintext(Plaintext::from(Literal::Group(*element))))
.ok_or_else(|| anyhow!("Failed to retrieve the Aleo generator."));
}
Operand::AleoGeneratorPowers(index) => match index {
None => {
return Ok(Value::Plaintext(Plaintext::Array(
N::g_powers().iter().map(|element| Plaintext::from(Literal::Group(*element))).collect(),
OnceLock::new(),
)));
}
Some(index) => {
return N::g_powers()
.get(**index as usize)
.map(|element| Value::Plaintext(Plaintext::from(Literal::Group(*element))))
.ok_or_else(|| anyhow!("Index {index} out of bounds for Aleo generator"));
}
},
Operand::BlockHeight => bail!("Cannot load the block height in a non-finalize context"),
Operand::BlockTimestamp => bail!("Cannot load the block timestamp 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 stack_value =
self.console_registers.get(®ister.locator()).ok_or_else(|| anyhow!("'{register}' does not exist"))?;
let stack_value = match register {
Register::Locator(..) => stack_value.clone(),
Register::Access(_, path) => {
match stack_value {
Value::Plaintext(plaintext) => Value::Plaintext(plaintext.find(path)?),
Value::Record(record) => match record.find(path)? {
Entry::Constant(plaintext) | Entry::Public(plaintext) | Entry::Private(plaintext) => {
Value::Plaintext(plaintext)
}
},
Value::Future(future) => future.find(path)?,
Value::DynamicRecord(dynamic_record) => dynamic_record.find(path)?,
Value::DynamicFuture(_) => bail!("Cannot invoke `find` on a dynamic future value"),
}
}
};
match self.register_types.get_type(stack, register) {
Ok(register_type) => stack.matches_register_type(&stack_value, ®ister_type)?,
Err(error) => bail!("Register '{register}' is not a member of the function: {error}"),
};
Ok(stack_value)
}
fn store(&mut self, stack: &impl StackTrait<N>, register: &Register<N>, stack_value: Value<N>) -> Result<()> {
match register {
Register::Locator(locator) => {
let expected_locator = self.console_registers.len() as u64;
ensure!(expected_locator == *locator, "Out-of-order write operation at '{register}'");
ensure!(
!self.console_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(&stack_value, ®ister_type)?,
Err(error) => bail!("Register '{register}' is missing a type definition: {error}"),
};
match self.console_registers.insert(*locator, stack_value) {
Some(..) => bail!("Attempted to write to register '{register}' again"),
None => Ok(()),
}
}
Register::Access(..) => bail!("Cannot store to a register access: '{register}'"),
}
}
}