Skip to content

Commit

Permalink
Merge pull request #2230 from AleoHQ/sample_response_checkdeployment
Browse files Browse the repository at this point in the history
Use evaluate_function for CallStack::PackageRun; Sample response for CallStack::CheckDeployment
  • Loading branch information
howardwu authored Jan 9, 2024
2 parents 8b43d18 + 53c69a8 commit 3d02f7f
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 27 deletions.
55 changes: 51 additions & 4 deletions synthesizer/process/src/stack/call/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@
// 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, 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 +242,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 @@ -257,8 +258,54 @@ impl<N: Network> CallTrait<N> for Call<N> {
// Push the request onto the call stack.
call_stack.push(request.clone())?;

// Execute the request.
let response = substack.execute_function::<A, R>(call_stack, console_caller, rng)?;
// Evaluate the request.
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| substack.sample_value(&address, output.value_type(), rng))
.collect::<Result<Vec<_>>>()?;
// Map the output operands to registers.
let output_registers = function
.outputs()
.iter()
.map(|output| match output.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))
}
}
26 changes: 26 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,30 @@ 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) => {
// Retrieve the external stack.
let stack = self.get_external_stack(locator.program_id())?;
// Sample the output.
Ok(Value::Record(stack.sample_record(burner_address, locator.resource(), rng)?))
}
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

0 comments on commit 3d02f7f

Please sign in to comment.