|
15 | 15 | use super::*;
|
16 | 16 |
|
17 | 17 | impl<N: Network> Stack<N> {
|
18 |
| - /// Returns a value for the given value type. |
19 |
| - pub fn sample_value<R: Rng + CryptoRng>( |
20 |
| - &self, |
21 |
| - burner_address: &Address<N>, |
22 |
| - value_type: &ValueType<N>, |
23 |
| - rng: &mut R, |
24 |
| - ) -> Result<Value<N>> { |
25 |
| - match value_type { |
26 |
| - ValueType::Constant(plaintext_type) |
27 |
| - | ValueType::Public(plaintext_type) |
28 |
| - | ValueType::Private(plaintext_type) => Ok(Value::Plaintext(self.sample_plaintext(plaintext_type, rng)?)), |
29 |
| - ValueType::Record(record_name) => { |
30 |
| - Ok(Value::Record(self.sample_record(burner_address, record_name, rng)?)) |
31 |
| - } |
32 |
| - ValueType::ExternalRecord(locator) => { |
33 |
| - bail!("Illegal operation: Cannot sample external records (for '{locator}.record').") |
34 |
| - } |
35 |
| - ValueType::Future(locator) => bail!("Illegal operation: Cannot sample futures (for '{locator}.future')."), |
36 |
| - } |
37 |
| - } |
38 |
| - |
39 | 18 | /// Returns a record for the given record name, with the given burner address.
|
40 | 19 | pub fn sample_record<R: Rng + CryptoRng>(
|
41 | 20 | &self,
|
@@ -64,6 +43,16 @@ impl<N: Network> Stack<N> {
|
64 | 43 | // Return the plaintext value.
|
65 | 44 | Ok(plaintext)
|
66 | 45 | }
|
| 46 | + |
| 47 | + /// Samples a future value according to the given future type. |
| 48 | + pub fn sample_future<R: Rng + CryptoRng>(&self, locator: &Locator<N>, rng: &mut R) -> Result<Future<N>> { |
| 49 | + // Sample a future value. |
| 50 | + let future = self.sample_future_internal(locator, 0, rng)?; |
| 51 | + // Ensure the future value matches the future type. |
| 52 | + self.matches_future(&future, locator)?; |
| 53 | + // Return the future value. |
| 54 | + Ok(future) |
| 55 | + } |
67 | 56 | }
|
68 | 57 |
|
69 | 58 | impl<N: Network> Stack<N> {
|
@@ -182,4 +171,46 @@ impl<N: Network> Stack<N> {
|
182 | 171 | // Return the plaintext.
|
183 | 172 | Ok(plaintext)
|
184 | 173 | }
|
| 174 | + |
| 175 | + /// Samples a future value according to the given locator. |
| 176 | + fn sample_future_internal<R: Rng + CryptoRng>( |
| 177 | + &self, |
| 178 | + locator: &Locator<N>, |
| 179 | + depth: usize, |
| 180 | + rng: &mut R, |
| 181 | + ) -> Result<Future<N>> { |
| 182 | + // Retrieve the associated function. |
| 183 | + let function = match locator.program_id() == self.program_id() { |
| 184 | + true => self.get_function_ref(locator.resource())?, |
| 185 | + false => self.get_external_program(locator.program_id())?.get_function_ref(locator.resource())?, |
| 186 | + }; |
| 187 | + |
| 188 | + // Retrieve the finalize inputs. |
| 189 | + let inputs = match function.finalize_logic() { |
| 190 | + Some(finalize_logic) => finalize_logic.inputs(), |
| 191 | + None => bail!("Function '{locator}' does not have a finalize block"), |
| 192 | + }; |
| 193 | + |
| 194 | + let arguments = inputs |
| 195 | + .into_iter() |
| 196 | + .map(|input| { |
| 197 | + match input.finalize_type() { |
| 198 | + FinalizeType::Plaintext(plaintext_type) => { |
| 199 | + // Sample the plaintext value. |
| 200 | + let plaintext = self.sample_plaintext_internal(plaintext_type, depth + 1, rng)?; |
| 201 | + // Return the argument. |
| 202 | + Ok(Argument::Plaintext(plaintext)) |
| 203 | + } |
| 204 | + FinalizeType::Future(locator) => { |
| 205 | + // Sample the future value. |
| 206 | + let future = self.sample_future_internal(locator, depth + 1, rng)?; |
| 207 | + // Return the argument. |
| 208 | + Ok(Argument::Future(future)) |
| 209 | + } |
| 210 | + } |
| 211 | + }) |
| 212 | + .collect::<Result<Vec<_>>>()?; |
| 213 | + |
| 214 | + Ok(Future::new(*locator.program_id(), *locator.resource(), arguments)) |
| 215 | + } |
185 | 216 | }
|
0 commit comments