Skip to content

Commit 8e2e74a

Browse files
[Doc] Cleanup Bus-Mapping, ExecutionSteps, and ExecutionTrace (privacy-scaling-explorations#1775)
### Description - Bus-Mapping has two library docs, one is inside the lib.rs, another locates in README.md, untested. We remove the one in lib.rs and make the README one checked. - ExecutionSteps and ExecutionTrace were We hope the update can reduce confusion. ### Issue Link ### Type of change - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [x] This change requires a documentation update - [ ] Refactor (no updates to logic) ### How Has This Been Tested? ``` cargo test --doc ``` --------- Co-authored-by: sm.wu <[email protected]>
1 parent 4bdc733 commit 8e2e74a

File tree

11 files changed

+92
-317
lines changed

11 files changed

+92
-317
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ stats_evm_circuit: # Print a table with EVM Circuit stats by ExecState/opcode
7777
stats_copy_circuit: # Print a table with Copy Circuit stats by ExecState/opcode
7878
@cargo run --bin stats --features stats -- copy
7979

80-
evm_exec_steps_occupancy: # Print a table for each EVM-CellManager CellType with the top 10 occupancy ExecutionSteps associated
80+
evm_exec_steps_occupancy: # Print a table for each EVM-CellManager CellType with the top 10 occupancy ExecSteps associated
8181
@cargo run --bin stats --features stats -- exec
8282

8383
.PHONY: clippy doc fmt test test_benches test-all evm_bench state_bench circuit_benches evm_exec_steps_occupancy stats_state_circuit stats_evm_circuit stats_copy_circuit help

bus-mapping/README.md

+78-88
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,36 @@
11
# ZKEVM Bus-Mapping
22

3-
![GitHub Workflow Status (branch)](https://img.shields.io/github/workflow/status/appliedzkp/zkevm-circuits/CI%20checks/main?style=for-the-badge)
3+
The `Bus-Mapping` crate is designed to parse EVM execution traces and manipulate the data they provide to obtain structured witness inputs for the EVM Proof and the State Proof.
44

5-
`Bus-Mapping` is a crate designed to parse EVM execution traces and manipulate
6-
all of the data they provide in order to obtain structured witness inputs
7-
for the EVM Proof and the State Proof.
5+
## Introduction
86

9-
### Introduction
10-
At the moment every node on ethereum has to validate every transaction in
11-
the ethereum virtual machine. This means that every transaction adds work
12-
that everyone needs to do to verify Ethereum’s history. Worse still is that
13-
each transaction needs to be verified by every new node. Which means the
14-
amount of work a new node needs to do the sync the network is growing
15-
constantly. We want to build a proof of validity for the Ethereum blocks to
16-
avoid this.
7+
Currently, every node on Ethereum must validate every transaction in the Ethereum Virtual Machine (EVM). This means that each transaction adds work that everyone must do to verify Ethereum’s history. Furthermore, each transaction needs to be verified by every new node, leading to a growing amount of work for new nodes to sync the network. To address this, we aim to build a proof of validity for Ethereum blocks.
178

18-
This means making a proof of validity for the EVM + state reads / writes +
19-
signatures.
20-
To simplify we separate our proofs into two components.
9+
This involves creating a proof of validity for the EVM, including state reads/writes and signatures. To simplify, we divide our proofs into two components:
2110

22-
- State proof: State/memory/stack ops have been performed correctly. This
23-
does not check if the correct location has been read/written. We allow our
24-
prover to pick any location here and in the EVM proof confirm it is correct.
11+
- State Proof: Validates that state/memory/stack operations have been performed correctly. However, it does not verify if the correct location has been read/written. Our prover can select any location here and in the EVM proof confirm its correctness.
12+
- EVM Proof: Validates that the correct opcode is called at the correct time, checking the validity of these opcodes. It also confirms that for each of these opcodes, the state proof performed the correct operation.
2513

26-
- EVM proof: This checks that the correct opcode is called at the correct
27-
time. It checks the validity of these opcodes. It also confirms that for
28-
each of these opcodes the state proof performed the correct operation.
14+
Only after verifying both proofs can we be confident that the Ethereum block is executed correctly.
2915

30-
Only after verifying both proofs are we confident that that Ethereum block
31-
is executed correctly.
16+
## Bus Mapping
3217

33-
### Bus Mapping
3418
The goal of this crate is to serve as:
35-
- A parsing lib for EVM execution traces.
36-
- A way to infer some witness data that can only be constructed once we've
37-
analyzed the full exec trace.
38-
- An easy interface to collect all of the data to witness into the circuits
39-
and witness it with few function calls.
40-
41-
### Parsing
42-
Provided a JSON file or a JSON as a stream of bytes, which contains an
43-
execution trace from an EVM, you can parse it and construct an
44-
`ExecutionTrace` instance from it. That will automatically fill all of the
45-
bus-mapping instances of each
46-
[`ExecutionStep`](crate::exec_trace::ExecutionStep) plus fill in an
47-
[`OperationContainer`](crate::operation::container::OperationContainer) with
48-
all of the Memory, Stack and Storage ops performed by the provided trace.
19+
20+
- A parsing library for EVM execution traces.
21+
- A way to infer some witness data that can only be constructed once we've analyzed the full exec trace.
22+
- An easy interface to collect all of the data to witness into the circuits and witness it with few function calls.
23+
24+
## Parsing
25+
26+
Given a JSON file or a JSON stream containing an execution trace from an EVM, you can parse it and construct a [`GethExecTrace`](eth_types::GethExecTrace) instance from it. This will automatically populate all of the bus-mapping instances of each [`ExecStep`](crate::circuit_input_builder::ExecStep) and fill an [`OperationContainer`](crate::operation::OperationContainer) with all of the memory, stack, and storage operations performed by the provided trace.
4927

5028
```rust
51-
use bus_mapping::{ExecutionTrace, ExecutionStep, BlockConstants, Error, evm::EvmWord};
29+
use bus_mapping::mock::BlockData;
30+
use eth_types::{
31+
GethExecTrace, GethExecStep, geth_types::GethData, bytecode
32+
};
33+
use mock::test_ctx::{TestContext, helpers::*};
5234

5335
let input_trace = r#"
5436
[
@@ -98,31 +80,48 @@ let input_trace = r#"
9880
]
9981
"#;
10082

101-
let block_ctants = BlockConstants::new(
102-
Word::from(0),
103-
pasta_curves::Fp::zero(),
104-
pasta_curves::Fp::zero(),
105-
pasta_curves::Fp::zero(),
106-
pasta_curves::Fp::zero(),
107-
pasta_curves::Fp::zero(),
108-
pasta_curves::Fp::zero(),
109-
pasta_curves::Fp::zero(),
110-
);
111-
112-
// Here we have the ExecutionTrace completely formed with all of the data to witness structured.
113-
let obtained_exec_trace = ExecutionTrace::from_trace_bytes(
114-
input_trace.as_bytes(),
115-
block_ctants,
116-
).expect("Error on trace generation");
83+
// We use the [`TestContext`] struct to mock a block.
84+
let code = bytecode! {
85+
// Write 0x6f to storage slot 0
86+
PUSH1(0x6fu64)
87+
PUSH1(0x00u64)
88+
SSTORE
89+
// Load storage slot 0
90+
PUSH1(0x00u64)
91+
SLOAD
92+
STOP
93+
};
94+
// Get the execution steps from the external tracer
95+
let block: GethData = TestContext::<2, 1>::new(
96+
None,
97+
account_0_code_account_1_no_code(code),
98+
tx_from_1_to_0,
99+
|block, _tx| block.number(0xcafeu64),
100+
)
101+
.unwrap()
102+
.into();
103+
// Here we update the circuit input with the data from the transaction trace.
104+
let builder = BlockData::new_from_geth_data(block.clone()).new_circuit_input_builder();
105+
let builder = builder
106+
.handle_block(&block.eth_block, &block.geth_traces)
107+
.unwrap();
108+
let geth_steps: Vec<GethExecStep> = serde_json::from_str(input_trace).unwrap();
109+
let _geth_trace = GethExecTrace {
110+
return_value: "".to_string(),
111+
gas: block.eth_block.transactions[0].gas.as_u64(),
112+
invalid: false,
113+
failed: false,
114+
struct_logs: geth_steps,
115+
};
117116

118117
// Get an ordered vector with all of the Stack operations of this trace.
119-
let stack_ops = obtained_exec_trace.sorted_stack_ops();
120-
118+
let _stack_ops = builder.block.container.sorted_stack();
121119
// You can also iterate over the steps of the trace and witness the EVM Proof.
122-
obtained_exec_trace.steps().iter();
120+
let _ = builder.block.txs()[0].steps().iter();
123121
```
124122

125-
Assume we have the following trace:
123+
Assuming we have the following trace:
124+
126125
```text,ignore
127126
pc op stack (top -> down) memory
128127
-- -------------- ---------------------------------- ---------------------------------------
@@ -148,37 +147,28 @@ pc op stack (top -> down) memory
148147
...
149148
```
150149

151-
Once you have the trace built (following the code found above) you can
152-
basically:
153-
- Get an iterator/vector over the `Stack`, `Memory` or `Storage` operations
154-
ordered on the way the State Proof needs.
150+
Once you have built the trace (following the code above), you can:
151+
152+
- Get an iterator/vector over the `Stack`, `Memory`, or `Storage` operations ordered in the way the State Proof needs.
153+
154+
For the Memory operations, it might look like this:
155155

156-
On that way, we would get something like this for the Memory ops:
157156
```text,ignore
158-
| `key` | `val` | `rw` | `gc` | Note |
159-
|:------:| ------------- | ------- | ---- | ---------------------------------------- |
160-
| `0x40` | `0` | `Write` | | Init |
161-
| `0x40` | `0x80` | `Write` | 0 | Assume written at the beginning of `code`|
162-
| `0x40` | `0x80` | `Read` | 4 | `56 MLOAD` |
163-
| - | | | | |
164-
| `0x80` | `0` | `Write` | | Init |
165-
| `0x80` | `0xdeadbeef` | `Write` | 10 | `63 MSTORE` |
166-
| `0x80` | `0xdeadbeef` | `Read` | 16 | `70 MLOAD` |
167-
| `0x80` | `0x1d97c6efb` | `Write` | 24 | `73 MSTORE` |
168-
| - | | | | |
169-
| `0xa0` | `0` | `Write` | | Init |
170-
| `0xa0` | `0xcafeb0ba` | `Write` | 34 | `83 MSTORE`
157+
| `key` | `val` | `rw` | `gc` | Note |
158+
| :----: | ------------- | ------- | ---- | ----------------------------------------- |
159+
| `0x40` | `0` | `Write` | | Init |
160+
| `0x40` | `0x80` | `Write` | 0 | Assume written at the beginning of `code` |
161+
| `0x40` | `0x80` | `Read` | 4 | `56 MLOAD` |
162+
| - | | | | |
163+
| `0x80` | `0` | `Write` | | Init |
164+
| `0x80` | `0xdeadbeef` | `Write` | 10 | `63 MSTORE` |
165+
| `0x80` | `0xdeadbeef` | `Read` | 16 | `70 MLOAD` |
166+
| `0x80` | `0x1d97c6efb` | `Write` | 24 | `73 MSTORE` |
167+
| - | | | | |
168+
| `0xa0` | `0` | `Write` | | Init |
169+
| `0xa0` | `0xcafeb0ba` | `Write` | 34 | `83 MSTORE` |
171170
```
172171

173-
Where as you see, we group by `memory_address` and then order by
174-
`global_counter`.
175-
176-
- Iterate over the `ExecutionTrace` itself over
177-
each `ExecutionStep`'s is formed by and check which Stack/Memory&Storage operations are linked to each step.
178-
This is also automatically done via the
179-
[`Opcode`](crate::evm::opcodes::Opcode) trait defined in this crate.
172+
Here, we group by `memory_address` and then order by `global_counter`.
180173

181-
### Documentation
182-
For extra documentation, check the book with the specs written for the
183-
entire ZK-EVM solution.
184-
See: <https://hackmd.io/@liangcc/zkvmbook/https%3A%2F%2Fhackmd.io%2FAmhZ2ryITxicmhYFyQ0DEw#Bus-Mapping>
174+
- Iterate over the [`GethExecTrace`](eth_types::GethExecTrace) itself, over each [`ExecStep`](crate::circuit_input_builder::ExecStep) formed by, and check which Stack/Memory&Storage operations are linked to each step. This is also automatically done via the [`Opcode`](crate::evm::opcodes::Opcode) trait defined in this crate.

bus-mapping/src/circuit_input_builder/input_state_ref.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ impl<'a> CircuitInputStateRef<'a> {
121121
}
122122
}
123123

124-
/// Push an [`Operation`](crate::operation::Operation) into the
124+
/// Push an [`Operation`] into the
125125
/// [`OperationContainer`](crate::operation::OperationContainer) with the
126126
/// next [`RWCounter`](crate::operation::RWCounter) and then adds a
127127
/// reference to the stored operation ([`OperationRef`]) inside the
@@ -196,8 +196,7 @@ impl<'a> CircuitInputStateRef<'a> {
196196
self.push_op(step, RW::WRITE, op)
197197
}
198198

199-
/// Push an [`Operation`](crate::operation::Operation) with reversible to be
200-
/// true into the
199+
/// Push an [`Operation`] with reversible to be true into the
201200
/// [`OperationContainer`](crate::operation::OperationContainer) with the
202201
/// next [`RWCounter`](crate::operation::RWCounter) and then adds a
203202
/// reference to the stored operation

bus-mapping/src/evm/opcodes.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,7 @@ pub use crate::precompile::PrecompileCallArgs;
115115

116116
/// Generic opcode trait which defines the logic of the
117117
/// [`Operation`](crate::operation::Operation) that should be generated for one
118-
/// or multiple [`ExecStep`](crate::circuit_input_builder::ExecStep) depending
119-
/// of the [`OpcodeId`] it contains.
118+
/// or multiple [`ExecStep`] depending of the [`OpcodeId`] it contains.
120119
pub trait Opcode: Debug {
121120
/// Generate the associated [`MemoryOp`](crate::operation::MemoryOp)s,
122121
/// [`StackOp`](crate::operation::StackOp)s, and

bus-mapping/src/evm/opcodes/error_oog_exp.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::{
77
use eth_types::GethExecStep;
88

99
/// Placeholder structure used to implement [`Opcode`] trait over it
10-
/// corresponding to the [`OogError::Exp`](crate::error::OogError::Exp).
10+
/// corresponding to the [`OogError::Exp`].
1111
#[derive(Clone, Copy, Debug)]
1212
pub(crate) struct OOGExp;
1313

bus-mapping/src/evm/opcodes/error_oog_memory_copy.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ use crate::{
88
use eth_types::{evm_types::OpcodeId, GethExecStep, ToAddress};
99

1010
/// Placeholder structure used to implement [`Opcode`] trait over it
11-
/// corresponding to the
12-
/// [`OogError::MemoryCopy`](crate::error::OogError::MemoryCopy).
11+
/// corresponding to the [`OogError::MemoryCopy`].
1312
#[derive(Clone, Copy, Debug)]
1413
pub(crate) struct OOGMemoryCopy;
1514

bus-mapping/src/evm/opcodes/error_oog_sload_sstore.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ use crate::{
88
use eth_types::{GethExecStep, ToWord};
99

1010
/// Placeholder structure used to implement [`Opcode`] trait over it
11-
/// corresponding to the
12-
/// [`OogError::SloadSstore`](crate::error::OogError::SloadSstore).
11+
/// corresponding to the [`OogError::SloadSstore`].
1312
#[derive(Clone, Copy, Debug)]
1413
pub(crate) struct OOGSloadSstore;
1514

bus-mapping/src/exec_trace.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::fmt;
55

66
#[derive(Clone, Copy, PartialEq, Eq)]
77
/// The target and index of an `Operation` in the context of an
8-
/// `ExecutionTrace`.
8+
/// [`GethExecTrace`](eth_types::GethExecTrace).
99
pub struct OperationRef(pub Target, pub usize);
1010

1111
impl fmt::Debug for OperationRef {

0 commit comments

Comments
 (0)