diff --git a/rusk/CHANGELOG.md b/rusk/CHANGELOG.md index 9f199491be..40b7d79493 100644 --- a/rusk/CHANGELOG.md +++ b/rusk/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Allow state transitions to be executed in parallel with queries [#970] - Change dependencies declarations enforce bytecheck [#1371] - Fixed tests passing incorrect arguments [#1371] +- Adjusted deployment charging [#2207] ### Added @@ -211,6 +212,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add linking between Rusk and Protobuff structs - Add build system that generates keys for circuits and caches them. +[#2207]: https://github.com/dusk-network/rusk/issues/2207 [#1884]: https://github.com/dusk-network/rusk/issues/1884 [#1882]: https://github.com/dusk-network/rusk/issues/1882 [#1675]: https://github.com/dusk-network/rusk/issues/1675 diff --git a/rusk/src/bin/config/chain.rs b/rusk/src/bin/config/chain.rs index fff953373b..e9a8416552 100644 --- a/rusk/src/bin/config/chain.rs +++ b/rusk/src/bin/config/chain.rs @@ -24,9 +24,9 @@ pub(crate) struct ChainConfig { max_queue_size: Option, - // NB: changing the gas_per_deploy_byte/block_gas_limit is equivalent to + // NB: changing the charge_per_deploy_byte/block_gas_limit is equivalent to // forking the chain. - gas_per_deploy_byte: Option, + charge_per_deploy_byte: Option, block_gas_limit: Option, } @@ -75,8 +75,8 @@ impl ChainConfig { self.generation_timeout } - pub(crate) fn gas_per_deploy_byte(&self) -> Option { - self.gas_per_deploy_byte + pub(crate) fn charge_per_deploy_byte(&self) -> Option { + self.charge_per_deploy_byte } pub(crate) fn max_queue_size(&self) -> usize { diff --git a/rusk/src/bin/main.rs b/rusk/src/bin/main.rs index 9a913b7408..cd85d0862c 100644 --- a/rusk/src/bin/main.rs +++ b/rusk/src/bin/main.rs @@ -66,7 +66,7 @@ async fn main() -> Result<(), Box> { state_dir, config.kadcast.chain_id(), config.chain.generation_timeout(), - config.chain.gas_per_deploy_byte(), + config.chain.charge_per_deploy_byte(), config.chain.block_gas_limit(), config.http.feeder_call_gas, _event_sender.clone(), diff --git a/rusk/src/lib/node.rs b/rusk/src/lib/node.rs index df4daeba3d..9b878639cd 100644 --- a/rusk/src/lib/node.rs +++ b/rusk/src/lib/node.rs @@ -44,7 +44,7 @@ pub struct Rusk { dir: PathBuf, pub(crate) chain_id: u8, pub(crate) generation_timeout: Option, - pub(crate) gas_per_deploy_byte: Option, + pub(crate) charge_per_deploy_byte: Option, pub(crate) feeder_gas_limit: u64, pub(crate) block_gas_limit: u64, pub(crate) event_sender: broadcast::Sender, diff --git a/rusk/src/lib/node/rusk.rs b/rusk/src/lib/node/rusk.rs index 39e3095c1b..40ea9c80b3 100644 --- a/rusk/src/lib/node/rusk.rs +++ b/rusk/src/lib/node/rusk.rs @@ -4,6 +4,7 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. +use std::cmp::max; use std::path::Path; use std::sync::{mpsc, Arc, LazyLock}; use std::time::{Duration, Instant}; @@ -49,14 +50,14 @@ pub static DUSK_KEY: LazyLock = LazyLock::new(|| { .expect("Dusk consensus public key to be valid") }); -const DEFAULT_GAS_PER_DEPLOY_BYTE: u64 = 100; +const DEFAULT_CHARGE_PER_DEPLOY_BYTE: u64 = 200000; impl Rusk { pub fn new>( dir: P, chain_id: u8, generation_timeout: Option, - gas_per_deploy_byte: Option, + charge_per_deploy_byte: Option, block_gas_limit: u64, feeder_gas_limit: u64, event_sender: broadcast::Sender, @@ -91,7 +92,7 @@ impl Rusk { dir: dir.into(), chain_id, generation_timeout, - gas_per_deploy_byte, + charge_per_deploy_byte, feeder_gas_limit, event_sender, block_gas_limit, @@ -140,7 +141,7 @@ impl Rusk { match execute( &mut session, &unspent_tx.inner, - self.gas_per_deploy_byte, + self.charge_per_deploy_byte, ) { Ok(receipt) => { let gas_spent = receipt.gas_spent; @@ -158,7 +159,7 @@ impl Rusk { let _ = execute( &mut session, &spent_tx.inner.inner, - self.gas_per_deploy_byte, + self.charge_per_deploy_byte, ); } @@ -243,7 +244,7 @@ impl Rusk { txs, slashing, voters, - self.gas_per_deploy_byte, + self.charge_per_deploy_byte, ) .map(|(a, b, _, _)| (a, b)) } @@ -274,7 +275,7 @@ impl Rusk { &txs[..], slashing, voters, - self.gas_per_deploy_byte, + self.charge_per_deploy_byte, )?; if let Some(expected_verification) = consistency_check { @@ -466,7 +467,7 @@ fn accept( txs: &[Transaction], slashing: Vec, voters: Option<&[Voter]>, - gas_per_deploy_byte: Option, + charge_per_deploy_byte: Option, ) -> Result<( Vec, VerificationOutput, @@ -485,7 +486,7 @@ fn accept( for unspent_tx in txs { let tx = &unspent_tx.inner; - let receipt = execute(&mut session, tx, gas_per_deploy_byte)?; + let receipt = execute(&mut session, tx, charge_per_deploy_byte)?; update_hasher(&mut event_hasher, &receipt.events); events.extend(receipt.events); @@ -532,13 +533,17 @@ fn accept( )) } -// Returns gas charge for bytecode deployment. +// Returns (economic) charge and gas charge for a given bytecode deployment. fn bytecode_charge( bytecode: &ContractBytecode, - gas_per_deploy_byte: &Option, -) -> u64 { - bytecode.bytes.len() as u64 - * gas_per_deploy_byte.unwrap_or(DEFAULT_GAS_PER_DEPLOY_BYTE) + charge_per_deploy_byte: &Option, + gas_price: u64, +) -> (u64, u64) { + let charge = bytecode.bytes.len() as u64 + * charge_per_deploy_byte.unwrap_or(DEFAULT_CHARGE_PER_DEPLOY_BYTE); + assert_ne!(gas_price, 0); + let gas_charge = max(charge / gas_price, 1); + (charge, gas_charge) } // Contract deployment will fail and charge full gas limit in the @@ -554,11 +559,13 @@ fn contract_deploy( session: &mut Session, deploy: &ContractDeploy, gas_limit: u64, - gas_per_deploy_byte: Option, + gas_price: u64, + charge_per_deploy_byte: Option, receipt: &mut CallReceipt, ContractError>>, ) { - let deploy_charge = bytecode_charge(&deploy.bytecode, &gas_per_deploy_byte); - let min_gas_limit = receipt.gas_spent + deploy_charge; + let (_, deploy_gas_charge) = + bytecode_charge(&deploy.bytecode, &charge_per_deploy_byte, gas_price); + let min_gas_limit = receipt.gas_spent + deploy_gas_charge; let hash = blake3::hash(deploy.bytecode.bytes.as_slice()); if gas_limit < min_gas_limit { receipt.data = Err(ContractError::OutOfGas); @@ -578,7 +585,7 @@ fn contract_deploy( gas_limit - receipt.gas_spent, ); match result { - Ok(_) => receipt.gas_spent += deploy_charge, + Ok(_) => receipt.gas_spent += deploy_gas_charge, Err(err) => { info!("Tx caused deployment error {err:?}"); receipt.data = @@ -624,14 +631,17 @@ fn contract_deploy( fn execute( session: &mut Session, tx: &ProtocolTransaction, - gas_per_deploy_byte: Option, + charge_per_deploy_byte: Option, ) -> Result, ContractError>>, PiecrustError> { // Transaction will be discarded if it is a deployment transaction // with gas limit smaller than deploy charge. if let Some(deploy) = tx.deploy() { - let deploy_charge = - bytecode_charge(&deploy.bytecode, &gas_per_deploy_byte); - if tx.gas_limit() < deploy_charge { + let (deploy_charge, _) = bytecode_charge( + &deploy.bytecode, + &charge_per_deploy_byte, + tx.gas_price(), + ); + if tx.gas_limit() * tx.gas_price() < deploy_charge { return Err(PiecrustError::Panic( "not enough gas to deploy".into(), )); @@ -655,7 +665,8 @@ fn execute( session, deploy, tx.gas_limit(), - gas_per_deploy_byte, + tx.gas_price(), + charge_per_deploy_byte, &mut receipt, ); }