Sha256RoundFunction


Sha256RoundFunction PI

Input

GitHubarrow-up-right

pub struct PrecompileFunctionInputData<F: SmallField> {
    pub initial_log_queue_state: QueueState<F, QUEUE_STATE_WIDTH>,
    pub initial_memory_queue_state: QueueState<F, FULL_SPONGE_QUEUE_STATE_WIDTH>,
}

Output

GitHubarrow-up-right

pub struct PrecompileFunctionOutputData<F: SmallField> {
    pub final_memory_state: QueueState<F, FULL_SPONGE_QUEUE_STATE_WIDTH>,
}

FSM Input and FSM Output

GitHubarrow-up-right

pub struct Sha256RoundFunctionFSMInputOutput<F: SmallField> {
    pub internal_fsm: Sha256RoundFunctionFSM<F>,
    pub log_queue_state: QueueState<F, QUEUE_STATE_WIDTH>,
    pub memory_queue_state: QueueState<F, FULL_SPONGE_QUEUE_STATE_WIDTH>,
}

pub struct Sha256RoundFunctionFSM<F: SmallField> {
    pub read_precompile_call: Boolean<F>,
    pub read_words_for_round: Boolean<F>,
    pub completed: Boolean<F>,
    pub sha256_inner_state: [UInt32<F>; 8],
    pub timestamp_to_use_for_read: UInt32<F>,
    pub timestamp_to_use_for_write: UInt32<F>,
    pub precompile_call_params: Sha256PrecompileCallParams<F>,
}

Main circuit logic

This is a precompile for the SHA256 hash function’s round function.

We start from witness allocation:

Check if requests_queue_state_from_input is trivial ( we didn't pop elements yet) and choose between input and fsm queue state:

the same procedure we do for memory_queue:

Call inner part where is main logic:

Form the final state (depending on flag we choose between states):

Finally, we compute a commitment to PublicInput and allocate it as witness variables.

Inner part

Start for set up different flags: precompile_address, aux_byte_for_precompile, and plugs:

We can have a degenerate case when the queue is empty, but it's the first circuit in the queue, so we take default FSM state that has state.read_precompile_call = true, we can only skip the full circuit if we are not in any form of progress:

Main work cycle:

Check income data with constants(precompile addresses aux byte for precompile and must match):

Create parameters that describe the call itself:

  • input_page – memory page for read_queue

  • input_offset – page indexread_queue

  • output_page – memory page for write_queue

  • output_offset – page indexwrite_queue

  • num_rounds – number of rounds for hash function

Setup timestamp:

Reset buffer if needed:

Now perform a few memory queries to read content:

We need to change endianness. Memory is BE, and each of the 4-byte chunks should be interpreted as BE u32 for sha256:

get the initial state for SHA256:

finally, compute sha256 and write into memory if we completed all hash rounds. BTW SHA256 algorithm you can read herearrow-up-right:

Update state:

Last updated