diff --git a/client-worker/.cargo/config.toml b/client-worker/.cargo/config.toml new file mode 100644 index 0000000..f4e8c00 --- /dev/null +++ b/client-worker/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +target = "wasm32-unknown-unknown" diff --git a/client-worker/Cargo.toml b/client-worker/Cargo.toml index 4e9678c..672d22f 100644 --- a/client-worker/Cargo.toml +++ b/client-worker/Cargo.toml @@ -31,6 +31,11 @@ features = ["web"] path = "../linera-protocol/linera-chain" features = ["web"] +[dependencies.linera-client] +path = "../linera-protocol/linera-client" +default-features = false +features = ["web", "local-storage"] + [dependencies.linera-core] path = "../linera-protocol/linera-core" features = ["web", "wasmer"] @@ -63,8 +68,3 @@ features = [ [dependencies.getrandom] version = "*" features = ["js"] - -[patch.crates-io.wasmer] -version = "4.3.0-alpha.1" -git = "https://github.com/Twey/wasmer" -branch = "non-send-environments" diff --git a/client-worker/src/config.rs b/client-worker/src/config.rs deleted file mode 100644 index 4ad7f09..0000000 --- a/client-worker/src/config.rs +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright (c) Zefchain Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use std::{ - io::{BufRead, BufReader, BufWriter, Write}, - path::{Path, PathBuf}, -}; - -use anyhow::{bail, Context as _}; -use linera_base::{ - crypto::{BcsSignable, KeyPair, PublicKey}, - data_types::{Amount, Timestamp}, - identifiers::{ChainDescription, ChainId}, -}; -use linera_execution::{ - committee::{Committee, ValidatorName, ValidatorState}, - ResourceControlPolicy, -}; -use linera_rpc::config::{ValidatorInternalNetworkConfig, ValidatorPublicNetworkConfig}; -use linera_storage::Storage; -use linera_views::views::ViewError; -use serde::{de::DeserializeOwned, Deserialize, Serialize}; - -use wasm_bindgen::JsError; - -use crate::wallet::Wallet; - -pub trait Import: DeserializeOwned { - fn read(path: &Path) -> Result { - unimplemented!() - } -} - -pub trait Export: Serialize { - fn write(&self, path: &Path) -> Result<(), std::io::Error> { - unimplemented!() - } -} - -/// The public configuration of a validator. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct ValidatorConfig { - /// The public key of the validator. - pub name: ValidatorName, - /// The network configuration for the validator. - pub network: ValidatorPublicNetworkConfig, -} - -/// The private configuration of a validator service. -#[derive(Serialize, Deserialize)] -pub struct ValidatorServerConfig { - pub validator: ValidatorConfig, - pub key: KeyPair, - pub internal_network: ValidatorInternalNetworkConfig, -} - -impl Import for ValidatorServerConfig {} -impl Export for ValidatorServerConfig {} - -/// The (public) configuration for all validators. -#[derive(Debug, Default, Clone, Deserialize, Serialize)] -pub struct CommitteeConfig { - pub validators: Vec, -} - -impl Import for CommitteeConfig {} -impl Export for CommitteeConfig {} - -impl CommitteeConfig { - pub fn into_committee(self, policy: ResourceControlPolicy) -> Committee { - let validators = self - .validators - .into_iter() - .map(|v| { - ( - v.name, - ValidatorState { - network_address: v.network.to_string(), - votes: 1, - }, - ) - }) - .collect(); - Committee::new(validators, policy) - } -} - -pub struct WalletState { inner: Wallet } - -impl WalletState { - pub fn inner(&self) -> &Wallet { - &self.inner - } - - pub fn inner_mut(&mut self) -> &mut Wallet { - &mut self.inner - } - - pub fn into_inner(self) -> Wallet { - self.inner - } - - pub fn create( - path: &Path, - genesis_config: GenesisConfig, - testing_prng_seed: Option, - ) -> Result { - unimplemented!() - } - - pub fn write(&mut self) -> Result<(), anyhow::Error> { - unimplemented!(); - } -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct GenesisConfig { - pub committee: CommitteeConfig, - pub admin_id: ChainId, - pub timestamp: Timestamp, - pub chains: Vec<(PublicKey, Amount)>, - pub policy: ResourceControlPolicy, - pub network_name: String, -} - -impl Import for GenesisConfig {} -impl Export for GenesisConfig {} -impl BcsSignable for GenesisConfig {} - -impl GenesisConfig { - pub fn new( - committee: CommitteeConfig, - admin_id: ChainId, - timestamp: Timestamp, - policy: ResourceControlPolicy, - network_name: String, - ) -> Self { - Self { - committee, - admin_id, - timestamp, - chains: Vec::new(), - policy, - network_name, - } - } - - pub async fn initialize_storage(&self, storage: &mut S) -> Result<(), JsError> - where - S: Storage + Clone + Send + Sync + 'static, - ViewError: From, - { - let committee = self.create_committee(); - for (chain_number, (public_key, balance)) in (0..).zip(&self.chains) { - let description = ChainDescription::Root(chain_number); - storage - .create_chain( - committee.clone(), - self.admin_id, - description, - *public_key, - *balance, - self.timestamp, - ) - .await?; - } - Ok(()) - } - - pub fn create_committee(&self) -> Committee { - self.committee.clone().into_committee(self.policy.clone()) - } -} diff --git a/client-worker/src/genesis_config.rs b/client-worker/src/genesis_config.rs deleted file mode 100644 index 44698c6..0000000 --- a/client-worker/src/genesis_config.rs +++ /dev/null @@ -1,78 +0,0 @@ -const GENESIS_CONFIG: &str = r#" -{ - "committee": { - "validators": [ - { - "name": "71a469f9952149321ccc2e2fb7c89013795f019bda0b8d0a2565cc14a22d2306", - "network": { - "protocol": { - "Grpc": "ClearText" - }, - "host": "127.0.0.1", - "port": 9000 - } - } - ] - }, - "admin_id": "e476187f6ddfeb9d588c7b45d3df334d5501d6499b3f9ad5595cae86cce16a65", - "timestamp": 1713448001948543, - "chains": [ - [ - "2f1351c55068186aa86c985e9f97fee574737184b046be87de2c8a7256cc2f47", - "1000000." - ], - [ - "98437660add0a507ea23270603dcf82638bb8617757ea7977618514713b5b3db", - "1000000." - ], - [ - "fafa1603c6d5a311aed12bc06cd543c007a070c36aea630f6201e121058bc2fd", - "1000000." - ], - [ - "852af7af7db9d9262eae10649940da06008bb29321daf356b8d04c99baaa1372", - "1000000." - ], - [ - "c5862d23c205bff1e0854af06837d4730aecccf712ca9d2b9ed5188a48195b07", - "1000000." - ], - [ - "480e2c10fab3bcf1e67756f4e646e1a1b88ec73a47e51bdae7d914daf837b138", - "1000000." - ], - [ - "3f6690f34b4709c5b5a73c1bd6678fbda0b69681d5b26e497066b4afa412e263", - "1000000." - ], - [ - "149d7119bd8662b159ae393779d8e90b1c8584412ce10f73183ad30d37461bef", - "1000000." - ], - [ - "a760f53e84dc43426520217b6f150d863ee03aee8ee068e5e685122f9cc29ff4", - "1000000." - ], - [ - "5e6ac37eafa7a6e61f37d60829a202d2a517e26a46045659c35a2f531dd00e0e", - "1000000." - ] - ], - "policy": { - "block": "0.", - "fuel_unit": "0.", - "read_operation": "0.", - "write_operation": "0.", - "byte_read": "0.", - "byte_written": "0.", - "byte_stored": "0.", - "operation": "0.", - "operation_byte": "0.", - "message": "0.", - "message_byte": "0.", - "maximum_bytes_read_per_block": 18446744073709551615, - "maximum_bytes_written_per_block": 18446744073709551615 - }, - "network_name": "linera-test-2024-04-18T13:46:41" -} -"#; diff --git a/client-worker/src/lib.rs b/client-worker/src/lib.rs index ac8e113..dde4d47 100644 --- a/client-worker/src/lib.rs +++ b/client-worker/src/lib.rs @@ -9,38 +9,15 @@ connected_. Outside of their type, which is checked at call time, arguments to these functions cannot be trusted and _must_ be verified! */ -use linera_base::{ - crypto::{CryptoRng, CryptoHash, KeyPair, PublicKey}, - data_types::{Amount, BlockHeight, Timestamp}, - identifiers::{ - ChainDescription, - ChainId, - }, +use linera_core::node::{ + LocalValidatorNode as _, + LocalValidatorNodeProvider as _, }; -use linera_core::{ - client::{ArcChainClient, ChainClient, ChainClientBuilder}, - node::{ - LocalValidatorNode as _, - LocalValidatorNodeProvider as _, - }, -}; -use linera_rpc::node_provider::{NodeOptions, NodeProvider}; use wasm_bindgen::prelude::*; use web_sys::*; -use std::collections::{BTreeMap, HashMap}; -use std::sync::RwLock; -use std::time::Duration; - -mod config; -mod options; -mod wallet; - -use options::ClientOptions; -use wallet::Wallet; - -type ChainClients = std::collections::BTreeMap>; +use linera_client::{chain_listener::ClientContext as _, client_options::ClientOptions, wallet::Wallet}; // TODO convert to IndexedDbStore once we refactor Context type WebStorage = linera_storage::DbStorage< @@ -48,7 +25,7 @@ type WebStorage = linera_storage::DbStorage< linera_storage::WallClock, >; -pub async fn get_storage() -> Result::ContextError> { +pub async fn get_storage() -> Result::StoreError> { linera_storage::DbStorage::new( linera_views::memory::MemoryStoreConfig::new(1), "linera", @@ -56,141 +33,65 @@ pub async fn get_storage() -> Result, - send_timeout: Duration, - recv_timeout: Duration, - notification_retry_delay: Duration, - notification_retries: u32, - prng: Box, -} - -impl ClientContext { - fn wallet_state(&self) -> &WalletState { - &self.wallet_state - } - fn make_chain_client(&self, storage: S, chain_id: ChainId) -> ChainClient { - let chain = self - .wallet_state.0 - .get(chain_id) - .unwrap_or_else(|| panic!("Unknown chain: {}", chain_id)); - let known_key_pairs = chain - .key_pair - .as_ref() - .map(|kp| kp.copy()) - .into_iter() - .collect(); - self.chain_client_builder.build( - chain_id, - known_key_pairs, - storage, - self.wallet_state.0.genesis_admin_chain(), - chain.block_hash, - chain.timestamp, - chain.next_block_height, - chain.pending_block.clone(), - chain.pending_blobs.clone(), - ) - } +type PersistentWallet = linera_client::persistent::LocalStorage; +type ClientContext = linera_client::client_context::ClientContext; - fn update_wallet_for_new_chain( - &mut self, - chain_id: ChainId, - key_pair: Option, - timestamp: Timestamp, - ) { - if self.wallet_state.0.get(chain_id).is_none() { - self.wallet_state.0.insert(wallet::UserChain { - chain_id, - key_pair: key_pair.as_ref().map(|kp| kp.copy()), - block_hash: None, - timestamp, - next_block_height: BlockHeight::ZERO, - pending_block: None, - pending_blobs: BTreeMap::default(), - }); - } - } +// TODO get from config +pub const OPTIONS: ClientOptions = ClientOptions { + wallet_state_path: None, + storage_config: None, + with_wallet: None, - pub async fn update_and_save_wallet<'a, S>(&mut self, state: &mut ChainClient) - where - S: linera_storage::Storage + Clone + Send + Sync + 'static, - linera_views::views::ViewError: From, - { - self.wallet_state.0.update_from_state(state).await; - self.wallet_state.0.refresh_prng_seed(&mut self.prng); - self.wallet_state.write(); - } + // Timeout for sending queries (milliseconds) + send_timeout: std::time::Duration::from_millis(4000), + recv_timeout: std::time::Duration::from_millis(4000), + max_pending_messages: 10, + // The WebAssembly runtime to use. + wasm_runtime: None, + // The maximal number of simultaneous queries to the database + max_concurrent_queries: None, + // The maximal number of simultaneous stream queries to the database + max_stream_queries: 10, - pub fn make_node_provider(&self) -> NodeProvider { - NodeProvider::new(self.make_node_options()) - } + // The maximal number of entries in the storage cache. + cache_size: 1000, - fn make_node_options(&self) -> NodeOptions { - NodeOptions { - send_timeout: self.send_timeout, - recv_timeout: self.recv_timeout, - notification_retry_delay: self.notification_retry_delay, - notification_retries: self.notification_retries, - } - } -} + // Delay increment for retrying to connect to a validator for notifications. + notification_retry_delay: std::time::Duration::from_millis(1000), -pub async fn get_client_context(wallet: &Wallet) -> Result { - // TODO get from config - let options: ClientOptions = options::OPTIONS; - - Ok(ClientContext { - prng: wallet.make_prng(), - wallet_state: WalletState(wallet.copy()), - chain_client_builder: ChainClientBuilder::new( - NodeProvider::new(NodeOptions { - send_timeout: options.send_timeout, - recv_timeout: options.recv_timeout, - notification_retry_delay: options.notification_retry_delay, - notification_retries: options.notification_retries, - }), - options.max_pending_messages, - linera_core::node::CrossChainMessageDelivery::new(true), - ), - send_timeout: options.send_timeout, - recv_timeout: options.recv_timeout, - notification_retry_delay: options.notification_retry_delay, - notification_retries: options.notification_retries, - }) -} + // Number of times to retry connecting to a validator for notifications. + notification_retries: 10, -struct WalletState(Wallet); + // Whether to wait until a quorum of validators has confirmed that all sent cross-chain + // messages have been delivered. + wait_for_outgoing_messages: false, -impl WalletState { - fn refresh_prng_seed(&mut self) { - // TODO - } + // The policy for handling incoming messages. + message_policy: linera_core::client::MessagePolicy::Accept, - fn write(&self) { - // TODO - } -} + // A dummy command, for now + command: linera_client::client_options::ClientCommand::Keygen, -#[wasm_bindgen] -pub async fn dapp_query_validators() -> Result<(), JsError> { - let wallet = WALLET.read()?; - let wallet = wallet.as_ref().ok_or(JsError::new("no wallet set"))?; + tokio_threads: Some(1), +}; +pub async fn get_client_context() -> Result { + let wallet = linera_client::config::WalletState::read_from_local_storage("linera-wallet")?; let mut storage = get_storage().await?; - wallet.genesis_config().initialize_storage(&mut storage).await?; + Ok(ClientContext::new(get_storage().await?, OPTIONS, wallet)) +} - let chain_id = wallet.default_chain().expect("No default chain"); - - let mut client_context: ClientContext = get_client_context(wallet).await?; +#[wasm_bindgen] +pub async fn dapp_query_validators() -> Result<(), JsError> { + let mut client_context: ClientContext = get_client_context().await?; + let chain_id = client_context.wallet().default_chain().expect("No default chain"); - let mut chain_client = client_context.make_chain_client(storage, chain_id); + let mut chain_client = client_context.make_chain_client(chain_id); log::info!( "Querying the validators of the current epoch of chain {}", chain_id @@ -223,11 +124,9 @@ pub async fn dapp_query_validators() -> Result<(), JsError> { Ok(()) } -static WALLET: RwLock> = RwLock::new(None); - #[wasm_bindgen] pub async fn set_wallet(wallet: &str) -> Result<(), wasm_bindgen::JsError> { - *WALLET.write()? = serde_json::from_str(wallet)?; + linera_client::config::WalletState::create_from_local_storage("linera-wallet", serde_json::from_str(wallet)?)?; Ok(()) } @@ -240,7 +139,7 @@ pub async fn dapp_query(n: u32) -> u32 { pub async fn main() { std::panic::set_hook(Box::new(console_error_panic_hook::hook)); - console_log::init_with_level(log::Level::Debug); + console_log::init_with_level(log::Level::Debug).unwrap(); log::info!("Hello World!"); } diff --git a/client-worker/src/options.rs b/client-worker/src/options.rs deleted file mode 100644 index 283399c..0000000 --- a/client-worker/src/options.rs +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) Zefchain Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use std::{env, iter, num::NonZeroU16, path::PathBuf, time::Duration}; - -use anyhow::Error; -use chrono::{DateTime, Utc}; -use linera_base::{ - crypto::PublicKey, - data_types::{Amount, TimeDelta}, - identifiers::{Account, ApplicationId, BytecodeId, ChainId, MessageId, Owner}, - ownership::{ChainOwnership, TimeoutConfig}, -}; -use linera_core::client::MessagePolicy; -use linera_execution::{ - committee::ValidatorName, system::SystemChannel, UserApplicationId, WasmRuntime, - WithWasmDefault, -}; -use linera_views::common::CommonStoreConfig; - -pub struct ClientOptions { - /// Sets the file storing the private state of user chains (an empty one will be created if missing) - pub wallet_state_path: Option, - - /// Storage configuration for the blockchain history. - pub storage_config: Option, - - /// Given an integer value N, read the wallet state and the wallet storage config from the - /// environment variables LINERA_WALLET_{N} and LINERA_STORAGE_{N} instead of - /// LINERA_WALLET and LINERA_STORAGE. - pub with_wallet: Option, - - /// Timeout for sending queries (milliseconds) - pub send_timeout: Duration, - - /// Timeout for receiving responses (milliseconds) - pub recv_timeout: Duration, - - pub max_pending_messages: usize, - - /// The WebAssembly runtime to use. - pub wasm_runtime: Option, - - /// The maximal number of simultaneous queries to the database - pub max_concurrent_queries: Option, - - /// The maximal number of simultaneous stream queries to the database - pub max_stream_queries: usize, - - /// The maximal number of entries in the storage cache. - pub cache_size: usize, - - /// Delay increment for retrying to connect to a validator for notifications. - pub notification_retry_delay: Duration, - - /// Number of times to retry connecting to a validator for notifications. - pub notification_retries: u32, - - /// Whether to wait until a quorum of validators has confirmed that all sent cross-chain - /// messages have been delivered. - pub wait_for_outgoing_messages: bool, - - /// The policy for handling incoming messages. - pub message_policy: MessagePolicy, -} - -pub const OPTIONS: ClientOptions = ClientOptions { - wallet_state_path: None, - storage_config: None, - with_wallet: None, - - /// Timeout for sending queries (milliseconds) - send_timeout: std::time::Duration::from_millis(4000), - recv_timeout: std::time::Duration::from_millis(4000), - max_pending_messages: 10, - - /// The WebAssembly runtime to use. - wasm_runtime: None, - - /// The maximal number of simultaneous queries to the database - max_concurrent_queries: None, - - /// The maximal number of simultaneous stream queries to the database - max_stream_queries: 10, - - /// The maximal number of entries in the storage cache. - cache_size: 1000, - - /// Delay increment for retrying to connect to a validator for notifications. - notification_retry_delay: std::time::Duration::from_millis(1000), - - /// Number of times to retry connecting to a validator for notifications. - notification_retries: 10, - - /// Whether to wait until a quorum of validators has confirmed that all sent cross-chain - /// messages have been delivered. - wait_for_outgoing_messages: false, - - /// The policy for handling incoming messages. - message_policy: MessagePolicy::Accept, -}; diff --git a/client-worker/src/util.rs b/client-worker/src/util.rs deleted file mode 100644 index 9229db7..0000000 --- a/client-worker/src/util.rs +++ /dev/null @@ -1,22 +0,0 @@ -use js_sys::Promise; -use std::time::Duration; -use wasm_bindgen_futures::JsFuture; -use web_sys::window; - -pub async fn sleep(duration: Duration) { - JsFuture::from(Promise::new(&mut |yes, _| { - window() - .unwrap() - .set_timeout_with_callback_and_timeout_and_arguments_0( - &yes, - duration.as_millis() as i32, - ) - .unwrap(); - })).await.unwrap(); -} - -macro_rules! log { - ( $( $t:tt )* ) => { - web_sys::console::log_1(&format!( $( $t )* ).into()); - } -} diff --git a/client-worker/src/wallet.rs b/client-worker/src/wallet.rs deleted file mode 100644 index 7643cdf..0000000 --- a/client-worker/src/wallet.rs +++ /dev/null @@ -1,251 +0,0 @@ -// Copyright (c) Zefchain Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use std::collections::{BTreeMap, HashMap}; - -use anyhow::Context as _; -use linera_base::{ - crypto::{CryptoHash, CryptoRng, KeyPair, PublicKey}, - data_types::{BlockHeight, HashedBlob, Timestamp}, - identifiers::{BlobId, ChainDescription, ChainId, Owner}, -}; -use linera_chain::data_types::Block; -use linera_core::{client::ChainClient, node::LocalValidatorNodeProvider}; -use linera_storage::Storage; -use linera_views::views::ViewError; -use rand::Rng as _; -use serde::{Deserialize, Serialize}; - -use crate::config::GenesisConfig; - -#[derive(Serialize, Deserialize)] -pub struct Wallet { - chains: BTreeMap, - unassigned_key_pairs: HashMap, - default: Option, - genesis_config: GenesisConfig, - testing_prng_seed: Option, -} - -impl Wallet { - pub fn new(genesis_config: GenesisConfig, testing_prng_seed: Option) -> Self { - Wallet { - chains: BTreeMap::new(), - unassigned_key_pairs: HashMap::new(), - default: None, - genesis_config, - testing_prng_seed, - } - } - - pub fn copy(&self) -> Self { - Self { - chains: self.chains.iter().map(|(k, v)| (k.clone(), v.copy())).collect(), - unassigned_key_pairs: self.unassigned_key_pairs.iter().map(|(k, v)| (k.clone(), v.copy())).collect(), - default: self.default.clone(), - genesis_config: self.genesis_config.clone(), - testing_prng_seed: self.testing_prng_seed.clone(), - } - } - - pub fn get(&self, chain_id: ChainId) -> Option<&UserChain> { - self.chains.get(&chain_id) - } - - pub fn insert(&mut self, chain: UserChain) { - if self.chains.is_empty() { - self.default = Some(chain.chain_id); - } - self.chains.insert(chain.chain_id, chain); - } - - pub fn forget_keys(&mut self, chain_id: &ChainId) -> Result { - let chain = self - .chains - .get_mut(chain_id) - .context(format!("Failed to get chain for chain id: {}", chain_id))?; - chain.key_pair.take().context("Failed to take keypair") - } - - pub fn forget_chain(&mut self, chain_id: &ChainId) -> Result { - self.chains - .remove(chain_id) - .context(format!("Failed to remove chain: {}", chain_id)) - } - - pub fn default_chain(&self) -> Option { - self.default - } - - pub fn chain_ids(&self) -> Vec { - self.chains.keys().copied().collect() - } - - /// Returns the list of all chain IDs for which we have a secret key. - pub fn own_chain_ids(&self) -> Vec { - self.chains - .iter() - .filter_map(|(chain_id, chain)| chain.key_pair.is_some().then_some(*chain_id)) - .collect() - } - - pub fn num_chains(&self) -> usize { - self.chains.len() - } - - pub fn last_chain(&mut self) -> Option<&UserChain> { - self.chains.values().last() - } - - pub fn chains_mut(&mut self) -> impl Iterator { - self.chains.values_mut() - } - - pub fn add_unassigned_key_pair(&mut self, keypair: KeyPair) { - self.unassigned_key_pairs.insert(keypair.public(), keypair); - } - - pub fn key_pair_for_pk(&self, key: &PublicKey) -> Option { - if let Some(key_pair) = self - .unassigned_key_pairs - .get(key) - .map(|key_pair| key_pair.copy()) - { - return Some(key_pair); - } - self.chains - .values() - .filter_map(|user_chain| user_chain.key_pair.as_ref()) - .find(|key_pair| key_pair.public() == *key) - .map(|key_pair| key_pair.copy()) - } - - pub fn assign_new_chain_to_key( - &mut self, - key: PublicKey, - chain_id: ChainId, - timestamp: Timestamp, - ) -> Result<(), anyhow::Error> { - let key_pair = self - .unassigned_key_pairs - .remove(&key) - .context("could not assign chain to key as unassigned key was not found")?; - let user_chain = UserChain { - chain_id, - key_pair: Some(key_pair), - block_hash: None, - timestamp, - next_block_height: BlockHeight(0), - pending_block: None, - pending_blobs: BTreeMap::default(), - }; - self.insert(user_chain); - Ok(()) - } - - pub fn set_default_chain(&mut self, chain_id: ChainId) -> Result<(), anyhow::Error> { - anyhow::ensure!( - self.chains.contains_key(&chain_id), - "Chain {} cannot be assigned as the default chain since it does not exist in the \ - wallet.", - &chain_id - ); - self.default = Some(chain_id); - Ok(()) - } - - pub async fn update_from_state(&mut self, state: &mut ChainClient) - where - P: LocalValidatorNodeProvider + Sync + 'static, - S: Storage + Clone + Send + Sync + 'static, - ViewError: From, - { - self.chains.insert( - state.chain_id(), - UserChain { - chain_id: state.chain_id(), - key_pair: state.key_pair().await.map(|k| k.copy()).ok(), - block_hash: state.block_hash(), - next_block_height: state.next_block_height(), - timestamp: state.timestamp(), - pending_block: state.pending_block().clone(), - pending_blobs: state.pending_blobs().clone(), - }, - ); - } - - pub fn genesis_admin_chain(&self) -> ChainId { - self.genesis_config.admin_id - } - - pub fn genesis_config(&self) -> &GenesisConfig { - &self.genesis_config - } - - pub fn make_prng(&self) -> Box { - self.testing_prng_seed.into() - } - - pub fn refresh_prng_seed(&mut self, rng: &mut R) { - if self.testing_prng_seed.is_some() { - self.testing_prng_seed = Some(rng.gen()); - } - } -} - -#[derive(Serialize, Deserialize)] -pub struct UserChain { - pub chain_id: ChainId, - pub key_pair: Option, - pub block_hash: Option, - pub timestamp: Timestamp, - pub next_block_height: BlockHeight, - pub pending_block: Option, - pub pending_blobs: BTreeMap, -} - -impl UserChain { - /// Create a user chain that we own. - pub fn make_initial( - rng: &mut R, - description: ChainDescription, - timestamp: Timestamp, - ) -> Self { - let key_pair = KeyPair::generate_from(rng); - Self { - chain_id: description.into(), - key_pair: Some(key_pair), - block_hash: None, - timestamp, - next_block_height: BlockHeight::ZERO, - pending_block: None, - pending_blobs: BTreeMap::default(), - } - } - - pub fn copy(&self) -> Self { - Self { - chain_id: self.chain_id.clone(), - key_pair: self.key_pair.as_ref().map(KeyPair::copy), - block_hash: self.block_hash.clone(), - timestamp: self.timestamp.clone(), - next_block_height: self.next_block_height.clone(), - pending_block: self.pending_block.clone(), - pending_blobs: self.pending_blobs.clone(), - } - } - - /// Creates an entry for a chain that we don't own. The timestamp must be the genesis - /// timestamp or earlier. - pub fn make_other(chain_id: ChainId, timestamp: Timestamp) -> Self { - Self { - chain_id, - key_pair: None, - block_hash: None, - timestamp, - next_block_height: BlockHeight::ZERO, - pending_block: None, - pending_blobs: BTreeMap::default(), - } - } -} diff --git a/flake.lock b/flake.lock index 0e025ca..25740c9 100644 --- a/flake.lock +++ b/flake.lock @@ -5,11 +5,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1715274763, - "narHash": "sha256-3Iv1PGHJn9sV3HO4FlOVaaztOxa9uGLfOmUWrH7v7+A=", + "lastModified": 1721842668, + "narHash": "sha256-k3oiD2z2AAwBFLa4+xfU+7G5fisRXfkvrMTCJrjZzXo=", "owner": "ipetkov", "repo": "crane", - "rev": "27025ab71bdca30e7ed0a16c88fd74c5970fc7f5", + "rev": "529c1a0b1f29f0d78fa3086b8f6a134c71ef3aaf", "type": "github" }, "original": { @@ -23,11 +23,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1714641030, - "narHash": "sha256-yzcRNDoyVP7+SCNX0wmuDju1NUCt8Dz9+lyUXEI0dbI=", + "lastModified": 1722555600, + "narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "e5d10a24b66c3ea8f150e47dfdb0416ab7c3390e", + "rev": "8471fe90ad337a8074e957b69ca4d0089218391d", "type": "github" }, "original": { @@ -41,11 +41,11 @@ "nixpkgs-lib": "nixpkgs-lib_2" }, "locked": { - "lastModified": 1714641030, - "narHash": "sha256-yzcRNDoyVP7+SCNX0wmuDju1NUCt8Dz9+lyUXEI0dbI=", + "lastModified": 1719994518, + "narHash": "sha256-pQMhCCHyQGRzdfAkdJ4cIWiw+JNuWsTX7f0ZYSyz0VY=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "e5d10a24b66c3ea8f150e47dfdb0416ab7c3390e", + "rev": "9227223f6d922fee3c7b190b2cc238a99527bbb7", "type": "github" }, "original": { @@ -54,38 +54,23 @@ "type": "github" } }, - "flake-utils": { - "inputs": { - "systems": "systems" - }, - "locked": { - "lastModified": 1705309234, - "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, "linera-protocol": { "inputs": { "crane": "crane", "flake-parts": "flake-parts_2", "nixpkgs": "nixpkgs_2", "rust-overlay": "rust-overlay", - "systems": "systems_2", + "systems": "systems", "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1, - "narHash": "sha256-G7I7bdzkHd3MvK2HJ2Wic1Q7EN70Fr/lo1SSY6nBmF0=", - "path": "linera-protocol", - "type": "path" + "lastModified": 1723282050, + "narHash": "sha256-SoZn4OGKPGh4XlN7WZ+y0SX87hY1k2kvzTEjoF3VLzs=", + "ref": "fde6dc46fe0166ccac61b80610c0a09c476df25e", + "rev": "fde6dc46fe0166ccac61b80610c0a09c476df25e", + "revCount": 3347, + "type": "git", + "url": "file:///home/twey/dev/linera/web/main/linera-protocol" }, "original": { "path": "linera-protocol", @@ -94,11 +79,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1714656196, - "narHash": "sha256-kjQkA98lMcsom6Gbhw8SYzmwrSo+2nruiTcTZp5jK7o=", + "lastModified": 1721116560, + "narHash": "sha256-++TYlGMAJM1Q+0nMVaWBSEvEUjRs7ZGiNQOpqbQApCU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "94035b482d181af0a0f8f77823a790b256b7c3cc", + "rev": "9355fa86e6f27422963132c2c9aeedb0fb963d93", "type": "github" }, "original": { @@ -110,35 +95,35 @@ }, "nixpkgs-lib": { "locked": { - "lastModified": 1714640452, - "narHash": "sha256-QBx10+k6JWz6u7VsohfSw8g8hjdBZEf8CFzXH1/1Z94=", + "lastModified": 1722555339, + "narHash": "sha256-uFf2QeW7eAHlYXuDktm9c25OxOyCoUOQmh5SZ9amE5Q=", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/50eb7ecf4cd0a5756d7275c8ba36790e5bd53e33.tar.gz" + "url": "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz" }, "original": { "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/50eb7ecf4cd0a5756d7275c8ba36790e5bd53e33.tar.gz" + "url": "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz" } }, "nixpkgs-lib_2": { "locked": { - "lastModified": 1714640452, - "narHash": "sha256-QBx10+k6JWz6u7VsohfSw8g8hjdBZEf8CFzXH1/1Z94=", + "lastModified": 1719876945, + "narHash": "sha256-Fm2rDDs86sHy0/1jxTOKB1118Q0O3Uc7EC0iXvXKpbI=", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/50eb7ecf4cd0a5756d7275c8ba36790e5bd53e33.tar.gz" + "url": "https://github.com/NixOS/nixpkgs/archive/5daf0514482af3f97abaefc78a6606365c9108e2.tar.gz" }, "original": { "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/50eb7ecf4cd0a5756d7275c8ba36790e5bd53e33.tar.gz" + "url": "https://github.com/NixOS/nixpkgs/archive/5daf0514482af3f97abaefc78a6606365c9108e2.tar.gz" } }, "nixpkgs_2": { "locked": { - "lastModified": 1715447595, - "narHash": "sha256-VsVAUQOj/cS1LCOmMjAGeRksXIAdPnFIjCQ0XLkCsT0=", + "lastModified": 1722062969, + "narHash": "sha256-QOS0ykELUmPbrrUGmegAUlpmUFznDQeR4q7rFhl8eQg=", "owner": "nixos", "repo": "nixpkgs", - "rev": "062ca2a9370a27a35c524dc82d540e6e9824b652", + "rev": "b73c2221a46c13557b1b3be9c2070cc42cf01eb3", "type": "github" }, "original": { @@ -150,11 +135,11 @@ }, "nixpkgs_3": { "locked": { - "lastModified": 1706487304, - "narHash": "sha256-LE8lVX28MV2jWJsidW13D2qrHU/RUUONendL2Q/WlJg=", + "lastModified": 1718428119, + "narHash": "sha256-WdWDpNaq6u1IPtxtYHHWpl5BmabtpmLnMAx0RdJ/vo8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "90f456026d284c22b3e3497be980b2e47d0b28ac", + "rev": "e6cea36f83499eb4e9cd184c8a8e823296b50ad5", "type": "github" }, "original": { @@ -166,11 +151,11 @@ }, "nixpkgs_4": { "locked": { - "lastModified": 1708475490, - "narHash": "sha256-g1v0TsWBQPX97ziznfJdWhgMyMGtoBFs102xSYO4syU=", + "lastModified": 1720957393, + "narHash": "sha256-oedh2RwpjEa+TNxhg5Je9Ch6d3W1NKi7DbRO1ziHemA=", "owner": "nixos", "repo": "nixpkgs", - "rev": "0e74ca98a74bc7270d28838369593635a5db3260", + "rev": "693bc46d169f5af9c992095736e82c3488bf7dbb", "type": "github" }, "original": { @@ -182,11 +167,11 @@ }, "nixpkgs_5": { "locked": { - "lastModified": 1715534503, - "narHash": "sha256-5ZSVkFadZbFP1THataCaSf0JH2cAH3S29hU9rrxTEqk=", + "lastModified": 1723175592, + "narHash": "sha256-M0xJ3FbDUc4fRZ84dPGx5VvgFsOzds77KiBMW/mMTnI=", "owner": "nixos", "repo": "nixpkgs", - "rev": "2057814051972fa1453ddfb0d98badbea9b83c06", + "rev": "5e0ca22929f3342b19569b21b2f3462f053e497b", "type": "github" }, "original": { @@ -201,20 +186,19 @@ "flake-parts": "flake-parts", "linera-protocol": "linera-protocol", "nixpkgs": "nixpkgs_5", - "systems": "systems_3" + "systems": "systems_2" } }, "rust-overlay": { "inputs": { - "flake-utils": "flake-utils", "nixpkgs": "nixpkgs_3" }, "locked": { - "lastModified": 1715480255, - "narHash": "sha256-gEZl8nYidQwqJhOigJ91JDjoBFoPEWVsd82AKnaE7Go=", + "lastModified": 1722219664, + "narHash": "sha256-xMOJ+HW4yj6e69PvieohUJ3dBSdgCfvI0nnCEe6/yVc=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "d690205a4f01ec0930303c4204e5063958e51255", + "rev": "a6fbda5d9a14fb5f7c69b8489d24afeb349c7bb4", "type": "github" }, "original": { @@ -253,31 +237,16 @@ "type": "github" } }, - "systems_3": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, "treefmt-nix": { "inputs": { "nixpkgs": "nixpkgs_4" }, "locked": { - "lastModified": 1714058656, - "narHash": "sha256-Qv4RBm4LKuO4fNOfx9wl40W2rBbv5u5m+whxRYUMiaA=", + "lastModified": 1721769617, + "narHash": "sha256-6Pqa0bi5nV74IZcENKYRToRNM5obo1EQ+3ihtunJ014=", "owner": "numtide", "repo": "treefmt-nix", - "rev": "c6aaf729f34a36c445618580a9f95a48f5e4e03f", + "rev": "8db8970be1fb8be9c845af7ebec53b699fe7e009", "type": "github" }, "original": { diff --git a/linera-protocol b/linera-protocol index 11f9838..101bde3 160000 --- a/linera-protocol +++ b/linera-protocol @@ -1 +1 @@ -Subproject commit 11f9838ca7bd037490a84d905c8909c109f01895 +Subproject commit 101bde3d17bd0fe36d1418188c3f586305d43f58