fc_storage/overrides/
mod.rs1use std::{marker::PhantomData, sync::Arc};
20
21use ethereum_types::{Address, H256, U256};
22use scale_codec::Decode;
23use sc_client_api::{Backend, StorageProvider};
25use sp_io::hashing::{blake2_128, twox_128};
26use sp_runtime::{traits::Block as BlockT, Permill};
27use sp_storage::StorageKey;
28use fp_rpc::TransactionStatus;
30use fp_storage::{constants::*, EthereumStorageSchema, PALLET_ETHEREUM_SCHEMA};
31
32mod runtime_api;
33mod schema;
34
35pub use self::{
36 runtime_api::RuntimeApiStorageOverride,
37 schema::{
38 v1::{
39 SchemaStorageOverride as SchemaV1StorageOverride,
40 SchemaStorageOverrideRef as SchemaV1StorageOverrideRef,
41 },
42 v2::{
43 SchemaStorageOverride as SchemaV2StorageOverride,
44 SchemaStorageOverrideRef as SchemaV2StorageOverrideRef,
45 },
46 v3::{
47 SchemaStorageOverride as SchemaV3StorageOverride,
48 SchemaStorageOverrideRef as SchemaV3StorageOverrideRef,
49 },
50 },
51};
52
53pub trait StorageOverride<Block: BlockT>: Send + Sync {
55 fn account_code_at(&self, at: Block::Hash, address: Address) -> Option<Vec<u8>>;
57 fn account_storage_at(&self, at: Block::Hash, address: Address, index: U256) -> Option<H256>;
59
60 fn current_block(&self, at: Block::Hash) -> Option<ethereum::BlockV3>;
62 fn current_receipts(&self, at: Block::Hash) -> Option<Vec<ethereum::ReceiptV4>>;
64 fn current_transaction_statuses(&self, at: Block::Hash) -> Option<Vec<TransactionStatus>>;
66
67 fn elasticity(&self, at: Block::Hash) -> Option<Permill>;
69 fn is_eip1559(&self, at: Block::Hash) -> bool;
71}
72
73fn storage_prefix_build(module: &[u8], storage: &[u8]) -> Vec<u8> {
74 [twox_128(module), twox_128(storage)].concat().to_vec()
75}
76
77fn blake2_128_extend(bytes: &[u8]) -> Vec<u8> {
78 let mut ext: Vec<u8> = blake2_128(bytes).to_vec();
79 ext.extend_from_slice(bytes);
80 ext
81}
82
83#[derive(Clone)]
85pub struct StorageQuerier<B, C, BE> {
86 client: Arc<C>,
87 _marker: PhantomData<(B, BE)>,
88}
89
90impl<B, C, BE> StorageQuerier<B, C, BE> {
91 pub fn new(client: Arc<C>) -> Self {
92 Self {
93 client,
94 _marker: PhantomData,
95 }
96 }
97}
98
99impl<B, C, BE> StorageQuerier<B, C, BE>
100where
101 B: BlockT,
102 C: StorageProvider<B, BE>,
103 BE: Backend<B>,
104{
105 pub fn query<T: Decode>(&self, at: B::Hash, key: &StorageKey) -> Option<T> {
106 if let Ok(Some(data)) = self.client.storage(at, key) {
107 if let Ok(result) = Decode::decode(&mut &data.0[..]) {
108 return Some(result);
109 }
110 }
111 None
112 }
113
114 pub fn storage_schema(&self, at: B::Hash) -> Option<EthereumStorageSchema> {
115 let key = PALLET_ETHEREUM_SCHEMA.to_vec();
116 self.query::<EthereumStorageSchema>(at, &StorageKey(key))
117 }
118
119 pub fn account_code(&self, at: B::Hash, address: Address) -> Option<Vec<u8>> {
120 let mut key: Vec<u8> = storage_prefix_build(PALLET_EVM, EVM_ACCOUNT_CODES);
121 key.extend(blake2_128_extend(address.as_bytes()));
122 self.query::<Vec<u8>>(at, &StorageKey(key))
123 }
124
125 pub fn account_storage(&self, at: B::Hash, address: Address, index: U256) -> Option<H256> {
126 let mut key: Vec<u8> = storage_prefix_build(PALLET_EVM, EVM_ACCOUNT_STORAGES);
127 key.extend(blake2_128_extend(address.as_bytes()));
128 key.extend(blake2_128_extend(&index.to_big_endian()));
129
130 self.query::<H256>(at, &StorageKey(key))
131 }
132
133 pub fn current_block<Block: Decode>(&self, at: B::Hash) -> Option<Block> {
134 let key = storage_prefix_build(PALLET_ETHEREUM, ETHEREUM_CURRENT_BLOCK);
135 self.query::<Block>(at, &StorageKey(key))
136 }
137
138 pub fn current_receipts<Receipt: Decode>(&self, at: B::Hash) -> Option<Vec<Receipt>> {
139 let key = storage_prefix_build(PALLET_ETHEREUM, ETHEREUM_CURRENT_RECEIPTS);
140 self.query::<Vec<Receipt>>(at, &StorageKey(key))
141 }
142
143 pub fn current_transaction_statuses(&self, at: B::Hash) -> Option<Vec<TransactionStatus>> {
144 let key = storage_prefix_build(PALLET_ETHEREUM, ETHEREUM_CURRENT_TRANSACTION_STATUSES);
145 self.query::<Vec<TransactionStatus>>(at, &StorageKey(key))
146 }
147
148 pub fn elasticity(&self, at: B::Hash) -> Option<Permill> {
149 let key = storage_prefix_build(PALLET_BASE_FEE, BASE_FEE_ELASTICITY);
150 self.query::<Permill>(at, &StorageKey(key))
151 }
152}