diff --git a/.prettierrc b/.prettierrc index b302ba926..ea37ecbea 100644 --- a/.prettierrc +++ b/.prettierrc @@ -4,9 +4,10 @@ "useTabs": false, "semi": true, "singleQuote": false, + "quoteProps": "consistent", "trailingComma": "all", "bracketSpacing": true, "bracketSameLine": false, "arrowParens": "always", - "endOfLine": "auto" + "endOfLine": "lf" } diff --git a/Cargo.lock b/Cargo.lock index 267e5c71f..20c660369 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9500,7 +9500,6 @@ version = "0.5.3" dependencies = [ "anyhow", "async-trait", - "indexmap 2.2.6", "log", "tari_base_node_client", "tari_common_types", @@ -9566,6 +9565,7 @@ dependencies = [ "log4rs", "mime_guess", "minotari_app_utilities", + "rand", "reqwest", "serde", "serde_json", diff --git a/applications/tari_dan_app_utilities/src/base_layer_scanner.rs b/applications/tari_dan_app_utilities/src/base_layer_scanner.rs index ac5900c41..375d1f74c 100644 --- a/applications/tari_dan_app_utilities/src/base_layer_scanner.rs +++ b/applications/tari_dan_app_utilities/src/base_layer_scanner.rs @@ -31,11 +31,14 @@ use tari_base_node_client::{ }; use tari_common::configuration::Network; use tari_common_types::types::{Commitment, FixedHash, FixedHashSizeError, PublicKey}; -use tari_core::transactions::transaction_components::{ - CodeTemplateRegistration, - SideChainFeature, - TransactionOutput, - ValidatorNodeRegistration, +use tari_core::transactions::{ + tari_amount::MicroMinotari, + transaction_components::{ + CodeTemplateRegistration, + SideChainFeature, + TransactionOutput, + ValidatorNodeRegistration, + }, }; use tari_crypto::{ ristretto::RistrettoPublicKey, @@ -334,9 +337,20 @@ impl BaseLayerScanner { }; match sidechain_feature { SideChainFeature::ValidatorNodeRegistration(reg) => { + info!( + target: LOG_TARGET, + "⛓️ Validator node registration UTXO for {} sidechain {} found at height {}", + reg.public_key(), + reg.sidechain_id().map(|v| v.to_hex()).unwrap_or("None".to_string()), + current_height, + ); if reg.sidechain_id() == self.validator_node_sidechain_id.as_ref() { - self.register_validator_node_registration(current_height, reg.clone()) - .await?; + self.register_validator_node_registration( + current_height, + reg.clone(), + output.minimum_value_promise, + ) + .await?; } else { warn!( target: LOG_TARGET, @@ -465,6 +479,7 @@ impl BaseLayerScanner { &mut self, height: u64, registration: ValidatorNodeRegistration, + minimum_value_promise: MicroMinotari, ) -> Result<(), BaseLayerScannerError> { info!( target: LOG_TARGET, @@ -474,7 +489,7 @@ impl BaseLayerScanner { ); self.epoch_manager - .add_validator_node_registration(height, registration) + .add_validator_node_registration(height, registration, minimum_value_promise) .await?; Ok(()) diff --git a/applications/tari_indexer/Cargo.toml b/applications/tari_indexer/Cargo.toml index 94a9d22eb..fc57b4324 100644 --- a/applications/tari_indexer/Cargo.toml +++ b/applications/tari_indexer/Cargo.toml @@ -56,6 +56,7 @@ log4rs = { workspace = true, features = [ "fixed_window_roller", ] } mime_guess = { workspace = true } +rand = { workspace = true } reqwest = { workspace = true } serde = { workspace = true, features = ["default", "derive"] } serde_json = { workspace = true } diff --git a/applications/tari_indexer/src/dry_run/processor.rs b/applications/tari_indexer/src/dry_run/processor.rs index 5e5bf1c4b..1065c2bee 100644 --- a/applications/tari_indexer/src/dry_run/processor.rs +++ b/applications/tari_indexer/src/dry_run/processor.rs @@ -179,7 +179,7 @@ where TSubstateCache: SubstateCache + 'static address: SubstateAddress, epoch: Epoch, ) -> Result<(SubstateId, Substate), DryRunTransactionProcessorError> { - let mut committee = self.epoch_manager.get_committee(epoch, address).await?; + let mut committee = self.epoch_manager.get_committee_for_substate(epoch, address).await?; committee.shuffle(); let mut nexist_count = 0; diff --git a/applications/tari_indexer/src/event_manager.rs b/applications/tari_indexer/src/event_manager.rs index 4e5b120d2..c6891f047 100644 --- a/applications/tari_indexer/src/event_manager.rs +++ b/applications/tari_indexer/src/event_manager.rs @@ -22,22 +22,16 @@ use std::{ collections::{BTreeMap, HashSet}, - ops::RangeInclusive, str::FromStr, }; use futures::StreamExt; use log::*; +use rand::{prelude::SliceRandom, rngs::OsRng}; use tari_bor::decode; use tari_common::configuration::Network; use tari_crypto::tari_utilities::message_format::MessageFormat; -use tari_dan_common_types::{ - committee::{Committee, CommitteeShardInfo}, - shard::Shard, - Epoch, - PeerAddress, - SubstateAddress, -}; +use tari_dan_common_types::{committee::Committee, shard::Shard, Epoch, PeerAddress}; use tari_dan_p2p::proto::rpc::{GetTransactionResultRequest, PayloadResultStatus, SyncBlocksRequest}; use tari_dan_storage::consensus_models::{Block, BlockId, Command, Decision, TransactionRecord}; use tari_engine_types::{commit_result::ExecuteResult, events::Event, substate::SubstateId}; @@ -88,18 +82,20 @@ impl EventManager { let mut event_count = 0; - let network_committee_info = self.epoch_manager.get_network_committees().await?; - let epoch = network_committee_info.epoch; - for committee in network_committee_info.committees { + let current_epoch = self.epoch_manager.current_epoch().await?; + // let network_committee_info = self.epoch_manager.get_network_committees().await?; + // let epoch = network_committee_info.epoch; + let current_committees = self.epoch_manager.get_committees(current_epoch).await?; + for (shard, committee) in current_committees { info!( target: LOG_TARGET, "Scanning committee epoch={}, shard={}", - epoch, - committee.shard + current_epoch, + shard ); // TODO: use the latest block id that we scanned for each committee let new_blocks = self - .get_new_blocks_from_committee(&mut committee.clone(), epoch) + .get_new_blocks_from_committee(shard, &mut committee.clone(), current_epoch) .await?; info!( target: LOG_TARGET, @@ -185,7 +181,7 @@ impl EventManager { async fn get_events_for_transaction(&self, transaction_id: TransactionId) -> Result, anyhow::Error> { let committee = self.get_all_vns().await?; - for member in committee.addresses() { + for member in &committee { let resp = self.get_execute_result_from_vn(member, &transaction_id).await; match resp { @@ -274,18 +270,18 @@ impl EventManager { #[allow(unused_assignments)] async fn get_new_blocks_from_committee( &self, - committee: &mut CommitteeShardInfo, + shard: Shard, + committee: &mut Committee, epoch: Epoch, ) -> Result, anyhow::Error> { // We start scanning from the last scanned block for this commitee - let shard = committee.shard; let start_block_id = { let mut tx = self.substate_store.create_read_tx()?; tx.get_last_scanned_block_id(epoch, shard)? }; let start_block_id = start_block_id.unwrap_or(self.build_genesis_block_id()); - committee.validators.shuffle(); + committee.members.shuffle(&mut OsRng); let mut last_block_id = start_block_id; info!( @@ -296,7 +292,7 @@ impl EventManager { shard ); - for member in committee.validators.addresses() { + for (member, _) in &committee.members { let resp = self.get_blocks_from_vn(member, start_block_id).await; match resp { @@ -353,18 +349,14 @@ impl EventManager { Ok(()) } - async fn get_all_vns(&self) -> Result, anyhow::Error> { + async fn get_all_vns(&self) -> Result, anyhow::Error> { // get all the committees - // TODO: optimize by getting all individual CommiteeShards instead of all the VNs let epoch = self.epoch_manager.current_epoch().await?; - let full_range = RangeInclusive::new(SubstateAddress::zero(), SubstateAddress::max()); - let mut committee = self + Ok(self .epoch_manager - .get_committee_within_shard_range(epoch, full_range) - .await?; - committee.shuffle(); - - Ok(committee) + .get_all_validator_nodes(epoch) + .await + .map(|v| v.iter().map(|m| m.address).collect())?) } async fn get_blocks_from_vn( diff --git a/applications/tari_indexer/src/json_rpc/handlers.rs b/applications/tari_indexer/src/json_rpc/handlers.rs index fa3072cfe..ceb5a1644 100644 --- a/applications/tari_indexer/src/json_rpc/handlers.rs +++ b/applications/tari_indexer/src/json_rpc/handlers.rs @@ -29,7 +29,7 @@ use axum_jrpc::{ JsonRpcResponse, }; use libp2p::swarm::dial_opts::{DialOpts, PeerCondition}; -use log::{error, warn}; +use log::warn; use serde_json::{self as json, json, Value}; use tari_base_node_client::{grpc::GrpcBaseNodeClient, types::BaseLayerConsensusConstants, BaseNodeClient}; use tari_crypto::tari_utilities::hex::to_hex; @@ -780,12 +780,7 @@ impl JsonRpcHandlers { } fn internal_error(answer_id: i64, error: T) -> JsonRpcResponse { - let msg = if cfg!(debug_assertions) || option_env!("CI").is_some() { - error.to_string() - } else { - error!(target: LOG_TARGET, "Internal error: {}", error); - "Something went wrong".to_string() - }; + let msg = error.to_string(); Self::error_response(answer_id, JsonRpcErrorReason::InternalError, msg) } } diff --git a/applications/tari_indexer/src/transaction_manager/mod.rs b/applications/tari_indexer/src/transaction_manager/mod.rs index afcecf19f..0c616652b 100644 --- a/applications/tari_indexer/src/transaction_manager/mod.rs +++ b/applications/tari_indexer/src/transaction_manager/mod.rs @@ -172,7 +172,10 @@ where // Get all unique members. The hashset already "shuffles" items owing to the random hash function. let mut all_members = HashSet::new(); for substate_address in substate_addresses { - let committee = self.epoch_manager.get_committee(epoch, substate_address).await?; + let committee = self + .epoch_manager + .get_committee_for_substate(epoch, substate_address) + .await?; all_members.extend(committee.into_addresses()); } diff --git a/applications/tari_swarm_daemon/src/process_manager/executables/manager.rs b/applications/tari_swarm_daemon/src/process_manager/executables/manager.rs index 06b147776..63083ed5e 100644 --- a/applications/tari_swarm_daemon/src/process_manager/executables/manager.rs +++ b/applications/tari_swarm_daemon/src/process_manager/executables/manager.rs @@ -60,13 +60,7 @@ impl ExecutableManager { exec.instance_type, compile.working_dir().display() ); - let mut child = cargo_build( - compile - .working_dir() - .canonicalize() - .context("working_dir does not exist")?, - &compile.package_name, - )?; + let mut child = cargo_build(compile.working_dir(), &compile.package_name)?; tasks.push(async move { let status = child.wait().await?; Ok::<_, anyhow::Error>((status, exec)) @@ -93,9 +87,7 @@ impl ExecutableManager { self.prepared.push(Executable { instance_type: exec.instance_type, - path: add_ext(&bin_path) - .canonicalize() - .with_context(|| anyhow!("The compiled binary at path '{}' does not exist.", bin_path.display()))?, + path: add_ext(&bin_path), env: exec.env.clone(), }) } @@ -195,7 +187,7 @@ fn add_ext>(path: P) -> PathBuf { let path = path.as_ref().to_path_buf(); if cfg!(windows) { - path.with_extension(".exe") + path.with_extension("exe") } else { path } diff --git a/applications/tari_validator_node/src/consensus/state_manager.rs b/applications/tari_validator_node/src/consensus/state_manager.rs index cb4f0682d..8bd1790d3 100644 --- a/applications/tari_validator_node/src/consensus/state_manager.rs +++ b/applications/tari_validator_node/src/consensus/state_manager.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: BSD-3-Clause use tari_consensus::traits::StateManager; -use tari_dan_common_types::{committee::CommitteeShard, SubstateAddress}; +use tari_dan_common_types::{committee::CommitteeInfo, SubstateAddress}; use tari_dan_storage::{ consensus_models::{Block, ExecutedTransaction, SubstateRecord}, StateStore, @@ -25,7 +25,7 @@ impl StateManager for TariStateManager { tx: &mut TStateStore::WriteTransaction<'_>, block: &Block, transaction: &ExecutedTransaction, - local_committee_shard: &CommitteeShard, + local_committee_info: &CommitteeInfo, ) -> Result<(), Self::Error> { let Some(diff) = transaction.result().finalize.result.accept() else { // We should only commit accepted transactions, might want to change this API to reflect that @@ -35,7 +35,7 @@ impl StateManager for TariStateManager { let down_shards = diff .down_iter() .map(|(addr, version)| SubstateAddress::from_address(addr, *version)) - .filter(|shard| local_committee_shard.includes_substate_address(shard)); + .filter(|shard| local_committee_info.includes_substate_address(shard)); SubstateRecord::destroy_many( tx, down_shards, @@ -49,7 +49,7 @@ impl StateManager for TariStateManager { let to_up = diff.up_iter().filter_map(|(addr, substate)| { let address = SubstateAddress::from_address(addr, substate.version()); // Commit all substates included in this shard. Every involved validator commits the transaction receipt. - if local_committee_shard.includes_substate_address(&address) || addr.is_transaction_receipt() { + if local_committee_info.includes_substate_address(&address) || addr.is_transaction_receipt() { Some(SubstateRecord::new( addr.clone(), substate.version(), diff --git a/applications/tari_validator_node/src/json_rpc/handlers.rs b/applications/tari_validator_node/src/json_rpc/handlers.rs index fa328d78d..ae377616e 100644 --- a/applications/tari_validator_node/src/json_rpc/handlers.rs +++ b/applications/tari_validator_node/src/json_rpc/handlers.rs @@ -26,7 +26,6 @@ use axum_jrpc::{ JsonRpcExtractor, JsonRpcResponse, }; -use indexmap::IndexMap; use libp2p::swarm::dial_opts::{DialOpts, PeerCondition}; use log::*; use serde_json::{self as json, json}; @@ -47,7 +46,6 @@ use tari_validator_node_client::types::{ self, AddPeerRequest, AddPeerResponse, - CommitteeShardInfo, ConnectionDirection, DryRunTransactionFinalizeResult, GetAllVnsRequest, @@ -65,7 +63,6 @@ use tari_validator_node_client::types::{ GetFilteredBlocksCountRequest, GetIdentityResponse, GetMempoolStatsResponse, - GetNetworkCommitteeResponse, GetRecentTransactionsResponse, GetShardKeyRequest, GetShardKeyResponse, @@ -589,7 +586,7 @@ impl JsonRpcHandlers { })?; let committee_shard = self .epoch_manager - .get_local_committee_shard(current_epoch) + .get_local_committee_info(current_epoch) .await .map(Some) .or_else(|err| { @@ -611,7 +608,7 @@ impl JsonRpcHandlers { current_block_height, current_block_hash, is_valid: committee_shard.is_some(), - committee_shard, + committee_info: committee_shard, }; Ok(JsonRpcResponse::success(answer_id, response)) } @@ -696,7 +693,7 @@ impl JsonRpcHandlers { let request = value.parse_params::()?; if let Ok(committee) = self .epoch_manager - .get_committee(request.epoch, request.substate_address) + .get_committee_for_substate(request.epoch, request.substate_address) .await { Ok(JsonRpcResponse::success(answer_id, GetCommitteeResponse { committee })) @@ -712,54 +709,6 @@ impl JsonRpcHandlers { } } - pub async fn get_network_committees(&self, value: JsonRpcExtractor) -> JrpcResult { - let answer_id = value.get_answer_id(); - let current_epoch = self - .epoch_manager - .current_epoch() - .await - .map_err(internal_error(answer_id))?; - let num_committees = self - .epoch_manager - .get_num_committees(current_epoch) - .await - .map_err(internal_error(answer_id))?; - - let mut validators = self - .epoch_manager - .get_all_validator_nodes(current_epoch) - .await - .map_err(internal_error(answer_id))?; - - validators.sort_by(|vn_a, vn_b| vn_b.committee_shard.cmp(&vn_a.committee_shard)); - // Group by bucket, IndexMap used to preserve ordering - let mut validators_per_bucket = IndexMap::with_capacity(validators.len()); - for validator in validators { - validators_per_bucket - .entry( - validator - .committee_shard - .expect("validator committee bucket must have been populated within valid epoch"), - ) - .or_insert_with(Vec::new) - .push(validator); - } - - let committees = validators_per_bucket - .into_iter() - .map(|(bucket, validators)| CommitteeShardInfo { - shard: bucket, - substate_address_range: bucket.to_substate_address_range(num_committees), - validators: validators.into_iter().map(Into::into).collect(), - }) - .collect(); - - Ok(JsonRpcResponse::success(answer_id, GetNetworkCommitteeResponse { - current_epoch, - committees, - })) - } - pub async fn get_all_vns(&self, value: JsonRpcExtractor) -> JrpcResult { let answer_id = value.get_answer_id(); let GetAllVnsRequest { epoch } = value.parse_params::()?; diff --git a/applications/tari_validator_node/src/json_rpc/server.rs b/applications/tari_validator_node/src/json_rpc/server.rs index 2a367f608..dcfb68cc1 100644 --- a/applications/tari_validator_node/src/json_rpc/server.rs +++ b/applications/tari_validator_node/src/json_rpc/server.rs @@ -91,7 +91,7 @@ async fn handler(Extension(handlers): Extension>, value: Js "get_shard_key" => handlers.get_shard_key(value).await, "get_committee" => handlers.get_committee(value).await, "get_all_vns" => handlers.get_all_vns(value).await, - "get_network_committees" => handlers.get_network_committees(value).await, + // "get_network_committees" => handlers.get_network_committees(value).await, "get_fees" => handlers.get_validator_fees(value).await, // Comms "add_peer" => handlers.add_peer(value).await, diff --git a/applications/tari_validator_node/src/p2p/services/mempool/gossip.rs b/applications/tari_validator_node/src/p2p/services/mempool/gossip.rs index 96bc5a381..49163103d 100644 --- a/applications/tari_validator_node/src/p2p/services/mempool/gossip.rs +++ b/applications/tari_validator_node/src/p2p/services/mempool/gossip.rs @@ -36,7 +36,7 @@ impl MempoolGossip { } pub async fn subscribe(&mut self, epoch: Epoch) -> Result<(), MempoolError> { - let committee_shard = self.epoch_manager.get_local_committee_shard(epoch).await?; + let committee_shard = self.epoch_manager.get_local_committee_info(epoch).await?; match self.is_subscribed { Some(b) if b == committee_shard.shard() => { return Ok(()); @@ -63,7 +63,7 @@ impl MempoolGossip { } pub async fn forward_to_local_replicas(&mut self, epoch: Epoch, msg: DanMessage) -> Result<(), MempoolError> { - let committee = self.epoch_manager.get_local_committee_shard(epoch).await?; + let committee = self.epoch_manager.get_local_committee_info(epoch).await?; let topic = format!("transactions-{}", committee.shard()); debug!( @@ -85,7 +85,7 @@ impl MempoolGossip { exclude_shard: Option, ) -> Result<(), MempoolError> { let n = self.epoch_manager.get_num_committees(epoch).await?; - let committee_shard = self.epoch_manager.get_local_committee_shard(epoch).await?; + let committee_shard = self.epoch_manager.get_local_committee_info(epoch).await?; let local_shard = committee_shard.shard(); let shards = substate_addresses .into_iter() diff --git a/applications/tari_validator_node/src/p2p/services/mempool/service.rs b/applications/tari_validator_node/src/p2p/services/mempool/service.rs index cf2d23f24..8e1040357 100644 --- a/applications/tari_validator_node/src/p2p/services/mempool/service.rs +++ b/applications/tari_validator_node/src/p2p/services/mempool/service.rs @@ -269,17 +269,19 @@ where let num_committees = self.epoch_manager.get_num_committees(current_epoch).await?; let maybe_sender_shard = self .epoch_manager - .get_validator_node(current_epoch, &from) + .get_committee_info_by_validator_address(current_epoch, &from) .await .optional()? - .and_then(|s| s.committee_shard); + .map(|c| c.shard()); // Only input shards propagate transactions to output shards. Check that this is true. if !unverified_output_shards.is_empty() { let Some(sender_shard) = maybe_sender_shard else { - debug!(target: LOG_TARGET, "Sender {from} isn't registered but tried to send a new transaction with output shards"); + debug!(target: LOG_TARGET, "Sender {from} isn't registered but tried to send a new transaction with + output shards"); return Ok(()); }; + let mut is_input_shard = transaction .all_inputs_iter() .filter_map(|s| s.to_committee_shard(num_committees)) @@ -288,7 +290,8 @@ where // invalid, however we must support them for now because of CreateFreeTestCoin transactions. is_input_shard |= transaction.inputs().is_empty() && transaction.filled_inputs().is_empty(); if !is_input_shard { - warn!(target: LOG_TARGET, "Sender {from} sent a message with output shards but was not an input shard. Ignoring message."); + warn!(target: LOG_TARGET, "Sender {from} sent a message with output shards but was not an input + shard. Ignoring message."); return Ok(()); } } @@ -341,7 +344,7 @@ where let current_epoch = self.epoch_manager.current_epoch().await?; let tx_substate_address = SubstateAddress::for_transaction_receipt(transaction.id().into_receipt_address()); - let local_committee_shard = self.epoch_manager.get_local_committee_shard(current_epoch).await?; + let local_committee_shard = self.epoch_manager.get_local_committee_info(current_epoch).await?; let transaction_inputs = transaction.all_inputs_iter().filter_map(|i| i.to_substate_address()); let mut is_input_shard = local_committee_shard.includes_any_shard(transaction_inputs); // Special temporary case: if there are no input shards an output shard will also propagate. No inputs is @@ -672,7 +675,7 @@ where let current_epoch = self.epoch_manager.current_epoch().await?; - let local_committee_shard = self.epoch_manager.get_local_committee_shard(current_epoch).await?; + let local_committee_shard = self.epoch_manager.get_local_committee_info(current_epoch).await?; let all_inputs_iter = executed.all_inputs_iter().map(|i| i.to_substate_address()); let is_input_shard = local_committee_shard.includes_any_shard(all_inputs_iter) | (executed.transaction().inputs().is_empty() && executed.transaction().filled_inputs().is_empty()); diff --git a/applications/tari_validator_node/src/substate_resolver.rs b/applications/tari_validator_node/src/substate_resolver.rs index 4e1c6f10c..c72edaadd 100644 --- a/applications/tari_validator_node/src/substate_resolver.rs +++ b/applications/tari_validator_node/src/substate_resolver.rs @@ -268,7 +268,7 @@ where return Ok(virtual_substates); } - let local_committee_shard = self.epoch_manager.get_local_committee_shard(current_epoch).await?; + let local_committee_shard = self.epoch_manager.get_local_committee_info(current_epoch).await?; #[allow(clippy::mutable_key_type)] let validators = self .epoch_manager diff --git a/applications/tari_validator_node_web_ui/src/routes/Committees/Committee.tsx b/applications/tari_validator_node_web_ui/src/routes/Committees/Committee.tsx index 5343e1305..a499c5bbf 100644 --- a/applications/tari_validator_node_web_ui/src/routes/Committees/Committee.tsx +++ b/applications/tari_validator_node_web_ui/src/routes/Committees/Committee.tsx @@ -111,7 +111,7 @@ function Committee({ Public Keys {members.map((member) => (
- {member.address} (Registration Epoch: {member.epoch}) + {member.address}
))} diff --git a/applications/tari_validator_node_web_ui/src/routes/VN/Components/Info.tsx b/applications/tari_validator_node_web_ui/src/routes/VN/Components/Info.tsx index 66e532a68..6374c3b5c 100644 --- a/applications/tari_validator_node_web_ui/src/routes/VN/Components/Info.tsx +++ b/applications/tari_validator_node_web_ui/src/routes/VN/Components/Info.tsx @@ -110,22 +110,6 @@ function Info({ Public key {identity.public_key} - - Committee info - - {epoch.committee_shard ? ( - <> - Bucket: {epoch.committee_shard.shard} -
- Num committees: {epoch.committee_shard.num_committees} -
- Num members: {epoch.committee_shard.num_members} - - ) : ( - "Validator not registered" - )} -
-
{renderShardKey()} diff --git a/bindings/index.ts b/bindings/index.ts index 4dc1c1050..1e955c749 100644 --- a/bindings/index.ts +++ b/bindings/index.ts @@ -4,52 +4,52 @@ export * from "./src/types/AccessRule"; export * from "./src/types/Account"; export * from "./src/types/Amount"; -export * from "./src/types/ArgDef"; export * from "./src/types/Arg"; +export * from "./src/types/ArgDef"; export * from "./src/types/AuthHook"; export * from "./src/types/Block"; export * from "./src/types/BucketId"; export * from "./src/types/Claims"; export * from "./src/types/Command"; -export * from "./src/types/CommitteeShardInfo"; -export * from "./src/types/CommitteeShard"; export * from "./src/types/Committee"; +export * from "./src/types/CommitteeInfo"; +export * from "./src/types/CommitteeShardInfo"; export * from "./src/types/ComponentAccessRules"; export * from "./src/types/ComponentAddress"; export * from "./src/types/ComponentBody"; export * from "./src/types/ComponentHeader"; export * from "./src/types/ComponentKey"; export * from "./src/types/ConfidentialClaim"; -export * from "./src/types/ConfidentialOutputStatement"; export * from "./src/types/ConfidentialOutput"; +export * from "./src/types/ConfidentialOutputStatement"; export * from "./src/types/ConfidentialStatement"; export * from "./src/types/ConfidentialTransferInputSelection"; export * from "./src/types/ConfidentialWithdrawProof"; export * from "./src/types/Decision"; export * from "./src/types/ElgamalVerifiableBalance"; export * from "./src/types/EntityId"; -export * from "./src/types/EpochEvent"; export * from "./src/types/Epoch"; +export * from "./src/types/EpochEvent"; export * from "./src/types/Event"; export * from "./src/types/Evidence"; export * from "./src/types/ExecutedTransaction"; export * from "./src/types/ExecuteResult"; export * from "./src/types/FeeBreakdown"; -export * from "./src/types/FeeClaimAddress"; export * from "./src/types/FeeClaim"; +export * from "./src/types/FeeClaimAddress"; export * from "./src/types/FeeCostBreakdown"; export * from "./src/types/FeeReceipt"; export * from "./src/types/FeeSource"; export * from "./src/types/FinalizeResult"; -export * from "./src/types/ForeignProposalState"; export * from "./src/types/ForeignProposal"; +export * from "./src/types/ForeignProposalState"; export * from "./src/types/FunctionDef"; export * from "./src/types/IndexedValue"; export * from "./src/types/IndexedWellKnownTypes"; -export * from "./src/types/InstructionResult"; export * from "./src/types/Instruction"; -export * from "./src/types/JrpcPermissions"; +export * from "./src/types/InstructionResult"; export * from "./src/types/JrpcPermission"; +export * from "./src/types/JrpcPermissions"; export * from "./src/types/LeaderFee"; export * from "./src/types/LockFlag"; export * from "./src/types/LogEntry"; @@ -57,14 +57,14 @@ export * from "./src/types/LogLevel"; export * from "./src/types/Metadata"; export * from "./src/types/NetworkCommitteeInfo"; export * from "./src/types/NodeHeight"; -export * from "./src/types/NonFungibleAddressContents"; +export * from "./src/types/NonFungible"; export * from "./src/types/NonFungibleAddress"; +export * from "./src/types/NonFungibleAddressContents"; export * from "./src/types/NonFungibleContainer"; export * from "./src/types/NonFungibleId"; -export * from "./src/types/NonFungibleIndexAddress"; export * from "./src/types/NonFungibleIndex"; +export * from "./src/types/NonFungibleIndexAddress"; export * from "./src/types/NonFungibleToken"; -export * from "./src/types/NonFungible"; export * from "./src/types/Ordering"; export * from "./src/types/OwnerRule"; export * from "./src/types/PeerAddress"; @@ -73,15 +73,16 @@ export * from "./src/types/QuorumCertificate"; export * from "./src/types/QuorumDecision"; export * from "./src/types/RejectReason"; export * from "./src/types/RequireRule"; +export * from "./src/types/Resource"; export * from "./src/types/ResourceAccessRules"; export * from "./src/types/ResourceAddress"; export * from "./src/types/ResourceContainer"; -export * from "./src/types/Resource"; export * from "./src/types/ResourceType"; export * from "./src/types/RestrictedAccessRule"; export * from "./src/types/RuleRequirement"; -export * from "./src/types/ShardEvidence"; export * from "./src/types/Shard"; +export * from "./src/types/ShardEvidence"; +export * from "./src/types/Substate"; export * from "./src/types/SubstateAddress"; export * from "./src/types/SubstateDestroyed"; export * from "./src/types/SubstateDiff"; @@ -89,27 +90,26 @@ export * from "./src/types/SubstateId"; export * from "./src/types/SubstateLockFlag"; export * from "./src/types/SubstateRecord"; export * from "./src/types/SubstateRequirement"; -export * from "./src/types/Substate"; export * from "./src/types/SubstateType"; export * from "./src/types/SubstateValue"; export * from "./src/types/TemplateDef"; export * from "./src/types/TemplateDefV1"; +export * from "./src/types/Transaction"; export * from "./src/types/TransactionAtom"; export * from "./src/types/TransactionPoolRecord"; export * from "./src/types/TransactionPoolStage"; -export * from "./src/types/TransactionReceiptAddress"; export * from "./src/types/TransactionReceipt"; +export * from "./src/types/TransactionReceiptAddress"; export * from "./src/types/TransactionResult"; export * from "./src/types/TransactionSignature"; export * from "./src/types/TransactionStatus"; -export * from "./src/types/Transaction"; export * from "./src/types/Type"; export * from "./src/types/UnclaimedConfidentialOutput"; export * from "./src/types/UnsignedTransaction"; export * from "./src/types/ValidatorSignature"; -export * from "./src/types/VaultId"; export * from "./src/types/Vault"; -export * from "./src/types/VersionedSubstateIdLockIntent"; +export * from "./src/types/VaultId"; export * from "./src/types/VersionedSubstateId"; +export * from "./src/types/VersionedSubstateIdLockIntent"; export * from "./src/types/ViewableBalanceProof"; export * from "./src/helpers/helpers"; diff --git a/bindings/replace-backslash.ps1 b/bindings/replace-backslash.ps1 new file mode 100644 index 000000000..dccf94e0e --- /dev/null +++ b/bindings/replace-backslash.ps1 @@ -0,0 +1,19 @@ +# Set the directory path where TypeScript files are located +$directory = "./src" + +# Get all TypeScript files in the directory +$typescriptFiles = Get-ChildItem -Path $directory -Filter *.ts -Recurse + +# Loop through each TypeScript file +foreach ($file in $typescriptFiles) { + # Read the content of the file + $content = Get-Content -Path $file.FullName -Raw + + # Replace "\\" with "/" + $newContent = $content -replace "\\\\", "/" + + # Write the updated content back to the file + Set-Content -Path $file.FullName -Value $newContent +} + +Write-Host "Conversion completed." diff --git a/bindings/src/types/CommitteeShard.ts b/bindings/src/types/CommitteeInfo.ts similarity index 83% rename from bindings/src/types/CommitteeShard.ts rename to bindings/src/types/CommitteeInfo.ts index 26e7b3311..27c69baa1 100644 --- a/bindings/src/types/CommitteeShard.ts +++ b/bindings/src/types/CommitteeInfo.ts @@ -1,6 +1,6 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -export interface CommitteeShard { +export interface CommitteeInfo { num_committees: number; num_members: number; shard: number; diff --git a/bindings/src/types/ResourceContainer.ts b/bindings/src/types/ResourceContainer.ts index 3c7833294..b7d88c943 100644 --- a/bindings/src/types/ResourceContainer.ts +++ b/bindings/src/types/ResourceContainer.ts @@ -6,19 +6,19 @@ import type { ResourceAddress } from "./ResourceAddress"; export type ResourceContainer = | { Fungible: { address: ResourceAddress; amount: Amount; locked_amount: Amount } } | { - NonFungible: { - address: ResourceAddress; - token_ids: Array; - locked_token_ids: Array; - }; - } + NonFungible: { + address: ResourceAddress; + token_ids: Array; + locked_token_ids: Array; + }; +} | { - Confidential: { - address: ResourceAddress; - commitments: Record; - revealed_amount: Amount; - locked_commitments: Record; - locked_revealed_amount: Amount; - }; - }; -import { ConfidentialOutput } from "./ConfidentialOutput"; + Confidential: { + address: ResourceAddress; + commitments: Record; + revealed_amount: Amount; + locked_commitments: Record; + locked_revealed_amount: Amount; + }; +}; +import { ConfidentialOutput } from "./ConfidentialOutput"; \ No newline at end of file diff --git a/bindings/src/types/validator-node-client/GetEpochManagerStatsResponse.ts b/bindings/src/types/validator-node-client/GetEpochManagerStatsResponse.ts index da5a10216..3a835902f 100644 --- a/bindings/src/types/validator-node-client/GetEpochManagerStatsResponse.ts +++ b/bindings/src/types/validator-node-client/GetEpochManagerStatsResponse.ts @@ -1,5 +1,5 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -import type { CommitteeShard } from "../CommitteeShard"; +import type { CommitteeInfo } from "../CommitteeInfo"; import type { Epoch } from "../Epoch"; export interface GetEpochManagerStatsResponse { @@ -7,5 +7,5 @@ export interface GetEpochManagerStatsResponse { current_block_height: number; current_block_hash: string; is_valid: boolean; - committee_shard: CommitteeShard | null; + committee_info: CommitteeInfo | null; } diff --git a/bindings/src/types/validator-node-client/ValidatorNode.ts b/bindings/src/types/validator-node-client/ValidatorNode.ts index 8e7679b7f..47efb1591 100644 --- a/bindings/src/types/validator-node-client/ValidatorNode.ts +++ b/bindings/src/types/validator-node-client/ValidatorNode.ts @@ -6,7 +6,7 @@ export interface ValidatorNode { address: string; public_key: string; shard_key: SubstateAddress; - epoch: Epoch; - committee_shard: number | null; + start_epoch: Epoch; + end_epoch: Epoch; fee_claim_public_key: string; } diff --git a/bindings/tari-indexer-client.ts b/bindings/tari-indexer-client.ts index 80ed23028..90131a82e 100644 --- a/bindings/tari-indexer-client.ts +++ b/bindings/tari-indexer-client.ts @@ -1,40 +1,40 @@ // Copyright 2023 The Tari Project // SPDX-License-Identifier: BSD-3-Clause -export * from "./src/types/tari-indexer-client/GetTransactionResultRequest"; -export * from "./src/types/tari-indexer-client/GetSubstateRequest"; -export * from "./src/types/tari-indexer-client/GetTemplateDefinitionRequest"; -export * from "./src/types/tari-indexer-client/AddPeerResponse"; +export * from "./src/types/tari-indexer-client/AddAddressRequest"; +export * from "./src/types/tari-indexer-client/AddAddressResponse"; export * from "./src/types/tari-indexer-client/AddPeerRequest"; +export * from "./src/types/tari-indexer-client/AddPeerResponse"; +export * from "./src/types/tari-indexer-client/ClearAddressesResponse"; +export * from "./src/types/tari-indexer-client/Connection"; +export * from "./src/types/tari-indexer-client/ConnectionDirection"; +export * from "./src/types/tari-indexer-client/DeleteAddressRequest"; +export * from "./src/types/tari-indexer-client/DeleteAddressResponse"; +export * from "./src/types/tari-indexer-client/GetAddressesResponse"; +export * from "./src/types/tari-indexer-client/GetAllVnsRequest"; +export * from "./src/types/tari-indexer-client/GetAllVnsResponse"; export * from "./src/types/tari-indexer-client/GetCommsStatsResponse"; -export * from "./src/types/tari-indexer-client/GetIdentityResponse"; -export * from "./src/types/tari-indexer-client/InspectSubstateRequest"; -export * from "./src/types/tari-indexer-client/GetRelatedTransactionsResponse"; -export * from "./src/types/tari-indexer-client/GetTransactionResultResponse"; -export * from "./src/types/tari-indexer-client/IndexerTransactionFinalizedResult"; export * from "./src/types/tari-indexer-client/GetConnectionsResponse"; +export * from "./src/types/tari-indexer-client/GetEpochManagerStatsResponse"; +export * from "./src/types/tari-indexer-client/GetIdentityResponse"; +export * from "./src/types/tari-indexer-client/GetNonFungibleCollectionsResponse"; +export * from "./src/types/tari-indexer-client/GetNonFungibleCountRequest"; +export * from "./src/types/tari-indexer-client/GetNonFungibleCountResponse"; export * from "./src/types/tari-indexer-client/GetNonFungiblesRequest"; -export * from "./src/types/tari-indexer-client/GetAddressesResponse"; -export * from "./src/types/tari-indexer-client/ClearAddressesResponse"; -export * from "./src/types/tari-indexer-client/Connection"; -export * from "./src/types/tari-indexer-client/AddAddressRequest"; -export * from "./src/types/tari-indexer-client/GetRelatedTransactionsRequest"; export * from "./src/types/tari-indexer-client/GetNonFungiblesResponse"; -export * from "./src/types/tari-indexer-client/GetTemplateDefinitionResponse"; +export * from "./src/types/tari-indexer-client/GetRelatedTransactionsRequest"; +export * from "./src/types/tari-indexer-client/GetRelatedTransactionsResponse"; +export * from "./src/types/tari-indexer-client/GetSubstateRequest"; export * from "./src/types/tari-indexer-client/GetSubstateResponse"; -export * from "./src/types/tari-indexer-client/GetAllVnsRequest"; -export * from "./src/types/tari-indexer-client/ListTemplatesResponse"; -export * from "./src/types/tari-indexer-client/DeleteAddressRequest"; +export * from "./src/types/tari-indexer-client/GetTemplateDefinitionRequest"; +export * from "./src/types/tari-indexer-client/GetTemplateDefinitionResponse"; +export * from "./src/types/tari-indexer-client/GetTransactionResultRequest"; +export * from "./src/types/tari-indexer-client/GetTransactionResultResponse"; +export * from "./src/types/tari-indexer-client/IndexerTransactionFinalizedResult"; +export * from "./src/types/tari-indexer-client/InspectSubstateRequest"; export * from "./src/types/tari-indexer-client/InspectSubstateResponse"; -export * from "./src/types/tari-indexer-client/GetNonFungibleCollectionsResponse"; -export * from "./src/types/tari-indexer-client/AddAddressResponse"; -export * from "./src/types/tari-indexer-client/NonFungibleSubstate"; -export * from "./src/types/tari-indexer-client/GetNonFungibleCountResponse"; export * from "./src/types/tari-indexer-client/ListTemplatesRequest"; +export * from "./src/types/tari-indexer-client/ListTemplatesResponse"; +export * from "./src/types/tari-indexer-client/NonFungibleSubstate"; export * from "./src/types/tari-indexer-client/SubmitTransactionRequest"; -export * from "./src/types/tari-indexer-client/ConnectionDirection"; -export * from "./src/types/tari-indexer-client/GetEpochManagerStatsResponse"; -export * from "./src/types/tari-indexer-client/DeleteAddressResponse"; export * from "./src/types/tari-indexer-client/SubmitTransactionResponse"; -export * from "./src/types/tari-indexer-client/GetNonFungibleCountRequest"; -export * from "./src/types/tari-indexer-client/GetAllVnsResponse"; diff --git a/bindings/tsconfig.json b/bindings/tsconfig.json index a27fffd81..3e27698b9 100644 --- a/bindings/tsconfig.json +++ b/bindings/tsconfig.json @@ -4,7 +4,7 @@ "target": "ESNext", "moduleResolution": "Bundler", "declaration": true, - "outDir": "./dist", + "outDir": "./dist" }, - "include": ["src/**/*"], + "include": ["src/**/*"] } diff --git a/bindings/validator-node-client.ts b/bindings/validator-node-client.ts index b2f8e4472..dcfc2a650 100644 --- a/bindings/validator-node-client.ts +++ b/bindings/validator-node-client.ts @@ -1,59 +1,59 @@ // Copyright 2023 The Tari Project // SPDX-License-Identifier: BSD-3-Clause -export * from "./src/types/validator-node-client/GetTransactionResultRequest"; -export * from "./src/types/validator-node-client/GetSubstateRequest"; -export * from "./src/types/validator-node-client/TemplateMetadata"; +export * from "./src/types/validator-node-client/AddPeerRequest"; export * from "./src/types/validator-node-client/AddPeerResponse"; export * from "./src/types/validator-node-client/ArgDef"; -export * from "./src/types/validator-node-client/GetFilteredBlocksCountRequest"; -export * from "./src/types/validator-node-client/GetShardKeyRequest"; -export * from "./src/types/validator-node-client/AddPeerRequest"; -export * from "./src/types/validator-node-client/GetCommsStatsResponse"; -export * from "./src/types/validator-node-client/GetIdentityResponse"; -export * from "./src/types/validator-node-client/GetTxPoolResponse"; -export * from "./src/types/validator-node-client/GetTemplateResponse"; +export * from "./src/types/validator-node-client/CommitteeShardInfo"; +export * from "./src/types/validator-node-client/Connection"; +export * from "./src/types/validator-node-client/ConnectionDirection"; +export * from "./src/types/validator-node-client/DryRunTransactionFinalizeResult"; export * from "./src/types/validator-node-client/FunctionDef"; +export * from "./src/types/validator-node-client/GetAllVnsRequest"; +export * from "./src/types/validator-node-client/GetAllVnsResponse"; +export * from "./src/types/validator-node-client/GetBlockRequest"; +export * from "./src/types/validator-node-client/GetBlockResponse"; export * from "./src/types/validator-node-client/GetBlocksCountResponse"; -export * from "./src/types/validator-node-client/VNGetValidatorFeesRequest"; -export * from "./src/types/validator-node-client/GetSubstatesByTransactionResponse"; -export * from "./src/types/validator-node-client/GetTransactionResultResponse"; -export * from "./src/types/validator-node-client/GetTemplatesResponse"; -export * from "./src/types/validator-node-client/GetTransactionRequest"; -export * from "./src/types/validator-node-client/GetStateRequest"; -export * from "./src/types/validator-node-client/GetConnectionsResponse"; export * from "./src/types/validator-node-client/GetBlocksRequest"; -export * from "./src/types/validator-node-client/Connection"; -export * from "./src/types/validator-node-client/GetTemplateRequest"; +export * from "./src/types/validator-node-client/GetBlocksResponse"; +export * from "./src/types/validator-node-client/GetCommitteeRequest"; +export * from "./src/types/validator-node-client/GetCommitteeResponse"; +export * from "./src/types/validator-node-client/GetCommsStatsResponse"; +export * from "./src/types/validator-node-client/GetConnectionsResponse"; +export * from "./src/types/validator-node-client/GetEpochManagerStatsResponse"; +export * from "./src/types/validator-node-client/GetFilteredBlocksCountRequest"; +export * from "./src/types/validator-node-client/GetIdentityResponse"; +export * from "./src/types/validator-node-client/GetMempoolStatsResponse"; +export * from "./src/types/validator-node-client/GetNetworkCommitteeResponse"; +export * from "./src/types/validator-node-client/GetRecentTransactionsRequest"; +export * from "./src/types/validator-node-client/GetRecentTransactionsResponse"; +export * from "./src/types/validator-node-client/GetShardKeyRequest"; export * from "./src/types/validator-node-client/GetShardKeyResponse"; +export * from "./src/types/validator-node-client/GetStateRequest"; +export * from "./src/types/validator-node-client/GetStateResponse"; +export * from "./src/types/validator-node-client/GetSubstateRequest"; +export * from "./src/types/validator-node-client/GetSubstateResponse"; export * from "./src/types/validator-node-client/GetSubstatesByTransactionRequest"; +export * from "./src/types/validator-node-client/GetSubstatesByTransactionResponse"; +export * from "./src/types/validator-node-client/GetTemplateRequest"; +export * from "./src/types/validator-node-client/GetTemplateResponse"; +export * from "./src/types/validator-node-client/GetTemplatesRequest"; +export * from "./src/types/validator-node-client/GetTemplatesResponse"; +export * from "./src/types/validator-node-client/GetTransactionRequest"; export * from "./src/types/validator-node-client/GetTransactionResponse"; -export * from "./src/types/validator-node-client/CommitteeShardInfo"; -export * from "./src/types/validator-node-client/GetCommitteeResponse"; -export * from "./src/types/validator-node-client/GetCommitteeRequest"; +export * from "./src/types/validator-node-client/GetTransactionResultRequest"; +export * from "./src/types/validator-node-client/GetTransactionResultResponse"; +export * from "./src/types/validator-node-client/GetTxPoolResponse"; +export * from "./src/types/validator-node-client/ListBlocksRequest"; +export * from "./src/types/validator-node-client/ListBlocksResponse"; export * from "./src/types/validator-node-client/LogEntry"; -export * from "./src/types/validator-node-client/GetSubstateResponse"; -export * from "./src/types/validator-node-client/DryRunTransactionFinalizeResult"; -export * from "./src/types/validator-node-client/VNGetValidatorFeesResponse"; -export * from "./src/types/validator-node-client/GetStateResponse"; +export * from "./src/types/validator-node-client/LogLevel"; +export * from "./src/types/validator-node-client/SubmitTransactionRequest"; +export * from "./src/types/validator-node-client/SubmitTransactionResponse"; export * from "./src/types/validator-node-client/SubstateStatus"; -export * from "./src/types/validator-node-client/GetAllVnsRequest"; -export * from "./src/types/validator-node-client/GetBlocksResponse"; -export * from "./src/types/validator-node-client/ListBlocksResponse"; -export * from "./src/types/validator-node-client/GetBlockRequest"; -export * from "./src/types/validator-node-client/GetRecentTransactionsRequest"; +export * from "./src/types/validator-node-client/TemplateAbi"; +export * from "./src/types/validator-node-client/TemplateMetadata"; export * from "./src/types/validator-node-client/ValidatorFee"; -export * from "./src/types/validator-node-client/GetRecentTransactionsResponse"; export * from "./src/types/validator-node-client/ValidatorNode"; -export * from "./src/types/validator-node-client/SubmitTransactionRequest"; -export * from "./src/types/validator-node-client/ListBlocksRequest"; -export * from "./src/types/validator-node-client/GetNetworkCommitteeResponse"; -export * from "./src/types/validator-node-client/GetMempoolStatsResponse"; -export * from "./src/types/validator-node-client/TemplateAbi"; -export * from "./src/types/validator-node-client/GetTemplatesRequest"; -export * from "./src/types/validator-node-client/ConnectionDirection"; -export * from "./src/types/validator-node-client/GetEpochManagerStatsResponse"; -export * from "./src/types/validator-node-client/GetBlockResponse"; -export * from "./src/types/validator-node-client/LogLevel"; -export * from "./src/types/validator-node-client/SubmitTransactionResponse"; -export * from "./src/types/validator-node-client/GetAllVnsResponse"; +export * from "./src/types/validator-node-client/VNGetValidatorFeesRequest"; +export * from "./src/types/validator-node-client/VNGetValidatorFeesResponse"; diff --git a/bindings/wallet-daemon-client.ts b/bindings/wallet-daemon-client.ts index 5074b222e..23c53dae4 100644 --- a/bindings/wallet-daemon-client.ts +++ b/bindings/wallet-daemon-client.ts @@ -1,90 +1,90 @@ // Copyright 2023 The Tari Project // SPDX-License-Identifier: BSD-3-Clause -export * from "./src/types/wallet-daemon-client/WalletSubstateRecord"; -export * from "./src/types/wallet-daemon-client/ProofsFinalizeResponse"; -export * from "./src/types/wallet-daemon-client/CallInstructionRequest"; -export * from "./src/types/wallet-daemon-client/AuthLoginAcceptResponse"; -export * from "./src/types/wallet-daemon-client/AccountsListRequest"; -export * from "./src/types/wallet-daemon-client/AuthGetAllJwtResponse"; -export * from "./src/types/wallet-daemon-client/AuthLoginResponse"; -export * from "./src/types/wallet-daemon-client/GetValidatorFeesRequest"; export * from "./src/types/wallet-daemon-client/AccountGetDefaultRequest"; -export * from "./src/types/wallet-daemon-client/AuthGetAllJwtRequest"; -export * from "./src/types/wallet-daemon-client/KeyBranch"; +export * from "./src/types/wallet-daemon-client/AccountGetRequest"; export * from "./src/types/wallet-daemon-client/AccountGetResponse"; -export * from "./src/types/wallet-daemon-client/SettingsSetRequest"; -export * from "./src/types/wallet-daemon-client/GetValidatorFeesResponse"; -export * from "./src/types/wallet-daemon-client/TransactionGetAllRequest"; -export * from "./src/types/wallet-daemon-client/RevealFundsRequest"; -export * from "./src/types/wallet-daemon-client/AuthLoginDenyResponse"; +export * from "./src/types/wallet-daemon-client/AccountInfo"; +export * from "./src/types/wallet-daemon-client/AccountsCreateFreeTestCoinsRequest"; +export * from "./src/types/wallet-daemon-client/AccountsCreateFreeTestCoinsResponse"; +export * from "./src/types/wallet-daemon-client/AccountsCreateRequest"; +export * from "./src/types/wallet-daemon-client/AccountsCreateResponse"; +export * from "./src/types/wallet-daemon-client/AccountSetDefaultRequest"; +export * from "./src/types/wallet-daemon-client/AccountSetDefaultResponse"; +export * from "./src/types/wallet-daemon-client/AccountsGetBalancesRequest"; +export * from "./src/types/wallet-daemon-client/AccountsGetBalancesResponse"; +export * from "./src/types/wallet-daemon-client/AccountsInvokeRequest"; +export * from "./src/types/wallet-daemon-client/AccountsInvokeResponse"; +export * from "./src/types/wallet-daemon-client/AccountsListRequest"; +export * from "./src/types/wallet-daemon-client/AccountsListResponse"; +export * from "./src/types/wallet-daemon-client/AccountsTransferRequest"; +export * from "./src/types/wallet-daemon-client/AccountsTransferResponse"; +export * from "./src/types/wallet-daemon-client/AuthGetAllJwtRequest"; +export * from "./src/types/wallet-daemon-client/AuthGetAllJwtResponse"; +export * from "./src/types/wallet-daemon-client/AuthLoginAcceptRequest"; +export * from "./src/types/wallet-daemon-client/AuthLoginAcceptResponse"; export * from "./src/types/wallet-daemon-client/AuthLoginDenyRequest"; -export * from "./src/types/wallet-daemon-client/TransactionSubmitResponse"; -export * from "./src/types/wallet-daemon-client/ProofsGenerateResponse"; -export * from "./src/types/wallet-daemon-client/ClaimValidatorFeesRequest"; +export * from "./src/types/wallet-daemon-client/AuthLoginDenyResponse"; export * from "./src/types/wallet-daemon-client/AuthLoginRequest"; -export * from "./src/types/wallet-daemon-client/ListAccountNftRequest"; -export * from "./src/types/wallet-daemon-client/TransactionGetRequest"; +export * from "./src/types/wallet-daemon-client/AuthLoginResponse"; +export * from "./src/types/wallet-daemon-client/AuthRevokeTokenRequest"; export * from "./src/types/wallet-daemon-client/AuthRevokeTokenResponse"; -export * from "./src/types/wallet-daemon-client/ProofsFinalizeRequest"; -export * from "./src/types/wallet-daemon-client/AccountsTransferRequest"; -export * from "./src/types/wallet-daemon-client/SettingsSetResponse"; -export * from "./src/types/wallet-daemon-client/KeysListRequest"; -export * from "./src/types/wallet-daemon-client/AccountsTransferResponse"; -export * from "./src/types/wallet-daemon-client/TransactionGetResultResponse"; +export * from "./src/types/wallet-daemon-client/BalanceEntry"; +export * from "./src/types/wallet-daemon-client/CallInstructionRequest"; export * from "./src/types/wallet-daemon-client/ClaimBurnRequest"; -export * from "./src/types/wallet-daemon-client/KeysListResponse"; -export * from "./src/types/wallet-daemon-client/SubstatesGetRequest"; -export * from "./src/types/wallet-daemon-client/TransactionSubmitRequest"; -export * from "./src/types/wallet-daemon-client/AccountsGetBalancesResponse"; -export * from "./src/types/wallet-daemon-client/TransactionGetAllResponse"; -export * from "./src/types/wallet-daemon-client/AccountsCreateFreeTestCoinsResponse"; -export * from "./src/types/wallet-daemon-client/ConfidentialTransferResponse"; -export * from "./src/types/wallet-daemon-client/TransactionGetResponse"; -export * from "./src/types/wallet-daemon-client/SubstatesGetResponse"; -export * from "./src/types/wallet-daemon-client/GetAccountNftRequest"; -export * from "./src/types/wallet-daemon-client/AuthRevokeTokenRequest"; -export * from "./src/types/wallet-daemon-client/ProofsGenerateRequest"; -export * from "./src/types/wallet-daemon-client/RevealFundsResponse"; -export * from "./src/types/wallet-daemon-client/AccountsInvokeResponse"; -export * from "./src/types/wallet-daemon-client/AccountsListResponse"; -export * from "./src/types/wallet-daemon-client/WebRtcStartResponse"; -export * from "./src/types/wallet-daemon-client/TransactionGetResultRequest"; -export * from "./src/types/wallet-daemon-client/ProofsCancelResponse"; -export * from "./src/types/wallet-daemon-client/AccountsCreateRequest"; -export * from "./src/types/wallet-daemon-client/MintAccountNftRequest"; -export * from "./src/types/wallet-daemon-client/TransactionClaimBurnResponse"; -export * from "./src/types/wallet-daemon-client/TransactionWaitResultRequest"; +export * from "./src/types/wallet-daemon-client/ClaimBurnResponse"; +export * from "./src/types/wallet-daemon-client/ClaimValidatorFeesRequest"; export * from "./src/types/wallet-daemon-client/ClaimValidatorFeesResponse"; +export * from "./src/types/wallet-daemon-client/ComponentAddressOrName"; export * from "./src/types/wallet-daemon-client/ConfidentialCreateOutputProofRequest"; -export * from "./src/types/wallet-daemon-client/KeysCreateRequest"; -export * from "./src/types/wallet-daemon-client/SettingsGetResponse"; -export * from "./src/types/wallet-daemon-client/ClaimBurnResponse"; -export * from "./src/types/wallet-daemon-client/WebRtcStartRequest"; -export * from "./src/types/wallet-daemon-client/ConfidentialViewVaultBalanceResponse"; -export * from "./src/types/wallet-daemon-client/WebRtcStart"; -export * from "./src/types/wallet-daemon-client/AccountSetDefaultRequest"; export * from "./src/types/wallet-daemon-client/ConfidentialCreateOutputProofResponse"; -export * from "./src/types/wallet-daemon-client/TemplatesGetResponse"; +export * from "./src/types/wallet-daemon-client/ConfidentialTransferRequest"; +export * from "./src/types/wallet-daemon-client/ConfidentialTransferResponse"; +export * from "./src/types/wallet-daemon-client/ConfidentialViewVaultBalanceRequest"; +export * from "./src/types/wallet-daemon-client/ConfidentialViewVaultBalanceResponse"; +export * from "./src/types/wallet-daemon-client/GetAccountNftRequest"; +export * from "./src/types/wallet-daemon-client/GetValidatorFeesRequest"; +export * from "./src/types/wallet-daemon-client/GetValidatorFeesResponse"; +export * from "./src/types/wallet-daemon-client/KeyBranch"; +export * from "./src/types/wallet-daemon-client/KeysCreateRequest"; +export * from "./src/types/wallet-daemon-client/KeysCreateResponse"; +export * from "./src/types/wallet-daemon-client/KeysListRequest"; +export * from "./src/types/wallet-daemon-client/KeysListResponse"; +export * from "./src/types/wallet-daemon-client/KeysSetActiveRequest"; +export * from "./src/types/wallet-daemon-client/KeysSetActiveResponse"; +export * from "./src/types/wallet-daemon-client/ListAccountNftRequest"; export * from "./src/types/wallet-daemon-client/ListAccountNftResponse"; -export * from "./src/types/wallet-daemon-client/AccountsGetBalancesRequest"; +export * from "./src/types/wallet-daemon-client/MintAccountNftRequest"; export * from "./src/types/wallet-daemon-client/MintAccountNftResponse"; -export * from "./src/types/wallet-daemon-client/AccountsCreateFreeTestCoinsRequest"; -export * from "./src/types/wallet-daemon-client/KeysCreateResponse"; -export * from "./src/types/wallet-daemon-client/AccountInfo"; -export * from "./src/types/wallet-daemon-client/SubstatesListRequest"; -export * from "./src/types/wallet-daemon-client/BalanceEntry"; -export * from "./src/types/wallet-daemon-client/TemplatesGetRequest"; -export * from "./src/types/wallet-daemon-client/AccountsInvokeRequest"; export * from "./src/types/wallet-daemon-client/ProofsCancelRequest"; -export * from "./src/types/wallet-daemon-client/AccountSetDefaultResponse"; +export * from "./src/types/wallet-daemon-client/ProofsCancelResponse"; +export * from "./src/types/wallet-daemon-client/ProofsFinalizeRequest"; +export * from "./src/types/wallet-daemon-client/ProofsFinalizeResponse"; +export * from "./src/types/wallet-daemon-client/ProofsGenerateRequest"; +export * from "./src/types/wallet-daemon-client/ProofsGenerateResponse"; +export * from "./src/types/wallet-daemon-client/RevealFundsRequest"; +export * from "./src/types/wallet-daemon-client/RevealFundsResponse"; +export * from "./src/types/wallet-daemon-client/SettingsGetResponse"; +export * from "./src/types/wallet-daemon-client/SettingsSetRequest"; +export * from "./src/types/wallet-daemon-client/SettingsSetResponse"; +export * from "./src/types/wallet-daemon-client/SubstatesGetRequest"; +export * from "./src/types/wallet-daemon-client/SubstatesGetResponse"; +export * from "./src/types/wallet-daemon-client/SubstatesListRequest"; export * from "./src/types/wallet-daemon-client/SubstatesListResponse"; -export * from "./src/types/wallet-daemon-client/KeysSetActiveResponse"; -export * from "./src/types/wallet-daemon-client/ComponentAddressOrName"; -export * from "./src/types/wallet-daemon-client/AuthLoginAcceptRequest"; -export * from "./src/types/wallet-daemon-client/KeysSetActiveRequest"; -export * from "./src/types/wallet-daemon-client/ConfidentialViewVaultBalanceRequest"; -export * from "./src/types/wallet-daemon-client/ConfidentialTransferRequest"; -export * from "./src/types/wallet-daemon-client/AccountsCreateResponse"; +export * from "./src/types/wallet-daemon-client/TemplatesGetRequest"; +export * from "./src/types/wallet-daemon-client/TemplatesGetResponse"; +export * from "./src/types/wallet-daemon-client/TransactionClaimBurnResponse"; +export * from "./src/types/wallet-daemon-client/TransactionGetAllRequest"; +export * from "./src/types/wallet-daemon-client/TransactionGetAllResponse"; +export * from "./src/types/wallet-daemon-client/TransactionGetRequest"; +export * from "./src/types/wallet-daemon-client/TransactionGetResponse"; +export * from "./src/types/wallet-daemon-client/TransactionGetResultRequest"; +export * from "./src/types/wallet-daemon-client/TransactionGetResultResponse"; +export * from "./src/types/wallet-daemon-client/TransactionSubmitRequest"; +export * from "./src/types/wallet-daemon-client/TransactionSubmitResponse"; +export * from "./src/types/wallet-daemon-client/TransactionWaitResultRequest"; export * from "./src/types/wallet-daemon-client/TransactionWaitResultResponse"; -export * from "./src/types/wallet-daemon-client/AccountGetRequest"; +export * from "./src/types/wallet-daemon-client/WalletSubstateRecord"; +export * from "./src/types/wallet-daemon-client/WebRtcStart"; +export * from "./src/types/wallet-daemon-client/WebRtcStartRequest"; +export * from "./src/types/wallet-daemon-client/WebRtcStartResponse"; diff --git a/clients/validator_node_client/src/types.rs b/clients/validator_node_client/src/types.rs index 4ea069b80..a0c3f219e 100644 --- a/clients/validator_node_client/src/types.rs +++ b/clients/validator_node_client/src/types.rs @@ -27,7 +27,7 @@ use serde::{Deserialize, Serialize}; use tari_base_node_client::types::BaseLayerValidatorNode; use tari_common_types::types::{FixedHash, PublicKey}; use tari_dan_common_types::{ - committee::{Committee, CommitteeShard}, + committee::{Committee, CommitteeInfo}, shard::Shard, Epoch, PeerAddress, @@ -464,9 +464,8 @@ pub struct ValidatorNode { #[cfg_attr(feature = "ts", ts(type = "string"))] pub public_key: PublicKey, pub shard_key: SubstateAddress, - pub epoch: Epoch, - #[cfg_attr(feature = "ts", ts(type = "number | null"))] - pub committee_shard: Option, + pub start_epoch: Epoch, + pub end_epoch: Epoch, #[cfg_attr(feature = "ts", ts(type = "string"))] pub fee_claim_public_key: PublicKey, } @@ -477,8 +476,8 @@ impl From> for ValidatorNode { address: value.address, public_key: value.public_key, shard_key: value.shard_key, - epoch: value.epoch, - committee_shard: value.committee_shard, + start_epoch: value.start_epoch, + end_epoch: value.end_epoch, fee_claim_public_key: value.fee_claim_public_key, } } @@ -608,7 +607,7 @@ pub struct GetEpochManagerStatsResponse { #[cfg_attr(feature = "ts", ts(type = "string"))] pub current_block_hash: FixedHash, pub is_valid: bool, - pub committee_shard: Option, + pub committee_info: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/dan_layer/common_types/src/committee.rs b/dan_layer/common_types/src/committee.rs index 07ba17c2d..63918369a 100644 --- a/dan_layer/common_types/src/committee.rs +++ b/dan_layer/common_types/src/committee.rs @@ -161,14 +161,14 @@ impl FromIterator> for Committee { /// Represents a "slice" of the 256-bit shard space #[derive(Debug, Clone, Copy, Serialize, Deserialize)] #[cfg_attr(feature = "ts", derive(TS), ts(export, export_to = "../../bindings/src/types/"))] -pub struct CommitteeShard { +pub struct CommitteeInfo { num_committees: u32, num_members: u32, #[cfg_attr(feature = "ts", ts(type = "number"))] shard: Shard, } -impl CommitteeShard { +impl CommitteeInfo { pub fn new(num_committees: u32, num_members: u32, shard: Shard) -> Self { Self { num_committees, diff --git a/dan_layer/consensus/src/block_validations.rs b/dan_layer/consensus/src/block_validations.rs index 869e2b228..054350d68 100644 --- a/dan_layer/consensus/src/block_validations.rs +++ b/dan_layer/consensus/src/block_validations.rs @@ -154,7 +154,7 @@ pub async fn check_quorum_certificate( .get_validator_node_by_public_key(qc.epoch(), signature.public_key()) .await?; let actual_shard = epoch_manager - .get_committee_shard(qc.epoch(), vn.shard_key) + .get_committee_info_for_substate(qc.epoch(), vn.shard_key) .await? .shard(); if actual_shard != qc.shard() { @@ -175,7 +175,7 @@ pub async fn check_quorum_certificate( } } let committee_shard = epoch_manager - .get_committee_shard_by_validator_public_key( + .get_committee_info_by_validator_public_key( qc.epoch(), qc.signatures() .first() diff --git a/dan_layer/consensus/src/hotstuff/on_propose.rs b/dan_layer/consensus/src/hotstuff/on_propose.rs index ee6056112..74292e10d 100644 --- a/dan_layer/consensus/src/hotstuff/on_propose.rs +++ b/dan_layer/consensus/src/hotstuff/on_propose.rs @@ -13,7 +13,7 @@ use tari_common::configuration::Network; use tari_common_types::types::{FixedHash, PublicKey}; use tari_crypto::tari_utilities::epoch_time::EpochTime; use tari_dan_common_types::{ - committee::{Committee, CommitteeShard}, + committee::{Committee, CommitteeInfo}, optional::Optional, Epoch, NodeHeight, @@ -126,7 +126,7 @@ where TConsensusSpec: ConsensusSpec } let validator = self.epoch_manager.get_our_validator_node(epoch).await?; - let local_committee_shard = self.epoch_manager.get_local_committee_shard(epoch).await?; + let local_committee_shard = self.epoch_manager.get_local_committee_info(epoch).await?; let (current_base_layer_block_height, current_base_layer_block_hash) = self.epoch_manager.current_base_layer_block_info().await?; let (high_qc, qc_block, locked_block) = self.store.with_read_tx(|tx| { @@ -240,7 +240,7 @@ where TConsensusSpec: ConsensusSpec parent_block: &LeafBlock, high_qc: QuorumCertificate, proposed_by: PublicKey, - local_committee_shard: &CommitteeShard, + local_committee_info: &CommitteeInfo, empty_block: bool, base_layer_block_height: u64, base_layer_block_hash: FixedHash, @@ -283,7 +283,7 @@ where TConsensusSpec: ConsensusSpec }) .chain(batch.into_iter().map(|t| { let command = - transaction_pool_record_to_command(tx, &t, local_committee_shard, &mut substate_changes)?; + transaction_pool_record_to_command(tx, &t, local_committee_info, &mut substate_changes)?; total_leader_fee += command .committing() .and_then(|tx| tx.leader_fee.as_ref()) @@ -312,8 +312,8 @@ where TConsensusSpec: ConsensusSpec let non_local_buckets = proposer::get_non_local_shards_from_commands( tx, &commands, - local_committee_shard.num_committees(), - local_committee_shard.shard(), + local_committee_info.num_committees(), + local_committee_info.shard(), )?; let foreign_counters = ForeignSendCounters::get_or_default(tx, parent_block.block_id())?; @@ -331,7 +331,7 @@ where TConsensusSpec: ConsensusSpec high_qc, next_height, epoch, - local_committee_shard.shard(), + local_committee_info.shard(), proposed_by, commands, state_root, @@ -353,10 +353,10 @@ where TConsensusSpec: ConsensusSpec fn transaction_pool_record_to_command( tx: &mut TTx, t: &TransactionPoolRecord, - local_committee_shard: &CommitteeShard, + local_committee_info: &CommitteeInfo, substate_changes: &mut Vec, ) -> Result { - let involved = local_committee_shard.count_distinct_shards(t.transaction().evidence.substate_addresses_iter()); + let involved = local_committee_info.count_distinct_shards(t.transaction().evidence.substate_addresses_iter()); if involved == 1 { info!( target: LOG_TARGET, diff --git a/dan_layer/consensus/src/hotstuff/on_ready_to_vote_on_local_block.rs b/dan_layer/consensus/src/hotstuff/on_ready_to_vote_on_local_block.rs index 778a34ecf..d7cf8e83f 100644 --- a/dan_layer/consensus/src/hotstuff/on_ready_to_vote_on_local_block.rs +++ b/dan_layer/consensus/src/hotstuff/on_ready_to_vote_on_local_block.rs @@ -6,7 +6,7 @@ use std::{collections::HashSet, num::NonZeroU64, ops::DerefMut}; use log::*; use tari_common::configuration::Network; use tari_dan_common_types::{ - committee::{Committee, CommitteeShard}, + committee::{Committee, CommitteeInfo}, optional::Optional, SubstateAddress, }; @@ -120,7 +120,7 @@ where TConsensusSpec: ConsensusSpec let local_committee_shard = self .epoch_manager - .get_committee_shard_by_validator_public_key(valid_block.epoch(), valid_block.proposed_by()) + .get_committee_info_by_validator_public_key(valid_block.epoch(), valid_block.proposed_by()) .await?; let mut locked_blocks = Vec::new(); let mut finalized_transactions = Vec::new(); @@ -218,7 +218,7 @@ where TConsensusSpec: ConsensusSpec fn decide_on_block( &self, tx: &mut ::WriteTransaction<'_>, - local_committee_shard: &CommitteeShard, + local_committee_info: &CommitteeInfo, block: &Block, epoch_should_start: bool, epoch_should_end: bool, @@ -226,7 +226,7 @@ where TConsensusSpec: ConsensusSpec let mut maybe_decision = None; if self.should_vote(tx.deref_mut(), block)? { maybe_decision = - self.decide_what_to_vote(tx, block, local_committee_shard, epoch_should_start, epoch_should_end)?; + self.decide_what_to_vote(tx, block, local_committee_info, epoch_should_start, epoch_should_end)?; } Ok(maybe_decision) @@ -238,7 +238,7 @@ where TConsensusSpec: ConsensusSpec tx: &mut ::WriteTransaction<'_>, high_qc: HighQc, tip_block: &Block, - local_committee_shard: &CommitteeShard, + local_committee_info: &CommitteeInfo, ) -> Result { let mut leaf = high_qc.get_block(tx.deref_mut())?; if leaf.is_processed() { @@ -262,7 +262,7 @@ where TConsensusSpec: ConsensusSpec if t.decision.is_commit() { let transaction = ExecutedTransaction::get(tx.deref_mut(), &t.id)?; // Lock all inputs for the transaction as part of Prepare - let is_inputs_locked = self.lock_inputs(tx, &transaction, local_committee_shard)?; + let is_inputs_locked = self.lock_inputs(tx, &transaction, local_committee_info)?; let is_outputs_locked = is_inputs_locked && self.lock_outputs(tx, leaf.id(), &transaction)?; // This should not be possible and may be due to a BUG. The failure to lock the leaf block @@ -300,7 +300,7 @@ where TConsensusSpec: ConsensusSpec Decision::Abort ); // Unlock any locked inputs because we are not voting - self.unlock_inputs(tx, &transaction, local_committee_shard)?; + self.unlock_inputs(tx, &transaction, local_committee_info)?; // We change our decision to ABORT so that the next time we propose/receive a // proposal we will check for ABORT let mut tx_rec = self.transaction_pool.get(tx, tip_block.as_leaf_block(), t.id())?; @@ -313,7 +313,7 @@ where TConsensusSpec: ConsensusSpec if t.decision.is_commit() { let transaction = ExecutedTransaction::get(tx.deref_mut(), &t.id)?; // Lock all inputs for the transaction as part of Prepare - let is_inputs_locked = self.lock_inputs(tx, &transaction, local_committee_shard)?; + let is_inputs_locked = self.lock_inputs(tx, &transaction, local_committee_info)?; let is_outputs_locked = is_inputs_locked && self.lock_outputs(tx, leaf.id(), &transaction)?; if !is_inputs_locked { @@ -347,7 +347,7 @@ where TConsensusSpec: ConsensusSpec Decision::Abort ); // Unlock any locked inputs because we are not voting - self.unlock_inputs(tx, &transaction, local_committee_shard)?; + self.unlock_inputs(tx, &transaction, local_committee_info)?; // We change our decision to ABORT so that the next time we propose/receive a // proposal we will check for ABORT let mut tx_rec = self.transaction_pool.get(tx, tip_block.as_leaf_block(), t.id())?; @@ -464,7 +464,7 @@ where TConsensusSpec: ConsensusSpec &self, tx: &mut ::WriteTransaction<'_>, block: &Block, - local_committee_shard: &CommitteeShard, + local_committee_info: &CommitteeInfo, epoch_should_start: bool, epoch_should_end: bool, ) -> Result, HotStuffError> { @@ -558,7 +558,7 @@ where TConsensusSpec: ConsensusSpec // part of the proposal DanMessage so that there is no race condition between receiving the // proposed block and receiving the foreign proposals. Because this is only added on locked block, // this should be less common. - tx_rec.add_evidence(local_committee_shard, *block.justify().id()); + tx_rec.add_evidence(local_committee_info, *block.justify().id()); debug!( target: LOG_TARGET, @@ -592,7 +592,7 @@ where TConsensusSpec: ConsensusSpec if tx_rec.current_decision() == t.decision { if tx_rec.current_decision().is_commit() { - if !local_committee_shard.includes_all_substate_addresses( + if !local_committee_info.includes_all_substate_addresses( tx_rec.transaction().evidence.substate_addresses_iter(), ) { warn!( @@ -607,7 +607,7 @@ where TConsensusSpec: ConsensusSpec let executed = ExecutedTransaction::get(tx.deref_mut(), &t.id)?; // Lock all inputs for the transaction as part of LocalOnly let is_inputs_locked = - self.check_lock_inputs(tx, &executed, local_committee_shard, &mut locked_inputs)?; + self.check_lock_inputs(tx, &executed, local_committee_info, &mut locked_inputs)?; let is_outputs_locked = is_inputs_locked && self.check_lock_outputs(tx, &executed, &mut locked_outputs, &locked_inputs)?; @@ -718,7 +718,7 @@ where TConsensusSpec: ConsensusSpec // Lock all inputs for the transaction as part of Prepare let is_inputs_locked = - self.check_lock_inputs(tx, &executed, local_committee_shard, &mut locked_inputs)?; + self.check_lock_inputs(tx, &executed, local_committee_info, &mut locked_inputs)?; let is_outputs_locked = is_inputs_locked && self.check_lock_outputs(tx, &executed, &mut locked_outputs, &locked_inputs)?; @@ -890,7 +890,7 @@ where TConsensusSpec: ConsensusSpec return Ok(None); } - let distinct_shards = local_committee_shard + let distinct_shards = local_committee_info .count_distinct_shards(tx_rec.transaction().evidence.substate_addresses_iter()); let distinct_shards = NonZeroU64::new(distinct_shards as u64).ok_or_else(|| { HotStuffError::InvariantError(format!( @@ -999,7 +999,7 @@ where TConsensusSpec: ConsensusSpec &self, tx: &mut ::WriteTransaction<'_>, transaction: &ExecutedTransaction, - local_committee_shard: &CommitteeShard, + local_committee_info: &CommitteeInfo, ) -> Result { let resolved_inputs = transaction.resolved_inputs().ok_or_else(|| { HotStuffError::InvariantError(format!( @@ -1011,7 +1011,7 @@ where TConsensusSpec: ConsensusSpec let state = SubstateRecord::try_lock_all( tx, transaction.id(), - local_committee_shard.filter( + local_committee_info.filter( resolved_inputs .iter() .filter(|i| i.lock_flag().is_write()) @@ -1032,7 +1032,7 @@ where TConsensusSpec: ConsensusSpec let state = SubstateRecord::try_lock_all( tx, transaction.id(), - local_committee_shard.filter( + local_committee_info.filter( resolved_inputs .iter() .filter(|i| i.lock_flag().is_read()) @@ -1064,7 +1064,7 @@ where TConsensusSpec: ConsensusSpec &self, tx: &mut ::ReadTransaction<'_>, transaction: &ExecutedTransaction, - local_committee_shard: &CommitteeShard, + local_committee_info: &CommitteeInfo, locked_inputs: &mut HashSet, ) -> Result { let resolved_inputs = transaction.resolved_inputs().ok_or_else(|| { @@ -1089,7 +1089,7 @@ where TConsensusSpec: ConsensusSpec let state = SubstateRecord::check_lock_all( tx, - local_committee_shard.filter( + local_committee_info.filter( resolved_inputs .iter() .filter(|i| i.lock_flag().is_write()) @@ -1109,7 +1109,7 @@ where TConsensusSpec: ConsensusSpec let state = SubstateRecord::check_lock_all( tx, - local_committee_shard.filter( + local_committee_info.filter( resolved_inputs .iter() .filter(|i| i.lock_flag().is_read()) @@ -1142,7 +1142,7 @@ where TConsensusSpec: ConsensusSpec &self, tx: &mut ::WriteTransaction<'_>, transaction: &ExecutedTransaction, - local_committee_shard: &CommitteeShard, + local_committee_info: &CommitteeInfo, ) -> Result<(), HotStuffError> { let inputs = transaction.resolved_inputs().ok_or_else(|| { HotStuffError::InvariantError(format!( @@ -1154,7 +1154,7 @@ where TConsensusSpec: ConsensusSpec SubstateRecord::try_unlock_many( tx, transaction.id(), - local_committee_shard.filter( + local_committee_info.filter( inputs .iter() .filter(|i| i.lock_flag().is_write()) @@ -1166,7 +1166,7 @@ where TConsensusSpec: ConsensusSpec SubstateRecord::try_unlock_many( tx, transaction.id(), - local_committee_shard.filter( + local_committee_info.filter( inputs .iter() .filter(|i| i.lock_flag().is_read()) @@ -1255,11 +1255,11 @@ where TConsensusSpec: ConsensusSpec &self, tx: &mut ::WriteTransaction<'_>, transaction: &ExecutedTransaction, - local_committee_shard: &CommitteeShard, + local_committee_info: &CommitteeInfo, ) -> Result<(), HotStuffError> { LockedOutput::try_release_all( tx, - local_committee_shard.filter(transaction.resulting_outputs().iter().map(|v| v.to_substate_address())), + local_committee_info.filter(transaction.resulting_outputs().iter().map(|v| v.to_substate_address())), )?; Ok(()) } @@ -1291,9 +1291,9 @@ where TConsensusSpec: ConsensusSpec tx: &mut ::WriteTransaction<'_>, last_executed: &LastExecuted, block: &Block, - local_committee_shard: &CommitteeShard, + local_committee_info: &CommitteeInfo, ) -> Result, HotStuffError> { - let committed_transactions = self.execute(tx, block, local_committee_shard)?; + let committed_transactions = self.execute(tx, block, local_committee_info)?; debug!( target: LOG_TARGET, "✅ COMMIT block {}, last executed height = {}", @@ -1383,7 +1383,7 @@ where TConsensusSpec: ConsensusSpec &self, tx: &mut ::WriteTransaction<'_>, block: &Block, - local_committee_shard: &CommitteeShard, + local_committee_info: &CommitteeInfo, ) -> Result, HotStuffError> { let mut finalized_transactions = Vec::with_capacity( block @@ -1426,7 +1426,7 @@ where TConsensusSpec: ConsensusSpec } self.state_manager - .commit_transaction(tx, block, &executed, local_committee_shard) + .commit_transaction(tx, block, &executed, local_committee_info) .map_err(|e| HotStuffError::StateManagerError(e.into()))?; } @@ -1434,9 +1434,9 @@ where TConsensusSpec: ConsensusSpec if tx_rec.current_decision().is_commit() { // We unlock just so that inputs that were not mutated are unlocked, even though those // should be in input_refs - self.unlock_inputs(tx, &executed, local_committee_shard)?; + self.unlock_inputs(tx, &executed, local_committee_info)?; // Unlock any outputs that were locked - self.unlock_outputs(tx, &executed, local_committee_shard)?; + self.unlock_outputs(tx, &executed, local_committee_info)?; } // We are accepting the transaction so can remove the transaction from the pool diff --git a/dan_layer/consensus/src/hotstuff/on_receive_foreign_proposal.rs b/dan_layer/consensus/src/hotstuff/on_receive_foreign_proposal.rs index 26d326f7d..d43f3dec5 100644 --- a/dan_layer/consensus/src/hotstuff/on_receive_foreign_proposal.rs +++ b/dan_layer/consensus/src/hotstuff/on_receive_foreign_proposal.rs @@ -3,7 +3,7 @@ use std::ops::DerefMut; use log::*; -use tari_dan_common_types::{committee::CommitteeShard, optional::Optional, shard::Shard}; +use tari_dan_common_types::{committee::CommitteeInfo, optional::Optional, shard::Shard}; use tari_dan_storage::{ consensus_models::{ Block, @@ -69,10 +69,10 @@ where TConsensusSpec: ConsensusSpec let vn = self.epoch_manager.get_validator_node(block.epoch(), &from).await?; let committee_shard = self .epoch_manager - .get_committee_shard(block.epoch(), vn.shard_key) + .get_committee_info_for_substate(block.epoch(), vn.shard_key) .await?; - let local_shard = self.epoch_manager.get_local_committee_shard(block.epoch()).await?; + let local_shard = self.epoch_manager.get_local_committee_info(block.epoch()).await?; if let Err(err) = self.validate_proposed_block( &from, &block, @@ -144,7 +144,7 @@ where TConsensusSpec: ConsensusSpec &self, tx: &mut ::WriteTransaction<'_>, block: &Block, - foreign_committee_shard: &CommitteeShard, + foreign_committee_info: &CommitteeInfo, ) -> Result<(), HotStuffError> { let leaf = LeafBlock::get(tx.deref_mut())?; // We only want to save the QC once if applicable @@ -183,7 +183,7 @@ where TConsensusSpec: ConsensusSpec is_qc_saved = true; } - tx_rec.update_remote_data(tx, remote_decision, *block.justify().id(), foreign_committee_shard)?; + tx_rec.update_remote_data(tx, remote_decision, *block.justify().id(), foreign_committee_info)?; // If all shards are complete and we've already received our LocalPrepared, we can set out LocalPrepared // transaction as ready to propose ACCEPT. If we have not received the local LocalPrepared, the transition diff --git a/dan_layer/consensus/src/hotstuff/on_receive_local_proposal.rs b/dan_layer/consensus/src/hotstuff/on_receive_local_proposal.rs index 9c01ea8a2..48323728a 100644 --- a/dan_layer/consensus/src/hotstuff/on_receive_local_proposal.rs +++ b/dan_layer/consensus/src/hotstuff/on_receive_local_proposal.rs @@ -10,7 +10,7 @@ use std::ops::{Deref, DerefMut}; use log::*; use tari_common::configuration::Network; use tari_dan_common_types::{ - committee::{Committee, CommitteeShard}, + committee::{Committee, CommitteeInfo}, optional::Optional, shard::Shard, NodeHeight, @@ -141,7 +141,7 @@ impl OnReceiveLocalProposalHandler OnReceiveLocalProposalHandler::WriteTransaction<'_>, block: Block, local_committee: &Committee, - local_committee_shard: &CommitteeShard, + local_committee_info: &CommitteeInfo, ) -> Result, HotStuffError> { let result = self - .validate_local_proposed_block(tx.deref_mut(), block, local_committee, local_committee_shard) + .validate_local_proposed_block(tx.deref_mut(), block, local_committee, local_committee_info) .and_then(|valid_block| { self.update_foreign_proposal_transactions(tx, valid_block.block())?; Ok(valid_block) @@ -368,7 +368,7 @@ impl OnReceiveLocalProposalHandler::ReadTransaction<'_>, candidate_block: Block, local_committee: &Committee, - local_committee_shard: &CommitteeShard, + local_committee_info: &CommitteeInfo, ) -> Result { if Block::has_been_processed(tx, candidate_block.id())? { return Err(ProposalValidationError::BlockAlreadyProcessed { @@ -417,8 +417,8 @@ impl OnReceiveLocalProposalHandler OnReceiveLocalProposalHandler Option { + fn calculate_threshold_decision(votes: &[Vote], local_committee_info: &CommitteeInfo) -> Option { let mut count_accept = 0; let mut count_reject = 0; for vote in votes { @@ -245,7 +245,7 @@ where TConsensusSpec: ConsensusSpec } } - let threshold = local_committee_shard.quorum_threshold() as usize; + let threshold = local_committee_info.quorum_threshold() as usize; if count_accept >= threshold { return Some(QuorumDecision::Accept); } diff --git a/dan_layer/consensus/src/traits/state_manager.rs b/dan_layer/consensus/src/traits/state_manager.rs index e8fa61487..a04424d37 100644 --- a/dan_layer/consensus/src/traits/state_manager.rs +++ b/dan_layer/consensus/src/traits/state_manager.rs @@ -1,7 +1,7 @@ // Copyright 2023 The Tari Project // SPDX-License-Identifier: BSD-3-Clause -use tari_dan_common_types::committee::CommitteeShard; +use tari_dan_common_types::committee::CommitteeInfo; use tari_dan_storage::{ consensus_models::{Block, ExecutedTransaction}, StateStore, @@ -15,6 +15,6 @@ pub trait StateManager { tx: &mut TStateStore::WriteTransaction<'_>, block: &Block, transaction: &ExecutedTransaction, - local_committee_shard: &CommitteeShard, + local_committee_info: &CommitteeInfo, ) -> Result<(), Self::Error>; } diff --git a/dan_layer/consensus_tests/src/support/epoch_manager.rs b/dan_layer/consensus_tests/src/support/epoch_manager.rs index 6bcb835c5..e5e5085d8 100644 --- a/dan_layer/consensus_tests/src/support/epoch_manager.rs +++ b/dan_layer/consensus_tests/src/support/epoch_manager.rs @@ -3,14 +3,13 @@ use std::{ collections::{HashMap, HashSet}, - ops::RangeInclusive, sync::Arc, }; use async_trait::async_trait; use tari_common_types::types::{FixedHash, PublicKey}; use tari_dan_common_types::{ - committee::{Committee, CommitteeShard, CommitteeShardInfo, NetworkCommitteeInfo}, + committee::{Committee, CommitteeInfo}, shard::Shard, Epoch, SubstateAddress, @@ -57,15 +56,29 @@ impl TestEpochManager { pub fn clone_for(&self, address: TestAddress, public_key: PublicKey, shard_key: SubstateAddress) -> Self { let mut copy = self.clone(); - copy.our_validator_node = Some(ValidatorNode { - address, - public_key, - shard_key, - epoch: Epoch(0), - committee_shard: None, - fee_claim_public_key: PublicKey::default(), - sidechain_id: None, - }); + if let Some(our_validator_node) = self.our_validator_node.clone() { + copy.our_validator_node = Some(ValidatorNode { + address, + public_key, + shard_key, + registered_at_base_height: our_validator_node.registered_at_base_height, + start_epoch: our_validator_node.start_epoch, + end_epoch: our_validator_node.end_epoch, + fee_claim_public_key: PublicKey::default(), + sidechain_id: None, + }); + } else { + copy.our_validator_node = Some(ValidatorNode { + address, + public_key, + shard_key, + registered_at_base_height: 0, + start_epoch: Epoch(0), + end_epoch: Epoch(1), + fee_claim_public_key: PublicKey::default(), + sidechain_id: None, + }); + } copy } @@ -77,7 +90,15 @@ impl TestEpochManager { let substate_address = random_substate_in_bucket(shard, num_committees); state.validator_shards.insert( address.clone(), - (shard, substate_address.to_substate_address(), pk.clone(), None), + ( + shard, + substate_address.to_substate_address(), + pk.clone(), + None, + 0, + Epoch(0), + Epoch(1), + ), ); state.address_shard.insert(address.clone(), shard); } @@ -86,18 +107,28 @@ impl TestEpochManager { } } - pub async fn all_validators(&self) -> Vec<(TestAddress, Shard, SubstateAddress, PublicKey)> { + pub async fn all_validators(&self) -> Vec<(TestAddress, Shard, SubstateAddress, PublicKey, u64, Epoch, Epoch)> { self.state_lock() .await .validator_shards .iter() - .filter_map(|(a, (shard, substate_address, pk, sidechain_id))| { - if sidechain_id.is_none() { - Some((a.clone(), *shard, *substate_address, pk.clone())) - } else { - None - } - }) + .filter_map( + |(a, (shard, substate_address, pk, sidechain_id, registered_at, start_epoch, end_epoch))| { + if sidechain_id.is_none() { + Some(( + a.clone(), + *shard, + *substate_address, + pk.clone(), + *registered_at, + *start_epoch, + *end_epoch, + )) + } else { + None + } + }, + ) .collect() } @@ -114,7 +145,7 @@ impl EpochManagerReader for TestEpochManager { Ok(self.tx_epoch_events.subscribe()) } - async fn get_committee( + async fn get_committee_for_substate( &self, _epoch: Epoch, substate_address: SubstateAddress, @@ -130,29 +161,38 @@ impl EpochManagerReader for TestEpochManager { async fn get_validator_node( &self, - epoch: Epoch, + _epoch: Epoch, addr: &Self::Addr, ) -> Result, EpochManagerError> { - let (shard, shard_key, public_key, sidechain_id) = self.state_lock().await.validator_shards[addr].clone(); + let (_shard, shard_key, public_key, sidechain_id, registered_at_base_height, start_epoch, end_epoch) = + self.state_lock().await.validator_shards[addr].clone(); Ok(ValidatorNode { address: addr.clone(), public_key, shard_key, - epoch, - committee_shard: Some(shard), + registered_at_base_height, + start_epoch, + end_epoch, fee_claim_public_key: PublicKey::default(), sidechain_id, }) } - async fn get_local_committee_shard(&self, epoch: Epoch) -> Result { + async fn get_all_validator_nodes( + &self, + _epoch: Epoch, + ) -> Result>, EpochManagerError> { + todo!() + } + + async fn get_local_committee_info(&self, epoch: Epoch) -> Result { let our_vn = self.get_our_validator_node(epoch).await?; let num_committees = self.get_num_committees(epoch).await?; - let committee = self.get_committee(epoch, our_vn.shard_key).await?; + let committee = self.get_committee_for_substate(epoch, our_vn.shard_key).await?; let our_shard = our_vn.shard_key.to_committee_shard(num_committees); - Ok(CommitteeShard::new(num_committees, committee.len() as u32, our_shard)) + Ok(CommitteeInfo::new(num_committees, committee.len() as u32, our_shard)) } async fn current_epoch(&self) -> Result { @@ -179,6 +219,18 @@ impl EpochManagerReader for TestEpochManager { Ok(self.inner.lock().await.committees.len() as u32) } + async fn get_committees(&self, _epoch: Epoch) -> Result>, EpochManagerError> { + todo!() + } + + async fn get_committee_info_by_validator_address( + &self, + _epoch: Epoch, + _address: &Self::Addr, + ) -> Result { + todo!() + } + async fn get_committees_by_shards( &self, _epoch: Epoch, @@ -193,16 +245,16 @@ impl EpochManagerReader for TestEpochManager { .collect()) } - async fn get_committee_shard( + async fn get_committee_info_for_substate( &self, epoch: Epoch, substate_address: SubstateAddress, - ) -> Result { + ) -> Result { let num_committees = self.get_num_committees(epoch).await?; - let committee = self.get_committee(epoch, substate_address).await?; + let committee = self.get_committee_for_substate(epoch, substate_address).await?; let shard = substate_address.to_committee_shard(num_committees); - Ok(CommitteeShard::new(num_committees, committee.len() as u32, shard)) + Ok(CommitteeInfo::new(num_committees, committee.len() as u32, shard)) } // async fn get_committees_by_shards( @@ -225,39 +277,25 @@ impl EpochManagerReader for TestEpochManager { // Ok(committees) // } - async fn get_committee_within_shard_range( - &self, - _epoch: Epoch, - range: RangeInclusive, - ) -> Result, EpochManagerError> { - let lock = self.state_lock().await; - Ok(Committee::new( - lock.validator_shards - .iter() - .filter(|(_, (_, s, _, _))| range.contains(s)) - .map(|(a, (_, _, pk, _))| (a.clone(), pk.clone())) - .collect(), - )) - } - async fn get_validator_node_by_public_key( &self, - epoch: Epoch, + _epoch: Epoch, public_key: &PublicKey, ) -> Result, EpochManagerError> { let lock = self.state_lock().await; - let (address, (shard, shard_key, public_key, sidechain_id)) = lock + let (address, (_shard, shard_key, public_key, sidechain_id, registered_at, start_epoch, end_epoch)) = lock .validator_shards .iter() - .find(|(_, (_, _, pk, _))| pk == public_key) + .find(|(_, (_, _, pk, _, _, _, _))| pk == public_key) .unwrap(); Ok(ValidatorNode { address: address.clone(), public_key: public_key.clone(), shard_key: *shard_key, - epoch, - committee_shard: Some(*shard), + registered_at_base_height: *registered_at, + start_epoch: *start_epoch, + end_epoch: *end_epoch, fee_claim_public_key: PublicKey::default(), sidechain_id: sidechain_id.clone(), }) @@ -266,31 +304,6 @@ impl EpochManagerReader for TestEpochManager { async fn get_base_layer_block_height(&self, _hash: FixedHash) -> Result, EpochManagerError> { Ok(Some(self.inner.lock().await.current_block_info.0)) } - - async fn get_network_committees(&self) -> Result, EpochManagerError> { - let lock = self.state_lock().await; - let commitees_lock = &lock.committees; - let num_committees = commitees_lock.len().try_into().unwrap(); - - let committees = commitees_lock - .iter() - .map(|s| { - let shard = s.0; - CommitteeShardInfo { - shard: *shard, - substate_address_range: shard.to_substate_address_range(num_committees), - validators: s.1.clone(), - } - }) - .collect(); - - let network_commitee_info = NetworkCommitteeInfo { - epoch: lock.current_epoch, - committees, - }; - - Ok(network_commitee_info) - } } #[derive(Debug, Clone)] @@ -299,7 +312,9 @@ pub struct TestEpochManagerState { pub current_block_info: (u64, FixedHash), pub last_block_of_current_epoch: FixedHash, pub is_epoch_active: bool, - pub validator_shards: HashMap)>, + #[allow(clippy::type_complexity)] + pub validator_shards: + HashMap, u64, Epoch, Epoch)>, pub committees: HashMap>, pub address_shard: HashMap, } diff --git a/dan_layer/consensus_tests/src/support/harness.rs b/dan_layer/consensus_tests/src/support/harness.rs index 24046642a..e7e48fde1 100644 --- a/dan_layer/consensus_tests/src/support/harness.rs +++ b/dan_layer/consensus_tests/src/support/harness.rs @@ -413,7 +413,7 @@ impl TestBuilder { .all_validators() .await .into_iter() - .map(|(address, bucket, shard, pk)| { + .map(|(address, bucket, shard, pk, _, _, _)| { let sql_address = self.sql_address.replace("{}", &address.0); let (channels, validator) = Validator::builder() .with_sql_url(sql_address) diff --git a/dan_layer/consensus_tests/src/support/state_manager.rs b/dan_layer/consensus_tests/src/support/state_manager.rs index 5632856b9..4cca8a76c 100644 --- a/dan_layer/consensus_tests/src/support/state_manager.rs +++ b/dan_layer/consensus_tests/src/support/state_manager.rs @@ -4,7 +4,7 @@ use std::sync::{atomic::AtomicBool, Arc}; use tari_consensus::traits::StateManager; -use tari_dan_common_types::{committee::CommitteeShard, SubstateAddress}; +use tari_dan_common_types::{committee::CommitteeInfo, SubstateAddress}; use tari_dan_storage::{ consensus_models::{Block, ExecutedTransaction, SubstateRecord}, StateStore, @@ -37,7 +37,7 @@ impl StateManager for TestStateManager { tx: &mut TStateStore::WriteTransaction<'_>, block: &Block, transaction: &ExecutedTransaction, - local_committee_shard: &CommitteeShard, + local_committee_info: &CommitteeInfo, ) -> Result<(), Self::Error> { let Some(diff) = transaction.result().finalize.result.accept() else { // We should only commit accepted transactions, might want to change this API to reflect that @@ -47,7 +47,7 @@ impl StateManager for TestStateManager { let down_shards = diff .down_iter() .map(|(addr, version)| SubstateAddress::from_address(addr, *version)) - .filter(|shard| local_committee_shard.includes_substate_address(shard)); + .filter(|shard| local_committee_info.includes_substate_address(shard)); SubstateRecord::destroy_many( tx, down_shards, @@ -62,7 +62,7 @@ impl StateManager for TestStateManager { let to_up = diff.up_iter().filter_map(|(addr, substate)| { let address = SubstateAddress::from_address(addr, substate.version()); // Commit all substates included in this shard. Every involved validator commits the transaction receipt. - if local_committee_shard.includes_substate_address(&address) || addr.is_transaction_receipt() { + if local_committee_info.includes_substate_address(&address) || addr.is_transaction_receipt() { Some(SubstateRecord::new( addr.clone(), substate.version(), diff --git a/dan_layer/epoch_manager/Cargo.toml b/dan_layer/epoch_manager/Cargo.toml index 501f7bcff..cca47a7d5 100644 --- a/dan_layer/epoch_manager/Cargo.toml +++ b/dan_layer/epoch_manager/Cargo.toml @@ -19,7 +19,6 @@ tari_utilities = {workspace = true} anyhow = { workspace = true } async-trait = { workspace = true } -indexmap = { workspace = true } log = { workspace = true , optional = true } thiserror = { workspace = true } tokio = { workspace = true, default-features = false, features = ["sync"] } diff --git a/dan_layer/epoch_manager/src/base_layer/base_layer_epoch_manager.rs b/dan_layer/epoch_manager/src/base_layer/base_layer_epoch_manager.rs index 9bbbc68a5..4bfdbeaf2 100644 --- a/dan_layer/epoch_manager/src/base_layer/base_layer_epoch_manager.rs +++ b/dan_layer/epoch_manager/src/base_layer/base_layer_epoch_manager.rs @@ -23,16 +23,14 @@ use std::{ cmp, collections::{HashMap, HashSet}, - ops::RangeInclusive, }; -use indexmap::IndexMap; use log::*; use tari_base_node_client::{grpc::GrpcBaseNodeClient, types::BaseLayerConsensusConstants, BaseNodeClient}; use tari_common_types::types::{FixedHash, PublicKey}; use tari_core::{blocks::BlockHeader, transactions::transaction_components::ValidatorNodeRegistration}; use tari_dan_common_types::{ - committee::{Committee, CommitteeShard, CommitteeShardInfo, NetworkCommitteeInfo}, + committee::{Committee, CommitteeInfo}, optional::Optional, shard::Shard, DerivableFromPublicKey, @@ -129,7 +127,7 @@ impl // persist the epoch data including the validator node set self.insert_current_epoch(epoch, epoch_header)?; self.update_base_layer_consensus_constants(base_layer_constants)?; - self.assign_validators_for_epoch()?; + self.assign_validators_for_epoch(epoch)?; // Only publish an epoch change event if we have synced the base layer (see on_scanning_complete) if self.is_initial_base_layer_sync_complete { @@ -139,16 +137,11 @@ impl Ok(()) } - fn assign_validators_for_epoch(&mut self) -> Result<(), EpochManagerError> { - let (start_epoch, end_epoch) = self.get_epoch_range(self.current_epoch)?; + fn assign_validators_for_epoch(&mut self, epoch: Epoch) -> Result<(), EpochManagerError> { let mut tx = self.global_db.create_transaction()?; let mut validator_nodes = self.global_db.validator_nodes(&mut tx); - let vns = validator_nodes.get_all_within_epochs( - start_epoch, - end_epoch, - self.config.validator_node_sidechain_id.as_ref(), - )?; + let vns = validator_nodes.get_all_within_epoch(epoch, self.config.validator_node_sidechain_id.as_ref())?; let num_committees = calculate_num_committees(vns.len() as u64, self.config.committee_size); @@ -157,14 +150,13 @@ impl vn.shard_key, vn.shard_key.to_committee_shard(num_committees), self.config.validator_node_sidechain_id.as_ref(), - self.current_epoch, + epoch, )?; } tx.commit()?; - if let Some(vn) = vns.iter().find(|vn| vn.public_key == self.node_public_key) { self.publish_event(EpochManagerEvent::ThisValidatorIsRegistered { - epoch: self.current_epoch, + epoch, shard_key: vn.shard_key, }); } @@ -212,6 +204,7 @@ impl let constants = self.get_base_layer_consensus_constants().await?; let next_epoch = constants.height_to_epoch(block_height) + Epoch(1); let next_epoch_height = constants.epoch_to_height(next_epoch); + let validator_node_expiry = constants.validator_node_registration_expiry; let shard_key = self .base_node_client @@ -223,11 +216,14 @@ impl })?; let mut tx = self.global_db.create_transaction()?; + info!(target: LOG_TARGET, "Registering validator node for epoch {}", next_epoch); self.global_db.validator_nodes(&mut tx).insert_validator_node( TAddr::derive_from_public_key(registration.public_key()), registration.public_key().clone(), shard_key, + block_height, next_epoch, + next_epoch + Epoch(validator_node_expiry), registration.claim_public_key().clone(), registration.sidechain_id().cloned(), )?; @@ -345,21 +341,15 @@ impl epoch: Epoch, public_key: &PublicKey, ) -> Result>, EpochManagerError> { - let (start_epoch, end_epoch) = self.get_epoch_range(epoch)?; - debug!( + trace!( target: LOG_TARGET, - "get_validator_node: epoch {}-{} with public key {}", start_epoch, end_epoch, public_key, + "get_validator_node: epoch {} with public key {}", epoch, public_key, ); let mut tx = self.global_db.create_transaction()?; let vn = self .global_db .validator_nodes(&mut tx) - .get_by_public_key( - start_epoch, - end_epoch, - public_key, - self.config.validator_node_sidechain_id.as_ref(), - ) + .get_by_public_key(epoch, public_key, self.config.validator_node_sidechain_id.as_ref()) .optional()?; Ok(vn) @@ -370,16 +360,15 @@ impl epoch: Epoch, address: &TAddr, ) -> Result>, EpochManagerError> { - let (start_epoch, end_epoch) = self.get_epoch_range(epoch)?; - debug!( + trace!( target: LOG_TARGET, - "get_validator_node: epoch {}-{} with public key {}", start_epoch, end_epoch, address, + "get_validator_node: epoch {} with public key {}", epoch, address, ); let mut tx = self.global_db.create_transaction()?; let vn = self .global_db .validator_nodes(&mut tx) - .get_by_address(start_epoch, end_epoch, address) + .get_by_address(epoch, address, self.config.validator_node_sidechain_id.as_ref()) .optional()?; Ok(vn) @@ -394,16 +383,10 @@ impl let mut validators = HashMap::with_capacity(epoch_validators.len()); for (epoch, public_key) in epoch_validators { - let (start_epoch, end_epoch) = self.get_epoch_range(epoch)?; let vn = self .global_db .validator_nodes(&mut tx) - .get_by_public_key( - start_epoch, - end_epoch, - &public_key, - self.config.validator_node_sidechain_id.as_ref(), - ) + .get_by_public_key(epoch, &public_key, self.config.validator_node_sidechain_id.as_ref()) .optional()? .ok_or_else(|| EpochManagerError::ValidatorNodeNotRegistered { address: public_key.to_string(), @@ -438,24 +421,27 @@ impl epoch.as_u64() >= current_epoch.as_u64().saturating_sub(10) && epoch.as_u64() <= current_epoch.as_u64() } - pub fn get_committees( - &self, - epoch: Epoch, - substate_addresses: &HashSet, - ) -> Result>, EpochManagerError> { - let num_committees = self.get_number_of_committees(epoch)?; - let (start_epoch, end_epoch) = self.get_epoch_range(epoch)?; + pub fn get_committees(&self, epoch: Epoch) -> Result>, EpochManagerError> { let mut tx = self.global_db.create_transaction()?; let mut validator_node_db = self.global_db.validator_nodes(&mut tx); - let buckets = substate_addresses - .iter() - .map(|addr| addr.to_committee_shard(num_committees)) - .collect(); - let result = validator_node_db.get_committees_by_buckets(start_epoch, end_epoch, buckets)?; - Ok(result) + Ok(validator_node_db.get_committees(epoch, self.config.validator_node_sidechain_id.as_ref())?) + } + + pub fn get_committee_info_by_validator_address( + &self, + epoch: Epoch, + validator_addr: TAddr, + ) -> Result { + let vn = self + .get_validator_node_by_address(epoch, &validator_addr)? + .ok_or_else(|| EpochManagerError::ValidatorNodeNotRegistered { + address: validator_addr.to_string(), + epoch, + })?; + self.get_committee_info_for_substate(epoch, vn.shard_key) } - pub fn get_committee_vns_from_shard_key( + pub(crate) fn get_committee_vns_from_shard_key( &self, epoch: Epoch, substate_address: SubstateAddress, @@ -477,75 +463,42 @@ impl // A shard a equal slice of the shard space that a validator fits into let shard = substate_address.to_committee_shard(num_committees); - let selected_vns = vns - .into_iter() - .filter(|vn| { - vn.committee_shard - .unwrap_or_else(|| vn.shard_key.to_committee_shard(num_committees)) == - shard - }) - .collect(); - - Ok(selected_vns) - } + let mut shards = HashSet::new(); + shards.insert(shard); + let selected = self.get_committees_for_shards(epoch, shards)?; + let shard_vns = selected.get(&shard).map(|c| c.members.clone()).unwrap_or_default(); - pub fn get_committee(&self, epoch: Epoch, shard: SubstateAddress) -> Result, EpochManagerError> { - let result = self.get_committee_vns_from_shard_key(epoch, shard)?; - Ok(Committee::new( - result.into_iter().map(|v| (v.address, v.public_key)).collect(), - )) + let mut res = vec![]; + for (_, pub_key) in shard_vns { + if let Some(vn) = vns.iter().find(|vn| vn.public_key == pub_key) { + res.push(vn.clone()); + } + } + Ok(res) } - pub fn is_validator_in_committee( + pub(crate) fn get_committee_for_substate( &self, epoch: Epoch, substate_address: SubstateAddress, - identity: &TAddr, - ) -> Result { - let (start_epoch, end_epoch) = self.get_epoch_range(epoch)?; - let mut tx = self.global_db.create_transaction()?; - let mut vn_db = self.global_db.validator_nodes(&mut tx); - let num_vns = vn_db.count(start_epoch, end_epoch, self.config.validator_node_sidechain_id.as_ref())?; - let vn = vn_db.get_by_address(start_epoch, end_epoch, identity)?; - let num_committees = calculate_num_committees(num_vns, self.config.committee_size); - let shard = substate_address.to_committee_shard(num_committees); - match vn.committee_shard { - Some(s) => Ok(s == shard), - None => Ok(false), - } + ) -> Result, EpochManagerError> { + let result = self.get_committee_vns_from_shard_key(epoch, substate_address)?; + Ok(Committee::new( + result.into_iter().map(|v| (v.address, v.public_key)).collect(), + )) } pub fn get_number_of_committees(&self, epoch: Epoch) -> Result { - let (start_epoch, end_epoch) = self.get_epoch_range(epoch)?; - - let mut tx = self.global_db.create_transaction()?; - let num_vns = self.global_db.validator_nodes(&mut tx).count( - start_epoch, - end_epoch, - self.config.validator_node_sidechain_id.as_ref(), - )?; + let num_vns = self.get_total_validator_count(epoch)?; Ok(calculate_num_committees(num_vns, self.config.committee_size)) } - fn get_epoch_range(&self, end_epoch: Epoch) -> Result<(Epoch, Epoch), EpochManagerError> { - let consensus_constants = self - .base_layer_consensus_constants - .as_ref() - .ok_or(EpochManagerError::BaseLayerConsensusConstantsNotSet)?; - - let start_epoch = end_epoch.saturating_sub(consensus_constants.validator_node_registration_expiry()); - Ok((start_epoch, end_epoch)) - } - pub fn get_validator_nodes_per_epoch(&self, epoch: Epoch) -> Result>, EpochManagerError> { - let (start_epoch, end_epoch) = self.get_epoch_range(epoch)?; - let mut tx = self.global_db.create_transaction()?; - let db_vns = self.global_db.validator_nodes(&mut tx).get_all_within_epochs( - start_epoch, - end_epoch, - self.config.validator_node_sidechain_id.as_ref(), - )?; + let db_vns = self + .global_db + .validator_nodes(&mut tx) + .get_all_within_epoch(epoch, self.config.validator_node_sidechain_id.as_ref())?; let vns = db_vns.into_iter().map(Into::into).collect(); Ok(vns) } @@ -581,55 +534,6 @@ impl Ok(expiry.checked_sub(num_blocks_since_last_reg)) } - pub fn get_local_shard_range( - &self, - epoch: Epoch, - addr: &TAddr, - ) -> Result, EpochManagerError> { - let vn = self.get_validator_node_by_address(epoch, addr)?.ok_or_else(|| { - EpochManagerError::ValidatorNodeNotRegistered { - address: addr.to_string(), - epoch, - } - })?; - - let num_committees = self.get_number_of_committees(epoch)?; - debug!( - target: LOG_TARGET, - "VN {} epoch: {}, num_committees: {}", addr, epoch, num_committees - ); - Ok(vn.shard_key.to_committee_range(num_committees)) - } - - pub fn get_committee_for_shard_range( - &self, - epoch: Epoch, - substate_address_range: RangeInclusive, - ) -> Result, EpochManagerError> { - let num_committees = self.get_number_of_committees(epoch)?; - - // Since we have fixed boundaries for committees, we want to include all validators within any range "touching" - // the range we are searching for. For e.g. the committee for half a committee shard is the same committee as - // for a whole committee shard. - let rounded_substate_address_range = { - let start_range = substate_address_range.start().to_committee_range(num_committees); - let end_range = substate_address_range.end().to_committee_range(num_committees); - *start_range.start()..=*end_range.end() - }; - let mut tx = self.global_db.create_transaction()?; - let mut validator_node_db = self.global_db.validator_nodes(&mut tx); - let (start_epoch, end_epoch) = self.get_epoch_range(epoch)?; - let validators = validator_node_db.get_by_shard_range( - start_epoch, - end_epoch, - self.config.validator_node_sidechain_id.as_ref(), - rounded_substate_address_range, - )?; - Ok(Committee::new( - validators.into_iter().map(|v| (v.address, v.public_key)).collect(), - )) - } - pub fn get_our_validator_node(&self, epoch: Epoch) -> Result, EpochManagerError> { let vn = self .get_validator_node_by_public_key(epoch, &self.node_public_key)? @@ -643,12 +547,12 @@ impl } pub fn get_total_validator_count(&self, epoch: Epoch) -> Result { - let mut tx = self.global_db.create_transaction()?; - let mut validator_node_db = self.global_db.validator_nodes(&mut tx); - let (start_epoch, end_epoch) = self.get_epoch_range(epoch)?; - let num_validators = - validator_node_db.count(start_epoch, end_epoch, self.config.validator_node_sidechain_id.as_ref())?; - Ok(num_validators) + self.get_validator_nodes_per_epoch(epoch)? + .len() + .try_into() + .map_err(|_| EpochManagerError::IntegerOverflow { + func: "get_total_validator_count", + }) } pub fn get_num_committees(&self, epoch: Epoch) -> Result { @@ -658,11 +562,11 @@ impl Ok(num_committees) } - pub fn get_committee_shard( + pub fn get_committee_info_for_substate( &self, epoch: Epoch, substate_address: SubstateAddress, - ) -> Result { + ) -> Result { let num_committees = self.get_number_of_committees(epoch)?; let shard = substate_address.to_committee_shard(num_committees); let mut tx = self.global_db.create_transaction()?; @@ -672,28 +576,27 @@ impl let num_validators = u32::try_from(num_validators).map_err(|_| EpochManagerError::IntegerOverflow { func: "get_committee_shard", })?; - Ok(CommitteeShard::new(num_committees, num_validators, shard)) + Ok(CommitteeInfo::new(num_committees, num_validators, shard)) } - pub fn get_local_committee_shard(&self, epoch: Epoch) -> Result { + pub fn get_local_committee_info(&self, epoch: Epoch) -> Result { let vn = self .get_validator_node_by_public_key(epoch, &self.node_public_key)? .ok_or_else(|| EpochManagerError::ValidatorNodeNotRegistered { address: self.node_public_key.to_string(), epoch, })?; - self.get_committee_shard(epoch, vn.shard_key) + self.get_committee_info_for_substate(epoch, vn.shard_key) } - pub fn get_committees_by_buckets( + pub(crate) fn get_committees_for_shards( &self, epoch: Epoch, - buckets: HashSet, + shards: HashSet, ) -> Result>, EpochManagerError> { let mut tx = self.global_db.create_transaction()?; let mut validator_node_db = self.global_db.validator_nodes(&mut tx); - let (start_epoch, end_epoch) = self.get_epoch_range(epoch)?; - let committees = validator_node_db.get_committees_by_buckets(start_epoch, end_epoch, buckets)?; + let committees = validator_node_db.get_committees_for_shards(epoch, shards)?; Ok(committees) } @@ -724,43 +627,6 @@ impl .map(|info| info.height); Ok(info) } - - pub async fn get_network_committees(&self) -> Result, EpochManagerError> { - let current_epoch = self.current_epoch; - let num_committees = self.get_num_committees(current_epoch)?; - - let mut validators = self.get_validator_nodes_per_epoch(current_epoch)?; - validators.sort_by(|vn_a, vn_b| vn_b.committee_shard.cmp(&vn_a.committee_shard)); - - // Group by bucket, IndexMap used to preserve ordering - let mut validators_per_bucket = IndexMap::with_capacity(validators.len()); - for validator in validators { - validators_per_bucket - .entry( - validator - .committee_shard - .expect("validator committee bucket must have been populated within valid epoch"), - ) - .or_insert_with(Vec::new) - .push(validator); - } - - let committees = validators_per_bucket - .into_iter() - .map(|(bucket, validators)| CommitteeShardInfo { - shard: bucket, - substate_address_range: bucket.to_substate_address_range(num_committees), - validators: Committee::new(validators.into_iter().map(|v| (v.address, v.public_key)).collect()), - }) - .collect(); - - let network_committee_info = NetworkCommitteeInfo { - epoch: current_epoch, - committees, - }; - - Ok(network_committee_info) - } } fn calculate_num_committees(num_vns: u64, committee_size: u32) -> u32 { diff --git a/dan_layer/epoch_manager/src/base_layer/epoch_manager_service.rs b/dan_layer/epoch_manager/src/base_layer/epoch_manager_service.rs index f309b78fa..7ce719643 100644 --- a/dan_layer/epoch_manager/src/base_layer/epoch_manager_service.rs +++ b/dan_layer/epoch_manager/src/base_layer/epoch_manager_service.rs @@ -20,7 +20,7 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use log::{debug, error, info}; +use log::{error, info, trace}; use tari_base_node_client::grpc::GrpcBaseNodeClient; use tari_common_types::types::PublicKey; use tari_dan_common_types::{DerivableFromPublicKey, NodeAddressable}; @@ -102,15 +102,18 @@ impl #[allow(clippy::too_many_lines)] async fn handle_request(&mut self, req: EpochManagerRequest) { - debug!(target: LOG_TARGET, "Received request: {:?}", req); + trace!(target: LOG_TARGET, "Received request: {:?}", req); + let context = &format!("{:?}", req); match req { - EpochManagerRequest::CurrentEpoch { reply } => handle(reply, Ok(self.inner.current_epoch())), - EpochManagerRequest::CurrentBlockInfo { reply } => handle(reply, Ok(self.inner.current_block_info())), + EpochManagerRequest::CurrentEpoch { reply } => handle(reply, Ok(self.inner.current_epoch()), context), + EpochManagerRequest::CurrentBlockInfo { reply } => { + handle(reply, Ok(self.inner.current_block_info()), context) + }, EpochManagerRequest::GetLastBlockOfTheEpoch { reply } => { - handle(reply, Ok(self.inner.last_block_of_current_epoch())) + handle(reply, Ok(self.inner.last_block_of_current_epoch()), context) }, EpochManagerRequest::IsLastBlockOfTheEpoch { block_height, reply } => { - handle(reply, self.inner.is_last_block_of_epoch(block_height).await) + handle(reply, self.inner.is_last_block_of_epoch(block_height).await, context) }, EpochManagerRequest::GetValidatorNode { epoch, addr, reply } => handle( reply, @@ -120,6 +123,7 @@ impl epoch, }) }), + context, ), EpochManagerRequest::GetValidatorNodeByPublicKey { epoch, @@ -135,104 +139,127 @@ impl epoch, }) }), + context, ), EpochManagerRequest::GetManyValidatorNodes { query, reply } => { - handle(reply, self.inner.get_many_validator_nodes(query)); + handle(reply, self.inner.get_many_validator_nodes(query), context); }, EpochManagerRequest::AddBlockHash { block_height, block_hash, reply, } => { - handle(reply, self.inner.add_base_layer_block_info(block_height, block_hash)); + handle( + reply, + self.inner.add_base_layer_block_info(block_height, block_hash), + context, + ); }, EpochManagerRequest::UpdateEpoch { block_height, block_hash, reply, } => { - handle(reply, self.inner.update_epoch(block_height, block_hash).await); + handle(reply, self.inner.update_epoch(block_height, block_hash).await, context); + }, + EpochManagerRequest::LastRegistrationEpoch { reply } => { + handle(reply, self.inner.last_registration_epoch(), context) }, - EpochManagerRequest::LastRegistrationEpoch { reply } => handle(reply, self.inner.last_registration_epoch()), EpochManagerRequest::UpdateLastRegistrationEpoch { epoch, reply } => { - handle(reply, self.inner.update_last_registration_epoch(epoch)); + handle(reply, self.inner.update_last_registration_epoch(epoch), context); }, - EpochManagerRequest::IsEpochValid { epoch, reply } => handle(reply, Ok(self.inner.is_epoch_valid(epoch))), - EpochManagerRequest::GetCommittees { epoch, shards, reply } => { - handle(reply, self.inner.get_committees(epoch, &shards)); + EpochManagerRequest::IsEpochValid { epoch, reply } => { + handle(reply, Ok(self.inner.is_epoch_valid(epoch)), context) }, - EpochManagerRequest::GetCommittee { epoch, shard, reply } => { - handle(reply, self.inner.get_committee(epoch, shard)); + EpochManagerRequest::GetCommittees { epoch, reply } => { + handle(reply, self.inner.get_committees(epoch), context); }, - EpochManagerRequest::GetCommitteeForShardRange { + EpochManagerRequest::GetCommitteeInfoByAddress { epoch, address, reply } => handle( + reply, + self.inner.get_committee_info_by_validator_address(epoch, address), + context, + ), + EpochManagerRequest::GetCommitteeForSubstate { epoch, - shard_range, + substate_address, reply, - } => handle(reply, self.inner.get_committee_for_shard_range(epoch, shard_range)), - EpochManagerRequest::IsValidatorInCommitteeForCurrentEpoch { shard, identity, reply } => { - let epoch = self.inner.current_epoch(); - handle(reply, self.inner.is_validator_in_committee(epoch, shard, &identity)); + } => { + handle( + reply, + self.inner.get_committee_for_substate(epoch, substate_address), + context, + ); }, - EpochManagerRequest::Subscribe { reply } => handle(reply, Ok(self.events.subscribe())), + EpochManagerRequest::Subscribe { reply } => handle(reply, Ok(self.events.subscribe()), context), EpochManagerRequest::GetValidatorNodesPerEpoch { epoch, reply } => { - handle(reply, self.inner.get_validator_nodes_per_epoch(epoch)) + handle(reply, self.inner.get_validator_nodes_per_epoch(epoch), context) }, EpochManagerRequest::AddValidatorNodeRegistration { block_height, registration, + value: _value, reply, } => handle( reply, self.inner .add_validator_node_registration(block_height, registration) .await, + context, ), // TODO: This should be rather be a state machine event EpochManagerRequest::NotifyScanningComplete { reply } => { - handle(reply, self.inner.on_scanning_complete().await) + handle(reply, self.inner.on_scanning_complete().await, context) }, EpochManagerRequest::RemainingRegistrationEpochs { reply } => { - handle(reply, self.inner.remaining_registration_epochs().await) - }, - EpochManagerRequest::GetBaseLayerConsensusConstants { reply } => { - handle(reply, self.inner.get_base_layer_consensus_constants().await.cloned()) - }, - EpochManagerRequest::GetLocalShardRange { epoch, for_addr, reply } => { - handle(reply, self.inner.get_local_shard_range(epoch, &for_addr)) + handle(reply, self.inner.remaining_registration_epochs().await, context) }, + EpochManagerRequest::GetBaseLayerConsensusConstants { reply } => handle( + reply, + self.inner.get_base_layer_consensus_constants().await.cloned(), + context, + ), EpochManagerRequest::GetOurValidatorNode { epoch, reply } => { - handle(reply, self.inner.get_our_validator_node(epoch)) + handle(reply, self.inner.get_our_validator_node(epoch), context) }, - EpochManagerRequest::GetCommitteeShard { epoch, shard, reply } => { - handle(reply, self.inner.get_committee_shard(epoch, shard)) - }, - EpochManagerRequest::GetLocalCommitteeShard { epoch, reply } => { - handle(reply, self.inner.get_local_committee_shard(epoch)) + EpochManagerRequest::GetCommitteeInfo { + epoch, + substate_address, + reply, + } => handle( + reply, + self.inner.get_committee_info_for_substate(epoch, substate_address), + context, + ), + EpochManagerRequest::GetLocalCommitteeInfo { epoch, reply } => { + handle(reply, self.inner.get_local_committee_info(epoch), context) }, EpochManagerRequest::GetNumCommittees { epoch, reply } => { - handle(reply, self.inner.get_num_committees(epoch)) + handle(reply, self.inner.get_num_committees(epoch), context) }, - EpochManagerRequest::GetCommitteesByBuckets { epoch, buckets, reply } => { - handle(reply, self.inner.get_committees_by_buckets(epoch, buckets)) + EpochManagerRequest::GetCommitteesForShards { epoch, shards, reply } => { + handle(reply, self.inner.get_committees_for_shards(epoch, shards), context) + }, + EpochManagerRequest::GetFeeClaimPublicKey { reply } => { + handle(reply, self.inner.get_fee_claim_public_key(), context) }, - EpochManagerRequest::GetFeeClaimPublicKey { reply } => handle(reply, self.inner.get_fee_claim_public_key()), EpochManagerRequest::SetFeeClaimPublicKey { public_key, reply } => { - handle(reply, self.inner.set_fee_claim_public_key(public_key)) + handle(reply, self.inner.set_fee_claim_public_key(public_key), context) }, EpochManagerRequest::GetBaseLayerBlockHeight { hash, reply } => { - handle(reply, self.inner.get_base_layer_block_height(hash).await) - }, - EpochManagerRequest::GetNetworkCommittees { reply } => { - handle(reply, self.inner.get_network_committees().await) + handle(reply, self.inner.get_base_layer_block_height(hash).await, context) }, } } } -fn handle(reply: oneshot::Sender>, result: Result) { +fn handle( + reply: oneshot::Sender>, + result: Result, + context: &str, +) { if let Err(ref e) = result { - error!(target: LOG_TARGET, "Request failed with error: {}", e); + error!(target: LOG_TARGET, "Request {} failed with error: {}", context, e); } if reply.send(result).is_err() { error!(target: LOG_TARGET, "Requester abandoned request"); diff --git a/dan_layer/epoch_manager/src/base_layer/handle.rs b/dan_layer/epoch_manager/src/base_layer/handle.rs index 329c8ae7b..0428b115b 100644 --- a/dan_layer/epoch_manager/src/base_layer/handle.rs +++ b/dan_layer/epoch_manager/src/base_layer/handle.rs @@ -1,17 +1,14 @@ // Copyright 2023 The Tari Project // SPDX-License-Identifier: BSD-3-Clause -use std::{ - collections::{HashMap, HashSet}, - ops::RangeInclusive, -}; +use std::collections::{HashMap, HashSet}; use async_trait::async_trait; use tari_base_node_client::types::BaseLayerConsensusConstants; use tari_common_types::types::{FixedHash, PublicKey}; -use tari_core::transactions::transaction_components::ValidatorNodeRegistration; +use tari_core::transactions::{tari_amount::MicroMinotari, transaction_components::ValidatorNodeRegistration}; use tari_dan_common_types::{ - committee::{Committee, CommitteeShard, NetworkCommitteeInfo}, + committee::{Committee, CommitteeInfo}, shard::Shard, Epoch, NodeAddressable, @@ -105,12 +102,14 @@ impl EpochManagerHandle { &self, block_height: u64, registration: ValidatorNodeRegistration, + value_of_registration: MicroMinotari, ) -> Result<(), EpochManagerError> { let (tx, rx) = oneshot::channel(); self.tx_request .send(EpochManagerRequest::AddValidatorNodeRegistration { block_height, registration, + value: value_of_registration, reply: tx, }) .await @@ -158,28 +157,10 @@ impl EpochManagerHandle { rx.await.map_err(|_| EpochManagerError::ReceiveError)? } - pub async fn get_all_validator_nodes(&self, epoch: Epoch) -> Result>, EpochManagerError> { + pub async fn get_committees(&self, epoch: Epoch) -> Result>, EpochManagerError> { let (tx, rx) = oneshot::channel(); self.tx_request - .send(EpochManagerRequest::GetValidatorNodesPerEpoch { epoch, reply: tx }) - .await - .map_err(|_| EpochManagerError::SendError)?; - - rx.await.map_err(|_| EpochManagerError::ReceiveError)? - } - - pub async fn get_committees_by_shards( - &self, - epoch: Epoch, - shards: HashSet, - ) -> Result>, EpochManagerError> { - let (tx, rx) = oneshot::channel(); - self.tx_request - .send(EpochManagerRequest::GetCommittees { - epoch, - shards, - reply: tx, - }) + .send(EpochManagerRequest::GetCommittees { epoch, reply: tx }) .await .map_err(|_| EpochManagerError::SendError)?; @@ -200,34 +181,36 @@ impl EpochManagerReader for EpochManagerHandle { rx.await.map_err(|_| EpochManagerError::ReceiveError)? } - async fn get_committee( - &self, - epoch: Epoch, - shard: SubstateAddress, - ) -> Result, EpochManagerError> { + async fn get_all_validator_nodes(&self, epoch: Epoch) -> Result>, EpochManagerError> { let (tx, rx) = oneshot::channel(); self.tx_request - .send(EpochManagerRequest::GetCommittee { - epoch, - shard, - reply: tx, - }) + .send(EpochManagerRequest::GetValidatorNodesPerEpoch { epoch, reply: tx }) + .await + .map_err(|_| EpochManagerError::SendError)?; + + rx.await.map_err(|_| EpochManagerError::ReceiveError)? + } + + async fn get_committees(&self, epoch: Epoch) -> Result>, EpochManagerError> { + let (tx, rx) = oneshot::channel(); + self.tx_request + .send(EpochManagerRequest::GetCommittees { epoch, reply: tx }) .await .map_err(|_| EpochManagerError::SendError)?; rx.await.map_err(|_| EpochManagerError::ReceiveError)? } - async fn get_committee_within_shard_range( + async fn get_committee_for_substate( &self, epoch: Epoch, - shard_range: RangeInclusive, + substate_address: SubstateAddress, ) -> Result, EpochManagerError> { let (tx, rx) = oneshot::channel(); self.tx_request - .send(EpochManagerRequest::GetCommitteeForShardRange { + .send(EpochManagerRequest::GetCommitteeForSubstate { epoch, - shard_range, + substate_address, reply: tx, }) .await @@ -295,26 +278,26 @@ impl EpochManagerReader for EpochManagerHandle { rx.await.map_err(|_| EpochManagerError::ReceiveError)? } - async fn get_local_committee_shard(&self, epoch: Epoch) -> Result { + async fn get_local_committee_info(&self, epoch: Epoch) -> Result { let (tx, rx) = oneshot::channel(); self.tx_request - .send(EpochManagerRequest::GetLocalCommitteeShard { epoch, reply: tx }) + .send(EpochManagerRequest::GetLocalCommitteeInfo { epoch, reply: tx }) .await .map_err(|_| EpochManagerError::SendError)?; rx.await.map_err(|_| EpochManagerError::ReceiveError)? } - async fn get_committee_shard( + async fn get_committee_info_for_substate( &self, epoch: Epoch, - shard: SubstateAddress, - ) -> Result { + substate_address: SubstateAddress, + ) -> Result { let (tx, rx) = oneshot::channel(); self.tx_request - .send(EpochManagerRequest::GetCommitteeShard { + .send(EpochManagerRequest::GetCommitteeInfo { epoch, - shard, + substate_address, reply: tx, }) .await @@ -323,6 +306,24 @@ impl EpochManagerReader for EpochManagerHandle { Ok(rx.await.map_err(|_| EpochManagerError::ReceiveError).unwrap().unwrap()) } + async fn get_committee_info_by_validator_address( + &self, + epoch: Epoch, + address: &TAddr, + ) -> Result { + let (tx, rx) = oneshot::channel(); + self.tx_request + .send(EpochManagerRequest::GetCommitteeInfoByAddress { + epoch, + address: address.clone(), + reply: tx, + }) + .await + .map_err(|_| EpochManagerError::SendError)?; + + rx.await.map_err(|_| EpochManagerError::ReceiveError)? + } + async fn current_epoch(&self) -> Result { let (tx, rx) = oneshot::channel(); self.tx_request @@ -389,13 +390,13 @@ impl EpochManagerReader for EpochManagerHandle { async fn get_committees_by_shards( &self, epoch: Epoch, - buckets: HashSet, + shards: HashSet, ) -> Result>, EpochManagerError> { let (tx, rx) = oneshot::channel(); self.tx_request - .send(EpochManagerRequest::GetCommitteesByBuckets { + .send(EpochManagerRequest::GetCommitteesForShards { epoch, - buckets, + shards, reply: tx, }) .await @@ -412,13 +413,4 @@ impl EpochManagerReader for EpochManagerHandle { .map_err(|_| EpochManagerError::SendError)?; rx.await.map_err(|_| EpochManagerError::ReceiveError)? } - - async fn get_network_committees(&self) -> Result, EpochManagerError> { - let (tx, rx) = oneshot::channel(); - self.tx_request - .send(EpochManagerRequest::GetNetworkCommittees { reply: tx }) - .await - .map_err(|_| EpochManagerError::SendError)?; - rx.await.map_err(|_| EpochManagerError::ReceiveError)? - } } diff --git a/dan_layer/epoch_manager/src/base_layer/types.rs b/dan_layer/epoch_manager/src/base_layer/types.rs index f2d3517de..4a44145e9 100644 --- a/dan_layer/epoch_manager/src/base_layer/types.rs +++ b/dan_layer/epoch_manager/src/base_layer/types.rs @@ -1,16 +1,13 @@ // Copyright 2023 The Tari Project // SPDX-License-Identifier: BSD-3-Clause -use std::{ - collections::{HashMap, HashSet}, - ops::RangeInclusive, -}; +use std::collections::{HashMap, HashSet}; use tari_base_node_client::types::BaseLayerConsensusConstants; use tari_common_types::types::{FixedHash, PublicKey}; -use tari_core::transactions::transaction_components::ValidatorNodeRegistration; +use tari_core::transactions::{tari_amount::MicroMinotari, transaction_components::ValidatorNodeRegistration}; use tari_dan_common_types::{ - committee::{Committee, CommitteeShard, NetworkCommitteeInfo}, + committee::{Committee, CommitteeInfo}, shard::Shard, Epoch, SubstateAddress, @@ -54,6 +51,7 @@ pub enum EpochManagerRequest { AddValidatorNodeRegistration { block_height: u64, registration: ValidatorNodeRegistration, + value: MicroMinotari, reply: Reply<()>, }, AddBlockHash { @@ -79,28 +77,22 @@ pub enum EpochManagerRequest { }, GetCommittees { epoch: Epoch, - shards: HashSet, reply: Reply>>, }, - GetCommittee { + GetCommitteeForSubstate { epoch: Epoch, - shard: SubstateAddress, + substate_address: SubstateAddress, reply: Reply>, }, - GetCommitteeForShardRange { + GetCommitteeInfoByAddress { epoch: Epoch, - shard_range: RangeInclusive, - reply: Reply>, + address: TAddr, + reply: Reply, }, GetValidatorNodesPerEpoch { epoch: Epoch, reply: Reply>>, }, - IsValidatorInCommitteeForCurrentEpoch { - shard: SubstateAddress, - identity: TAddr, - reply: Reply, - }, Subscribe { reply: Reply>, }, @@ -113,31 +105,26 @@ pub enum EpochManagerRequest { GetBaseLayerConsensusConstants { reply: Reply, }, - GetLocalShardRange { - epoch: Epoch, - for_addr: TAddr, - reply: Reply>, - }, GetOurValidatorNode { epoch: Epoch, reply: Reply>, }, - GetCommitteeShard { + GetCommitteeInfo { epoch: Epoch, - shard: SubstateAddress, - reply: Reply, + substate_address: SubstateAddress, + reply: Reply, }, - GetLocalCommitteeShard { + GetLocalCommitteeInfo { epoch: Epoch, - reply: Reply, + reply: Reply, }, GetNumCommittees { epoch: Epoch, reply: Reply, }, - GetCommitteesByBuckets { + GetCommitteesForShards { epoch: Epoch, - buckets: HashSet, + shards: HashSet, reply: Reply>>, }, GetBaseLayerBlockHeight { @@ -151,7 +138,4 @@ pub enum EpochManagerRequest { public_key: PublicKey, reply: Reply<()>, }, - GetNetworkCommittees { - reply: Reply>, - }, } diff --git a/dan_layer/epoch_manager/src/traits.rs b/dan_layer/epoch_manager/src/traits.rs index 02fd18e40..da93a885d 100644 --- a/dan_layer/epoch_manager/src/traits.rs +++ b/dan_layer/epoch_manager/src/traits.rs @@ -20,15 +20,12 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use std::{ - collections::{HashMap, HashSet}, - ops::RangeInclusive, -}; +use std::collections::{HashMap, HashSet}; use async_trait::async_trait; use tari_common_types::types::{FixedHash, PublicKey}; use tari_dan_common_types::{ - committee::{Committee, CommitteeShard, NetworkCommitteeInfo}, + committee::{Committee, CommitteeInfo}, shard::Shard, Epoch, NodeAddressable, @@ -45,16 +42,20 @@ pub trait EpochManagerReader: Send + Sync { async fn subscribe(&self) -> Result, EpochManagerError>; - async fn get_committee( + async fn get_all_validator_nodes(&self, epoch: Epoch) -> Result>, EpochManagerError>; + + async fn get_committees(&self, epoch: Epoch) -> Result>, EpochManagerError>; + async fn get_committee_info_by_validator_address( &self, epoch: Epoch, - shard: SubstateAddress, - ) -> Result, EpochManagerError>; - async fn get_committee_within_shard_range( + address: &Self::Addr, + ) -> Result; + async fn get_committee_for_substate( &self, epoch: Epoch, - range: RangeInclusive, + substate_address: SubstateAddress, ) -> Result, EpochManagerError>; + async fn get_validator_node( &self, epoch: Epoch, @@ -83,20 +84,20 @@ pub trait EpochManagerReader: Send + Sync { } async fn get_our_validator_node(&self, epoch: Epoch) -> Result, EpochManagerError>; - async fn get_local_committee_shard(&self, epoch: Epoch) -> Result; - async fn get_committee_shard( + async fn get_local_committee_info(&self, epoch: Epoch) -> Result; + async fn get_committee_info_for_substate( &self, epoch: Epoch, shard: SubstateAddress, - ) -> Result; + ) -> Result; - async fn get_committee_shard_by_validator_public_key( + async fn get_committee_info_by_validator_public_key( &self, epoch: Epoch, public_key: &PublicKey, - ) -> Result { + ) -> Result { let validator = self.get_validator_node_by_public_key(epoch, public_key).await?; - self.get_committee_shard(epoch, validator.shard_key).await + self.get_committee_info_for_substate(epoch, validator.shard_key).await } async fn current_epoch(&self) -> Result; @@ -115,7 +116,7 @@ pub trait EpochManagerReader: Send + Sync { async fn get_local_committee(&self, epoch: Epoch) -> Result, EpochManagerError> { let validator = self.get_our_validator_node(epoch).await?; - let committee = self.get_committee(epoch, validator.shard_key).await?; + let committee = self.get_committee_for_substate(epoch, validator.shard_key).await?; Ok(committee) } @@ -125,7 +126,7 @@ pub trait EpochManagerReader: Send + Sync { public_key: &PublicKey, ) -> Result, EpochManagerError> { let validator = self.get_validator_node_by_public_key(epoch, public_key).await?; - let committee = self.get_committee(epoch, validator.shard_key).await?; + let committee = self.get_committee_for_substate(epoch, validator.shard_key).await?; Ok(committee) } @@ -145,11 +146,11 @@ pub trait EpochManagerReader: Send + Sync { shard: SubstateAddress, ) -> Result, EpochManagerError> { let current_epoch = self.current_epoch().await?; - self.get_committee(current_epoch, shard).await + self.get_committee_for_substate(current_epoch, shard).await } async fn get_local_threshold_for_epoch(&self, epoch: Epoch) -> Result { - let committee = self.get_local_committee_shard(epoch).await?; + let committee = self.get_local_committee_info(epoch).await?; Ok(committee.quorum_threshold() as usize) } @@ -159,19 +160,14 @@ pub trait EpochManagerReader: Send + Sync { } // TODO: might want to improve this - self.get_local_committee_shard(epoch) - .await - .map(|_| true) - .or_else(|err| { - if err.is_not_registered_error() { - Ok(false) - } else { - Err(err) - } - }) + self.get_local_committee_info(epoch).await.map(|_| true).or_else(|err| { + if err.is_not_registered_error() { + Ok(false) + } else { + Err(err) + } + }) } async fn get_base_layer_block_height(&self, hash: FixedHash) -> Result, EpochManagerError>; - - async fn get_network_committees(&self) -> Result, EpochManagerError>; } diff --git a/dan_layer/indexer_lib/src/substate_scanner.rs b/dan_layer/indexer_lib/src/substate_scanner.rs index b8ad9faf2..b41ce9be0 100644 --- a/dan_layer/indexer_lib/src/substate_scanner.rs +++ b/dan_layer/indexer_lib/src/substate_scanner.rs @@ -217,10 +217,13 @@ where /// Returns a specific version. If this is not found an error is returned. pub async fn get_specific_substate_from_committee_by_shard( &self, - shard: SubstateAddress, + substate_address: SubstateAddress, ) -> Result { let epoch = self.committee_provider.current_epoch().await?; - let mut committee = self.committee_provider.get_committee(epoch, shard).await?; + let mut committee = self + .committee_provider + .get_committee_for_substate(epoch, substate_address) + .await?; committee.shuffle(); @@ -229,11 +232,11 @@ where let mut last_error = None; for vn_addr in committee.addresses() { // TODO: we cannot request data from ourselves via p2p rpc - so we should exclude ourselves from requests - debug!(target: LOG_TARGET, "Getting substate {} from vn {}", shard, vn_addr); + debug!(target: LOG_TARGET, "Getting substate {} from vn {}", substate_address, vn_addr); - match self.get_substate_from_vn(vn_addr, shard).await { + match self.get_substate_from_vn(vn_addr, substate_address).await { Ok(substate_result) => { - debug!(target: LOG_TARGET, "Got substate result for {} from vn {}: {:?}", shard, vn_addr, substate_result); + debug!(target: LOG_TARGET, "Got substate result for {} from vn {}: {:?}", substate_address, vn_addr, substate_result); match substate_result { SubstateResult::Up { .. } | SubstateResult::Down { .. } => return Ok(substate_result), SubstateResult::DoesNotExist => { @@ -248,7 +251,7 @@ where // We ignore a single VN error and keep querying the rest of the committee error!( target: LOG_TARGET, - "Could not get substate {} from vn {}: {}", shard, vn_addr, e + "Could not get substate {} from vn {}: {}", substate_address, vn_addr, e ); last_error = Some(e); }, @@ -257,7 +260,7 @@ where error!( target: LOG_TARGET, - "Could not get substate for shard {} from any of the validator nodes", shard, + "Could not get substate for shard {} from any of the validator nodes", substate_address, ); if let Some(e) = last_error { @@ -272,7 +275,10 @@ where shard_location: SubstateAddress, ) -> Result { let epoch = self.committee_provider.current_epoch().await?; - let mut committee = self.committee_provider.get_committee(epoch, shard_location).await?; + let mut committee = self + .committee_provider + .get_committee_for_substate(epoch, shard_location) + .await?; committee.shuffle(); @@ -346,7 +352,10 @@ where let substate_address = SubstateAddress::from_address(substate_id, version); let epoch = self.committee_provider.current_epoch().await?; - let mut committee = self.committee_provider.get_committee(epoch, substate_address).await?; + let mut committee = self + .committee_provider + .get_committee_for_substate(epoch, substate_address) + .await?; committee.members.shuffle(&mut OsRng); diff --git a/dan_layer/rpc_state_sync/src/manager.rs b/dan_layer/rpc_state_sync/src/manager.rs index c0828e251..c19bad078 100644 --- a/dan_layer/rpc_state_sync/src/manager.rs +++ b/dan_layer/rpc_state_sync/src/manager.rs @@ -270,9 +270,16 @@ where TConsensusSpec: ConsensusSpec let local_committee = if block.justifies_parent() { Committee::new(vec![]) } else { - self.epoch_manager.get_local_committee(block.epoch()).await? + self.epoch_manager + .get_committees_by_shards(block.epoch(), vec![block.shard()].into_iter().collect()) + .await? + .into_iter() + .next() + .map(|(_, committee)| committee) + .unwrap_or_else(Committee::empty) }; + // TODO: Validate before we save anything. self.state_store.with_write_tx(|tx| { for transaction in transactions { transaction.save(tx)?; @@ -586,7 +593,7 @@ where TConsensusSpec: ConsensusSpec + Send + Sync + 'static // We are behind at least one epoch. // We get the current substate range, and we asks committees from previous epoch in this range to give us // data. - let local_shard = self.epoch_manager.get_local_committee_shard(current_epoch).await?; + let local_shard = self.epoch_manager.get_local_committee_info(current_epoch).await?; let current_num_committee = self.epoch_manager.get_num_committees(current_epoch).await?; let range = local_shard.shard().to_substate_address_range(current_num_committee); let prev_epoch = current_epoch.saturating_sub(Epoch(1)); @@ -638,7 +645,7 @@ where TConsensusSpec: ConsensusSpec + Send + Sync + 'static // We are behind at least one epoch. // We get the current substate range, and we asks committees from previous epoch in this range to give us // data. - let local_shard = self.epoch_manager.get_local_committee_shard(current_epoch).await?; + let local_shard = self.epoch_manager.get_local_committee_info(current_epoch).await?; let current_num_committee = self.epoch_manager.get_num_committees(current_epoch).await?; let range = local_shard.shard().to_substate_address_range(current_num_committee); let prev_epoch = current_epoch.saturating_sub(Epoch(1)); diff --git a/dan_layer/storage/src/consensus_models/transaction_pool.rs b/dan_layer/storage/src/consensus_models/transaction_pool.rs index 34ac9e887..298a1d03b 100644 --- a/dan_layer/storage/src/consensus_models/transaction_pool.rs +++ b/dan_layer/storage/src/consensus_models/transaction_pool.rs @@ -11,7 +11,7 @@ use std::{ use log::*; use serde::{Deserialize, Serialize}; use tari_dan_common_types::{ - committee::CommitteeShard, + committee::CommitteeInfo, optional::{IsNotFoundError, Optional}, }; use tari_transaction::TransactionId; @@ -388,10 +388,10 @@ impl TransactionPoolRecord { self } - pub fn add_evidence(&mut self, committee_shard: &CommitteeShard, qc_id: QcId) -> &mut Self { + pub fn add_evidence(&mut self, committee_info: &CommitteeInfo, qc_id: QcId) -> &mut Self { let evidence = &mut self.transaction.evidence; for (address, evidence_mut) in evidence.iter_mut() { - if committee_shard.includes_substate_address(address) { + if committee_info.includes_substate_address(address) { evidence_mut.qc_ids.insert(qc_id); } } @@ -448,9 +448,9 @@ impl TransactionPoolRecord { tx: &mut TTx, decision: Decision, foreign_qc_id: QcId, - foreign_committee_shard: &CommitteeShard, + foreign_committee_info: &CommitteeInfo, ) -> Result<(), TransactionPoolError> { - self.add_evidence(foreign_committee_shard, foreign_qc_id); + self.add_evidence(foreign_committee_info, foreign_qc_id); self.set_remote_decision(decision); tx.transaction_pool_update( &self.transaction.id, diff --git a/dan_layer/storage/src/global/backend_adapter.rs b/dan_layer/storage/src/global/backend_adapter.rs index fed386018..dba9e59cf 100644 --- a/dan_layer/storage/src/global/backend_adapter.rs +++ b/dan_layer/storage/src/global/backend_adapter.rs @@ -85,37 +85,38 @@ pub trait GlobalDbAdapter: AtomicDb + Send + Sync + Clone { address: Self::Addr, public_key: PublicKey, shard_key: SubstateAddress, - epoch: Epoch, + registered_at_base_height: u64, + start_epoch: Epoch, + end_epoch: Epoch, fee_claim_public_key: PublicKey, sidechain_id: Option, ) -> Result<(), Self::Error>; - fn get_validator_nodes_within_epochs( + fn get_validator_nodes_within_epoch( &self, tx: &mut Self::DbTransaction<'_>, - start_epoch: Epoch, - end_epoch: Epoch, + epoch: Epoch, sidechain_id: Option<&PublicKey>, ) -> Result>, Self::Error>; + fn get_validator_node_by_address( &self, tx: &mut Self::DbTransaction<'_>, - start_epoch: Epoch, - end_epoch: Epoch, + epoch: Epoch, address: &Self::Addr, + sidechain_id: Option<&PublicKey>, ) -> Result, Self::Error>; + fn get_validator_node_by_public_key( &self, tx: &mut Self::DbTransaction<'_>, - start_epoch: Epoch, - end_epoch: Epoch, + epoch: Epoch, public_key: &PublicKey, sidechain_id: Option<&PublicKey>, ) -> Result, Self::Error>; fn validator_nodes_count( &self, tx: &mut Self::DbTransaction<'_>, - start_epoch: Epoch, - end_epoch: Epoch, + epoch: Epoch, sidechain_id: Option<&PublicKey>, ) -> Result; fn validator_nodes_count_for_bucket( @@ -135,21 +136,26 @@ pub trait GlobalDbAdapter: AtomicDb + Send + Sync + Clone { epoch: Epoch, ) -> Result<(), Self::Error>; - fn validator_nodes_get_by_shard_range( + fn validator_nodes_get_by_substate_range( &self, tx: &mut Self::DbTransaction<'_>, - start_epoch: Epoch, - end_epoch: Epoch, + epoch: Epoch, sidechain_id: Option<&PublicKey>, - shard_range: RangeInclusive, + substate_range: RangeInclusive, ) -> Result>, Self::Error>; - fn validator_nodes_get_by_buckets( + fn validator_nodes_get_for_shards( &self, tx: &mut Self::DbTransaction<'_>, - start_epoch: Epoch, - end_epoch: Epoch, - buckets: HashSet, + epoch: Epoch, + shards: HashSet, + ) -> Result>, Self::Error>; + + fn validator_nodes_get_committees_for_epoch( + &self, + tx: &mut Self::DbTransaction<'_>, + epoch: Epoch, + sidechain_id: Option<&PublicKey>, ) -> Result>, Self::Error>; fn insert_epoch(&self, tx: &mut Self::DbTransaction<'_>, epoch: DbEpoch) -> Result<(), Self::Error>; diff --git a/dan_layer/storage/src/global/models/validator_node.rs b/dan_layer/storage/src/global/models/validator_node.rs index 709dfba20..42038c1e0 100644 --- a/dan_layer/storage/src/global/models/validator_node.rs +++ b/dan_layer/storage/src/global/models/validator_node.rs @@ -4,15 +4,16 @@ use serde::{Deserialize, Serialize}; use tari_common::configuration::Network; use tari_common_types::types::{FixedHash, PublicKey}; -use tari_dan_common_types::{shard::Shard, vn_node_hash, Epoch, NodeAddressable, SubstateAddress}; +use tari_dan_common_types::{vn_node_hash, Epoch, NodeAddressable, SubstateAddress}; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ValidatorNode { pub address: TAddr, pub public_key: PublicKey, pub shard_key: SubstateAddress, - pub epoch: Epoch, - pub committee_shard: Option, + pub registered_at_base_height: u64, + pub start_epoch: Epoch, + pub end_epoch: Epoch, pub fee_claim_public_key: PublicKey, pub sidechain_id: Option, } diff --git a/dan_layer/storage/src/global/validator_node_db.rs b/dan_layer/storage/src/global/validator_node_db.rs index 881c30ff5..802e5a7aa 100644 --- a/dan_layer/storage/src/global/validator_node_db.rs +++ b/dan_layer/storage/src/global/validator_node_db.rs @@ -20,10 +20,7 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use std::{ - collections::{HashMap, HashSet}, - ops::RangeInclusive, -}; +use std::collections::{HashMap, HashSet}; use tari_common_types::types::PublicKey; use tari_dan_common_types::{committee::Committee, shard::Shard, Epoch, SubstateAddress}; @@ -45,7 +42,9 @@ impl<'a, 'tx, TGlobalDbAdapter: GlobalDbAdapter> ValidatorNodeDb<'a, 'tx, TGloba peer_address: TGlobalDbAdapter::Addr, public_key: PublicKey, shard_key: SubstateAddress, - epoch: Epoch, + registered_at_base_height: u64, + start_epoch: Epoch, + end_epoch: Epoch, fee_claim_public_key: PublicKey, sidechain_id: Option, ) -> Result<(), TGlobalDbAdapter::Error> { @@ -55,21 +54,18 @@ impl<'a, 'tx, TGlobalDbAdapter: GlobalDbAdapter> ValidatorNodeDb<'a, 'tx, TGloba peer_address, public_key, shard_key, - epoch, + registered_at_base_height, + start_epoch, + end_epoch, fee_claim_public_key, sidechain_id, ) .map_err(TGlobalDbAdapter::Error::into) } - pub fn count( - &mut self, - start_epoch: Epoch, - end_epoch: Epoch, - sidechain_id: Option<&PublicKey>, - ) -> Result { + pub fn count(&mut self, epoch: Epoch, sidechain_id: Option<&PublicKey>) -> Result { self.backend - .validator_nodes_count(self.tx, start_epoch, end_epoch, sidechain_id) + .validator_nodes_count(self.tx, epoch, sidechain_id) .map_err(TGlobalDbAdapter::Error::into) } @@ -86,58 +82,64 @@ impl<'a, 'tx, TGlobalDbAdapter: GlobalDbAdapter> ValidatorNodeDb<'a, 'tx, TGloba pub fn get_by_public_key( &mut self, - start_epoch: Epoch, - end_epoch: Epoch, + epoch: Epoch, public_key: &PublicKey, sidechain_id: Option<&PublicKey>, ) -> Result, TGlobalDbAdapter::Error> { self.backend - .get_validator_node_by_public_key(self.tx, start_epoch, end_epoch, public_key, sidechain_id) + .get_validator_node_by_public_key(self.tx, epoch, public_key, sidechain_id) .map_err(TGlobalDbAdapter::Error::into) } pub fn get_by_address( &mut self, - start_epoch: Epoch, - end_epoch: Epoch, + epoch: Epoch, address: &TGlobalDbAdapter::Addr, + sidechain_id: Option<&PublicKey>, ) -> Result, TGlobalDbAdapter::Error> { self.backend - .get_validator_node_by_address(self.tx, start_epoch, end_epoch, address) + .get_validator_node_by_address(self.tx, epoch, address, sidechain_id) .map_err(TGlobalDbAdapter::Error::into) } - pub fn get_all_within_epochs( + pub fn get_all_within_epoch( &mut self, - start_epoch: Epoch, - end_epoch: Epoch, + epoch: Epoch, sidechain_id: Option<&PublicKey>, ) -> Result>, TGlobalDbAdapter::Error> { self.backend - .get_validator_nodes_within_epochs(self.tx, start_epoch, end_epoch, sidechain_id) + .get_validator_nodes_within_epoch(self.tx, epoch, sidechain_id) .map_err(TGlobalDbAdapter::Error::into) } - pub fn get_by_shard_range( + pub fn get_committees_for_shards( &mut self, - start_epoch: Epoch, - end_epoch: Epoch, - sidechain_id: Option<&PublicKey>, - shard_range: RangeInclusive, - ) -> Result>, TGlobalDbAdapter::Error> { + epoch: Epoch, + shards: HashSet, + ) -> Result>, TGlobalDbAdapter::Error> { self.backend - .validator_nodes_get_by_shard_range(self.tx, start_epoch, end_epoch, sidechain_id, shard_range) + .validator_nodes_get_for_shards(self.tx, epoch, shards) .map_err(TGlobalDbAdapter::Error::into) } - pub fn get_committees_by_buckets( + pub fn get_committee_for_shard( &mut self, - start_epoch: Epoch, - end_epoch: Epoch, - buckets: HashSet, + epoch: Epoch, + shard: Shard, + ) -> Result>, TGlobalDbAdapter::Error> { + let mut buckets = HashSet::new(); + buckets.insert(shard); + let res = self.get_committees_for_shards(epoch, buckets)?; + Ok(res.get(&shard).cloned()) + } + + pub fn get_committees( + &mut self, + epoch: Epoch, + sidechain_id: Option<&PublicKey>, ) -> Result>, TGlobalDbAdapter::Error> { self.backend - .validator_nodes_get_by_buckets(self.tx, start_epoch, end_epoch, buckets) + .validator_nodes_get_committees_for_epoch(self.tx, epoch, sidechain_id) .map_err(TGlobalDbAdapter::Error::into) } diff --git a/dan_layer/storage_sqlite/migrations/2022-09-30-212244_create_vns_and_committees/up.sql b/dan_layer/storage_sqlite/migrations/2022-09-30-212244_create_vns_and_committees/up.sql index 929e3c048..1c69f48f6 100644 --- a/dan_layer/storage_sqlite/migrations/2022-09-30-212244_create_vns_and_committees/up.sql +++ b/dan_layer/storage_sqlite/migrations/2022-09-30-212244_create_vns_and_committees/up.sql @@ -25,8 +25,8 @@ create table validator_nodes id integer primary key autoincrement not null, public_key blob not null, shard_key blob not null, - epoch bigint not null + registered_at_base_height bigint not null, + start_epoch bigint not null, + end_epoch bigint not null ); -create index validator_nodes_epoch_index on validator_nodes (epoch); -create unique index validator_nodes_public_key_uniq_idx on validator_nodes (public_key); diff --git a/dan_layer/storage_sqlite/migrations/2024-04-01-121212_add_sidechain_id/up.sql b/dan_layer/storage_sqlite/migrations/2024-04-01-121212_add_sidechain_id/up.sql index 93cbc8fe8..e6b11222d 100644 --- a/dan_layer/storage_sqlite/migrations/2024-04-01-121212_add_sidechain_id/up.sql +++ b/dan_layer/storage_sqlite/migrations/2024-04-01-121212_add_sidechain_id/up.sql @@ -2,6 +2,6 @@ ALTER TABLE validator_nodes ADD COLUMN sidechain_id BLOB NOT NULL; -drop index validator_nodes_public_key_uniq_idx; +-- drop index validator_nodes_public_key_uniq_idx; -create unique index validator_nodes_public_key_uniq_idx on validator_nodes (public_key, sidechain_id); \ No newline at end of file +-- create unique index validator_nodes_public_key_uniq_idx on validator_nodes (public_key, sidechain_id); \ No newline at end of file diff --git a/dan_layer/storage_sqlite/src/global/backend_adapter.rs b/dan_layer/storage_sqlite/src/global/backend_adapter.rs index 38377274b..8626556b7 100644 --- a/dan_layer/storage_sqlite/src/global/backend_adapter.rs +++ b/dan_layer/storage_sqlite/src/global/backend_adapter.rs @@ -33,7 +33,6 @@ use diesel::{ sql_types::{BigInt, Bigint}, ExpressionMethods, JoinOnDsl, - NullableExpressionMethods, OptionalExtension, QueryDsl, RunQueryDsl, @@ -364,7 +363,9 @@ impl GlobalDbAdapter for SqliteGlobalDbAdapter { address: Self::Addr, public_key: PublicKey, shard_key: SubstateAddress, - epoch: Epoch, + registered_at_base_height: u64, + start_epoch: Epoch, + end_epoch: Epoch, fee_claim_public_key: PublicKey, sidechain_id: Option, ) -> Result<(), Self::Error> { @@ -376,16 +377,9 @@ impl GlobalDbAdapter for SqliteGlobalDbAdapter { validator_nodes::address.eq(&addr), validator_nodes::public_key.eq(ByteArray::as_bytes(&public_key)), validator_nodes::shard_key.eq(shard_key.as_bytes()), - validator_nodes::epoch.eq(epoch.as_u64() as i64), - validator_nodes::fee_claim_public_key.eq(ByteArray::as_bytes(&fee_claim_public_key)), - validator_nodes::sidechain_id.eq(sidechain_id.as_ref().map(|id| id.as_bytes()).unwrap_or(&[0u8; 32])), - )) - .on_conflict((validator_nodes::public_key, validator_nodes::sidechain_id)) - .do_update() - .set(( - validator_nodes::address.eq(&addr), - validator_nodes::shard_key.eq(shard_key.as_bytes()), - validator_nodes::epoch.eq(epoch.as_u64() as i64), + validator_nodes::registered_at_base_height.eq(registered_at_base_height as i64), + validator_nodes::start_epoch.eq(start_epoch.as_u64() as i64), + validator_nodes::end_epoch.eq(end_epoch.as_u64() as i64), validator_nodes::fee_claim_public_key.eq(ByteArray::as_bytes(&fee_claim_public_key)), validator_nodes::sidechain_id.eq(sidechain_id.as_ref().map(|id| id.as_bytes()).unwrap_or(&[0u8; 32])), )) @@ -398,35 +392,68 @@ impl GlobalDbAdapter for SqliteGlobalDbAdapter { Ok(()) } + fn get_validator_node_by_address( + &self, + tx: &mut Self::DbTransaction<'_>, + epoch: Epoch, + address: &Self::Addr, + sidechain_id: Option<&PublicKey>, + ) -> Result, Self::Error> { + use crate::global::schema::validator_nodes; + + let vn = validator_nodes::table + .select(( + validator_nodes::id, + validator_nodes::public_key, + validator_nodes::shard_key, + validator_nodes::registered_at_base_height, + validator_nodes::start_epoch, + validator_nodes::end_epoch, + validator_nodes::fee_claim_public_key, + validator_nodes::address, + validator_nodes::sidechain_id, + )) + .filter(validator_nodes::start_epoch.le(epoch.as_u64() as i64)) + .filter(validator_nodes::end_epoch.gt(epoch.as_u64() as i64)) + .filter(validator_nodes::address.eq(serialize_json(address)?)) + .filter(validator_nodes::sidechain_id.eq(sidechain_id.map(ByteArray::as_bytes).unwrap_or(&[0u8; 32]))) + .order_by(validator_nodes::registered_at_base_height.desc()) + .first::(tx.connection()) + .map_err(|source| SqliteStorageError::DieselError { + source, + operation: "get::validator_node".to_string(), + })?; + + let vn = vn.try_into()?; + Ok(vn) + } + fn get_validator_node_by_public_key( &self, tx: &mut Self::DbTransaction<'_>, - start_epoch: Epoch, - end_epoch: Epoch, + epoch: Epoch, public_key: &PublicKey, sidechain_id: Option<&PublicKey>, ) -> Result, Self::Error> { - use crate::global::schema::{committees, validator_nodes}; + use crate::global::schema::validator_nodes; let vn = validator_nodes::table - .left_join(committees::table.on(committees::validator_node_id.eq(validator_nodes::id))) .select(( validator_nodes::id, validator_nodes::public_key, validator_nodes::shard_key, - coalesce_bigint(committees::epoch.nullable(), validator_nodes::epoch), - committees::committee_bucket.nullable(), + validator_nodes::registered_at_base_height, + validator_nodes::start_epoch, + validator_nodes::end_epoch, validator_nodes::fee_claim_public_key, validator_nodes::address, validator_nodes::sidechain_id, )) - .filter( - coalesce_bigint(committees::epoch.nullable(), validator_nodes::epoch).ge(start_epoch.as_u64() as i64), - ) - .filter(coalesce_bigint(committees::epoch.nullable(), validator_nodes::epoch).le(end_epoch.as_u64() as i64)) + .filter(validator_nodes::start_epoch.le(epoch.as_u64() as i64)) + .filter(validator_nodes::end_epoch.gt(epoch.as_u64() as i64)) .filter(validator_nodes::public_key.eq(ByteArray::as_bytes(public_key))) .filter(validator_nodes::sidechain_id.eq(sidechain_id.map(ByteArray::as_bytes).unwrap_or(&[0u8; 32]))) - .order_by(committees::epoch.desc()) + .order_by(validator_nodes::registered_at_base_height.desc()) .first::(tx.connection()) .map_err(|source| SqliteStorageError::DieselError { source, @@ -440,17 +467,16 @@ impl GlobalDbAdapter for SqliteGlobalDbAdapter { fn validator_nodes_count( &self, tx: &mut Self::DbTransaction<'_>, - start_epoch: Epoch, - end_epoch: Epoch, + epoch: Epoch, sidechain_id: Option<&PublicKey>, ) -> Result { let db_sidechain_id = sidechain_id.map(|id| id.as_bytes()).unwrap_or(&[0u8; 32]); let count = sql_query( - "SELECT COUNT(distinct public_key) as cnt FROM validator_nodes WHERE epoch >= ? AND epoch <= ? AND \ - sidechain_id = ?", + "SELECT COUNT(distinct public_key) as cnt FROM validator_nodes WHERE start_epoch <= ? AND end_epoch <= ? \ + AND sidechain_id = ?", ) - .bind::(start_epoch.as_u64() as i64) - .bind::(end_epoch.as_u64() as i64) + .bind::(epoch.as_u64() as i64) + .bind::(epoch.as_u64() as i64) .bind::(db_sidechain_id) .get_result::(tx.connection()) .map_err(|source| SqliteStorageError::DieselError { @@ -487,6 +513,46 @@ impl GlobalDbAdapter for SqliteGlobalDbAdapter { Ok(count as u64) } + fn validator_nodes_get_committees_for_epoch( + &self, + tx: &mut Self::DbTransaction<'_>, + epoch: Epoch, + sidechain_id: Option<&PublicKey>, + ) -> Result>, Self::Error> { + use crate::global::schema::{committees, validator_nodes}; + + let db_sidechain_id = sidechain_id.map(|id| id.as_bytes()).unwrap_or(&[0u8; 32]); + let count = committees::table + .inner_join(validator_nodes::table.on(committees::validator_node_id.eq(validator_nodes::id))) + .select(( + committees::committee_bucket, + validator_nodes::address, + validator_nodes::public_key, + )) + .filter(committees::epoch.eq(epoch.as_u64() as i64)) + .filter(validator_nodes::sidechain_id.eq(db_sidechain_id)) + .limit(1) + .load::<(i64, String, Vec)>(tx.connection()) + .map_err(|source| SqliteStorageError::DieselError { + source, + operation: "validator_nodes_get_committees".to_string(), + })?; + + let mut committees = HashMap::new(); + for (bucket, address, public_key) in count { + let addr = DbValidatorNode::try_parse_address(&address)?; + let pk = PublicKey::from_canonical_bytes(&public_key) + .map_err(|_| SqliteStorageError::MalformedDbData("Invalid public key".to_string()))?; + committees + .entry(Shard::from(bucket as u32)) + .or_insert_with(Committee::empty) + .members + .push((addr, pk)); + } + + Ok(committees) + } + fn validator_nodes_set_committee_bucket( &self, tx: &mut Self::DbTransaction<'_>, @@ -497,10 +563,15 @@ impl GlobalDbAdapter for SqliteGlobalDbAdapter { ) -> Result<(), Self::Error> { use crate::global::schema::{committees, validator_nodes}; let db_sidechain_id = sidechain_id.map(|id| id.as_bytes()).unwrap_or(&[0u8; 32]); + // This is probably not the most robust way of doing this. Ideally you would pass the validator ID to the + // function and use that to insert into the committees table. let validator_id = validator_nodes::table .select(validator_nodes::id) .filter(validator_nodes::shard_key.eq(shard_key.as_bytes())) + .filter(validator_nodes::start_epoch.le(epoch.as_u64() as i64)) + .filter(validator_nodes::end_epoch.gt(epoch.as_u64() as i64)) .filter(validator_nodes::sidechain_id.eq(db_sidechain_id)) + .order_by(validator_nodes::registered_at_base_height.desc()) .first::(tx.connection()) .map_err(|source| SqliteStorageError::DieselError { source, @@ -520,37 +591,37 @@ impl GlobalDbAdapter for SqliteGlobalDbAdapter { Ok(()) } - fn validator_nodes_get_by_shard_range( + fn validator_nodes_get_by_substate_range( &self, tx: &mut Self::DbTransaction<'_>, - start_epoch: Epoch, - end_epoch: Epoch, + epoch: Epoch, sidechain_id: Option<&PublicKey>, shard_range: RangeInclusive, ) -> Result>, Self::Error> { - use crate::global::schema::{committees, validator_nodes}; + // TODO: is this method still needed? Most of this can be handled by the committees table + use crate::global::schema::validator_nodes; let db_sidechain_id = sidechain_id.map(|id| id.as_bytes()).unwrap_or(&[0u8; 32]); let validators = validator_nodes::table - .left_join(committees::table.on(committees::validator_node_id.eq(validator_nodes::id))) .select(( validator_nodes::id, validator_nodes::public_key, validator_nodes::shard_key, - coalesce_bigint(committees::epoch.nullable(), validator_nodes::epoch), - committees::committee_bucket.nullable(), + validator_nodes::registered_at_base_height, + validator_nodes::start_epoch, + validator_nodes::end_epoch, validator_nodes::fee_claim_public_key, validator_nodes::address, validator_nodes::sidechain_id )) - .filter(coalesce_bigint(committees::epoch.nullable(), validator_nodes::epoch).ge(start_epoch.as_u64() as i64)) - .filter(coalesce_bigint(committees::epoch.nullable(), validator_nodes::epoch).le(end_epoch.as_u64() as i64)) + .filter(validator_nodes::start_epoch.le(epoch.as_u64() as i64)) + .filter(validator_nodes::end_epoch.gt(epoch.as_u64() as i64)) // SQLite compares BLOB types using memcmp which, IIRC, compares bytes "left to right"/big-endian which is // the same way convert shard IDs to 256-bit integers when allocating committee shards. .filter(validator_nodes::shard_key.ge(shard_range.start().as_bytes())) .filter(validator_nodes::shard_key.le(shard_range.end().as_bytes())) .filter(validator_nodes::sidechain_id.eq(db_sidechain_id)) - .order_by((validator_nodes::shard_key.asc(), committees::epoch.desc())) + .order_by(validator_nodes::shard_key.asc()) .get_results::(tx.connection()) .map_err(|source| SqliteStorageError::DieselError { source, @@ -560,130 +631,78 @@ impl GlobalDbAdapter for SqliteGlobalDbAdapter { distinct_validators_sorted(validators) } - fn validator_nodes_get_by_buckets( + fn validator_nodes_get_for_shards( &self, tx: &mut Self::DbTransaction<'_>, - start_epoch: Epoch, - end_epoch: Epoch, + epoch: Epoch, shards: HashSet, ) -> Result>, Self::Error> { use crate::global::schema::{committees, validator_nodes}; - - let validators = validator_nodes::table - .left_join(committees::table.on(committees::validator_node_id.eq(validator_nodes::id))) - .select(( - validator_nodes::id, - validator_nodes::public_key, - validator_nodes::shard_key, - coalesce_bigint(committees::epoch.nullable(), validator_nodes::epoch), - committees::committee_bucket.nullable(), - validator_nodes::fee_claim_public_key, - validator_nodes::address, - validator_nodes::sidechain_id, - )) - .filter( - coalesce_bigint(committees::epoch.nullable(), validator_nodes::epoch).ge(start_epoch.as_u64() as i64), - ) - .filter(coalesce_bigint(committees::epoch.nullable(), validator_nodes::epoch).le(end_epoch.as_u64() as i64)) - .filter(committees::committee_bucket.eq_any(shards.iter().map(|b| i64::from(b.as_u32())))) - .order_by(committees::epoch.desc()) - .get_results::(tx.connection()) - .map_err(|source| SqliteStorageError::DieselError { - source, - operation: "validator_nodes_get_by_buckets".to_string(), - })?; - let mut shards = shards .into_iter() .map(|b| (b, Committee::empty())) .collect::>(); - for validator in distinct_validators_sorted(validators)? { - let Some(bucket) = validator.committee_shard else { - continue; - }; - if let Some(committee_mut) = shards.get_mut(&bucket) { - committee_mut.members.push((validator.address, validator.public_key)); + for (shard, committee) in &mut shards { + let validators = validator_nodes::table + .left_join(committees::table.on(committees::validator_node_id.eq(validator_nodes::id))) + .select(validator_nodes::all_columns) + .filter(committees::epoch.eq(epoch.as_u64() as i64)) + .filter(committees::committee_bucket.eq(i64::from(shard.as_u32()))) + .get_results::(tx.connection()) + .map_err(|source| SqliteStorageError::DieselError { + source, + operation: "validator_nodes_get_by_buckets".to_string(), + })?; + + for validator in validators { + committee.members.push(( + DbValidatorNode::try_parse_address(&validator.address)?, + PublicKey::from_canonical_bytes(&validator.public_key).map_err(|_| { + SqliteStorageError::MalformedDbData(format!( + "Invalid public key in validator node record id={}", + validator.id + )) + })?, + )); } } - Ok(shards) } - fn get_validator_nodes_within_epochs( + fn get_validator_nodes_within_epoch( &self, tx: &mut Self::DbTransaction<'_>, - start_epoch: Epoch, - end_epoch: Epoch, + epoch: Epoch, sidechain_id: Option<&PublicKey>, ) -> Result>, Self::Error> { - use crate::global::schema::{committees, validator_nodes}; + use crate::global::schema::validator_nodes; let db_sidechain_id = sidechain_id.map(|id| id.as_bytes()).unwrap_or(&[0u8; 32]); let sqlite_vns = validator_nodes::table - .left_join(committees::table.on(committees::validator_node_id.eq(validator_nodes::id))) .select(( validator_nodes::id, validator_nodes::public_key, validator_nodes::shard_key, - coalesce_bigint(committees::epoch.nullable(), validator_nodes::epoch), - committees::committee_bucket.nullable(), + validator_nodes::registered_at_base_height, + validator_nodes::start_epoch, + validator_nodes::end_epoch, validator_nodes::fee_claim_public_key, validator_nodes::address, validator_nodes::sidechain_id, )) - .filter( - coalesce_bigint(committees::epoch.nullable(), validator_nodes::epoch).ge(start_epoch.as_u64() as i64), - ) - .filter(coalesce_bigint(committees::epoch.nullable(), validator_nodes::epoch).le(end_epoch.as_u64() as i64)) + .filter(validator_nodes::start_epoch.le(epoch.as_u64() as i64)) + .filter(validator_nodes::end_epoch.gt(epoch.as_u64() as i64)) .filter(validator_nodes::sidechain_id.eq(db_sidechain_id)) - .order_by(committees::epoch.desc()) .get_results::(tx.connection()) .map_err(|source| SqliteStorageError::DieselError { source, - operation: format!("get::get_validator_nodes_within_epochs({}, {})", start_epoch, end_epoch), + operation: format!("get::get_validator_nodes_within_epochs({})", epoch), })?; distinct_validators_sorted(sqlite_vns) } - fn get_validator_node_by_address( - &self, - tx: &mut Self::DbTransaction<'_>, - start_epoch: Epoch, - end_epoch: Epoch, - address: &Self::Addr, - ) -> Result, Self::Error> { - use crate::global::schema::{committees, validator_nodes}; - - let vn = validator_nodes::table - .left_join(committees::table.on(committees::validator_node_id.eq(validator_nodes::id))) - .select(( - validator_nodes::id, - validator_nodes::public_key, - validator_nodes::shard_key, - coalesce_bigint(committees::epoch.nullable(), validator_nodes::epoch), - committees::committee_bucket.nullable(), - validator_nodes::fee_claim_public_key, - validator_nodes::address, - validator_nodes::sidechain_id, - )) - .filter( - coalesce_bigint(committees::epoch.nullable(), validator_nodes::epoch).ge(start_epoch.as_u64() as i64), - ) - .filter(coalesce_bigint(committees::epoch.nullable(), validator_nodes::epoch).le(end_epoch.as_u64() as i64)) - .filter(validator_nodes::address.eq(serialize_json(address)?)) - .order_by(committees::epoch.desc()) - .first::(tx.connection()) - .map_err(|source| SqliteStorageError::DieselError { - source, - operation: "get::validator_node".to_string(), - })?; - - let vn = vn.try_into()?; - Ok(vn) - } - fn insert_epoch(&self, tx: &mut Self::DbTransaction<'_>, epoch: DbEpoch) -> Result<(), Self::Error> { use crate::global::schema::epochs; @@ -820,9 +839,11 @@ impl Clone for SqliteGlobalDbAdapter { } fn distinct_validators( - sqlite_vns: Vec, + mut sqlite_vns: Vec, ) -> Result>, SqliteStorageError> { + // first, sort by registration block height so that we get newer registrations first let mut db_vns = Vec::with_capacity(sqlite_vns.len()); + sqlite_vns.sort_by(|a, b| a.registered_at_base_height.cmp(&b.registered_at_base_height).reverse()); let mut dedup_map = HashSet::>::with_capacity(sqlite_vns.len()); for vn in sqlite_vns { if !dedup_map.contains(&vn.public_key) { diff --git a/dan_layer/storage_sqlite/src/global/models/validator_node.rs b/dan_layer/storage_sqlite/src/global/models/validator_node.rs index 41180ee26..4ee014a7d 100644 --- a/dan_layer/storage_sqlite/src/global/models/validator_node.rs +++ b/dan_layer/storage_sqlite/src/global/models/validator_node.rs @@ -21,7 +21,7 @@ // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. use tari_common_types::types::PublicKey; -use tari_dan_common_types::{shard::Shard, Epoch, NodeAddressable, SubstateAddress}; +use tari_dan_common_types::{Epoch, NodeAddressable, SubstateAddress}; use tari_dan_storage::global::models::ValidatorNode; use tari_utilities::ByteArray; @@ -36,8 +36,9 @@ pub struct DbValidatorNode { pub id: i32, pub public_key: Vec, pub shard_key: Vec, - pub epoch: i64, - pub committee_bucket: Option, + pub registered_at_base_height: i64, + pub start_epoch: i64, + pub end_epoch: i64, pub fee_claim_public_key: Vec, pub address: String, pub sidechain_id: Vec, @@ -50,13 +51,13 @@ impl TryFrom for ValidatorNode { shard_key: SubstateAddress::try_from(vn.shard_key).map_err(|_| { SqliteStorageError::MalformedDbData(format!("Invalid shard id in validator node record id={}", vn.id)) })?, - address: deserialize_json(&vn.address)?, + address: DbValidatorNode::try_parse_address(&vn.address)?, public_key: PublicKey::from_canonical_bytes(&vn.public_key).map_err(|_| { SqliteStorageError::MalformedDbData(format!("Invalid public key in validator node record id={}", vn.id)) })?, - epoch: Epoch(vn.epoch as u64), - committee_shard: vn.committee_bucket.map(|v| v as u32).map(Shard::from), - + registered_at_base_height: vn.registered_at_base_height as u64, + start_epoch: Epoch(vn.start_epoch as u64), + end_epoch: Epoch(vn.end_epoch as u64), fee_claim_public_key: PublicKey::from_canonical_bytes(&vn.fee_claim_public_key).map_err(|_| { SqliteStorageError::MalformedDbData(format!( "Invalid fee claim public key in validator node record id={}", @@ -77,11 +78,8 @@ impl TryFrom for ValidatorNode { } } -#[derive(Insertable)] -#[diesel(table_name = validator_nodes)] -pub struct NewValidatorNode { - pub public_key: Vec, - pub shard_key: Vec, - pub epoch: i64, - pub fee_claim_public_key: Vec, +impl DbValidatorNode { + pub fn try_parse_address(address: &str) -> Result { + deserialize_json(address) + } } diff --git a/dan_layer/storage_sqlite/src/global/schema.rs b/dan_layer/storage_sqlite/src/global/schema.rs index 56ebf90ec..807c9eef3 100644 --- a/dan_layer/storage_sqlite/src/global/schema.rs +++ b/dan_layer/storage_sqlite/src/global/schema.rs @@ -60,7 +60,9 @@ diesel::table! { id -> Integer, public_key -> Binary, shard_key -> Binary, - epoch -> BigInt, + registered_at_base_height -> BigInt, + start_epoch -> BigInt, + end_epoch -> BigInt, fee_claim_public_key -> Binary, address -> Text, sidechain_id -> Binary, diff --git a/dan_layer/storage_sqlite/tests/global_db.rs b/dan_layer/storage_sqlite/tests/global_db.rs index 4463149c5..74b28f43b 100644 --- a/dan_layer/storage_sqlite/tests/global_db.rs +++ b/dan_layer/storage_sqlite/tests/global_db.rs @@ -34,14 +34,21 @@ fn insert_vns( sidechain_id: Option, ) { for _ in 0..num { - insert_vn_with_public_key(validator_nodes, new_public_key(), epoch, sidechain_id.clone()) + insert_vn_with_public_key( + validator_nodes, + new_public_key(), + epoch, + epoch + Epoch(1), + sidechain_id.clone(), + ) } } fn insert_vn_with_public_key( validator_nodes: &mut ValidatorNodeDb<'_, '_, SqliteGlobalDbAdapter>, public_key: PublicKey, - epoch: Epoch, + start_epoch: Epoch, + end_epoch: Epoch, sidechain_id: Option, ) { validator_nodes @@ -49,7 +56,9 @@ fn insert_vn_with_public_key( public_key.clone().into(), public_key.clone(), derived_substate_address(&public_key), - epoch, + 0, + start_epoch, + end_epoch, public_key, sidechain_id, ) @@ -72,12 +81,9 @@ fn insert_and_get_within_epoch() { let db = create_db(); let mut tx = db.create_transaction().unwrap(); let mut validator_nodes = db.validator_nodes(&mut tx); - insert_vns(&mut validator_nodes, 2, Epoch(0), None); - insert_vns(&mut validator_nodes, 1, Epoch(10), None); - - let vns = validator_nodes - .get_all_within_epochs(Epoch(0), Epoch(10), None) - .unwrap(); + insert_vns(&mut validator_nodes, 3, Epoch(0), None); + insert_vns(&mut validator_nodes, 2, Epoch(1), None); + let vns = validator_nodes.get_all_within_epoch(Epoch(0), None).unwrap(); assert_eq!(vns.len(), 3); } @@ -87,70 +93,14 @@ fn change_committee_bucket() { let mut tx = db.create_transaction().unwrap(); let mut validator_nodes = db.validator_nodes(&mut tx); let pk = new_public_key(); - insert_vn_with_public_key(&mut validator_nodes, pk.clone(), Epoch(0), None); + insert_vn_with_public_key(&mut validator_nodes, pk.clone(), Epoch(0), Epoch(4), None); update_committee_bucket(&mut validator_nodes, &pk, Shard::from(1), Epoch(0)); update_committee_bucket(&mut validator_nodes, &pk, Shard::from(3), Epoch(1)); update_committee_bucket(&mut validator_nodes, &pk, Shard::from(7), Epoch(2)); update_committee_bucket(&mut validator_nodes, &pk, Shard::from(4), Epoch(3)); let vns = validator_nodes - .get_all_within_epochs(Epoch(0), Epoch(10), None) - .unwrap(); - assert_eq!(vns[0].committee_shard, Some(Shard::from(4))); -} - -#[test] -fn insert_and_get_within_shard_range_duplicate_public_keys() { - // Testing fetching within a shard range. Specifically, the ability for Sqlite to compare blob columns - let db = create_db(); - let mut tx = db.create_transaction().unwrap(); - let mut validator_nodes = db.validator_nodes(&mut tx); - // Insert lower shard key - insert_vn_with_public_key(&mut validator_nodes, PublicKey::default(), Epoch(0), None); - - let pk = new_public_key(); - insert_vn_with_public_key(&mut validator_nodes, pk.clone(), Epoch(0), None); - update_committee_bucket(&mut validator_nodes, &pk, Shard::from(0), Epoch(0)); - update_committee_bucket(&mut validator_nodes, &pk, Shard::from(2), Epoch(2)); - let pk2 = new_public_key(); - insert_vn_with_public_key(&mut validator_nodes, pk2.clone(), Epoch(1), None); - update_committee_bucket(&mut validator_nodes, &pk2, Shard::from(1), Epoch(1)); - update_committee_bucket(&mut validator_nodes, &pk2, Shard::from(3), Epoch(3)); - - tx.commit().unwrap(); - let mut tx = db.create_transaction().unwrap(); - let mut validator_nodes = db.validator_nodes(&mut tx); - - let shard_id = derived_substate_address(&pk); - let shard_id2 = derived_substate_address(&pk2); - let (start, end) = if shard_id > shard_id2 { - (shard_id2, shard_id) - } else { - (shard_id, shard_id2) - }; - - let vns = validator_nodes - .get_by_shard_range(Epoch(0), Epoch(10), None, start..=end) - .unwrap(); - if shard_id > shard_id2 { - assert_eq!(vns[0].public_key, pk2); - assert_eq!(vns[0].committee_shard, Some(Shard::from(3))); - assert_eq!(vns[0].epoch, Epoch(3)); - assert_eq!(vns[1].public_key, pk); - assert_eq!(vns[1].committee_shard, Some(Shard::from(2))); - assert_eq!(vns[1].epoch, Epoch(2)); - } else { - assert_eq!(vns[0].public_key, pk); - assert_eq!(vns[0].committee_shard, Some(Shard::from(2))); - assert_eq!(vns[0].epoch, Epoch(2)); - assert_eq!(vns[1].public_key, pk2); - assert_eq!(vns[1].committee_shard, Some(Shard::from(3))); - assert_eq!(vns[1].epoch, Epoch(3)); - } - assert_eq!(vns.len(), 2); - - let vn = validator_nodes - .get_by_public_key(Epoch(0), Epoch(10), &pk, None) + .get_committee_for_shard(Epoch(3), Shard::from(4)) + .unwrap() .unwrap(); - assert_eq!(vn.epoch, Epoch(2)); - assert_eq!(vn.committee_shard, Some(Shard::from(2))); + assert_eq!(vns.len(), 1); } diff --git a/dan_layer/template_test_tooling/templates/faucet/Cargo.lock b/dan_layer/template_test_tooling/templates/faucet/Cargo.lock index 2cd63834a..a0c8e36c3 100644 --- a/dan_layer/template_test_tooling/templates/faucet/Cargo.lock +++ b/dan_layer/template_test_tooling/templates/faucet/Cargo.lock @@ -376,7 +376,7 @@ dependencies = [ [[package]] name = "tari_bor" -version = "0.5.1" +version = "0.5.3" dependencies = [ "ciborium", "ciborium-io", @@ -385,7 +385,7 @@ dependencies = [ [[package]] name = "tari_template_abi" -version = "0.5.1" +version = "0.5.3" dependencies = [ "serde", "tari_bor", @@ -393,7 +393,7 @@ dependencies = [ [[package]] name = "tari_template_lib" -version = "0.5.1" +version = "0.5.3" dependencies = [ "newtype-ops", "serde", @@ -405,7 +405,7 @@ dependencies = [ [[package]] name = "tari_template_macros" -version = "0.5.1" +version = "0.5.3" dependencies = [ "proc-macro2", "quote", diff --git a/integration_tests/src/wallet_daemon_cli.rs b/integration_tests/src/wallet_daemon_cli.rs index 7b53ff39c..45fa27227 100644 --- a/integration_tests/src/wallet_daemon_cli.rs +++ b/integration_tests/src/wallet_daemon_cli.rs @@ -290,7 +290,6 @@ pub async fn create_account_with_free_coins( .get(&k) .unwrap_or_else(|| panic!("Wallet {} not found", wallet_daemon_name)) }); - dbg!(key_index); let request = AccountsCreateFreeTestCoinsRequest { account: Some(ComponentAddressOrName::Name(account_name.clone())), amount, diff --git a/integration_tests/tests/features/block_sync.feature b/integration_tests/tests/features/block_sync.feature index 5edc56fa4..66444d8bb 100644 --- a/integration_tests/tests/features/block_sync.feature +++ b/integration_tests/tests/features/block_sync.feature @@ -1,6 +1,6 @@ # Copyright 2022 The Tari Project # SPDX-License-Identifier: BSD-3-Clause - +@block_sync Feature: Block Sync @serial @fixed diff --git a/integration_tests/tests/features/claim_burn.feature b/integration_tests/tests/features/claim_burn.feature index dcf9dbd83..fc63e7381 100644 --- a/integration_tests/tests/features/claim_burn.feature +++ b/integration_tests/tests/features/claim_burn.feature @@ -1,6 +1,6 @@ # Copyright 2022 The Tari Project # SPDX-License-Identifier: BSD-3-Clause - +@claim_burn Feature: Claim Burn @serial @fixed diff --git a/integration_tests/tests/features/claim_fees.feature b/integration_tests/tests/features/claim_fees.feature index 7dcea7c36..ebe16fb4a 100644 --- a/integration_tests/tests/features/claim_fees.feature +++ b/integration_tests/tests/features/claim_fees.feature @@ -1,6 +1,6 @@ # Copyright 2022 The Tari Project # SPDX-License-Identifier: BSD-3-Clause - +@claim_fees Feature: Claim Fees @serial @fixed Scenario: Claim validator fees diff --git a/integration_tests/tests/features/committee.feature b/integration_tests/tests/features/committee.feature index 5a0468157..84c2fa3c2 100644 --- a/integration_tests/tests/features/committee.feature +++ b/integration_tests/tests/features/committee.feature @@ -1,6 +1,6 @@ # Copyright 2022 The Tari Project # SPDX-License-Identifier: BSD-3-Clause - +@committee Feature: Committee scenarios @serial @fixed diff --git a/integration_tests/tests/features/concurrency.feature b/integration_tests/tests/features/concurrency.feature index 429387a74..71b6e8483 100644 --- a/integration_tests/tests/features/concurrency.feature +++ b/integration_tests/tests/features/concurrency.feature @@ -1,6 +1,7 @@ # Copyright 2024 The Tari Project # SPDX-License-Identifier: BSD-3-Clause +@concurrency Feature: Concurrency @serial diff --git a/integration_tests/tests/features/counter.feature b/integration_tests/tests/features/counter.feature index 901e937eb..00160569d 100644 --- a/integration_tests/tests/features/counter.feature +++ b/integration_tests/tests/features/counter.feature @@ -1,6 +1,7 @@ # Copyright 2022 The Tari Project # SPDX-License-Identifier: BSD-3-Clause +@counter Feature: Counter template @serial diff --git a/integration_tests/tests/features/epoch_change.feature b/integration_tests/tests/features/epoch_change.feature index 30dd94fce..2b50f3725 100644 --- a/integration_tests/tests/features/epoch_change.feature +++ b/integration_tests/tests/features/epoch_change.feature @@ -1,9 +1,10 @@ # Copyright 2022 The Tari Project # SPDX-License-Identifier: BSD-3-Clause +@epoch_change Feature: Epoch change - @serial + @serial @current Scenario: EpochEnd and EpochStart commands are used on epoch change Given fees are disabled # Initialize a base node, wallet, miner and VN diff --git a/integration_tests/tests/features/fungible.feature b/integration_tests/tests/features/fungible.feature index 0b3a29b66..9e8646cd9 100644 --- a/integration_tests/tests/features/fungible.feature +++ b/integration_tests/tests/features/fungible.feature @@ -1,6 +1,7 @@ # Copyright 2022 The Tari Project # SPDX-License-Identifier: BSD-3-Clause +@fungible Feature: Fungible tokens @serial diff --git a/integration_tests/tests/features/indexer.feature b/integration_tests/tests/features/indexer.feature index e07b722db..979176fe9 100644 --- a/integration_tests/tests/features/indexer.feature +++ b/integration_tests/tests/features/indexer.feature @@ -1,7 +1,7 @@ # Copyright 2022 The Tari Project # SPDX-License-Identifier: BSD-3-Clause - +@indexer Feature: Indexer node @serial diff --git a/integration_tests/tests/features/nft.feature b/integration_tests/tests/features/nft.feature index 629aad828..17f80a0a4 100644 --- a/integration_tests/tests/features/nft.feature +++ b/integration_tests/tests/features/nft.feature @@ -1,9 +1,10 @@ # Copyright 2022 The Tari Project # SPDX-License-Identifier: BSD-3-Clause +@nft Feature: NFTs - @serial @current + @serial Scenario: Mint, mutate and burn non fungible tokens Given fees are disabled # Initialize a base node, wallet, miner and VN diff --git a/integration_tests/tests/features/substates.feature b/integration_tests/tests/features/substates.feature index 940d772cc..d00cce78c 100644 --- a/integration_tests/tests/features/substates.feature +++ b/integration_tests/tests/features/substates.feature @@ -1,6 +1,7 @@ # Copyright 2022 The Tari Project # SPDX-License-Identifier: BSD-3-Clause +@substates Feature: Substates @serial diff --git a/integration_tests/tests/features/transfer.feature b/integration_tests/tests/features/transfer.feature index 4b17e69e1..16e234489 100644 --- a/integration_tests/tests/features/transfer.feature +++ b/integration_tests/tests/features/transfer.feature @@ -1,6 +1,7 @@ # Copyright 2022 The Tari Project # SPDX-License-Identifier: BSD-3-Clause +@transfer Feature: Account transfers @serial diff --git a/integration_tests/tests/features/wallet_daemon.feature b/integration_tests/tests/features/wallet_daemon.feature index ca21e3e41..d892f5997 100644 --- a/integration_tests/tests/features/wallet_daemon.feature +++ b/integration_tests/tests/features/wallet_daemon.feature @@ -1,6 +1,7 @@ # Copyright 2022 The Tari Project # SPDX-License-Identifier: BSD-3-Clause +@wallet_daemon Feature: Wallet Daemon @serial