pause relays(s) when node is syncing (#605)

This commit is contained in:
Svyatoslav Nikolsky
2021-02-02 13:27:18 +03:00
committed by Bastian Köcher
parent 8ee90afae6
commit 8953967d92
15 changed files with 93 additions and 6 deletions
+22 -2
View File
@@ -16,8 +16,8 @@
use crate::rpc::Ethereum;
use crate::types::{
Address, Bytes, CallRequest, Header, HeaderWithTransactions, Receipt, SignedRawTx, Transaction, TransactionHash,
H256, U256,
Address, Bytes, CallRequest, Header, HeaderWithTransactions, Receipt, SignedRawTx, SyncState, Transaction,
TransactionHash, H256, U256,
};
use crate::{ConnectionParams, Error, Result};
@@ -25,6 +25,9 @@ use jsonrpsee::raw::RawClient;
use jsonrpsee::transport::http::HttpTransportClient;
use jsonrpsee::Client as RpcClient;
/// Number of headers missing from the Ethereum node for us to consider node not synced.
const MAJOR_SYNC_BLOCKS: u64 = 5;
/// The client used to interact with an Ethereum node through RPC.
#[derive(Clone)]
pub struct Client {
@@ -53,6 +56,23 @@ impl Client {
pub fn reconnect(&mut self) {
self.client = Self::build_client(&self.params);
}
}
impl Client {
/// Returns true if client is connected to at least one peer and is in synced state.
pub async fn ensure_synced(&self) -> Result<()> {
match Ethereum::syncing(&self.client).await? {
SyncState::NotSyncing => Ok(()),
SyncState::Syncing(syncing) => {
let missing_headers = syncing.highest_block.saturating_sub(syncing.current_block);
if missing_headers > MAJOR_SYNC_BLOCKS.into() {
return Err(Error::ClientNotSynced(missing_headers));
}
Ok(())
}
}
}
/// Estimate gas usage for the given call.
pub async fn estimate_gas(&self, call_request: CallRequest) -> Result<U256> {
+13 -1
View File
@@ -16,6 +16,8 @@
//! Ethereum node RPC errors.
use crate::types::U256;
use jsonrpsee::client::RequestError;
use relay_utils::MaybeConnectionError;
@@ -40,6 +42,9 @@ pub enum Error {
InvalidSubstrateBlockNumber,
/// An invalid index has been received from an Ethereum node.
InvalidIncompleteIndex,
/// The client we're connected to is not synced, so we can't rely on its state. Contains
/// number of unsynced headers.
ClientNotSynced(U256),
}
impl From<RequestError> for Error {
@@ -50,7 +55,11 @@ impl From<RequestError> for Error {
impl MaybeConnectionError for Error {
fn is_connection_error(&self) -> bool {
matches!(*self, Error::Request(RequestError::TransportError(_)))
matches!(
*self,
Error::Request(RequestError::TransportError(_))
| Error::ClientNotSynced(_),
)
}
}
@@ -66,6 +75,9 @@ impl ToString for Error {
Self::IncompleteTransaction => "Incomplete Ethereum Transaction (missing required field - raw)".to_string(),
Self::InvalidSubstrateBlockNumber => "Received an invalid Substrate block from Ethereum Node".to_string(),
Self::InvalidIncompleteIndex => "Received an invalid incomplete index from Ethereum Node".to_string(),
Self::ClientNotSynced(missing_headers) => {
format!("Ethereum client is not synced: syncing {} headers", missing_headers)
}
}
}
}
+4 -1
View File
@@ -22,11 +22,14 @@
#![allow(unused_variables)]
use crate::types::{
Address, Bytes, CallRequest, Header, HeaderWithTransactions, Receipt, Transaction, TransactionHash, H256, U256, U64,
Address, Bytes, CallRequest, Header, HeaderWithTransactions, Receipt, SyncState, Transaction, TransactionHash,
H256, U256, U64,
};
jsonrpsee::rpc_api! {
pub(crate) Ethereum {
#[rpc(method = "eth_syncing", positional_params)]
fn syncing() -> SyncState;
#[rpc(method = "eth_estimateGas", positional_params)]
fn estimate_gas(call_request: CallRequest) -> U256;
#[rpc(method = "eth_blockNumber", positional_params)]
+1 -1
View File
@@ -18,7 +18,7 @@
use headers_relay::sync_types::SourceHeader;
pub use web3::types::{Address, Bytes, CallRequest, H256, U128, U256, U64};
pub use web3::types::{Address, Bytes, CallRequest, SyncState, H256, U128, U256, U64};
/// When header is just received from the Ethereum node, we check that it has
/// both number and hash fields filled.