Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added blacklisting transaction on the TxPool #1743

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,31 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

Description of the upcoming release here.

### 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
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 @@ -25,7 +25,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 @@ -64,6 +67,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 @@ -151,7 +155,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 @@ -174,22 +182,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 @@ -237,10 +229,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 @@ -286,10 +275,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 @@ -300,6 +286,24 @@ impl Command {
max_wait_time: max_wait_time.into(),
};

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 @@ -322,6 +326,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)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where did the "4064" come from?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like it was just copied over from before

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,
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ fn test_update_sender_inner(ops: Vec<Op>) {
Op::DropRecv(i) => {
// Real
if i < receivers.len() {
receivers.remove(i);
let _ = receivers.remove(i);
}
// Model
if i < model_receivers.len() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ fn test_subscriber(input: Input) {
let Input { tx_id, senders } = input;
let mut senders = box_senders(senders);
let len_before = senders.values().map(|v| v.len()).sum::<usize>();
subscribe::<_, MockCreateChannel>(
let _ = subscribe::<_, MockCreateChannel>(
Bytes32::from([tx_id; 32]),
&mut senders,
Box::new(()),
Expand Down
Loading
Loading