Skip to content

Commit 5c92cb7

Browse files
mergify[bot]AdityaSripalsrdtrk
authored
imp: add support for ParamChange migration (backport #509) (#510)
Co-authored-by: Aditya <[email protected]> Co-authored-by: srdtrk <[email protected]> Co-authored-by: srdtrk <[email protected]>
1 parent dcf8c4d commit 5c92cb7

File tree

3 files changed

+168
-18
lines changed

3 files changed

+168
-18
lines changed
Binary file not shown.

programs/cw-ics08-wasm-eth/src/contract.rs

Lines changed: 153 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
33
use cosmwasm_std::{entry_point, Binary, Deps, DepsMut, Env, MessageInfo, Response};
44

5-
use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg, SudoMsg};
6-
use crate::{custom_query::EthereumCustomQuery, instantiate, msg::MigrateMsg, query};
5+
use crate::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, Migration, QueryMsg, SudoMsg};
6+
use crate::{custom_query::EthereumCustomQuery, instantiate, query, state};
77
use crate::{sudo, ContractError};
88

99
/// The version of the contracts state.
@@ -109,9 +109,23 @@ pub fn migrate(
109109
// Check if the state version is older than the current one and update it
110110
cw2::ensure_from_older_version(deps.storage, CONTRACT_NAME, STATE_VERSION)?;
111111

112-
// Re-initialize the client if needed.
113-
if let Some(instantiate_msg) = msg.instantiate_msg {
114-
instantiate::client(deps.storage, instantiate_msg)?;
112+
// Perform the migration
113+
match msg.migration {
114+
Migration::CodeOnly => {} // do nothing here
115+
Migration::Reinstantiate(instantiate_msg) => {
116+
// Re-instantiate the client
117+
instantiate::client(deps.storage, instantiate_msg)?;
118+
}
119+
Migration::UpdateForkParameters(fork_parameters) => {
120+
// Change the fork parameters
121+
let mut client_state = state::get_eth_client_state(deps.storage)?;
122+
client_state.fork_parameters = fork_parameters;
123+
let client_state_bz: Vec<u8> = serde_json::to_vec(&client_state)
124+
.map_err(ContractError::SerializeClientStateFailed)?;
125+
let mut wasm_client_state = state::get_wasm_client_state(deps.storage)?;
126+
wasm_client_state.data = client_state_bz;
127+
state::store_client_state(deps.storage, &wasm_client_state)?;
128+
}
115129
}
116130

117131
Ok(Response::default())
@@ -283,8 +297,8 @@ mod tests {
283297
use crate::{
284298
contract::{instantiate, migrate, query, sudo},
285299
msg::{
286-
Height, InstantiateMsg, MerklePath, MigrateMsg, QueryMsg, SudoMsg, UpdateStateMsg,
287-
UpdateStateResult, VerifyClientMessageMsg, VerifyMembershipMsg,
300+
Height, InstantiateMsg, MerklePath, MigrateMsg, Migration, QueryMsg, SudoMsg,
301+
UpdateStateMsg, UpdateStateResult, VerifyClientMessageMsg, VerifyMembershipMsg,
288302
},
289303
state::HOST_CLIENT_STATE_KEY,
290304
test::mk_deps,
@@ -311,7 +325,7 @@ mod tests {
311325
let client_state_bz: Vec<u8> = serde_json::to_vec(&client_state).unwrap();
312326
let consensus_state_bz: Vec<u8> = serde_json::to_vec(&consensus_state).unwrap();
313327

314-
let msg = crate::msg::InstantiateMsg {
328+
let msg = InstantiateMsg {
315329
client_state: Binary::from(client_state_bz),
316330
consensus_state: Binary::from(consensus_state_bz),
317331
checksum: b"checksum".into(),
@@ -412,7 +426,7 @@ mod tests {
412426
let client_state_bz: Vec<u8> = serde_json::to_vec(&client_state).unwrap();
413427
let consensus_state_bz: Vec<u8> = serde_json::to_vec(&consensus_state).unwrap();
414428

415-
let msg = crate::msg::InstantiateMsg {
429+
let msg = InstantiateMsg {
416430
client_state: Binary::from(client_state_bz),
417431
consensus_state: Binary::from(consensus_state_bz),
418432
checksum: b"checksum".into(),
@@ -583,7 +597,7 @@ mod tests {
583597
let client_state_bz: Vec<u8> = serde_json::to_vec(&client_state).unwrap();
584598
let consensus_state_bz: Vec<u8> = serde_json::to_vec(&consensus_state).unwrap();
585599

586-
let msg = crate::msg::InstantiateMsg {
600+
let msg = InstantiateMsg {
587601
client_state: Binary::from(client_state_bz),
588602
consensus_state: Binary::from(consensus_state_bz),
589603
checksum: b"checksum".into(),
@@ -632,7 +646,7 @@ mod tests {
632646
let client_state_bz: Vec<u8> = serde_json::to_vec(&client_state).unwrap();
633647
let consensus_state_bz: Vec<u8> = serde_json::to_vec(&consensus_state).unwrap();
634648

635-
let msg = crate::msg::InstantiateMsg {
649+
let msg = InstantiateMsg {
636650
client_state: Binary::from(client_state_bz),
637651
consensus_state: Binary::from(consensus_state_bz),
638652
checksum: b"checksum".into(),
@@ -733,7 +747,7 @@ mod tests {
733747
let client_state_bz: Vec<u8> = serde_json::to_vec(&client_state).unwrap();
734748
let consensus_state_bz: Vec<u8> = serde_json::to_vec(&consensus_state).unwrap();
735749

736-
let msg = crate::msg::InstantiateMsg {
750+
let msg = InstantiateMsg {
737751
client_state: Binary::from(client_state_bz),
738752
consensus_state: Binary::from(consensus_state_bz),
739753
checksum: b"checksum".into(),
@@ -901,7 +915,7 @@ mod tests {
901915
let client_state_bz: Vec<u8> = serde_json::to_vec(&client_state).unwrap();
902916
let consensus_state_bz: Vec<u8> = serde_json::to_vec(&consensus_state).unwrap();
903917

904-
let msg = crate::msg::InstantiateMsg {
918+
let msg = InstantiateMsg {
905919
client_state: Binary::from(client_state_bz),
906920
consensus_state: Binary::from(consensus_state_bz),
907921
checksum: b"checksum".into(),
@@ -913,8 +927,8 @@ mod tests {
913927
migrate(
914928
deps.as_mut(),
915929
mock_env(),
916-
crate::msg::MigrateMsg {
917-
instantiate_msg: None,
930+
MigrateMsg {
931+
migration: Migration::CodeOnly,
918932
},
919933
)
920934
.unwrap();
@@ -1008,7 +1022,7 @@ mod tests {
10081022
};
10091023

10101024
let migrate_msg = MigrateMsg {
1011-
instantiate_msg: Some(msg.clone()),
1025+
migration: Migration::Reinstantiate(msg.clone()),
10121026
};
10131027

10141028
// Migrate without any changes (i.e. same state version)
@@ -1026,5 +1040,128 @@ mod tests {
10261040
client_state.latest_slot
10271041
);
10281042
}
1043+
1044+
#[allow(clippy::too_many_lines)]
1045+
#[test]
1046+
fn test_migrate_with_fork_parameters() {
1047+
let mut deps = mk_deps();
1048+
let creator = deps.api.addr_make("creator");
1049+
let info = message_info(&creator, &coins(1, "uatom"));
1050+
1051+
let client_state = EthClientState {
1052+
chain_id: 0,
1053+
genesis_validators_root: B256::from([0; 32]),
1054+
min_sync_committee_participants: 0,
1055+
genesis_time: 0,
1056+
genesis_slot: 0,
1057+
fork_parameters: ForkParameters {
1058+
genesis_fork_version: FixedBytes([0; 4]),
1059+
genesis_slot: 0,
1060+
altair: Fork {
1061+
version: FixedBytes([0; 4]),
1062+
epoch: 0,
1063+
},
1064+
bellatrix: Fork {
1065+
version: FixedBytes([0; 4]),
1066+
epoch: 0,
1067+
},
1068+
capella: Fork {
1069+
version: FixedBytes([0; 4]),
1070+
epoch: 0,
1071+
},
1072+
deneb: Fork {
1073+
version: FixedBytes([0; 4]),
1074+
epoch: 0,
1075+
},
1076+
electra: Fork {
1077+
version: FixedBytes([0; 4]),
1078+
epoch: 0,
1079+
},
1080+
},
1081+
sync_committee_size: 512,
1082+
seconds_per_slot: 10,
1083+
slots_per_epoch: 8,
1084+
epochs_per_sync_committee_period: 0,
1085+
latest_slot: 42,
1086+
latest_execution_block_number: 38,
1087+
ibc_commitment_slot: U256::from(0),
1088+
ibc_contract_address: Address::default(),
1089+
is_frozen: false,
1090+
};
1091+
let client_state_bz: Vec<u8> = serde_json::to_vec(&client_state).unwrap();
1092+
1093+
let consensus_state = EthConsensusState {
1094+
slot: 42,
1095+
state_root: B256::from([0; 32]),
1096+
storage_root: B256::from([0; 32]),
1097+
timestamp: 0,
1098+
current_sync_committee: SummarizedSyncCommittee::default(),
1099+
next_sync_committee: None,
1100+
};
1101+
let consensus_state_bz: Vec<u8> = serde_json::to_vec(&consensus_state).unwrap();
1102+
1103+
let msg = InstantiateMsg {
1104+
client_state: client_state_bz.into(),
1105+
consensus_state: consensus_state_bz.into(),
1106+
checksum: b"checksum".into(),
1107+
};
1108+
let msg_copy = msg.clone();
1109+
1110+
let res = instantiate(deps.as_mut(), mock_env(), info, msg).unwrap();
1111+
assert_eq!(0, res.messages.len());
1112+
1113+
let migrate_msg = MigrateMsg {
1114+
migration: Migration::UpdateForkParameters(ForkParameters {
1115+
genesis_fork_version: FixedBytes([0; 4]),
1116+
genesis_slot: 0,
1117+
altair: Fork {
1118+
version: FixedBytes([0; 4]),
1119+
epoch: 0,
1120+
},
1121+
bellatrix: Fork {
1122+
version: FixedBytes([0; 4]),
1123+
epoch: 0,
1124+
},
1125+
capella: Fork {
1126+
version: FixedBytes([0; 4]),
1127+
epoch: 0,
1128+
},
1129+
deneb: Fork {
1130+
version: FixedBytes([0; 4]),
1131+
epoch: 0,
1132+
},
1133+
electra: Fork {
1134+
version: FixedBytes([0; 4]),
1135+
epoch: 5000,
1136+
},
1137+
}),
1138+
};
1139+
1140+
// Migrate without any changes and without reinitializing (i.e. same state version)
1141+
migrate(deps.as_mut(), mock_env(), migrate_msg).unwrap();
1142+
1143+
let actual_wasm_client_state_any_bz =
1144+
deps.storage.get(HOST_CLIENT_STATE_KEY.as_bytes()).unwrap();
1145+
let actual_wasm_client_state_any =
1146+
Any::decode(actual_wasm_client_state_any_bz.as_slice()).unwrap();
1147+
let wasm_client_state =
1148+
WasmClientState::decode(actual_wasm_client_state_any.value.as_slice()).unwrap();
1149+
// verify checksum hasn't changed
1150+
assert_eq!(msg_copy.checksum, wasm_client_state.checksum);
1151+
// verify latest height hasn't changed
1152+
assert_eq!(
1153+
wasm_client_state.latest_height.unwrap().revision_height,
1154+
client_state.latest_slot
1155+
);
1156+
// verify fork parameters have changed
1157+
let eth_client_state: EthClientState =
1158+
serde_json::from_slice(&wasm_client_state.data).unwrap();
1159+
assert_eq!(eth_client_state.latest_slot, client_state.latest_slot);
1160+
assert_ne!(
1161+
eth_client_state.fork_parameters.electra.epoch,
1162+
client_state.fork_parameters.electra.epoch
1163+
);
1164+
assert_eq!(eth_client_state.fork_parameters.electra.epoch, 5000);
1165+
}
10291166
}
10301167
}

programs/cw-ics08-wasm-eth/src/msg.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use cosmwasm_schema::{cw_serde, QueryResponses};
55
use cosmwasm_std::Binary;
66
use ethereum_light_client::header::ActiveSyncCommittee;
7+
use ethereum_types::consensus::fork::ForkParameters;
78
use ethereum_types::consensus::light_client_header::LightClientUpdate;
89

910
/// The message to instantiate the contract
@@ -62,8 +63,20 @@ pub enum QueryMsg {
6263
/// The message to migrate the contract
6364
#[cw_serde]
6465
pub struct MigrateMsg {
65-
/// The optional instantiate msg to re-initialize the client
66-
pub instantiate_msg: Option<InstantiateMsg>,
66+
/// Migration enum that defines the type of migration
67+
/// and any additional data needed for the migration
68+
pub migration: Migration,
69+
}
70+
71+
/// The supported migration types
72+
#[cw_serde]
73+
pub enum Migration {
74+
/// Migrate only the contract code not state
75+
CodeOnly,
76+
/// Migrate the contract code and reinitialize state
77+
Reinstantiate(InstantiateMsg),
78+
/// Migrate the contract code and update fork parameters
79+
UpdateForkParameters(ForkParameters),
6780
}
6881

6982
/// Verify membership message

0 commit comments

Comments
 (0)