Fix: high load RPC putting node in a broken state: avoid running blocking tasks within blocking tasks (#4461)

Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
swbartosz
2023-09-03 15:16:38 +01:00
committed by GitHub
parent acedc8cf4c
commit e8f2a56f40
3 changed files with 36 additions and 38 deletions

View File

@ -47,8 +47,12 @@ where
/// Estimate gas needed for execution of the `request` at the [BlockId].
pub async fn estimate_gas_at(&self, request: CallRequest, at: BlockId) -> EthResult<U256> {
let (cfg, block_env, at) = self.evm_env_at(at).await?;
let state = self.state_at(at)?;
self.estimate_gas_with(cfg, block_env, request, state)
self.on_blocking_task(|this| async move {
let state = this.state_at(at)?;
this.estimate_gas_with(cfg, block_env, request, state)
})
.await
}
/// Executes the call request (`eth_call`) and returns the output

View File

@ -236,14 +236,7 @@ where
) -> Result<Bytes> {
trace!(target: "rpc::eth", ?request, ?block_number, ?state_overrides, ?block_overrides, "Serving eth_call");
Ok(self
.on_blocking_task(|this| async move {
this.call(
request,
block_number,
EvmOverrides::new(state_overrides, block_overrides),
)
.await
})
.call(request, block_number, EvmOverrides::new(state_overrides, block_overrides))
.await?)
}
@ -265,15 +258,11 @@ where
block_number: Option<BlockId>,
) -> Result<AccessListWithGasUsed> {
trace!(target: "rpc::eth", ?request, ?block_number, "Serving eth_createAccessList");
Ok(self
.on_blocking_task(|this| async move {
let block_id = block_number.unwrap_or(BlockId::Number(BlockNumberOrTag::Latest));
let access_list = this.create_access_list_at(request.clone(), block_number).await?;
request.access_list = Some(access_list.clone());
let gas_used = this.estimate_gas_at(request, block_id).await?;
Ok(AccessListWithGasUsed { access_list, gas_used })
})
.await?)
let block_id = block_number.unwrap_or(BlockId::Number(BlockNumberOrTag::Latest));
let access_list = self.create_access_list_at(request.clone(), block_number).await?;
request.access_list = Some(access_list.clone());
let gas_used = self.estimate_gas_at(request, block_id).await?;
Ok(AccessListWithGasUsed { access_list, gas_used })
}
/// Handler for: `eth_estimateGas`
@ -284,13 +273,10 @@ where
) -> Result<U256> {
trace!(target: "rpc::eth", ?request, ?block_number, "Serving eth_estimateGas");
Ok(self
.on_blocking_task(|this| async move {
this.estimate_gas_at(
request,
block_number.unwrap_or(BlockId::Number(BlockNumberOrTag::Latest)),
)
.await
})
.estimate_gas_at(
request,
block_number.unwrap_or(BlockId::Number(BlockNumberOrTag::Latest)),
)
.await?)
}

View File

@ -400,20 +400,28 @@ where
}
async fn transaction_receipt(&self, hash: H256) -> EthResult<Option<TransactionReceipt>> {
self.on_blocking_task(|this| async move {
let (tx, meta) = match this.provider().transaction_by_hash_with_meta(hash)? {
Some((tx, meta)) => (tx, meta),
None => return Ok(None),
};
let result = self
.on_blocking_task(|this| async move {
let (tx, meta) = match this.provider().transaction_by_hash_with_meta(hash)? {
Some((tx, meta)) => (tx, meta),
None => return Ok(None),
};
let receipt = match this.provider().receipt_by_hash(hash)? {
Some(recpt) => recpt,
None => return Ok(None),
};
let receipt = match this.provider().receipt_by_hash(hash)? {
Some(recpt) => recpt,
None => return Ok(None),
};
this.build_transaction_receipt(tx, meta, receipt).await.map(Some)
})
.await
Ok(Some((tx, meta, receipt)))
})
.await?;
let (tx, meta, receipt) = match result {
Some((tx, meta, receipt)) => (tx, meta, receipt),
None => return Ok(None),
};
self.build_transaction_receipt(tx, meta, receipt).await.map(Some)
}
async fn send_raw_transaction(&self, tx: Bytes) -> EthResult<H256> {