Keccak is a precompile for the keccak hash function, and is responsible for hashing any input data sent in by contract executions. Roughly speaking, the keccak circuit will receive metadata about queued up precompile calls, and ensure that the first-in-line call is indeed a call to the keccak precompile. The circuit then collects some metadata about the call itself, which tells the circuit at which memory position the input can be found, and at which memory position the output should be written, along with some peripheral data like the timestamp of the hash.
Next, the circuit will take data from another queue, which contains memory queries. This will give the circuit witnesses to push into the keccak buffer.
We chose what memory_queue state and log_queue state to continue to work with.
let requests_queue_state =QueueState::conditionally_select( cs, start_flag,&requests_queue_state_from_input,&requests_queue_state_from_fsm,);let memory_queue_state =QueueState::conditionally_select( cs, start_flag,&memory_queue_state_from_input,&memory_queue_state_from_fsm,);
We do the same with inner FSM part.
let initial_state =Keccak256RoundFunctionFSM::conditionally_select( cs, start_flag,&starting_fsm_state,&structured_input.hidden_fsm_input.internal_fsm,);
Our main cycle starts with getting a new precompile request from the queue.
let (precompile_call, _) = precompile_calls_queue.pop_front(cs, state.read_precompile_call);
We check that fields are correct.
Num::conditionally_enforce_equal( cs, state.read_precompile_call,&Num::from_variable(precompile_call.aux_byte.get_variable()),&Num::from_variable(aux_byte_for_precompile.get_variable()),);for (a, b) in precompile_call.address.inner.iter().zip(precompile_address.inner.iter()){Num::conditionally_enforce_equal( cs, state.read_precompile_call,&Num::from_variable(a.get_variable()),&Num::from_variable(b.get_variable()), );}
Also, we prepare some additional information for the call.