1010//! Both bytecode kinds are right-padded to consist of an integer, odd number of 32-byte words. All methods
1111//! in this module operate on padded bytecodes unless explicitly specified otherwise.
1212
13+ use std:: iter;
14+
1315use anyhow:: Context as _;
1416use sha2:: { Digest , Sha256 } ;
1517
@@ -68,21 +70,31 @@ pub struct BytecodeHash(H256);
6870impl BytecodeHash {
6971 /// Hashes the provided EraVM bytecode.
7072 pub fn for_bytecode ( bytecode : & [ u8 ] ) -> Self {
71- Self :: for_generic_bytecode ( BytecodeMarker :: EraVm , bytecode)
73+ Self :: for_generic_bytecode ( BytecodeMarker :: EraVm , bytecode, bytecode . len ( ) )
7274 }
7375
7476 /// Hashes the provided padded EVM bytecode.
75- pub fn for_evm_bytecode ( bytecode : & [ u8 ] ) -> Self {
76- Self :: for_generic_bytecode ( BytecodeMarker :: Evm , bytecode)
77+ pub fn for_evm_bytecode ( raw_bytecode_len : usize , bytecode : & [ u8 ] ) -> Self {
78+ Self :: for_generic_bytecode ( BytecodeMarker :: Evm , bytecode, raw_bytecode_len)
79+ }
80+
81+ /// Hashes the provided raw EVM bytecode.
82+ pub fn for_raw_evm_bytecode ( bytecode : & [ u8 ] ) -> Self {
83+ let padded_evm_bytecode = pad_evm_bytecode ( bytecode) ;
84+ Self :: for_evm_bytecode ( bytecode. len ( ) , & padded_evm_bytecode)
7785 }
7886
79- fn for_generic_bytecode ( kind : BytecodeMarker , bytecode : & [ u8 ] ) -> Self {
87+ fn for_generic_bytecode (
88+ kind : BytecodeMarker ,
89+ bytecode : & [ u8 ] ,
90+ bytecode_len_in_bytes : usize ,
91+ ) -> Self {
8092 validate_bytecode ( bytecode) . expect ( "invalid bytecode" ) ;
8193
8294 let mut hasher = Sha256 :: new ( ) ;
8395 let len = match kind {
84- BytecodeMarker :: EraVm => ( bytecode . len ( ) / 32 ) as u16 ,
85- BytecodeMarker :: Evm => bytecode . len ( ) as u16 ,
96+ BytecodeMarker :: EraVm => ( bytecode_len_in_bytes / 32 ) as u16 ,
97+ BytecodeMarker :: Evm => bytecode_len_in_bytes as u16 ,
8698 } ;
8799 hasher. update ( bytecode) ;
88100 let result = hasher. finalize ( ) ;
@@ -157,46 +169,65 @@ impl BytecodeMarker {
157169}
158170
159171/// Removes padding from an EVM bytecode, returning the original EVM bytecode.
160- pub fn trim_padded_evm_bytecode ( raw : & [ u8 ] ) -> anyhow:: Result < & [ u8 ] > {
172+ pub fn trim_padded_evm_bytecode ( bytecode_hash : BytecodeHash , raw : & [ u8 ] ) -> anyhow:: Result < & [ u8 ] > {
173+ if bytecode_hash. marker ( ) != BytecodeMarker :: Evm {
174+ anyhow:: bail!( "only EVM bytecode hashes allowed" )
175+ }
161176 validate_bytecode ( raw) . context ( "bytecode fails basic validity checks" ) ?;
162177
163- // EVM bytecodes are prefixed with a big-endian `U256` bytecode length.
164- let bytecode_len_bytes = raw. get ( ..32 ) . context ( "length < 32" ) ?;
165- let bytecode_len = U256 :: from_big_endian ( bytecode_len_bytes) ;
166- let bytecode_len: usize = bytecode_len
167- . try_into ( )
168- . map_err ( |_| anyhow:: anyhow!( "length ({bytecode_len}) overflow" ) ) ?;
169- let bytecode = raw. get ( 32 ..( 32 + bytecode_len) ) . with_context ( || {
178+ // Actual raw unpadded EVM bytecode length is encoded in bytecode hash
179+ let bytecode_len: usize = bytecode_hash. len_in_bytes ( ) ;
180+ let bytecode = raw. get ( 0 ..bytecode_len) . with_context ( || {
170181 format ! (
171- "prefixed length ({bytecode_len}) exceeds real length ({})" ,
172- raw. len( ) - 32
182+ "encoded length ({bytecode_len}) exceeds real length ({})" ,
183+ raw. len( )
173184 )
174185 } ) ?;
175186 // Since slicing above succeeded, this one is safe.
176- let padding = & raw [ ( 32 + bytecode_len) ..] ;
187+ let padding = & raw [ bytecode_len..] ;
177188 anyhow:: ensure!(
178189 padding. iter( ) . all( |& b| b == 0 ) ,
179190 "bytecode padding contains non-zero bytes"
180191 ) ;
181192 Ok ( bytecode)
182193}
183194
195+ /// Pads an EVM bytecode in the same ways it's done by system contracts.
196+ pub fn pad_evm_bytecode ( deployed_bytecode : & [ u8 ] ) -> Vec < u8 > {
197+ let mut padded = Vec :: with_capacity ( deployed_bytecode. len ( ) ) ;
198+ padded. extend_from_slice ( deployed_bytecode) ;
199+
200+ // Pad to the 32-byte word boundary.
201+ if padded. len ( ) % 32 != 0 {
202+ padded. extend ( iter:: repeat ( 0 ) . take ( 32 - padded. len ( ) % 32 ) ) ;
203+ }
204+ assert_eq ! ( padded. len( ) % 32 , 0 ) ;
205+
206+ // Pad to contain the odd number of words.
207+ if ( padded. len ( ) / 32 ) % 2 != 1 {
208+ padded. extend_from_slice ( & [ 0 ; 32 ] ) ;
209+ }
210+ assert_eq ! ( ( padded. len( ) / 32 ) % 2 , 1 ) ;
211+ padded
212+ }
213+
184214#[ doc( hidden) ] // only useful for tests
185215pub mod testonly {
186216 use const_decoder:: Decoder ;
187217
188- pub const RAW_EVM_BYTECODE : & [ u8 ] = & const_decoder:: decode!(
218+ pub const PADDED_EVM_BYTECODE : & [ u8 ] = & const_decoder:: decode!(
189219 Decoder :: Hex ,
190- b"00000000000000000000000000000000000000000000000000000000000001266080604052348015 \
191- 600e575f80fd5b50600436106030575f3560e01c8063816898ff146034578063fb5343f314604c57 \
192- 5b5f80fd5b604a60048036038101906046919060a6565b6066565b005b6052606f565b604051605d \
193- 919060d9565b60405180910390f35b805f8190555050565b5f5481565b5f80fd5b5f819050919050 \
194- 565b6088816078565b81146091575f80fd5b50565b5f8135905060a0816081565b92915050565b5f \
195- 6020828403121560b85760b76074565b5b5f60c3848285016094565b91505092915050565b60d381 \
196- 6078565b82525050565b5f60208201905060ea5f83018460cc565b9291505056fea2646970667358 \
197- 221220caca1247066da378f2ec77c310f2ae51576272367b4fa11cc4350af4e9ce4d0964736f6c63 \
198- 4300081a00330000000000000000000000000000000000000000000000000000 "
220+ b"6080604052348015600e575f80fd5b50600436106030575f3560e01c8063816898ff146034578063 \
221+ fb5343f314604c575b5f80fd5b604a60048036038101906046919060a6565b6066565b005b605260 \
222+ 6f565b604051605d919060d9565b60405180910390f35b805f8190555050565b5f5481565b5f80fd \
223+ 5b5f819050919050565b6088816078565b81146091575f80fd5b50565b5f8135905060a081608156 \
224+ 5b92915050565b5f6020828403121560b85760b76074565b5b5f60c3848285016094565b91505092 \
225+ 915050565b60d3816078565b82525050565b5f60208201905060ea5f83018460cc565b9291505056 \
226+ fea2646970667358221220caca1247066da378f2ec77c310f2ae51576272367b4fa11cc4350af4e9 \
227+ ce4d0964736f6c634300081a00330000000000000000000000000000000000000000000000000000 \
228+ 0000000000000000000000000000000000000000000000000000000000000000 "
199229 ) ;
230+
200231 pub const PROCESSED_EVM_BYTECODE : & [ u8 ] = & const_decoder:: decode!(
201232 Decoder :: Hex ,
202233 b"6080604052348015600e575f80fd5b50600436106030575f3560e01c8063816898ff146034578063\
@@ -213,7 +244,7 @@ pub mod testonly {
213244#[ cfg( test) ]
214245mod tests {
215246 use super :: {
216- testonly:: { PROCESSED_EVM_BYTECODE , RAW_EVM_BYTECODE } ,
247+ testonly:: { PADDED_EVM_BYTECODE , PROCESSED_EVM_BYTECODE } ,
217248 * ,
218249 } ;
219250
@@ -223,14 +254,20 @@ mod tests {
223254 assert_eq ! ( bytecode_hash. marker( ) , BytecodeMarker :: EraVm ) ;
224255 assert_eq ! ( bytecode_hash. len_in_bytes( ) , 32 ) ;
225256
226- let bytecode_hash = BytecodeHash :: for_evm_bytecode ( & [ 0 ; 32 ] ) ;
257+ let bytecode_hash = BytecodeHash :: for_raw_evm_bytecode ( & [ 0 ; 32 ] ) ;
258+ assert_eq ! ( bytecode_hash. marker( ) , BytecodeMarker :: Evm ) ;
259+ assert_eq ! ( bytecode_hash. len_in_bytes( ) , 32 ) ;
260+
261+ let bytecode_hash = BytecodeHash :: for_evm_bytecode ( 32 , & [ 0 ; 96 ] ) ;
227262 assert_eq ! ( bytecode_hash. marker( ) , BytecodeMarker :: Evm ) ;
228263 assert_eq ! ( bytecode_hash. len_in_bytes( ) , 32 ) ;
229264 }
230265
231266 #[ test]
232267 fn preparing_evm_bytecode ( ) {
233- let prepared = trim_padded_evm_bytecode ( RAW_EVM_BYTECODE ) . unwrap ( ) ;
268+ let bytecode_hash =
269+ BytecodeHash :: for_evm_bytecode ( PROCESSED_EVM_BYTECODE . len ( ) , & PADDED_EVM_BYTECODE ) ;
270+ let prepared = trim_padded_evm_bytecode ( bytecode_hash, PADDED_EVM_BYTECODE ) . unwrap ( ) ;
234271 assert_eq ! ( prepared, PROCESSED_EVM_BYTECODE ) ;
235272 }
236273}
0 commit comments