diff --git a/docs/img/cdk/cdk-block-explorer-empty.png b/docs/img/cdk/cdk-block-explorer-empty.png index cca69cd3a..36dddf23f 100644 Binary files a/docs/img/cdk/cdk-block-explorer-empty.png and b/docs/img/cdk/cdk-block-explorer-empty.png differ diff --git a/docs/img/cdk/cdk-bridge.png b/docs/img/cdk/cdk-bridge.png index a8f73ad51..c0abd0c5d 100644 Binary files a/docs/img/cdk/cdk-bridge.png and b/docs/img/cdk/cdk-bridge.png differ diff --git a/docs/img/cdk/zksupernets-dac.png b/docs/img/cdk/zksupernets-dac.png index 3297aa83b..0105f5a07 100644 Binary files a/docs/img/cdk/zksupernets-dac.png and b/docs/img/cdk/zksupernets-dac.png differ diff --git a/docs/img/pos/create-app.png b/docs/img/pos/create-app.png index 3cc32a5c3..7cab3a7cb 100644 Binary files a/docs/img/pos/create-app.png and b/docs/img/pos/create-app.png differ diff --git a/docs/img/pos/polygon-scan.png b/docs/img/pos/polygon-scan.png index 9847ed691..1f4f20ebf 100644 Binary files a/docs/img/pos/polygon-scan.png and b/docs/img/pos/polygon-scan.png differ diff --git a/docs/img/pos/polygonscan.png b/docs/img/pos/polygonscan.png index 73bc3cc63..cbc7da8da 100644 Binary files a/docs/img/pos/polygonscan.png and b/docs/img/pos/polygonscan.png differ diff --git a/docs/img/pos/tw-explore.png b/docs/img/pos/tw-explore.png index 0fcd69106..4408944b7 100644 Binary files a/docs/img/pos/tw-explore.png and b/docs/img/pos/tw-explore.png differ diff --git a/docs/img/pos/view-key.png b/docs/img/pos/view-key.png index c4382f985..2b93ccb38 100644 Binary files a/docs/img/pos/view-key.png and b/docs/img/pos/view-key.png differ diff --git a/docs/img/zkEVM/01L2-overview-l2-state-management.png b/docs/img/zkEVM/01L2-overview-l2-state-management.png new file mode 100644 index 000000000..c2e44b9a9 Binary files /dev/null and b/docs/img/zkEVM/01L2-overview-l2-state-management.png differ diff --git a/docs/img/zkEVM/01arith-sch-mlt-eg.png b/docs/img/zkEVM/01arith-sch-mlt-eg.png new file mode 100644 index 000000000..e60c56da6 Binary files /dev/null and b/docs/img/zkEVM/01arith-sch-mlt-eg.png differ diff --git a/docs/img/zkEVM/01b2f-44-2-one-multiplex.png b/docs/img/zkEVM/01b2f-44-2-one-multiplex.png new file mode 100644 index 000000000..db000b91e Binary files /dev/null and b/docs/img/zkEVM/01b2f-44-2-one-multiplex.png differ diff --git a/docs/img/zkEVM/01bin-cdfctn-3bit-strngs.png b/docs/img/zkEVM/01bin-cdfctn-3bit-strngs.png new file mode 100644 index 000000000..734650969 Binary files /dev/null and b/docs/img/zkEVM/01bin-cdfctn-3bit-strngs.png differ diff --git a/docs/img/zkEVM/01circom-witness-zkprover.png b/docs/img/zkEVM/01circom-witness-zkprover.png new file mode 100644 index 000000000..a291d8d90 Binary files /dev/null and b/docs/img/zkEVM/01circom-witness-zkprover.png differ diff --git a/docs/img/zkEVM/01kkb-chunk-divs-136-bytes.png b/docs/img/zkEVM/01kkb-chunk-divs-136-bytes.png new file mode 100644 index 000000000..9951b296e Binary files /dev/null and b/docs/img/zkEVM/01kkb-chunk-divs-136-bytes.png differ diff --git a/docs/img/zkEVM/01kkf-state-array-calibrated.png b/docs/img/zkEVM/01kkf-state-array-calibrated.png new file mode 100644 index 000000000..7078a71f0 Binary files /dev/null and b/docs/img/zkEVM/01kkf-state-array-calibrated.png differ diff --git a/docs/img/zkEVM/01mem-align-schm-mld-eg.png b/docs/img/zkEVM/01mem-align-schm-mld-eg.png new file mode 100644 index 000000000..2429e2026 Binary files /dev/null and b/docs/img/zkEVM/01mem-align-schm-mld-eg.png differ diff --git a/docs/img/zkEVM/01mem-fig-exec-trc.png b/docs/img/zkEVM/01mem-fig-exec-trc.png new file mode 100644 index 000000000..a39ab77b1 Binary files /dev/null and b/docs/img/zkEVM/01mem-fig-exec-trc.png differ diff --git a/docs/img/zkEVM/01msm-evm-components.png b/docs/img/zkEVM/01msm-evm-components.png new file mode 100644 index 000000000..3a01bce28 Binary files /dev/null and b/docs/img/zkEVM/01msm-evm-components.png differ diff --git a/docs/img/zkEVM/01pkk-input-strings-allocate.png b/docs/img/zkEVM/01pkk-input-strings-allocate.png new file mode 100644 index 000000000..08c492efa Binary files /dev/null and b/docs/img/zkEVM/01pkk-input-strings-allocate.png differ diff --git a/docs/img/zkEVM/01prf-rec-pil-stark.png b/docs/img/zkEVM/01prf-rec-pil-stark.png new file mode 100644 index 000000000..8d4521c78 Binary files /dev/null and b/docs/img/zkEVM/01prf-rec-pil-stark.png differ diff --git a/docs/img/zkEVM/01psd-hades-based-poseidon-perm.png b/docs/img/zkEVM/01psd-hades-based-poseidon-perm.png new file mode 100644 index 000000000..a8fdd67ac Binary files /dev/null and b/docs/img/zkEVM/01psd-hades-based-poseidon-perm.png differ diff --git a/docs/img/zkEVM/01pzb-polygon-zkevm-schema.png b/docs/img/zkEVM/01pzb-polygon-zkevm-schema.png new file mode 100644 index 000000000..04a7e0804 Binary files /dev/null and b/docs/img/zkEVM/01pzb-polygon-zkevm-schema.png differ diff --git a/docs/img/zkEVM/02b2f-44-bits-to-64bit-fe.png b/docs/img/zkEVM/02b2f-44-bits-to-64bit-fe.png new file mode 100644 index 000000000..ddae09da3 Binary files /dev/null and b/docs/img/zkEVM/02b2f-44-bits-to-64bit-fe.png differ diff --git a/docs/img/zkEVM/02bin-trth-tbls-bitws.png b/docs/img/zkEVM/02bin-trth-tbls-bitws.png new file mode 100644 index 000000000..21d0780d6 Binary files /dev/null and b/docs/img/zkEVM/02bin-trth-tbls-bitws.png differ diff --git a/docs/img/zkEVM/02circom-overall-context.png b/docs/img/zkEVM/02circom-overall-context.png new file mode 100644 index 000000000..9d21dca6d Binary files /dev/null and b/docs/img/zkEVM/02circom-overall-context.png differ diff --git a/docs/img/zkEVM/02kkb-pad-kk-bit-to-kk-f.png b/docs/img/zkEVM/02kkb-pad-kk-bit-to-kk-f.png new file mode 100644 index 000000000..859a2f42f Binary files /dev/null and b/docs/img/zkEVM/02kkb-pad-kk-bit-to-kk-f.png differ diff --git a/docs/img/zkEVM/02kkf-theta-map-one-bit.png b/docs/img/zkEVM/02kkf-theta-map-one-bit.png new file mode 100644 index 000000000..2048df89e Binary files /dev/null and b/docs/img/zkEVM/02kkf-theta-map-one-bit.png differ diff --git a/docs/img/zkEVM/02l2-l2-state-timeline.png b/docs/img/zkEVM/02l2-l2-state-timeline.png new file mode 100644 index 000000000..f5acf24c9 Binary files /dev/null and b/docs/img/zkEVM/02l2-l2-state-timeline.png differ diff --git a/docs/img/zkEVM/02mem-align-schm-mstr-eg.png b/docs/img/zkEVM/02mem-align-schm-mstr-eg.png new file mode 100644 index 000000000..5c6fa62dd Binary files /dev/null and b/docs/img/zkEVM/02mem-align-schm-mstr-eg.png differ diff --git a/docs/img/zkEVM/02msm-prover-structure.png b/docs/img/zkEVM/02msm-prover-structure.png new file mode 100644 index 000000000..6a3c4f837 Binary files /dev/null and b/docs/img/zkEVM/02msm-prover-structure.png differ diff --git a/docs/img/zkEVM/02prf-rec-simple-composition.png b/docs/img/zkEVM/02prf-rec-simple-composition.png new file mode 100644 index 000000000..a2847bd10 Binary files /dev/null and b/docs/img/zkEVM/02prf-rec-simple-composition.png differ diff --git a/docs/img/zkEVM/02psd-poseidon-hash-pic.png b/docs/img/zkEVM/02psd-poseidon-hash-pic.png new file mode 100644 index 000000000..c32f77998 Binary files /dev/null and b/docs/img/zkEVM/02psd-poseidon-hash-pic.png differ diff --git a/docs/img/zkEVM/02pzb-global-exit-tree.png b/docs/img/zkEVM/02pzb-global-exit-tree.png new file mode 100644 index 000000000..0f4e9b66c Binary files /dev/null and b/docs/img/zkEVM/02pzb-global-exit-tree.png differ diff --git a/docs/img/zkEVM/03circom-simple-arith-circuit.png b/docs/img/zkEVM/03circom-simple-arith-circuit.png new file mode 100644 index 000000000..216684ced Binary files /dev/null and b/docs/img/zkEVM/03circom-simple-arith-circuit.png differ diff --git a/docs/img/zkEVM/03kkf-pi-stepmap-shuffle.png b/docs/img/zkEVM/03kkf-pi-stepmap-shuffle.png new file mode 100644 index 000000000..59485e479 Binary files /dev/null and b/docs/img/zkEVM/03kkf-pi-stepmap-shuffle.png differ diff --git a/docs/img/zkEVM/03l2-sequencing-batches.png b/docs/img/zkEVM/03l2-sequencing-batches.png new file mode 100644 index 000000000..ba070e7df Binary files /dev/null and b/docs/img/zkEVM/03l2-sequencing-batches.png differ diff --git a/docs/img/zkEVM/03msm-state-transition-gen-regs.png b/docs/img/zkEVM/03msm-state-transition-gen-regs.png new file mode 100644 index 000000000..05b460f09 Binary files /dev/null and b/docs/img/zkEVM/03msm-state-transition-gen-regs.png differ diff --git a/docs/img/zkEVM/03prf-rec-setup-phase-rec.png b/docs/img/zkEVM/03prf-rec-setup-phase-rec.png new file mode 100644 index 000000000..c2548ba7f Binary files /dev/null and b/docs/img/zkEVM/03prf-rec-setup-phase-rec.png differ diff --git a/docs/img/zkEVM/03pzb-exit-leaf-add-L1-L2.png b/docs/img/zkEVM/03pzb-exit-leaf-add-L1-L2.png new file mode 100644 index 000000000..5dcd8ded6 Binary files /dev/null and b/docs/img/zkEVM/03pzb-exit-leaf-add-L1-L2.png differ diff --git a/docs/img/zkEVM/04circom-batch-prover.png b/docs/img/zkEVM/04circom-batch-prover.png new file mode 100644 index 000000000..741cb6b13 Binary files /dev/null and b/docs/img/zkEVM/04circom-batch-prover.png differ diff --git a/docs/img/zkEVM/04kkf-chi-map-5bit-row.png b/docs/img/zkEVM/04kkf-chi-map-5bit-row.png new file mode 100644 index 000000000..931f1caa7 Binary files /dev/null and b/docs/img/zkEVM/04kkf-chi-map-5bit-row.png differ diff --git a/docs/img/zkEVM/04l2-batch-chain-acc-hash.png b/docs/img/zkEVM/04l2-batch-chain-acc-hash.png new file mode 100644 index 000000000..e982d05d4 Binary files /dev/null and b/docs/img/zkEVM/04l2-batch-chain-acc-hash.png differ diff --git a/docs/img/zkEVM/04msm-simple-state-transition.png b/docs/img/zkEVM/04msm-simple-state-transition.png new file mode 100644 index 000000000..ea1b85f81 Binary files /dev/null and b/docs/img/zkEVM/04msm-simple-state-transition.png differ diff --git a/docs/img/zkEVM/04prf-rec-proving-phase-rec.png b/docs/img/zkEVM/04prf-rec-proving-phase-rec.png new file mode 100644 index 000000000..51fcaf2cb Binary files /dev/null and b/docs/img/zkEVM/04prf-rec-proving-phase-rec.png differ diff --git a/docs/img/zkEVM/04pzb-overall-interact-bridge-scs.png b/docs/img/zkEVM/04pzb-overall-interact-bridge-scs.png new file mode 100644 index 000000000..caa3472b7 Binary files /dev/null and b/docs/img/zkEVM/04pzb-overall-interact-bridge-scs.png differ diff --git a/docs/img/zkEVM/05circom-forming-batch.png b/docs/img/zkEVM/05circom-forming-batch.png new file mode 100644 index 000000000..0f7aedaeb Binary files /dev/null and b/docs/img/zkEVM/05circom-forming-batch.png differ diff --git a/docs/img/zkEVM/05kkf-iota-rc-bits-lfsr.png b/docs/img/zkEVM/05kkf-iota-rc-bits-lfsr.png new file mode 100644 index 000000000..1e90a323c Binary files /dev/null and b/docs/img/zkEVM/05kkf-iota-rc-bits-lfsr.png differ diff --git a/docs/img/zkEVM/05l2-off-chain-on-chain-trans.png b/docs/img/zkEVM/05l2-off-chain-on-chain-trans.png new file mode 100644 index 000000000..74a7828c9 Binary files /dev/null and b/docs/img/zkEVM/05l2-off-chain-on-chain-trans.png differ diff --git a/docs/img/zkEVM/05msm-addr-reg-contexts.png b/docs/img/zkEVM/05msm-addr-reg-contexts.png new file mode 100644 index 000000000..634f9e717 Binary files /dev/null and b/docs/img/zkEVM/05msm-addr-reg-contexts.png differ diff --git a/docs/img/zkEVM/05prf-rec-binary-aggreg-eg.png b/docs/img/zkEVM/05prf-rec-binary-aggreg-eg.png new file mode 100644 index 000000000..abbb2939a Binary files /dev/null and b/docs/img/zkEVM/05prf-rec-binary-aggreg-eg.png differ diff --git a/docs/img/zkEVM/05pzb-l2-related-scs.png b/docs/img/zkEVM/05pzb-l2-related-scs.png new file mode 100644 index 000000000..e0e459aa8 Binary files /dev/null and b/docs/img/zkEVM/05pzb-l2-related-scs.png differ diff --git a/docs/img/zkEVM/06circom-typical-recursive-prover.png b/docs/img/zkEVM/06circom-typical-recursive-prover.png new file mode 100644 index 000000000..b08f65985 Binary files /dev/null and b/docs/img/zkEVM/06circom-typical-recursive-prover.png differ diff --git a/docs/img/zkEVM/06kkf-all-24-rc-hex.png b/docs/img/zkEVM/06kkf-all-24-rc-hex.png new file mode 100644 index 000000000..f1329eac4 Binary files /dev/null and b/docs/img/zkEVM/06kkf-all-24-rc-hex.png differ diff --git a/docs/img/zkEVM/06l2-actor-income-outcomes.png b/docs/img/zkEVM/06l2-actor-income-outcomes.png new file mode 100644 index 000000000..c4837adb3 Binary files /dev/null and b/docs/img/zkEVM/06l2-actor-income-outcomes.png differ diff --git a/docs/img/zkEVM/06msm-eth-state-trie.png b/docs/img/zkEVM/06msm-eth-state-trie.png new file mode 100644 index 000000000..71219b7bd Binary files /dev/null and b/docs/img/zkEVM/06msm-eth-state-trie.png differ diff --git a/docs/img/zkEVM/06prf-rec-setup-s2c-detail.png b/docs/img/zkEVM/06prf-rec-setup-s2c-detail.png new file mode 100644 index 000000000..ecab89530 Binary files /dev/null and b/docs/img/zkEVM/06prf-rec-setup-s2c-detail.png differ diff --git a/docs/img/zkEVM/06pzb-complete-asset-flow-l1-l2.png b/docs/img/zkEVM/06pzb-complete-asset-flow-l1-l2.png new file mode 100644 index 000000000..4ea684e10 Binary files /dev/null and b/docs/img/zkEVM/06pzb-complete-asset-flow-l1-l2.png differ diff --git a/docs/img/zkvm/07l2-batch-fee-var.png b/docs/img/zkEVM/07l2-batch-fee-var.png similarity index 100% rename from docs/img/zkvm/07l2-batch-fee-var.png rename to docs/img/zkEVM/07l2-batch-fee-var.png diff --git a/docs/img/zkEVM/07msm-zkevm-state-trie.png b/docs/img/zkEVM/07msm-zkevm-state-trie.png new file mode 100644 index 000000000..1850f870b Binary files /dev/null and b/docs/img/zkEVM/07msm-zkevm-state-trie.png differ diff --git a/docs/img/zkEVM/07prf-rec-inputs-stark-verifier-circuit.png b/docs/img/zkEVM/07prf-rec-inputs-stark-verifier-circuit.png new file mode 100644 index 000000000..c8ad61910 Binary files /dev/null and b/docs/img/zkEVM/07prf-rec-inputs-stark-verifier-circuit.png differ diff --git a/docs/img/zkEVM/08l2-batches-below-time-target.png b/docs/img/zkEVM/08l2-batches-below-time-target.png new file mode 100644 index 000000000..9316eb2e3 Binary files /dev/null and b/docs/img/zkEVM/08l2-batches-below-time-target.png differ diff --git a/docs/img/zkEVM/08msm-zkevm-memory-regions.png b/docs/img/zkEVM/08msm-zkevm-memory-regions.png new file mode 100644 index 000000000..ca2e24b2e Binary files /dev/null and b/docs/img/zkEVM/08msm-zkevm-memory-regions.png differ diff --git a/docs/img/zkEVM/08prf-rec-setup-step-c2s.png b/docs/img/zkEVM/08prf-rec-setup-step-c2s.png new file mode 100644 index 000000000..af833d741 Binary files /dev/null and b/docs/img/zkEVM/08prf-rec-setup-step-c2s.png differ diff --git a/docs/img/zkEVM/09l2-forced-batch-seq-flow.png b/docs/img/zkEVM/09l2-forced-batch-seq-flow.png new file mode 100644 index 000000000..bb4e57cad Binary files /dev/null and b/docs/img/zkEVM/09l2-forced-batch-seq-flow.png differ diff --git a/docs/img/zkEVM/09msm-evm-zkevm-mem-align.png b/docs/img/zkEVM/09msm-evm-zkevm-mem-align.png new file mode 100644 index 000000000..82af251d4 Binary files /dev/null and b/docs/img/zkEVM/09msm-evm-zkevm-mem-align.png differ diff --git a/docs/img/zkEVM/09prf-rec-stark-prf-rec-step.png b/docs/img/zkEVM/09prf-rec-stark-prf-rec-step.png new file mode 100644 index 000000000..c668c1440 Binary files /dev/null and b/docs/img/zkEVM/09prf-rec-stark-prf-rec-step.png differ diff --git a/docs/img/zkEVM/10l2-diff-trustd-virtual-state.png b/docs/img/zkEVM/10l2-diff-trustd-virtual-state.png new file mode 100644 index 000000000..3277a3ba6 Binary files /dev/null and b/docs/img/zkEVM/10l2-diff-trustd-virtual-state.png differ diff --git a/docs/img/zkEVM/10msm-zkevm-stack-slots.png b/docs/img/zkEVM/10msm-zkevm-stack-slots.png new file mode 100644 index 000000000..25ea48a4d Binary files /dev/null and b/docs/img/zkEVM/10msm-zkevm-stack-slots.png differ diff --git a/docs/img/zkEVM/10prf-rec-proving-arch-outline.png b/docs/img/zkEVM/10prf-rec-proving-arch-outline.png new file mode 100644 index 000000000..dcf3e46c7 Binary files /dev/null and b/docs/img/zkEVM/10prf-rec-proving-arch-outline.png differ diff --git a/docs/img/zkEVM/11l2-stages-timeline-pending.png b/docs/img/zkEVM/11l2-stages-timeline-pending.png new file mode 100644 index 000000000..2d6621232 Binary files /dev/null and b/docs/img/zkEVM/11l2-stages-timeline-pending.png differ diff --git a/docs/img/zkEVM/11pil-2-progs-2-exec-traces-eg.png b/docs/img/zkEVM/11pil-2-progs-2-exec-traces-eg.png new file mode 100644 index 000000000..d0e83be33 Binary files /dev/null and b/docs/img/zkEVM/11pil-2-progs-2-exec-traces-eg.png differ diff --git a/docs/img/zkEVM/11prf-rec-build-zkevm-stark.png b/docs/img/zkEVM/11prf-rec-build-zkevm-stark.png new file mode 100644 index 000000000..702c6ebff Binary files /dev/null and b/docs/img/zkEVM/11prf-rec-build-zkevm-stark.png differ diff --git a/docs/img/zkEVM/12prf-rec-convert-verification-to-circuit.png b/docs/img/zkEVM/12prf-rec-convert-verification-to-circuit.png new file mode 100644 index 000000000..8d6b1aeeb Binary files /dev/null and b/docs/img/zkEVM/12prf-rec-convert-verification-to-circuit.png differ diff --git a/docs/img/zkEVM/13prf-rec-convert-zkevm-verifier-to-stark.png b/docs/img/zkEVM/13prf-rec-convert-zkevm-verifier-to-stark.png new file mode 100644 index 000000000..67563fdf4 Binary files /dev/null and b/docs/img/zkEVM/13prf-rec-convert-zkevm-verifier-to-stark.png differ diff --git a/docs/img/zkEVM/14prf-rec-convert-stark-to-circuit-verifier.png b/docs/img/zkEVM/14prf-rec-convert-stark-to-circuit-verifier.png new file mode 100644 index 000000000..7aee69de8 Binary files /dev/null and b/docs/img/zkEVM/14prf-rec-convert-stark-to-circuit-verifier.png differ diff --git a/docs/img/zkEVM/15prf-rec-convert-circuit-to-assoc-stark.png b/docs/img/zkEVM/15prf-rec-convert-circuit-to-assoc-stark.png new file mode 100644 index 000000000..590ca191e Binary files /dev/null and b/docs/img/zkEVM/15prf-rec-convert-circuit-to-assoc-stark.png differ diff --git a/docs/img/zkEVM/16prf-rec-recursive2-circuit.png b/docs/img/zkEVM/16prf-rec-recursive2-circuit.png new file mode 100644 index 000000000..1d3737c41 Binary files /dev/null and b/docs/img/zkEVM/16prf-rec-recursive2-circuit.png differ diff --git a/docs/img/zkEVM/17pil2-table-proga-progb-perm-args-1st-eg-table.png b/docs/img/zkEVM/17pil2-table-proga-progb-perm-args-1st-eg-table.png new file mode 100644 index 000000000..08f853a9b Binary files /dev/null and b/docs/img/zkEVM/17pil2-table-proga-progb-perm-args-1st-eg-table.png differ diff --git a/docs/img/zkEVM/17prf-rec-stark-to-circuit-recursive2.png b/docs/img/zkEVM/17prf-rec-stark-to-circuit-recursive2.png new file mode 100644 index 000000000..eae909b56 Binary files /dev/null and b/docs/img/zkEVM/17prf-rec-stark-to-circuit-recursive2.png differ diff --git a/docs/img/zkEVM/18pil2-two-table-proga-progb-exec-traces.png b/docs/img/zkEVM/18pil2-two-table-proga-progb-exec-traces.png new file mode 100644 index 000000000..1f0a0897e Binary files /dev/null and b/docs/img/zkEVM/18pil2-two-table-proga-progb-exec-traces.png differ diff --git a/docs/img/zkEVM/18prf-rec-recursive2-circuit-2-stark.png b/docs/img/zkEVM/18prf-rec-recursive2-circuit-2-stark.png new file mode 100644 index 000000000..b0e33de2c Binary files /dev/null and b/docs/img/zkEVM/18prf-rec-recursive2-circuit-2-stark.png differ diff --git a/docs/img/zkEVM/19prf-rec-recursive2-stark-to-recursivef-circuit.png b/docs/img/zkEVM/19prf-rec-recursive2-stark-to-recursivef-circuit.png new file mode 100644 index 000000000..9dc16b497 Binary files /dev/null and b/docs/img/zkEVM/19prf-rec-recursive2-stark-to-recursivef-circuit.png differ diff --git a/docs/img/zkEVM/20prf-rec-recursivef-circuit-2-stark.png b/docs/img/zkEVM/20prf-rec-recursivef-circuit-2-stark.png new file mode 100644 index 000000000..062e4cba0 Binary files /dev/null and b/docs/img/zkEVM/20prf-rec-recursivef-circuit-2-stark.png differ diff --git a/docs/img/zkEVM/21pil2-exec-trace-connection-arg.png b/docs/img/zkEVM/21pil2-exec-trace-connection-arg.png new file mode 100644 index 000000000..8d5e19db9 Binary files /dev/null and b/docs/img/zkEVM/21pil2-exec-trace-connection-arg.png differ diff --git a/docs/img/zkEVM/21prf-rec-recursivef-stark-to-final-circom.png b/docs/img/zkEVM/21prf-rec-recursivef-stark-to-final-circom.png new file mode 100644 index 000000000..29b9daff6 Binary files /dev/null and b/docs/img/zkEVM/21prf-rec-recursivef-stark-to-final-circom.png differ diff --git a/docs/img/zkEVM/22pil2-multi-column-connection-arg.png b/docs/img/zkEVM/22pil2-multi-column-connection-arg.png new file mode 100644 index 000000000..d6ade2498 Binary files /dev/null and b/docs/img/zkEVM/22pil2-multi-column-connection-arg.png differ diff --git a/docs/img/zkEVM/22prf-rec-generation-stark-proof-for-recursivef.png b/docs/img/zkEVM/22prf-rec-generation-stark-proof-for-recursivef.png new file mode 100644 index 000000000..e89c6e603 Binary files /dev/null and b/docs/img/zkEVM/22prf-rec-generation-stark-proof-for-recursivef.png differ diff --git a/docs/img/zkEVM/23prf-rec-generation-stark-proof-for-c12.png b/docs/img/zkEVM/23prf-rec-generation-stark-proof-for-c12.png new file mode 100644 index 000000000..92b876e13 Binary files /dev/null and b/docs/img/zkEVM/23prf-rec-generation-stark-proof-for-c12.png differ diff --git a/docs/img/zkEVM/24pil2-plonk-like-circuit.png b/docs/img/zkEVM/24pil2-plonk-like-circuit.png new file mode 100644 index 000000000..c37832aa5 Binary files /dev/null and b/docs/img/zkEVM/24pil2-plonk-like-circuit.png differ diff --git a/docs/img/zkEVM/24prf-rec-generation-stark-proof-for-recursive1.png b/docs/img/zkEVM/24prf-rec-generation-stark-proof-for-recursive1.png new file mode 100644 index 000000000..9caa53d00 Binary files /dev/null and b/docs/img/zkEVM/24prf-rec-generation-stark-proof-for-recursive1.png differ diff --git a/docs/img/zkEVM/25pil2-exec-circuit-plonk-like-circuit.png b/docs/img/zkEVM/25pil2-exec-circuit-plonk-like-circuit.png new file mode 100644 index 000000000..c5d0f8995 Binary files /dev/null and b/docs/img/zkEVM/25pil2-exec-circuit-plonk-like-circuit.png differ diff --git a/docs/img/zkEVM/25prf-rec-generation-stark-proof-for-recursive2.png b/docs/img/zkEVM/25prf-rec-generation-stark-proof-for-recursive2.png new file mode 100644 index 000000000..ae8c2448f Binary files /dev/null and b/docs/img/zkEVM/25prf-rec-generation-stark-proof-for-recursive2.png differ diff --git a/docs/img/zkEVM/26prf-rec-generation-zkevm-proof.png b/docs/img/zkEVM/26prf-rec-generation-zkevm-proof.png new file mode 100644 index 000000000..310a3f4f9 Binary files /dev/null and b/docs/img/zkEVM/26prf-rec-generation-zkevm-proof.png differ diff --git a/docs/img/zkEVM/CPU.png b/docs/img/zkEVM/CPU.png new file mode 100644 index 000000000..3c2bc1919 Binary files /dev/null and b/docs/img/zkEVM/CPU.png differ diff --git a/docs/img/zkEVM/big-picture.png b/docs/img/zkEVM/big-picture.png new file mode 100644 index 000000000..06c0cde83 Binary files /dev/null and b/docs/img/zkEVM/big-picture.png differ diff --git a/docs/img/zkEVM/fib10-pil-eg-mfibonacci.png b/docs/img/zkEVM/fib10-pil-eg-mfibonacci.png new file mode 100644 index 000000000..b83cc1d8e Binary files /dev/null and b/docs/img/zkEVM/fib10-pil-eg-mfibonacci.png differ diff --git a/docs/img/zkEVM/fib11-pilcom-res-mfibon.png b/docs/img/zkEVM/fib11-pilcom-res-mfibon.png new file mode 100644 index 000000000..c1aa531ef Binary files /dev/null and b/docs/img/zkEVM/fib11-pilcom-res-mfibon.png differ diff --git a/docs/img/zkEVM/fib12-inside-parsed-pil.png b/docs/img/zkEVM/fib12-inside-parsed-pil.png new file mode 100644 index 000000000..e1bd78d77 Binary files /dev/null and b/docs/img/zkEVM/fib12-inside-parsed-pil.png differ diff --git a/docs/img/zkEVM/fib13-pil-stark-setup.png b/docs/img/zkEVM/fib13-pil-stark-setup.png new file mode 100644 index 000000000..3d9ad5e32 Binary files /dev/null and b/docs/img/zkEVM/fib13-pil-stark-setup.png differ diff --git a/docs/img/zkEVM/fib14-pil-stark-in-prover.png b/docs/img/zkEVM/fib14-pil-stark-in-prover.png new file mode 100644 index 000000000..cde8c9d49 Binary files /dev/null and b/docs/img/zkEVM/fib14-pil-stark-in-prover.png differ diff --git a/docs/img/zkEVM/fib15-pil-stark-in-verifier.png b/docs/img/zkEVM/fib15-pil-stark-in-verifier.png new file mode 100644 index 000000000..d33144358 Binary files /dev/null and b/docs/img/zkEVM/fib15-pil-stark-in-verifier.png differ diff --git a/docs/img/zkEVM/fib17-mfib-pil-w-pubs.png b/docs/img/zkEVM/fib17-mfib-pil-w-pubs.png new file mode 100644 index 000000000..3debc99c0 Binary files /dev/null and b/docs/img/zkEVM/fib17-mfib-pil-w-pubs.png differ diff --git a/docs/img/zkEVM/fib18-non-empt-pubs-field.png b/docs/img/zkEVM/fib18-non-empt-pubs-field.png new file mode 100644 index 000000000..9d0d7499a Binary files /dev/null and b/docs/img/zkEVM/fib18-non-empt-pubs-field.png differ diff --git a/docs/img/zkEVM/fib19-init-node-project.png b/docs/img/zkEVM/fib19-init-node-project.png new file mode 100644 index 000000000..296dcc28a Binary files /dev/null and b/docs/img/zkEVM/fib19-init-node-project.png differ diff --git a/docs/img/zkEVM/fib20-dependncs-install-mfib.png b/docs/img/zkEVM/fib20-dependncs-install-mfib.png new file mode 100644 index 000000000..e8ab1e62c Binary files /dev/null and b/docs/img/zkEVM/fib20-dependncs-install-mfib.png differ diff --git a/docs/img/zkEVM/fib4-deterministic-compt.png b/docs/img/zkEVM/fib4-deterministic-compt.png new file mode 100644 index 000000000..e7b0247fa Binary files /dev/null and b/docs/img/zkEVM/fib4-deterministic-compt.png differ diff --git a/docs/img/zkEVM/fib5-design-approach-outline.png b/docs/img/zkEVM/fib5-design-approach-outline.png new file mode 100644 index 000000000..8c03a8cde Binary files /dev/null and b/docs/img/zkEVM/fib5-design-approach-outline.png differ diff --git a/docs/img/zkEVM/fib6-mfibon-sm-2-regs.png b/docs/img/zkEVM/fib6-mfibon-sm-2-regs.png new file mode 100644 index 000000000..dbad6d04c Binary files /dev/null and b/docs/img/zkEVM/fib6-mfibon-sm-2-regs.png differ diff --git a/docs/img/zkEVM/fib7-mfibon-sm-3-regs.png b/docs/img/zkEVM/fib7-mfibon-sm-3-regs.png new file mode 100644 index 000000000..47ce47e40 Binary files /dev/null and b/docs/img/zkEVM/fib7-mfibon-sm-3-regs.png differ diff --git a/docs/img/zkEVM/fib8-code-eg-exec-trace.png b/docs/img/zkEVM/fib8-code-eg-exec-trace.png new file mode 100644 index 000000000..925dba595 Binary files /dev/null and b/docs/img/zkEVM/fib8-code-eg-exec-trace.png differ diff --git a/docs/img/zkEVM/fib9-stark-prf-sizes-times.png b/docs/img/zkEVM/fib9-stark-prf-sizes-times.png new file mode 100644 index 000000000..da0b77ce2 Binary files /dev/null and b/docs/img/zkEVM/fib9-stark-prf-sizes-times.png differ diff --git a/docs/img/zkEVM/fig-micro-pro-pic.png b/docs/img/zkEVM/fig-micro-pro-pic.png new file mode 100644 index 000000000..ac4b75ad5 Binary files /dev/null and b/docs/img/zkEVM/fig-micro-pro-pic.png differ diff --git a/docs/img/zkEVM/fig1-gen-state-mchn.png b/docs/img/zkEVM/fig1-gen-state-mchn.png new file mode 100644 index 000000000..7af1f1b5d Binary files /dev/null and b/docs/img/zkEVM/fig1-gen-state-mchn.png differ diff --git a/docs/img/zkEVM/fig1-simpl-arch.png b/docs/img/zkEVM/fig1-simpl-arch.png new file mode 100644 index 000000000..9ccaa9b6f Binary files /dev/null and b/docs/img/zkEVM/fig1-simpl-arch.png differ diff --git a/docs/img/zkEVM/fig1-zkprv-and-node.png b/docs/img/zkEVM/fig1-zkprv-and-node.png new file mode 100644 index 000000000..cc9403041 Binary files /dev/null and b/docs/img/zkEVM/fig1-zkprv-and-node.png differ diff --git a/docs/img/zkEVM/fig10-key-not-set-eg.png b/docs/img/zkEVM/fig10-key-not-set-eg.png new file mode 100644 index 000000000..1c7d5793f Binary files /dev/null and b/docs/img/zkEVM/fig10-key-not-set-eg.png differ diff --git a/docs/img/zkEVM/fig11-val-update-eg.png b/docs/img/zkEVM/fig11-val-update-eg.png new file mode 100644 index 000000000..ed37fb552 Binary files /dev/null and b/docs/img/zkEVM/fig11-val-update-eg.png differ diff --git a/docs/img/zkEVM/fig12-crt-zero-node.png b/docs/img/zkEVM/fig12-crt-zero-node.png new file mode 100644 index 000000000..1ab2123fa Binary files /dev/null and b/docs/img/zkEVM/fig12-crt-zero-node.png differ diff --git a/docs/img/zkEVM/fig13-a-crt-nzleaf-ext.png b/docs/img/zkEVM/fig13-a-crt-nzleaf-ext.png new file mode 100644 index 000000000..5818907a8 Binary files /dev/null and b/docs/img/zkEVM/fig13-a-crt-nzleaf-ext.png differ diff --git a/docs/img/zkEVM/fig13-b-crt-nzleaf-xt.png b/docs/img/zkEVM/fig13-b-crt-nzleaf-xt.png new file mode 100644 index 000000000..6c5af2c53 Binary files /dev/null and b/docs/img/zkEVM/fig13-b-crt-nzleaf-xt.png differ diff --git a/docs/img/zkEVM/fig14-a-dlt-nz-sib.png b/docs/img/zkEVM/fig14-a-dlt-nz-sib.png new file mode 100644 index 000000000..e81b3d024 Binary files /dev/null and b/docs/img/zkEVM/fig14-a-dlt-nz-sib.png differ diff --git a/docs/img/zkEVM/fig14-b-dlt-z-sib.png b/docs/img/zkEVM/fig14-b-dlt-z-sib.png new file mode 100644 index 000000000..2cc6b4f90 Binary files /dev/null and b/docs/img/zkEVM/fig14-b-dlt-z-sib.png differ diff --git a/docs/img/zkEVM/fig15-path-frm-key.png b/docs/img/zkEVM/fig15-path-frm-key.png new file mode 100644 index 000000000..76c52b454 Binary files /dev/null and b/docs/img/zkEVM/fig15-path-frm-key.png differ diff --git a/docs/img/zkEVM/fig16-posdn-eg.png b/docs/img/zkEVM/fig16-posdn-eg.png new file mode 100644 index 000000000..f44127caf Binary files /dev/null and b/docs/img/zkEVM/fig16-posdn-eg.png differ diff --git a/docs/img/zkEVM/fig2-actions-sec-sm.png b/docs/img/zkEVM/fig2-actions-sec-sm.png new file mode 100644 index 000000000..59972480b Binary files /dev/null and b/docs/img/zkEVM/fig2-actions-sec-sm.png differ diff --git a/docs/img/zkEVM/fig2-mkl-tree-gen.png b/docs/img/zkEVM/fig2-mkl-tree-gen.png new file mode 100644 index 000000000..d7c4d9eb9 Binary files /dev/null and b/docs/img/zkEVM/fig2-mkl-tree-gen.png differ diff --git a/docs/img/zkvm/fig2-simple-poe.png b/docs/img/zkEVM/fig2-simple-poe.png similarity index 100% rename from docs/img/zkvm/fig2-simple-poe.png rename to docs/img/zkEVM/fig2-simple-poe.png diff --git a/docs/img/zkEVM/fig3-zkNode-arch.png b/docs/img/zkEVM/fig3-zkNode-arch.png new file mode 100644 index 000000000..b8a54eb28 Binary files /dev/null and b/docs/img/zkEVM/fig3-zkNode-arch.png differ diff --git a/docs/img/zkEVM/fig4-sngl-kv-eg.png b/docs/img/zkEVM/fig4-sngl-kv-eg.png new file mode 100644 index 000000000..9d2e3cf18 Binary files /dev/null and b/docs/img/zkEVM/fig4-sngl-kv-eg.png differ diff --git a/docs/img/zkvm/fig4-zkProv-arch.png b/docs/img/zkEVM/fig4-zkProv-arch.png similarity index 100% rename from docs/img/zkvm/fig4-zkProv-arch.png rename to docs/img/zkEVM/fig4-zkProv-arch.png diff --git a/docs/img/zkEVM/fig5-a-mpt-kv-eg.png b/docs/img/zkEVM/fig5-a-mpt-kv-eg.png new file mode 100644 index 000000000..751dc143e Binary files /dev/null and b/docs/img/zkEVM/fig5-a-mpt-kv-eg.png differ diff --git a/docs/img/zkEVM/fig5-b-mpt-kv-eg.png b/docs/img/zkEVM/fig5-b-mpt-kv-eg.png new file mode 100644 index 000000000..f52cef753 Binary files /dev/null and b/docs/img/zkEVM/fig5-b-mpt-kv-eg.png differ diff --git a/docs/img/zkEVM/fig5-c-mpt-kv-eg.png b/docs/img/zkEVM/fig5-c-mpt-kv-eg.png new file mode 100644 index 000000000..86f335eef Binary files /dev/null and b/docs/img/zkEVM/fig5-c-mpt-kv-eg.png differ diff --git a/docs/img/zkEVM/fig5-main-prts-zkpr.png b/docs/img/zkEVM/fig5-main-prts-zkpr.png new file mode 100644 index 000000000..aebb54d02 Binary files /dev/null and b/docs/img/zkEVM/fig5-main-prts-zkpr.png differ diff --git a/docs/img/zkEVM/fig6-mpt-gen-eg.png b/docs/img/zkEVM/fig6-mpt-gen-eg.png new file mode 100644 index 000000000..13abf5329 Binary files /dev/null and b/docs/img/zkEVM/fig6-mpt-gen-eg.png differ diff --git a/docs/img/zkEVM/fig7-fake-leaf-eg.png b/docs/img/zkEVM/fig7-fake-leaf-eg.png new file mode 100644 index 000000000..1e6d5a888 Binary files /dev/null and b/docs/img/zkEVM/fig7-fake-leaf-eg.png differ diff --git a/docs/img/zkEVM/fig8-non-binding-eg.png b/docs/img/zkEVM/fig8-non-binding-eg.png new file mode 100644 index 000000000..e6916a042 Binary files /dev/null and b/docs/img/zkEVM/fig8-non-binding-eg.png differ diff --git a/docs/img/zkEVM/fig9-zk-mkl-prf.png b/docs/img/zkEVM/fig9-zk-mkl-prf.png new file mode 100644 index 000000000..1467b56d8 Binary files /dev/null and b/docs/img/zkEVM/fig9-zk-mkl-prf.png differ diff --git a/docs/img/zkvm/flatten-code-remix.png b/docs/img/zkEVM/flatten-code-remix.png similarity index 100% rename from docs/img/zkvm/flatten-code-remix.png rename to docs/img/zkEVM/flatten-code-remix.png diff --git a/docs/img/zkEVM/gen1-typical-gen-sm.png b/docs/img/zkEVM/gen1-typical-gen-sm.png new file mode 100644 index 000000000..fc25a7cf7 Binary files /dev/null and b/docs/img/zkEVM/gen1-typical-gen-sm.png differ diff --git a/docs/img/zkEVM/gen2-mfib-exec-w-inputs.png b/docs/img/zkEVM/gen2-mfib-exec-w-inputs.png new file mode 100644 index 000000000..2565aa856 Binary files /dev/null and b/docs/img/zkEVM/gen2-mfib-exec-w-inputs.png differ diff --git a/docs/img/zkEVM/gen3-gen-sm-w-input-instrctn.png b/docs/img/zkEVM/gen3-gen-sm-w-input-instrctn.png new file mode 100644 index 000000000..ee89e5562 Binary files /dev/null and b/docs/img/zkEVM/gen3-gen-sm-w-input-instrctn.png differ diff --git a/docs/img/zkEVM/gen4-sm-alg-processor.png b/docs/img/zkEVM/gen4-sm-alg-processor.png new file mode 100644 index 000000000..d1ec16907 Binary files /dev/null and b/docs/img/zkEVM/gen4-sm-alg-processor.png differ diff --git a/docs/img/zkEVM/gen5-sm-exec-broader-contxt.png b/docs/img/zkEVM/gen5-sm-exec-broader-contxt.png new file mode 100644 index 000000000..91a7dd4b6 Binary files /dev/null and b/docs/img/zkEVM/gen5-sm-exec-broader-contxt.png differ diff --git a/docs/img/zkEVM/gen6-pil-4instrct-prog.png b/docs/img/zkEVM/gen6-pil-4instrct-prog.png new file mode 100644 index 000000000..0e3875bcb Binary files /dev/null and b/docs/img/zkEVM/gen6-pil-4instrct-prog.png differ diff --git a/docs/img/zkEVM/gen7-state-machine-w-zkpc.png b/docs/img/zkEVM/gen7-state-machine-w-zkpc.png new file mode 100644 index 000000000..c136465dd Binary files /dev/null and b/docs/img/zkEVM/gen7-state-machine-w-zkpc.png differ diff --git a/docs/img/zkEVM/gen8-end-prog-w-loop.png b/docs/img/zkEVM/gen8-end-prog-w-loop.png new file mode 100644 index 000000000..34cfe4d09 Binary files /dev/null and b/docs/img/zkEVM/gen8-end-prog-w-loop.png differ diff --git a/docs/img/zkEVM/governance-tree.png b/docs/img/zkEVM/governance-tree.png new file mode 100644 index 000000000..8bb067836 Binary files /dev/null and b/docs/img/zkEVM/governance-tree.png differ diff --git a/docs/img/zkEVM/hsh01-sponge-construction.png b/docs/img/zkEVM/hsh01-sponge-construction.png new file mode 100644 index 000000000..a541f0422 Binary files /dev/null and b/docs/img/zkEVM/hsh01-sponge-construction.png differ diff --git a/docs/img/zkEVM/hsh02-sm-kk-framework.png b/docs/img/zkEVM/hsh02-sm-kk-framework.png new file mode 100644 index 000000000..64e1164e4 Binary files /dev/null and b/docs/img/zkEVM/hsh02-sm-kk-framework.png differ diff --git a/docs/img/zkEVM/lxly-1-v1-asset-transfer.png b/docs/img/zkEVM/lxly-1-v1-asset-transfer.png new file mode 100644 index 000000000..caa3472b7 Binary files /dev/null and b/docs/img/zkEVM/lxly-1-v1-asset-transfer.png differ diff --git a/docs/img/zkEVM/lxly-2-new-bridge-design.png b/docs/img/zkEVM/lxly-2-new-bridge-design.png new file mode 100644 index 000000000..6ba71d53c Binary files /dev/null and b/docs/img/zkEVM/lxly-2-new-bridge-design.png differ diff --git a/docs/img/zkEVM/lxly-3-flow-rollupmanager.png b/docs/img/zkEVM/lxly-3-flow-rollupmanager.png new file mode 100644 index 000000000..27763b222 Binary files /dev/null and b/docs/img/zkEVM/lxly-3-flow-rollupmanager.png differ diff --git a/docs/img/zkEVM/machine-cycle.png b/docs/img/zkEVM/machine-cycle.png new file mode 100644 index 000000000..7712f08b8 Binary files /dev/null and b/docs/img/zkEVM/machine-cycle.png differ diff --git a/docs/img/zkEVM/plook-ops-mainSM-copy.png b/docs/img/zkEVM/plook-ops-mainSM-copy.png new file mode 100644 index 000000000..f6390a529 Binary files /dev/null and b/docs/img/zkEVM/plook-ops-mainSM-copy.png differ diff --git a/docs/img/zkEVM/plook-ops-mainSM.png b/docs/img/zkEVM/plook-ops-mainSM.png new file mode 100644 index 000000000..f6390a529 Binary files /dev/null and b/docs/img/zkEVM/plook-ops-mainSM.png differ diff --git a/docs/img/zkEVM/plookup-generic-sm-pil.png b/docs/img/zkEVM/plookup-generic-sm-pil.png new file mode 100644 index 000000000..a7243807c Binary files /dev/null and b/docs/img/zkEVM/plookup-generic-sm-pil.png differ diff --git a/docs/img/zkEVM/security-council-overview.png b/docs/img/zkEVM/security-council-overview.png new file mode 100644 index 000000000..fd4e61341 Binary files /dev/null and b/docs/img/zkEVM/security-council-overview.png differ diff --git a/docs/img/zkEVM/sm-topology-1.png b/docs/img/zkEVM/sm-topology-1.png new file mode 100644 index 000000000..0677ebe4d Binary files /dev/null and b/docs/img/zkEVM/sm-topology-1.png differ diff --git a/docs/img/zkEVM/sm-topology-2.png b/docs/img/zkEVM/sm-topology-2.png new file mode 100644 index 000000000..ee6953906 Binary files /dev/null and b/docs/img/zkEVM/sm-topology-2.png differ diff --git a/docs/img/zkEVM/sm-topology-3.png b/docs/img/zkEVM/sm-topology-3.png new file mode 100644 index 000000000..3f6423dd7 Binary files /dev/null and b/docs/img/zkEVM/sm-topology-3.png differ diff --git a/docs/img/zkEVM/tup-pattern.png b/docs/img/zkEVM/tup-pattern.png new file mode 100644 index 000000000..abfd3427b Binary files /dev/null and b/docs/img/zkEVM/tup-pattern.png differ diff --git a/docs/img/zkvm/tutorial.mp4 b/docs/img/zkEVM/tutorial.mp4 similarity index 100% rename from docs/img/zkvm/tutorial.mp4 rename to docs/img/zkEVM/tutorial.mp4 diff --git a/docs/img/zkEVM/upgrade-overview.png b/docs/img/zkEVM/upgrade-overview.png new file mode 100644 index 000000000..c47ffe447 Binary files /dev/null and b/docs/img/zkEVM/upgrade-overview.png differ diff --git a/docs/img/zkvm/zkevmwallettestnet.mp4 b/docs/img/zkEVM/zkevmwallettestnet.mp4 similarity index 100% rename from docs/img/zkvm/zkevmwallettestnet.mp4 rename to docs/img/zkEVM/zkevmwallettestnet.mp4 diff --git a/docs/img/zkEVM/zkv-bridge2.jpg b/docs/img/zkEVM/zkv-bridge2.jpg new file mode 100644 index 000000000..82858d424 Binary files /dev/null and b/docs/img/zkEVM/zkv-bridge2.jpg differ diff --git a/docs/img/zkvm/zkv-confirm-zketh.png b/docs/img/zkEVM/zkv-confirm-zketh.png similarity index 100% rename from docs/img/zkvm/zkv-confirm-zketh.png rename to docs/img/zkEVM/zkv-confirm-zketh.png diff --git a/docs/img/zkvm/zkv-end-product-nft-code.png b/docs/img/zkEVM/zkv-end-product-nft-code.png similarity index 100% rename from docs/img/zkvm/zkv-end-product-nft-code.png rename to docs/img/zkEVM/zkv-end-product-nft-code.png diff --git a/docs/img/zkEVM/zkv-faucet-zketh.png b/docs/img/zkEVM/zkv-faucet-zketh.png new file mode 100644 index 000000000..2bf564e46 Binary files /dev/null and b/docs/img/zkEVM/zkv-faucet-zketh.png differ diff --git a/docs/img/zkEVM/zkv-metamask1.jpg b/docs/img/zkEVM/zkv-metamask1.jpg new file mode 100644 index 000000000..e445fad46 Binary files /dev/null and b/docs/img/zkEVM/zkv-metamask1.jpg differ diff --git a/docs/img/zkEVM/zkv-proj-created-outcome.png b/docs/img/zkEVM/zkv-proj-created-outcome.png new file mode 100644 index 000000000..c059d37f4 Binary files /dev/null and b/docs/img/zkEVM/zkv-proj-created-outcome.png differ diff --git a/docs/img/zkEVM/zkv-success-deploy-sbtdotsol.png b/docs/img/zkEVM/zkv-success-deploy-sbtdotsol.png new file mode 100644 index 000000000..5b24bd109 Binary files /dev/null and b/docs/img/zkEVM/zkv-success-deploy-sbtdotsol.png differ diff --git a/docs/img/zkEVM/zkv-success-forge-build.png b/docs/img/zkEVM/zkv-success-forge-build.png new file mode 100644 index 000000000..4668b9f2e Binary files /dev/null and b/docs/img/zkEVM/zkv-success-forge-build.png differ diff --git a/docs/img/zkEVM/zkv-success-zketh.png b/docs/img/zkEVM/zkv-success-zketh.png new file mode 100644 index 000000000..d9006b526 Binary files /dev/null and b/docs/img/zkEVM/zkv-success-zketh.png differ diff --git a/docs/img/zkEVM/zkv-test-forge-build.png b/docs/img/zkEVM/zkv-test-forge-build.png new file mode 100644 index 000000000..412dd728a Binary files /dev/null and b/docs/img/zkEVM/zkv-test-forge-build.png differ diff --git a/docs/img/zkEVM/zkv-transaction-history.jpg b/docs/img/zkEVM/zkv-transaction-history.jpg new file mode 100644 index 000000000..4c3426263 Binary files /dev/null and b/docs/img/zkEVM/zkv-transaction-history.jpg differ diff --git a/docs/img/zkEVM/zkv-zkwallet-1.jpg b/docs/img/zkEVM/zkv-zkwallet-1.jpg new file mode 100644 index 000000000..0c91ac498 Binary files /dev/null and b/docs/img/zkEVM/zkv-zkwallet-1.jpg differ diff --git a/docs/img/zkvm/01L2-overview-l2-state-management.png b/docs/img/zkvm/01L2-overview-l2-state-management.png deleted file mode 100644 index 3d66e1784..000000000 Binary files a/docs/img/zkvm/01L2-overview-l2-state-management.png and /dev/null differ diff --git a/docs/img/zkvm/01arith-sch-mlt-eg.png b/docs/img/zkvm/01arith-sch-mlt-eg.png deleted file mode 100644 index 370a1fa0f..000000000 Binary files a/docs/img/zkvm/01arith-sch-mlt-eg.png and /dev/null differ diff --git a/docs/img/zkvm/01b2f-44-2-one-multiplex.png b/docs/img/zkvm/01b2f-44-2-one-multiplex.png deleted file mode 100644 index 9bac6db70..000000000 Binary files a/docs/img/zkvm/01b2f-44-2-one-multiplex.png and /dev/null differ diff --git a/docs/img/zkvm/01bin-cdfctn-3bit-strngs.png b/docs/img/zkvm/01bin-cdfctn-3bit-strngs.png deleted file mode 100644 index 1c274c53f..000000000 Binary files a/docs/img/zkvm/01bin-cdfctn-3bit-strngs.png and /dev/null differ diff --git a/docs/img/zkvm/01circom-witness-zkprover.png b/docs/img/zkvm/01circom-witness-zkprover.png deleted file mode 100755 index b54f46298..000000000 Binary files a/docs/img/zkvm/01circom-witness-zkprover.png and /dev/null differ diff --git a/docs/img/zkvm/01kkb-chunk-divs-136-bytes.png b/docs/img/zkvm/01kkb-chunk-divs-136-bytes.png deleted file mode 100644 index 199931390..000000000 Binary files a/docs/img/zkvm/01kkb-chunk-divs-136-bytes.png and /dev/null differ diff --git a/docs/img/zkvm/01kkf-state-array-calibrated.png b/docs/img/zkvm/01kkf-state-array-calibrated.png deleted file mode 100644 index 3cee8d97e..000000000 Binary files a/docs/img/zkvm/01kkf-state-array-calibrated.png and /dev/null differ diff --git a/docs/img/zkvm/01mem-align-schm-mld-eg.png b/docs/img/zkvm/01mem-align-schm-mld-eg.png deleted file mode 100644 index b9e5d4ba0..000000000 Binary files a/docs/img/zkvm/01mem-align-schm-mld-eg.png and /dev/null differ diff --git a/docs/img/zkvm/01mem-fig-exec-trc.png b/docs/img/zkvm/01mem-fig-exec-trc.png deleted file mode 100644 index 72a916b43..000000000 Binary files a/docs/img/zkvm/01mem-fig-exec-trc.png and /dev/null differ diff --git a/docs/img/zkvm/01msm-evm-components.png b/docs/img/zkvm/01msm-evm-components.png deleted file mode 100644 index 0c45ad9df..000000000 Binary files a/docs/img/zkvm/01msm-evm-components.png and /dev/null differ diff --git a/docs/img/zkvm/01pkk-input-strings-allocate.png b/docs/img/zkvm/01pkk-input-strings-allocate.png deleted file mode 100644 index 428f424d7..000000000 Binary files a/docs/img/zkvm/01pkk-input-strings-allocate.png and /dev/null differ diff --git a/docs/img/zkvm/01prf-rec-pil-stark.png b/docs/img/zkvm/01prf-rec-pil-stark.png deleted file mode 100644 index 82c75e24c..000000000 Binary files a/docs/img/zkvm/01prf-rec-pil-stark.png and /dev/null differ diff --git a/docs/img/zkvm/01psd-hades-based-poseidon-perm.png b/docs/img/zkvm/01psd-hades-based-poseidon-perm.png deleted file mode 100644 index c703614b7..000000000 Binary files a/docs/img/zkvm/01psd-hades-based-poseidon-perm.png and /dev/null differ diff --git a/docs/img/zkvm/01pzb-polygon-zkevm-schema.png b/docs/img/zkvm/01pzb-polygon-zkevm-schema.png deleted file mode 100644 index 9021efc96..000000000 Binary files a/docs/img/zkvm/01pzb-polygon-zkevm-schema.png and /dev/null differ diff --git a/docs/img/zkvm/02b2f-44-bits-to-64bit-fe.png b/docs/img/zkvm/02b2f-44-bits-to-64bit-fe.png deleted file mode 100644 index 2bdf9d2ee..000000000 Binary files a/docs/img/zkvm/02b2f-44-bits-to-64bit-fe.png and /dev/null differ diff --git a/docs/img/zkvm/02bin-trth-tbls-bitws.png b/docs/img/zkvm/02bin-trth-tbls-bitws.png deleted file mode 100644 index 4b764ec7f..000000000 Binary files a/docs/img/zkvm/02bin-trth-tbls-bitws.png and /dev/null differ diff --git a/docs/img/zkvm/02circom-overall-context.png b/docs/img/zkvm/02circom-overall-context.png deleted file mode 100755 index 2f3f9bf08..000000000 Binary files a/docs/img/zkvm/02circom-overall-context.png and /dev/null differ diff --git a/docs/img/zkvm/02kkb-pad-kk-bit-to-kk-f.png b/docs/img/zkvm/02kkb-pad-kk-bit-to-kk-f.png deleted file mode 100644 index 6ae484e62..000000000 Binary files a/docs/img/zkvm/02kkb-pad-kk-bit-to-kk-f.png and /dev/null differ diff --git a/docs/img/zkvm/02kkf-theta-map-one-bit.png b/docs/img/zkvm/02kkf-theta-map-one-bit.png deleted file mode 100644 index b118cf4e6..000000000 Binary files a/docs/img/zkvm/02kkf-theta-map-one-bit.png and /dev/null differ diff --git a/docs/img/zkvm/02l2-l2-state-timeline.png b/docs/img/zkvm/02l2-l2-state-timeline.png deleted file mode 100644 index ced5347c1..000000000 Binary files a/docs/img/zkvm/02l2-l2-state-timeline.png and /dev/null differ diff --git a/docs/img/zkvm/02mem-align-schm-mstr-eg.png b/docs/img/zkvm/02mem-align-schm-mstr-eg.png deleted file mode 100644 index cb46eb9eb..000000000 Binary files a/docs/img/zkvm/02mem-align-schm-mstr-eg.png and /dev/null differ diff --git a/docs/img/zkvm/02msm-prover-structure.png b/docs/img/zkvm/02msm-prover-structure.png deleted file mode 100644 index 6b483241d..000000000 Binary files a/docs/img/zkvm/02msm-prover-structure.png and /dev/null differ diff --git a/docs/img/zkvm/02prf-rec-simple-composition.png b/docs/img/zkvm/02prf-rec-simple-composition.png deleted file mode 100644 index b17ce6580..000000000 Binary files a/docs/img/zkvm/02prf-rec-simple-composition.png and /dev/null differ diff --git a/docs/img/zkvm/02psd-poseidon-hash-pic.png b/docs/img/zkvm/02psd-poseidon-hash-pic.png deleted file mode 100644 index ce1ca9e0b..000000000 Binary files a/docs/img/zkvm/02psd-poseidon-hash-pic.png and /dev/null differ diff --git a/docs/img/zkvm/02pzb-global-exit-tree.png b/docs/img/zkvm/02pzb-global-exit-tree.png deleted file mode 100644 index b64097a49..000000000 Binary files a/docs/img/zkvm/02pzb-global-exit-tree.png and /dev/null differ diff --git a/docs/img/zkvm/03circom-simple-arith-circuit.png b/docs/img/zkvm/03circom-simple-arith-circuit.png deleted file mode 100755 index 8fd4bbaf2..000000000 Binary files a/docs/img/zkvm/03circom-simple-arith-circuit.png and /dev/null differ diff --git a/docs/img/zkvm/03kkf-pi-stepmap-shuffle.png b/docs/img/zkvm/03kkf-pi-stepmap-shuffle.png deleted file mode 100644 index e718d1587..000000000 Binary files a/docs/img/zkvm/03kkf-pi-stepmap-shuffle.png and /dev/null differ diff --git a/docs/img/zkvm/03l2-sequencing-batches.png b/docs/img/zkvm/03l2-sequencing-batches.png deleted file mode 100644 index 3366f0967..000000000 Binary files a/docs/img/zkvm/03l2-sequencing-batches.png and /dev/null differ diff --git a/docs/img/zkvm/03msm-state-transition-gen-regs.png b/docs/img/zkvm/03msm-state-transition-gen-regs.png deleted file mode 100644 index 678987880..000000000 Binary files a/docs/img/zkvm/03msm-state-transition-gen-regs.png and /dev/null differ diff --git a/docs/img/zkvm/03prf-rec-setup-phase-rec.png b/docs/img/zkvm/03prf-rec-setup-phase-rec.png deleted file mode 100644 index bf03060c0..000000000 Binary files a/docs/img/zkvm/03prf-rec-setup-phase-rec.png and /dev/null differ diff --git a/docs/img/zkvm/03pzb-exit-leaf-add-L1-L2.png b/docs/img/zkvm/03pzb-exit-leaf-add-L1-L2.png deleted file mode 100644 index cc726c7b9..000000000 Binary files a/docs/img/zkvm/03pzb-exit-leaf-add-L1-L2.png and /dev/null differ diff --git a/docs/img/zkvm/04circom-batch-prover.png b/docs/img/zkvm/04circom-batch-prover.png deleted file mode 100755 index 87f58701f..000000000 Binary files a/docs/img/zkvm/04circom-batch-prover.png and /dev/null differ diff --git a/docs/img/zkvm/04kkf-chi-map-5bit-row.png b/docs/img/zkvm/04kkf-chi-map-5bit-row.png deleted file mode 100644 index 14a9dc057..000000000 Binary files a/docs/img/zkvm/04kkf-chi-map-5bit-row.png and /dev/null differ diff --git a/docs/img/zkvm/04l2-batch-chain-acc-hash.png b/docs/img/zkvm/04l2-batch-chain-acc-hash.png deleted file mode 100644 index 87b19b8ca..000000000 Binary files a/docs/img/zkvm/04l2-batch-chain-acc-hash.png and /dev/null differ diff --git a/docs/img/zkvm/04msm-simple-state-transition.png b/docs/img/zkvm/04msm-simple-state-transition.png deleted file mode 100644 index 86f04a6e7..000000000 Binary files a/docs/img/zkvm/04msm-simple-state-transition.png and /dev/null differ diff --git a/docs/img/zkvm/04prf-rec-proving-phase-rec.png b/docs/img/zkvm/04prf-rec-proving-phase-rec.png deleted file mode 100644 index 5939f4c15..000000000 Binary files a/docs/img/zkvm/04prf-rec-proving-phase-rec.png and /dev/null differ diff --git a/docs/img/zkvm/04pzb-overall-interact-bridge-scs.png b/docs/img/zkvm/04pzb-overall-interact-bridge-scs.png deleted file mode 100644 index ab7d3bc18..000000000 Binary files a/docs/img/zkvm/04pzb-overall-interact-bridge-scs.png and /dev/null differ diff --git a/docs/img/zkvm/05circom-forming-batch.png b/docs/img/zkvm/05circom-forming-batch.png deleted file mode 100755 index af8b6e71c..000000000 Binary files a/docs/img/zkvm/05circom-forming-batch.png and /dev/null differ diff --git a/docs/img/zkvm/05kkf-iota-rc-bits-lfsr.png b/docs/img/zkvm/05kkf-iota-rc-bits-lfsr.png deleted file mode 100644 index a1872aad0..000000000 Binary files a/docs/img/zkvm/05kkf-iota-rc-bits-lfsr.png and /dev/null differ diff --git a/docs/img/zkvm/05l2-off-chain-on-chain-trans.png b/docs/img/zkvm/05l2-off-chain-on-chain-trans.png deleted file mode 100644 index 1fe574151..000000000 Binary files a/docs/img/zkvm/05l2-off-chain-on-chain-trans.png and /dev/null differ diff --git a/docs/img/zkvm/05msm-addr-reg-contexts.png b/docs/img/zkvm/05msm-addr-reg-contexts.png deleted file mode 100644 index 0efee858a..000000000 Binary files a/docs/img/zkvm/05msm-addr-reg-contexts.png and /dev/null differ diff --git a/docs/img/zkvm/05prf-rec-binary-aggreg-eg.png b/docs/img/zkvm/05prf-rec-binary-aggreg-eg.png deleted file mode 100644 index bd0961a52..000000000 Binary files a/docs/img/zkvm/05prf-rec-binary-aggreg-eg.png and /dev/null differ diff --git a/docs/img/zkvm/05pzb-l2-related-scs.png b/docs/img/zkvm/05pzb-l2-related-scs.png deleted file mode 100644 index 03ff4fdfa..000000000 Binary files a/docs/img/zkvm/05pzb-l2-related-scs.png and /dev/null differ diff --git a/docs/img/zkvm/06circom-typical-recursive-prover.png b/docs/img/zkvm/06circom-typical-recursive-prover.png deleted file mode 100755 index cf3beaf0e..000000000 Binary files a/docs/img/zkvm/06circom-typical-recursive-prover.png and /dev/null differ diff --git a/docs/img/zkvm/06kkf-all-24-rc-hex.png b/docs/img/zkvm/06kkf-all-24-rc-hex.png deleted file mode 100644 index 925f2bcd3..000000000 Binary files a/docs/img/zkvm/06kkf-all-24-rc-hex.png and /dev/null differ diff --git a/docs/img/zkvm/06l2-actor-income-outcomes.png b/docs/img/zkvm/06l2-actor-income-outcomes.png deleted file mode 100644 index 21c2ccd1b..000000000 Binary files a/docs/img/zkvm/06l2-actor-income-outcomes.png and /dev/null differ diff --git a/docs/img/zkvm/06msm-eth-state-trie.png b/docs/img/zkvm/06msm-eth-state-trie.png deleted file mode 100644 index c5b7a1e3d..000000000 Binary files a/docs/img/zkvm/06msm-eth-state-trie.png and /dev/null differ diff --git a/docs/img/zkvm/06prf-rec-setup-s2c-detail.png b/docs/img/zkvm/06prf-rec-setup-s2c-detail.png deleted file mode 100644 index 29cb3860a..000000000 Binary files a/docs/img/zkvm/06prf-rec-setup-s2c-detail.png and /dev/null differ diff --git a/docs/img/zkvm/06pzb-complete-asset-flow-l1-l2.png b/docs/img/zkvm/06pzb-complete-asset-flow-l1-l2.png deleted file mode 100644 index 4776e80f6..000000000 Binary files a/docs/img/zkvm/06pzb-complete-asset-flow-l1-l2.png and /dev/null differ diff --git a/docs/img/zkvm/07msm-zkevm-state-trie.png b/docs/img/zkvm/07msm-zkevm-state-trie.png deleted file mode 100644 index e0485973b..000000000 Binary files a/docs/img/zkvm/07msm-zkevm-state-trie.png and /dev/null differ diff --git a/docs/img/zkvm/07prf-rec-inputs-stark-verifier-circuit.png b/docs/img/zkvm/07prf-rec-inputs-stark-verifier-circuit.png deleted file mode 100644 index 0af7d6395..000000000 Binary files a/docs/img/zkvm/07prf-rec-inputs-stark-verifier-circuit.png and /dev/null differ diff --git a/docs/img/zkvm/08l2-batches-below-time-target.png b/docs/img/zkvm/08l2-batches-below-time-target.png deleted file mode 100644 index 2eaa7542d..000000000 Binary files a/docs/img/zkvm/08l2-batches-below-time-target.png and /dev/null differ diff --git a/docs/img/zkvm/08msm-zkevm-memory-regions.png b/docs/img/zkvm/08msm-zkevm-memory-regions.png deleted file mode 100644 index 9638a7ee6..000000000 Binary files a/docs/img/zkvm/08msm-zkevm-memory-regions.png and /dev/null differ diff --git a/docs/img/zkvm/08prf-rec-setup-step-c2s.png b/docs/img/zkvm/08prf-rec-setup-step-c2s.png deleted file mode 100644 index 9e3a2e4fa..000000000 Binary files a/docs/img/zkvm/08prf-rec-setup-step-c2s.png and /dev/null differ diff --git a/docs/img/zkvm/09l2-forced-batch-seq-flow.png b/docs/img/zkvm/09l2-forced-batch-seq-flow.png deleted file mode 100644 index 8fbb4f13d..000000000 Binary files a/docs/img/zkvm/09l2-forced-batch-seq-flow.png and /dev/null differ diff --git a/docs/img/zkvm/09msm-evm-zkevm-mem-align.png b/docs/img/zkvm/09msm-evm-zkevm-mem-align.png deleted file mode 100644 index b8860a92a..000000000 Binary files a/docs/img/zkvm/09msm-evm-zkevm-mem-align.png and /dev/null differ diff --git a/docs/img/zkvm/09prf-rec-stark-prf-rec-step.png b/docs/img/zkvm/09prf-rec-stark-prf-rec-step.png deleted file mode 100644 index a8d6f0f9c..000000000 Binary files a/docs/img/zkvm/09prf-rec-stark-prf-rec-step.png and /dev/null differ diff --git a/docs/img/zkvm/10l2-diff-trustd-virtual-state.png b/docs/img/zkvm/10l2-diff-trustd-virtual-state.png deleted file mode 100644 index ed93c40ab..000000000 Binary files a/docs/img/zkvm/10l2-diff-trustd-virtual-state.png and /dev/null differ diff --git a/docs/img/zkvm/10msm-zkevm-stack-slots.png b/docs/img/zkvm/10msm-zkevm-stack-slots.png deleted file mode 100644 index c269c04e2..000000000 Binary files a/docs/img/zkvm/10msm-zkevm-stack-slots.png and /dev/null differ diff --git a/docs/img/zkvm/10prf-rec-proving-arch-outline.png b/docs/img/zkvm/10prf-rec-proving-arch-outline.png deleted file mode 100644 index bcd3b234c..000000000 Binary files a/docs/img/zkvm/10prf-rec-proving-arch-outline.png and /dev/null differ diff --git a/docs/img/zkvm/11l2-stages-timeline-pending.png b/docs/img/zkvm/11l2-stages-timeline-pending.png deleted file mode 100644 index 17bc622ed..000000000 Binary files a/docs/img/zkvm/11l2-stages-timeline-pending.png and /dev/null differ diff --git a/docs/img/zkvm/11prf-rec-build-zkevm-stark.png b/docs/img/zkvm/11prf-rec-build-zkevm-stark.png deleted file mode 100644 index eeee32128..000000000 Binary files a/docs/img/zkvm/11prf-rec-build-zkevm-stark.png and /dev/null differ diff --git a/docs/img/zkvm/12prf-rec-convert-verification-to-circuit.png b/docs/img/zkvm/12prf-rec-convert-verification-to-circuit.png deleted file mode 100644 index 3426a16fe..000000000 Binary files a/docs/img/zkvm/12prf-rec-convert-verification-to-circuit.png and /dev/null differ diff --git a/docs/img/zkvm/13prf-rec-convert-zkevm-verifier-to-stark.png b/docs/img/zkvm/13prf-rec-convert-zkevm-verifier-to-stark.png deleted file mode 100644 index ee58d8e4b..000000000 Binary files a/docs/img/zkvm/13prf-rec-convert-zkevm-verifier-to-stark.png and /dev/null differ diff --git a/docs/img/zkvm/14prf-rec-convert-stark-to-circuit-verifier.png b/docs/img/zkvm/14prf-rec-convert-stark-to-circuit-verifier.png deleted file mode 100644 index 73762fff1..000000000 Binary files a/docs/img/zkvm/14prf-rec-convert-stark-to-circuit-verifier.png and /dev/null differ diff --git a/docs/img/zkvm/15prf-rec-convert-circuit-to-assoc-stark.png b/docs/img/zkvm/15prf-rec-convert-circuit-to-assoc-stark.png deleted file mode 100644 index bca2b70ac..000000000 Binary files a/docs/img/zkvm/15prf-rec-convert-circuit-to-assoc-stark.png and /dev/null differ diff --git a/docs/img/zkvm/16prf-rec-recursive2-circuit.png b/docs/img/zkvm/16prf-rec-recursive2-circuit.png deleted file mode 100644 index 0e79fd1c7..000000000 Binary files a/docs/img/zkvm/16prf-rec-recursive2-circuit.png and /dev/null differ diff --git a/docs/img/zkvm/17prf-rec-stark-to-circuit-recursive2.png b/docs/img/zkvm/17prf-rec-stark-to-circuit-recursive2.png deleted file mode 100644 index df84a4629..000000000 Binary files a/docs/img/zkvm/17prf-rec-stark-to-circuit-recursive2.png and /dev/null differ diff --git a/docs/img/zkvm/18prf-rec-recursive2-circuit-2-stark.png b/docs/img/zkvm/18prf-rec-recursive2-circuit-2-stark.png deleted file mode 100644 index 3b9651050..000000000 Binary files a/docs/img/zkvm/18prf-rec-recursive2-circuit-2-stark.png and /dev/null differ diff --git a/docs/img/zkvm/19prf-rec-recursive2-stark-to-recursivef-circuit.png b/docs/img/zkvm/19prf-rec-recursive2-stark-to-recursivef-circuit.png deleted file mode 100644 index 616339ee2..000000000 Binary files a/docs/img/zkvm/19prf-rec-recursive2-stark-to-recursivef-circuit.png and /dev/null differ diff --git a/docs/img/zkvm/20prf-rec-recursivef-circuit-2-stark.png b/docs/img/zkvm/20prf-rec-recursivef-circuit-2-stark.png deleted file mode 100644 index ec7115aaa..000000000 Binary files a/docs/img/zkvm/20prf-rec-recursivef-circuit-2-stark.png and /dev/null differ diff --git a/docs/img/zkvm/21prf-rec-recursivef-stark-to-final-circom.png b/docs/img/zkvm/21prf-rec-recursivef-stark-to-final-circom.png deleted file mode 100644 index 57790612c..000000000 Binary files a/docs/img/zkvm/21prf-rec-recursivef-stark-to-final-circom.png and /dev/null differ diff --git a/docs/img/zkvm/22prf-rec-generation-stark-proof-for-recursivef.png b/docs/img/zkvm/22prf-rec-generation-stark-proof-for-recursivef.png deleted file mode 100644 index 5a8a44566..000000000 Binary files a/docs/img/zkvm/22prf-rec-generation-stark-proof-for-recursivef.png and /dev/null differ diff --git a/docs/img/zkvm/23prf-rec-generation-stark-proof-for-c12.png b/docs/img/zkvm/23prf-rec-generation-stark-proof-for-c12.png deleted file mode 100644 index d2c0fc39d..000000000 Binary files a/docs/img/zkvm/23prf-rec-generation-stark-proof-for-c12.png and /dev/null differ diff --git a/docs/img/zkvm/24prf-rec-generation-stark-proof-for-recursive1.png b/docs/img/zkvm/24prf-rec-generation-stark-proof-for-recursive1.png deleted file mode 100644 index c79a42d94..000000000 Binary files a/docs/img/zkvm/24prf-rec-generation-stark-proof-for-recursive1.png and /dev/null differ diff --git a/docs/img/zkvm/25prf-rec-generation-stark-proof-for-recursive2.png b/docs/img/zkvm/25prf-rec-generation-stark-proof-for-recursive2.png deleted file mode 100644 index ea473e42f..000000000 Binary files a/docs/img/zkvm/25prf-rec-generation-stark-proof-for-recursive2.png and /dev/null differ diff --git a/docs/img/zkvm/26prf-rec-generation-zkevm-proof.png b/docs/img/zkvm/26prf-rec-generation-zkevm-proof.png deleted file mode 100644 index 8683e205f..000000000 Binary files a/docs/img/zkvm/26prf-rec-generation-zkevm-proof.png and /dev/null differ diff --git a/docs/img/zkvm/fib10-pil-eg-mfibonacci.png b/docs/img/zkvm/fib10-pil-eg-mfibonacci.png deleted file mode 100644 index e2b21ed5f..000000000 Binary files a/docs/img/zkvm/fib10-pil-eg-mfibonacci.png and /dev/null differ diff --git a/docs/img/zkvm/fib11-pilcom-res-mfibon.png b/docs/img/zkvm/fib11-pilcom-res-mfibon.png deleted file mode 100644 index 59e12ad11..000000000 Binary files a/docs/img/zkvm/fib11-pilcom-res-mfibon.png and /dev/null differ diff --git a/docs/img/zkvm/fib12-inside-parsed-pil.png b/docs/img/zkvm/fib12-inside-parsed-pil.png deleted file mode 100644 index cf646282b..000000000 Binary files a/docs/img/zkvm/fib12-inside-parsed-pil.png and /dev/null differ diff --git a/docs/img/zkvm/fib13-pil-stark-setup.png b/docs/img/zkvm/fib13-pil-stark-setup.png deleted file mode 100644 index 4eca838b4..000000000 Binary files a/docs/img/zkvm/fib13-pil-stark-setup.png and /dev/null differ diff --git a/docs/img/zkvm/fib14-pil-stark-in-prover.png b/docs/img/zkvm/fib14-pil-stark-in-prover.png deleted file mode 100644 index 7c1d4ac7e..000000000 Binary files a/docs/img/zkvm/fib14-pil-stark-in-prover.png and /dev/null differ diff --git a/docs/img/zkvm/fib15-pil-stark-in-verifier.png b/docs/img/zkvm/fib15-pil-stark-in-verifier.png deleted file mode 100644 index cc11bfe1a..000000000 Binary files a/docs/img/zkvm/fib15-pil-stark-in-verifier.png and /dev/null differ diff --git a/docs/img/zkvm/fib17-mfib-pil-w-pubs.png b/docs/img/zkvm/fib17-mfib-pil-w-pubs.png deleted file mode 100644 index be2a2291d..000000000 Binary files a/docs/img/zkvm/fib17-mfib-pil-w-pubs.png and /dev/null differ diff --git a/docs/img/zkvm/fib18-non-empt-pubs-field.png b/docs/img/zkvm/fib18-non-empt-pubs-field.png deleted file mode 100644 index 3176d98d4..000000000 Binary files a/docs/img/zkvm/fib18-non-empt-pubs-field.png and /dev/null differ diff --git a/docs/img/zkvm/fib19-init-node-project.png b/docs/img/zkvm/fib19-init-node-project.png deleted file mode 100644 index f94eceb7a..000000000 Binary files a/docs/img/zkvm/fib19-init-node-project.png and /dev/null differ diff --git a/docs/img/zkvm/fib20-dependncs-install-mfib.png b/docs/img/zkvm/fib20-dependncs-install-mfib.png deleted file mode 100644 index 3e0af124d..000000000 Binary files a/docs/img/zkvm/fib20-dependncs-install-mfib.png and /dev/null differ diff --git a/docs/img/zkvm/fib4-deterministic-compt.png b/docs/img/zkvm/fib4-deterministic-compt.png deleted file mode 100644 index 5a251d702..000000000 Binary files a/docs/img/zkvm/fib4-deterministic-compt.png and /dev/null differ diff --git a/docs/img/zkvm/fib5-design-approach-outline.png b/docs/img/zkvm/fib5-design-approach-outline.png deleted file mode 100644 index 7c1ae5f7a..000000000 Binary files a/docs/img/zkvm/fib5-design-approach-outline.png and /dev/null differ diff --git a/docs/img/zkvm/fib6-mfibon-sm-2-regs.png b/docs/img/zkvm/fib6-mfibon-sm-2-regs.png deleted file mode 100644 index c24621cc1..000000000 Binary files a/docs/img/zkvm/fib6-mfibon-sm-2-regs.png and /dev/null differ diff --git a/docs/img/zkvm/fib7-mfibon-sm-3-regs.png b/docs/img/zkvm/fib7-mfibon-sm-3-regs.png deleted file mode 100644 index 0c96e6d61..000000000 Binary files a/docs/img/zkvm/fib7-mfibon-sm-3-regs.png and /dev/null differ diff --git a/docs/img/zkvm/fib8-code-eg-exec-trace.png b/docs/img/zkvm/fib8-code-eg-exec-trace.png deleted file mode 100644 index 4a429f579..000000000 Binary files a/docs/img/zkvm/fib8-code-eg-exec-trace.png and /dev/null differ diff --git a/docs/img/zkvm/fib9-stark-prf-sizes-times.png b/docs/img/zkvm/fib9-stark-prf-sizes-times.png deleted file mode 100644 index e15105cd7..000000000 Binary files a/docs/img/zkvm/fib9-stark-prf-sizes-times.png and /dev/null differ diff --git a/docs/img/zkvm/fig-micro-pro-pic.png b/docs/img/zkvm/fig-micro-pro-pic.png deleted file mode 100644 index 4f10406b9..000000000 Binary files a/docs/img/zkvm/fig-micro-pro-pic.png and /dev/null differ diff --git a/docs/img/zkvm/fig1-gen-state-mchn.png b/docs/img/zkvm/fig1-gen-state-mchn.png deleted file mode 100644 index 19176669d..000000000 Binary files a/docs/img/zkvm/fig1-gen-state-mchn.png and /dev/null differ diff --git a/docs/img/zkvm/fig1-simpl-arch.png b/docs/img/zkvm/fig1-simpl-arch.png deleted file mode 100644 index 4f77f6e8f..000000000 Binary files a/docs/img/zkvm/fig1-simpl-arch.png and /dev/null differ diff --git a/docs/img/zkvm/fig1-zkprv-and-node.png b/docs/img/zkvm/fig1-zkprv-and-node.png deleted file mode 100644 index 53fecd3c1..000000000 Binary files a/docs/img/zkvm/fig1-zkprv-and-node.png and /dev/null differ diff --git a/docs/img/zkvm/fig10-key-not-set-eg.png b/docs/img/zkvm/fig10-key-not-set-eg.png deleted file mode 100644 index 4d5a9d066..000000000 Binary files a/docs/img/zkvm/fig10-key-not-set-eg.png and /dev/null differ diff --git a/docs/img/zkvm/fig11-val-update-eg.png b/docs/img/zkvm/fig11-val-update-eg.png deleted file mode 100644 index 1ff42361b..000000000 Binary files a/docs/img/zkvm/fig11-val-update-eg.png and /dev/null differ diff --git a/docs/img/zkvm/fig12-crt-zero-node.png b/docs/img/zkvm/fig12-crt-zero-node.png deleted file mode 100644 index 36057a534..000000000 Binary files a/docs/img/zkvm/fig12-crt-zero-node.png and /dev/null differ diff --git a/docs/img/zkvm/fig13-a-crt-nzleaf-ext.png b/docs/img/zkvm/fig13-a-crt-nzleaf-ext.png deleted file mode 100644 index 0aa0a3fb7..000000000 Binary files a/docs/img/zkvm/fig13-a-crt-nzleaf-ext.png and /dev/null differ diff --git a/docs/img/zkvm/fig13-b-crt-nzleaf-xt.png b/docs/img/zkvm/fig13-b-crt-nzleaf-xt.png deleted file mode 100644 index 03c226904..000000000 Binary files a/docs/img/zkvm/fig13-b-crt-nzleaf-xt.png and /dev/null differ diff --git a/docs/img/zkvm/fig14-a-dlt-nz-sib.png b/docs/img/zkvm/fig14-a-dlt-nz-sib.png deleted file mode 100644 index 2fe38d266..000000000 Binary files a/docs/img/zkvm/fig14-a-dlt-nz-sib.png and /dev/null differ diff --git a/docs/img/zkvm/fig14-b-dlt-z-sib.png b/docs/img/zkvm/fig14-b-dlt-z-sib.png deleted file mode 100644 index ff132dcb5..000000000 Binary files a/docs/img/zkvm/fig14-b-dlt-z-sib.png and /dev/null differ diff --git a/docs/img/zkvm/fig15-path-frm-key.png b/docs/img/zkvm/fig15-path-frm-key.png deleted file mode 100644 index a64b68a28..000000000 Binary files a/docs/img/zkvm/fig15-path-frm-key.png and /dev/null differ diff --git a/docs/img/zkvm/fig16-posdn-eg.png b/docs/img/zkvm/fig16-posdn-eg.png deleted file mode 100644 index 9a1d2bc48..000000000 Binary files a/docs/img/zkvm/fig16-posdn-eg.png and /dev/null differ diff --git a/docs/img/zkvm/fig2-actions-sec-sm.png b/docs/img/zkvm/fig2-actions-sec-sm.png deleted file mode 100644 index 1c3013df8..000000000 Binary files a/docs/img/zkvm/fig2-actions-sec-sm.png and /dev/null differ diff --git a/docs/img/zkvm/fig2-mkl-tree-gen.png b/docs/img/zkvm/fig2-mkl-tree-gen.png deleted file mode 100644 index 909eb6ea7..000000000 Binary files a/docs/img/zkvm/fig2-mkl-tree-gen.png and /dev/null differ diff --git a/docs/img/zkvm/fig3-zkNode-arch.png b/docs/img/zkvm/fig3-zkNode-arch.png deleted file mode 100644 index 967270231..000000000 Binary files a/docs/img/zkvm/fig3-zkNode-arch.png and /dev/null differ diff --git a/docs/img/zkvm/fig4-sngl-kv-eg.png b/docs/img/zkvm/fig4-sngl-kv-eg.png deleted file mode 100644 index 95660e251..000000000 Binary files a/docs/img/zkvm/fig4-sngl-kv-eg.png and /dev/null differ diff --git a/docs/img/zkvm/fig5-a-mpt-kv-eg.png b/docs/img/zkvm/fig5-a-mpt-kv-eg.png deleted file mode 100644 index afcb4488a..000000000 Binary files a/docs/img/zkvm/fig5-a-mpt-kv-eg.png and /dev/null differ diff --git a/docs/img/zkvm/fig5-b-mpt-kv-eg.png b/docs/img/zkvm/fig5-b-mpt-kv-eg.png deleted file mode 100644 index 9c56b2c5c..000000000 Binary files a/docs/img/zkvm/fig5-b-mpt-kv-eg.png and /dev/null differ diff --git a/docs/img/zkvm/fig5-c-mpt-kv-eg.png b/docs/img/zkvm/fig5-c-mpt-kv-eg.png deleted file mode 100644 index 7878909ae..000000000 Binary files a/docs/img/zkvm/fig5-c-mpt-kv-eg.png and /dev/null differ diff --git a/docs/img/zkvm/fig5-main-prts-zkpr.png b/docs/img/zkvm/fig5-main-prts-zkpr.png deleted file mode 100644 index 6bd53228d..000000000 Binary files a/docs/img/zkvm/fig5-main-prts-zkpr.png and /dev/null differ diff --git a/docs/img/zkvm/fig6-mpt-gen-eg.png b/docs/img/zkvm/fig6-mpt-gen-eg.png deleted file mode 100644 index 40aac31a9..000000000 Binary files a/docs/img/zkvm/fig6-mpt-gen-eg.png and /dev/null differ diff --git a/docs/img/zkvm/fig7-fake-leaf-eg.png b/docs/img/zkvm/fig7-fake-leaf-eg.png deleted file mode 100644 index 9a2d9e02c..000000000 Binary files a/docs/img/zkvm/fig7-fake-leaf-eg.png and /dev/null differ diff --git a/docs/img/zkvm/fig8-non-binding-eg.png b/docs/img/zkvm/fig8-non-binding-eg.png deleted file mode 100644 index 0eacd498e..000000000 Binary files a/docs/img/zkvm/fig8-non-binding-eg.png and /dev/null differ diff --git a/docs/img/zkvm/fig9-zk-mkl-prf.png b/docs/img/zkvm/fig9-zk-mkl-prf.png deleted file mode 100644 index 689a0fff4..000000000 Binary files a/docs/img/zkvm/fig9-zk-mkl-prf.png and /dev/null differ diff --git a/docs/img/zkvm/gen1-typical-gen-sm.png b/docs/img/zkvm/gen1-typical-gen-sm.png deleted file mode 100644 index 2bbb453a9..000000000 Binary files a/docs/img/zkvm/gen1-typical-gen-sm.png and /dev/null differ diff --git a/docs/img/zkvm/gen2-mfib-exec-w-inputs.png b/docs/img/zkvm/gen2-mfib-exec-w-inputs.png deleted file mode 100644 index 4628eeb4a..000000000 Binary files a/docs/img/zkvm/gen2-mfib-exec-w-inputs.png and /dev/null differ diff --git a/docs/img/zkvm/gen3-gen-sm-w-input-instrctn.png b/docs/img/zkvm/gen3-gen-sm-w-input-instrctn.png deleted file mode 100644 index 1fc681f26..000000000 Binary files a/docs/img/zkvm/gen3-gen-sm-w-input-instrctn.png and /dev/null differ diff --git a/docs/img/zkvm/gen4-sm-alg-processor.png b/docs/img/zkvm/gen4-sm-alg-processor.png deleted file mode 100644 index c99f2b75e..000000000 Binary files a/docs/img/zkvm/gen4-sm-alg-processor.png and /dev/null differ diff --git a/docs/img/zkvm/gen5-sm-exec-broader-contxt.png b/docs/img/zkvm/gen5-sm-exec-broader-contxt.png deleted file mode 100644 index cbdd37b5d..000000000 Binary files a/docs/img/zkvm/gen5-sm-exec-broader-contxt.png and /dev/null differ diff --git a/docs/img/zkvm/gen6-pil-4instrct-prog.png b/docs/img/zkvm/gen6-pil-4instrct-prog.png deleted file mode 100644 index 948e71c2d..000000000 Binary files a/docs/img/zkvm/gen6-pil-4instrct-prog.png and /dev/null differ diff --git a/docs/img/zkvm/gen7-state-machine-w-zkpc.png b/docs/img/zkvm/gen7-state-machine-w-zkpc.png deleted file mode 100644 index f4bfeceed..000000000 Binary files a/docs/img/zkvm/gen7-state-machine-w-zkpc.png and /dev/null differ diff --git a/docs/img/zkvm/gen8-end-prog-w-loop.png b/docs/img/zkvm/gen8-end-prog-w-loop.png deleted file mode 100644 index b15bcc314..000000000 Binary files a/docs/img/zkvm/gen8-end-prog-w-loop.png and /dev/null differ diff --git a/docs/img/zkvm/governance-tree.png b/docs/img/zkvm/governance-tree.png deleted file mode 100644 index 822eb5306..000000000 Binary files a/docs/img/zkvm/governance-tree.png and /dev/null differ diff --git a/docs/img/zkvm/hsh01-sponge-construction.png b/docs/img/zkvm/hsh01-sponge-construction.png deleted file mode 100644 index f0501cd96..000000000 Binary files a/docs/img/zkvm/hsh01-sponge-construction.png and /dev/null differ diff --git a/docs/img/zkvm/hsh02-sm-kk-framework.png b/docs/img/zkvm/hsh02-sm-kk-framework.png deleted file mode 100644 index 58c469d17..000000000 Binary files a/docs/img/zkvm/hsh02-sm-kk-framework.png and /dev/null differ diff --git a/docs/img/zkvm/lxly-1-v1-asset-transfer.png b/docs/img/zkvm/lxly-1-v1-asset-transfer.png deleted file mode 100755 index ab7d3bc18..000000000 Binary files a/docs/img/zkvm/lxly-1-v1-asset-transfer.png and /dev/null differ diff --git a/docs/img/zkvm/lxly-2-new-bridge-design.png b/docs/img/zkvm/lxly-2-new-bridge-design.png deleted file mode 100755 index 87a583c06..000000000 Binary files a/docs/img/zkvm/lxly-2-new-bridge-design.png and /dev/null differ diff --git a/docs/img/zkvm/lxly-3-flow-rollupmanager.png b/docs/img/zkvm/lxly-3-flow-rollupmanager.png deleted file mode 100755 index 9ffed2449..000000000 Binary files a/docs/img/zkvm/lxly-3-flow-rollupmanager.png and /dev/null differ diff --git a/docs/img/zkvm/plook-ops-mainSM-copy.png b/docs/img/zkvm/plook-ops-mainSM-copy.png deleted file mode 100644 index 1f153ce1c..000000000 Binary files a/docs/img/zkvm/plook-ops-mainSM-copy.png and /dev/null differ diff --git a/docs/img/zkvm/plook-ops-mainSM.png b/docs/img/zkvm/plook-ops-mainSM.png deleted file mode 100644 index 1f153ce1c..000000000 Binary files a/docs/img/zkvm/plook-ops-mainSM.png and /dev/null differ diff --git a/docs/img/zkvm/plookup-generic-sm-pil.png b/docs/img/zkvm/plookup-generic-sm-pil.png deleted file mode 100644 index 4fbc35a1f..000000000 Binary files a/docs/img/zkvm/plookup-generic-sm-pil.png and /dev/null differ diff --git a/docs/img/zkvm/security-council-overview.png b/docs/img/zkvm/security-council-overview.png deleted file mode 100644 index 41a9a70bc..000000000 Binary files a/docs/img/zkvm/security-council-overview.png and /dev/null differ diff --git a/docs/img/zkvm/sm-topology-1.png b/docs/img/zkvm/sm-topology-1.png deleted file mode 100644 index deb2e10dc..000000000 Binary files a/docs/img/zkvm/sm-topology-1.png and /dev/null differ diff --git a/docs/img/zkvm/sm-topology-2.png b/docs/img/zkvm/sm-topology-2.png deleted file mode 100644 index c5cbce738..000000000 Binary files a/docs/img/zkvm/sm-topology-2.png and /dev/null differ diff --git a/docs/img/zkvm/sm-topology-3.png b/docs/img/zkvm/sm-topology-3.png deleted file mode 100644 index a8b07d062..000000000 Binary files a/docs/img/zkvm/sm-topology-3.png and /dev/null differ diff --git a/docs/img/zkvm/tup-pattern.png b/docs/img/zkvm/tup-pattern.png deleted file mode 100644 index 47b85f166..000000000 Binary files a/docs/img/zkvm/tup-pattern.png and /dev/null differ diff --git a/docs/img/zkvm/upgrade-overview.png b/docs/img/zkvm/upgrade-overview.png deleted file mode 100644 index f83493c3a..000000000 Binary files a/docs/img/zkvm/upgrade-overview.png and /dev/null differ diff --git a/docs/img/zkvm/zkv-bridge2.jpg b/docs/img/zkvm/zkv-bridge2.jpg deleted file mode 100644 index 91c7f8587..000000000 Binary files a/docs/img/zkvm/zkv-bridge2.jpg and /dev/null differ diff --git a/docs/img/zkvm/zkv-faucet-zketh.png b/docs/img/zkvm/zkv-faucet-zketh.png deleted file mode 100644 index d31e38bce..000000000 Binary files a/docs/img/zkvm/zkv-faucet-zketh.png and /dev/null differ diff --git a/docs/img/zkvm/zkv-metamask1.jpg b/docs/img/zkvm/zkv-metamask1.jpg deleted file mode 100644 index e3dfc9862..000000000 Binary files a/docs/img/zkvm/zkv-metamask1.jpg and /dev/null differ diff --git a/docs/img/zkvm/zkv-proj-created-outcome.png b/docs/img/zkvm/zkv-proj-created-outcome.png deleted file mode 100644 index 05e1fbbe2..000000000 Binary files a/docs/img/zkvm/zkv-proj-created-outcome.png and /dev/null differ diff --git a/docs/img/zkvm/zkv-success-deploy-sbtdotsol.png b/docs/img/zkvm/zkv-success-deploy-sbtdotsol.png deleted file mode 100644 index b0ec7c3bb..000000000 Binary files a/docs/img/zkvm/zkv-success-deploy-sbtdotsol.png and /dev/null differ diff --git a/docs/img/zkvm/zkv-success-forge-build.png b/docs/img/zkvm/zkv-success-forge-build.png deleted file mode 100644 index 24bf26a08..000000000 Binary files a/docs/img/zkvm/zkv-success-forge-build.png and /dev/null differ diff --git a/docs/img/zkvm/zkv-success-zketh.png b/docs/img/zkvm/zkv-success-zketh.png deleted file mode 100644 index dec8b9e9d..000000000 Binary files a/docs/img/zkvm/zkv-success-zketh.png and /dev/null differ diff --git a/docs/img/zkvm/zkv-test-forge-build.png b/docs/img/zkvm/zkv-test-forge-build.png deleted file mode 100644 index 37bc890de..000000000 Binary files a/docs/img/zkvm/zkv-test-forge-build.png and /dev/null differ diff --git a/docs/img/zkvm/zkv-transaction-history.jpg b/docs/img/zkvm/zkv-transaction-history.jpg deleted file mode 100644 index ced23c4ca..000000000 Binary files a/docs/img/zkvm/zkv-transaction-history.jpg and /dev/null differ diff --git a/docs/img/zkvm/zkv-zkwallet-1.jpg b/docs/img/zkvm/zkv-zkwallet-1.jpg deleted file mode 100644 index 1c9a892bb..000000000 Binary files a/docs/img/zkvm/zkv-zkwallet-1.jpg and /dev/null differ diff --git a/docs/js/katex.js b/docs/js/katex.js new file mode 100644 index 000000000..3828300a7 --- /dev/null +++ b/docs/js/katex.js @@ -0,0 +1,10 @@ +document$.subscribe(({ body }) => { + renderMathInElement(body, { + delimiters: [ + { left: "$$", right: "$$", display: true }, + { left: "$", right: "$", display: false }, + { left: "\\(", right: "\\)", display: false }, + { left: "\\[", right: "\\]", display: true } + ], + }) + }) \ No newline at end of file diff --git a/docs/js/mathjax.js b/docs/js/mathjax.js new file mode 100644 index 000000000..06dbf38bf --- /dev/null +++ b/docs/js/mathjax.js @@ -0,0 +1,16 @@ +window.MathJax = { + tex: { + inlineMath: [["\\(", "\\)"]], + displayMath: [["\\[", "\\]"]], + processEscapes: true, + processEnvironments: true + }, + options: { + ignoreHtmlClass: ".*|", + processHtmlClass: "arithmatex" + } +}; + +document$.subscribe(() => { + MathJax.typesetPromise() +}) diff --git a/docs/zkEVM/architecture/architecture.md b/docs/zkEVM/architecture/index.md similarity index 84% rename from docs/zkEVM/architecture/architecture.md rename to docs/zkEVM/architecture/index.md index c53275951..d247523fe 100644 --- a/docs/zkEVM/architecture/architecture.md +++ b/docs/zkEVM/architecture/index.md @@ -4,15 +4,15 @@ The major components of zkEVM are: - Consensus Contract (PolygonZkEVM.sol) - zkNode - - Synchronizer - - Sequencers & Aggregators - - RPC + - Synchronizer + - Sequencers & Aggregators + - RPC - zkProver - zkEVM Bridge The skeletal architecture of Polygon zkEVM is shown below: -![Skeletal Overview of zkEVM](../../img/zkvm/fig1-simpl-arch.png) +![Skeletal Overview of zkEVM](../../img/zkEVM/fig1-simpl-arch.png) ## Consensus contract @@ -24,13 +24,16 @@ The earlier **Proof of Donation (PoD)** mechanism was based on a decentralized a The latest version of the zkEVM **Consensus Contract (deployed on Layer 1)** is modelled after the [Proof of Efficiency](https://ethresear.ch/t/proof-of-efficiency-a-new-consensus-mechanism-for-zk-rollups/11988). It leverages the experience of the existing PoD in v1.0 and adds support for the permissionless participation of multiple coordinators to produce batches in L2. ​ + ### Implementation model + ​ The **Consensus Contract** model leverages the existing PoD mechanism and supports the permissionless participation of multiple coordinators to produce batches in L2. These batches are created from the rolled-up transactions of L1. The **Consensus Contract (PolygonZkEVM.sol)** employs a simpler technique and is favoured due to its greater efficiency in resolving the challenges involved in PoD. -The strategic implementation of the contract-based consensus promises to ensure that the network: +The strategic implementation of the contract-based consensus promises to ensure that the network: ​ -- Maintains its **Permissionless** feature to produce L2 batches + +- Maintains its **Permissionless** feature to produce L2 batches - Is **highly efficient**, a criterion which is key for the overall network performance - Attains an **acceptable degree of decentralization** - Is **protected from malicious attacks**, especially by validators @@ -41,20 +44,22 @@ The strategic implementation of the contract-based consensus promises to ensure Possibilities of coupling the Consensus Contract (previously called Proof of Efficiency or PoE) with a PoS (Proof of Stake) are currently being explored. A detailed description is published on the [Ethereum Research](https://ethresear.ch/t/proof-of-efficiency-a-new-consensus-mechanism-for-zk-rollups/11988) website. - - ### On-chain data availability + ​ A **Full ZK-Rollup** schema requires the publication of both **the data** (which users need to reconstruct the full state) and **the validity proofs** (zero-knowledge proofs) on-chain. However, given the Ethereum configuration, publishing data on-chain incurs gas prices, which is an issue with Layer 1. This makes deciding between a Full ZK-Rollup configuration and a Hybrid configuration challenging. Under a Hybrid schema, either of the following is possible: ​ - - **Validium**: Data is stored off-chain and only the validity proofs are published on-chain. - - **Volition**: For some transactions, both the data and the validity proofs remain on-chain while for the remaining ones, only proofs go on-chain. - + +- **Validium**: Data is stored off-chain and only the validity proofs are published on-chain. +- **Volition**: For some transactions, both the data and the validity proofs remain on-chain while for the remaining ones, only proofs go on-chain. + Unless, among other things, the proving module can be highly accelerated to mitigate costs for the validators, a Hybrid schema remains viable. ​ + ### PolygonZkEVM.sol + ​ The underlying protocol in zkEVM ensures that the state transitions are correct by employing a validity proof. To ensure that a set of pre-determined rules have been followed for allowing state transitions, the **Consensus Contract** (`PolygonZkEVM.sol`, deployed on L1) is utilized. ​ @@ -64,30 +69,36 @@ The underlying protocol in zkEVM ensures that the state transitions are correct ​ A smart contract verifies the validity proofs to ensure that each transition is completed correctly. This is accomplished by employing zk-SNARK circuits. A system of this type requires two processes: **transaction batching** and **transaction validation**. -To carry out these procedures, zkEVM employs two sorts of participants: **Sequencers** and **Aggregators**. Under this two-layer model: +To carry out these procedures, zkEVM employs two sorts of participants: **Sequencers** and **Aggregators**. Under this two-layer model: ​ + - **Sequencers** → propose transaction batches to the network, i.e. they roll-up the transaction requests in batches and add them to the Consensus Contract. ​ - **Aggregators** → check the validity of the transaction batches and provide validity proofs. Any permissionless Aggregator can submit the proof to demonstrate the correctness of the state transition computation. The Smart Contract, therefore, makes two calls: one to receive batches from Sequencers, and another to Aggregators, requesting batches to be validated. ​ -![Simplified Proof of Efficiency](../../img/zkvm/fig2-simple-poe.png) +![Simplified Proof of Efficiency](../../img/zkEVM/fig2-simple-poe.png) ​ + ### Tokenomics + ​ The Consensus Smart Contract imposes the following requirements on Sequencers and Aggregators: ​ + #### Sequencers -- Anyone with the software necessary for running a zkEVM node can be a Sequencer. -- Every Sequencer must pay a fee in form of MATIC tokens to earn the right to create and propose batches. -- A Sequencer that proposes valid batches (which consist of valid transactions), is incentivised with the fee paid by transaction-requestors or the users of the network. +- Anyone with the software necessary for running a zkEVM node can be a Sequencer. +- Every Sequencer must pay a fee in form of MATIC tokens to earn the right to create and propose batches. +- A Sequencer that proposes valid batches (which consist of valid transactions), is incentivised with the fee paid by transaction-requestors or the users of the network. ​ + #### Aggregators -An Aggregator receives all the transaction information from the Sequencer and sends it to the Prover which provides a small zk-Proof after complex polynomial computations. The smart contract validates this proof. This way, an aggregator collects the data, sends it to the Prover, receives its output and finally, sends the information to the smart contract to check that the validity proof from the Prover is correct. +An Aggregator receives all the transaction information from the Sequencer and sends it to the Prover which provides a small zk-Proof after complex polynomial computations. The smart contract validates this proof. This way, an aggregator collects the data, sends it to the Prover, receives its output and finally, sends the information to the smart contract to check that the validity proof from the Prover is correct. ​ + - An Aggregator's task is to provide validity proofs for the L2 transactions proposed by Sequencers. - In addition to running zkEVM's zkNode software, Aggregators need to have specialized hardware for creating the zero-knowledge validity proofs utilizing zkProver. - For a given batch or batches, an Aggregator that submits a validity proof first earns the MATIC fee (which is being paid by the Sequencer(s) of the batch(es)). @@ -100,23 +111,24 @@ zkNode is the software needed to run any zkEVM node. It is a client that the net - As a node to know the state of the network, or - As a participant in the process of batch production in any of the two roles: **Sequencer** or **Aggregator** -The zkNode architecture is modular in nature. You can dig deeper into zkNode and its components [here](../zknode/zknode-overview.md). +The zkNode architecture is modular in nature. You can dig deeper into zkNode and its components [here](zknode/index.md). ### Incentivization structure The two permissionless participants of the zkEVM network are: **Sequencers** and **Aggregators**. Proper incentive structures have been devised to keep the zkEVM network fast and secure. Below is a summary of the fee structure for Sequencers and Aggregators: + - **Sequencer** - - Collect transactions and publish them in a batch - - Receive fees from the published transactions - - Pay L1 transaction fees + MATIC (depends on pending batches) - - MATIC goes to Aggregators - - Profitable if: `txs fees` > `L1 call` + `MATIC` fee + - Collect transactions and publish them in a batch + - Receive fees from the published transactions + - Pay L1 transaction fees + MATIC (depends on pending batches) + - MATIC goes to Aggregators + - Profitable if: `txs fees` > `L1 call` + `MATIC` fee - **Aggregator** - - Process transactions published by Sequencers - - Build zkProof - - Receive MATIC from Sequencer - - Static Cost: L1 call cost + Server cost (to build a proof) - - Profitable if: `MATIC fee` > `L1 call` + `Server cost` + - Process transactions published by Sequencers + - Build zkProof + - Receive MATIC from Sequencer + - Static Cost: L1 call cost + Server cost (to build a proof) + - Profitable if: `MATIC fee` > `L1 call` + `Server cost` ## zkProver @@ -124,9 +136,9 @@ zkEVM employs advanced zero-knowledge technology to create validity proofs. It u It consists of a **Main State Machine Executor**, a collection of **secondary State Machines** (each with its own executor), a **STARK-proof builder**, and a **SNARK-proof builder**. -![Skeletal Overview of zkProver](../../img/zkvm/fig4-zkProv-arch.png) +![Skeletal Overview of zkProver](../../img/zkEVM/fig4-zkProv-arch.png) -In a nutshell, **the zkEVM expresses state changes in a polynomial form**. As a result, the constraints that each proposed batch must meet are polynomial constraints or polynomial identities. To put it another way, all valid batches must satisfy specific polynomial constraints. Check out the detailed architecture of zkProver [here](../zkprover/zkprover-overview.md). +In a nutshell, **the zkEVM expresses state changes in a polynomial form**. As a result, the constraints that each proposed batch must meet are polynomial constraints or polynomial identities. To put it another way, all valid batches must satisfy specific polynomial constraints. Check out the detailed architecture of zkProver [here](zkprover/zkprover-overview.md). ## zkEVM bridge @@ -147,19 +159,19 @@ The Verifier contract is currently deployed on the [Ethereum Mainnet](https://et Before getting into a transaction flow in L2, users need some funds to perform any L2 transaction. In order to do so, users need to transfer some ether from L1 to L2 through the zkEVM Bridge dApp. - **Bridge** - - Deposit ether - - Wait until `globalExitRoot` is posted on L2 - - Perform claim on L2 and receive the funds + - Deposit ether + - Wait until `globalExitRoot` is posted on L2 + - Perform claim on L2 and receive the funds - **L2 transactions** - - User initiates tx in a Wallet (e.g. Metamask) and sends it to a Sequencer - - It gets finalized on L2 once Sequencer commits to add his transaction - - Transaction has finalized on L2, but not on L1 (simply put, L2 state is not yet on L1). Also known as **Trusted State** - - Sequencer sends the batch data to L1 smart contract, enabling any node to synchronize from L1 in a trustless way (aka **Virtual State**) - - Aggregator will take pending transactions to be verified and build a Proof in order to achieve finality on L1 - - Once the Proof is validated, user's transactions will attain L1 finality (important for withdrawals). This is called the **consolidated state**. - -The above process is a summarized version of how transactions are processed in zkEVM. We recommend you to take a look at the complete [transaction life cycle](../protocol/l2-transaction-cycle-intro.md) document. + - User initiates tx in a Wallet (e.g. Metamask) and sends it to a Sequencer + - It gets finalized on L2 once Sequencer commits to add his transaction + - Transaction has finalized on L2, but not on L1 (simply put, L2 state is not yet on L1). Also known as **Trusted State** + - Sequencer sends the batch data to L1 smart contract, enabling any node to synchronize from L1 in a trustless way (aka **Virtual State**) + - Aggregator will take pending transactions to be verified and build a Proof in order to achieve finality on L1 + - Once the Proof is validated, user's transactions will attain L1 finality (important for withdrawals). This is called the **consolidated state**. + +The above process is a summarized version of how transactions are processed in zkEVM. We recommend you to take a look at the complete [transaction life cycle](../protocol/submit-transaction.md) document. ## Design characteristics diff --git a/docs/zkEVM/zknode/zknode-overview.md b/docs/zkEVM/architecture/zknode/index.md similarity index 92% rename from docs/zkEVM/zknode/zknode-overview.md rename to docs/zkEVM/architecture/zknode/index.md index d1a267be1..decc12c08 100644 --- a/docs/zkEVM/zknode/zknode-overview.md +++ b/docs/zkEVM/architecture/zknode/index.md @@ -4,7 +4,7 @@ The main actors influencing the L2 State and its finality are the _trusted Seque The zkNode architecture is modular in nature. See the below diagram for more clarity. -![zkNode Diagram](../../img/zkvm/fig3-zkNode-arch.png) +![zkNode Diagram](../../../img/zkEVM/fig3-zkNode-arch.png) Most important to understand, is the primary path taken by transactions; from when users submit the transactions to the zkEVM network up until they are finalized and incorporated in the L1 State. @@ -19,4 +19,4 @@ Polygon zkEVM achieves this by utilizing several actors. Here is a list of the m - The **Aggregator** is another node whose role is to produce proofs attesting to the integrity of the Sequencer's proposed state change. These proofs are zero-knowledge proofs (or ZK-proofs) and the Aggregator employs a cryptographic component called the Prover for this purpose. - The **Prover** is a complex cryptographic tool capable of producing ZK-proofs of hundreds of batches, and aggregating these into a single ZK-proof which is published as the validity proof. -Users can set up their own _local zkNode_ by following this guide [here](../setup-local-node.md), or a production zkNode as detailed [here](../setup-production-node.md). +Users can set up their own _local zkNode_ by following this guide [here](../../setup-local-node.md), or a production zkNode as detailed [here](../../setup-production-node.md). diff --git a/docs/zkEVM/zkprover/arithmetic-sm.md b/docs/zkEVM/architecture/zkprover/arithmetic-sm.md similarity index 91% rename from docs/zkEVM/zkprover/arithmetic-sm.md rename to docs/zkEVM/architecture/zkprover/arithmetic-sm.md index 79424d769..c55d82003 100644 --- a/docs/zkEVM/zkprover/arithmetic-sm.md +++ b/docs/zkEVM/architecture/zkprover/arithmetic-sm.md @@ -1,6 +1,6 @@ The **Arithmetic State Machine** is a secondary state machine that also **has an executor (the Arithmetic SM Executor)** and **an internal Arithmetic program (a set of verification rules written in the PIL language)**. The Arithmetic SM Executor is available in two languages: Javascript and C/C++. -It is **one of the six secondary state machines** receiving instructions from the Main SM Executor. The main purpose of the Arithmetic SM is to carry out elliptic curve arithmetic operations, such as Point Addition and Point Doubling as well as performing 256-bit operations like addition, product or division. +It is **one of the six secondary state machines** receiving instructions from the Main SM Executor. The main purpose of the Arithmetic SM is to carry out elliptic curve arithmetic operations, such as Point Addition and Point Doubling as well as performing 256-bit operations like addition, product or division. ## Standard elliptic curve arithmetic @@ -16,7 +16,7 @@ $$ y^2 = x^3 + 7. $$ -### Point addition +### Point addition Given two points, $P = (x_1,y_1)$ and $Q = (x_2,y_2)$, on the curve $E$ with $x_1 \neq x_2$, the point $P+Q = (x_3,y_3)$ is computed as follows, @@ -25,7 +25,7 @@ x_3 = s^2 - x_1 - x_2,\quad \\ y_3 = s (x_1 - x_3) - y_1 $$ -### Point doubling +### Point doubling Given a point $P = (x_1,y_1)$ on the curve $E$ such that $P \neq \mathcal{O}$, the point $P+P = 2P = (x_3,y_3)$ is computed as follows, @@ -41,7 +41,7 @@ $$ s = \dfrac{3x_1^2}{2y_1}. $$ -### Field arithmetic +### Field arithmetic Several 256-bit operations can be expressed in the following form: @@ -51,7 +51,7 @@ $$ where $A, B, C, D$ and $E$ are 256-bit integers. -For instance, if $C = 0$, then $\bf{Eqn\ A}$ states that the result of multiplying $A$ and $B$ is $E$ with a carry of $D$. That is, $D$ is the chunk that exceeds 256 bits. +For instance, if $C = 0$, then $\bf{Eqn\ A}$ states that the result of multiplying $A$ and $B$ is $E$ with a carry of $D$. That is, $D$ is the chunk that exceeds 256 bits. Or, if $B = 1$, $\bf{Eqn\ A}$ states that the result of adding $A$ and $C$ is the same as before: $E$ with a carry of $D$. Similarly, division and modular reductions can also be expressed as derivatives of $\bf{Eqn\ A}$. @@ -62,6 +62,7 @@ $$ $$ #### Remark + Since the above Elliptic Curve operations are implemented in the PIL language, it is more convenient to express them in terms of the constraints they must satisfy. These constraints are: $$ @@ -78,12 +79,12 @@ q_0 \cdot p = 0, \\ \end{aligned} $$ -where $q_0,q_1,q_2 \in \mathbb{Z}$, implying that these equations hold true over the integers. +where $q_0,q_1,q_2 \in \mathbb{Z}$, implying that these equations hold true over the integers. This approach is taken because of the need to compute divisions by $p$. Note that **only three possible computation scenarios can arise**: 1. $\text{EQ}_0$ is activated while the rest are deactivated, -2. $\text{EQ}_1$, $\text{EQ}_3$ and $\text{EQ}_4$ are activated but $\text{EQ}_0$ and $\text{EQ}_2$ are deactivated, +2. $\text{EQ}_1$, $\text{EQ}_3$ and $\text{EQ}_4$ are activated but $\text{EQ}_0$ and $\text{EQ}_2$ are deactivated, 3. $\text{EQ}_2$, $\text{EQ}_3$ and $\text{EQ}_4$ are activated and $\text{EQ}_0$ and $\text{EQ}_1$ are deactivated. Since at most, one of $\text{EQ}_1$ and $\text{EQ}_2$ are activated in any scenario, we can afford "sharing'' the same $q_0$ for both. @@ -96,17 +97,17 @@ x_1,\ y_1,\ x_2,\ y_2,\ x_3,\ y_3. \end{aligned} $$ -There is also a need to provide $s$ and $q_0,q_1,q_2$, which are also 256-bit field elements. +There is also a need to provide $s$ and $q_0,q_1,q_2$, which are also 256-bit field elements. ## How operations are performed -Compute the previous operations at 2-byte level. For instance, if one is performing the multiplication of $x_1$ and $y_1$, at the first clock $x_1[0] \cdot y_1[0]$ is computed. +Compute the previous operations at 2-byte level. For instance, if one is performing the multiplication of $x_1$ and $y_1$, at the first clock $x_1[0] \cdot y_1[0]$ is computed. -Then, $(x_1[0] \cdot y_1[1]) + (x_1[1] \cdot y_1[0])$ is computed in the second clock, followed by $(x_1[0] \cdot y_1[2]) + (x_1[1] \cdot y_1[1]) + (x_1[2] \cdot y_1[0])$ in the third, and so on. +Then, $(x_1[0] \cdot y_1[1]) + (x_1[1] \cdot y_1[0])$ is computed in the second clock, followed by $(x_1[0] \cdot y_1[2]) + (x_1[1] \cdot y_1[1]) + (x_1[2] \cdot y_1[0])$ in the third, and so on. As depicted in the below figure, this process is completely analogous to the schoolbook multiplication. However, it is performed at 2-byte level, instead of decimal level. -![School Multiplication Example](../../img/zkvm/01arith-sch-mlt-eg.png) +![School Multiplication Example](../../../img/zkEVM/01arith-sch-mlt-eg.png) Use the following notation: @@ -119,7 +120,7 @@ $$ But then, the carry generated by $\mathbf{eq}$ has to be taken into account by $\mathbf{eq'}$. -Going back to our equations $\text{EQ}_0, \text{EQ}_1, \text{EQ}_2, \text{EQ}_4$; let's see how the operation is performed in $\text{EQ}_0$. +Going back to our equations $\text{EQ}_0, \text{EQ}_1, \text{EQ}_2, \text{EQ}_4$; let's see how the operation is performed in $\text{EQ}_0$. 1. Compute $\mathbf{eq}_0 = (x_1[0] \cdot y_1[0]) + x_2[0] - y_3[0]$ @@ -127,11 +128,11 @@ Going back to our equations $\text{EQ}_0, \text{EQ}_1, \text{EQ}_2, \text{EQ}_4$ 3. $\mathbf{eq}_2 = (x_1[0] \cdot y_1[2]) + (x_1[1] \cdot y_1[1]) + (x_1[2] \cdot y_1[0]) + x_2[2] - y_3[2]$ -This is continued until one reaches the computation, $\mathbf{eq}_{15} = (x_1[0] \cdot y_1[15]) + (x_1[1] \cdot y_1[14]) + \dots + x_2[15] - y_3[15]$. +This is continued until one reaches the computation, $\mathbf{eq}_{15} = (x_1[0] \cdot y_1[15]) + (x_1[1] \cdot y_1[14]) + \dots + x_2[15] - y_3[15]$. At this stage $y_2$ comes into place. -Since the first 256 bits of the result of the operation have been filled (and the result can be made of more than 256-bits), a new register is needed to store the rest of the output. We change the addition of $x_2[i] - y_3[i]$ by $-y_2[i]$. +Since the first 256 bits of the result of the operation have been filled (and the result can be made of more than 256-bits), a new register is needed to store the rest of the output. We change the addition of $x_2[i] - y_3[i]$ by $-y_2[i]$. Therefore, we obtain that: @@ -143,14 +144,14 @@ $$ \end{aligned} $$ -and so on. +and so on. Continuing until the last two: $$ \begin{aligned} \mathbf{eq}_{30} &= (x_1[15] \cdot y_1[15]) - y_2[14], \\ -\mathbf{eq}_{31} &= -y_2[15]. +\mathbf{eq}_{31} &= -y_2[15]. \end{aligned} $$ @@ -163,6 +164,7 @@ $$ where $\text{carry}$ represents the carry taken into account in the actual clock, and $\text{carry}'$ represents the carry generated by the actual operation. #### Remark + A technicality is that $\text{carry}$ is subdivided into two other $\text{carry}_L$ and $\text{carry}_H$ such that: $$ @@ -175,4 +177,4 @@ The Polygon zkEVM repository is available on [GitHub](https://github.com/0xPolyg **Arithmetic SM Executor**: [sm_arith folder](https://github.com/0xPolygonHermez/zkevm-proverjs/tree/main/src/sm/sm_arith) -**Arithmetic SM PIL**: [arith.pil](https://github.com/0xPolygonHermez/zkevm-proverjs/blob/main/pil/arith.pil) +**Arithmetic SM PIL**: [arith.pil](https://github.com/0xPolygonHermez/zkevm-proverjs/blob/main/pil/arith.pil) diff --git a/docs/zkEVM/zkprover/binary-sm.md b/docs/zkEVM/architecture/zkprover/binary-sm.md similarity index 94% rename from docs/zkEVM/zkprover/binary-sm.md rename to docs/zkEVM/architecture/zkprover/binary-sm.md index 7907d5177..fd34cfd59 100644 --- a/docs/zkEVM/zkprover/binary-sm.md +++ b/docs/zkEVM/architecture/zkprover/binary-sm.md @@ -12,7 +12,7 @@ The zkEVM performs the following binary operations on 256-bit strings: - The **signed less-than** operation, denoted by $\text{SLT }$ ($<$), checks if a 256-bit number is smaller than another 256-bit number, but takes into consideration the respective signs of the numbers, - The **equal** operation, denoted by $\text{EQ }$ ($=$), checks if two 256-bit numbers are equal, - The **AND** operation, denoted by $\text{AND }$ ($\land$), computes the bit-wise "AND" of two numbers, -- The **OR** operation, denoted by $\text{OR }$ ($\lor$), computes the bit-wise "OR" of two numbers, +- The **OR** operation, denoted by $\text{OR }$ ($\lor$), computes the bit-wise "OR" of two numbers, - The **XOR** operation, denoted by $\text{XOR }$ ($\oplus$), computes the bit-wise "XOR" of two numbers, - The **NOT** operation, denoted by $\text{NOT }$ ($\neg$), computes the bit-wise "NOT" of a binary number. @@ -22,7 +22,7 @@ In order to understand how the $\text{ADD}$ and $\text{SUB}$ operations work, on Below figure shows these codifications for 3-bit strings but the idea can be easily extended to 256-bit strings. -![Figure 1: Codifications of 3-bit strings for signed and unsigned integers as used by the EVM](../../img/zkvm/01bin-cdfctn-3bit-strngs.png) +![Figure 1: Codifications of 3-bit strings for signed and unsigned integers as used by the EVM](../../../img/zkEVM/01bin-cdfctn-3bit-strngs.png) Adding two strings is performed bit-by-bit using the corresponding carry. @@ -32,7 +32,7 @@ For example, add the 3-bit strings $\mathtt{0b001}$ and $\mathtt{0b101}$, where $1+1+carry=1+1+0=0$, so the next carry becomes $carry'=1$. -- Next, add the second least-significant bits using the previous carry, +- Next, add the second least-significant bits using the previous carry, $0+0+carry = 0+0+1 = 1$, this time the next carry is $carry'=0$. @@ -68,7 +68,7 @@ Consider the bit-wise operations; $\text{AND}$, $\text{OR}$, $\text{XOR}$ and $\ The below table depicts the truth tables of $\text{AND}$, $\text{OR}$ and $\text{XOR}$ operators, respectively. -![Truth Tables of bit-wise operations](../../img/zkvm/02bin-trth-tbls-bitws.png) +![Truth Tables of bit-wise operations](../../../img/zkEVM/02bin-trth-tbls-bitws.png) Notice that we do not consider the $\text{NOT}$ operation. This is because the $\text{NOT}$ operation can be easily implemented with the $\text{XOR}$ operation, by taking an $\text{XOR}$ of the given 256-bit string and $\texttt{0xff...ff}$. @@ -104,7 +104,7 @@ In instances where none of the defined binary operations is carried out, the Bin ### Internal byte plookups -The Binary SM is internally designed to use Plookups of bytes for all the binary operations. +The Binary SM is internally designed to use Plookups of bytes for all the binary operations. It uses Plookups that contain all the possible input bytes and output byte combinations, @@ -135,7 +135,7 @@ $$ \mathbf{a} = a_{31}\cdot (2^8)^{31} + a_{30}\cdot (2^8)^{30} + \cdots + a_1\cdot2^8 + a_0 = \sum_{i = {31}}^{0} a_i \cdot (2^8)^i, $$ -where each $a_i$ is a byte that can take values between $0$ and $2^8 - 1$. +where each $a_i$ is a byte that can take values between $0$ and $2^8 - 1$. **Example 1** @@ -145,7 +145,7 @@ If $\mathbf{a} = 29967$, its byte decomposition can be written as $\mathbf{a} = Here is how the addition operation on two $256$-bit numbers is reduced to a byte-by-byte addition, and thus ready to use the byte-wise Plookup table. -Observe that adding two bytes $a$ and $b$ (i.e., $a$ and $b$ are members of the set $[0, 2^8-1]$), may result in a sum $c$ which cannot be expressed as a single byte. +Observe that adding two bytes $a$ and $b$ (i.e., $a$ and $b$ are members of the set $[0, 2^8-1]$), may result in a sum $c$ which cannot be expressed as a single byte. For example, if $a = \mathtt{0xFF}$ and $b = \mathtt{0x01}$, then, @@ -231,13 +231,13 @@ Consider the following two scenarios: \mathbf{a} + \mathbf{b} = (c_2, c_1). $$ -Observe that addition of $256$-bit numbers can be reduced to additions at byte-level by operating through the previous cases in an iterative manner. +Observe that addition of $256$-bit numbers can be reduced to additions at byte-level by operating through the previous cases in an iterative manner. ### Subtraction -Reducing Subtraction to byte-level turns out to be trickier than Addition case. +Reducing Subtraction to byte-level turns out to be trickier than Addition case. -Suppose $\mathbf{a} = \mathtt{0x0101}$ and $\mathbf{b} = \mathtt{0x00FF}$. +Suppose $\mathbf{a} = \mathtt{0x0101}$ and $\mathbf{b} = \mathtt{0x00FF}$. Observe that $\mathtt{0xFF}$ cannot be subtracted from $\mathtt{0x01}$ because $\mathtt{0xFF} > \mathtt{0x01}$. @@ -254,7 +254,7 @@ $$ \end{aligned} $$ -The output byte decomposition is $\mathbf{a} = (c_1, c_0) = (\mathtt{0x00}, \mathtt{0x02})$. +The output byte decomposition is $\mathbf{a} = (c_1, c_0) = (\mathtt{0x00}, \mathtt{0x02})$. Nonetheless, it may be necessary to look at more examples so as to better understand how subtraction works at byte-level in a more general sense. @@ -275,13 +275,13 @@ $$ \begin{aligned} &(\mathtt{0x00} - \mathtt{0xFE}) \cdot 2^{16} + (\mathtt{0x01} - \mathtt{0xFF} - \mathtt{0x01}) \cdot 2^8 + \mathtt{0xFF} = \\ &(\mathtt{0x00} - \mathtt{0xFE} - \mathtt{0x01}) \cdot 2^{16} + (\mathtt{2^8} + \mathtt{0x01} - \mathtt{0xFF} - \mathtt{0x01}) \cdot 2^8 + \mathtt{0xFF} = \\ -&(\mathtt{0x00} - \mathtt{0xFE} - \mathtt{0x01}) \cdot 2^{16} + \mathtt{0x01} \cdot 2^8 + \mathtt{0xFF}. +&(\mathtt{0x00} - \mathtt{0xFE} - \mathtt{0x01}) \cdot 2^{16} + \mathtt{0x01} \cdot 2^8 + \mathtt{0xFF}. \end{aligned} $$ -Observe that the previous example is included in this case. +Observe that the previous example is included in this case. -In general, let $a = (a_i)_i$ and $b = (b_i)_i$, with $a_i, b_i$ bytes, be the byte representations of $a$ and $b$. Instead of checking if we can perform the subtraction $a_i - b_i$ for some bytes $i$, we are checking if $a_i - b_i - \texttt{carry} \geq 0$. Equivalently, we are checking if $a_i - \texttt{carry} \geq b_i$. The previous case can be recovered by setting $\texttt{carry} = 1$ and the first case corresponds to setting $\mathtt{carry = 0}$. +In general, let $a = (a_i)_i$ and $b = (b_i)_i$, with $a_i, b_i$ bytes, be the byte representations of $a$ and $b$. Instead of checking if we can perform the subtraction $a_i - b_i$ for some bytes $i$, we are checking if $a_i - b_i - \texttt{carry} \geq 0$. Equivalently, we are checking if $a_i - \texttt{carry} \geq b_i$. The previous case can be recovered by setting $\texttt{carry} = 1$ and the first case corresponds to setting $\mathtt{carry = 0}$. We have two possible cases, @@ -334,7 +334,7 @@ Henceforth, we should output a $0$, independently to the previous carry decision - If $a_i < b_i$, we set $\mathtt{carry}$ to $1$. If we are at the most significant byte, we output $1$. - If $a_i = b_i$, we let $\mathtt{carry}$ unchanged in order to maintain the previous decision. If we are at the most significant byte, we output $\mathtt{carry}$. -- If $a_i > b_i$, we set $\mathtt{carry}$ to $0$. If we are at the most significant byte, we output $0$. +- If $a_i > b_i$, we set $\mathtt{carry}$ to $0$. If we are at the most significant byte, we output $0$. ### Signed less than @@ -356,9 +356,9 @@ $$ 10000 - 0010 = 1110. $$ -Hence, observe that $-1 > -2$ because $1111 > 1110$ and, conversely, the order is preserved for integers of the same sign. +Hence, observe that $-1 > -2$ because $1111 > 1110$ and, conversely, the order is preserved for integers of the same sign. -We will describe a method to compare signed integers byte-wise. First of all, let us analyze the order among all the signed bytes, in order to understand how to compare them. Once we achieve this, the strategy will be very similar to the previous Less Than. +We will describe a method to compare signed integers byte-wise. First of all, let us analyze the order among all the signed bytes, in order to understand how to compare them. Once we achieve this, the strategy will be very similar to the previous Less Than. Let $a = (a_{31}, a_{30}, \dots, a_0)$ and $b = (b_{31}, b_{30}, \dots, b_0)$ be the byte-representation of the 256-bits unsigned integers $a$ and $b$. We will define $\texttt{sgn}(a) = a_{31, 7}$, where @@ -378,9 +378,9 @@ because $\texttt{sgn}(a) > \texttt{sgn}(b)$ i.e. $a$ is negative and $b$ is posi 2. If $\texttt{sgn}(a) = 0$ and $\texttt{sgn}(b) = 1$, then $a > b$. 3. If $\texttt{sgn}(a) = \texttt{sgn}(b)$, the order is the usual one and hence, we already know how to compare $a$ and $b$. -Recall that we are processing the bytes of $a$ and $b$ from the less significant bytes to the most significant bytes. Hence, we need to adapt our strategy following this order. The strategy will be almost the same than in the unsigned operation. +Recall that we are processing the bytes of $a$ and $b$ from the less significant bytes to the most significant bytes. Hence, we need to adapt our strategy following this order. The strategy will be almost the same than in the unsigned operation. -1. First of all, we start comparing $a_0$ and $b_0$. +1. First of all, we start comparing $a_0$ and $b_0$. (a) If $a_0 < b_0$, we set $\texttt{carry} = 1$. @@ -401,20 +401,20 @@ Recall that we are processing the bytes of $a$ and $b$ from the less significant (b) If $\texttt{sgn}(a) < \texttt{sgn}(b)$, we output a $0$, so $a < b$. (c) If $\texttt{sgn}(a) = \texttt{sgn}(b)$, we compare the last bytes $a_{31}$ and $b_{31}$ in the same way we have compared the previous bytes. We output $0$ or $1$ accordingly. - + 1. If $a_{31} < b_{31}$, we output a $1$, so $a < b$. 2. If $a_{31} = b_{31}$, we output the previous $\texttt{carry}$, maintaining the last decision. - 3. Otherwise, we output a $0$, so $a \not < b$. + 3. Otherwise, we output a $0$, so $a \not < b$. -Let us exemplify the previous procedure setting $a = \mathtt{0xFF FF FF 00}$ and $b = \mathtt{0x00 FF FF FF}$. We know that $a < b$, so we should output a $1$. Observe that the less significant byte of $a$ is leaser than the less significant byte of $b$. Hence, we should put $\texttt{carry}$ equal to $1$. The next two bytes of $a$ and $b$ are both equal to $\mathtt{0xFF FF}$, therefore we maintain $\texttt{carry}$ unchanged equal to $1$. However, since $a$ is negative and $b$ is positive, we should change the decision and output a $1$, independently of the $\texttt{carry}$. +Let us exemplify the previous procedure setting $a = \mathtt{0xFF FF FF 00}$ and $b = \mathtt{0x00 FF FF FF}$. We know that $a < b$, so we should output a $1$. Observe that the less significant byte of $a$ is leaser than the less significant byte of $b$. Hence, we should put $\texttt{carry}$ equal to $1$. The next two bytes of $a$ and $b$ are both equal to $\mathtt{0xFF FF}$, therefore we maintain $\texttt{carry}$ unchanged equal to $1$. However, since $a$ is negative and $b$ is positive, we should change the decision and output a $1$, independently of the $\texttt{carry}$. ### Equality -We want to describe the equality comparator byte-wise. For unsigned $256$-bits integers, the operation $=$ will output $c = 1$ if $a = b$ and $c = 0$ otherwise. This operation is very simple to describe byte-wise, since $a = b$ if and only if all its bytes coincide. +We want to describe the equality comparator byte-wise. For unsigned $256$-bits integers, the operation $=$ will output $c = 1$ if $a = b$ and $c = 0$ otherwise. This operation is very simple to describe byte-wise, since $a = b$ if and only if all its bytes coincide. -Let us compare $a = \mathtt{0xFF 00 a0 10}$ and $b = \mathtt{0xFF 00 00 10}$ byte-wise. Observe that the first byte is the same $\mathtt{0x10}$, however the next byte is different $\mathtt{0xa0} \neq \mathtt{0x00}$. Hence, we can finish here and state that $a \neq b$. +Let us compare $a = \mathtt{0xFF 00 a0 10}$ and $b = \mathtt{0xFF 00 00 10}$ byte-wise. Observe that the first byte is the same $\mathtt{0x10}$, however the next byte is different $\mathtt{0xa0} \neq \mathtt{0x00}$. Hence, we can finish here and state that $a \neq b$. We will describe an algorithm in order to proceed processing all the bytes. We will use a carry to mark up when a difference among bytes has $\textbf{not}$ been found (i.e. if $\texttt{carry}$ reach $0$, then $a$ and $b$ should differ). Hence, the algorithm to compare two $32$-bytes integers $a = (a_{31}, a_{30}, \dots, a_{0})$ and $b = (b_{31}, b_{30}, \dots, b_0)$ is the following: @@ -442,7 +442,7 @@ $$ a \star b = (a_i \star b_i)_i = (a_{31} \star b_{31}, a_{30} \star b_{30}, \dots, a_0 \star b_0) $$ -for $\star$ being $\land, \lor$ or $\oplus$. +for $\star$ being $\land, \lor$ or $\oplus$. For example, if $a = \mathtt{0xCB} = \mathtt{0b11001011}$ and $b = \mathtt{0xEA} = \mathtt{0b11101010}$ then, @@ -468,21 +468,21 @@ The binary operations it executes, together with their specific opcodes, are: 3. The logical operations; `AND`, `OR`, `XOR` and `NOT`, each with its special opcode; `9` ,`10`, `11` and `12`, respectively. -**Firstly,** the Binary SM Executor translates the Binary Actions into the PIL language. +**Firstly,** the Binary SM Executor translates the Binary Actions into the PIL language. -**Secondly,** it executes the Binary Actions. +**Secondly,** it executes the Binary Actions. **And thirdly,** it uses the [Binary PIL program](https://github.com/hermeznetwork/zkproverjs/blob/main/pil/binary.pil), to check correct execution of the Binary Actions using Plookup. #### Translation to PIL language -It builds the constant polynomials, which are generated once-off at the beginning. These are; +It builds the constant polynomials, which are generated once-off at the beginning. These are; -- the 4 bits long operation code `P_OPCODE`, -- the 1-bit Carry-in `P_CIN`, -- the Last-byte `P_LAST`, -- the 1 byte input polynomials `P_A` and `P_B`, -- the 16-bit output polynomial `P_C`, +- the 4 bits long operation code `P_OPCODE`, +- the 1-bit Carry-in `P_CIN`, +- the Last-byte `P_LAST`, +- the 1 byte input polynomials `P_A` and `P_B`, +- the 16-bit output polynomial `P_C`, - the 1-bit Carry-out `P_COUT`. It also creates constants required in the Binary PIL program; @@ -492,19 +492,19 @@ It also creates constants required in the Binary PIL program; ### Execution of Binary actions -The crux of the Binary SM Executor is in the `lines 371 to 636` of [sm_binary.js](https://github.com/0xPolygonHermez/zkevm-proverjs/blob/main/src/sm/sm_binary.js). This is where it executes Binary Actions. +The crux of the Binary SM Executor is in the `lines 371 to 636` of [sm_binary.js](https://github.com/0xPolygonHermez/zkevm-proverjs/blob/main/src/sm/sm_binary.js). This is where it executes Binary Actions. -1. It takes the committed polynomials A, B and C, and breaks them into bytes (in little-endian form). +1. It takes the committed polynomials A, B and C, and breaks them into bytes (in little-endian form). 2. It sequentially pushes each triplet of bytes (`freeInA`, `freeInB`, `freeInC`) into their corresponding registries (`ai`, `bi`, `ci`). - It runs one for-loop for all committed polynomials (A, B, C), over all the bytes of the 8 registries, which are altogether 32 bytes per committed polynomial. + It runs one for-loop for all committed polynomials (A, B, C), over all the bytes of the 8 registries, which are altogether 32 bytes per committed polynomial. Recall that `LATCH_SIZE = REGISTERS_NUM * BYTES_PER_REGISTER` = 8 registries * 4 bytes. It hence amounts to 32 bytes for each committed polynomial. -3. Once the 256-bit LATCH is built, it checks the opcodes and then computes the required binary operations in accordance with the instructions of the Main SM. +3. Once the 256-bit LATCH is built, it checks the opcodes and then computes the required binary operations in accordance with the instructions of the Main SM. -4. It also generates the final registries. +4. It also generates the final registries. ### The Binary PIL (program) @@ -514,12 +514,12 @@ The program operates byte-wise to carry out 256-bit Plookup operations. Each row of the lookup table is a vector of the form; \{ `P_LAST`, `P_OPCODE`, `P_A`, `P_B`, `P_CIN`, `P_C`, `P_COUT` \}, consisting of the constant polynomials created by the Binary SM Executor. As seen above, -- `P_LAST` is the Last-byte, -- `P_OPCODE` is the 4-bit operation code, +- `P_LAST` is the Last-byte, +- `P_OPCODE` is the 4-bit operation code, - `P_A` and `P_B`, are the 1-byte input polynomials, - `P_CIN` is the 1-bit Carry-in, -- `P_C` is the 16-bit output polynomial, +- `P_C` is the 16-bit output polynomial, - `P_COUT` is the 1-bit Carry-out. The Binary PIL program takes in byte-size inputs, as in the Binary SM Executor, each 256-bit input committed polynomial is first broken into 32 bytes. @@ -539,7 +539,7 @@ For each of the 32 triplets `freeInA`, `freeInB` and `freeInC`, tallying with th Line 104. `c0Temp' = c0Temp * (1 - RESET) + freeInC * FACTOR[0];` - Line 105. ` c0' = useCarry * (cOut - c0Temp ) + c0Temp;` + Line 105. `c0' = useCarry * (cOut - c0Temp ) + c0Temp;` For all non-Boolean operations; the default value for `useCarry` is zero, making `c0' = c0Temp`. The value of `c0'` is therefore of the same form as other `ci'` update values. @@ -551,6 +551,6 @@ The Polygon zkEVM repository is available on [GitHub](https://github.com/0xPolyg **Binary SM Executor**: [sm_binary.js](https://github.com/0xPolygonHermez/zkevm-proverjs/blob/main/src/sm/sm_binary.js) -**Binary SM PIL**: [binary.pil](https://github.com/0xPolygonHermez/zkevm-proverjs/blob/main/pil/binary.pil) +**Binary SM PIL**: [binary.pil](https://github.com/0xPolygonHermez/zkevm-proverjs/blob/main/pil/binary.pil) **Test Vectors**: [binary_test.js](https://github.com/0xPolygonHermez/zkevm-proverjs/blob/main/test/sm/sm_binary_test.js) diff --git a/docs/zkEVM/zkprover/bits2field-sm.md b/docs/zkEVM/architecture/zkprover/bits2field-sm.md similarity index 93% rename from docs/zkEVM/zkprover/bits2field-sm.md rename to docs/zkEVM/architecture/zkprover/bits2field-sm.md index e7e220348..5e200eceb 100644 --- a/docs/zkEVM/zkprover/bits2field-sm.md +++ b/docs/zkEVM/architecture/zkprover/bits2field-sm.md @@ -1,12 +1,12 @@ The **Bits2Field State Machine** is one of the auxiliary state machines used specifically for parallelizing the implementation of KECCAK-F SM. Its source code is available [here](https://github.com/0xPolygonHermez/zkevm-prover/blob/main/src/sm/bits2field/bits2field_executor.cpp). -The Bits2Field state machine ensures correct packing of $\mathtt{44}$ bits from $\mathtt{44}$ different $\mathtt{1600}$-row blocks of the Padding-KK-Bit SM into a single field element. Therefore, **it operates like a (44 bits to 1 field element) multiplexer between the Padding-KK-Bit SM and the Keccak-F SM**. +The Bits2Field state machine ensures correct packing of $\mathtt{44}$ bits from $\mathtt{44}$ different $\mathtt{1600}$-row blocks of the Padding-KK-Bit SM into a single field element. Therefore, **it operates like a (44 bits to 1 field element) multiplexer between the Padding-KK-Bit SM and the Keccak-F SM**. In simpler terms, it takes bits from $\mathtt{44}$ different blocks, places them into the first 44 bit-positions of a single field element, whereupon the KECCAK-F circuit runs. **The name Bits2Field State Machine refers to the processing where $44$ **bits** from $44$ different blocks of the Padding-KK-Bit SM are inserted into a single field element**. Although the KECCAK-F SM is a binary circuit, instead of executing on a bit-by-bit basis, **it is implemented to execute KECCAK-F operations on a 44bits-by-44bits basis**. This is tantamount to running $\mathtt{44}$ KECCAK-F hashing circuits in parallel. -![The 44 bits to 1 field-element Multiplexing](../../img/zkvm/01b2f-44-2-one-multiplex.png) +![The 44 bits to 1 field-element Multiplexing](../../../img/zkEVM/01b2f-44-2-one-multiplex.png) ## Mapping 44 Bits To A 64-bit Field Element @@ -14,7 +14,7 @@ Suppose operations are carried out in a field $\mathbb{F}_p$ of $\mathtt{64}$-bi After multiplexing, the 44 bits are loaded into the first 44 least significant bit-positions of the field element as depicted in the figure below. -![Figure 2: 44 Bits mapped to a 64-bit field element](../../img/zkvm/02b2f-44-bits-to-64bit-fe.png) +![Figure 2: 44 Bits mapped to a 64-bit field element](../../../img/zkEVM/02b2f-44-bits-to-64bit-fe.png) A field element as an input to the KECCAK-F circuit is of the form, @@ -31,7 +31,7 @@ Given the capacity of $2^{23}$ in terms of the state machine evaluations (i.e., The [Bits2Field executor](https://github.com/0xPolygonHermez/zkevm-prover/blob/main/src/sm/bits2field/bits2field_executor.cpp) executes the multiplexing of forty-four $\mathtt{1600}$-bit blocks into $\mathtt{1600}$ field elements, where each is a $\mathtt{N}$-bit field element. For reference, see the above figure where $\mathtt{N = 64}$. -The question here is how to identify each of the original 9 bits of the field element to track their corresponding resultant $\mathtt{XOR}$ values or $\mathtt{ANDP}$ values? +The question here is how to identify each of the original 9 bits of the field element to track their corresponding resultant $\mathtt{XOR}$ values or $\mathtt{ANDP}$ values? Note that every bit $\mathtt{b_{i,j}}$ from the $\mathtt{i}$-th $\mathtt{1600}$-bit block is placed at the $\mathtt{2^{i}}$-th position of the $\mathtt{N}$-bit field element. diff --git a/docs/zkEVM/zkprover/circom-in-zkprover.md b/docs/zkEVM/architecture/zkprover/circom-in-zkprover.md similarity index 96% rename from docs/zkEVM/zkprover/circom-in-zkprover.md rename to docs/zkEVM/architecture/zkprover/circom-in-zkprover.md index 788daadc8..0a7a8f1f2 100644 --- a/docs/zkEVM/zkprover/circom-in-zkprover.md +++ b/docs/zkEVM/architecture/zkprover/circom-in-zkprover.md @@ -3,7 +3,6 @@ Although CIRCOM is mainly used to convert a STARK proof into its respective Arit !!!info This document gives further elaboration on the [Proving Architecture](proving-architecture.md) by focusing on the CIRCOM Arithmetic circuits, while highlighting CIRCOM's pivotal role in the STARK Recursion process. - ## zkEVM Batch Prover The first step in proving Computational Integrity starts with the **zkEVM Batch Prover**. @@ -12,7 +11,7 @@ It is a circuit that proves correctness of the state transition from an `oldStat The **zkEVM Batch Prover** takes as inputs; the `oldStateRoot`, `oldAccInputHash`, `oldBatchNum`, `chainID` and `forkID`. And its outputs are; the `newStateRoot`, `newAccInputHash`, `localExitRoot` and `newBatchNum`, -![zkEVM Batch Prover](../../img/zkvm/04circom-batch-prover.png) +![zkEVM Batch Prover](../../../img/zkEVM/04circom-batch-prover.png) The `localExitRoot` is the Merkle root of the `ExitTree` used in the Bridge to transfer information from the L2 to the Ethereum L1. @@ -22,7 +21,7 @@ All transactions being processed are encoded into the batch via the `oldAccInput Although built in a smart contract, the encoding of transactions resembles a blockchain, where transactions are chained together with the Keccak hash function. See figure below depicting this encoding. -![Transactions chained into a batch](../../img/zkvm/05circom-forming-batch.png) +![Transactions chained into a batch](../../../img/zkEVM/05circom-forming-batch.png) The main idea, when proving validity of a batch, is for the `oldAccInputHash` and its corresponding `newAccInputHash` to match accordingly. @@ -54,7 +53,7 @@ Since the underlying proof scheme is PIL-STARK, in each of these prover circuits A typical $\mathtt{recursive_x}\ \mathtt{Verifier}$ CIRCOM template, for any $\texttt{x} \in \{1, 2, f\}$, looks like the circuit shown below. -![Figure _ : Typical $\mathtt{recursive_1}\ \mathtt{Prover}$ CIRCOM template](../../img/zkvm/06circom-typical-recursive-prover.png) +![Figure _ : Typical $\mathtt{recursive_1}\ \mathtt{Prover}$ CIRCOM template](../../../img/zkEVM/06circom-typical-recursive-prover.png) ## Proof-Size Reductions diff --git a/docs/zkEVM/zkprover/construct-key-path.md b/docs/zkEVM/architecture/zkprover/construct-key-path.md similarity index 97% rename from docs/zkEVM/zkprover/construct-key-path.md rename to docs/zkEVM/architecture/zkprover/construct-key-path.md index c5a6fca15..d94b46278 100644 --- a/docs/zkEVM/zkprover/construct-key-path.md +++ b/docs/zkEVM/architecture/zkprover/construct-key-path.md @@ -6,7 +6,7 @@ $$ \text{Key}_{\mathbf{0123}} = \big( \text{Key}_{\mathbf{0}} , \text{Key}_{\mathbf{1}} , \text{Key}_{\mathbf{2}} , \text{Key}_{\mathbf{3}} \big) $$ -where each $\text{Key}_{\mathbf{i}} \in \mathbb{F}_p$, where $p = 2^{64} - 2^{32} + 1$. +where each $\text{Key}_{\mathbf{i}} \in \mathbb{F}_p$, where $p = 2^{64} - 2^{32} + 1$. Although hashed-values are also 256-bit long and are used in quadruple form, **committed** values are 256-bit long and are often expressed as octets. It is mainly due to the POSEIDON SM convention, where 256-bit committed values are input as $\text{V}_{\mathbf{01..7}} = \big( \text{V}_{\mathbf{0}} , \text{V}_{\mathbf{1}} , \text{V}_{\mathbf{2}} , \dots , \text{V}_{\mathbf{7}} \big)$ and each 32-bit $V_{\mathbf{j}}$ chunk of bits. @@ -14,7 +14,7 @@ In fact, almost every other 256-bit value in the Storage is expressed in the for ## How keys are created -In the key-value pair SMT context of our storage design, a key uniquely identifies a leaf. And it is because, although values can change, keys do not. +In the key-value pair SMT context of our storage design, a key uniquely identifies a leaf. And it is because, although values can change, keys do not. Keys must consequently be generated deterministically, and in such a way that there are no collisions. That is, there must be a one-to-correspondence between keys and leaves. @@ -44,13 +44,13 @@ $$ That is, the Navigation Path to the leaf corresponding to $\text{Key}_{\mathbf{0123}}$ is the string of bits composed of: - The least-significant bits of the four key parts, $\text{Key}_{\mathbf{0}} , \text{Key}_{\mathbf{1}} , \text{Key}_{\mathbf{2}} , \text{Key}_{\mathbf{3}}$, appearing in the order of the key parts as: $k_{\mathbf{0,0}\ } k_{\mathbf{1,0}\ } k_{\mathbf{2,0}\ } k_{\mathbf{3,0}}$. -- Followed by the second least-significant bits of the four key parts, $\text{Key}_{\mathbf{0}} , \text{Key}_{\mathbf{1}} , \text{Key}_{\mathbf{2}} , \text{Key}_{\mathbf{3}}$, appearing in the order of the key parts as: $k_{\mathbf{0,1}\ } k_{\mathbf{1,1}\ } k_{\mathbf{2,1}\ } k_{\mathbf{3,1}}$. +- Followed by the second least-significant bits of the four key parts, $\text{Key}_{\mathbf{0}} , \text{Key}_{\mathbf{1}} , \text{Key}_{\mathbf{2}} , \text{Key}_{\mathbf{3}}$, appearing in the order of the key parts as: $k_{\mathbf{0,1}\ } k_{\mathbf{1,1}\ } k_{\mathbf{2,1}\ } k_{\mathbf{3,1}}$. - Then the third least-significant bits of the four key parts, $\text{Key}_{\mathbf{0}} , \text{Key}_{\mathbf{1}} , \text{Key}_{\mathbf{2}} , \text{Key}_{\mathbf{3}}$, appearing in the order of the key parts as: $k_{\mathbf{0,2}\ } k_{\mathbf{1,2}\ } k_{\mathbf{2,2}\ } k_{\mathbf{3,2}}$. - Up until the most-significant bits of the four key parts, $\text{Key}_{\mathbf{0}} , \text{Key}_{\mathbf{1}} , \text{Key}_{\mathbf{2}} , \text{Key}_{\mathbf{3}}$, appearing in the order of the key parts as: $k_{\mathbf{0,63}\ } k_{\mathbf{1,63}\ } k_{\mathbf{2,63}\ } k_{\mathbf{3,63} }$. -![Navigation Path Derivation](../../img/zkvm/fig15-path-frm-key.png) +![Navigation Path Derivation](../../../img/zkEVM/fig15-path-frm-key.png) -This construction ensures that in every quadruplet of consecutive path-bits, there is a one-to-one correspondence between the bits and the four parts of the key, $\text{Key}_{\mathbf{0}} , \text{Key}_{\mathbf{1}} , \text{Key}_{\mathbf{2}} , \text{Key}_{\mathbf{3}}$. +This construction ensures that in every quadruplet of consecutive path-bits, there is a one-to-one correspondence between the bits and the four parts of the key, $\text{Key}_{\mathbf{0}} , \text{Key}_{\mathbf{1}} , \text{Key}_{\mathbf{2}} , \text{Key}_{\mathbf{3}}$. ## Reconstructing the key from path-bits @@ -102,18 +102,18 @@ In order to explore cyclic groups of order 4, take the vector $\mathbf{x} = (1, Note that, rotating $\mathbf{x} = (1,0,0,0)$ -- once, yields $(0,0,0,1)$ +- once, yields $(0,0,0,1)$ - twice, one obtains $(0,0,1,0)$ -- thrice, one gets $(0,1,0,0)$ -- four times, and the result is $\mathbf{x} = (1,0,0,0)$ +- thrice, one gets $(0,1,0,0)$ +- four times, and the result is $\mathbf{x} = (1,0,0,0)$ -Continuously rotating $\mathbf{x} = (1,0,0,0)$ will not result in any other vector but the four vectors +Continuously rotating $\mathbf{x} = (1,0,0,0)$ will not result in any other vector but the four vectors $$ \mathbf{G_4} = \{ (1,0,0,0),\ (0,0,0,1),\ (0,0,1,0),\ (0,1,0,0) \}. $$ -This set of four vectors $\mathbf{G_4}$ together with the described **rotation**, forms a group. +This set of four vectors $\mathbf{G_4}$ together with the described **rotation**, forms a group. In fact, $\mathbf{G_4}$ is isomorphic (or homomorphically equivalent) to $\mathbb{Z}_4$ under **addition modulo 4**. diff --git a/docs/zkEVM/zkprover/executor-pil.md b/docs/zkEVM/architecture/zkprover/executor-pil.md similarity index 96% rename from docs/zkEVM/zkprover/executor-pil.md rename to docs/zkEVM/architecture/zkprover/executor-pil.md index 6a64a8d40..65f6958a3 100644 --- a/docs/zkEVM/zkprover/executor-pil.md +++ b/docs/zkEVM/architecture/zkprover/executor-pil.md @@ -16,17 +16,17 @@ The Executor therefore uses an internal 4-element register called `op = [_,_,_,_ All the function calls seen in the Assembly code: -`GetSibling()`, `GetValueLow()`, `GetValueHigh()`, `GetRKey()`, `GetSiblingRKey()`, `GetSiblingHash()`, `GetSiblingValueLow()`, `GetSiblingValueHigh()`, `GetOldValueLow()`, `GetOldValueHigh()`, `GetLevelBit()`, `GetTopTree()`, `GetTopBranch()` and `GetNextKeyBit()`; +`GetSibling()`, `GetValueLow()`, `GetValueHigh()`, `GetRKey()`, `GetSiblingRKey()`, `GetSiblingHash()`, `GetSiblingValueLow()`, `GetSiblingValueHigh()`, `GetOldValueLow()`, `GetOldValueHigh()`, `GetLevelBit()`, `GetTopTree()`, `GetTopBranch()` and `GetNextKeyBit()`; -are actually performed by the Storage Executor. The values being fetched are carried with the `op` register. For instance, if the function call is `GetRKey()` then the Storage Executor gets the RKey from the rom.line file, carries it with `op` as; +are actually performed by the Storage Executor. The values being fetched are carried with the `op` register. For instance, if the function call is `GetRKey()` then the Storage Executor gets the RKey from the rom.line file, carries it with `op` as; -`op[0] = ctx.rkey[0];` +`op[0] = ctx.rkey[0];` `op[1] = ctx.rkey[1];` `op[2] = ctx.rkey[2];` -`op[3] = ctx.rkey[3];` where `ctx` signifies a **Storage Action**. +`op[3] = ctx.rkey[3];` where `ctx` signifies a **Storage Action**. Also, since all Storage Actions require some hashing, the Storage SM delegates all hashing actions to the POSEIDON SM. However, from within the Storage SM, it is best to treat the POSEIDON SM as a blackbox. The Storage Executor simply specifies the sets of twelve values to be digested. And the POSEIDON SM then returns the required digests of the values. @@ -38,7 +38,6 @@ The preparation for these polynomial constraints actually starts in the Storage
- | Selectors | Setters | Instructions | | :--------------------- | :--------------------- | :---------------- | | selFree[i] | setHashLeft[i] | iHash | @@ -58,7 +57,7 @@ The preparation for these polynomial constraints actually starts in the Storage
-Every time each of these Boolean polynomials are utilised or performed, a record of a "1" is kept in its register. This is called an **Execution Trace**. +Every time each of these Boolean polynomials are utilised or performed, a record of a "1" is kept in its register. This is called an **Execution Trace**. Therefore, instead of performing some expensive computations in order to verify correctness of execution (at times repeating the same computations being verified), the trace of execution is tested. @@ -66,18 +65,18 @@ The verifier takes the execution trace, and tests if it satisfies the polynomial ## The Poseidon hash -Poseidon SM is more straightforward once one understands the internal mechanism of the original Poseidon hash function. The hash function's permutation process translates readily to the Poseidon SM states. +Poseidon SM is more straightforward once one understands the internal mechanism of the original Poseidon hash function. The hash function's permutation process translates readily to the Poseidon SM states. The POSEIDON State Machine carries out POSEIDON Actions in accordance with instructions from the Main SM Executor and requests from the Storage SM. That is, it computes hashes of messages sent from any of the two SMs, and also checks if the hashes were correctly computed. The zkProver uses the **goldilocks POSEIDON** which is defined over the field $\mathbb{F}_p$, where $p = 2^{64} - 2^{32} + 1$. -The states of the POSEIDON SM coincide with the twelve (12) internal states of the $\text{POSEIDON}^{\pi}$ permutation function. These are; `in0`, `in1`, ... , `in7`, `hashType`, `cap1`, `cap2` and `cap3`. +The states of the POSEIDON SM coincide with the twelve (12) internal states of the $\text{POSEIDON}^{\pi}$ permutation function. These are; `in0`, `in1`, ... , `in7`, `hashType`, `cap1`, `cap2` and `cap3`. $\text{POSEIDON}^{\pi}$ runs 30 rounds, 3 times. Adding up to a total of 90 rounds. It outputs four (4) hash values; `hash0`, `hash1`, `hash2` and `hash3`. -![POSEIDON HASH0 ](../../img/zkvm/fig16-posdn-eg.png) +![POSEIDON HASH0 ](../../../img/zkEVM/fig16-posdn-eg.png) -In the case of the zkProver storage, two slightly different POSEIDON hashes are used; $\text{HASH0}$ is used when a branch node is created, whilst $\text{HASH1}$ is used when a leaf node is created. This depends on the `hashType`, which is a boolean. So POSEIDON acts as $\text{HASH1}$ when `hashType` = 1, and $\text{HASH0}$ when `hashType` = 0. +In the case of the zkProver storage, two slightly different POSEIDON hashes are used; $\text{HASH0}$ is used when a branch node is created, whilst $\text{HASH1}$ is used when a leaf node is created. This depends on the `hashType`, which is a boolean. So POSEIDON acts as $\text{HASH1}$ when `hashType` = 1, and $\text{HASH0}$ when `hashType` = 0. Since POSEIDON Hashes outputs $4 * \lfloor(63.99)\rfloor \text{ bits} = 252$, and one bit is needed to encode each direction, the tree can therefore have a maximum of 252 levels. diff --git a/docs/zkEVM/zkprover/final-recursion-step.md b/docs/zkEVM/architecture/zkprover/final-recursion-step.md similarity index 91% rename from docs/zkEVM/zkprover/final-recursion-step.md rename to docs/zkEVM/architecture/zkprover/final-recursion-step.md index 621176f84..468b92b63 100644 --- a/docs/zkEVM/zkprover/final-recursion-step.md +++ b/docs/zkEVM/architecture/zkprover/final-recursion-step.md @@ -12,11 +12,11 @@ In order to achieve this, a verifier circuit `recursive2.verifier.circom` is gen by filling the $\mathtt{stark\_} \texttt{verifier.circom.ejs}$ template. -The output CIRCOM file `recursivef.circom`, obtained by running a different script called `genrecursivef`, is in turn compiled into an R1CS `recursivef.r1cs` file and a \$\text{witness calculator program` `recursivef.witnesscal`. +The output CIRCOM file `recursivef.circom`, obtained by running a different script called `genrecursivef`, is in turn compiled into an R1CS `recursivef.r1cs` file and a \$\text{witness calculator program``recursivef.witnesscal`. Both these outputs are used later on, to build and fill the next execution trace. -![Figure 19: Convert the `recursive2` STARK to its verifier circuit called `recursivef`.](../../img/zkvm/19prf-rec-recursive2-stark-to-recursivef-circuit.png) +![Figure 19: Convert the `recursive2` STARK to its verifier circuit called `recursivef`.](../../../img/zkEVM/19prf-rec-recursive2-stark-to-recursivef-circuit.png) ## Setup `C2S` for `recursivef` @@ -33,7 +33,7 @@ Since all FRI-related parameters are stored in a `recursive.starkstruct` file, a - the `recursivef.pil` file as inputs to the $\mathtt{generate\_starkinfo}$ service in order to generate the `recursivef.starkinfo` file, and - the `recursivef.const` as inputs to the component that builds the Merkle tree of evaluations of constant polynomials, `recursivef.consttree`, and its root `recursivef.verkey`. -![Figure 20: Convert the `recursivef` circuit to its associated STARK.](../../img/zkvm/20prf-rec-recursivef-circuit-2-stark.png) +![Figure 20: Convert the `recursivef` circuit to its associated STARK.](../../../img/zkEVM/20prf-rec-recursivef-circuit-2-stark.png) ## Setup `S2C` for final @@ -49,4 +49,4 @@ by filling the $\mathtt{stark\_} \texttt{verifier.circom.ejs}$ template. This verifier CIRCOM file gets imported by the `final.circom` circuit in order to generate the circuit being proved, using `FFLONK` procedure. -![Convert the `recursivef` STARK to its verifier circuit called `final.circom}$.](../../img/zkvm/21prf-rec-recursivef-stark-to-final-circom.png) +![Convert the `recursivef` STARK to its verifier circuit called `final.circom}$.](../../../img/zkEVM/21prf-rec-recursivef-stark-to-final-circom.png) diff --git a/docs/zkEVM/zkprover/intermediate-recursion.md b/docs/zkEVM/architecture/zkprover/intermediate-recursion.md similarity index 94% rename from docs/zkEVM/zkprover/intermediate-recursion.md rename to docs/zkEVM/architecture/zkprover/intermediate-recursion.md index ea3a968b8..2e10be160 100644 --- a/docs/zkEVM/zkprover/intermediate-recursion.md +++ b/docs/zkEVM/architecture/zkprover/intermediate-recursion.md @@ -24,7 +24,7 @@ The verifier circuit is instantiated inside $\mathtt{recursive1.circom}$, connec The output circom file `recursive1.circom` , is compiled into a R1CS `recursive1.r1cs` file and a `witness calculator program`, $\mathtt{recursive1.witnesscal}$, which will be used for both building and filling the next execution trace. -![Convert the c12a STARK to a c12a verifier circuit](../../img/zkvm/14prf-rec-convert-stark-to-circuit-verifier.png) +![Convert the c12a STARK to a c12a verifier circuit](../../../img/zkEVM/14prf-rec-convert-stark-to-circuit-verifier.png) ## Setup `C2S` for `recursive1` @@ -41,7 +41,7 @@ Note that all the FRI-related parameters are stored in a `recursive.starkstruct` In this case, a blowup factor of $2^4 = 16$ is used, and thus allowing the number of queries to be $32$. -![Convert the `recursive1` circuit to its associated STARK](../../img/zkvm/15prf-rec-convert-circuit-to-assoc-stark.png) +![Convert the `recursive1` circuit to its associated STARK](../../../img/zkEVM/15prf-rec-convert-circuit-to-assoc-stark.png) ## Setup `S2C` for `recursive2` @@ -68,7 +68,7 @@ Henceforth, the `recursive2.circom` circuit has two verifiers and two multiplexo A schema of the `recursive2` circuit generated is as shown in the below Figure. -![Figure 16: Convert the `recursive1` circuit to its associated STARK](../../img/zkvm/16prf-rec-recursive2-circuit.png) +![Figure 16: Convert the `recursive1` circuit to its associated STARK](../../../img/zkEVM/16prf-rec-recursive2-circuit.png) Observe that, since the upper proof is of the $\mathtt{\pi_{rec2}}$-type, the Multiplexor does not provides the constant root `rootC` to the `Verifier A` for hardcoding it, because this verifier should get it through a public input from the previous circuit. @@ -76,7 +76,7 @@ Otherwise, since the lower proof has the $\mathtt{\pi_{rec1}}$-type, the Multipl The output CIRCOM file `recursive2.circom` , is obtained by running a different script called `genrecursive` which is compiled into an R1CS `recursive2.r1cs` file and a witness calculator program `recursive2.witnesscal` and they will both be used, later on, to build and fill the next execution trace. -![Convert the `recursive1` STARK to its verifier circuit called `recursive2` ](../../img/zkvm/17prf-rec-stark-to-circuit-recursive2.png) +![Convert the `recursive1` STARK to its verifier circuit called `recursive2` ](../../../img/zkEVM/17prf-rec-stark-to-circuit-recursive2.png) ## Setup `C2S` for `recursive2` @@ -98,4 +98,4 @@ Note that all the FRI-related parameters are stored in a `recursive.starkstruct` In this case, we are using the same blowup factor of $2^4 = 16$, allowing the number of queries to be $32$. -![Convert the `recursive2` circuit to its associated STARK.](../../img/zkvm/18prf-rec-recursive2-circuit-2-stark.png) +![Convert the `recursive2` circuit to its associated STARK.](../../../img/zkEVM/18prf-rec-recursive2-circuit-2-stark.png) diff --git a/docs/zkEVM/zkprover/intro-hashing-sm.md b/docs/zkEVM/architecture/zkprover/intro-hashing-sm.md similarity index 95% rename from docs/zkEVM/zkprover/intro-hashing-sm.md rename to docs/zkEVM/architecture/zkprover/intro-hashing-sm.md index b9b249a42..607e268c1 100644 --- a/docs/zkEVM/zkprover/intro-hashing-sm.md +++ b/docs/zkEVM/architecture/zkprover/intro-hashing-sm.md @@ -24,7 +24,7 @@ The state array is split into two chunks, one with $r$ bits and the other with $ The elements that completely describe a single instance of a sponge construction are: the **fixed-length permutation $f$**, the **padding rule pad**, the **bitrate value $r$**, and the **capacity $c$**. A schema of the sponge construction is shown in the below figure. -![A Sponge Function Construction](../../img/zkvm/hsh01-sponge-construction.png) +![A Sponge Function Construction](../../../img/zkEVM/hsh01-sponge-construction.png) ### Initializing phase @@ -36,7 +36,7 @@ The **state of the hash function is initialized to a $b$-bit vector (or array) o During this phase, the $r$-bit input blocks are XOR-ed sequentially with the first $r$ bits of the state, intermixed with permutation function $f$ applications. This process is repeated until all input blocks have been XOR-ed with the state. -Take note that **the last $c$ bits, which correspond to the capacity value, do not absorb any external input**. +Take note that **the last $c$ bits, which correspond to the capacity value, do not absorb any external input**. ### Squeezing phase diff --git a/docs/zkEVM/zkprover/intro-main-sm.md b/docs/zkEVM/architecture/zkprover/intro-main-sm.md similarity index 94% rename from docs/zkEVM/zkprover/intro-main-sm.md rename to docs/zkEVM/architecture/zkprover/intro-main-sm.md index 0271c7357..653295eb6 100644 --- a/docs/zkEVM/zkprover/intro-main-sm.md +++ b/docs/zkEVM/architecture/zkprover/intro-main-sm.md @@ -1,10 +1,10 @@ -Main State Machine is a component of the zkProver that can be instantiated with various computations pertaining to transactions submitted by users to the Polygon zkEVM network. +Main State Machine is a component of the zkProver that can be instantiated with various computations pertaining to transactions submitted by users to the Polygon zkEVM network. In addition to carrying out these computations, the Main SM also generates fixed-length, easy-to-verify cryptographic proofs of Computational Integrity (CI). These proofs can be verified by spending only a minimal amount of computational resources. It achieves this by using cutting-edge zero-knowledge technology. In particular, these proofs are STARK proofs that are recursively aggregated into one STARK proof, which is in turn proved with a SNARK proof. This last SNARK proof is published as the validity proof. You can read a summary of the STARK proofs recursion [here](zkprover-overview.md), and its complete documentation [here](intro-stark-recursion.md). -![zkEVM batch prover structure](../../img/zkvm/02msm-prover-structure.png) +![zkEVM batch prover structure](../../../img/zkEVM/02msm-prover-structure.png) ## The ROM @@ -23,7 +23,6 @@ All EVM opcodes are interpreted in the ROM, as well as interpretation of batches **EVM opcodes** → Set of instructions designed to target the EVM, used to define smart contract’s computations. - Although zkASM instructions and EVM opcodes are different types of instructions, the Polygon zkEVM's ROM contains a piece of code written in zkASM instructions to implement each EVM opcode. ## Public Parameters @@ -84,15 +83,15 @@ $$ where the Ethereum Account is composed of; the Nonce, Balance, Storage Root, and Code hash. -The Storage Root is basically all the storage of the State that a smart contract has, and is coded into another Modified Patricia Merkle Tree. +The Storage Root is basically all the storage of the State that a smart contract has, and is coded into another Modified Patricia Merkle Tree. Here is how the tree in the EVM looks like: -![A simplified EVM's State Trie](../../img/zkvm/06msm-eth-state-trie.png) +![A simplified EVM's State Trie](../../../img/zkEVM/06msm-eth-state-trie.png) ### zkEVM State Trie -There are some differences between the zkEVM Merkle tree and EVM Merkle tree. +There are some differences between the zkEVM Merkle tree and EVM Merkle tree. A zkEVM State is stored in the form of a Sparse Merkle Tree (SMT), which is a binary tree. Instead of **Keccak-256**, the `POSEIDON` Hash Function is used to build the SMTs, mainly due to its STARK-friendliness. @@ -106,13 +105,13 @@ Also, each value in a leaf is an array of eight values, $[\texttt{V0}, \texttt{V The $32$-bit field elements are $8$ in number, so as to be compatible with the $256$-bit EVM words. -So although in the EVM context computation work with $256$-bit words, internally the zkEVM uses $8$ times $32$-bit field elements. +So although in the EVM context computation work with $256$-bit words, internally the zkEVM uses $8$ times $32$-bit field elements. Each of the values; $\texttt{V0}, \texttt{V1}, \texttt{V2}, \dots , \texttt{V7}$; is composed of the $32$ less significant bits of the $63.99$-bit Goldilocks prime field elements. The figure below depicts the 5 leaf-types together with the corresponding keys: -![A simplified Polygon zkEVM's State Trie](../../img/zkvm/07msm-zkevm-state-trie.png) +![A simplified Polygon zkEVM's State Trie](../../../img/zkEVM/07msm-zkevm-state-trie.png) ## Memory Regions @@ -132,7 +131,7 @@ $$ The `Stack` and `Memory` are each filled with relevant values in accordance with the call that has been made. Similar to how the EVM uses the Stack, zkEVM operations can be performed by pushing and popping values on and off the Stack. -`Memory` is divided into different Contexts of $\mathtt{0x40000}$ words. +`Memory` is divided into different Contexts of $\mathtt{0x40000}$ words. Each word is $256$ bits in length, so each Context is $8$ Megabytes (MB) in size. @@ -142,13 +141,13 @@ There can be several Contexts within one transaction. Specific registers are use As depicted in the figure below, each Context is divided into three word-blocks. And these are: -- `VARS`: contains the local Context's variables which are pre-defined in the language. +- `VARS`: contains the local Context's variables which are pre-defined in the language. It has a relative offset of `0x00000` and a height of `0x10000` words (taking $2$ MB of the $8$ MB allocated for a Context). The list of all Context variables can be found in the [`vars.zkasm`](https://github.com/0xPolygonHermez/zkevm-rom/blob/main/main/vars.zkasm) file. -- `STACK`: contains the stack of the EVM. So, a `STACK` is defined per Context. +- `STACK`: contains the stack of the EVM. So, a `STACK` is defined per Context. It has a relative offset of `0x10000`, a height of `0x10000` words and takes $2$MB of the $8$MB allocated for a Context. @@ -158,7 +157,7 @@ As depicted in the figure below, each Context is divided into three word-blocks. `MEM`, like `STACK`, is also defined per Context. -![Schema of contexts and memory regions of the zkEVM](../../img/zkvm/08msm-zkevm-memory-regions.png) +![Schema of contexts and memory regions of the zkEVM](../../../img/zkEVM/08msm-zkevm-memory-regions.png) For a given slot in memory, its pointer is computed as: @@ -180,17 +179,17 @@ There is a major difference between the EVM Memory and the zkEVM Memory. That difference is the EVM Memory is created in the form of slots where each slot has $8$-bit capacity, while each Memory slot in the zkEVM can store $256$ bits of data. -It was therefore necessary to align the EVM's $8$-bit slots with the zkEVM's $256$-bit slots. +It was therefore necessary to align the EVM's $8$-bit slots with the zkEVM's $256$-bit slots. A mapping to synchronize the two Memories comes in the form a special state machine called the [**Mem-Align State Machine**](mem-align-sm.md). It is a specialized SM solely dealing with the alignment of the EVM Memory with the zkEVM Memory. -![Aligning the EVM Memory to the zkEVM Memory](../../img/zkvm/09msm-evm-zkevm-mem-align.png) +![Aligning the EVM Memory to the zkEVM Memory](../../../img/zkEVM/09msm-evm-zkevm-mem-align.png) ### zkEVM Stack The zkEVM Stack is exactly the same as the EVM Stack except for the number of steps. It has $65536$ steps instead of $1024$. -Note that the EVM works with $256$-bit words, and thus the elements of the EVM Stack are also $256$-bit. +Note that the EVM works with $256$-bit words, and thus the elements of the EVM Stack are also $256$-bit. The zkEVM Stack therefore, with its $8 \times 32$-bits representation of values, naturally mimics the $256$-bit architecture of the EVM Stack. @@ -200,13 +199,13 @@ The rest of the zkEVM Stack slots are used to store `CALLDATA` and its interpret The figure below displays a schematic representation of the zkEVM Stack and the EVM Stack: -![Schematic comparison of the zkEVM Stack and the EVM Stack](../../img/zkvm/10msm-zkevm-stack-slots.png) +![Schematic comparison of the zkEVM Stack and the EVM Stack](../../../img/zkEVM/10msm-zkevm-stack-slots.png) -## TLDR; +## TLDR → The ROM is a program written in zkASM. It contains the instructions that the zkProver must execute in order to produce verifiable Computational Integrity proofs. The ROM contains the rules and logic that form the firmware of the zkProver. Its code can be found [here](https://github.com/0xPolygonHermez/zkevm-rom) in the GitHub repository. -→ The zkEVM uses SMT with five different leaf types. +→ The zkEVM uses SMT with five different leaf types. → Memory alignment between the EVM and the zkEVM is handled by a specialist state machine, the [**Mem-Align State Machine**](mem-align-sm.md). diff --git a/docs/zkEVM/zkprover/intro-stark-recursion.md b/docs/zkEVM/architecture/zkprover/intro-stark-recursion.md similarity index 95% rename from docs/zkEVM/zkprover/intro-stark-recursion.md rename to docs/zkEVM/architecture/zkprover/intro-stark-recursion.md index 8ee6cf810..967c0e847 100644 --- a/docs/zkEVM/zkprover/intro-stark-recursion.md +++ b/docs/zkEVM/architecture/zkprover/intro-stark-recursion.md @@ -17,7 +17,7 @@ The process that leads to achieving such a State Machine-based system takes a fe These Polynomial Identities are equations that can be easily tested in order to verify the Prover's claims. -A **Commitment Scheme** is required for facilitating the proving and verification. Henceforth, in the zkProver context, a proof/verification scheme called **PIL-STARK** is used. Check out the documentation [here](../concepts/commitment-scheme.md) for the Polygon zkEVM's commitment scheme setting. +A **Commitment Scheme** is required for facilitating the proving and verification. Henceforth, in the zkProver context, a proof/verification scheme called **PIL-STARK** is used. Check out the documentation [here](../../concepts/commitment-scheme.md) for the Polygon zkEVM's commitment scheme setting. ## Overall Process @@ -25,7 +25,7 @@ In a nutshell, a state machine's execution trace is expressed in PIL, and this e In the non-recursive case, a PIL specification is transformed into a verifiable **STARK** proof by using PIL-STARK. -Subsequently, CIRCOM takes the above **STARK** proof as an input and generates an **Arithmetic circuit** and its corresponding **witness**. +Subsequently, CIRCOM takes the above **STARK** proof as an input and generates an **Arithmetic circuit** and its corresponding **witness**. The Arithmetic circuit is expressed in terms of its equivalent **Rank-1 Constraint System (R1CS)**, while the **witness** is actuallly a set of input, intermediate and output values of the circuit wires, satisfying the R1CS. diff --git a/docs/zkEVM/zkprover/intro-storage-sm.md b/docs/zkEVM/architecture/zkprover/intro-storage-sm.md similarity index 86% rename from docs/zkEVM/zkprover/intro-storage-sm.md rename to docs/zkEVM/architecture/zkprover/intro-storage-sm.md index f2f8257da..1857996c1 100644 --- a/docs/zkEVM/zkprover/intro-storage-sm.md +++ b/docs/zkEVM/architecture/zkprover/intro-storage-sm.md @@ -1,7 +1,8 @@ ## Introduction + A standard state machine is characterized by sets of states (as inputs) stored in registers, instructions on how the states should transition, and the resultant states (as outputs) stored as new values in the same registers. The below figure demonstrates a standard state machine. -![A Generic State Machine](../../img/zkvm/fig1-gen-state-mchn.png) +![A Generic State Machine](../../../img/zkEVM/fig1-gen-state-mchn.png) State machine can be monolithic, where it is a prototype of one particular computation, while others may specialise with certain types of computations. Depending on the computational algorithm, a state machine may have to run through a number of state transitions before producing the desired output. Iterations of the same sequence of operations may be required, to the extend that most common state machines are cyclic by nature. @@ -17,7 +18,7 @@ The Main SM's instructions, or Storage Actions, are parsed to the Storage SM Exe The hardware part uses another novel language, called **Polynomial Identity Language** (PIL), which is also developed by the team and especially designed for the zkProver, because almost all state machines express computations in terms of polynomials. State transitions in state machines must satisfy computation-specific polynomial identities. -In order for the Storage SM to carry out Storage Actions, its Executor generates committed and constant polynomials, which are then checked against polynomial identities to prove that computations were correctly executed. See the [Design Approach](../concepts/mfibonacci.md) section for how this achieved. +In order for the Storage SM to carry out Storage Actions, its Executor generates committed and constant polynomials, which are then checked against polynomial identities to prove that computations were correctly executed. See the [Design Approach](../../concepts/mfibonacci.md) section for how this achieved. ## zkProver's storage @@ -27,13 +28,13 @@ The Main SM performs computations on the key-value data stored in special Merkle The mechanics of the Storage SM and its basic operations are described in detail in later sections of this documentation. They cover: -1. The basic design of the zkProver's Storage and some preliminaries. Also explains how the Sparse Merkle Trees (SMTs) are built. +1. The basic design of the zkProver's Storage and some preliminaries. Also explains how the Sparse Merkle Trees (SMTs) are built. -2. Explanations of the basic operations routinely performed on these SMTs. +2. Explanations of the basic operations routinely performed on these SMTs. -3. Details about specific parameters the Storage SM uses, such as how keys and paths are created, and the two `POSEIDON` hash functions used in the SMTs. +3. Details about specific parameters the Storage SM uses, such as how keys and paths are created, and the two `POSEIDON` hash functions used in the SMTs. -4. The three main components of the Storage SM: - - the Storage SM Assembly - - the Storage SM Executor, and +4. The three main components of the Storage SM: + - the Storage SM Assembly + - the Storage SM Executor, and - the Storage SM PIL code, for all the polynomial identities and proving correctness of execution. diff --git a/docs/zkEVM/zkprover/keccak-framework.md b/docs/zkEVM/architecture/zkprover/keccak-framework.md similarity index 96% rename from docs/zkEVM/zkprover/keccak-framework.md rename to docs/zkEVM/architecture/zkprover/keccak-framework.md index a529ff451..9ed06134f 100644 --- a/docs/zkEVM/zkprover/keccak-framework.md +++ b/docs/zkEVM/architecture/zkprover/keccak-framework.md @@ -2,7 +2,7 @@ The zkEVM, as an L2 zk-Rollup for Ethereum, employs the Keccak hash function to 1. **The Padding-KK SM** is used for padding purposes, as well as validation of hash-related computations pertaining to the Main SM's queries. As depicted in the below figure, the **Padding-KK SM is Main SM's gateway to the Keccak hashing state machines**. - ![Keccak Design Schema](../../img/zkvm/hsh02-sm-kk-framework.png) + ![Keccak Design Schema](../../../img/zkEVM/hsh02-sm-kk-framework.png) 2. The **Padding-KK-Bit SM** converts between two string formats, the bytes of the Padding-KK SM to the bits of the Keccak-F Hashing SM, and vice-versa. diff --git a/docs/zkEVM/zkprover/keccakf-sm.md b/docs/zkEVM/architecture/zkprover/keccakf-sm.md similarity index 96% rename from docs/zkEVM/zkprover/keccakf-sm.md rename to docs/zkEVM/architecture/zkprover/keccakf-sm.md index 8f8a2f95d..393e6174e 100644 --- a/docs/zkEVM/zkprover/keccakf-sm.md +++ b/docs/zkEVM/architecture/zkprover/keccakf-sm.md @@ -12,7 +12,7 @@ The Keccak-F circuit is briefly described in this article, along with a thorough ## Keccak-F Circuit -The Keccak-F circuit has two types of gates, types $\mathtt{0}$ and $\mathtt{1}$, corresponding to the two binary operations it performs, the $\mathtt{XOR}$ and $\mathtt{ANDP}$. +The Keccak-F circuit has two types of gates, types $\mathtt{0}$ and $\mathtt{1}$, corresponding to the two binary operations it performs, the $\mathtt{XOR}$ and $\mathtt{ANDP}$. The Keccak-F executor builds the constant polynomials, $\mathtt{ConnA}$, $\mathtt{ConnB}$ and $\mathtt{ConnC}$, and these are to be tested if they match their corresponding polynomials, $\mathtt{kA}$, $\mathtt{kB}$ and $\mathtt{kC}$. @@ -23,7 +23,7 @@ $$ \texttt{op} \big( \mathtt{kA}, \mathtt{kB} \big) = \mathtt{kC} $$ -The $44$ bits are loaded into the state machine as $11$-bit chunks. +The $44$ bits are loaded into the state machine as $11$-bit chunks. In `keccakf.pil`, each committed polynomial $\texttt{a[4]}$ is expressed in terms of 4 chunks, where each is $11$ bits long. The corresponding a $44$-bit array can be expressed as, @@ -57,7 +57,7 @@ The zkProver's Keccak State Machine is a verifiable automisation of a Keccak-F p The EVM utilises the Keccak-256 hash function, which is a sponge construction with capacity $c = 512$ bits, and denoted by Keccak$[512]$. That is, the Keccak-256 notation puts emphasis on the $256$-bit security level, while the Keccak$[512]$ notation seeks to depict the actual capacity of $512$ bits. -### Bitrate and capacity +### Bitrate and capacity Although the internal state is $\mathtt{1600}$ bits, Keccak-F intakes a fixed number of bits as input, called the $\texttt{bitrate}$ (or simply, $\texttt{rate}$) and it is denoted by $\texttt{r}$. In our specific case, the bitrate $\texttt{r} = 1088$, whilst the capacity, $\texttt{c} = 512$. @@ -65,7 +65,7 @@ The size of a single output is $\texttt{r} = 1088$ bits. However, users can cho The Keccak-F permutation used in Keccak $[c]$ is Keccak-$p[1600, 24]$ (see [NIST SHA-3 Standard](https://csrc.nist.gov/publications/detail/fips/202/final)). -Thus, given an input bit string $\mathtt{M}$ and a output length $\mathtt{d}$, Keccak $[c](M, d)$ outputs a $d$-bit string following the previous sponge construction description. +Thus, given an input bit string $\mathtt{M}$ and a output length $\mathtt{d}$, Keccak $[c](M, d)$ outputs a $d$-bit string following the previous sponge construction description. ### Keccak-F padding rule @@ -79,7 +79,7 @@ But not every input string comes with this tailored bit-length. Therefore, every input string is split into $\mathtt{1088}$-bit chunks, where padding is applied to the tail-end chunk with $\mathtt{1088}$ bits or lesser. -The last ingredient we need to define in order to completely specify the hash function is the padding rule. +The last ingredient we need to define in order to completely specify the hash function is the padding rule. In Keccak $[c]$, the padding $\texttt{pad10*1}$ is used. If we define $\mathtt{j = (-m-2) \mod{r}}$, where $\mathtt{m}$ is the length of the input in bits, then the padding we have to append to the original input message is, @@ -108,9 +108,9 @@ See the below figure for a $\mathtt{1600}$-bit state array, displaying; 1. The 64-bit lane $\{[3,2,z]\}$ shown in orange, consisting of $64$ bits, $\mathtt{Bit}[3,2,0]$ to $\mathtt{Bit}[3,2,63]$, and -2. The 5-bit column $\{[2,y,63]\}$ shown in green, consisting of $5$ bits, $\mathtt{Bit}[2,0,63]$ to $\mathtt{Bit}[2,4,63]$. +2. The 5-bit column $\{[2,y,63]\}$ shown in green, consisting of $5$ bits, $\mathtt{Bit}[2,0,63]$ to $\mathtt{Bit}[2,4,63]$. -![Figure 1: Keccak's 1600-bit State as a 3D Array](../../img/zkvm/01kkf-state-array-calibrated.png) +![Figure 1: Keccak's 1600-bit State as a 3D Array](../../../img/zkEVM/01kkf-state-array-calibrated.png) A bit in the state $\mathbf{s}$ can be denoted by $\texttt{Bit}[x][y][z]$ as an element of the 3D-array state, but as $\texttt{Bit}[x,y,z]$ to indicate its location in position $(x,y,z)$ with respect to the Cartesian coordinate system. @@ -169,18 +169,18 @@ $$ \small \begin{array}{|l|c|c|c|c|c|} \hline -\textbf{Pseudo-code of the Composition} & \textbf{The keccak\_f.cpp Code}\\ \hline +\textbf{Pseudo-code of the Composition} & \textbf{The keccak\_f.cpp Code}\\ \hline \text{Run a *for-loop* over bits in a 25-bit slice of the state } \texttt{S} & \texttt{for} \mathtt{(uint64\_t\ \ ir=0; ir<24; ir++ )}\\ \hline \text{ } &\{ \text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\\ \hline -\text{Apply step mapping } \theta \text{ on current state}\texttt{ S} &\text{ } \mathtt{KeccakTheta(S, ir);} \text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ } \\ \hline -\text{Copy output of } \theta \text{ and set it as an input state of } \rho & \text{ } \mathtt{S.copySoutRefsToSinRefs();} \\ \hline -\text{Apply step mapping } \rho \text{ to the input state. } & \text{ } \mathtt{KeccakRho(S);} \text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ } \\ \hline -\text{Copy output of } \rho \text{ and set it as an input state of } \pi & \text{ } \mathtt{S.copySoutRefsToSinRefs();} \\ \hline -\text{Apply step mapping } \pi \text{ to the input state.} & \text{ } \mathtt{KeccakPi(S);} \text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ } \\ \hline -\text{Copy output of } \pi \text{ and set it as an input state of } \chi & \text{ } \mathtt{S.copySoutRefsToSinRefs();} \\ \hline -\text{Apply step mapping } \chi \text{ to the input state.} & \text{ } \mathtt{KeccakChi(S);} \text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ } \\ \hline -\text{Copy output of } \chi \text{ and set it as an input state of } \iota & \text{ } \mathtt{S.copySoutRefsToSinRefs();} \\ \hline -\text{Apply step mapping } \iota \text{ to the input state.} & \text{ } \mathtt{KeccakIota(S);} \text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ } \\ \hline +\text{Apply step mapping } \theta \text{ on current state}\texttt{ S} &\text{ } \mathtt{KeccakTheta(S, ir);} \text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ } \\ \hline +\text{Copy output of } \theta \text{ and set it as an input state of } \rho & \text{ } \mathtt{S.copySoutRefsToSinRefs();} \\ \hline +\text{Apply step mapping } \rho \text{ to the input state. } & \text{ } \mathtt{KeccakRho(S);} \text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ } \\ \hline +\text{Copy output of } \rho \text{ and set it as an input state of } \pi & \text{ } \mathtt{S.copySoutRefsToSinRefs();} \\ \hline +\text{Apply step mapping } \pi \text{ to the input state.} & \text{ } \mathtt{KeccakPi(S);} \text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ } \\ \hline +\text{Copy output of } \pi \text{ and set it as an input state of } \chi & \text{ } \mathtt{S.copySoutRefsToSinRefs();} \\ \hline +\text{Apply step mapping } \chi \text{ to the input state.} & \text{ } \mathtt{KeccakChi(S);} \text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ } \\ \hline +\text{Copy output of } \chi \text{ and set it as an input state of } \iota & \text{ } \mathtt{S.copySoutRefsToSinRefs();} \\ \hline +\text{Apply step mapping } \iota \text{ to the input state.} & \text{ } \mathtt{KeccakIota(S);} \text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ } \\ \hline \text{Set output of } \iota \text{ as new state, and reset to } 0 \text{ for next round } & \text{ } \mathtt{S.copySoutRefsToSinRefs();} \\ \hline \text{ } &\} \text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\\ \hline \end{array} @@ -196,9 +196,9 @@ The first step mapping, $\mathtt{\theta}$, referred to as $\texttt{KeccakTheta() $$ \begin{aligned} -\mathtt{C[(x-1)\text{ mod }5, z] = } \text{ } \mathtt{Bit[(x-1)\text{ mod }5,0,z]} \oplus\\ \mathtt{Bit[(x-1)\text{ mod }5,1,z]} \oplus\\ +\mathtt{C[(x-1)\text{ mod }5, z] = } \text{ } \mathtt{Bit[(x-1)\text{ mod }5,0,z]} \oplus\\ \mathtt{Bit[(x-1)\text{ mod }5,1,z]} \oplus\\ \mathtt{Bit[(x-1)\text{ mod }5,2,z]} \oplus\\ -\mathtt{Bit[(x-1)\text{ mod }5,3,z]} \oplus\\ +\mathtt{Bit[(x-1)\text{ mod }5,3,z]} \oplus\\ \mathtt{Bit[(x-1)\text{ mod }5,0,z]}\text{ }\text{ }\text{ } \end{aligned} $$ @@ -210,7 +210,7 @@ $$ \mathtt{C[(x+1)\text{ mod }5, (z-1)\text{ mod } 64] =\text{ }} \mathtt{Bit[(x+1)\text{ mod }5,0,(z-1)\text{ mod } 64]} \oplus \\ \mathtt{Bit[(x+1)\text{ mod }5,1,(z-1)\text{ mod } 64]}\text{ }\oplus\\ -\mathtt{Bit[(x+1)\text{ mod }5,2,(z-1)\text{ mod } 64]}\text{ } \oplus\\ +\mathtt{Bit[(x+1)\text{ mod }5,2,(z-1)\text{ mod } 64]}\text{ } \oplus\\ \mathtt{Bit[(x+1)\text{ mod }5,3,(z-1)\text{ mod } 64]}\text{ }\oplus\\ \mathtt{Bit[(x+1)\text{ mod }5,0,(z-1)\text{ mod } 64]}\quad \end{aligned} @@ -232,7 +232,7 @@ See the below figure, for an illustration of the $\theta$ step mapping applied o The code of the $\theta$ step mapping is found here: [keccak_theta.cpp](https://github.com/0xPolygonHermez/zkevm-prover/blob/main/tools/sm/keccak_f/keccak_theta.cpp) -![Theta Step Mapping On One Bit](../../img/zkvm/02kkf-theta-map-one-bit.png) +![Theta Step Mapping On One Bit](../../../img/zkEVM/02kkf-theta-map-one-bit.png) ### Mapping Rho @@ -329,7 +329,7 @@ $$ Below diagram, showing the $(x,y)$-slices, depicts the shuffling of the bits in accordance with the above table. This figure is in fact the mapping displayed in Figure 2.3 of the [Keccak Reference 3.0 [Page 20; 2011]](https://keccak.team/files/Keccak-reference-3.0.pdf). -![How Pi shuffles bits on a 25-bit (x,y)-slice](../../img/zkvm/03kkf-pi-stepmap-shuffle.png) +![How Pi shuffles bits on a 25-bit (x,y)-slice](../../../img/zkEVM/03kkf-pi-stepmap-shuffle.png) The code of the $\pi$ step mapping is found here: [keccak_pi.cpp](https://github.com/0xPolygonHermez/zkevm-prover/blob/main/tools/sm/keccak_f/keccak_pi.cpp) @@ -363,7 +363,7 @@ where $x \in \{3,4,0,1,2\}$. Overall, the $\chi$ step mapping can be depicted as a "circuit" of gates as in the below diagram, taken from [FIPS PUB 202, August 2015 (Figure 6, Page 15)](https://csrc.nist.gov/publications/detail/fips/202/final). -![The KeccakChi Gates Circuit](../../img/zkvm/04kkf-chi-map-5bit-row.png) +![The KeccakChi Gates Circuit](../../../img/zkEVM/04kkf-chi-map-5bit-row.png) The code of the $\chi$ step mapping is found here: [keccak_chi.cpp](https://github.com/0xPolygonHermez/zkevm-prover/blob/main/tools/sm/keccak_f/keccak_chi.cpp) @@ -377,9 +377,9 @@ $$ The round-constants are XOR-ed only to a single lane of the state, in particular, the origin lane (i.e., the 64 bits $\{\mathtt{Bit}[0,0,z]\}$ where $0\leq z \leq 63$). -#### Here's how $\large{\iota}$ operates on the origin lane, $\{\mathtt{Bit}[0,0,z]\ |\ 0\leq z \leq 63\}$ +#### Here's how $\large{\iota}$ operates on the origin lane, $\{\mathtt{Bit}[0,0,z]\ |\ 0\leq z \leq 63\}$ -Firstly, the derivation of the round-constants $RC[ir]$. As shown in the algorithm of $\large{\iota}$, the round-constant $RC$ is initialized to $0^{w}$ at the beginning of each round of $\large{\iota}$. After which, 7 specific bit-places $\{2^j – 1\ |\ 0 \leq j \leq 6 \}$ of the round-constant are set to the bits $\{rc[j + 7 ir]\ |\ 0 \leq j \leq 6 \}$. Meanwhile, the rest of the bits remain as zeros. +Firstly, the derivation of the round-constants $RC[ir]$. As shown in the algorithm of $\large{\iota}$, the round-constant $RC$ is initialized to $0^{w}$ at the beginning of each round of $\large{\iota}$. After which, 7 specific bit-places $\{2^j – 1\ |\ 0 \leq j \leq 6 \}$ of the round-constant are set to the bits $\{rc[j + 7 ir]\ |\ 0 \leq j \leq 6 \}$. Meanwhile, the rest of the bits remain as zeros. $$ \begin{array}{|l|c|c|c|c|c|c|} @@ -405,16 +405,16 @@ $$ \textbf{Input: }\text{ state array }\mathbf{ A }\text{, round index } ir \text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ } \\ \textbf{Output:}\text{ state array }\mathbf{ A'}\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{} \\ \text{Steps:}\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ } \\ -\text{ 1. For all triples } (x, y, z) \text{ such that } 0 ≤ x <5, 0 ≤ y < 5,\\ +\text{ 1. For all triples } (x, y, z) \text{ such that } 0 ≤ x <5, 0 ≤ y < 5,\\ \text{ and } 0 ≤ z < w, \text{ let } \mathbf{A'}[x, y, z] = \mathbf{A}[x, y, z]\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\\ \text{2. Let } RC = 0^w. \text{ } \ \text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\\ \text{3. For } j \text{ from } 0 \text{ to } l, \text{ let } RC[2^j – 1] = rc[j + 7 ir]. \text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\\ -\text{4. For all } z \text{ such that } 0 ≤ z **FRI**](https://drops.dagstuhl.de/opus/volltexte/2018/9018/pdf/LIPIcs-ICALP-2018-14.pdf) refers to **Fast Reed-Solomon Interactive Oracle Proof of Proximity**. The FRI protocol consists of two phases: a **commit phase** and **query phase**. You can read more about the protocol in [this document](https://eprint.iacr.org/2021/582.pdf) by **StarkWare Team**. - 1. **Low-degree reduction phase** During this phase, we receive a FRI polynomial, which codifies the validity of the execution trace values according to the PIL code into the fact that it has a low degree. This polynomial, along with numerous other polynomials required to provide consistency checks, is committed to the Verifier. @@ -52,4 +51,4 @@ On a high level, the description of the e**STARK** protocol can be broken down i - $Round\ 6$: The Prover receives two random values from the Verifier, which are used to construct the FRI polynomial. Then the Prover and the Verifier get engaged (non-Interactively) in a FRI Protocol, which ends with the Prover sending the corresponding FRI proof to the Verifier. -After the proof is generated, it is sent to the Verifier instance for the verification procedure to begin. The final output is either an `accept` or a `reject`, indicating whether the proof was accepted or rejected. \ No newline at end of file +After the proof is generated, it is sent to the Verifier instance for the verification procedure to begin. The final output is either an `accept` or a `reject`, indicating whether the proof was accepted or rejected. diff --git a/docs/zkEVM/zkprover/recursion-sub-process.md b/docs/zkEVM/architecture/zkprover/recursion-sub-process.md similarity index 94% rename from docs/zkEVM/zkprover/recursion-sub-process.md rename to docs/zkEVM/architecture/zkprover/recursion-sub-process.md index 61d4658f6..81e258d88 100644 --- a/docs/zkEVM/zkprover/recursion-sub-process.md +++ b/docs/zkEVM/architecture/zkprover/recursion-sub-process.md @@ -1,4 +1,4 @@ -This document provides a deep dive into the sub-processes **S2C** and **C2S** of the Recursion of Proofs. +This document provides a deep dive into the sub-processes **S2C** and **C2S** of the Recursion of Proofs. ## Setup S2C @@ -6,15 +6,15 @@ Recall that **S2C** denotes the process of converting a given **STARK** into its The architecture of this generic conversion is depicted in the below figure, where a $\mathtt{STARK_x}$ is converted into a circuit denoted as $\textbf{C}_{\text{y}}$. -![Detailing the Setup **S2C**](../../img/zkvm/06prf-rec-setup-s2c-detail.png) +![Detailing the Setup **S2C**](../../../img/zkEVM/06prf-rec-setup-s2c-detail.png) -The input of **S2C** is all the information needed to set up a circuit for verifying the given **STARK**. +The input of **S2C** is all the information needed to set up a circuit for verifying the given **STARK**. In our architecture, the inputs are; -- The PIL file `x.pil`, specifying **STARK** constraints that are going to be validated and the polynomial names, -- The `x.starkInfo` file containing the FRI-related parameters (blowup factor, the number of queries to be done, etc.), and -- The `x.verkey` which is the root (`constRoot`) of the Merkle tree of the computation constants. +- The PIL file `x.pil`, specifying **STARK** constraints that are going to be validated and the polynomial names, +- The `x.starkInfo` file containing the FRI-related parameters (blowup factor, the number of queries to be done, etc.), and +- The `x.verkey` which is the root (`constRoot`) of the Merkle tree of the computation constants. The output `y.circom` of the `generate circom` process, is a **CIRCOM** description. @@ -22,7 +22,7 @@ The circuit is actually generated by filling an `EJS` template for the CIRCOM de As illustrated in the below figure, the inputs of the generated **STARK** Verifier circuits are divided in two groups; private inputs and public inputs called `publics`. -![Inputs of the STARK Verifier circuits](../../img/zkvm/07prf-rec-inputs-stark-verifier-circuit.png) +![Inputs of the STARK Verifier circuits](../../../img/zkEVM/07prf-rec-inputs-stark-verifier-circuit.png) The `private inputs` are the parameters of the previous STARK proof: @@ -62,7 +62,7 @@ In the **C2S** step, which is part of the pre-processing, the Verifier circuit i A picture of a generic **C2S** step is displayed in the below Figure, where a circuit denoted by $\textbf{C}_{\text{y}}$ is converted into its corresponding **STARK**, denoted by $\mathtt{STARK}_{\text{y}}$. -![Setup recursion step C2S](../../img/zkvm/08prf-rec-setup-step-c2s.png) +![Setup recursion step C2S](../../../img/zkEVM/08prf-rec-setup-step-c2s.png) As shown in the above figure, the first process of the **C2S** step is the PIL setup, which takes the R1CS constraints of a given intermediate circuit as input, and produces all the **STARK**-related artifacts. @@ -86,7 +86,7 @@ The STARK arithmetization includes several other custom gates for carrying out s In particular, the custom gates providing the various functionalities are; -- **Poseidon**: This custom gate is capable of validating a Poseidon hash from a given eight ($8$) field elements as inputs, four ($4$) field elements as the capacity, and a variable number of output elements. +- **Poseidon**: This custom gate is capable of validating a Poseidon hash from a given eight ($8$) field elements as inputs, four ($4$) field elements as the capacity, and a variable number of output elements. More specifically, this circuit implements the MDS matrix as its diffusion layer, and the $7$-th power of field elements computations as the non-linear layer (S-boxes), in executing each of the rounds of the Poseidon hash's sponge construction. The Poseidon hash is documented [here](poseidon-sm.md). @@ -116,11 +116,11 @@ The proof of each intermediate **STARK** needs to be computed in order to genera Each intermediate **STARK** proof is generated using the witness values provided by the execution of the associated `circuit witness calculator` program, which in turn takes as inputs the `publics` and the values of the previous proof. -These values are then rearranged properly in order to build the **STARK** execution trace using the corresponding `.exec` file. +These values are then rearranged properly in order to build the **STARK** execution trace using the corresponding `.exec` file. The below figure provides the schema of how the proof of an intermediate **STARK** is generated. -![STARK Proof of a recursion step](../../img/zkvm/09prf-rec-stark-prf-rec-step.png) +![STARK Proof of a recursion step](../../../img/zkEVM/09prf-rec-stark-prf-rec-step.png) 1. Observe that the **STARK** executor process takes the parameters of the previous proof together with the public inputs; diff --git a/docs/zkEVM/zkprover/stark-recursion-detail.md b/docs/zkEVM/architecture/zkprover/stark-recursion-detail.md similarity index 93% rename from docs/zkEVM/zkprover/stark-recursion-detail.md rename to docs/zkEVM/architecture/zkprover/stark-recursion-detail.md index 6e5584201..2993f5968 100644 --- a/docs/zkEVM/zkprover/stark-recursion-detail.md +++ b/docs/zkEVM/architecture/zkprover/stark-recursion-detail.md @@ -12,7 +12,7 @@ In this case, if the Prover can provide a proof $\pi_{CIRCUIT}$, of correct exec As shown in the figure below, the Verifier entity just verifies the proof $\pi_{CIRCUIT}$ of the **STARK** verification circuit. The main advantage of this composition is that $\pi_{CIRCUIT}$ is smaller and faster to verify than $\pi_{STARK}$. -![Simple composition](../../img/zkvm/02prf-rec-simple-composition.png) +![Simple composition](../../../img/zkEVM/02prf-rec-simple-composition.png) ## Recursion of Proofs @@ -28,7 +28,7 @@ This phase takes advantage of the fact that Verifiers are much more efficient th The design idea is to create a cascade of Verifier circuits, where at each step a lot more efficiently verifiable proof is recursively created. The process therefore consists of an alternating series of two sub-processes; converting a STARK proof into a Verifier circuit, and converting a Verifier circuit into a STARK proof, denoted by **S2C** and **C2S**, respectively. -![the Setup Phase of Recursion](../../img/zkvm/03prf-rec-setup-phase-rec.png) +![the Setup Phase of Recursion](../../../img/zkEVM/03prf-rec-setup-phase-rec.png) The overall process, as depicted in the figure above, is composed of an alternating series of sub-processes; **STARK-to-CIRCUIT** and **CIRCUIT-to-STARK**. @@ -48,9 +48,9 @@ CIRCOM is used as an intermediate representation language for the description of #### CIRCUIT-to-STARK or C2S Sub-process -The circuit definition in the form of R1CS is taken and automatically translated into a new **STARK** definition. +The circuit definition in the form of R1CS is taken and automatically translated into a new **STARK** definition. -In this **C2S** sub-process, a circuit Verifier is translated into a STARK proof. That is, a new `pil` description, new `constants` and a `starkinfo`. +In this **C2S** sub-process, a circuit Verifier is translated into a STARK proof. That is, a new `pil` description, new `constants` and a `starkinfo`. This translation, is herein referred to as **C2S** (short for **CIRCUIT-to-STARK**). @@ -70,7 +70,7 @@ The first proof is generated by providing the first **STARK** Prover with the pr In the below figure, it is shown how in essence a chain of recursive **STARK** Provers work. -![Recursive Provers](../../img/zkvm/04prf-rec-proving-phase-rec.png) +![Recursive Provers](../../../img/zkEVM/04prf-rec-proving-phase-rec.png) Notice that the final proof is actually a circuit-based proof, which is in fact a SNARK proof, specified per implementation. More details about the Proving Phase can be found in the **Recursion Step Proof** section. @@ -82,4 +82,4 @@ Aggregation is a type of proof composition in which multiple valid proofs can be The below figure shows an example of aggregation with binary aggregators. -![binary aggregation example](../../img/zkvm/05prf-rec-binary-aggreg-eg.png) +![binary aggregation example](../../../img/zkEVM/05prf-rec-binary-aggreg-eg.png) diff --git a/docs/zkEVM/zkprover/storage-sm-mechanism.md b/docs/zkEVM/architecture/zkprover/storage-sm-mechanism.md similarity index 94% rename from docs/zkEVM/zkprover/storage-sm-mechanism.md rename to docs/zkEVM/architecture/zkprover/storage-sm-mechanism.md index 93eb994b9..67ec0893a 100644 --- a/docs/zkEVM/zkprover/storage-sm-mechanism.md +++ b/docs/zkEVM/architecture/zkprover/storage-sm-mechanism.md @@ -2,13 +2,13 @@ The **Storage SM** is one of zkProver's secondary state machines, and thus recei The Storage SM is designed as a microprocessor and it is therefore composed of three parts: -- Storage Assembly code, +- Storage Assembly code, - Storage Executor code, - Storage PIL code. ## The Storage Assembly -The Storage Assembly is the interpreter between the Main State Machine and its own Executor. +The Storage Assembly is the interpreter between the Main State Machine and its own Executor. The Storage SM receives instructions from the Main SM written in zkASM. It then generates a JSON-file containing the corresponding rules and logic, which are stored in a special ROM for the Storage SM. @@ -27,14 +27,13 @@ Considering some special cases, there are eight secondary [Storage Assembly](htt | DELETE leaf with zero sibling | Set_DeleteNotFound | SDNF | isSetDeleteNotFound() | | SET a zero node to zero | Set_ZeroToZero | SZTZ | isSetZeroToZero() | - Input and output states of the Storage SM are literally SMTs, given in the form of; the Merkle roots, the relevant siblings, as well as the key-value pairs. -Note that state machines use registers in the place of variables. All values needed, for carrying out the basic operations, are stored by the primary Assembly code in the following registers; +Note that state machines use registers in the place of variables. All values needed, for carrying out the basic operations, are stored by the primary Assembly code in the following registers; `HASH_LEFT`, `HASH_RIGHT`, `OLD_ROOT`, `NEW_ROOT`, `VALUE_LOW`, `VALUE_HIGH`, `SIBLING_VALUE_HASH`, `RKEY`, `SIBLING_RKEY`, `RKEY_BIT`, `LEVEL`. -The `SIBLING_VALUE_HASH` and `SIBLING_RKEY` registers are only used by the `Set_InsertFound` and the `Set_DeleteFound` secondary Assembly codes. The rest of the registers are used in all the secondary Assembly codes. +The `SIBLING_VALUE_HASH` and `SIBLING_RKEY` registers are only used by the `Set_InsertFound` and the `Set_DeleteFound` secondary Assembly codes. The rest of the registers are used in all the secondary Assembly codes. ## SMT Action Selectors In Primary Assembly Code @@ -45,7 +44,7 @@ The primary Assembly code uses selectors by following the sequence in which thes - It first checks if the required action is a `Get`. If it is so, the [storage_sm_get.zkasm](https://github.com/0xPolygonHermez/zkevm-storage-rom/blob/main/zkasm/storage_sm_get.zkasm) code is fetched for execution. - If not, it checks if the required action is `Set_Update`. If it is so, the [storage_sm_set_update.zkasm](https://github.com/0xPolygonHermez/zkevm-storage-rom/blob/main/zkasm/storage_sm_set_update.zkasm) code is fetched for execution. - If not, it continues to check if the required action is `Set_InsertFound`. If it is so, the [storage_sm_set_insert_found.zkasm](https://github.com/0xPolygonHermez/zkevm-storage-rom/blob/main/zkasm/storage_sm_set_insert_found.zkasm) code is fetched for execution. -- If not, it continues in the same way until the correct action is selected, in which case the corresponding code is fetched for execution. +- If not, it continues in the same way until the correct action is selected, in which case the corresponding code is fetched for execution. That's all the primary Storage Assembly code does and the details of how each of the SMT Actions is stipulated in the individual secondary Assembly codes. @@ -53,13 +52,13 @@ The primary and secondary Storage Assembly files are stored as JSON-files in the ## The UPDATE zkASM Code -Take as an example the `Set_UPDATE` zkASM code. The primary Storage Assembly code uses the selector `isSetUpdate()` for `Set_UPDATE`. +Take as an example the `Set_UPDATE` zkASM code. The primary Storage Assembly code uses the selector `isSetUpdate()` for `Set_UPDATE`. Note that an **UPDATE** involves the following actions: 1. Reconstructs the corresponding key, from both the remaining key found at the leaf and key-bits used to navigate to the leaf. 2. Ascertains that indeed the old value was included in the old root, -3. Carries out the UPDATE of the old value with the new value, as well as updating all nodes along the path from the leaf to the root. +3. Carries out the UPDATE of the old value with the new value, as well as updating all nodes along the path from the leaf to the root. There is only one `Set_UPDATE` Assembly code, [storage_sm_set_update.zkasm](https://github.com/0xPolygonHermez/zkevm-storage-rom/blob/main/zkasm/storage_sm_set_update.zkasm), for all the above three computations. @@ -74,9 +73,9 @@ Key Reconstruction is achieved in two steps: positioning of the bit "1" in the ` **Case 1**. If the least-significant bit of leaf level is `0`, then the `GetLevelBit()` function is used again to read the second least-significant bit of the leaf level. - **Subcase 1.1**: If the second least-significant bit of the leaf level is `0`, it means the leaf level is a multiple of 4, which is equivalent to 0 because leaf level works in `modulo` 4. So, the `LEVEL` register must remain as `(1,0,0,0)`. - - **Subcase 1.2**: If the second least-significant bit of the leaf level is `1`, it means the leaf level in its binary form ends with a `10`. Hence, leaf level is a number of the form `2 + 4k`, for some positive integer `k`. As a result, the `LEVEL` register must be rotated to the position, `(0,0,1,0)`. The code therefore applies `ROTATE_LEVEL` twice to `LEVEL = (1,0,0,0)` in order to bring it to `(0,0,1,0)`. + - **Subcase 1.2**: If the second least-significant bit of the leaf level is `1`, it means the leaf level in its binary form ends with a `10`. Hence, leaf level is a number of the form `2 + 4k`, for some positive integer `k`. As a result, the `LEVEL` register must be rotated to the position, `(0,0,1,0)`. The code therefore applies `ROTATE_LEVEL` twice to `LEVEL = (1,0,0,0)` in order to bring it to `(0,0,1,0)`. - **Case 2**. If the least-significant bit of leaf level is `1`; then, the `LEVEL` register is rotated three times to the left, using ROTATE_LEVEL, and bringing the `LEVEL` register to `(0,1,0,0)`. Next, the `GetLevelBit()` function is used again to read the second least-significant bit of the leaf level. + **Case 2**. If the least-significant bit of leaf level is `1`; then, the `LEVEL` register is rotated three times to the left, using ROTATE_LEVEL, and bringing the `LEVEL` register to `(0,1,0,0)`. Next, the `GetLevelBit()` function is used again to read the second least-significant bit of the leaf level. - **Subcase 2.1**: If the second least-significant bit of the leaf level is `0`, it means the leaf level in its binary form ends with a `01`. That is, leaf level is a number of the form `1 + 4k`, for some positive integer `k`. And thus, the `LEVEL` register must remain in its current position, `(0,1,0,0)`. So it does not need to be rotated. - **Subcase 2.2**: Otherwise, the second least-significant bit of the leaf level is `1`, which means the leaf level in its binary form ends with a `11`. Hence, leaf level is a number of the form `3 + 4k`, for some positive integer `k`. Consequently, the `LEVEL` register needs to be rotated from the current position `(0,1,0,0)` to the position `(0,0,0,1)`. @@ -85,13 +84,13 @@ Key Reconstruction is achieved in two steps: positioning of the bit "1" in the ` The **Remaining Key** is fetched using the `GetRKey()` function and stored in the `RKEY` register. - When climbing the tree, there are two functions that are used in the code: the CLIMB_RKEY and the ROTATE_LEVEL. + When climbing the tree, there are two functions that are used in the code: the CLIMB_RKEY and the ROTATE_LEVEL. - First, the `LEVEL` register is used to pinpoint the correct part of the Remaining Key to which the path-bit last used in the navigation must be appended. - Second, the ROTATE_LEVEL is used to rotate the `LEVEL` register once. - The CLIMB_RKEY is used. Firstly, to shift the value of the pinpointed RKey part one position to the left. Secondly, to insert the last used path bit to the least-significant position of the shifted-value of the pinpointed RKey part. -The above two steps are repeated until all the path bits used in navigation have been appended. Later, equality between the reconstructed key and the original key is checked. +The above two steps are repeated until all the path bits used in navigation have been appended. Later, equality between the reconstructed key and the original key is checked. ### Checking Inclusion Of Old Value In Old Root @@ -116,47 +115,47 @@ All values, $\text{V}_{0123}=\big(\text{V}_{0},\text{V}_{1},\text{V}_{2},\text{V !!!info This means the `HASH_RIGHT` and the `HASH_LOW` are 'make-shift' registers. Whenever a value is stored in it, the old value that was previously stored therein is simply pushed out. They hold values only for the next computation. - 4. Next the Rkey is copied into the `HASH_LEFT` register. And the leaf value is computed by using `HASH1` as, $\text{HASH1}\big(\text{HASH}\_ {\text{LEFT}}\|\text{HASH}\_ {\text{RIGHT}}\big)$. i.e., The value of the leaf is, $\text{HASH1}\big( \text{RKey}\|\text{HashedValue}\big)$. The leaf value is then copied into another register called `NEW_ROOT`. + 4. Next the Rkey is copied into the `HASH_LEFT` register. And the leaf value is computed by using `HASH1` as, $\text{HASH1}\big(\text{HASH}\_ {\text{LEFT}}\|\text{HASH}\_ {\text{RIGHT}}\big)$. i.e., The value of the leaf is, $\text{HASH1}\big( \text{RKey}\|\text{HashedValue}\big)$. The leaf value is then copied into another register called `NEW_ROOT`. 2. **Climbing the SMT** Check if the path bit that led to the leaf is 0 or 1, by using the `GetNextKeyBit()` function. - **Case 1**: If the path bit (called 'key bit' in the code) is 0, then the corresponding sibling is on the right. Therefore, using 'jump if zero' `JMPZ`, the code jumps to the `SU_SiblingIsRight` routine. + **Case 1**: If the path bit (called 'key bit' in the code) is 0, then the corresponding sibling is on the right. Therefore, using 'jump if zero' `JMPZ`, the code jumps to the `SU_SiblingIsRight` routine. - - The leaf value in `NEW_ROOT` is pushed into the `HASH_LEFT` register. + - The leaf value in `NEW_ROOT` is pushed into the `HASH_LEFT` register. - The hash value of the sibling node is fetched, using the `GetSiblingHash()` function. And it is pushed into the `HASH_RIGHT` register. - - The hash value of the parent node is computed using `HASH0` as follows, $\text{HASH0}\big(\text{HASH}\_ {\text{LEFT}} \|\text{HASH}\_{\text{RIGHT}}\big)$. + - The hash value of the parent node is computed using `HASH0` as follows, $\text{HASH0}\big(\text{HASH}\_ {\text{LEFT}} \|\text{HASH}\_{\text{RIGHT}}\big)$. The parent node is $\text{POSEIDON}\big(0\|0\|0\|0\|\text{LeafValue}\|\text{SiblingHash}\big)$. - **Case 2**: If the path bit is 1, then the corresponding sibling is on the left. The routine `SU_SiblingIsRight` is then executed. + **Case 2**: If the path bit is 1, then the corresponding sibling is on the left. The routine `SU_SiblingIsRight` is then executed. - - The leaf value in `NEW_ROOT` is pushed into the `HASH_RIGHT` register. + - The leaf value in `NEW_ROOT` is pushed into the `HASH_RIGHT` register. - The hash value of the sibling node is fetched, using the `GetSiblingHash()` function. And it is pushed into the `HASH_LEFT` register. - - The hash value of the parent node is computed using `HASH0` as follows, $\text{HASH0}\big(\text{HASH}\_ {\text{LEFT}}\|\text{HASH}\_ \text{RIGHT}\big)$. + - The hash value of the parent node is computed using `HASH0` as follows, $\text{HASH0}\big(\text{HASH}\_ {\text{LEFT}}\|\text{HASH}\_ \text{RIGHT}\big)$. - The parent node is $\text{POSEIDON}\big(0\|0\|0\|0\|\text{SiblingHash}\|\text{LeafValue}\big)$. + The parent node is $\text{POSEIDON}\big(0\|0\|0\|0\|\text{SiblingHash}\|\text{LeafValue}\big)$. 3. **Check if tree top has been reached** The code uses the function `GetTopTree()` to check is the top of the tree has been reached. - **Case 1**. If `GetTopTree()` returns 1, then Step 2 is repeated. But this time using the hash value of the corresponding sibling at the next level (at `leaf level - 1`). + **Case 1**. If `GetTopTree()` returns 1, then Step 2 is repeated. But this time using the hash value of the corresponding sibling at the next level (at `leaf level - 1`). - **Case 2**. If `GetTopTree()` returns 0, then the code jumps to the `SU_Latch` routine. + **Case 2**. If `GetTopTree()` returns 0, then the code jumps to the `SU_Latch` routine. -The `SU_Latch` is an overall routine for the entire `Set_UPDATE` Assembly code. It is here where, +The `SU_Latch` is an overall routine for the entire `Set_UPDATE` Assembly code. It is here where, - Equality between the reconstructed key and the original key is checked. - Equality between the computed old root value and the original old root is checked. -Once consistency is established both between the keys and the old roots, then all new values; the new root, the new hash value, and the new leaf value are set using `LATCH_SET`. +Once consistency is established both between the keys and the old roots, then all new values; the new root, the new hash value, and the new leaf value are set using `LATCH_SET`. ## Remaining Secondary Assembly Codes @@ -164,14 +163,14 @@ The Assembly codes for the other seven SMT Actions to a certain extent follow a Actions such as: -1. The `Set_InsertFound` (or `SIF`) may involve a change in the topology of the SMT by extending a branch once or several times. +1. The `Set_InsertFound` (or `SIF`) may involve a change in the topology of the SMT by extending a branch once or several times. In cases where a branch has been extended, the SIF Assembly code, when computing the new root, uses another routine called `SIF_ClimbBranch` just for updating values along the newly extended branch. This is done in addition to the `SIF_ClimbTree`, which is the exact same routine as the aforementioned `SU_ClimbTree` of the `Set_UPDATE` case. - It is for the same reason that SIF Assembly utilizes special registers: the `SIBLING_VALUE_HASH` and `SIBLING_RKEY`. + It is for the same reason that SIF Assembly utilizes special registers: the `SIBLING_VALUE_HASH` and `SIBLING_RKEY`. 2. The opposite SMT Action, the `Set_DeleteFound` or `SDF`, may entail a previously extended branch being reversed. As in the SIF case, if a branch had been extended but now the extension needs to be reversed due to a deleted leaf value, a special routine called `SDF_ClimbBranch` is used when updating values of nodes along the newly shortened branch. This `SDF_ClimbBranch` routine is the exact same routine as the`SIF_ClimbBranch`. Similarly, the SDF Assembly code uses the `SDF_ClimbTree` as in the Set_UPDATE Assembly. -Note also that there is only one `Get` Assembly code for the READ SMT Action, and the rest of the secondary Assembly codes are `Set_` Assembly codes differing according to their respective SMT Actions. So `Get` uses `LATCH_GET` at the end of a run, while the `Set_` codes use `LATCH_SET`. \ No newline at end of file +Note also that there is only one `Get` Assembly code for the READ SMT Action, and the rest of the secondary Assembly codes are `Set_` Assembly codes differing according to their respective SMT Actions. So `Get` uses `LATCH_GET` at the end of a run, while the `Set_` codes use `LATCH_SET`. diff --git a/docs/zkEVM/zkprover/the-processor.md b/docs/zkEVM/architecture/zkprover/the-processor.md similarity index 93% rename from docs/zkEVM/zkprover/the-processor.md rename to docs/zkEVM/architecture/zkprover/the-processor.md index 73bebaf62..fb371c1e1 100644 --- a/docs/zkEVM/zkprover/the-processor.md +++ b/docs/zkEVM/architecture/zkprover/the-processor.md @@ -13,9 +13,9 @@ As a Generic SM, it can be thought of as being composed of two parts: Instead of executing all the various computations on its own, the Main SM achieves efficiency by delegating verification of complex computations to specialized secondary state machines. These are: - [Storage SM](intro-storage-sm.md) which handles all storage-related computations (e.g., Create, Read, Update and Delete). -- [Arithmetic SM](arithmetic-sm.md) which carries out elliptic curve arithmetic operations related to ECDSA. +- [Arithmetic SM](arithmetic-sm.md) which carries out elliptic curve arithmetic operations related to ECDSA. - [Binary SM](binary-sm.md) which is responsible for performing all binary operations as the Executor requires. -- [Memory SM](memory-sm.md) which in the zkEVM plays the same role the EVM Memory plays in Ethereum. +- [Memory SM](memory-sm.md) which in the zkEVM plays the same role the EVM Memory plays in Ethereum. - [Keccak SM](keccakf-sm.md) which is a binary circuit that computes hash values of strings as instructed by the Main SM. And, it is implemented within a special framework, detailed [here](keccak-framework.md). - [Poseidon SM](poseidon-sm.md) which specialises with computing hash values required in building Sparse Merkle Trees as per the Main SM instructions. @@ -23,13 +23,13 @@ There are other *auxiliary* state machines used in the zkProver; the [Padding-KK ## Algebraic Processor -The Polygon zkEVM is a microprocessor that takes an input state, executes computations in line with ROM instructions, and outputs a new state. +The Polygon zkEVM is a microprocessor that takes an input state, executes computations in line with ROM instructions, and outputs a new state. Every computation, whether executed by the Main SM or any of the specialist state machines, is limited to an execution trace of size $2^{23}$. That is, $2^{23}$ steps of the computation. ### Generic Registers -In order to emulate the EVM opcodes, the Polygon zkEVM introduces five state-related generic registers, namely; $\texttt{A}$, $\texttt{B}$, $\texttt{C}$, $\texttt{D}$ and $\texttt{E}$. Each is equivalent to $256$-bit EVM words. +In order to emulate the EVM opcodes, the Polygon zkEVM introduces five state-related generic registers, namely; $\texttt{A}$, $\texttt{B}$, $\texttt{C}$, $\texttt{D}$ and $\texttt{E}$. Each is equivalent to $256$-bit EVM words. However, since the Main SM operates over a finite field of almost, but less than $64$ bits, each register is split into $8$ subcomponents of $32$ bits each: @@ -45,11 +45,11 @@ $$ \mathtt{E_0,...,E_7} $$ -with $\mathtt{A_i}$, $\mathtt{B_i}$, $\mathtt{C_i}$, $\mathtt{D_i}$, $\mathtt{E_i}$ $\mathtt{ \in \{ 0, \dots , 2^{32 − 1}\}}$. +with $\mathtt{A_i}$, $\mathtt{B_i}$, $\mathtt{C_i}$, $\mathtt{D_i}$, $\mathtt{E_i}$ $\mathtt{ \in \{ 0, \dots , 2^{32 − 1}\}}$. When storing a value in a register, the least significant bits are placed in the lowest subcomponent. That is, -- if a $32$-bit value is allocated to register $\texttt{A}$, then only $\mathtt{A_0}$ gets filled with the value. +- if a $32$-bit value is allocated to register $\texttt{A}$, then only $\mathtt{A_0}$ gets filled with the value. - if a $64$-bit value allocated to register $\texttt{A}$, then both $\mathtt{A_0}$ and $\mathtt{A_1}$ get filled with the value. #### Example @@ -58,7 +58,7 @@ If the value $\mathtt{0x12345678}$ needs to be stored in register $\texttt{A}$, ### OP Register -The `OP` register acts as an intermediate carrier of the computation being executed. +The `OP` register acts as an intermediate carrier of the computation being executed. It is expressible as a linear combination of the input values stored in the generic registers as follows, @@ -70,7 +70,7 @@ where $\mathtt{inA}$, $\mathtt{inB}$, $\mathtt{inC}$, $\mathtt{inD}$ and $\matht The figure below displays the Main SM's state transition, showing the generic registers, the selector registers, setter registers and the `OP` register. -![Main SM's state transition showing only generic registers](../../img/zkvm/03msm-state-transition-gen-regs.png) +![Main SM's state transition showing only generic registers](../../../img/zkEVM/03msm-state-transition-gen-regs.png) The output value of each register is given by: @@ -82,9 +82,9 @@ $$ \texttt{E}' = (\mathtt{op - E}) * \mathtt{setE} + \texttt{E}, $$ -so that, +so that, -- if the setter $\texttt{setX} = 0$ then the output $\texttt{X}' \texttt{ = X}$. That is, the $\texttt{X}$ register value remains unchanged. +- if the setter $\texttt{setX} = 0$ then the output $\texttt{X}' \texttt{ = X}$. That is, the $\texttt{X}$ register value remains unchanged. - if the setter $\texttt{setX} = 1$ then the output $\texttt{X}'\ \mathtt{=}\ (\mathtt{op - X}) * \mathtt{setX} + \texttt{A} \ \mathtt{=}\ (\mathtt{op - A}) + \texttt{A} \ \mathtt{=}\ \texttt{op}$. That is, the $\texttt{X}$ register value changes to the new value of the $\mathtt{op}$. #### Example @@ -115,7 +115,7 @@ This is read as follows, "the next value stored in register $\texttt{B}$ is $\te #### Main Execution Routine -Each ROM instruction stipulates which registers should be included in computing `OP`, as well as where the resulting output values should be stored. +Each ROM instruction stipulates which registers should be included in computing `OP`, as well as where the resulting output values should be stored. For each register `X`, the Executor therefore checks whether `inX` is zero or not. It selects the register `X` if $\texttt{inX} \ \mathtt{\not=}\ 0$. Similarly, the Executor only stores an output value in the register `Y`, only if `setY` = 1. @@ -124,8 +124,8 @@ The main loop of the Executor looks like this: ```c for (i=0; i> 256) > 0); @@ -408,11 +408,11 @@ for (i=0; iDisclosures]() section. - -Users can deposit assets from Ethereum and transact off-chain on Polygon zkEVM. For moving assets across chains (L1 ↔ zkEVM), you will need to use the zkEVM Bridge. The bridge interface is available for both Mainnet Beta and Testnet in the [Polygon Wallet Suite](https://wallet.polygon.technology/zkEVM/bridge). +Users can deposit assets from Ethereum and transact off-chain on Polygon zkEVM. For moving assets across chains (L1 ↔ zkEVM), you will need to use the zkEVM Bridge. The bridge interface is available for both Mainnet Beta and Testnet in the [Polygon Wallet Suite](https://wallet.polygon.technology/zkEVM/bridge). The next video is a guide on how to bridge tokens from L1 to the zkEVM Testnet. The same video applies to the zkEVM Mainnet. @@ -20,18 +19,18 @@ Follow this step-by-step guide on how to bridge assets from Ethereum to Polygon - On the [Polygon Wallet Suite website](https://wallet.polygon.technology/), select the zkEVM tab, which is next to the Proof-of-Stake tab: -![Figure: wallet](../img/zkvm/zkv-zkwallet-1.jpg) +![Figure: wallet](../img/zkEVM/zkv-zkwallet-1.jpg) - Click on the **Bridge** module to access the zkEVM environment. - Set the amount of tokens to transfer from Ethereum network to zkEVM Mainnet (Or, from an Ethereum testnet to zkEVM testnet). -![Figure: bridge2](../img/zkvm/zkv-bridge2.jpg) +![Figure: bridge2](../img/zkEVM/zkv-bridge2.jpg) - Recent transactions and pending transactions can be viewed on the right hand side of the page. - Click the `Bridge ETH to zkEVM testnet` button to proceed. This is followed by Metamask's prompt to approve gas to be spent. -![Figure: metamask1](../img/zkvm/zkv-metamask1.jpg) +![Figure: metamask1](../img/zkEVM/zkv-metamask1.jpg) - Click `Confirm` to approve the bridge transaction. @@ -39,4 +38,4 @@ Follow this step-by-step guide on how to bridge assets from Ethereum to Polygon - Once it is completed, past and pending transactions can be viewed by clicking the "Transactions" button located on the left side of the menu. -![Figure: tx-history](../img/zkvm/zkv-transaction-history.jpg) \ No newline at end of file +![Figure: tx-history](../img/zkEVM/zkv-transaction-history.jpg) diff --git a/docs/zkEVM/concepts/basic-smt-ops.md b/docs/zkEVM/concepts/basic-smt-ops.md index b332a1696..edc43f5fb 100644 --- a/docs/zkEVM/concepts/basic-smt-ops.md +++ b/docs/zkEVM/concepts/basic-smt-ops.md @@ -4,17 +4,17 @@ Now that the basic design is established, the other operations can be delineated ## The READ Operation -First, we illustrate the **READ** operation, which is in fact a **Get**. +First, we illustrate the **READ** operation, which is in fact a **Get**. The prover can commit to a key-value pair $(K_{\mathbf{x}}, \text{HV}_{\mathbf{x}})$ where $\text{HV}_{\mathbf{x}}$ is the hash of the value $V_{\mathbf{x}}$. That is, he claims that he created a leaf $\mathbf{L}_{\mathbf{x}}$ which contains the value $V_{\mathbf{x}}$ and it can be located using the key $K_{\mathbf{x}}$. **READ** therefore means locating the leaf $\mathbf{L}_{\mathbf{x}}$ and verifying that it contains the value $V_{\mathbf{x}}$ by using a Merkle proof. -Hence, in addition to $(K_{\mathbf{x}}, \text{HV}_{\mathbf{x}})$, prover has to provide the rest of the information needed for completing the Merkle proof. That is, the root, the key-bits $\text{kb}_\mathbf{j}$ for locating the leaf $\mathbf{L}_{\mathbf{x}}$, the Remaining Key $\text{RK}_\mathbf{x}$ and all the necessary siblings. +Hence, in addition to $(K_{\mathbf{x}}, \text{HV}_{\mathbf{x}})$, prover has to provide the rest of the information needed for completing the Merkle proof. That is, the root, the key-bits $\text{kb}_\mathbf{j}$ for locating the leaf $\mathbf{L}_{\mathbf{x}}$, the Remaining Key $\text{RK}_\mathbf{x}$ and all the necessary siblings. #### What if the key is not set? -The next example demonstrates the **READ** operation when a key is not set in the tree. That is, it illustrates how to check whether a value is not on a given SMT. +The next example demonstrates the **READ** operation when a key is not set in the tree. That is, it illustrates how to check whether a value is not on a given SMT. There are two cases that can occur. The given key may lead either to a zero node or to an existing leaf. @@ -24,9 +24,9 @@ But if the given **key leads to an existing leaf**, the verifier has to prove th ### When The Key Is Not Set -Suppose the verifier needs to prove that the keys, $K_{\mathbf{x}} = 11010101$ and $K_{\mathbf{z}} = 10101010$ are not set in the SMT depicted in the figure below. +Suppose the verifier needs to prove that the keys, $K_{\mathbf{x}} = 11010101$ and $K_{\mathbf{z}} = 10101010$ are not set in the SMT depicted in the figure below. -![Key Not Set Example](../../img/zkvm/fig10-key-not-set-eg.png) +![Key Not Set Example](../../img/zkEVM/fig10-key-not-set-eg.png) #### Case 1: When the key leads to a zero-node @@ -36,7 +36,7 @@ Since the least-significant key-bit of the given key, $\text{kb}_0 = 1$, navigat The task here is to verify that the node is indeed a zero-node. -So the verifier computes the root as follows, $\mathbf{{\tilde{root}}_{ab0}} = \mathbf{H_{noleaf}} (\mathbf{{S}_{1}} \| \mathbf{0} ) = \mathbf{H}( \mathbf{{B}_{\mathbf{ab}}} \| \mathbf{0} )$. +So the verifier computes the root as follows, $\mathbf{{\tilde{root}}_{ab0}} = \mathbf{H_{noleaf}} (\mathbf{{S}_{1}} \| \mathbf{0} ) = \mathbf{H}( \mathbf{{B}_{\mathbf{ab}}} \| \mathbf{0} )$. Note that he concatenates $\mathbf{{S}_{1}}$ and $\mathbf{0}$ in the given ordering, because $\text{kb}_0 = 1$. @@ -50,25 +50,25 @@ The verifier is given; the key $K_{\mathbf{z}} = 10101010$, the Remaining Key $\ When navigating the tree from $\mathbf{{root}_{ab0}}$, using the key-bits $\text{kb}_{\mathbf{0}} = 0$ and $\text{kb}_{\mathbf{1}} = 1$, and with reference to the above figure, -- the key-bit $\text{kb}_{\mathbf{0}} = 0$ leads to the branch $\mathbf{{B}_{\mathbf{ab}}}$, +- the key-bit $\text{kb}_{\mathbf{0}} = 0$ leads to the branch $\mathbf{{B}_{\mathbf{ab}}}$, - then from $\mathbf{{B}_{\mathbf{ab}}}$, the key-bit $\text{kb}_{\mathbf{1}} = 1$ leads to the leaf $\mathbf{L}_\mathbf{b}$, which is the leaf circled in brown in the above figure. Since the key navigates to a leaf, the Verifier's task is to prove two things simultaneously; -1. The leaf is in the SMT described in the above figure, and +1. The leaf is in the SMT described in the above figure, and 2. The Remaining Key at the leaf $\mathbf{L}_\mathbf{b}$ is different from the Remaining Key supplied by the prover. In proving that $\mathbf{L}_{\mathbf{b}}$ is indeed in the tree, the verifier carries out the following tasks simultaneously; - **Checks The Root** - 1. Computes the hash of the hashed-value, $\mathbf{ \tilde{L} }_{\mathbf{b}} = \mathbf{H_{leaf}} ( \text{RK}_{\mathbf{b}} \| \text{HV}_{\mathbf{b}} )$, - - 2. Uses the first sibling to compute, $\mathbf{{\tilde{B}}_{\mathbf{ab}}} = \mathbf{H_{noleaf}} \big( \mathbf{L}_{\mathbf{a}} \| \mathbf{ \tilde{L}}_{\mathbf{b}} \big)$, + 1. Computes the hash of the hashed-value, $\mathbf{ \tilde{L} }_{\mathbf{b}} = \mathbf{H_{leaf}} ( \text{RK}_{\mathbf{b}} \| \text{HV}_{\mathbf{b}} )$, - 3. Then, uses the second sibling to compute the root, $\mathbf{\tilde{root}}_{ab0} = \mathbf{H_{noleaf}} \big( \mathbf{{\tilde{B}}_{\mathbf{ab}}} \| \mathbf{0} \big)$. + 2. Uses the first sibling to compute, $\mathbf{{\tilde{B}}_{\mathbf{ab}}} = \mathbf{H_{noleaf}} \big( \mathbf{L}_{\mathbf{a}} \| \mathbf{ \tilde{L}}_{\mathbf{b}} \big)$, - 4. Completes the root-check by testing equality, $\mathbf{\tilde{root}}_{ab0} = \mathbf{{root}}_{ab0}$. + 3. Then, uses the second sibling to compute the root, $\mathbf{\tilde{root}}_{ab0} = \mathbf{H_{noleaf}} \big( \mathbf{{\tilde{B}}_{\mathbf{ab}}} \| \mathbf{0} \big)$. + + 4. Completes the root-check by testing equality, $\mathbf{\tilde{root}}_{ab0} = \mathbf{{root}}_{ab0}$. - **Checks The Keys** @@ -88,7 +88,7 @@ The last check, where the verifier checks inequality of keys, turns out to be ve ::: -## The UPDATE Operation +## The UPDATE Operation The **UPDATE** operation does not change the topology of the tree. When carrying out the **UPDATE**, it is therefore important to retain all labels of nodes. @@ -102,7 +102,7 @@ First, the verifier needs to be provided with the following data, i.e., **the re The verifier can continue with **Step 2** only if all the checks in **Step 1** pass verification. -For the **UPDATE** operation, **Step 1** is exactly the same as the **READ** operation. We therefore focus on illustrating **Step 2**. +For the **UPDATE** operation, **Step 1** is exactly the same as the **READ** operation. We therefore focus on illustrating **Step 2**. ### Example: UPDATE Operation @@ -110,31 +110,31 @@ Suppose the set key is $K_{\mathbf{c}} = 10110100$ corresponding to the old valu The verifier is provided with the following data; -1. the $\text{RK}_{\mathbf{c}} = 10110$ +1. the $\text{RK}_{\mathbf{c}} = 10110$ 2. the least-significant key-bit $\text{kb}_0 = 0$ 3. the second least-significant key-bit $\text{kb}_1 = 0$ 4. the third least-significant key-bit $\text{kb}_2 = 1$ 5. the old hashed value $\text{HV}_{\mathbf{c}}$ -6. the old root $\mathbf{{root}_{ab..f }}$ +6. the old root $\mathbf{{root}_{ab..f }}$ 7. the siblings $\mathbf{{S}_{1}} = \mathbf{{S}_{\mathbf{ab}}}$, $\mathbf{{S}_{2}} = \mathbf{{L}_{d}}$ and $\mathbf{{S}_{3}} = \mathbf{{S}_{\mathbf{ef}}}$ Consider the SMT given in the below figure. -![Value UPDATE Example](../../img/zkvm/fig11-val-update-eg.png) +![Value UPDATE Example](../../img/zkEVM/fig11-val-update-eg.png) -The required **Step 2** of the **UPDATE** operation involves: +The required **Step 2** of the **UPDATE** operation involves: 1. Computing the hash of the new value $V_\mathbf{new}$ as; $\text{HV}_{\mathbf{new}} = \mathbf{H_{noleaf}}(V_\mathbf{new})$, -2. Forming the new leaf by again hashing the hashed value $\text{HV}_{\mathbf{new}}$ as; $\mathbf{ \tilde{L} }_{\mathbf{new}} = \mathbf{H_{leaf}}( \text{RK}_{\mathbf{new}} \| \text{HV}_{\mathbf{new}} )$, +2. Forming the new leaf by again hashing the hashed value $\text{HV}_{\mathbf{new}}$ as; $\mathbf{ \tilde{L} }_{\mathbf{new}} = \mathbf{H_{leaf}}( \text{RK}_{\mathbf{new}} \| \text{HV}_{\mathbf{new}} )$, -3. Using the first sibling $\mathbf{{S}_{1}} = \mathbf{{S}_{\mathbf{ab}}}$ to compute, $\mathbf{{\bar{B}}_{abc}} = \mathbf{H_{noleaf}} \big( \mathbf{{S}_{\mathbf{ab}}} \| \mathbf{ \tilde{L}}_{\mathbf{new}} \big)$, +3. Using the first sibling $\mathbf{{S}_{1}} = \mathbf{{S}_{\mathbf{ab}}}$ to compute, $\mathbf{{\bar{B}}_{abc}} = \mathbf{H_{noleaf}} \big( \mathbf{{S}_{\mathbf{ab}}} \| \mathbf{ \tilde{L}}_{\mathbf{new}} \big)$, -4. Again, using the second sibling $\mathbf{{S}_{2}} = \mathbf{{L}_{d}}$ to compute, $\mathbf{{\bar{B}}_{\mathbf{abcd}}} = \mathbf{H_{noleaf}} \big( \mathbf{{\bar{B}}_{abc}} \| \mathbf{{L}_{d}} \big)$, +4. Again, using the second sibling $\mathbf{{S}_{2}} = \mathbf{{L}_{d}}$ to compute, $\mathbf{{\bar{B}}_{\mathbf{abcd}}} = \mathbf{H_{noleaf}} \big( \mathbf{{\bar{B}}_{abc}} \| \mathbf{{L}_{d}} \big)$, 5. Then, uses the third sibling $\mathbf{{S}_{3}} = \mathbf{{S}_{\mathbf{ef}}}$ to compute the root, $\mathbf{{{root}}_{\mathbf{new}}} = \mathbf{H_{noleaf}} \big( \mathbf{{\bar{B}}_{\mathbf{abcd}}} \| \mathbf{{S}_{\mathbf{ef}}}\big)$. -Note that the key-bits are not changed. Therefore, replacing the following old values in the SMT, +Note that the key-bits are not changed. Therefore, replacing the following old values in the SMT, $\text{HV}_\mathbf{c}, \mathbf{{B}_{abc}}, \mathbf{{B}_{abcb}}, \mathbf{{root}_{ab..f } }$, with the new ones, $\text{HV}_\mathbf{new}, \mathbf{{\bar{B}}_{abc}}, \mathbf{{\bar{B}}_{abcb}}, \mathbf{{root}_{new } }$, respectively, completes the **UPDATE** operation. @@ -150,11 +150,11 @@ That is, the first $l$ least-significant bits of the key $\mathbf{K_{new}}$ lead The first step is to double-check that indeed the node is a zero node. That is, the verifier performs a Merkle proof starting with either $\mathbf{H_{noleaf}} ( \mathbf{S_1} \| \mathbf{0} )$ or $\mathbf{H_{noleaf}} ( \mathbf{0} \| \mathbf{S_1} )$, depending on whether the sibling of the zero-node is on the right (the edge corresponding to a key-bit $1$) or on the left (the edge corresponding to a key-bit $0$), respectively. -Once it is established that the new key $\mathbf{K_{new}}$ has led to a zero node, the verifier simply changes the zero node to the leaf $\mathbf{L_{new}}$ that stores the value $\mathbf{V_{new}}$. +Once it is established that the new key $\mathbf{K_{new}}$ has led to a zero node, the verifier simply changes the zero node to the leaf $\mathbf{L_{new}}$ that stores the value $\mathbf{V_{new}}$. The **CREATE** operation, in this case, therefore boils down to an **UPDATE** operation on the zero node. It amounts to; -- Computing the hash of the new value $V_\mathbf{new}$ as, $\text{HV}_{\mathbf{new}} = \mathbf{H_{noleaf}}(V_\mathbf{new})$, +- Computing the hash of the new value $V_\mathbf{new}$ as, $\text{HV}_{\mathbf{new}} = \mathbf{H_{noleaf}}(V_\mathbf{new})$, - Then forming the new leaf, $\mathbf{L_{new}} = \mathbf{H_{leaf}}( \text{RK}_{\mathbf{new}} \| \text{HV}_{\mathbf{new}})$, - Recomputing all the nodes along the path climbing from the leaf $\mathbf{L_{new}}$ to the root, including computing the new root. @@ -170,23 +170,23 @@ Suppose a new leaf with the key-value pair $\big(K_{\mathbf{new}}, \text{V}_{\ma As illustrated in the below figure, the two least-significant key-bits $\text{kb}_0 = 0$ and $\text{kb}_1 = 1$, lead to a zero node. That is, navigating from the root; -​ (a) The lsb, $\text{kb}_{0} = 0$ leads to the node $\mathbf{{B}_{ab0}}$, +​ (a) The lsb, $\text{kb}_{0} = 0$ leads to the node $\mathbf{{B}_{ab0}}$, -​ (b) Whilst the second lsb, $\text{kb}_{1} = 1$ leads to a zero node. +​ (b) Whilst the second lsb, $\text{kb}_{1} = 1$ leads to a zero node. At this stage the verifier checks if this is indeed a zero node; -1. First it computes $\mathbf{{\tilde{B}}_{ab0}} = \mathbf{H_{noleaf}} \big( \mathbf{{S}_{\mathbf{ab}}} \| \mathbf{0} \big)$. -2. Then it computes $\mathbf{{\tilde{root}}_{ab0c}} = \mathbf{H_{noleaf}} \big( \mathbf{{\tilde{B}}_{ab0}} \| \mathbf{L_{c}} \big)$. -3. And, checks if $\mathbf{{\tilde{root}}_{ab0c}}$ equals $\mathbf{{root}_{ab0c}}$. +1. First it computes $\mathbf{{\tilde{B}}_{ab0}} = \mathbf{H_{noleaf}} \big( \mathbf{{S}_{\mathbf{ab}}} \| \mathbf{0} \big)$. +2. Then it computes $\mathbf{{\tilde{root}}_{ab0c}} = \mathbf{H_{noleaf}} \big( \mathbf{{\tilde{B}}_{ab0}} \| \mathbf{L_{c}} \big)$. +3. And, checks if $\mathbf{{\tilde{root}}_{ab0c}}$ equals $\mathbf{{root}_{ab0c}}$. -![CREATE Operation - Zero Node](../../img/zkvm/fig12-crt-zero-node.png) +![CREATE Operation - Zero Node](../../img/zkEVM/fig12-crt-zero-node.png) Once the zero-value is checked, the verifier now creates a non-zero leaf with the key-value pair $\big( \mathbf{K_{new}} , \text{HV}_{\mathbf{new}}\big)$. -1. It computes the hash of $\text{V}_{\mathbf{new}}$ as, $\text{HV}_{\mathbf{new}} = \mathbf{H_{noleaf}}(V_\mathbf{new})$, -2. It then forms the leaf $\mathbf{L_{new}} = \mathbf{H_{leaf}}( \text{RK}_{\mathbf{new}} \| \text{HV}_{\mathbf{new}})$, -3. Also computes $\mathbf{B_{new}} = \mathbf{H_{noleaf}} ( \mathbf{{S}_{\mathbf{ab}}} \| \mathbf{L_{new}})$, +1. It computes the hash of $\text{V}_{\mathbf{new}}$ as, $\text{HV}_{\mathbf{new}} = \mathbf{H_{noleaf}}(V_\mathbf{new})$, +2. It then forms the leaf $\mathbf{L_{new}} = \mathbf{H_{leaf}}( \text{RK}_{\mathbf{new}} \| \text{HV}_{\mathbf{new}})$, +3. Also computes $\mathbf{B_{new}} = \mathbf{H_{noleaf}} ( \mathbf{{S}_{\mathbf{ab}}} \| \mathbf{L_{new}})$, 4. And computes $\mathbf{{root}_{new}} = \mathbf{H_{noleaf}} ( \mathbf{B_{new}} \| \mathbf{L_{c}} )$. An update of these values; the branch $\mathbf{B_{ab0}}$ to $\mathbf{B_{new}}$ and the old root $\mathbf{{root}_{ab0c}}$ to $\mathbf{{root}_{new}}$; completes the **CREATE** operation. @@ -197,11 +197,11 @@ That is, the first $\mathbf{l}$ least-significant bits of the key $\mathbf{K_{ne #### 1. Checking Leaf Inclusion -The first step is to double-check that indeed the value $V_\mathbf{z}$ stored at the leaf $\mathbf{L_z}$ is indeed included in the root. +The first step is to double-check that indeed the value $V_\mathbf{z}$ stored at the leaf $\mathbf{L_z}$ is indeed included in the root. That is, the verifier performs a Merkle proof starting with either $\mathbf{H_{noleaf}} ( \mathbf{S_1} \| \mathbf{L_z} )$ or $\mathbf{H_{noleaf}} ( \mathbf{L_z} \| \mathbf{S_1} )$, for some sibling $\mathbf{S_1}$. The ordering of the hash arguments depends on whether the sibling of the leaf $\mathbf{L_z}$ is on the left (the edge corresponding to a key-bit $0$) or on the right (the edge corresponding to a key-bit $1$), respectively. The check of value-inclusion gets completed by climbing the tree as usual. -Once it is established that the value $V_\mathbf{z}$ stored at the leaf $\mathbf{L_z}$ is included in the root, the new leaf $\mathbf{L_{new}}$ storing the key-value pair can now be created. +Once it is established that the value $V_\mathbf{z}$ stored at the leaf $\mathbf{L_z}$ is included in the root, the new leaf $\mathbf{L_{new}}$ storing the key-value pair can now be created. #### 2. Extending The SMT @@ -211,7 +211,7 @@ As discussed earlier in this document, when building binary SMTs, the aim is to So then, for as long as the next corresponding key-bits between $\mathbf{K_{new}}$ and $\mathbf{K_{z}}$ coincide, a new extension branch needs to be formed. -Here's the general procedure; +Here's the general procedure; 1. Start with the next least-significant key-bits, $\text{kb}_\mathbf{(l+1)new}$ and $\text{kb}_\mathbf{(l+1)z}$, and check if $\text{kb}_\mathbf{(l+1)new} = \text{kb}_\mathbf{(l+1)z}$ or not. 2. If they are not the same (i.e., if $\text{kb}_\mathbf{(l+1)new} \neq \text{kb}_\mathbf{(l+1)z}$), then one new extension branch $\mathbf{B_{ext1}}$ with $\mathbf{L_{new}}$ and $\mathbf{L_{z}}$ as its child-nodes, suffices. @@ -227,19 +227,19 @@ The **CREATE** Operation is actually only complete once all the values on the na ### Example: CREATE Operation with Single Branch Extension -Suppose a leaf needs to be created to store a new key-value pair $\big({K_{\mathbf{new}}\ } , V_\mathbf{{new}}\big)$, where $K_{\mathbf{new}} = 11010110$. +Suppose a leaf needs to be created to store a new key-value pair $\big({K_{\mathbf{new}}\ } , V_\mathbf{{new}}\big)$, where $K_{\mathbf{new}} = 11010110$. Consider the SMT shown in the below figure. -![CREATE Operation - Non-zero Leaf Node](../../img/zkvm/fig13-a-crt-nzleaf-ext.png) +![CREATE Operation - Non-zero Leaf Node](../../img/zkEVM/fig13-a-crt-nzleaf-ext.png) In this example, navigation using the least-significant key-bits, $\text{kb}_\mathbf{0} = 0$ and $\text{kb}_\mathbf{1} = 1$, leads to an existing leaf $\mathbf{L_{\mathbf{c}}}$. And the key-value pair $(V_\mathbf{\mathbf{c}}, \text{HV}_\mathbf{\mathbf{c}})$ stored at $\mathbf{L_{\mathbf{c}}}$ has the key $K_{\mathbf{c}} = 11010010$. 1. **Value-Inclusion Check** - A value-inclusion check of $V_\mathbf{\mathbf{c}}$ is performed before creating any new leaf. Since this amounts to a **READ** Operation, which has been illustrated in previous examples, we omit how this is done here. + A value-inclusion check of $V_\mathbf{\mathbf{c}}$ is performed before creating any new leaf. Since this amounts to a **READ** Operation, which has been illustrated in previous examples, we omit how this is done here. - Once $V_\mathbf{\mathbf{c}}$ passes the check, the **CREATE** Operation continues by inserting the new leaf. + Once $V_\mathbf{\mathbf{c}}$ passes the check, the **CREATE** Operation continues by inserting the new leaf. 2. **New Leaf Insertion** @@ -251,14 +251,14 @@ In this example, navigation using the least-significant key-bits, $\text{kb}_\ma The next process, after forming the branch extension, is to **UPDATE** all the nodes along the path from the root to the new leaf $\mathbf{L_{new}}$. The verifier follows the steps of the **UPDATE** operation to accomplish this. -3. **UPDATE of SMT Values** +3. **UPDATE of SMT Values** The verifier computes the following; - 1. The hashed value, $\text{HV}_{\mathbf{new}} = \mathbf{H_{noleaf}}(V_\mathbf{new})$, - 2. The new leaf, $\mathbf{L_{new}} = \mathbf{H_{leaf}} ( \text{RK}_{\mathbf{new}} \| \text{HV}_{\mathbf{new}})$, - 3. Then, $\mathbf{B_{ext}} = \mathbf{H_{noleaf}} ( \mathbf{L_{c}} \| \mathbf{L_{new}})$, - 4. Again, $\mathbf{B_{new}} = \mathbf{H_{noleaf}}( \mathbf{S_{ab}} \| \mathbf{B_{ext}} )$, + 1. The hashed value, $\text{HV}_{\mathbf{new}} = \mathbf{H_{noleaf}}(V_\mathbf{new})$, + 2. The new leaf, $\mathbf{L_{new}} = \mathbf{H_{leaf}} ( \text{RK}_{\mathbf{new}} \| \text{HV}_{\mathbf{new}})$, + 3. Then, $\mathbf{B_{ext}} = \mathbf{H_{noleaf}} ( \mathbf{L_{c}} \| \mathbf{L_{new}})$, + 4. Again, $\mathbf{B_{new}} = \mathbf{H_{noleaf}}( \mathbf{S_{ab}} \| \mathbf{B_{ext}} )$, 5. And finally computes, $\mathbf{{root}_{new}} = \mathbf{H_{noleaf}}( \mathbf{B_{new}} \| \mathbf{L_{d}} )$. This illustrates how the **CREATE** Operation is performed at a non-zero leaf, when only one branch extension is required. @@ -271,13 +271,13 @@ Suppose a leaf must be created to store a new key-value pair $\big(K_{\mathbf{ne Consider the SMT shown in the below figure. -![CREATE Operation - Three Branch Extensions](../../img/zkvm/fig13-b-crt-nzleaf-xt.png) +![CREATE Operation - Three Branch Extensions](../../img/zkEVM/fig13-b-crt-nzleaf-xt.png) Navigating the tree by using the least-significant key-bits, $\text{kb}_\mathbf{0} = 0$ and $\text{kb}_\mathbf{1} = 1$, leads to an existing leaf $\mathbf{L_{\mathbf{c}}}$. In this example, suppose the key-value pair $(K_{\mathbf{c}}, \text{HV}_\mathbf{\mathbf{c}})$ stored at $\mathbf{L_{\mathbf{c}}}$ has the key $K_{\mathbf{c}} = 11100110$. 1. **Value-Inclusion Check** - Before creating the new leaf, it is important to first check if $V_\mathbf{\mathbf{c}}$ is indeed included in the root, $\mathbf{root}_\mathbf{abcd}$. Since this amounts to performing a **READ** Operation, which has been illustrated in previous examples, we omit here how this is done. + Before creating the new leaf, it is important to first check if $V_\mathbf{\mathbf{c}}$ is indeed included in the root, $\mathbf{root}_\mathbf{abcd}$. Since this amounts to performing a **READ** Operation, which has been illustrated in previous examples, we omit here how this is done. Once $V_\mathbf{\mathbf{c}}$ passes the value-inclusion check, the **CREATE** Operation proceeds with inserting the new leaf. @@ -285,7 +285,7 @@ Navigating the tree by using the least-significant key-bits, $\text{kb}_\mathbf{ Note that the first and second least-significant key-bits for both $K_\mathbf{new}$ and $K_\mathbf{c}$ are the same. That is, $\text{kb}_\mathbf{0new} = 0 = \text{kb}_\mathbf{0c}$ and $\text{kb}_\mathbf{1new} = 1 = \text{kb}_\mathbf{1c}$. - As a result, the new leaf $\mathbf{L_{new}}$ cannot be inserted at the key-address `01`, where $\mathbf{L_{\mathbf{c}}}$ is positioned. An extension branch $\mathbf{{B}_{ext1}}$ is formed at the tree-address `01`. + As a result, the new leaf $\mathbf{L_{new}}$ cannot be inserted at the key-address `01`, where $\mathbf{L_{\mathbf{c}}}$ is positioned. An extension branch $\mathbf{{B}_{ext1}}$ is formed at the tree-address `01`. **But, can the leaves $\mathbf{L_{new}}$ and $\mathbf{L_{c}}$ be child-nodes to $\mathbf{{B}_{ext1}}$?** @@ -297,7 +297,7 @@ Navigating the tree by using the least-significant key-bits, $\text{kb}_\mathbf{ A third extension branch $\mathbf{{B}_{ext3}}$ is needed at the tree-address `0110`. - In this case, the fifth least-significant key-bits of $K_\mathbf{new}$ and $K_\mathbf{c}$ are different, i.e., $\text{kb}_\mathbf{4new} = 1$ and $\text{kb}_\mathbf{4c} = 0$. + In this case, the fifth least-significant key-bits of $K_\mathbf{new}$ and $K_\mathbf{c}$ are different, i.e., $\text{kb}_\mathbf{4new} = 1$ and $\text{kb}_\mathbf{4c} = 0$. The leaves $\mathbf{L_{new}}$ and $\mathbf{L_{c}}$ are now made child-nodes of the extension branch $\mathbf{{B}_{ext3}}$. See the above figure. @@ -308,16 +308,16 @@ Navigating the tree by using the least-significant key-bits, $\text{kb}_\mathbf{ The verifier computes, 1. The hash of the new value, $\text{HV}_\mathbf{new} = \mathbf{H_{noleaf}}(V_\mathbf{new})$, - 2. The new leaf, $\mathbf{L_{new}} = \mathbf{H_{leaf}} ( \text{RK}_{\mathbf{new}} \| \text{HV}_{\mathbf{new}})$, - 3. Then, $\mathbf{B_{ext3}} = \mathbf{H_{noleaf}}( \mathbf{L_{c}} \| \mathbf{L_{new}})$, + 2. The new leaf, $\mathbf{L_{new}} = \mathbf{H_{leaf}} ( \text{RK}_{\mathbf{new}} \| \text{HV}_{\mathbf{new}})$, + 3. Then, $\mathbf{B_{ext3}} = \mathbf{H_{noleaf}}( \mathbf{L_{c}} \| \mathbf{L_{new}})$, 4. Followed by $\mathbf{B_{ext2}} = \mathbf{H_{noleaf}}( \mathbf{B_{ext3}} \| \mathbf{0} )$, 5. And, $\mathbf{B_{ext1}} = \mathbf{H_{noleaf}}( \mathbf{0} \| \mathbf{B_{ext2}} )$, - 6. Again, $\mathbf{B_{new}} = \mathbf{H_{noleaf}}( \mathbf{S_{ab}} \| \mathbf{B_{ext2}} )$, + 6. Again, $\mathbf{B_{new}} = \mathbf{H_{noleaf}}( \mathbf{S_{ab}} \| \mathbf{B_{ext2}} )$, 7. And finally computes, $\mathbf{{root}_{new}} = \mathbf{H_{noleaf}}( \mathbf{B_{new}} \| \mathbf{L_{d}} )$. This completes the **CREATE** operation at an existing leaf where several branch extensions are needed. Note that the **CREATE** operation at a non-leaf node clearly changes the topology of the tree. -## The DELETE Operation +## The DELETE Operation The **DELETE** Operation refers to a removal of a certain key-value pair from a binary SMT. It is in fact the reverse of the **CREATE** Operation. @@ -329,13 +329,13 @@ On the other hand, a **DELETE** Operation can be tantamount to the reverse of a A **DELETE** Operation involves two main steps; -1. A **READ** of the value to be deleted is executed. That is; +1. A **READ** of the value to be deleted is executed. That is; - - Navigating to the value, - - Checking if the value is included in the root, and + - Navigating to the value, + - Checking if the value is included in the root, and - Checking if the given key (reconstructed from the given **Remaining Key** and the least-significant key-bits) matches the key at the leaf (reconstructed from the **Remaining Key** found at the leaf and the given key-bits). -2. This step depends on whether the sibling of the **leaf to be deleted** is zero or not; +2. This step depends on whether the sibling of the **leaf to be deleted** is zero or not; - If the **sibling is not a zero node**, an **UPDATE** to a zero is performed. - If the **sibling is a zero-node**, an **UPDATE** to a zero is performed and the parent-node is turned into a NULL node with no child-nodes. @@ -348,11 +348,11 @@ Suppose the data provided includes; the Remaining Key $\tilde{\text{RK}}_{\mathb With reference to the figure below, navigation leads to the leaf $\mathbf{L_b}$. -![DELETE Operation - Non-Zero Sibling](../../img/zkvm/fig14-a-dlt-nz-sib.png) +![DELETE Operation - Non-Zero Sibling](../../img/zkEVM/fig14-a-dlt-nz-sib.png) Next, perform a Merkle proof to check if the hashed value $\text{HV}_\mathbf{b}$ at $\mathbf{L_b}$ is included in the given root; -- Compute $\tilde{\mathbf{L}}_\mathbf{b} = \mathbf{H_{leaf}} ( \text{RK}_{\mathbf{b}} \| \text{HV}_\mathbf{b} )$ +- Compute $\tilde{\mathbf{L}}_\mathbf{b} = \mathbf{H_{leaf}} ( \text{RK}_{\mathbf{b}} \| \text{HV}_\mathbf{b} )$ - Then $\tilde{\mathbf{B}}_\mathbf{ab} = \mathbf{H_{noleaf}} ( \mathbf{L_a} \| \tilde{\mathbf{L}}_\mathbf{b})$ - And, $\tilde{\mathbf{root}}_\mathbf{abc} = \mathbf{H_{noleaf}} ( \tilde{\mathbf{B}}_\mathbf{ab} \| \mathbf{L_c} )$ - Check if $\tilde{\mathbf{root}}_\mathbf{abc}$ equals $\mathbf{{root}_{abc}}$. @@ -363,9 +363,9 @@ Since the sibling $\mathbf{L_a}$ is not a zero node, the hashed value $\text{HV} - The leaf $\mathbf{L_b}$ is set to "$\mathbf{0}$", a zero node. - The parent-node is now, $\mathbf{B_{a0}} = \mathbf{H_{noleaf}} ( \mathbf{L_a} \| \mathbf{0} )$. -- And, the new root, $\mathbf{{root}_{abc}} = \mathbf{H_{noleaf}}(\mathbf{B_{a0}} \| \mathbf{L_a})$. +- And, the new root, $\mathbf{{root}_{abc}} = \mathbf{H_{noleaf}}(\mathbf{B_{a0}} \| \mathbf{L_a})$. -Notice how the SMT maintains its original shape. +Notice how the SMT maintains its original shape. ### DELETE Leaves With Zero Siblings @@ -375,17 +375,17 @@ Suppose the data provided includes; the Remaining Key $\tilde{\text{RK}}_{\mathb With reference to the figure below, navigation leads to the leaf $\mathbf{L_c}$. -![Figure 14(../../img/zkvm/fig14-b-dlt-z-sib.png): DELETE Operation - Zero Sibling](../../img/zkvm/fig14-b-dlt-z-sib.png) +![Figure 14(../../img/zkEVM/fig14-b-dlt-z-sib.png): DELETE Operation - Zero Sibling](../../img/zkEVM/fig14-b-dlt-z-sib.png) -The **READ** step in this case is similar to what is seen in the above case. +The **READ** step in this case is similar to what is seen in the above case. -The **UPDATE** step depends on the sibling of $\mathbf{L_c}$. Since the sibling is $\mathbf{0}$, an **UPDATE** of $\mathbf{L_c}$ to zero results in the branch $\mathbf{B_{0c}}$ having two zero nodes as child-nodes. Since $\mathbf{H_{noleaf}} ( \mathbf{0} \| \mathbf{0}) = 0$, it is therefore expedient to turn the branch $\mathbf{B_{0c}}$ into a zero node with no child-nodes. +The **UPDATE** step depends on the sibling of $\mathbf{L_c}$. Since the sibling is $\mathbf{0}$, an **UPDATE** of $\mathbf{L_c}$ to zero results in the branch $\mathbf{B_{0c}}$ having two zero nodes as child-nodes. Since $\mathbf{H_{noleaf}} ( \mathbf{0} \| \mathbf{0}) = 0$, it is therefore expedient to turn the branch $\mathbf{B_{0c}}$ into a zero node with no child-nodes. That is, the **UPDATE** step of this **DELETE** Operation concludes as follows; - The original branch $\mathbf{B_{0c}}$ is now "$\mathbf{0}$", a zero node. - The parent-node is now, $\mathbf{B_{a0}} = \mathbf{H_{noleaf}} ( \mathbf{L_a} \| \mathbf{0} )$. -- And, the new root, $\mathbf{{root}_{a0d}} = \mathbf{H_{noleaf}}(\mathbf{B_{a0}} \| \mathbf{L_d})$. +- And, the new root, $\mathbf{{root}_{a0d}} = \mathbf{H_{noleaf}}(\mathbf{B_{a0}} \| \mathbf{L_d})$. Notice that in this example, the **DELETE** Operation alters the topology of the SMT. diff --git a/docs/zkEVM/concepts/circom-intro-brief.md b/docs/zkEVM/concepts/circom-intro-brief.md index 4e2ee2e50..2787b6615 100755 --- a/docs/zkEVM/concepts/circom-intro-brief.md +++ b/docs/zkEVM/concepts/circom-intro-brief.md @@ -1,11 +1,10 @@ !!!info - In this document, we describe the CIRCOM component of the zkProver. It is one of the four main components of the zkProver, as outlined [here](../zkprover/zkprover-overview.md). These principal components are; the Executor or Main SM, STARK Recursion, CIRCOM, and Rapid SNARK. + In this document, we describe the CIRCOM component of the zkProver. It is one of the four main components of the zkProver, as outlined [here](../architecture/zkprover/zkprover-overview.md). These principal components are; the Executor or Main SM, STARK Recursion, CIRCOM, and Rapid SNARK. You may refer to the original [CIRCOM research paper](https://www.techrxiv.org/articles/preprint/CIRCOM_A_Robust_and_Scalable_Language_for_Building_Complex_Zero-Knowledge_Circuits/19374986/1) for more details. - -As seen in the [zkProver Overview](../zkprover/zkprover-overview.md) document, the output of the STARK Recursion component is a STARK proof. +As seen in the [zkProver Overview](../architecture/zkprover/zkprover-overview.md) document, the output of the STARK Recursion component is a STARK proof. The next step in the zkProver's process of providing validity proof is to **produce the witness similar to the output of the STARK Recursion**. @@ -15,7 +14,7 @@ Although the zkProver is designed as a state machine emulating the EVM, in order The witness is in turn taken as input to the Rapid SNARK, which is used to generate a SNARK proof published as the validity proof. -![CIRCOM's input and output](../../img/zkvm/01circom-witness-zkprover.png) +![CIRCOM's input and output](../../img/zkEVM/01circom-witness-zkprover.png) In fact, CIRCOM takes a STARK proof as input and produces its corresponding Arithmetic circuit, expressed as the equivalent set of equations called Rank-1 Constraint System (R1CS). @@ -47,7 +46,7 @@ CIRCOM was developed for the very purpose of scaling complex Arithmetic circuits CIRCOM is a Domain-Specific Language (DSL) used to define Arithmetic circuits, and it has an associated compiler of Arithmetic circuits to their respective Rank-1 Constraint System (or R1CS). -![CIRCOM Overall Context](../../img/zkvm/02circom-overall-context.png) +![CIRCOM Overall Context](../../img/zkEVM/02circom-overall-context.png) ### CIRCOM As A DSL @@ -80,7 +79,7 @@ The CIRCOM language has its own peculiarities. The focus in this subsection is o Consider as an example, the `Multiplier` circuit with input signals $\texttt{a}$ and $\texttt{b}$, and an output signal $\texttt{c}$ satisfying the constraint $\texttt{a} \times \texttt{b} \texttt{ - c = 0}$. -![A simple Multiplier Arithmetic circuit](../../img/zkvm/03circom-simple-arith-circuit.png) +![A simple Multiplier Arithmetic circuit](../../img/zkEVM/03circom-simple-arith-circuit.png) The figure above depicts a simple `Multiplier` Arithmetic circuit with input wires labeled $\texttt{a}$ and $\texttt{b}$ and an output wire labeled $\texttt{c}$ such that $\texttt{a} \times \texttt{b\ = } \texttt{c}$. The wires are referred to as signals. The constraint related to this Multiplier circuit is: @@ -243,7 +242,7 @@ template Multiplier() { signal input a; signal input b; signal output c; - c <== a * b; + c <== a * b; } component main {public [a]} = Multiplier(); diff --git a/docs/zkEVM/concepts/commitment-scheme.md b/docs/zkEVM/concepts/commitment-scheme.md index f07218386..f40aadd84 100644 --- a/docs/zkEVM/concepts/commitment-scheme.md +++ b/docs/zkEVM/concepts/commitment-scheme.md @@ -5,7 +5,6 @@ In practice though, the so-called **Fiat-Shamir transformation** is used to turn !!!caution This document dives deep into the technical details of commitment schemes underpinning the zkProver. - It describes what a commitment scheme is, the necessary properties such a scheme must possess, and how the previously stated polynomial identities look like in reality. ## Commitment scheme protocol @@ -39,10 +38,9 @@ Proof systems based on testing polynomial identities take advantage of a basic p According to the Schwartz-Zippel Lemma; ->For any non-zero polynomial ${Q(X_1, . . . , X_n)}$ on ${n}$ variables with degree ${d}$, and ${S}$ a finite but sufficiently large subset of the field $\mathbb{F}$, then values ${ X_1, . . . , X_n }$ from ${S}$ are independently and uniformly assigned at random, then +>For any non-zero polynomial ${Q(X_1, . . . , X_n)}$ on ${n}$ variables with degree ${d}$, and ${S}$ a finite but sufficiently large subset of the field $\mathbb{F}$, then values ${ X_1, . . . , X_n }$ from ${S}$ are independently and uniformly assigned at random, then ${Pr[Q(X_1, . . . , X_n) = 0] ≤ \dfrac{d}{|S|}}$. - **Here's what the Schwartz-Zippel Lemma means in the specific case of the mFibonacci state machine**: >​If the verifier selects the challenges $\{ \alpha_1, \alpha_2 . . . , \alpha_l \}$ randomly and uniformly, then the probability of the prover finding a false polynomial ${Q'}$ of degree $d$, such that ${Q'(\alpha_j) = 0 = Q(\alpha_j)}$ for all $j \in \{ 1, 2, \dots , l \}$ , is at most ${\dfrac{d}{|S|}}$, which is very small. @@ -59,7 +57,7 @@ In a typical commitment scheme, the following protocol is followed; 2. The verifier selects a random point $\alpha$, sends it to the prover, with a request for relevant *openings*. 3. The prover then provides the openings; $P(\alpha)$, $P(\omega \alpha)$, $Q(\alpha)$ and $Q(\omega \alpha)$. -4. The verifier can check correctness of the openings, by using transition constraints, +4. The verifier can check correctness of the openings, by using transition constraints, $$ \begin{aligned} \big( 1 − R(X) \big) \cdot \big[ P(X\cdot \omega) − Q(X) \big] = \bigg\lvert_{\mathcal{H}}\ 0\qquad\quad\text{ }\text{ } @@ -130,4 +128,4 @@ $$ \big(P(\omega^{\mathtt{T}}) - \mathcal{K} \big)\cdot R(X) = \mathtt{Z}_{\mathcal{H}}(X)\cdot q_3(X) \qquad\text{}\text{}\quad\qquad\qquad\qquad\text{ } $$ -The representatives $R(X)$ and $Z_{\mathcal{H}}(X)$ in the PCS, can be preprocessed and be made public (i.e., known to both the Prover and the Verifier). The Verifier can check specific openings of these polynomials, $R(X)$ and $Z_{\mathcal{H}}(X)$. \ No newline at end of file +The representatives $R(X)$ and $Z_{\mathcal{H}}(X)$ in the PCS, can be preprocessed and be made public (i.e., known to both the Prover and the Verifier). The Verifier can check specific openings of these polynomials, $R(X)$ and $Z_{\mathcal{H}}(X)$. diff --git a/docs/zkEVM/concepts/detailed-smt.md b/docs/zkEVM/concepts/detailed-smt.md index 9cbdeccb5..3cc8fa6ff 100644 --- a/docs/zkEVM/concepts/detailed-smt.md +++ b/docs/zkEVM/concepts/detailed-smt.md @@ -2,15 +2,15 @@ This document covers more concepts needed in understanding our specific design o First is the level of a leaf. The **level of a leaf**, $\mathbf{L}_{\mathbf{x}}$, in a binary SMT is defined as the number of edges one traverses when navigating from the root to the leaf. Denote the level of the leaf $\mathbf{L_x}$ by $\text{lvl}(\mathbf{L_x})$. -## Leaf levels +## Leaf levels Consider the below figure for an SMT storing seven key-value pairs, built by following the principles explained in the foregoing subsection; $$ -(\mathbf{K}_{\mathbf{a}} , V_{\mathbf{a}}),\ \ (\mathbf{K}_{\mathbf{b}} , V_{\mathbf{b}}),\ \ -(\mathbf{K}_{\mathbf{c}} , V_{\mathbf{c}}),\ \ (\mathbf{K}_{\mathbf{c}}, V_{\mathbf{c}}),\\ -(\mathbf{K}_{\mathbf{d}}, V_{\mathbf{d}}),\ \ -(\mathbf{K}_{\mathbf{e}}, V_{\mathbf{e}}),\ \ +(\mathbf{K}_{\mathbf{a}} , V_{\mathbf{a}}),\ \ (\mathbf{K}_{\mathbf{b}} , V_{\mathbf{b}}),\ \ +(\mathbf{K}_{\mathbf{c}} , V_{\mathbf{c}}),\ \ (\mathbf{K}_{\mathbf{c}}, V_{\mathbf{c}}),\\ +(\mathbf{K}_{\mathbf{d}}, V_{\mathbf{d}}),\ \ +(\mathbf{K}_{\mathbf{e}}, V_{\mathbf{e}}),\ \ (\mathbf{K}_{\mathbf{f}}, V_{\mathbf{f}})\ \ {\text{and}}\ \ (\mathbf{K}_{\mathbf{g}} , V_{\mathbf{g}}) $$ @@ -24,9 +24,9 @@ The leaf levels are as follows; $\text{lvl}(\mathbf{L}_{\mathbf{a}}) = 2$, $\text{lvl}(\mathbf{L}_{\mathbf{b}}) = 4$, $\text{lvl}(\mathbf{L}_{\mathbf{c}}) = 4$, $\text{lvl}(\mathbf{L}_{\mathbf{d}}) = 3$, $\text{lvl}(\mathbf{L}_{\mathbf{e}}) = 2$, $\text{lvl}(\mathbf{L}_{\mathbf{f}}) = 3$ and $\text{lvl}(\mathbf{L}_{\mathbf{g}}) = 3$. -![Figure 6: An SMT of 7 key-value pairs](../../img/zkvm/fig6-mpt-gen-eg.png) +![Figure 6: An SMT of 7 key-value pairs](../../img/zkEVM/fig6-mpt-gen-eg.png) -As illustrated, keys basically determine the shape of the SMT. They dictate where respective leaves must be placed when building the SMT. +As illustrated, keys basically determine the shape of the SMT. They dictate where respective leaves must be placed when building the SMT. The main determining factor of the SMT shape is in fact the common key-bits among the keys. For instance, the reason why the leaves $\mathbf{L}_{\mathbf{b}}$ and $\mathbf{L}_{\mathbf{c}}$ have the largest leaf level $4$ is because the two leaves have the longest string of common key-bits "$010$" in the SMT of Figure 6 above. @@ -36,23 +36,23 @@ The **height of a Merkle Tree** refers to the largest number of edges traversed But this is not the case for SMTs. Since leaf levels differ from one leaf to another in SMTs, the height of an SMT is not the same as the leaf level. -Rather, the **height of an SMT** is defined as the largest leaf level among the various leaf levels of leaves on the SMT. For instance, **the height of the SMT** depicted in the figure above, is $4$. +Rather, the **height of an SMT** is defined as the largest leaf level among the various leaf levels of leaves on the SMT. For instance, **the height of the SMT** depicted in the figure above, is $4$. Now, since all keys have the same fixed key-length, they not only influence SMT leaf levels and shapes, but also restrict SMT heights to the fixed key-length. The maximum height of an SMT is the maximum key-length imposed on all keys. ### Remaining keys -In a general Sparse Merkle Tree (SMT), values are stored at their respective leaf-nodes. +In a general Sparse Merkle Tree (SMT), values are stored at their respective leaf-nodes. But a leaf node $\mathbf{L}_{\mathbf{x}}$ not only stores a value, $V_{\mathbf{x}}$, but also the key-bits that are left unused in the navigation from the root to $\mathbf{L}_{\mathbf{x}}$. These unused key-bits are called **the remaining key**, and are denoted by $\text{RK}_{\mathbf{x}}$ for the leaf node $\mathbf{L}_{\mathbf{x}}$. -Consider again the SMT of the 7 key-value pairs depicted in the figure above. The remaining keys of each of the 7 leaves in the SMT are as follows; +Consider again the SMT of the 7 key-value pairs depicted in the figure above. The remaining keys of each of the 7 leaves in the SMT are as follows; $\text{RK}_{\mathbf{a}} = 110101$, $\text{RK}_{\mathbf{b}} = 1001$, $\text{RK}_{\mathbf{c}} = 0001$, $\text{RK}_{\mathbf{d}} = 00111$, $\text{RK}_{\mathbf{e}} = 101111$, $\text{RK}_{\mathbf{f}} = 10001$ and $\text{RK}_{\mathbf{g}} = 11000$. ## Fake-leaf attack -Note that the above simplified design of binary SMTs, based on key-value pairs, presents some problems. The characteristic of binary SMTs having leaves at different levels can be problematic to verifiers, especially when carrying out a simple Merkle proof. +Note that the above simplified design of binary SMTs, based on key-value pairs, presents some problems. The characteristic of binary SMTs having leaves at different levels can be problematic to verifiers, especially when carrying out a simple Merkle proof. ### Scenario: Fake SMT leaf @@ -69,26 +69,26 @@ That is, the Attacker claims that some $V_{\mathbf{fk}}$ is stored at $\mathbf{L Verifier is unaware that $V_{\mathbf{fk}}$ is in fact the concatenated value of the hidden real leaves, $\mathbf{L_{a}}$ and $\mathbf{L_{b}}$, that are children of the *supposed* leaf $\mathbf{L_{fk}}$. i.e., Verifier does not know that leaf $\mathbf{L_{fk}}$ is in fact a branch. -![Figure 7: MPT - Fake Leaf Attack](../../img/zkvm/fig7-fake-leaf-eg.png) +![Figure 7: MPT - Fake Leaf Attack](../../img/zkEVM/fig7-fake-leaf-eg.png) -So then, the verifier being unaware that $\mathbf{L_{fk}}$ is not a properly constructed leaf, starts verification as follows; +So then, the verifier being unaware that $\mathbf{L_{fk}}$ is not a properly constructed leaf, starts verification as follows; 1. He uses the key $K_{\mathbf{fk}}$ to navigate the tree until locating the supposed leaf $\mathbf{L_{fk}}$. -2. He computes $\mathbf{H}(V_{\mathbf{fk}})$ and sets it as - $\tilde{\mathbf{L}}_{\mathbf{fk}} := \mathbf{H}(V_{\mathbf{fk}})$. +2. He computes $\mathbf{H}(V_{\mathbf{fk}})$ and sets it as + $\tilde{\mathbf{L}}_{\mathbf{fk}} := \mathbf{H}(V_{\mathbf{fk}})$. 3. Then takes the sibling $\mathbf{{S}_{\mathbf{cd}}}$ and calculates - $\tilde{ \mathbf{B}}_{\mathbf{fkcd}} = \mathbf{H} \big( \tilde{\mathbf{L}}_{\mathbf{fk}} \| \mathbf{S}_{\mathbf{cd}} \big)$. + $\tilde{ \mathbf{B}}_{\mathbf{fkcd}} = \mathbf{H} \big( \tilde{\mathbf{L}}_{\mathbf{fk}} \| \mathbf{S}_{\mathbf{cd}} \big)$. 4. And then, uses $\tilde{ \mathbf{B}}_{\mathbf{fkcd}}$ to compute the root, $\tilde{ \mathbf{root}}_{\mathbf{ab..f}} = \mathbf{H} \big( \tilde{ \mathbf{B}}_{\mathbf{fkcd}}\| \mathbf{S}_{\mathbf{ef}} \big)$. The question is: "Does the fake leaf $\mathbf{L_{fk}}$ pass the verifier's Merkle proof or not?" Or, equivalently: "Is $\tilde{ \mathbf{root}}_{\mathbf{ab..f}}$ equal to $\mathbf{root}_{\mathbf{ab..f}}$?" -Since the actual branch $\mathbf{{B}_{ab}}$ is by construction the hash, -$\mathbf{H}(\mathbf{L_{a}} \| \mathbf{L_{b}})$, then -$\mathbf{{B}_{ab}} = \tilde{\mathbf{L}}_{\mathbf{fk}}$. -The parent branch ${\mathbf{B}}_{\mathbf{abcd}}$ also, being constructed as the hash, -$\mathbf{H} \big( \mathbf{B}_{\mathbf{ab}}\| { \mathbf{S}}_{\mathbf{cd}} \big)$, should be equal to $\mathbf{H} \big( \tilde{\mathbf{L}}_{\mathbf{fk}} \| \mathbf{S}_{\mathbf{cd}} \big) = \tilde{ \mathbf{B}}_{\mathbf{fkcd}}$. As a result, $\mathbf{root}_{\mathbf{ab..f}} = \mathbf{H} \big( {\mathbf{B}}_{\mathbf{abcd}} \| \mathbf{S}_{\mathbf{ef}} \big) = \mathbf{H} \big( \tilde{ \mathbf{B}}_{\mathbf{fkcd}}\| \mathbf{S}_{\mathbf{ef}} \big) = \tilde{ \mathbf{root}}_{\mathbf{ab..f}}$. +Since the actual branch $\mathbf{{B}_{ab}}$ is by construction the hash, +$\mathbf{H}(\mathbf{L_{a}} \| \mathbf{L_{b}})$, then +$\mathbf{{B}_{ab}} = \tilde{\mathbf{L}}_{\mathbf{fk}}$. +The parent branch ${\mathbf{B}}_{\mathbf{abcd}}$ also, being constructed as the hash, +$\mathbf{H} \big( \mathbf{B}_{\mathbf{ab}}\| { \mathbf{S}}_{\mathbf{cd}} \big)$, should be equal to $\mathbf{H} \big( \tilde{\mathbf{L}}_{\mathbf{fk}} \| \mathbf{S}_{\mathbf{cd}} \big) = \tilde{ \mathbf{B}}_{\mathbf{fkcd}}$. As a result, $\mathbf{root}_{\mathbf{ab..f}} = \mathbf{H} \big( {\mathbf{B}}_{\mathbf{abcd}} \| \mathbf{S}_{\mathbf{ef}} \big) = \mathbf{H} \big( \tilde{ \mathbf{B}}_{\mathbf{fkcd}}\| \mathbf{S}_{\mathbf{ef}} \big) = \tilde{ \mathbf{root}}_{\mathbf{ab..f}}$. -Therefore, the fake leaf $\mathbf{L_{fk}}$ passes the Merkle proof. +Therefore, the fake leaf $\mathbf{L_{fk}}$ passes the Merkle proof. ### Solution to the Fake-leaf attack @@ -105,31 +105,31 @@ Reconsider now, the Scenario A, given above. Recall that the Attacker provides - The key-value $(K_{\mathbf{fk}}, V_\mathbf{{fk}})$, where $K_{\mathbf{fk}} = 11010100$ and $V_{\mathbf{fk}} = \mathbf{L_{a}} \| \mathbf{L_{b}}$. - The root $ \mathbf{{root}_{ab..f}}$ , the number of levels to root, and the siblings $\mathbf{{S}_{\mathbf{cd}}}$ and $\mathbf{{S}_{\mathbf{ef}}}$. -The verifier suspecting no foul, uses $K_{\mathbf{fk}} = 11010100$ to navigate the tree until he finds $V_{\mathbf{fk}}$ stored at $\mathbf{L_{fk}} := \mathbf{{B}_{ab}}$. +The verifier suspecting no foul, uses $K_{\mathbf{fk}} = 11010100$ to navigate the tree until he finds $V_{\mathbf{fk}}$ stored at $\mathbf{L_{fk}} := \mathbf{{B}_{ab}}$. -He subsequently starts the Merkle proof by hashing the value $\tilde{V}_{\mathbf{fk}}$ stored at the located leaf. Since, this computation amounts to forming a leaf, he uses the leaf-hash function, $\mathbf{H}_{\mathbf{leaf}}$. +He subsequently starts the Merkle proof by hashing the value $\tilde{V}_{\mathbf{fk}}$ stored at the located leaf. Since, this computation amounts to forming a leaf, he uses the leaf-hash function, $\mathbf{H}_{\mathbf{leaf}}$. - He then sets $\tilde{\mathbf{L}}_{\mathbf{fk}} := \mathbf{H}_{\mathbf{leaf}} \big( V_{\mathbf{fk}} \big) = \mathbf{H}_{\mathbf{leaf}} \big( \mathbf{L_{a}} \| \mathbf{L_{b}} \big)$. -- And further computes $\tilde{ \mathbf{B}}_{\mathbf{fkcd}} = \mathbf{H}_{\mathbf{noleaf}} \big( \tilde{\mathbf{L}}_{\mathbf{fk}} \| \mathbf{S}_{\mathbf{cd}} \big)$. +- And further computes $\tilde{ \mathbf{B}}_{\mathbf{fkcd}} = \mathbf{H}_{\mathbf{noleaf}} \big( \tilde{\mathbf{L}}_{\mathbf{fk}} \| \mathbf{S}_{\mathbf{cd}} \big)$. - Again, calculates the root, $\tilde{ \mathbf{root}}_{\mathbf{ab..f}} = \mathbf{H}_{\mathbf{noleaf}} \big( \tilde{ \mathbf{B}}_{\mathbf{fkcd}}\| \mathbf{S}_{\mathbf{ef}} \big)$. -But the actual branch $\mathbf{{B}_{ab}}$ was constructed with the no-leaf-hash function, +But the actual branch $\mathbf{{B}_{ab}}$ was constructed with the no-leaf-hash function, $\mathbf{H}_{\mathbf{noleaf}}$. That is, $$ \mathbf{{B}_{ab}} = \mathbf{H}_{\mathbf{noleaf}} (\mathbf{L_{a}} \| \mathbf{L_{b}}) \neq \mathbf{H}_{\mathbf{leaf}} \big(\mathbf{L_{a}} \| \mathbf{L_{b}} \big) = \tilde{\mathbf{L}}_{\mathbf{fk}}. $$ -The parent branch ${\mathbf{B}}_{\mathbf{abcd}}$ also, was constructed as, ${\mathbf{B}}_{\mathbf{abcd}} = \mathbf{H}_{\mathbf{noleaf}} \big(\mathbf{B}_{\mathbf{ab}}\| {\mathbf{S}}_{\mathbf{cd}}\big)$. -Since the hash functions used are collision-resistant, ${\mathbf{B}}_{\mathbf{abcd}}$ cannot be equal to $\mathbf{H}_{\mathbf{noleaf}} \big( \tilde{\mathbf{L}}_{\mathbf{fk}} \| \mathbf{S}_{\mathbf{cd}} \big) = \tilde{ \mathbf{B}}_{\mathbf{fkcd}}$. Consequently, $\mathbf{root}_{\mathbf{ab..f}} \neq \tilde{ \mathbf{root}}_{\mathbf{ab..f}}$. Therefore, the Merkle Proof fails. +The parent branch ${\mathbf{B}}_{\mathbf{abcd}}$ also, was constructed as, ${\mathbf{B}}_{\mathbf{abcd}} = \mathbf{H}_{\mathbf{noleaf}} \big(\mathbf{B}_{\mathbf{ab}}\| {\mathbf{S}}_{\mathbf{cd}}\big)$. +Since the hash functions used are collision-resistant, ${\mathbf{B}}_{\mathbf{abcd}}$ cannot be equal to $\mathbf{H}_{\mathbf{noleaf}} \big( \tilde{\mathbf{L}}_{\mathbf{fk}} \| \mathbf{S}_{\mathbf{cd}} \big) = \tilde{ \mathbf{B}}_{\mathbf{fkcd}}$. Consequently, $\mathbf{root}_{\mathbf{ab..f}} \neq \tilde{ \mathbf{root}}_{\mathbf{ab..f}}$. Therefore, the Merkle Proof fails. ## Non-binding key-value pairs -Whenever the verifier needs to check inclusion of the given key-value pair $(K_{\mathbf{x}}, \text{V}_{\mathbf{x}})$ in a binary SMT identified by the $\mathbf{{root}_{a..x}}$, he first navigates the SMT in order to locate the leaf $\mathbf{{L}_{x}}$ storing $\text{V}_{\mathbf{x}}$, and thereafter carries out two computations. +Whenever the verifier needs to check inclusion of the given key-value pair $(K_{\mathbf{x}}, \text{V}_{\mathbf{x}})$ in a binary SMT identified by the $\mathbf{{root}_{a..x}}$, he first navigates the SMT in order to locate the leaf $\mathbf{{L}_{x}}$ storing $\text{V}_{\mathbf{x}}$, and thereafter carries out two computations. Both computations involve climbing the tree from the located leaf $\mathbf{{L}_{x}}$ back to the root, $\mathbf{{root}_{a..x}}$. And the two computations are; -1. Checking **correctness of the key** $K_{\mathbf{x}}$. +1. Checking **correctness of the key** $K_{\mathbf{x}}$. That is, verifier takes the Remaining Key, $\text{RK}_{\mathbf{x}}$, and reconstructs the key $K_{\mathbf{x}}$ by concatenating the key bits used to navigate to $\mathbf{{L}_{x}}$ from $\mathbf{{root}_{a..x}}$, in the reverse order. @@ -143,11 +143,11 @@ Both computations involve climbing the tree from the located leaf $\mathbf{{L}_{ - Concatenates $\text{kb}_\mathbf{0}$ and gets $\text{ } \text{RK} \| \text{kb}_\mathbf{2} \| \text{kb}_\mathbf{1} \| \text{kb}_\mathbf{0}$. - He then sets $\tilde{K}_{\mathbf{x}} := \text{RK} \| \text{kb}_\mathbf{2} \| \text{kb}_\mathbf{1} \| \text{kb}_\mathbf{0}$, and checks if $\tilde{K}_{\mathbf{x}}$ equals $K_{\mathbf{x}}$. + He then sets $\tilde{K}_{\mathbf{x}} := \text{RK} \| \text{kb}_\mathbf{2} \| \text{kb}_\mathbf{1} \| \text{kb}_\mathbf{0}$, and checks if $\tilde{K}_{\mathbf{x}}$ equals $K_{\mathbf{x}}$. -2. **The Merkle proof**: That is, checking whether the value stored at the located leaf $\mathbf{{L}_{x}}$ was indeed included in computing the root, $\mathbf{{root}_{a..x}}$. +2. **The Merkle proof**: That is, checking whether the value stored at the located leaf $\mathbf{{L}_{x}}$ was indeed included in computing the root, $\mathbf{{root}_{a..x}}$. - This computation was illustrated several times in the above discussions. Note that the **key-correctness** and the Merkle proof are simultaneously carried out. + This computation was illustrated several times in the above discussions. Note that the **key-correctness** and the Merkle proof are simultaneously carried out. ### Example: Indistinguishable leaves @@ -159,22 +159,22 @@ An Attacker can pick the key-value pair $(K_{\mathbf{x}}, V_\mathbf{{x}})$ such Consider the below figure and suppose the Attacker provides the following data; -![Non-binding Key-Value Pairs](../../img/zkvm/fig8-non-binding-eg.png) +![Non-binding Key-Value Pairs](../../img/zkEVM/fig8-non-binding-eg.png) -- The key-value $(K_{\mathbf{x}}, V_\mathbf{{x}})$, where +- The key-value $(K_{\mathbf{x}}, V_\mathbf{{x}})$, where $K_{\mathbf{x}} = 10100110$ and $V_{\mathbf{x}} = V_\mathbf{d}$. -- The root, $\mathbf{{root}_{a..x}}$, the number of *levels to root* = 3, and the siblings - $\mathbf{{B}_{\mathbf{bc}}}$, $\mathbf{L_{a}}$ and $\mathbf{{S}_{\mathbf{efg}}}$. +- The root, $\mathbf{{root}_{a..x}}$, the number of *levels to root* = 3, and the siblings + $\mathbf{{B}_{\mathbf{bc}}}$, $\mathbf{L_{a}}$ and $\mathbf{{S}_{\mathbf{efg}}}$. The verifier uses the least-significant key bits; $\text{kb}_\mathbf{0} = 0$, $\text{kb}_\mathbf{1} = 1$ and $\text{kb}_\mathbf{2} = 1$; to navigate the tree and locate the leaf $\mathbf{L_{x}}$ which is positioned at $\mathbf{L_{d}}$. -In order to ensure that $\mathbf{L_{x}}$ actually stores the value $V_\mathbf{{x}}$; The verifier first checks key-correctness. He takes the remaining key $\text{RK} = 10100$ and, +In order to ensure that $\mathbf{L_{x}}$ actually stores the value $V_\mathbf{{x}}$; The verifier first checks key-correctness. He takes the remaining key $\text{RK} = 10100$ and, 1. Concatenates $\text{kb}_\mathbf{2} = 1$, and gets $\text{ } \text{RK} \| \text{kb}_\mathbf{2} = 10100 \|1$, 2. Concatenates $\text{kb}_\mathbf{1} = 0$ to get $\text{ } \text{RK} \| \text{kb}_\mathbf{2} \| \text{kb}_\mathbf{1} = 10100 \|1\|0$, -3. Concatenates $\text{kb}_\mathbf{0} = 0$, yielding $\text{ } \text{RK} \| \text{kb}_\mathbf{2} \| \text{kb}_\mathbf{1} \| \text{kb}_\mathbf{0} = 10100 \|1\|0\|0$. +3. Concatenates $\text{kb}_\mathbf{0} = 0$, yielding $\text{ } \text{RK} \| \text{kb}_\mathbf{2} \| \text{kb}_\mathbf{1} \| \text{kb}_\mathbf{0} = 10100 \|1\|0\|0$. He sets $\tilde{K}_{\mathbf{x}} := 10100 \|1\|0\|0 = 10100100$. Since $\tilde{K}_{\mathbf{x}}$ equals $K_{\mathbf{x}}$, the verifier concludes that the supplied key is correct. @@ -186,14 +186,14 @@ As the verifier **climbs** the tree to test key-correctness, he concurrently che - He also uses $\mathbf{L_{a}}$ to compute, $\tilde{\mathbf{B}}_{\mathbf{abcd}} = \mathbf{H_{noleaf}}(\mathbf{L_{a}} \| \tilde{\mathbf{B}}_{\mathbf{bcd}})$. -- He further calculates, $\tilde{\mathbf{root}}_{\mathbf{abcd}} = \mathbf{H_{noleaf}}(\tilde{\mathbf{B}}_{\mathbf{abcd}} \| \mathbf{{S}_{\mathbf{efg}}})$. +- He further calculates, $\tilde{\mathbf{root}}_{\mathbf{abcd}} = \mathbf{H_{noleaf}}(\tilde{\mathbf{B}}_{\mathbf{abcd}} \| \mathbf{{S}_{\mathbf{efg}}})$. Next, the verifier checks if $\tilde{\mathbf{root}}_{\mathbf{abcd}}$ equals $\mathbf{root}_{\mathbf{abcd}}$. Since $V_\mathbf{{x}} = V_\mathbf{{d}}$, it follows that all the corresponding intermediate values to the root are equal; -- $\mathbf{L_{d}} = \mathbf{H_{leaf}}(V_\mathbf{{d}}) = \mathbf{H_{leaf}}(V_\mathbf{{x}}) = \tilde{\mathbf{L}}_\mathbf{x}$, -- $\mathbf{B}_{\mathbf{bcd}} = \mathbf{H_{noleaf}}(\mathbf{{B}_{\mathbf{bc}}} \| \mathbf{L}_\mathbf{d}) = \mathbf{H_{noleaf}}(\mathbf{{B}_{\mathbf{bc}}} \|\tilde{\mathbf{L}}_\mathbf{x}) = \tilde{\mathbf{B}}_{\mathbf{bcd}}$, +- $\mathbf{L_{d}} = \mathbf{H_{leaf}}(V_\mathbf{{d}}) = \mathbf{H_{leaf}}(V_\mathbf{{x}}) = \tilde{\mathbf{L}}_\mathbf{x}$, +- $\mathbf{B}_{\mathbf{bcd}} = \mathbf{H_{noleaf}}(\mathbf{{B}_{\mathbf{bc}}} \| \mathbf{L}_\mathbf{d}) = \mathbf{H_{noleaf}}(\mathbf{{B}_{\mathbf{bc}}} \|\tilde{\mathbf{L}}_\mathbf{x}) = \tilde{\mathbf{B}}_{\mathbf{bcd}}$, - $\mathbf{B}_{\mathbf{abcd}} = \mathbf{H_{noleaf}}(\mathbf{L_{a}} \| \mathbf{B}_{\mathbf{bcd}} ) = \mathbf{H_{noleaf}}(\mathbf{L_{a}} \| \tilde{\mathbf{B}}_{\mathbf{bcd}} ) = \tilde{\mathbf{B}}_{\mathbf{abcd}}$, - $\mathbf{root}_{\mathbf{abcd}} = \mathbf{H_{noleaf}}(\mathbf{B}_{\mathbf{abcd}} \| \mathbf{{S}_{\mathbf{efg}}} ) = \mathbf{H_{noleaf}}(\tilde{\mathbf{B}}_{\mathbf{abcd}} \| \mathbf{{S}_{\mathbf{efg}}} ) = \tilde{\mathbf{root}}_{\mathbf{abcd}}$. @@ -236,10 +236,10 @@ $$ Consequently, although the key-value pairs $(K_{\mathbf{x}}, V_\mathbf{{x}})$ and $(K_{\mathbf{z}}, V_\mathbf{{z}})$ might falsely pass the key-correctness check, they will not pass the Merkle proof test. And this is because, collision-resistance also guarantees that the following series of inequalities hold true; $$ -\mathbf{L_{x}} = \mathbf{H_{leaf}}(K_{\mathbf{x}} \| V_\mathbf{{x}}) \neq \mathbf{H_{leaf}}(K_{\mathbf{z}} \| V_\mathbf{{z}}) = \mathbf{L_{z}} \\ -\\ -\mathbf{B_{bx}} = \mathbf{H_{noleaf}}(\mathbf{S}_\mathbf{{b}} \| \mathbf{L}_{\mathbf{x}}) \neq \mathbf{H_{noleaf}}(\mathbf{S}'_\mathbf{{b}} \| \mathbf{L}_{\mathbf{z}}) = \mathbf{B_{bz}} \\ -\\ +\mathbf{L_{x}} = \mathbf{H_{leaf}}(K_{\mathbf{x}} \| V_\mathbf{{x}}) \neq \mathbf{H_{leaf}}(K_{\mathbf{z}} \| V_\mathbf{{z}}) = \mathbf{L_{z}} \\ +\\ +\mathbf{B_{bx}} = \mathbf{H_{noleaf}}(\mathbf{S}_\mathbf{{b}} \| \mathbf{L}_{\mathbf{x}}) \neq \mathbf{H_{noleaf}}(\mathbf{S}'_\mathbf{{b}} \| \mathbf{L}_{\mathbf{z}}) = \mathbf{B_{bz}} \\ +\\ \mathbf{B_{abx}} = \mathbf{H_{noleaf}}(\mathbf{S}_\mathbf{{a}} \| \mathbf{B_{bx}} ) \neq \mathbf{H_{noleaf}}(\mathbf{S}'_\mathbf{{a}} \| \mathbf{B_{bz}}) = \mathbf{B_{abz}} $$ @@ -261,9 +261,9 @@ $$ \mathbf{L_{x}} = \mathbf{H_{leaf}}( \text{RK}_\mathbf{x} \| \text{V}_\mathbf{{x}}). $$ -With this strategy, the verifier needs the remaining key $\text{RK}_\mathbf{{x}}$ , instead of the whole key, in order to carry out a Merkle proof. So he adjusts the Merkle proof by; +With this strategy, the verifier needs the remaining key $\text{RK}_\mathbf{{x}}$ , instead of the whole key, in order to carry out a Merkle proof. So he adjusts the Merkle proof by; -- Firstly, picking the correct hash function $\mathbf{H_{leaf}}$ for leaves, +- Firstly, picking the correct hash function $\mathbf{H_{leaf}}$ for leaves, - Secondly, concatenating the value $V_{\mathbf{x}}$ stored at the leaf $L_{\mathbf{x}}$ and the remaining key $\text{RK}_\mathbf{{x}}$, instead of the whole key $K_{\mathbf{x}}$, - Thirdly, hashing the concatenation $\mathbf{H_{leaf}}( \text{RK}_\mathbf{x} \| \text{V}_\mathbf{{x}}) =: \mathbf{L_{x}}$. @@ -274,7 +274,7 @@ The strategy of using the $\text{RK}_\mathbf{x}$ instead of the key $K_{\mathbf{ ## Hiding values It is often necessary to ensure that a commitment scheme has the hiding property. -And this can be achieved by storing hashes of values, as opposed to plainly storing the values. +And this can be achieved by storing hashes of values, as opposed to plainly storing the values. A leaf therefore is henceforth constructed in two steps; @@ -292,7 +292,7 @@ Since it is infeasible to compute the preimage of the hash functions, $\mathbf{H The prover therefore achieves zero-knowledge by providing the pair, $(K_{\mathbf{x}}, \text{HV}_\mathbf{{x}})$, as the key-value pair instead of the explicit one, $(K_{\mathbf{x}}, V_\mathbf{{x}})$. -The verifier, on the other hand, has to adjust the Merkle proof by starting with; +The verifier, on the other hand, has to adjust the Merkle proof by starting with; - Firstly, picking the correct hash function $\mathbf{H_{leaf}}$ for leaf nodes, - Secondly, concatenating the hashed-value $\text{HV}_\mathbf{{x}}$ and the remaining key $\text{RK}_\mathbf{{x}}$, @@ -304,7 +304,7 @@ The following example illustrates a Merkle proof when the above strategy is appl Consider an SMT where the keys are 8-bit long, and the prover commits to the key-value $( K_{\mathbf{c}} , \text{HV}_{\mathbf{c}} )$ with $K_{\mathbf{c}} = 10010100$. See figure below. -![ZK Merkle Proof Example](../../img/zkvm/fig9-zk-mkl-prf.png) +![ZK Merkle Proof Example](../../img/zkEVM/fig9-zk-mkl-prf.png) Since the levels to root is 3, the prover provides; the least-significant key-bits, $\text{kb}_0 = 0$, $\text{kb}_1 = 0$, $\text{kb}_2 = 1$, the stored hashed-value $\text{HV}_{\mathbf{c}}$, the root $\mathbf{{root}_{a..f}}$, the Remaining Key $\mathbf{ \text{RK}_{\mathbf{c}}} = 10010$, and the siblings $\mathbf{{S}_{ab}}$, $\mathbf{{L}_{d}}$ and $\mathbf{{S}_{\mathbf{ef}}}$. @@ -320,4 +320,4 @@ The verifier first uses the least-significant bits of the key $K_{\mathbf{c}} = 5. Checks if $\tilde{ \mathbf{root}}_{\mathbf{ab..f}}$ equals ${ \mathbf{root}}_{\mathbf{ab..f}}$. -The verifier accepts that the key-value pair $( K_{\mathbf{c}} , V_{\mathbf{c}} )$ is in the SMT only if $\tilde{ \mathbf{root}}_{\mathbf{ab..f}} = { \mathbf{root}}_{\mathbf{ab..f}}$. And he does this without any clue about the exact value $V_{\mathbf{c}}$ which is hidden as $\text{HV}_{\mathbf{c}}$. \ No newline at end of file +The verifier accepts that the key-value pair $( K_{\mathbf{c}} , V_{\mathbf{c}} )$ is in the SMT only if $\tilde{ \mathbf{root}}_{\mathbf{ab..f}} = { \mathbf{root}}_{\mathbf{ab..f}}$. And he does this without any clue about the exact value $V_{\mathbf{c}}$ which is hidden as $\text{HV}_{\mathbf{c}}$. diff --git a/docs/zkEVM/concepts/ending-program.md b/docs/zkEVM/concepts/ending-program.md index 086cfd3f2..9bc4f9155 100644 --- a/docs/zkEVM/concepts/ending-program.md +++ b/docs/zkEVM/concepts/ending-program.md @@ -2,7 +2,7 @@ Before looking at ways to properly end a program, let us first make a few remarks on how to handle negative numbers. -Recall that all values of the execution trace belong to a field $\mathbb{F}_p$ where $p=2^{64} −2^{32} +1$. +Recall that all values of the execution trace belong to a field $\mathbb{F}_p$ where $p=2^{64} −2^{32} +1$. Since $\mathtt{(p-x) + x \equiv p \texttt{ modulo } p}$ for all $\mathtt{x \in \mathbb{F}_p }$ and $\mathtt{p \equiv 0 \texttt{ modulo } p}$, it follows that $\mathtt{-x \equiv p-x \texttt{ modulo } p}$. Any negative number $\mathtt{-a}$ is therefore interpreted as $\mathtt{p − a}$. @@ -21,8 +21,8 @@ $$ \end{array} \hspace{0.1cm} -\begin{array}{|l|c|c|c|c|c|c|c|}\hline - \texttt{FREE} & \texttt{CONST}& \texttt{setB}& \mathtt{setA}& \texttt{inFREE}& \mathtt{inB} & \mathtt{inA} \\ \hline +\begin{array}{|l|c|c|c|c|c|c|c|}\hline + \texttt{FREE} & \texttt{CONST}& \texttt{setB}& \mathtt{setA}& \texttt{inFREE}& \mathtt{inB} & \mathtt{inA} \\ \hline \texttt{7} & \texttt{0} & \texttt{0} & \texttt{1} & \texttt{1} & \texttt{0} & \texttt{0} \\ \hline \texttt{0} & \texttt{p-3} & \texttt{1} & \texttt{0} & \texttt{0} & \texttt{0} & \texttt{0} \\ \hline @@ -64,8 +64,8 @@ $$ \end{array} \hspace{0.1cm} -\begin{array}{|l|c|c|c|c|c|c|c|}\hline - \texttt{FREE} & \texttt{CONST}& \texttt{setB}& \mathtt{setA}& \texttt{inFREE}& \mathtt{inB} & \mathtt{inA} \\ \hline +\begin{array}{|l|c|c|c|c|c|c|c|}\hline + \texttt{FREE} & \texttt{CONST}& \texttt{setB}& \mathtt{setA}& \texttt{inFREE}& \mathtt{inB} & \mathtt{inA} \\ \hline \texttt{7} & \texttt{0} & \texttt{0} & \texttt{1} & \texttt{1} & \texttt{0} & \texttt{0} \\ \hline \texttt{0} & \texttt{3} & \texttt{1} & \texttt{0} & \texttt{0} & \texttt{0} & \texttt{0} \\ \hline @@ -113,8 +113,8 @@ $$ \end{array} \hspace{0.1cm} -\begin{array}{|l|c|c|c|c|c|c|c|}\hline - \texttt{FREE} & \texttt{CONST}& \texttt{setB}& \mathtt{setA}& \texttt{inFREE}& \mathtt{inB} & \mathtt{inA} \\ \hline +\begin{array}{|l|c|c|c|c|c|c|c|}\hline + \texttt{FREE} & \texttt{CONST}& \texttt{setB}& \mathtt{setA}& \texttt{inFREE}& \mathtt{inB} & \mathtt{inA} \\ \hline \texttt{7} & \texttt{0} & \texttt{0} & \texttt{1} & \texttt{1} & \texttt{0} & \texttt{0} \\ \hline \texttt{0} & \texttt{3} & \texttt{1} & \texttt{0} & \texttt{0} & \texttt{0} & \texttt{0} \\ \hline \texttt{0} & \texttt{0} & \texttt{0} & \texttt{1} & \texttt{0} & \texttt{1} & \texttt{1} \\ \hline @@ -151,14 +151,14 @@ Since this instruction needs to specify the destination of the jump, we need to $$ \begin{aligned} \begin{array}{|l|c|} -\hline +\hline \texttt{ line } & \bf{Instructions } \text{ }\text{ }\text{ }\text{ } \\ \hline \quad\texttt{ 0 } & \text{ }\mathtt{\$\{getAFreeInput()\} => A} \text{ }\\ \hline \quad\texttt{ 1 } & \text{ }\mathtt{-3 => B} \qquad\qquad\qquad\quad\quad \\ \hline \quad\texttt{ 2 } & \text{ }\mathtt{:ADD } \qquad\qquad\qquad\quad\quad\quad\text{ }\text{ } \\ \hline \quad\texttt{ 3 } & \text{ }\mathtt{A : JMPZ(5) } \quad\qquad\quad\quad\quad\text{ }\text{ } \\ \hline \quad\texttt{ 4 } & \text{ }\mathtt{:ADD } \qquad\qquad\qquad\quad\quad\quad\text{ }\text{ } \\ \hline -\quad\texttt{ 5 } & \text{ }\mathtt{:END } \qquad\qquad\qquad\quad\qquad\text{}\text{ }\text{ } \\ \hline +\quad\texttt{ 5 } & \text{ }\mathtt{:END } \qquad\qquad\qquad\quad\qquad\text{}\text{ }\text{ } \\ \hline \end{array} \end{aligned} $$ @@ -167,9 +167,9 @@ With regards to the instruction "$\texttt{A:JMPZ(5)}$" in $\texttt{line}$ $\text 1. The $\texttt{A}$ registry, preceding the colon, means that $\texttt{op}$ is set to the value of $\texttt{A}$. -2. If $\texttt{op = 0}$, the program jumps to $\texttt{line}$ $\texttt{5}$. +2. If $\texttt{op = 0}$, the program jumps to $\texttt{line}$ $\texttt{5}$. -3. If $\mathtt{op \not= 0}$, the program continues sequentially with the instruction at $\texttt{line}$ $\texttt{4}$. +3. If $\mathtt{op \not= 0}$, the program continues sequentially with the instruction at $\texttt{line}$ $\texttt{4}$. ## Conditional jumps examples @@ -184,14 +184,14 @@ In this example, the free input is $\mathtt{FREE = 7}$. Focusing on $\texttt{lin $$ \begin{aligned} \begin{array}{|l|c|} -\hline +\hline \texttt{ line } & \bf{Instructions } \text{ }\text{ }\text{ }\text{ } \\ \hline \quad\texttt{ 0 } & \text{ }\mathtt{\$\{getAFreeInput()\} => A} \text{ }\\ \hline \quad\texttt{ 1 } & \text{ }\mathtt{-3 => B} \qquad\qquad\qquad\quad\quad \\ \hline \quad\texttt{ 2 } & \text{ }\mathtt{:ADD } \qquad\qquad\qquad\quad\quad\quad\text{ }\text{ } \\ \hline \quad\texttt{ 3 } & \text{ }\mathtt{A : JMPZ(5) } \quad\qquad\quad\quad\quad\text{ }\text{ } \\ \hline \quad\texttt{ 4 } & \text{ }\mathtt{:ADD } \qquad\qquad\qquad\quad\quad\quad\text{ }\text{ } \\ \hline -\quad\texttt{ 5 } & \text{ }\mathtt{:END } \qquad\qquad\qquad\quad\qquad\text{}\text{ }\text{ } \\ \hline +\quad\texttt{ 5 } & \text{ }\mathtt{:END } \qquad\qquad\qquad\quad\qquad\text{}\text{ }\text{ } \\ \hline \end{array} \hspace{0.1cm} @@ -215,13 +215,13 @@ In this case, the free input is $\mathtt{FREE = 3}$. Again, focusing on $\texttt $$ \begin{aligned} \begin{array}{|l|c|} -\hline +\hline \texttt{ line } & \bf{Instructions } \text{ }\text{ }\text{ }\text{ } \\ \hline \quad\texttt{ 0 } & \text{ }\mathtt{\$\{getAFreeInput()\} => A} \text{ }\\ \hline \quad\texttt{ 1 } & \text{ }\mathtt{-3 => B} \qquad\qquad\qquad\quad\quad \\ \hline \quad\texttt{ 2 } & \text{ }\mathtt{:ADD } \qquad\qquad\qquad\quad\quad\quad\text{ }\text{ } \\ \hline \quad\texttt{ 3 } & \text{ }\mathtt{A : JMPZ(5) } \quad\qquad\quad\quad\quad\text{ }\text{ } \\ \hline -\quad\texttt{ 5 } & \text{ }\mathtt{:END } \qquad\qquad\qquad\quad\qquad\text{}\text{ }\text{ } \\ \hline +\quad\texttt{ 5 } & \text{ }\mathtt{:END } \qquad\qquad\qquad\quad\qquad\text{}\text{ }\text{ } \\ \hline \end{array} \hspace{0.1cm} @@ -258,7 +258,7 @@ Since the instructions require the executor to perform varied operations, and du 3. **Check correct program ending** - How the program ends also needs to be managed. Due to the presence of jumps, the length of the execution trace is no longer constant for the same program if the free inputs are varied. + How the program ends also needs to be managed. Due to the presence of jumps, the length of the execution trace is no longer constant for the same program if the free inputs are varied. 4. **Check positioning of Publics** diff --git a/docs/zkEVM/concepts/evm-basics.md b/docs/zkEVM/concepts/evm-basics.md index fb8bb778e..f18847940 100644 --- a/docs/zkEVM/concepts/evm-basics.md +++ b/docs/zkEVM/concepts/evm-basics.md @@ -10,13 +10,13 @@ keywords: - ethereum virtual machine --- -In this series of documents, we will dig deeper into the Main State Machine Executor component of the zkProver. It is one of the four main components of the zkProver, outlined [here](../zkprover/zkprover-overview.md). These are - **Executor**, **STARK Recursion**, **CIRCOM**, and **Rapid SNARK**. +In this series of documents, we will dig deeper into the Main State Machine Executor component of the zkProver. It is one of the four main components of the zkProver, outlined [here](../architecture/zkprover/zkprover-overview.md). These are - **Executor**, **STARK Recursion**, **CIRCOM**, and **Rapid SNARK**. Since the design of the zkProver emulates that of the EVM, this document focuses on explaining the basics of **Ethereum Virtual Machine** (EVM). ## Overview of Polygon zkEVM -**Polygon zkEVM is an L2 network that implements a special instance of the Ethereum Virtual Machine (EVM)**. It emulates the EVM in that the zkProver, which is core to proving and verifying computation correctness, is also designed as a state machine or a cluster of state machines. +**Polygon zkEVM is an L2 network that implements a special instance of the Ethereum Virtual Machine (EVM)**. It emulates the EVM in that the zkProver, which is core to proving and verifying computation correctness, is also designed as a state machine or a cluster of state machines. The terms **state machine** and **virtual machine** are used interchangeably in this documentation. @@ -36,7 +36,7 @@ The EVM is categorized as a **quasi–Turing-complete state machine** because it At any given point in time, the current state of the Ethereum blockchain is defined by a collection of the blockchain data. An Ethereum state therefore includes **account balances**, **smart contract code**, **smart contract storage**, and other information relevant to the operation of the network. -Since Ethereum is a distributed digital ledger, its state is maintained by each of the network's full-nodes. +Since Ethereum is a distributed digital ledger, its state is maintained by each of the network's full-nodes. ## Key features of EVM @@ -52,13 +52,13 @@ In terms of how it operates, the EVM is described as; **deterministic**, **sandb The EVM is made up of several components that work together to execute smart contracts on the Ethereum blockchain and provide the above-mentioned features. -![EVM Components Involved in the Processing of a Transaction](../../img/zkvm/01msm-evm-components.png) +![EVM Components Involved in the Processing of a Transaction](../../img/zkEVM/01msm-evm-components.png) The main components of the EVM involved in the processing of a transaction are: -1. **Smart contract bytecode**, which is the low-level code executed by the EVM. +1. **Smart contract bytecode**, which is the low-level code executed by the EVM. - Each bytecode is a sequence of opcodes (machine-level instructions). And each opcode in an EVM bytecode corresponds to a specific operation, such as arithmetic, conditional branching or memory manipulation. The EVM executes bytecode in a step-by-step fashion, with each opcode being processed in a given sequence. + Each bytecode is a sequence of opcodes (machine-level instructions). And each opcode in an EVM bytecode corresponds to a specific operation, such as arithmetic, conditional branching or memory manipulation. The EVM executes bytecode in a step-by-step fashion, with each opcode being processed in a given sequence. In general, smart contracts are written in a high-level programming language, such as [Solidity](https://docs.soliditylang.org/en/v0.8.20/) or [Vyper](https://docs.vyperlang.org/en/stable/), and then compiled into an EVM bytecode. @@ -86,7 +86,7 @@ The EVM is a variant of the [**Von Neumann architecture**](https://en.wikipedia. ### EVM Computational Costs -The EVM has its own instruction set or list of available **opcodes**, which is a set of low-level commands used to manipulate data in the Stack, Memory and Storage components. +The EVM has its own instruction set or list of available **opcodes**, which is a set of low-level commands used to manipulate data in the Stack, Memory and Storage components. The instruction set includes operations such as Arithmetic, Bit manipulation and Control flow. @@ -128,7 +128,7 @@ If a contract attempts to `PUSH` more elements onto the Stack, exceeding the $10 ## Memory -The EVM Memory is used for storing large data structures, such as arrays and strings. It is a linear array of bytes used by smart contracts to store and retrieve data. The size of the memory is dynamically allocated at runtime, meaning that the amount of memory available to a smart contract can grow depending on its needs. +The EVM Memory is used for storing large data structures, such as arrays and strings. It is a linear array of bytes used by smart contracts to store and retrieve data. The size of the memory is dynamically allocated at runtime, meaning that the amount of memory available to a smart contract can grow depending on its needs. EVM Memory is byte-addressable, which means that each byte in the memory can be individually addressed using a unique index. @@ -144,7 +144,7 @@ It’s also worth noting that, since accessing and modifying EVM Memory consumes - The parent contract’s memory space is saved, and the new contract’s memory space is initialized. The new contract can then make use of its memory as needed. -- When the called contract’s execution is completed, the memory space is released and the parent contract’s saved memory is restored. +- When the called contract’s execution is completed, the memory space is released and the parent contract’s saved memory is restored. It is worth noting that if a smart contract does not actually use the memory it has been allocated, that memory cannot be reclaimed or reused in the execution context of another contract. @@ -164,7 +164,7 @@ The opcodes related to memory are as follows: Accessing and modifying storage is a relatively expensive operation in terms of gas costs. EVM storage is implemented as a modified version of the **Merkle Patricia Tree** data structure, which allows for efficient access and modification of the storage data. -A **Patricia Tree** is a specific type of a trie designed to be more space-efficient than a standard trie, by storing only the unique parts of the keys in the tree. Patricia Trees are particularly useful in scenarios where keys share common prefixes, as they allow for more efficient use of memory and faster lookups compared to standard tries. +A **Patricia Tree** is a specific type of a trie designed to be more space-efficient than a standard trie, by storing only the unique parts of the keys in the tree. Patricia Trees are particularly useful in scenarios where keys share common prefixes, as they allow for more efficient use of memory and faster lookups compared to standard tries. The following opcodes are used to manipulate the storage of a smart contract: @@ -188,25 +188,25 @@ Transactions are decoded so as to obtain relevant information such as; the recip ### Signature Verification -Every transaction is digitally signed with a signature, which is generated using the **Elliptic Curve Digital Signature Algorithm (ECDSA)**. +Every transaction is digitally signed with a signature, which is generated using the **Elliptic Curve Digital Signature Algorithm (ECDSA)**. The ECDSA signature is represented by three (3) values, generally denoted as $\texttt{r}, \texttt{s}, \texttt{v}$. -Since the signature, or in particular the triplet $(\texttt{r}, \texttt{s}, \texttt{v})$, was computed from the secret key which is uniquely associated with the address of the Ethereum account (being debited), the three values $(\texttt{r}, \texttt{s}, \texttt{v})$ are sufficient to accurately verify that the transaction has been signed by the owner of the Ethereum account. +Since the signature, or in particular the triplet $(\texttt{r}, \texttt{s}, \texttt{v})$, was computed from the secret key which is uniquely associated with the address of the Ethereum account (being debited), the three values $(\texttt{r}, \texttt{s}, \texttt{v})$ are sufficient to accurately verify that the transaction has been signed by the owner of the Ethereum account. The Ethereum account is identified by a 20-byte (160-bit) address. The address is derived from the public key associated with the Ethereum account. It is in fact the last 20 bytes of the 256-bit Keccak hash of the public key. ### Processing A Transaction -The EVM begins by creating a context with an empty stack and memory space. +The EVM begins by creating a context with an empty stack and memory space. The bytecode instructions are then executed. The execution involves values being pushed and popped onto and from the Stack as required. -EVM uses a Program Counter to keep track of which instruction to execute next. Each opcode has a fixed number of bytes, so the Program Counter increments by the appropriate number of bytes after each instruction is executed. +EVM uses a Program Counter to keep track of which instruction to execute next. Each opcode has a fixed number of bytes, so the Program Counter increments by the appropriate number of bytes after each instruction is executed. ### Stack Elements And Word Size -Stack elements are 32 bytes in size. This means each value pushed onto the Stack by an opcode, as well as each value popped off the Stack by an opcode, are each 32 bytes in size. +Stack elements are 32 bytes in size. This means each value pushed onto the Stack by an opcode, as well as each value popped off the Stack by an opcode, are each 32 bytes in size. The 32-byte size limit for Stack elements is a fundamental design choice in Ethereum, and is purely based on the size of the **EVM word**. The **EVM word is the basic unit of storage and processing in the EVM, defined as a 256-bit (32-byte) unsigned integer**. Since the EVM word is the smallest unit of data that can be processed by the EVM, the stack elements are conveniently set to be of the same size. @@ -235,8 +235,8 @@ Some of the most commonly used opcodes include: ## References -The [Ethereum yellow paper](https://ethereum.github.io/yellowpaper/paper.pdf) entails technical details on the Ethereum with some of the opcodes listed and described on Pages 30 to 38. +The [Ethereum yellow paper](https://ethereum.github.io/yellowpaper/paper.pdf) entails technical details on the Ethereum with some of the opcodes listed and described on Pages 30 to 38. -A more elaborate exposition of the Ethereum Blockchain is provided in the book [Mastering Ethereum](https://github.com/ethereumbook/ethereumbook) by Andreas M. Antonopoulos and Gavin Wood. +A more elaborate exposition of the Ethereum Blockchain is provided in the book [Mastering Ethereum](https://github.com/ethereumbook/ethereumbook) by Andreas M. Antonopoulos and Gavin Wood. The shortest and less technical paper on Ethereum is [Beigepaper: An Ethereum Technical Specification](https://github.com/chronaeon/beigepaper/blob/master/beigepaper.pdf) by Micah Dameron. diff --git a/docs/zkEVM/concepts/exec-trace-correct.md b/docs/zkEVM/concepts/exec-trace-correct.md index 09510f55d..c294bc20c 100644 --- a/docs/zkEVM/concepts/exec-trace-correct.md +++ b/docs/zkEVM/concepts/exec-trace-correct.md @@ -10,7 +10,7 @@ Since these arithmetic constraints govern state transitions, they express the ne We therefore need auxiliary columns for **selectors**. Like switches that can either be ON or OFF, selectors too can either have a value $\mathtt{1}$ or $\mathtt{0}$, depending on the instruction being executed. -In continuing with the previous example of a four-instruction state machine, +In continuing with the previous example of a four-instruction state machine, - We use selectors; $\texttt{inFREE}$, $\texttt{inA}$, $\texttt{inB}$, $\texttt{setA}$ and $\texttt{setB}$; corresponding to the columns; $\texttt{FREE}$, $\texttt{A}$, $\texttt{B}$, $\mathtt{A'}$ and $\mathtt{B'}$, respectively. @@ -23,61 +23,61 @@ In continuing with the previous example of a four-instruction state machine, The **arithmetic constraints** are therefore defined by the following linear combinations; $$ -\mathtt{A′ = A + setA \cdot \big( inA \cdot A + inB \cdot B + inFREE \cdot FREE + CONST - A \big)} \\ +\mathtt{A′ = A + setA \cdot \big( inA \cdot A + inB \cdot B + inFREE \cdot FREE + CONST - A \big)} \\ \mathtt{B′ = B + setB \cdot \big( inA \cdot A + inB \cdot B + inFREE \cdot FREE + CONST - B \big)} \\ \tag{Eqn 1} $$ The figure below depicts the linear combinations of our state machine as an algebraic processor of sorts. -![The Generic State Machine as an Algebraic Processor](../../img/zkvm/gen4-sm-alg-processor.png) +![The Generic State Machine as an Algebraic Processor](../../img/zkEVM/gen4-sm-alg-processor.png) -The vertical gray box (with the "+" sign) in the above figure denotes addition. It expresses forming linear combinations of some of the columns; $\texttt{FREE}$, $\texttt{A}$, $\texttt{B}$, or $\texttt{CONST}$. Each is either included or excluded from the linear combination depending on whether their corresponding selectors have the value $\mathtt{1}$ or $\mathtt{0}$. An extra register denoted by $\texttt{op}$ acts as a carrier of intermediate of the computation being executed and waiting to be placed in the correct output register (on the right in above figure), depending on the values of $\texttt{setA}$ and $\texttt{setB}$. +The vertical gray box (with the "+" sign) in the above figure denotes addition. It expresses forming linear combinations of some of the columns; $\texttt{FREE}$, $\texttt{A}$, $\texttt{B}$, or $\texttt{CONST}$. Each is either included or excluded from the linear combination depending on whether their corresponding selectors have the value $\mathtt{1}$ or $\mathtt{0}$. An extra register denoted by $\texttt{op}$ acts as a carrier of intermediate of the computation being executed and waiting to be placed in the correct output register (on the right in above figure), depending on the values of $\texttt{setA}$ and $\texttt{setB}$. ## Testing Arithmetic Constraints We now test if the arithmetic constraints tally with each of the four instructions of our program. -1. **The first instruction: "$\mathtt{\$\{getAFreeInput()\} => A}$"** +1. **The first instruction: "$\mathtt{\$\{getAFreeInput()\} => A}$"** The first instruction involves a free input $7$ and this free input is moved into registry $\texttt{A}$, as its the next value. Therefore, by definition of the selectors, $\mathtt{inFREE = 1}$ and $\mathtt{setA = 1}$. Also, the value of the other selectors is $\texttt{0}$. Substituting these values in the above arithmetic constraints yields; $$ - \mathtt{A′ = A + 1 \cdot \big( 0 \cdot A + 0 \cdot B + 1 \cdot 7 + 0 - A \big) = A + (7 - A) = 7}\text{ } \\ + \mathtt{A′ = A + 1 \cdot \big( 0 \cdot A + 0 \cdot B + 1 \cdot 7 + 0 - A \big) = A + (7 - A) = 7}\text{ } \\ \mathtt{B′ = B + 0 \cdot \big( 0 \cdot A + 0 \cdot B + 1 \cdot 7 + 0 - B \big) = B}\qquad\qquad\qquad \\ $$ This illustrates that the value of the free input was moved into $\texttt{A}$, while $\texttt{B}$ remains unaltered. Hence, the first instruction was correctly executed. -2. **The second instruction: "$\mathtt{3 => B}$"** +2. **The second instruction: "$\mathtt{3 => B}$"** The second instruction involves the $\mathtt{CONST}$ column, and the constant value $\texttt{3}$ is moved into registry $\texttt{B}$, as its next value. Consequently, $\mathtt{CONST = 3}$ and $\mathtt{setB = 1}$. All other selectors have the value $\texttt{0}$. Again, substituting these values in the arithmetic constraints yields; $$ - \mathtt{A′ = A + 0 \cdot \big( 0 \cdot A + 0 \cdot B + 0 \cdot FREE + 3 - A \big) = A}\qquad\qquad\qquad \\ + \mathtt{A′ = A + 0 \cdot \big( 0 \cdot A + 0 \cdot B + 0 \cdot FREE + 3 - A \big) = A}\qquad\qquad\qquad \\ \mathtt{B′ = B + 1 \cdot \big( 0 \cdot A + 0 \cdot B + 0 \cdot FREE + 3 - B \big) = B + (3 - B) = 3} \\ $$ This shows that the value of $\texttt{A}$ was not changed, but the constant value $\mathtt{3}$ was moved into $\texttt{B}$. And thus, the second instruction was correctly executed. -3. **The third instruction, "$\mathtt{:ADD }$"** +3. **The third instruction, "$\mathtt{:ADD }$"** This instruction involves the registries $\texttt{A}$ and $\texttt{B}$, and the result is moved into registry $\texttt{A}$, as its the next value. This means, the values of the corresponding selectors are as follows; $\mathtt{inA = 1}$, $\mathtt{inB = 1}$ and $\mathtt{setA = 1}$. The arithmetic constraints become; $$ - \mathtt{A′ = A + 1 \cdot \big( 1 \cdot A + 1 \cdot B + 0 \cdot FREE + 0 - A \big) = A + (A + B - A) = A + B}\text{ } \\ + \mathtt{A′ = A + 1 \cdot \big( 1 \cdot A + 1 \cdot B + 0 \cdot FREE + 0 - A \big) = A + (A + B - A) = A + B}\text{ } \\ \mathtt{B′ = B + 0 \cdot \big( 1 \cdot A + 1 \cdot B + 0 \cdot FREE + 0 - B \big) = B}\qquad\qquad\qquad\qquad\quad \\ $$ The sum of the registry values in $\mathtt{A}$ and $\mathtt{B}$ was moved into $\texttt{A}$, while $\texttt{B}$ remains unmodified, proving that the third instruction was correctly executed. -4. **The fourth instruction, "$\mathtt{:END }$"** +4. **The fourth instruction, "$\mathtt{:END }$"** The fourth instruction moves the initial registry values (i.e., $\mathtt{A = 0}$ and $\mathtt{B_0 = 0}$) into registries $\texttt{A}$ and $\texttt{B}$, as their next values, respectively. As a result, values of the corresponding selectors are; $\mathtt{setA = 1}$ and $\mathtt{setB = 1}$. Substitutions into the arithmetic constraints give us the following; $$ - \mathtt{A′ = A + 1 \cdot \big( 0 \cdot A + 0 \cdot B + 0 \cdot FREE + 0 - A \big) = A - A = 0} \\ + \mathtt{A′ = A + 1 \cdot \big( 0 \cdot A + 0 \cdot B + 0 \cdot FREE + 0 - A \big) = A - A = 0} \\ \mathtt{B′ = B + 1 \cdot \big( 0 \cdot A + 0 \cdot B + 0 \cdot FREE + 0 - B \big) = B - B = 0} \\ $$ @@ -99,8 +99,8 @@ $$ \end{array} \hspace{0.1cm} -\begin{array}{|l|c|c|c|c|c|c|c|}\hline - \texttt{FREE} & \texttt{CONST}& \texttt{setB}& \mathtt{setA}& \texttt{inFREE}& \mathtt{inB} & \mathtt{inA} \\ \hline +\begin{array}{|l|c|c|c|c|c|c|c|}\hline + \texttt{FREE} & \texttt{CONST}& \texttt{setB}& \mathtt{setA}& \texttt{inFREE}& \mathtt{inB} & \mathtt{inA} \\ \hline \texttt{7} & \texttt{0} & \texttt{0} & \texttt{1} & \texttt{1} & \texttt{0} & \texttt{0} \\ \hline \texttt{0} & \texttt{3} & \texttt{1} & \texttt{0} & \texttt{0} & \texttt{0} & \texttt{0} \\ \hline @@ -122,13 +122,13 @@ $$ \end{aligned} $$ -## Remarks +## Remarks -1. The $\texttt{CONST}$ column stores the constants of the computation. It should however, not be mistaken for a constant polynomial. The term 'constant' refers to the fact that the column contains constants of the computations. +1. The $\texttt{CONST}$ column stores the constants of the computation. It should however, not be mistaken for a constant polynomial. The term 'constant' refers to the fact that the column contains constants of the computations. -2. It shall be seen later, in our implementation of a state machine with jumps, that $\texttt{CONST}$ is in fact a committed polynomial rather than a constant polynomial. +2. It shall be seen later, in our implementation of a state machine with jumps, that $\texttt{CONST}$ is in fact a committed polynomial rather than a constant polynomial. -3. All the operations in the constraints are carried out $\mathtt{\ modulo }$ the order $p$ of the prime field. The so-called **Goldilocks-like Field**, with $p = 2^{64} − 2^{32} +1$, is mainly used where 64-bit numbers suffice (see [Plonky2](https://github.com/mir-protocol/plonky2/blob/main/plonky2/plonky2.pdf)). Otherwise, the [BN128 field](https://iden3-docs.readthedocs.io/en/latest/iden3_repos/research/publications/zkproof-standards-workshop-2/baby-jubjub/baby-jubjub.html) is deployed. +3. All the operations in the constraints are carried out $\mathtt{\ modulo }$ the order $p$ of the prime field. The so-called **Goldilocks-like Field**, with $p = 2^{64} − 2^{32} +1$, is mainly used where 64-bit numbers suffice (see [Plonky2](https://github.com/mir-protocol/plonky2/blob/main/plonky2/plonky2.pdf)). Otherwise, the [BN128 field](https://iden3-docs.readthedocs.io/en/latest/iden3_repos/research/publications/zkproof-standards-workshop-2/baby-jubjub/baby-jubjub.html) is deployed. In order to match the type of commitment scheme used in the zkEVM, these arithmetic constraints must first be expressed as polynomial identities, which are in turn compiled with PILCOM. @@ -142,11 +142,11 @@ Also, **the free inputs may come in the form of another JSON file**, let's name See below diagram for a concise description of what the Executor does. -![Figure 5: SM Executor in a broader context](../../img/zkvm/gen5-sm-exec-broader-contxt.png) +![Figure 5: SM Executor in a broader context](../../img/zkEVM/gen5-sm-exec-broader-contxt.png) -Although the execution trace is composed of the evaluations of the committed polynomials and the evaluations of the constant polynomials, the two evaluations do not happen simultaneously. +Although the execution trace is composed of the evaluations of the committed polynomials and the evaluations of the constant polynomials, the two evaluations do not happen simultaneously. -Instead, the constant polynomials are preprocessed only once, because they do not change and are specific for a particular state machine. +Instead, the constant polynomials are preprocessed only once, because they do not change and are specific for a particular state machine. The committed polynomials, on the other hand, can vary. And are therefore only processed as and when their corresponding verifiable proof is required. @@ -180,7 +180,7 @@ $$ \mathtt{ inB = [0,0,1,0] } \text{ }\text{ } \iff\text{ } \ \mathtt{inB(x) = inB(\omega^i) = inB[i]} \quad\text{}\text{}\qquad\qquad\text{ }\text{ }\text{}\text{ }\text{ }\text{ } \\ -\mathtt{ setA = [1,0,1,1] \text{ }\text{ } \iff\text{ } \ \mathtt{ setA(x) = setA(\omega^i) = setA[i] } }\qquad\quad\text{ }\text{ }\text{ }\text{ } \\ +\mathtt{ setA = [1,0,1,1] \text{ }\text{ } \iff\text{ } \ \mathtt{ setA(x) = setA(\omega^i) = setA[i] } }\qquad\quad\text{ }\text{ }\text{ }\text{ } \\ \mathtt{ setB = [0,1,0,1] } \text{ }\text{ } \iff\text{ } \ \mathtt{setB(x) = setB(\omega^i) = setB[i]} \qquad\qquad\text{}\\ @@ -188,7 +188,6 @@ $$ \mathtt{ CONST = [1,0,0,0] }\text{ }\text{ } \iff\text{ } \ \mathtt{CONST(x) = CONST(\omega^i) = CONST[i]}\qquad\text{} \\ - \text{ }\mathtt{ inFREE = [1,0,0,0] } \text{ }\text{ } \iff\text{ } \ \mathtt{inFREE(x) = inFREE(\omega^i) = inFREE[i]} \\ \end{aligned} $$ @@ -196,12 +195,12 @@ $$ The arithmetic constraints seen above as $\bf{Eqn\ 1}$, are easily written as polynomial identities, as follows, $$ -\mathtt{A(x\omega) - \big(A(x) + setA(x) \cdot \big( op(x) - A(x) \big) \big) = 0} \\ +\mathtt{A(x\omega) - \big(A(x) + setA(x) \cdot \big( op(x) - A(x) \big) \big) = 0} \\ \mathtt{B(x\omega) - \big( B(x) + setB(x) \cdot \big( op(x) - B(x) \big) \big) = 0} \\ $$ -where $\mathtt{op(x) = inA(x) \cdot A(x) + inB(x) \cdot B(x) + inFREE(x) \cdot FREE(x) + CONST(x)}$. +where $\mathtt{op(x) = inA(x) \cdot A(x) + inB(x) \cdot B(x) + inFREE(x) \cdot FREE(x) + CONST(x)}$. As far as **boundary constraints** are concerned, we can, for instance, @@ -214,10 +213,10 @@ As far as **boundary constraints** are concerned, we can, for instance, \mathtt{L1(x) \cdot \big(FREE(\omega^0) - input\big) = 0} \\ \mathtt{L2(x) \cdot \big(A(\omega^{3}) - output\big) = 0}\quad \\ $$ - where $\mathtt{L1(x)}$ and $\mathtt{L2(x)}$ are precomputed constant polynomials. In fact, $\mathtt{L1(x) = [1,0,0,0]}$ and $\mathtt{L2(x) = [0,0,0,1]}$. + where $\mathtt{L1(x)}$ and $\mathtt{L2(x)}$ are precomputed constant polynomials. In fact, $\mathtt{L1(x) = [1,0,0,0]}$ and $\mathtt{L2(x) = [0,0,0,1]}$. In the big scheme of things, these are Lagrange polynomials emanating from interpolation. Verification relies on the fact that: these polynomial identities, including the boundary constraints, hold true *if, and only if* the execution trace is correct and faithful to the instructions in the zkASM program. The PIL description of the SM Executor, reading instructions from the zkASM program with four instructions, is depicted in the figure provided below. -![The PIL description for the 4-instruction program](../../img/zkvm/gen6-pil-4instrct-prog.png) +![The PIL description for the 4-instruction program](../../img/zkEVM/gen6-pil-4instrct-prog.png) diff --git a/docs/zkEVM/concepts/intro-generic-sm.md b/docs/zkEVM/concepts/intro-generic-sm.md index 57484d633..3635e56f9 100644 --- a/docs/zkEVM/concepts/intro-generic-sm.md +++ b/docs/zkEVM/concepts/intro-generic-sm.md @@ -6,11 +6,11 @@ The idea here is to create a state machine that behaves like a processor of sort See Figure below, for such a state machine with registries $\texttt{A}$ and $\texttt{B}$, and a state $\big(\texttt{A}^{\texttt{i}},\texttt{B}^{\texttt{i}}\big)$ that changes to another state $\big(\texttt{A}^{\texttt{i+2}},\texttt{B}^{\texttt{i+2}}\big)$ in accordance with two instructions, $\texttt{Instruction}_{\texttt{i}}$ and $\texttt{Instruction}_{\texttt{i+1}}$. -![Figure 1: A typical generic state machine](../../img/zkvm/gen1-typical-gen-sm.png) +![Figure 1: A typical generic state machine](../../img/zkEVM/gen1-typical-gen-sm.png) The aim with this document is to explain how the machinery used in the mFibonacci SM; to execute computations, produce proofs of correctness of execution, and verify these proofs; can extend to a generic state machine. -Think of our state machine as being composed of two parts; the part that has to do with generating the execution trace, while the other part is focused on verifying that the executions were correctly executed. +Think of our state machine as being composed of two parts; the part that has to do with generating the execution trace, while the other part is focused on verifying that the executions were correctly executed. - The former part is more like the "software" of the state machine, as it is concerned with interpreting program instructions and correctly generating the execution trace. A novel language dubbed the **Zero-knowledge Assembly Language** (zkASM) is used in this part. @@ -18,13 +18,13 @@ Think of our state machine as being composed of two parts; the part that has to ## Generic SM Executor -As seen with the mFibonacci SM, the SM executor takes certain inputs together with the description of the SM, in order to produce the execution trace specifically corresponding to these inputs. +As seen with the mFibonacci SM, the SM executor takes certain inputs together with the description of the SM, in order to produce the execution trace specifically corresponding to these inputs. -![Figure 2: mFibonacci State Machine producing input-specific execution trace](../../img/zkvm/gen2-mfib-exec-w-inputs.png) +![Figure 2: mFibonacci State Machine producing input-specific execution trace](../../img/zkEVM/gen2-mfib-exec-w-inputs.png) The main difference, in the Generic State Machine case, is the inclusion of a program which stipulates computations to be carried out by the SM executor. These computations could range from a simple addition of two registry values, or moving the value in registry $\texttt{A}$ to registry $\texttt{B}$, to computing some linear combination of several registry values. -![Figure 3: A Generic State Machine producing input- and program-specific execution trace ](../../img/zkvm/gen3-gen-sm-w-input-instrctn.png) +![Figure 3: A Generic State Machine producing input- and program-specific execution trace ](../../img/zkEVM/gen3-gen-sm-w-input-instrctn.png) So then, instead of programming the SM executor ourselves with a specific set of instructions as we did with the mFibonacci SM, the executor of a Generic SM is programmed to read arbitrary instructions encapsulated in some program (depending on the capacity of the SM or the SM's context of application). As mentioned above, each of these programs is initially written, not in a language like Javascript, but in the zkASM language. @@ -37,12 +37,12 @@ Here is an example of a program containing four instructions, expressed in the z $$ \begin{aligned} \begin{array}{|l|c|} -\hline +\hline \texttt{ } & \bf{Instructions } \text{ }\text{ }\text{ }\text{ } \\ \hline \texttt{ } & \mathtt{\$\{getAFreeInput()\} => A} \text{ }\\ \hline \texttt{ } & \mathtt{3 => B} \qquad\qquad\qquad\qquad\quad \\ \hline \texttt{ } & \mathtt{:ADD } \qquad\qquad\qquad\quad\quad\quad\text{ }\text{ } \\ \hline -\texttt{ } & \mathtt{:END } \qquad\qquad\qquad\quad\qquad\text{}\text{ }\text{ } \\ \hline +\texttt{ } & \mathtt{:END } \qquad\qquad\qquad\quad\qquad\text{}\text{ }\text{ } \\ \hline \end{array} \end{aligned} $$ @@ -61,8 +61,8 @@ In addition to carrying out computations as per instructions in programs, the ex Consider, as an example, the execution trace the executor produces for the above program of four instructions. Suppose the free input value used is $7$. The generated execution trace can be depicted in tabular form as shown below. $$ -\begin{aligned}\begin{array}{|l|c|c|c|c|c|c|c|}\hline -\texttt{ } & \bf{Instructions } \text{ }\text{ }\text{ }\text{ } & \texttt{FREE} & \texttt{CONST}& \texttt{A}& \mathtt{A'}& \texttt{B}& \mathtt{B'} \\ \hline +\begin{aligned}\begin{array}{|l|c|c|c|c|c|c|c|}\hline +\texttt{ } & \bf{Instructions } \text{ }\text{ }\text{ }\text{ } & \texttt{FREE} & \texttt{CONST}& \texttt{A}& \mathtt{A'}& \texttt{B}& \mathtt{B'} \\ \hline \texttt{ } & \mathtt{\$\{getAFreeInput()\} => A} \text{ } & \texttt{7} & \texttt{0} & \texttt{0} & \texttt{7} & \texttt{0} & \texttt{0}\\ \hline \texttt{ } & \mathtt{3 => B} \qquad\qquad\qquad\qquad\quad & \texttt{0} & \texttt{3} & \texttt{7} & \texttt{7} & \texttt{0} & \texttt{3} \\ \hline @@ -76,7 +76,7 @@ $$ \end{aligned} $$ -This execution trace utilises a total of six columns. Perhaps the use of the columns corresponding to the two registries $\texttt{A}$ and $\texttt{B}$, as well as the columns for the constant $\texttt{CONST}$ and the free input $\texttt{FREE}$, are a bit obvious. But the reason for having the other two columns, $\mathtt{A'}$ and $\mathtt{B'}$, may not be so apparent. +This execution trace utilises a total of six columns. Perhaps the use of the columns corresponding to the two registries $\texttt{A}$ and $\texttt{B}$, as well as the columns for the constant $\texttt{CONST}$ and the free input $\texttt{FREE}$, are a bit obvious. But the reason for having the other two columns, $\mathtt{A'}$ and $\mathtt{B'}$, may not be so apparent. The reason there are two extra columns, instead of only four, is the need to capture each state transition in full, and per instruction. The column labelled $\mathtt{A'}$ therefore denotes the next state of the registry $\mathtt{A}$, and similarly, $\mathtt{B'}$ denotes the next state of the registry $\mathtt{B}$. This ensures that each row of the execution trace reflects the entire state transition pertaining to each specific instruction. diff --git a/docs/zkEVM/concepts/mfibonacci-example.md b/docs/zkEVM/concepts/mfibonacci-example.md index a55659e0b..2d6a46681 100644 --- a/docs/zkEVM/concepts/mfibonacci-example.md +++ b/docs/zkEVM/concepts/mfibonacci-example.md @@ -2,12 +2,12 @@ Consider a proof/verification scheme, using an arbitrary Polynomial Commitment S ## What is a multiplicative Fibonacci series? -The multiplicative Fibonacci Series (or simply mFibonacci Series), denoted by +The multiplicative Fibonacci Series (or simply mFibonacci Series), denoted by $$ \mathbf{a_0, a_1, a_2, \dots , a_n} $$ -has the property that the product of every two consecutive members $\mathbf{a_{i-1}}$ and $\mathbf{a_i}$ gives the value of the next member $\mathbf{a_{i+1}}$. That is, $\mathbf{ a_{i+1} = a_{i-1}\cdot a_i }$. +has the property that the product of every two consecutive members $\mathbf{a_{i-1}}$ and $\mathbf{a_i}$ gives the value of the next member $\mathbf{a_{i+1}}$. That is, $\mathbf{ a_{i+1} = a_{i-1}\cdot a_i }$. Also, the initial values are specified as $\mathbf{a_0} = 2$ and $\mathbf{a_1} = 1$. @@ -17,7 +17,7 @@ $$ \mathbf{ \ \ 2,\ \ 1,\ \ 2,\ \ 2,\ \ 4,\ \ 8,\ \ 32,\ \ 256,\ \ 8192,\ \ 2097152,\ \ \dots } $$ -As a trivial example, the challenge may be: Prove knowledge of the initial values that produced $\mathbf{a_{10} = 17179869184}$, the eleventh member of the mFibonacci Series, without revealing the initial values. +As a trivial example, the challenge may be: Prove knowledge of the initial values that produced $\mathbf{a_{10} = 17179869184}$, the eleventh member of the mFibonacci Series, without revealing the initial values. The task therefore, is to first build a state machine that would enable anyone to prove knowledge of the initial values $\mathbf{a_0}$ and $\mathbf{a_1}$ that yields a specific N-th member of the mFibonacci Series. @@ -26,7 +26,7 @@ The task therefore, is to first build a state machine that would enable anyone t Consider a state machine with two registries $\mathbf{A}$ and $\mathbf{B}$ where $$ \begin{aligned} -\mathbf{A} = [A_0, A_1, \dots , A_T ], \\ +\mathbf{A} = [A_0, A_1, \dots , A_T ], \\ \mathbf{B} = [B_0, B_ 1, \dots , B_T] \end{aligned} $$ @@ -34,7 +34,7 @@ such that the i-th state is the pair $\big( A_i , B_i \big)$. Such a state machine is an **mFibonacci state machine** if indeed the registry values conform to the format of the mFibonnacci Series. See Figure 4 below, for an mFibonacci state machine with the initial conditions, $A_0 = 2$ and $B_0 = 1$. -![Figure 4: mFibonacci SM with two registries](../../img/zkvm/fib6-mfibon-sm-2-regs.png) +![Figure 4: mFibonacci SM with two registries](../../img/zkEVM/fib6-mfibon-sm-2-regs.png) The state transitions from $\mathtt{S} = \big( A_i , B_i \big)$ to $\mathtt{S}' = \big( A_{i+1} , B_{i+1} \big)$ conform to the following constraints; @@ -49,7 +49,7 @@ The aim here is to; express the evolution of the execution trace in terms of pol ## Building polynomial identities -The polynomials that represent the two registries are taken from the set of polynomials $\mathbb{F}_p [X]$, where the coefficients are elements of a prime field $\mathbb{F}_p$ and $p = 2^{64} − 2^{32} + 1$. +The polynomials that represent the two registries are taken from the set of polynomials $\mathbb{F}_p [X]$, where the coefficients are elements of a prime field $\mathbb{F}_p$ and $p = 2^{64} − 2^{32} + 1$. The polynomials are evaluated over the subgroup $$ @@ -100,7 +100,7 @@ However, the unrestricted value of $i$, which implies there is no bound on the n Let us test if the polynomial identities hold true for all permissible values of $i$. So let $X = \omega^7$ and refer to the registry values given in Figure 4. -- For the first identity we get, +- For the first identity we get, $$ \begin{aligned} @@ -109,7 +109,7 @@ P(X\cdot \omega) = P(\omega^7 \cdot \omega) = P(\omega^8) = P(\omega^0) = A_0 = \end{aligned} $$ -- Similarly, for the second identity, we get, +- Similarly, for the second identity, we get, $$ \begin{aligned} @@ -126,7 +126,7 @@ In order to inject some cyclicity into the mFibonacci SM, we add a third registr Hence the mFibonacci SM is as depicted in Figure 5 below. -![mFibonacci SM with three registries](../../img/zkvm/fib7-mfibon-sm-3-regs.png) +![mFibonacci SM with three registries](../../img/zkEVM/fib7-mfibon-sm-3-regs.png) The corresponding polynomial $R(x)$ is defined as follows; $$ @@ -146,10 +146,10 @@ The polynomial $R(x)$ is incorporated into the previous polynomial identities as $$ \begin{aligned} -P(X \cdot \omega) = \bigg\lvert_{\mathcal{H}}\ \ - Q(X) \cdot \big( 1 − R(X) \big) + R(X)\cdot A_0 +P(X \cdot \omega) = \bigg\lvert_{\mathcal{H}}\ \ + Q(X) \cdot \big( 1 − R(X) \big) + R(X)\cdot A_0 \quad\quad\text{ }\text{ }\text{ } \\ -Q(X\cdot \omega) = \bigg\lvert_{\mathcal{H}}\ \ +Q(X\cdot \omega) = \bigg\lvert_{\mathcal{H}}\ \ (1 − R(X)) \cdot P(X)\cdot Q(X) + R(X)\cdot B_0 \end{aligned} $$ @@ -177,7 +177,7 @@ $$ \end{aligned} $$ -- Similarly, for the second identity, we observe that, +- Similarly, for the second identity, we observe that, $$ \begin{aligned} @@ -233,7 +233,7 @@ In other words, the prover has to provide three polynomials $P(X)$, $Q(X)$, $P(X This logic is valid simply because the computations carried out by the state machine are deterministic by nature. -### Proof elements and verification +### Proof elements and verification All computations are carried out in a field $\mathbb{F}_p$ , where $p = \mathtt{2^{64}-2^{32}+1}$, a Goldilocks-like prime number. @@ -249,4 +249,4 @@ $$ Anyone who knows the three polynomials and the correct initial conditions, say $A_0 = 234$ and $B_0 = 135$, can simply run the mFibonacci SM code to compute $A_{\mathtt{1023}} = P(\omega^{\mathtt{1023}})$. See below figure for the JS code. -![Code Example of the mFibonacci SM's Computation Trace](../../img/zkvm/fib8-code-eg-exec-trace.png) +![Code Example of the mFibonacci SM's Computation Trace](../../img/zkEVM/fib8-code-eg-exec-trace.png) diff --git a/docs/zkEVM/concepts/mfibonacci.md b/docs/zkEVM/concepts/mfibonacci.md index 900c7247d..2889ec85d 100644 --- a/docs/zkEVM/concepts/mfibonacci.md +++ b/docs/zkEVM/concepts/mfibonacci.md @@ -1,9 +1,10 @@ ## Introduction -This document gives a short summary of the **Multiplicative Fibonacci State Machine**, presented as a simple model for the zkProver State Machines. As already mentioned in preceding sections, the overall design of the Polygon zkEVM follows the State Machine model, and thus emulates the Ethereum Virtual Machine (EVM). + +This document gives a short summary of the **Multiplicative Fibonacci State Machine**, presented as a simple model for the zkProver State Machines. As already mentioned in preceding sections, the overall design of the Polygon zkEVM follows the State Machine model, and thus emulates the Ethereum Virtual Machine (EVM). The computations involved in Ethereum, such as; making payments, transferring ERC20 tokens and running smart contracts; are repeatedly carried out and are all deterministic. That is, a particular input always produces the same output. Unlike the arithmetic circuit model which would need loops to be unrolled and hence resulting in undesirably larger circuits, the **State Machine** model is most suitable for iterative and deterministic computations. -![Deterministic Computation](../../img/zkvm/fib4-deterministic-compt.png) +![Deterministic Computation](../../img/zkEVM/fib4-deterministic-compt.png) ## zkProver's state machine design @@ -12,22 +13,21 @@ In order to break down the complexity of the zkProver's design, we use a simplif !!!info Computing consecutive members of the well-known Fibonacci series, starting with specific initial values, is a deterministic computation. - Consider a scenario where a party called the prover needs to prove knowledge of the initial values of the Fibonacci series that produced a given N-th value of the series, in a verifiable manner. -These types of computations form a perfect analogy of what the zkProver has to do. That is, to produce verifiable proofs that attest to the validity of the transactions submitted to the Ethereum blockchain. +These types of computations form a perfect analogy of what the zkProver has to do. That is, to produce verifiable proofs that attest to the validity of the transactions submitted to the Ethereum blockchain. The approach taken, is that of developing a State Machine that allows a prover to create and submit a verifiable proof of knowledge, and anyone can take such a proof to verify its validity. -![A Skeletal View of the Design Process](../../img/zkvm/fib5-design-approach-outline.png) +![A Skeletal View of the Design Process](../../img/zkEVM/fib5-design-approach-outline.png) -The process that leads to achieving such a State Machine-based system takes a few steps; +The process that leads to achieving such a State Machine-based system takes a few steps; - Modelling the deterministic computation involved as a State Machine - Stating the equations that fully describe the state transitions of the State Machine, called Arithmetic Constraints - Using established and efficient Mathematical methods to define the corresponding polynomials -- Expressing the previously stated Arithmetic Constraints into their equivalent Polynomial Identities. +- Expressing the previously stated Arithmetic Constraints into their equivalent Polynomial Identities. These Polynomial Identities are equations that can be easily tested in order to verify the prover's claims. A so-called Commitment Scheme is required for facilitating the proving and the verification. Hence, in the zkProver context, a proof/verification scheme called PIL-STARK is used. -The Multiplicative Fibonacci SM document culminates in a DIY guide to implementing the proving and verification of the mFibonacci State Machine. \ No newline at end of file +The Multiplicative Fibonacci SM document culminates in a DIY guide to implementing the proving and verification of the mFibonacci State Machine. diff --git a/docs/zkEVM/concepts/pil-stark-demo.md b/docs/zkEVM/concepts/pil-stark-demo.md index 41ac389c5..95ea5c850 100644 --- a/docs/zkEVM/concepts/pil-stark-demo.md +++ b/docs/zkEVM/concepts/pil-stark-demo.md @@ -2,7 +2,6 @@ !!!note This document is a guide to a DIY implementation of the PIL-STARK proof/verification system. - Before delving into the implementation, we first ensure the boundary constraints in the $\texttt{mFibonacci.pil}$ code are not hardcoded. The aim here is to implement these values as $\texttt{publics}$. This subsequently populates the $\texttt{publics}$' field in the parsed $\texttt{\{ \} fibonacci.pil.json}$ file. ## Boundary Constraints As Publics @@ -39,11 +38,11 @@ where the **` : `** colon-prefix indicates a read of the value stored at $\tex The modified $\texttt{mFibonacci.pil}$ file, before compilation with $\texttt{PILCOM}$, is now as follows, -![mFibonacci.pil file with "publics"](../../img/zkvm/fib17-mfib-pil-w-pubs.png) +![mFibonacci.pil file with "publics"](../../img/zkEVM/fib17-mfib-pil-w-pubs.png) This modified $\texttt{mFibonacci.pil}$ file can be compiled with $\texttt{PILCOM}$ in the manner demonstrated earlier. The resulting parsed PIL file, "$\texttt{\{ \} mfibonacci.pil.json}$", now reflects some information in the "$\texttt{publics}$" field, as shown here: -![A non-empty "publics" field the parsed PIL file ](../../img/zkvm/fib18-non-empt-pubs-field.png) +![A non-empty "publics" field the parsed PIL file ](../../img/zkEVM/fib18-non-empt-pubs-field.png) ## PIL-STARK Implementation Guide @@ -59,7 +58,7 @@ npm init -y A successful initialisation looks like this: -![Successful node initialisation](../../img/zkvm/fib19-init-node-project.png) +![Successful node initialisation](../../img/zkEVM/fib19-init-node-project.png) Next, install the required dependencies with the following command, @@ -69,7 +68,7 @@ npm install pil-stark yargs chai The installation takes seconds, and again the results looks like this, -![Installed dependencies](../../img/zkvm/fib20-dependncs-install-mfib.png) +![Installed dependencies](../../img/zkEVM/fib20-dependncs-install-mfib.png) ### Create Input Files @@ -86,11 +85,11 @@ First of all, the overall inputs to PIL-STARK are; the $\texttt{.pil}$ file desc pol ab = a*b; // publics - public out = a(%N-1); + public out = a(%N-1); // transition constraints - (1-ISLAST) * (a' - b) = 0; - (1-ISLAST) * (b' - (ab)) = 0; + (1-ISLAST) * (a' - b) = 0; + (1-ISLAST) * (b' - (ab)) = 0; // boundary constraint ISLAST*(a-:out)=0; @@ -105,10 +104,10 @@ First of all, the overall inputs to PIL-STARK are; the $\texttt{.pil}$ file desc "nQueries": 8, "verificationHashType": "GL", "steps": [ - {"nBits": 11}, + {"nBits": 11}, {"nBits": 7}, {"nBits": 3} - ] + ] } ``` @@ -124,26 +123,26 @@ Create a new file and call it `executor_mfibonacci.js`. Copy the code-text show const { FGL } = require("pil-stark"); module.exports.buildConstants = async function (pols) { - const N = 1024; - for ( let i=0; i A}\text{ }\\ \hline \quad\texttt{1} & \mathtt{-3 => B}\text{ }\qquad\qquad\qquad\text{ }\text{ } \\ \hline @@ -245,8 +245,6 @@ $$ $$ The Program Counter therefore moves to the subsequent line of instruction. That is, the next instruction to be executed must the one in $\texttt{line}$ $\texttt{3}$ of the Assembly code. - - ### Step 3: "A :JMPZ(finalWait)" According this instruction, the executor has to jump on condition that $\texttt{A}$ is $\mathtt{0}$, otherwise there is no jump. The polynomials immediately involved in this instruction are $\mathtt{inA}$ and $\mathtt{JMPZ}$. Therefore, $\mathtt{inA = 1}$ and $\mathtt{JMPZ = 1}$. @@ -275,13 +273,13 @@ $$ ### Step 4: "{beforeLast()} :JMPZ(finalWait)" -The $\texttt{beforeLast()}$ function, which keeps track of the number of steps being executed, reads the current step-number as a free input. Since the execution trace is currently at step $\mathtt{4}$ and not $\mathtt{6}$, then the executor returns a zero. And thus, $\mathtt{inFREE = 1}$ and $\mathtt{JMPZ = 1}$ but $\mathtt{inA = 0}$, $\mathtt{inB =0}$, $\mathtt{FREE = 0}$ and $\mathtt{CONST = 0}$. Consequently, +The $\texttt{beforeLast()}$ function, which keeps track of the number of steps being executed, reads the current step-number as a free input. Since the execution trace is currently at step $\mathtt{4}$ and not $\mathtt{6}$, then the executor returns a zero. And thus, $\mathtt{inFREE = 1}$ and $\mathtt{JMPZ = 1}$ but $\mathtt{inA = 0}$, $\mathtt{inB =0}$, $\mathtt{FREE = 0}$ and $\mathtt{CONST = 0}$. Consequently, $$ \mathtt{op\ =\ inA \cdot A\ +\ inB \cdot B\ +\ inFREE \cdot FREE\ +\ CONST\ =\ 0 \cdot A\ +\ 0 \cdot B\ +\ 1 \cdot 0\ +\ 0\ =\ 0}. $$ Therefore $\mathtt{isZero \ := (1 − op \cdot invOp)\ = (1 − 0 \cdot \alpha) = 1}$. Hence according to $\texttt{JMPZ(finalWait)}$, a jump is executed. This means the executor must jump to the $\mathtt{offset = 5}$ address, as computed by the Assembly compiler. It follows that $\mathtt{zkPC′}$ must be $\mathtt{5}$. -Let us use Eqn 4* to check if indeed $\mathtt{zkPC′ = 5}$. We first note that, there are no unconditional jumps, so $\mathtt{JMP = 0}$. And, +Let us use Eqn 4* to check if indeed $\mathtt{zkPC′ = 5}$. We first note that, there are no unconditional jumps, so $\mathtt{JMP = 0}$. And, $$ \mathtt{doJMP := JPMZ \cdot isZero + JMP = 1 \cdot 1 + 0 = 1}. \qquad\qquad\qquad\qquad\qquad \\ @@ -296,7 +294,7 @@ The execution trace is currently as follows, $$ \small \begin{array}{|l|c|} -\hline +\hline \texttt{step} & \bf{instructions} \\ \hline \quad\texttt{0} & \mathtt{{getAFreeInput()} => A}\quad\qquad\qquad\\ \hline \quad\texttt{1} & \mathtt{-3 => B}\qquad\qquad\qquad\qquad\qquad\qquad\text{ }\text{ } \\ \hline @@ -348,7 +346,7 @@ $$ \mathtt{op\ =\ inA \cdot A\ +\ inB \cdot B\ +\ inFREE \cdot FREE\ +\ CONST\ =\ 0 \cdot A\ +\ 0 \cdot B\ +\ 1 \cdot 0\ +\ 0\ =\ 0}, $$ -which means $\mathtt{FREE = 0}$ and $\mathtt{isZero \ := (1 − op \cdot invOp)\ = (1 − 0 \cdot \alpha) = 1}$. So, again $\texttt{JMPZ(finalWait)}$ gets executed. +which means $\mathtt{FREE = 0}$ and $\mathtt{isZero \ := (1 − op \cdot invOp)\ = (1 − 0 \cdot \alpha) = 1}$. So, again $\texttt{JMPZ(finalWait)}$ gets executed. The absence of unconditional jumps means $\mathtt{JMP = 0}$, while $\mathtt{JMPZ = 1}$. Since $\mathtt{offset = 5}$, the Program Counter, $\mathtt{zkPC′}$, must in the next step be $\mathtt{5}$. @@ -370,9 +368,9 @@ In this case, the current step is the last but one step. That is, the $\texttt{b $$ \mathtt{op\ =\ inA \cdot A\ +\ inB \cdot B\ +\ inFREE \cdot FREE\ +\ CONST\ =\ 0 \cdot A\ +\ 0 \cdot B\ +\ 1 \cdot 1\ +\ 0\ =\ 1}. $$ -This means $\mathtt{FREE = 1}$ and $\mathtt{isZero \ := (1 − op \cdot invOp)\ = (1 − 1 \cdot 1) = 0}$. And, this time $\texttt{JMPZ(finalWait)}$ is not executed, implying the next Program Counter, $\mathtt{zkPC′ = zkPC + 1}$. +This means $\mathtt{FREE = 1}$ and $\mathtt{isZero \ := (1 − op \cdot invOp)\ = (1 − 1 \cdot 1) = 0}$. And, this time $\texttt{JMPZ(finalWait)}$ is not executed, implying the next Program Counter, $\mathtt{zkPC′ = zkPC + 1}$. -Since there are no jumps in this step, $\mathtt{JMP = 0}$ and $\mathtt{JMPZ = 0}$, yielding +Since there are no jumps in this step, $\mathtt{JMP = 0}$ and $\mathtt{JMPZ = 0}$, yielding $$ \mathtt{doJMP := JPMZ \cdot isZero + JMP = 0 \cdot 1 + 0 = 0}, \\ $$ @@ -383,15 +381,15 @@ $$ ### Step 7: "0=>A,B :JMP(start)" -The aim with this instruction is to complete the execution trace such that it is of the correct size (which is $\mathtt{8}$ in this example). +The aim with this instruction is to complete the execution trace such that it is of the correct size (which is $\mathtt{8}$ in this example). -It ends the execution by setting $\texttt{A}$ and $\texttt{B}$ to zero, and jumps to $\mathtt{start}$, which is line $\mathtt{0}$. And thus, $\mathtt{zkPC'}$ must be $\mathtt{0}$. Hence, $\mathtt{setA = 1}$, $\mathtt{setB = 1}$ and $\mathtt{JMP = 1}$ but $\mathtt{inFREE = 0}$, $\mathtt{inA =0}$, $\mathtt{inB =0}$ and $\mathtt{CONST = 0}$. Consequently, +It ends the execution by setting $\texttt{A}$ and $\texttt{B}$ to zero, and jumps to $\mathtt{start}$, which is line $\mathtt{0}$. And thus, $\mathtt{zkPC'}$ must be $\mathtt{0}$. Hence, $\mathtt{setA = 1}$, $\mathtt{setB = 1}$ and $\mathtt{JMP = 1}$ but $\mathtt{inFREE = 0}$, $\mathtt{inA =0}$, $\mathtt{inB =0}$ and $\mathtt{CONST = 0}$. Consequently, $$ \mathtt{op\ =\ inA \cdot A\ +\ inB \cdot B\ +\ inFREE \cdot FREE\ +\ CONST\ =\ 0 \cdot 0\ +\ 0 \cdot (-3)\ +\ 0 \cdot 1\ +\ 0\ =\ 0}. $$ -Therefore $\mathtt{isZero \ := (1 − op \cdot invOp)\ = (1 − 0 \cdot \alpha) = 1}$. +Therefore $\mathtt{isZero \ := (1 − op \cdot invOp)\ = (1 − 0 \cdot \alpha) = 1}$. -There are no conditional jumps, so $\mathtt{JMPZ = 0}$. Then, as a consequence of this, +There are no conditional jumps, so $\mathtt{JMPZ = 0}$. Then, as a consequence of this, $$ \mathtt{doJMP := JPMZ \cdot isZero + JMP = 0 \cdot 1 + 1 = 1}. \\ $$ @@ -407,7 +405,7 @@ See the complete execution trace below, $$ \small \begin{array}{|l|c|} -\hline +\hline \texttt{step} & \bf{instructions} \\ \hline \quad\texttt{0} & \mathtt{{getAFreeInput()} => A}\quad\qquad\qquad\\ \hline \quad\texttt{1} & \mathtt{-3 => B}\qquad\qquad\qquad\qquad\qquad\qquad\text{ }\text{ } \\ \hline @@ -467,7 +465,7 @@ Note that in cases where the jumps are such that $\mathtt{offset}$ is one of the ## Publics Placed at Known Steps -Regarding the $\texttt{publics}$, it is best to place these at specific and known steps. +Regarding the $\texttt{publics}$, it is best to place these at specific and known steps. Notice that, in the above example, the final loop added to Assembly program repeats the values of the registries $\mathtt{A}$ and $\mathtt{B}$ until they are reset to Step $\mathtt{0}$. diff --git a/docs/zkEVM/concepts/simple-smt.md b/docs/zkEVM/concepts/simple-smt.md index 4df31ad78..12b86e6f0 100644 --- a/docs/zkEVM/concepts/simple-smt.md +++ b/docs/zkEVM/concepts/simple-smt.md @@ -1,28 +1,28 @@ -Understanding the finer details of how the Storage SM operates requires a good grasp of the way the zkProver's Sparse Merkle Trees (SMTs) are constructed. This document explains how these SMTs are built. +Understanding the finer details of how the Storage SM operates requires a good grasp of the way the zkProver's Sparse Merkle Trees (SMTs) are constructed. This document explains how these SMTs are built. Consider key-value pair based binary SMTs. The focus here is on explaining how to construct an SMT that represents a given set of key-value pairs. And, for the sake of simplicity, we assume 8-bit key-lengths. A NULL or **empty** SMT has a zero root. That is, it has no key and no value recorded in it. Similarly, a zero node or NULL node refers to a node that carries no value. -## A binary SMT with one key-value pair +## A binary SMT with one key-value pair -A binary SMT with a **single key-value pair** $(K_{\mathbf{a}}, \text{V}_{\mathbf{a}})$, is built as follows. +A binary SMT with a **single key-value pair** $(K_{\mathbf{a}}, \text{V}_{\mathbf{a}})$, is built as follows. Suppose that $K_{\mathbf{a}} = 11010110$. In order to build a binary SMT with this single key-value $(K_{\mathbf{a}}, \text{V}_{\mathbf{a}})$, -1. One computes the hash $\mathbf{H}( \text{V}_{\mathbf{a}})$ of the value $\text{V}_{\mathbf{a}}$, +1. One computes the hash $\mathbf{H}( \text{V}_{\mathbf{a}})$ of the value $\text{V}_{\mathbf{a}}$, -2. Sets the leaf $\mathbf{L}_{\mathbf{a}} := \mathbf{H}( \text{V}_{\mathbf{a}})$, +2. Sets the leaf $\mathbf{L}_{\mathbf{a}} := \mathbf{H}( \text{V}_{\mathbf{a}})$, -3. Sets the sibling leaf as a NULL leaf, simply represented as "$\mathbf{0}$", +3. Sets the sibling leaf as a NULL leaf, simply represented as "$\mathbf{0}$", -4. Computes the root as $\mathbf{root}_{a0} = \mathbf{H}(\mathbf{L}_{\mathbf{a}} \| \mathbf{0} )$, with the leaf $\mathbf{L}_{\mathbf{a}}$ on the left because the $\text{lsb}(K_{\mathbf{a}}) = 0$. That is, between the two edges leading up to the root, the leaf $\mathbf{L}_{\mathbf{a}}$ is on the left edge, while the NULL leaf "$\mathbf{0}$" is on the right. +4. Computes the root as $\mathbf{root}_{a0} = \mathbf{H}(\mathbf{L}_{\mathbf{a}} \| \mathbf{0} )$, with the leaf $\mathbf{L}_{\mathbf{a}}$ on the left because the $\text{lsb}(K_{\mathbf{a}}) = 0$. That is, between the two edges leading up to the root, the leaf $\mathbf{L}_{\mathbf{a}}$ is on the left edge, while the NULL leaf "$\mathbf{0}$" is on the right. See the below figure for the SMT representing the single key-value pair $(K_{\mathbf{a}}, \text{V}_{\mathbf{a}})$, where $K_{\mathbf{a}} = 11010110$. -![A Single key-value pair SMT](../../img/zkvm/fig4-sngl-kv-eg.png) +![A Single key-value pair SMT](../../img/zkEVM/fig4-sngl-kv-eg.png) -Note that the last nodes in binary SMT branches are generally either leaves or zero-nodes. +Note that the last nodes in binary SMT branches are generally either leaves or zero-nodes. In the case where the least-significant bit, **lsb of $K_{\mathbf{a}}$ is $1$**, the SMT with a single key-value pair $(K_{\mathbf{a}}, \text{V}_{\mathbf{a}})$ would be a mirror image of what is seen in Figure 3. And its root, $\mathbf{root}_{0a} = \mathbf{H}( \mathbf{0}\| \mathbf{L}_{\mathbf{a}} ) \neq \mathbf{root}_{a0}$ because $\mathbf{H}$ is a collision-resistant hash function. @@ -30,7 +30,7 @@ This example also explains why we need a zero node. Since all trees used in our ## Binary SMTs with two key-value pairs -Consider now SMTs with **two key-value pairs**, $(K_{\mathbf{a}}, \text{V}_{\mathbf{a}})$ and $(K_{\mathbf{b}}, \text{V}_{\mathbf{b}})$. +Consider now SMTs with **two key-value pairs**, $(K_{\mathbf{a}}, \text{V}_{\mathbf{a}})$ and $(K_{\mathbf{b}}, \text{V}_{\mathbf{b}})$. There are three distinct cases of how corresponding SMTs can be built, each determined by the keys, $K_{\mathbf{a}}$ and $K_{\mathbf{b}}$. @@ -38,7 +38,7 @@ There are three distinct cases of how corresponding SMTs can be built, each dete The keys are such that the $\text{lsb}(K_{\mathbf{a}}) = 0$ and the $\text{lsb}(K_{\mathbf{b}}) = 1$. -Suppose that the keys are given as $K_{\mathbf{a}} = 11010110$ and $K_{\mathbf{b}} = 11010101$. +Suppose that the keys are given as $K_{\mathbf{a}} = 11010110$ and $K_{\mathbf{b}} = 11010101$. To build a binary SMT with this two key-values, $(K_{\mathbf{a}}, \text{V}_{\mathbf{a}})$ and $(K_{\mathbf{b}}, \text{V}_{\mathbf{b}})$, @@ -50,19 +50,19 @@ To build a binary SMT with this two key-values, $(K_{\mathbf{a}}, \text{V}_{\mat 4. Since the $\text{lsb}(K_{\mathbf{a}}) = 0$ and the $\text{lsb}(K_{\mathbf{b}}) = 1$, it means **the two leaves can be siblings**, -5. One can then compute the root as, $\mathbf{root}_{\mathbf{ab}} = \mathbf{H}(\mathbf{L}_{\mathbf{a}} \| \mathbf{L}_{\mathbf{b}})$. +5. One can then compute the root as, $\mathbf{root}_{\mathbf{ab}} = \mathbf{H}(\mathbf{L}_{\mathbf{a}} \| \mathbf{L}_{\mathbf{b}})$. Note that the leaf $\mathbf{L}_{\mathbf{a}}$ is on the left because the $\text{lsb}(K_{\mathbf{a}}) = 0$, but $\mathbf{L}_{\mathbf{b}}$ is on the right because the $\text{lsb}(K_{\mathbf{b}}) = 1$. That is, between **the two edges leading up to the $\mathbf{root}_{\mathbf{ab}}$**, the leaf $\mathbf{L}_{\mathbf{a}}$ must be on the edge from the left, while $\mathbf{L}_{\mathbf{b}}$ is on the edge from the right. See the below figure for the SMT representing the two key-value pairs $(K_{\mathbf{a}}, \text{V}_{\mathbf{a}})$ and $(K_{\mathbf{b}}, \text{V}_{\mathbf{b}})$, where $K_{\mathbf{a}} = 11010110$ and $K_{\mathbf{b}} = 11010101$. -![Two key-value pairs SMT - Case 1](../../img/zkvm/fig5-a-mpt-kv-eg.png) +![Two key-value pairs SMT - Case 1](../../img/zkEVM/fig5-a-mpt-kv-eg.png) ### Case 2 Both keys end with the same key-bit. That is, the $\text{lsb}(K_{\mathbf{a}}) = \text{lsb}(K_{\mathbf{b}})$, but their second least-significant bits differ. -Suppose that the two keys are given as $K_{\mathbf{a}} = 11010100$ and $K_{\mathbf{b}} = 11010110$. +Suppose that the two keys are given as $K_{\mathbf{a}} = 11010100$ and $K_{\mathbf{b}} = 11010110$. To build a binary SMT with this two key-values, $(K_{\mathbf{a}}, \text{V}_{\mathbf{a}})$ and $(K_{\mathbf{b}}, \text{V}_{\mathbf{b}})$; @@ -80,9 +80,9 @@ To build a binary SMT with this two key-values, $(K_{\mathbf{a}}, \text{V}_{\mat 7. As a result, it is possible to compute the root as, $\mathbf{root}_{\mathbf{ab0}} = \mathbf{H}(\mathbf{B}_{\mathbf{ab}} \| \mathbf{0})$. Note that, the branch $\mathbf{B}_{\mathbf{ab}}$ is on the left because the $\text{lsb}(K_{\mathbf{a}}) = 0$, and $\mathbf{0}$ must therefore be on the right. That is, between *the two edges leading up to the $\mathbf{root}_{\mathbf{ab0}}$*, the branch $\mathbf{B}_{\mathbf{ab}}$ must be on the edge from the left, while $\mathbf{0}$ is on the edge from the right. -See the below figure depicting the SMT representing the two key-value pairs $(K_{\mathbf{a}}, \text{V}_{\mathbf{a}})$ and $(K_{\mathbf{b}}, \text{V}_{\mathbf{b}})$, where $K_{\mathbf{a}} = 11010100$ and $K_{\mathbf{b}} = 11010110$. +See the below figure depicting the SMT representing the two key-value pairs $(K_{\mathbf{a}}, \text{V}_{\mathbf{a}})$ and $(K_{\mathbf{b}}, \text{V}_{\mathbf{b}})$, where $K_{\mathbf{a}} = 11010100$ and $K_{\mathbf{b}} = 11010110$. -![Two key-value pairs SMT - Case 2](../../img/zkvm/fig5-b-mpt-kv-eg.png) +![Two key-value pairs SMT - Case 2](../../img/zkEVM/fig5-b-mpt-kv-eg.png) ### Case 3 @@ -106,13 +106,13 @@ Suppose that the two keys are given as $K_{\mathbf{a}} = 11011000$ and $K_{\math 8. One can now compute the hash $\mathbf{H}(\mathbf{B}_{\mathbf{ab}} \| \mathbf{0})$, and set it as the branch $\mathbf{B}_{\mathbf{ab0}} := \mathbf{H}(\mathbf{B}_{\mathbf{ab}} \| \mathbf{0})$ at the tree-address `0`. The hash is computed with the branch $\mathbf{B}_{\mathbf{ab}}$ on the left because the second lsb of both keys, $K_{\mathbf{a}}$ and $K_{\mathbf{b}}$, equals $0$. Therefore the NULL leaf "$\mathbf{0}$" must be on the right as an argument to the hash. -9. The branch $\mathbf{B}_{\mathbf{ab0}} := \mathbf{H}(\mathbf{B}_{\mathbf{ab}} \| \mathbf{0})$ also needs a sibling. For the same reason given above, one sets a NULL leaf "$\mathbf{0}$" as the sibling leaf to $\mathbf{B}_{\mathbf{ab0}}$. +9. The branch $\mathbf{B}_{\mathbf{ab0}} := \mathbf{H}(\mathbf{B}_{\mathbf{ab}} \| \mathbf{0})$ also needs a sibling. For the same reason given above, one sets a NULL leaf "$\mathbf{0}$" as the sibling leaf to $\mathbf{B}_{\mathbf{ab0}}$. 10. Now, one is able to compute the root as $\mathbf{root}_{\mathbf{ab00}} = \mathbf{H}(\mathbf{B}_{\mathbf{ab0}} \| \mathbf{0})$. Note that the hash is computed with the branch $\mathbf{B}_{\mathbf{ab0}}$ on the left because the lsb of both keys, $K_{\mathbf{a}}$ and $K_{\mathbf{b}}$, equals $0$. That is, between *the two edges leading up to the $\mathbf{root}_{\mathbf{ab00}}$*, the branch $\mathbf{B}_{\mathbf{ab0}}$ must be on the edge from the left, while "$\mathbf{0}$" is on the edge from the right. See the below figure depicting the SMT representing the two key-value pairs $(K_{\mathbf{a}}, \text{V}_{\mathbf{a}})$ and $(K_{\mathbf{b}}, \text{V}_{\mathbf{b}})$, where $K_{\mathbf{a}} = 11011000$ and $K_{\mathbf{b}} = 10010100$. -![Two key-value pairs SMT - Case 3](../../img/zkvm/fig5-c-mpt-kv-eg.png) +![Two key-value pairs SMT - Case 3](../../img/zkEVM/fig5-c-mpt-kv-eg.png) There are several other SMTs of two key-value pairs $(K_{\mathbf{x}}, \text{V}_{\mathbf{x}})$ and $(K_{\mathbf{z}}, \text{V}_{\mathbf{z}})$ that can be constructed depending on how long the strings of the common least-significant bits between $K_{\mathbf{x}}$ and $K_{\mathbf{z}}$ are. diff --git a/docs/zkEVM/concepts/sparse-merkle-tree.md b/docs/zkEVM/concepts/sparse-merkle-tree.md index 104bd125d..cff74a85d 100644 --- a/docs/zkEVM/concepts/sparse-merkle-tree.md +++ b/docs/zkEVM/concepts/sparse-merkle-tree.md @@ -3,7 +3,6 @@ zkProver's data is stored in the form of a special **Sparse Merkle Tree (SMT), w !!!tip The content of this document is rather elementary. Experienced developers can fast-forward to later sections and only refer back as the need arises. - A typical Merkle tree has **leaves**, **branches** and a **root**. A leaf is a node with no child-nodes, while a branch is a node with child-nodes. The root is therefore the node with no parent-node. See the below figure for an example of how a hash function $\mathbf{H}$ is used to create a Merkle tree recording eight values; @@ -12,18 +11,18 @@ $$ \text{V}_{\mathbf{a}}, \text{V}_{\mathbf{b}}, \text{V}_{\mathbf{c}}, \text{V}_{\mathbf{d}}, \text{V}_{\mathbf{e}}, \text{V}_{\mathbf{f}}, \text{V}_{\mathbf{g}}, \text{V}_{\mathbf{h}} $$ -![A Merkle Tree Example](../../img/zkvm/fig2-mkl-tree-gen.png) +![A Merkle Tree Example](../../img/zkEVM/fig2-mkl-tree-gen.png) Firstly, each leaf is nothing but the hash value $\mathbf{H}(\text{V}_{\mathbf{i}})$ of a particular value $\text{V}_{\mathbf{i}}$, where $\mathbf{i}$ is an element of the index-set $\{ \mathbf{a}, \mathbf{b}, \mathbf{c}, \mathbf{d}, \mathbf{e}, \mathbf{f}, \mathbf{g}, \mathbf{h} \}$. -Secondly, the branch nodes are computed as follows; +Secondly, the branch nodes are computed as follows; $$ -\mathbf{B}_{\mathbf{ab}} = \mathbf{H} \big(\mathbf{H}(\text{V}_{\mathbf{a}})\| \mathbf{H}(\text{V}_{\mathbf{b}})\big), \\ +\mathbf{B}_{\mathbf{ab}} = \mathbf{H} \big(\mathbf{H}(\text{V}_{\mathbf{a}})\| \mathbf{H}(\text{V}_{\mathbf{b}})\big), \\ \mathbf{B}_{\mathbf{cd}} = \mathbf{H} \big(\mathbf{H}(\text{V}_{\mathbf{c}})\| \mathbf{H}(\text{V}_{\mathbf{d}})\big), \\ \mathbf{B}_{\mathbf{ef}} = \mathbf{H} \big(\mathbf{H}(\text{V}_{\mathbf{e}})\| \mathbf{H}(\text{V}_{\mathbf{f}})\big),\text{ } \\ \mathbf{B}_{\mathbf{gh}} = \mathbf{H} \big(\mathbf{H}(\text{V}_{\mathbf{g}})\| \mathbf{H}(\text{V}_{\mathbf{h}})\big), \\ -\mathbf{B}_{\mathbf{abcd}} = \mathbf{H} \big(\mathbf{B}_{\mathbf{ab}}\| \mathbf{B}_{\mathbf{cd}}\big), \text{} \text{and} \\ +\mathbf{B}_{\mathbf{abcd}} = \mathbf{H} \big(\mathbf{B}_{\mathbf{ab}}\| \mathbf{B}_{\mathbf{cd}}\big), \text{} \text{and} \\ \mathbf{B}_{\mathbf{efgh}} = \mathbf{H} \big( \mathbf{B}_{\mathbf{ef}}\| \mathbf{B}_{\mathbf{gh}}\big). \quad \text{ } \text{ } \text{ } $$ @@ -39,9 +38,9 @@ Suppose one is given the key-value pair $( K_{\mathbf{d}} , V_{\mathbf{d}})$, wh In order to locate the key-value pair $( K_{\mathbf{d}} , V_{\mathbf{d}})$ in the Merkle depicted in the figure above, the key $K_{\mathbf{d}}$ is read bit-by-bit from the right-most bit to the left-most bit. While traversing the tree ***from the root downwards***, -- a zero-key-bit "$0$" means "**follow the edge going to the left**", +- a zero-key-bit "$0$" means "**follow the edge going to the left**", -- a key-bit "$1$" means "**follow the edge going to the right**". +- a key-bit "$1$" means "**follow the edge going to the right**". Since $K_{\mathbf{d} } = 10010110$, as follows: @@ -53,7 +52,7 @@ Since $\mathbf{H}( V_{\mathbf{d}})$ is a leaf and not a branch, and the navigati One can similarly **climb** the tree, going in the reverse direction, by using the key-bits of the given key in the reverse order. That is, starting with the last key-bit used to reach the leaf and ending with the least-significant bit of the key. -The **tree-address** of the value $V_{\mathbf{x}}$, herein refers to the position of the leaf $L_{\mathbf{x}} := \mathbf{H}( V_{\mathbf{x}})$, denoted by the key-bits used to reach $L_{\mathbf{d}}$ but in the reverse order. +The **tree-address** of the value $V_{\mathbf{x}}$, herein refers to the position of the leaf $L_{\mathbf{x}} := \mathbf{H}( V_{\mathbf{x}})$, denoted by the key-bits used to reach $L_{\mathbf{d}}$ but in the reverse order. In the above example, the tree-address of $V_{\mathbf{d}}$ is `011`. @@ -77,11 +76,10 @@ The verifier then checks the prover's claim by computing the Merkle root as foll 3. Next, he computes $\mathbf{H} \big( \tilde{ \mathbf{B}}_{\mathbf{ef}}\|\mathbf{B}_{\mathbf{gh}} \big) =: \tilde{ \mathbf{B}}_{\mathbf{efgh}}$, corresponding to the branch node $\mathbf{B}_{\mathbf{efgh}}$. -4. Now, uses $\mathbf{H} \big( \mathbf{B}_{\mathbf{abcd}}\| \tilde{ \mathbf{B}}_{\mathbf{efgh}} \big) =: \tilde{ \mathbf{root}}_{\mathbf{a..h}}$. +4. Now, uses $\mathbf{H} \big( \mathbf{B}_{\mathbf{abcd}}\| \tilde{ \mathbf{B}}_{\mathbf{efgh}} \big) =: \tilde{ \mathbf{root}}_{\mathbf{a..h}}$. The Merkle proof is concluded by checking whether $\tilde{ \mathbf{root}}_{\mathbf{a\dots h}}$ equals to the publicly known root $\mathbf{root}_{\mathbf{a..h}}$. - !!!note - The symbol `tilde` denoted $\tilde{\Box}$, is used throughout the document to indicate + The symbol `tilde` denoted $\tilde{\Box}$, is used throughout the document to indicate that the computed value, $\tilde{\Box}$, still needs to be checked, or tested to be true. diff --git a/docs/zkEVM/concepts/verification-scheme.md b/docs/zkEVM/concepts/verification-scheme.md index 3552c0d4a..55afce6a6 100644 --- a/docs/zkEVM/concepts/verification-scheme.md +++ b/docs/zkEVM/concepts/verification-scheme.md @@ -1,8 +1,9 @@ ## Constructing the verification scheme -The zkEVM's basic proof system for proving correctness of all state machine computations is a **STARK**. +The zkEVM's basic proof system for proving correctness of all state machine computations is a **STARK**. The fundamental configuration of the zkProver: + - It utilises STARK proofs for proving correctness of computations, due to their speed. - For succinct verification, these STARK proofs are in turn proved with a single SNARK. - So, it employs STARK proofs internally, while the publicised validity proofs are SNARKs. @@ -17,7 +18,7 @@ A STARK falls short of succinctness because, although verifier arithmetic comple See the table below, taken from the presentation [here](https://docs.google.com/presentation/d/1gfB6WZMvM9mmDKofFibIgsyYShdf0RV_Y8TLz3k1Ls0/edit#slide=id.g443ebc39b4_0_110), for a quick comparison of proofs sizes, prover and verification times, between STARKs, SNARKs and [Bulletproofs](https://eprint.iacr.org/2017/1066.pdf). -![Comparison of Proof Sizes, Proof and Verification Times](../../img/zkvm/fib9-stark-prf-sizes-times.png) +![Comparison of Proof Sizes, Proof and Verification Times](../../img/zkEVM/fib9-stark-prf-sizes-times.png) ### FRI-PCS context @@ -31,20 +32,20 @@ FRI is in fact a Merkle commitment scheme where commitments are roots of Merkle **The FRI protocol is considered fast for several reasons;** -1. Due to its resemblance of the ubiquitous Fast Fourier Transforms (FFTs). +1. Due to its resemblance of the ubiquitous Fast Fourier Transforms (FFTs). 2. The arithmetic complexity of the prover is strictly linear. -3. The size of the proof is O(n log(n)). +3. The size of the proof is O(n log(n)). 4. The arithmetic complexity of the verifier is strictly logarithmic. -Our special implementation of a STARK is called **PIL-STARK**, and its polynomial commitment scheme (PCS) is also based on the FRI protocol. We will later demonstrate how PIL-STARK is used to prove the polynomial identities of the mFibonacci state machine. +Our special implementation of a STARK is called **PIL-STARK**, and its polynomial commitment scheme (PCS) is also based on the FRI protocol. We will later demonstrate how PIL-STARK is used to prove the polynomial identities of the mFibonacci state machine. Before describing PIL-STARK a quick look at the novel Polynomial Identities Language (PIL), and some of its distinguishing features, will be helpful. ### Polynomial Identity Language -**PIL** is a domain-specific language (DSL) that provides a method for naming polynomials and describing the identities that define computations carried out by a state machine. +**PIL** is a domain-specific language (DSL) that provides a method for naming polynomials and describing the identities that define computations carried out by a state machine. -A typical $\texttt{.pil}$ file for a given state machine specifies the details of the computation that the state machine carries out; +A typical $\texttt{.pil}$ file for a given state machine specifies the details of the computation that the state machine carries out; - the size (or degree) of the polynomials. i.e., the number of rows of the execution trace. - the namespace of the state machine, which becomes a prefix to names of the SM's polynomials. @@ -57,7 +58,7 @@ In cases where several state machines are being proved; although each SM may hav See the figure below for a description of the mFibonacci SM in PIL, as an $\texttt{mFibonacci.pil}$ file. -![The .pil file of the mFibonacci State Machine](../../img/zkvm/fib10-pil-eg-mfibonacci.png) +![The .pil file of the mFibonacci State Machine](../../img/zkEVM/fib10-pil-eg-mfibonacci.png) The value of the polynomial $\mathtt{a}$ in the next step (or state) of the state machine, is denoted by $\mathtt{a'}$ and it is read "a"-prime. i.e., If $\mathtt{a = P(\omega^i)}$ then $\mathtt{a' = P(\omega^{i+1})}$. @@ -79,14 +80,14 @@ We demonstrate compiling the $\texttt{mFibonacci.pil}$ file into a $\texttt{.jso Here's how to achieve the compilation of the $\texttt{mFibonacci.pil}$ file; -1. Clone the $\texttt{PILCOM}$ [repo](https://github.com/0xPolygonHermez/pilcom), +1. Clone the $\texttt{PILCOM}$ [repo](https://github.com/0xPolygonHermez/pilcom), $$ \texttt{git clone https://github.com/0xPolygonHermez/pilcom} $$ -2. Once cloned, switch directory to $\texttt{pilcom/}$, and install the module and build the parser, +2. Once cloned, switch directory to $\texttt{pilcom/}$, and install the module and build the parser, $$ - \texttt{pilcom\$ npm install}\text{ }\text{ }\text{ }\text{ } \\ + \texttt{pilcom\$ npm install}\text{ }\text{ }\text{ }\text{ } \\ \texttt{pilcom\$ npm run build} $$ @@ -103,7 +104,7 @@ Here's how to achieve the compilation of the $\texttt{mFibonacci.pil}$ file; $$ You might need to prefix the path "$\texttt{myproject/mfibonacci.pil}$" with "~/" -5. If successful, the output report (printed in the terminal) looks like this, ![PILCOM Result For mFibonacci SM](../../img/zkvm/fib11-pilcom-res-mfibon.png) +5. If successful, the output report (printed in the terminal) looks like this, ![PILCOM Result For mFibonacci SM](../../img/zkEVM/fib11-pilcom-res-mfibon.png) It provides information on the number of polynomials used (both constant and committed), the number of polynomial identities to be checked, and other information pertaining to the number of identities checked with; $\texttt{Plookup}$ tables, $\texttt{Permutation}$ checks and $\texttt{Connection}$ checks. @@ -111,11 +112,11 @@ Here's how to achieve the compilation of the $\texttt{mFibonacci.pil}$ file; In our case, the $\texttt{.json}$ file produced by $\texttt{PILCOM}$ appears in the "MYPROJECT" folder as $\texttt{\{ \} fibonacci.pil.json}$ and its content looks like this (Well, after removing the many newlines), - ![Contents of the {} fibonacci.pil.json file](../../img/zkvm/fib12-inside-parsed-pil.png) + ![Contents of the {} fibonacci.pil.json file](../../img/zkEVM/fib12-inside-parsed-pil.png) - The $\texttt{\{ \} fibonacci.pil.json}$ file contains much more detail than the results seen in Step 5 above. For instance, it reflects the polynomial names prefixed with the state machine namespace $\texttt{mFibonacci}$ as stipulated to in the $\texttt{mFibonacci.pil}$ file. + The $\texttt{\{ \} fibonacci.pil.json}$ file contains much more detail than the results seen in Step 5 above. For instance, it reflects the polynomial names prefixed with the state machine namespace $\texttt{mFibonacci}$ as stipulated to in the $\texttt{mFibonacci.pil}$ file. - Each polynomial is further described with four (4) attributes; + Each polynomial is further described with four (4) attributes; (a) $\texttt{type}$ which specifies whether the polynomial is committed, constant or intermediate. diff --git a/docs/zkEVM/connect-wallet.md b/docs/zkEVM/connect-wallet.md index bb5efd7ab..1c03ce304 100644 --- a/docs/zkEVM/connect-wallet.md +++ b/docs/zkEVM/connect-wallet.md @@ -1,9 +1,7 @@ - !!!caution Check the list of potential risks associated with the use of Polygon zkEVM in the [Disclosures]() section. - Add the **Polygon zkEVM** network to your wallet in order to interact with either the mainnet or the testnet. Navigate to `Add network` in your wallet, and enter the respective network details as given in the below table: @@ -16,10 +14,10 @@ Navigate to `Add network` in your wallet, and enter the respective network detai Here is a video tutorial on **how to add Polygon zkEVM Testnet to MetaMask and deploy smart contracts**: Once the wallet is connected, the next step is to bridge crypto assets from Ethereum to zkEVM. -For testnet purposes, you can use the zkEVM faucet to get testnet tokens. \ No newline at end of file +For testnet purposes, you can use the zkEVM faucet to get testnet tokens. diff --git a/docs/zkEVM/deployzkevm/setup-goerlinode.md b/docs/zkEVM/deployzkevm/setup-goerlinode.md index 3eec5b8bb..42a065b54 100644 --- a/docs/zkEVM/deployzkevm/setup-goerlinode.md +++ b/docs/zkEVM/deployzkevm/setup-goerlinode.md @@ -11,6 +11,7 @@ Next, make sure you have the following commands installed: - wget - jq - docker + ```bash sudo apt update -y sudo apt install -y wget jq docker.io @@ -24,16 +25,20 @@ Additionally, you will need **an L1 Goerli address** to proceed with the setup t ## Preparation 1. Create a directory for your Goerli node: + ```bash mkdir -p ~/goerli-node/docker-volumes/{geth,prysm} ``` + 2. Create a `docker-compose.yml` file and open it for editing: + ```bash cd ~/goerli-node/ vim docker-compose.yml ``` 3. Copy and paste the following content into the `docker-compose.yml` file: + ```yaml services: geth: @@ -85,12 +90,14 @@ mkdir -p ~/goerli-node/docker-volumes/{geth,prysm} 4. Save and Close the `docker-compose.yml` file. 5. Create an `.env` file and open it for editing: + ```bash cd ~/goerli-node/ vim .env ``` 6. Set the following environment variables in the `.env` file: + ```bash L1_RPC_PORT=8845 L1_SUGGESTED_FEE_RECIPIENT_ADDR=0x # Put your Goerli account address @@ -100,10 +107,12 @@ vim .env 7. Save and Close the `.env` file. 8. Add geth config.toml file with following values to increase RPC timeouts + ```bash cd ~/goerli-node/ vim config.toml ``` + ```bash [Node.HTTPTimeouts] ReadTimeout = 600000000000 @@ -115,26 +124,32 @@ IdleTimeout = 1200000000000 ## Deploy 1. Start the compose services: + ```bash cd ~/goerli-node/ docker compose --env-file /root/goerli-node/.env -f /root/goerli-node/docker-compose.yml up -d ``` 2. Check the logs of the prysm service to monitor the synchronization progress: + ```bash docker compose --env-file /root/goerli-node/.env -f /root/goerli-node/docker-compose.yml logs -f prysm --tail 20 ``` + Wait for the initial sync to complete. You will see log messages similar to the following indicating the progress: + ```bash #goerli-consensus | time="2023-06-19 09:39:44" level=info msg="Synced up to slot 5888296" prefix=initial-sync ``` 3. Check the logs of the geth service to monitor the initial download and sync progress: + ```bash docker compose --env-file /root/goerli-node/.env -f /root/goerli-node/docker-compose.yml logs -f geth --tail 20 ``` - This process may take a couple of hours. Look for log messages similar to the following indicating the progress: + ```bash #goerli-execution | INFO [06-19|09:43:24.954] Syncing beacon headers downloaded=25600 left=9,177,918 eta=1h5m31.860s #goerli-execution | INFO [06-19|10:09:19.488] Syncing: state download in progress synced=0.30% state=331.34MiB accounts=81053@20.52MiB slots=1,112,986@239.47MiB codes=11681@71.34MiB > diff --git a/docs/zkEVM/deployzkevm/step1-fullzkevm.md b/docs/zkEVM/deployzkevm/step1-fullzkevm.md index 789bdbfb8..8cc50c6af 100644 --- a/docs/zkEVM/deployzkevm/step1-fullzkevm.md +++ b/docs/zkEVM/deployzkevm/step1-fullzkevm.md @@ -16,13 +16,11 @@ However, in order to allow for in-between breaks, the process is aesthetically s - [**Sixth step**](step6-fullzkevm.md): Activating forced txs and Bridging/claiming Assets. - !!!caution Instructions in this document are subject to frequent updates as the zkEVM software is still in early development stages. Please report [here](https://support.polygon.technology/support/tickets/new) or reach out to our [support team on Discord](https://discord.com/invite/0xPolygon) if you encounter any issues. - ## Overview and setting up Implementing the full stack Polygon zkEVM involves more than just running an RPC zkNode or the Prover to validate batches, and deploying Smart Contracts. In its entirety, it encompasses all these processes and more. @@ -41,7 +39,6 @@ The below table enlists all the zkEVM components/services and their correspondin Our zkEVM deployment-guide provides CLI commands to automatically create these Docker containers. - | Component | Container | Brief\ Description | | :---------------- | :------------------- | ------------------------------------------------------------ | | Sequencer | zkevm-sequencer | Fetches txs from Pool DB, checks if valid, then puts valid ones into a batch. | @@ -62,11 +59,9 @@ Our zkEVM deployment-guide provides CLI commands to automatically create these D | Goërli Execution | goerli-execution | L1 node's execution layer. | | Goërli Consensus | goerli-consensus | L1 node's consensus layer. | - -!!!info +!!!info The **first step** of this deployment-guide begins here! - ### Preliminary setup Implementing the Polygon zkEVM requires either a Linux machine or a virtual machine running Linux as a Guest OS. @@ -91,7 +86,6 @@ In order to run multiple Docker containers, an extra tool called **docker compos !!!info One more thing, since the Prover is resource-heavy, you will need to run its container externally. Access to cloud computing services such as AWS EC2 or DigitalOcean will be required. - ### Prerequisites Next, ensure that you have checked your system specs, and have at hand all the variables listed below. @@ -124,12 +118,11 @@ The full prover is resource-intensive as it utilises the exact same proving stac - 96-core CPU - Minimum 768GB RAM - The Mock Prover is a dummy prover which simply adds a "Valid ✅" checkmark to every batch. !!!info The **mock prover**, on the other hand only requires: - + - 4-core CPU - 8GB RAM (16GB recommended) diff --git a/docs/zkEVM/deployzkevm/step2-fullzkevm.md b/docs/zkEVM/deployzkevm/step2-fullzkevm.md index 0ce8463e1..d74f961f8 100644 --- a/docs/zkEVM/deployzkevm/step2-fullzkevm.md +++ b/docs/zkEVM/deployzkevm/step2-fullzkevm.md @@ -39,7 +39,6 @@ Next, add these to your `.profile`: source .profile ``` - Lastly, confirm the installation of Golang by running this command: `$ go version` ## Download/extract mainnet files @@ -69,7 +68,6 @@ for url in "${urls[@]}"; do done ``` -