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
|
## OpenEthereum v3.3.0-rc.15
|
||||||
|
|
||||||
* Revert eip1559BaseFeeMinValue activation on xDai at London hardfork block
|
* Revert eip1559BaseFeeMinValue activation on xDai at London hardfork block
|
||||||
|
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -2932,7 +2932,7 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openethereum"
|
name = "openethereum"
|
||||||
version = "3.3.0-rc.15"
|
version = "3.3.0-rc.16"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term 0.10.2",
|
"ansi_term 0.10.2",
|
||||||
"atty",
|
"atty",
|
||||||
@ -3282,7 +3282,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parity-version"
|
name = "parity-version"
|
||||||
version = "3.3.0-rc.15"
|
version = "3.3.0-rc.16"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"parity-bytes",
|
"parity-bytes",
|
||||||
"rlp",
|
"rlp",
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
description = "OpenEthereum"
|
description = "OpenEthereum"
|
||||||
name = "openethereum"
|
name = "openethereum"
|
||||||
# NOTE Make sure to update util/version/Cargo.toml as well
|
# 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"
|
license = "GPL-3.0"
|
||||||
authors = [
|
authors = [
|
||||||
"OpenEthereum developers",
|
"OpenEthereum developers",
|
||||||
|
@ -189,8 +189,8 @@ impl txpool::VerifiedTransaction for VerifiedTransaction {
|
|||||||
&self.sender
|
&self.sender
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_service(&self) -> bool {
|
fn has_zero_gas_price(&self) -> bool {
|
||||||
self.transaction.is_service()
|
self.transaction.has_zero_gas_price()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,12 +131,12 @@ impl Transaction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cheeck if transaction is service transaction
|
/// Check if transaction has zero gas price
|
||||||
pub fn is_service(&self) -> bool {
|
pub fn has_zero_gas_price(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
Transaction::Unverified(ref tx) => tx.is_service(),
|
Transaction::Unverified(ref tx) => tx.has_zero_gas_price(),
|
||||||
Transaction::Retracted(ref tx) => tx.is_service(),
|
Transaction::Retracted(ref tx) => tx.has_zero_gas_price(),
|
||||||
Transaction::Local(ref tx) => tx.is_service(),
|
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_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
|
// Quick exit for non-service and non-local transactions
|
||||||
//
|
//
|
||||||
// We're checking if the transaction is below configured minimal gas price
|
// We're checking if the transaction is below configured minimal gas price
|
||||||
// or the effective minimal gas price in case the pool is full.
|
// 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);
|
let effective_priority_fee = tx.effective_priority_fee(self.options.block_base_fee);
|
||||||
|
|
||||||
if effective_priority_fee < self.options.minimal_gas_price {
|
if effective_priority_fee < self.options.minimal_gas_price {
|
||||||
|
@ -72,7 +72,7 @@ impl ServiceTransactionChecker {
|
|||||||
SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME.to_owned(),
|
SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME.to_owned(),
|
||||||
BlockId::Latest,
|
BlockId::Latest,
|
||||||
)
|
)
|
||||||
.ok_or_else(|| "contract is not configured")?;
|
.ok_or_else(|| "Certifier contract is not configured")?;
|
||||||
self.call_contract(client, contract_address, sender)
|
self.call_contract(client, contract_address, sender)
|
||||||
.and_then(|allowed| {
|
.and_then(|allowed| {
|
||||||
if let Some(mut cache) = self.certified_addresses_cache.try_write() {
|
if let Some(mut cache) = self.certified_addresses_cache.try_write() {
|
||||||
|
@ -488,6 +488,50 @@ impl Importer {
|
|||||||
.epoch_transition(parent.number(), *header.parent_hash())
|
.epoch_transition(parent.number(), *header.parent_hash())
|
||||||
.is_some();
|
.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.
|
// t_nb 8.0 Block enacting. Execution of transactions.
|
||||||
let enact_result = enact_verified(
|
let enact_result = enact_verified(
|
||||||
block,
|
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
|
// 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 {
|
return Err(ExecutionError::GasPriceLowerThanBaseFee {
|
||||||
gas_price: t.tx().gas_price,
|
gas_price: t.tx().gas_price,
|
||||||
base_fee: self.info.base_fee.unwrap_or_default(),
|
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
|
// 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
|
// 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)
|
// 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) =
|
let (fee, overflow_3) =
|
||||||
gas_used.overflowing_mul(self.info.base_fee.unwrap_or_default());
|
gas_used.overflowing_mul(self.info.base_fee.unwrap_or_default());
|
||||||
if overflow_3 {
|
if overflow_3 {
|
||||||
|
@ -376,7 +376,7 @@ impl EthereumMachine {
|
|||||||
header: &Header,
|
header: &Header,
|
||||||
) -> Result<SignedTransaction, transaction::Error> {
|
) -> Result<SignedTransaction, transaction::Error> {
|
||||||
// ensure that the user was willing to at least pay the base fee
|
// 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 {
|
return Err(transaction::Error::GasPriceLowerThanBaseFee {
|
||||||
gas_price: t.tx().gas_price,
|
gas_price: t.tx().gas_price,
|
||||||
base_fee: header.base_fee().unwrap_or_default(),
|
base_fee: header.base_fee().unwrap_or_default(),
|
||||||
|
@ -657,7 +657,7 @@ impl TypedTransaction {
|
|||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_service(&self) -> bool {
|
pub fn has_zero_gas_price(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::EIP1559Transaction(tx) => {
|
Self::EIP1559Transaction(tx) => {
|
||||||
tx.tx().gas_price.is_zero() && tx.max_priority_fee_per_gas.is_zero()
|
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
|
/// Transaction sender
|
||||||
fn sender(&self) -> &Self::Sender;
|
fn sender(&self) -> &Self::Sender;
|
||||||
|
|
||||||
/// Is it a service transaction?
|
/// Does it have zero gas price?
|
||||||
fn is_service(&self) -> bool;
|
fn has_zero_gas_price(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
@ -651,7 +651,7 @@ where
|
|||||||
Readiness::Ready => {
|
Readiness::Ready => {
|
||||||
//return transaction with score higher or equal to desired
|
//return transaction with score higher or equal to desired
|
||||||
if score >= &self.includable_boundary
|
if score >= &self.includable_boundary
|
||||||
|| tx.transaction.is_service()
|
|| tx.transaction.has_zero_gas_price()
|
||||||
{
|
{
|
||||||
return Some(tx.transaction.clone());
|
return Some(tx.transaction.clone());
|
||||||
}
|
}
|
||||||
@ -740,7 +740,7 @@ where
|
|||||||
if tx_state == Readiness::Ready {
|
if tx_state == Readiness::Ready {
|
||||||
//return transaction with score higher or equal to desired
|
//return transaction with score higher or equal to desired
|
||||||
if best.score >= self.includable_boundary
|
if best.score >= self.includable_boundary
|
||||||
|| best.transaction.transaction.is_service()
|
|| best.transaction.transaction.has_zero_gas_price()
|
||||||
{
|
{
|
||||||
return Some(best.transaction.transaction);
|
return Some(best.transaction.transaction);
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ impl VerifiedTransaction for Transaction {
|
|||||||
fn sender(&self) -> &Address {
|
fn sender(&self) -> &Address {
|
||||||
&self.sender
|
&self.sender
|
||||||
}
|
}
|
||||||
fn is_service(&self) -> bool {
|
fn has_zero_gas_price(&self) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "parity-version"
|
name = "parity-version"
|
||||||
# NOTE: this value is used for OpenEthereum version string (via env CARGO_PKG_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>"]
|
authors = ["Parity Technologies <admin@parity.io>"]
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user