Skip to content

Commit

Permalink
refactor: rename read request to note hash read request (#4888)
Browse files Browse the repository at this point in the history
  • Loading branch information
LeilaWang authored Mar 1, 2024
1 parent d8c770b commit bd3f614
Show file tree
Hide file tree
Showing 57 changed files with 3,014 additions and 2,993 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ An example of how to use this operation is visible in the `easy_private_state`:

This function returns the notes the account has access to.

The kernel circuits are constrained to a maximum number of notes this function can return at a time. Check [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr) and look for `MAX_READ_REQUESTS_PER_CALL` for the up-to-date number.
The kernel circuits are constrained to a maximum number of notes this function can return at a time. Check [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr) and look for `MAX_NOTE_HASH_READ_REQUESTS_PER_CALL` for the up-to-date number.

Because of this limit, we should always consider using the second argument `NoteGetterOptions` to limit the number of notes we need to read and constrain in our programs. This is quite important as every extra call increases the time used to prove the program and we don't want to spend more time than necessary.

Expand Down Expand Up @@ -268,7 +268,7 @@ When the `limit` is set to a non-zero value, the data oracle will return a maxim

This setting enables us to skip the first `offset` notes. It's particularly useful for pagination.

### `filter: fn ([Option<Note>; MAX_READ_REQUESTS_PER_CALL], FILTER_ARGS) -> [Option<Note>; MAX_READ_REQUESTS_PER_CALL]`
### `filter: fn ([Option<Note>; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL], FILTER_ARGS) -> [Option<Note>; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]`

Developers have the option to provide a custom filter. This allows specific logic to be applied to notes that meet the criteria outlined above. The filter takes the notes returned from the oracle and `filter_args` as its parameters.

Expand All @@ -292,7 +292,7 @@ This function initializes a `NoteGetterOptions` that simply returns the maximum

### `fn with_filter(filter, filter_args) -> NoteGetterOptions<Note, N, FILTER_ARGS>`

This function initializes a `NoteGetterOptions` with a [`filter`](#filter-fn-optionnote-max_read_requests_per_call-filter_args---optionnote-max_read_requests_per_call) and [`filter_args`](#filter_args-filter_args).
This function initializes a `NoteGetterOptions` with a [`filter`](#filter-fn-optionnote-max_note_hash_read_requests_per_call-filter_args---optionnote-max_note_hash_read_requests_per_call) and [`filter_args`](#filter_args-filter_args).

### `.select`

Expand Down Expand Up @@ -346,7 +346,7 @@ We can use it as a filter to further reduce the number of the final notes:

One thing to remember is, `filter` will be applied on the notes after they are picked from the database, so it is more efficient to use select with comparators where possible. Another side effect of this is that it's possible that the actual notes we end up getting are fewer than the limit.

The limit is `MAX_READ_REQUESTS_PER_CALL` by default. But we can set it to any value **smaller** than that:
The limit is `MAX_NOTE_HASH_READ_REQUESTS_PER_CALL` by default. But we can set it to any value **smaller** than that:

#include_code state_vars-NoteGetterOptionsPickOne /noir-projects/noir-contracts/contracts/docs_example_contract/src/options.nr rust

Expand Down
4 changes: 2 additions & 2 deletions l1-contracts/src/core/libraries/ConstantsGen.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ library Constants {
uint256 internal constant MAX_NEW_L2_TO_L1_MSGS_PER_CALL = 2;
uint256 internal constant MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL = 16;
uint256 internal constant MAX_PUBLIC_DATA_READS_PER_CALL = 16;
uint256 internal constant MAX_READ_REQUESTS_PER_CALL = 32;
uint256 internal constant MAX_NOTE_HASH_READ_REQUESTS_PER_CALL = 32;
uint256 internal constant MAX_NULLIFIER_READ_REQUESTS_PER_CALL = 2;
uint256 internal constant MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL = 1;
uint256 internal constant MAX_NEW_NOTE_HASHES_PER_TX = 64;
Expand All @@ -44,7 +44,7 @@ library Constants {
uint256 internal constant MAX_REVERTIBLE_PUBLIC_DATA_READS_PER_TX = 16;
uint256 internal constant MAX_NEW_L2_TO_L1_MSGS_PER_TX = 2;
uint256 internal constant MAX_NEW_CONTRACTS_PER_TX = 1;
uint256 internal constant MAX_READ_REQUESTS_PER_TX = 128;
uint256 internal constant MAX_NOTE_HASH_READ_REQUESTS_PER_TX = 128;
uint256 internal constant MAX_NULLIFIER_READ_REQUESTS_PER_TX = 8;
uint256 internal constant MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX = 4;
uint256 internal constant NUM_ENCRYPTED_LOGS_HASHES_PER_TX = 1;
Expand Down
34 changes: 16 additions & 18 deletions noir-projects/aztec-nr/aztec/src/context/private_context.nr
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::{
context::{inputs::PrivateContextInputs, interface::ContextInterface},
key::nullifier_key::validate_nullifier_key_against_address,
messaging::process_l1_to_l2_message,
key::nullifier_key::validate_nullifier_key_against_address, messaging::process_l1_to_l2_message,
oracle::{
arguments, call_private_function::call_private_function_internal,
enqueue_public_function_call::enqueue_public_function_call_internal, context::get_portal_address,
Expand All @@ -11,21 +10,20 @@ use crate::{
};
use dep::protocol_types::{
abis::{
call_context::CallContext, function_data::FunctionData, function_selector::FunctionSelector,
nullifier_key_validation_request::NullifierKeyValidationRequest,
private_call_stack_item::PrivateCallStackItem,
private_circuit_public_inputs::PrivateCircuitPublicInputs,
public_call_stack_item::PublicCallStackItem,
public_circuit_public_inputs::PublicCircuitPublicInputs,
read_request::ReadRequest,
side_effect::{SideEffect, SideEffectLinkedToNoteHash}
},
call_context::CallContext, function_data::FunctionData, function_selector::FunctionSelector,
nullifier_key_validation_request::NullifierKeyValidationRequest,
private_call_stack_item::PrivateCallStackItem,
private_circuit_public_inputs::PrivateCircuitPublicInputs,
public_call_stack_item::PublicCallStackItem,
public_circuit_public_inputs::PublicCircuitPublicInputs, read_request::ReadRequest,
side_effect::{SideEffect, SideEffectLinkedToNoteHash}
},
address::{AztecAddress, EthAddress},
constants::{
MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,
MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,
MAX_PUBLIC_DATA_READS_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL,
MAX_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,
MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,
MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL, NUM_FIELDS_PER_SHA256, RETURN_VALUES_LENGTH
},
contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},
Expand All @@ -48,7 +46,7 @@ struct PrivateContext {
args_hash : Field,
return_values : BoundedVec<Field, RETURN_VALUES_LENGTH>,

read_requests: BoundedVec<SideEffect, MAX_READ_REQUESTS_PER_CALL>,
note_hash_read_requests: BoundedVec<SideEffect, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL>,
nullifier_read_requests: BoundedVec<ReadRequest, MAX_NULLIFIER_READ_REQUESTS_PER_CALL>,
nullifier_key_validation_requests: BoundedVec<NullifierKeyValidationRequest, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL>,

Expand Down Expand Up @@ -121,7 +119,7 @@ impl PrivateContext {
min_revertible_side_effect_counter,
args_hash,
return_values: BoundedVec::new(),
read_requests: BoundedVec::new(),
note_hash_read_requests: BoundedVec::new(),
nullifier_read_requests: BoundedVec::new(),
nullifier_key_validation_requests: BoundedVec::new(),
new_note_hashes: BoundedVec::new(),
Expand Down Expand Up @@ -171,7 +169,7 @@ impl PrivateContext {
// I've had to initialize the counter here so that it would work for contract deployments
// the above checks should be doable after we figure out fee payments for contract deployments
min_revertible_side_effect_counter: self.min_revertible_side_effect_counter,
read_requests: self.read_requests.storage,
note_hash_read_requests: self.note_hash_read_requests.storage,
nullifier_read_requests: self.nullifier_read_requests.storage,
nullifier_key_validation_requests: self.nullifier_key_validation_requests.storage,
new_note_hashes: self.new_note_hashes.storage,
Expand All @@ -196,9 +194,9 @@ impl PrivateContext {
self.min_revertible_side_effect_counter = self.side_effect_counter;
}

pub fn push_read_request(&mut self, read_request: Field) {
let side_effect = SideEffect { value: read_request, counter: self.side_effect_counter };
self.read_requests.push(side_effect);
pub fn push_note_hash_read_request(&mut self, note_hash: Field) {
let side_effect = SideEffect { value: note_hash, counter: self.side_effect_counter };
self.note_hash_read_requests.push(side_effect);
self.side_effect_counter = self.side_effect_counter + 1;
}

Expand Down
9 changes: 4 additions & 5 deletions noir-projects/aztec-nr/aztec/src/context/public_context.nr
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::{
context::{inputs::PublicContextInputs, interface::ContextInterface},
messaging::process_l1_to_l2_message,
oracle::{arguments, public_call::call_public_function_internal}
context::{inputs::PublicContextInputs, interface::ContextInterface},
messaging::process_l1_to_l2_message, oracle::{arguments, public_call::call_public_function_internal}
};
use dep::protocol_types::{
abis::{
Expand All @@ -15,8 +14,8 @@ use dep::protocol_types::{
constants::{
MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,
MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL,
MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_READ_REQUESTS_PER_CALL, NUM_FIELDS_PER_SHA256,
RETURN_VALUES_LENGTH
MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,
NUM_FIELDS_PER_SHA256, RETURN_VALUES_LENGTH
},
contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},
hash::hash_args, header::Header, messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader
Expand Down
12 changes: 6 additions & 6 deletions noir-projects/aztec-nr/aztec/src/note/note_getter.nr
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use dep::std::option::Option;
use dep::protocol_types::{
constants::{
MAX_READ_REQUESTS_PER_CALL, GET_NOTE_ORACLE_RETURN_LENGTH, GET_NOTES_ORACLE_RETURN_LENGTH,
MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, GET_NOTE_ORACLE_RETURN_LENGTH, GET_NOTES_ORACLE_RETURN_LENGTH,
MAX_NOTES_PER_PAGE, VIEW_NOTE_ORACLE_RETURN_LENGTH
}
};
Expand Down Expand Up @@ -75,15 +75,15 @@ pub fn get_note<Note, N>(

let note_hash_for_read_request = compute_note_hash_for_consumption(note);

context.push_read_request(note_hash_for_read_request);
context.push_note_hash_read_request(note_hash_for_read_request);
note
}

pub fn get_notes<Note, N, FILTER_ARGS>(
context: &mut PrivateContext,
storage_slot: Field,
options: NoteGetterOptions<Note, N, FILTER_ARGS>
) -> [Option<Note>; MAX_READ_REQUESTS_PER_CALL] where Note: NoteInterface<N> {
) -> [Option<Note>; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL] where Note: NoteInterface<N> {
let opt_notes = get_notes_internal(storage_slot, options);
let mut num_notes = 0;
let mut prev_fields = [0; N];
Expand All @@ -102,7 +102,7 @@ pub fn get_notes<Note, N, FILTER_ARGS>(
let note_hash_for_read_request = compute_note_hash_for_consumption(note);
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/1410): test to ensure
// failure if malicious oracle injects 0 nonce here for a "pre-existing" note.
context.push_read_request(note_hash_for_read_request);
context.push_note_hash_read_request(note_hash_for_read_request);

num_notes += 1;
};
Expand Down Expand Up @@ -137,9 +137,9 @@ unconstrained fn get_note_internal<Note, N>(storage_slot: Field) -> Note where N
unconstrained fn get_notes_internal<Note, N, FILTER_ARGS>(
storage_slot: Field,
options: NoteGetterOptions<Note, N, FILTER_ARGS>
) -> [Option<Note>; MAX_READ_REQUESTS_PER_CALL] where Note: NoteInterface<N> {
) -> [Option<Note>; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL] where Note: NoteInterface<N> {
let (num_selects, select_by, select_values, select_comparators, sort_by, sort_order) = flatten_options(options.selects, options.sorts);
let placeholder_opt_notes = [Option::none(); MAX_READ_REQUESTS_PER_CALL];
let placeholder_opt_notes = [Option::none(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL];
let placeholder_fields = [0; GET_NOTES_ORACLE_RETURN_LENGTH];
let placeholder_note_length = [0; N];
let opt_notes = oracle::notes::get_notes(
Expand Down
16 changes: 8 additions & 8 deletions noir-projects/aztec-nr/aztec/src/note/note_getter_options.nr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use dep::std::option::Option;
use dep::protocol_types::{constants::MAX_READ_REQUESTS_PER_CALL};
use dep::protocol_types::{constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL};
use crate::note::note_interface::NoteInterface;

struct ComparatorEnum {
Expand Down Expand Up @@ -65,9 +65,9 @@ global NoteStatus = NoteStatusEnum {
};

fn return_all_notes<Note, N>(
notes: [Option<Note>; MAX_READ_REQUESTS_PER_CALL],
notes: [Option<Note>; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],
_p: Field
) -> [Option<Note>; MAX_READ_REQUESTS_PER_CALL] {
) -> [Option<Note>; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL] {
notes
}

Expand All @@ -77,7 +77,7 @@ struct NoteGetterOptions<Note, N, FILTER_ARGS> {
sorts: BoundedVec<Option<Sort>, N>,
limit: u32,
offset: u32,
filter: fn ([Option<Note>; MAX_READ_REQUESTS_PER_CALL], FILTER_ARGS) -> [Option<Note>; MAX_READ_REQUESTS_PER_CALL],
filter: fn ([Option<Note>; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL], FILTER_ARGS) -> [Option<Note>; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],
filter_args: FILTER_ARGS,
status: u8,
}
Expand All @@ -93,7 +93,7 @@ impl<Note, N, FILTER_ARGS> NoteGetterOptions<Note, N, FILTER_ARGS> {
NoteGetterOptions {
selects: BoundedVec::new(),
sorts: BoundedVec::new(),
limit: MAX_READ_REQUESTS_PER_CALL as u32,
limit: MAX_NOTE_HASH_READ_REQUESTS_PER_CALL as u32,
offset: 0,
filter: return_all_notes,
filter_args: 0,
Expand All @@ -104,13 +104,13 @@ impl<Note, N, FILTER_ARGS> NoteGetterOptions<Note, N, FILTER_ARGS> {
// This function initializes a NoteGetterOptions with a filter, which takes the notes returned from the database and filter_args as its parameters.
// `filter_args` allows you to provide additional data or context to the custom filter.
pub fn with_filter(
filter: fn([Option<Note>; MAX_READ_REQUESTS_PER_CALL], FILTER_ARGS) -> [Option<Note>; MAX_READ_REQUESTS_PER_CALL],
filter: fn([Option<Note>; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL], FILTER_ARGS) -> [Option<Note>; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],
filter_args: FILTER_ARGS
) -> Self where Note: NoteInterface<N> {
NoteGetterOptions {
selects: BoundedVec::new(),
sorts: BoundedVec::new(),
limit: MAX_READ_REQUESTS_PER_CALL as u32,
limit: MAX_NOTE_HASH_READ_REQUESTS_PER_CALL as u32,
offset: 0,
filter,
filter_args,
Expand All @@ -136,7 +136,7 @@ impl<Note, N, FILTER_ARGS> NoteGetterOptions<Note, N, FILTER_ARGS> {

// This method lets you set a limit for the maximum number of notes to be retrieved in a single query result.
pub fn set_limit(&mut self, limit: u32) -> Self {
assert(limit <= MAX_READ_REQUESTS_PER_CALL as u32);
assert(limit <= MAX_NOTE_HASH_READ_REQUESTS_PER_CALL as u32);
self.limit = limit;
*self
}
Expand Down
6 changes: 3 additions & 3 deletions noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use dep::std::option::Option;
use dep::protocol_types::{
constants::{MAX_NOTES_PER_PAGE, MAX_READ_REQUESTS_PER_CALL},
constants::{MAX_NOTES_PER_PAGE, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL},
abis::side_effect::{SideEffect, SideEffectLinkedToNoteHash}
};
use crate::context::{PrivateContext, PublicContext, Context};
Expand Down Expand Up @@ -63,7 +63,7 @@ impl<Note> PrivateSet<Note> {
pub fn remove<N>(self, note: Note) where Note: NoteInterface<N> {
let context = self.context.private.unwrap();
let note_hash = compute_note_hash_for_consumption(note);
let has_been_read = context.read_requests.any(|r: SideEffect| r.value == note_hash);
let has_been_read = context.note_hash_read_requests.any(|r: SideEffect| r.value == note_hash);
assert(has_been_read, "Can only remove a note that has been read from the set.");

destroy_note(context, note);
Expand All @@ -74,7 +74,7 @@ impl<Note> PrivateSet<Note> {
pub fn get_notes<N, FILTER_ARGS>(
self,
options: NoteGetterOptions<Note, N, FILTER_ARGS>
) -> [Option<Note>; MAX_READ_REQUESTS_PER_CALL] where Note: NoteInterface<N> {
) -> [Option<Note>; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL] where Note: NoteInterface<N> {
let storage_slot = self.storage_slot;
let opt_notes = get_notes(self.context.private.unwrap(), storage_slot, options);
opt_notes
Expand Down
8 changes: 4 additions & 4 deletions noir-projects/aztec-nr/value-note/src/filter.nr
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use dep::std::option::Option;
use dep::aztec::protocol_types::constants::MAX_READ_REQUESTS_PER_CALL;
use dep::aztec::protocol_types::constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL;
use crate::value_note::ValueNote;

pub fn filter_notes_min_sum(
notes: [Option<ValueNote>; MAX_READ_REQUESTS_PER_CALL],
notes: [Option<ValueNote>; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],
min_sum: Field
) -> [Option<ValueNote>; MAX_READ_REQUESTS_PER_CALL] {
let mut selected = [Option::none(); MAX_READ_REQUESTS_PER_CALL];
) -> [Option<ValueNote>; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL] {
let mut selected = [Option::none(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL];
let mut sum = U128::from_integer(0);
for i in 0..notes.len() {
if notes[i].is_some() & (sum < U128::from_integer(min_sum)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use dep::aztec::{
protocol_types::{address::AztecAddress, constants::{MAX_NOTES_PER_PAGE, MAX_READ_REQUESTS_PER_CALL}},
protocol_types::{address::AztecAddress, constants::{MAX_NOTES_PER_PAGE, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL}},
context::{PrivateContext, PublicContext, Context},
note::{
note_getter_options::NoteGetterOptions, note_viewer_options::NoteViewerOptions,
Expand Down Expand Up @@ -66,10 +66,10 @@ struct Deck {
}

pub fn filter_cards<N>(
notes: [Option<ValueNote>; MAX_READ_REQUESTS_PER_CALL],
notes: [Option<ValueNote>; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],
desired_cards: [Card; N]
) -> [Option<ValueNote>; MAX_READ_REQUESTS_PER_CALL] {
let mut selected = [Option::none(); MAX_READ_REQUESTS_PER_CALL];
) -> [Option<ValueNote>; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL] {
let mut selected = [Option::none(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL];

let mut found = [false; N];

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::types::card_note::{CardNote, CARD_NOTE_LEN};
use dep::aztec::protocol_types::{address::AztecAddress, constants::MAX_READ_REQUESTS_PER_CALL};
use dep::aztec::protocol_types::{address::AztecAddress, constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL};
use dep::aztec::note::note_getter_options::{NoteGetterOptions, Sort, SortOrder};
use dep::std::option::Option;

Expand All @@ -26,10 +26,10 @@ pub fn create_exact_card_getter_options(

// docs:start:state_vars-OptionFilter
pub fn filter_min_points(
cards: [Option<CardNote>; MAX_READ_REQUESTS_PER_CALL],
cards: [Option<CardNote>; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],
min_points: u8
) -> [Option<CardNote>; MAX_READ_REQUESTS_PER_CALL] {
let mut selected_cards = [Option::none(); MAX_READ_REQUESTS_PER_CALL];
) -> [Option<CardNote>; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL] {
let mut selected_cards = [Option::none(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL];
let mut num_selected = 0;
for i in 0..cards.len() {
if cards[i].is_some() & cards[i].unwrap_unchecked().points >= min_points {
Expand Down
Loading

0 comments on commit bd3f614

Please sign in to comment.