Skip to content

Commit

Permalink
Merge pull request #370 from dusk-network/price-imports
Browse files Browse the repository at this point in the history
Price event bytes at the same rate as storage
  • Loading branch information
Eduardo Leegwater Simões authored Jul 2, 2024
2 parents 2d32532 + b88c100 commit ac5c8b8
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 1 deletion.
16 changes: 16 additions & 0 deletions contracts/eventer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

#![no_std]

extern crate alloc;
use alloc::vec::Vec;

use piecrust_uplink as uplink;

/// Struct that describes the state of the eventer contract
Expand All @@ -23,10 +26,23 @@ impl Eventer {
uplink::emit("number", i);
}
}

pub fn emit_input(&mut self, input: Vec<u8>) -> (u64, u64) {
let spent_before = uplink::spent();
uplink::emit("input", input);
let spent_after = uplink::spent();
(spent_before, spent_after)
}
}

/// Expose `Eventer::emit_num()` to the host
#[no_mangle]
unsafe fn emit_events(arg_len: u32) -> u32 {
uplink::wrap_call(arg_len, |num| STATE.emit_num(num))
}

/// Expose `Eventer::emit_input()` to the host
#[no_mangle]
unsafe fn emit_input(arg_len: u32) -> u32 {
uplink::wrap_call(arg_len, |input| STATE.emit_input(input))
}
4 changes: 4 additions & 0 deletions piecrust/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed

- Make each event byte cost the same as a storage byte [#359]

### Fixed

- Fix incomplete removal of economic protocol functionality
Expand Down
8 changes: 8 additions & 0 deletions piecrust/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) DUSK NETWORK. All rights reserved.

// The gas cost for each byte
pub const BYTE_STORE_COST: i64 = 4;
11 changes: 11 additions & 0 deletions piecrust/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use piecrust_uplink::{
ContractError, ContractId, ARGBUF_LEN, CONTRACT_ID_BYTES,
};

use crate::config::BYTE_STORE_COST;
use crate::instance::{Env, WrappedInstance};
use crate::Error;

Expand Down Expand Up @@ -324,6 +325,16 @@ pub(crate) fn emit(
check_ptr(instance, topic_ofs, topic_len)?;
check_arg(instance, arg_len)?;

// charge for each byte emitted in an event
let gas_remaining = instance.get_remaining_gas();
let gas_cost = BYTE_STORE_COST as u64 * (topic_len as u64 + arg_len as u64);

if gas_cost > gas_remaining {
instance.set_remaining_gas(0);
Err(Error::OutOfGas)?;
}
instance.set_remaining_gas(gas_remaining - gas_cost);

let data = instance.with_arg_buf(|buf| {
let arg_len = arg_len as usize;
Vec::from(&buf[..arg_len])
Expand Down
1 change: 1 addition & 0 deletions piecrust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
#[macro_use]
mod bytecode_macro;
mod call_tree;
mod config;
mod contract;
mod error;
mod imports;
Expand Down
2 changes: 1 addition & 1 deletion piecrust/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use dusk_wasmtime::{
};
use tempfile::tempdir;

use crate::config::BYTE_STORE_COST;
use crate::session::{Session, SessionData};
use crate::store::ContractStore;
use crate::Error::{self, PersistenceError};
Expand Down Expand Up @@ -58,7 +59,6 @@ fn config() -> Config {
// Support 64-bit memories
config.wasm_memory64(true);

const BYTE_STORE_COST: i64 = 4;
const BYTE4_STORE_COST: i64 = 4 * BYTE_STORE_COST;
const BYTE8_STORE_COST: i64 = 8 * BYTE_STORE_COST;
const BYTE16_STORE_COST: i64 = 16 * BYTE_STORE_COST;
Expand Down
52 changes: 52 additions & 0 deletions piecrust/tests/eventer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,55 @@ pub fn vm_center_events() -> Result<(), Error> {

Ok(())
}

#[test]
pub fn event_costs() -> Result<(), Error> {
let vm = VM::ephemeral()?;

let mut session = vm.session(SessionData::builder())?;

let eventer_id = session.deploy(
contract_bytecode!("eventer"),
ContractData::builder().owner(OWNER),
LIMIT,
)?;

// This call is to "prime" the contract
let _ = session.call::<_, (u64, u64)>(
eventer_id,
"emit_input",
&vec![1u8; 100],
LIMIT,
)?;

let mut costs = vec![];

for size in (4..=40).step_by(4) {
let input = vec![1u8; size];
let (spent_before, spent_after) = session
.call::<_, (u64, u64)>(eventer_id, "emit_input", &input, LIMIT)?
.data;
let cost = spent_after - spent_before;
print!("{cost} ");
costs.push(cost);
}

// cost grows linearly with the amount of bytes processed, at a predictable
// rate.
//
// NOTE: it is not possible to directly test emission costs, unless this is
// externally configurable
let mut cost_diffs = Vec::with_capacity(costs.len() - 1);
for i in 0..costs.len() - 1 {
cost_diffs.push(costs[i + 1] - costs[i]);
}
let (ref_cost_diff, cost_diffs) = cost_diffs.split_first().unwrap();
for cost_diff in cost_diffs {
assert_eq!(
cost_diff, ref_cost_diff,
"cost should grow at a linear rate"
);
}

Ok(())
}

0 comments on commit ac5c8b8

Please sign in to comment.