use super::*;
impl<N: Network> Stack<N> {
#[inline]
pub fn check_upgrade_is_valid(old_program: &Program<N>, new_program: &Program<N>) -> Result<()> {
let program_id = new_program.id();
ensure!(program_id != &ProgramID::from_str("credits.aleo")?, "Cannot upgrade 'credits.aleo'");
ensure!(old_program.id() == new_program.id(), "Cannot upgrade '{program_id}' with different program ID");
for old_import in old_program.imports().keys() {
if !new_program.contains_import(old_import) {
bail!("Cannot upgrade '{program_id}' because it is missing the original import '{old_import}'");
}
}
match (old_program.constructor(), new_program.constructor()) {
(_, None) => bail!("A program cannot be upgraded to a program without a constructor"),
(None, _) => bail!("A program without a constructor cannot be upgraded"),
(Some(old_constructor), Some(new_constructor)) => {
ensure!(
old_constructor == new_constructor,
"Cannot upgrade '{program_id}' because the constructor does not match"
);
}
}
for (old_mapping_id, old_mapping_type) in old_program.mappings() {
let new_mapping_type = new_program.get_mapping(old_mapping_id)?;
ensure!(
*old_mapping_type == new_mapping_type,
"Cannot upgrade '{program_id}' because the mapping '{old_mapping_id}' does not match"
);
}
for (old_struct_id, old_struct_type) in old_program.structs() {
let new_struct_type = new_program.get_struct(old_struct_id)?;
ensure!(
old_struct_type == new_struct_type,
"Cannot upgrade '{program_id}' because the struct '{old_struct_id}' does not match"
);
}
for (old_record_id, old_record_type) in old_program.records() {
let new_record_type = new_program.get_record(old_record_id)?;
ensure!(
old_record_type == new_record_type,
"Cannot upgrade '{program_id}' because the record '{old_record_id}' does not match"
);
}
for old_closure in old_program.closures().values() {
let old_closure_name = old_closure.name();
let new_closure = new_program.get_closure(old_closure_name)?;
ensure!(
old_closure == &new_closure,
"Cannot upgrade '{program_id}' because the closure '{old_closure_name}' does not match"
);
}
for old_function in old_program.functions().values() {
let old_function_name = old_function.name();
let new_function = new_program.get_function_ref(old_function_name)?;
ensure!(
old_function.input_types() == new_function.input_types(),
"Cannot upgrade '{program_id}' because the input types to the function '{old_function_name}' do not match"
);
ensure!(
old_function.output_types() == new_function.output_types(),
"Cannot upgrade '{program_id}' because the output types of the function '{old_function_name}' do not match"
);
match (old_function.finalize_logic(), new_function.finalize_logic()) {
(None, None) => {} (None, Some(_)) => bail!(
"Cannot upgrade '{program_id}' because the function '{old_function_name}' should not have a finalize block"
),
(Some(_), None) => bail!(
"Cannot upgrade '{program_id}' because the function '{old_function_name}' should have a finalize block"
),
(Some(old_finalize), Some(new_finalize)) => {
ensure!(
old_finalize.input_types() == new_finalize.input_types(),
"Cannot upgrade '{program_id}' because the finalize inputs to the function '{old_function_name}' do not match"
);
}
}
}
Ok(())
}
}