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

feat(versioning): include protocol versions in Version message #2545

Merged
merged 1 commit into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
15 changes: 14 additions & 1 deletion data_structures/src/builders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ use crate::{
SuperBlockVote,
},
error::BuildersError,
get_protocol_version_activation_epoch, get_protocol_version_period,
proto::versioning::ProtocolVersion,
strum::IntoEnumIterator,
transaction::Transaction,
types::{
Address, Command, GetPeers, InventoryAnnouncement, InventoryRequest, IpAddress, LastBeacon,
Message, Peers, Verack, Version,
Message, Peers, ProtocolVersion as ProtocolVersionType, Verack, Version,
},
};

Expand Down Expand Up @@ -59,6 +62,15 @@ impl Message {
beacon: LastBeacon,
) -> Message {
let addr = sender_addr.map(to_address);

let mut protocol_versions = vec![];
for protocol in ProtocolVersion::iter() {
protocol_versions.push(ProtocolVersionType {
version: protocol.into(),
activation_epoch: get_protocol_version_activation_epoch(protocol),
checkpoint_period: get_protocol_version_period(protocol),
});
}
Message::build_message(
magic,
Command::Version(Version {
Expand All @@ -70,6 +82,7 @@ impl Message {
user_agent: user_agent(),
nonce: random_nonce(),
beacon,
protocol_versions,
}),
)
}
Expand Down
12 changes: 11 additions & 1 deletion data_structures/src/proto/versioning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::{
},
ProtobufConvert,
},
types::Message,
types::{Message, ProtocolVersionName},
};

#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
Expand Down Expand Up @@ -167,6 +167,16 @@ impl PartialOrd for ProtocolVersion {
}
}

impl From<ProtocolVersionName> for ProtocolVersion {
fn from(version: ProtocolVersionName) -> Self {
match version {
ProtocolVersionName::V1_7(_) => ProtocolVersion::V1_7,
ProtocolVersionName::V1_8(_) => ProtocolVersion::V1_8,
ProtocolVersionName::V2_0(_) => ProtocolVersion::V2_0,
}
}
}

pub trait Versioned: ProtobufConvert {
type LegacyType: protobuf::Message;

Expand Down
52 changes: 50 additions & 2 deletions data_structures/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ use serde::{Deserialize, Serialize};

use crate::{
chain::{Block, CheckpointBeacon, Hashable, InventoryEntry, SuperBlock, SuperBlockVote},
proto::{schema::witnet, ProtobufConvert},
proto::{
schema::witnet, versioning::ProtocolVersion as VersioningProtocolVersion, ProtobufConvert,
},
transaction::Transaction,
};

Expand Down Expand Up @@ -50,7 +52,26 @@ impl fmt::Display for Command {
Command::GetPeers(_) => f.write_str("GET_PEERS"),
Command::Peers(_) => f.write_str("PEERS"),
Command::Verack(_) => f.write_str("VERACK"),
Command::Version(_) => f.write_str("VERSION"),
Command::Version(Version {
version: v,
sender_address: sa,
protocol_versions: pv,
..
}) => {
let mut protocol_versions_str = String::from("(");
for protocol in pv {
protocol_versions_str.push_str(&format!(
"(version: {:?}, activation_epoch: {}, period: {}),",
protocol.version, protocol.activation_epoch, protocol.checkpoint_period
));
}
protocol_versions_str.push_str(")");
write!(
f,
"VERSION MESSAGE: version = {}, sender_address = {:?}, protocol_versions = {}",
v, sa, protocol_versions_str,
)
}
Command::Block(block) => write!(
f,
"BLOCK #{}: {}",
Expand Down Expand Up @@ -112,6 +133,32 @@ pub struct Peers {
#[protobuf_convert(pb = "witnet::Verack")]
pub struct Verack;

#[derive(Clone, Copy, Debug, Eq, PartialEq, ProtobufConvert)]
#[protobuf_convert(pb = "witnet::ProtocolVersionName")]
pub enum ProtocolVersionName {
V1_7(bool),
V1_8(bool),
V2_0(bool),
}

impl From<VersioningProtocolVersion> for ProtocolVersionName {
fn from(version: VersioningProtocolVersion) -> Self {
match version {
VersioningProtocolVersion::V1_7 => ProtocolVersionName::V1_7(true),
VersioningProtocolVersion::V1_8 => ProtocolVersionName::V1_8(true),
VersioningProtocolVersion::V2_0 => ProtocolVersionName::V2_0(true),
}
}
}

#[derive(Debug, Eq, PartialEq, Clone, ProtobufConvert)]
#[protobuf_convert(pb = "witnet::ProtocolVersion")]
pub struct ProtocolVersion {
pub version: ProtocolVersionName,
pub activation_epoch: u32,
pub checkpoint_period: u16,
}

#[derive(Debug, Eq, PartialEq, Clone, ProtobufConvert)]
#[protobuf_convert(pb = "witnet::Version")]
pub struct Version {
Expand All @@ -123,6 +170,7 @@ pub struct Version {
pub user_agent: String,
pub nonce: u64,
pub beacon: LastBeacon,
pub protocol_versions: Vec<ProtocolVersion>,
}

///////////////////////////////////////////////////////////
Expand Down
49 changes: 47 additions & 2 deletions node/src/actors/chain_manager/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ use crate::{
GetMempoolResult, GetNodeStats, GetProtocolInfo, GetReputation, GetReputationResult,
GetSignalingInfo, GetState, GetSuperBlockVotes, GetSupplyInfo, GetUtxoInfo,
IsConfirmedBlock, PeersBeacons, QueryStake, ReputationStats, Rewind, SendLastBeacon,
SessionUnitResult, SetLastBeacon, SetPeersLimits, SignalingInfo, SnapshotExport,
SnapshotImport, TryMineBlock,
SendProtocolVersions, SessionUnitResult, SetEpochConstants, SetLastBeacon,
SetPeersLimits, SignalingInfo, SnapshotExport, SnapshotImport, TryMineBlock,
},
sessions_manager::SessionsManager,
},
Expand Down Expand Up @@ -2132,6 +2132,51 @@ impl Handler<SnapshotImport> for ChainManager {
Box::pin(fut)
}
}

impl Handler<SetEpochConstants> for ChainManager {
type Result = ();

fn handle(&mut self, msg: SetEpochConstants, _ctx: &mut Context<Self>) -> Self::Result {
log::debug!("Received new epoch constants: {:?}", msg.epoch_constants);
self.epoch_constants = Some(msg.epoch_constants);

let previous_epoch = self.current_epoch.unwrap();
self.current_epoch = match msg.epoch_constants.epoch_at(get_timestamp()) {
Ok(epoch) => Some(epoch),
Err(_) => panic!("Could not recalculate current epoch"),
};
log::debug!(
"Updating current epoch from {} to {}",
previous_epoch,
self.current_epoch.unwrap()
);
}
}

impl Handler<SendProtocolVersions> for ChainManager {
type Result = ();

fn handle(&mut self, msg: SendProtocolVersions, _ctx: &mut Context<Self>) {
if let Some(ref mut chain_info) = &mut self.chain_state.chain_info {
log::debug!("Setting protocol versions info in Chain Manager");
for protocol in msg.protocol_versions {
if chain_info
.protocol
.all_versions
.get_activation_epoch(protocol.version.into())
== u32::MAX
{
chain_info.protocol.register(
protocol.activation_epoch,
protocol.version.into(),
protocol.checkpoint_period,
);
}
}
}
}
}

#[derive(Debug, Eq, PartialEq)]
pub enum BlockBatches<T> {
TargetNotReached(Vec<T>),
Expand Down
24 changes: 22 additions & 2 deletions node/src/actors/epoch_manager/handlers.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use actix::{Context, Handler};
use std::time::Duration;

use actix::{AsyncContext, Context, Handler};

use witnet_data_structures::chain::Epoch;

Expand Down Expand Up @@ -79,7 +81,9 @@ impl Handler<GetEpochConstants> for EpochManager {
impl Handler<SetEpochConstants> for EpochManager {
type Result = ();

fn handle(&mut self, msg: SetEpochConstants, _ctx: &mut Context<Self>) -> Self::Result {
fn handle(&mut self, msg: SetEpochConstants, ctx: &mut Context<Self>) -> Self::Result {
log::debug!("Received new epoch constants: {:?}", msg.epoch_constants);

// Check if the epoch calculated with the current version of the epoch constants
// and the last_checked_epoch are different and if they are, subtract that difference
// from the new last_checked_epoch.
Expand All @@ -99,5 +103,21 @@ impl Handler<SetEpochConstants> for EpochManager {
.unwrap_or_default()
.saturating_sub(epoch_diff),
);

// Reschedule next epoch
let current_epoch = self.current_epoch();
log::debug!(
"Rescheduling timeout for epoch {}",
current_epoch.unwrap_or_default()
);
ctx.cancel_future(self.last_future);
let time_to_next_checkpoint =
self.time_to_next_checkpoint(current_epoch)
.unwrap_or_else(|_| {
let retry_seconds = self.constants.as_ref().unwrap().checkpoints_period;
log::warn!("Failed to calculate time to next checkpoint");
Duration::from_secs(u64::from(retry_seconds))
});
self.checkpoint_monitor(ctx, time_to_next_checkpoint);
}
}
7 changes: 5 additions & 2 deletions node/src/actors/epoch_manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ pub struct EpochManager {

/// Last epoch that was checked by the epoch monitor process
last_checked_epoch: Option<Epoch>,

/// Last spawned future
last_future: SpawnHandle,
}

impl Drop for EpochManager {
Expand Down Expand Up @@ -203,13 +206,13 @@ impl EpochManager {
)
}
/// Method to monitor checkpoints and execute some actions on each
fn checkpoint_monitor(&self, ctx: &mut Context<Self>, time_to_next_checkpoint: Duration) {
fn checkpoint_monitor(&mut self, ctx: &mut Context<Self>, time_to_next_checkpoint: Duration) {
// Wait until next checkpoint to execute the periodic function
log::debug!(
"Checkpoint monitor: time to next checkpoint: {:?}",
time_to_next_checkpoint
);
ctx.run_later(time_to_next_checkpoint, move |act, ctx| {
self.last_future = ctx.run_later(time_to_next_checkpoint, move |act, ctx| {
let current_epoch = act.current_epoch();
log::debug!(
"Current epoch {:?}. Last checked epoch {:?}",
Expand Down
15 changes: 14 additions & 1 deletion node/src/actors/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use witnet_data_structures::{
UnstakeTransaction, VTTransaction,
},
transaction_factory::NodeBalance,
types::LastBeacon,
types::{LastBeacon, ProtocolVersion},
utxo_pool::{UtxoInfo, UtxoSelectionStrategy},
wit::Wit,
};
Expand Down Expand Up @@ -1472,6 +1472,19 @@ impl Message for crate::actors::messages::GetProtocolInfo {
type Result = Result<Option<ProtocolInfo>, failure::Error>;
}

/// Message indicating the last beacon received from a peer
#[derive(Clone, Debug)]
pub struct SendProtocolVersions {
/// Socket address which identifies the peer
pub address: SocketAddr,
/// Protocol versions received from peer
pub protocol_versions: Vec<ProtocolVersion>,
}

impl Message for SendProtocolVersions {
type Result = ();
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
/// A value that can either be L, R, where an R can always be obtained through the `do_magic` method.
Expand Down
Loading
Loading