Skip to content

Commit

Permalink
Duplicating blacklisting feature for TxPool from 0.22.4 (#1748)
Browse files Browse the repository at this point in the history
Duplicates the FuelLabs/fuel-core#1743 for the
`master`

---------

Co-authored-by: Brandon Kite <[email protected]>
  • Loading branch information
crypto523 and Voxelot committed Mar 11, 2024
1 parent e1d0f61 commit 2d19774
Show file tree
Hide file tree
Showing 7 changed files with 460 additions and 38 deletions.
39 changes: 39 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,45 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- [#1573](https://github.com/FuelLabs/fuel-core/pull/1573): Remove nested p2p request/response encoding. Only breaks p2p networking compatibility with older fuel-core versions, but is otherwise fully internal.


## [Version 0.22.4]

### Added

- [#1743](https://github.com/FuelLabs/fuel-core/pull/1743): Added blacklisting of the transactions on the `TxPool` level.
```shell
--tx-blacklist-addresses <TX_BLACKLIST_ADDRESSES>
The list of banned addresses ignored by the `TxPool`

[env: TX_BLACKLIST_ADDRESSES=]

--tx-blacklist-coins <TX_BLACKLIST_COINS>
The list of banned coins ignored by the `TxPool`

[env: TX_BLACKLIST_COINS=]

--tx-blacklist-messages <TX_BLACKLIST_MESSAGES>
The list of banned messages ignored by the `TxPool`

[env: TX_BLACKLIST_MESSAGES=]

--tx-blacklist-contracts <TX_BLACKLIST_CONTRACTS>
The list of banned contracts ignored by the `TxPool`

[env: TX_BLACKLIST_CONTRACTS=]
```

## [Version 0.22.3]

### Added

- [#1732](https://github.com/FuelLabs/fuel-core/pull/1732): Added `Clone` bounds to most datatypes of `fuel-core-client`.

## [Version 0.22.2]

### Added

- [#1729](https://github.com/FuelLabs/fuel-core/pull/1729): Exposed the `schema.sdl` file from `fuel-core-client`. The user can create his own queries by using this file.

## [Version 0.22.1]

### Fixed
Expand Down
67 changes: 36 additions & 31 deletions bin/fuel-core/src/cli/run.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
#![allow(unused_variables)]
use crate::{
cli::{
run::consensus::PoATriggerArgs,
run::{
consensus::PoATriggerArgs,
tx_pool::TxPoolArgs,
},
DEFAULT_DB_PATH,
},
FuelService,
};
use anyhow::{
anyhow,
Context,
};
use anyhow::Context;
use clap::Parser;
use fuel_core::{
chain_config::{
Expand All @@ -30,7 +30,10 @@ use fuel_core::{
ServiceTrait,
VMConfig,
},
txpool::Config as TxPoolConfig,
txpool::{
config::BlackList,
Config as TxPoolConfig,
},
types::{
blockchain::primitives::SecretKeyWrapper,
fuel_tx::ContractId,
Expand Down Expand Up @@ -73,6 +76,7 @@ mod consensus;
mod profiling;
#[cfg(feature = "relayer")]
mod relayer;
mod tx_pool;

/// Run the Fuel client node locally.
#[derive(Debug, Clone, Parser)]
Expand Down Expand Up @@ -155,7 +159,11 @@ pub struct Command {
///
/// If not set, `consensus_key` is used as the provider of the `Address`.
#[arg(long = "coinbase-recipient", env)]
pub coinbase_recipient: Option<String>,
pub coinbase_recipient: Option<ContractId>,

/// The cli arguments supported by the `TxPool`.
#[clap(flatten)]
pub tx_pool: TxPoolArgs,

#[cfg_attr(feature = "relayer", clap(flatten))]
#[cfg(feature = "relayer")]
Expand All @@ -178,22 +186,6 @@ pub struct Command {
#[clap(long = "verify-max-relayer-wait", default_value = "30s", env)]
pub max_wait_time: humantime::Duration,

/// The max time to live of the transaction inside of the `TxPool`.
#[clap(long = "tx-pool-ttl", default_value = "5m", env)]
pub tx_pool_ttl: humantime::Duration,

/// The max number of transactions that the `TxPool` can simultaneously store.
#[clap(long = "tx-max-number", default_value = "4064", env)]
pub tx_max_number: usize,

/// The max depth of the dependent transactions that supported by the `TxPool`.
#[clap(long = "tx-max-depth", default_value = "10", env)]
pub tx_max_depth: usize,

/// The maximum number of active subscriptions that supported by the `TxPool`.
#[clap(long = "tx-number-active-subscriptions", default_value = "4064", env)]
pub tx_number_active_subscriptions: usize,

/// The number of reserved peers to connect to before starting to sync.
#[clap(long = "min-connected-reserved-peers", default_value = "0", env)]
pub min_connected_reserved_peers: usize,
Expand Down Expand Up @@ -241,10 +233,7 @@ impl Command {
metrics,
max_da_lag,
max_wait_time,
tx_pool_ttl,
tx_max_number,
tx_max_depth,
tx_number_active_subscriptions,
tx_pool,
min_connected_reserved_peers,
time_until_synced,
query_log_threshold_time,
Expand Down Expand Up @@ -301,10 +290,7 @@ impl Command {
});

let coinbase_recipient = if let Some(coinbase_recipient) = coinbase_recipient {
Some(
ContractId::from_str(coinbase_recipient.as_str())
.map_err(|err| anyhow!(err))?,
)
Some(coinbase_recipient)
} else {
tracing::warn!("The coinbase recipient `ContractId` is not set!");
None
Expand All @@ -324,6 +310,24 @@ impl Command {
let block_importer =
fuel_core::service::config::fuel_core_importer::Config::new(&chain_conf);

let TxPoolArgs {
tx_pool_ttl,
tx_max_number,
tx_max_depth,
tx_number_active_subscriptions,
tx_blacklist_addresses,
tx_blacklist_coins,
tx_blacklist_messages,
tx_blacklist_contracts,
} = tx_pool;

let blacklist = BlackList::new(
tx_blacklist_addresses,
tx_blacklist_coins,
tx_blacklist_messages,
tx_blacklist_contracts,
);

let config = Config {
addr,
api_request_timeout: api_request_timeout.into(),
Expand All @@ -345,6 +349,7 @@ impl Command {
metrics,
tx_pool_ttl.into(),
tx_number_active_subscriptions,
blacklist,
),
block_producer: ProducerConfig {
utxo_validation,
Expand Down
104 changes: 104 additions & 0 deletions bin/fuel-core/src/cli/run/tx_pool.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
//! Clap configuration related to consensus parameters
use fuel_core::txpool::types::ContractId;
use fuel_core_types::{
fuel_tx::{
Address,
UtxoId,
},
fuel_types::Nonce,
};

#[derive(Debug, Clone, clap::Args)]
pub struct TxPoolArgs {
/// The max time to live of the transaction inside of the `TxPool`.
#[clap(long = "tx-pool-ttl", default_value = "5m", env)]
pub tx_pool_ttl: humantime::Duration,

/// The max number of transactions that the `TxPool` can simultaneously store.
#[clap(long = "tx-max-number", default_value = "4064", env)]
pub tx_max_number: usize,

/// The max depth of the dependent transactions that supported by the `TxPool`.
#[clap(long = "tx-max-depth", default_value = "10", env)]
pub tx_max_depth: usize,

/// The maximum number of active subscriptions that supported by the `TxPool`.
#[clap(long = "tx-number-active-subscriptions", default_value = "4064", env)]
pub tx_number_active_subscriptions: usize,

/// The list of banned addresses ignored by the `TxPool`.
#[clap(long = "tx-blacklist-addresses", value_delimiter = ',', env)]
pub tx_blacklist_addresses: Vec<Address>,

/// The list of banned coins ignored by the `TxPool`.
#[clap(long = "tx-blacklist-coins", value_delimiter = ',', env)]
pub tx_blacklist_coins: Vec<UtxoId>,

/// The list of banned messages ignored by the `TxPool`.
#[clap(long = "tx-blacklist-messages", value_delimiter = ',', env)]
pub tx_blacklist_messages: Vec<Nonce>,

/// The list of banned contracts ignored by the `TxPool`.
#[clap(long = "tx-blacklist-contracts", value_delimiter = ',', env)]
pub tx_blacklist_contracts: Vec<ContractId>,
}

#[cfg(test)]
mod tests {
use super::*;
use clap::Parser;
use fuel_core::txpool::config::BlackList;
use test_case::test_case;

#[derive(Debug, Clone, Parser)]
pub struct Command {
#[clap(flatten)]
tx_pool: TxPoolArgs,
}

fn blacklist(
a: Vec<Address>,
c: Vec<UtxoId>,
m: Vec<Nonce>,
ct: Vec<ContractId>,
) -> BlackList {
BlackList::new(a, c, m, ct)
}

#[test_case(&[""] => Ok(blacklist(vec![], vec![], vec![], vec![])); "defaults works")]
#[test_case(&["", "--tx-blacklist-addresses=\
0x0000000000000000000000000000000000000000000000000000000000000000,\
0101010101010101010101010101010101010101010101010101010101010101"
]
=> Ok(blacklist(vec![[0; 32].into(), [1; 32].into()], vec![], vec![], vec![])); "addresses works")]
#[test_case(&["", "--tx-blacklist-coins=\
0x000000000000000000000000000000000000000000000000000000000000000002,\
010101010101010101010101010101010101010101010101010101010101010103"
]
=> Ok(blacklist(vec![], vec![UtxoId::new([0; 32].into(), 2), UtxoId::new([1; 32].into(), 3)], vec![], vec![])); "coins works")]
#[test_case(&["", "--tx-blacklist-messages=\
0x0000000000000000000000000000000000000000000000000000000000000000,\
0101010101010101010101010101010101010101010101010101010101010101"
]
=> Ok(blacklist(vec![], vec![], vec![[0; 32].into(), [1; 32].into()], vec![])); "messages works")]
#[test_case(&["", "--tx-blacklist-contracts=\
0x0000000000000000000000000000000000000000000000000000000000000000,\
0101010101010101010101010101010101010101010101010101010101010101"
]
=> Ok(blacklist(vec![], vec![], vec![], vec![[0; 32].into(), [1; 32].into()])); "contracts works")]
fn parse(args: &[&str]) -> Result<BlackList, String> {
let command: Command =
Command::try_parse_from(args).map_err(|e| e.to_string())?;
let args = command.tx_pool;

let blacklist = blacklist(
args.tx_blacklist_addresses,
args.tx_blacklist_coins,
args.tx_blacklist_messages,
args.tx_blacklist_contracts,
);

Ok(blacklist)
}
}
62 changes: 61 additions & 1 deletion crates/services/txpool/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,60 @@
use crate::types::ContractId;
use fuel_core_chain_config::ChainConfig;
use std::time::Duration;
use fuel_core_types::{
fuel_tx::{
Address,
UtxoId,
},
fuel_types::Nonce,
};
use std::{
collections::HashSet,
time::Duration,
};

#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct BlackList {
/// Blacklisted addresses.
pub(crate) owners: HashSet<Address>,
/// Blacklisted UTXO ids.
pub(crate) coins: HashSet<UtxoId>,
/// Blacklisted messages by `Nonce`.
pub(crate) messages: HashSet<Nonce>,
/// Blacklisted contracts.
pub(crate) contracts: HashSet<ContractId>,
}

impl BlackList {
pub fn new(
owners: Vec<Address>,
utxo_ids: Vec<UtxoId>,
messages: Vec<Nonce>,
contracts: Vec<ContractId>,
) -> Self {
Self {
owners: owners.into_iter().collect(),
coins: utxo_ids.into_iter().collect(),
messages: messages.into_iter().collect(),
contracts: contracts.into_iter().collect(),
}
}

pub fn contains_address(&self, address: &Address) -> bool {
self.owners.contains(address)
}

pub fn contains_coin(&self, utxo_id: &UtxoId) -> bool {
self.coins.contains(utxo_id)
}

pub fn contains_message(&self, nonce: &Nonce) -> bool {
self.messages.contains(nonce)
}

pub fn contains_contract(&self, contract_id: &ContractId) -> bool {
self.contracts.contains(contract_id)
}
}

#[derive(Debug, Clone)]
pub struct Config {
Expand All @@ -19,6 +74,8 @@ pub struct Config {
pub transaction_ttl: Duration,
/// The number of allowed active transaction status subscriptions.
pub number_of_active_subscription: usize,
/// The blacklist used to validate transaction.
pub blacklist: BlackList,
}

impl Default for Config {
Expand All @@ -40,6 +97,7 @@ impl Default for Config {
metrics,
transaction_ttl,
number_of_active_subscription,
Default::default(),
)
}
}
Expand All @@ -55,6 +113,7 @@ impl Config {
metrics: bool,
transaction_ttl: Duration,
number_of_active_subscription: usize,
blacklist: BlackList,
) -> Self {
// # Dev-note: If you add a new field, be sure that this field is propagated correctly
// in all places where `new` is used.
Expand All @@ -67,6 +126,7 @@ impl Config {
metrics,
transaction_ttl,
number_of_active_subscription,
blacklist,
}
}
}
Loading

0 comments on commit 2d19774

Please sign in to comment.