New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ZKS-02] Update the set of authorized validators #3118
Changes from 5 commits
ed6409f
b1c0ddc
9bd3df5
1b89d09
aefd5d6
00b96cf
6b353a0
f57c694
dbcdcb8
7d8d262
d0443cc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,7 +14,7 @@ | |
|
||
use crate::{ | ||
events::{EventCodec, PrimaryPing}, | ||
helpers::{assign_to_worker, Cache, PrimarySender, Resolver, SyncSender, WorkerSender}, | ||
helpers::{assign_to_worker, Cache, PrimarySender, Resolver, Storage, SyncSender, WorkerSender}, | ||
spawn_blocking, | ||
Worker, | ||
CONTEXT, | ||
|
@@ -39,7 +39,7 @@ use snarkos_node_bft_events::{ | |
ValidatorsResponse, | ||
}; | ||
use snarkos_node_bft_ledger_service::LedgerService; | ||
use snarkos_node_sync::communication_service::CommunicationService; | ||
use snarkos_node_sync::{communication_service::CommunicationService, MAX_BLOCKS_BEHIND}; | ||
use snarkos_node_tcp::{ | ||
is_bogon_ip, | ||
is_unspecified_or_broadcast_ip, | ||
|
@@ -100,6 +100,8 @@ pub trait Transport<N: Network>: Send + Sync { | |
pub struct Gateway<N: Network> { | ||
/// The account of the node. | ||
account: Account<N>, | ||
/// The storage. | ||
storage: Storage<N>, | ||
/// The ledger service. | ||
ledger: Arc<dyn LedgerService<N>>, | ||
/// The TCP stack. | ||
|
@@ -133,6 +135,7 @@ impl<N: Network> Gateway<N> { | |
/// Initializes a new gateway. | ||
pub fn new( | ||
account: Account<N>, | ||
storage: Storage<N>, | ||
ledger: Arc<dyn LedgerService<N>>, | ||
ip: Option<SocketAddr>, | ||
trusted_validators: &[SocketAddr], | ||
|
@@ -149,6 +152,7 @@ impl<N: Network> Gateway<N> { | |
// Return the gateway. | ||
Ok(Self { | ||
account, | ||
storage, | ||
ledger, | ||
tcp, | ||
cache: Default::default(), | ||
|
@@ -330,18 +334,35 @@ impl<N: Network> Gateway<N> { | |
|
||
/// Returns `true` if the given address is an authorized validator. | ||
pub fn is_authorized_validator_address(&self, validator_address: Address<N>) -> bool { | ||
// Determine if the validator address is a member of the committee lookback or the current committee. | ||
// Retrieve the previous block height to consider from the sync tolerance. | ||
let previous_block_height = self.ledger.latest_block_height().saturating_sub(MAX_BLOCKS_BEHIND); | ||
// Determine if the validator is in any of the previous committee lookbacks. | ||
let exists_in_previous_committee_lookback = match self.ledger.get_block_round(previous_block_height) { | ||
Ok(block_round) => (block_round..self.storage.current_round()).step_by(2).any(|round| { | ||
self.ledger | ||
.get_committee_lookback_for_round(round) | ||
.map_or(false, |committee| committee.is_committee_member(validator_address)) | ||
}), | ||
Err(_) => false, | ||
}; | ||
|
||
// Determine if the validator is in the current committee with lookback. | ||
let exists_in_current_committee_lookback = self | ||
.ledger | ||
.get_committee_lookback_for_round(self.storage.current_round()) | ||
.map_or(false, |committee| committee.is_committee_member(validator_address)); | ||
|
||
// Determine if the validator is in the latest committee on the ledger. | ||
let exists_in_latest_committee = | ||
self.ledger.current_committee().map_or(false, |committee| committee.is_committee_member(validator_address)); | ||
|
||
// Determine if the validator address is a member of the previous committee lookbacks, | ||
// the committee lookback, or the current committee. | ||
// We allow leniency in this validation check in order to accommodate these two scenarios: | ||
// 1. New validators should be able to connect immediately once bonded as a committee member. | ||
// 2. Existing validators must remain connected until they are no longer bonded as a committee member. | ||
// (i.e. meaning they must stay online until the next block has been produced) | ||
self.ledger | ||
.get_committee_lookback_for_round(self.ledger.latest_round()) | ||
.map_or(false, |committee| committee.is_committee_member(validator_address)) | ||
|| self | ||
.ledger | ||
.current_committee() | ||
.map_or(false, |committee| committee.is_committee_member(validator_address)) | ||
exists_in_previous_committee_lookback || exists_in_current_committee_lookback || exists_in_latest_committee | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. there's some potential for faster early returns here; once we know that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. in addition, I'd guess that the first of the checks is the slowest and the last one is the fastest, so it would probably be a good idea to reverse their order for the purpose for potential early returns |
||
} | ||
|
||
/// Returns the maximum number of connected peers. | ||
|
@@ -1402,6 +1423,7 @@ mod prop_tests { | |
.prop_map(|(storage, _, private_key, address)| { | ||
Gateway::new( | ||
Account::try_from(private_key).unwrap(), | ||
storage.clone(), | ||
storage.ledger().clone(), | ||
address.ip(), | ||
&[], | ||
|
@@ -1450,7 +1472,9 @@ mod prop_tests { | |
let (storage, _, private_key, dev) = input; | ||
let account = Account::try_from(private_key).unwrap(); | ||
|
||
let gateway = Gateway::new(account.clone(), storage.ledger().clone(), dev.ip(), &[], dev.port()).unwrap(); | ||
let gateway = | ||
Gateway::new(account.clone(), storage.clone(), storage.ledger().clone(), dev.ip(), &[], dev.port()) | ||
.unwrap(); | ||
let tcp_config = gateway.tcp().config(); | ||
assert_eq!(tcp_config.listener_ip, Some(IpAddr::V4(Ipv4Addr::LOCALHOST))); | ||
assert_eq!(tcp_config.desired_listening_port, Some(MEMORY_POOL_PORT + dev.port().unwrap())); | ||
|
@@ -1465,7 +1489,9 @@ mod prop_tests { | |
let (storage, _, private_key, dev) = input; | ||
let account = Account::try_from(private_key).unwrap(); | ||
|
||
let gateway = Gateway::new(account.clone(), storage.ledger().clone(), dev.ip(), &[], dev.port()).unwrap(); | ||
let gateway = | ||
Gateway::new(account.clone(), storage.clone(), storage.ledger().clone(), dev.ip(), &[], dev.port()) | ||
.unwrap(); | ||
let tcp_config = gateway.tcp().config(); | ||
if let Some(socket_addr) = dev.ip() { | ||
assert_eq!(tcp_config.listener_ip, Some(socket_addr.ip())); | ||
|
@@ -1490,7 +1516,8 @@ mod prop_tests { | |
let worker_storage = storage.clone(); | ||
let account = Account::try_from(private_key).unwrap(); | ||
|
||
let gateway = Gateway::new(account, storage.ledger().clone(), dev.ip(), &[], dev.port()).unwrap(); | ||
let gateway = | ||
Gateway::new(account, storage.clone(), storage.ledger().clone(), dev.ip(), &[], dev.port()).unwrap(); | ||
|
||
let (primary_sender, _) = init_primary_channels(); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it would probably be better if this was an
RwLock
, as I can see several read-only operations available