Skip to content

Commit

Permalink
rusk: gas_per_deploy_byte configuration parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
miloszm committed Jul 18, 2024
1 parent b566a14 commit 7208f91
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 14 deletions.
2 changes: 2 additions & 0 deletions rusk/default.config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#db_path = '/home/user/.dusk/rusk'
#consensus_keys_path = '/home/user/.dusk/rusk/consensus.keys'
#generation_timeout = '3s'
# Note: changing the gas per deploy byte parameter is equivalent to forking the chain.
#gas_per_deploy_byte = 100

[databroker]
max_inv_entries = 100
Expand Down
7 changes: 7 additions & 0 deletions rusk/src/bin/config/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ pub(crate) struct ChainConfig {
consensus_keys_path: Option<PathBuf>,
#[serde(with = "humantime_serde")]
generation_timeout: Option<Duration>,
// Note: changing the gas per deploy byte parameter is equivalent to
// forking the chain.
gas_per_deploy_byte: Option<u64>,
}

impl ChainConfig {
Expand Down Expand Up @@ -65,4 +68,8 @@ impl ChainConfig {
pub(crate) fn generation_timeout(&self) -> Option<Duration> {
self.generation_timeout
}

pub(crate) fn gas_per_deploy_byte(&self) -> Option<u64> {
self.gas_per_deploy_byte
}
}
1 change: 1 addition & 0 deletions rusk/src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let rusk = Rusk::new(
state_dir,
config.chain.generation_timeout(),
config.chain.gas_per_deploy_byte(),
config.http.feeder_call_gas,
_event_sender,
)?;
Expand Down
1 change: 1 addition & 0 deletions rusk/src/lib/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub struct Rusk {
pub(crate) vm: Arc<VM>,
dir: PathBuf,
pub(crate) generation_timeout: Option<Duration>,
pub(crate) gas_per_deploy_byte: Option<u64>,
pub(crate) feeder_gas_limit: u64,
pub(crate) event_sender: broadcast::Sender<RuesEvent>,
}
Expand Down
47 changes: 35 additions & 12 deletions rusk/src/lib/chain/rusk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use dusk_bytes::{DeserializableSlice, Serializable};
use dusk_consensus::operations::{
CallParams, VerificationOutput, VoterWithCredits,
};
use execution_core::bytecode::Bytecode;
use execution_core::{
stake::StakeData, transfer::Transaction as PhoenixTransaction, BlsScalar,
StakePublicKey,
Expand All @@ -43,12 +44,13 @@ pub static DUSK_KEY: LazyLock<StakePublicKey> = LazyLock::new(|| {
.expect("Dusk consensus public key to be valid")
});

const GAS_PER_DEPLOY_BYTE: u64 = 100;
const DEFAULT_GAS_PER_DEPLOY_BYTE: u64 = 100;

impl Rusk {
pub fn new<P: AsRef<Path>>(
dir: P,
generation_timeout: Option<Duration>,
gas_per_deploy_byte: Option<u64>,
feeder_gas_limit: u64,
event_sender: broadcast::Sender<RuesEvent>,
) -> Result<Self> {
Expand Down Expand Up @@ -81,6 +83,7 @@ impl Rusk {
vm,
dir: dir.into(),
generation_timeout,
gas_per_deploy_byte,
feeder_gas_limit,
event_sender,
})
Expand Down Expand Up @@ -124,7 +127,11 @@ impl Rusk {
continue;
}

match execute(&mut session, &unspent_tx.inner) {
match execute(
&mut session,
&unspent_tx.inner,
self.gas_per_deploy_byte,
) {
Ok(receipt) => {
let gas_spent = receipt.gas_spent;

Expand All @@ -138,8 +145,11 @@ impl Rusk {
for spent_tx in &spent_txs {
// We know these transactions were correctly
// executed before, so we don't bother checking.
let _ =
execute(&mut session, &spent_tx.inner.inner);
let _ = execute(
&mut session,
&spent_tx.inner.inner,
self.gas_per_deploy_byte,
);
}

continue;
Expand Down Expand Up @@ -213,6 +223,7 @@ impl Rusk {
txs,
missed_generators,
voters,
self.gas_per_deploy_byte,
)
.map(|(a, b, _, _)| (a, b))
}
Expand Down Expand Up @@ -243,6 +254,7 @@ impl Rusk {
&txs[..],
missed_generators,
voters,
self.gas_per_deploy_byte,
)?;

if let Some(expected_verification) = consistency_check {
Expand Down Expand Up @@ -418,6 +430,7 @@ fn accept(
txs: &[Transaction],
missed_generators: &[StakePublicKey],
voters: Option<&[VoterWithCredits]>,
gas_per_deploy_byte: Option<u64>,
) -> Result<(
Vec<SpentTransaction>,
VerificationOutput,
Expand All @@ -436,7 +449,7 @@ fn accept(

for unspent_tx in txs {
let tx = &unspent_tx.inner;
let receipt = execute(&mut session, tx)?;
let receipt = execute(&mut session, tx, gas_per_deploy_byte)?;

update_hasher(&mut event_hasher, &receipt.events);
events.extend(receipt.events);
Expand Down Expand Up @@ -483,6 +496,15 @@ fn accept(
))
}

// Returns gas charge for bytecode deployment.
fn bytecode_charge(
bytecode: &Bytecode,
gas_per_deploy_byte: &Option<u64>,
) -> u64 {
bytecode.bytes.len() as u64
* gas_per_deploy_byte.unwrap_or(DEFAULT_GAS_PER_DEPLOY_BYTE)
}

/// Executes a transaction, returning the receipt of the call and the gas spent.
/// The following steps are performed:
///
Expand All @@ -497,11 +519,12 @@ fn accept(
fn execute(
session: &mut Session,
tx: &PhoenixTransaction,
gas_per_deploy_byte: Option<u64>,
) -> Result<CallReceipt<Result<Vec<u8>, ContractError>>, PiecrustError> {
if let Some(deploy) = tx.payload().contract_deploy() {
let bytecode_charge =
deploy.bytecode.bytes.len() as u64 * GAS_PER_DEPLOY_BYTE;
if tx.payload().fee.gas_limit < bytecode_charge {
let deploy_charge =
bytecode_charge(&deploy.bytecode, &gas_per_deploy_byte);
if tx.payload().fee.gas_limit < deploy_charge {
return Err(PiecrustError::Panic(
"not enough gas to deploy".into(),
));
Expand All @@ -521,9 +544,9 @@ fn execute(
// Deploy if this is a deployment transaction
if let Some(deploy) = tx.payload().contract_deploy() {
if receipt.data.is_ok() {
let bytecode_charge =
deploy.bytecode.bytes.len() as u64 * GAS_PER_DEPLOY_BYTE;
let min_gas_limit = receipt.gas_spent + bytecode_charge;
let deploy_charge =
bytecode_charge(&deploy.bytecode, &gas_per_deploy_byte);
let min_gas_limit = receipt.gas_spent + deploy_charge;
let hash = blake3::hash(deploy.bytecode.bytes.as_slice());
if tx.payload().fee.gas_limit < min_gas_limit {
receipt.data = Err(OutOfGas);
Expand All @@ -539,7 +562,7 @@ fn execute(
);
match result {
Ok(_) => {
receipt.gas_spent += bytecode_charge;
receipt.gas_spent += deploy_charge;
}
Err(err) => {
info!("Tx caused deployment error {err:?}");
Expand Down
2 changes: 1 addition & 1 deletion rusk/tests/common/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub fn new_state<P: AsRef<Path>>(dir: P, snapshot: &Snapshot) -> Result<Rusk> {

let (sender, _) = broadcast::channel(10);

let rusk = Rusk::new(dir, None, u64::MAX, sender)
let rusk = Rusk::new(dir, None, None, u64::MAX, sender)
.expect("Instantiating rusk should succeed");

assert_eq!(
Expand Down
2 changes: 1 addition & 1 deletion rusk/tests/services/contract_deployment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ fn initial_state<P: AsRef<Path>>(dir: P, deploy_bob: bool) -> Result<Rusk> {

let (sender, _) = broadcast::channel(10);

let rusk = Rusk::new(dir, None, u64::MAX, sender)
let rusk = Rusk::new(dir, None, None, u64::MAX, sender)
.expect("Instantiating rusk should succeed");
Ok(rusk)
}
Expand Down

0 comments on commit 7208f91

Please sign in to comment.