diff --git a/node/src/storage_mngr/node_migrations.rs b/node/src/storage_mngr/node_migrations.rs index 131a25620..ddab40a11 100644 --- a/node/src/storage_mngr/node_migrations.rs +++ b/node/src/storage_mngr/node_migrations.rs @@ -62,21 +62,27 @@ fn migrate_chain_state_v3_to_v4(old_chain_state_bytes: &[u8]) -> Vec { let db_version: u32 = 4; let db_version_bytes = db_version.to_le_bytes(); - // FIXME: the protocol info migration is not 100% correct, for reasons unknown. - // Extra fields in ChainState v4: - let protocol_info = ProtocolInfo::default(); - let protocol_info_bytes = serialize(&protocol_info).unwrap(); - let stakes = StakesTracker::default(); - let stakes_bytes = serialize(&stakes).unwrap(); - - [ - &db_version_bytes, - &old_chain_state_bytes[4..5], - &protocol_info_bytes, - &old_chain_state_bytes[5..], - &stakes_bytes, - ] - .concat() + // This little trick makes sure that we don't run a migration on a v4 chain state that was + // incorrectly tagged as v3 in the context of a development release, by checking if the bytes + // match a pattern where the environment enum is stored at a certain position + if old_chain_state_bytes[5..9] == [0x02, 0x00, 0x00, 0x00] { + // Extra fields in ChainState v4: + let protocol_info = ProtocolInfo::default(); + let protocol_info_bytes = serialize(&protocol_info).unwrap(); + let stakes = StakesTracker::default(); + let stakes_bytes = serialize(&stakes).unwrap(); + + [ + &db_version_bytes, + &old_chain_state_bytes[4..5], + &protocol_info_bytes, + &old_chain_state_bytes[5..], + &stakes_bytes, + ] + .concat() + } else { + [&db_version_bytes, &old_chain_state_bytes[4..]].concat() + } } fn migrate_chain_state(mut bytes: Vec) -> Result { @@ -208,7 +214,7 @@ pub fn put_chain_state_in_batch( where K: serde::Serialize + 'static, { - let db_version: u32 = 3; + let db_version: u32 = 4; // The first byte of the ChainState db_version must never be 0 or 1, // because that can be confused with version 0. assert!(db_version.to_le_bytes()[0] >= 2);