├── rust-toolchain ├── .resources ├── release-version └── license_header ├── .rusty-hook.toml ├── .github ├── dependabot.yml ├── ISSUE_TEMPLATE.md ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── proposal.md │ ├── documentation.md │ ├── feature.md │ └── bug.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .devnet ├── .analytics │ └── package.json ├── fetch-logs.sh ├── stop.sh ├── clean.sh ├── analytics.sh ├── monitor.sh ├── install.sh ├── config.sh ├── reinstall.sh ├── start_sync_test.sh └── start.sh ├── node ├── metrics │ ├── docker-compose.yml │ ├── prometheus.yml │ ├── Cargo.toml │ └── README.md ├── rest │ ├── README.md │ ├── src │ │ └── helpers │ │ │ ├── mod.rs │ │ │ └── error.rs │ └── Cargo.toml ├── sync │ ├── README.md │ ├── locators │ │ ├── README.md │ │ ├── src │ │ │ └── lib.rs │ │ └── Cargo.toml │ ├── communication-service │ │ ├── README.md │ │ ├── Cargo.toml │ │ └── src │ │ │ └── lib.rs │ ├── src │ │ ├── lib.rs │ │ └── helpers │ │ │ └── mod.rs │ └── Cargo.toml ├── cdn │ ├── README.md │ ├── src │ │ └── lib.rs │ └── Cargo.toml ├── README.md ├── bft │ ├── events │ │ ├── README.md │ │ ├── src │ │ │ ├── helpers │ │ │ │ └── mod.rs │ │ │ ├── validators_request.rs │ │ │ ├── block_request.rs │ │ │ ├── batch_signature.rs │ │ │ ├── batch_certified.rs │ │ │ ├── certificate_request.rs │ │ │ ├── worker_ping.rs │ │ │ ├── challenge_response.rs │ │ │ ├── transmission_request.rs │ │ │ └── batch_propose.rs │ │ └── Cargo.toml │ ├── ledger-service │ │ ├── README.md │ │ ├── Cargo.toml │ │ └── src │ │ │ └── lib.rs │ ├── storage-service │ │ ├── README.md │ │ ├── src │ │ │ ├── lib.rs │ │ │ └── traits.rs │ │ └── Cargo.toml │ ├── tests │ │ ├── components │ │ │ ├── mod.rs │ │ │ └── pending.rs │ │ └── common │ │ │ └── mod.rs │ ├── examples │ │ ├── start-nodes.sh │ │ ├── monitor.rs │ │ └── README.md │ ├── src │ │ ├── helpers │ │ │ ├── mod.rs │ │ │ └── timestamp.rs │ │ └── lib.rs │ └── README.md ├── consensus │ ├── README.md │ └── Cargo.toml ├── tcp │ ├── README.md │ ├── Cargo.toml │ └── src │ │ ├── helpers │ │ ├── mod.rs │ │ ├── known_peers.rs │ │ └── stats.rs │ │ ├── lib.rs │ │ └── protocols │ │ ├── mod.rs │ │ ├── on_connect.rs │ │ └── disconnect.rs ├── router │ ├── README.md │ ├── messages │ │ ├── README.md │ │ ├── src │ │ │ ├── helpers │ │ │ │ ├── mod.rs │ │ │ │ └── node_type.rs │ │ │ ├── peer_request.rs │ │ │ ├── puzzle_request.rs │ │ │ ├── pong.rs │ │ │ ├── block_request.rs │ │ │ ├── peer_response.rs │ │ │ └── puzzle_response.rs │ │ └── Cargo.toml │ ├── src │ │ ├── helpers │ │ │ ├── mod.rs │ │ │ └── resolver.rs │ │ └── routing.rs │ ├── Cargo.toml │ └── tests │ │ └── cleanups.rs ├── tests │ ├── common │ │ ├── mod.rs │ │ └── node.rs │ └── peering.rs └── Cargo.toml ├── cli ├── README.md ├── src │ ├── lib.rs │ ├── helpers │ │ ├── log_writer.rs │ │ └── bech32m.rs │ └── commands │ │ ├── update.rs │ │ ├── mod.rs │ │ └── clean.rs └── Cargo.toml ├── display ├── README.md ├── src │ ├── pages │ │ ├── mod.rs │ │ ├── overview.rs │ │ └── logs.rs │ └── tabs.rs └── Cargo.toml ├── .rustfmt.toml ├── account ├── README.md └── Cargo.toml ├── run-client.sh ├── .integration ├── Cargo.toml └── src │ └── lib.rs ├── run-prover.sh ├── run-validator.sh ├── snarkos └── main.rs └── Cargo.toml /rust-toolchain: -------------------------------------------------------------------------------- 1 | 1.76.0 2 | -------------------------------------------------------------------------------- /.resources/release-version: -------------------------------------------------------------------------------- 1 | v2.2.7 -------------------------------------------------------------------------------- /.rusty-hook.toml: -------------------------------------------------------------------------------- 1 | [hooks] 2 | pre-commit = "cargo clippy --workspace --all-targets --all-features && cargo +nightly fmt --all -- --check" 3 | 4 | [logging] 5 | verbose = true 6 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: cargo 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "10:00" 8 | target-branch: "mainnet" 9 | open-pull-requests-limit: 10 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/*.idea/ 2 | **/target 3 | **.DS_Store 4 | wasm/Cargo.lock 5 | **/build 6 | **.ledger-* 7 | **.logs-* 8 | validator-* 9 | **.bft-storage-*/ 10 | **proptest-regressions/ 11 | **package-lock.json 12 | **node_modules/ 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## 👉 [Please follow one of these issue templates](https://github.com/AleoHQ/snarkOS/issues/new/choose) 👈 2 | 3 | Note: to keep the backlog clean and actionable, issues may be immediately closed if they do not follow one of the above issue templates. 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: ❓ Q&A Technical Support Channel 4 | url: https://discord.gg/aleo 5 | about: For quick questions or technical troubleshooting, please ask them on our dedicated Discord channel. 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/proposal.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 💥 Proposal 3 | about: Propose a non-trivial change to snarkOS 4 | title: "[Proposal]" 5 | labels: 'proposal' 6 | --- 7 | 8 | ## 💥 Proposal 9 | 10 | 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/documentation.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 📚 Documentation 3 | about: Report an issue related to documentation 4 | title: "[Docs]" 5 | labels: 'documentation' 6 | --- 7 | 8 | ## 📚 Documentation 9 | 10 | 11 | -------------------------------------------------------------------------------- /.devnet/.analytics/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "analytics", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "analytics.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "The Aleo Team", 10 | "license": "Apache 2.0", 11 | "dependencies": { 12 | "axios": "^1.5.1", 13 | "yargs": "^17.7.2" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Motivation 4 | 5 | (Write your motivation here) 6 | 7 | ## Test Plan 8 | 9 | (If you changed any code, please provide clear instructions on how you verified your changes work.) 10 | 11 | ## Related PRs 12 | 13 | (Link any related PRs here) 14 | -------------------------------------------------------------------------------- /node/metrics/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | prometheus: 3 | image: ubuntu/prometheus:2.33-22.04_beta 4 | volumes: 5 | - ./prometheus.yml:/etc/prometheus/prometheus.yml 6 | ports: 7 | - 9090:9090 8 | extra_hosts: 9 | - "host.docker.internal:host-gateway" 10 | grafana: 11 | image: grafana/grafana 12 | depends_on: [prometheus] 13 | ports: 14 | - 3000:3000 15 | -------------------------------------------------------------------------------- /node/rest/README.md: -------------------------------------------------------------------------------- 1 | # snarkos-node-rest 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/snarkos-node-rest.svg?color=neon)](https://crates.io/crates/snarkos-node-rest) 4 | [![Authors](https://img.shields.io/badge/authors-Aleo-orange.svg)](https://aleo.org) 5 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE.md) 6 | 7 | The `snarkos-node-rest` crate provides a REST API for the `snarkos` node. 8 | -------------------------------------------------------------------------------- /node/sync/README.md: -------------------------------------------------------------------------------- 1 | # snarkos-node-sync 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/snarkos-node-sync.svg?color=neon)](https://crates.io/crates/snarkos-node-sync) 4 | [![Authors](https://img.shields.io/badge/authors-Aleo-orange.svg)](https://aleo.org) 5 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE.md) 6 | 7 | The `snarkos-node-sync` crate provides a synchronization module for nodes. 8 | -------------------------------------------------------------------------------- /node/cdn/README.md: -------------------------------------------------------------------------------- 1 | # snarkos-node-cdn 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/snarkos-node-cdn.svg?color=neon)](https://crates.io/crates/snarkos-node-cdn) 4 | [![Authors](https://img.shields.io/badge/authors-Aleo-orange.svg)](https://aleo.org) 5 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE.md) 6 | 7 | The `snarkos-node-cdn` crate provides helpers for fetching ledger state from a CDN. 8 | -------------------------------------------------------------------------------- /node/README.md: -------------------------------------------------------------------------------- 1 | # snarkos-node 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/snarkos-node.svg?color=neon)](https://crates.io/crates/snarkos-node) 4 | [![Authors](https://img.shields.io/badge/authors-Aleo-orange.svg)](https://aleo.org) 5 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE.md) 6 | 7 | The `snarkos-node` crate provides the `Node` struct, which is responsible for running a node in the Aleo network. 8 | -------------------------------------------------------------------------------- /cli/README.md: -------------------------------------------------------------------------------- 1 | # snarkos-cli 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/snarkos-cli.svg?color=neon)](https://crates.io/crates/snarkos-cli) 4 | [![Authors](https://img.shields.io/badge/authors-Aleo-orange.svg)](https://aleo.org) 5 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE.md) 6 | 7 | The `snarkos-cli` crate provides the `CLI` struct, which is responsible for providing a command-line interface to the node. 8 | -------------------------------------------------------------------------------- /node/bft/events/README.md: -------------------------------------------------------------------------------- 1 | # snarkos-node-bft-events 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/snarkos-node-bft-events.svg?color=neon)](https://crates.io/crates/snarkos-node-bft-events) 4 | [![Authors](https://img.shields.io/badge/authors-Aleo-orange.svg)](https://aleo.org) 5 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE.md) 6 | 7 | The `snarkos-node-bft-events` crate provides the events for a memory pool. 8 | -------------------------------------------------------------------------------- /node/consensus/README.md: -------------------------------------------------------------------------------- 1 | # snarkos-node-consensus 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/snarkos-node-consensus.svg?color=neon)](https://crates.io/crates/snarkos-node-consensus) 4 | [![Authors](https://img.shields.io/badge/authors-Aleo-orange.svg)](https://aleo.org) 5 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE.md) 6 | 7 | The `snarkos-node-consensus` crate provides the consensus layer for the snarkOS node. 8 | -------------------------------------------------------------------------------- /display/README.md: -------------------------------------------------------------------------------- 1 | # snarkos-display 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/snarkos-display.svg?color=neon)](https://crates.io/crates/snarkos-display) 4 | [![Authors](https://img.shields.io/badge/authors-Aleo-orange.svg)](https://aleo.org) 5 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE.md) 6 | 7 | The `snarkos-display` crate provides the `Display` struct, which is responsible for displaying information about the node. 8 | -------------------------------------------------------------------------------- /node/sync/locators/README.md: -------------------------------------------------------------------------------- 1 | # snarkos-node-sync-locators 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/snarkos-node-sync-locators.svg?color=neon)](https://crates.io/crates/snarkos-node-sync-locators) 4 | [![Authors](https://img.shields.io/badge/authors-Aleo-orange.svg)](https://aleo.org) 5 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE.md) 6 | 7 | The `snarkos-node-sync-locators` crate provides locators to synchronize nodes. 8 | -------------------------------------------------------------------------------- /node/tcp/README.md: -------------------------------------------------------------------------------- 1 | # snarkos-node-tcp 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/snarkos-node-tcp.svg?color=neon)](https://crates.io/crates/snarkos-node-tcp) 4 | [![Authors](https://img.shields.io/badge/authors-Aleo-orange.svg)](https://aleo.org) 5 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE.md) 6 | 7 | The `snarkos-node-tcp` crate provides the `Tcp` struct, which is responsible for establishing TCP connections between nodes. 8 | -------------------------------------------------------------------------------- /node/router/README.md: -------------------------------------------------------------------------------- 1 | # snarkos-node-router 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/snarkos-node-router.svg?color=neon)](https://crates.io/crates/snarkos-node-router) 4 | [![Authors](https://img.shields.io/badge/authors-Aleo-orange.svg)](https://aleo.org) 5 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE.md) 6 | 7 | The `snarkos-node-router` crate provides the `Router` struct, which is responsible for routing messages between nodes. 8 | -------------------------------------------------------------------------------- /.rustfmt.toml: -------------------------------------------------------------------------------- 1 | # https://github.com/rust-lang/rustfmt/blob/master/Configurations.md 2 | 3 | # Stable configurations 4 | edition = "2021" 5 | max_width = 120 6 | merge_derives = true 7 | use_field_init_shorthand = true 8 | use_small_heuristics = "Max" 9 | use_try_shorthand = true 10 | 11 | # Nightly configurations 12 | imports_layout = "HorizontalVertical" 13 | imports_granularity = "Crate" 14 | overflow_delimited_expr = true 15 | reorder_impl_items = true 16 | version = "Two" 17 | -------------------------------------------------------------------------------- /account/README.md: -------------------------------------------------------------------------------- 1 | # snarkos-account 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/snarkos-account.svg?color=neon)](https://crates.io/crates/snarkos-account) 4 | [![Authors](https://img.shields.io/badge/authors-Aleo-orange.svg)](https://aleo.org) 5 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE.md) 6 | 7 | The `snarkos-account` crate provides the `Account` struct, which is responsible for managing a user's private key, view key, and address. 8 | -------------------------------------------------------------------------------- /node/router/messages/README.md: -------------------------------------------------------------------------------- 1 | # snarkos-node-router-messages 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/snarkos-node-router-messages.svg?color=neon)](https://crates.io/crates/snarkos-node-router-messages) 4 | [![Authors](https://img.shields.io/badge/authors-Aleo-orange.svg)](https://aleo.org) 5 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE.md) 6 | 7 | The `snarkos-node-router-messages` crate provides the message types used by the `snarkos-node-router` crate. 8 | -------------------------------------------------------------------------------- /node/bft/ledger-service/README.md: -------------------------------------------------------------------------------- 1 | # snarkos-node-bft-ledger-service 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/snarkos-node-bft-ledger-service.svg?color=neon)](https://crates.io/crates/snarkos-node-bft-ledger-service) 4 | [![Authors](https://img.shields.io/badge/authors-Aleo-orange.svg)](https://aleo.org) 5 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE.md) 6 | 7 | The `snarkos-node-bft-ledger-service` crate provides a ledger service implementation for a memory pool. 8 | -------------------------------------------------------------------------------- /node/bft/storage-service/README.md: -------------------------------------------------------------------------------- 1 | # snarkos-node-bft-storage-service 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/snarkos-node-bft-storage-service.svg?color=neon)](https://crates.io/crates/snarkos-node-bft-storage-service) 4 | [![Authors](https://img.shields.io/badge/authors-Aleo-orange.svg)](https://aleo.org) 5 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE.md) 6 | 7 | The `snarkos-node-bft-storage-service` crate provides a storage service implementation for a memory pool. 8 | -------------------------------------------------------------------------------- /node/sync/communication-service/README.md: -------------------------------------------------------------------------------- 1 | # snarkos-node-sync-communication-service 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/snarkos-node-sync-communication-service.svg?color=neon)](https://crates.io/crates/snarkos-node-sync-communication-service) 4 | [![Authors](https://img.shields.io/badge/authors-Aleo-orange.svg)](https://aleo.org) 5 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE.md) 6 | 7 | The `snarkos-node-sync-communication-service` crate provides a communication service implementation for a synchronization module. 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🚀 Feature 3 | about: Submit a new feature request 4 | title: "[Feature]" 5 | labels: feature 6 | --- 7 | 8 | ## 🚀 Feature 9 | 10 | 11 | 12 | ## Motivation 13 | 14 | 15 | 16 | ## Implementation 17 | 18 | 19 | 20 | **Are you willing to open a pull request?** (See [CONTRIBUTING](../../CONTRIBUTING.md)) 21 | -------------------------------------------------------------------------------- /node/metrics/prometheus.yml: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 15s 3 | scrape_timeout: 10s 4 | evaluation_interval: 1m 5 | scrape_configs: 6 | - job_name: prometheus 7 | honor_timestamps: true 8 | scrape_interval: 15s 9 | scrape_timeout: 10s 10 | metrics_path: /metrics 11 | scheme: http 12 | follow_redirects: true 13 | static_configs: 14 | - targets: 15 | - localhost:9090 16 | - job_name: snarkos 17 | honor_timestamps: true 18 | scrape_interval: 15s 19 | scrape_timeout: 10s 20 | metrics_path: /metrics 21 | scheme: http 22 | follow_redirects: true 23 | static_configs: 24 | - targets: 25 | - host.docker.internal:9000 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🐛 Bug Report 3 | about: Submit a bug report if something isn't working 4 | title: "[Bug]" 5 | labels: bug 6 | --- 7 | 8 | ## 🐛 Bug Report 9 | 10 | 11 | 12 | ## Steps to Reproduce 13 | 14 | 15 | 16 | ## Expected Behavior 17 | 18 | 19 | 20 | ## Your Environment 21 | 22 | - 23 | - 24 | - 25 | -------------------------------------------------------------------------------- /.resources/license_header: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. -------------------------------------------------------------------------------- /node/sync/communication-service/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snarkos-node-sync-communication-service" 3 | version = "2.2.7" 4 | authors = [ "The Aleo Team " ] 5 | description = "A communication service for the sync module in a decentralized operating system" 6 | homepage = "https://aleo.org" 7 | repository = "https://github.com/AleoHQ/snarkOS" 8 | keywords = [ 9 | "aleo", 10 | "cryptography", 11 | "blockchain", 12 | "decentralized", 13 | "zero-knowledge" 14 | ] 15 | categories = [ "cryptography", "operating-systems" ] 16 | license = "Apache-2.0" 17 | edition = "2021" 18 | 19 | [dependencies.async-trait] 20 | version = "0.1" 21 | 22 | [dependencies.tokio] 23 | version = "1.28" 24 | features = [ "sync" ] 25 | -------------------------------------------------------------------------------- /node/bft/events/src/helpers/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | mod codec; 16 | pub use codec::*; 17 | -------------------------------------------------------------------------------- /account/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snarkos-account" 3 | version = "2.2.7" 4 | authors = [ "The Aleo Team " ] 5 | description = "Account for a decentralized operating system" 6 | homepage = "https://aleo.org" 7 | repository = "https://github.com/AleoHQ/snarkOS" 8 | keywords = [ 9 | "aleo", 10 | "cryptography", 11 | "blockchain", 12 | "decentralized", 13 | "zero-knowledge" 14 | ] 15 | categories = [ "cryptography", "operating-systems" ] 16 | license = "Apache-2.0" 17 | edition = "2021" 18 | 19 | [dependencies.anyhow] 20 | version = "1.0.79" 21 | 22 | [dependencies.colored] 23 | version = "2" 24 | 25 | [dependencies.rand] 26 | version = "0.8" 27 | default-features = false 28 | 29 | [dependencies.snarkvm] 30 | workspace = true 31 | features = [ "console" ] 32 | -------------------------------------------------------------------------------- /node/rest/src/helpers/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | mod auth; 16 | pub use auth::*; 17 | 18 | mod error; 19 | pub use error::*; 20 | -------------------------------------------------------------------------------- /node/bft/tests/components/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | pub mod pending; 16 | pub mod worker; 17 | 18 | const ITERATIONS: u32 = 100; 19 | -------------------------------------------------------------------------------- /run-client.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # USAGE examples: 4 | # CLI : ./run-client.sh 5 | 6 | COMMAND='cargo run --release -- start --nodisplay --client' 7 | 8 | for word in $*; 9 | do 10 | COMMAND="${COMMAND} ${word}" 11 | done 12 | 13 | function exit_node() 14 | { 15 | echo "Exiting..." 16 | kill $! 17 | exit 18 | } 19 | 20 | trap exit_node SIGINT 21 | 22 | echo "Running an Aleo client node..." 23 | $COMMAND & 24 | 25 | while : 26 | do 27 | echo "Checking for updates..." 28 | git stash 29 | rm Cargo.lock 30 | STATUS=$(git pull) 31 | 32 | if [ "$STATUS" != "Already up to date." ]; then 33 | echo "Updated code found, rebuilding and relaunching client" 34 | cargo clean 35 | kill -INT $!; sleep 2; $COMMAND & 36 | fi 37 | 38 | sleep 1800 39 | 40 | done 41 | -------------------------------------------------------------------------------- /node/router/src/helpers/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | mod cache; 16 | pub use cache::Cache; 17 | 18 | mod peer; 19 | pub use peer::*; 20 | 21 | mod resolver; 22 | pub use resolver::*; 23 | -------------------------------------------------------------------------------- /node/sync/locators/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #![forbid(unsafe_code)] 16 | 17 | #[macro_use] 18 | extern crate tracing; 19 | 20 | mod block_locators; 21 | pub use block_locators::*; 22 | -------------------------------------------------------------------------------- /cli/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #![forbid(unsafe_code)] 16 | #![recursion_limit = "256"] 17 | 18 | #[macro_use] 19 | extern crate thiserror; 20 | 21 | pub mod commands; 22 | pub mod helpers; 23 | -------------------------------------------------------------------------------- /node/cdn/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #![forbid(unsafe_code)] 16 | 17 | #[macro_use] 18 | extern crate tracing; 19 | 20 | mod blocks; 21 | pub use blocks::{load_blocks, sync_ledger_with_cdn}; 22 | -------------------------------------------------------------------------------- /display/src/pages/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | mod logs; 16 | pub(crate) use logs::Logs; 17 | 18 | mod overview; 19 | pub(crate) use overview::Overview; 20 | 21 | pub(crate) const PAGES: [&str; 2] = [" Overview ", " Logs "]; 22 | -------------------------------------------------------------------------------- /node/router/messages/src/helpers/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | mod codec; 16 | pub use codec::MessageCodec; 17 | 18 | mod disconnect; 19 | pub use disconnect::DisconnectReason; 20 | 21 | mod node_type; 22 | pub use node_type::*; 23 | -------------------------------------------------------------------------------- /display/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snarkos-display" 3 | version = "2.2.7" 4 | authors = [ "The Aleo Team " ] 5 | description = "A display for a decentralized operating system" 6 | homepage = "https://aleo.org" 7 | repository = "https://github.com/AleoHQ/snarkOS" 8 | keywords = [ 9 | "aleo", 10 | "cryptography", 11 | "blockchain", 12 | "decentralized", 13 | "zero-knowledge" 14 | ] 15 | categories = [ "cryptography", "operating-systems" ] 16 | license = "Apache-2.0" 17 | edition = "2021" 18 | 19 | [dependencies.anyhow] 20 | version = "1.0.79" 21 | 22 | [dependencies.crossterm] 23 | version = "0.27" 24 | 25 | [dependencies.ratatui] 26 | version = "0.25" 27 | 28 | [dependencies.snarkos-node] 29 | path = "../node" 30 | version = "=2.2.7" 31 | 32 | [dependencies.snarkvm] 33 | workspace = true 34 | 35 | [dependencies.tokio] 36 | version = "1.28" 37 | features = [ "rt" ] 38 | -------------------------------------------------------------------------------- /node/sync/locators/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snarkos-node-sync-locators" 3 | version = "2.2.7" 4 | authors = [ "The Aleo Team " ] 5 | description = "Locators to synchronize a decentralized operating system" 6 | homepage = "https://aleo.org" 7 | repository = "https://github.com/AleoHQ/snarkOS" 8 | keywords = [ 9 | "aleo", 10 | "cryptography", 11 | "blockchain", 12 | "decentralized", 13 | "zero-knowledge" 14 | ] 15 | categories = [ "cryptography", "operating-systems" ] 16 | license = "Apache-2.0" 17 | edition = "2021" 18 | 19 | [features] 20 | default = [ ] 21 | test = [ ] 22 | 23 | [dependencies.anyhow] 24 | version = "1.0" 25 | 26 | [dependencies.indexmap] 27 | version = "2.1" 28 | features = [ "serde", "rayon" ] 29 | 30 | [dependencies.serde] 31 | version = "1" 32 | 33 | [dependencies.snarkvm] 34 | workspace = true 35 | 36 | [dependencies.tracing] 37 | version = "0.1" 38 | -------------------------------------------------------------------------------- /node/bft/tests/common/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | pub mod primary; 16 | pub mod test_peer; 17 | pub mod utils; 18 | 19 | pub type CurrentNetwork = snarkvm::prelude::MainnetV0; 20 | 21 | pub type TranslucentLedgerService = snarkos_node_bft_ledger_service::TranslucentLedgerService; 22 | -------------------------------------------------------------------------------- /.integration/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snarkos-integration" 3 | version = "2.2.7" 4 | authors = [ "The Aleo Team " ] 5 | description = "A integration testing suite for a decentralized operating system" 6 | homepage = "https://aleo.org" 7 | repository = "https://github.com/AleoHQ/snarkOS" 8 | keywords = [ 9 | "aleo", 10 | "cryptography", 11 | "blockchain", 12 | "decentralized", 13 | "zero-knowledge" 14 | ] 15 | categories = [ "cryptography", "operating-systems" ] 16 | license = "Apache-2.0" 17 | edition = "2021" 18 | 19 | [dev-dependencies.aleo-std] 20 | workspace = true 21 | 22 | [dev-dependencies.snarkos-node-cdn] 23 | path = "../node/cdn" 24 | 25 | [dev-dependencies.snarkvm] 26 | workspace = true 27 | features = [ "synthesizer" ] 28 | 29 | [dev-dependencies.tokio] 30 | version = "1.28" 31 | features = [ "rt" ] 32 | 33 | [dev-dependencies.tracing] 34 | version = "0.1" 35 | 36 | [dev-dependencies.tracing-test] 37 | version = "0.1" 38 | -------------------------------------------------------------------------------- /node/sync/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #![forbid(unsafe_code)] 16 | 17 | #[macro_use] 18 | extern crate tracing; 19 | 20 | pub use snarkos_node_sync_communication_service as communication_service; 21 | pub use snarkos_node_sync_locators as locators; 22 | 23 | mod block_sync; 24 | pub use block_sync::*; 25 | 26 | mod helpers; 27 | pub use helpers::*; 28 | -------------------------------------------------------------------------------- /node/metrics/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snarkos-node-metrics" 3 | version = "2.2.7" 4 | authors = [ "The Aleo Team " ] 5 | description = "A node for a decentralized operating system" 6 | homepage = "https://aleo.org" 7 | repository = "https://github.com/AleoHQ/snarkOS" 8 | keywords = [ 9 | "aleo", 10 | "cryptography", 11 | "blockchain", 12 | "decentralized", 13 | "zero-knowledge" 14 | ] 15 | categories = [ "cryptography", "operating-systems" ] 16 | license = "Apache-2.0" 17 | edition = "2021" 18 | 19 | [features] 20 | default = [ "rayon", "snarkvm/metrics"] 21 | metrics = [ "snarkvm/metrics" ] 22 | serial = ["snarkvm/metrics"] 23 | 24 | [dependencies.metrics-exporter-prometheus] 25 | version = "0.13" 26 | 27 | [dependencies.parking_lot] 28 | version = "0.12" 29 | 30 | [dependencies.rayon] 31 | version = "1" 32 | optional = true 33 | 34 | [dependencies.snarkvm] 35 | workspace = true 36 | features = [ "metrics" ] 37 | 38 | [dependencies.time] 39 | version = "0.3" 40 | 41 | [dependencies.tokio] 42 | version = "1.28" 43 | features = [ "rt" ] 44 | -------------------------------------------------------------------------------- /node/bft/storage-service/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #![forbid(unsafe_code)] 16 | #![allow(clippy::type_complexity)] 17 | 18 | #[cfg(feature = "memory")] 19 | pub mod memory; 20 | #[cfg(feature = "memory")] 21 | pub use memory::*; 22 | 23 | #[cfg(feature = "persistent")] 24 | pub mod persistent; 25 | #[cfg(feature = "persistent")] 26 | pub use persistent::*; 27 | 28 | pub mod traits; 29 | pub use traits::*; 30 | -------------------------------------------------------------------------------- /node/bft/storage-service/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snarkos-node-bft-storage-service" 3 | version = "2.2.7" 4 | authors = [ "The Aleo Team " ] 5 | description = "A storage service for the memory pool in a decentralized operating system" 6 | homepage = "https://aleo.org" 7 | repository = "https://github.com/AleoHQ/snarkOS" 8 | keywords = [ 9 | "aleo", 10 | "cryptography", 11 | "blockchain", 12 | "decentralized", 13 | "zero-knowledge" 14 | ] 15 | categories = [ "cryptography", "operating-systems" ] 16 | license = "Apache-2.0" 17 | edition = "2021" 18 | 19 | [features] 20 | default = [ ] 21 | memory = [ "parking_lot", "tracing" ] 22 | persistent = [ ] 23 | test = [ "memory" ] 24 | 25 | [dependencies.aleo-std] 26 | workspace = true 27 | 28 | [dependencies.indexmap] 29 | version = "2.1" 30 | features = [ "serde", "rayon" ] 31 | 32 | [dependencies.parking_lot] 33 | version = "0.12" 34 | optional = true 35 | 36 | [dependencies.snarkvm] 37 | workspace = true 38 | 39 | [dependencies.tracing] 40 | version = "0.1" 41 | optional = true 42 | 43 | [dev-dependencies.snarkvm] 44 | workspace = true 45 | features = [ "test" ] 46 | -------------------------------------------------------------------------------- /.devnet/fetch-logs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Determine the number of AWS EC2 instances by checking ~/.ssh/config 4 | NODE_ID=0 5 | while [ -n "$(grep "aws-n${NODE_ID}" ~/.ssh/config)" ]; do 6 | NODE_ID=$((NODE_ID + 1)) 7 | done 8 | 9 | # Read the number of AWS EC2 instances to query from the user 10 | read -p "Enter the number of AWS EC2 instances to query (default: $NODE_ID): " NUM_INSTANCES 11 | NUM_INSTANCES="${NUM_INSTANCES:-$NODE_ID}" 12 | 13 | echo "Using $NUM_INSTANCES AWS EC2 instances for querying." 14 | 15 | # Define the directory where logs will be saved 16 | log_directory="$HOME/snarkos_logs" 17 | 18 | # Create the log directory if it doesn't already exist 19 | mkdir -p "$log_directory" 20 | 21 | # Loop from 0 to 49 22 | for i in $(seq 0 $(($NUM_INSTANCES - 1))); do 23 | echo "Connecting to aws-n$i..." 24 | # Use sftp to connect, execute commands, and exit 25 | sftp aws-n$i << EOF 26 | cd /tmp 27 | get snarkos.log "$log_directory/snarkos-$i.log" 28 | EOF 29 | echo "Downloaded snarkos.log from aws-n$i as snarkos-$i.log into $log_directory" 30 | done 31 | 32 | echo "All files have been downloaded to $log_directory." 33 | -------------------------------------------------------------------------------- /display/src/tabs.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | pub(super) struct Tabs { 16 | pub titles: Vec<&'static str>, 17 | pub index: usize, 18 | } 19 | 20 | impl Tabs { 21 | pub fn new(titles: Vec<&'static str>) -> Self { 22 | Self { titles, index: 0 } 23 | } 24 | 25 | pub fn next(&mut self) { 26 | self.index = (self.index + 1) % self.titles.len(); 27 | } 28 | 29 | pub fn previous(&mut self) { 30 | if self.index > 0 { 31 | self.index -= 1; 32 | } else { 33 | self.index = self.titles.len() - 1; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /node/rest/src/helpers/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use axum::{ 16 | http::StatusCode, 17 | response::{IntoResponse, Response}, 18 | }; 19 | 20 | /// An enum of error handlers for the REST API server. 21 | pub struct RestError(pub String); 22 | 23 | impl IntoResponse for RestError { 24 | fn into_response(self) -> Response { 25 | (StatusCode::INTERNAL_SERVER_ERROR, format!("Something went wrong: {}", self.0)).into_response() 26 | } 27 | } 28 | 29 | impl From for RestError { 30 | fn from(err: anyhow::Error) -> Self { 31 | Self(err.to_string()) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /run-prover.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # USAGE examples: 3 | # CLI with env vars: PROVER_PRIVATE_KEY=APrivateKey1... ./run-prover.sh 4 | # CLI with prompts for vars: ./run-prover.sh 5 | 6 | # If the env var PROVER_PRIVATE_KEY is not set, prompt for it 7 | if [ -z "${PROVER_PRIVATE_KEY}" ] 8 | then 9 | read -r -p "Enter the Aleo Prover account private key: " 10 | PROVER_PRIVATE_KEY=$REPLY 11 | fi 12 | 13 | if [ "${PROVER_PRIVATE_KEY}" == "" ] 14 | then 15 | echo "Missing account private key. (run 'snarkos account new' and try again)" 16 | exit 17 | fi 18 | 19 | COMMAND="cargo run --release -- start --nodisplay --prover --private-key ${PROVER_PRIVATE_KEY}" 20 | 21 | for word in $*; 22 | do 23 | COMMAND="${COMMAND} ${word}" 24 | done 25 | 26 | function exit_node() 27 | { 28 | echo "Exiting..." 29 | kill $! 30 | exit 31 | } 32 | 33 | trap exit_node SIGINT 34 | 35 | echo "Running an Aleo Prover node..." 36 | $COMMAND & 37 | 38 | while : 39 | do 40 | echo "Checking for updates..." 41 | git stash 42 | STATUS=$(git pull) 43 | 44 | if [ "$STATUS" != "Already up to date." ]; then 45 | echo "Updated code found, rebuilding and relaunching prover" 46 | cargo clean 47 | kill -INT $!; sleep 2; $COMMAND & 48 | fi 49 | 50 | sleep 1800; 51 | done 52 | -------------------------------------------------------------------------------- /run-validator.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # USAGE examples: 3 | # CLI with env vars: VALIDATOR_PRIVATE_KEY=APrivateKey1... ./run-validator.sh 4 | # CLI with prompts for vars: ./run-validator.sh 5 | 6 | # If the env var VALIDATOR_PRIVATE_KEY is not set, prompt for it 7 | if [ -z "${VALIDATOR_PRIVATE_KEY}" ] 8 | then 9 | read -r -p "Enter the Aleo Validator account private key: " 10 | VALIDATOR_PRIVATE_KEY=$REPLY 11 | fi 12 | 13 | if [ "${VALIDATOR_PRIVATE_KEY}" == "" ] 14 | then 15 | echo "Missing account private key. (run 'snarkos account new' and try again)" 16 | exit 17 | fi 18 | 19 | COMMAND="cargo run --release -- start --nodisplay --validator --private-key ${VALIDATOR_PRIVATE_KEY}" 20 | 21 | for word in $*; 22 | do 23 | COMMAND="${COMMAND} ${word}" 24 | done 25 | 26 | function exit_node() 27 | { 28 | echo "Exiting..." 29 | kill $! 30 | exit 31 | } 32 | 33 | trap exit_node SIGINT 34 | 35 | echo "Running an Aleo Validator node..." 36 | $COMMAND & 37 | 38 | while : 39 | do 40 | echo "Checking for updates..." 41 | git stash 42 | rm Cargo.lock 43 | STATUS=$(git pull) 44 | 45 | if [ "$STATUS" != "Already up to date." ]; then 46 | echo "Updated code found, rebuilding and relaunching validator" 47 | cargo clean 48 | kill -INT $!; sleep 2; $COMMAND & 49 | fi 50 | 51 | sleep 1800; 52 | done 53 | -------------------------------------------------------------------------------- /node/tcp/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snarkos-node-tcp" 3 | version = "2.2.7" 4 | authors = [ "The Aleo Team " ] 5 | description = "A TCP stack for a decentralized operating system" 6 | homepage = "https://aleo.org" 7 | repository = "https://github.com/AleoHQ/snarkOS" 8 | keywords = [ 9 | "aleo", 10 | "cryptography", 11 | "blockchain", 12 | "decentralized", 13 | "zero-knowledge" 14 | ] 15 | categories = [ "cryptography", "operating-systems" ] 16 | license = "Apache-2.0" 17 | edition = "2021" 18 | 19 | [features] 20 | default = [ ] 21 | metrics = [ "dep:metrics" ] 22 | 23 | [dependencies] 24 | async-trait = "0.1" 25 | bytes = "1" 26 | parking_lot = "0.12" 27 | 28 | [dependencies.futures-util] 29 | version = "0.3" 30 | features = [ "sink" ] 31 | 32 | [dependencies.metrics] 33 | package = "snarkos-node-metrics" 34 | path = "../metrics" 35 | version = "=2.2.7" 36 | optional = true 37 | 38 | [dependencies.once_cell] 39 | version = "1" 40 | features = [ "parking_lot" ] 41 | 42 | [dependencies.tokio] 43 | version = "1.28" 44 | features = [ "io-util", "net", "parking_lot", "rt", "sync", "time" ] 45 | 46 | [dependencies.tokio-util] 47 | version = "0.7" 48 | features = [ "codec" ] 49 | 50 | [dependencies.tracing] 51 | version = "0.1" 52 | default-features = false 53 | 54 | [dev-dependencies.tokio] 55 | version = "1.28" 56 | features = [ "macros" ] 57 | -------------------------------------------------------------------------------- /.devnet/stop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Determine the number of AWS EC2 instances by checking ~/.ssh/config 4 | NODE_ID=0 5 | while [ -n "$(grep "aws-n${NODE_ID}" ~/.ssh/config)" ]; do 6 | NODE_ID=$((NODE_ID + 1)) 7 | done 8 | 9 | # Read the number of AWS EC2 instances to query from the user 10 | read -p "Enter the number of AWS EC2 instances to query (default: $NODE_ID): " NUM_INSTANCES 11 | NUM_INSTANCES="${NUM_INSTANCES:-$NODE_ID}" 12 | 13 | echo "Using $NUM_INSTANCES AWS EC2 instances for querying." 14 | 15 | # Define a function to terminate the tmux session on a node 16 | terminate_tmux_session() { 17 | local NODE_ID=$1 18 | 19 | # SSH into the node and send the "tmux kill-session" command to terminate the tmux session 20 | ssh -o StrictHostKeyChecking=no aws-n$NODE_ID << EOF 21 | # Command to terminate the tmux session 22 | sudo -i # Switch to root user 23 | tmux kill-session -t snarkos-session 24 | 25 | exit # Exit root user 26 | EOF 27 | 28 | # Check the exit status of the SSH command 29 | if [ $? -eq 0 ]; then 30 | echo "tmux session terminated successfully on aws-n$NODE_ID." 31 | else 32 | echo "Failed to terminate tmux session on aws-n$NODE_ID." 33 | fi 34 | } 35 | 36 | # Loop through aws-n nodes and terminate tmux sessions in parallel 37 | for NODE_ID in $(seq 0 $(($NUM_INSTANCES - 1))); do 38 | terminate_tmux_session $NODE_ID & 39 | done 40 | 41 | # Wait for all background jobs to finish 42 | wait 43 | -------------------------------------------------------------------------------- /snarkos/main.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use snarkos_cli::{commands::CLI, helpers::Updater}; 16 | 17 | use clap::Parser; 18 | use std::process::exit; 19 | 20 | #[cfg(all(target_os = "linux", target_arch = "x86_64"))] 21 | use tikv_jemallocator::Jemalloc; 22 | 23 | #[cfg(all(target_os = "linux", target_arch = "x86_64"))] 24 | #[global_allocator] 25 | static GLOBAL: Jemalloc = Jemalloc; 26 | 27 | fn main() -> anyhow::Result<()> { 28 | // Parse the given arguments. 29 | let cli = CLI::parse(); 30 | // Run the updater. 31 | println!("{}", Updater::print_cli()); 32 | // Run the CLI. 33 | match cli.command.parse() { 34 | Ok(output) => println!("{output}\n"), 35 | Err(error) => { 36 | println!("⚠️ {error}\n"); 37 | exit(1); 38 | } 39 | } 40 | Ok(()) 41 | } 42 | -------------------------------------------------------------------------------- /node/cdn/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snarkos-node-cdn" 3 | version = "2.2.7" 4 | authors = [ "The Aleo Team " ] 5 | description = "A CDN client for a decentralized operating system" 6 | homepage = "https://aleo.org" 7 | repository = "https://github.com/AleoHQ/snarkOS" 8 | keywords = [ 9 | "aleo", 10 | "cryptography", 11 | "blockchain", 12 | "decentralized", 13 | "zero-knowledge" 14 | ] 15 | categories = [ "cryptography", "operating-systems" ] 16 | license = "Apache-2.0" 17 | edition = "2021" 18 | 19 | [features] 20 | default = [ "parallel" ] 21 | parallel = [ "rayon" ] 22 | 23 | [dependencies.anyhow] 24 | version = "1.0.79" 25 | 26 | [dependencies.bincode] 27 | version = "1.0" 28 | 29 | [dependencies.colored] 30 | version = "2" 31 | 32 | [dependencies.futures] 33 | version = "0.3" 34 | 35 | [dependencies.parking_lot] 36 | version = "0.12" 37 | 38 | [dependencies.rayon] 39 | version = "1" 40 | optional = true 41 | 42 | [dependencies.reqwest] 43 | version = "0.11" 44 | 45 | [dependencies.serde] 46 | version = "1" 47 | 48 | [dependencies.serde_json] 49 | version = "1" 50 | features = [ "preserve_order" ] 51 | 52 | [dependencies.snarkvm] 53 | workspace = true 54 | features = [ "synthesizer" ] 55 | 56 | [dependencies.tokio] 57 | version = "1.28" 58 | features = [ "rt" ] 59 | 60 | [dependencies.tracing] 61 | version = "0.1" 62 | 63 | [dev-dependencies.tokio] 64 | version = "1.28" 65 | features = [ "rt", "rt-multi-thread" ] 66 | 67 | [dev-dependencies.tokio-test] 68 | version = "0.4" 69 | -------------------------------------------------------------------------------- /.devnet/clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Determine the number of AWS EC2 instances by checking ~/.ssh/config 4 | NODE_ID=0 5 | while [ -n "$(grep "aws-n${NODE_ID}" ~/.ssh/config)" ]; do 6 | NODE_ID=$((NODE_ID + 1)) 7 | done 8 | 9 | # Read the number of AWS EC2 instances to query from the user 10 | read -p "Enter the number of AWS EC2 instances to query (default: $NODE_ID): " NUM_INSTANCES 11 | NUM_INSTANCES="${NUM_INSTANCES:-$NODE_ID}" 12 | 13 | echo "Using $NUM_INSTANCES AWS EC2 instances for querying." 14 | 15 | # Define a function to terminate the tmux session on a node 16 | terminate_tmux_session() { 17 | local NODE_ID=$1 18 | 19 | # SSH into the node and send the "tmux kill-session" command to terminate the tmux session 20 | ssh -o StrictHostKeyChecking=no aws-n$NODE_ID << EOF 21 | # Command to terminate the tmux session 22 | sudo -i # Switch to root user 23 | WORKSPACE=~/snarkOS 24 | cd \$WORKSPACE 25 | 26 | tmux kill-session -t snarkos-session 27 | snarkos clean --dev $NODE_ID 28 | 29 | exit # Exit root user 30 | EOF 31 | 32 | # Check the exit status of the SSH command 33 | if [ $? -eq 0 ]; then 34 | echo "tmux session terminated successfully on aws-n$NODE_ID." 35 | else 36 | echo "Failed to terminate tmux session on aws-n$NODE_ID." 37 | fi 38 | } 39 | 40 | # Loop through aws-n nodes and terminate tmux sessions in parallel 41 | for NODE_ID in $(seq 0 $(($NUM_INSTANCES - 1))); do 42 | terminate_tmux_session $NODE_ID & 43 | done 44 | 45 | # Wait for all background jobs to finish 46 | wait 47 | -------------------------------------------------------------------------------- /node/bft/tests/components/pending.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use crate::common::{primary::new_test_committee, utils::sample_ledger, CurrentNetwork}; 16 | use snarkos_node_bft::helpers::max_redundant_requests; 17 | use snarkvm::{ledger::committee::Committee, prelude::TestRng}; 18 | 19 | #[test] 20 | fn test_max_redundant_requests() { 21 | const NUM_NODES: u16 = Committee::::MAX_COMMITTEE_SIZE; 22 | 23 | // Initialize the RNG. 24 | let mut rng = TestRng::default(); 25 | // Initialize the accounts and the committee. 26 | let (accounts, committee) = new_test_committee(NUM_NODES, &mut rng); 27 | // Sample a ledger. 28 | let ledger = sample_ledger(&accounts, &committee, &mut rng); 29 | // Ensure the maximum number of redundant requests is correct and consistent across iterations. 30 | assert_eq!(max_redundant_requests(ledger, 0), 34, "Update me if the formula changes"); 31 | } 32 | -------------------------------------------------------------------------------- /.devnet/analytics.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Get the directory of the bash script 4 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 5 | 6 | # Navigate to the directory containing the JavaScript program 7 | cd "$SCRIPT_DIR/.analytics" 8 | 9 | # Check if the 'node_modules' directory exists 10 | if [ ! -d "node_modules" ]; then 11 | echo "Node.js dependencies not found. Running 'npm install'..." 12 | npm install 13 | else 14 | echo "Node.js dependencies already installed." 15 | fi 16 | 17 | # Prompt the user to select a metric type 18 | PS3="Select a metric type: " 19 | options=("Average Block Time" "Rounds in Blocks" "Check Block Hash" "Quit") 20 | select opt in "${options[@]}" 21 | do 22 | case $opt in 23 | "Average Block Time") 24 | echo "" 25 | node analytics.js --metric-type averageBlockTime 26 | break 27 | ;; 28 | "Rounds in Blocks") 29 | echo "" 30 | node analytics.js --metric-type roundsInBlocks 31 | break 32 | ;; 33 | "Check Block Hash") 34 | echo "You selected 'Check Block Hash'. Please enter the block height:" 35 | read blockHeight 36 | echo "" 37 | # Validate input is an integer 38 | if ! [[ "$blockHeight" =~ ^[0-9]+$ ]]; then 39 | echo "Error: Block height must be a positive integer." 40 | exit 1 41 | fi 42 | node analytics.js --metric-type checkBlockHash --block-height "$blockHeight" 43 | break 44 | ;; 45 | "Quit") 46 | echo "Quitting..." 47 | break 48 | ;; 49 | *) echo "Invalid option";; 50 | esac 51 | done 52 | -------------------------------------------------------------------------------- /node/sync/communication-service/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #![forbid(unsafe_code)] 16 | 17 | #[macro_use] 18 | extern crate async_trait; 19 | 20 | use std::{io, net::SocketAddr}; 21 | use tokio::sync::oneshot; 22 | 23 | #[async_trait] 24 | pub trait CommunicationService: Send + Sync { 25 | /// The message type. 26 | type Message: Clone; 27 | 28 | /// Prepares a block request to be sent. 29 | fn prepare_block_request(start: u32, end: u32) -> Self::Message; 30 | 31 | /// Sends the given message to specified peer. 32 | /// 33 | /// This function returns as soon as the message is queued to be sent, 34 | /// without waiting for the actual delivery; instead, the caller is provided with a [`oneshot::Receiver`] 35 | /// which can be used to determine when and whether the message has been delivered. 36 | async fn send(&self, peer_ip: SocketAddr, message: Self::Message) -> Option>>; 37 | } 38 | -------------------------------------------------------------------------------- /node/tcp/src/helpers/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | mod config; 16 | pub use config::Config; 17 | 18 | pub mod connections; 19 | pub use connections::{Connection, ConnectionSide}; 20 | 21 | mod known_peers; 22 | pub use known_peers::KnownPeers; 23 | 24 | mod stats; 25 | pub use stats::Stats; 26 | 27 | use tracing::{debug_span, error_span, info_span, trace_span, warn_span, Span}; 28 | 29 | /// Creates the Tcp's tracing span based on its name. 30 | pub fn create_span(tcp_name: &str) -> Span { 31 | let mut span = trace_span!("tcp", name = tcp_name); 32 | if span.is_disabled() { 33 | span = debug_span!("tcp", name = tcp_name); 34 | } 35 | if span.is_disabled() { 36 | span = info_span!("tcp", name = tcp_name); 37 | } 38 | if span.is_disabled() { 39 | span = warn_span!("tcp", name = tcp_name); 40 | } 41 | if span.is_disabled() { 42 | span = error_span!("tcp", name = tcp_name); 43 | } 44 | span 45 | } 46 | -------------------------------------------------------------------------------- /node/bft/ledger-service/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snarkos-node-bft-ledger-service" 3 | version = "2.2.7" 4 | authors = [ "The Aleo Team " ] 5 | description = "A ledger service for the memory pool in a decentralized operating system" 6 | homepage = "https://aleo.org" 7 | repository = "https://github.com/AleoHQ/snarkOS" 8 | keywords = [ 9 | "aleo", 10 | "cryptography", 11 | "blockchain", 12 | "decentralized", 13 | "zero-knowledge" 14 | ] 15 | categories = [ "cryptography", "operating-systems" ] 16 | license = "Apache-2.0" 17 | edition = "2021" 18 | 19 | [features] 20 | default = [ ] 21 | ledger = [ "lru", "parking_lot", "rand", "tokio", "tracing" ] 22 | ledger-write = [ ] 23 | metrics = ["dep:metrics", "snarkvm/metrics"] 24 | mock = [ "parking_lot", "tracing" ] 25 | prover = [ ] 26 | test = [ "mock", "translucent" ] 27 | translucent = [ "ledger" ] 28 | 29 | [dependencies.async-trait] 30 | version = "0.1" 31 | 32 | [dependencies.indexmap] 33 | version = "2.1" 34 | features = [ "serde", "rayon" ] 35 | 36 | [dependencies.lru] 37 | version = "0.12" 38 | optional = true 39 | 40 | [dependencies.metrics] 41 | package = "snarkos-node-metrics" 42 | path = "../../metrics" 43 | version = "=2.2.7" 44 | optional = true 45 | 46 | [dependencies.parking_lot] 47 | version = "0.12" 48 | optional = true 49 | 50 | [dependencies.rand] 51 | version = "0.8" 52 | optional = true 53 | 54 | [dependencies.snarkvm] 55 | workspace = true 56 | 57 | [dependencies.tokio] 58 | version = "1.28" 59 | features = [ "macros", "rt-multi-thread" ] 60 | optional = true 61 | 62 | [dependencies.tracing] 63 | version = "0.1" 64 | optional = true 65 | -------------------------------------------------------------------------------- /node/bft/examples/start-nodes.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ $# -lt 1 ]; then 4 | echo "Usage: $0 [num_nodes]" 5 | echo "mode: bft or narwhal" 6 | echo "num_nodes: number of nodes to spin up (default: 4)" 7 | exit 8 | fi 9 | 10 | # The mode - bft or narwhal 11 | mode=$1 12 | 13 | # Default number of nodes to spin up 14 | default_num_nodes=4 15 | 16 | # Command to run for each node 17 | command="cargo +stable r --release --example simple_node" 18 | path=$(pwd) 19 | 20 | terminal_app="" 21 | 22 | case "$TERM_PROGRAM" in 23 | "iTerm.app") 24 | terminal_app="iTerm" 25 | ;; 26 | "Apple_Terminal") 27 | terminal_app="Terminal" 28 | ;; 29 | *) 30 | terminal_app="Unknown" 31 | ;; 32 | esac 33 | 34 | # Get the number of nodes from the command-line argument 35 | num_nodes=${2:-$default_num_nodes} 36 | 37 | # Loop to open terminal windows and execute the command 38 | for ((i = 0; i < num_nodes; i++)); do 39 | FULL_COMMAND="$command -- --mode $mode --id $i --num-nodes $num_nodes --fire-transmissions" 40 | 41 | if [[ "$terminal_app" == "iTerm" ]]; then 42 | osascript -e "tell application \"$terminal_app\" to create window with default profile" 43 | sleep 0.5 44 | osascript -e "tell application \"$terminal_app\" to tell current window to tell current session to write text \"cd $path && $FULL_COMMAND\"" 45 | elif [[ "$terminal_app" == "Terminal" ]]; then 46 | osascript -e "tell application \"$terminal_app\" to do script \"cd $path; $FULL_COMMAND\"" 47 | else 48 | if ! command -v xterm &>/dev/null; then 49 | echo "xterm could not be found, please install it" 50 | exit 51 | fi 52 | xterm -e "cd $path; $FULL_COMMAND" & 53 | fi 54 | done 55 | -------------------------------------------------------------------------------- /node/bft/src/helpers/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | pub mod cache; 16 | pub use cache::*; 17 | 18 | pub mod channels; 19 | pub use channels::*; 20 | 21 | pub mod dag; 22 | pub use dag::*; 23 | 24 | pub mod partition; 25 | pub use partition::*; 26 | 27 | pub mod pending; 28 | pub use pending::*; 29 | 30 | pub mod proposal; 31 | pub use proposal::*; 32 | 33 | pub mod proposal_cache; 34 | pub use proposal_cache::*; 35 | 36 | pub mod ready; 37 | pub use ready::*; 38 | 39 | pub mod resolver; 40 | pub use resolver::*; 41 | 42 | pub mod signed_proposals; 43 | pub use signed_proposals::*; 44 | 45 | pub mod storage; 46 | pub use storage::*; 47 | 48 | pub mod timestamp; 49 | pub use timestamp::*; 50 | 51 | /// Formats an ID into a truncated identifier (for logging purposes). 52 | pub fn fmt_id(id: impl ToString) -> String { 53 | let id = id.to_string(); 54 | let mut formatted_id = id.chars().take(16).collect::(); 55 | if id.chars().count() > 16 { 56 | formatted_id.push_str(".."); 57 | } 58 | formatted_id 59 | } 60 | -------------------------------------------------------------------------------- /node/bft/events/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snarkos-node-bft-events" 3 | version = "2.2.7" 4 | authors = [ "The Aleo Team " ] 5 | description = "Events for the gateway in a decentralized operating system" 6 | homepage = "https://aleo.org" 7 | repository = "https://github.com/AleoHQ/snarkOS" 8 | keywords = [ 9 | "aleo", 10 | "cryptography", 11 | "blockchain", 12 | "decentralized", 13 | "zero-knowledge" 14 | ] 15 | categories = [ "cryptography", "operating-systems" ] 16 | license = "Apache-2.0" 17 | edition = "2021" 18 | 19 | [features] 20 | default = [ ] 21 | metrics = ["dep:metrics", "snarkvm/metrics"] 22 | 23 | [dependencies.anyhow] 24 | version = "1.0" 25 | 26 | [dependencies.bytes] 27 | version = "1" 28 | 29 | [dependencies.indexmap] 30 | version = "2.1" 31 | features = [ "serde", "rayon" ] 32 | 33 | [dependencies.metrics] 34 | package = "snarkos-node-metrics" 35 | path = "../../metrics" 36 | version = "=2.2.7" 37 | optional = true 38 | 39 | [dependencies.rayon] 40 | version = "1" 41 | 42 | [dependencies.serde] 43 | version = "1" 44 | 45 | [dependencies.snarkos-node-sync-locators] 46 | path = "../../sync/locators" 47 | version = "=2.2.7" 48 | 49 | [dependencies.snarkvm] 50 | workspace = true 51 | 52 | [dependencies.tokio-util] 53 | version = "0.7" 54 | features = [ "codec" ] 55 | 56 | [dependencies.tracing] 57 | version = "0.1" 58 | 59 | [dev-dependencies.proptest] 60 | version = "1.4.0" 61 | 62 | [dev-dependencies.snarkvm] 63 | workspace = true 64 | features = [ "test-helpers" ] 65 | 66 | [dev-dependencies.test-strategy] 67 | version = "0.3.1" 68 | 69 | [dev-dependencies.time] 70 | version = "0.3" 71 | 72 | [dev-dependencies.snarkos-node-sync-locators] 73 | path = "../../sync/locators" 74 | features = [ "test" ] 75 | -------------------------------------------------------------------------------- /cli/src/helpers/log_writer.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use std::io; 16 | use tokio::sync::mpsc; 17 | 18 | pub enum LogWriter { 19 | /// Writes to stdout. 20 | Stdout(io::Stdout), 21 | /// Writes to a channel. 22 | Sender(mpsc::Sender>), 23 | } 24 | 25 | impl LogWriter { 26 | /// Initialize a new log writer. 27 | pub fn new(log_sender: &Option>>) -> Self { 28 | if let Some(sender) = log_sender { Self::Sender(sender.clone()) } else { Self::Stdout(io::stdout()) } 29 | } 30 | } 31 | 32 | impl io::Write for LogWriter { 33 | /// Writes the given buffer into the log writer. 34 | fn write(&mut self, buf: &[u8]) -> io::Result { 35 | match self { 36 | Self::Stdout(stdout) => stdout.write(buf), 37 | Self::Sender(sender) => { 38 | let log = buf.to_vec(); 39 | let _ = sender.try_send(log); 40 | Ok(buf.len()) 41 | } 42 | } 43 | } 44 | 45 | /// Flushes the log writer (no-op). 46 | fn flush(&mut self) -> io::Result<()> { 47 | Ok(()) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /node/router/messages/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snarkos-node-router-messages" 3 | version = "2.2.7" 4 | authors = [ "The Aleo Team " ] 5 | description = "Node messages for a decentralized operating system" 6 | homepage = "https://aleo.org" 7 | repository = "https://github.com/AleoHQ/snarkOS" 8 | keywords = [ 9 | "aleo", 10 | "cryptography", 11 | "blockchain", 12 | "decentralized", 13 | "zero-knowledge" 14 | ] 15 | categories = [ "cryptography", "operating-systems" ] 16 | license = "Apache-2.0" 17 | edition = "2021" 18 | 19 | [features] 20 | default = [ ] 21 | test = [ ] 22 | 23 | [dependencies.anyhow] 24 | version = "1.0" 25 | 26 | [dependencies.bytes] 27 | version = "1" 28 | 29 | [dependencies.indexmap] 30 | version = "2.1" 31 | features = [ "serde", "rayon" ] 32 | 33 | [dependencies.rayon] 34 | version = "1" 35 | 36 | [dependencies.serde] 37 | version = "1" 38 | 39 | [dependencies.snarkos-node-bft-events] 40 | path = "../../bft/events" 41 | version = "=2.2.7" 42 | 43 | [dependencies.snarkos-node-sync-locators] 44 | path = "../../sync/locators" 45 | version = "=2.2.7" 46 | 47 | [dependencies.snarkvm] 48 | workspace = true 49 | 50 | [dependencies.tokio] 51 | version = "1.28" 52 | features = [ 53 | "io-util", 54 | "macros", 55 | "net", 56 | "rt-multi-thread", 57 | "signal", 58 | "sync", 59 | "time" 60 | ] 61 | 62 | [dependencies.tokio-util] 63 | version = "0.7" 64 | features = [ "codec" ] 65 | 66 | [dependencies.tracing] 67 | version = "0.1" 68 | 69 | [dev-dependencies.snarkos-node-sync-locators] 70 | path = "../../sync/locators" 71 | features = [ "test" ] 72 | 73 | [dev-dependencies.snarkvm] 74 | workspace = true 75 | features = [ "algorithms", "test-helpers" ] 76 | 77 | [dev-dependencies.proptest] 78 | version = "1.4.0" 79 | 80 | [dev-dependencies.test-strategy] 81 | version = "0.3.1" 82 | -------------------------------------------------------------------------------- /node/bft/examples/monitor.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use axum::{routing::get, Router}; 16 | use std::net::SocketAddr; 17 | use tokio::net::TcpListener; 18 | use tower_http::services::{ServeDir, ServeFile}; 19 | 20 | const SERVER_URL: &str = "127.0.0.1:6060"; 21 | 22 | async fn start_server() { 23 | // Serve the 'assets/' directory. 24 | let serve_dir = ServeDir::new("assets").fallback(ServeFile::new("assets/index.html")); 25 | 26 | // Initialize the routes. 27 | let router = Router::new().route("/", get(|| async { "Hello, World!" })).fallback_service(serve_dir); 28 | 29 | // Run the server. 30 | println!("Starting server at '{SERVER_URL}'..."); 31 | let rest_addr: SocketAddr = SERVER_URL.parse().unwrap(); 32 | let rest_listener = TcpListener::bind(rest_addr).await.unwrap(); 33 | axum::serve(rest_listener, router.into_make_service_with_connect_info::()).await.unwrap(); 34 | } 35 | 36 | #[tokio::main] 37 | async fn main() { 38 | tokio::spawn(async move { start_server().await }); 39 | open::that(format!("http://{SERVER_URL}/assets/index.html")).expect("Failed to open website"); 40 | // Note: Do not move this. 41 | std::future::pending::<()>().await; 42 | } 43 | -------------------------------------------------------------------------------- /node/sync/src/helpers/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use snarkvm::prelude::Network; 16 | 17 | use core::hash::Hash; 18 | use indexmap::IndexSet; 19 | use std::net::SocketAddr; 20 | 21 | /// A tuple of the block hash (optional), previous block hash (optional), and the number of sync IPS to request from. 22 | pub type PrepareSyncRequest = (Option<::BlockHash>, Option<::BlockHash>, usize); 23 | 24 | /// A tuple of the block hash (optional), previous block hash (optional), and sync IPs. 25 | pub type SyncRequest = (Option<::BlockHash>, Option<::BlockHash>, IndexSet); 26 | 27 | #[derive(Copy, Clone, Debug)] 28 | pub(crate) struct PeerPair(pub SocketAddr, pub SocketAddr); 29 | 30 | impl Eq for PeerPair {} 31 | 32 | impl PartialEq for PeerPair { 33 | fn eq(&self, other: &Self) -> bool { 34 | (self.0 == other.0 && self.1 == other.1) || (self.0 == other.1 && self.1 == other.0) 35 | } 36 | } 37 | 38 | impl Hash for PeerPair { 39 | fn hash(&self, state: &mut H) { 40 | let (a, b) = if self.0 < self.1 { (self.0, self.1) } else { (self.1, self.0) }; 41 | a.hash(state); 42 | b.hash(state); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /node/bft/events/src/validators_request.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use super::*; 16 | 17 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] 18 | pub struct ValidatorsRequest; 19 | 20 | impl EventTrait for ValidatorsRequest { 21 | /// Returns the event name. 22 | #[inline] 23 | fn name(&self) -> Cow<'static, str> { 24 | "ValidatorsRequest".into() 25 | } 26 | } 27 | 28 | impl ToBytes for ValidatorsRequest { 29 | fn write_le(&self, _writer: W) -> IoResult<()> { 30 | Ok(()) 31 | } 32 | } 33 | 34 | impl FromBytes for ValidatorsRequest { 35 | fn read_le(_reader: R) -> IoResult { 36 | Ok(Self) 37 | } 38 | } 39 | 40 | #[cfg(test)] 41 | pub mod tests { 42 | use crate::ValidatorsRequest; 43 | 44 | use bytes::{Buf, BufMut, BytesMut}; 45 | use snarkvm::utilities::{FromBytes, ToBytes}; 46 | 47 | #[test] 48 | fn validators_request_roundtrip() { 49 | let validators_request = ValidatorsRequest; 50 | let mut bytes = BytesMut::default().writer(); 51 | validators_request.write_le(&mut bytes).unwrap(); 52 | let decoded = ValidatorsRequest::read_le(&mut bytes.into_inner().reader()).unwrap(); 53 | assert_eq![decoded, validators_request]; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /node/router/messages/src/peer_request.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use super::*; 16 | 17 | use snarkvm::prelude::{FromBytes, ToBytes}; 18 | 19 | use std::borrow::Cow; 20 | 21 | #[derive(Clone, Debug, PartialEq, Eq)] 22 | pub struct PeerRequest; 23 | 24 | impl MessageTrait for PeerRequest { 25 | /// Returns the message name. 26 | #[inline] 27 | fn name(&self) -> Cow<'static, str> { 28 | "PeerRequest".into() 29 | } 30 | } 31 | 32 | impl ToBytes for PeerRequest { 33 | fn write_le(&self, _writer: W) -> io::Result<()> { 34 | Ok(()) 35 | } 36 | } 37 | 38 | impl FromBytes for PeerRequest { 39 | fn read_le(_reader: R) -> io::Result { 40 | Ok(Self) 41 | } 42 | } 43 | 44 | #[cfg(test)] 45 | pub mod tests { 46 | use crate::PeerRequest; 47 | use snarkvm::utilities::{FromBytes, ToBytes}; 48 | 49 | use bytes::{Buf, BufMut, BytesMut}; 50 | 51 | #[test] 52 | fn peer_request_roundtrip() { 53 | let peer_request = PeerRequest; 54 | let mut bytes = BytesMut::default().writer(); 55 | peer_request.write_le(&mut bytes).unwrap(); 56 | let decoded = PeerRequest::read_le(&mut bytes.into_inner().reader()).unwrap(); 57 | assert_eq!(decoded, peer_request); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /node/tcp/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #![deny(missing_docs)] 16 | #![deny(unsafe_code)] 17 | 18 | //! **Tcp** is a simple, low-level, and customizable implementation of a TCP stack. 19 | 20 | mod helpers; 21 | pub use helpers::*; 22 | 23 | pub mod protocols; 24 | 25 | mod tcp; 26 | pub use tcp::Tcp; 27 | 28 | use std::net::IpAddr; 29 | 30 | /// A trait for objects containing a [`Tcp`]; it is required to implement protocols. 31 | pub trait P2P { 32 | /// Returns a reference to the TCP instance. 33 | fn tcp(&self) -> &Tcp; 34 | } 35 | 36 | /// Checks if the given IP address is a bogon address. 37 | /// 38 | /// A bogon address is an IP address that should not appear on the public Internet. 39 | /// This includes private addresses, loopback addresses, and link-local addresses. 40 | pub fn is_bogon_ip(ip: IpAddr) -> bool { 41 | match ip { 42 | IpAddr::V4(ipv4) => ipv4.is_loopback() || ipv4.is_private() || ipv4.is_link_local(), 43 | IpAddr::V6(ipv6) => ipv6.is_loopback(), 44 | } 45 | } 46 | 47 | /// Checks if the given IP address is unspecified or broadcast. 48 | pub fn is_unspecified_or_broadcast_ip(ip: IpAddr) -> bool { 49 | match ip { 50 | IpAddr::V4(ipv4) => ipv4.is_unspecified() || ipv4.is_broadcast(), 51 | ipv6 => ipv6.is_unspecified(), 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /node/router/messages/src/puzzle_request.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use super::*; 16 | 17 | use snarkvm::prelude::{FromBytes, ToBytes}; 18 | 19 | use std::borrow::Cow; 20 | 21 | #[derive(Clone, Debug, PartialEq, Eq)] 22 | pub struct PuzzleRequest; 23 | 24 | impl MessageTrait for PuzzleRequest { 25 | /// Returns the message name. 26 | #[inline] 27 | fn name(&self) -> Cow<'static, str> { 28 | "PuzzleRequest".into() 29 | } 30 | } 31 | 32 | impl ToBytes for PuzzleRequest { 33 | fn write_le(&self, _writer: W) -> io::Result<()> { 34 | Ok(()) 35 | } 36 | } 37 | 38 | impl FromBytes for PuzzleRequest { 39 | fn read_le(_reader: R) -> io::Result { 40 | Ok(Self) 41 | } 42 | } 43 | 44 | #[cfg(test)] 45 | pub mod tests { 46 | use crate::PuzzleRequest; 47 | use snarkvm::utilities::{FromBytes, ToBytes}; 48 | 49 | use bytes::{Buf, BufMut, BytesMut}; 50 | 51 | #[test] 52 | fn puzzle_request_roundtrip() { 53 | let puzzle_request = PuzzleRequest; 54 | let mut bytes = BytesMut::default().writer(); 55 | puzzle_request.write_le(&mut bytes).unwrap(); 56 | let decoded = PuzzleRequest::read_le(&mut bytes.into_inner().reader()).unwrap(); 57 | assert_eq!(decoded, puzzle_request); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /.devnet/monitor.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Determine the number of AWS EC2 instances by checking ~/.ssh/config 4 | NODE_ID=0 5 | while [ -n "$(grep "aws-n${NODE_ID}" ~/.ssh/config)" ]; do 6 | NODE_ID=$((NODE_ID + 1)) 7 | done 8 | 9 | # Read the number of AWS EC2 instances to query from the user 10 | read -p "Enter the number of AWS EC2 instances to query (default: $NODE_ID): " NUM_INSTANCES 11 | NUM_INSTANCES="${NUM_INSTANCES:-$NODE_ID}" 12 | 13 | echo "Using $NUM_INSTANCES AWS EC2 instances for querying." 14 | 15 | # Create a new local tmux session named "devnet-aws" 16 | tmux new-session -d -s "devnet-aws" -n "window0" 17 | 18 | # Generate validator indices from 0 to (NUM_INSTANCES - 1) 19 | validator_indices=($(seq 0 $((NUM_INSTANCES - 1)))) 20 | 21 | # Loop through the list of validator indices and create a new window for each 22 | for validator_index in "${validator_indices[@]}"; do 23 | # Create a new window with a unique name 24 | tmux new-window -t "devnet-aws:$validator_index" -n "window$validator_index" 25 | 26 | # Define the SSH command to run on the remote instance 27 | ssh_command="sudo -i tmux attach-session -t 'snarkos-session'" 28 | 29 | # Send the SSH command to the new window 30 | tmux send-keys -t "devnet-aws:window$validator_index" "ssh -t -o StrictHostKeyChecking=no aws-n$validator_index \"$ssh_command\"" C-m 31 | done 32 | 33 | # Attach to the tmux session to view and interact with the windows 34 | tmux attach-session -t "devnet-aws" 35 | 36 | 37 | ## Read the node ID to query from the user 38 | #read -p "Enter the node ID (default: 0): " NODE_ID 39 | #NODE_ID="${NODE_ID:-0}" 40 | # 41 | ## SSH into the node and attach to the snarkOS tmux session 42 | ##ssh -o StrictHostKeyChecking=no aws-n$NODE_ID << EOF 43 | ## # Commands to run on the remote instance 44 | ## sudo -i # Switch to root user 45 | ## tmux attach-session -t "snarkos-session" 46 | ##EOF 47 | #ssh -t -o StrictHostKeyChecking=no aws-n$NODE_ID "sudo -i tmux attach-session -t 'snarkos-session'" 48 | -------------------------------------------------------------------------------- /.devnet/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Prompt the user for the branch to install (default is "mainnet") 4 | read -p "Enter the branch to install (default: mainnet): " BRANCH 5 | BRANCH=${BRANCH:-mainnet} 6 | 7 | # Determine the number of AWS EC2 instances by checking ~/.ssh/config 8 | NODE_ID=0 9 | while [ -n "$(grep "aws-n${NODE_ID}" ~/.ssh/config)" ]; do 10 | NODE_ID=$((NODE_ID + 1)) 11 | done 12 | 13 | # Read the number of AWS EC2 instances to query from the user 14 | read -p "Enter the number of AWS EC2 instances to query (default: $NODE_ID): " NUM_INSTANCES 15 | NUM_INSTANCES="${NUM_INSTANCES:-$NODE_ID}" 16 | 17 | echo "Using $NUM_INSTANCES AWS EC2 instances for querying." 18 | 19 | # Define a function to run the installation on a node 20 | run_installation() { 21 | local NODE_ID=$1 22 | local BRANCH=$2 23 | # SSH into the node 24 | ssh -o StrictHostKeyChecking=no aws-n$NODE_ID << EOF 25 | # Commands to run on the remote instance 26 | sudo -i # Switch to root user 27 | WORKSPACE=~/snarkOS 28 | 29 | if [ -d "\$WORKSPACE" ]; then 30 | # The workspace directory exists, update the existing repository 31 | cd \$WORKSPACE 32 | git pull origin $BRANCH 33 | else 34 | # The workspace directory doesn't exist, clone the repository 35 | git clone https://github.com/AleoHQ/snarkOS.git \$WORKSPACE 36 | cd \$WORKSPACE 37 | git checkout $BRANCH # Checkout the specified branch 38 | fi 39 | 40 | sudo ./build_ubuntu.sh 41 | exit # Exit root user 42 | EOF 43 | 44 | # Check the exit status of the SSH command 45 | if [ $? -eq 0 ]; then 46 | echo "Installation on aws-n$NODE_ID completed successfully." 47 | else 48 | echo "Installation on aws-n$NODE_ID failed." 49 | fi 50 | } 51 | 52 | # Loop through aws-n nodes and run installations in parallel 53 | for NODE_ID in $(seq 0 $(($NUM_INSTANCES - 1))); do 54 | run_installation $NODE_ID $BRANCH & 55 | done 56 | 57 | # Wait for all background jobs to finish 58 | wait 59 | -------------------------------------------------------------------------------- /.integration/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #![forbid(unsafe_code)] 16 | 17 | #[cfg(test)] 18 | mod tests { 19 | use aleo_std::StorageMode; 20 | use snarkos_node_cdn::sync_ledger_with_cdn; 21 | use snarkvm::prelude::{ 22 | block::Block, 23 | store::helpers::memory::ConsensusMemory, 24 | FromBytes, 25 | Ledger, 26 | MainnetV0, 27 | Network, 28 | }; 29 | 30 | use tracing_test::traced_test; 31 | 32 | type CurrentNetwork = MainnetV0; 33 | 34 | const TEST_BASE_URL: &str = "https://testnet3.blocks.aleo.org/phase3"; 35 | 36 | #[test] 37 | #[traced_test] 38 | fn test_sync_ledger_with_cdn_0_to_tip() { 39 | // Initialize the genesis block. 40 | let genesis = Block::::read_le(CurrentNetwork::genesis_bytes()).unwrap(); 41 | // Initialize the ledger. 42 | let ledger = Ledger::<_, ConsensusMemory<_>>::load(genesis, StorageMode::Production).unwrap(); 43 | // Perform the sync. 44 | let rt = tokio::runtime::Runtime::new().unwrap(); 45 | rt.block_on(async { 46 | let completed_height = 47 | sync_ledger_with_cdn(TEST_BASE_URL, ledger.clone(), Default::default()).await.unwrap(); 48 | assert_eq!(completed_height, ledger.latest_height()); 49 | }); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /node/bft/ledger-service/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #![forbid(unsafe_code)] 16 | 17 | #[macro_use] 18 | extern crate async_trait; 19 | 20 | #[cfg(feature = "ledger")] 21 | pub mod ledger; 22 | #[cfg(feature = "ledger")] 23 | pub use ledger::*; 24 | 25 | #[cfg(feature = "mock")] 26 | pub mod mock; 27 | #[cfg(feature = "mock")] 28 | pub use mock::*; 29 | 30 | #[cfg(feature = "prover")] 31 | pub mod prover; 32 | #[cfg(feature = "prover")] 33 | pub use prover::*; 34 | 35 | #[cfg(feature = "translucent")] 36 | pub mod translucent; 37 | #[cfg(feature = "translucent")] 38 | pub use translucent::*; 39 | 40 | pub mod traits; 41 | pub use traits::*; 42 | 43 | /// Formats an ID into a truncated identifier (for logging purposes). 44 | pub fn fmt_id(id: impl ToString) -> String { 45 | let id = id.to_string(); 46 | let mut formatted_id = id.chars().take(16).collect::(); 47 | if id.chars().count() > 16 { 48 | formatted_id.push_str(".."); 49 | } 50 | formatted_id 51 | } 52 | 53 | /// A helper macro to spawn a blocking task. 54 | #[macro_export] 55 | macro_rules! spawn_blocking { 56 | ($expr:expr) => { 57 | match tokio::task::spawn_blocking(move || $expr).await { 58 | Ok(value) => value, 59 | Err(error) => Err(snarkvm::prelude::anyhow!("[tokio::spawn_blocking] {error}")), 60 | } 61 | }; 62 | } 63 | -------------------------------------------------------------------------------- /node/rest/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snarkos-node-rest" 3 | version = "2.2.7" 4 | authors = [ "The Aleo Team " ] 5 | description = "A REST API server for a decentralized virtual machine" 6 | homepage = "https://aleo.org" 7 | repository = "https://github.com/AleoHQ/snarkOS" 8 | keywords = [ 9 | "aleo", 10 | "cryptography", 11 | "blockchain", 12 | "decentralized", 13 | "zero-knowledge" 14 | ] 15 | categories = [ "cryptography", "operating-systems" ] 16 | license = "Apache-2.0" 17 | edition = "2021" 18 | 19 | [features] 20 | default = [ "parallel" ] 21 | parallel = [ "rayon" ] 22 | 23 | [dependencies.anyhow] 24 | version = "1.0.79" 25 | 26 | [dependencies.axum] 27 | version = "0.7" 28 | 29 | [dependencies.axum-extra] 30 | version = "0.9.0" 31 | features = [ "erased-json", "typed-header" ] 32 | 33 | [dependencies.http] 34 | version = "1.0" 35 | 36 | [dependencies.indexmap] 37 | version = "2.1" 38 | features = [ "serde", "rayon" ] 39 | 40 | [dependencies.jsonwebtoken] 41 | version = "9.2" 42 | 43 | [dependencies.once_cell] 44 | version = "1.19" 45 | 46 | [dependencies.parking_lot] 47 | version = "0.12" 48 | 49 | [dependencies.serde] 50 | version = "1" 51 | default-features = false 52 | features = [ "derive" ] 53 | 54 | [dependencies.serde_json] 55 | version = "1" 56 | features = [ "preserve_order" ] 57 | 58 | [dependencies.snarkos-node-consensus] 59 | path = "../consensus" 60 | version = "=2.2.7" 61 | 62 | [dependencies.snarkos-node-router] 63 | path = "../router" 64 | version = "=2.2.7" 65 | 66 | [dependencies.rand] 67 | version = "0.8" 68 | 69 | [dependencies.rayon] 70 | version = "1" 71 | optional = true 72 | 73 | [dependencies.snarkvm] 74 | workspace = true 75 | 76 | [dependencies.time] 77 | version = "0.3" 78 | 79 | [dependencies.tokio] 80 | version = "1" 81 | 82 | [dependencies.tower] 83 | version = "0.4" 84 | 85 | [dependencies.tower_governor] 86 | version = "0.3" 87 | 88 | [dependencies.tower-http] 89 | version = "0.5" 90 | features = [ "cors", "trace" ] 91 | 92 | [dependencies.tracing] 93 | version = "0.1" 94 | -------------------------------------------------------------------------------- /.devnet/config.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Read the EC2 instance name from the user 4 | read -p "Enter the EC2 instance name to filter by (e.g. Name) (default: devnet): " INSTANCE_NAME 5 | INSTANCE_NAME="${INSTANCE_NAME:-devnet}" 6 | 7 | # Read the PEM file path from the user or use the default in ~/.ssh 8 | read -p "Enter the PEM file path (default: ~/.ssh/s3-devnet.pem): " PEM_FILE 9 | PEM_FILE="${PEM_FILE:-~/.ssh/s3-devnet.pem}" 10 | 11 | # Use the AWS CLI to describe running EC2 instances, filter by the provided name, and store the JSON output in a variable 12 | instance_info=$(aws ec2 describe-instances \ 13 | --filters "Name=tag:Name,Values=$INSTANCE_NAME" "Name=instance-state-name,Values=running" \ 14 | --output json) 15 | 16 | # Parse the JSON output to extract information about the instances 17 | instance_ids=($(echo "$instance_info" | jq -r '.Reservations[].Instances[].InstanceId')) 18 | instance_names=($(echo "$instance_info" | jq -r '.Reservations[].Instances[].Tags[] | select(.Key=="Name") | .Value')) 19 | instance_states=($(echo "$instance_info" | jq -r '.Reservations[].Instances[].State.Name')) 20 | instance_ips=($(echo "$instance_info" | jq -r '.Reservations[].Instances[].PublicIpAddress')) 21 | 22 | # Initialize the SSH config string 23 | SSH_CONFIG="" 24 | 25 | # Loop through the instance IDs and print information for each instance 26 | for i in ${!instance_ids[@]}; do 27 | # echo "Instance ID: ${instance_ids[$i]}" 28 | # echo "Instance Name: ${instance_names[$i]}" 29 | # echo "Instance State: ${instance_states[$i]}" 30 | # echo "Instance IP: ${instance_ips[$i]}" 31 | # echo "------------------------" 32 | 33 | # Append SSH config entries to the string 34 | SSH_CONFIG+="Host aws-n$i"$'\n' 35 | SSH_CONFIG+=" HostName ${instance_ips[$i]}"$'\n' 36 | SSH_CONFIG+=" User ubuntu"$'\n' 37 | SSH_CONFIG+=" IdentityFile $PEM_FILE"$'\n' 38 | SSH_CONFIG+=" Port 22"$'\n' 39 | SSH_CONFIG+=$'\n' 40 | done 41 | 42 | # Print or save the SSH config string as needed 43 | echo -e "\n\n# AWS Devnet Nodes\n\n$SSH_CONFIG" 44 | -------------------------------------------------------------------------------- /node/tests/common/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | pub mod node; 16 | pub mod test_peer; 17 | 18 | use std::{env, str::FromStr}; 19 | 20 | use snarkos_account::Account; 21 | use snarkvm::prelude::{block::Block, FromBytes, MainnetV0 as CurrentNetwork, Network}; 22 | 23 | /// Returns a fixed account. 24 | pub fn sample_account() -> Account { 25 | Account::::from_str("APrivateKey1zkp2oVPTci9kKcUprnbzMwq95Di1MQERpYBhEeqvkrDirK1").unwrap() 26 | } 27 | 28 | /// Loads the current network's genesis block. 29 | pub fn sample_genesis_block() -> Block { 30 | Block::::from_bytes_le(CurrentNetwork::genesis_bytes()).unwrap() 31 | } 32 | 33 | /// Enables logging in tests. 34 | pub fn initialise_logger(level: u8) { 35 | match level { 36 | 0 => env::set_var("RUST_LOG", "info"), 37 | 1 => env::set_var("RUST_LOG", "debug"), 38 | 2 | 3 => env::set_var("RUST_LOG", "trace"), 39 | _ => env::set_var("RUST_LOG", "info"), 40 | }; 41 | 42 | // Filter out undesirable logs. 43 | let filter = tracing_subscriber::EnvFilter::from_default_env() 44 | .add_directive("snarkos=off".parse().unwrap()) 45 | .add_directive("tokio_util=off".parse().unwrap()) 46 | .add_directive("mio=off".parse().unwrap()); 47 | 48 | // Initialize tracing. 49 | let _ = tracing_subscriber::fmt().with_env_filter(filter).with_target(level == 3).try_init(); 50 | } 51 | -------------------------------------------------------------------------------- /node/consensus/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snarkos-node-consensus" 3 | version = "2.2.7" 4 | authors = [ "The Aleo Team " ] 5 | description = "A node consensus for a decentralized operating system" 6 | homepage = "https://aleo.org" 7 | repository = "https://github.com/AleoHQ/snarkOS" 8 | keywords = [ 9 | "aleo", 10 | "cryptography", 11 | "blockchain", 12 | "decentralized", 13 | "zero-knowledge" 14 | ] 15 | categories = [ "cryptography", "operating-systems" ] 16 | license = "Apache-2.0" 17 | edition = "2021" 18 | 19 | [features] 20 | default = [ ] 21 | metrics = [ "dep:metrics" ] 22 | 23 | [dependencies.aleo-std] 24 | workspace = true 25 | 26 | [dependencies.anyhow] 27 | version = "1.0.79" 28 | 29 | [dependencies.colored] 30 | version = "2" 31 | 32 | [dependencies.indexmap] 33 | version = "2.1" 34 | features = [ "serde", "rayon" ] 35 | 36 | [dependencies.lru] 37 | version = "0.12.1" 38 | 39 | [dependencies.metrics] 40 | package = "snarkos-node-metrics" 41 | path = "../metrics" 42 | version = "=2.2.7" 43 | optional = true 44 | 45 | [dependencies.parking_lot] 46 | version = "0.12" 47 | 48 | [dependencies.rand] 49 | version = "0.8" 50 | 51 | [dependencies.snarkos-account] 52 | path = "../../account" 53 | version = "=2.2.7" 54 | 55 | [dependencies.snarkos-node-bft] 56 | path = "../bft" 57 | version = "=2.2.7" 58 | 59 | [dependencies.snarkos-node-bft-ledger-service] 60 | path = "../bft/ledger-service" 61 | version = "=2.2.7" 62 | default-features = false 63 | features = [ "ledger", "ledger-write" ] 64 | 65 | [dependencies.snarkos-node-bft-storage-service] 66 | path = "../bft/storage-service" 67 | version = "=2.2.7" 68 | default-features = false 69 | features = [ "persistent" ] 70 | 71 | [dependencies.snarkvm] 72 | workspace = true 73 | 74 | [dependencies.tokio] 75 | version = "1.28" 76 | features = [ "macros", "rt-multi-thread", "signal" ] 77 | 78 | [dependencies.tracing] 79 | version = "0.1" 80 | 81 | [dev-dependencies.indexmap] 82 | version = "2.0" 83 | 84 | [dev-dependencies.itertools] 85 | version = "0.12" 86 | 87 | [dev-dependencies.once_cell] 88 | version = "1.19" 89 | 90 | [dev-dependencies.tracing-test] 91 | version = "0.2" 92 | -------------------------------------------------------------------------------- /display/src/pages/overview.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use snarkos_node::Node; 16 | use snarkvm::prelude::Network; 17 | 18 | use ratatui::{ 19 | layout::{Constraint, Direction, Layout, Rect}, 20 | style::{Color, Style}, 21 | text::Span, 22 | widgets::{canvas::Canvas, Block, Borders}, 23 | Frame, 24 | }; 25 | 26 | pub(crate) struct Overview; 27 | 28 | impl Overview { 29 | pub(crate) fn draw(&self, f: &mut Frame, area: Rect, _node: &Node) { 30 | // Initialize the layout of the page. 31 | let chunks = Layout::default() 32 | .direction(Direction::Vertical) 33 | .constraints([Constraint::Percentage(10), Constraint::Percentage(70), Constraint::Max(2)].as_ref()) 34 | .split(area); 35 | 36 | let canvas = Canvas::default().block(Block::default().borders(Borders::ALL).title("Block")).paint(|_ctx| { 37 | // ctx.draw(&ball); 38 | }); 39 | f.render_widget(canvas, chunks[0]); 40 | 41 | let canvas = Canvas::default().block(Block::default().borders(Borders::ALL).title("Peers")).paint(|_ctx| { 42 | // ctx.draw(&ball); 43 | }); 44 | f.render_widget(canvas, chunks[1]); 45 | 46 | let canvas = Canvas::default().block(Block::default().borders(Borders::ALL).title("Help")).paint(|ctx| { 47 | ctx.print(0f64, 0f64, Span::styled("Press ESC to quit", Style::default().fg(Color::White))); 48 | }); 49 | f.render_widget(canvas, chunks[2]); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /node/sync/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snarkos-node-sync" 3 | version = "2.2.7" 4 | authors = [ "The Aleo Team " ] 5 | description = "A synchronization module for a decentralized operating system" 6 | homepage = "https://aleo.org" 7 | repository = "https://github.com/AleoHQ/snarkOS" 8 | keywords = [ 9 | "aleo", 10 | "cryptography", 11 | "blockchain", 12 | "decentralized", 13 | "zero-knowledge" 14 | ] 15 | categories = [ "cryptography", "operating-systems" ] 16 | license = "Apache-2.0" 17 | edition = "2021" 18 | 19 | [features] 20 | default = [ ] 21 | metrics = [ "dep:metrics" ] 22 | test = [ "snarkos-node-sync-locators/test" ] 23 | 24 | [dependencies.anyhow] 25 | version = "1.0" 26 | 27 | [dependencies.indexmap] 28 | version = "2.1" 29 | features = [ "serde", "rayon" ] 30 | 31 | [dependencies.itertools] 32 | version = "0.12" 33 | 34 | [dependencies.once_cell] 35 | version = "1" 36 | 37 | [dependencies.parking_lot] 38 | version = "0.12" 39 | 40 | [dependencies.rand] 41 | version = "0.8" 42 | 43 | [dependencies.serde] 44 | version = "1" 45 | 46 | [dependencies.snarkos-node-bft-ledger-service] 47 | path = "../bft/ledger-service" 48 | version = "=2.2.7" 49 | features = [ "ledger-write" ] 50 | 51 | [dependencies.metrics] 52 | package = "snarkos-node-metrics" 53 | path = "../metrics" 54 | version = "=2.2.7" 55 | optional = true 56 | 57 | [dependencies.snarkos-node-router] 58 | path = "../router" 59 | version = "=2.2.7" 60 | 61 | [dependencies.snarkos-node-sync-communication-service] 62 | path = "communication-service" 63 | version = "=2.2.7" 64 | 65 | [dependencies.snarkos-node-sync-locators] 66 | path = "locators" 67 | version = "=2.2.7" 68 | 69 | [dependencies.snarkvm] 70 | workspace = true 71 | 72 | [dependencies.tokio] 73 | version = "1.28" 74 | features = [ "rt", "signal" ] 75 | 76 | [dependencies.tracing] 77 | version = "0.1" 78 | 79 | [dev-dependencies.snarkos-node-bft-ledger-service] 80 | path = "../bft/ledger-service" 81 | features = [ "test" ] 82 | 83 | [dev-dependencies.snarkos-node-sync-locators] 84 | path = "locators" 85 | features = [ "test" ] 86 | 87 | [dev-dependencies.snarkvm] 88 | workspace = true 89 | features = [ "test-helpers" ] 90 | -------------------------------------------------------------------------------- /.devnet/reinstall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Prompt the user for the branch to install (default is "mainnet") 4 | read -p "Enter the branch to install (default: mainnet): " BRANCH 5 | BRANCH=${BRANCH:-mainnet} 6 | 7 | # Determine the number of AWS EC2 instances by checking ~/.ssh/config 8 | NODE_ID=0 9 | while [ -n "$(grep "aws-n${NODE_ID}" ~/.ssh/config)" ]; do 10 | NODE_ID=$((NODE_ID + 1)) 11 | done 12 | 13 | # Read the number of AWS EC2 instances to query from the user 14 | read -p "Enter the number of AWS EC2 instances to query (default: $NODE_ID): " NUM_INSTANCES 15 | NUM_INSTANCES="${NUM_INSTANCES:-$NODE_ID}" 16 | 17 | echo "Using $NUM_INSTANCES AWS EC2 instances for querying." 18 | 19 | # Define a function to run the installation on a node 20 | run_installation() { 21 | local NODE_ID=$1 22 | local BRANCH=$2 23 | # SSH into the node 24 | ssh -o StrictHostKeyChecking=no aws-n$NODE_ID << EOF 25 | # Commands to run on the remote instance 26 | sudo -i # Switch to root user 27 | WORKSPACE=~/snarkOS 28 | 29 | if [ -d "\$WORKSPACE" ]; then 30 | # The workspace directory exists, update the existing repository 31 | # rm -rf \$WORKSPACE 32 | # git clone https://github.com/AleoHQ/snarkOS.git \$WORKSPACE 33 | cd \$WORKSPACE 34 | git pull # If we are switching branches, this will find the new branch 35 | git checkout $BRANCH # Checkout the specified branch 36 | git pull origin $BRANCH 37 | else 38 | # The workspace directory doesn't exist, clone the repository 39 | git clone https://github.com/AleoHQ/snarkOS.git \$WORKSPACE 40 | cd \$WORKSPACE 41 | git checkout $BRANCH # Checkout the specified branch 42 | fi 43 | 44 | cargo install --path . 45 | exit # Exit root user 46 | EOF 47 | 48 | # Check the exit status of the SSH command 49 | if [ $? -eq 0 ]; then 50 | echo "Installation on aws-n$NODE_ID completed successfully." 51 | else 52 | echo "Installation on aws-n$NODE_ID failed." 53 | fi 54 | } 55 | 56 | # Loop through aws-n nodes and run installations in parallel 57 | for NODE_ID in $(seq 0 $(($NUM_INSTANCES - 1))); do 58 | run_installation $NODE_ID $BRANCH & 59 | done 60 | 61 | # Wait for all background jobs to finish 62 | wait 63 | -------------------------------------------------------------------------------- /node/bft/src/helpers/timestamp.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use crate::MAX_TIMESTAMP_DELTA_IN_SECS; 16 | use snarkvm::prelude::{bail, Result}; 17 | 18 | use time::OffsetDateTime; 19 | 20 | /// Returns the current UTC epoch timestamp. 21 | pub fn now() -> i64 { 22 | OffsetDateTime::now_utc().unix_timestamp() 23 | } 24 | 25 | /// Sanity checks the timestamp for liveness. 26 | pub fn check_timestamp_for_liveness(timestamp: i64) -> Result<()> { 27 | // Ensure the timestamp is within range. 28 | if timestamp > (now() + MAX_TIMESTAMP_DELTA_IN_SECS) { 29 | bail!("Timestamp {timestamp} is too far in the future") 30 | } 31 | Ok(()) 32 | } 33 | 34 | #[cfg(test)] 35 | mod prop_tests { 36 | use super::*; 37 | use crate::MAX_TIMESTAMP_DELTA_IN_SECS; 38 | 39 | use proptest::prelude::*; 40 | use test_strategy::proptest; 41 | 42 | fn any_valid_timestamp() -> BoxedStrategy { 43 | (Just(now()), 0..MAX_TIMESTAMP_DELTA_IN_SECS).prop_map(|(now, delta)| now + delta).boxed() 44 | } 45 | 46 | fn any_invalid_timestamp() -> BoxedStrategy { 47 | (Just(now()), MAX_TIMESTAMP_DELTA_IN_SECS..).prop_map(|(now, delta)| now + delta).boxed() 48 | } 49 | 50 | #[proptest] 51 | fn test_check_timestamp_for_liveness(#[strategy(any_valid_timestamp())] timestamp: i64) { 52 | check_timestamp_for_liveness(timestamp).unwrap(); 53 | } 54 | 55 | #[proptest] 56 | fn test_check_timestamp_for_liveness_too_far_in_future(#[strategy(any_invalid_timestamp())] timestamp: i64) { 57 | assert!(check_timestamp_for_liveness(timestamp).is_err()); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /.devnet/start_sync_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Determine the number of AWS EC2 instances by checking ~/.ssh/config 4 | NODE_ID=0 5 | while [ -n "$(grep "aws-n${NODE_ID}" ~/.ssh/config)" ]; do 6 | NODE_ID=$((NODE_ID + 1)) 7 | done 8 | 9 | # Read the number of AWS EC2 instances to query from the user 10 | read -p "Enter the number of AWS EC2 instances to query (default: $NODE_ID): " NUM_INSTANCES 11 | NUM_INSTANCES="${NUM_INSTANCES:-$NODE_ID}" 12 | 13 | echo "Using $NUM_INSTANCES AWS EC2 instances for querying." 14 | 15 | # Read the verbosity level from the user (default: 1) 16 | read -p "Enter the verbosity level (default: 1): " VERBOSITY 17 | VERBOSITY="${VERBOSITY:-1}" 18 | 19 | echo "Using verbosity level $VERBOSITY." 20 | 21 | # Get the IP address of NODE 0 from the SSH config for aws-n0 22 | NODE_0_IP=$(awk '/Host aws-n0/{f=1} f&&/HostName/{print $2; exit}' ~/.ssh/config) 23 | 24 | # Define a function to start snarkOS in a tmux session on a node 25 | start_snarkos_in_tmux() { 26 | local NODE_ID=$1 27 | local NODE_IP=$2 28 | 29 | # SSH into the node and start snarkOS in a new tmux session 30 | ssh -o StrictHostKeyChecking=no aws-n$NODE_ID << EOF 31 | # Commands to run on the remote instance 32 | sudo -i # Switch to root user 33 | WORKSPACE=~/snarkOS 34 | cd \$WORKSPACE 35 | 36 | # Start snarkOS within a new tmux session named "snarkos-session" 37 | tmux new-session -d -s snarkos-session 38 | 39 | # Send the snarkOS start command to the tmux session with the NODE_ID 40 | tmux send-keys -t "snarkos-session" "snarkos start --client --nocdn --nodisplay --rest 0.0.0.0:3030 --node 0.0.0.0:4130 --verbosity 4 --metrics --logfile "/tmp/snarkos-syncing-range-3.log" --peers 167.71.249.65:4130,157.245.218.195:4130,167.71.249.55:4130" C-m 41 | 42 | exit # Exit root user 43 | EOF 44 | 45 | # Check the exit status of the SSH command 46 | if [ $? -eq 0 ]; then 47 | echo "snarkOS started successfully in a tmux session on aws-n$NODE_ID." 48 | else 49 | echo "Failed to start snarkOS in a tmux session on aws-n$NODE_ID." 50 | fi 51 | } 52 | 53 | # Loop through aws-n nodes and start snarkOS in tmux sessions in parallel 54 | for NODE_ID in $(seq 0 $(($NUM_INSTANCES - 1))); do 55 | start_snarkos_in_tmux $NODE_ID "$NODE_0_IP" & 56 | done 57 | 58 | # Wait for all background jobs to finish 59 | wait 60 | -------------------------------------------------------------------------------- /.devnet/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Determine the number of AWS EC2 instances by checking ~/.ssh/config 4 | NODE_ID=0 5 | while [ -n "$(grep "aws-n${NODE_ID}" ~/.ssh/config)" ]; do 6 | NODE_ID=$((NODE_ID + 1)) 7 | done 8 | 9 | # Read the number of AWS EC2 instances to query from the user 10 | read -p "Enter the number of AWS EC2 instances to query (default: $NODE_ID): " NUM_INSTANCES 11 | NUM_INSTANCES="${NUM_INSTANCES:-$NODE_ID}" 12 | 13 | echo "Using $NUM_INSTANCES AWS EC2 instances for querying." 14 | 15 | # Read the verbosity level from the user (default: 1) 16 | read -p "Enter the verbosity level (default: 1): " VERBOSITY 17 | VERBOSITY="${VERBOSITY:-1}" 18 | 19 | echo "Using verbosity level $VERBOSITY." 20 | 21 | # Get the IP address of NODE 0 from the SSH config for aws-n0 22 | NODE_0_IP=$(awk '/Host aws-n0/{f=1} f&&/HostName/{print $2; exit}' ~/.ssh/config) 23 | 24 | # Define a function to start snarkOS in a tmux session on a node 25 | start_snarkos_in_tmux() { 26 | local NODE_ID=$1 27 | local NODE_IP=$2 28 | 29 | # SSH into the node and start snarkOS in a new tmux session 30 | ssh -o StrictHostKeyChecking=no aws-n$NODE_ID << EOF 31 | # Commands to run on the remote instance 32 | sudo -i # Switch to root user 33 | WORKSPACE=~/snarkOS 34 | cd \$WORKSPACE 35 | 36 | # Start snarkOS within a new tmux session named "snarkos-session" 37 | tmux new-session -d -s snarkos-session 38 | 39 | # Send the snarkOS start command to the tmux session with the NODE_ID 40 | tmux send-keys -t "snarkos-session" "snarkos start --nodisplay --bft 0.0.0.0:5000 --rest 0.0.0.0:3030 --allow-external-peers --peers $NODE_IP:4130 --validators $NODE_IP:5000 --rest-rps 1000 --verbosity $VERBOSITY --dev $NODE_ID --dev-num-validators $NUM_INSTANCES --validator --metrics" C-m 41 | 42 | exit # Exit root user 43 | EOF 44 | 45 | # Check the exit status of the SSH command 46 | if [ $? -eq 0 ]; then 47 | echo "snarkOS started successfully in a tmux session on aws-n$NODE_ID." 48 | else 49 | echo "Failed to start snarkOS in a tmux session on aws-n$NODE_ID." 50 | fi 51 | } 52 | 53 | # Loop through aws-n nodes and start snarkOS in tmux sessions in parallel 54 | for NODE_ID in $(seq 0 $(($NUM_INSTANCES - 1))); do 55 | start_snarkos_in_tmux $NODE_ID "$NODE_0_IP" & 56 | done 57 | 58 | # Wait for all background jobs to finish 59 | wait 60 | -------------------------------------------------------------------------------- /node/router/src/routing.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use crate::{Heartbeat, Inbound, Outbound}; 16 | use snarkos_node_tcp::{ 17 | protocols::{Disconnect, Handshake, OnConnect}, 18 | P2P, 19 | }; 20 | use snarkvm::prelude::Network; 21 | 22 | use core::time::Duration; 23 | 24 | #[async_trait] 25 | pub trait Routing: 26 | P2P + Disconnect + OnConnect + Handshake + Inbound + Outbound + Heartbeat 27 | { 28 | /// Initialize the routing. 29 | async fn initialize_routing(&self) { 30 | // Enable the TCP protocols. 31 | self.enable_handshake().await; 32 | self.enable_reading().await; 33 | self.enable_writing().await; 34 | self.enable_disconnect().await; 35 | self.enable_on_connect().await; 36 | // Enable the TCP listener. Note: This must be called after the above protocols. 37 | self.enable_listener().await; 38 | // Initialize the heartbeat. 39 | self.initialize_heartbeat(); 40 | } 41 | 42 | // Start listening for inbound connections. 43 | async fn enable_listener(&self) { 44 | self.tcp().enable_listener().await.expect("Failed to enable the TCP listener"); 45 | } 46 | 47 | /// Initialize a new instance of the heartbeat. 48 | fn initialize_heartbeat(&self) { 49 | let self_clone = self.clone(); 50 | self.router().spawn(async move { 51 | loop { 52 | // Process a heartbeat in the router. 53 | self_clone.heartbeat(); 54 | // Sleep for `HEARTBEAT_IN_SECS` seconds. 55 | tokio::time::sleep(Duration::from_secs(Self::HEARTBEAT_IN_SECS)).await; 56 | } 57 | }); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /cli/src/commands/update.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use crate::helpers::Updater; 16 | 17 | use anyhow::Result; 18 | use clap::Parser; 19 | 20 | /// Update snarkOS. 21 | #[derive(Debug, Parser)] 22 | pub struct Update { 23 | /// Lists all available versions of snarkOS 24 | #[clap(short = 'l', long)] 25 | list: bool, 26 | /// Suppress outputs to terminal 27 | #[clap(short = 'q', long)] 28 | quiet: bool, 29 | /// Update to specified version 30 | #[clap(short = 'v', long)] 31 | version: Option, 32 | } 33 | 34 | impl Update { 35 | /// Update snarkOS. 36 | pub fn parse(self) -> Result { 37 | match self.list { 38 | true => match Updater::show_available_releases() { 39 | Ok(output) => Ok(output), 40 | Err(error) => Ok(format!("Failed to list the available versions of snarkOS\n{error}\n")), 41 | }, 42 | false => { 43 | let result = Updater::update_to_release(!self.quiet, self.version); 44 | if !self.quiet { 45 | match result { 46 | Ok(status) => { 47 | if status.uptodate() { 48 | Ok("\nsnarkOS is already on the latest version".to_string()) 49 | } else if status.updated() { 50 | Ok(format!("\nsnarkOS has updated to version {}", status.version())) 51 | } else { 52 | Ok(String::new()) 53 | } 54 | } 55 | Err(e) => Ok(format!("\nFailed to update snarkOS to the latest version\n{e}\n")), 56 | } 57 | } else { 58 | Ok(String::new()) 59 | } 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /node/tcp/src/helpers/known_peers.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use std::{collections::HashMap, net::SocketAddr, sync::Arc}; 16 | 17 | use parking_lot::RwLock; 18 | 19 | use crate::Stats; 20 | 21 | /// Contains statistics related to Tcp's peers, currently connected or not. 22 | #[derive(Default)] 23 | pub struct KnownPeers(RwLock>>); 24 | 25 | impl KnownPeers { 26 | /// Adds an address to the list of known peers. 27 | pub fn add(&self, addr: SocketAddr) { 28 | self.0.write().entry(addr).or_default(); 29 | } 30 | 31 | /// Returns the stats for the given peer. 32 | pub fn get(&self, addr: SocketAddr) -> Option> { 33 | self.0.read().get(&addr).map(Arc::clone) 34 | } 35 | 36 | /// Removes an address from the list of known peers. 37 | pub fn remove(&self, addr: SocketAddr) -> Option> { 38 | self.0.write().remove(&addr) 39 | } 40 | 41 | /// Returns the list of all known peers and their stats. 42 | pub fn snapshot(&self) -> HashMap> { 43 | self.0.read().clone() 44 | } 45 | 46 | /// Registers a submission of a message to the given address. 47 | pub fn register_sent_message(&self, to: SocketAddr, size: usize) { 48 | if let Some(stats) = self.0.read().get(&to) { 49 | stats.register_sent_message(size); 50 | } 51 | } 52 | 53 | /// Registers a receipt of a message to the given address. 54 | pub fn register_received_message(&self, from: SocketAddr, size: usize) { 55 | if let Some(stats) = self.0.read().get(&from) { 56 | stats.register_received_message(size); 57 | } 58 | } 59 | 60 | /// Registers a failure associated with the given address. 61 | pub fn register_failure(&self, addr: SocketAddr) { 62 | if let Some(stats) = self.0.read().get(&addr) { 63 | stats.register_failure(); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /node/router/messages/src/pong.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use super::*; 16 | 17 | use snarkvm::prelude::{FromBytes, ToBytes}; 18 | 19 | use std::borrow::Cow; 20 | 21 | #[derive(Clone, Debug, PartialEq, Eq)] 22 | pub struct Pong { 23 | pub is_fork: Option, 24 | } 25 | 26 | impl MessageTrait for Pong { 27 | /// Returns the message name. 28 | #[inline] 29 | fn name(&self) -> Cow<'static, str> { 30 | "Pong".into() 31 | } 32 | } 33 | 34 | impl ToBytes for Pong { 35 | fn write_le(&self, writer: W) -> io::Result<()> { 36 | let serialized_is_fork: u8 = match self.is_fork { 37 | Some(true) => 0, 38 | Some(false) => 1, 39 | None => 2, 40 | }; 41 | 42 | serialized_is_fork.write_le(writer) 43 | } 44 | } 45 | 46 | impl FromBytes for Pong { 47 | fn read_le(mut reader: R) -> io::Result { 48 | let is_fork = match u8::read_le(&mut reader)? { 49 | 0 => Some(true), 50 | 1 => Some(false), 51 | 2 => None, 52 | _ => return Err(error("Invalid 'Pong' message")), 53 | }; 54 | 55 | Ok(Self { is_fork }) 56 | } 57 | } 58 | 59 | #[cfg(test)] 60 | pub mod tests { 61 | use crate::Pong; 62 | use snarkvm::utilities::{FromBytes, ToBytes}; 63 | 64 | use bytes::{Buf, BufMut, BytesMut}; 65 | use proptest::{ 66 | option::of, 67 | prelude::{any, BoxedStrategy, Strategy}, 68 | }; 69 | use test_strategy::proptest; 70 | 71 | pub fn any_pong() -> BoxedStrategy { 72 | of(any::()).prop_map(|is_fork| Pong { is_fork }).boxed() 73 | } 74 | 75 | #[proptest] 76 | fn pong_roundtrip(#[strategy(any_pong())] pong: Pong) { 77 | let mut bytes = BytesMut::default().writer(); 78 | pong.write_le(&mut bytes).unwrap(); 79 | let decoded = Pong::read_le(&mut bytes.into_inner().reader()).unwrap(); 80 | assert_eq!(pong, decoded); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /node/tcp/src/helpers/stats.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use std::sync::atomic::{AtomicU64, Ordering::Relaxed}; 16 | 17 | /// Contains statistics related to Tcp. 18 | #[derive(Default)] 19 | pub struct Stats { 20 | /// The number of all messages sent. 21 | msgs_sent: AtomicU64, 22 | /// The number of all messages received. 23 | msgs_received: AtomicU64, 24 | /// The number of all bytes sent. 25 | bytes_sent: AtomicU64, 26 | /// The number of all bytes received. 27 | bytes_received: AtomicU64, 28 | /// The number of failures. 29 | failures: AtomicU64, 30 | } 31 | 32 | impl Stats { 33 | /// Returns the number of sent messages and their collective size in bytes. 34 | pub fn sent(&self) -> (u64, u64) { 35 | let msgs = self.msgs_sent.load(Relaxed); 36 | let bytes = self.bytes_sent.load(Relaxed); 37 | 38 | (msgs, bytes) 39 | } 40 | 41 | /// Returns the number of received messages and their collective size in bytes. 42 | pub fn received(&self) -> (u64, u64) { 43 | let msgs = self.msgs_received.load(Relaxed); 44 | let bytes = self.bytes_received.load(Relaxed); 45 | 46 | (msgs, bytes) 47 | } 48 | 49 | /// Returns the number of failures. 50 | pub fn failures(&self) -> u64 { 51 | self.failures.load(Relaxed) 52 | } 53 | 54 | /// Registers a sent message of the provided `size` in bytes. 55 | pub fn register_sent_message(&self, size: usize) { 56 | self.msgs_sent.fetch_add(1, Relaxed); 57 | self.bytes_sent.fetch_add(size as u64, Relaxed); 58 | } 59 | 60 | /// Registers a received message of the provided `size` in bytes. 61 | pub fn register_received_message(&self, size: usize) { 62 | self.msgs_received.fetch_add(1, Relaxed); 63 | self.bytes_received.fetch_add(size as u64, Relaxed); 64 | } 65 | 66 | /// Registers a failure. 67 | pub fn register_failure(&self) { 68 | self.failures.fetch_add(1, Relaxed); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /node/router/src/helpers/resolver.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use parking_lot::RwLock; 16 | use std::{collections::HashMap, net::SocketAddr}; 17 | 18 | #[derive(Debug)] 19 | pub struct Resolver { 20 | /// The map of the listener address to (ambiguous) peer address. 21 | from_listener: RwLock>, 22 | /// The map of the (ambiguous) peer address to listener address. 23 | to_listener: RwLock>, 24 | } 25 | 26 | impl Default for Resolver { 27 | /// Initializes a new instance of the resolver. 28 | fn default() -> Self { 29 | Self::new() 30 | } 31 | } 32 | 33 | impl Resolver { 34 | /// Initializes a new instance of the resolver. 35 | pub fn new() -> Self { 36 | Self { from_listener: Default::default(), to_listener: Default::default() } 37 | } 38 | 39 | /// Returns the listener address for the given (ambiguous) peer address, if it exists. 40 | pub fn get_listener(&self, peer_addr: &SocketAddr) -> Option { 41 | self.to_listener.read().get(peer_addr).copied() 42 | } 43 | 44 | /// Returns the (ambiguous) peer address for the given listener address, if it exists. 45 | pub fn get_ambiguous(&self, peer_ip: &SocketAddr) -> Option { 46 | self.from_listener.read().get(peer_ip).copied() 47 | } 48 | 49 | /// Inserts a bidirectional mapping of the listener address and the (ambiguous) peer address. 50 | pub fn insert_peer(&self, listener_ip: SocketAddr, peer_addr: SocketAddr) { 51 | self.from_listener.write().insert(listener_ip, peer_addr); 52 | self.to_listener.write().insert(peer_addr, listener_ip); 53 | } 54 | 55 | /// Removes the bidirectional mapping of the listener address and the (ambiguous) peer address. 56 | pub fn remove_peer(&self, listener_ip: &SocketAddr) { 57 | if let Some(peer_addr) = self.from_listener.write().remove(listener_ip) { 58 | self.to_listener.write().remove(&peer_addr); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /node/bft/README.md: -------------------------------------------------------------------------------- 1 | # snarkos-node-bft 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/snarkos-node-bft.svg?color=neon)](https://crates.io/crates/snarkos-node-bft) 4 | [![Authors](https://img.shields.io/badge/authors-Aleo-orange.svg)](https://aleo.org) 5 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE.md) 6 | 7 | The `snarkos-node-bft` crate provides a node implementation for a BFT-based memory pool. 8 | 9 | ## Primary 10 | 11 | The primary is the coordinator, responsible for advancing rounds and broadcasting the anchor. 12 | 13 | #### Triggering Round Advancement 14 | 15 | Each round runs until one of two conditions is met: 16 | 1. The coinbase target has been reached, or 17 | 2. The round has reached its timeout (currently set to 10 seconds) 18 | 19 | #### Advancing Rounds 20 | 21 | As described in the paper, the BFT advances rounds whenever n − f vertices are delivered. 22 | ``` 23 | The problem in advancing rounds whenever n − f vertices are delivered is that parties 24 | might not vote for the anchor even if the party that broadcast it is just slightly slower 25 | than the fastest n − f parties. To deal with this, the BFT integrates timeouts into 26 | the DAG construction. If the first n − f vertices a party p gets in an even-numbered round r 27 | do not include the anchor of round r, then p sets a timer and waits for the anchor 28 | until the timer expires. Similarly, in an odd-numbered round, parties wait for either 29 | f + 1 vertices that vote for the anchor, or 2f + 1 vertices that do not, or a timeout. 30 | ``` 31 | 32 | ## Workers 33 | 34 | The workers are simple entry replicators that receive transactions from the network and append them to their memory pool. 35 | 36 | In order to function properly, workers must be synced to the latest round, and capable of performing verification 37 | on the entries they receive from other validators' workers. 38 | 39 | ## Test Cases 40 | 41 | - Two validators, one with X workers, another with Y workers. Check that they are compatible. 42 | - If a primary sees that f+1 other primaries have certified this round, it should skip to the next round if it has not been certified yet. 43 | - Ensure taking a set number of transmissions from workers leaves the remaining transmissions in place for the next round. 44 | - Send back a mismatching transmission for a transmission ID, ensure it catches it. 45 | - Send back a mismatching certificate for a certificate ID, ensure it catches it. 46 | 47 | ## Open Questions 48 | 49 | 1. How does one guarantee the number of accepted transactions and solutions does not exceed the block limits? 50 | - We need to set limits on the number of transmissions for the workers, but also the primary. 51 | -------------------------------------------------------------------------------- /node/tcp/src/protocols/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //! Opt-in protocols available to the node; each protocol is expected to spawn its own task that runs throughout the 16 | //! node's lifetime and handles a specific functionality. The communication with these tasks is done via dedicated 17 | //! handler objects. 18 | 19 | use std::{io, net::SocketAddr}; 20 | 21 | use once_cell::race::OnceBox; 22 | use tokio::sync::{mpsc, oneshot}; 23 | 24 | use crate::connections::Connection; 25 | 26 | mod disconnect; 27 | mod handshake; 28 | mod on_connect; 29 | mod reading; 30 | mod writing; 31 | 32 | pub use disconnect::Disconnect; 33 | pub use handshake::Handshake; 34 | pub use on_connect::OnConnect; 35 | pub use reading::Reading; 36 | pub use writing::Writing; 37 | 38 | #[derive(Default)] 39 | pub(crate) struct Protocols { 40 | pub(crate) handshake: OnceBox>>, 41 | pub(crate) reading: OnceBox>>, 42 | pub(crate) writing: OnceBox, 43 | pub(crate) on_connect: OnceBox>, 44 | pub(crate) disconnect: OnceBox>, 45 | } 46 | 47 | /// An object sent to a protocol handler task; the task assumes control of a protocol-relevant item `T`, 48 | /// and when it's done with it, it returns it (possibly in a wrapper object) or another relevant object 49 | /// to the callsite via the counterpart [`oneshot::Receiver`]. 50 | pub(crate) type ReturnableItem = (T, oneshot::Sender); 51 | 52 | pub(crate) type ReturnableConnection = ReturnableItem>; 53 | 54 | pub(crate) struct ProtocolHandler(mpsc::UnboundedSender>); 55 | 56 | pub(crate) trait Protocol { 57 | fn trigger(&self, item: ReturnableItem); 58 | } 59 | 60 | impl Protocol for ProtocolHandler { 61 | fn trigger(&self, item: ReturnableItem) { 62 | // ignore errors; they can only happen if a disconnect interrupts the protocol setup process 63 | let _ = self.0.send(item); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /node/tests/common/node.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use crate::common::test_peer::sample_genesis_block; 16 | use snarkos_account::Account; 17 | use snarkos_node::{Client, Prover, Validator}; 18 | use snarkvm::prelude::{store::helpers::memory::ConsensusMemory, MainnetV0 as CurrentNetwork}; 19 | 20 | use aleo_std::StorageMode; 21 | use std::str::FromStr; 22 | 23 | pub async fn client() -> Client> { 24 | Client::new( 25 | "127.0.0.1:0".parse().unwrap(), 26 | None, 27 | 10, 28 | Account::::from_str("APrivateKey1zkp2oVPTci9kKcUprnbzMwq95Di1MQERpYBhEeqvkrDirK1").unwrap(), 29 | &[], 30 | sample_genesis_block(), 31 | None, // No CDN. 32 | StorageMode::Production, 33 | Default::default(), 34 | ) 35 | .await 36 | .expect("couldn't create client instance") 37 | } 38 | 39 | pub async fn prover() -> Prover> { 40 | Prover::new( 41 | "127.0.0.1:0".parse().unwrap(), 42 | Account::::from_str("APrivateKey1zkp2oVPTci9kKcUprnbzMwq95Di1MQERpYBhEeqvkrDirK1").unwrap(), 43 | &[], 44 | sample_genesis_block(), 45 | StorageMode::Production, 46 | Default::default(), 47 | ) 48 | .await 49 | .expect("couldn't create prover instance") 50 | } 51 | 52 | pub async fn validator() -> Validator> { 53 | Validator::new( 54 | "127.0.0.1:0".parse().unwrap(), 55 | None, 56 | None, 57 | 10, 58 | Account::::from_str("APrivateKey1zkp2oVPTci9kKcUprnbzMwq95Di1MQERpYBhEeqvkrDirK1").unwrap(), 59 | &[], 60 | &[], 61 | sample_genesis_block(), // Should load the current network's genesis block. 62 | None, // No CDN. 63 | StorageMode::Production, 64 | true, // This test requires validators to connect to peers. 65 | false, // No dev traffic in production mode. 66 | Default::default(), 67 | ) 68 | .await 69 | .expect("couldn't create validator instance") 70 | } 71 | -------------------------------------------------------------------------------- /node/bft/storage-service/src/traits.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use snarkvm::{ 16 | ledger::narwhal::{BatchHeader, Transmission, TransmissionID}, 17 | prelude::{Field, Network, Result}, 18 | }; 19 | 20 | use indexmap::IndexSet; 21 | use std::{ 22 | collections::{HashMap, HashSet}, 23 | fmt::Debug, 24 | }; 25 | 26 | pub trait StorageService: Debug + Send + Sync { 27 | /// Returns `true` if the storage contains the specified `transmission ID`. 28 | fn contains_transmission(&self, transmission_id: TransmissionID) -> bool; 29 | 30 | /// Returns the transmission for the given `transmission ID`. 31 | /// If the transmission ID does not exist in storage, `None` is returned. 32 | fn get_transmission(&self, transmission_id: TransmissionID) -> Option>; 33 | 34 | /// Returns the missing transmissions in storage from the given transmissions. 35 | fn find_missing_transmissions( 36 | &self, 37 | batch_header: &BatchHeader, 38 | transmissions: HashMap, Transmission>, 39 | aborted_transmissions: HashSet>, 40 | ) -> Result, Transmission>>; 41 | 42 | /// Inserts the given certificate ID for each of the transmission IDs, using the missing transmissions map, into storage. 43 | fn insert_transmissions( 44 | &self, 45 | certificate_id: Field, 46 | transmission_ids: IndexSet>, 47 | aborted_transmission_ids: HashSet>, 48 | missing_transmissions: HashMap, Transmission>, 49 | ); 50 | 51 | /// Removes the certificate ID for the transmissions from storage. 52 | /// 53 | /// If the transmission no longer references any certificate IDs, the entry is removed from storage. 54 | fn remove_transmissions(&self, certificate_id: &Field, transmission_ids: &IndexSet>); 55 | 56 | /// Returns a HashMap over the `(transmission ID, (transmission, certificate IDs))` entries. 57 | #[cfg(any(test, feature = "test"))] 58 | fn as_hashmap(&self) -> HashMap, (Transmission, IndexSet>)>; 59 | } 60 | -------------------------------------------------------------------------------- /cli/src/commands/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | mod account; 16 | pub use account::*; 17 | 18 | mod clean; 19 | pub use clean::*; 20 | 21 | mod developer; 22 | pub use developer::*; 23 | 24 | mod start; 25 | pub use start::*; 26 | 27 | mod update; 28 | pub use update::*; 29 | 30 | use anstyle::{AnsiColor, Color, Style}; 31 | use anyhow::Result; 32 | use clap::{builder::Styles, Parser}; 33 | 34 | const HEADER_COLOR: Option = Some(Color::Ansi(AnsiColor::Yellow)); 35 | const LITERAL_COLOR: Option = Some(Color::Ansi(AnsiColor::Green)); 36 | const STYLES: Styles = Styles::plain() 37 | .header(Style::new().bold().fg_color(HEADER_COLOR)) 38 | .usage(Style::new().bold().fg_color(HEADER_COLOR)) 39 | .literal(Style::new().bold().fg_color(LITERAL_COLOR)); 40 | 41 | #[derive(Debug, Parser)] 42 | #[clap(name = "snarkOS", author = "The Aleo Team ", styles = STYLES)] 43 | pub struct CLI { 44 | /// Specify the verbosity [options: 0, 1, 2, 3] 45 | #[clap(default_value = "2", short, long)] 46 | pub verbosity: u8, 47 | /// Specify a subcommand. 48 | #[clap(subcommand)] 49 | pub command: Command, 50 | } 51 | 52 | #[derive(Debug, Parser)] 53 | pub enum Command { 54 | #[clap(subcommand)] 55 | Account(Account), 56 | #[clap(name = "clean")] 57 | Clean(Clean), 58 | #[clap(subcommand)] 59 | Developer(Developer), 60 | #[clap(name = "start")] 61 | Start(Box), 62 | #[clap(name = "update")] 63 | Update(Update), 64 | } 65 | 66 | impl Command { 67 | /// Parses the command. 68 | pub fn parse(self) -> Result { 69 | match self { 70 | Self::Account(command) => command.parse(), 71 | Self::Clean(command) => command.parse(), 72 | Self::Developer(command) => command.parse(), 73 | Self::Start(command) => command.parse(), 74 | Self::Update(command) => command.parse(), 75 | } 76 | } 77 | } 78 | 79 | #[cfg(test)] 80 | mod tests { 81 | use super::*; 82 | 83 | // As per the official clap recommendation. 84 | #[test] 85 | fn verify_cli() { 86 | use clap::CommandFactory; 87 | CLI::command().debug_assert() 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /display/src/pages/logs.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use ratatui::{ 16 | layout::{Constraint, Direction, Layout, Rect}, 17 | widgets::{Block, Borders, Paragraph}, 18 | Frame, 19 | }; 20 | use std::collections::VecDeque; 21 | use tokio::sync::mpsc; 22 | 23 | pub(crate) struct Logs { 24 | log_receiver: mpsc::Receiver>, 25 | log_cache: VecDeque, 26 | log_limit: usize, 27 | } 28 | 29 | impl Logs { 30 | pub(crate) fn new(log_receiver: mpsc::Receiver>) -> Self { 31 | let log_limit = 128; // an arbitrary number fitting the testing terminal room 32 | 33 | Self { log_receiver, log_cache: VecDeque::with_capacity(log_limit), log_limit } 34 | } 35 | 36 | pub(crate) fn draw(&mut self, f: &mut Frame, area: Rect) { 37 | // Initialize the layout of the page. 38 | let chunks = Layout::default() 39 | .direction(Direction::Vertical) 40 | .constraints([Constraint::Percentage(100)].as_ref()) 41 | .split(area); 42 | 43 | let mut new_logs = Vec::new(); 44 | while let Ok(log) = self.log_receiver.try_recv() { 45 | new_logs.push(match String::from_utf8(log) { 46 | Ok(log) => log, 47 | _ => String::new(), 48 | }); 49 | } 50 | 51 | let all_logs = self.log_cache.len() + new_logs.len(); 52 | if all_logs > self.log_limit { 53 | let remaining_room = self.log_limit - self.log_cache.len(); 54 | let overflow = all_logs - self.log_cache.len(); 55 | 56 | if overflow > self.log_limit { 57 | self.log_cache.clear(); 58 | } else { 59 | let missing_room = all_logs - remaining_room; 60 | for _ in 0..missing_room { 61 | self.log_cache.pop_front(); 62 | } 63 | } 64 | }; 65 | 66 | self.log_cache.extend(new_logs.into_iter().take(self.log_limit)); 67 | 68 | let combined_logs = self.log_cache.iter().map(|s| s.as_str()).collect::(); 69 | 70 | let combined_logs = Paragraph::new(combined_logs).block(Block::default().borders(Borders::ALL).title("Logs")); 71 | f.render_widget(combined_logs, chunks[0]); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /node/router/messages/src/helpers/node_type.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use snarkvm::prelude::{error, FromBytes, ToBytes}; 16 | 17 | use serde::{Deserialize, Serialize}; 18 | use std::io; 19 | 20 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)] 21 | #[repr(u8)] 22 | pub enum NodeType { 23 | /// A client node is a full node, capable of syncing with the network. 24 | Client = 0, 25 | /// A prover is a light node, capable of producing proofs for consensus. 26 | Prover, 27 | /// A validator is a full node, capable of validating blocks. 28 | Validator, 29 | } 30 | 31 | impl NodeType { 32 | /// Returns a string representation of the node type. 33 | pub const fn description(&self) -> &str { 34 | match self { 35 | Self::Client => "a client node", 36 | Self::Prover => "a prover node", 37 | Self::Validator => "a validator node", 38 | } 39 | } 40 | 41 | /// Returns `true` if the node type is a client. 42 | pub const fn is_client(&self) -> bool { 43 | matches!(self, Self::Client) 44 | } 45 | 46 | /// Returns `true` if the node type is a prover. 47 | pub const fn is_prover(&self) -> bool { 48 | matches!(self, Self::Prover) 49 | } 50 | 51 | /// Returns `true` if the node type is a validator. 52 | pub const fn is_validator(&self) -> bool { 53 | matches!(self, Self::Validator) 54 | } 55 | } 56 | 57 | impl core::fmt::Display for NodeType { 58 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 59 | write!(f, "{}", match self { 60 | Self::Client => "Client", 61 | Self::Prover => "Prover", 62 | Self::Validator => "Validator", 63 | }) 64 | } 65 | } 66 | 67 | impl ToBytes for NodeType { 68 | fn write_le(&self, writer: W) -> io::Result<()> { 69 | (*self as u8).write_le(writer) 70 | } 71 | } 72 | 73 | impl FromBytes for NodeType { 74 | fn read_le(reader: R) -> io::Result { 75 | match u8::read_le(reader)? { 76 | 0 => Ok(Self::Client), 77 | 1 => Ok(Self::Prover), 78 | 2 => Ok(Self::Validator), 79 | _ => Err(error("Invalid node type")), 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /cli/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snarkos-cli" 3 | version = "2.2.7" 4 | authors = [ "The Aleo Team " ] 5 | description = "A CLI for a decentralized operating system" 6 | homepage = "https://aleo.org" 7 | repository = "https://github.com/AleoHQ/snarkOS" 8 | keywords = [ 9 | "aleo", 10 | "cryptography", 11 | "blockchain", 12 | "decentralized", 13 | "zero-knowledge" 14 | ] 15 | categories = [ "cryptography", "operating-systems" ] 16 | license = "Apache-2.0" 17 | edition = "2021" 18 | 19 | [features] 20 | default = [ "snarkos-node/metrics" ] 21 | 22 | [dependencies.aleo-std] 23 | workspace = true 24 | 25 | [dependencies.anstyle] 26 | version = "1" 27 | 28 | [dependencies.anyhow] 29 | version = "1.0.79" 30 | 31 | [dependencies.bincode] 32 | version = "1.0" 33 | 34 | [dependencies.clap] 35 | version = "4.4" 36 | features = [ "derive", "color", "unstable-styles" ] 37 | 38 | [dependencies.colored] 39 | version = "2" 40 | 41 | [dependencies.crossterm] 42 | version = "0.27" 43 | 44 | [dependencies.indexmap] 45 | version = "2.1" 46 | features = [ "serde", "rayon" ] 47 | 48 | [dependencies.metrics] 49 | package = "snarkos-node-metrics" 50 | path = "../node/metrics" 51 | version = "=2.2.7" 52 | 53 | [dependencies.num_cpus] 54 | version = "1" 55 | 56 | [dependencies.parking_lot] 57 | version = "0.12" 58 | 59 | [dependencies.rand] 60 | version = "0.8" 61 | default-features = false 62 | 63 | [dependencies.rand_chacha] 64 | version = "0.3.0" 65 | default-features = false 66 | 67 | [dependencies.rayon] 68 | version = "1" 69 | 70 | [dependencies.self_update] 71 | version = "0.39" 72 | 73 | [dependencies.serde] 74 | version = "1" 75 | 76 | [dependencies.serde_json] 77 | version = "1" 78 | features = [ "preserve_order" ] 79 | 80 | [dependencies.snarkos-account] 81 | path = "../account" 82 | version = "=2.2.7" 83 | 84 | [dependencies.snarkos-display] 85 | path = "../display" 86 | version = "=2.2.7" 87 | 88 | [dependencies.snarkos-node] 89 | path = "../node" 90 | version = "=2.2.7" 91 | 92 | [dependencies.snarkos-node-cdn] 93 | path = "../node/cdn" 94 | version = "=2.2.7" 95 | 96 | [dependencies.snarkos-node-rest] 97 | path = "../node/rest" 98 | version = "=2.2.7" 99 | 100 | [dependencies.snarkvm] 101 | workspace = true 102 | 103 | [dependencies.sys-info] 104 | version = "0.9" 105 | 106 | [dependencies.time] 107 | version = "0.3" 108 | 109 | [dependencies.thiserror] 110 | version = "1.0" 111 | 112 | [dependencies.tokio] 113 | version = "1.28" 114 | features = [ "rt" ] 115 | 116 | [dependencies.tracing] 117 | version = "0.1" 118 | 119 | [dependencies.tracing-subscriber] 120 | version = "0.3" 121 | features = [ "env-filter" ] 122 | 123 | [dependencies.ureq] 124 | version = "2.9" 125 | 126 | [dependencies.zeroize] 127 | version = "1" 128 | features = [ "derive" ] 129 | 130 | [target."cfg(target_family = \"unix\")".dependencies.nix] 131 | version = "0.26" 132 | -------------------------------------------------------------------------------- /node/metrics/README.md: -------------------------------------------------------------------------------- 1 | # snarkos-node-metrics 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/snarkos-node-metrics.svg?color=neon)](https://crates.io/crates/snarkos-node-metrics) 4 | [![Authors](https://img.shields.io/badge/authors-Aleo-orange.svg)](https://aleo.org) 5 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE.md) 6 | 7 | The `snarkos-node-metrics` crate provides access to metrics for the `snarkos` node. 8 | 9 | ## Instructions 10 | 11 | #### Quick Start 12 | 13 | To start up Grafana and Prometheus, run the following command: 14 | ```bash 15 | cd node/metrics 16 | docker-compose up --detach 17 | ``` 18 | 19 | To check that the metrics are running, go to http://localhost:9000. 20 | 21 | Lastly, go to [http://localhost:3000/](http://localhost:3000/) to see the metrics dashboard. 22 | The initial login is `admin` and the password is `admin`. 23 | 24 | #### First-Time Setup 25 | 26 | 1. **Start snarkOS with Metrics Enabled** 27 | - Launch snarkOS using the command line with the `--metrics` flag to enable metrics tracking. 28 | 29 | 2. **Navigate to Metrics Directory** 30 | - Change your current directory to `node/metrics` using the command `cd node/metrics`. 31 | 32 | 3. **Deploy Prometheus and Grafana with Docker** 33 | - Execute `docker-compose up --detach`. This command uses the `docker-compose.yml` file to set up two containers: Prometheus and Grafana, eliminating the need for direct installation. 34 | 35 | 4. **Verify Metrics Accessibility** 36 | - Use the command `curl http://localhost:9000` to check if the metrics are accessible at the specified URL. 37 | 38 | 5. **Access Grafana Dashboard** 39 | - Open your web browser and navigate to `http://localhost:3000`. This is the Grafana user interface. 40 | 41 | 6. **Grafana Login Process** 42 | - Log in using the default credentials: username `admin` and password `admin`. On first login, you'll be prompted to change the password, but you can choose to skip this step. 43 | 44 | 7. **Configure Prometheus Data Source** 45 | - In Grafana, navigate to `Datasources`. 46 | - Select `Prometheus` as the data source. 47 | - Enter `http://prometheus:9090` as the server URL. 48 | - Confirm the setup by clicking `Save and Test`. You should see a message confirming successful connection to the Prometheus API. 49 | 50 | 8. **Import snarkOS Dashboard** 51 | - Return to the Grafana home page by clicking `Home` in the top breadcrumb navigation. 52 | - Click on the arrow next to the `+` icon in the top right corner. 53 | - Select `Import dashboard`. 54 | - Drag and drop the `node/metrics/snarkOS-grafana.json` file into the top panel of the import interface. 55 | - From the dropdown box, choose the Prometheus data source you previously set up. 56 | - Finalize the process by clicking `Import`. 57 | 58 | Following these steps will successfully set up and configure a monitoring environment for your snarkOS nodes using Docker, Prometheus, and Grafana. 59 | -------------------------------------------------------------------------------- /node/bft/events/src/block_request.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use super::*; 16 | 17 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] 18 | pub struct BlockRequest { 19 | /// The starting block height (inclusive). 20 | pub start_height: u32, 21 | /// The ending block height (exclusive). 22 | pub end_height: u32, 23 | } 24 | 25 | impl BlockRequest { 26 | /// Initializes a new block request event. 27 | pub fn new(start_height: u32, end_height: u32) -> Self { 28 | Self { start_height, end_height } 29 | } 30 | } 31 | 32 | impl EventTrait for BlockRequest { 33 | /// Returns the event name. 34 | #[inline] 35 | fn name(&self) -> Cow<'static, str> { 36 | let start = self.start_height; 37 | let end = self.end_height; 38 | match start + 1 == end { 39 | true => format!("BlockRequest {start}"), 40 | false => format!("BlockRequest {start}..{end}"), 41 | } 42 | .into() 43 | } 44 | } 45 | 46 | impl ToBytes for BlockRequest { 47 | fn write_le(&self, mut writer: W) -> IoResult<()> { 48 | self.start_height.write_le(&mut writer)?; 49 | self.end_height.write_le(&mut writer) 50 | } 51 | } 52 | 53 | impl FromBytes for BlockRequest { 54 | fn read_le(mut reader: R) -> IoResult { 55 | let start_height = u32::read_le(&mut reader)?; 56 | let end_height = u32::read_le(&mut reader)?; 57 | 58 | Ok(Self::new(start_height, end_height)) 59 | } 60 | } 61 | 62 | #[cfg(test)] 63 | pub mod prop_tests { 64 | use crate::BlockRequest; 65 | 66 | use bytes::{Buf, BufMut, BytesMut}; 67 | use proptest::prelude::{any, BoxedStrategy, Strategy}; 68 | use snarkvm::utilities::{FromBytes, ToBytes}; 69 | use test_strategy::proptest; 70 | 71 | pub fn any_block_request() -> BoxedStrategy { 72 | any::<(u32, u32)>().prop_map(|(start_height, end_height)| BlockRequest::new(start_height, end_height)).boxed() 73 | } 74 | 75 | #[proptest] 76 | fn block_request_roundtrip(#[strategy(any_block_request())] block_request: BlockRequest) { 77 | let mut bytes = BytesMut::default().writer(); 78 | block_request.write_le(&mut bytes).unwrap(); 79 | let decoded = BlockRequest::read_le(&mut bytes.into_inner().reader()).unwrap(); 80 | assert_eq![decoded, block_request]; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /node/router/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snarkos-node-router" 3 | version = "2.2.7" 4 | authors = [ "The Aleo Team " ] 5 | description = "A node router for a decentralized operating system" 6 | homepage = "https://aleo.org" 7 | repository = "https://github.com/AleoHQ/snarkOS" 8 | keywords = [ 9 | "aleo", 10 | "cryptography", 11 | "blockchain", 12 | "decentralized", 13 | "zero-knowledge" 14 | ] 15 | categories = [ "cryptography", "operating-systems" ] 16 | license = "Apache-2.0" 17 | edition = "2021" 18 | 19 | [features] 20 | test = [ ] 21 | metrics = [ "dep:metrics" ] 22 | 23 | [dependencies.anyhow] 24 | version = "1.0.79" 25 | 26 | [dependencies.async-trait] 27 | version = "0.1" 28 | 29 | [dependencies.bincode] 30 | version = "1.0" 31 | 32 | [dependencies.bytes] 33 | version = "1" 34 | 35 | [dependencies.colored] 36 | version = "2" 37 | 38 | [dependencies.futures] 39 | version = "0.3.30" 40 | features = [ "thread-pool" ] 41 | 42 | [dependencies.indexmap] 43 | version = "2.1" 44 | features = [ "serde", "rayon" ] 45 | 46 | [dependencies.linked-hash-map] 47 | version = "0.5" 48 | 49 | [dependencies.metrics] 50 | package = "snarkos-node-metrics" 51 | path = "../metrics" 52 | version = "=2.2.7" 53 | optional = true 54 | 55 | [dependencies.parking_lot] 56 | version = "0.12" 57 | 58 | [dependencies.rand] 59 | version = "0.8" 60 | 61 | [dependencies.reqwest] 62 | version = "0.11" 63 | 64 | [dependencies.serde] 65 | version = "1" 66 | 67 | [dependencies.snarkos-account] 68 | path = "../../account" 69 | version = "=2.2.7" 70 | 71 | [dependencies.snarkos-node-sync-locators] 72 | path = "../sync/locators" 73 | version = "=2.2.7" 74 | 75 | [dependencies.snarkos-node-router-messages] 76 | path = "messages" 77 | version = "=2.2.7" 78 | 79 | [dependencies.snarkos-node-tcp] 80 | path = "../tcp" 81 | version = "=2.2.7" 82 | 83 | [dependencies.snarkvm] 84 | workspace = true 85 | 86 | [dependencies.time] 87 | version = "0.3" 88 | 89 | [dependencies.tokio] 90 | version = "1.28" 91 | features = [ 92 | "io-util", 93 | "macros", 94 | "net", 95 | "rt-multi-thread", 96 | "signal", 97 | "sync", 98 | "time" 99 | ] 100 | 101 | [dependencies.tokio-util] 102 | version = "0.7" 103 | features = [ "codec" ] 104 | 105 | [dependencies.tokio-stream] 106 | version = "=0.1" 107 | 108 | [dependencies.tracing] 109 | version = "0.1" 110 | 111 | [dev-dependencies.deadline] 112 | version = "0.2" 113 | 114 | [dev-dependencies.futures-util] 115 | version = "0.3" 116 | features = [ "sink" ] 117 | 118 | [dev-dependencies.peak_alloc] 119 | version = "0.2" 120 | 121 | [dev-dependencies.snarkos-node-sync] 122 | path = "../sync" 123 | features = [ "test" ] 124 | 125 | [dev-dependencies.snarkos-node-router] 126 | path = "." 127 | features = [ "test" ] 128 | 129 | [dev-dependencies.snarkos-node-router-messages] 130 | path = "messages" 131 | features = [ "test" ] 132 | 133 | [dev-dependencies.tracing-subscriber] 134 | version = "0.3" 135 | features = [ "env-filter", "fmt" ] 136 | -------------------------------------------------------------------------------- /node/router/messages/src/block_request.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use super::*; 16 | 17 | use snarkvm::prelude::{FromBytes, ToBytes}; 18 | 19 | use std::borrow::Cow; 20 | 21 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] 22 | pub struct BlockRequest { 23 | /// The starting block height (inclusive). 24 | pub start_height: u32, 25 | /// The ending block height (exclusive). 26 | pub end_height: u32, 27 | } 28 | 29 | impl MessageTrait for BlockRequest { 30 | /// Returns the message name. 31 | #[inline] 32 | fn name(&self) -> Cow<'static, str> { 33 | let start = self.start_height; 34 | let end = self.end_height; 35 | match start + 1 == end { 36 | true => format!("BlockRequest {start}"), 37 | false => format!("BlockRequest {start}..{end}"), 38 | } 39 | .into() 40 | } 41 | } 42 | 43 | impl ToBytes for BlockRequest { 44 | fn write_le(&self, mut writer: W) -> io::Result<()> { 45 | self.start_height.write_le(&mut writer)?; 46 | self.end_height.write_le(&mut writer)?; 47 | Ok(()) 48 | } 49 | } 50 | 51 | impl FromBytes for BlockRequest { 52 | fn read_le(mut reader: R) -> io::Result { 53 | let start_height = u32::read_le(&mut reader)?; 54 | let end_height = u32::read_le(&mut reader)?; 55 | Ok(Self { start_height, end_height }) 56 | } 57 | } 58 | 59 | impl Display for BlockRequest { 60 | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 61 | write!(f, "{}..{}", self.start_height, self.end_height) 62 | } 63 | } 64 | 65 | #[cfg(test)] 66 | pub mod prop_tests { 67 | use crate::BlockRequest; 68 | use snarkvm::utilities::{FromBytes, ToBytes}; 69 | 70 | use bytes::{Buf, BufMut, BytesMut}; 71 | use proptest::prelude::{any, BoxedStrategy, Strategy}; 72 | use test_strategy::proptest; 73 | 74 | pub fn any_block_request() -> BoxedStrategy { 75 | any::<(u32, u32)>().prop_map(|(start_height, end_height)| BlockRequest { start_height, end_height }).boxed() 76 | } 77 | 78 | #[proptest] 79 | fn block_request_roundtrip(#[strategy(any_block_request())] block_request: BlockRequest) { 80 | let mut bytes = BytesMut::default().writer(); 81 | block_request.write_le(&mut bytes).unwrap(); 82 | let decoded = BlockRequest::read_le(&mut bytes.into_inner().reader()).unwrap(); 83 | assert_eq![decoded, block_request]; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /node/bft/events/src/batch_signature.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use super::*; 16 | 17 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] 18 | pub struct BatchSignature { 19 | pub batch_id: Field, 20 | pub signature: Signature, 21 | } 22 | 23 | impl BatchSignature { 24 | /// Initializes a new batch signature event. 25 | pub fn new(batch_id: Field, signature: Signature) -> Self { 26 | Self { batch_id, signature } 27 | } 28 | } 29 | 30 | impl EventTrait for BatchSignature { 31 | /// Returns the event name. 32 | #[inline] 33 | fn name(&self) -> Cow<'static, str> { 34 | "BatchSignature".into() 35 | } 36 | } 37 | 38 | impl ToBytes for BatchSignature { 39 | fn write_le(&self, mut writer: W) -> IoResult<()> { 40 | self.batch_id.write_le(&mut writer)?; 41 | self.signature.write_le(&mut writer)?; 42 | Ok(()) 43 | } 44 | } 45 | 46 | impl FromBytes for BatchSignature { 47 | fn read_le(mut reader: R) -> IoResult { 48 | let batch_id = Field::read_le(&mut reader)?; 49 | let signature = Signature::read_le(&mut reader)?; 50 | 51 | Ok(Self { batch_id, signature }) 52 | } 53 | } 54 | 55 | #[cfg(test)] 56 | pub mod prop_tests { 57 | use crate::{ 58 | certificate_request::prop_tests::any_field, 59 | challenge_response::prop_tests::any_signature, 60 | BatchSignature, 61 | }; 62 | use snarkvm::console::prelude::{FromBytes, ToBytes}; 63 | 64 | use bytes::{Buf, BufMut, BytesMut}; 65 | use proptest::prelude::{BoxedStrategy, Strategy}; 66 | use test_strategy::proptest; 67 | 68 | type CurrentNetwork = snarkvm::prelude::MainnetV0; 69 | 70 | pub fn any_batch_signature() -> BoxedStrategy> { 71 | (any_field(), any_signature()) 72 | .prop_map(|(certificate_id, signature)| BatchSignature::new(certificate_id, signature)) 73 | .boxed() 74 | } 75 | 76 | #[proptest] 77 | fn serialize_deserialize(#[strategy(any_batch_signature())] original: BatchSignature) { 78 | let mut buf = BytesMut::default().writer(); 79 | BatchSignature::write_le(&original, &mut buf).unwrap(); 80 | 81 | let deserialized: BatchSignature = BatchSignature::read_le(buf.into_inner().reader()).unwrap(); 82 | assert_eq!(original, deserialized); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /node/bft/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #![forbid(unsafe_code)] 16 | #![allow(clippy::blocks_in_conditions)] 17 | #![allow(clippy::type_complexity)] 18 | 19 | #[macro_use] 20 | extern crate async_trait; 21 | #[macro_use] 22 | extern crate tracing; 23 | 24 | pub use snarkos_node_bft_events as events; 25 | pub use snarkos_node_bft_ledger_service as ledger_service; 26 | pub use snarkos_node_bft_storage_service as storage_service; 27 | 28 | pub mod helpers; 29 | 30 | mod bft; 31 | pub use bft::*; 32 | 33 | mod gateway; 34 | pub use gateway::*; 35 | 36 | mod primary; 37 | pub use primary::*; 38 | 39 | mod sync; 40 | pub use sync::*; 41 | 42 | mod worker; 43 | pub use worker::*; 44 | 45 | pub const CONTEXT: &str = "[MemoryPool]"; 46 | 47 | /// The port on which the memory pool listens for incoming connections. 48 | pub const MEMORY_POOL_PORT: u16 = 5000; // port 49 | 50 | /// The maximum number of milliseconds to wait before proposing a batch. 51 | pub const MAX_BATCH_DELAY_IN_MS: u64 = 2500; // ms 52 | /// The minimum number of seconds to wait before proposing a batch. 53 | pub const MIN_BATCH_DELAY_IN_SECS: u64 = 1; // seconds 54 | /// The maximum number of milliseconds to wait before timing out on a fetch. 55 | pub const MAX_FETCH_TIMEOUT_IN_MS: u64 = 3 * MAX_BATCH_DELAY_IN_MS; // ms 56 | /// The maximum number of seconds allowed for the leader to send their certificate. 57 | pub const MAX_LEADER_CERTIFICATE_DELAY_IN_SECS: i64 = 2 * MAX_BATCH_DELAY_IN_MS as i64 / 1000; // seconds 58 | /// The maximum number of seconds before the timestamp is considered expired. 59 | pub const MAX_TIMESTAMP_DELTA_IN_SECS: i64 = 10; // seconds 60 | /// The maximum number of workers that can be spawned. 61 | pub const MAX_WORKERS: u8 = 1; // worker(s) 62 | 63 | /// The frequency at which each primary broadcasts a ping to every other node. 64 | /// Note: If this is updated, be sure to update `MAX_BLOCKS_BEHIND` to correspond properly. 65 | pub const PRIMARY_PING_IN_MS: u64 = 2 * MAX_BATCH_DELAY_IN_MS; // ms 66 | /// The frequency at which each worker broadcasts a ping to every other node. 67 | pub const WORKER_PING_IN_MS: u64 = 4 * MAX_BATCH_DELAY_IN_MS; // ms 68 | 69 | /// A helper macro to spawn a blocking task. 70 | #[macro_export] 71 | macro_rules! spawn_blocking { 72 | ($expr:expr) => { 73 | match tokio::task::spawn_blocking(move || $expr).await { 74 | Ok(value) => value, 75 | Err(error) => Err(anyhow::anyhow!("[tokio::spawn_blocking] {error}")), 76 | } 77 | }; 78 | } 79 | -------------------------------------------------------------------------------- /node/bft/events/src/batch_certified.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use super::*; 16 | 17 | #[derive(Clone, Debug, PartialEq, Eq)] 18 | pub struct BatchCertified { 19 | pub certificate: Data>, 20 | } 21 | 22 | impl BatchCertified { 23 | /// Initializes a new batch certified event. 24 | pub fn new(certificate: Data>) -> Self { 25 | Self { certificate } 26 | } 27 | } 28 | 29 | impl From> for BatchCertified { 30 | /// Initializes a new batch certified event. 31 | fn from(certificate: BatchCertificate) -> Self { 32 | Self::new(Data::Object(certificate)) 33 | } 34 | } 35 | 36 | impl EventTrait for BatchCertified { 37 | /// Returns the event name. 38 | #[inline] 39 | fn name(&self) -> Cow<'static, str> { 40 | "BatchCertified".into() 41 | } 42 | } 43 | 44 | impl ToBytes for BatchCertified { 45 | fn write_le(&self, mut writer: W) -> IoResult<()> { 46 | self.certificate.write_le(&mut writer)?; 47 | Ok(()) 48 | } 49 | } 50 | 51 | impl FromBytes for BatchCertified { 52 | fn read_le(reader: R) -> IoResult { 53 | let certificate = Data::read_le(reader)?; 54 | 55 | Ok(Self { certificate }) 56 | } 57 | } 58 | 59 | #[cfg(test)] 60 | pub mod prop_tests { 61 | use crate::{certificate_response::prop_tests::any_batch_certificate, BatchCertified}; 62 | use snarkvm::console::prelude::{FromBytes, ToBytes}; 63 | 64 | use bytes::{Buf, BufMut, BytesMut}; 65 | use proptest::prelude::{BoxedStrategy, Strategy}; 66 | use test_strategy::proptest; 67 | 68 | type CurrentNetwork = snarkvm::prelude::MainnetV0; 69 | 70 | pub fn any_batch_certified() -> BoxedStrategy> { 71 | any_batch_certificate().prop_map(BatchCertified::from).boxed() 72 | } 73 | 74 | #[proptest] 75 | fn serialize_deserialize(#[strategy(any_batch_certified())] original: BatchCertified) { 76 | let mut buf = BytesMut::default().writer(); 77 | BatchCertified::write_le(&original, &mut buf).unwrap(); 78 | 79 | let deserialized: BatchCertified = BatchCertified::read_le(buf.into_inner().reader()).unwrap(); 80 | assert_eq!( 81 | original.certificate.deserialize_blocking().unwrap(), 82 | deserialized.certificate.deserialize_blocking().unwrap() 83 | ); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /cli/src/commands/clean.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use snarkos_node::bft::helpers::proposal_cache_path; 16 | 17 | use aleo_std::StorageMode; 18 | use anyhow::{bail, Result}; 19 | use clap::Parser; 20 | use colored::Colorize; 21 | use std::path::PathBuf; 22 | 23 | /// Cleans the snarkOS node storage. 24 | #[derive(Debug, Parser)] 25 | pub struct Clean { 26 | /// Specify the network to remove from storage. 27 | #[clap(default_value = "0", long = "network")] 28 | pub network: u16, 29 | /// Enables development mode, specify the unique ID of the local node to clean. 30 | #[clap(long)] 31 | pub dev: Option, 32 | /// Specify the path to a directory containing the ledger 33 | #[clap(long = "path")] 34 | pub path: Option, 35 | } 36 | 37 | impl Clean { 38 | /// Cleans the snarkOS node storage. 39 | pub fn parse(self) -> Result { 40 | // Remove the current proposal cache file, if it exists. 41 | let proposal_cache_path = proposal_cache_path(self.network, self.dev); 42 | if proposal_cache_path.exists() { 43 | if let Err(err) = std::fs::remove_file(&proposal_cache_path) { 44 | bail!("Failed to remove the current proposal cache file at {}: {err}", proposal_cache_path.display()); 45 | } 46 | } 47 | // Remove the specified ledger from storage. 48 | Self::remove_ledger(self.network, match self.path { 49 | Some(path) => StorageMode::Custom(path), 50 | None => StorageMode::from(self.dev), 51 | }) 52 | } 53 | 54 | /// Removes the specified ledger from storage. 55 | pub(crate) fn remove_ledger(network: u16, mode: StorageMode) -> Result { 56 | // Construct the path to the ledger in storage. 57 | let path = aleo_std::aleo_ledger_dir(network, mode); 58 | 59 | // Prepare the path string. 60 | let path_string = format!("(in \"{}\")", path.display()).dimmed(); 61 | 62 | // Check if the path to the ledger exists in storage. 63 | if path.exists() { 64 | // Remove the ledger files from storage. 65 | match std::fs::remove_dir_all(&path) { 66 | Ok(_) => Ok(format!("✅ Cleaned the snarkOS node storage {path_string}")), 67 | Err(error) => { 68 | bail!("Failed to remove the snarkOS node storage {path_string}\n{}", error.to_string().dimmed()) 69 | } 70 | } 71 | } else { 72 | Ok(format!("✅ No snarkOS node storage was found {path_string}")) 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /node/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snarkos-node" 3 | version = "2.2.7" 4 | authors = [ "The Aleo Team " ] 5 | description = "A node for a decentralized operating system" 6 | homepage = "https://aleo.org" 7 | repository = "https://github.com/AleoHQ/snarkOS" 8 | keywords = [ 9 | "aleo", 10 | "cryptography", 11 | "blockchain", 12 | "decentralized", 13 | "zero-knowledge" 14 | ] 15 | categories = [ "cryptography", "operating-systems" ] 16 | license = "Apache-2.0" 17 | edition = "2021" 18 | 19 | [features] 20 | default = [ "parallel" ] 21 | parallel = [ "rayon" ] 22 | timer = [ "aleo-std/timer" ] 23 | metrics = [ 24 | "dep:metrics", 25 | "snarkos-node-bft/metrics", 26 | "snarkos-node-consensus/metrics", 27 | "snarkos-node-router/metrics", 28 | "snarkos-node-tcp/metrics" 29 | ] 30 | 31 | [dependencies.aleo-std] 32 | workspace = true 33 | 34 | [dependencies.anyhow] 35 | version = "1.0.79" 36 | 37 | [dependencies.async-trait] 38 | version = "0.1" 39 | 40 | [dependencies.colored] 41 | version = "2" 42 | 43 | [dependencies.futures-util] 44 | version = "0.3" 45 | features = [ "sink" ] 46 | 47 | [dependencies.indexmap] 48 | version = "2.1" 49 | 50 | [dependencies.metrics] 51 | package = "snarkos-node-metrics" 52 | path = "./metrics" 53 | version = "=2.2.7" 54 | optional = true 55 | 56 | [dependencies.num_cpus] 57 | version = "1" 58 | 59 | [dependencies.once_cell] 60 | version = "1" 61 | 62 | [dependencies.parking_lot] 63 | version = "0.12" 64 | 65 | [dependencies.rand] 66 | version = "0.8" 67 | default-features = false 68 | 69 | [dependencies.rayon] 70 | version = "1" 71 | optional = true 72 | 73 | [dependencies.serde_json] 74 | version = "1" 75 | features = [ "preserve_order" ] 76 | 77 | [dependencies.snarkos-account] 78 | path = "../account" 79 | version = "=2.2.7" 80 | 81 | [dependencies.snarkos-node-bft] 82 | path = "./bft" 83 | version = "=2.2.7" 84 | 85 | [dependencies.snarkos-node-cdn] 86 | path = "./cdn" 87 | version = "=2.2.7" 88 | 89 | [dependencies.snarkos-node-consensus] 90 | path = "./consensus" 91 | version = "=2.2.7" 92 | 93 | [dependencies.snarkos-node-rest] 94 | path = "./rest" 95 | version = "=2.2.7" 96 | 97 | [dependencies.snarkos-node-router] 98 | path = "./router" 99 | version = "=2.2.7" 100 | 101 | [dependencies.snarkos-node-sync] 102 | path = "./sync" 103 | version = "=2.2.7" 104 | 105 | [dependencies.snarkos-node-tcp] 106 | path = "./tcp" 107 | version = "=2.2.7" 108 | 109 | [dependencies.snarkvm] 110 | workspace = true 111 | 112 | [dependencies.time] 113 | version = "0.3" 114 | 115 | [dependencies.tokio] 116 | version = "1.28" 117 | features = [ "rt", "signal" ] 118 | 119 | [dependencies.tokio-util] 120 | version = "0.7" 121 | 122 | [dependencies.tracing] 123 | version = "0.1" 124 | 125 | [dev-dependencies.deadline] 126 | version = "0.2" 127 | 128 | [dev-dependencies.paste] 129 | version = "1" 130 | 131 | [dev-dependencies.pea2pea] 132 | version = "0.49" 133 | 134 | [dev-dependencies.snarkos-node-router] 135 | path = "./router" 136 | features = [ "test" ] 137 | 138 | [dev-dependencies.tracing-subscriber] 139 | version = "0.3" 140 | features = [ "env-filter", "fmt" ] 141 | 142 | [dev-dependencies.rand_chacha] 143 | version = "0.3.0" 144 | -------------------------------------------------------------------------------- /node/bft/events/src/certificate_request.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use super::*; 16 | 17 | #[derive(Clone, Debug, PartialEq, Eq)] 18 | pub struct CertificateRequest { 19 | pub certificate_id: Field, 20 | } 21 | 22 | impl CertificateRequest { 23 | /// Initializes a new certificate request event. 24 | pub const fn new(certificate_id: Field) -> Self { 25 | Self { certificate_id } 26 | } 27 | } 28 | 29 | impl From> for CertificateRequest { 30 | /// Initializes a new certificate request event. 31 | fn from(certificate_id: Field) -> Self { 32 | Self::new(certificate_id) 33 | } 34 | } 35 | 36 | impl EventTrait for CertificateRequest { 37 | /// Returns the event name. 38 | #[inline] 39 | fn name(&self) -> Cow<'static, str> { 40 | "CertificateRequest".into() 41 | } 42 | } 43 | 44 | impl ToBytes for CertificateRequest { 45 | fn write_le(&self, mut writer: W) -> IoResult<()> { 46 | self.certificate_id.write_le(&mut writer)?; 47 | Ok(()) 48 | } 49 | } 50 | 51 | impl FromBytes for CertificateRequest { 52 | fn read_le(mut reader: R) -> IoResult { 53 | let certificate_id = Field::read_le(&mut reader)?; 54 | 55 | Ok(Self { certificate_id }) 56 | } 57 | } 58 | 59 | #[cfg(test)] 60 | pub mod prop_tests { 61 | use crate::CertificateRequest; 62 | use snarkvm::{ 63 | console::prelude::{FromBytes, ToBytes}, 64 | prelude::{Field, TestRng, Uniform}, 65 | }; 66 | 67 | use bytes::{Buf, BufMut, BytesMut}; 68 | use proptest::prelude::{any, BoxedStrategy, Strategy}; 69 | use test_strategy::proptest; 70 | 71 | type CurrentNetwork = snarkvm::prelude::MainnetV0; 72 | 73 | pub fn any_field() -> BoxedStrategy> { 74 | any::().prop_map(|_| Field::rand(&mut TestRng::default())).boxed() 75 | } 76 | 77 | pub fn any_certificate_request() -> BoxedStrategy> { 78 | any_field().prop_map(CertificateRequest::new).boxed() 79 | } 80 | 81 | #[proptest] 82 | fn serialize_deserialize(#[strategy(any_certificate_request())] original: CertificateRequest) { 83 | let mut buf = BytesMut::default().writer(); 84 | CertificateRequest::write_le(&original, &mut buf).unwrap(); 85 | 86 | let deserialized: CertificateRequest = 87 | CertificateRequest::read_le(buf.into_inner().reader()).unwrap(); 88 | assert_eq!(original, deserialized); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /node/bft/examples/README.md: -------------------------------------------------------------------------------- 1 | # Simple Node 2 | 3 | ## Quick Start 4 | 5 | To start 4 **BFT** nodes, run: 6 | ```bash 7 | ./start-nodes.sh bft 8 | ``` 9 | 10 | To start 4 **Narwhal** nodes, run: 11 | ```bash 12 | ./start-nodes.sh narwhal 13 | ``` 14 | 15 | (WIP - not ready) To monitor the nodes, run: 16 | ```bash 17 | cargo run --release -- example monitor 18 | ``` 19 | 20 | ## Development 21 | 22 | ``` 23 | Usage: simple_node [OPTIONS] --mode --id --num-nodes 24 | 25 | Options: 26 | --mode 27 | The mode to run the node in 28 | 29 | Possible values: 30 | - narwhal: Runs the node with the Narwhal memory pool protocol 31 | - bft: Runs the node with the Bullshark BFT protocol (on top of Narwhal) 32 | 33 | --id 34 | The ID of the node 35 | 36 | --num-nodes 37 | The number of nodes in the network 38 | 39 | --config 40 | If set, the path to the file containing the committee configuration 41 | 42 | --fire-solutions [] 43 | Enables the solution cannons, and optionally the interval in ms to run them on 44 | 45 | --fire-transactions [] 46 | Enables the transaction cannons, and optionally the interval in ms to run them on 47 | 48 | --fire-transmissions [] 49 | Enables the solution and transaction cannons, and optionally the interval in ms to run them on 50 | 51 | -h, --help 52 | Print help (see a summary with '-h') 53 | ``` 54 | 55 | To start 4 **BFT** nodes manually, run: 56 | ```bash 57 | # Terminal 1 58 | cargo run --release --example simple_node --mode bft --id 0 --num-nodes 4 --fire-transmissions 59 | # Terminal 2 60 | cargo run --release --example simple_node --mode bft --id 1 --num-nodes 4 --fire-transmissions 61 | # Terminal 3 62 | cargo run --release --example simple_node --mode bft --id 2 --num-nodes 4 --fire-transmissions 63 | # Terminal 4 64 | cargo run --release --example simple_node --mode bft --id 3 --num-nodes 4 --fire-transmissions 65 | ``` 66 | 67 | To start 4 **Narwhal** nodes manually, run: 68 | ```bash 69 | # Terminal 1 70 | cargo run --release --example simple_node --mode narwhal --id 0 --num-nodes 4 --fire-transmissions 71 | # Terminal 2 72 | cargo run --release --example simple_node --mode narwhal --id 1 --num-nodes 4 --fire-transmissions 73 | # Terminal 3 74 | cargo run --release --example simple_node --mode narwhal --id 2 --num-nodes 4 --fire-transmissions 75 | # Terminal 4 76 | cargo run --release --example simple_node --mode narwhal --id 3 --num-nodes 4 --fire-transmissions 77 | ``` 78 | 79 | These initialize 4 nodes, and tells each node that there are 4 validators in the committee. 80 | 81 | ## Advanced Usage 82 | 83 | You may optionally provide a filename as an option with `--config`. 84 | The file must contain the peer node IDs, IP addresses and ports, in the following form `id=ip:port`: 85 | ``` 86 | 0=192.168.1.1:5000 87 | 1=192.168.1.2:5001 88 | 2=192.168.1.3:5002 89 | 3=192.168.1.4:5003 90 | ``` 91 | 92 | If this parameter is not present, all nodes are run on localhost. 93 | 94 | In addition, `--fire-transmissions` will enable the transaction and solution cannons for each node. 95 | If enabled, the interval in milliseconds can optionally be passed in as an argument. 96 | -------------------------------------------------------------------------------- /cli/src/helpers/bech32m.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | pub const BECH32M_CHARSET: &str = "qpzry9x8gf2tvdw0s3jn54khce6mua7l1"; 16 | 17 | /// Check if a string is a valid bech32m character set. 18 | /// 19 | /// A bech32m character set is considered valid if it consists of the following characters: 20 | /// ```ignore 21 | /// qpzry9x8gf2tvdw0s3jn54khce6mua7l1 22 | /// ``` 23 | /// The function returns `true` if the string is a valid bech32m character set, and `false` otherwise. 24 | pub fn is_in_bech32m_charset(s: &str) -> bool { 25 | s.as_bytes().iter().all(|b| BECH32M_CHARSET.as_bytes().contains(b)) 26 | } 27 | 28 | /// Check if a given vanity string exists at the start or end of the data part of a bech32m string. 29 | /// 30 | /// The bech32m string must have the following format: 31 | /// ```ignore 32 | /// 1[] 33 | /// ``` 34 | /// where: 35 | /// 36 | /// - `` is the human-readable part of the bech32m string. 37 | /// - `1` is the separator between the HRP and the data part. 38 | /// - `` is the data part of the bech32m string. 39 | /// - `` is the vanity string to search for. This string may or may not be present at 40 | /// the start or end of the data part. 41 | /// 42 | /// The function returns `true` if the vanity string exists at the start or end of the data part, and 43 | /// `false` otherwise. 44 | pub fn has_vanity_string(s: &str, vanity: &str) -> bool { 45 | // Split the bech32m string into the HRP and data parts. 46 | let (hrp, data) = match s.split_once('1') { 47 | Some((hrp, data)) => (hrp, data), 48 | // The bech32m string is invalid. 49 | None => return false, 50 | }; 51 | // Ensure neither the HRP nor the data part are empty. 52 | if hrp.is_empty() || data.is_empty() { 53 | return false; 54 | } 55 | // Check if the vanity string exists at the start or end of the data part. 56 | data.starts_with(vanity) || data.ends_with(vanity) 57 | } 58 | 59 | #[test] 60 | fn test_is_in_bech32m_charset() { 61 | assert!(is_in_bech32m_charset("qpzry9x8gf2tvdw0s3jn54khce6mua7l1qpzry9x8gf2tvdw0s3jn54khce6mua7l1")); 62 | assert!(!is_in_bech32m_charset("qpzry9x8gf2tvdw0s3jn54khce6mua7l1qpzry9x8gf2tvdw0s3jn54khce6mua7lo")); 63 | } 64 | 65 | #[test] 66 | fn test_has_vanity_string() { 67 | assert!(has_vanity_string("myhrp1myvanitystring", "myvanitystring")); 68 | assert!(!has_vanity_string("myhrp1myvanitystring", "anotherstring")); 69 | assert!(has_vanity_string("myhrp1myvanitystring1234", "myvanitystring")); 70 | assert!(has_vanity_string("myhrp11234myvanitystring", "myvanitystring")); 71 | assert!(!has_vanity_string("myhrp1anotherstring1234", "myvanitystring")); 72 | } 73 | -------------------------------------------------------------------------------- /node/router/messages/src/peer_response.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use super::*; 16 | 17 | use snarkvm::prelude::{FromBytes, ToBytes}; 18 | 19 | use std::borrow::Cow; 20 | 21 | #[derive(Clone, Debug, PartialEq, Eq)] 22 | pub struct PeerResponse { 23 | pub peers: Vec, 24 | } 25 | 26 | impl MessageTrait for PeerResponse { 27 | /// Returns the message name. 28 | #[inline] 29 | fn name(&self) -> Cow<'static, str> { 30 | "PeerResponse".into() 31 | } 32 | } 33 | 34 | impl ToBytes for PeerResponse { 35 | fn write_le(&self, mut writer: W) -> io::Result<()> { 36 | // Return error if the number of peers exceeds the maximum. 37 | if self.peers.len() > u8::MAX as usize { 38 | return Err(io::Error::new(io::ErrorKind::InvalidInput, format!("Too many peers: {}", self.peers.len()))); 39 | } 40 | 41 | (self.peers.len() as u8).write_le(&mut writer)?; 42 | for peer in self.peers.iter() { 43 | peer.write_le(&mut writer)?; 44 | } 45 | Ok(()) 46 | } 47 | } 48 | 49 | impl FromBytes for PeerResponse { 50 | fn read_le(mut reader: R) -> io::Result { 51 | let count = u8::read_le(&mut reader)?; 52 | let mut peers = Vec::with_capacity(count as usize); 53 | for _ in 0..count { 54 | peers.push(SocketAddr::read_le(&mut reader)?); 55 | } 56 | 57 | Ok(Self { peers }) 58 | } 59 | } 60 | 61 | #[cfg(test)] 62 | pub mod prop_tests { 63 | use crate::PeerResponse; 64 | use snarkvm::utilities::{FromBytes, ToBytes}; 65 | 66 | use bytes::{Buf, BufMut, BytesMut}; 67 | use proptest::{ 68 | collection::vec, 69 | prelude::{any, BoxedStrategy, Strategy}, 70 | }; 71 | use std::net::{IpAddr, SocketAddr}; 72 | use test_strategy::proptest; 73 | 74 | pub fn any_valid_socket_addr() -> BoxedStrategy { 75 | any::<(IpAddr, u16)>().prop_map(|(ip_addr, port)| SocketAddr::new(ip_addr, port)).boxed() 76 | } 77 | 78 | pub fn any_vec() -> BoxedStrategy> { 79 | vec(any_valid_socket_addr(), 0..50).prop_map(|v| v).boxed() 80 | } 81 | 82 | pub fn any_peer_response() -> BoxedStrategy { 83 | any_vec().prop_map(|peers| PeerResponse { peers }).boxed() 84 | } 85 | 86 | #[proptest] 87 | fn peer_response_roundtrip(#[strategy(any_peer_response())] peer_response: PeerResponse) { 88 | let mut bytes = BytesMut::default().writer(); 89 | peer_response.write_le(&mut bytes).unwrap(); 90 | let decoded = PeerResponse::read_le(&mut bytes.into_inner().reader()).unwrap(); 91 | assert_eq!(decoded, peer_response); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /node/bft/events/src/worker_ping.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use super::*; 16 | 17 | #[derive(Clone, Debug, PartialEq, Eq)] 18 | pub struct WorkerPing { 19 | pub transmission_ids: IndexSet>, 20 | } 21 | 22 | impl WorkerPing { 23 | /// Initializes a new ping event. 24 | pub fn new(transmission_ids: IndexSet>) -> Self { 25 | Self { transmission_ids } 26 | } 27 | } 28 | 29 | impl From>> for WorkerPing { 30 | /// Initializes a new ping event. 31 | fn from(transmission_ids: IndexSet>) -> Self { 32 | Self::new(transmission_ids) 33 | } 34 | } 35 | 36 | impl EventTrait for WorkerPing { 37 | /// Returns the event name. 38 | #[inline] 39 | fn name(&self) -> Cow<'static, str> { 40 | "WorkerPing".into() 41 | } 42 | } 43 | 44 | impl ToBytes for WorkerPing { 45 | fn write_le(&self, mut writer: W) -> IoResult<()> { 46 | u16::try_from(self.transmission_ids.len()).map_err(error)?.write_le(&mut writer)?; 47 | for transmission_id in &self.transmission_ids { 48 | transmission_id.write_le(&mut writer)?; 49 | } 50 | Ok(()) 51 | } 52 | } 53 | 54 | impl FromBytes for WorkerPing { 55 | fn read_le(mut reader: R) -> IoResult { 56 | let num_transmissions = u16::read_le(&mut reader)?; 57 | let mut transmission_ids = IndexSet::new(); 58 | for _ in 0..num_transmissions { 59 | transmission_ids.insert(TransmissionID::read_le(&mut reader)?); 60 | } 61 | Ok(Self { transmission_ids }) 62 | } 63 | } 64 | 65 | #[cfg(test)] 66 | pub mod prop_tests { 67 | use crate::{prop_tests::any_transmission_id, WorkerPing}; 68 | use snarkvm::console::prelude::{FromBytes, ToBytes}; 69 | 70 | use bytes::{Buf, BufMut, BytesMut}; 71 | use proptest::{ 72 | collection::hash_set, 73 | prelude::{BoxedStrategy, Strategy}, 74 | }; 75 | use test_strategy::proptest; 76 | 77 | type CurrentNetwork = snarkvm::prelude::MainnetV0; 78 | 79 | pub fn any_worker_ping() -> BoxedStrategy> { 80 | hash_set(any_transmission_id(), 1..16).prop_map(|ids| WorkerPing::new(ids.into_iter().collect())).boxed() 81 | } 82 | 83 | #[proptest] 84 | fn serialize_deserialize(#[strategy(any_worker_ping())] original: WorkerPing) { 85 | let mut buf = BytesMut::default().writer(); 86 | WorkerPing::write_le(&original, &mut buf).unwrap(); 87 | 88 | let deserialized = WorkerPing::read_le(buf.into_inner().reader()).unwrap(); 89 | assert_eq!(original, deserialized); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /node/tcp/src/protocols/on_connect.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use std::net::SocketAddr; 16 | 17 | use tokio::sync::{mpsc, oneshot}; 18 | use tracing::*; 19 | 20 | use crate::{protocols::ProtocolHandler, P2P}; 21 | #[cfg(doc)] 22 | use crate::{ 23 | protocols::{Reading, Writing}, 24 | Connection, 25 | }; 26 | 27 | /// Can be used to automatically perform some initial actions once the connection with a peer is 28 | /// fully established. 29 | #[async_trait::async_trait] 30 | pub trait OnConnect: P2P 31 | where 32 | Self: Clone + Send + Sync + 'static, 33 | { 34 | /// Attaches the behavior specified in [`OnConnect::on_connect`] right after every successful 35 | /// handshake. 36 | async fn enable_on_connect(&self) { 37 | let (from_node_sender, mut from_node_receiver) = mpsc::unbounded_channel::<(SocketAddr, oneshot::Sender<()>)>(); 38 | 39 | // use a channel to know when the on_connect task is ready 40 | let (tx, rx) = oneshot::channel::<()>(); 41 | 42 | // spawn a background task dedicated to executing the desired post-handshake actions 43 | let self_clone = self.clone(); 44 | let on_connect_task = tokio::spawn(async move { 45 | trace!(parent: self_clone.tcp().span(), "spawned the OnConnect handler task"); 46 | if tx.send(()).is_err() { 47 | error!(parent: self_clone.tcp().span(), "OnConnect handler creation interrupted! shutting down the node"); 48 | self_clone.tcp().shut_down().await; 49 | return; 50 | } 51 | 52 | while let Some((addr, notifier)) = from_node_receiver.recv().await { 53 | let self_clone2 = self_clone.clone(); 54 | tokio::spawn(async move { 55 | // perform the specified initial actions 56 | self_clone2.on_connect(addr).await; 57 | // notify the node that the initial actions have concluded 58 | let _ = notifier.send(()); // can't really fail 59 | }); 60 | } 61 | }); 62 | let _ = rx.await; 63 | self.tcp().tasks.lock().push(on_connect_task); 64 | 65 | // register the OnConnect handler with the Node 66 | let hdl = Box::new(ProtocolHandler(from_node_sender)); 67 | assert!(self.tcp().protocols.on_connect.set(hdl).is_ok(), "the OnConnect protocol was enabled more than once!"); 68 | } 69 | 70 | /// Any initial actions to be executed after the handshake is concluded; in order to be able to 71 | /// communicate with the peer in the usual manner (i.e. via [`Writing`]), only its [`SocketAddr`] 72 | /// (as opposed to the related [`Connection`] object) is provided as an argument. 73 | async fn on_connect(&self, addr: SocketAddr); 74 | } 75 | -------------------------------------------------------------------------------- /node/router/messages/src/puzzle_response.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use super::*; 16 | 17 | use snarkvm::{ 18 | ledger::narwhal::Data, 19 | prelude::{FromBytes, ToBytes}, 20 | }; 21 | 22 | use std::borrow::Cow; 23 | 24 | #[derive(Clone, Debug, PartialEq, Eq)] 25 | pub struct PuzzleResponse { 26 | pub epoch_hash: N::BlockHash, 27 | pub block_header: Data>, 28 | } 29 | 30 | impl MessageTrait for PuzzleResponse { 31 | /// Returns the message name. 32 | #[inline] 33 | fn name(&self) -> Cow<'static, str> { 34 | "PuzzleResponse".into() 35 | } 36 | } 37 | 38 | impl ToBytes for PuzzleResponse { 39 | fn write_le(&self, mut writer: W) -> io::Result<()> { 40 | self.epoch_hash.write_le(&mut writer)?; 41 | self.block_header.write_le(&mut writer) 42 | } 43 | } 44 | 45 | impl FromBytes for PuzzleResponse { 46 | fn read_le(mut reader: R) -> io::Result { 47 | Ok(Self { epoch_hash: N::BlockHash::read_le(&mut reader)?, block_header: Data::read_le(reader)? }) 48 | } 49 | } 50 | 51 | #[cfg(test)] 52 | pub mod prop_tests { 53 | use crate::{challenge_response::prop_tests::any_genesis_header, PuzzleResponse}; 54 | use snarkvm::{ 55 | console::prelude::{FromBytes, ToBytes}, 56 | ledger::narwhal::Data, 57 | prelude::{Network, Rng, TestRng}, 58 | }; 59 | 60 | use bytes::{Buf, BufMut, BytesMut}; 61 | use proptest::prelude::{any, BoxedStrategy, Strategy}; 62 | use test_strategy::proptest; 63 | 64 | type CurrentNetwork = snarkvm::prelude::MainnetV0; 65 | 66 | pub fn any_epoch_hash() -> BoxedStrategy<::BlockHash> { 67 | any::() 68 | .prop_map(|seed| { 69 | let mut rng = TestRng::fixed(seed); 70 | rng.gen() 71 | }) 72 | .boxed() 73 | } 74 | 75 | pub fn any_puzzle_response() -> BoxedStrategy> { 76 | (any_epoch_hash(), any_genesis_header()) 77 | .prop_map(|(epoch_hash, bh)| PuzzleResponse { epoch_hash, block_header: Data::Object(bh) }) 78 | .boxed() 79 | } 80 | 81 | #[proptest] 82 | fn puzzle_response_roundtrip(#[strategy(any_puzzle_response())] original: PuzzleResponse) { 83 | let mut buf = BytesMut::default().writer(); 84 | PuzzleResponse::write_le(&original, &mut buf).unwrap(); 85 | 86 | let deserialized: PuzzleResponse = PuzzleResponse::read_le(buf.into_inner().reader()).unwrap(); 87 | assert_eq!(original.epoch_hash, deserialized.epoch_hash); 88 | assert_eq!( 89 | original.block_header.deserialize_blocking().unwrap(), 90 | deserialized.block_header.deserialize_blocking().unwrap(), 91 | ); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /node/tcp/src/protocols/disconnect.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use std::net::SocketAddr; 16 | 17 | use tokio::sync::{mpsc, oneshot}; 18 | use tracing::*; 19 | 20 | use crate::{protocols::ProtocolHandler, P2P}; 21 | #[cfg(doc)] 22 | use crate::{protocols::Writing, Connection}; 23 | 24 | /// Can be used to automatically perform some extra actions when the node disconnects from its 25 | /// peer, which is especially practical if the disconnect is triggered automatically, e.g. due 26 | /// to the peer exceeding the allowed number of failures or severing its connection with the node 27 | /// on its own. 28 | #[async_trait::async_trait] 29 | pub trait Disconnect: P2P 30 | where 31 | Self: Clone + Send + Sync + 'static, 32 | { 33 | /// Attaches the behavior specified in [`Disconnect::handle_disconnect`] to every occurrence of the 34 | /// node disconnecting from a peer. 35 | async fn enable_disconnect(&self) { 36 | let (from_node_sender, mut from_node_receiver) = mpsc::unbounded_channel::<(SocketAddr, oneshot::Sender<()>)>(); 37 | 38 | // use a channel to know when the disconnect task is ready 39 | let (tx, rx) = oneshot::channel::<()>(); 40 | 41 | // spawn a background task dedicated to handling disconnect events 42 | let self_clone = self.clone(); 43 | let disconnect_task = tokio::spawn(async move { 44 | trace!(parent: self_clone.tcp().span(), "spawned the Disconnect handler task"); 45 | tx.send(()).unwrap(); // safe; the channel was just opened 46 | 47 | while let Some((peer_addr, notifier)) = from_node_receiver.recv().await { 48 | let self_clone2 = self_clone.clone(); 49 | tokio::spawn(async move { 50 | // perform the specified extra actions 51 | self_clone2.handle_disconnect(peer_addr).await; 52 | // notify the node that the extra actions have concluded 53 | // and that the related connection can be dropped 54 | let _ = notifier.send(()); // can't really fail 55 | }); 56 | } 57 | }); 58 | let _ = rx.await; 59 | self.tcp().tasks.lock().push(disconnect_task); 60 | 61 | // register the Disconnect handler with the Tcp 62 | let hdl = Box::new(ProtocolHandler(from_node_sender)); 63 | assert!( 64 | self.tcp().protocols.disconnect.set(hdl).is_ok(), 65 | "the Disconnect protocol was enabled more than once!" 66 | ); 67 | } 68 | 69 | /// Any extra actions to be executed during a disconnect; in order to still be able to 70 | /// communicate with the peer in the usual manner (i.e. via [`Writing`]), only its [`SocketAddr`] 71 | /// (as opposed to the related [`Connection`] object) is provided as an argument. 72 | async fn handle_disconnect(&self, peer_addr: SocketAddr); 73 | } 74 | -------------------------------------------------------------------------------- /node/bft/events/src/challenge_response.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use super::*; 16 | 17 | #[derive(Clone, Debug, PartialEq, Eq)] 18 | pub struct ChallengeResponse { 19 | pub signature: Data>, 20 | pub nonce: u64, 21 | } 22 | 23 | impl EventTrait for ChallengeResponse { 24 | /// Returns the event name. 25 | #[inline] 26 | fn name(&self) -> Cow<'static, str> { 27 | "ChallengeResponse".into() 28 | } 29 | } 30 | 31 | impl ToBytes for ChallengeResponse { 32 | fn write_le(&self, mut writer: W) -> IoResult<()> { 33 | self.signature.write_le(&mut writer)?; 34 | self.nonce.write_le(&mut writer)?; 35 | Ok(()) 36 | } 37 | } 38 | 39 | impl FromBytes for ChallengeResponse { 40 | fn read_le(mut reader: R) -> IoResult { 41 | let signature = Data::read_le(&mut reader)?; 42 | let nonce = u64::read_le(&mut reader)?; 43 | 44 | Ok(Self { signature, nonce }) 45 | } 46 | } 47 | 48 | #[cfg(test)] 49 | pub mod prop_tests { 50 | use crate::ChallengeResponse; 51 | use snarkvm::{ 52 | console::prelude::{FromBytes, ToBytes}, 53 | ledger::narwhal::Data, 54 | prelude::{PrivateKey, Signature}, 55 | utilities::rand::{TestRng, Uniform}, 56 | }; 57 | 58 | use bytes::{Buf, BufMut, BytesMut}; 59 | use proptest::prelude::{any, BoxedStrategy, Strategy}; 60 | use test_strategy::proptest; 61 | 62 | type CurrentNetwork = snarkvm::prelude::MainnetV0; 63 | 64 | pub fn any_signature() -> BoxedStrategy> { 65 | (0..64) 66 | .prop_map(|message_size| { 67 | let rng = &mut TestRng::default(); 68 | let message: Vec<_> = (0..message_size).map(|_| Uniform::rand(rng)).collect(); 69 | let private_key = PrivateKey::new(rng).unwrap(); 70 | Signature::sign(&private_key, &message, rng).unwrap() 71 | }) 72 | .boxed() 73 | } 74 | 75 | pub fn any_challenge_response() -> BoxedStrategy> { 76 | (any_signature(), any::()) 77 | .prop_map(|(sig, nonce)| ChallengeResponse { signature: Data::Object(sig), nonce }) 78 | .boxed() 79 | } 80 | 81 | #[proptest] 82 | fn serialize_deserialize(#[strategy(any_challenge_response())] original: ChallengeResponse) { 83 | let mut buf = BytesMut::default().writer(); 84 | ChallengeResponse::write_le(&original, &mut buf).unwrap(); 85 | 86 | let deserialized: ChallengeResponse = 87 | ChallengeResponse::read_le(buf.into_inner().reader()).unwrap(); 88 | assert_eq!( 89 | original.signature.deserialize_blocking().unwrap(), 90 | deserialized.signature.deserialize_blocking().unwrap() 91 | ); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /node/router/tests/cleanups.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | mod common; 16 | use common::*; 17 | 18 | use deadline::deadline; 19 | use peak_alloc::PeakAlloc; 20 | use snarkos_node_router::Routing; 21 | use snarkos_node_tcp::{ 22 | protocols::{Disconnect, Handshake}, 23 | P2P, 24 | }; 25 | use snarkvm::{prelude::Rng, utilities::TestRng}; 26 | 27 | use core::time::Duration; 28 | 29 | #[global_allocator] 30 | static PEAK_ALLOC: PeakAlloc = PeakAlloc; 31 | 32 | #[tokio::test] 33 | async fn test_connection_cleanups() { 34 | // The number of connections to start and close. 35 | const NUM_CONNECTIONS: usize = 10; 36 | 37 | // Initialize an Rng. 38 | let mut rng = TestRng::default(); 39 | 40 | // Create 2 routers of random types. 41 | let mut nodes = Vec::with_capacity(2); 42 | for _ in 0..2 { 43 | let node = match rng.gen_range(0..3) % 3 { 44 | 0 => client(0, 1).await, 45 | 1 => prover(0, 1).await, 46 | 2 => validator(0, 1, &[], true).await, 47 | _ => unreachable!(), 48 | }; 49 | 50 | nodes.push(node); 51 | } 52 | 53 | // Enable handshake handling. 54 | nodes[0].enable_handshake().await; 55 | nodes[1].enable_handshake().await; 56 | 57 | nodes[0].enable_disconnect().await; 58 | nodes[1].enable_disconnect().await; 59 | 60 | nodes[0].enable_listener().await; 61 | nodes[1].enable_listener().await; 62 | 63 | // We'll want to register heap use after a single connection, after the related collections are initialized. 64 | let mut heap_after_one_conn = None; 65 | 66 | // Connect and disconnect in a loop. 67 | for i in 0..NUM_CONNECTIONS { 68 | // Connect one of the nodes to the other one. 69 | nodes[1].connect(nodes[0].local_ip()); 70 | 71 | // Wait until the connection is complete. 72 | let tcp0 = nodes[0].tcp().clone(); 73 | let tcp1 = nodes[1].tcp().clone(); 74 | deadline!(Duration::from_secs(3), move || tcp0.num_connected() == 1 && tcp1.num_connected() == 1); 75 | 76 | // Since the connectee doesn't read from the connector, it can't tell that the connector disconnected 77 | // from it, so it needs to disconnect from it manually. 78 | nodes[0].disconnect(nodes[1].local_ip()); 79 | nodes[1].disconnect(nodes[0].local_ip()); 80 | 81 | // Wait until the disconnect is complete. 82 | let tcp0 = nodes[0].tcp().clone(); 83 | let tcp1 = nodes[1].tcp().clone(); 84 | deadline!(Duration::from_secs(3), move || tcp0.num_connected() == 0 && tcp1.num_connected() == 0); 85 | 86 | // Register heap use after a single connection. 87 | if i == 0 { 88 | heap_after_one_conn = Some(PEAK_ALLOC.current_usage()); 89 | } 90 | } 91 | 92 | // Register final heap use. 93 | let heap_after_loop = PEAK_ALLOC.current_usage(); 94 | 95 | // Final heap use should equal that after the first connection. 96 | assert_eq!(heap_after_one_conn.unwrap(), heap_after_loop); 97 | } 98 | -------------------------------------------------------------------------------- /node/bft/events/src/transmission_request.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use super::*; 16 | 17 | #[derive(Clone, Debug, PartialEq, Eq)] 18 | pub struct TransmissionRequest { 19 | pub transmission_id: TransmissionID, 20 | } 21 | 22 | impl TransmissionRequest { 23 | /// Initializes a new transmission request event. 24 | pub const fn new(transmission_id: TransmissionID) -> Self { 25 | Self { transmission_id } 26 | } 27 | } 28 | 29 | impl From> for TransmissionRequest { 30 | /// Initializes a new transmission request event. 31 | fn from(transmission_id: TransmissionID) -> Self { 32 | Self::new(transmission_id) 33 | } 34 | } 35 | 36 | impl EventTrait for TransmissionRequest { 37 | /// Returns the event name. 38 | #[inline] 39 | fn name(&self) -> Cow<'static, str> { 40 | "TransmissionRequest".into() 41 | } 42 | } 43 | 44 | impl ToBytes for TransmissionRequest { 45 | fn write_le(&self, mut writer: W) -> IoResult<()> { 46 | self.transmission_id.write_le(&mut writer)?; 47 | Ok(()) 48 | } 49 | } 50 | 51 | impl FromBytes for TransmissionRequest { 52 | fn read_le(mut reader: R) -> IoResult { 53 | let transmission_id = TransmissionID::read_le(&mut reader)?; 54 | 55 | Ok(Self { transmission_id }) 56 | } 57 | } 58 | 59 | #[cfg(test)] 60 | pub mod prop_tests { 61 | use crate::{ 62 | prop_tests::{any_solution_id, any_transaction_id}, 63 | TransmissionRequest, 64 | }; 65 | use snarkvm::{ 66 | console::prelude::{FromBytes, ToBytes}, 67 | ledger::narwhal::TransmissionID, 68 | }; 69 | 70 | use bytes::{Buf, BufMut, BytesMut}; 71 | use proptest::{ 72 | prelude::{BoxedStrategy, Strategy}, 73 | prop_oneof, 74 | }; 75 | use test_strategy::proptest; 76 | 77 | type CurrentNetwork = snarkvm::prelude::MainnetV0; 78 | 79 | fn any_transmission_id() -> BoxedStrategy> { 80 | prop_oneof![ 81 | any_solution_id().prop_map(TransmissionID::Solution), 82 | any_transaction_id().prop_map(TransmissionID::Transaction), 83 | ] 84 | .boxed() 85 | } 86 | 87 | pub fn any_transmission_request() -> BoxedStrategy> { 88 | any_transmission_id().prop_map(TransmissionRequest::new).boxed() 89 | } 90 | 91 | #[proptest] 92 | fn serialize_deserialize(#[strategy(any_transmission_request())] original: TransmissionRequest) { 93 | let mut buf = BytesMut::default().writer(); 94 | TransmissionRequest::write_le(&original, &mut buf).unwrap(); 95 | 96 | let deserialized = TransmissionRequest::read_le(buf.into_inner().reader()).unwrap(); 97 | assert_eq!(original, deserialized); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snarkos" 3 | version = "2.2.7" 4 | authors = [ "The Aleo Team " ] 5 | description = "A decentralized operating system" 6 | homepage = "https://aleo.org" 7 | repository = "https://github.com/AleoHQ/snarkOS" 8 | keywords = [ 9 | "aleo", 10 | "cryptography", 11 | "blockchain", 12 | "decentralized", 13 | "zero-knowledge" 14 | ] 15 | categories = [ "cryptography", "operating-systems" ] 16 | license = "Apache-2.0" 17 | edition = "2021" 18 | rust-version = "1.76.0" # Attention - Change the MSRV in rust-toolchain and in .circleci/config.yml as well 19 | 20 | [workspace] 21 | members = [ 22 | "account", 23 | "cli", 24 | "display", 25 | "node", 26 | "node/bft", 27 | "node/bft/events", 28 | "node/bft/ledger-service", 29 | "node/bft/storage-service", 30 | "node/cdn", 31 | "node/consensus", 32 | "node/metrics", 33 | "node/rest", 34 | "node/router", 35 | "node/router/messages", 36 | "node/sync", 37 | "node/sync/communication-service", 38 | "node/sync/locators", 39 | "node/tcp", 40 | ".integration" 41 | ] 42 | 43 | [workspace.dependencies.aleo-std] 44 | version = "=0.1.24" 45 | default-features = false 46 | 47 | [workspace.dependencies.snarkvm] 48 | git = "https://github.com/AleoHQ/snarkVM.git" 49 | rev = "3ebe60c" 50 | #version = "=0.16.18" 51 | features = [ "circuit", "console", "rocks" ] 52 | 53 | [[bin]] 54 | name = "snarkos" 55 | path = "snarkos/main.rs" 56 | 57 | [features] 58 | metrics = [ "snarkos-node-metrics", "snarkos-node/metrics" ] 59 | 60 | [dependencies.anyhow] 61 | version = "1.0.79" 62 | 63 | [dependencies.clap] 64 | version = "4.4" 65 | features = [ "derive" ] 66 | 67 | [dependencies.crossterm] 68 | version = "0.27.0" 69 | 70 | [dependencies.once_cell] 71 | version = "1" 72 | 73 | [dependencies.snarkos-account] 74 | path = "./account" 75 | version = "=2.2.7" 76 | 77 | [dependencies.snarkos-cli] 78 | path = "./cli" 79 | version = "=2.2.7" 80 | 81 | [dependencies.snarkos-display] 82 | path = "./display" 83 | version = "=2.2.7" 84 | 85 | [dependencies.snarkos-node] 86 | path = "./node" 87 | version = "=2.2.7" 88 | 89 | [dependencies.snarkos-node-bft] 90 | path = "./node/bft" 91 | version = "=2.2.7" 92 | 93 | [dependencies.snarkos-node-cdn] 94 | path = "./node/cdn" 95 | version = "=2.2.7" 96 | 97 | [dependencies.snarkos-node-consensus] 98 | path = "./node/consensus" 99 | version = "=2.2.7" 100 | 101 | [dependencies.snarkos-node-metrics] 102 | path = "./node/metrics" 103 | version = "=2.2.7" 104 | optional = true 105 | 106 | [dependencies.snarkos-node-rest] 107 | path = "./node/rest" 108 | version = "=2.2.7" 109 | 110 | [dependencies.snarkos-node-router] 111 | path = "./node/router" 112 | version = "=2.2.7" 113 | 114 | [dependencies.snarkos-node-sync] 115 | path = "./node/sync" 116 | version = "=2.2.7" 117 | 118 | [dependencies.snarkos-node-tcp] 119 | path = "./node/tcp" 120 | version = "=2.2.7" 121 | 122 | [target.'cfg(all(target_os = "linux", target_arch = "x86_64"))'.dependencies] 123 | tikv-jemallocator = "0.5" 124 | 125 | [dev-dependencies.rusty-hook] 126 | version = "0.11.2" 127 | 128 | [build-dependencies.walkdir] 129 | version = "2" 130 | 131 | [profile.release] 132 | opt-level = 3 133 | lto = "thin" 134 | incremental = true 135 | 136 | [profile.bench] 137 | opt-level = 3 138 | debug = false 139 | rpath = false 140 | lto = "thin" 141 | incremental = true 142 | debug-assertions = false 143 | 144 | [profile.dev] 145 | opt-level = 2 146 | lto = "thin" 147 | incremental = true 148 | 149 | [profile.test] 150 | opt-level = 2 151 | lto = "thin" 152 | incremental = true 153 | debug = true 154 | debug-assertions = true 155 | -------------------------------------------------------------------------------- /node/tests/peering.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #[allow(dead_code)] 16 | mod common; 17 | use common::test_peer::TestPeer; 18 | 19 | use snarkos_node_router::{ 20 | messages::{Message, PeerResponse}, 21 | Outbound, 22 | }; 23 | use snarkos_node_tcp::P2P; 24 | 25 | use deadline::deadline; 26 | use paste::paste; 27 | use pea2pea::{protocols::Writing, Pea2Pea}; 28 | use std::time::Duration; 29 | 30 | macro_rules! test_reject_unsolicited_peer_response { 31 | ($($node_type:ident),*) => { 32 | $( 33 | paste! { 34 | #[tokio::test] 35 | async fn [<$node_type _rejects_unsolicited_peer_response>]() { 36 | // Spin up a full node. 37 | let node = $crate::common::node::$node_type().await; 38 | 39 | // Spin up a test peer (synthetic node), it doesn't really matter what type it is. 40 | let peer = TestPeer::validator().await; 41 | let peer_addr = peer.node().listening_addr().unwrap(); 42 | 43 | // Connect the node to the test peer. 44 | node.router().connect(peer_addr).unwrap().await.unwrap(); 45 | 46 | // Check the peer counts. 47 | let node_clone = node.clone(); 48 | deadline!(Duration::from_secs(5), move || node_clone.router().number_of_connected_peers() == 1); 49 | let node_clone = node.clone(); 50 | deadline!(Duration::from_secs(5), move || node_clone.tcp().num_connected() == 1); 51 | let peer_clone = peer.clone(); 52 | deadline!(Duration::from_secs(5), move || peer_clone.node().num_connected() == 1); 53 | 54 | // Check the candidate peers. 55 | assert_eq!(node.router().number_of_candidate_peers(), 0); 56 | 57 | let peers = vec!["1.1.1.1:1111".parse().unwrap(), "2.2.2.2:2222".parse().unwrap()]; 58 | 59 | // Send a `PeerResponse` to the node. 60 | assert!( 61 | peer.unicast( 62 | *peer.node().connected_addrs().first().unwrap(), 63 | Message::PeerResponse(PeerResponse { peers: peers.clone() }) 64 | ) 65 | .is_ok() 66 | ); 67 | 68 | // Wait for the peer to be disconnected for a protocol violation. 69 | let node_clone = node.clone(); 70 | deadline!(Duration::from_secs(5), move || node_clone.router().number_of_connected_peers() == 0); 71 | 72 | // Make sure the sent addresses weren't inserted in the candidate peers. 73 | for peer in peers { 74 | assert!(!node.router().candidate_peers().contains(&peer)); 75 | } 76 | } 77 | } 78 | )* 79 | }; 80 | } 81 | 82 | test_reject_unsolicited_peer_response!(client, prover, validator); 83 | -------------------------------------------------------------------------------- /node/bft/events/src/batch_propose.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2023 Aleo Systems Inc. 2 | // This file is part of the snarkOS library. 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at: 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use super::*; 16 | 17 | #[derive(Clone, Debug, PartialEq, Eq)] 18 | pub struct BatchPropose { 19 | pub round: u64, 20 | pub batch_header: Data>, 21 | } 22 | 23 | impl BatchPropose { 24 | /// Initializes a new batch propose event. 25 | pub fn new(round: u64, batch_header: Data>) -> Self { 26 | Self { round, batch_header } 27 | } 28 | } 29 | 30 | impl From> for BatchPropose { 31 | /// Initializes a new batch propose event. 32 | fn from(batch_header: BatchHeader) -> Self { 33 | Self::new(batch_header.round(), Data::Object(batch_header)) 34 | } 35 | } 36 | 37 | impl EventTrait for BatchPropose { 38 | /// Returns the event name. 39 | #[inline] 40 | fn name(&self) -> Cow<'static, str> { 41 | "BatchPropose".into() 42 | } 43 | } 44 | 45 | impl ToBytes for BatchPropose { 46 | fn write_le(&self, mut writer: W) -> IoResult<()> { 47 | self.round.write_le(&mut writer)?; 48 | self.batch_header.write_le(&mut writer)?; 49 | Ok(()) 50 | } 51 | } 52 | 53 | impl FromBytes for BatchPropose { 54 | fn read_le(mut reader: R) -> IoResult { 55 | let round = u64::read_le(&mut reader)?; 56 | let batch_header = Data::read_le(&mut reader)?; 57 | 58 | Ok(Self { round, batch_header }) 59 | } 60 | } 61 | 62 | #[cfg(test)] 63 | pub mod prop_tests { 64 | use crate::{certificate_response::prop_tests::any_batch_header, BatchPropose}; 65 | use snarkvm::{ 66 | console::prelude::{FromBytes, ToBytes}, 67 | ledger::committee::prop_tests::CommitteeContext, 68 | prelude::narwhal::Data, 69 | }; 70 | 71 | use bytes::{Buf, BufMut, BytesMut}; 72 | use proptest::prelude::{any, BoxedStrategy, Strategy}; 73 | use test_strategy::proptest; 74 | 75 | type CurrentNetwork = snarkvm::prelude::MainnetV0; 76 | 77 | pub fn any_batch_propose() -> BoxedStrategy> { 78 | any::() 79 | .prop_flat_map(|committee| (any::(), any_batch_header(&committee))) 80 | .prop_map(|(round, batch_header)| BatchPropose::new(round, Data::Object(batch_header))) 81 | .boxed() 82 | } 83 | 84 | #[proptest] 85 | fn serialize_deserialize(#[strategy(any_batch_propose())] original: BatchPropose) { 86 | let mut buf = BytesMut::default().writer(); 87 | BatchPropose::write_le(&original, &mut buf).unwrap(); 88 | 89 | let deserialized: BatchPropose = BatchPropose::read_le(buf.into_inner().reader()).unwrap(); 90 | // because of the Data enum, we cannot compare the structs directly even though it derives PartialEq 91 | assert_eq!(original.round, deserialized.round); 92 | assert_eq!( 93 | original.batch_header.deserialize_blocking().unwrap(), 94 | deserialized.batch_header.deserialize_blocking().unwrap() 95 | ); 96 | } 97 | } 98 | --------------------------------------------------------------------------------