This circuit handles the sorting and deduplication of code cancellation requests. Before starting, during the pre-start phase, the first decommitter queue is generated. To decommitter a code, the input will receive the hash root of the code, the length of the code, the code hash of the opcode, the number of opcodes and the code of the page. Next, it sorts the queue and, in the process, identifies and removes identical requests, serving as a filtering mechanism in case the same contract is called several times.
The detailed explanation of sorting and deduplicating can be found here.
First part
The circuit begins with allocating input part of the PI.
In this part, we should decide what initial_queue_state to use (the one from Input or the other one from FSM Input). We do the same for sorted queue.
let state =QueueState::conditionally_select( cs, structured_input.start_flag,&initial_queue_from_passthrough_state,&initial_log_queue_state_from_fsm_state,);
Also, we decide to create a new result queue or use one from the previous circuit.
let state =QueueState::conditionally_select( cs, structured_input.start_flag,&empty_state,&final_sorted_queue_from_fsm_state,);
Now we need to generate challenges for permutation argument.
Also, we need to deduplicate some decommit requests if there are the same ones.
// decide if we should add the PREVIOUS into the queuelet add_to_the_queue =Boolean::multi_and(cs, &[previous_is_non_trivial, different_hash]);result_queue.push(cs, record_to_add, add_to_the_queue);
Now we update inner variables.
previous_item_is_trivial = is_trivial;// may be update the timestamp*first_encountered_timestamp =UInt32::conditionally_select( cs, same_hash,&first_encountered_timestamp,&sorted_item.timestamp,);*previous_record = sorted_item;*previous_packed_key = packed_key;
In the end, if the queues are empty, and we have taken the last element, we push it immediately.
let add_to_the_queue =Boolean::multi_and(cs, &[previous_is_non_trivial, completed]);result_queue.push(cs, record_to_add, add_to_the_queue);
Final part
We check that permutation accumulators are equal, if the queues are already empty.
for (lhs, rhs) in new_lhs.iter().zip(new_rhs.iter()) {Num::conditionally_enforce_equal(cs, completed, lhs, rhs);}
Now we update PI output parts and compute a commitment. Then we allocate it as public variables.
let compact_form =ClosedFormInputCompactForm::from_full_form(cs, &structured_input, round_function);let input_commitment =commit_variable_length_encodable_item(cs, &compact_form, round_function);for el in input_commitment.iter() {let gate =PublicInputGate::new(el.get_variable()); gate.add_to_cs(cs);}