Skip to content

Commit d6143b0

Browse files
committed
Add gas cost
1 parent 3d4e9ca commit d6143b0

File tree

4 files changed

+180
-48
lines changed

4 files changed

+180
-48
lines changed

packages/vm/src/environment.rs

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

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

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

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

0 commit comments

Comments
 (0)