1use ethers_core::types::{Address, Block, Chain, H256, U256};
2#[cfg(feature = "providers")]
3use ethers_providers::{JsonRpcClient, Provider};
4use halo2_base::{gates::GateInstructions, Context};
5use itertools::Itertools;
6use serde::{Deserialize, Serialize};
7use std::marker::PhantomData;
8use zkevm_hashes::util::eth_types::ToBigEndian;
9
10use crate::{
11 block_header::get_block_header_rlp_max_lens,
12 mpt::{MPTChip, MPTInput},
13 rlc::{circuit::builder::RlcCircuitBuilder, FIRST_PHASE},
14 utils::{
15 assign_vec, encode_addr_to_field, encode_h256_to_hilo, eth_circuit::EthCircuitInstructions,
16 },
17 Field,
18};
19
20use super::{
21 EIP1186ResponseDigest, EthBlockAccountStorageWitness, EthBlockStorageInputAssigned,
22 EthStorageChip, EthStorageInputAssigned,
23};
24
25#[derive(Clone, Debug, Hash, Serialize, Deserialize)]
26pub struct EthStorageInput {
27 pub addr: Address,
28 pub acct_pf: MPTInput,
29 pub acct_state: Vec<Vec<u8>>,
30 pub storage_pfs: Vec<(U256, U256, MPTInput)>,
32}
33
34#[derive(Clone, Debug, Deserialize, Serialize)]
35pub struct EthBlockStorageInput {
36 pub block: Block<H256>,
37 pub block_number: u32,
38 pub block_hash: H256, pub block_header: Vec<u8>,
40 pub storage: EthStorageInput,
41}
42
43impl EthStorageInput {
44 pub fn assign<F: Field>(self, ctx: &mut Context<F>) -> EthStorageInputAssigned<F> {
45 let address = encode_addr_to_field(&self.addr);
46 let address = ctx.load_witness(address);
47 let acct_pf = self.acct_pf.assign(ctx);
48 let storage_pfs = self
49 .storage_pfs
50 .into_iter()
51 .map(|(slot, _, pf)| {
52 let slot = encode_h256_to_hilo(&H256(slot.to_be_bytes())).hi_lo();
53 let slot = slot.map(|slot| ctx.load_witness(slot));
54 let pf = pf.assign(ctx);
55 (slot, pf)
56 })
57 .collect();
58 EthStorageInputAssigned { address, acct_pf, storage_pfs }
59 }
60}
61
62impl EthBlockStorageInput {
63 pub fn assign<F: Field>(
64 self,
65 ctx: &mut Context<F>,
66 network: Chain,
67 ) -> EthBlockStorageInputAssigned<F> {
68 let storage = self.storage.assign(ctx);
71 let max_len = get_block_header_rlp_max_lens(network).0;
72 let block_header = assign_vec(ctx, self.block_header, max_len);
73 EthBlockStorageInputAssigned { block_header, storage }
74 }
75}
76
77#[derive(Clone, Debug)]
78pub struct EthBlockStorageCircuit<F> {
79 pub inputs: EthBlockStorageInput, pub network: Chain,
81 _marker: PhantomData<F>,
82}
83
84impl<F> EthBlockStorageCircuit<F> {
85 pub fn new(inputs: EthBlockStorageInput, network: Chain) -> Self {
86 Self { inputs, network, _marker: PhantomData }
87 }
88
89 #[cfg(feature = "providers")]
90 pub fn from_provider<P: JsonRpcClient>(
91 provider: &Provider<P>,
92 block_number: u32,
93 address: Address,
94 slots: Vec<H256>,
95 acct_pf_max_depth: usize,
96 storage_pf_max_depth: usize,
97 network: Chain,
98 ) -> Self {
99 use crate::providers::storage::get_block_storage_input;
100
101 let inputs = get_block_storage_input(
102 provider,
103 block_number,
104 address,
105 slots,
106 acct_pf_max_depth,
107 storage_pf_max_depth,
108 );
109 Self::new(inputs, network)
110 }
111}
112
113impl<F: Field> EthCircuitInstructions<F> for EthBlockStorageCircuit<F> {
114 type FirstPhasePayload = (EthBlockAccountStorageWitness<F>, Chain);
115
116 fn virtual_assign_phase0(
117 &self,
118 builder: &mut RlcCircuitBuilder<F>,
119 mpt: &MPTChip<F>,
120 ) -> Self::FirstPhasePayload {
121 let chip = EthStorageChip::new(mpt, Some(self.network));
122 let ctx = builder.base.main(FIRST_PHASE);
124 let input = self.inputs.clone().assign(ctx, self.network);
125 let (witness, digest) = chip.parse_eip1186_proofs_from_block_phase0(builder, input);
126 let EIP1186ResponseDigest {
127 block_hash,
128 block_number,
129 address,
130 slots_values,
131 address_is_empty,
132 slot_is_empty,
133 } = digest;
134 let assigned_instances = block_hash
135 .into_iter()
136 .chain([block_number, address])
137 .chain(slots_values.into_iter().flat_map(|(slot, value)| slot.into_iter().chain(value)))
138 .collect_vec();
139 assert_eq!(builder.base.assigned_instances.len(), 1);
140 builder.base.assigned_instances[0] = assigned_instances;
141 {
143 let ctx = builder.base.main(FIRST_PHASE);
144 mpt.gate().assert_is_const(ctx, &address_is_empty, &F::ZERO);
145 for slot_is_empty in slot_is_empty {
146 mpt.gate().assert_is_const(ctx, &slot_is_empty, &F::ZERO);
147 }
148 }
149 (witness, self.network)
150 }
151
152 fn virtual_assign_phase1(
153 &self,
154 builder: &mut RlcCircuitBuilder<F>,
155 mpt: &MPTChip<F>,
156 (witness, network): Self::FirstPhasePayload,
157 ) {
158 let chip = EthStorageChip::new(mpt, Some(network));
159 let _trace = chip.parse_eip1186_proofs_from_block_phase1(builder, witness);
160 }
161}