diff --git a/CLI.md b/CLI.md index 46f45580e34a..cbdb6ad10bd9 100644 --- a/CLI.md +++ b/CLI.md @@ -491,39 +491,23 @@ Create genesis configuration for a Linera deployment. Create initial user chains Default value: `0` * `--start-timestamp ` — The start timestamp: no blocks can be created before this time -* `--block-price ` — Set the base price for creating a block +* `--policy-config ` — Configure the resource control policy (notably fees) according to pre-defined settings - Default value: `0` -* `--fuel-unit-price ` — Set the price per unit of fuel + Default value: `default` - Default value: `0` -* `--read-operation-price ` — Set the price per read operation + Possible values: `default`, `only-fuel`, `fuel-and-block`, `all-categories`, `devnet` - Default value: `0` +* `--block-price ` — Set the base price for creating a block +* `--fuel-unit-price ` — Set the price per unit of fuel +* `--read-operation-price ` — Set the price per read operation * `--write-operation-price ` — Set the price per write operation - - Default value: `0` * `--byte-read-price ` — Set the price per byte read - - Default value: `0` * `--byte-written-price ` — Set the price per byte written - - Default value: `0` * `--byte-stored-price ` — Set the price per byte stored - - Default value: `0` * `--operation-price ` — Set the base price of sending an operation from a block.. - - Default value: `0` * `--operation-byte-price ` — Set the additional price for each byte in the argument of a user operation - - Default value: `0` * `--message-price ` — Set the base price of sending a message from a block.. - - Default value: `0` * `--message-byte-price ` — Set the additional price for each byte in the argument of a user message - - Default value: `0` * `--maximum-fuel-per-block ` — Set the maximum amount of fuel per block * `--maximum-executed-block-size ` — Set the maximum size of an executed block * `--maximum-bytecode-size ` — Set the maximum size of decompressed contract or service bytecode, in bytes diff --git a/Cargo.lock b/Cargo.lock index a0b2f5eece08..c37e8d9b9f2e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4926,6 +4926,7 @@ dependencies = [ "fs_extra", "fungible", "futures", + "heck 0.4.1", "hex", "http 1.2.0", "k8s-openapi", diff --git a/linera-client/src/client_options.rs b/linera-client/src/client_options.rs index d07c74835cde..87a0ef419659 100644 --- a/linera-client/src/client_options.rs +++ b/linera-client/src/client_options.rs @@ -640,49 +640,54 @@ pub enum ClientCommand { /// Number of initial (aka "root") chains to create in addition to the admin chain. num_other_initial_chains: u32, + /// Configure the resource control policy (notably fees) according to pre-defined + /// settings. + #[arg(long, default_value = "default")] + policy_config: ResourceControlPolicyConfig, + /// Set the base price for creating a block. - #[arg(long, default_value = "0")] - block_price: Amount, + #[arg(long)] + block_price: Option, /// Set the price per unit of fuel. - #[arg(long, default_value = "0")] - fuel_unit_price: Amount, + #[arg(long)] + fuel_unit_price: Option, /// Set the price per read operation. - #[arg(long, default_value = "0")] - read_operation_price: Amount, + #[arg(long)] + read_operation_price: Option, /// Set the price per write operation. - #[arg(long, default_value = "0")] - write_operation_price: Amount, + #[arg(long)] + write_operation_price: Option, /// Set the price per byte read. - #[arg(long, default_value = "0")] - byte_read_price: Amount, + #[arg(long)] + byte_read_price: Option, /// Set the price per byte written. - #[arg(long, default_value = "0")] - byte_written_price: Amount, + #[arg(long)] + byte_written_price: Option, /// Set the price per byte stored. - #[arg(long, default_value = "0")] - byte_stored_price: Amount, + #[arg(long)] + byte_stored_price: Option, /// Set the base price of sending an operation from a block.. - #[arg(long, default_value = "0")] - operation_price: Amount, + #[arg(long)] + operation_price: Option, /// Set the additional price for each byte in the argument of a user operation. - #[arg(long, default_value = "0")] - operation_byte_price: Amount, + #[arg(long)] + operation_byte_price: Option, /// Set the base price of sending a message from a block.. - #[arg(long, default_value = "0")] - message_price: Amount, + #[arg(long)] + message_price: Option, /// Set the additional price for each byte in the argument of a user message. - #[arg(long, default_value = "0")] - message_byte_price: Amount, + #[arg(long)] + message_byte_price: Option, /// Set the maximum amount of fuel per block. #[arg(long)] diff --git a/linera-service/Cargo.toml b/linera-service/Cargo.toml index 1c706b2a7553..622b167b723d 100644 --- a/linera-service/Cargo.toml +++ b/linera-service/Cargo.toml @@ -80,6 +80,7 @@ current_platform = "0.2.0" fs-err = { workspace = true, features = ["tokio"] } fs_extra = { workspace = true, optional = true } futures.workspace = true +heck.workspace = true hex.workspace = true http.workspace = true k8s-openapi = { workspace = true, optional = true } diff --git a/linera-service/src/cli_wrappers/local_kubernetes_net.rs b/linera-service/src/cli_wrappers/local_kubernetes_net.rs index e7194803b65b..47eb3a12f479 100644 --- a/linera-service/src/cli_wrappers/local_kubernetes_net.rs +++ b/linera-service/src/cli_wrappers/local_kubernetes_net.rs @@ -12,7 +12,7 @@ use linera_base::{ command::{resolve_binary, CommandExt}, data_types::Amount, }; -use linera_execution::ResourceControlPolicy; +use linera_client::client_options::ResourceControlPolicyConfig; use tempfile::{tempdir, TempDir}; use tokio::process::Command; #[cfg(with_testing)] @@ -48,7 +48,7 @@ pub struct LocalKubernetesNetConfig { pub binaries: BuildArg, pub no_build: bool, pub docker_image_name: String, - pub policy: ResourceControlPolicy, + pub policy_config: ResourceControlPolicyConfig, } /// A wrapper of [`LocalKubernetesNetConfig`] to create a shared local Kubernetes network @@ -102,7 +102,7 @@ impl SharedLocalKubernetesNetTestingConfig { binaries, no_build: false, docker_image_name: String::from("linera:latest"), - policy: ResourceControlPolicy::devnet(), + policy_config: ResourceControlPolicyConfig::Devnet, }) } } @@ -142,7 +142,7 @@ impl LineraNetConfig for LocalKubernetesNetConfig { .create_genesis_config( self.num_other_initial_chains, self.initial_amount, - self.policy, + self.policy_config, ) .await .unwrap(); diff --git a/linera-service/src/cli_wrappers/local_net.rs b/linera-service/src/cli_wrappers/local_net.rs index 8f3ea4cea25c..074beb6ab80c 100644 --- a/linera-service/src/cli_wrappers/local_net.rs +++ b/linera-service/src/cli_wrappers/local_net.rs @@ -19,9 +19,11 @@ use linera_base::{ command::{resolve_binary, CommandExt}, data_types::Amount, }; -use linera_client::storage::{StorageConfig, StorageConfigNamespace}; +use linera_client::{ + client_options::ResourceControlPolicyConfig, + storage::{StorageConfig, StorageConfigNamespace}, +}; use linera_core::node::ValidatorNodeProvider; -use linera_execution::ResourceControlPolicy; #[cfg(all(feature = "storage-service", with_testing))] use linera_storage_service::common::storage_service_test_endpoint; #[cfg(all(feature = "scylladb", with_testing))] @@ -161,7 +163,7 @@ pub struct LocalNetConfig { pub initial_amount: Amount, pub num_initial_validators: usize, pub num_shards: usize, - pub policy: ResourceControlPolicy, + pub policy_config: ResourceControlPolicyConfig, pub storage_config_builder: StorageConfigBuilder, pub path_provider: PathProvider, } @@ -258,7 +260,7 @@ impl LocalNetConfig { network, num_other_initial_chains: 2, initial_amount: Amount::from_tokens(1_000_000), - policy: ResourceControlPolicy::devnet(), + policy_config: ResourceControlPolicyConfig::Devnet, testing_prng_seed: Some(37), namespace: linera_views::random::generate_test_namespace(), num_initial_validators: 4, @@ -294,7 +296,7 @@ impl LineraNetConfig for LocalNetConfig { .create_genesis_config( self.num_other_initial_chains, self.initial_amount, - self.policy, + self.policy_config, ) .await .unwrap(); diff --git a/linera-service/src/cli_wrappers/wallet.rs b/linera-service/src/cli_wrappers/wallet.rs index 95db7eff7c90..0a21ca0021b8 100644 --- a/linera-service/src/cli_wrappers/wallet.rs +++ b/linera-service/src/cli_wrappers/wallet.rs @@ -17,6 +17,7 @@ use anyhow::{bail, ensure, Context, Result}; use async_graphql::InputType; use async_tungstenite::tungstenite::{client::IntoClientRequest as _, http::HeaderValue}; use futures::{SinkExt as _, Stream, StreamExt as _, TryStreamExt as _}; +use heck::ToKebabCase; use linera_base::{ abi::ContractAbi, command::{resolve_binary, CommandExt}, @@ -24,9 +25,9 @@ use linera_base::{ data_types::{Amount, Bytecode}, identifiers::{Account, ApplicationId, BytecodeId, ChainId, MessageId, Owner}, }; -use linera_client::wallet::Wallet; +use linera_client::{client_options::ResourceControlPolicyConfig, wallet::Wallet}; use linera_core::worker::Notification; -use linera_execution::{system::SystemChannel, ResourceControlPolicy}; +use linera_execution::system::SystemChannel; use linera_faucet::ClaimOutcome; use linera_faucet_client::Faucet; use serde::{de::DeserializeOwned, ser::Serialize}; @@ -232,29 +233,8 @@ impl ClientWrapper { &self, num_other_initial_chains: u32, initial_funding: Amount, - policy: ResourceControlPolicy, + policy_config: ResourceControlPolicyConfig, ) -> Result<()> { - let ResourceControlPolicy { - block, - fuel_unit, - read_operation, - write_operation, - byte_read, - byte_written, - byte_stored, - operation, - operation_byte, - message, - message_byte, - maximum_fuel_per_block, - maximum_executed_block_size, - maximum_blob_size, - maximum_published_blobs, - maximum_bytecode_size, - maximum_block_proposal_size, - maximum_bytes_read_per_block, - maximum_bytes_written_per_block, - } = policy; let mut command = self.command().await?; command .args([ @@ -264,46 +244,11 @@ impl ClientWrapper { .args(["--initial-funding", &initial_funding.to_string()]) .args(["--committee", "committee.json"]) .args(["--genesis", "genesis.json"]) - .args(["--block-price", &block.to_string()]) - .args(["--fuel-unit-price", &fuel_unit.to_string()]) - .args(["--read-operation-price", &read_operation.to_string()]) - .args(["--byte-read-price", &byte_read.to_string()]) - .args(["--byte-written-price", &byte_written.to_string()]) - .args(["--byte-stored-price", &byte_stored.to_string()]) - .args(["--message-byte-price", &message_byte.to_string()]) - .args(["--write-operation-price", &write_operation.to_string()]) - .args(["--operation-price", &operation.to_string()]) - .args(["--operation-byte-price", &operation_byte.to_string()]) - .args(["--message-price", &message.to_string()]) .args([ - "--maximum-fuel-per-block", - &maximum_fuel_per_block.to_string(), - ]) - .args([ - "--maximum-executed-block-size", - &maximum_executed_block_size.to_string(), - ]) - .args(["--maximum-blob-size", &maximum_blob_size.to_string()]) - .args([ - "--maximum-published-blobs", - &maximum_published_blobs.to_string(), - ]) - .args([ - "--maximum-bytecode-size", - &maximum_bytecode_size.to_string(), - ]) - .args([ - "--maximum-block-proposal-size", - &maximum_block_proposal_size.to_string(), - ]) - .args([ - "--maximum-bytes-read-per-block", - &maximum_bytes_read_per_block.to_string(), - ]) - .args([ - "--maximum-bytes-written-per-block", - &maximum_bytes_written_per_block.to_string(), + "--policy-config", + &policy_config.to_string().to_kebab_case(), ]); + if let Some(seed) = self.testing_prng_seed { command.arg("--testing-prng-seed").arg(seed.to_string()); } diff --git a/linera-service/src/linera/main.rs b/linera-service/src/linera/main.rs index fbe245a074ff..967c64ff1d8c 100644 --- a/linera-service/src/linera/main.rs +++ b/linera-service/src/linera/main.rs @@ -41,7 +41,7 @@ use linera_core::{ }; use linera_execution::{ committee::{Committee, ValidatorState}, - Message, ResourceControlPolicy, SystemMessage, + Message, SystemMessage, }; use linera_faucet_server::FaucetService; use linera_sdk::base::ValidatorPublicKey; @@ -1454,6 +1454,7 @@ async fn run(options: &ClientOptions) -> Result { initial_funding, start_timestamp, num_other_initial_chains, + policy_config, block_price, fuel_unit_price, read_operation_price, @@ -1479,36 +1480,64 @@ async fn run(options: &ClientOptions) -> Result { let start_time = Instant::now(); let committee_config: CommitteeConfig = util::read_json(committee_config_path) .expect("Unable to read committee config file"); - let maximum_fuel_per_block = maximum_fuel_per_block.unwrap_or(u64::MAX); - let maximum_bytes_read_per_block = maximum_bytes_read_per_block.unwrap_or(u64::MAX); - let maximum_bytes_written_per_block = - maximum_bytes_written_per_block.unwrap_or(u64::MAX); - let maximum_executed_block_size = maximum_executed_block_size.unwrap_or(u64::MAX); - let maximum_blob_size = maximum_blob_size.unwrap_or(u64::MAX); - let maximum_published_blobs = maximum_published_blobs.unwrap_or(u64::MAX); - let maximum_bytecode_size = maximum_bytecode_size.unwrap_or(u64::MAX); - let maximum_block_proposal_size = maximum_block_proposal_size.unwrap_or(u64::MAX); - let policy = ResourceControlPolicy { - block: *block_price, - fuel_unit: *fuel_unit_price, - read_operation: *read_operation_price, - write_operation: *write_operation_price, - byte_read: *byte_read_price, - byte_written: *byte_written_price, - byte_stored: *byte_stored_price, - operation_byte: *operation_byte_price, - operation: *operation_price, - message_byte: *message_byte_price, - message: *message_price, - maximum_fuel_per_block, - maximum_executed_block_size, - maximum_blob_size, - maximum_published_blobs, - maximum_bytecode_size, - maximum_block_proposal_size, - maximum_bytes_read_per_block, - maximum_bytes_written_per_block, - }; + let mut policy = policy_config.into_policy(); + if let Some(block_price) = block_price { + policy.block = *block_price; + } + if let Some(fuel_unit_price) = fuel_unit_price { + policy.fuel_unit = *fuel_unit_price; + } + if let Some(read_operation_price) = read_operation_price { + policy.read_operation = *read_operation_price; + } + if let Some(write_operation_price) = write_operation_price { + policy.write_operation = *write_operation_price; + } + if let Some(byte_read_price) = byte_read_price { + policy.byte_read = *byte_read_price; + } + if let Some(byte_written_price) = byte_written_price { + policy.byte_written = *byte_written_price; + } + if let Some(byte_stored_price) = byte_stored_price { + policy.byte_stored = *byte_stored_price; + } + if let Some(operation_price) = operation_price { + policy.operation = *operation_price; + } + if let Some(operation_byte_price) = operation_byte_price { + policy.operation_byte = *operation_byte_price; + } + if let Some(message_price) = message_price { + policy.message = *message_price; + } + if let Some(message_byte_price) = message_byte_price { + policy.message_byte = *message_byte_price; + } + if let Some(maximum_fuel_per_block) = maximum_fuel_per_block { + policy.maximum_fuel_per_block = *maximum_fuel_per_block; + } + if let Some(maximum_executed_block_size) = maximum_executed_block_size { + policy.maximum_executed_block_size = *maximum_executed_block_size; + } + if let Some(maximum_blob_size) = maximum_blob_size { + policy.maximum_blob_size = *maximum_blob_size; + } + if let Some(maximum_published_blobs) = maximum_published_blobs { + policy.maximum_published_blobs = *maximum_published_blobs; + } + if let Some(maximum_bytecode_size) = maximum_bytecode_size { + policy.maximum_bytecode_size = *maximum_bytecode_size; + } + if let Some(maximum_block_proposal_size) = maximum_block_proposal_size { + policy.maximum_block_proposal_size = *maximum_block_proposal_size; + } + if let Some(maximum_bytes_read_per_block) = maximum_bytes_read_per_block { + policy.maximum_bytes_read_per_block = *maximum_bytes_read_per_block; + } + if let Some(maximum_bytes_written_per_block) = maximum_bytes_written_per_block { + policy.maximum_bytes_written_per_block = *maximum_bytes_written_per_block; + } let timestamp = start_timestamp .map(|st| { let micros = @@ -1625,7 +1654,7 @@ async fn run(options: &ClientOptions) -> Result { binaries, *no_build, docker_image_name.clone(), - policy_config.into_policy(), + *policy_config, *with_faucet, *faucet_chain, *faucet_port, @@ -1658,7 +1687,7 @@ async fn run(options: &ClientOptions) -> Result { *validators, *shards, *testing_prng_seed, - policy_config.into_policy(), + *policy_config, path, storage, external_protocol.clone(), diff --git a/linera-service/src/linera/net_up_utils.rs b/linera-service/src/linera/net_up_utils.rs index f7ac9fab255c..a460adfc3e3e 100644 --- a/linera-service/src/linera/net_up_utils.rs +++ b/linera-service/src/linera/net_up_utils.rs @@ -7,8 +7,10 @@ use colored::Colorize as _; use linera_base::{ data_types::Amount, identifiers::ChainId, listen_for_shutdown_signals, time::Duration, }; -use linera_client::storage::{StorageConfig, StorageConfigNamespace}; -use linera_execution::ResourceControlPolicy; +use linera_client::{ + client_options::ResourceControlPolicyConfig, + storage::{StorageConfig, StorageConfigNamespace}, +}; use linera_service::cli_wrappers::{ local_net::{Database, LocalNetConfig, PathProvider, StorageConfigBuilder}, ClientWrapper, FaucetService, LineraNet, LineraNetConfig, Network, NetworkConfig, @@ -110,7 +112,7 @@ pub async fn handle_net_up_kubernetes( binaries: &Option>, no_build: bool, docker_image_name: String, - policy: ResourceControlPolicy, + policy_config: ResourceControlPolicyConfig, with_faucet: bool, faucet_chain: Option, faucet_port: NonZeroU16, @@ -142,7 +144,7 @@ pub async fn handle_net_up_kubernetes( binaries: binaries.clone().into(), no_build, docker_image_name, - policy, + policy_config, }; let (mut net, client) = config.instantiate().await?; let faucet_service = print_messages_and_create_faucet( @@ -164,7 +166,7 @@ pub async fn handle_net_up_service( num_initial_validators: usize, num_shards: usize, testing_prng_seed: Option, - policy: ResourceControlPolicy, + policy_config: ResourceControlPolicyConfig, path: &Option, storage: &Option, external_protocol: String, @@ -205,7 +207,7 @@ pub async fn handle_net_up_service( initial_amount: Amount::from_tokens(initial_amount), num_initial_validators, num_shards, - policy, + policy_config, storage_config_builder, path_provider, };