From 72018f4834b8ee8fe1228c25a6be33189bdd2a3c Mon Sep 17 00:00:00 2001 From: stringhandler Date: Tue, 27 Sep 2022 11:31:46 +0200 Subject: [PATCH] fix: fix validator node registration logic (#4718) --- .../tari_app_grpc/proto/base_node.proto | 11 +- .../src/conversions/active_validator_node.rs | 59 --------- .../tari_app_grpc/src/conversions/mod.rs | 1 - .../src/grpc/base_node_grpc_server.rs | 29 +---- .../comms_interface/comms_response.rs | 4 +- .../comms_interface/local_interface.rs | 2 +- .../chain_storage/active_validator_node.rs | 3 +- base_layer/core/src/chain_storage/async_db.rs | 3 +- .../src/chain_storage/blockchain_backend.rs | 2 +- .../src/chain_storage/blockchain_database.rs | 4 +- .../core/src/chain_storage/db_transaction.rs | 6 +- .../core/src/chain_storage/lmdb_db/lmdb_db.rs | 115 ++++++++++++------ .../core/src/consensus/consensus_constants.rs | 4 +- .../core/src/test_helpers/blockchain.rs | 5 +- 14 files changed, 103 insertions(+), 145 deletions(-) delete mode 100644 applications/tari_app_grpc/src/conversions/active_validator_node.rs diff --git a/applications/tari_app_grpc/proto/base_node.proto b/applications/tari_app_grpc/proto/base_node.proto index 063ff4481c..957176e14b 100644 --- a/applications/tari_app_grpc/proto/base_node.proto +++ b/applications/tari_app_grpc/proto/base_node.proto @@ -89,7 +89,7 @@ service BaseNode { // Get mempool stats rpc GetMempoolStats(Empty) returns (MempoolStatsResponse); // Get VNs - rpc GetActiveValidatorNodes(GetActiveValidatorNodesRequest) returns (stream ActiveValidatorNode); + rpc GetActiveValidatorNodes(GetActiveValidatorNodesRequest) returns (stream GetActiveValidatorNodesResponse); rpc GetCommittee(GetCommitteeRequest) returns (GetCommitteeResponse); rpc GetShardKey(GetShardKeyRequest) returns (GetShardKeyResponse); } @@ -442,13 +442,12 @@ message GetActiveValidatorNodesRequest { uint64 height = 1; } -message ActiveValidatorNode { +message GetActiveValidatorNodesResponse { bytes shard_key = 1; - uint64 from_height = 2; - uint64 to_height = 3; - bytes public_key = 4; + bytes public_key = 2; } + message GetCommitteeRequest { uint64 height = 1; bytes shard_key = 2; @@ -465,4 +464,4 @@ message GetShardKeyRequest { message GetShardKeyResponse { bytes shard_key = 1; -} \ No newline at end of file +} diff --git a/applications/tari_app_grpc/src/conversions/active_validator_node.rs b/applications/tari_app_grpc/src/conversions/active_validator_node.rs deleted file mode 100644 index 4c22cd8116..0000000000 --- a/applications/tari_app_grpc/src/conversions/active_validator_node.rs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2020. The Tari Project -// -// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the -// following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following -// disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the -// following disclaimer in the documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote -// products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// 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::convert::{TryFrom, TryInto}; - -use tari_common_types::types::PublicKey; -use tari_core::chain_storage::ActiveValidatorNode; -use tari_utilities::ByteArray; - -use crate::tari_rpc as grpc; - -impl TryFrom for grpc::ActiveValidatorNode { - type Error = String; - - fn try_from(active_validator_node: ActiveValidatorNode) -> Result { - Ok(Self { - shard_key: active_validator_node.shard_key.to_vec(), - from_height: active_validator_node.from_height, - to_height: active_validator_node.to_height, - public_key: active_validator_node.public_key.to_vec(), - }) - } -} - -impl TryFrom for ActiveValidatorNode { - type Error = String; - - fn try_from(active_validator_node: grpc::ActiveValidatorNode) -> Result { - let shard_key = active_validator_node.shard_key.try_into().unwrap(); - let public_key = - PublicKey::from_vec(&active_validator_node.public_key).map_err(|_| "Could not public key".to_string())?; - - Ok(Self { - shard_key, - from_height: active_validator_node.from_height, - to_height: active_validator_node.to_height, - public_key, - }) - } -} diff --git a/applications/tari_app_grpc/src/conversions/mod.rs b/applications/tari_app_grpc/src/conversions/mod.rs index eb58f7d42c..f9b6d30455 100644 --- a/applications/tari_app_grpc/src/conversions/mod.rs +++ b/applications/tari_app_grpc/src/conversions/mod.rs @@ -20,7 +20,6 @@ // 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. -mod active_validator_node; mod aggregate_body; mod base_node_state; mod block; diff --git a/applications/tari_base_node/src/grpc/base_node_grpc_server.rs b/applications/tari_base_node/src/grpc/base_node_grpc_server.rs index 98f78a490a..61666eac5d 100644 --- a/applications/tari_base_node/src/grpc/base_node_grpc_server.rs +++ b/applications/tari_base_node/src/grpc/base_node_grpc_server.rs @@ -135,7 +135,7 @@ impl BaseNodeGrpcServer {} #[tonic::async_trait] impl tari_rpc::base_node_server::BaseNode for BaseNodeGrpcServer { type FetchMatchingUtxosStream = mpsc::Receiver>; - type GetActiveValidatorNodesStream = mpsc::Receiver>; + type GetActiveValidatorNodesStream = mpsc::Receiver>; type GetBlocksStream = mpsc::Receiver>; type GetMempoolTransactionsStream = mpsc::Receiver>; type GetNetworkDifficultyStream = mpsc::Receiver>; @@ -1488,28 +1488,11 @@ impl tari_rpc::base_node_server::BaseNode for BaseNodeGrpcServer { }, Ok(data) => data, }; - for active_validator_node in active_validator_nodes { - let active_validator_node = match tari_rpc::ActiveValidatorNode::try_from(active_validator_node) { - Ok(t) => t, - Err(e) => { - warn!( - target: LOG_TARGET, - "Error sending converting active validator node for GRPC: {}", e - ); - match tx - .send(Err(obscure_error_if_true( - report_error_flag, - Status::internal("Error converting active validator node"), - ))) - .await - { - Ok(_) => (), - Err(send_err) => { - warn!(target: LOG_TARGET, "Error sending error to GRPC client: {}", send_err) - }, - } - return; - }, + dbg!(&active_validator_nodes); + for (public_key, shard_key) in active_validator_nodes { + let active_validator_node = tari_rpc::GetActiveValidatorNodesResponse { + public_key: public_key.to_vec(), + shard_key: shard_key.to_vec(), }; match tx.send(Ok(active_validator_node)).await { diff --git a/base_layer/core/src/base_node/comms_interface/comms_response.rs b/base_layer/core/src/base_node/comms_interface/comms_response.rs index 6298ba8cc7..214b00216e 100644 --- a/base_layer/core/src/base_node/comms_interface/comms_response.rs +++ b/base_layer/core/src/base_node/comms_interface/comms_response.rs @@ -27,7 +27,7 @@ use std::{ use tari_common_types::{ chain_metadata::ChainMetadata, - types::{HashOutput, PrivateKey}, + types::{HashOutput, PrivateKey, PublicKey}, }; use crate::{ @@ -71,7 +71,7 @@ pub enum NodeCommsResponse { FetchOutputsByContractIdResponse { outputs: Vec, }, - FetchValidatorNodesKeysResponse(Vec), + FetchValidatorNodesKeysResponse(Vec<(PublicKey, [u8; 32])>), FetchCommitteeResponse(Vec), GetShardKeyResponse([u8; 32]), } diff --git a/base_layer/core/src/base_node/comms_interface/local_interface.rs b/base_layer/core/src/base_node/comms_interface/local_interface.rs index be699e725d..ada66a3644 100644 --- a/base_layer/core/src/base_node/comms_interface/local_interface.rs +++ b/base_layer/core/src/base_node/comms_interface/local_interface.rs @@ -276,7 +276,7 @@ impl LocalNodeCommsInterface { pub async fn get_active_validator_nodes( &mut self, height: u64, - ) -> Result, CommsInterfaceError> { + ) -> Result, CommsInterfaceError> { match self .request_sender .call(NodeCommsRequest::FetchValidatorNodesKeys { height }) diff --git a/base_layer/core/src/chain_storage/active_validator_node.rs b/base_layer/core/src/chain_storage/active_validator_node.rs index fa6a4a7dfe..374317bc20 100644 --- a/base_layer/core/src/chain_storage/active_validator_node.rs +++ b/base_layer/core/src/chain_storage/active_validator_node.rs @@ -21,7 +21,7 @@ // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. use serde::{Deserialize, Serialize}; -use tari_common_types::types::PublicKey; +use tari_common_types::types::{HashOutput, PublicKey}; #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct ActiveValidatorNode { @@ -29,4 +29,5 @@ pub struct ActiveValidatorNode { pub from_height: u64, pub to_height: u64, pub public_key: PublicKey, + pub output_hash: HashOutput, } diff --git a/base_layer/core/src/chain_storage/async_db.rs b/base_layer/core/src/chain_storage/async_db.rs index 95bccf91b1..14ad5b9c35 100644 --- a/base_layer/core/src/chain_storage/async_db.rs +++ b/base_layer/core/src/chain_storage/async_db.rs @@ -64,7 +64,6 @@ use crate::{ proof_of_work::{PowAlgorithm, TargetDifficultyWindow}, transactions::transaction_components::{TransactionKernel, TransactionOutput}, }; - const LOG_TARGET: &str = "c::bn::async_db"; fn trace_log(name: &str, f: F) -> R @@ -266,7 +265,7 @@ impl AsyncBlockchainDb { make_async_fn!(fetch_total_size_stats() -> DbTotalSizeStats, "fetch_total_size_stats"); - make_async_fn!(fetch_active_validator_nodes(height: u64) -> Vec, "fetch_active_validator_nodes"); + make_async_fn!(fetch_active_validator_nodes(height: u64) -> Vec<(PublicKey, [u8;32])>, "fetch_active_validator_nodes"); make_async_fn!(fetch_committee(height: u64, shard: [u8;32]) -> Vec, "fetch_committee"); diff --git a/base_layer/core/src/chain_storage/blockchain_backend.rs b/base_layer/core/src/chain_storage/blockchain_backend.rs index c7f0d72626..fbc8dc1b4d 100644 --- a/base_layer/core/src/chain_storage/blockchain_backend.rs +++ b/base_layer/core/src/chain_storage/blockchain_backend.rs @@ -193,7 +193,7 @@ pub trait BlockchainBackend: Send + Sync { /// Fetches all tracked reorgs fn fetch_all_reorgs(&self) -> Result, ChainStorageError>; - fn fetch_active_validator_nodes(&self, height: u64) -> Result, ChainStorageError>; + fn fetch_active_validator_nodes(&self, height: u64) -> Result, ChainStorageError>; fn fetch_committee(&self, height: u64, shard: [u8; 32]) -> Result, ChainStorageError>; fn get_shard_key(&self, height: u64, public_key: PublicKey) -> Result<[u8; 32], ChainStorageError>; } diff --git a/base_layer/core/src/chain_storage/blockchain_database.rs b/base_layer/core/src/chain_storage/blockchain_database.rs index 0b3b882428..59d54b4c23 100644 --- a/base_layer/core/src/chain_storage/blockchain_database.rs +++ b/base_layer/core/src/chain_storage/blockchain_database.rs @@ -1172,7 +1172,7 @@ where B: BlockchainBackend db.write(txn) } - pub fn fetch_active_validator_nodes(&self, height: u64) -> Result, ChainStorageError> { + pub fn fetch_active_validator_nodes(&self, height: u64) -> Result, ChainStorageError> { let db = self.db_read_access()?; db.fetch_active_validator_nodes(height) } @@ -1322,7 +1322,7 @@ pub fn calculate_mmr_roots(db: &T, block: &Block) -> Resul output_mmr.compress(); let validator_nodes = db.fetch_active_validator_nodes(metadata.height_of_longest_chain() + 1)?; - let vn_mmr = ValidatorNodeMmr::new(validator_nodes.iter().map(|vn| vn.shard_key.to_vec()).collect()); + let vn_mmr = ValidatorNodeMmr::new(validator_nodes.iter().map(|vn| vn.1.to_vec()).collect()); let mmr_roots = MmrRoots { kernel_mr: FixedHash::try_from(kernel_mmr.get_merkle_root()?)?, diff --git a/base_layer/core/src/chain_storage/db_transaction.rs b/base_layer/core/src/chain_storage/db_transaction.rs index 105f217f29..6eb2ed3f4f 100644 --- a/base_layer/core/src/chain_storage/db_transaction.rs +++ b/base_layer/core/src/chain_storage/db_transaction.rs @@ -27,7 +27,7 @@ use std::{ }; use croaring::Bitmap; -use tari_common_types::types::{BlockHash, Commitment, HashOutput, PublicKey}; +use tari_common_types::types::{BlockHash, Commitment, HashOutput}; use tari_utilities::hex::Hex; use super::ActiveValidatorNode; @@ -362,9 +362,6 @@ pub enum WriteOperation { InsertValidatorNode { validator_node: ActiveValidatorNode, }, - DeleteValidatorNode { - public_key: PublicKey, - }, } impl fmt::Display for WriteOperation { @@ -464,7 +461,6 @@ impl fmt::Display for WriteOperation { InsertValidatorNode { validator_node } => { write!(f, "Inserting VN {:?}", validator_node) }, - DeleteValidatorNode { public_key } => write!(f, "Delete VN key {}", public_key), } } } diff --git a/base_layer/core/src/chain_storage/lmdb_db/lmdb_db.rs b/base_layer/core/src/chain_storage/lmdb_db/lmdb_db.rs index 8586c28516..977b381319 100644 --- a/base_layer/core/src/chain_storage/lmdb_db/lmdb_db.rs +++ b/base_layer/core/src/chain_storage/lmdb_db/lmdb_db.rs @@ -25,7 +25,18 @@ #![allow(clippy::ptr_arg)] -use std::{convert::TryFrom, fmt, fs, fs::File, mem, ops::Deref, path::Path, sync::Arc, time::Instant}; +use std::{ + collections::HashMap, + convert::TryFrom, + fmt, + fs, + fs::File, + mem, + ops::Deref, + path::Path, + sync::Arc, + time::Instant, +}; use croaring::Bitmap; use fs2::FileExt; @@ -133,6 +144,7 @@ const LMDB_DB_BAD_BLOCK_LIST: &str = "bad_blocks"; const LMDB_DB_REORGS: &str = "reorgs"; const LMDB_DB_VALIDATOR_NODES: &str = "validator_nodes"; const LMDB_DB_VALIDATOR_NODES_MAPPING: &str = "validator_nodes_mapping"; +const LMDB_DB_VALIDATOR_NODE_ENDING: &str = "validator_node_ending"; pub fn create_lmdb_database>( path: P, @@ -177,6 +189,7 @@ pub fn create_lmdb_database>( .add_database(LMDB_DB_REORGS, flags | db::INTEGERKEY) .add_database(LMDB_DB_VALIDATOR_NODES, flags | db::DUPSORT) .add_database(LMDB_DB_VALIDATOR_NODES_MAPPING, flags | db::DUPSORT) + .add_database(LMDB_DB_VALIDATOR_NODE_ENDING, flags | db::INTEGERKEY | db::DUPSORT) .build() .map_err(|err| ChainStorageError::CriticalError(format!("Could not create LMDB store:{}", err)))?; debug!(target: LOG_TARGET, "LMDB database creation successful"); @@ -239,6 +252,8 @@ pub struct LMDBDatabase { validator_nodes: DatabaseRef, /// Maps VN Shard Key -> VN Public Key validator_nodes_mapping: DatabaseRef, + /// Maps the end block height of nodes + validator_nodes_ending: DatabaseRef, _file_lock: Arc, consensus_manager: ConsensusManager, } @@ -281,6 +296,7 @@ impl LMDBDatabase { reorgs: get_database(store, LMDB_DB_REORGS)?, validator_nodes: get_database(store, LMDB_DB_VALIDATOR_NODES)?, validator_nodes_mapping: get_database(store, LMDB_DB_VALIDATOR_NODES_MAPPING)?, + validator_nodes_ending: get_database(store, LMDB_DB_VALIDATOR_NODE_ENDING)?, env, env_config: store.env_config(), _file_lock: Arc::new(file_lock), @@ -486,11 +502,6 @@ impl LMDBDatabase { InsertValidatorNode { validator_node } => { self.insert_validator_node(&write_txn, validator_node)?; }, - DeleteValidatorNode { public_key } => { - let txn = self.read_transaction()?; - let shard_key = self.get_vn_mapping(&txn, public_key)?; - self.delete_validator_node(&write_txn, public_key, &shard_key)?; - }, } } write_txn.commit()?; @@ -1272,9 +1283,7 @@ impl LMDBDatabase { .as_ref() .and_then(|f| f.validator_node_registration()) { - let read_txn = self.read_transaction()?; - let shard_key = self.get_vn_mapping(&read_txn, &vn_reg.public_key)?; - self.delete_validator_node(txn, &vn_reg.public_key, &shard_key)?; + self.delete_validator_node(txn, &vn_reg.public_key, &input.output_hash())?; } if !output_mmr.delete(index) { @@ -1311,8 +1320,9 @@ impl LMDBDatabase { 1 + self.consensus_manager .consensus_constants(header.height) - .get_validator_node_timeout(), + .validator_node_timeout(), public_key: vn_reg.public_key.clone(), + output_hash: output.hash(), }; self.insert_validator_node(txn, &validator_node)?; } @@ -1562,12 +1572,14 @@ impl LMDBDatabase { txn: &WriteTransaction<'_>, validator_node: &ActiveValidatorNode, ) -> Result<(), ChainStorageError> { - lmdb_insert( + let mut key = validator_node.public_key.to_vec(); + key.extend(validator_node.output_hash.as_slice()); + lmdb_insert(txn, &self.validator_nodes, &key, validator_node, "validator_nodes")?; + lmdb_insert_dup( txn, - &self.validator_nodes, - validator_node.public_key.as_bytes(), + &self.validator_nodes_ending, + &validator_node.to_height.to_le_bytes(), validator_node, - "validator_nodes", )?; lmdb_insert( txn, @@ -1578,25 +1590,29 @@ impl LMDBDatabase { ) } - fn get_vn_mapping(&self, txn: &ReadTransaction<'_>, public_key: &PublicKey) -> Result<[u8; 32], ChainStorageError> { - let x: ActiveValidatorNode = lmdb_get(txn, &self.validator_nodes, public_key.as_bytes())?.ok_or_else(|| { - ChainStorageError::ValueNotFound { - entity: "ActiveValidatorNode", - field: "public_key", - value: public_key.to_hex(), - } - })?; - Ok(x.shard_key) - } - fn delete_validator_node( &self, txn: &WriteTransaction<'_>, public_key: &PublicKey, - shard_key: &[u8; 32], + output_hash: &HashOutput, ) -> Result<(), ChainStorageError> { - lmdb_delete(txn, &self.validator_nodes, public_key.as_bytes(), "validator_nodes")?; - lmdb_delete(txn, &self.validator_nodes, shard_key, "validator_nodes_mapping")?; + let mut key = public_key.to_vec(); + key.extend(output_hash.as_slice()); + let x: ActiveValidatorNode = + lmdb_get(txn, &self.validator_nodes, &key)?.ok_or_else(|| ChainStorageError::ValueNotFound { + entity: "ActiveValidatorNode", + field: "public_key and outputhash", + value: key.to_hex(), + })?; + + lmdb_delete_key_value(txn, &self.validator_nodes_ending, &x.to_height.to_le_bytes(), &x)?; + lmdb_delete(txn, &self.validator_nodes, &key, "validator_nodes")?; + lmdb_delete( + txn, + &self.validator_nodes_mapping, + &x.shard_key, + "validator_nodes_mapping", + )?; Ok(()) } @@ -2407,15 +2423,42 @@ impl BlockchainBackend for LMDBDatabase { lmdb_filter_map_values(&txn, &self.reorgs, Some) } - fn fetch_active_validator_nodes(&self, height: u64) -> Result, ChainStorageError> { + // The clippy warning is because PublicKey has a public inner type that could change. In this case + // it should be fine to ignore the warning. You could also change the logic to use something + // other than a hashmap. + #[allow(clippy::mutable_key_type)] + fn fetch_active_validator_nodes(&self, height: u64) -> Result, ChainStorageError> { let txn = self.read_transaction()?; - lmdb_filter_map_values(&txn, &self.validator_nodes, |vn: ActiveValidatorNode| { - if vn.from_height <= height && vn.to_height >= height { - Some(vn) - } else { - None - } - }) + let validator_node_timeout = self + .consensus_manager + .consensus_constants(height) + .validator_node_timeout(); + let mut pub_keys = HashMap::new(); + + let end = height + validator_node_timeout; + for h in height..end { + lmdb_get_multiple(&txn, &self.validator_nodes_ending, &h.to_le_bytes())? + .into_iter() + .for_each(|v: ActiveValidatorNode| { + if v.from_height <= height { + if let Some((shard_key, start)) = + pub_keys.insert(v.public_key.clone(), (v.shard_key, v.from_height)) + { + // If the node is already in the map, check if the start height is higher. If it is, replace + // the old value with the new one. + if start > v.from_height { + pub_keys.insert(v.public_key, (shard_key, start)); + } + } + } + }); + } + + // now remove the heights + Ok(pub_keys + .into_iter() + .map(|(pk, (shard_key, _))| (pk, shard_key)) + .collect()) } fn fetch_committee(&self, height: u64, shard: [u8; 32]) -> Result, ChainStorageError> { diff --git a/base_layer/core/src/consensus/consensus_constants.rs b/base_layer/core/src/consensus/consensus_constants.rs index 0b658722cc..e4cbcf6708 100644 --- a/base_layer/core/src/consensus/consensus_constants.rs +++ b/base_layer/core/src/consensus/consensus_constants.rs @@ -288,7 +288,7 @@ impl ConsensusConstants { self.permitted_output_types } - pub fn get_validator_node_timeout(&self) -> u64 { + pub fn validator_node_timeout(&self) -> u64 { self.validator_node_timeout } @@ -415,7 +415,7 @@ impl ConsensusConstants { kernel_version_range, // igor is the first network to support the new output types permitted_output_types: OutputType::all(), - validator_node_timeout: 0, + validator_node_timeout: 100, }] } diff --git a/base_layer/core/src/test_helpers/blockchain.rs b/base_layer/core/src/test_helpers/blockchain.rs index c37c03cd05..88b7e9204c 100644 --- a/base_layer/core/src/test_helpers/blockchain.rs +++ b/base_layer/core/src/test_helpers/blockchain.rs @@ -414,10 +414,7 @@ impl BlockchainBackend for TempDatabase { self.db.as_ref().unwrap().fetch_all_reorgs() } - fn fetch_active_validator_nodes( - &self, - height: u64, - ) -> Result, ChainStorageError> { + fn fetch_active_validator_nodes(&self, height: u64) -> Result, ChainStorageError> { self.db.as_ref().unwrap().fetch_active_validator_nodes(height) }