Merge pull request #48 from vacp2p/Pravdyvy/gas-modeling

Gas Calculation Model
This commit is contained in:
Pravdyvy 2025-03-05 10:22:44 +02:00 committed by GitHub
commit 37ce873db8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 1160 additions and 461 deletions

1412
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,7 @@ serde_json.workspace = true
serde.workspace = true
reqwest.workspace = true
monotree.workspace = true
risc0-zkvm = { git = "https://github.com/risc0/risc0.git", branch = "release-1.2" }
risc0-zkvm = { git = "https://github.com/risc0/risc0.git", branch = "release-1.3" }
[dependencies.rpc_primitives]
path = "../rpc_primitives"

View File

@ -52,6 +52,10 @@ pub enum ExecutionFailureKind {
SequencerClientError(#[from] SequencerClientError),
#[error("Datebase returned error : {0:?}")]
MonoTreeError(#[from] monotree::Errors),
#[error("Insufficient gas for operation")]
InsufficientGasError,
#[error("Can not pay for operation")]
InsufficientFundsError,
}
impl ExecutionFailureKind {

View File

@ -19,7 +19,7 @@ reqwest.workspace = true
thiserror.workspace = true
tokio.workspace = true
tempfile.workspace = true
risc0-zkvm = { git = "https://github.com/risc0/risc0.git", branch = "release-1.2" }
risc0-zkvm = { git = "https://github.com/risc0/risc0.git", branch = "release-1.3" }
hex.workspace = true
actix-rt.workspace = true

View File

@ -1,6 +1,39 @@
use std::path::PathBuf;
use serde::{Deserialize, Serialize};
use zkvm::gas_calculator::GasCalculator;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GasConfig {
/// Gas spent per deploying one byte of data
pub gas_fee_per_byte_deploy: u64,
/// Gas spent per reading one byte of data in VM
pub gas_fee_per_input_buffer_runtime: u64,
/// Gas spent per one byte of contract data in runtime
pub gas_fee_per_byte_runtime: u64,
/// Cost of one gas of runtime in public balance
pub gas_cost_runtime: u64,
/// Cost of one gas of deployment in public balance
pub gas_cost_deploy: u64,
/// Gas limit for deployment
pub gas_limit_deploy: u64,
/// Gas limit for runtime
pub gas_limit_runtime: u64,
}
impl From<GasConfig> for zkvm::gas_calculator::GasCalculator {
fn from(value: GasConfig) -> Self {
GasCalculator::new(
value.gas_fee_per_byte_deploy,
value.gas_fee_per_input_buffer_runtime,
value.gas_fee_per_byte_runtime,
value.gas_cost_runtime,
value.gas_cost_deploy,
value.gas_limit_deploy,
value.gas_limit_runtime,
)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NodeConfig {
@ -14,4 +47,6 @@ pub struct NodeConfig {
pub seq_poll_timeout_secs: u64,
///Port to listen
pub port: u16,
///Gas config
pub gas_config: GasConfig,
}

View File

@ -23,8 +23,9 @@ use storage::NodeChainStore;
use tokio::{sync::RwLock, task::JoinHandle};
use utxo::utxo_core::UTXO;
use zkvm::{
prove_mint_utxo, prove_mint_utxo_multiple_assets, prove_send_utxo, prove_send_utxo_deshielded,
prove_send_utxo_multiple_assets_one_receiver, prove_send_utxo_shielded,
gas_calculator::GasCalculator, prove_mint_utxo, prove_mint_utxo_multiple_assets,
prove_send_utxo, prove_send_utxo_deshielded, prove_send_utxo_multiple_assets_one_receiver,
prove_send_utxo_shielded,
};
pub const BLOCK_GEN_DELAY_SECS: u64 = 20;
@ -70,6 +71,7 @@ pub struct NodeCore {
pub node_config: NodeConfig,
pub db_updater_handle: JoinHandle<Result<()>>,
pub sequencer_client: Arc<SequencerClient>,
pub gas_calculator: GasCalculator,
}
impl NodeCore {
@ -141,6 +143,7 @@ impl NodeCore {
node_config: config.clone(),
db_updater_handle: updater_handle,
sequencer_client: client.clone(),
gas_calculator: GasCalculator::from(config.gas_config),
})
}

View File

@ -71,6 +71,12 @@ pub fn cast_common_execution_error_into_rpc_error(comm_exec_err: ExecutionFailur
ExecutionFailureKind::AmountMismatchError => {
RpcError::new_internal_error(None, &error_string)
}
ExecutionFailureKind::InsufficientGasError => {
RpcError::new_internal_error(None, &error_string)
}
ExecutionFailureKind::InsufficientFundsError => {
RpcError::new_internal_error(None, &error_string)
}
ExecutionFailureKind::SequencerClientError(seq_cli_err) => {
cast_seq_client_error_into_rpc_error(seq_cli_err)
}

View File

@ -3,5 +3,14 @@
"override_rust_log": null,
"sequencer_addr": "http://127.0.0.1:3040",
"seq_poll_timeout_secs": 10,
"port": 3041
"port": 3041,
"gas_config": {
"gas_fee_per_byte_deploy": 100,
"gas_fee_per_input_buffer_runtime": 1000,
"gas_fee_per_byte_runtime": 10,
"gas_cost_runtime": 100,
"gas_cost_deploy": 1000,
"gas_limit_deploy": 30000000,
"gas_limit_runtime": 30000000
}
}

View File

@ -11,7 +11,7 @@ log.workspace = true
serde.workspace = true
thiserror.workspace = true
risc0-zkvm = { git = "https://github.com/risc0/risc0.git", branch = "release-1.2" }
risc0-zkvm = { git = "https://github.com/risc0/risc0.git", branch = "release-1.3" }
test-methods = { path = "test_methods" }
[dependencies.accounts]

113
zkvm/src/gas_calculator.rs Normal file
View File

@ -0,0 +1,113 @@
#[derive(Debug, Clone)]
pub struct GasCalculator {
/// Gas spent per deploying one byte of data
gas_fee_per_byte_deploy: u64,
/// Gas spent per reading one byte of data in VM
gas_fee_per_input_buffer_runtime: u64,
/// Gas spent per one byte of contract data in runtime
gas_fee_per_byte_runtime: u64,
/// Cost of one gas of runtime in public balance
gas_cost_runtime: u64,
/// Cost of one gas of deployment in public balance
gas_cost_deploy: u64,
/// Gas limit for deployment
gas_limit_deploy: u64,
/// Gas limit for runtime
gas_limit_runtime: u64,
}
impl GasCalculator {
pub fn new(
gas_fee_per_byte_deploy: u64,
gas_fee_per_input_buffer_runtime: u64,
gas_fee_per_byte_runtime: u64,
gas_cost_runtime: u64,
gas_cost_deploy: u64,
gas_limit_deploy: u64,
gas_limit_runtime: u64,
) -> Self {
Self {
gas_fee_per_byte_deploy,
gas_fee_per_input_buffer_runtime,
gas_fee_per_byte_runtime,
gas_cost_deploy,
gas_cost_runtime,
gas_limit_deploy,
gas_limit_runtime,
}
}
pub fn gas_fee_per_byte_deploy(&self) -> u64 {
self.gas_fee_per_byte_deploy
}
pub fn gas_fee_per_input_buffer_runtime(&self) -> u64 {
self.gas_fee_per_input_buffer_runtime
}
pub fn gas_fee_per_byte_runtime(&self) -> u64 {
self.gas_fee_per_byte_runtime
}
pub fn gas_cost_runtime(&self) -> u64 {
self.gas_cost_runtime
}
pub fn gas_cost_deploy(&self) -> u64 {
self.gas_cost_deploy
}
pub fn gas_limit_deploy(&self) -> u64 {
self.gas_limit_deploy
}
pub fn gas_limit_runtime(&self) -> u64 {
self.gas_limit_runtime
}
///Returns Option<u64>
///
/// Some(_) - in case if `gas` < `gas_limit_deploy`
///
/// None - else
pub fn gas_deploy(&self, elf: &[u8]) -> Option<u64> {
let gas = self.gas_fee_per_byte_deploy() * (elf.len() as u64);
if gas < self.gas_limit_deploy() {
Some(gas)
} else {
None
}
}
pub fn gas_runtime(&self, elf: &[u8]) -> u64 {
self.gas_fee_per_byte_runtime() * (elf.len() as u64)
}
pub fn gas_input_buffer(&self, input_length: usize) -> u64 {
self.gas_fee_per_input_buffer_runtime() * (input_length as u64)
}
///Returns Option<u64>
///
/// Some(_) - in case if `gas` < `gas_limit_runtime`
///
/// None - else
pub fn gas_runtime_full(&self, elf: &[u8], input_length: usize) -> Option<u64> {
let gas = self.gas_runtime(elf) + self.gas_input_buffer(input_length);
if gas < self.gas_limit_runtime() {
Some(gas)
} else {
None
}
}
pub fn deploy_cost(&self, deploy_gas: u64) -> u64 {
deploy_gas * self.gas_cost_deploy()
}
pub fn runtime_cost(&self, runtime_gas: u64) -> u64 {
runtime_gas * self.gas_cost_runtime()
}
}

View File

@ -1,8 +1,33 @@
use accounts::account_core::AccountAddress;
use common::ExecutionFailureKind;
use risc0_zkvm::{default_executor, default_prover, sha::Digest, ExecutorEnv, Receipt};
use serde::Serialize;
use utxo::utxo_core::{UTXOPayload, UTXO};
pub mod gas_calculator;
pub fn gas_limits_check<INP: Serialize>(
input_buffer: INP,
elf: &[u8],
gas_calculator: &gas_calculator::GasCalculator,
attached_funds: u64,
) -> Result<(), ExecutionFailureKind> {
let mut input_buffer_len: usize = 0;
input_buffer_len += serde_json::to_vec(&input_buffer).unwrap().len();
let gas_limit = gas_calculator
.gas_runtime_full(elf, input_buffer_len)
.ok_or(ExecutionFailureKind::InsufficientGasError)?;
let cost = gas_calculator.runtime_cost(gas_limit);
if cost > attached_funds {
return Err(ExecutionFailureKind::InsufficientFundsError);
}
Ok(())
}
pub fn prove_mint_utxo(
amount_to_mint: u128,
owner: AccountAddress,

View File

@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"
[build-dependencies]
risc0-build = { git = "https://github.com/risc0/risc0.git", branch = "release-1.2" }
risc0-build = { git = "https://github.com/risc0/risc0.git", branch = "release-1.3" }
[package.metadata.risc0]
methods = ["guest"]