Skip to content

Commit 2b7f2fa

Browse files
committed
Add gas cost
1 parent dd5b03c commit 2b7f2fa

File tree

4 files changed

+179
-47
lines changed

4 files changed

+179
-47
lines changed

packages/vm/src/environment.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ pub struct GasConfig {
4040
pub ed25519_batch_verify_cost: u64,
4141
/// ed25519 batch signature verification cost (single public key)
4242
pub ed25519_batch_verify_one_pubkey_cost: u64,
43+
/// cost for reading memory regions <= 8MB
44+
pub read_region_small_cost: LinearGasCost,
45+
/// cost for reading memory regions > 8MB
46+
pub read_region_large_cost: LinearGasCost,
47+
/// cost for validating bytes into a String
48+
pub string_from_bytes_cost: LinearGasCost,
49+
/// cost for calling a host function
50+
pub host_call_cost: u64,
4351
}
4452

4553
impl Default for GasConfig {
@@ -57,10 +65,58 @@ impl Default for GasConfig {
5765
// From https://docs.rs/ed25519-zebra/2.2.0/ed25519_zebra/batch/index.html
5866
ed25519_batch_verify_cost: 63 * GAS_PER_US / 2,
5967
ed25519_batch_verify_one_pubkey_cost: 63 * GAS_PER_US / 4,
68+
read_region_small_cost: LinearGasCost {
69+
base: 200000,
70+
per_item: 115,
71+
},
72+
read_region_large_cost: LinearGasCost {
73+
base: 0,
74+
per_item: 520,
75+
},
76+
string_from_bytes_cost: LinearGasCost {
77+
base: 28700,
78+
per_item: 1400,
79+
},
80+
host_call_cost: 18000,
81+
}
82+
}
83+
}
84+
85+
impl GasConfig {
86+
pub fn read_region_cost(&self, bytes: usize) -> VmResult<u64> {
87+
const THRESHOLD: usize = 8 * 1000 * 1000;
88+
if bytes <= THRESHOLD {
89+
self.read_region_small_cost.total_cost(bytes as u64)
90+
} else {
91+
self.read_region_large_cost.total_cost(bytes as u64)
6092
}
6193
}
6294
}
6395

96+
/// Linear gas cost model where the cost is linear in the number of items.
97+
///
98+
/// To calculate it, you sample the cost for a few different amounts of items and fit a line to it.
99+
/// Let `b` be that line of best fit. Then `base = b(0)` is the y-intercept and
100+
/// `per_item = b(1) - b(0)` the slope.
101+
#[derive(Clone, PartialEq, Eq, Debug)]
102+
pub struct LinearGasCost {
103+
/// This is a flat part of the cost, charged once per batch.
104+
base: u64,
105+
/// This is the cost per item in the batch.
106+
per_item: u64,
107+
}
108+
109+
impl LinearGasCost {
110+
pub fn total_cost(&self, items: u64) -> VmResult<u64> {
111+
self.total_cost_opt(items)
112+
.ok_or_else(VmError::gas_depletion)
113+
}
114+
115+
fn total_cost_opt(&self, items: u64) -> Option<u64> {
116+
self.base.checked_add(self.per_item.checked_mul(items)?)
117+
}
118+
}
119+
64120
/** context data **/
65121

66122
#[derive(Clone, PartialEq, Eq, Debug, Default)]

0 commit comments

Comments
 (0)