Skip to content

Commit

Permalink
Feature listing and code gating (#5147)
Browse files Browse the repository at this point in the history
Description
---
This PR is for reflective purposes regarding feature gating at compile time. See #5135 for more info. This PR as it stands is to be used as an example of a network _type_ based feature gate at compile time.
It allows setting an ENVVAR for the network with conditional compilation for features. The feature sets can be imported across any crate in the project easily and then used with the `#[cfg(tari_feature_...)]` attribute macro.

I played with a few styles of gating code. In the case of burning, and validator registration what I found was it became easier to focus on the entry and exit points of the code. These functions don't have much outside effect other than their distinct purpose so preventing someone from calling them is good enough conditional compilation. It's easier than trying to remove every aspect of their existence throughout. This wouldn't always be the case though- with a feature that changes an existing feature the style of code writing has the potential to change heavily with possible duplication of entire enums or structs. It could be useful to have more examples to help guide people with, but also is something we'll probably see patterns for emerge naturally. The nice part is we have the flexibility to support different needs.

There was a desire to use the network based feature gating to prevent a "mainnet" compiled bin from compiling with testnet configuration at all. To remove conensus constants, or even the knowledge of the testnets. This proved more difficult with the current code base and would require a lot of refactoring. I've made another PR with a branch I consider broken demonstrating the minimal amount of changes needed to perform this kind of task and it doesn't seem to bring us a major benefit for the time being.

---------

Co-authored-by: Cayle Sharrock <CjS77@users.noreply.github.com>
  • Loading branch information
brianp and CjS77 committed Apr 4, 2023
1 parent 44efd6c commit 1311a0d
Show file tree
Hide file tree
Showing 12 changed files with 334 additions and 14 deletions.
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion applications/tari_base_node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,5 @@ metrics = ["tari_metrics", "tari_comms/metrics"]
safe = []
libtor = ["tari_libtor"]


[build-dependencies]
tari_features = { version = "0.0.1", path = "../../common/tari_features"}
8 changes: 7 additions & 1 deletion applications/tari_base_node/build.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
// Copyright 2022 The Tari Project
// SPDX-License-Identifier: BSD-3-Clause

use tari_features::resolver::build_features;

#[cfg(windows)]
fn main() {
build_features();
use std::env;
println!("cargo:rerun-if-changed=icon.res");
let mut path = env::current_dir().unwrap();
Expand All @@ -11,4 +14,7 @@ fn main() {
}

#[cfg(not(windows))]
fn main() {}
pub fn main() {
build_features();
// Build as usual
}
22 changes: 13 additions & 9 deletions applications/tari_console_wallet/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,22 @@ edition = "2018"
license = "BSD-3-Clause"

[dependencies]
tari_wallet = { path = "../../base_layer/wallet", features = ["bundled_sqlite"] }
tari_crypto = { version = "0.16.11"}
tari_common = { path = "../../common" }
tari_app_grpc = { path = "../tari_app_grpc" }
tari_app_utilities = { path = "../tari_app_utilities" }
tari_common = { path = "../../common" }
tari_common_types = { path = "../../base_layer/common_types" }
tari_comms = { path = "../../comms/core" }
tari_comms_dht = { path = "../../comms/dht" }
tari_common_types = { path = "../../base_layer/common_types" }
tari_contacts = { path = "../../base_layer/contacts" }
tari_crypto = { version = "0.16.11"}
tari_features = { version = "0.0.1", path = "../../common/tari_features"}
tari_key_manager = { path = "../../base_layer/key_manager" }
tari_libtor = { path = "../../infrastructure/libtor", optional = true }
tari_p2p = { path = "../../base_layer/p2p", features = ["auto-update"] }
tari_app_grpc = { path = "../tari_app_grpc" }
tari_script = { path = "../../infrastructure/tari_script" }
tari_shutdown = { path = "../../infrastructure/shutdown" }
tari_key_manager = { path = "../../base_layer/key_manager" }
tari_utilities = "0.4.10"
tari_script = { path = "../../infrastructure/tari_script" }
tari_contacts = { path = "../../base_layer/contacts" }
tari_wallet = { path = "../../base_layer/wallet", features = ["bundled_sqlite"] }

# Uncomment for tokio tracing via tokio-console (needs "tracing" featurs)
#console-subscriber = "0.1.3"
Expand Down Expand Up @@ -63,9 +64,12 @@ version = "^0.16"
default-features = false
features = ["crossterm"]

[build-dependencies]
tari_features = { version = "0.0.1", path = "../../common/tari_features"}

[features]
avx2 = ["tari_core/avx2", "tari_crypto/simd_backend", "tari_wallet/avx2", "tari_comms/avx2", "tari_comms_dht/avx2", "tari_p2p/avx2", "tari_key_manager/avx2"]
libtor = ["tari_libtor"]

[package.metadata.cargo-machete]
ignored = ["strum"]
ignored = ["strum"]
8 changes: 7 additions & 1 deletion applications/tari_console_wallet/build.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
// Copyright 2022 The Tari Project
// SPDX-License-Identifier: BSD-3-Clause

use tari_features::resolver::build_features;

#[cfg(windows)]
fn main() {
build_features();
use std::env;
println!("cargo:rerun-if-changed=icon.res");
let mut path = env::current_dir().unwrap();
Expand All @@ -11,4 +14,7 @@ fn main() {
}

#[cfg(not(windows))]
fn main() {}
pub fn main() {
build_features();
// Build as usual
}
3 changes: 2 additions & 1 deletion applications/tari_merge_mining_proxy/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,5 @@ tonic = "0.6.2"
tracing = "0.1"
url = "2.1.1"

[dev-dependencies]
[build-dependencies]
tari_features = { version = "0.0.1", path = "../../common/tari_features"}
8 changes: 7 additions & 1 deletion applications/tari_merge_mining_proxy/build.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
// Copyright 2022 The Tari Project
// SPDX-License-Identifier: BSD-3-Clause

use tari_features::resolver::build_features;

#[cfg(windows)]
fn main() {
build_features();
use std::env;
println!("cargo:rerun-if-changed=icon.res");
let mut path = env::current_dir().unwrap();
Expand All @@ -11,4 +14,7 @@ fn main() {
}

#[cfg(not(windows))]
fn main() {}
pub fn main() {
build_features();
// Build as usual
}
15 changes: 15 additions & 0 deletions common/tari_features/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "tari_features"
description = "Compilable features for Tari applications"
authors = ["The Tari Development Community"]
repository = "https://github.com/tari-project/tari"
homepage = "https://tari.com"
readme = "README.md"
license = "BSD-3-Clause"
version = "0.0.1"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
tari_common = { path = "../../common" }
87 changes: 87 additions & 0 deletions common/tari_features/src/feature.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright 2023. The Tari Project
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
// following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
// disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
// following disclaimer in the documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
// products derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use std::fmt::{Display, Formatter};

use super::Status;

pub struct Feature {
name: &'static str,
description: &'static str,
tracking_issue: Option<usize>,
status: Status,
}

impl Feature {
pub const fn new(
name: &'static str,
description: &'static str,
tracking_issue: Option<usize>,
status: Status,
) -> Self {
Feature {
name,
description,
tracking_issue,
status,
}
}

pub fn issue_url(&self) -> String {
match self.tracking_issue {
Some(n) => format!("https://github.com/tari-project/tari/issues/{}", n),
None => "None".into(),
}
}

pub fn attr_name(&self) -> String {
format!("tari_feature_{}", self.name)
}

pub fn is_active_in_testnet(&self) -> bool {
matches!(self.status, Status::New | Status::Testing)
}

pub fn is_active_in_nextnet(&self) -> bool {
matches!(self.status, Status::Testing)
}

pub fn is_active(&self) -> bool {
matches!(self.status, Status::Active)
}

pub fn was_removed(&self) -> bool {
matches!(self.status, Status::Removed)
}
}

impl Display for Feature {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}. {}. Tracking issue: {}",
self.name,
self.description,
self.issue_url()
)
}
}
37 changes: 37 additions & 0 deletions common/tari_features/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright 2023. The Tari Project
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
// following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
// disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
// following disclaimer in the documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
// products derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

mod feature;
pub mod resolver;
mod status;

pub use feature::Feature;
pub use status::Status;

pub const FEATURE_LIST: [Feature; 0] = [
// Feature::new(
// "example_feature_name",
// "example description",
// None,
// Status::New,
// ),
];
Loading

0 comments on commit 1311a0d

Please sign in to comment.