Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(gstd, backend): Introduce gr_env_vars sys-call #3403

Merged
merged 20 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions core-backend/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ where
{
#[rustfmt::skip]
fn bind_funcs(builder: &mut EnvBuilder<Ext>) {
builder.add_func(ExecSettings, wrap_common_func!(FuncsHandler::exec_settings, (3) -> ()));
builder.add_func(BlockHeight, wrap_common_func!(FuncsHandler::block_height, (2) -> ()));
builder.add_func(BlockTimestamp,wrap_common_func!(FuncsHandler::block_timestamp, (2) -> ()));
builder.add_func(CreateProgram, wrap_common_func!(FuncsHandler::create_program, (8) -> ()));
Expand Down
2 changes: 2 additions & 0 deletions core-backend/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ pub enum UnrecoverableExecutionError {
TooBigReadLen,
#[display(fmt = "Cannot take data in payload range from message with size")]
ReadWrongRange,
#[display(fmt = "Unexpected version of execution settings encountered ")]
UnexpectedExecSettingsVersion,
ark0f marked this conversation as resolved.
Show resolved Hide resolved
DennisInSky marked this conversation as resolved.
Show resolved Hide resolved
}

/// Memory error in infallible sys-call.
Expand Down
16 changes: 16 additions & 0 deletions core-backend/src/funcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,22 @@ where
Ok(res.is_err() as i32)
}

#[host(cost = RuntimeCosts::ExecSettings)]
pub fn exec_settings(
ctx: &mut CallerWrap<'_, '_, Ext>,
gas: u64,
settings_ver: u32,
settings_ptr: u32,
) -> Result<(u64, ()), HostError> {
let settings = ctx.ext_mut().exec_settings(settings_ver)?;
let settings_bytes = settings.to_bytes();
let settings_write = ctx
.manager
.register_write(settings_ptr, settings_bytes.len() as u32);
ctx.write(settings_write, settings_bytes)
.map_err(Into::into)
}

#[host(cost = RuntimeCosts::BlockHeight)]
pub fn block_height(
ctx: &mut CallerWrap<'_, '_, Ext>,
Expand Down
16 changes: 12 additions & 4 deletions core-backend/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ use core::{cell::Cell, fmt, fmt::Debug};
use gear_core::{
costs::RuntimeCosts,
env::{Externalities, PayloadSliceLock, UnlockPayloadBound},
exec_settings::{ExecSettings, ExecSettingsV1},
gas::{ChargeError, CounterType, CountersOwner, GasAmount, GasCounter, GasLeft},
ids::{MessageId, ProgramId, ReservationId},
memory::{Memory, MemoryError, MemoryInterval},
message::{HandlePacket, InitPacket, ReplyPacket},
pages::{PageNumber, PageU32Size, WasmPage, WASM_PAGE_SIZE},
percent::Percent,
};
use gear_core_errors::{ReplyCode, SignalCode};
use gear_lazy_pages_common::ProcessAccessError;
Expand Down Expand Up @@ -115,15 +115,23 @@ impl Externalities for MockExt {
fn free(&mut self, _page: WasmPage) -> Result<(), Self::AllocError> {
Err(Error)
}
fn exec_settings(&self, version: u32) -> Result<ExecSettings, Self::UnrecoverableError> {
match version {
1 => Ok(ExecSettings::V1(ExecSettingsV1 {
performance_multiplier_percent: 100,
existential_deposit: 10,
mailbox_threshold: 20,
gas_to_value_multiplier: 30,
})),
_ => unreachable!("Unexpected version of execution settings"),
}
}
fn block_height(&self) -> Result<u32, Self::UnrecoverableError> {
Ok(0)
}
fn block_timestamp(&self) -> Result<u64, Self::UnrecoverableError> {
Ok(0)
}
fn performance_multiplier(&self) -> Result<Percent, Self::UnrecoverableError> {
Ok(Percent::new(100))
}
fn send_init(&mut self) -> Result<u32, Self::UnrecoverableError> {
Ok(0)
}
Expand Down
4 changes: 4 additions & 0 deletions core-processor/src/configs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ pub struct ExecutionSettings {
pub random_data: (Vec<u8>, u32),
/// Rent cost per block.
pub rent_cost: u128,
/// Value per gas multiplier.
pub gas_to_value_multiplier: u128,
DennisInSky marked this conversation as resolved.
Show resolved Hide resolved
}

/// Stable parameters for the whole block across processing runs.
Expand Down Expand Up @@ -221,4 +223,6 @@ pub struct BlockConfig {
pub code_instrumentation_byte_cost: u64,
/// Rent cost per block.
pub rent_cost: u128,
/// Value per gas multiplier.
pub gas_to_value_multiplier: u128,
}
2 changes: 2 additions & 0 deletions core-processor/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ where
reservation: settings.reservation,
random_data: settings.random_data,
rent_cost: settings.rent_cost,
gas_to_value_multiplier: settings.gas_to_value_multiplier,
};

let lazy_pages_weights = context.page_costs.lazy_pages_weights();
Expand Down Expand Up @@ -418,6 +419,7 @@ where
random_data: Default::default(),
system_reservation: Default::default(),
rent_cost: Default::default(),
gas_to_value_multiplier: Default::default(),
};

let lazy_pages_weights = context.page_costs.lazy_pages_weights();
Expand Down
20 changes: 16 additions & 4 deletions core-processor/src/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use alloc::{
use gear_core::{
costs::{HostFnWeights, RuntimeCosts},
env::{Externalities, PayloadSliceLock, UnlockPayloadBound},
exec_settings::{ExecSettings, ExecSettingsV1},
gas::{
ChargeError, ChargeResult, CounterType, CountersOwner, GasAllowanceCounter, GasAmount,
GasCounter, GasLeft, Token, ValueCounter,
Expand Down Expand Up @@ -109,6 +110,8 @@ pub struct ProcessorContext {
pub random_data: (Vec<u8>, u32),
/// Rent cost per block.
pub rent_cost: u128,
/// Gas to value multiplier.
pub gas_to_value_multiplier: u128,
}

#[cfg(any(feature = "mock", test))]
Expand Down Expand Up @@ -154,6 +157,7 @@ impl ProcessorContext {
reservation: 0,
random_data: ([0u8; 32].to_vec(), 0),
rent_cost: 0,
gas_to_value_multiplier: Default::default(),
}
}
}
Expand Down Expand Up @@ -721,6 +725,18 @@ impl Externalities for Ext {
.map_err(Into::into)
}

fn exec_settings(&self, version: u32) -> Result<ExecSettings, Self::UnrecoverableError> {
match version {
1 => Ok(ExecSettings::V1(ExecSettingsV1 {
performance_multiplier_percent: self.context.performance_multiplier.value(),
DennisInSky marked this conversation as resolved.
Show resolved Hide resolved
existential_deposit: self.context.existential_deposit,
mailbox_threshold: self.context.mailbox_threshold,
gas_to_value_multiplier: self.context.gas_to_value_multiplier,
})),
_ => Err(UnrecoverableExecutionError::UnexpectedExecSettingsVersion.into()),
}
}

fn block_height(&self) -> Result<u32, Self::UnrecoverableError> {
Ok(self.context.block_info.height)
}
Expand All @@ -729,10 +745,6 @@ impl Externalities for Ext {
Ok(self.context.block_info.timestamp)
}

fn performance_multiplier(&self) -> Result<Percent, Self::UnrecoverableError> {
Ok(self.context.performance_multiplier)
}

fn send_init(&mut self) -> Result<u32, Self::FallibleError> {
let handle = self.context.message_context.send_init()?;
Ok(handle)
Expand Down
2 changes: 2 additions & 0 deletions core-processor/src/processing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ where
reservation,
write_cost,
rent_cost,
gas_to_value_multiplier,
..
} = block_config.clone();

Expand All @@ -89,6 +90,7 @@ where
reservation,
random_data,
rent_cost,
gas_to_value_multiplier,
};

let dispatch = execution_context.dispatch;
Expand Down
1 change: 1 addition & 0 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ repository.workspace = true

[dependencies]
gear-core-errors = { workspace = true, features = ["codec"] }
gsys.workspace = true
blake2-rfc.workspace = true
parity-scale-codec = { workspace = true, features = ["derive", "max-encoded-len"] }
scale-info = { workspace = true, features = ["derive"] }
Expand Down
6 changes: 6 additions & 0 deletions core/src/costs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ pub struct HostFnWeights {
/// Weight per payload byte by `gr_read`.
pub gr_read_per_byte: u64,

/// Weight of calling `gr_exec_settings`.
pub gr_exec_settings: u64,

/// Weight of calling `gr_block_height`.
pub gr_block_height: u64,

Expand Down Expand Up @@ -349,6 +352,8 @@ pub enum RuntimeCosts {
Read,
/// Weight of calling `gr_read` per read buffer bytes number.
ReadPerByte(u32),
/// Weight of calling `gr_exec_settings`.
ExecSettings,
/// Weight of calling `gr_block_height`.
BlockHeight,
/// Weight of calling `gr_block_timestamp`.
Expand Down Expand Up @@ -475,6 +480,7 @@ impl RuntimeCosts {
Size => s.gr_size,
Read => s.gr_read,
ReadPerByte(len) => cost_per_byte(s.gr_read_per_byte, len),
ExecSettings => s.gr_exec_settings,
BlockHeight => s.gr_block_height,
BlockTimestamp => s.gr_block_timestamp,
Random => s.gr_random,
Expand Down
9 changes: 5 additions & 4 deletions core/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@
//! Environment for running a module.

use crate::{
exec_settings::ExecSettings,
ids::{MessageId, ProgramId, ReservationId},
memory::Memory,
message::{HandlePacket, InitPacket, MessageContext, Payload, ReplyPacket},
pages::WasmPage,
percent::Percent,
};
use alloc::collections::BTreeSet;
use core::{fmt::Display, mem};
Expand Down Expand Up @@ -198,15 +198,16 @@ pub trait Externalities {
/// should be `free`-d separately.
fn free(&mut self, page: WasmPage) -> Result<(), Self::AllocError>;

/// Get execution settings currently set in the system and in the form
/// corresponded to the requested version.
fn exec_settings(&self, version: u32) -> Result<ExecSettings, Self::UnrecoverableError>;

/// Get the current block height.
fn block_height(&self) -> Result<u32, Self::UnrecoverableError>;

/// Get the current block timestamp.
fn block_timestamp(&self) -> Result<u64, Self::UnrecoverableError>;

/// Get current performance multiplier.
fn performance_multiplier(&self) -> Result<Percent, Self::UnrecoverableError>;

/// Initialize a new incomplete message for another program and return its handle.
fn send_init(&mut self) -> Result<u32, Self::FallibleError>;

Expand Down
43 changes: 43 additions & 0 deletions core/src/exec_settings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// This file is part of Gear.

// Copyright (C) 2021-2023 Gear Technologies Inc.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

//! Execution settings

use core::{mem, slice};
pub use gsys::ExecSettings as ExecSettingsV1;

/// All supported versions of execution settings
pub enum ExecSettings {
/// Values of execution settings V1
// When a new version is introduced in gsys, the previous version should be
// copied here as ExecSettingsV1 whereas the most recent version should be bound
// to the variant corresponding to it
V1(ExecSettingsV1),
}

impl ExecSettings {
/// Returns byte representation of execution settings
pub fn to_bytes(&self) -> &[u8] {
match self {
ExecSettings::V1(v1) => {
let ptr = v1 as *const ExecSettingsV1 as *const u8;
unsafe { slice::from_raw_parts(ptr, mem::size_of::<ExecSettingsV1>()) }
}
}
}
}
1 change: 1 addition & 0 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ extern crate alloc;
pub mod code;
pub mod costs;
pub mod env;
pub mod exec_settings;
pub mod gas;
pub mod ids;
pub mod memory;
Expand Down
2 changes: 1 addition & 1 deletion core/src/percent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl Percent {
Self(value)
}

/// Returns the inner `u16` value.
/// Returns the inner `u32` value.
pub fn value(self) -> u32 {
self.0
}
Expand Down
9 changes: 9 additions & 0 deletions examples/sys-calls/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ pub use code::WASM_BINARY_OPT as WASM_BINARY;

type MessageId = [u8; 32];
type ActorId = [u8; 32];
type Value = u128;
type Gas = u64;

// Instead of proper gstd primitives we use their raw versions to make this contract
// compilable as a dependency for the build of the `gear` with `runtime-benchmarking` feature.
Expand Down Expand Up @@ -76,6 +78,13 @@ pub enum Kind {
ReplyDetails(MessageId, [u8; 4]),
SignalDetails,
SignalDetailsWake,
// Expected values
ExecSettings {
performance_multiplier: u32,
existential_deposit: Value,
mailbox_threshold: Gas,
gas_to_value_multiplier: Value,
},
// Expected(block height)
BlockHeight(u32),
// Expected(block timestamp)
Expand Down
28 changes: 28 additions & 0 deletions examples/sys-calls/src/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,34 @@ fn process(syscall_kind: Kind) {
Kind::SignalDetailsWake => {
panic!("must be called in handle_reply");
}
Kind::ExecSettings {
performance_multiplier: expected_performance_multiplier_percent,
existential_deposit: expected_existential_deposit,
mailbox_threshold: expected_mailbox_threshold,
gas_to_value_multiplier: expected_gas_to_value_multiplier,
} => {
let settings = exec::settings();
let actual_performance_multiplier_percent = settings.performance_multiplier_percent;
assert_eq!(
actual_performance_multiplier_percent, expected_performance_multiplier_percent,
"Kind::ExecSettings: performance_multiplier test failed"
);
let actual_existential_deposit = settings.existential_deposit;
assert_eq!(
actual_existential_deposit, expected_existential_deposit,
"Kind::ExecSettings: existential_deposit test failed"
);
let actual_mailbox_threshold = settings.mailbox_threshold;
assert_eq!(
actual_mailbox_threshold, expected_mailbox_threshold,
"Kind::ExecSettings: mailbox_threshold test failed"
);
let actual_gas_to_value_multiplier = settings.gas_to_value_multiplier;
assert_eq!(
actual_gas_to_value_multiplier, expected_gas_to_value_multiplier,
"Kind::ExecSettings: gas_to_value_multiplier test failed"
);
}
Kind::BlockHeight(expected_height) => {
let actual_height = exec::block_height();
assert_eq!(
Expand Down
Loading