Skip to content

Commit

Permalink
feat(versioning): include protocol versions in Version message
Browse files Browse the repository at this point in the history
  • Loading branch information
drcpu-github committed Dec 6, 2024
1 parent 200cb90 commit 716b8e4
Show file tree
Hide file tree
Showing 12 changed files with 635 additions and 40 deletions.
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

0 comments on commit 716b8e4

Please sign in to comment.