eth_rlp_verify/block_header.rs
1use ethereum_types::H256;
2use sha3::{Digest, Keccak256};
3
4/// Represents an Ethereum block header with various properties like block hash, gas limits, and more.
5///
6/// This struct provides a way to store and manipulate data related to an Ethereum block header,
7/// including cryptographic information (like the block hash and state root), as well as metadata
8/// about the block (such as gas usage and the miner address). It supports fields with optional values,
9/// as certain block headers may lack specific information, depending on their context in the chain.
10///
11/// # Fields
12///
13/// - `block_hash`: The unique identifier for the block, as a 66-character hexadecimal string (not null).
14/// - `number`: The block number, a sequential integer starting from 0 (not null).
15/// - `gas_limit`: The maximum amount of gas that can be spent on transactions in this block (not null).
16/// - `gas_used`: The actual amount of gas used by transactions within the block (not null).
17/// - `nonce`: A 78-character string representing the proof-of-work nonce (not null).
18/// - `transaction_root`: The Merkle root of the transactions in the block, if available (optional).
19/// - `receipts_root`: The Merkle root of the transaction receipts in the block, if available (optional).
20/// - `state_root`: The root of the state trie after transactions in the block are processed (optional).
21/// - `base_fee_per_gas`: The base fee per gas for the block in the new fee market mechanism (optional).
22/// - `parent_hash`: The hash of the previous block, which this block references (optional).
23/// - `ommers_hash`: The hash of the ommers (or uncles), which are alternative blocks that could have been part of the chain (optional).
24/// - `miner`: The address of the miner that mined the block (optional).
25/// - `logs_bloom`: The bloom filter for logs included in the block, useful for filtering logs efficiently (optional).
26/// - `difficulty`: The difficulty level required to mine the block (optional).
27/// - `total_difficulty`: The total difficulty of the chain up to this block (optional).
28/// - `sha3_uncles`: The SHA3 hash of the uncles (ommers) included in the block (optional).
29/// - `timestamp`: The time at which the block was mined, as a string (optional).
30/// - `extra_data`: Extra data included in the block, up to 1024 bytes (optional).
31/// - `mix_hash`: A hash used to verify the proof of work, ensuring that the mining process was valid (optional).
32/// - `withdrawals_root`: The Merkle root of withdrawal data for withdrawals included in the block, if any (optional).
33/// - `blob_gas_used`: The amount of blob gas used, specific to blob transactions (optional).
34/// - `excess_blob_gas`: The excess blob gas present in the block (optional).
35/// - `parent_beacon_block_root`: The root of the parent beacon block, used in Ethereum's proof-of-stake chain (optional).
36#[derive(Debug)]
37pub struct BlockHeader {
38 pub block_hash: String, // character(66) NOT NULL
39 pub number: i64, // bigint NOT NULL
40 pub gas_limit: i64, // bigint NOT NULL
41 pub gas_used: i64, // bigint NOT NULL
42 pub nonce: String, // character varying(78) NOT NULL
43 pub transaction_root: Option<String>, // character(66)
44 pub receipts_root: Option<String>, // character(66)
45 pub state_root: Option<String>, // character(66)
46 pub base_fee_per_gas: Option<String>, // character varying(78)
47 pub parent_hash: Option<String>,
48 pub ommers_hash: Option<String>, // character varying(66)
49 pub miner: Option<String>, // character varying(42)
50 pub logs_bloom: Option<String>, // character varying(1024)
51 pub difficulty: Option<String>, // character varying(78)
52 pub total_difficulty: Option<String>, // character varying(78)
53 pub sha3_uncles: Option<String>, // character varying(66)
54 pub timestamp: Option<String>, // character varying(100)
55 pub extra_data: Option<String>, // character varying(1024)
56 pub mix_hash: Option<String>, // character varying(66)
57 pub withdrawals_root: Option<String>, // character varying(66)
58 pub blob_gas_used: Option<String>, // character varying(78)
59 pub excess_blob_gas: Option<String>, // character varying(78)
60 pub parent_beacon_block_root: Option<String>, // character varying(66)
61}
62
63/// A trait that defines common behaviors for Ethereum block headers, including RLP encoding and hash computation.
64///
65/// This trait provides methods to handle standard operations on Ethereum block headers such as encoding
66/// and hashing, which are critical for verifying the integrity of a block and its inclusion in the blockchain.
67/// It also provides a utility method for converting hexadecimal strings into fixed-size byte arrays, which is
68/// useful when handling Ethereum's cryptographic data.
69///
70/// # Example
71///
72/// ```rust
73/// struct MyBlockHeader {
74/// // block header fields...
75/// }
76///
77/// impl BlockHeaderTrait for MyBlockHeader {
78/// fn rlp_encode(&self) -> Vec<u8> {
79/// // perform RLP encoding...
80/// }
81/// }
82///
83/// let my_header = MyBlockHeader { /* fields... */ };
84/// let block_hash = my_header.compute_hash();
85/// ```
86pub trait BlockHeaderTrait {
87 /// Encodes the block header using RLP (Recursive Length Prefix) encoding, which is used to serialize Ethereum objects.
88 ///
89 /// This method should encode the block header into a byte vector using RLP encoding. It is essential for
90 /// transmitting the block header in a compact format or for use in cryptographic operations, such as computing
91 /// the block hash.
92 ///
93 /// # Returns
94 ///
95 /// A `Vec<u8>` containing the RLP-encoded block header.
96 fn rlp_encode(&self) -> Vec<u8>;
97
98 /// Computes the Keccak256 hash of the block header.
99 ///
100 /// This method first encodes the block header using the `rlp_encode` method and then computes the Keccak256
101 /// hash of the resulting bytes. This hash is used as the block's unique identifier (`block_hash`) in the Ethereum
102 /// blockchain and plays a crucial role in the consensus and security mechanisms.
103 ///
104 /// # Returns
105 ///
106 /// An `H256` hash, representing the 32-byte Keccak256 hash of the block header.
107 fn compute_hash(&self) -> H256 {
108 let rlp_encoded = self.rlp_encode();
109 let hash = Keccak256::digest(rlp_encoded);
110 H256::from_slice(&hash)
111 }
112
113 /// Converts a hexadecimal string to a fixed-size byte array.
114 ///
115 /// This utility function converts a hexadecimal string (prefixed with "0x") into a fixed-size array of bytes.
116 /// It ensures that the length of the byte array matches the expected size, and will panic if the input
117 /// string does not have the correct length.
118 ///
119 /// # Arguments
120 ///
121 /// - `hex_str`: A string slice containing a hexadecimal string (e.g., "0x1234...").
122 ///
123 /// # Returns
124 ///
125 /// A fixed-size array of `N` bytes representing the decoded hexadecimal string.
126 ///
127 /// # Panics
128 ///
129 /// This function will panic if the length of the decoded bytes does not match the expected size `N`.
130 fn hex_to_fixed_array<const N: usize>(hex_str: &str) -> [u8; N] {
131 let bytes = hex::decode(&hex_str[2..]).unwrap();
132 let mut array = [0u8; N];
133 let len = bytes.len();
134 if len != N {
135 panic!("Invalid input length: expected {}, got {}", N, len);
136 }
137 array.copy_from_slice(&bytes);
138 array
139 }
140}