Next time, allocate extra space so there is room to upgrade, as try_from_slice_unchecked & client-side desers will (generally) work if there are extra bytes. New fields are Option<T>
and will be deser'd to None.
Because you have existing account data, or if you've hit your padding limit, you should make a new account and add a migration path in your program.
Something like
[#account]
struct MyThing {
pub a: u8,
}
[#account]
struct MyThingV2 {
pub a: u8,
pub b: u8,
}
const MY_THING_V2_SIZE = 8 + 1 + 1 + 100; // 100 for padding
if you're using a PDA and don't want to change, you could do something like this
let my_thing: MyThingV2 = match existing_account.data_len() {
1 => {
// deser & get V1 state. Resize existing_account to MY_THING_V2_SIZE bytes, return V2
},
110 => {
// deser and return V2
},
_ => panic!("Unexpected length"),
}
otherwise, you can use anchor account macros to init the accountV2, pass in the accountV1, copy the data over & close v1. Include this as a separate ix that is optionally added to your tx if you detect that the accountV2 doesn't exist.
The first method reuses the existing account, which preserves transaction history and maintains the same PDA derivation, while the latter creates a completely new account.
Docs for realloc here. Good luck!