Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use evaluate_function for CallStack::PackageRun; Sample response for CallStack::CheckDeployment #2230

Merged
merged 6 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 72 additions & 3 deletions synthesizer/process/src/stack/call/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,23 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::{CallStack, Registers, RegistersCall, StackEvaluate, StackExecute};
use crate::{
stack::{
Address,
ValueType::{ExternalRecord, Record},
},
CallStack,
Registers,
RegistersCall,
StackEvaluate,
StackExecute,
};
use aleo_std::prelude::{finish, lap, timer};
use console::{network::prelude::*, program::Request};
use synthesizer_program::{
Call,
CallOperator,
Operand,
RegistersLoad,
RegistersLoadCircuit,
RegistersSigner,
Expand Down Expand Up @@ -241,7 +252,7 @@ impl<N: Network> CallTrait<N> for Call<N> {
// Return the request and response.
(request, response)
}
CallStack::CheckDeployment(_, private_key, ..) | CallStack::PackageRun(_, private_key, ..) => {
CallStack::PackageRun(_, private_key, ..) => {
// Compute the request.
let request = Request::sign(
&private_key,
Expand All @@ -258,7 +269,65 @@ impl<N: Network> CallTrait<N> for Call<N> {
call_stack.push(request.clone())?;

// Execute the request.
howardwu marked this conversation as resolved.
Show resolved Hide resolved
let response = substack.execute_function::<A, R>(call_stack, console_caller, rng)?;
let response = substack.evaluate_function::<A>(call_stack, console_caller)?;

// Return the request and response.
(request, response)
}
CallStack::CheckDeployment(_, private_key, ..) => {
// Compute the request.
let request = Request::sign(
&private_key,
*substack.program_id(),
*function.name(),
inputs.iter(),
&function.input_types(),
rng,
)?;

// Compute the address.
let address = Address::try_from(&private_key)?;
// Sample dummy outputs
let outputs = function
.outputs()
.iter()
.map(|output| match output.value_type() {
ExternalRecord(locator) => {
// Retrieve the external stack.
let stack = substack.get_external_stack(locator.program_id())?;
// Sample the output.
stack.sample_value(&address, &Record(*locator.resource()), rng)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not move this case directly into the impl of fn sample_value?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Smart a9f3483

_ => substack.sample_value(&address, output.value_type(), rng),
})
.collect::<Result<Vec<_>>>()?;

// Retrieve the output operands.
let output_operands =
&function.outputs().iter().map(|output| output.operand()).collect::<Vec<_>>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we collecting?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blind code copy pasta 53c69a8


// Map the output operands to registers.
let output_registers = output_operands
.iter()
.map(|operand| match operand {
Operand::Register(register) => Some(register.clone()),
_ => None,
})
.collect::<Vec<_>>();

// Compute the response.
let response = crate::Response::new(
request.network_id(),
substack.program().id(),
function.name(),
request.inputs().len(),
request.tvk(),
request.tcm(),
outputs,
&function.output_types(),
&output_registers,
)?;

// Return the request and response.
(request, response)
}
Expand Down
8 changes: 7 additions & 1 deletion synthesizer/process/src/stack/evaluate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ impl<N: Network> StackEvaluate<N> for Stack<N> {
// Retrieve the next request, based on the call stack mode.
let (request, call_stack) = match &call_stack {
CallStack::Evaluate(authorization) => (authorization.next()?, call_stack),
CallStack::PackageRun(requests, _, _) => {
let last_request = requests.last().ok_or(anyhow!("CallStack does not contain request"))?.clone();
(last_request, call_stack)
}
// If the evaluation is performed in the `Execute` mode, create a new `Evaluate` mode.
// This is done to ensure that evaluation during execution is performed consistently.
CallStack::Execute(authorization, _) => {
Expand All @@ -116,7 +120,9 @@ impl<N: Network> StackEvaluate<N> for Stack<N> {
let call_stack = CallStack::Evaluate(authorization);
(request, call_stack)
}
_ => bail!("Illegal operation: call stack must be `Evaluate` or `Execute` in `evaluate_function`."),
_ => bail!(
"Illegal operation: call stack must be `PackageRun`, `Evaluate` or `Execute` in `evaluate_function`."
),
};
lap!(timer, "Retrieve the next request");

Expand Down
1 change: 0 additions & 1 deletion synthesizer/process/src/stack/helpers/matches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
// limitations under the License.

use super::*;
use console::program::{Argument, FinalizeType};

impl<N: Network> StackMatches<N> for Stack<N> {
/// Checks that the given value matches the layout of the value type.
Expand Down
73 changes: 52 additions & 21 deletions synthesizer/process/src/stack/helpers/sample.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,6 @@
use super::*;

impl<N: Network> Stack<N> {
/// Returns a value for the given value type.
pub fn sample_value<R: Rng + CryptoRng>(
&self,
burner_address: &Address<N>,
value_type: &ValueType<N>,
rng: &mut R,
) -> Result<Value<N>> {
match value_type {
ValueType::Constant(plaintext_type)
| ValueType::Public(plaintext_type)
| ValueType::Private(plaintext_type) => Ok(Value::Plaintext(self.sample_plaintext(plaintext_type, rng)?)),
ValueType::Record(record_name) => {
Ok(Value::Record(self.sample_record(burner_address, record_name, rng)?))
}
ValueType::ExternalRecord(locator) => {
bail!("Illegal operation: Cannot sample external records (for '{locator}.record').")
}
ValueType::Future(locator) => bail!("Illegal operation: Cannot sample futures (for '{locator}.future')."),
}
}

/// Returns a record for the given record name, with the given burner address.
pub fn sample_record<R: Rng + CryptoRng>(
&self,
Expand Down Expand Up @@ -64,6 +43,16 @@ impl<N: Network> Stack<N> {
// Return the plaintext value.
Ok(plaintext)
}

/// Samples a future value according to the given future type.
pub fn sample_future<R: Rng + CryptoRng>(&self, locator: &Locator<N>, rng: &mut R) -> Result<Future<N>> {
// Sample a future value.
let future = self.sample_future_internal(locator, 0, rng)?;
// Ensure the future value matches the future type.
self.matches_future(&future, locator)?;
// Return the future value.
Ok(future)
}
}

impl<N: Network> Stack<N> {
Expand Down Expand Up @@ -182,4 +171,46 @@ impl<N: Network> Stack<N> {
// Return the plaintext.
Ok(plaintext)
}

/// Samples a future value according to the given locator.
fn sample_future_internal<R: Rng + CryptoRng>(
&self,
locator: &Locator<N>,
depth: usize,
rng: &mut R,
) -> Result<Future<N>> {
// Retrieve the associated function.
let function = match locator.program_id() == self.program_id() {
true => self.get_function_ref(locator.resource())?,
false => self.get_external_program(locator.program_id())?.get_function_ref(locator.resource())?,
};

// Retrieve the finalize inputs.
let inputs = match function.finalize_logic() {
Some(finalize_logic) => finalize_logic.inputs(),
None => bail!("Function '{locator}' does not have a finalize block"),
};

let arguments = inputs
.into_iter()
.map(|input| {
match input.finalize_type() {
FinalizeType::Plaintext(plaintext_type) => {
// Sample the plaintext value.
let plaintext = self.sample_plaintext_internal(plaintext_type, depth + 1, rng)?;
// Return the argument.
Ok(Argument::Plaintext(plaintext))
}
FinalizeType::Future(locator) => {
// Sample the future value.
let future = self.sample_future_internal(locator, depth + 1, rng)?;
// Return the argument.
Ok(Argument::Future(future))
}
}
})
.collect::<Result<Vec<_>>>()?;

Ok(Future::new(*locator.program_id(), *locator.resource(), arguments))
}
}
23 changes: 23 additions & 0 deletions synthesizer/process/src/stack/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ use console::{
account::{Address, PrivateKey},
network::prelude::*,
program::{
Argument,
Entry,
EntryType,
FinalizeType,
Future,
Identifier,
Literal,
Expand Down Expand Up @@ -292,6 +294,27 @@ impl<N: Network> StackProgram<N> for Stack<N> {
}
Ok(num_calls)
}

/// Returns a value for the given value type.
fn sample_value<R: Rng + CryptoRng>(
&self,
burner_address: &Address<N>,
value_type: &ValueType<N>,
rng: &mut R,
) -> Result<Value<N>> {
match value_type {
ValueType::Constant(plaintext_type)
| ValueType::Public(plaintext_type)
| ValueType::Private(plaintext_type) => Ok(Value::Plaintext(self.sample_plaintext(plaintext_type, rng)?)),
ValueType::Record(record_name) => {
Ok(Value::Record(self.sample_record(burner_address, record_name, rng)?))
}
ValueType::ExternalRecord(locator) => {
bail!("Illegal operation: Cannot sample external records (for '{locator}.record').")
}
ValueType::Future(locator) => Ok(Value::Future(self.sample_future(locator, rng)?)),
}
}
}

impl<N: Network> StackProgramTypes<N> for Stack<N> {
Expand Down
9 changes: 9 additions & 0 deletions synthesizer/program/src/traits/stack_and_registers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use console::{
},
types::{Address, Field},
};
use rand::{CryptoRng, Rng};

pub trait StackMatches<N: Network> {
/// Checks that the given value matches the layout of the value type.
Expand Down Expand Up @@ -83,6 +84,14 @@ pub trait StackProgram<N: Network> {

/// Returns the expected number of calls for the given function name.
fn get_number_of_calls(&self, function_name: &Identifier<N>) -> Result<usize>;

/// Samples a value for the given value_type.
fn sample_value<R: Rng + CryptoRng>(
&self,
burner_address: &Address<N>,
value_type: &ValueType<N>,
rng: &mut R,
) -> Result<Value<N>>;
}

pub trait FinalizeRegistersState<N: Network> {
Expand Down