mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
Feature: Support db get for duptables (CLI) (#4653)
Co-authored-by: Dragan Pilipovic <admin@Admins-MacBook-Pro.local> Co-authored-by: Roman Krasiuk <rokrassyuk@gmail.com>
This commit is contained in:
@ -33,7 +33,6 @@ impl<DB: Database> TableViewer<()> for ClearViewer<'_, DB> {
|
||||
let tx = self.db.tx_mut()?;
|
||||
tx.clear::<T>()?;
|
||||
tx.commit()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
use crate::utils::DbTool;
|
||||
use clap::Parser;
|
||||
|
||||
use reth_db::{database::Database, table::Table, RawKey, RawTable, TableType, TableViewer, Tables};
|
||||
use reth_db::{
|
||||
database::Database,
|
||||
table::{DupSort, Table},
|
||||
RawKey, RawTable, TableViewer, Tables,
|
||||
};
|
||||
use tracing::error;
|
||||
|
||||
/// The arguments for the `reth db get` command
|
||||
@ -16,6 +19,10 @@ pub struct Command {
|
||||
#[arg(value_parser = maybe_json_value_parser)]
|
||||
pub key: String,
|
||||
|
||||
/// The subkey to get content for
|
||||
#[arg(value_parser = maybe_json_value_parser)]
|
||||
pub subkey: Option<String>,
|
||||
|
||||
/// Output bytes instead of human-readable decoded value
|
||||
#[clap(long)]
|
||||
pub raw: bool,
|
||||
@ -24,12 +31,6 @@ pub struct Command {
|
||||
impl Command {
|
||||
/// Execute `db get` command
|
||||
pub fn execute<DB: Database>(self, tool: &DbTool<'_, DB>) -> eyre::Result<()> {
|
||||
if self.table.table_type() == TableType::DupSort {
|
||||
error!(target: "reth::cli", "Unsupported table.");
|
||||
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
self.table.view(&GetValueViewer { tool, args: &self })?;
|
||||
|
||||
Ok(())
|
||||
@ -41,6 +42,13 @@ impl Command {
|
||||
|
||||
serde_json::from_str::<T::Key>(&self.key).map_err(|e| eyre::eyre!(e))
|
||||
}
|
||||
|
||||
/// Get an instance of subkey for given dupsort table
|
||||
fn table_subkey<T: DupSort>(&self) -> Result<T::SubKey, eyre::Error> {
|
||||
assert_eq!(T::NAME, self.table.name());
|
||||
serde_json::from_str::<T::SubKey>(&self.subkey.clone().unwrap_or_default())
|
||||
.map_err(|e| eyre::eyre!(e))
|
||||
}
|
||||
}
|
||||
|
||||
struct GetValueViewer<'a, DB: Database> {
|
||||
@ -52,7 +60,6 @@ impl<DB: Database> TableViewer<()> for GetValueViewer<'_, DB> {
|
||||
type Error = eyre::Report;
|
||||
|
||||
fn view<T: Table>(&self) -> Result<(), Self::Error> {
|
||||
// get a key for given table
|
||||
let key = self.args.table_key::<T>()?;
|
||||
|
||||
let content = if self.args.raw {
|
||||
@ -74,6 +81,24 @@ impl<DB: Database> TableViewer<()> for GetValueViewer<'_, DB> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn view_dupsort<T: DupSort>(&self) -> Result<(), Self::Error> {
|
||||
// get a key for given table
|
||||
let key = self.args.table_key::<T>()?;
|
||||
|
||||
// process dupsort table
|
||||
let subkey = self.args.table_subkey::<T>()?;
|
||||
|
||||
match self.tool.get_dup::<T>(key, subkey)? {
|
||||
Some(content) => {
|
||||
println!("{}", serde_json::to_string_pretty(&content)?);
|
||||
}
|
||||
None => {
|
||||
error!(target: "reth::cli", "No content for the given table subkey.");
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Map the user input value to json
|
||||
|
||||
@ -101,7 +101,7 @@ impl TableViewer<()> for ListTableViewer<'_> {
|
||||
final_entry_idx = total_entries - 1,
|
||||
table = self.args.table.name()
|
||||
);
|
||||
return Ok(());
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -4,9 +4,9 @@ use boyer_moore_magiclen::BMByte;
|
||||
use eyre::Result;
|
||||
use reth_consensus_common::validation::validate_block_standalone;
|
||||
use reth_db::{
|
||||
cursor::DbCursorRO,
|
||||
cursor::{DbCursorRO, DbDupCursorRO},
|
||||
database::Database,
|
||||
table::{Decode, Decompress, Table, TableRow},
|
||||
table::{Decode, Decompress, DupSort, Table, TableRow},
|
||||
transaction::{DbTx, DbTxMut},
|
||||
DatabaseError, RawTable, TableRawRow,
|
||||
};
|
||||
@ -194,6 +194,13 @@ impl<'a, DB: Database> DbTool<'a, DB> {
|
||||
self.db.view(|tx| tx.get::<T>(key))?.map_err(|e| eyre::eyre!(e))
|
||||
}
|
||||
|
||||
/// Grabs the content of the DupSort table for the given key and subkey
|
||||
pub fn get_dup<T: DupSort>(&self, key: T::Key, subkey: T::SubKey) -> Result<Option<T::Value>> {
|
||||
self.db
|
||||
.view(|tx| tx.cursor_dup_read::<T>()?.seek_by_key_subkey(key, subkey))?
|
||||
.map_err(|e| eyre::eyre!(e))
|
||||
}
|
||||
|
||||
/// Drops the database at the given path.
|
||||
pub fn drop(&mut self, path: impl AsRef<Path>) -> Result<()> {
|
||||
let path = path.as_ref();
|
||||
|
||||
@ -59,7 +59,10 @@ pub const NUM_TABLES: usize = 26;
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use reth_db::{table::Table, TableViewer, Tables};
|
||||
/// use reth_db::{
|
||||
/// table::{DupSort, Table},
|
||||
/// TableViewer, Tables,
|
||||
/// };
|
||||
/// use std::str::FromStr;
|
||||
///
|
||||
/// let headers = Tables::from_str("Headers").unwrap();
|
||||
@ -71,7 +74,12 @@ pub const NUM_TABLES: usize = 26;
|
||||
/// type Error = &'static str;
|
||||
///
|
||||
/// fn view<T: Table>(&self) -> Result<(), Self::Error> {
|
||||
/// // operate on table in generic way
|
||||
/// // operate on table in a generic way
|
||||
/// Ok(())
|
||||
/// }
|
||||
///
|
||||
/// fn view_dupsort<T: DupSort>(&self) -> Result<(), Self::Error> {
|
||||
/// // operate on a dupsort table in a generic way
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// }
|
||||
@ -82,15 +90,24 @@ pub const NUM_TABLES: usize = 26;
|
||||
/// let _ = transactions.view(&viewer);
|
||||
/// ```
|
||||
pub trait TableViewer<R> {
|
||||
/// type of error to return
|
||||
/// The error type returned by the viewer.
|
||||
type Error;
|
||||
|
||||
/// operate on table in generic way
|
||||
/// Operate on the table in a generic way.
|
||||
fn view<T: Table>(&self) -> Result<R, Self::Error>;
|
||||
|
||||
/// Operate on the dupsort table in a generic way.
|
||||
/// By default, the `view` function is invoked unless overridden.
|
||||
fn view_dupsort<T: DupSort>(&self) -> Result<R, Self::Error> {
|
||||
self.view::<T>()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! tables {
|
||||
([$(($table:ident, $type:expr)),*]) => {
|
||||
([
|
||||
(TableType::Table, [$($table:ident),*]),
|
||||
(TableType::DupSort, [$($dupsort:ident),*])
|
||||
]) => {
|
||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||
/// Default tables that should be present inside database.
|
||||
pub enum Tables {
|
||||
@ -98,11 +115,15 @@ macro_rules! tables {
|
||||
#[doc = concat!("Represents a ", stringify!($table), " table")]
|
||||
$table,
|
||||
)*
|
||||
$(
|
||||
#[doc = concat!("Represents a ", stringify!($dupsort), " dupsort table")]
|
||||
$dupsort,
|
||||
)*
|
||||
}
|
||||
|
||||
impl Tables {
|
||||
/// Array of all tables in database
|
||||
pub const ALL: [Tables; NUM_TABLES] = [$(Tables::$table,)*];
|
||||
pub const ALL: [Tables; NUM_TABLES] = [$(Tables::$table,)* $(Tables::$dupsort,)*];
|
||||
|
||||
/// The name of the given table in database
|
||||
pub const fn name(&self) -> &str {
|
||||
@ -110,6 +131,9 @@ macro_rules! tables {
|
||||
$(Tables::$table => {
|
||||
$table::NAME
|
||||
},)*
|
||||
$(Tables::$dupsort => {
|
||||
$dupsort::NAME
|
||||
},)*
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,7 +141,10 @@ macro_rules! tables {
|
||||
pub const fn table_type(&self) -> TableType {
|
||||
match self {
|
||||
$(Tables::$table => {
|
||||
$type
|
||||
TableType::Table
|
||||
},)*
|
||||
$(Tables::$dupsort => {
|
||||
TableType::DupSort
|
||||
},)*
|
||||
}
|
||||
}
|
||||
@ -131,6 +158,9 @@ macro_rules! tables {
|
||||
$(Tables::$table => {
|
||||
visitor.view::<$table>()
|
||||
},)*
|
||||
$(Tables::$dupsort => {
|
||||
visitor.view_dupsort::<$dupsort>()
|
||||
},)*
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -147,10 +177,13 @@ macro_rules! tables {
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
$($table::NAME => {
|
||||
return Ok(Tables::$table)
|
||||
Ok(Tables::$table)
|
||||
},)*
|
||||
$($dupsort::NAME => {
|
||||
Ok(Tables::$dupsort)
|
||||
},)*
|
||||
_ => {
|
||||
return Err("Unknown table".to_string())
|
||||
Err("Unknown table".to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -159,32 +192,36 @@ macro_rules! tables {
|
||||
}
|
||||
|
||||
tables!([
|
||||
(CanonicalHeaders, TableType::Table),
|
||||
(HeaderTD, TableType::Table),
|
||||
(HeaderNumbers, TableType::Table),
|
||||
(Headers, TableType::Table),
|
||||
(BlockBodyIndices, TableType::Table),
|
||||
(BlockOmmers, TableType::Table),
|
||||
(BlockWithdrawals, TableType::Table),
|
||||
(TransactionBlock, TableType::Table),
|
||||
(Transactions, TableType::Table),
|
||||
(TxHashNumber, TableType::Table),
|
||||
(Receipts, TableType::Table),
|
||||
(PlainAccountState, TableType::Table),
|
||||
(PlainStorageState, TableType::DupSort),
|
||||
(Bytecodes, TableType::Table),
|
||||
(AccountHistory, TableType::Table),
|
||||
(StorageHistory, TableType::Table),
|
||||
(AccountChangeSet, TableType::DupSort),
|
||||
(StorageChangeSet, TableType::DupSort),
|
||||
(HashedAccount, TableType::Table),
|
||||
(HashedStorage, TableType::DupSort),
|
||||
(AccountsTrie, TableType::Table),
|
||||
(StoragesTrie, TableType::DupSort),
|
||||
(TxSenders, TableType::Table),
|
||||
(SyncStage, TableType::Table),
|
||||
(SyncStageProgress, TableType::Table),
|
||||
(PruneCheckpoints, TableType::Table)
|
||||
(
|
||||
TableType::Table,
|
||||
[
|
||||
CanonicalHeaders,
|
||||
HeaderTD,
|
||||
HeaderNumbers,
|
||||
Headers,
|
||||
BlockBodyIndices,
|
||||
BlockOmmers,
|
||||
BlockWithdrawals,
|
||||
TransactionBlock,
|
||||
Transactions,
|
||||
TxHashNumber,
|
||||
Receipts,
|
||||
PlainAccountState,
|
||||
Bytecodes,
|
||||
AccountHistory,
|
||||
StorageHistory,
|
||||
HashedAccount,
|
||||
AccountsTrie,
|
||||
TxSenders,
|
||||
SyncStage,
|
||||
SyncStageProgress,
|
||||
PruneCheckpoints
|
||||
]
|
||||
),
|
||||
(
|
||||
TableType::DupSort,
|
||||
[PlainStorageState, AccountChangeSet, StorageChangeSet, HashedStorage, StoragesTrie]
|
||||
)
|
||||
]);
|
||||
|
||||
/// Macro to declare key value table.
|
||||
@ -439,20 +476,20 @@ mod tests {
|
||||
(TableType::Table, TxHashNumber::NAME),
|
||||
(TableType::Table, Receipts::NAME),
|
||||
(TableType::Table, PlainAccountState::NAME),
|
||||
(TableType::DupSort, PlainStorageState::NAME),
|
||||
(TableType::Table, Bytecodes::NAME),
|
||||
(TableType::Table, AccountHistory::NAME),
|
||||
(TableType::Table, StorageHistory::NAME),
|
||||
(TableType::DupSort, AccountChangeSet::NAME),
|
||||
(TableType::DupSort, StorageChangeSet::NAME),
|
||||
(TableType::Table, HashedAccount::NAME),
|
||||
(TableType::DupSort, HashedStorage::NAME),
|
||||
(TableType::Table, AccountsTrie::NAME),
|
||||
(TableType::DupSort, StoragesTrie::NAME),
|
||||
(TableType::Table, TxSenders::NAME),
|
||||
(TableType::Table, SyncStage::NAME),
|
||||
(TableType::Table, SyncStageProgress::NAME),
|
||||
(TableType::Table, PruneCheckpoints::NAME),
|
||||
(TableType::DupSort, PlainStorageState::NAME),
|
||||
(TableType::DupSort, AccountChangeSet::NAME),
|
||||
(TableType::DupSort, StorageChangeSet::NAME),
|
||||
(TableType::DupSort, HashedStorage::NAME),
|
||||
(TableType::DupSort, StoragesTrie::NAME),
|
||||
];
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user