1
+ use array_init:: array_init;
1
2
use bus_mapping:: precompile:: PrecompileAuxData ;
2
3
3
4
use eth_types:: { evm_types:: GasCost , Field , ToLittleEndian , ToScalar } ;
4
5
use gadgets:: util:: { select, Expr } ;
5
6
use halo2_proofs:: { circuit:: Value , plonk:: Error } ;
7
+ use itertools:: Itertools ;
6
8
7
9
use crate :: {
8
10
evm_circuit:: {
9
11
execution:: ExecutionGadget ,
10
- param:: N_BYTES_ACCOUNT_ADDRESS ,
12
+ param:: { N_BYTES_ACCOUNT_ADDRESS , N_BYTES_WORD } ,
11
13
step:: ExecutionState ,
12
14
util:: {
13
15
common_gadget:: RestoreContextGadget ,
@@ -22,13 +24,17 @@ use crate::{
22
24
#[ derive( Clone , Debug ) ]
23
25
pub struct EcrecoverGadget < F > {
24
26
recovered : Cell < F > ,
25
- msg_hash_rlc : Cell < F > ,
26
- sig_v_rlc : Cell < F > ,
27
- sig_r_rlc : Cell < F > ,
28
- sig_s_rlc : Cell < F > ,
29
- recovered_addr_rlc : RandomLinearCombination < F , N_BYTES_ACCOUNT_ADDRESS > ,
27
+ msg_hash_keccak_rlc : Cell < F > ,
28
+ sig_v_keccak_rlc : Cell < F > ,
29
+ sig_r_keccak_rlc : Cell < F > ,
30
+ sig_s_keccak_rlc : Cell < F > ,
31
+ recovered_addr_keccak_rlc : RandomLinearCombination < F , N_BYTES_ACCOUNT_ADDRESS > ,
30
32
gas_cost : Cell < F > ,
31
33
34
+ msg_hash : [ Cell < F > ; N_BYTES_WORD ] ,
35
+ sig_r : [ Cell < F > ; N_BYTES_WORD ] ,
36
+ sig_s : [ Cell < F > ; N_BYTES_WORD ] ,
37
+
32
38
is_success : Cell < F > ,
33
39
callee_address : Cell < F > ,
34
40
caller_id : Cell < F > ,
@@ -45,7 +51,14 @@ impl<F: Field> ExecutionGadget<F> for EcrecoverGadget<F> {
45
51
const NAME : & ' static str = "ECRECOVER" ;
46
52
47
53
fn configure ( cb : & mut EVMConstraintBuilder < F > ) -> Self {
48
- let ( recovered, msg_hash_rlc, sig_v_rlc, sig_r_rlc, sig_s_rlc, recovered_addr_rlc) = (
54
+ let (
55
+ recovered,
56
+ msg_hash_keccak_rlc,
57
+ sig_v_keccak_rlc,
58
+ sig_r_keccak_rlc,
59
+ sig_s_keccak_rlc,
60
+ recovered_addr_keccak_rlc,
61
+ ) = (
49
62
cb. query_bool ( ) ,
50
63
cb. query_cell_phase2 ( ) ,
51
64
cb. query_cell_phase2 ( ) ,
@@ -60,21 +73,41 @@ impl<F: Field> ExecutionGadget<F> for EcrecoverGadget<F> {
60
73
GasCost :: PRECOMPILE_ECRECOVER_BASE . expr ( ) ,
61
74
) ;
62
75
76
+ let msg_hash = array_init ( |_| cb. query_byte ( ) ) ;
77
+ let sig_r = array_init ( |_| cb. query_byte ( ) ) ;
78
+ let sig_s = array_init ( |_| cb. query_byte ( ) ) ;
79
+
80
+ cb. require_equal (
81
+ "msg hash cells assigned incorrectly" ,
82
+ msg_hash_keccak_rlc. expr ( ) ,
83
+ cb. keccak_rlc ( msg_hash. clone ( ) . map ( |x| x. expr ( ) ) ) ,
84
+ ) ;
85
+ cb. require_equal (
86
+ "sig_r cells assigned incorrectly" ,
87
+ sig_r_keccak_rlc. expr ( ) ,
88
+ cb. keccak_rlc ( sig_r. clone ( ) . map ( |x| x. expr ( ) ) ) ,
89
+ ) ;
90
+ cb. require_equal (
91
+ "sig_s cells assigned incorrectly" ,
92
+ sig_s_keccak_rlc. expr ( ) ,
93
+ cb. keccak_rlc ( sig_s. clone ( ) . map ( |x| x. expr ( ) ) ) ,
94
+ ) ;
95
+
63
96
cb. condition ( recovered. expr ( ) , |cb| {
64
97
// if address was recovered, the sig_v (recovery ID) was correct.
65
98
cb. require_zero (
66
99
"sig_v == 27 or 28" ,
67
- ( sig_v_rlc . expr ( ) - 27 . expr ( ) ) * ( sig_v_rlc . expr ( ) - 28 . expr ( ) ) ,
100
+ ( sig_v_keccak_rlc . expr ( ) - 27 . expr ( ) ) * ( sig_v_keccak_rlc . expr ( ) - 28 . expr ( ) ) ,
68
101
) ;
69
102
70
103
// lookup to the sign_verify table
71
104
// || v | r | s | msg_hash | recovered_addr ||
72
105
cb. sig_table_lookup (
73
- msg_hash_rlc . expr ( ) ,
74
- sig_v_rlc . expr ( ) - 27 . expr ( ) ,
75
- sig_r_rlc . expr ( ) ,
76
- sig_s_rlc . expr ( ) ,
77
- from_bytes:: expr ( & recovered_addr_rlc . cells ) ,
106
+ cb . word_rlc ( msg_hash . clone ( ) . map ( |x| x . expr ( ) ) ) ,
107
+ sig_v_keccak_rlc . expr ( ) - 27 . expr ( ) ,
108
+ cb . word_rlc ( sig_r . clone ( ) . map ( |x| x . expr ( ) ) ) ,
109
+ cb . word_rlc ( sig_s . clone ( ) . map ( |x| x . expr ( ) ) ) ,
110
+ from_bytes:: expr ( & recovered_addr_keccak_rlc . cells ) ,
78
111
) ;
79
112
} ) ;
80
113
@@ -108,13 +141,17 @@ impl<F: Field> ExecutionGadget<F> for EcrecoverGadget<F> {
108
141
109
142
Self {
110
143
recovered,
111
- msg_hash_rlc ,
112
- sig_v_rlc ,
113
- sig_r_rlc ,
114
- sig_s_rlc ,
115
- recovered_addr_rlc ,
144
+ msg_hash_keccak_rlc ,
145
+ sig_v_keccak_rlc ,
146
+ sig_r_keccak_rlc ,
147
+ sig_s_keccak_rlc ,
148
+ recovered_addr_keccak_rlc ,
116
149
gas_cost,
117
150
151
+ msg_hash,
152
+ sig_r,
153
+ sig_s,
154
+
118
155
is_success,
119
156
callee_address,
120
157
caller_id,
@@ -139,39 +176,48 @@ impl<F: Field> ExecutionGadget<F> for EcrecoverGadget<F> {
139
176
let recovered = !aux_data. recovered_addr . is_zero ( ) ;
140
177
self . recovered
141
178
. assign ( region, offset, Value :: known ( F :: from ( recovered as u64 ) ) ) ?;
142
- self . msg_hash_rlc . assign (
179
+ self . msg_hash_keccak_rlc . assign (
143
180
region,
144
181
offset,
145
182
region
146
183
. challenges ( )
147
184
. keccak_input ( )
148
185
. map ( |r| rlc:: value ( & aux_data. msg_hash . to_le_bytes ( ) , r) ) ,
149
186
) ?;
150
- self . sig_v_rlc . assign (
187
+ self . sig_v_keccak_rlc . assign (
151
188
region,
152
189
offset,
153
190
region
154
191
. challenges ( )
155
192
. keccak_input ( )
156
193
. map ( |r| rlc:: value ( & aux_data. sig_v . to_le_bytes ( ) , r) ) ,
157
194
) ?;
158
- self . sig_r_rlc . assign (
195
+ self . sig_r_keccak_rlc . assign (
159
196
region,
160
197
offset,
161
198
region
162
199
. challenges ( )
163
200
. keccak_input ( )
164
201
. map ( |r| rlc:: value ( & aux_data. sig_r . to_le_bytes ( ) , r) ) ,
165
202
) ?;
166
- self . sig_s_rlc . assign (
203
+ self . sig_s_keccak_rlc . assign (
167
204
region,
168
205
offset,
169
206
region
170
207
. challenges ( )
171
208
. keccak_input ( )
172
209
. map ( |r| rlc:: value ( & aux_data. sig_s . to_le_bytes ( ) , r) ) ,
173
210
) ?;
174
- self . recovered_addr_rlc . assign (
211
+ for ( cells, value) in [
212
+ ( & self . msg_hash , aux_data. msg_hash ) ,
213
+ ( & self . sig_r , aux_data. sig_r ) ,
214
+ ( & self . sig_s , aux_data. sig_s ) ,
215
+ ] {
216
+ for ( cell, & byte_value) in cells. iter ( ) . zip_eq ( value. to_le_bytes ( ) . iter ( ) ) {
217
+ cell. assign ( region, offset, Value :: known ( F :: from ( byte_value as u64 ) ) ) ?;
218
+ }
219
+ }
220
+ self . recovered_addr_keccak_rlc . assign (
175
221
region,
176
222
offset,
177
223
Some ( {
0 commit comments