mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-01-10 07:48:19 -05:00
feat(rpc): implement debug_dbGet (#19369)
This commit is contained in:
@@ -222,7 +222,7 @@ pub trait DebugApi<TxReq: RpcObject> {
|
||||
|
||||
/// Returns the raw value of a key stored in the database.
|
||||
#[method(name = "dbGet")]
|
||||
async fn debug_db_get(&self, key: String) -> RpcResult<()>;
|
||||
async fn debug_db_get(&self, key: String) -> RpcResult<Option<Bytes>>;
|
||||
|
||||
/// Retrieves the state that corresponds to the block number and returns a list of accounts
|
||||
/// (including storage and code).
|
||||
|
||||
@@ -1694,3 +1694,47 @@ async fn test_eth_fee_history_raw() {
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_debug_db_get() {
|
||||
reth_tracing::init_test_tracing();
|
||||
|
||||
let handle = launch_http(vec![RethRpcModule::Debug]).await;
|
||||
let client = handle.http_client().unwrap();
|
||||
|
||||
let valid_test_cases = [
|
||||
"0x630000000000000000000000000000000000000000000000000000000000000000",
|
||||
"c00000000000000000000000000000000",
|
||||
];
|
||||
|
||||
for key in valid_test_cases {
|
||||
DebugApiClient::<()>::debug_db_get(&client, key.into()).await.unwrap();
|
||||
}
|
||||
|
||||
// Invalid test cases
|
||||
let test_cases = [
|
||||
("0x0000", "Key must be 33 bytes, got 2"),
|
||||
("00", "Key must be 33 bytes, got 2"),
|
||||
(
|
||||
"0x000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Key prefix must be 0x63",
|
||||
),
|
||||
("000000000000000000000000000000000", "Key prefix must be 0x63"),
|
||||
("0xc0000000000000000000000000000000000000000000000000000000000000000", "Invalid hex key"),
|
||||
];
|
||||
|
||||
let match_error_msg = |err: jsonrpsee::core::client::Error, expected: String| -> bool {
|
||||
match err {
|
||||
jsonrpsee::core::client::Error::Call(error_obj) => {
|
||||
error_obj.code() == ErrorCode::InvalidParams.code() &&
|
||||
error_obj.message() == expected
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
};
|
||||
|
||||
for (key, expected) in test_cases {
|
||||
let err = DebugApiClient::<()>::debug_db_get(&client, key.into()).await.unwrap_err();
|
||||
assert!(match_error_msg(err, expected.into()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use alloy_consensus::{
|
||||
use alloy_eips::{eip2718::Encodable2718, BlockId, BlockNumberOrTag};
|
||||
use alloy_evm::env::BlockEnvironment;
|
||||
use alloy_genesis::ChainConfig;
|
||||
use alloy_primitives::{uint, Address, Bytes, B256};
|
||||
use alloy_primitives::{hex::decode, uint, Address, Bytes, B256};
|
||||
use alloy_rlp::{Decodable, Encodable};
|
||||
use alloy_rpc_types_debug::ExecutionWitness;
|
||||
use alloy_rpc_types_eth::{
|
||||
@@ -1143,8 +1143,38 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn debug_db_get(&self, _key: String) -> RpcResult<()> {
|
||||
Ok(())
|
||||
/// `debug_db_get` - database key lookup
|
||||
///
|
||||
/// Currently supported:
|
||||
/// * Contract bytecode associated with a code hash. The key format is: `<0x63><code_hash>`
|
||||
/// * Prefix byte: 0x63 (required)
|
||||
/// * Code hash: 32 bytes
|
||||
/// Must be provided as either:
|
||||
/// * Hex string: "0x63..." (66 hex characters after 0x)
|
||||
/// * Raw byte string: raw byte string (33 bytes)
|
||||
/// See Geth impl: <https://github.com/ethereum/go-ethereum/blob/737ffd1bf0cbee378d0111a5b17ae4724fb2216c/core/rawdb/schema.go#L120>
|
||||
async fn debug_db_get(&self, key: String) -> RpcResult<Option<Bytes>> {
|
||||
let key_bytes = if key.starts_with("0x") {
|
||||
decode(&key).map_err(|_| EthApiError::InvalidParams("Invalid hex key".to_string()))?
|
||||
} else {
|
||||
key.into_bytes()
|
||||
};
|
||||
|
||||
if key_bytes.len() != 33 {
|
||||
return Err(EthApiError::InvalidParams(format!(
|
||||
"Key must be 33 bytes, got {}",
|
||||
key_bytes.len()
|
||||
))
|
||||
.into());
|
||||
}
|
||||
if key_bytes[0] != 0x63 {
|
||||
return Err(EthApiError::InvalidParams("Key prefix must be 0x63".to_string()).into());
|
||||
}
|
||||
|
||||
let code_hash = B256::from_slice(&key_bytes[1..33]);
|
||||
|
||||
// No block ID is provided, so it defaults to the latest block
|
||||
self.debug_code_by_hash(code_hash, None).await.map_err(Into::into)
|
||||
}
|
||||
|
||||
async fn debug_dump_block(&self, _number: BlockId) -> RpcResult<()> {
|
||||
|
||||
Reference in New Issue
Block a user