Skip to content

Commit 92a8034

Browse files
committed
AuxStore logs
1 parent 833758f commit 92a8034

File tree

5 files changed

+129
-29
lines changed

5 files changed

+129
-29
lines changed

consensus/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ sp-api = { git = "https://github.com/paritytech/substrate.git", branch = "rococo
1616
sc-client-api = { git = "https://github.com/paritytech/substrate.git", branch = "rococo-branch" }
1717
sp-block-builder = { git = "https://github.com/paritytech/substrate.git", branch = "rococo-branch" }
1818
sp-inherents = { git = "https://github.com/paritytech/substrate.git", branch = "rococo-branch" }
19+
sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "rococo-branch" }
1920
frontier-consensus-primitives = { path = "primitives" }
21+
frontier-rpc-primitives = { path = "../rpc/primitives" }
2022
sp-consensus = { git = "https://github.com/paritytech/substrate.git", branch = "rococo-branch" }
2123
log = "0.4.8"
2224
futures = { version = "0.3.1", features = ["compat"] }

consensus/src/aux_schema.rs

+28
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use sp_core::H256;
2121
use sp_runtime::traits::Block as BlockT;
2222
use sc_client_api::backend::AuxStore;
2323
use sp_blockchain::{Result as ClientResult, Error as ClientError};
24+
use frontier_rpc_primitives::TransactionStatus;
2425

2526
fn load_decode<B: AuxStore, T: Decode>(backend: &B, key: &[u8]) -> ClientResult<Option<T>> {
2627
let corrupt = |e: codec::Error| {
@@ -96,3 +97,30 @@ pub fn write_transaction_metadata<F, R>(
9697
let key = transaction_metadata_key(hash);
9798
write_aux(&[(&key, &metadata.encode())])
9899
}
100+
/// Map a Ethereum block number to the current runtime stored Ethereum logs.
101+
pub fn log_key(block_number: u32) -> Vec<u8> {
102+
let mut ret = b"ethereum_log:".to_vec();
103+
ret.append(&mut block_number.to_be_bytes().to_vec());
104+
ret
105+
}
106+
107+
/// Given an Ethereum block number, get the corresponding Ethereum logs.
108+
pub fn load_logs<B: AuxStore>(
109+
backend: &B,
110+
block_number: u32,
111+
) -> ClientResult<Option<(H256, Vec<TransactionStatus>)>> {
112+
let key = log_key(block_number);
113+
load_decode(backend, &key)
114+
}
115+
116+
/// Update Aux logs.
117+
pub fn write_logs<F, R>(
118+
block_number: u32,
119+
data: (H256, Vec<TransactionStatus>),
120+
write_aux: F,
121+
) -> R where
122+
F: FnOnce(&[(&[u8], &[u8])]) -> R,
123+
{
124+
let key = log_key(block_number);
125+
write_aux(&[(&key, &data.encode())])
126+
}

consensus/src/lib.rs

+63-11
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,26 @@
1818

1919
mod aux_schema;
2020

21-
pub use crate::aux_schema::{load_block_hash, load_transaction_metadata};
21+
pub use crate::aux_schema::{load_block_hash, load_transaction_metadata, load_logs};
2222

2323
use std::sync::Arc;
2424
use std::collections::HashMap;
2525
use std::marker::PhantomData;
26+
use codec::Decode;
2627
use frontier_consensus_primitives::{FRONTIER_ENGINE_ID, ConsensusLog};
27-
use sc_client_api::{BlockOf, backend::AuxStore};
28+
use sc_client_api::{BlockOf, backend::AuxStore, StorageProvider, Backend, StateBackend};
2829
use sp_blockchain::{HeaderBackend, ProvideCache, well_known_cache_keys::Id as CacheKeyId};
2930
use sp_block_builder::BlockBuilder as BlockBuilderApi;
30-
use sp_runtime::generic::OpaqueDigestItemId;
31-
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
31+
use sp_runtime::generic::{OpaqueDigestItemId, BlockId};
32+
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, BlakeTwo256, UniqueSaturatedInto, Saturating, One};
3233
use sp_api::ProvideRuntimeApi;
34+
use sp_core::{H256, storage::StorageKey};
35+
use sp_io::hashing::twox_128;
3336
use sp_consensus::{
3437
BlockImportParams, Error as ConsensusError, BlockImport,
3538
BlockCheckParams, ImportResult,
3639
};
40+
use frontier_rpc_primitives::TransactionStatus;
3741
use log::*;
3842
use sc_client_api;
3943

@@ -57,14 +61,14 @@ impl std::convert::From<Error> for ConsensusError {
5761
}
5862
}
5963

60-
pub struct FrontierBlockImport<B: BlockT, I, C> {
64+
pub struct FrontierBlockImport<B: BlockT, I, C, BE> {
6165
inner: I,
6266
client: Arc<C>,
6367
enabled: bool,
64-
_marker: PhantomData<B>,
68+
_marker: PhantomData<(B, BE)>,
6569
}
6670

67-
impl<Block: BlockT, I: Clone + BlockImport<Block>, C> Clone for FrontierBlockImport<Block, I, C> {
71+
impl<Block: BlockT, I: Clone + BlockImport<Block>, C, BE> Clone for FrontierBlockImport<Block, I, C, BE> {
6872
fn clone(&self) -> Self {
6973
FrontierBlockImport {
7074
inner: self.inner.clone(),
@@ -75,11 +79,13 @@ impl<Block: BlockT, I: Clone + BlockImport<Block>, C> Clone for FrontierBlockImp
7579
}
7680
}
7781

78-
impl<B, I, C> FrontierBlockImport<B, I, C> where
82+
impl<B, I, C, BE> FrontierBlockImport<B, I, C, BE> where
7983
B: BlockT,
84+
BE: Backend<B>,
85+
BE::State: StateBackend<BlakeTwo256>,
8086
I: BlockImport<B, Transaction = sp_api::TransactionFor<C, B>> + Send + Sync,
8187
I::Error: Into<ConsensusError>,
82-
C: ProvideRuntimeApi<B> + Send + Sync + HeaderBackend<B> + AuxStore + ProvideCache<B> + BlockOf,
88+
C: ProvideRuntimeApi<B> + Send + Sync + HeaderBackend<B> + AuxStore + ProvideCache<B> + BlockOf + StorageProvider<B,BE>,
8389
C::Api: BlockBuilderApi<B, Error = sp_blockchain::Error>,
8490
{
8591
pub fn new(
@@ -96,11 +102,13 @@ impl<B, I, C> FrontierBlockImport<B, I, C> where
96102
}
97103
}
98104

99-
impl<B, I, C> BlockImport<B> for FrontierBlockImport<B, I, C> where
105+
impl<B, I, C, BE> BlockImport<B> for FrontierBlockImport<B, I, C, BE> where
100106
B: BlockT,
107+
BE: Backend<B>,
108+
BE::State: StateBackend<BlakeTwo256>,
101109
I: BlockImport<B, Transaction = sp_api::TransactionFor<C, B>> + Send + Sync,
102110
I::Error: Into<ConsensusError>,
103-
C: ProvideRuntimeApi<B> + Send + Sync + HeaderBackend<B> + AuxStore + ProvideCache<B> + BlockOf,
111+
C: ProvideRuntimeApi<B> + Send + Sync + HeaderBackend<B> + AuxStore + ProvideCache<B> + BlockOf + StorageProvider<B,BE>,
104112
C::Api: BlockBuilderApi<B, Error = sp_blockchain::Error>,
105113
{
106114
type Error = ConsensusError;
@@ -145,6 +153,20 @@ impl<B, I, C> BlockImport<B> for FrontierBlockImport<B, I, C> where
145153
insert_closure!(),
146154
);
147155
}
156+
157+
// Store already processed TransactionStatus by block number.
158+
if *block.header.number() > One::one() {
159+
let number = UniqueSaturatedInto::<u32>::unique_saturated_into(
160+
block.header.number().saturating_sub(One::one())
161+
);
162+
if let Some(data) = logs(client.as_ref(), number) {
163+
aux_schema::write_logs(
164+
number,
165+
data,
166+
insert_closure!()
167+
);
168+
}
169+
}
148170
},
149171
}
150172
}
@@ -170,3 +192,33 @@ fn find_frontier_log<B: BlockT>(
170192

171193
Ok(frontier_log.ok_or(Error::NoPostRuntimeLog)?)
172194
}
195+
196+
fn logs<B, BE, C>(
197+
client: &C,
198+
block_number: u32,
199+
) -> Option<(H256, Vec<TransactionStatus>)> where
200+
B: BlockT,
201+
BE: Backend<B>,
202+
BE::State: StateBackend<BlakeTwo256>,
203+
C: HeaderBackend<B> + StorageProvider<B,BE>,
204+
{
205+
if let Ok(Some(header)) = client.header(BlockId::Number(block_number.into()))
206+
{
207+
if let Ok(ConsensusLog::EndBlock { block_hash, .. }) = find_frontier_log::<B>(&header) {
208+
if let Ok(Some(data)) = client.storage(
209+
&BlockId::Number(block_number.into()),
210+
&StorageKey(
211+
storage_prefix_build(b"Ethereum", b"CurrentTransactionStatuses")
212+
)
213+
) {
214+
let statuses: Vec<TransactionStatus> = Decode::decode(&mut &data.0[..]).unwrap();
215+
return Some((block_hash, statuses))
216+
}
217+
}
218+
}
219+
None
220+
}
221+
222+
fn storage_prefix_build(module: &[u8], storage: &[u8]) -> Vec<u8> {
223+
[twox_128(module), twox_128(storage)].concat().to_vec()
224+
}

frame/ethereum/src/lib.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,17 @@ impl<T: Trait> Module<T> {
279279
}
280280

281281
CurrentBlock::put(block.clone());
282-
CurrentReceipts::put(receipts.clone());
283-
CurrentTransactionStatuses::put(statuses.clone());
282+
if receipts.len() > 0 {
283+
CurrentReceipts::put(receipts.clone());
284+
} else {
285+
CurrentReceipts::kill();
286+
}
287+
288+
if statuses.len() > 0 {
289+
CurrentTransactionStatuses::put(statuses.clone());
290+
} else {
291+
CurrentTransactionStatuses::kill();
292+
}
284293

285294
let digest = DigestItem::<T::Hash>::Consensus(
286295
FRONTIER_ENGINE_ID,

rpc/src/eth.rs

+25-16
Original file line numberDiff line numberDiff line change
@@ -830,8 +830,13 @@ impl<B, C, P, CT, BE, A> EthApiT for EthApi<B, C, P, CT, BE, A> where
830830
let block: Option<ethereum::Block> = self.current_block(&id);
831831
let statuses: Option<Vec<TransactionStatus>> = self.current_statuses(&id);
832832

833-
if let (Some(block), Some(statuses)) = (block, statuses) {
834-
blocks_and_statuses.push((block, statuses));
833+
let block_hash = Some(H256::from_slice(
834+
Keccak256::digest(&rlp::encode(&block.clone().unwrap().header)).as_slice()
835+
));
836+
let block_number = Some(block.unwrap().header.number);
837+
838+
if let (Some(block_hash), Some(block_number), Some(statuses)) = (block_hash, block_number, statuses) {
839+
blocks_and_statuses.push((block_hash, block_number, statuses));
835840
}
836841
} else {
837842
let mut current_number = filter.to_block
@@ -848,14 +853,21 @@ impl<B, C, P, CT, BE, A> EthApiT for EthApi<B, C, P, CT, BE, A> where
848853
self.client.info().best_number
849854
);
850855
while current_number >= from_number {
851-
let id = BlockId::Number(current_number);
852-
853-
let block: Option<ethereum::Block> = self.current_block(&id);
854-
let statuses: Option<Vec<TransactionStatus>> = self.current_statuses(&id);
855-
856-
if let (Some(block), Some(statuses)) = (block, statuses) {
857-
blocks_and_statuses.push((block, statuses));
858-
}
856+
let number = UniqueSaturatedInto::<u32>::unique_saturated_into(current_number);
857+
858+
match frontier_consensus::load_logs(
859+
self.client.as_ref(),
860+
number
861+
).map_err(|err| internal_err(format!("fetch aux store failed: {:?}", err)))?
862+
{
863+
Some((block_hash, statuses)) => {
864+
let block_number = U256::from(
865+
UniqueSaturatedInto::<u32>::unique_saturated_into(current_number)
866+
);
867+
blocks_and_statuses.push((block_hash, block_number, statuses));
868+
},
869+
_ => {},
870+
};
859871

860872
if current_number == Zero::zero() {
861873
break
@@ -868,14 +880,11 @@ impl<B, C, P, CT, BE, A> EthApiT for EthApi<B, C, P, CT, BE, A> where
868880
let mut blocks_processed: u32 = 0;
869881
let mut logs_processed: u32 = 0;
870882

871-
'outer: for (block, statuses) in blocks_and_statuses {
883+
'outer: for (block_hash, block_number, statuses) in blocks_and_statuses {
872884
if blocks_processed == eth_block_limit {
873885
break;
874886
}
875887
let mut block_log_index: u32 = 0;
876-
let block_hash = H256::from_slice(
877-
Keccak256::digest(&rlp::encode(&block.header)).as_slice()
878-
);
879888
for status in statuses.iter() {
880889
let logs = status.logs.clone();
881890
let mut transaction_log_index: u32 = 0;
@@ -911,8 +920,8 @@ impl<B, C, P, CT, BE, A> EthApiT for EthApi<B, C, P, CT, BE, A> where
911920
address: log.address.clone(),
912921
topics: log.topics.clone(),
913922
data: Bytes(log.data.clone()),
914-
block_hash: Some(block_hash),
915-
block_number: Some(block.header.number.clone()),
923+
block_hash: Some(block_hash.clone()),
924+
block_number: Some(block_number.clone()),
916925
transaction_hash: Some(transaction_hash),
917926
transaction_index: Some(U256::from(status.transaction_index)),
918927
log_index: Some(U256::from(block_log_index)),

0 commit comments

Comments
 (0)