referrerpolicy=no-referrer-when-downgrade

pallet_revive/evm/
block_hash.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Types, and traits to integrate pallet-revive with EVM.
19#![warn(missing_docs)]
20
21mod receipt;
22use pallet_revive_types::runtime_api::*;
23pub use receipt::{AccumulateReceipt, CommittedReceiptLogs, LogsBloom};
24
25mod hash_builder;
26pub use hash_builder::{BuilderPhase, IncrementalHashBuilder, IncrementalHashBuilderIR};
27
28mod block_builder;
29pub use block_builder::{EthereumBlockBuilder, EthereumBlockBuilderIR};
30
31use crate::evm::Block;
32
33use alloc::vec::Vec;
34use alloy_core::primitives::{B256, bytes::BufMut};
35
36use codec::{Decode, Encode, MaxEncodedLen};
37use scale_info::TypeInfo;
38use sp_core::{H160, H256, U256};
39
40/// Details needed to reconstruct the receipt info in the RPC
41/// layer without losing accuracy.
42#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Clone, Debug, Default, PartialEq, Eq)]
43pub struct ReceiptGasInfo {
44	/// The amount of gas used for this specific transaction alone.
45	pub gas_used: U256,
46
47	/// The effective gas price for this transaction.
48	pub effective_gas_price: U256,
49}
50
51impl From<ReceiptGasInfo> for ReceiptGasInfoV1 {
52	fn from(value: ReceiptGasInfo) -> Self {
53		Self { gas_used: value.gas_used, effective_gas_price: value.effective_gas_price }
54	}
55}
56
57/// What the block committed to its synthetic transaction, the one carrying the logs emitted
58/// outside any ethereum transaction.
59#[derive(Encode, Decode, TypeInfo, Clone, Debug, Default, PartialEq, Eq)]
60pub struct SyntheticTransactionInfo {
61	/// Its receipt gas entry. Kept out of [`crate::ReceiptInfoData`] because the
62	/// `eth_receipt_data` runtime API is versioned on exactly that split: V1 promises one entry
63	/// per ethereum transaction.
64	pub gas_info: ReceiptGasInfo,
65
66	/// The `frame_system` event index of each log that went into it, in receipt order. These are
67	/// the logs the block's `logs_bloom` and `receipts_root` commit to, which is what lets the
68	/// serving layer pick them out of the block's `ContractEmitted` events: a contract log outside
69	/// an ethereum transaction and a log past the buffer's cap are deposited but not buffered.
70	pub log_event_indices: Vec<u32>,
71}
72
73impl From<SyntheticTransactionInfo> for SyntheticTransactionV1 {
74	fn from(value: SyntheticTransactionInfo) -> Self {
75		Self { gas_info: value.gas_info.into(), log_event_indices: value.log_event_indices }
76	}
77}
78
79/// A log buffered for the block's synthetic transaction.
80#[derive(Encode, Decode, TypeInfo, Clone, Debug, PartialEq, Eq)]
81pub struct OutsideFrameLog {
82	/// The `frame_system` event index of its [`crate::Event::ContractEmitted`].
83	pub event_index: u32,
84	/// The address the log is attributed to.
85	pub contract: H160,
86	/// The log's topics.
87	pub topics: Vec<H256>,
88	/// The log's data.
89	pub data: Vec<u8>,
90}
91
92impl Block {
93	/// Compute the trie root using the `(rlp(index), encoded(item))` pairs.
94	pub fn compute_trie_root(items: &[Vec<u8>]) -> B256 {
95		alloy_consensus::proofs::ordered_trie_root_with_encoder(items, |item, buf| {
96			buf.put_slice(item)
97		})
98	}
99
100	/// Compute the ETH header hash.
101	pub fn header_hash(&self) -> H256 {
102		// Note: Cap the gas limit to u64::MAX.
103		// In practice, it should be impossible to fill a u64::MAX gas limit
104		// of an either Ethereum or Substrate block.
105		let gas_limit = self.gas_limit.try_into().unwrap_or(u64::MAX);
106
107		let alloy_header = alloy_consensus::Header {
108			state_root: self.state_root.0.into(),
109			transactions_root: self.transactions_root.0.into(),
110			receipts_root: self.receipts_root.0.into(),
111
112			parent_hash: self.parent_hash.0.into(),
113			beneficiary: self.miner.0.into(),
114			number: self.number.as_u64(),
115			logs_bloom: self.logs_bloom.0.into(),
116			gas_limit,
117			gas_used: self.gas_used.as_u64(),
118			timestamp: self.timestamp.as_u64(),
119
120			ommers_hash: self.sha_3_uncles.0.into(),
121			extra_data: self.extra_data.clone().0.into(),
122			mix_hash: self.mix_hash.0.into(),
123			nonce: self.nonce.0.into(),
124
125			base_fee_per_gas: Some(self.base_fee_per_gas.as_u64()),
126			withdrawals_root: Some(self.withdrawals_root.0.into()),
127			blob_gas_used: Some(self.blob_gas_used.as_u64()),
128			excess_blob_gas: Some(self.excess_blob_gas.as_u64()),
129			parent_beacon_block_root: self.parent_beacon_block_root.map(|root| root.0.into()),
130			requests_hash: self.requests_hash.map(|hash| hash.0.into()),
131
132			..Default::default()
133		};
134
135		alloy_header.hash_slow().0.into()
136	}
137}