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

"Expected array index to be a known constant" within an if statement #1964

Closed
spalladino opened this issue Jul 18, 2023 · 3 comments · Fixed by #1969
Closed

"Expected array index to be a known constant" within an if statement #1964

spalladino opened this issue Jul 18, 2023 · 3 comments · Fixed by #1969
Assignees
Labels
bug Something isn't working

Comments

@spalladino
Copy link
Contributor

Aim

In the Aztec Noir library we have an entrypoint module with a function for executing a set of requests. Each loop currently runs only once, since ACCOUNT_MAX_PRIVATE_CALLS and ACCOUNT_MAX_PUBLIC_CALLS are both 1.

  fn execute_calls(self, mut context: Context) -> Context {
    for i in 0..ACCOUNT_MAX_PRIVATE_CALLS {
        let target_address = self.flattened_targets[i];
        if target_address != 0 {
            let function_selector = self.flattened_selectors[i];
            let args_hash = self.flattened_args_hashes[i];
            let (_callStackItem, updated_context) = PrivateCallStackItem::call_with_packed_args(target_address, function_selector, args_hash, context);
            context = updated_context;
        }
    }
    for i in ACCOUNT_MAX_PRIVATE_CALLS..ACCOUNT_MAX_CALLS {
        let target_address = self.flattened_targets[i];
        if target_address != 0 {
            let function_selector = self.flattened_selectors[i];
            let args_hash = self.flattened_args_hashes[i];
            let (_callStackItem, updated_context) = PublicCallStackItem::call_with_packed_args(target_address, function_selector, args_hash, context);
            context = updated_context;
        }
    }
    context
  }

https://github.com/AztecProtocol/aztec-packages/blob/07032c47f642de5bbd4bb8a2e16230f7a86662af/yarn-project/noir-contracts/src/libs/noir-aztec/src/entrypoint.nr#L91-L111

When increasing them to two, the compiler starts failing with the following error:

The application panicked (crashed).
Message:  Expected array index to be a known constant
Location: crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs:388

I've tried unrolling the loops and setting the index for accessing the arrays as a constant, like the following, but the error persists:

// Executes all private and public calls 
  fn execute_calls(self, mut context: Context) -> Context {
    if self.flattened_targets[0] != 0 {
        let (_callStackItem, updated_context) = PrivateCallStackItem::call_with_packed_args(
          self.flattened_targets[0], 
          self.flattened_selectors[0], 
          self.flattened_args_hashes[0], 
          context
        );
        context = updated_context;
    }

    if self.flattened_targets[1] != 0 {
        let (_callStackItem, updated_context) = PrivateCallStackItem::call_with_packed_args(
          self.flattened_targets[1], 
          self.flattened_selectors[1], 
          self.flattened_args_hashes[1], 
          context
        );
        context = updated_context;
    }

    context
  }

However, removing the if statements eliminates the problem:

// Executes all private and public calls 
  fn execute_calls(self, mut context: Context) -> Context {
    {
        let (_callStackItem, updated_context) = PrivateCallStackItem::call_with_packed_args(
          self.flattened_targets[0], 
          self.flattened_selectors[0], 
          self.flattened_args_hashes[0], 
          context
        );
        context = updated_context;
    }

    {
        let (_callStackItem, updated_context) = PrivateCallStackItem::call_with_packed_args(
          self.flattened_targets[1], 
          self.flattened_selectors[1], 
          self.flattened_args_hashes[1], 
          context
        );
        context = updated_context;
    }

    context
  }

Expected Behavior

Code shown above should compile.

Bug

Full output of the error in the first snippet, with constants set to two:

f12:
  CONST R6 = 11
  ALLOCATE_ARRAY R5 SIZE R6
  MOV R5, Stack
  Stack = Stack + R6
  FOREIGN_CALL enqueuePublicFunctionCall (R2, R3, R4) => R5[0..11]
  // return R5;
  MOV R7, R5
  MOV R2, R7
  STOP
f33:
  CONST R6 = 54
  ALLOCATE_ARRAY R5 SIZE R6
  MOV R5, Stack
  Stack = Stack + R6
  FOREIGN_CALL callPrivateFunction (R2, R3, R4) => R5[0..54]
  // return R5;
  MOV R7, R5
  MOV R2, R7
  STOP
The application panicked (crashed).
Message:  Expected array index to be a known constant
Location: crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs:388

Full output of the error in the unrolled version:

f11:
  CONST R6 = 54
  ALLOCATE_ARRAY R5 SIZE R6
  MOV R5, Stack
  Stack = Stack + R6
  FOREIGN_CALL callPrivateFunction (R2, R3, R4) => R5[0..54]
  // return R5;
  MOV R7, R5
  MOV R2, R7
  STOP
The application panicked (crashed).
Message:  Expected array index to be a known constant
Location: crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs:388

To Reproduce

No response

Installation Method

None

Nargo Version

nargo 0.8.0 (git version hash: ea80de5, is dirty: false)

Additional Context

No response

Would you like to submit a PR for this Issue?

No

Support Needs

No response

@kevaundray
Copy link
Contributor

Would modifying it in the way below change the business logic of the program?

    for i in 0..ACCOUNT_MAX_PRIVATE_CALLS {
        let target_address = self.flattened_targets[i];
        if target_address != 0 {
            let function_selector = self.flattened_selectors[i];
            let args_hash = self.flattened_args_hashes[i];
            let (_callStackItem, updated_context) = PrivateCallStackItem::call_with_packed_args(target_address, function_selector, args_hash, context);
            context = updated_context;
        }
    }

to

    for i in 0..ACCOUNT_MAX_PRIVATE_CALLS {
       let target_address = self.flattened_targets[i];
       let function_selector = self.flattened_selectors[i];
       let args_hash = self.flattened_args_hashes[i];
       if target_address != 0 {
           let (_callStackItem, updated_context) = PrivateCallStackItem::call_with_packed_args(target_address, function_selector, args_hash, context);
           context = updated_context;
       }
   }

@spalladino
Copy link
Contributor Author

Thanks for the quick reply @kevaundray! Unfortunately that doesn't fix the issue, I'm still getting the same compiler error:

f11:
  CONST R6 = 54
  ALLOCATE_ARRAY R5 SIZE R6
  MOV R5, Stack
  Stack = Stack + R6
  FOREIGN_CALL callPrivateFunction (R2, R3, R4) => R5[0..54]
  // return R5;
  MOV R7, R5
  MOV R2, R7
  STOP
The application panicked (crashed).
Message:  Expected array index to be a known constant
Location: crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs:388

@jfecher
Copy link
Contributor

jfecher commented Jul 19, 2023

I'd guess the error may be related to the entire context being conditionally assigned to within each if. On the second if (or second iteration of the loop) one of the BoundedVecs in the context now has a length that is non-constant since it depends on some runtime witness of the previous if condition.

This should be fixed once the dynamic indexing PR is merged: #1969

@kevaundray kevaundray self-assigned this Jul 23, 2023
@github-project-automation github-project-automation bot moved this from 📋 Backlog to ✅ Done in Noir Jul 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

3 participants