From db3856205cb9616e5ff857955a6f2fc88379068b Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Thu, 23 Dec 2021 12:23:45 +0100 Subject: [PATCH] Update MIGRATING.md signed int keys migration code --- MIGRATING.md | 81 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 23 deletions(-) diff --git a/MIGRATING.md b/MIGRATING.md index fa9df0a16..b625219fe 100644 --- a/MIGRATING.md +++ b/MIGRATING.md @@ -23,30 +23,65 @@ You shouldn't need these, except when manually handling raw integer keys seriali Migration code example: ```rust #[cfg_attr(not(feature = "library"), entry_point)] -pub fn migrate(deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result { - let version = get_contract_version(deps.storage)?; - if version.contract != CONTRACT_NAME { - return Err(ContractError::CannotMigrate { - previous_contract: version.contract, - }); - } +pub fn migrate(deps: DepsMut, _env: Env, _msg: Empty) -> Result { + let version: Version = CONTRACT_VERSION.parse()?; + let storage_version: Version = get_contract_version(deps.storage)?.version.parse()?; + + if storage_version < version { + set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + + // Do the migration // Original map - signed_int_map: Map = Map::new("signed_int_map"); - // New map - signed_int_map_new: Map = Map::new("signed_int_map-v2"); - - signed_int_map - .range_raw(deps.storage, None, None, Order::Ascending) - .map(|(k, v)| { - let signed = i8::from_be_bytes(k); - signed_int_map_new.save(deps.storage, signed, v); - }) - .collect()?; - - // Code to remove the old map keys - ... - - Ok(Response::default()) + let signed_int_map: Map, String> = Map::new("signed_int_map"); + + // New map (using a different namespace for safety. It could be the same with enough care) + let signed_int_map_new: Map = Map::new("signed_int_map-v2"); + + // Obtain all current keys (this will need to be paginated if there are many entries, + // i.e. i32 or i64 instead of i8). + // This may be gas intensive + let current = signed_int_map + .range(deps.storage, None, None, Order::Ascending) + .collect::>>()?; + + // Store length for quality control (adjust if paginated) + let current_count = current.len(); + + // Remove the old map keys + for (k, _) in current.iter() { + signed_int_map.remove(deps.storage, IntKeyOld::::from(*k)); + } + + // Save in new format + for (k, v) in current.iter() { + signed_int_map_new.save(deps.storage, *k, v)?; + } + + // Confirm old map is empty + if signed_int_map + .keys_raw(deps.storage, None, None, Order::Ascending) + .next() + .is_some() + { + return Err(StdError::generic_err("Original still not empty!").into()); + } + + // Obtain new keys, and confirm their amount. + // May be gas intensive. + let new_count = signed_int_map_new + .keys_raw(deps.storage, None, None, Order::Ascending) + .count(); + + if current_count != new_count { + return Err(StdError::generic_err(format!( + "Current ({}) and new ({}) counts differ!", + current_count, new_count + )) + .into()); + } + } + + Ok(Response::new()) } ```