Add additional service transactions checking to block verifier
This commit is contained in:
parent
88eb7d3257
commit
caa210107e
@ -1,3 +1,8 @@
|
||||
## OpenEthereum v3.3.0-rc.16
|
||||
|
||||
Enhancements:
|
||||
* Additionally check zero gas price transactions by block verifier
|
||||
|
||||
## OpenEthereum v3.3.0-rc.15
|
||||
|
||||
* Revert eip1559BaseFeeMinValue activation on xDai at London hardfork block
|
||||
|
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -2932,7 +2932,7 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
|
||||
|
||||
[[package]]
|
||||
name = "openethereum"
|
||||
version = "3.3.0-rc.15"
|
||||
version = "3.3.0-rc.16"
|
||||
dependencies = [
|
||||
"ansi_term 0.10.2",
|
||||
"atty",
|
||||
@ -3282,7 +3282,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "parity-version"
|
||||
version = "3.3.0-rc.15"
|
||||
version = "3.3.0-rc.16"
|
||||
dependencies = [
|
||||
"parity-bytes",
|
||||
"rlp",
|
||||
|
@ -2,7 +2,7 @@
|
||||
description = "OpenEthereum"
|
||||
name = "openethereum"
|
||||
# NOTE Make sure to update util/version/Cargo.toml as well
|
||||
version = "3.3.0-rc.15"
|
||||
version = "3.3.0-rc.16"
|
||||
license = "GPL-3.0"
|
||||
authors = [
|
||||
"OpenEthereum developers",
|
||||
|
@ -189,8 +189,8 @@ impl txpool::VerifiedTransaction for VerifiedTransaction {
|
||||
&self.sender
|
||||
}
|
||||
|
||||
fn is_service(&self) -> bool {
|
||||
self.transaction.is_service()
|
||||
fn has_zero_gas_price(&self) -> bool {
|
||||
self.transaction.has_zero_gas_price()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,12 +131,12 @@ impl Transaction {
|
||||
}
|
||||
}
|
||||
|
||||
/// Cheeck if transaction is service transaction
|
||||
pub fn is_service(&self) -> bool {
|
||||
/// Check if transaction has zero gas price
|
||||
pub fn has_zero_gas_price(&self) -> bool {
|
||||
match *self {
|
||||
Transaction::Unverified(ref tx) => tx.is_service(),
|
||||
Transaction::Retracted(ref tx) => tx.is_service(),
|
||||
Transaction::Local(ref tx) => tx.is_service(),
|
||||
Transaction::Unverified(ref tx) => tx.has_zero_gas_price(),
|
||||
Transaction::Retracted(ref tx) => tx.has_zero_gas_price(),
|
||||
Transaction::Local(ref tx) => tx.has_zero_gas_price(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -243,13 +243,13 @@ impl<C: Client> txpool::Verifier<Transaction>
|
||||
}
|
||||
|
||||
let is_own = tx.is_local();
|
||||
let is_service = tx.is_service();
|
||||
let has_zero_gas_price = tx.has_zero_gas_price();
|
||||
// Quick exit for non-service and non-local transactions
|
||||
//
|
||||
// We're checking if the transaction is below configured minimal gas price
|
||||
// or the effective minimal gas price in case the pool is full.
|
||||
|
||||
if !is_service && !is_own {
|
||||
if !has_zero_gas_price && !is_own {
|
||||
let effective_priority_fee = tx.effective_priority_fee(self.options.block_base_fee);
|
||||
|
||||
if effective_priority_fee < self.options.minimal_gas_price {
|
||||
|
@ -72,7 +72,7 @@ impl ServiceTransactionChecker {
|
||||
SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME.to_owned(),
|
||||
BlockId::Latest,
|
||||
)
|
||||
.ok_or_else(|| "contract is not configured")?;
|
||||
.ok_or_else(|| "Certifier contract is not configured")?;
|
||||
self.call_contract(client, contract_address, sender)
|
||||
.and_then(|allowed| {
|
||||
if let Some(mut cache) = self.certified_addresses_cache.try_write() {
|
||||
|
@ -488,6 +488,50 @@ impl Importer {
|
||||
.epoch_transition(parent.number(), *header.parent_hash())
|
||||
.is_some();
|
||||
|
||||
// Check if zero gas price transactions are certified to be service transactions
|
||||
// using the Certifier contract. If they are not certified, the block is treated as invalid.
|
||||
let service_transaction_checker = self.miner.service_transaction_checker();
|
||||
if service_transaction_checker.is_some() {
|
||||
match service_transaction_checker.unwrap().refresh_cache(client) {
|
||||
Ok(true) => {
|
||||
trace!(target: "client", "Service transaction cache was refreshed successfully");
|
||||
}
|
||||
Ok(false) => {
|
||||
trace!(target: "client", "Registrar or/and service transactions contract does not exist");
|
||||
}
|
||||
Err(e) => {
|
||||
error!(target: "client", "Error occurred while refreshing service transaction cache: {}", e)
|
||||
}
|
||||
};
|
||||
};
|
||||
for t in &block.transactions {
|
||||
if t.has_zero_gas_price() {
|
||||
match self.miner.service_transaction_checker() {
|
||||
None => {
|
||||
let e = "Service transactions are not allowed. You need to enable Certifier contract.";
|
||||
warn!(target: "client", "Service tx checker error: {:?}", e);
|
||||
bail!(e);
|
||||
}
|
||||
Some(ref checker) => match checker.check(client, &t) {
|
||||
Ok(true) => {}
|
||||
Ok(false) => {
|
||||
let e = format!(
|
||||
"Service transactions are not allowed for the sender {:?}",
|
||||
t.sender()
|
||||
);
|
||||
warn!(target: "client", "Service tx checker error: {:?}", e);
|
||||
bail!(e);
|
||||
}
|
||||
Err(e) => {
|
||||
debug!(target: "client", "Unable to verify service transaction: {:?}", e);
|
||||
warn!(target: "client", "Service tx checker error: {:?}", e);
|
||||
bail!(e);
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// t_nb 8.0 Block enacting. Execution of transactions.
|
||||
let enact_result = enact_verified(
|
||||
block,
|
||||
|
@ -1207,7 +1207,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
}
|
||||
|
||||
// ensure that the user was willing to at least pay the base fee
|
||||
if t.tx().gas_price < self.info.base_fee.unwrap_or_default() && !t.is_service() {
|
||||
if t.tx().gas_price < self.info.base_fee.unwrap_or_default() && !t.has_zero_gas_price() {
|
||||
return Err(ExecutionError::GasPriceLowerThanBaseFee {
|
||||
gas_price: t.tx().gas_price,
|
||||
base_fee: self.info.base_fee.unwrap_or_default(),
|
||||
@ -1516,7 +1516,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
// Up until now, fees_value is calculated for each type of transaction based on their gas prices
|
||||
// Now, if eip1559 is activated, burn the base fee
|
||||
// miner only receives the inclusion fee; note that the base fee is not given to anyone (it is burned)
|
||||
let burnt_fee = if schedule.eip1559 && !t.is_service() {
|
||||
let burnt_fee = if schedule.eip1559 && !t.has_zero_gas_price() {
|
||||
let (fee, overflow_3) =
|
||||
gas_used.overflowing_mul(self.info.base_fee.unwrap_or_default());
|
||||
if overflow_3 {
|
||||
|
@ -376,7 +376,7 @@ impl EthereumMachine {
|
||||
header: &Header,
|
||||
) -> Result<SignedTransaction, transaction::Error> {
|
||||
// ensure that the user was willing to at least pay the base fee
|
||||
if t.tx().gas_price < header.base_fee().unwrap_or_default() && !t.is_service() {
|
||||
if t.tx().gas_price < header.base_fee().unwrap_or_default() && !t.has_zero_gas_price() {
|
||||
return Err(transaction::Error::GasPriceLowerThanBaseFee {
|
||||
gas_price: t.tx().gas_price,
|
||||
base_fee: header.base_fee().unwrap_or_default(),
|
||||
|
@ -657,7 +657,7 @@ impl TypedTransaction {
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn is_service(&self) -> bool {
|
||||
pub fn has_zero_gas_price(&self) -> bool {
|
||||
match self {
|
||||
Self::EIP1559Transaction(tx) => {
|
||||
tx.tx().gas_price.is_zero() && tx.max_priority_fee_per_gas.is_zero()
|
||||
|
@ -114,6 +114,6 @@ pub trait VerifiedTransaction: fmt::Debug {
|
||||
/// Transaction sender
|
||||
fn sender(&self) -> &Self::Sender;
|
||||
|
||||
/// Is it a service transaction?
|
||||
fn is_service(&self) -> bool;
|
||||
/// Does it have zero gas price?
|
||||
fn has_zero_gas_price(&self) -> bool;
|
||||
}
|
||||
|
@ -651,7 +651,7 @@ where
|
||||
Readiness::Ready => {
|
||||
//return transaction with score higher or equal to desired
|
||||
if score >= &self.includable_boundary
|
||||
|| tx.transaction.is_service()
|
||||
|| tx.transaction.has_zero_gas_price()
|
||||
{
|
||||
return Some(tx.transaction.clone());
|
||||
}
|
||||
@ -740,7 +740,7 @@ where
|
||||
if tx_state == Readiness::Ready {
|
||||
//return transaction with score higher or equal to desired
|
||||
if best.score >= self.includable_boundary
|
||||
|| best.transaction.transaction.is_service()
|
||||
|| best.transaction.transaction.has_zero_gas_price()
|
||||
{
|
||||
return Some(best.transaction.transaction);
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ impl VerifiedTransaction for Transaction {
|
||||
fn sender(&self) -> &Address {
|
||||
&self.sender
|
||||
}
|
||||
fn is_service(&self) -> bool {
|
||||
fn has_zero_gas_price(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "parity-version"
|
||||
# NOTE: this value is used for OpenEthereum version string (via env CARGO_PKG_VERSION)
|
||||
version = "3.3.0-rc.15"
|
||||
version = "3.3.0-rc.16"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
build = "build.rs"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user