-
Notifications
You must be signed in to change notification settings - Fork 39
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(drive): platform version patching and state migrations #1941
Changes from 4 commits
be2b0cc
a4d0988
b45a1db
bbad647
82dbe71
4e5a790
3857883
386cb65
90e984b
3fb9e7a
17c7c72
a8f2746
fc90dac
3c68376
b23e693
dacdf32
9e6312b
a2e62b7
b644ac7
975e57a
eb972df
25eefa8
94bfc42
6cb211b
f7ef6b3
febed5e
ffb2607
a9621f3
127ceae
4d7eb3e
f98b441
c0552dc
26cd101
cb923ac
b67c6d0
29e5314
5139ca7
31734aa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
use crate::platform_types::platform::Platform; | ||
use crate::platform_types::platform_state::PlatformState; | ||
use dpp::block::block_info::BlockInfo; | ||
|
||
impl<C> Platform<C> { | ||
pub(super) fn migration_42_example( | ||
&self, | ||
_block_info: &BlockInfo, | ||
_block_platform_state: &mut PlatformState, | ||
) { | ||
// Use Drive or GroveDB directly to modify state | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
mod migration_42_example; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should not be inside the build... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok |
||
|
||
use crate::error::Error; | ||
|
||
use dpp::block::block_info::BlockInfo; | ||
|
||
use crate::platform_types::platform::Platform; | ||
|
||
use crate::platform_types::platform_state::PlatformState; | ||
|
||
impl<C> Platform<C> { | ||
/// Perform state migration based on block information | ||
pub fn migrate_state( | ||
&self, | ||
block_info: &BlockInfo, | ||
block_platform_state: &mut PlatformState, | ||
) -> Result<(), Error> { | ||
// Implement functions in a separate modules with meaningful names and block height | ||
match block_info.height { | ||
42 => self.migration_42_example(block_info, block_platform_state), | ||
52 => self.migration_42_example(block_info, block_platform_state), | ||
_ => {} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why did we leave in examples? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For people so they see how to follow. I will hide it for builds There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed all test data from the code. Now it's defined in tests |
||
} | ||
|
||
Ok(()) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,6 @@ | ||
/// Clearing the drive cache should happen when a new block is going to be run | ||
pub(in crate::execution) mod clear_drive_block_cache; | ||
/// State migration | ||
pub(in crate::execution) mod migrate_state; | ||
/// Patch platform version to apply fixes for urgent bugs, which aren't a part of the normal upgrade process | ||
pub mod patch_platform_version; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
mod patch_0_15_example; | ||
|
||
use crate::error::Error; | ||
use crate::execution::platform_events::block_start::patch_platform_version::patch_0_15_example::patch_0_15_example; | ||
use dpp::block::block_info::BlockInfo; | ||
use dpp::prelude::BlockHeight; | ||
use dpp::util::deserializer::ProtocolVersion; | ||
use dpp::version::PlatformVersion; | ||
use indexmap::IndexMap; | ||
use once_cell::sync::Lazy; | ||
use std::collections::HashMap; | ||
use std::ops::Range; | ||
use std::sync::RwLock; | ||
|
||
use crate::platform_types::platform_state::v0::PlatformStateV0Methods; | ||
use crate::platform_types::platform_state::PlatformState; | ||
|
||
static PREVIOUS_PATCH_PATTERN: RwLock<Option<(ProtocolVersion, Range<BlockHeight>)>> = | ||
RwLock::new(None); | ||
|
||
type PatchFn = fn(PlatformVersion) -> PlatformVersion; | ||
|
||
type HeightToPatchRanges = IndexMap<Range<BlockHeight>, PatchFn>; | ||
|
||
static PATCHES: Lazy<HashMap<ProtocolVersion, HeightToPatchRanges>> = Lazy::new(|| { | ||
HashMap::from_iter(vec![ | ||
( | ||
1, | ||
IndexMap::from_iter(vec![ | ||
(15..30, patch_0_15_example as PatchFn), | ||
(30..45, patch_0_15_example as PatchFn), | ||
// (45..BlockHeight::MAX, patch_0_15_example as PatchFn), | ||
]), | ||
), | ||
// ( | ||
// 2, | ||
// IndexMap::from_iter(vec![(15..24, patch_0_15_example as PatchFn)]), | ||
// ), | ||
]) | ||
}); | ||
|
||
/// Patch platform version to change function versions to fix chain halt bugs | ||
pub fn patch_platform_version( | ||
block_info: &BlockInfo, | ||
current_platform_version: &PlatformVersion, | ||
block_platform_state: &mut PlatformState, | ||
) -> Result<(), Error> { | ||
// Check if a patch that matches protocol version and block height is already applied | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should be able to apply more than one patch. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. More than one patch for the same version? You can. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Per block height There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
if block_platform_state.patched_platform_version().is_some() { | ||
let previous_patch_pattern = PREVIOUS_PATCH_PATTERN.read().unwrap(); | ||
if let Some((protocol_version, height_range)) = previous_patch_pattern.as_ref() { | ||
if protocol_version == ¤t_platform_version.protocol_version | ||
&& height_range.contains(&block_info.height) | ||
{ | ||
tracing::trace!( | ||
protocol_version = current_platform_version.protocol_version, | ||
height = block_info.height, | ||
"Continue using patched platform version {} and height range {:?}", | ||
protocol_version, | ||
height_range | ||
); | ||
|
||
return Ok(()); | ||
} else { | ||
let height_range = height_range.clone(); | ||
drop(previous_patch_pattern); | ||
|
||
let mut previous_path_pattern = PREVIOUS_PATCH_PATTERN.write().unwrap(); | ||
*previous_path_pattern = None; | ||
|
||
tracing::debug!( | ||
protocol_version = current_platform_version.protocol_version, | ||
height = block_info.height, | ||
"Disable patch for platform version {} and height range {:?}", | ||
current_platform_version.protocol_version, | ||
height_range | ||
); | ||
} | ||
} | ||
} | ||
|
||
// Find a patch that matches protocol version first | ||
let Some(height_to_patch_ranges) = PATCHES.get(¤t_platform_version.protocol_version) | ||
else { | ||
// Drop patch | ||
block_platform_state.set_patched_platform_version(None); | ||
|
||
return Ok(()); | ||
}; | ||
|
||
// Find a patch that matches block height | ||
let Some((height_range, patch_fn)) = height_to_patch_ranges | ||
.iter() | ||
.find(|(height_range, _)| height_range.contains(&block_info.height)) | ||
else { | ||
// Drop patch | ||
block_platform_state.set_patched_platform_version(None); | ||
|
||
return Ok(()); | ||
}; | ||
|
||
// Apply the patch | ||
let patched_version = patch_fn(current_platform_version.clone()); | ||
|
||
// Make patch version as static ref to transparently replace original version | ||
let boxed_version = Box::new(patched_version); | ||
let static_version: &'static PlatformVersion = Box::leak(boxed_version); | ||
|
||
// Set patched version to the Platform (execution) state that will be used | ||
// instead of the current version | ||
block_platform_state.set_patched_platform_version(Some(static_version)); | ||
|
||
// Store the patch pattern to avoid applying the same patch multiple times | ||
PREVIOUS_PATCH_PATTERN.write().unwrap().replace(( | ||
current_platform_version.protocol_version, | ||
height_range.clone(), | ||
)); | ||
|
||
tracing::debug!( | ||
protocol_version = current_platform_version.protocol_version, | ||
height = block_info.height, | ||
"Apply patch for platform version {} and height range {:?}", | ||
current_platform_version.protocol_version, | ||
height_range | ||
); | ||
|
||
Ok(()) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
use dpp::version::PlatformVersion; | ||
|
||
pub fn patch_0_15_example(mut platform_version: PlatformVersion) -> PlatformVersion { | ||
platform_version.drive_abci.methods.engine.check_tx = 0; | ||
|
||
platform_version | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be one call only. We should call it, check_for_chain_halt_hot_fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And it should do everything inside.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Migrations aren't only for chain halts. We might want to migrate data for features as well.