@@ -3,53 +3,54 @@ extern crate reth_rlp;
3
3
4
4
use reth_primitives:: { Transaction , TransactionSigned } ;
5
5
use reth_rlp:: Decodable ;
6
- use std:: collections:: HashSet ;
7
6
use types:: { EthSpec , ExecutionPayloadRef , Hash256 , Unsigned , VersionedHash } ;
8
7
9
8
#[ derive( Debug ) ]
10
9
pub enum Error {
11
10
DecodingTransaction ( String ) ,
12
11
LengthMismatch { expected : usize , found : usize } ,
13
- MissingHash ( VersionedHash ) ,
12
+ VersionHashMismatch { expected : Hash256 , found : Hash256 } ,
14
13
}
15
14
16
15
pub fn verify_versioned_hashes < E : EthSpec > (
17
16
execution_payload : ExecutionPayloadRef < E > ,
18
- expected_versioned_hashes : & Vec < VersionedHash > ,
17
+ expected_versioned_hashes : & [ VersionedHash ] ,
19
18
) -> Result < ( ) , Error > {
20
- match execution_payload {
21
- ExecutionPayloadRef :: Merge ( _) | ExecutionPayloadRef :: Capella ( _) => Ok ( ( ) ) ,
22
- ExecutionPayloadRef :: Deneb ( payload) => {
23
- let versioned_hashes = get_versioned_hashes :: < E > ( & payload. transactions ) ?;
24
- // ensure that all expected hashes are present
25
- for expected_hash in expected_versioned_hashes {
26
- if !versioned_hashes. contains ( expected_hash) {
27
- return Err ( Error :: MissingHash ( * expected_hash) ) ;
28
- }
29
- }
30
- // ensure that there are no extra hashes
31
- if versioned_hashes. len ( ) != expected_versioned_hashes. len ( ) {
32
- return Err ( Error :: LengthMismatch {
33
- expected : expected_versioned_hashes. len ( ) ,
34
- found : versioned_hashes. len ( ) ,
35
- } ) ;
36
- }
37
- Ok ( ( ) )
19
+ let versioned_hashes =
20
+ extract_versioned_hashes_from_transactions :: < E > ( execution_payload. transactions ( ) ) ?;
21
+ if versioned_hashes. len ( ) != expected_versioned_hashes. len ( ) {
22
+ return Err ( Error :: LengthMismatch {
23
+ expected : expected_versioned_hashes. len ( ) ,
24
+ found : versioned_hashes. len ( ) ,
25
+ } ) ;
26
+ }
27
+ for ( found, expected) in versioned_hashes
28
+ . iter ( )
29
+ . zip ( expected_versioned_hashes. iter ( ) )
30
+ {
31
+ if found != expected {
32
+ return Err ( Error :: VersionHashMismatch {
33
+ expected : * expected,
34
+ found : * found,
35
+ } ) ;
38
36
}
39
37
}
38
+
39
+ Ok ( ( ) )
40
40
}
41
41
42
- pub fn get_versioned_hashes < E : EthSpec > (
42
+ pub fn extract_versioned_hashes_from_transactions < E : EthSpec > (
43
43
transactions : & types:: Transactions < E > ,
44
- ) -> Result < HashSet < VersionedHash > , Error > {
44
+ ) -> Result < Vec < VersionedHash > , Error > {
45
45
Ok ( transactions
46
46
. into_iter ( )
47
47
. map ( beacon_tx_to_reth_signed_tx)
48
48
. collect :: < Result < Vec < _ > , _ > > ( ) ?
49
49
. into_iter ( )
50
50
. filter_map ( |tx| match tx. transaction {
51
51
Transaction :: Eip4844 ( blob_tx) => Some ( blob_tx. blob_versioned_hashes ) ,
52
- _ => None ,
52
+ // enumerating all variants explicitly to make pattern irrefutable in case new types are added
53
+ Transaction :: Eip1559 ( _) | Transaction :: Eip2930 ( _) | Transaction :: Legacy ( _) => None ,
53
54
} )
54
55
. flatten ( )
55
56
. map ( Hash256 :: from)
@@ -70,9 +71,10 @@ mod test {
70
71
use crate :: static_valid_tx;
71
72
use reth_primitives:: Transaction ;
72
73
74
+ type E = types:: MainnetEthSpec ;
75
+
73
76
#[ test]
74
77
fn test_decode_reth_transaction ( ) {
75
- type E = types:: MainnetEthSpec ;
76
78
let valid_tx = static_valid_tx :: < E > ( ) . expect ( "should give me known valid transaction" ) ;
77
79
let tx = beacon_tx_to_reth_signed_tx ( & valid_tx) . expect ( "should decode tx" ) ;
78
80
assert ! ( matches!(
@@ -86,4 +88,35 @@ mod test {
86
88
} )
87
89
) ) ;
88
90
}
91
+
92
+ #[ test]
93
+ fn test_extract_versioned_hashes ( ) {
94
+ use serde:: Deserialize ;
95
+
96
+ #[ derive( Deserialize ) ]
97
+ #[ serde( transparent) ]
98
+ struct TestTransactions < E : EthSpec > (
99
+ #[ serde( with = "ssz_types::serde_utils::list_of_hex_var_list" ) ] types:: Transactions < E > ,
100
+ ) ;
101
+
102
+ let TestTransactions ( raw_transactions) : TestTransactions < E > = serde_json:: from_str ( r#"[
103
+ "0x03f901388501a1f0ff430f843b9aca00843b9aca0082520894e7249813d8ccf6fa95a2203f46a64166073d58878080c002f8c6a0012e98362c814f1724262c0d211a1463418a5f6382a8d457b37a2698afbe7b5ea00100ef985761395dfa8ed5ce91f3f2180b612401909e4cb8f33b90c8a454d9baa0013d45411623b90d90f916e4025ada74b453dd4ca093c017c838367c9de0f801a001753e2af0b1e70e7ef80541355b2a035cc9b2c177418bb2a4402a9b346cf84da0011789b520a8068094a92aa0b04db8d8ef1c6c9818947c5210821732b8744049a0011c4c4f95597305daa5f62bf5f690e37fa11f5de05a95d05cac4e2119e394db80a0ccd86a742af0e042d08cbb35d910ddc24bbc6538f9e53be6620d4b6e1bb77662a01a8bacbc614940ac2f5c23ffc00a122c9f085046883de65c88ab0edb859acb99",
104
+ "0x02f9017a8501a1f0ff4382363485012a05f2008512a05f2000830249f094c1b0bc605e2c808aa0867bfc98e51a1fe3e9867f80b901040cc7326300000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000009445a285baa43e00000000000000000000000000c500931f24edb821cef6e28f7adb33b38578c82000000000000000000000000fc7360b3b28cf4204268a8354dbec60720d155d2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000009a054a063f0fe7b9c68de8df91aaa5e96c15ab540000000000000000000000000c8d41b8fcc066cdabaf074d78e5153e8ce018a9c080a008e14475c1173cd9f5740c24c08b793f9e16c36c08fa73769db95050e31e3396a019767dcdda26c4a774ca28c9df15d0c20e43bd07bd33ee0f84d6096cb5a1ebed"
105
+ ]"# ) . expect ( "should get raw transactions" ) ;
106
+ let expected_versioned_hashes = vec ! [
107
+ "0x012e98362c814f1724262c0d211a1463418a5f6382a8d457b37a2698afbe7b5e" ,
108
+ "0x0100ef985761395dfa8ed5ce91f3f2180b612401909e4cb8f33b90c8a454d9ba" ,
109
+ "0x013d45411623b90d90f916e4025ada74b453dd4ca093c017c838367c9de0f801" ,
110
+ "0x01753e2af0b1e70e7ef80541355b2a035cc9b2c177418bb2a4402a9b346cf84d" ,
111
+ "0x011789b520a8068094a92aa0b04db8d8ef1c6c9818947c5210821732b8744049" ,
112
+ "0x011c4c4f95597305daa5f62bf5f690e37fa11f5de05a95d05cac4e2119e394db" ,
113
+ ]
114
+ . into_iter ( )
115
+ . map ( |tx| Hash256 :: from_slice ( & hex:: decode ( & tx[ 2 ..] ) . expect ( "should decode hex" ) ) )
116
+ . collect :: < Vec < _ > > ( ) ;
117
+
118
+ let versioned_hashes = extract_versioned_hashes_from_transactions :: < E > ( & raw_transactions)
119
+ . expect ( "should get versioned hashes" ) ;
120
+ assert_eq ! ( versioned_hashes, expected_versioned_hashes) ;
121
+ }
89
122
}
0 commit comments