Skip to content

Commit

Permalink
Add gas cost
Browse files Browse the repository at this point in the history
  • Loading branch information
chipshort committed Jan 29, 2025
1 parent 3d4e9ca commit d6143b0
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 48 deletions.
56 changes: 56 additions & 0 deletions packages/vm/src/environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ pub struct GasConfig {
pub ed25519_batch_verify_cost: u64,
/// ed25519 batch signature verification cost (single public key)
pub ed25519_batch_verify_one_pubkey_cost: u64,
/// cost for reading memory regions <= 8MB
pub read_region_small_cost: LinearGasCost,
/// cost for reading memory regions > 8MB
pub read_region_large_cost: LinearGasCost,
/// cost for validating bytes into a String
pub string_from_bytes_cost: LinearGasCost,
/// cost for calling a host function
pub host_call_cost: u64,
}

impl Default for GasConfig {
Expand All @@ -58,10 +66,58 @@ impl Default for GasConfig {
// From https://docs.rs/ed25519-zebra/2.2.0/ed25519_zebra/batch/index.html
ed25519_batch_verify_cost: 63 * GAS_PER_US / 2,
ed25519_batch_verify_one_pubkey_cost: 63 * GAS_PER_US / 4,
read_region_small_cost: LinearGasCost {
base: 200000,
per_item: 115,
},
read_region_large_cost: LinearGasCost {
base: 0,
per_item: 520,
},
string_from_bytes_cost: LinearGasCost {
base: 28700,
per_item: 1400,
},
host_call_cost: 18000,
}
}
}

impl GasConfig {
pub fn read_region_cost(&self, bytes: usize) -> VmResult<u64> {
const THRESHOLD: usize = 8 * 1000 * 1000;
if bytes <= THRESHOLD {
self.read_region_small_cost.total_cost(bytes as u64)
} else {
self.read_region_large_cost.total_cost(bytes as u64)
}
}
}

/// Linear gas cost model where the cost is linear in the number of items.
///
/// To calculate it, you sample the cost for a few different amounts of items and fit a line to it.
/// Let `b` be that line of best fit. Then `base = b(0)` is the y-intercept and
/// `per_item = b(1) - b(0)` the slope.
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct LinearGasCost {
/// This is a flat part of the cost, charged once per batch.
base: u64,
/// This is the cost per item in the batch.
per_item: u64,
}

impl LinearGasCost {
pub fn total_cost(&self, items: u64) -> VmResult<u64> {
self.total_cost_opt(items)
.ok_or_else(VmError::gas_depletion)
}

fn total_cost_opt(&self, items: u64) -> Option<u64> {
self.base.checked_add(self.per_item.checked_mul(items)?)
}
}

/** context data **/

#[derive(Clone, PartialEq, Eq, Debug, Default)]
Expand Down
Loading

0 comments on commit d6143b0

Please sign in to comment.