Fix RPC crash on too high base fee

This commit is contained in:
Artem Vorotnikov
2022-05-29 21:39:02 +03:00
parent b0ec5ce6e3
commit 203d532b7b
7 changed files with 40 additions and 31 deletions

View File

@@ -2,7 +2,7 @@ use crate::execution::tracer::{NoopTracer, Tracer};
use super::{
common::{InterpreterMessage, Output},
CreateMessage,
CreateMessage, StatusCode,
};
use bytes::Bytes;
use ethereum_types::Address;
@@ -101,7 +101,7 @@ pub trait Host {
/// Call to another account.
fn call(&mut self, msg: Call) -> Output;
/// Retrieve transaction context.
fn get_tx_context(&mut self) -> TxContext;
fn get_tx_context(&mut self) -> Result<TxContext, StatusCode>;
/// Get block hash.
///
/// Returns `Ok(U256::zero())` if block does not exist.

View File

@@ -130,7 +130,7 @@ pub(crate) fn blockhash<H: Host>(
) -> Result<(), StatusCode> {
let number = state.stack.pop();
let upper_bound = host.get_tx_context().block_number;
let upper_bound = host.get_tx_context()?.block_number;
let lower_bound = upper_bound.saturating_sub(256);
let mut header = U256::ZERO;

View File

@@ -378,21 +378,21 @@ where
}
OpCode::ORIGIN => state
.stack
.push(address_to_u256(host.get_tx_context().tx_origin)),
.push(address_to_u256(host.get_tx_context()?.tx_origin)),
OpCode::COINBASE => state
.stack
.push(address_to_u256(host.get_tx_context().block_coinbase)),
OpCode::GASPRICE => state.stack.push(host.get_tx_context().tx_gas_price),
.push(address_to_u256(host.get_tx_context()?.block_coinbase)),
OpCode::GASPRICE => state.stack.push(host.get_tx_context()?.tx_gas_price),
OpCode::TIMESTAMP => state
.stack
.push(host.get_tx_context().block_timestamp.into()),
OpCode::NUMBER => state.stack.push(host.get_tx_context().block_number.into()),
OpCode::DIFFICULTY => state.stack.push(host.get_tx_context().block_difficulty),
.push(host.get_tx_context()?.block_timestamp.into()),
OpCode::NUMBER => state.stack.push(host.get_tx_context()?.block_number.into()),
OpCode::DIFFICULTY => state.stack.push(host.get_tx_context()?.block_difficulty),
OpCode::GASLIMIT => state
.stack
.push(host.get_tx_context().block_gas_limit.into()),
OpCode::CHAINID => state.stack.push(host.get_tx_context().chain_id),
OpCode::BASEFEE => state.stack.push(host.get_tx_context().block_base_fee),
.push(host.get_tx_context()?.block_gas_limit.into()),
OpCode::CHAINID => state.stack.push(host.get_tx_context()?.chain_id),
OpCode::BASEFEE => state.stack.push(host.get_tx_context()?.block_base_fee),
OpCode::SELFBALANCE => {
external::selfbalance(state, host);
}

View File

@@ -244,8 +244,8 @@ impl Host for MockedHost {
self.call_result.clone()
}
fn get_tx_context(&mut self) -> TxContext {
self.tx_context.clone()
fn get_tx_context(&mut self) -> Result<TxContext, StatusCode> {
Ok(self.tx_context.clone())
}
fn get_block_hash(&mut self, block_number: u64) -> U256 {

View File

@@ -576,9 +576,13 @@ impl<'r, 'state, 'tracer, 'analysis, 'h, 'c, 't, 'a, B: State> Host
}
}
fn get_tx_context(&mut self) -> TxContext {
fn get_tx_context(&mut self) -> Result<TxContext, StatusCode> {
let base_fee_per_gas = self.inner.header.base_fee_per_gas.unwrap_or(U256::ZERO);
let tx_gas_price = self.inner.message.effective_gas_price(base_fee_per_gas);
let tx_gas_price = self
.inner
.message
.effective_gas_price(base_fee_per_gas)
.ok_or(StatusCode::InternalError("tx gas price too low"))?;
let tx_origin = self.inner.sender;
let block_coinbase = self.inner.beneficiary;
let block_number = self.inner.header.number.0;
@@ -588,7 +592,7 @@ impl<'r, 'state, 'tracer, 'analysis, 'h, 'c, 't, 'a, B: State> Host
let chain_id = self.inner.block_spec.params.chain_id.0.into();
let block_base_fee = base_fee_per_gas;
TxContext {
Ok(TxContext {
tx_gas_price,
tx_origin,
block_coinbase,
@@ -598,7 +602,7 @@ impl<'r, 'state, 'tracer, 'analysis, 'h, 'c, 't, 'a, B: State> Host
block_difficulty,
chain_id,
block_base_fee,
}
})
}
fn get_block_hash(&mut self, block_number: u64) -> U256 {

View File

@@ -36,7 +36,7 @@ fn refund_gas<'r, S>(
message: &Message,
sender: Address,
mut gas_left: u64,
) -> anyhow::Result<u64>
) -> Result<u64, DuoError>
where
S: State,
{
@@ -54,7 +54,9 @@ where
gas_left += refund;
let base_fee_per_gas = header.base_fee_per_gas.unwrap_or(U256::ZERO);
let effective_gas_price = message.effective_gas_price(base_fee_per_gas);
let effective_gas_price = message
.effective_gas_price(base_fee_per_gas)
.ok_or(ValidationError::MaxFeeLessThanBase)?;
state.add_to_balance(sender, U256::from(gas_left) * effective_gas_price)?;
Ok(gas_left)
@@ -80,7 +82,9 @@ where
state.access_account(sender);
let base_fee_per_gas = header.base_fee_per_gas.unwrap_or(U256::ZERO);
let effective_gas_price = message.effective_gas_price(base_fee_per_gas);
let effective_gas_price = message
.effective_gas_price(base_fee_per_gas)
.ok_or(ValidationError::MaxFeeLessThanBase)?;
state.subtract_from_balance(
sender,
U256::from(message.gas_limit()) * effective_gas_price,
@@ -134,7 +138,9 @@ where
)?;
// award the miner
let priority_fee_per_gas = message.priority_fee_per_gas(base_fee_per_gas);
let priority_fee_per_gas = message
.priority_fee_per_gas(base_fee_per_gas)
.ok_or(ValidationError::MaxFeeLessThanBase)?;
state.add_to_balance(
header.beneficiary,
U256::from(gas_used) * priority_fee_per_gas,

View File

@@ -16,7 +16,7 @@ use secp256k1::{
};
use serde::*;
use sha3::*;
use std::{borrow::Cow, cmp::min};
use std::borrow::Cow;
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum TxType {
@@ -858,16 +858,15 @@ impl Message {
}
}
pub(crate) fn priority_fee_per_gas(&self, base_fee_per_gas: U256) -> U256 {
assert!(self.max_fee_per_gas() >= base_fee_per_gas);
min(
self.max_priority_fee_per_gas(),
self.max_fee_per_gas() - base_fee_per_gas,
)
pub(crate) fn priority_fee_per_gas(&self, base_fee_per_gas: U256) -> Option<U256> {
self.max_fee_per_gas()
.checked_sub(base_fee_per_gas)
.map(|v| std::cmp::min(self.max_priority_fee_per_gas(), v))
}
pub(crate) fn effective_gas_price(&self, base_fee_per_gas: U256) -> U256 {
self.priority_fee_per_gas(base_fee_per_gas) + base_fee_per_gas
pub(crate) fn effective_gas_price(&self, base_fee_per_gas: U256) -> Option<U256> {
self.priority_fee_per_gas(base_fee_per_gas)
.map(|v| v + base_fee_per_gas)
}
}