mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-20 01:05:41 +00:00
Refactored block body database scheme (#10779)
* Refactored tx storage database scheme * Bump parity-db * fmt * Fix handling invalid index size + test * Removed superflous result * Minor changes * fmt
This commit is contained in:
@@ -29,7 +29,7 @@ use sc_consensus::{
|
|||||||
use sc_service::{
|
use sc_service::{
|
||||||
config::{
|
config::{
|
||||||
DatabaseSource, KeepBlocks, KeystoreConfig, NetworkConfiguration, OffchainWorkerConfig,
|
DatabaseSource, KeepBlocks, KeystoreConfig, NetworkConfiguration, OffchainWorkerConfig,
|
||||||
PruningMode, TransactionStorageMode, WasmExecutionMethod,
|
PruningMode, WasmExecutionMethod,
|
||||||
},
|
},
|
||||||
BasePath, Configuration, Role,
|
BasePath, Configuration, Role,
|
||||||
};
|
};
|
||||||
@@ -76,7 +76,6 @@ fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase {
|
|||||||
state_cache_child_ratio: None,
|
state_cache_child_ratio: None,
|
||||||
state_pruning: PruningMode::ArchiveAll,
|
state_pruning: PruningMode::ArchiveAll,
|
||||||
keep_blocks: KeepBlocks::All,
|
keep_blocks: KeepBlocks::All,
|
||||||
transaction_storage: TransactionStorageMode::BlockBody,
|
|
||||||
chain_spec: spec,
|
chain_spec: spec,
|
||||||
wasm_method: WasmExecutionMethod::Compiled,
|
wasm_method: WasmExecutionMethod::Compiled,
|
||||||
execution_strategies: ExecutionStrategies {
|
execution_strategies: ExecutionStrategies {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ use sc_client_api::execution_extensions::ExecutionStrategies;
|
|||||||
use sc_service::{
|
use sc_service::{
|
||||||
config::{
|
config::{
|
||||||
DatabaseSource, KeepBlocks, KeystoreConfig, NetworkConfiguration, OffchainWorkerConfig,
|
DatabaseSource, KeepBlocks, KeystoreConfig, NetworkConfiguration, OffchainWorkerConfig,
|
||||||
PruningMode, TransactionPoolOptions, TransactionStorageMode, WasmExecutionMethod,
|
PruningMode, TransactionPoolOptions, WasmExecutionMethod,
|
||||||
},
|
},
|
||||||
BasePath, Configuration, Role,
|
BasePath, Configuration, Role,
|
||||||
};
|
};
|
||||||
@@ -67,7 +67,6 @@ fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase {
|
|||||||
state_cache_child_ratio: None,
|
state_cache_child_ratio: None,
|
||||||
state_pruning: PruningMode::ArchiveAll,
|
state_pruning: PruningMode::ArchiveAll,
|
||||||
keep_blocks: KeepBlocks::All,
|
keep_blocks: KeepBlocks::All,
|
||||||
transaction_storage: TransactionStorageMode::BlockBody,
|
|
||||||
chain_spec: spec,
|
chain_spec: spec,
|
||||||
wasm_method: WasmExecutionMethod::Interpreted,
|
wasm_method: WasmExecutionMethod::Interpreted,
|
||||||
// NOTE: we enforce the use of the native runtime to make the errors more debuggable
|
// NOTE: we enforce the use of the native runtime to make the errors more debuggable
|
||||||
|
|||||||
@@ -393,7 +393,6 @@ impl BenchDb {
|
|||||||
state_pruning: PruningMode::ArchiveAll,
|
state_pruning: PruningMode::ArchiveAll,
|
||||||
source: database_type.into_settings(dir.into()),
|
source: database_type.into_settings(dir.into()),
|
||||||
keep_blocks: sc_client_db::KeepBlocks::All,
|
keep_blocks: sc_client_db::KeepBlocks::All,
|
||||||
transaction_storage: sc_client_db::TransactionStorageMode::BlockBody,
|
|
||||||
};
|
};
|
||||||
let task_executor = TaskExecutor::new();
|
let task_executor = TaskExecutor::new();
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ use sc_service::{
|
|||||||
NodeKeyConfig, OffchainWorkerConfig, PrometheusConfig, PruningMode, Role, RpcMethods,
|
NodeKeyConfig, OffchainWorkerConfig, PrometheusConfig, PruningMode, Role, RpcMethods,
|
||||||
TelemetryEndpoints, TransactionPoolOptions, WasmExecutionMethod,
|
TelemetryEndpoints, TransactionPoolOptions, WasmExecutionMethod,
|
||||||
},
|
},
|
||||||
ChainSpec, KeepBlocks, TracingReceiver, TransactionStorageMode,
|
ChainSpec, KeepBlocks, TracingReceiver,
|
||||||
};
|
};
|
||||||
use sc_tracing::logging::LoggerBuilder;
|
use sc_tracing::logging::LoggerBuilder;
|
||||||
use std::{net::SocketAddr, path::PathBuf};
|
use std::{net::SocketAddr, path::PathBuf};
|
||||||
@@ -198,14 +198,6 @@ pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
|
|||||||
Ok(self.database_params().map(|x| x.database_cache_size()).unwrap_or_default())
|
Ok(self.database_params().map(|x| x.database_cache_size()).unwrap_or_default())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the database transaction storage scheme.
|
|
||||||
fn database_transaction_storage(&self) -> Result<TransactionStorageMode> {
|
|
||||||
Ok(self
|
|
||||||
.database_params()
|
|
||||||
.map(|x| x.transaction_storage())
|
|
||||||
.unwrap_or(TransactionStorageMode::BlockBody))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the database backend variant.
|
/// Get the database backend variant.
|
||||||
///
|
///
|
||||||
/// By default this is retrieved from `DatabaseParams` if it is available. Otherwise its `None`.
|
/// By default this is retrieved from `DatabaseParams` if it is available. Otherwise its `None`.
|
||||||
@@ -519,7 +511,6 @@ pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
|
|||||||
state_cache_child_ratio: self.state_cache_child_ratio()?,
|
state_cache_child_ratio: self.state_cache_child_ratio()?,
|
||||||
state_pruning: self.state_pruning(unsafe_pruning, &role)?,
|
state_pruning: self.state_pruning(unsafe_pruning, &role)?,
|
||||||
keep_blocks: self.keep_blocks()?,
|
keep_blocks: self.keep_blocks()?,
|
||||||
transaction_storage: self.database_transaction_storage()?,
|
|
||||||
wasm_method: self.wasm_method()?,
|
wasm_method: self.wasm_method()?,
|
||||||
wasm_runtime_overrides: self.wasm_runtime_overrides(),
|
wasm_runtime_overrides: self.wasm_runtime_overrides(),
|
||||||
execution_strategies: self.execution_strategies(is_dev, is_validator)?,
|
execution_strategies: self.execution_strategies(is_dev, is_validator)?,
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
use crate::arg_enums::Database;
|
use crate::arg_enums::Database;
|
||||||
use clap::Args;
|
use clap::Args;
|
||||||
use sc_service::TransactionStorageMode;
|
|
||||||
|
|
||||||
/// Parameters for block import.
|
/// Parameters for block import.
|
||||||
#[derive(Debug, Clone, PartialEq, Args)]
|
#[derive(Debug, Clone, PartialEq, Args)]
|
||||||
@@ -36,15 +35,6 @@ pub struct DatabaseParams {
|
|||||||
/// Limit the memory the database cache can use.
|
/// Limit the memory the database cache can use.
|
||||||
#[clap(long = "db-cache", value_name = "MiB")]
|
#[clap(long = "db-cache", value_name = "MiB")]
|
||||||
pub database_cache_size: Option<usize>,
|
pub database_cache_size: Option<usize>,
|
||||||
|
|
||||||
/// Enable storage chain mode
|
|
||||||
///
|
|
||||||
/// This changes the storage format for blocks bodies.
|
|
||||||
/// If this is enabled, each transaction is stored separately in the
|
|
||||||
/// transaction database column and is only referenced by hash
|
|
||||||
/// in the block body column.
|
|
||||||
#[clap(long)]
|
|
||||||
pub storage_chain: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DatabaseParams {
|
impl DatabaseParams {
|
||||||
@@ -57,13 +47,4 @@ impl DatabaseParams {
|
|||||||
pub fn database_cache_size(&self) -> Option<usize> {
|
pub fn database_cache_size(&self) -> Option<usize> {
|
||||||
self.database_cache_size
|
self.database_cache_size
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transaction storage scheme.
|
|
||||||
pub fn transaction_storage(&self) -> TransactionStorageMode {
|
|
||||||
if self.storage_chain {
|
|
||||||
TransactionStorageMode::StorageChain
|
|
||||||
} else {
|
|
||||||
TransactionStorageMode::BlockBody
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+261
-218
@@ -111,13 +111,18 @@ pub const DB_HASH_LEN: usize = 32;
|
|||||||
/// Hash type that this backend uses for the database.
|
/// Hash type that this backend uses for the database.
|
||||||
pub type DbHash = sp_core::H256;
|
pub type DbHash = sp_core::H256;
|
||||||
|
|
||||||
/// This is used as block body when storage-chain mode is enabled.
|
/// An extrinsic entry in the database.
|
||||||
#[derive(Debug, Encode, Decode)]
|
#[derive(Debug, Encode, Decode)]
|
||||||
struct ExtrinsicHeader {
|
enum DbExtrinsic<B: BlockT> {
|
||||||
/// Hash of the indexed part
|
/// Extrinsic that contains indexed data.
|
||||||
indexed_hash: DbHash, // Zero hash if there's no indexed data
|
Indexed {
|
||||||
/// The rest of the data.
|
/// Hash of the indexed part.
|
||||||
data: Vec<u8>,
|
hash: DbHash,
|
||||||
|
/// Extrinsic header.
|
||||||
|
header: Vec<u8>,
|
||||||
|
},
|
||||||
|
/// Complete extrinsic data.
|
||||||
|
Full(B::Extrinsic),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A reference tracking state.
|
/// A reference tracking state.
|
||||||
@@ -295,8 +300,6 @@ pub struct DatabaseSettings {
|
|||||||
pub source: DatabaseSource,
|
pub source: DatabaseSource,
|
||||||
/// Block pruning mode.
|
/// Block pruning mode.
|
||||||
pub keep_blocks: KeepBlocks,
|
pub keep_blocks: KeepBlocks,
|
||||||
/// Block body/Transaction storage scheme.
|
|
||||||
pub transaction_storage: TransactionStorageMode,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Block pruning settings.
|
/// Block pruning settings.
|
||||||
@@ -308,16 +311,6 @@ pub enum KeepBlocks {
|
|||||||
Some(u32),
|
Some(u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Block body storage scheme.
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub enum TransactionStorageMode {
|
|
||||||
/// Store block body as an encoded list of full transactions in the BODY column
|
|
||||||
BlockBody,
|
|
||||||
/// Store a list of hashes in the BODY column and each transaction individually
|
|
||||||
/// in the TRANSACTION column.
|
|
||||||
StorageChain,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Where to find the database..
|
/// Where to find the database..
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum DatabaseSource {
|
pub enum DatabaseSource {
|
||||||
@@ -406,6 +399,7 @@ pub(crate) mod columns {
|
|||||||
pub const OFFCHAIN: u32 = 9;
|
pub const OFFCHAIN: u32 = 9;
|
||||||
/// Transactions
|
/// Transactions
|
||||||
pub const TRANSACTION: u32 = 11;
|
pub const TRANSACTION: u32 = 11;
|
||||||
|
pub const BODY_INDEX: u32 = 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PendingBlock<Block: BlockT> {
|
struct PendingBlock<Block: BlockT> {
|
||||||
@@ -453,14 +447,10 @@ pub struct BlockchainDb<Block: BlockT> {
|
|||||||
leaves: RwLock<LeafSet<Block::Hash, NumberFor<Block>>>,
|
leaves: RwLock<LeafSet<Block::Hash, NumberFor<Block>>>,
|
||||||
header_metadata_cache: Arc<HeaderMetadataCache<Block>>,
|
header_metadata_cache: Arc<HeaderMetadataCache<Block>>,
|
||||||
header_cache: Mutex<LinkedHashMap<Block::Hash, Option<Block::Header>>>,
|
header_cache: Mutex<LinkedHashMap<Block::Hash, Option<Block::Header>>>,
|
||||||
transaction_storage: TransactionStorageMode,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Block: BlockT> BlockchainDb<Block> {
|
impl<Block: BlockT> BlockchainDb<Block> {
|
||||||
fn new(
|
fn new(db: Arc<dyn Database<DbHash>>) -> ClientResult<Self> {
|
||||||
db: Arc<dyn Database<DbHash>>,
|
|
||||||
transaction_storage: TransactionStorageMode,
|
|
||||||
) -> ClientResult<Self> {
|
|
||||||
let meta = read_meta::<Block>(&*db, columns::HEADER)?;
|
let meta = read_meta::<Block>(&*db, columns::HEADER)?;
|
||||||
let leaves = LeafSet::read_from_db(&*db, columns::META, meta_keys::LEAF_PREFIX)?;
|
let leaves = LeafSet::read_from_db(&*db, columns::META, meta_keys::LEAF_PREFIX)?;
|
||||||
Ok(BlockchainDb {
|
Ok(BlockchainDb {
|
||||||
@@ -469,7 +459,6 @@ impl<Block: BlockT> BlockchainDb<Block> {
|
|||||||
meta: Arc::new(RwLock::new(meta)),
|
meta: Arc::new(RwLock::new(meta)),
|
||||||
header_metadata_cache: Arc::new(HeaderMetadataCache::default()),
|
header_metadata_cache: Arc::new(HeaderMetadataCache::default()),
|
||||||
header_cache: Default::default(),
|
header_cache: Default::default(),
|
||||||
transaction_storage,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -558,59 +547,61 @@ impl<Block: BlockT> sc_client_api::blockchain::HeaderBackend<Block> for Blockcha
|
|||||||
|
|
||||||
impl<Block: BlockT> sc_client_api::blockchain::Backend<Block> for BlockchainDb<Block> {
|
impl<Block: BlockT> sc_client_api::blockchain::Backend<Block> for BlockchainDb<Block> {
|
||||||
fn body(&self, id: BlockId<Block>) -> ClientResult<Option<Vec<Block::Extrinsic>>> {
|
fn body(&self, id: BlockId<Block>) -> ClientResult<Option<Vec<Block::Extrinsic>>> {
|
||||||
let body = match read_db(&*self.db, columns::KEY_LOOKUP, columns::BODY, id)? {
|
if let Some(body) = read_db(&*self.db, columns::KEY_LOOKUP, columns::BODY, id)? {
|
||||||
Some(body) => body,
|
// Plain body
|
||||||
None => return Ok(None),
|
match Decode::decode(&mut &body[..]) {
|
||||||
};
|
Ok(body) => return Ok(Some(body)),
|
||||||
match self.transaction_storage {
|
|
||||||
TransactionStorageMode::BlockBody => match Decode::decode(&mut &body[..]) {
|
|
||||||
Ok(body) => Ok(Some(body)),
|
|
||||||
Err(err) =>
|
Err(err) =>
|
||||||
return Err(sp_blockchain::Error::Backend(format!(
|
return Err(sp_blockchain::Error::Backend(format!(
|
||||||
"Error decoding body: {}",
|
"Error decoding body: {}",
|
||||||
err
|
err
|
||||||
))),
|
))),
|
||||||
},
|
}
|
||||||
TransactionStorageMode::StorageChain => {
|
|
||||||
match Vec::<ExtrinsicHeader>::decode(&mut &body[..]) {
|
|
||||||
Ok(index) => {
|
|
||||||
let extrinsics: ClientResult<Vec<Block::Extrinsic>> = index
|
|
||||||
.into_iter()
|
|
||||||
.map(|ExtrinsicHeader { indexed_hash, data }| {
|
|
||||||
let decode_result = if indexed_hash != Default::default() {
|
|
||||||
match self.db.get(columns::TRANSACTION, indexed_hash.as_ref()) {
|
|
||||||
Some(t) => {
|
|
||||||
let mut input =
|
|
||||||
utils::join_input(data.as_ref(), t.as_ref());
|
|
||||||
Block::Extrinsic::decode(&mut input)
|
|
||||||
},
|
|
||||||
None =>
|
|
||||||
return Err(sp_blockchain::Error::Backend(format!(
|
|
||||||
"Missing indexed transaction {:?}",
|
|
||||||
indexed_hash
|
|
||||||
))),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Block::Extrinsic::decode(&mut data.as_ref())
|
|
||||||
};
|
|
||||||
decode_result.map_err(|err| {
|
|
||||||
sp_blockchain::Error::Backend(format!(
|
|
||||||
"Error decoding extrinsic: {}",
|
|
||||||
err
|
|
||||||
))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
Ok(Some(extrinsics?))
|
|
||||||
},
|
|
||||||
Err(err) =>
|
|
||||||
return Err(sp_blockchain::Error::Backend(format!(
|
|
||||||
"Error decoding body list: {}",
|
|
||||||
err
|
|
||||||
))),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(index) = read_db(&*self.db, columns::KEY_LOOKUP, columns::BODY_INDEX, id)? {
|
||||||
|
match Vec::<DbExtrinsic<Block>>::decode(&mut &index[..]) {
|
||||||
|
Ok(index) => {
|
||||||
|
let mut body = Vec::new();
|
||||||
|
for ex in index {
|
||||||
|
match ex {
|
||||||
|
DbExtrinsic::Indexed { hash, header } => {
|
||||||
|
match self.db.get(columns::TRANSACTION, hash.as_ref()) {
|
||||||
|
Some(t) => {
|
||||||
|
let mut input =
|
||||||
|
utils::join_input(header.as_ref(), t.as_ref());
|
||||||
|
let ex = Block::Extrinsic::decode(&mut input).map_err(
|
||||||
|
|err| {
|
||||||
|
sp_blockchain::Error::Backend(format!(
|
||||||
|
"Error decoding indexed extrinsic: {}",
|
||||||
|
err
|
||||||
|
))
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
body.push(ex);
|
||||||
|
},
|
||||||
|
None =>
|
||||||
|
return Err(sp_blockchain::Error::Backend(format!(
|
||||||
|
"Missing indexed transaction {:?}",
|
||||||
|
hash
|
||||||
|
))),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
DbExtrinsic::Full(ex) => {
|
||||||
|
body.push(ex);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(Some(body))
|
||||||
|
},
|
||||||
|
Err(err) =>
|
||||||
|
return Err(sp_blockchain::Error::Backend(format!(
|
||||||
|
"Error decoding body list: {}",
|
||||||
|
err
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn justifications(&self, id: BlockId<Block>) -> ClientResult<Option<Justifications>> {
|
fn justifications(&self, id: BlockId<Block>) -> ClientResult<Option<Justifications>> {
|
||||||
@@ -648,37 +639,29 @@ impl<Block: BlockT> sc_client_api::blockchain::Backend<Block> for BlockchainDb<B
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn block_indexed_body(&self, id: BlockId<Block>) -> ClientResult<Option<Vec<Vec<u8>>>> {
|
fn block_indexed_body(&self, id: BlockId<Block>) -> ClientResult<Option<Vec<Vec<u8>>>> {
|
||||||
match self.transaction_storage {
|
let body = match read_db(&*self.db, columns::KEY_LOOKUP, columns::BODY_INDEX, id)? {
|
||||||
TransactionStorageMode::BlockBody => Ok(None),
|
Some(body) => body,
|
||||||
TransactionStorageMode::StorageChain => {
|
None => return Ok(None),
|
||||||
let body = match read_db(&*self.db, columns::KEY_LOOKUP, columns::BODY, id)? {
|
};
|
||||||
Some(body) => body,
|
match Vec::<DbExtrinsic<Block>>::decode(&mut &body[..]) {
|
||||||
None => return Ok(None),
|
Ok(index) => {
|
||||||
};
|
let mut transactions = Vec::new();
|
||||||
match Vec::<ExtrinsicHeader>::decode(&mut &body[..]) {
|
for ex in index.into_iter() {
|
||||||
Ok(index) => {
|
if let DbExtrinsic::Indexed { hash, .. } = ex {
|
||||||
let mut transactions = Vec::new();
|
match self.db.get(columns::TRANSACTION, hash.as_ref()) {
|
||||||
for ExtrinsicHeader { indexed_hash, .. } in index.into_iter() {
|
Some(t) => transactions.push(t),
|
||||||
if indexed_hash != Default::default() {
|
None =>
|
||||||
match self.db.get(columns::TRANSACTION, indexed_hash.as_ref()) {
|
return Err(sp_blockchain::Error::Backend(format!(
|
||||||
Some(t) => transactions.push(t),
|
"Missing indexed transaction {:?}",
|
||||||
None =>
|
hash
|
||||||
return Err(sp_blockchain::Error::Backend(format!(
|
))),
|
||||||
"Missing indexed transaction {:?}",
|
|
||||||
indexed_hash
|
|
||||||
))),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(Some(transactions))
|
}
|
||||||
},
|
|
||||||
Err(err) =>
|
|
||||||
return Err(sp_blockchain::Error::Backend(format!(
|
|
||||||
"Error decoding body list: {}",
|
|
||||||
err
|
|
||||||
))),
|
|
||||||
}
|
}
|
||||||
|
Ok(Some(transactions))
|
||||||
},
|
},
|
||||||
|
Err(err) =>
|
||||||
|
Err(sp_blockchain::Error::Backend(format!("Error decoding body list: {}", err))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1005,7 +988,6 @@ pub struct Backend<Block: BlockT> {
|
|||||||
import_lock: Arc<RwLock<()>>,
|
import_lock: Arc<RwLock<()>>,
|
||||||
is_archive: bool,
|
is_archive: bool,
|
||||||
keep_blocks: KeepBlocks,
|
keep_blocks: KeepBlocks,
|
||||||
transaction_storage: TransactionStorageMode,
|
|
||||||
io_stats: FrozenForDuration<(kvdb::IoStats, StateUsageInfo)>,
|
io_stats: FrozenForDuration<(kvdb::IoStats, StateUsageInfo)>,
|
||||||
state_usage: Arc<StateUsageStats>,
|
state_usage: Arc<StateUsageStats>,
|
||||||
genesis_state: RwLock<Option<Arc<DbGenesisStorage<Block>>>>,
|
genesis_state: RwLock<Option<Arc<DbGenesisStorage<Block>>>>,
|
||||||
@@ -1023,20 +1005,12 @@ impl<Block: BlockT> Backend<Block> {
|
|||||||
/// Create new memory-backed client backend for tests.
|
/// Create new memory-backed client backend for tests.
|
||||||
#[cfg(any(test, feature = "test-helpers"))]
|
#[cfg(any(test, feature = "test-helpers"))]
|
||||||
pub fn new_test(keep_blocks: u32, canonicalization_delay: u64) -> Self {
|
pub fn new_test(keep_blocks: u32, canonicalization_delay: u64) -> Self {
|
||||||
Self::new_test_with_tx_storage(
|
Self::new_test_with_tx_storage(keep_blocks, canonicalization_delay)
|
||||||
keep_blocks,
|
|
||||||
canonicalization_delay,
|
|
||||||
TransactionStorageMode::BlockBody,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create new memory-backed client backend for tests.
|
/// Create new memory-backed client backend for tests.
|
||||||
#[cfg(any(test, feature = "test-helpers"))]
|
#[cfg(any(test, feature = "test-helpers"))]
|
||||||
pub fn new_test_with_tx_storage(
|
pub fn new_test_with_tx_storage(keep_blocks: u32, canonicalization_delay: u64) -> Self {
|
||||||
keep_blocks: u32,
|
|
||||||
canonicalization_delay: u64,
|
|
||||||
transaction_storage: TransactionStorageMode,
|
|
||||||
) -> Self {
|
|
||||||
let db = kvdb_memorydb::create(crate::utils::NUM_COLUMNS);
|
let db = kvdb_memorydb::create(crate::utils::NUM_COLUMNS);
|
||||||
let db = sp_database::as_database(db);
|
let db = sp_database::as_database(db);
|
||||||
let db_setting = DatabaseSettings {
|
let db_setting = DatabaseSettings {
|
||||||
@@ -1045,7 +1019,6 @@ impl<Block: BlockT> Backend<Block> {
|
|||||||
state_pruning: PruningMode::keep_blocks(keep_blocks),
|
state_pruning: PruningMode::keep_blocks(keep_blocks),
|
||||||
source: DatabaseSource::Custom(db),
|
source: DatabaseSource::Custom(db),
|
||||||
keep_blocks: KeepBlocks::Some(keep_blocks),
|
keep_blocks: KeepBlocks::Some(keep_blocks),
|
||||||
transaction_storage,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Self::new(db_setting, canonicalization_delay).expect("failed to create test-db")
|
Self::new(db_setting, canonicalization_delay).expect("failed to create test-db")
|
||||||
@@ -1074,7 +1047,7 @@ impl<Block: BlockT> Backend<Block> {
|
|||||||
config: &DatabaseSettings,
|
config: &DatabaseSettings,
|
||||||
) -> ClientResult<Self> {
|
) -> ClientResult<Self> {
|
||||||
let is_archive_pruning = config.state_pruning.is_archive();
|
let is_archive_pruning = config.state_pruning.is_archive();
|
||||||
let blockchain = BlockchainDb::new(db.clone(), config.transaction_storage.clone())?;
|
let blockchain = BlockchainDb::new(db.clone())?;
|
||||||
let map_e = |e: sc_state_db::Error<io::Error>| sp_blockchain::Error::from_state_db(e);
|
let map_e = |e: sc_state_db::Error<io::Error>| sp_blockchain::Error::from_state_db(e);
|
||||||
let state_db: StateDb<_, _> = StateDb::new(
|
let state_db: StateDb<_, _> = StateDb::new(
|
||||||
config.state_pruning.clone(),
|
config.state_pruning.clone(),
|
||||||
@@ -1100,7 +1073,6 @@ impl<Block: BlockT> Backend<Block> {
|
|||||||
io_stats: FrozenForDuration::new(std::time::Duration::from_secs(1)),
|
io_stats: FrozenForDuration::new(std::time::Duration::from_secs(1)),
|
||||||
state_usage: Arc::new(StateUsageStats::new()),
|
state_usage: Arc::new(StateUsageStats::new()),
|
||||||
keep_blocks: config.keep_blocks.clone(),
|
keep_blocks: config.keep_blocks.clone(),
|
||||||
transaction_storage: config.transaction_storage.clone(),
|
|
||||||
genesis_state: RwLock::new(None),
|
genesis_state: RwLock::new(None),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1334,26 +1306,18 @@ impl<Block: BlockT> Backend<Block> {
|
|||||||
|
|
||||||
transaction.set_from_vec(columns::HEADER, &lookup_key, pending_block.header.encode());
|
transaction.set_from_vec(columns::HEADER, &lookup_key, pending_block.header.encode());
|
||||||
if let Some(body) = pending_block.body {
|
if let Some(body) = pending_block.body {
|
||||||
match self.transaction_storage {
|
// If we have any index operations we save block in the new format with indexed
|
||||||
TransactionStorageMode::BlockBody => {
|
// extrinsic headers Otherwise we save the body as a single blob.
|
||||||
transaction.set_from_vec(columns::BODY, &lookup_key, body.encode());
|
if operation.index_ops.is_empty() {
|
||||||
},
|
transaction.set_from_vec(columns::BODY, &lookup_key, body.encode());
|
||||||
TransactionStorageMode::StorageChain => {
|
} else {
|
||||||
let body =
|
let body =
|
||||||
apply_index_ops::<Block>(&mut transaction, body, operation.index_ops);
|
apply_index_ops::<Block>(&mut transaction, body, operation.index_ops);
|
||||||
transaction.set_from_vec(columns::BODY, &lookup_key, body);
|
transaction.set_from_vec(columns::BODY_INDEX, &lookup_key, body);
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(body) = pending_block.indexed_body {
|
if let Some(body) = pending_block.indexed_body {
|
||||||
match self.transaction_storage {
|
apply_indexed_body::<Block>(&mut transaction, body);
|
||||||
TransactionStorageMode::BlockBody => {
|
|
||||||
debug!(target: "db", "Commit: ignored indexed block body");
|
|
||||||
},
|
|
||||||
TransactionStorageMode::StorageChain => {
|
|
||||||
apply_indexed_body::<Block>(&mut transaction, body);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if let Some(justifications) = pending_block.justifications {
|
if let Some(justifications) = pending_block.justifications {
|
||||||
transaction.set_from_vec(
|
transaction.set_from_vec(
|
||||||
@@ -1691,7 +1655,7 @@ impl<Block: BlockT> Backend<Block> {
|
|||||||
let mut hash = h.clone();
|
let mut hash = h.clone();
|
||||||
// Follow displaced chains back until we reach a finalized block.
|
// Follow displaced chains back until we reach a finalized block.
|
||||||
// Since leaves are discarded due to finality, they can't have parents
|
// Since leaves are discarded due to finality, they can't have parents
|
||||||
// that are canonical, but not yet finalized. So we stop deletig as soon as
|
// that are canonical, but not yet finalized. So we stop deleting as soon as
|
||||||
// we reach canonical chain.
|
// we reach canonical chain.
|
||||||
while self.blockchain.hash(number)? != Some(hash.clone()) {
|
while self.blockchain.hash(number)? != Some(hash.clone()) {
|
||||||
let id = BlockId::<Block>::hash(hash.clone());
|
let id = BlockId::<Block>::hash(hash.clone());
|
||||||
@@ -1714,36 +1678,37 @@ impl<Block: BlockT> Backend<Block> {
|
|||||||
transaction: &mut Transaction<DbHash>,
|
transaction: &mut Transaction<DbHash>,
|
||||||
id: BlockId<Block>,
|
id: BlockId<Block>,
|
||||||
) -> ClientResult<()> {
|
) -> ClientResult<()> {
|
||||||
match read_db(&*self.storage.db, columns::KEY_LOOKUP, columns::BODY, id)? {
|
debug!(target: "db", "Removing block #{}", id);
|
||||||
Some(body) => {
|
utils::remove_from_db(
|
||||||
debug!(target: "db", "Removing block #{}", id);
|
transaction,
|
||||||
utils::remove_from_db(
|
&*self.storage.db,
|
||||||
transaction,
|
columns::KEY_LOOKUP,
|
||||||
&*self.storage.db,
|
columns::BODY,
|
||||||
columns::KEY_LOOKUP,
|
id,
|
||||||
columns::BODY,
|
)?;
|
||||||
id,
|
if let Some(index) =
|
||||||
)?;
|
read_db(&*self.storage.db, columns::KEY_LOOKUP, columns::BODY_INDEX, id)?
|
||||||
match self.transaction_storage {
|
{
|
||||||
TransactionStorageMode::BlockBody => {},
|
utils::remove_from_db(
|
||||||
TransactionStorageMode::StorageChain => {
|
transaction,
|
||||||
match Vec::<ExtrinsicHeader>::decode(&mut &body[..]) {
|
&*self.storage.db,
|
||||||
Ok(body) =>
|
columns::KEY_LOOKUP,
|
||||||
for ExtrinsicHeader { indexed_hash, .. } in body {
|
columns::BODY_INDEX,
|
||||||
if indexed_hash != Default::default() {
|
id,
|
||||||
transaction.release(columns::TRANSACTION, indexed_hash);
|
)?;
|
||||||
}
|
match Vec::<DbExtrinsic<Block>>::decode(&mut &index[..]) {
|
||||||
},
|
Ok(index) =>
|
||||||
Err(err) =>
|
for ex in index {
|
||||||
return Err(sp_blockchain::Error::Backend(format!(
|
if let DbExtrinsic::Indexed { hash, .. } = ex {
|
||||||
"Error decoding body list: {}",
|
transaction.release(columns::TRANSACTION, hash);
|
||||||
err
|
|
||||||
))),
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
Err(err) =>
|
||||||
},
|
return Err(sp_blockchain::Error::Backend(format!(
|
||||||
None => return Ok(()),
|
"Error decoding body list: {}",
|
||||||
|
err
|
||||||
|
))),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -1785,7 +1750,7 @@ fn apply_index_ops<Block: BlockT>(
|
|||||||
body: Vec<Block::Extrinsic>,
|
body: Vec<Block::Extrinsic>,
|
||||||
ops: Vec<IndexOperation>,
|
ops: Vec<IndexOperation>,
|
||||||
) -> Vec<u8> {
|
) -> Vec<u8> {
|
||||||
let mut extrinsic_headers: Vec<ExtrinsicHeader> = Vec::with_capacity(body.len());
|
let mut extrinsic_index: Vec<DbExtrinsic<Block>> = Vec::with_capacity(body.len());
|
||||||
let mut index_map = HashMap::new();
|
let mut index_map = HashMap::new();
|
||||||
let mut renewed_map = HashMap::new();
|
let mut renewed_map = HashMap::new();
|
||||||
for op in ops {
|
for op in ops {
|
||||||
@@ -1799,37 +1764,44 @@ fn apply_index_ops<Block: BlockT>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (index, extrinsic) in body.into_iter().enumerate() {
|
for (index, extrinsic) in body.into_iter().enumerate() {
|
||||||
let extrinsic = extrinsic.encode();
|
let db_extrinsic = if let Some(hash) = renewed_map.get(&(index as u32)) {
|
||||||
let extrinsic_header = if let Some(hash) = renewed_map.get(&(index as u32)) {
|
|
||||||
// Bump ref counter
|
// Bump ref counter
|
||||||
|
let extrinsic = extrinsic.encode();
|
||||||
transaction.reference(columns::TRANSACTION, DbHash::from_slice(hash.as_ref()));
|
transaction.reference(columns::TRANSACTION, DbHash::from_slice(hash.as_ref()));
|
||||||
ExtrinsicHeader { indexed_hash: hash.clone(), data: extrinsic }
|
DbExtrinsic::Indexed { hash: hash.clone(), header: extrinsic }
|
||||||
} else {
|
} else {
|
||||||
match index_map.get(&(index as u32)) {
|
match index_map.get(&(index as u32)) {
|
||||||
Some((hash, size)) if *size as usize <= extrinsic.len() => {
|
Some((hash, size)) => {
|
||||||
let offset = extrinsic.len() - *size as usize;
|
let encoded = extrinsic.encode();
|
||||||
transaction.store(
|
if *size as usize <= encoded.len() {
|
||||||
columns::TRANSACTION,
|
let offset = encoded.len() - *size as usize;
|
||||||
DbHash::from_slice(hash.as_ref()),
|
transaction.store(
|
||||||
extrinsic[offset..].to_vec(),
|
columns::TRANSACTION,
|
||||||
);
|
DbHash::from_slice(hash.as_ref()),
|
||||||
ExtrinsicHeader {
|
encoded[offset..].to_vec(),
|
||||||
indexed_hash: DbHash::from_slice(hash.as_ref()),
|
);
|
||||||
data: extrinsic[..offset].to_vec(),
|
DbExtrinsic::Indexed {
|
||||||
|
hash: DbHash::from_slice(hash.as_ref()),
|
||||||
|
header: encoded[..offset].to_vec(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Invalid indexed slice. Just store full data and don't index anything.
|
||||||
|
DbExtrinsic::Full(extrinsic)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => ExtrinsicHeader { indexed_hash: Default::default(), data: extrinsic },
|
_ => DbExtrinsic::Full(extrinsic),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
extrinsic_headers.push(extrinsic_header);
|
extrinsic_index.push(db_extrinsic);
|
||||||
}
|
}
|
||||||
debug!(
|
debug!(
|
||||||
target: "db",
|
target: "db",
|
||||||
"DB transaction index: {} inserted, {} renewed",
|
"DB transaction index: {} inserted, {} renewed, {} full",
|
||||||
index_map.len(),
|
index_map.len(),
|
||||||
renewed_map.len()
|
renewed_map.len(),
|
||||||
|
extrinsic_index.len() - index_map.len() - renewed_map.len(),
|
||||||
);
|
);
|
||||||
extrinsic_headers.encode()
|
extrinsic_index.encode()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_indexed_body<Block: BlockT>(transaction: &mut Transaction<DbHash>, body: Vec<Vec<u8>>) {
|
fn apply_indexed_body<Block: BlockT>(transaction: &mut Transaction<DbHash>, body: Vec<Vec<u8>>) {
|
||||||
@@ -2417,7 +2389,6 @@ pub(crate) mod tests {
|
|||||||
state_pruning: PruningMode::keep_blocks(1),
|
state_pruning: PruningMode::keep_blocks(1),
|
||||||
source: DatabaseSource::Custom(backing),
|
source: DatabaseSource::Custom(backing),
|
||||||
keep_blocks: KeepBlocks::All,
|
keep_blocks: KeepBlocks::All,
|
||||||
transaction_storage: TransactionStorageMode::BlockBody,
|
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
@@ -3087,46 +3058,43 @@ pub(crate) mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn prune_blocks_on_finalize() {
|
fn prune_blocks_on_finalize() {
|
||||||
for storage in &[TransactionStorageMode::BlockBody, TransactionStorageMode::StorageChain] {
|
let backend = Backend::<Block>::new_test_with_tx_storage(2, 0);
|
||||||
let backend = Backend::<Block>::new_test_with_tx_storage(2, 0, *storage);
|
let mut blocks = Vec::new();
|
||||||
let mut blocks = Vec::new();
|
let mut prev_hash = Default::default();
|
||||||
let mut prev_hash = Default::default();
|
for i in 0..5 {
|
||||||
for i in 0..5 {
|
let hash = insert_block(
|
||||||
let hash = insert_block(
|
&backend,
|
||||||
&backend,
|
i,
|
||||||
i,
|
prev_hash,
|
||||||
prev_hash,
|
None,
|
||||||
None,
|
Default::default(),
|
||||||
Default::default(),
|
vec![i.into()],
|
||||||
vec![i.into()],
|
None,
|
||||||
None,
|
)
|
||||||
)
|
.unwrap();
|
||||||
.unwrap();
|
blocks.push(hash);
|
||||||
blocks.push(hash);
|
prev_hash = hash;
|
||||||
prev_hash = hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
let mut op = backend.begin_operation().unwrap();
|
|
||||||
backend.begin_state_operation(&mut op, BlockId::Hash(blocks[4])).unwrap();
|
|
||||||
for i in 1..5 {
|
|
||||||
op.mark_finalized(BlockId::Hash(blocks[i]), None).unwrap();
|
|
||||||
}
|
|
||||||
backend.commit_operation(op).unwrap();
|
|
||||||
}
|
|
||||||
let bc = backend.blockchain();
|
|
||||||
assert_eq!(None, bc.body(BlockId::hash(blocks[0])).unwrap());
|
|
||||||
assert_eq!(None, bc.body(BlockId::hash(blocks[1])).unwrap());
|
|
||||||
assert_eq!(None, bc.body(BlockId::hash(blocks[2])).unwrap());
|
|
||||||
assert_eq!(Some(vec![3.into()]), bc.body(BlockId::hash(blocks[3])).unwrap());
|
|
||||||
assert_eq!(Some(vec![4.into()]), bc.body(BlockId::hash(blocks[4])).unwrap());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut op = backend.begin_operation().unwrap();
|
||||||
|
backend.begin_state_operation(&mut op, BlockId::Hash(blocks[4])).unwrap();
|
||||||
|
for i in 1..5 {
|
||||||
|
op.mark_finalized(BlockId::Hash(blocks[i]), None).unwrap();
|
||||||
|
}
|
||||||
|
backend.commit_operation(op).unwrap();
|
||||||
|
}
|
||||||
|
let bc = backend.blockchain();
|
||||||
|
assert_eq!(None, bc.body(BlockId::hash(blocks[0])).unwrap());
|
||||||
|
assert_eq!(None, bc.body(BlockId::hash(blocks[1])).unwrap());
|
||||||
|
assert_eq!(None, bc.body(BlockId::hash(blocks[2])).unwrap());
|
||||||
|
assert_eq!(Some(vec![3.into()]), bc.body(BlockId::hash(blocks[3])).unwrap());
|
||||||
|
assert_eq!(Some(vec![4.into()]), bc.body(BlockId::hash(blocks[4])).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn prune_blocks_on_finalize_with_fork() {
|
fn prune_blocks_on_finalize_with_fork() {
|
||||||
let backend =
|
let backend = Backend::<Block>::new_test_with_tx_storage(2, 10);
|
||||||
Backend::<Block>::new_test_with_tx_storage(2, 10, TransactionStorageMode::StorageChain);
|
|
||||||
let mut blocks = Vec::new();
|
let mut blocks = Vec::new();
|
||||||
let mut prev_hash = Default::default();
|
let mut prev_hash = Default::default();
|
||||||
for i in 0..5 {
|
for i in 0..5 {
|
||||||
@@ -3185,10 +3153,86 @@ pub(crate) mod tests {
|
|||||||
assert_eq!(Some(vec![4.into()]), bc.body(BlockId::hash(blocks[4])).unwrap());
|
assert_eq!(Some(vec![4.into()]), bc.body(BlockId::hash(blocks[4])).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn indexed_data_block_body() {
|
||||||
|
let backend = Backend::<Block>::new_test_with_tx_storage(1, 10);
|
||||||
|
|
||||||
|
let x0 = ExtrinsicWrapper::from(0u64).encode();
|
||||||
|
let x1 = ExtrinsicWrapper::from(1u64).encode();
|
||||||
|
let x0_hash = <HashFor<Block> as sp_core::Hasher>::hash(&x0[1..]);
|
||||||
|
let x1_hash = <HashFor<Block> as sp_core::Hasher>::hash(&x1[1..]);
|
||||||
|
let index = vec![
|
||||||
|
IndexOperation::Insert {
|
||||||
|
extrinsic: 0,
|
||||||
|
hash: x0_hash.as_ref().to_vec(),
|
||||||
|
size: (x0.len() - 1) as u32,
|
||||||
|
},
|
||||||
|
IndexOperation::Insert {
|
||||||
|
extrinsic: 1,
|
||||||
|
hash: x1_hash.as_ref().to_vec(),
|
||||||
|
size: (x1.len() - 1) as u32,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
let hash = insert_block(
|
||||||
|
&backend,
|
||||||
|
0,
|
||||||
|
Default::default(),
|
||||||
|
None,
|
||||||
|
Default::default(),
|
||||||
|
vec![0u64.into(), 1u64.into()],
|
||||||
|
Some(index),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let bc = backend.blockchain();
|
||||||
|
assert_eq!(bc.indexed_transaction(&x0_hash).unwrap().unwrap(), &x0[1..]);
|
||||||
|
assert_eq!(bc.indexed_transaction(&x1_hash).unwrap().unwrap(), &x1[1..]);
|
||||||
|
|
||||||
|
// Push one more blocks and make sure block is pruned and transaction index is cleared.
|
||||||
|
insert_block(&backend, 1, hash, None, Default::default(), vec![], None).unwrap();
|
||||||
|
backend.finalize_block(BlockId::Number(1), None).unwrap();
|
||||||
|
assert_eq!(bc.body(BlockId::Number(0)).unwrap(), None);
|
||||||
|
assert_eq!(bc.indexed_transaction(&x0_hash).unwrap(), None);
|
||||||
|
assert_eq!(bc.indexed_transaction(&x1_hash).unwrap(), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn index_invalid_size() {
|
||||||
|
let backend = Backend::<Block>::new_test_with_tx_storage(1, 10);
|
||||||
|
|
||||||
|
let x0 = ExtrinsicWrapper::from(0u64).encode();
|
||||||
|
let x1 = ExtrinsicWrapper::from(1u64).encode();
|
||||||
|
let x0_hash = <HashFor<Block> as sp_core::Hasher>::hash(&x0[..]);
|
||||||
|
let x1_hash = <HashFor<Block> as sp_core::Hasher>::hash(&x1[..]);
|
||||||
|
let index = vec![
|
||||||
|
IndexOperation::Insert {
|
||||||
|
extrinsic: 0,
|
||||||
|
hash: x0_hash.as_ref().to_vec(),
|
||||||
|
size: (x0.len()) as u32,
|
||||||
|
},
|
||||||
|
IndexOperation::Insert {
|
||||||
|
extrinsic: 1,
|
||||||
|
hash: x1_hash.as_ref().to_vec(),
|
||||||
|
size: (x1.len() + 1) as u32,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
insert_block(
|
||||||
|
&backend,
|
||||||
|
0,
|
||||||
|
Default::default(),
|
||||||
|
None,
|
||||||
|
Default::default(),
|
||||||
|
vec![0u64.into(), 1u64.into()],
|
||||||
|
Some(index),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let bc = backend.blockchain();
|
||||||
|
assert_eq!(bc.indexed_transaction(&x0_hash).unwrap().unwrap(), &x0[..]);
|
||||||
|
assert_eq!(bc.indexed_transaction(&x1_hash).unwrap(), None);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn renew_transaction_storage() {
|
fn renew_transaction_storage() {
|
||||||
let backend =
|
let backend = Backend::<Block>::new_test_with_tx_storage(2, 10);
|
||||||
Backend::<Block>::new_test_with_tx_storage(2, 10, TransactionStorageMode::StorageChain);
|
|
||||||
let mut blocks = Vec::new();
|
let mut blocks = Vec::new();
|
||||||
let mut prev_hash = Default::default();
|
let mut prev_hash = Default::default();
|
||||||
let x1 = ExtrinsicWrapper::from(0u64).encode();
|
let x1 = ExtrinsicWrapper::from(0u64).encode();
|
||||||
@@ -3235,8 +3279,7 @@ pub(crate) mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_leaf_block_works() {
|
fn remove_leaf_block_works() {
|
||||||
let backend =
|
let backend = Backend::<Block>::new_test_with_tx_storage(2, 10);
|
||||||
Backend::<Block>::new_test_with_tx_storage(2, 10, TransactionStorageMode::StorageChain);
|
|
||||||
let mut blocks = Vec::new();
|
let mut blocks = Vec::new();
|
||||||
let mut prev_hash = Default::default();
|
let mut prev_hash = Default::default();
|
||||||
for i in 0..2 {
|
for i in 0..2 {
|
||||||
|
|||||||
@@ -38,20 +38,22 @@ pub fn open<H: Clone + AsRef<[u8]>>(
|
|||||||
path: &std::path::Path,
|
path: &std::path::Path,
|
||||||
db_type: DatabaseType,
|
db_type: DatabaseType,
|
||||||
create: bool,
|
create: bool,
|
||||||
|
upgrade: bool,
|
||||||
) -> parity_db::Result<std::sync::Arc<dyn Database<H>>> {
|
) -> parity_db::Result<std::sync::Arc<dyn Database<H>>> {
|
||||||
let mut config = parity_db::Options::with_columns(path, NUM_COLUMNS as u8);
|
let mut config = parity_db::Options::with_columns(path, NUM_COLUMNS as u8);
|
||||||
|
|
||||||
match db_type {
|
match db_type {
|
||||||
DatabaseType::Full => {
|
DatabaseType::Full => {
|
||||||
let indexes = [
|
let compressed = [
|
||||||
columns::STATE,
|
columns::STATE,
|
||||||
columns::HEADER,
|
columns::HEADER,
|
||||||
columns::BODY,
|
columns::BODY,
|
||||||
|
columns::BODY_INDEX,
|
||||||
columns::TRANSACTION,
|
columns::TRANSACTION,
|
||||||
columns::JUSTIFICATIONS,
|
columns::JUSTIFICATIONS,
|
||||||
];
|
];
|
||||||
|
|
||||||
for i in indexes {
|
for i in compressed {
|
||||||
let mut column = &mut config.columns[i as usize];
|
let mut column = &mut config.columns[i as usize];
|
||||||
column.compression = parity_db::CompressionType::Lz4;
|
column.compression = parity_db::CompressionType::Lz4;
|
||||||
}
|
}
|
||||||
@@ -60,9 +62,21 @@ pub fn open<H: Clone + AsRef<[u8]>>(
|
|||||||
state_col.ref_counted = true;
|
state_col.ref_counted = true;
|
||||||
state_col.preimage = true;
|
state_col.preimage = true;
|
||||||
state_col.uniform = true;
|
state_col.uniform = true;
|
||||||
|
|
||||||
|
let mut tx_col = &mut config.columns[columns::TRANSACTION as usize];
|
||||||
|
tx_col.ref_counted = true;
|
||||||
|
tx_col.preimage = true;
|
||||||
|
tx_col.uniform = true;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if upgrade {
|
||||||
|
log::info!("Upgrading database metadata.");
|
||||||
|
if let Some(meta) = parity_db::Options::load_metadata(path)? {
|
||||||
|
config.write_metadata(path, &meta.salt)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let db = if create {
|
let db = if create {
|
||||||
parity_db::Db::open_or_create(&config)?
|
parity_db::Db::open_or_create(&config)?
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -33,11 +33,12 @@ use sp_runtime::traits::Block as BlockT;
|
|||||||
const VERSION_FILE_NAME: &'static str = "db_version";
|
const VERSION_FILE_NAME: &'static str = "db_version";
|
||||||
|
|
||||||
/// Current db version.
|
/// Current db version.
|
||||||
const CURRENT_VERSION: u32 = 3;
|
const CURRENT_VERSION: u32 = 4;
|
||||||
|
|
||||||
/// Number of columns in v1.
|
/// Number of columns in v1.
|
||||||
const V1_NUM_COLUMNS: u32 = 11;
|
const V1_NUM_COLUMNS: u32 = 11;
|
||||||
const V2_NUM_COLUMNS: u32 = 12;
|
const V2_NUM_COLUMNS: u32 = 12;
|
||||||
|
const V3_NUM_COLUMNS: u32 = 12;
|
||||||
|
|
||||||
/// Database upgrade errors.
|
/// Database upgrade errors.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -68,7 +69,7 @@ impl fmt::Display for UpgradeError {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
UpgradeError::UnknownDatabaseVersion => {
|
UpgradeError::UnknownDatabaseVersion => {
|
||||||
write!(f, "Database version cannot be read from exisiting db_version file")
|
write!(f, "Database version cannot be read from existing db_version file")
|
||||||
},
|
},
|
||||||
UpgradeError::MissingDatabaseVersionFile => write!(f, "Missing database version file"),
|
UpgradeError::MissingDatabaseVersionFile => write!(f, "Missing database version file"),
|
||||||
UpgradeError::UnsupportedVersion(version) => {
|
UpgradeError::UnsupportedVersion(version) => {
|
||||||
@@ -92,9 +93,16 @@ pub fn upgrade_db<Block: BlockT>(db_path: &Path, db_type: DatabaseType) -> Upgra
|
|||||||
0 => return Err(UpgradeError::UnsupportedVersion(db_version)),
|
0 => return Err(UpgradeError::UnsupportedVersion(db_version)),
|
||||||
1 => {
|
1 => {
|
||||||
migrate_1_to_2::<Block>(db_path, db_type)?;
|
migrate_1_to_2::<Block>(db_path, db_type)?;
|
||||||
migrate_2_to_3::<Block>(db_path, db_type)?
|
migrate_2_to_3::<Block>(db_path, db_type)?;
|
||||||
|
migrate_3_to_4::<Block>(db_path, db_type)?;
|
||||||
|
},
|
||||||
|
2 => {
|
||||||
|
migrate_2_to_3::<Block>(db_path, db_type)?;
|
||||||
|
migrate_3_to_4::<Block>(db_path, db_type)?;
|
||||||
|
},
|
||||||
|
3 => {
|
||||||
|
migrate_3_to_4::<Block>(db_path, db_type)?;
|
||||||
},
|
},
|
||||||
2 => migrate_2_to_3::<Block>(db_path, db_type)?,
|
|
||||||
CURRENT_VERSION => (),
|
CURRENT_VERSION => (),
|
||||||
_ => return Err(UpgradeError::FutureDatabaseVersion(db_version)),
|
_ => return Err(UpgradeError::FutureDatabaseVersion(db_version)),
|
||||||
}
|
}
|
||||||
@@ -139,6 +147,15 @@ fn migrate_2_to_3<Block: BlockT>(db_path: &Path, _db_type: DatabaseType) -> Upgr
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Migration from version3 to version4:
|
||||||
|
/// 1) the number of columns has changed from 12 to 13;
|
||||||
|
/// 2) BODY_INDEX column is added;
|
||||||
|
fn migrate_3_to_4<Block: BlockT>(db_path: &Path, _db_type: DatabaseType) -> UpgradeResult<()> {
|
||||||
|
let db_cfg = DatabaseConfig::with_columns(V3_NUM_COLUMNS);
|
||||||
|
let db = Database::open(&db_cfg, db_path)?;
|
||||||
|
db.add_column().map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
/// Reads current database version from the file at given path.
|
/// Reads current database version from the file at given path.
|
||||||
/// If the file does not exist returns 0.
|
/// If the file does not exist returns 0.
|
||||||
fn current_version(path: &Path) -> UpgradeResult<u32> {
|
fn current_version(path: &Path) -> UpgradeResult<u32> {
|
||||||
@@ -173,9 +190,7 @@ fn version_file_path(path: &Path) -> PathBuf {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{
|
use crate::{tests::Block, DatabaseSettings, DatabaseSource, KeepBlocks};
|
||||||
tests::Block, DatabaseSettings, DatabaseSource, KeepBlocks, TransactionStorageMode,
|
|
||||||
};
|
|
||||||
use sc_state_db::PruningMode;
|
use sc_state_db::PruningMode;
|
||||||
|
|
||||||
fn create_db(db_path: &Path, version: Option<u32>) {
|
fn create_db(db_path: &Path, version: Option<u32>) {
|
||||||
@@ -194,7 +209,6 @@ mod tests {
|
|||||||
state_pruning: PruningMode::ArchiveAll,
|
state_pruning: PruningMode::ArchiveAll,
|
||||||
source: DatabaseSource::RocksDb { path: db_path.to_owned(), cache_size: 128 },
|
source: DatabaseSource::RocksDb { path: db_path.to_owned(), cache_size: 128 },
|
||||||
keep_blocks: KeepBlocks::All,
|
keep_blocks: KeepBlocks::All,
|
||||||
transaction_storage: TransactionStorageMode::BlockBody,
|
|
||||||
},
|
},
|
||||||
db_type,
|
db_type,
|
||||||
)
|
)
|
||||||
@@ -229,4 +243,16 @@ mod tests {
|
|||||||
assert_eq!(current_version(&db_path).unwrap(), CURRENT_VERSION);
|
assert_eq!(current_version(&db_path).unwrap(), CURRENT_VERSION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn upgrade_to_4_works() {
|
||||||
|
let db_type = DatabaseType::Full;
|
||||||
|
for version_from_file in &[None, Some(1), Some(2), Some(3)] {
|
||||||
|
let db_dir = tempfile::TempDir::new().unwrap();
|
||||||
|
let db_path = db_dir.path().join(db_type.as_str());
|
||||||
|
create_db(&db_path, *version_from_file);
|
||||||
|
open_database(&db_path, db_type).unwrap();
|
||||||
|
assert_eq!(current_version(&db_path).unwrap(), CURRENT_VERSION);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ use sp_trie::DBValue;
|
|||||||
feature = "test-helpers",
|
feature = "test-helpers",
|
||||||
test
|
test
|
||||||
))]
|
))]
|
||||||
pub const NUM_COLUMNS: u32 = 12;
|
pub const NUM_COLUMNS: u32 = 13;
|
||||||
/// Meta column. The set of keys in the column is shared by full && light storages.
|
/// Meta column. The set of keys in the column is shared by full && light storages.
|
||||||
pub const COLUMN_META: u32 = 0;
|
pub const COLUMN_META: u32 = 0;
|
||||||
|
|
||||||
@@ -252,7 +252,7 @@ impl From<OpenDbError> for sp_blockchain::Error {
|
|||||||
#[cfg(feature = "with-parity-db")]
|
#[cfg(feature = "with-parity-db")]
|
||||||
impl From<parity_db::Error> for OpenDbError {
|
impl From<parity_db::Error> for OpenDbError {
|
||||||
fn from(err: parity_db::Error) -> Self {
|
fn from(err: parity_db::Error) -> Self {
|
||||||
if err.to_string().contains("use open_or_create") {
|
if matches!(err, parity_db::Error::DatabaseNotFound) {
|
||||||
OpenDbError::DoesNotExist
|
OpenDbError::DoesNotExist
|
||||||
} else {
|
} else {
|
||||||
OpenDbError::Internal(err.to_string())
|
OpenDbError::Internal(err.to_string())
|
||||||
@@ -272,8 +272,14 @@ impl From<io::Error> for OpenDbError {
|
|||||||
|
|
||||||
#[cfg(feature = "with-parity-db")]
|
#[cfg(feature = "with-parity-db")]
|
||||||
fn open_parity_db<Block: BlockT>(path: &Path, db_type: DatabaseType, create: bool) -> OpenDbResult {
|
fn open_parity_db<Block: BlockT>(path: &Path, db_type: DatabaseType, create: bool) -> OpenDbResult {
|
||||||
let db = crate::parity_db::open(path, db_type, create)?;
|
match crate::parity_db::open(path, db_type, create, false) {
|
||||||
Ok(db)
|
Ok(db) => Ok(db),
|
||||||
|
Err(parity_db::Error::InvalidConfiguration(_)) => {
|
||||||
|
// Try to update the database with the new config
|
||||||
|
Ok(crate::parity_db::open(path, db_type, create, true)?)
|
||||||
|
},
|
||||||
|
Err(e) => Err(e.into()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "with-parity-db"))]
|
#[cfg(not(feature = "with-parity-db"))]
|
||||||
@@ -573,7 +579,7 @@ impl<'a, 'b> codec::Input for JoinInput<'a, 'b> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{KeepBlocks, TransactionStorageMode};
|
use crate::KeepBlocks;
|
||||||
use codec::Input;
|
use codec::Input;
|
||||||
use sc_state_db::PruningMode;
|
use sc_state_db::PruningMode;
|
||||||
use sp_runtime::testing::{Block as RawBlock, ExtrinsicWrapper};
|
use sp_runtime::testing::{Block as RawBlock, ExtrinsicWrapper};
|
||||||
@@ -689,7 +695,6 @@ mod tests {
|
|||||||
state_pruning: PruningMode::ArchiveAll,
|
state_pruning: PruningMode::ArchiveAll,
|
||||||
source,
|
source,
|
||||||
keep_blocks: KeepBlocks::All,
|
keep_blocks: KeepBlocks::All,
|
||||||
transaction_storage: TransactionStorageMode::BlockBody,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
build_network_future,
|
build_network_future,
|
||||||
client::{Client, ClientConfig},
|
client::{Client, ClientConfig},
|
||||||
config::{Configuration, KeystoreConfig, PrometheusConfig, TransactionStorageMode},
|
config::{Configuration, KeystoreConfig, PrometheusConfig},
|
||||||
error::Error,
|
error::Error,
|
||||||
metrics::MetricsService,
|
metrics::MetricsService,
|
||||||
start_rpc_servers, RpcHandlers, SpawnTaskHandle, TaskManager, TransactionPoolAdapter,
|
start_rpc_servers, RpcHandlers, SpawnTaskHandle, TaskManager, TransactionPoolAdapter,
|
||||||
@@ -39,7 +39,7 @@ use sc_executor::RuntimeVersionOf;
|
|||||||
use sc_keystore::LocalKeystore;
|
use sc_keystore::LocalKeystore;
|
||||||
use sc_network::{
|
use sc_network::{
|
||||||
block_request_handler::{self, BlockRequestHandler},
|
block_request_handler::{self, BlockRequestHandler},
|
||||||
config::{Role, SyncMode},
|
config::Role,
|
||||||
light_client_requests::{self, handler::LightClientRequestHandler},
|
light_client_requests::{self, handler::LightClientRequestHandler},
|
||||||
state_request_handler::{self, StateRequestHandler},
|
state_request_handler::{self, StateRequestHandler},
|
||||||
warp_request_handler::{self, RequestHandler as WarpSyncRequestHandler, WarpSyncProvider},
|
warp_request_handler::{self, RequestHandler as WarpSyncRequestHandler, WarpSyncProvider},
|
||||||
@@ -264,7 +264,6 @@ where
|
|||||||
state_pruning: config.state_pruning.clone(),
|
state_pruning: config.state_pruning.clone(),
|
||||||
source: config.database.clone(),
|
source: config.database.clone(),
|
||||||
keep_blocks: config.keep_blocks.clone(),
|
keep_blocks: config.keep_blocks.clone(),
|
||||||
transaction_storage: config.transaction_storage.clone(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let backend = new_db_backend(db_config)?;
|
let backend = new_db_backend(db_config)?;
|
||||||
@@ -842,7 +841,7 @@ where
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut network_params = sc_network::config::Params {
|
let network_params = sc_network::config::Params {
|
||||||
role: config.role.clone(),
|
role: config.role.clone(),
|
||||||
executor: {
|
executor: {
|
||||||
let spawn_handle = Clone::clone(&spawn_handle);
|
let spawn_handle = Clone::clone(&spawn_handle);
|
||||||
@@ -869,13 +868,6 @@ where
|
|||||||
light_client_request_protocol_config,
|
light_client_request_protocol_config,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Storage chains don't keep full block history and can't be synced in full mode.
|
|
||||||
// Force fast sync when storage chain mode is enabled.
|
|
||||||
if matches!(config.transaction_storage, TransactionStorageMode::StorageChain) {
|
|
||||||
network_params.network_config.sync_mode =
|
|
||||||
SyncMode::Fast { storage_chain_mode: true, skip_proofs: false };
|
|
||||||
}
|
|
||||||
|
|
||||||
let has_bootnodes = !network_params.network_config.boot_nodes.is_empty();
|
let has_bootnodes = !network_params.network_config.boot_nodes.is_empty();
|
||||||
let network_mut = sc_network::NetworkWorker::new(network_params)?;
|
let network_mut = sc_network::NetworkWorker::new(network_params)?;
|
||||||
let network = network_mut.service().clone();
|
let network = network_mut.service().clone();
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
//! Service configuration.
|
//! Service configuration.
|
||||||
|
|
||||||
pub use sc_client_api::execution_extensions::{ExecutionStrategies, ExecutionStrategy};
|
pub use sc_client_api::execution_extensions::{ExecutionStrategies, ExecutionStrategy};
|
||||||
pub use sc_client_db::{Database, DatabaseSource, KeepBlocks, PruningMode, TransactionStorageMode};
|
pub use sc_client_db::{Database, DatabaseSource, KeepBlocks, PruningMode};
|
||||||
pub use sc_executor::WasmExecutionMethod;
|
pub use sc_executor::WasmExecutionMethod;
|
||||||
pub use sc_network::{
|
pub use sc_network::{
|
||||||
config::{
|
config::{
|
||||||
@@ -71,8 +71,6 @@ pub struct Configuration {
|
|||||||
pub state_pruning: PruningMode,
|
pub state_pruning: PruningMode,
|
||||||
/// Number of blocks to keep in the db.
|
/// Number of blocks to keep in the db.
|
||||||
pub keep_blocks: KeepBlocks,
|
pub keep_blocks: KeepBlocks,
|
||||||
/// Transaction storage scheme.
|
|
||||||
pub transaction_storage: TransactionStorageMode,
|
|
||||||
/// Chain configuration.
|
/// Chain configuration.
|
||||||
pub chain_spec: Box<dyn ChainSpec>,
|
pub chain_spec: Box<dyn ChainSpec>,
|
||||||
/// Wasm execution method.
|
/// Wasm execution method.
|
||||||
|
|||||||
@@ -58,7 +58,6 @@ pub use self::{
|
|||||||
};
|
};
|
||||||
pub use config::{
|
pub use config::{
|
||||||
BasePath, Configuration, DatabaseSource, KeepBlocks, PruningMode, Role, RpcMethods, TaskType,
|
BasePath, Configuration, DatabaseSource, KeepBlocks, PruningMode, Role, RpcMethods, TaskType,
|
||||||
TransactionStorageMode,
|
|
||||||
};
|
};
|
||||||
pub use sc_chain_spec::{
|
pub use sc_chain_spec::{
|
||||||
ChainSpec, ChainType, Extension as ChainSpecExtension, GenericChainSpec, NoExtension,
|
ChainSpec, ChainType, Extension as ChainSpecExtension, GenericChainSpec, NoExtension,
|
||||||
|
|||||||
@@ -23,9 +23,7 @@ use sc_block_builder::BlockBuilderProvider;
|
|||||||
use sc_client_api::{
|
use sc_client_api::{
|
||||||
in_mem, BlockBackend, BlockchainEvents, FinalityNotifications, StorageProvider,
|
in_mem, BlockBackend, BlockchainEvents, FinalityNotifications, StorageProvider,
|
||||||
};
|
};
|
||||||
use sc_client_db::{
|
use sc_client_db::{Backend, DatabaseSettings, DatabaseSource, KeepBlocks, PruningMode};
|
||||||
Backend, DatabaseSettings, DatabaseSource, KeepBlocks, PruningMode, TransactionStorageMode,
|
|
||||||
};
|
|
||||||
use sc_consensus::{
|
use sc_consensus::{
|
||||||
BlockCheckParams, BlockImport, BlockImportParams, ForkChoiceStrategy, ImportResult,
|
BlockCheckParams, BlockImport, BlockImportParams, ForkChoiceStrategy, ImportResult,
|
||||||
};
|
};
|
||||||
@@ -1203,7 +1201,6 @@ fn doesnt_import_blocks_that_revert_finality() {
|
|||||||
state_cache_child_ratio: None,
|
state_cache_child_ratio: None,
|
||||||
state_pruning: PruningMode::ArchiveAll,
|
state_pruning: PruningMode::ArchiveAll,
|
||||||
keep_blocks: KeepBlocks::All,
|
keep_blocks: KeepBlocks::All,
|
||||||
transaction_storage: TransactionStorageMode::BlockBody,
|
|
||||||
source: DatabaseSource::RocksDb { path: tmp.path().into(), cache_size: 1024 },
|
source: DatabaseSource::RocksDb { path: tmp.path().into(), cache_size: 1024 },
|
||||||
},
|
},
|
||||||
u64::MAX,
|
u64::MAX,
|
||||||
@@ -1419,7 +1416,6 @@ fn returns_status_for_pruned_blocks() {
|
|||||||
state_cache_child_ratio: None,
|
state_cache_child_ratio: None,
|
||||||
state_pruning: PruningMode::keep_blocks(1),
|
state_pruning: PruningMode::keep_blocks(1),
|
||||||
keep_blocks: KeepBlocks::All,
|
keep_blocks: KeepBlocks::All,
|
||||||
transaction_storage: TransactionStorageMode::BlockBody,
|
|
||||||
source: DatabaseSource::RocksDb { path: tmp.path().into(), cache_size: 1024 },
|
source: DatabaseSource::RocksDb { path: tmp.path().into(), cache_size: 1024 },
|
||||||
},
|
},
|
||||||
u64::MAX,
|
u64::MAX,
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ use sc_service::{
|
|||||||
client::Client,
|
client::Client,
|
||||||
config::{BasePath, DatabaseSource, KeystoreConfig},
|
config::{BasePath, DatabaseSource, KeystoreConfig},
|
||||||
ChainSpecExtension, Configuration, Error, GenericChainSpec, KeepBlocks, Role, RuntimeGenesis,
|
ChainSpecExtension, Configuration, Error, GenericChainSpec, KeepBlocks, Role, RuntimeGenesis,
|
||||||
SpawnTaskHandle, TaskManager, TransactionStorageMode,
|
SpawnTaskHandle, TaskManager,
|
||||||
};
|
};
|
||||||
use sc_transaction_pool_api::TransactionPool;
|
use sc_transaction_pool_api::TransactionPool;
|
||||||
use sp_api::BlockId;
|
use sp_api::BlockId;
|
||||||
@@ -235,7 +235,6 @@ fn node_config<
|
|||||||
state_cache_child_ratio: None,
|
state_cache_child_ratio: None,
|
||||||
state_pruning: Default::default(),
|
state_pruning: Default::default(),
|
||||||
keep_blocks: KeepBlocks::All,
|
keep_blocks: KeepBlocks::All,
|
||||||
transaction_storage: TransactionStorageMode::BlockBody,
|
|
||||||
chain_spec: Box::new((*spec).clone()),
|
chain_spec: Box::new((*spec).clone()),
|
||||||
wasm_method: sc_service::config::WasmExecutionMethod::Interpreted,
|
wasm_method: sc_service::config::WasmExecutionMethod::Interpreted,
|
||||||
wasm_runtime_overrides: Default::default(),
|
wasm_runtime_overrides: Default::default(),
|
||||||
|
|||||||
@@ -105,11 +105,7 @@ impl<Block: BlockT, ExecutorDispatch, G: GenesisInit>
|
|||||||
|
|
||||||
/// Create new `TestClientBuilder` with default backend and storage chain mode
|
/// Create new `TestClientBuilder` with default backend and storage chain mode
|
||||||
pub fn with_tx_storage(keep_blocks: u32) -> Self {
|
pub fn with_tx_storage(keep_blocks: u32) -> Self {
|
||||||
let backend = Arc::new(Backend::new_test_with_tx_storage(
|
let backend = Arc::new(Backend::new_test_with_tx_storage(keep_blocks, 0));
|
||||||
keep_blocks,
|
|
||||||
0,
|
|
||||||
sc_client_db::TransactionStorageMode::StorageChain,
|
|
||||||
));
|
|
||||||
Self::with_backend(backend)
|
Self::with_backend(backend)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user