在這個 EVM Circuits 的範例中,我們將運用多個不同的元素,如槽位(slot)、選擇器(q)、和多個變數(如op, va, vb, vc),來驗證一個智能合約操作 (例如 8 = 3 + 5) 的正確性,而不會暴露操作的具體細節。
在給定的表格範例中,"q", "a_1" 到 "a_32" 是定義的各種變數和操作。"q" 是用於開啟特定約束的選擇器,而 "a_1" 到 "a_32" 可能是用於存儲或操作數據的部分。
is_zero(op - 1) 確定只有當操作是ADD時,自定義約束才會被開啟。bus_mapping_lookup 函數來查詢與特定操作相關的資料(例如:資料讀取和寫入)。gc_next === gc + 3,確保下一個全局計數器的值符合預期。// switch on custom constraint only when the opcode is ADD
if is_zero(op - 1) {
    if case_success {
        // two source read
        for (gc, sp, v) in [(gc, sp, va), (gc+1, sp+1, vb)] {
            bus_mapping_lookup(
                gc,
                Stack,
                sp,
                compress(v),
                Read
            )
        }
        // one result write
        bus_mapping_lookup(
            gc+2,
            Stack,
            sp+1,
            compress(vc),
            Write
        )
        // result is indeed added by two source
        eight_bit_lookup(va[0])
        eight_bit_lookup(vb[0])
        eight_bit_lookup(vc[0])
        256 * carry[0] + vc[0] === va[0] + vb[0]
        for i in range 1..=31 {
            eight_bit_lookup(va[i])
            eight_bit_lookup(vb[i])
            eight_bit_lookup(vc[i])
            256 * carry[i] + vc[i] === va[i] + vb[i] + carry[i-1]
        }
        // gc in the next slot should increase 3
        gc_next === gc + 3
        // addr should be same
        addr_next === addr
        // pc should increase 1
        pc_next === pc + 1
        // sp should increase 1 (ADD = 2 POP + 1 PUSH)
        sp_next === sp + 1
    }
    if case_err_out_of_gas {
        // TODO:
        // - gas_left > gas_cost
        // - consume all give gas
        // - context switch to parent
        // - ...
    }
    if case_err_stack_underflow {
        // TODO:
        // - sp + 1 === 1023 + surfeit
        // - consume all give gas
        // - context switch to parent
        // - ...
    }
}
Python Circuits 實現
def add_sub(instruction: Instruction):
    opcode = instruction.opcode_lookup(True)
    is_sub, _ = instruction.pair_select(opcode, Opcode.SUB, Opcode.ADD)
    a = instruction.stack_pop()
    b = instruction.stack_pop()
    c = instruction.stack_push()
    instruction.constrain_equal_word(
        instruction.add_words([instruction.select_word(is_sub, c, a), b])[0],
        instruction.select_word(is_sub, a, c),
    )
    instruction.step_state_transition_in_same_context(
        opcode,
        rw_counter=Transition.delta(3),
        program_counter=Transition.delta(1),
        stack_pointer=Transition.delta(1),
    )