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 Versioning middleware #3664

Closed
wants to merge 17 commits into from
Closed
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
483 changes: 254 additions & 229 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions massa-models/src/config/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,8 @@ pub const NETWORK_NODE_EVENT_CHANNEL_SIZE: usize = 10_000;
//
/// Threshold to accept a new versioning
pub const VERSIONING_THRESHOLD_TRANSITION_ACCEPTED: Amount = Amount::from_mantissa_scale(75, 0);
/// versioning block stats queue size
pub const VERSIONING_COUNT_BLOCKS_CONSIDERED: usize = 1000;

// Some checks at compile time that should not be ignored!
#[allow(clippy::assertions_on_constants)]
Expand Down
2 changes: 2 additions & 0 deletions massa-node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ massa_time = { path = "../massa-time" }
massa_wallet = { path = "../massa-wallet" }
massa_factory_exports = { path = "../massa-factory-exports" }
massa_factory_worker = { path = "../massa-factory-worker" }
massa_versioning_exports = { path = "../massa-versioning-exports" }
massa_versioning_worker = { path = "../massa-versioning-worker" }

# for more information on what are the following features used for, see the cargo.toml at workspace level
[features]
Expand Down
14 changes: 13 additions & 1 deletion massa-node/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ use massa_models::config::constants::{
NETWORK_NODE_COMMAND_CHANNEL_SIZE, NETWORK_NODE_EVENT_CHANNEL_SIZE, OPERATION_VALIDITY_PERIODS,
PERIODS_PER_CYCLE, POOL_CONTROLLER_CHANNEL_SIZE, POS_MISS_RATE_DEACTIVATION_THRESHOLD,
POS_SAVED_CYCLES, PROTOCOL_CONTROLLER_CHANNEL_SIZE, PROTOCOL_EVENT_CHANNEL_SIZE, ROLL_PRICE,
T0, THREAD_COUNT, VERSION,
T0, THREAD_COUNT, VERSION, VERSIONING_COUNT_BLOCKS_CONSIDERED,
};
use massa_models::config::CONSENSUS_BOOTSTRAP_PART_SIZE;
use massa_network_exports::{Establisher, NetworkConfig, NetworkManager};
Expand All @@ -60,6 +60,8 @@ use massa_protocol_exports::{
use massa_protocol_worker::start_protocol_controller;
use massa_storage::Storage;
use massa_time::MassaTime;
use massa_versioning_exports::VersioningConfig;
use massa_versioning_worker::{versioning::MipStore, versioning_middleware::VersioningMiddleware};
use massa_wallet::Wallet;
use parking_lot::RwLock;
use std::path::PathBuf;
Expand Down Expand Up @@ -316,6 +318,16 @@ async fn launch(
.checked_mul_u64(LEDGER_ENTRY_DATASTORE_BASE_SIZE as u64)
.expect("Overflow when creating constant ledger_entry_datastore_base_size"),
};

let versioning_config = VersioningConfig {
count_blocks_considered: VERSIONING_COUNT_BLOCKS_CONSIDERED,
};

// Creates an empty default store
let mip_store = MipStore::try_from([]).unwrap();

let _versioning_middleware = VersioningMiddleware::new(versioning_config, mip_store.clone());

// launch execution module
let execution_config = ExecutionConfig {
max_final_events: SETTINGS.execution.max_final_events,
Expand Down
6 changes: 6 additions & 0 deletions massa-versioning-exports/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
mod settings;

pub use settings::VersioningConfig;

#[cfg(test)]
pub mod tests;
5 changes: 5 additions & 0 deletions massa-versioning-exports/src/settings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#[derive(Clone)]
pub struct VersioningConfig {
/// Nb blocks to consider for versioning stats
pub count_blocks_considered: usize,
}
4 changes: 4 additions & 0 deletions massa-versioning-worker/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,15 @@ parking_lot = "0.12"
thiserror = "1.0"
num_enum = "0.5"
nom = "7.1"
tokio = { version = "1.23", features = ["full"] }
tracing = "0.1"
queues = "1.1.0"

# custom module
massa_time = { path = "../massa-time" }
massa_models = { path = "../massa-models" }
massa_serialization = { path = "../massa-serialization" }
massa_versioning_exports = { path = "../massa-versioning-exports" }

[dev-dependencies]
chrono = "0.4"
Expand Down
1 change: 1 addition & 0 deletions massa-versioning-worker/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@

pub mod versioning;
pub mod versioning_factory;
pub mod versioning_middleware;
pub mod versioning_ser_der;
sydhds marked this conversation as resolved.
Show resolved Hide resolved

/// Test utils
Expand Down
63 changes: 33 additions & 30 deletions massa-versioning-worker/src/versioning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,8 @@ pub struct MipInfo {
pub name: String,
/// Network (or global) version (to be included in block header)
pub version: u32,
/// Component concerned by this versioning (e.g. a new Block version)
pub component: MipComponent,
/// Component version
pub component_version: u32,
/// Components concerned by this versioning (e.g. a new Block version), and the associated component_version
pub components: HashMap<MipComponent, u32>,
sydhds marked this conversation as resolved.
Show resolved Hide resolved
/// a timestamp at which the version gains its meaning (e.g. accepted in block header)
pub start: MassaTime,
/// a timestamp at which the deployment is considered active or failed (timeout > start)
Expand All @@ -58,7 +56,7 @@ impl PartialEq for MipInfo {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
&& self.version == other.version
&& self.component == other.component
&& self.components == other.components
&& self.start == other.start
&& self.timeout == other.timeout
}
Expand All @@ -71,7 +69,9 @@ impl Hash for MipInfo {
fn hash<H: Hasher>(&self, state: &mut H) {
self.name.hash(state);
self.version.hash(state);
self.component.hash(state);
for elt in self.components.clone() {
elt.hash(state);
}
self.start.hash(state);
self.timeout.hash(state);
}
Expand Down Expand Up @@ -477,11 +477,12 @@ impl MipStoreRaw {
// We then return the list of new MipInfo so we can warn and ask
// to update the software

let mut component_versions: HashMap<MipComponent, u32> = self
.0
.iter()
.map(|i| (i.0.component.clone(), i.0.component_version))
.collect();
let mut component_versions: HashMap<MipComponent, u32> = Default::default();
for i in self.0.iter() {
for component in i.0.components.iter() {
component_versions.insert(component.0.clone(), *component.1);
}
}
let mut names: BTreeSet<String> = self.0.iter().map(|i| i.0.name.clone()).collect();
let mut to_update: BTreeMap<MipInfo, MipState> = Default::default();
let mut to_add: BTreeMap<MipInfo, MipState> = Default::default();
Expand Down Expand Up @@ -526,18 +527,27 @@ impl MipStoreRaw {
.or(self.0.last_key_value().map(|i| i.0));

if let Some(last_v_info) = last_v_info_ {
// check for versions of all components in v_info
let mut version_compatible = true;
for component in v_info.components.iter() {
if component.1 <= component_versions.get(component.0).unwrap_or(&0) {
version_compatible = false;
break;
}
}
if v_info.start > last_v_info.timeout
&& v_info.timeout > v_info.start
&& v_info.version > last_v_info.version
&& !names.contains(&v_info.name)
&& v_info.component_version
> *component_versions.get(&v_info.component).unwrap_or(&0)
&& version_compatible
{
// Time range is ok / version is ok / name is unique, let's add it
to_add.insert(v_info.clone(), v_state.clone());
names.insert(v_info.name.clone());
component_versions
.insert(v_info.component.clone(), v_info.component_version);

for component in v_info.components.iter() {
component_versions.insert(component.0.clone(), *component.1);
}
} else {
// Something is wrong (time range not ok? / version not incr? / names?
// or component version not incr?)
Expand Down Expand Up @@ -626,8 +636,7 @@ mod test {
MipInfo {
name: "MIP-0002".to_string(),
version: 2,
component: MipComponent::Address,
component_version: 1,
components: HashMap::from([(MipComponent::Address, 1)]),
start: MassaTime::from(start.timestamp() as u64),
timeout: MassaTime::from(timeout.timestamp() as u64),
},
Expand Down Expand Up @@ -900,17 +909,15 @@ mod test {
let vi_1 = MipInfo {
name: "MIP-0002".to_string(),
version: 2,
component: MipComponent::Address,
component_version: 1,
components: HashMap::from([(MipComponent::Address, 1)]),
start: MassaTime::from(2),
timeout: MassaTime::from(5),
};
// Another versioning info (from an attacker) for testing
let vi_2 = MipInfo {
name: "MIP-0002".to_string(),
version: 2,
component: MipComponent::Address,
component_version: 1,
components: HashMap::from([(MipComponent::Address, 1)]),
start: MassaTime::from(7),
timeout: MassaTime::from(10),
};
Expand Down Expand Up @@ -973,8 +980,7 @@ mod test {
let vi_1 = MipInfo {
name: "MIP-0002".to_string(),
version: 2,
component: MipComponent::Address,
component_version: 1,
components: HashMap::from([(MipComponent::Address, 1)]),
start: MassaTime::from(2),
timeout: MassaTime::from(5),
};
Expand All @@ -985,8 +991,7 @@ mod test {
let vi_2 = MipInfo {
name: "MIP-0003".to_string(),
version: 3,
component: MipComponent::Address,
component_version: 2,
components: HashMap::from([(MipComponent::Address, 2)]),
start: MassaTime::from(17),
timeout: MassaTime::from(27),
};
Expand Down Expand Up @@ -1019,8 +1024,7 @@ mod test {
let vi_1 = MipInfo {
name: "MIP-0002".to_string(),
version: 2,
component: MipComponent::Address,
component_version: 1,
components: HashMap::from([(MipComponent::Address, 1)]),
start: MassaTime::from(0),
timeout: MassaTime::from(5),
};
Expand All @@ -1030,8 +1034,7 @@ mod test {
let vi_2 = MipInfo {
name: "MIP-0003".to_string(),
version: 3,
component: MipComponent::Address,
component_version: 2,
components: HashMap::from([(MipComponent::Address, 2)]),
start: MassaTime::from(17),
timeout: MassaTime::from(27),
};
Expand Down Expand Up @@ -1068,7 +1071,7 @@ mod test {
.unwrap();

let mut vi_2_2 = vi_2.clone();
vi_2_2.component_version = vi_1.component_version;
vi_2_2.components = vi_1.components.clone();

let vs_2_2 = advance_state_until(ComponentState::defined(), &vi_2_2);
let vs_raw_2 = MipStoreRaw(BTreeMap::from([
Expand Down
41 changes: 25 additions & 16 deletions massa-versioning-worker/src/versioning_factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,11 @@ pub trait VersioningFactory {
.iter()
.rev()
.find_map(|(vi, vsh)| {
(vi.component == component && vsh.inner == state_active)
.then_some(vi.component_version)
if vsh.inner == state_active {
vi.components.get(&component).copied()
} else {
None
}
})
.unwrap_or(0)
}
Expand All @@ -84,11 +87,13 @@ pub trait VersioningFactory {
.0
.iter()
.rev()
.filter(|(vi, vsh)| vi.component == component && vsh.inner == state_active)
.filter(|(vi, vsh)| {
vi.components.get(&component).is_some() && vsh.inner == state_active
})
.find_map(|(vi, vsh)| {
let res = vsh.state_at(ts, vi.start, vi.timeout);
match res {
Ok(ComponentStateTypeId::Active) => Some(vi.component_version),
Ok(ComponentStateTypeId::Active) => vi.components.get(&component).copied(),
_ => None,
}
})
Expand All @@ -105,7 +110,11 @@ pub trait VersioningFactory {

let state_active = ComponentState::active();
let versions_iter = vi_store.0.iter().filter_map(|(vi, vsh)| {
(vi.component == component && vsh.inner == state_active).then_some(vi.component_version)
if vsh.inner == state_active {
vi.components.get(&component).copied()
} else {
None
}
});
let versions: Vec<u32> = iter::once(0).chain(versions_iter).collect();
versions
Expand All @@ -118,8 +127,12 @@ pub trait VersioningFactory {
let vi_store = vi_store_.0.read();

let versions_iter = vi_store.0.iter().filter_map(|(vi, vsh)| {
(vi.component == component)
.then_some((vi.component_version, ComponentStateTypeId::from(&vsh.inner)))
vi.components
.get(&component)
.copied()
.map(|component_version| {
(component_version, ComponentStateTypeId::from(&vsh.inner))
})
});
iter::once((0, ComponentStateTypeId::Active))
.chain(versions_iter)
Expand All @@ -138,7 +151,7 @@ pub trait VersioningFactory {
mod test {
use super::*;

use std::collections::BTreeMap;
use std::collections::{BTreeMap, HashMap};

use crate::test_helpers::versioning_helpers::advance_state_until;
use crate::versioning::{MipInfo, MipState};
Expand Down Expand Up @@ -260,8 +273,7 @@ mod test {
let vi_1 = MipInfo {
name: "MIP-0002".to_string(),
version: 1,
component: MipComponent::Address,
component_version: 1,
components: HashMap::from([(MipComponent::Address, 1)]),
start: MassaTime::from(12),
timeout: MassaTime::from(15),
};
Expand All @@ -270,8 +282,7 @@ mod test {
let vi_2 = MipInfo {
name: "MIP-0003".to_string(),
version: 2,
component: MipComponent::Address,
component_version: 2,
components: HashMap::from([(MipComponent::Address, 2)]),
start: MassaTime::from(25),
timeout: MassaTime::from(28),
};
Expand Down Expand Up @@ -341,8 +352,7 @@ mod test {
let vi_1 = MipInfo {
name: "MIP-0002".to_string(),
version: 1,
component: MipComponent::Address,
component_version: 1,
components: HashMap::from([(MipComponent::Address, 1)]),
start: MassaTime::from(12),
timeout: MassaTime::from(15),
};
Expand All @@ -351,8 +361,7 @@ mod test {
let vi_2 = MipInfo {
name: "MIP-0003".to_string(),
version: 2,
component: MipComponent::Address,
component_version: 2,
components: HashMap::from([(MipComponent::Address, 2)]),
start: MassaTime::from(25),
timeout: MassaTime::from(28),
};
Expand Down
Loading