1
+ use std:: collections:: HashMap ;
2
+
3
+ use super :: circuit:: {
4
+ MAX_BYTECODE , MAX_CALLDATA , MAX_EXP_STEPS , MAX_KECCAK_ROWS , MAX_MPT_ROWS , MAX_POSEIDON_ROWS ,
5
+ MAX_RWS , MAX_VERTICLE_ROWS ,
6
+ } ;
7
+
1
8
use super :: circuit:: {
2
9
block_traces_to_witness_block_with_updated_state, calculate_row_usage_of_witness_block,
3
10
fill_zktrie_state_from_proofs,
4
11
} ;
12
+ use eth_types:: H256 ;
5
13
use itertools:: Itertools ;
6
14
use mpt_zktrie:: state:: ZktrieState ;
7
15
use serde_derive:: { Deserialize , Serialize } ;
@@ -38,41 +46,21 @@ impl RowUsage {
38
46
}
39
47
// We treat 1M as 100%
40
48
pub fn normalize ( & self ) -> Self {
41
- /*
42
- const MAX_TXS: usize = 100;
43
- const MAX_INNER_BLOCKS: usize = 100;
44
- const MAX_EXP_STEPS: usize = 10_000;
45
- const MAX_CALLDATA: usize = 400_000;
46
- const MAX_BYTECODE: usize = 400_000;
47
- const MAX_MPT_ROWS: usize = 400_000;
48
- const MAX_KECCAK_ROWS: usize = 524_000;
49
- const MAX_RWS: usize = 1_000_000;
50
- const MAX_PRECOMPILE_EC_ADD: usize = 50;
51
- const MAX_PRECOMPILE_EC_MUL: usize = 50;
52
- const MAX_PRECOMPILE_EC_PAIRING: usize = 2;
53
- */
54
- use super :: circuit:: {
55
- MAX_BYTECODE , MAX_CALLDATA , MAX_EXP_STEPS , MAX_KECCAK_ROWS , MAX_MPT_ROWS , MAX_RWS ,
56
- } ;
57
- // 14 in total
58
- // "evm", "state", "bytecode", "copy",
59
- // "keccak", "tx", "rlp", "exp", "modexp", "pi",
60
- // "poseidon", "sig", "ecc", "mpt",
61
49
let real_available_rows = [
62
- MAX_RWS ,
63
- MAX_RWS ,
64
- MAX_BYTECODE ,
65
- MAX_RWS ,
66
- MAX_KECCAK_ROWS ,
67
- MAX_CALLDATA ,
68
- MAX_CALLDATA ,
50
+ MAX_RWS , // evm
51
+ MAX_RWS , // state
52
+ MAX_BYTECODE , // bytecode
53
+ MAX_RWS , // copy
54
+ MAX_KECCAK_ROWS , // keccak
55
+ MAX_CALLDATA , // tx
56
+ MAX_CALLDATA , // rlp
69
57
7 * MAX_EXP_STEPS , // exp
70
- MAX_KECCAK_ROWS ,
71
- MAX_RWS ,
72
- MAX_MPT_ROWS , // poseidon
73
- ( 1 << 20 ) - 256 , // sig
74
- ( 1 << 20 ) - 256 , // FIXME: pairing may be limit to 1, fix later
75
- MAX_MPT_ROWS ,
58
+ MAX_KECCAK_ROWS , // modexp
59
+ MAX_RWS , // pi
60
+ MAX_POSEIDON_ROWS , // poseidon
61
+ MAX_VERTICLE_ROWS , // sig
62
+ MAX_VERTICLE_ROWS , // ecc
63
+ MAX_MPT_ROWS , // mpt
76
64
]
77
65
. map ( |x| ( x as f32 * 0.95 ) as usize ) ;
78
66
let details = self
@@ -131,6 +119,8 @@ pub struct CircuitCapacityChecker {
131
119
pub acc_row_usage : RowUsage ,
132
120
pub row_usages : Vec < RowUsage > ,
133
121
pub state : Option < ZktrieState > ,
122
+ // poseidon codehash to code len
123
+ pub codelen : HashMap < H256 , usize > ,
134
124
}
135
125
136
126
// Currently TxTrace is same as BlockTrace, with "transactions" and "executionResults" should be of
@@ -151,27 +141,42 @@ impl CircuitCapacityChecker {
151
141
row_usages : Vec :: new ( ) ,
152
142
state : None ,
153
143
light_mode : true ,
144
+ codelen : HashMap :: new ( ) ,
154
145
}
155
146
}
156
147
pub fn reset ( & mut self ) {
157
148
self . state = None ;
158
149
self . acc_row_usage = RowUsage :: new ( ) ;
159
150
self . row_usages = Vec :: new ( ) ;
151
+ self . codelen = HashMap :: new ( ) ;
160
152
}
161
153
pub fn estimate_circuit_capacity (
162
154
& mut self ,
163
155
txs : & [ TxTrace ] ,
164
- ) -> Result < ( RowUsage , RowUsage ) , anyhow:: Error > {
156
+ ) -> Result < RowUsage , anyhow:: Error > {
165
157
assert ! ( !txs. is_empty( ) ) ;
166
158
if self . state . is_none ( ) {
167
159
self . state = Some ( ZktrieState :: construct ( txs[ 0 ] . storage_trace . root_before ) ) ;
168
160
}
169
161
let traces = txs;
170
162
let state = self . state . as_mut ( ) . unwrap ( ) ;
171
163
fill_zktrie_state_from_proofs ( state, traces, self . light_mode ) ?;
172
- let witness_block =
164
+ let ( witness_block, codedb ) =
173
165
block_traces_to_witness_block_with_updated_state ( traces, state, self . light_mode ) ?;
174
- let rows = calculate_row_usage_of_witness_block ( & witness_block) ?;
166
+ let mut rows = calculate_row_usage_of_witness_block ( & witness_block) ?;
167
+
168
+ // Dedup bytecode row usage for bytecode circuit / poseidon circuit
169
+ for ( hash, bytes) in & codedb. 0 {
170
+ if self . codelen . contains_key ( hash) {
171
+ assert_eq ! ( rows[ 2 ] . name, "bytecode" ) ;
172
+ rows[ 2 ] . row_num_real -= bytes. len ( ) + 1 ;
173
+ assert_eq ! ( rows[ 10 ] . name, "poseidon" ) ;
174
+ rows[ 10 ] . row_num_real -= bytes. len ( ) / ( 31 * 2 ) * 9 ;
175
+ } else {
176
+ self . codelen . insert ( * hash, bytes. len ( ) ) ;
177
+ }
178
+ }
179
+
175
180
let row_usage_details: Vec < SubCircuitRowUsage > = rows
176
181
. into_iter ( )
177
182
. map ( |x| SubCircuitRowUsage {
@@ -182,6 +187,6 @@ impl CircuitCapacityChecker {
182
187
let tx_row_usage = RowUsage :: from_row_usage_details ( row_usage_details) ;
183
188
self . row_usages . push ( tx_row_usage. clone ( ) ) ;
184
189
self . acc_row_usage . add ( & tx_row_usage) ;
185
- Ok ( ( self . acc_row_usage . normalize ( ) , tx_row_usage . normalize ( ) ) )
190
+ Ok ( self . acc_row_usage . normalize ( ) )
186
191
}
187
192
}
0 commit comments