Skip to content

Commit b0cf93b

Browse files
authored
Merge pull request #2355 from AleoHQ/cleanup/mapping-op-ids
[Cleanup] Address TODOs for `Command` parsers and serializers.
2 parents f262864 + 874c691 commit b0cf93b

File tree

6 files changed

+161
-272
lines changed

6 files changed

+161
-272
lines changed

synthesizer/process/src/stack/finalize_types/initialize.rs

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ use crate::RegisterTypes;
1717
use synthesizer_program::{
1818
Await,
1919
Branch,
20+
CallOperator,
2021
CastType,
2122
Contains,
2223
Get,
2324
GetOrUse,
24-
MappingLocator,
2525
RandChaCha,
2626
Remove,
2727
Set,
@@ -174,7 +174,7 @@ impl<N: Network> FinalizeTypes<N> {
174174
match command {
175175
Command::Instruction(instruction) => self.check_instruction(stack, finalize.name(), instruction)?,
176176
Command::Await(await_) => self.check_await(stack, await_)?,
177-
Command::Contains(contains) => self.check_contains(stack, finalize.name(), contains)?,
177+
Command::Contains(contains) => self.check_contains(stack, contains)?,
178178
Command::Get(get) => self.check_get(stack, get)?,
179179
Command::GetOrUse(get_or_use) => self.check_get_or_use(stack, get_or_use)?,
180180
Command::RandChaCha(rand_chacha) => self.check_rand_chacha(stack, finalize.name(), rand_chacha)?,
@@ -252,16 +252,43 @@ impl<N: Network> FinalizeTypes<N> {
252252
fn check_contains(
253253
&mut self,
254254
stack: &(impl StackMatches<N> + StackProgram<N>),
255-
finalize_name: &Identifier<N>,
256255
contains: &Contains<N>,
257256
) -> Result<()> {
258-
// Ensure the declared mapping in `contains` is defined in the program.
259-
if !stack.program().contains_mapping(contains.mapping_name()) {
260-
bail!("Mapping '{}' in '{}/{finalize_name}' is not defined.", contains.mapping_name(), stack.program_id())
261-
}
262-
// Retrieve the mapping from the program.
263-
// Note that the unwrap is safe, as we have already checked the mapping exists.
264-
let mapping = stack.program().get_mapping(contains.mapping_name()).unwrap();
257+
// Retrieve the mapping.
258+
let mapping = match contains.mapping() {
259+
CallOperator::Locator(locator) => {
260+
// Retrieve the program ID.
261+
let program_id = locator.program_id();
262+
// Retrieve the mapping_name.
263+
let mapping_name = locator.resource();
264+
265+
// Ensure the locator does not reference the current program.
266+
if stack.program_id() == program_id {
267+
bail!("Locator '{locator}' does not reference an external mapping.");
268+
}
269+
// Ensure the current program contains an import for this external program.
270+
if !stack.program().imports().keys().contains(program_id) {
271+
bail!("External program '{program_id}' is not imported by '{}'.", stack.program_id());
272+
}
273+
// Retrieve the program.
274+
let external = stack.get_external_program(program_id)?;
275+
// Ensure the mapping exists in the program.
276+
if !external.contains_mapping(mapping_name) {
277+
bail!("Mapping '{mapping_name}' in '{program_id}' is not defined.")
278+
}
279+
// Retrieve the mapping from the program.
280+
external.get_mapping(mapping_name)?
281+
}
282+
CallOperator::Resource(mapping_name) => {
283+
// Ensure the declared mapping in `contains` is defined in the current program.
284+
if !stack.program().contains_mapping(mapping_name) {
285+
bail!("Mapping '{mapping_name}' in '{}' is not defined.", stack.program_id())
286+
}
287+
// Retrieve the mapping from the program.
288+
stack.program().get_mapping(mapping_name)?
289+
}
290+
};
291+
265292
// Get the mapping key type.
266293
let mapping_key_type = mapping.key().plaintext_type();
267294
// Retrieve the register type of the key.
@@ -291,7 +318,7 @@ impl<N: Network> FinalizeTypes<N> {
291318
fn check_get(&mut self, stack: &(impl StackMatches<N> + StackProgram<N>), get: &Get<N>) -> Result<()> {
292319
// Retrieve the mapping.
293320
let mapping = match get.mapping() {
294-
MappingLocator::Locator(locator) => {
321+
CallOperator::Locator(locator) => {
295322
// Retrieve the program ID.
296323
let program_id = locator.program_id();
297324
// Retrieve the mapping_name.
@@ -314,7 +341,7 @@ impl<N: Network> FinalizeTypes<N> {
314341
// Retrieve the mapping from the program.
315342
external.get_mapping(mapping_name)?
316343
}
317-
MappingLocator::Resource(mapping_name) => {
344+
CallOperator::Resource(mapping_name) => {
318345
// Ensure the declared mapping in `get` is defined in the current program.
319346
if !stack.program().contains_mapping(mapping_name) {
320347
bail!("Mapping '{mapping_name}' in '{}' is not defined.", stack.program_id())
@@ -357,7 +384,7 @@ impl<N: Network> FinalizeTypes<N> {
357384
) -> Result<()> {
358385
// Retrieve the mapping.
359386
let mapping = match get_or_use.mapping() {
360-
MappingLocator::Locator(locator) => {
387+
CallOperator::Locator(locator) => {
361388
// Retrieve the program ID.
362389
let program_id = locator.program_id();
363390
// Retrieve the mapping_name.
@@ -380,7 +407,7 @@ impl<N: Network> FinalizeTypes<N> {
380407
// Retrieve the mapping from the program.
381408
external.get_mapping(mapping_name)?
382409
}
383-
MappingLocator::Resource(mapping_name) => {
410+
CallOperator::Resource(mapping_name) => {
384411
// Ensure the declared mapping in `get.or_use` is defined in the current program.
385412
if !stack.program().contains_mapping(mapping_name) {
386413
bail!("Mapping '{mapping_name}' in '{}' is not defined.", stack.program_id())

synthesizer/program/src/logic/command/contains.rs

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,13 @@
1414

1515
use crate::{
1616
traits::{FinalizeStoreTrait, RegistersLoad, RegistersStore, StackMatches, StackProgram},
17+
CallOperator,
1718
Opcode,
1819
Operand,
1920
};
2021
use console::{
2122
network::prelude::*,
22-
program::{Identifier, Literal, Register, Value},
23+
program::{Literal, Register, Value},
2324
types::Boolean,
2425
};
2526

@@ -28,7 +29,7 @@ use console::{
2829
#[derive(Clone, PartialEq, Eq, Hash)]
2930
pub struct Contains<N: Network> {
3031
/// The mapping name.
31-
mapping: Identifier<N>,
32+
mapping: CallOperator<N>,
3233
/// The key to access the mapping.
3334
key: Operand<N>,
3435
/// The destination register.
@@ -48,9 +49,9 @@ impl<N: Network> Contains<N> {
4849
vec![self.key.clone()]
4950
}
5051

51-
/// Returns the mapping name.
52+
/// Returns the mapping.
5253
#[inline]
53-
pub const fn mapping_name(&self) -> &Identifier<N> {
54+
pub const fn mapping(&self) -> &CallOperator<N> {
5455
&self.mapping
5556
}
5657

@@ -76,16 +77,22 @@ impl<N: Network> Contains<N> {
7677
store: &impl FinalizeStoreTrait<N>,
7778
registers: &mut (impl RegistersLoad<N> + RegistersStore<N>),
7879
) -> Result<()> {
80+
// Determine the program ID and mapping name.
81+
let (program_id, mapping_name) = match self.mapping {
82+
CallOperator::Locator(locator) => (*locator.program_id(), *locator.resource()),
83+
CallOperator::Resource(mapping_name) => (*stack.program_id(), mapping_name),
84+
};
85+
7986
// Ensure the mapping exists in storage.
80-
if !store.contains_mapping_confirmed(stack.program_id(), &self.mapping)? {
81-
bail!("Mapping '{}/{}' does not exist in storage", stack.program_id(), self.mapping);
87+
if !store.contains_mapping_confirmed(&program_id, &mapping_name)? {
88+
bail!("Mapping '{program_id}/{mapping_name}' does not exist in storage");
8289
}
8390

8491
// Load the operand as a plaintext.
8592
let key = registers.load_plaintext(stack, &self.key)?;
8693

8794
// Determine if the key exists in the mapping.
88-
let contains_key = store.contains_key_speculative(*stack.program_id(), self.mapping, &key)?;
95+
let contains_key = store.contains_key_speculative(program_id, mapping_name, &key)?;
8996

9097
// Assign the value to the destination register.
9198
registers.store(stack, &self.destination, Value::from(Literal::Boolean(Boolean::new(contains_key))))?;
@@ -106,7 +113,7 @@ impl<N: Network> Parser for Contains<N> {
106113
let (string, _) = Sanitizer::parse_whitespaces(string)?;
107114

108115
// Parse the mapping name from the string.
109-
let (string, mapping) = Identifier::parse(string)?;
116+
let (string, mapping) = CallOperator::parse(string)?;
110117
// Parse the "[" from the string.
111118
let (string, _) = tag("[")(string)?;
112119
// Parse the whitespace from the string.
@@ -177,7 +184,7 @@ impl<N: Network> FromBytes for Contains<N> {
177184
/// Reads the command from a buffer.
178185
fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
179186
// Read the mapping name.
180-
let mapping = Identifier::read_le(&mut reader)?;
187+
let mapping = CallOperator::read_le(&mut reader)?;
181188
// Read the key operand.
182189
let key = Operand::read_le(&mut reader)?;
183190
// Read the destination register.
@@ -210,9 +217,26 @@ mod tests {
210217
fn test_parse() {
211218
let (string, contains) = Contains::<CurrentNetwork>::parse("contains account[r0] into r1;").unwrap();
212219
assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");
213-
assert_eq!(contains.mapping, Identifier::from_str("account").unwrap());
220+
assert_eq!(contains.mapping, CallOperator::from_str("account").unwrap());
221+
assert_eq!(contains.operands().len(), 1, "The number of operands is incorrect");
222+
assert_eq!(contains.key, Operand::Register(Register::Locator(0)), "The first operand is incorrect");
223+
assert_eq!(contains.destination, Register::Locator(1), "The second operand is incorrect");
224+
225+
let (string, contains) =
226+
Contains::<CurrentNetwork>::parse("contains credits.aleo/account[r0] into r1;").unwrap();
227+
assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");
228+
assert_eq!(contains.mapping, CallOperator::from_str("credits.aleo/account").unwrap());
214229
assert_eq!(contains.operands().len(), 1, "The number of operands is incorrect");
215230
assert_eq!(contains.key, Operand::Register(Register::Locator(0)), "The first operand is incorrect");
216231
assert_eq!(contains.destination, Register::Locator(1), "The second operand is incorrect");
217232
}
233+
234+
#[test]
235+
fn test_from_bytes() {
236+
let (string, contains) = Contains::<CurrentNetwork>::parse("contains account[r0] into r1;").unwrap();
237+
assert!(string.is_empty());
238+
let bytes_le = contains.to_bytes_le().unwrap();
239+
let result = Contains::<CurrentNetwork>::from_bytes_le(&bytes_le[..]);
240+
assert!(result.is_ok())
241+
}
218242
}

0 commit comments

Comments
 (0)