diff --git a/Cargo.lock b/Cargo.lock index 9228a906a729..ef8519b80671 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5396,6 +5396,7 @@ version = "0.16.0" dependencies = [ "linera-base", "linera-client", + "linera-execution", "linera-version", "reqwest 0.11.27", "serde", diff --git a/linera-execution/src/committee.rs b/linera-execution/src/committee.rs index ad4462604c17..19f9cdce300f 100644 --- a/linera-execution/src/committee.rs +++ b/linera-execution/src/committee.rs @@ -4,7 +4,6 @@ use std::{borrow::Cow, collections::BTreeMap, str::FromStr}; -use async_graphql::InputObject; use linera_base::crypto::{AccountPublicKey, CryptoError, ValidatorPublicKey}; use serde::{Deserialize, Serialize}; @@ -59,7 +58,8 @@ pub struct ValidatorState { } /// A set of validators (identified by their public keys) and their voting rights. -#[derive(Eq, PartialEq, Hash, Clone, Debug, Default, InputObject)] +#[derive(Eq, PartialEq, Hash, Clone, Debug, Default)] +#[cfg_attr(with_graphql, derive(async_graphql::InputObject))] pub struct Committee { /// The validators in the committee. pub validators: BTreeMap, diff --git a/linera-execution/src/graphql.rs b/linera-execution/src/graphql.rs index fe7a82eaffdd..650f116afb4a 100644 --- a/linera-execution/src/graphql.rs +++ b/linera-execution/src/graphql.rs @@ -14,12 +14,19 @@ use linera_views::{context::Context, map_view::MapView}; use crate::{ committee::{Committee, ValidatorState}, + policy::ResourceControlPolicy, system::UserData, ExecutionStateView, SystemExecutionStateView, }; doc_scalar!(UserData, "Optional user message attached to a transfer"); +async_graphql::scalar!( + ResourceControlPolicy, + "ResourceControlPolicyScalar", + "A collection of prices and limits associated with block execution" +); + #[async_graphql::Object(cache_control(no_cache))] impl Committee { #[graphql(derived(name = "validators"))] @@ -41,6 +48,11 @@ impl Committee { async fn _validity_threshold(&self) -> u64 { self.validity_threshold() } + + #[graphql(derived(name = "policy"))] + async fn _policy(&self) -> &ResourceControlPolicy { + self.policy() + } } #[async_graphql::Object(cache_control(no_cache))] diff --git a/linera-execution/src/policy.rs b/linera-execution/src/policy.rs index 8fb0dd133ca8..bad5c08716ed 100644 --- a/linera-execution/src/policy.rs +++ b/linera-execution/src/policy.rs @@ -11,7 +11,6 @@ use std::{collections::BTreeSet, fmt}; -use async_graphql::InputObject; use linera_base::{ data_types::{Amount, ArithmeticError, BlobContent, CompressedBytecode, Resources}, ensure, @@ -23,7 +22,7 @@ use serde::{Deserialize, Serialize}; use crate::ExecutionError; /// A collection of prices and limits associated with block execution. -#[derive(Eq, PartialEq, Hash, Clone, Debug, Serialize, Deserialize, InputObject)] +#[derive(Eq, PartialEq, Hash, Clone, Debug, Serialize, Deserialize)] pub struct ResourceControlPolicy { /// The price per unit of fuel (aka gas) for Wasm execution. pub wasm_fuel_unit: Amount, diff --git a/linera-faucet/client/Cargo.toml b/linera-faucet/client/Cargo.toml index 0f0dc008470e..4cffa80501b8 100644 --- a/linera-faucet/client/Cargo.toml +++ b/linera-faucet/client/Cargo.toml @@ -14,6 +14,7 @@ edition.workspace = true [dependencies] linera-base.workspace = true linera-client.workspace = true +linera-execution.workspace = true linera-version.workspace = true reqwest.workspace = true serde.workspace = true diff --git a/linera-faucet/client/src/lib.rs b/linera-faucet/client/src/lib.rs index a4d401ff03c6..a75e321bd2e6 100644 --- a/linera-faucet/client/src/lib.rs +++ b/linera-faucet/client/src/lib.rs @@ -5,8 +5,11 @@ // TODO(#3362): generate this code +use std::collections::BTreeMap; + use linera_base::{crypto::ValidatorPublicKey, data_types::ChainDescription}; use linera_client::config::GenesisConfig; +use linera_execution::{committee::ValidatorState, Committee, ResourceControlPolicy}; use linera_version::VersionInfo; use thiserror_context::Context; @@ -137,4 +140,34 @@ impl Faucet { .map(|validator| (validator.public_key, validator.network_address)) .collect()) } + + pub async fn current_committee(&self) -> Result { + #[derive(serde::Deserialize)] + struct CommitteeResponse { + validators: BTreeMap, + policy: ResourceControlPolicy, + } + + #[derive(serde::Deserialize)] + #[serde(rename_all = "camelCase")] + struct Response { + current_committee: CommitteeResponse, + } + + let response = self + .query::( + "query { currentCommittee { \ + validators \ + policy \ + } }", + ) + .await?; + + let committee_response = response.current_committee; + + Ok(Committee::new( + committee_response.validators, + committee_response.policy, + )) + } } diff --git a/linera-faucet/server/src/lib.rs b/linera-faucet/server/src/lib.rs index 1487db6a04fb..4a7b90141628 100644 --- a/linera-faucet/server/src/lib.rs +++ b/linera-faucet/server/src/lib.rs @@ -39,7 +39,7 @@ use linera_core::{ }; use linera_execution::{ system::{OpenChainConfig, SystemOperation}, - ExecutionError, Operation, + Committee, ExecutionError, Operation, }; #[cfg(feature = "metrics")] use linera_metrics::prometheus_server; @@ -195,6 +195,11 @@ where }) .collect()) } + + /// Returns the current committee, including weights and resource policy. + async fn current_committee(&self) -> Result { + Ok(self.client.local_committee().await?) + } } #[async_graphql::Object(cache_control(no_cache))] diff --git a/linera-service-graphql-client/gql/service_schema.graphql b/linera-service-graphql-client/gql/service_schema.graphql index 9ce38343ea8d..28407fe6cdf7 100644 --- a/linera-service-graphql-client/gql/service_schema.graphql +++ b/linera-service-graphql-client/gql/service_schema.graphql @@ -450,7 +450,7 @@ input Committee { """ The policy agreed on for this epoch. """ - policy: ResourceControlPolicy! + policy: ResourceControlPolicyScalar! } type ConfirmedBlock { @@ -1252,139 +1252,9 @@ type ReentrantCollectionView_ChainId_OutboxStateView_06c2376d { } """ -A collection of prices and limits associated with block execution. +A collection of prices and limits associated with block execution """ -input ResourceControlPolicy { - """ - The price per unit of fuel (aka gas) for Wasm execution. - """ - wasmFuelUnit: Amount! - """ - The price per unit of fuel (aka gas) for EVM execution. - """ - evmFuelUnit: Amount! - """ - The price of one read operation. - """ - readOperation: Amount! - """ - The price of one write operation. - """ - writeOperation: Amount! - """ - The price of accessing one byte from the runtime. - """ - byteRuntime: Amount! - """ - The price of reading a byte. - """ - byteRead: Amount! - """ - The price of writing a byte - """ - byteWritten: Amount! - """ - The base price to read a blob. - """ - blobRead: Amount! - """ - The base price to publish a blob. - """ - blobPublished: Amount! - """ - The price to read a blob, per byte. - """ - blobByteRead: Amount! - """ - The price to publish a blob, per byte. - """ - blobBytePublished: Amount! - """ - The price of increasing storage by a byte. - """ - byteStored: Amount! - """ - The base price of adding an operation to a block. - """ - operation: Amount! - """ - The additional price for each byte in the argument of a user operation. - """ - operationByte: Amount! - """ - The base price of sending a message from a block. - """ - message: Amount! - """ - The additional price for each byte in the argument of a user message. - """ - messageByte: Amount! - """ - The price per query to a service as an oracle. - """ - serviceAsOracleQuery: Amount! - """ - The price for a performing an HTTP request. - """ - httpRequest: Amount! - """ - The maximum amount of Wasm fuel a block can consume. - """ - maximumWasmFuelPerBlock: Int! - """ - The maximum amount of EVM fuel a block can consume. - """ - maximumEvmFuelPerBlock: Int! - """ - The maximum time in milliseconds that a block can spend executing services as oracles. - """ - maximumServiceOracleExecutionMs: Int! - """ - The maximum size of a block. This includes the block proposal itself as well as - the execution outcome. - """ - maximumBlockSize: Int! - """ - The maximum size of decompressed contract or service bytecode, in bytes. - """ - maximumBytecodeSize: Int! - """ - The maximum size of a blob. - """ - maximumBlobSize: Int! - """ - The maximum number of published blobs per block. - """ - maximumPublishedBlobs: Int! - """ - The maximum size of a block proposal. - """ - maximumBlockProposalSize: Int! - """ - The maximum data to read per block - """ - maximumBytesReadPerBlock: Int! - """ - The maximum data to write per block - """ - maximumBytesWrittenPerBlock: Int! - """ - The maximum size in bytes of an oracle response. - """ - maximumOracleResponseBytes: Int! - """ - The maximum size in bytes of a received HTTP response. - """ - maximumHttpResponseBytes: Int! - """ - The maximum amount of time allowed to wait for an HTTP response. - """ - httpRequestTimeoutMs: Int! - """ - The list of hosts that contracts and services can send HTTP requests to. - """ - httpRequestAllowList: [String!]! -} +scalar ResourceControlPolicyScalar """ A number to identify successive attempts to decide a value in a consensus protocol. diff --git a/linera-service/src/cli/main.rs b/linera-service/src/cli/main.rs index 725cf0acc813..ac694edb1201 100644 --- a/linera-service/src/cli/main.rs +++ b/linera-service/src/cli/main.rs @@ -19,7 +19,7 @@ use chrono::Utc; use colored::Colorize; use futures::{lock::Mutex, FutureExt as _, StreamExt}; use linera_base::{ - crypto::{AccountPublicKey, InMemorySigner, Signer}, + crypto::{InMemorySigner, Signer}, data_types::{ApplicationPermissions, Timestamp}, identifiers::{AccountOwner, ChainId}, listen_for_shutdown_signals, @@ -1624,24 +1624,8 @@ impl Runnable for Job { signer.into_value(), ); let faucet = cli_wrappers::Faucet::new(faucet_url); - let validators = faucet.current_validators().await?; + let committee = faucet.current_committee().await?; let chain_client = context.make_chain_client(network_description.admin_chain_id); - // TODO(#4434): This is a quick workaround with an equal-weight committee. Instead, - // the faucet should provide the full committee including weights. - let committee = Committee::new( - validators - .into_iter() - .map(|(pub_key, network_address)| { - let state = ValidatorState { - network_address, - votes: 100, - account_public_key: AccountPublicKey::from_slice(&[0; 33]).unwrap(), - }; - (pub_key, state) - }) - .collect(), - Default::default(), // unused - ); chain_client .synchronize_chain_state_from_committee(committee) .await?;