Skip to content

Commit

Permalink
add more methods and fix docker spec
Browse files Browse the repository at this point in the history
  • Loading branch information
tonyke-bot committed Feb 8, 2024
1 parent 31d6282 commit 0b947bc
Show file tree
Hide file tree
Showing 24 changed files with 992 additions and 563 deletions.
867 changes: 519 additions & 348 deletions Cargo.lock

Large diffs are not rendered by default.

30 changes: 15 additions & 15 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
actix-web = "4"
alloy-primitives = { version = "0.6.2", features = ["serde"] }
anyhow = "1.0.71"
async-trait = "0.1.77"
clap = { version = "4.3.4", features = ["derive"] }
dashmap = { version = "5.5.3", features = ["serde"] }
env_logger = "0.10.0"
hex = "0.4.3"
r2d2 = "0.8.10"
redis = { version = "0.24.0", features = ["r2d2", "async-std"] }
reqwest = { version = "0.11.18", features = ["rustls", "json", "serde_json"] }
serde = { version = "1.0.164", features = ["derive"] }
serde_json = { version = "1.0.97", features = ["std"] }
sha1 = "0.10.5"
tracing = "0.1.40"
actix-web = "4.4"
alloy-primitives = { version = "0.6", features = ["serde"] }
anyhow = "1.0"
async-trait = "0.1"
clap = { version = "4.4", features = ["derive"] }
dashmap = { version = "5.5", features = ["serde"] }
env_logger = "0.11"
hex = "0.4"
r2d2 = "0.8"
redis = { version = "0.24", features = ["r2d2", "async-std"] }
reqwest = { version = "0.11", features = ["rustls", "json", "serde_json"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0", features = ["std"] }
sha1 = "0.10"
tracing = "0.1"
22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,22 @@ Multiple endpoints/chains can be configured to be cached.

2. `docker-compose up`
### Usage
With
`redis-url` is optional

```shell
cargo run --release -- \
<<<<<<< HEAD
--port=8124 \
--bind=0.0.0.0 \
--endpoint=eth=https://rpc.ankr.com/eth \
--endpoint=bsc=https://rpc.ankr.com/bsc \
--redis-url=redis://localhost:6379
=======
--port 8124 \
--redis-url "redis://redis:6379" \
--endpoint "eth=https://rpc.ankr.com/eth" \
--endpoint "bsc=https://rpc.ankr.com/bsc"
>>>>>>> ab7ad00 (add more methods and fix docker spec)
```
Following redirection will be made:
* http://localhost:8124/eth -> https://rpc.ankr.com/eth
Expand All @@ -26,13 +34,21 @@ Mainly supported requests with determined block number. Other methods will be di

- `eth_call`
- `eth_chainId`
- `eth_estimateGas`
- `eth_getBalance`
- `eth_getBlockByHash`
- `eth_getBlockByNumber`
- `eth_getBlockReceipts`
- `eth_getCode`
- `eth_getLogs`
- `eth_getStorageAt`
- `eth_getTransactionByBlockHashAndIndex`
- `eth_getTransactionByBlockNumberAndIndex`
- `eth_getTransactionByHash`
- `eth_getTransactionCount`
- `eth_getTransactionReceipt`
- `eth_getTransactionByBlockNumberAndIndex`
- `eth_getTransactionByBlockHashAndIndex`

- `debug_traceBlockByHash`
- `debug_traceBlockByNumber`
- `debug_traceCall`
- `debug_traceTransaction`
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ services:
- --bind=0.0.0.0
- --endpoint=eth=https://rpc.ankr.com/eth
- --endpoint=bsc=https://rpc.ankr.com/bsc
- --redis-url=redis://docker-redis:6379
- --redis-url=redis://redis:6379

redis:
image: redis:alpine
Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ async fn main() -> std::io::Result<()> {
http_client: reqwest::Client::new(),
};

let handler_factories = rpc_cache_handler::all_factories();
let handler_factories = rpc_cache_handler::factories();

for (name, rpc_url) in args.endpoints.iter() {
tracing::info!("Linked `{name}` to endpoint {rpc_url}");
Expand Down
67 changes: 36 additions & 31 deletions src/rpc_cache_handler/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,18 @@ pub enum ParamsSpec {
}

pub fn require_array_params(params: &Value, len: ParamsSpec) -> anyhow::Result<&Vec<Value>> {
let array = params
.as_array()
.context("expect params to be an array")?;
let array = params.as_array().context("expect params to be an array")?;

match len {
ParamsSpec::Exact(expected_len) if array.len() != expected_len => {
anyhow::bail!("expected {} params, got {}", expected_len, array.len());
}
ParamsSpec::AtLeast(expected_len) if array.len() < expected_len => {
anyhow::bail!("expected at least {} params, got {}", expected_len, array.len());
anyhow::bail!(
"expected at least {} params, got {}",
expected_len,
array.len()
);
}
_ => {}
};
Expand All @@ -34,7 +36,9 @@ pub fn extract_address_cache_key(params: &Value) -> anyhow::Result<Option<String
let account: Address =
serde_json::from_value(params[0].clone()).context("params[0] not a valid address")?;

let block_tag = match extract_and_format_block_tag(&params[1]).context("params[1] not a valid block tag")? {
let block_tag = match extract_and_format_block_tag(&params[1])
.context("params[1] not a valid block tag")?
{
Some(block_tag) => block_tag,
None => return Ok(None),
};
Expand All @@ -54,13 +58,11 @@ pub fn extract_and_format_block_number(value: &Value) -> anyhow::Result<Option<S
let value = value.as_str().context("block tag not a string")?;

let block_tag = match value {
"earliest" |
"latest" |
"pending" |
"finalized" |
"safe" => None,
"earliest" | "latest" | "pending" | "finalized" | "safe" => None,
_ => {
let v = U64::from_str(value).context("block tag not a valid block number")?.as_limbs()[0];
let v = U64::from_str(value)
.context("block tag not a valid block number")?
.as_limbs()[0];
Some(format!("0x{:x}", v))
}
};
Expand Down Expand Up @@ -136,13 +138,25 @@ mod test {

#[test]
fn test_block_hash() {
let block_tag = extract_and_format_block_tag(&json!("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef")).unwrap();
assert_eq!(block_tag, Some("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef".to_string()));
let block_tag = extract_and_format_block_tag(&json!(
"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
))
.unwrap();
assert_eq!(
block_tag,
Some(
"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
.to_string()
)
);
}

#[test]
fn test_invalid_block_hash() {
let block_tag = extract_and_format_block_tag(&json!("0x1234567890abcdef1234567890abcdef1234567890abcdef123456789ggggggg")).unwrap_err();
let block_tag = extract_and_format_block_tag(&json!(
"0x1234567890abcdef1234567890abcdef1234567890abcdef123456789ggggggg"
))
.unwrap_err();

assert_eq!(block_tag.to_string(), "expect a valid block hash");
}
Expand All @@ -167,43 +181,34 @@ mod test {

#[test]
fn test_fixed_block() {
let params = json!([
"0x1234567890abcdef1234567890abcdef12345678",
"0x12345"
]);
let params = json!(["0x1234567890abcdef1234567890abcdef12345678", "0x12345"]);

let cache_key = extract_address_cache_key(&params).unwrap().unwrap();
assert_eq!(cache_key, "0x12345-0x1234567890abcdef1234567890abcdef12345678");
assert_eq!(
cache_key,
"0x12345-0x1234567890abcdef1234567890abcdef12345678"
);
}

#[test]
fn test_with_block_tag() {
let params = json!([
"0x1234567890abcdef1234567890abcdef12345678",
"earliest"
]);
let params = json!(["0x1234567890abcdef1234567890abcdef12345678", "earliest"]);

let cache_key = extract_address_cache_key(&params).unwrap();
assert_eq!(cache_key, None);
}

#[test]
fn test_invalid_address() {
let params = json!([
"0x1234567890abcdef1234567890abcdef1234gggg",
"latest"
]);
let params = json!(["0x1234567890abcdef1234567890abcdef1234gggg", "latest"]);

let err = extract_address_cache_key(&params).unwrap_err();
assert_eq!(err.to_string(), "params[0] not a valid address");
}

#[test]
fn test_invalid_block_tag() {
let params = json!([
"0x1234567890abcdef1234567890abcdef12345678",
"ggg tag"
]);
let params = json!(["0x1234567890abcdef1234567890abcdef12345678", "ggg tag"]);

let err = extract_address_cache_key(&params).unwrap_err();
assert_eq!(err.to_string(), "params[1] not a valid block tag");
Expand Down
12 changes: 4 additions & 8 deletions src/rpc_cache_handler/debug_trace_block_by_hash.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use anyhow::Context;
use serde_json::Value;

use crate::rpc_cache_handler::{common, RpcCacheHandler};
use crate::rpc_cache_handler::common::ParamsSpec;
use crate::rpc_cache_handler::{common, RpcCacheHandler};

#[derive(Default, Clone)]
pub struct Handler;
Expand Down Expand Up @@ -61,9 +61,7 @@ mod test {

#[test]
fn test_normal_case_without_tracer_config() {
let params = json!([
"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
]);
let params = json!(["0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"]);

let cache_key = HANDLER.extract_cache_key(&params).unwrap().unwrap();
assert_eq!(
Expand All @@ -74,11 +72,9 @@ mod test {

#[test]
fn test_invalid_block_hash() {
let params = json!([
"0x1234567890abcdef1234567890abcdef1234567890abcdef123456789ggggggg"
]);
let params = json!(["0x1234567890abcdef1234567890abcdef1234567890abcdef123456789ggggggg"]);

let err = HANDLER.extract_cache_key(&params).unwrap_err();
assert_eq!(err.to_string(), "params[0] not a valid block hash");
}
}
}
23 changes: 8 additions & 15 deletions src/rpc_cache_handler/debug_trace_block_by_number.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use anyhow::Context;
use serde_json::Value;

use crate::rpc_cache_handler::{common, RpcCacheHandler};
use crate::rpc_cache_handler::common::ParamsSpec;
use crate::rpc_cache_handler::{common, RpcCacheHandler};

#[derive(Default, Clone)]
pub struct Handler;
Expand All @@ -15,7 +15,8 @@ impl RpcCacheHandler for Handler {
fn extract_cache_key(&self, params: &Value) -> anyhow::Result<Option<String>> {
let params = common::require_array_params(params, ParamsSpec::AtLeast(1))?;

let block_tag = common::extract_and_format_block_number(&params[0]).context("params[0] not a valid block number")?;
let block_tag = common::extract_and_format_block_number(&params[0])
.context("params[0] not a valid block number")?;
let block_number = match block_tag {
Some(block_tag) => block_tag,
None => return Ok(None),
Expand All @@ -29,12 +30,11 @@ impl RpcCacheHandler for Handler {

Ok(Some(format!("{block_number}-{tracer_config_hash}")))
} else {
Ok(Some(format!("{block_number}")))
Ok(Some(block_number))
}
}
}


#[cfg(test)]
mod test {
use super::*;
Expand Down Expand Up @@ -65,24 +65,17 @@ mod test {

#[test]
fn test_normal_case_without_tracer_config() {
let params = json!([
"0x12341324"
]);
let params = json!(["0x12341324"]);

let cache_key = HANDLER.extract_cache_key(&params).unwrap().unwrap();
assert_eq!(
cache_key,
"0x12341324"
);
assert_eq!(cache_key, "0x12341324");
}

#[test]
fn test_invalid_block_number() {
let params = json!([
"0xgg"
]);
let params = json!(["0xgg"]);

let err = HANDLER.extract_cache_key(&params).unwrap_err();
assert_eq!(err.to_string(), "params[0] not a valid block number");
}
}
}
19 changes: 12 additions & 7 deletions src/rpc_cache_handler/debug_trace_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,14 @@ impl RpcCacheHandler for Handler {
fn extract_cache_key(&self, params: &Value) -> anyhow::Result<Option<String>> {
let params = common::require_array_params(params, common::ParamsSpec::AtLeast(1))?;

let tx = serde_json::to_string(params[0].as_object().context("params[0] not a transaction call object")?).unwrap();
let block_tag = common::extract_and_format_block_tag(&params[1]).context("params[1] not a valid block tag")?;
let tx = serde_json::to_string(
params[0]
.as_object()
.context("params[0] not a transaction call object")?,
)
.unwrap();
let block_tag = common::extract_and_format_block_tag(&params[1])
.context("params[1] not a valid block tag")?;

let block_tag = match block_tag {
Some(block_tag) => block_tag,
Expand All @@ -26,7 +32,8 @@ impl RpcCacheHandler for Handler {

if params.len() > 2 {
let tracer_config =
serde_json::to_string(params[2].as_object().context("params[2] not an object")?).unwrap();
serde_json::to_string(params[2].as_object().context("params[2] not an object")?)
.unwrap();

let tracer_config_hash = common::hash_string(tracer_config.as_str());
Ok(Some(format!("{block_tag}-{tx_hash}-{tracer_config_hash}")))
Expand Down Expand Up @@ -89,9 +96,7 @@ mod test {

#[test]
fn test_invalid_tx() {
let params = json!([
"0xgg"
]);
let params = json!(["0xgg"]);

let err = HANDLER.extract_cache_key(&params).unwrap_err();
assert_eq!(err.to_string(), "params[0] not a transaction call object");
Expand All @@ -111,4 +116,4 @@ mod test {
let err = HANDLER.extract_cache_key(&params).unwrap_err();
assert_eq!(err.to_string(), "params[1] not a valid block tag");
}
}
}
Loading

0 comments on commit 0b947bc

Please sign in to comment.