Skip to content

Commit

Permalink
Release 0.20.8 (#1435)
Browse files Browse the repository at this point in the history
Beta 4 authority node punished some sentries because of some invalid
transactions they sent because of block race.

The fix is to not punish the reserved peer for sending an invalid
transaction.

---------

Co-authored-by: Brandon Kite <brandonkite92@gmail.com>
  • Loading branch information
xgreenx and Voxelot authored Oct 23, 2023
1 parent 7bf5cb2 commit 6c95b54
Show file tree
Hide file tree
Showing 10 changed files with 401 additions and 121 deletions.
159 changes: 84 additions & 75 deletions Cargo.lock

Large diffs are not rendered by default.

46 changes: 23 additions & 23 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,32 +45,32 @@ homepage = "https://fuel.network/"
keywords = ["blockchain", "cryptocurrencies", "fuel-vm", "vm"]
license = "BUSL-1.1"
repository = "https://github.com/FuelLabs/fuel-core"
version = "0.20.7"
version = "0.20.8"

[workspace.dependencies]
# Workspace members
fuel-core = { version = "0.20.7", path = "./crates/fuel-core", default-features = false }
fuel-core-client-bin = { version = "0.20.7", path = "./bin/fuel-core-client" }
fuel-core-bin = { version = "0.20.7", path = "./bin/fuel-core" }
fuel-core-keygen = { version = "0.20.7", path = "./bin/keygen" }
fuel-core-chain-config = { version = "0.20.7", path = "./crates/chain-config" }
fuel-core-client = { version = "0.20.7", path = "./crates/client" }
fuel-core-database = { version = "0.20.7", path = "./crates/database" }
fuel-core-metrics = { version = "0.20.7", path = "./crates/metrics" }
fuel-core-services = { version = "0.20.7", path = "./crates/services" }
fuel-core-consensus-module = { version = "0.20.7", path = "./crates/services/consensus_module" }
fuel-core-bft = { version = "0.20.7", path = "./crates/services/consensus_module/bft" }
fuel-core-poa = { version = "0.20.7", path = "./crates/services/consensus_module/poa" }
fuel-core-executor = { version = "0.20.7", path = "./crates/services/executor" }
fuel-core-importer = { version = "0.20.7", path = "./crates/services/importer" }
fuel-core-p2p = { version = "0.20.7", path = "./crates/services/p2p" }
fuel-core-producer = { version = "0.20.7", path = "./crates/services/producer" }
fuel-core-relayer = { version = "0.20.7", path = "./crates/services/relayer" }
fuel-core-sync = { version = "0.20.7", path = "./crates/services/sync" }
fuel-core-txpool = { version = "0.20.7", path = "./crates/services/txpool" }
fuel-core-storage = { version = "0.20.7", path = "./crates/storage" }
fuel-core-trace = { version = "0.20.7", path = "./crates/trace" }
fuel-core-types = { version = "0.20.7", path = "./crates/types", default-features = false }
fuel-core = { version = "0.20.8", path = "./crates/fuel-core", default-features = false }
fuel-core-client-bin = { version = "0.20.8", path = "./bin/fuel-core-client" }
fuel-core-bin = { version = "0.20.8", path = "./bin/fuel-core" }
fuel-core-keygen = { version = "0.20.8", path = "./bin/keygen" }
fuel-core-chain-config = { version = "0.20.8", path = "./crates/chain-config" }
fuel-core-client = { version = "0.20.8", path = "./crates/client" }
fuel-core-database = { version = "0.20.8", path = "./crates/database" }
fuel-core-metrics = { version = "0.20.8", path = "./crates/metrics" }
fuel-core-services = { version = "0.20.8", path = "./crates/services" }
fuel-core-consensus-module = { version = "0.20.8", path = "./crates/services/consensus_module" }
fuel-core-bft = { version = "0.20.8", path = "./crates/services/consensus_module/bft" }
fuel-core-poa = { version = "0.20.8", path = "./crates/services/consensus_module/poa" }
fuel-core-executor = { version = "0.20.8", path = "./crates/services/executor" }
fuel-core-importer = { version = "0.20.8", path = "./crates/services/importer" }
fuel-core-p2p = { version = "0.20.8", path = "./crates/services/p2p" }
fuel-core-producer = { version = "0.20.8", path = "./crates/services/producer" }
fuel-core-relayer = { version = "0.20.8", path = "./crates/services/relayer" }
fuel-core-sync = { version = "0.20.8", path = "./crates/services/sync" }
fuel-core-txpool = { version = "0.20.8", path = "./crates/services/txpool" }
fuel-core-storage = { version = "0.20.8", path = "./crates/storage" }
fuel-core-trace = { version = "0.20.8", path = "./crates/trace" }
fuel-core-types = { version = "0.20.8", path = "./crates/types", default-features = false }
fuel-core-tests = { version = "0.0.0", path = "./tests" }
fuel-core-xtask = { version = "0.0.0", path = "./xtask" }

Expand Down
110 changes: 105 additions & 5 deletions crates/fuel-core/src/p2p_test_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ use crate::{
use fuel_core_p2p::{
codecs::postcard::PostcardCodec,
network_service::FuelP2PService,
p2p_service::FuelP2PEvent,
service::to_message_acceptance,
};
use fuel_core_poa::{
ports::BlockImporter,
Expand Down Expand Up @@ -43,6 +45,7 @@ use fuel_core_types::{
Bytes32,
},
secrecy::Secret,
services::p2p::GossipsubMessageAcceptance,
};
use futures::StreamExt;
use itertools::Itertools;
Expand All @@ -62,6 +65,12 @@ use std::{
};
use tokio::sync::broadcast;

#[derive(Copy, Clone)]
pub enum BootstrapType {
BootstrapNodes,
ReservedNodes,
}

#[derive(Clone)]
/// Setup for a producer node
pub struct ProducerSetup {
Expand All @@ -71,6 +80,10 @@ pub struct ProducerSetup {
pub secret: SecretKey,
/// Number of test transactions to create for this producer.
pub num_test_txs: usize,
/// Enable full utxo stateful validation.
pub utxo_validation: bool,
/// Indicates the type of initial connections.
pub bootstrap_type: BootstrapType,
}

#[derive(Clone)]
Expand All @@ -80,6 +93,10 @@ pub struct ValidatorSetup {
pub name: String,
/// Public key of the producer to sync from.
pub pub_key: Address,
/// Enable full utxo stateful validation.
pub utxo_validation: bool,
/// Indicates the type of initial connections.
pub bootstrap_type: BootstrapType,
}

#[derive(Clone)]
Expand Down Expand Up @@ -126,7 +143,20 @@ impl Bootstrap {
assert!(result.is_ok());
break;
}
_ = bootstrap.next_event() => {}
event = bootstrap.next_event() => {
// The bootstrap node only forwards data without validating it.
if let Some(FuelP2PEvent::GossipsubMessage {
peer_id,
message_id,
..
}) = event {
bootstrap.report_message_validation_result(
&message_id,
peer_id,
to_message_acceptance(&GossipsubMessageAcceptance::Accept)
)
}
}
}
}
});
Expand Down Expand Up @@ -253,9 +283,27 @@ pub async fn make_nodes(

let mut test_txs = Vec::with_capacity(0);
node_config.block_production = Trigger::Instant;
node_config.p2p.as_mut().unwrap().bootstrap_nodes = boots.clone();

if let Some((ProducerSetup { secret, .. }, txs)) = s {
if let Some((
ProducerSetup {
secret,
utxo_validation,
bootstrap_type,
..
},
txs,
)) = s
{
match bootstrap_type {
BootstrapType::BootstrapNodes => {
node_config.p2p.as_mut().unwrap().bootstrap_nodes = boots.clone();
}
BootstrapType::ReservedNodes => {
node_config.p2p.as_mut().unwrap().reserved_nodes = boots.clone();
}
}

node_config.utxo_validation = utxo_validation;
let pub_key = secret.public_key();
match &mut node_config.chain_conf.consensus {
crate::chain_config::ConsensusConfig::PoA { signing_key } => {
Expand Down Expand Up @@ -283,9 +331,24 @@ pub async fn make_nodes(
chain_config.clone(),
);
node_config.block_production = Trigger::Never;
node_config.p2p.as_mut().unwrap().bootstrap_nodes = boots.clone();

if let Some(ValidatorSetup { pub_key, .. }) = s {
if let Some(ValidatorSetup {
pub_key,
utxo_validation,
bootstrap_type,
..
}) = s
{
node_config.utxo_validation = utxo_validation;

match bootstrap_type {
BootstrapType::BootstrapNodes => {
node_config.p2p.as_mut().unwrap().bootstrap_nodes = boots.clone();
}
BootstrapType::ReservedNodes => {
node_config.p2p.as_mut().unwrap().reserved_nodes = boots.clone();
}
}
match &mut node_config.chain_conf.consensus {
crate::chain_config::ConsensusConfig::PoA { signing_key } => {
*signing_key = pub_key;
Expand Down Expand Up @@ -340,6 +403,11 @@ fn extract_p2p_config(node_config: &Config) -> fuel_core_p2p::config::Config {
}

impl Node {
/// Returns the vector of valid transactions for pre-initialized state.
pub fn test_transactions(&self) -> &Vec<Transaction> {
&self.test_txs
}

/// Waits for `number_of_blocks` and each block should be `is_local`
pub async fn wait_for_blocks(&self, number_of_blocks: usize, is_local: bool) {
let mut stream = self
Expand Down Expand Up @@ -450,6 +518,8 @@ impl ProducerSetup {
name: Default::default(),
secret,
num_test_txs: Default::default(),
utxo_validation: true,
bootstrap_type: BootstrapType::BootstrapNodes,
}
}

Expand All @@ -466,13 +536,29 @@ impl ProducerSetup {
..self
}
}

pub fn utxo_validation(self, utxo_validation: bool) -> Self {
Self {
utxo_validation,
..self
}
}

pub fn bootstrap_type(self, bootstrap_type: BootstrapType) -> Self {
Self {
bootstrap_type,
..self
}
}
}

impl ValidatorSetup {
pub fn new(pub_key: Address) -> Self {
Self {
pub_key,
name: Default::default(),
utxo_validation: true,
bootstrap_type: BootstrapType::BootstrapNodes,
}
}

Expand All @@ -482,6 +568,20 @@ impl ValidatorSetup {
..self
}
}

pub fn utxo_validation(self, utxo_validation: bool) -> Self {
Self {
utxo_validation,
..self
}
}

pub fn bootstrap_type(self, bootstrap_type: BootstrapType) -> Self {
Self {
bootstrap_type,
..self
}
}
}
impl BootstrapSetup {
pub fn new(pub_key: Address) -> Self {
Expand Down
2 changes: 1 addition & 1 deletion crates/services/consensus_module/poa/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ where
p2p_port: P,
) -> Self {
let tx_status_update_stream = txpool.transaction_status_events();
let (request_sender, request_receiver) = mpsc::channel(100);
let (request_sender, request_receiver) = mpsc::channel(1024);
let (last_height, last_timestamp, last_block_created) =
Self::extract_block_info(last_block);

Expand Down
16 changes: 8 additions & 8 deletions crates/services/p2p/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
mod behavior;
pub mod behavior;
pub mod codecs;
pub mod config;
mod discovery;
mod gossipsub;
mod heartbeat;
mod p2p_service;
mod peer_manager;
mod peer_report;
pub mod discovery;
pub mod gossipsub;
pub mod heartbeat;
pub mod p2p_service;
pub mod peer_manager;
pub mod peer_report;
pub mod ports;
mod request_response;
pub mod request_response;
pub mod service;

pub use gossipsub::config as gossipsub_config;
Expand Down
9 changes: 8 additions & 1 deletion crates/services/p2p/src/p2p_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,15 @@ impl<Codec: NetworkCodec> FuelP2PService<Codec> {
&mut self,
msg_id: &MessageId,
propagation_source: PeerId,
acceptance: MessageAcceptance,
mut acceptance: MessageAcceptance,
) {
// Even invalid transactions shouldn't affect reserved peer reputation.
if let MessageAcceptance::Reject = acceptance {
if self.peer_manager.is_reserved(&propagation_source) {
acceptance = MessageAcceptance::Ignore;
}
}

if let Some(gossip_score) = self
.swarm
.behaviour_mut()
Expand Down
4 changes: 4 additions & 0 deletions crates/services/p2p/src/peer_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ impl PeerManager {
self.reserved_peers_updates.clone()
}

pub fn is_reserved(&self, peer_id: &PeerId) -> bool {
self.reserved_peers.contains(peer_id)
}

pub fn handle_gossip_score_update<T: Punisher>(
&self,
peer_id: PeerId,
Expand Down
38 changes: 33 additions & 5 deletions crates/services/p2p/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,35 @@ enum TaskRequest {

impl Debug for TaskRequest {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "TaskRequest")
match self {
TaskRequest::BroadcastTransaction(_) => {
write!(f, "TaskRequest::BroadcastTransaction")
}
TaskRequest::BroadcastBlock(_) => {
write!(f, "TaskRequest::BroadcastBlock")
}
TaskRequest::BroadcastVote(_) => {
write!(f, "TaskRequest::BroadcastVote")
}
TaskRequest::GetPeerIds(_) => {
write!(f, "TaskRequest::GetPeerIds")
}
TaskRequest::GetBlock { .. } => {
write!(f, "TaskRequest::GetBlock")
}
TaskRequest::GetSealedHeader { .. } => {
write!(f, "TaskRequest::GetSealedHeader")
}
TaskRequest::GetTransactions { .. } => {
write!(f, "TaskRequest::GetTransactions")
}
TaskRequest::RespondWithGossipsubMessageReport(_) => {
write!(f, "TaskRequest::RespondWithGossipsubMessageReport")
}
TaskRequest::RespondWithPeerReport { .. } => {
write!(f, "TaskRequest::RespondWithPeerReport")
}
}
}
}

Expand All @@ -131,9 +159,9 @@ impl<D> Task<D> {
db: Arc<D>,
block_importer: Arc<B>,
) -> Self {
let (request_sender, request_receiver) = mpsc::channel(100);
let (tx_broadcast, _) = broadcast::channel(100);
let (block_height_broadcast, _) = broadcast::channel(100);
let (request_sender, request_receiver) = mpsc::channel(1024 * 10);
let (tx_broadcast, _) = broadcast::channel(1024 * 10);
let (block_height_broadcast, _) = broadcast::channel(1024 * 10);

let next_block_height = block_importer.next_block_height();
let max_block_size = config.max_block_size;
Expand Down Expand Up @@ -506,7 +534,7 @@ where
))
}

pub(crate) fn to_message_acceptance(
pub fn to_message_acceptance(
acceptance: &GossipsubMessageAcceptance,
) -> MessageAcceptance {
match acceptance {
Expand Down
2 changes: 1 addition & 1 deletion deployment/charts/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ apiVersion: v2
name: ${fuel_core_service_name}
description: ${fuel_core_service_name} Helm Chart
type: application
appVersion: "0.20.7"
appVersion: "0.20.8"
version: 0.1.0
Loading

0 comments on commit 6c95b54

Please sign in to comment.