Skip to content

Commit

Permalink
Merge bump/snarkVM-d48f6fb
Browse files Browse the repository at this point in the history
  • Loading branch information
raychu86 committed Apr 13, 2024
2 parents 926b5f7 + 29cf16a commit 5a3ed41
Show file tree
Hide file tree
Showing 35 changed files with 1,614 additions and 572 deletions.
614 changes: 307 additions & 307 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ default-features = false

[workspace.dependencies.snarkvm]
git = "https://github.com/AleoHQ/snarkVM.git"
rev = "d233d20"
rev = "d48f6fb"
#version = "=0.16.18"
features = [ "circuit", "console", "rocks" ]

Expand Down
61 changes: 36 additions & 25 deletions cli/src/commands/start.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const DEVELOPMENT_MODE_NUM_GENESIS_COMMITTEE_MEMBERS: u16 = 4;

/// A mapping of `staker_address` to `(validator_address, withdrawal_address, amount)`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
struct BondedBalances(IndexMap<String, (String, String, u64)>);
pub struct BondedBalances(IndexMap<String, (String, String, u64)>);

impl FromStr for BondedBalances {
type Err = serde_json::Error;
Expand Down Expand Up @@ -90,8 +90,8 @@ pub struct Start {
pub private_key_file: Option<PathBuf>,

/// Specify the IP address and port for the node server
#[clap(default_value = "0.0.0.0:4130", long = "node")]
pub node: SocketAddr,
#[clap(long = "node")]
pub node: Option<SocketAddr>,
/// Specify the IP address and port for the BFT
#[clap(long = "bft")]
pub bft: Option<SocketAddr>,
Expand All @@ -101,6 +101,9 @@ pub struct Start {
/// Specify the IP address and port of the validator(s) to connect to
#[clap(default_value = "", long = "validators")]
pub validators: String,
/// If the flag is set, a node will allow untrusted peers to connect
#[clap(long = "allow-external-peers")]
pub allow_external_peers: bool,

/// Specify the IP address and port for the REST server
#[clap(default_value = "0.0.0.0:3030", long = "rest")]
Expand All @@ -125,6 +128,9 @@ pub struct Start {
#[clap(default_value = "false", long = "metrics")]
pub metrics: bool,

/// Specify the path to a directory containing the storage database for the ledger
#[clap(long = "storage")]
pub storage: Option<PathBuf>,
/// Enables the node to prefetch initial blocks from a CDN
#[clap(default_value = "https://s3.us-west-1.amazonaws.com/testnet3.blocks/phase3", long = "cdn")]
pub cdn: String,
Expand All @@ -141,17 +147,9 @@ pub struct Start {
/// If developtment mode is enabled, specify whether node 0 should generate traffic to drive the network
#[clap(default_value = "false", long = "no-dev-txs")]
pub no_dev_txs: bool,
/// Specify the path to a directory containing the ledger
#[clap(long = "storage_path")]
pub storage_path: Option<PathBuf>,

/// If development mode is enabled, specify the custom bonded balances as a json object. (default: None)
/// If development mode is enabled, specify the custom bonded balances as a JSON object (default: None)
#[clap(long)]
dev_bonded_balances: Option<BondedBalances>,

/// If the flag is set, the validator will allow untrusted peers to connect
#[clap(long = "allow-external-peers")]
allow_external_peers: bool,
pub dev_bonded_balances: Option<BondedBalances>,
}

impl Start {
Expand Down Expand Up @@ -317,11 +315,15 @@ impl Start {
}
}
// Set the node IP to `4130 + dev`.
self.node = SocketAddr::from_str(&format!("0.0.0.0:{}", 4130 + dev))?;
//
// Note: the `node` flag is an option to detect remote devnet testing.
if self.node.is_none() {
self.node = Some(SocketAddr::from_str(&format!("0.0.0.0:{}", 4130 + dev))?);
}
// If the `norest` flag is not set, and the `bft` flag was not overridden,
// then set the REST IP to `3030 + dev`.
//
// Note: the reason the `bft` flag is an option is to detect for remote devnet testing.
// Note: the `bft` flag is an option to detect remote devnet testing.
if !self.norest && self.bft.is_none() {
self.rest = SocketAddr::from_str(&format!("0.0.0.0:{}", 3030 + dev))?;
}
Expand Down Expand Up @@ -494,6 +496,16 @@ impl Start {
// Parse the node type.
let node_type = self.parse_node_type();

// Parse the node IP.
let node_ip = match self.node {
Some(node_ip) => node_ip,
None => SocketAddr::from_str("0.0.0.0:4130").unwrap(),
};
// Parse the BFT IP.
let bft_ip = match self.dev.is_some() {
true => self.bft,
false => None
};
// Parse the REST IP.
let rest_ip = match self.norest {
true => None,
Expand All @@ -509,7 +521,7 @@ impl Start {
"🧭 Starting {} on {} at {}.\n",
node_type.description().bold(),
N::NAME.bold(),
self.node.to_string().bold()
node_ip.to_string().bold()
);

// If the node is running a REST server, print the REST IP and JWT.
Expand Down Expand Up @@ -538,7 +550,7 @@ impl Start {
}

// Initialize the storage mode.
let storage_mode = match &self.storage_path {
let storage_mode = match &self.storage {
Some(path) => StorageMode::Custom(path.clone()),
None => StorageMode::from(self.dev),
};
Expand All @@ -556,11 +568,10 @@ impl Start {
};

// Initialize the node.
let bft_ip = if self.dev.is_some() { self.bft } else { None };
match node_type {
NodeType::Validator => Node::new_validator(self.node, bft_ip, rest_ip, self.rest_rps, account, &trusted_peers, &trusted_validators, genesis, cdn, storage_mode, self.allow_external_peers, dev_txs).await,
NodeType::Prover => Node::new_prover(self.node, account, &trusted_peers, genesis, storage_mode).await,
NodeType::Client => Node::new_client(self.node, rest_ip, self.rest_rps, account, &trusted_peers, genesis, cdn, storage_mode).await,
NodeType::Validator => Node::new_validator(node_ip, bft_ip, rest_ip, self.rest_rps, account, &trusted_peers, &trusted_validators, genesis, cdn, storage_mode, self.allow_external_peers, dev_txs).await,
NodeType::Prover => Node::new_prover(node_ip, account, &trusted_peers, genesis, storage_mode).await,
NodeType::Client => Node::new_client(node_ip, rest_ip, self.rest_rps, account, &trusted_peers, genesis, cdn, storage_mode).await,
}
}

Expand Down Expand Up @@ -846,7 +857,7 @@ mod tests {
let mut config = Start::try_parse_from(["snarkos", "--dev", "0"].iter()).unwrap();
config.parse_development(&mut trusted_peers, &mut trusted_validators).unwrap();
let expected_genesis = config.parse_genesis::<CurrentNetwork>().unwrap();
assert_eq!(config.node, SocketAddr::from_str("0.0.0.0:4130").unwrap());
assert_eq!(config.node, Some(SocketAddr::from_str("0.0.0.0:4130").unwrap()));
assert_eq!(config.rest, SocketAddr::from_str("0.0.0.0:3030").unwrap());
assert_eq!(trusted_peers.len(), 0);
assert_eq!(trusted_validators.len(), 1);
Expand All @@ -861,7 +872,7 @@ mod tests {
Start::try_parse_from(["snarkos", "--dev", "1", "--validator", "--private-key", ""].iter()).unwrap();
config.parse_development(&mut trusted_peers, &mut trusted_validators).unwrap();
let genesis = config.parse_genesis::<CurrentNetwork>().unwrap();
assert_eq!(config.node, SocketAddr::from_str("0.0.0.0:4131").unwrap());
assert_eq!(config.node, Some(SocketAddr::from_str("0.0.0.0:4131").unwrap()));
assert_eq!(config.rest, SocketAddr::from_str("0.0.0.0:3031").unwrap());
assert_eq!(trusted_peers.len(), 1);
assert_eq!(trusted_validators.len(), 1);
Expand All @@ -876,7 +887,7 @@ mod tests {
Start::try_parse_from(["snarkos", "--dev", "2", "--prover", "--private-key", ""].iter()).unwrap();
config.parse_development(&mut trusted_peers, &mut trusted_validators).unwrap();
let genesis = config.parse_genesis::<CurrentNetwork>().unwrap();
assert_eq!(config.node, SocketAddr::from_str("0.0.0.0:4132").unwrap());
assert_eq!(config.node, Some(SocketAddr::from_str("0.0.0.0:4132").unwrap()));
assert_eq!(config.rest, SocketAddr::from_str("0.0.0.0:3032").unwrap());
assert_eq!(trusted_peers.len(), 2);
assert_eq!(trusted_validators.len(), 2);
Expand All @@ -891,7 +902,7 @@ mod tests {
Start::try_parse_from(["snarkos", "--dev", "3", "--client", "--private-key", ""].iter()).unwrap();
config.parse_development(&mut trusted_peers, &mut trusted_validators).unwrap();
let genesis = config.parse_genesis::<CurrentNetwork>().unwrap();
assert_eq!(config.node, SocketAddr::from_str("0.0.0.0:4133").unwrap());
assert_eq!(config.node, Some(SocketAddr::from_str("0.0.0.0:4133").unwrap()));
assert_eq!(config.rest, SocketAddr::from_str("0.0.0.0:3033").unwrap());
assert_eq!(trusted_peers.len(), 3);
assert_eq!(trusted_validators.len(), 2);
Expand Down
2 changes: 1 addition & 1 deletion node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ version = "0.2"
version = "1"

[dev-dependencies.pea2pea]
version = "0.46"
version = "0.49"

[dev-dependencies.snarkos-node-router]
path = "./router"
Expand Down
5 changes: 4 additions & 1 deletion node/bft/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ edition = "2021"

[features]
default = [ ]
metrics = [ "dep:metrics", "snarkos-node-bft-events/metrics" ]
metrics = [ "dep:metrics", "snarkos-node-bft-events/metrics", "snarkos-node-bft-ledger-service/metrics" ]

[dependencies.aleo-std]
workspace = true
Expand Down Expand Up @@ -137,6 +137,9 @@ version = "5"
[dev-dependencies.paste]
version = "1"

[dev-dependencies.pea2pea]
version = "0.49"

[dev-dependencies.proptest]
version = "1.4.0"

Expand Down
2 changes: 1 addition & 1 deletion node/bft/events/src/block_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ pub struct DataBlocks<N: Network>(pub Vec<Block<N>>);

impl<N: Network> DataBlocks<N> {
/// The maximum number of blocks that can be sent in a single message.
pub const MAXIMUM_NUMBER_OF_BLOCKS: u8 = 1;
pub const MAXIMUM_NUMBER_OF_BLOCKS: u8 = 10;

/// Ensures that the blocks are well-formed in a block response.
pub fn ensure_response_is_well_formed(
Expand Down
5 changes: 1 addition & 4 deletions node/bft/events/src/helpers/codec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,7 @@ use tracing::*;
/// The maximum size of an event that can be transmitted during the handshake.
const MAX_HANDSHAKE_SIZE: usize = 1024 * 1024; // 1 MiB
/// The maximum size of an event that can be transmitted in the network.
const MAX_EVENT_SIZE: usize = 128 * 1024 * 1024; // 128 MiB

/// The type of noise handshake to use for network encryption.
pub const NOISE_HANDSHAKE_TYPE: &str = "Noise_XX_25519_ChaChaPoly_BLAKE2s";
const MAX_EVENT_SIZE: usize = 256 * 1024 * 1024; // 256 MiB

/// The codec used to decode and encode network `Event`s.
pub struct EventCodec<N: Network> {
Expand Down
7 changes: 7 additions & 0 deletions node/bft/ledger-service/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ edition = "2021"
default = [ ]
ledger = [ "lru", "parking_lot", "rand", "tokio", "tracing" ]
ledger-write = [ ]
metrics = ["dep:metrics", "snarkvm/metrics"]
mock = [ "parking_lot", "tracing" ]
prover = [ ]
test = [ "mock", "translucent" ]
Expand All @@ -36,6 +37,12 @@ features = [ "serde", "rayon" ]
version = "0.12"
optional = true

[dependencies.metrics]
package = "snarkos-node-metrics"
path = "../../metrics"
version = "=2.2.7"
optional = true

[dependencies.parking_lot]
version = "0.12"
optional = true
Expand Down
12 changes: 12 additions & 0 deletions node/bft/ledger-service/src/ledger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,18 @@ impl<N: Network, C: ConsensusStorage<N>> LedgerService<N> for CoreLedgerService<
}
// Advance to the next block.
self.ledger.advance_to_next_block(block)?;
// Update BFT metrics.
#[cfg(feature = "metrics")]
{
let num_sol = block.solutions().len();
let num_tx = block.transactions().len();

metrics::gauge(metrics::bft::HEIGHT, block.height() as f64);
metrics::gauge(metrics::bft::LAST_COMMITTED_ROUND, block.round() as f64);
metrics::increment_gauge(metrics::blocks::SOLUTIONS, num_sol as f64);
metrics::increment_gauge(metrics::blocks::TRANSACTIONS, num_tx as f64);
}

tracing::info!("\n\nAdvanced to block {} at round {} - {}\n", block.height(), block.round(), block.hash());
Ok(())
}
Expand Down
41 changes: 35 additions & 6 deletions node/bft/src/helpers/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ impl<N: Network> Storage<N> {
&self,
batch_header: &BatchHeader<N>,
transmissions: HashMap<TransmissionID<N>, Transmission<N>>,
aborted_transmissions: HashSet<TransmissionID<N>>,
) -> Result<HashMap<TransmissionID<N>, Transmission<N>>> {
// Retrieve the round.
let round = batch_header.round();
Expand Down Expand Up @@ -367,7 +368,7 @@ impl<N: Network> Storage<N> {
// Retrieve the missing transmissions in storage from the given transmissions.
let missing_transmissions = self
.transmissions
.find_missing_transmissions(batch_header, transmissions)
.find_missing_transmissions(batch_header, transmissions, aborted_transmissions)
.map_err(|e| anyhow!("{e} for round {round} {gc_log}"))?;

// Compute the previous round.
Expand Down Expand Up @@ -435,6 +436,7 @@ impl<N: Network> Storage<N> {
&self,
certificate: &BatchCertificate<N>,
transmissions: HashMap<TransmissionID<N>, Transmission<N>>,
aborted_transmissions: HashSet<TransmissionID<N>>,
) -> Result<HashMap<TransmissionID<N>, Transmission<N>>> {
// Retrieve the round.
let round = certificate.round();
Expand All @@ -454,7 +456,8 @@ impl<N: Network> Storage<N> {
}

// Ensure the batch header is well-formed.
let missing_transmissions = self.check_batch_header(certificate.batch_header(), transmissions)?;
let missing_transmissions =
self.check_batch_header(certificate.batch_header(), transmissions, aborted_transmissions)?;

// Check the timestamp for liveness.
check_timestamp_for_liveness(certificate.timestamp())?;
Expand Down Expand Up @@ -503,11 +506,12 @@ impl<N: Network> Storage<N> {
&self,
certificate: BatchCertificate<N>,
transmissions: HashMap<TransmissionID<N>, Transmission<N>>,
aborted_transmissions: HashSet<TransmissionID<N>>,
) -> Result<()> {
// Ensure the certificate round is above the GC round.
ensure!(certificate.round() > self.gc_round(), "Certificate round is at or below the GC round");
// Ensure the certificate and its transmissions are valid.
let missing_transmissions = self.check_certificate(&certificate, transmissions)?;
let missing_transmissions = self.check_certificate(&certificate, transmissions, aborted_transmissions)?;
// Insert the certificate into storage.
self.insert_certificate_atomic(certificate, missing_transmissions);
Ok(())
Expand Down Expand Up @@ -631,6 +635,13 @@ impl<N: Network> Storage<N> {
// Retrieve the transmissions for the certificate.
let mut missing_transmissions = HashMap::new();

// Retrieve the aborted transmissions for the certificate.
let mut aborted_transmissions = HashSet::new();

// Track the block's aborted solutions and transactions.
let aborted_solutions: IndexSet<_> = block.aborted_solution_ids().iter().collect();
let aborted_transactions: IndexSet<_> = block.aborted_transaction_ids().iter().collect();

// Iterate over the transmission IDs.
for transmission_id in certificate.transmission_ids() {
// If the transmission ID already exists in the map, skip it.
Expand All @@ -653,8 +664,17 @@ impl<N: Network> Storage<N> {
None => match self.ledger.get_solution(solution_id) {
// Insert the solution.
Ok(solution) => missing_transmissions.insert(*transmission_id, solution.into()),
// Check if the solution is in the aborted solutions.
Err(_) => {
error!("Missing solution {solution_id} in block {}", block.height());
// Insert the aborted solution if it exists in the block or ledger.
match aborted_solutions.contains(solution_id)
|| self.ledger.contains_transmission(transmission_id).unwrap_or(false)
{
true => {
aborted_transmissions.insert(*transmission_id);
}
false => error!("Missing solution {solution_id} in block {}", block.height()),
}
continue;
}
},
Expand All @@ -669,8 +689,17 @@ impl<N: Network> Storage<N> {
None => match self.ledger.get_unconfirmed_transaction(*transaction_id) {
// Insert the transaction.
Ok(transaction) => missing_transmissions.insert(*transmission_id, transaction.into()),
// Check if the transaction is in the aborted transactions.
Err(_) => {
warn!("Missing transaction {transaction_id} in block {}", block.height());
// Insert the aborted transaction if it exists in the block or ledger.
match aborted_transactions.contains(transaction_id)
|| self.ledger.contains_transmission(transmission_id).unwrap_or(false)
{
true => {
aborted_transmissions.insert(*transmission_id);
}
false => warn!("Missing transaction {transaction_id} in block {}", block.height()),
}
continue;
}
},
Expand All @@ -685,7 +714,7 @@ impl<N: Network> Storage<N> {
certificate.round(),
certificate.transmission_ids().len()
);
if let Err(error) = self.insert_certificate(certificate, missing_transmissions) {
if let Err(error) = self.insert_certificate(certificate, missing_transmissions, aborted_transmissions) {
error!("Failed to insert certificate '{certificate_id}' from block {} - {error}", block.height());
}
}
Expand Down
11 changes: 10 additions & 1 deletion node/bft/src/helpers/timestamp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::MAX_TIMESTAMP_DELTA_IN_SECS;
use crate::{MAX_TIMESTAMP_DELTA_IN_SECS, PROPOSAL_EXPIRATION_IN_SECS};
use snarkvm::prelude::{bail, Result};

use time::OffsetDateTime;
Expand All @@ -31,6 +31,15 @@ pub fn check_timestamp_for_liveness(timestamp: i64) -> Result<()> {
Ok(())
}

/// Returns whether the proposal is expired.
pub fn is_proposal_expired(current_timestamp: i64, proposal_timestamp: i64) -> bool {
debug_assert!(
current_timestamp >= proposal_timestamp,
"Current timestamp must be greater or equal to the proposal timestamp"
);
current_timestamp.saturating_sub(proposal_timestamp) >= PROPOSAL_EXPIRATION_IN_SECS
}

#[cfg(test)]
mod prop_tests {
use super::*;
Expand Down
Loading

0 comments on commit 5a3ed41

Please sign in to comment.