-
Notifications
You must be signed in to change notification settings - Fork 66
Introduce gas floor #3941
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Introduce gas floor #3941
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -61,7 +61,7 @@ pub enum TxAcceptanceError { | |
| VerificationFailed(String), | ||
| #[error("gas price lower than minimum {0}")] | ||
| GasPriceTooLow(u64), | ||
| #[error("gas limit lower than minimum {0}")] | ||
| #[error("gas limit lower than minimum {0} LUX")] | ||
| GasLimitTooLow(u64), | ||
| #[error("Maximum count of transactions exceeded {0}")] | ||
| MaxTxnCountExceeded(usize), | ||
|
|
@@ -349,10 +349,16 @@ impl MempoolSrv { | |
| dusk_consensus::validate_blob_sidecars(tx)?; | ||
| } | ||
|
|
||
| // Check global minimum gas limit | ||
| let min_gas_limit = vm.min_gas_limit(); | ||
| if tx.inner.gas_limit() < min_gas_limit { | ||
| return Err(TxAcceptanceError::GasLimitTooLow(min_gas_limit)); | ||
| // Check global minimum gas limit and per-tx fee floor | ||
|
||
| let chain_min_gas_limit = vm.min_gas_limit(); | ||
| let min_tx_gas = vm.min_tx_gas(tip_height); | ||
| let required_gas_limit = | ||
| core::cmp::max(chain_min_gas_limit, min_tx_gas); | ||
|
|
||
| if tx.inner.gas_limit() < required_gas_limit { | ||
| return Err(TxAcceptanceError::GasLimitTooLow( | ||
| required_gas_limit, | ||
| )); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 | |
|
|
||
| ## [Unreleased] | ||
|
|
||
| ### Added | ||
|
|
||
| - Add TX floor price feature, including for well-known chain ids [#3940] | ||
|
||
|
|
||
| ## [1.4.1] - 2025-12-04 | ||
|
|
||
| ### Added | ||
|
|
@@ -406,6 +410,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 | |
| - Add build system that generates keys for circuits and caches them. | ||
|
|
||
| <!-- Issues --> | ||
| [#3940]: https://github.com/dusk-network/rusk/issues/3940 | ||
| [#3917]: https://github.com/dusk-network/rusk/issues/3917 | ||
| [#3897]: https://github.com/dusk-network/rusk/issues/3897 | ||
| [#3894]: https://github.com/dusk-network/rusk/issues/3894 | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -321,6 +321,19 @@ impl VMExecution for Rusk { | |
| .map(|activation| activation.is_active_at(block_height)) | ||
| .unwrap_or(false) | ||
| } | ||
|
|
||
| fn min_tx_gas(&self, height: u64) -> u64 { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would return this as Option to be aligned with its meaning |
||
| self.vm_config | ||
| .feature(FEATURE_MIN_TX_GAS) | ||
| .map(|activation| { | ||
| if activation.is_active_at(height) { | ||
| self.vm_config.min_tx_gas | ||
| } else { | ||
| 0 | ||
| } | ||
| }) | ||
| .unwrap_or(0) | ||
| } | ||
| } | ||
|
|
||
| fn has_unique_elements<T>(iter: T) -> bool | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,6 +21,8 @@ const DEFAULT_GAS_PER_BLOB: u64 = 1_000_000; | |
| const DEFAULT_MIN_DEPLOY_POINTS: u64 = 5_000_000; | ||
| const DEFAULT_MIN_DEPLOYMENT_GAS_PRICE: u64 = 2_000; | ||
| const DEFAULT_BLOCK_GAS_LIMIT: u64 = 3 * 1_000_000_000; | ||
| /// Default per‑tx minimum gas floor. 0 disables it. | ||
| const DEFAULT_MIN_TX_GAS: u64 = 5_000_000; | ||
|
|
||
| /// Configuration for the execution of a transaction. | ||
| #[derive(Debug, Clone, serde::Serialize)] | ||
|
|
@@ -45,6 +47,9 @@ pub struct Config { | |
| #[serde(with = "humantime_serde")] | ||
| pub generation_timeout: Option<Duration>, | ||
|
|
||
| /// Minimum gas charged for any transaction. | ||
| pub min_tx_gas: u64, | ||
|
||
|
|
||
| /// Set of features to activate | ||
| features: HashMap<String, FeatureActivation>, | ||
| } | ||
|
|
@@ -61,6 +66,7 @@ pub(crate) mod feature { | |
| pub const FEATURE_DISABLE_WASM64: &str = "DISABLE_WASM64"; | ||
| pub const FEATURE_DISABLE_WASM32: &str = "DISABLE_WASM32"; | ||
| pub const FEATURE_DISABLE_3RD_PARTY: &str = "DISABLE_3RD_PARTY"; | ||
| pub const FEATURE_MIN_TX_GAS: &str = "MIN_TX_GAS"; | ||
|
|
||
| pub const HQ_KECCAK256: &str = "HQ_KECCAK256"; | ||
| } | ||
|
|
@@ -73,6 +79,7 @@ impl Config { | |
| min_deployment_gas_price: DEFAULT_MIN_DEPLOYMENT_GAS_PRICE, | ||
| min_deploy_points: DEFAULT_MIN_DEPLOY_POINTS, | ||
| block_gas_limit: DEFAULT_BLOCK_GAS_LIMIT, | ||
| min_tx_gas: DEFAULT_MIN_TX_GAS, | ||
| generation_timeout: None, | ||
| features: HashMap::new(), | ||
| } | ||
|
|
@@ -121,6 +128,12 @@ impl Config { | |
| self | ||
| } | ||
|
|
||
| /// Set the minimum gas charged for any transaction. | ||
| pub const fn with_min_tx_gas(mut self, min_tx_gas: u64) -> Self { | ||
| self.min_tx_gas = min_tx_gas; | ||
| self | ||
| } | ||
|
|
||
| /// Create a new `Config` with the given parameters. | ||
| pub fn to_execution_config(&self, block_height: u64) -> ExecutionConfig { | ||
| let with_public_sender: bool = self | ||
|
|
@@ -143,11 +156,23 @@ impl Config { | |
| .feature(feature::FEATURE_DISABLE_3RD_PARTY) | ||
| .map(|activation| activation.is_active_at(block_height)) | ||
| .unwrap_or_default(); | ||
| let min_tx_gas = self | ||
| .feature(feature::FEATURE_MIN_TX_GAS) | ||
| .map(|activation| { | ||
| if activation.is_active_at(block_height) { | ||
| self.min_tx_gas | ||
| } else { | ||
| 0 | ||
| } | ||
| }) | ||
| .unwrap_or(0); | ||
|
|
||
| ExecutionConfig { | ||
| gas_per_blob: self.gas_per_blob, | ||
| gas_per_deploy_byte: self.gas_per_deploy_byte, | ||
| min_deploy_points: self.min_deploy_points, | ||
| min_deploy_gas_price: self.min_deployment_gas_price, | ||
| min_tx_gas, | ||
| with_public_sender, | ||
| with_blob, | ||
| disable_wasm64, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,7 +10,9 @@ use std::sync::LazyLock; | |
|
|
||
| use dusk_vm::FeatureActivation; | ||
|
|
||
| use crate::node::{FEATURE_DISABLE_3RD_PARTY, FEATURE_DISABLE_WASM32}; | ||
| use crate::node::{ | ||
| FEATURE_DISABLE_3RD_PARTY, FEATURE_DISABLE_WASM32, FEATURE_MIN_TX_GAS, | ||
| }; | ||
|
|
||
| use super::feature::{ | ||
| FEATURE_ABI_PUBLIC_SENDER, FEATURE_BLOB, FEATURE_DISABLE_WASM64, | ||
|
|
@@ -19,6 +21,7 @@ use super::feature::{ | |
| use super::{ | ||
| DEFAULT_BLOCK_GAS_LIMIT, DEFAULT_GAS_PER_BLOB, DEFAULT_GAS_PER_DEPLOY_BYTE, | ||
| DEFAULT_MIN_DEPLOYMENT_GAS_PRICE, DEFAULT_MIN_DEPLOY_POINTS, | ||
| DEFAULT_MIN_TX_GAS, | ||
| }; | ||
|
|
||
| pub const MAINNET_ID: u8 = 1; | ||
|
|
@@ -36,7 +39,8 @@ pub struct WellKnownConfig { | |
| pub min_deploy_points: u64, | ||
| pub min_deployment_gas_price: u64, | ||
| pub block_gas_limit: u64, | ||
| pub features: [(&'static str, FeatureActivation); 6], | ||
| pub min_tx_gas: u64, | ||
| pub features: [(&'static str, FeatureActivation); 7], | ||
| } | ||
|
|
||
| impl WellKnownConfig { | ||
|
|
@@ -79,6 +83,9 @@ static MAINNET_DISABLE_WASM_64: LazyLock<FeatureActivation> = | |
| const MAINNET_BLOB_ACTIVATION: FeatureActivation = | ||
| FeatureActivation::Height(MAINNET_AT_10_12_2025_AT_09_00_UTC); | ||
|
|
||
| const MAINNET_MIN_TX_GAS_ACTIVATION: FeatureActivation = | ||
|
||
| FeatureActivation::Height(3_060_210); | ||
|
|
||
| /// Mainnet VM configuration. | ||
| static MAINNET_CONFIG: LazyLock<WellKnownConfig> = | ||
| LazyLock::new(|| WellKnownConfig { | ||
|
|
@@ -87,34 +94,41 @@ static MAINNET_CONFIG: LazyLock<WellKnownConfig> = | |
| min_deploy_points: DEFAULT_MIN_DEPLOY_POINTS, | ||
| min_deployment_gas_price: DEFAULT_MIN_DEPLOYMENT_GAS_PRICE, | ||
| block_gas_limit: DEFAULT_BLOCK_GAS_LIMIT, | ||
| min_tx_gas: DEFAULT_MIN_TX_GAS, | ||
| features: [ | ||
| (FEATURE_ABI_PUBLIC_SENDER, MAINNET_SENDER_ACTIVATION_HEIGHT), | ||
| (HQ_KECCAK256, NEVER), | ||
| (FEATURE_BLOB, MAINNET_BLOB_ACTIVATION), | ||
| (FEATURE_DISABLE_WASM64, MAINNET_DISABLE_WASM_64.clone()), | ||
| (FEATURE_DISABLE_WASM32, MAINNET_3RD_PARTY_OFF.clone()), | ||
| (FEATURE_DISABLE_3RD_PARTY, MAINNET_3RD_PARTY_OFF.clone()), | ||
| (FEATURE_MIN_TX_GAS, MAINNET_MIN_TX_GAS_ACTIVATION), | ||
| ], | ||
| }); | ||
|
|
||
| /// Estimated testnet block height for 12th November 2025, 09:00 UTC. | ||
| const TESTNET_AT_12_11_2025_AT_09_00_UTC: FeatureActivation = | ||
| FeatureActivation::Height(1_814_090); | ||
|
|
||
| const TESTNET_MIN_TX_GAS_ACTIVATION: FeatureActivation = | ||
|
||
| FeatureActivation::Height(2_242_800); | ||
|
|
||
| /// Testnet VM configuration. | ||
| const TESTNET_CONFIG: WellKnownConfig = WellKnownConfig { | ||
| gas_per_blob: DEFAULT_GAS_PER_BLOB, | ||
| gas_per_deploy_byte: DEFAULT_GAS_PER_DEPLOY_BYTE, | ||
| min_deploy_points: DEFAULT_MIN_DEPLOY_POINTS, | ||
| min_deployment_gas_price: DEFAULT_MIN_DEPLOYMENT_GAS_PRICE, | ||
| block_gas_limit: DEFAULT_BLOCK_GAS_LIMIT, | ||
| min_tx_gas: DEFAULT_MIN_TX_GAS, | ||
| features: [ | ||
| (FEATURE_ABI_PUBLIC_SENDER, GENESIS), | ||
| (HQ_KECCAK256, NEVER), | ||
| (FEATURE_BLOB, TESTNET_AT_12_11_2025_AT_09_00_UTC), | ||
| (FEATURE_DISABLE_WASM64, TESTNET_AT_12_11_2025_AT_09_00_UTC), | ||
| (FEATURE_DISABLE_WASM32, NEVER), | ||
| (FEATURE_DISABLE_3RD_PARTY, NEVER), | ||
| (FEATURE_MIN_TX_GAS, TESTNET_MIN_TX_GAS_ACTIVATION), | ||
| ], | ||
| }; | ||
|
|
||
|
|
@@ -125,13 +139,15 @@ const DEVNET_CONFIG: WellKnownConfig = WellKnownConfig { | |
| min_deploy_points: DEFAULT_MIN_DEPLOY_POINTS, | ||
| min_deployment_gas_price: DEFAULT_MIN_DEPLOYMENT_GAS_PRICE, | ||
| block_gas_limit: DEFAULT_BLOCK_GAS_LIMIT, | ||
| min_tx_gas: DEFAULT_MIN_TX_GAS, | ||
| features: [ | ||
| (FEATURE_ABI_PUBLIC_SENDER, GENESIS), | ||
| (HQ_KECCAK256, GENESIS), | ||
| (FEATURE_BLOB, GENESIS), | ||
| (FEATURE_DISABLE_WASM64, GENESIS), | ||
| (FEATURE_DISABLE_WASM32, NEVER), | ||
| (FEATURE_DISABLE_3RD_PARTY, NEVER), | ||
| (FEATURE_MIN_TX_GAS, GENESIS), | ||
| ], | ||
| }; | ||
|
|
||
|
|
@@ -142,12 +158,14 @@ const LOCALNET_CONFIG: WellKnownConfig = WellKnownConfig { | |
| min_deploy_points: DEFAULT_MIN_DEPLOY_POINTS, | ||
| min_deployment_gas_price: DEFAULT_MIN_DEPLOYMENT_GAS_PRICE, | ||
| block_gas_limit: DEFAULT_BLOCK_GAS_LIMIT, | ||
| min_tx_gas: DEFAULT_MIN_TX_GAS, | ||
| features: [ | ||
| (FEATURE_ABI_PUBLIC_SENDER, GENESIS), | ||
| (HQ_KECCAK256, GENESIS), | ||
| (FEATURE_BLOB, GENESIS), | ||
| (FEATURE_DISABLE_WASM64, GENESIS), | ||
| (FEATURE_DISABLE_WASM32, NEVER), | ||
| (FEATURE_DISABLE_3RD_PARTY, NEVER), | ||
| (FEATURE_MIN_TX_GAS, GENESIS), | ||
| ], | ||
| }; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gas limit is not expressed in LUX