Skip to content

Commit 46ca76f

Browse files
authored
Add get block info RPC endpoints (#3957)
* move context into the another module, make it more general * share context to the RPC service * add block/header type converters, add first version of the eth_getBlockByHash rpc method * add another RPC endpoints * fix CI * update * add transaction wrapper type * update * fix test * fix CI * fix clippy * update block struct * add comments * add correct corresponded ethereum rpc block number type * fix suggestions * update changelog * fix clippy, rename rpc to jrpc * Revert "update changelog" This reverts commit b7ba5b4. * update changelog * update
1 parent c7e05a3 commit 46ca76f

File tree

26 files changed

+608
-136
lines changed

26 files changed

+608
-136
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
- Bump ed25519-bip32 from 0.4.0 to 0.4.1
2424
- Now the tally is incremental and is always available in the rest API. The
2525
- Add standalone explorer crate.
26+
- Add new Ethreum RPC endpoints for the getting block info: eth_getBlockByHash, eth_getBlockByNumber, eth_getBlockTransactionCountByHash, eth_getBlockTransactionCountByNumber, eth_getUncleCountByBlockHash, eth_getUncleCountByBlockNumber, eth_blockNumber
2627
- Bump clap from 2.34.0 to 3.1.13
2728
- Bump time from 0.3.7 to 0.3.9
2829
- Bump libc from 0.2.117 to 0.2.124

Cargo.lock

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

explorer/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ warp = {version = "0.3.1", features = ["tls"]}
2626
tracing = "0.1"
2727
tracing-futures = "0.2"
2828
tracing-gelf = { version = "0.6", optional = true }
29-
tracing-journald = { version = "0.2.0", optional = true }
3029
tracing-subscriber = { version = "0.3", features = ["fmt", "json"] }
3130
tracing-appender = "0.2"
3231
tokio = { version = "^1.4", features = ["rt-multi-thread", "time", "sync", "rt", "signal", "test-util"] }

jormungandr-lib/src/interfaces/config/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ mod secret;
66
pub use log::{Log, LogEntry, LogOutput};
77
pub use mempool::{LogMaxEntries, Mempool, PersistentLog, PoolMaxEntries};
88
pub use node::{
9-
Cors, CorsOrigin, LayersConfig, NodeConfig, NodeId, P2p, Policy, PreferredListConfig, Rest,
10-
Rpc, Tls, TopicsOfInterest, TrustedPeer,
9+
Cors, CorsOrigin, JRpc, LayersConfig, NodeConfig, NodeId, P2p, Policy, PreferredListConfig,
10+
Rest, Tls, TopicsOfInterest, TrustedPeer,
1111
};
1212
pub use secret::{Bft, GenesisPraos, NodeSecret};

jormungandr-lib/src/interfaces/config/node.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub struct Rest {
2121
}
2222

2323
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
24-
pub struct Rpc {
24+
pub struct JRpc {
2525
pub listen: SocketAddr,
2626
}
2727

@@ -294,7 +294,7 @@ pub struct NodeConfig {
294294
#[serde(skip_serializing_if = "Option::is_none")]
295295
pub storage: Option<PathBuf>,
296296
pub rest: Rest,
297-
pub rpc: Rpc,
297+
pub jrpc: JRpc,
298298
pub p2p: P2p,
299299
pub log: Option<Log>,
300300
pub mempool: Option<Mempool>,

jormungandr/Cargo.toml

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ chain-network = { git = "https://github.com/input-output-hk/chain-libs.git", bra
2020
chain-storage = { git = "https://github.com/input-output-hk/chain-libs.git", branch = "master" }
2121
chain-time = { git = "https://github.com/input-output-hk/chain-libs.git", branch = "master" }
2222
chain-vote = { git = "https://github.com/input-output-hk/chain-libs.git", branch = "master" }
23+
chain-evm = { git = "https://github.com/input-output-hk/chain-libs.git", branch = "master", optional = true }
2324
cardano-legacy-address = { git = "https://github.com/input-output-hk/chain-libs.git", branch = "master" }
2425
imhamt = { git = "https://github.com/input-output-hk/chain-libs.git", branch = "master" }
2526

@@ -60,12 +61,9 @@ warp = { version = "0.3.2", features = ["tls"] }
6061
serde_with = { version = "1.12", features = ["macros"] }
6162
http-zipkin = "0.3.0"
6263
prometheus = { version = "0.13", optional = true }
63-
jsonrpsee-http-server = "0.11.0"
64-
65-
[dependencies.reqwest]
66-
version = "0.11"
67-
default-features = false
68-
features = ["rustls-tls"]
64+
jsonrpsee-http-server = { version = "0.11.0" }
65+
jsonrpsee-core = { version = "0.11.0" }
66+
reqwest = { version = "0.11", default-features = false, features = ["rustls-tls"] }
6967

7068
[dev-dependencies]
7169
tokio = { version = "^1.15", features = ["full"] }
@@ -97,4 +95,4 @@ soak-test = []
9795
systemd = ["tracing-journald"]
9896
gelf = ["tracing-gelf"]
9997
prometheus-metrics = ["prometheus"]
100-
evm = [ "chain-impl-mockchain/evm", "jormungandr-lib/evm" ]
98+
evm = [ "chain-impl-mockchain/evm", "jormungandr-lib/evm", "chain-evm" ]

jormungandr/benches/rest_v0.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use criterion::black_box;
22
use criterion::Criterion;
33
use criterion::{criterion_group, criterion_main};
4+
use jormungandr::context::Context;
45
use jormungandr::rest::v0::logic::get_message_logs;
5-
use jormungandr::rest::Context;
66
use tokio::runtime::Runtime;
77

88
fn tokio() -> Runtime {

jormungandr/src/rest/context.rs renamed to jormungandr/src/context/mod.rs

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,38 @@
1-
use std::sync::Arc;
2-
31
use crate::{
42
blockchain::{Blockchain, Tip},
53
diagnostic::Diagnostic,
64
intercom::{NetworkMsg, TopologyMsg, TransactionMsg},
75
leadership::Logs as LeadershipLogs,
86
metrics::backends::SimpleCounter,
97
network::GlobalStateR as NetworkStateR,
10-
rest::ServerStopper,
118
secure::enclave::Enclave,
129
utils::async_msg::MessageBox,
1310
};
11+
use futures::channel::mpsc;
1412
use jormungandr_lib::interfaces::NodeState;
15-
13+
use std::sync::Arc;
1614
use tokio::sync::RwLock;
1715
use tokio_util::sync::CancellationToken;
1816
use tracing::Span;
1917

2018
pub type ContextLock = Arc<RwLock<Context>>;
2119

20+
#[derive(Clone)]
21+
pub struct ServerStopper(mpsc::Sender<()>);
22+
23+
impl ServerStopper {
24+
pub fn new(sender: mpsc::Sender<()>) -> Self {
25+
Self(sender)
26+
}
27+
28+
pub fn stop(&self) {
29+
self.0.clone().try_send(()).unwrap();
30+
}
31+
}
32+
2233
pub struct Context {
2334
full: Option<FullContext>,
24-
server_stopper: Option<ServerStopper>,
35+
rest_server_stopper: Option<ServerStopper>,
2536
node_state: NodeState,
2637
span: Option<Span>,
2738
diagnostic: Option<Diagnostic>,
@@ -32,17 +43,17 @@ pub struct Context {
3243

3344
#[derive(Debug, thiserror::Error)]
3445
pub enum Error {
35-
#[error("Full REST context not available yet")]
46+
#[error("Full REST/RPC context not available yet")]
3647
FullContext,
37-
#[error("Server stopper not set in REST context")]
48+
#[error("Server stopper not set in REST/RPC context")]
3849
ServerStopper,
39-
#[error("Log span not set in REST context")]
50+
#[error("Log span not set in REST/RPC context")]
4051
Span,
41-
#[error("Blockchain not set in REST context")]
52+
#[error("Blockchain not set in REST/RPC context")]
4253
Blockchain,
43-
#[error("Blockchain tip not set in REST context")]
54+
#[error("Blockchain tip not set in REST/RPC context")]
4455
BlockchainTip,
45-
#[error("Diagnostic data not set in REST context")]
56+
#[error("Diagnostic data not set in REST/RPC context")]
4657
Diagnostic,
4758
}
4859

@@ -58,7 +69,7 @@ impl Context {
5869
pub fn new() -> Self {
5970
Context {
6071
full: Default::default(),
61-
server_stopper: Default::default(),
72+
rest_server_stopper: Default::default(),
6273
node_state: NodeState::StartingRestServer,
6374
span: Default::default(),
6475
diagnostic: Default::default(),
@@ -76,12 +87,14 @@ impl Context {
7687
self.full.as_ref().ok_or(Error::FullContext)
7788
}
7889

79-
pub fn set_server_stopper(&mut self, server_stopper: ServerStopper) {
80-
self.server_stopper = Some(server_stopper);
90+
pub fn set_rest_server_stopper(&mut self, server_stopper: ServerStopper) {
91+
self.rest_server_stopper = Some(server_stopper);
8192
}
8293

83-
pub fn server_stopper(&self) -> Result<&ServerStopper, Error> {
84-
self.server_stopper.as_ref().ok_or(Error::ServerStopper)
94+
pub fn rest_server_stopper(&self) -> Result<&ServerStopper, Error> {
95+
self.rest_server_stopper
96+
.as_ref()
97+
.ok_or(Error::ServerStopper)
8598
}
8699

87100
pub fn set_node_state(&mut self, node_state: NodeState) {
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
use super::Error;
2+
use crate::{
3+
context::Context,
4+
jrpc::eth_types::{block::Block, block_number::BlockNumber},
5+
};
6+
use chain_evm::ethereum_types::{H256, U256};
7+
8+
pub fn get_block_by_hash(
9+
_hash: H256,
10+
full: bool,
11+
_context: &Context,
12+
) -> Result<Option<Block>, Error> {
13+
// TODO implement
14+
Ok(Some(Block::build(full)))
15+
}
16+
17+
pub fn get_block_by_number(
18+
_number: BlockNumber,
19+
_full: bool,
20+
_context: &Context,
21+
) -> Result<Option<Block>, Error> {
22+
// TODO implement
23+
Ok(Some(Block::default()))
24+
}
25+
26+
pub fn get_transaction_count_by_hash(
27+
_hash: H256,
28+
_context: &Context,
29+
) -> Result<Option<U256>, Error> {
30+
// TODO implement
31+
Ok(Some(0.into()))
32+
}
33+
34+
pub fn get_transaction_count_by_number(
35+
_number: BlockNumber,
36+
_context: &Context,
37+
) -> Result<Option<U256>, Error> {
38+
// TODO implement
39+
Ok(Some(0.into()))
40+
}
41+
42+
pub fn get_uncle_count_by_hash(_: H256, _: &Context) -> Result<Option<U256>, Error> {
43+
// jormungandr block does not have any ethereum "uncles" so we allways return 0
44+
Ok(Some(0.into()))
45+
}
46+
47+
pub fn get_uncle_count_by_number(_: BlockNumber, _: &Context) -> Result<Option<U256>, Error> {
48+
// jormungandr block does not have any ethereum "uncles" so we allways return 0
49+
Ok(Some(0.into()))
50+
}
51+
52+
pub fn get_block_number(_: &Context) -> Result<U256, Error> {
53+
// TODO implement
54+
Ok(0.into())
55+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
use crate::{blockchain::StorageError, context::ContextLock};
2+
use jsonrpsee_http_server::RpcModule;
3+
4+
mod logic;
5+
6+
#[derive(Debug, thiserror::Error)]
7+
pub enum Error {
8+
#[error(transparent)]
9+
ContextError(#[from] crate::context::Error),
10+
#[error(transparent)]
11+
Storage(#[from] StorageError),
12+
}
13+
14+
pub fn eth_get_blocks_info_module(context: ContextLock) -> RpcModule<ContextLock> {
15+
let mut module = RpcModule::new(context);
16+
17+
module
18+
.register_async_method("eth_getBlockByHash", |params, context| async move {
19+
let context = context.read().await;
20+
let (block_hash, full) = params.parse()?;
21+
logic::get_block_by_hash(block_hash, full, &context)
22+
.map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))
23+
})
24+
.unwrap();
25+
26+
module
27+
.register_async_method("eth_getBlockByNumber", |params, context| async move {
28+
let context = context.read().await;
29+
let (block_number, full) = params.parse()?;
30+
logic::get_block_by_number(block_number, full, &context)
31+
.map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))
32+
})
33+
.unwrap();
34+
35+
module
36+
.register_async_method(
37+
"eth_getBlockTransactionCountByHash",
38+
|params, context| async move {
39+
let context = context.read().await;
40+
let block_hash = params.parse()?;
41+
logic::get_transaction_count_by_hash(block_hash, &context)
42+
.map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))
43+
},
44+
)
45+
.unwrap();
46+
47+
module
48+
.register_async_method(
49+
"eth_getBlockTransactionCountByNumber",
50+
|params, context| async move {
51+
let context = context.read().await;
52+
let block_number = params.parse()?;
53+
logic::get_transaction_count_by_number(block_number, &context)
54+
.map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))
55+
},
56+
)
57+
.unwrap();
58+
59+
module
60+
.register_async_method(
61+
"eth_getUncleCountByBlockHash",
62+
|params, context| async move {
63+
let context = context.read().await;
64+
let block_hash = params.parse()?;
65+
logic::get_uncle_count_by_hash(block_hash, &context)
66+
.map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))
67+
},
68+
)
69+
.unwrap();
70+
71+
module
72+
.register_async_method(
73+
"eth_getUncleCountByBlockNumber",
74+
|params, context| async move {
75+
let context = context.read().await;
76+
let block_number = params.parse()?;
77+
logic::get_uncle_count_by_number(block_number, &context)
78+
.map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))
79+
},
80+
)
81+
.unwrap();
82+
83+
module
84+
.register_async_method("eth_blockNumber", |_, context| async move {
85+
let context = context.read().await;
86+
87+
logic::get_block_number(&context)
88+
.map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))
89+
})
90+
.unwrap();
91+
92+
module
93+
}

0 commit comments

Comments
 (0)