Protobuf Upgrade Safety
Overview
Step-by-Step Process
1
Preserve the Previous Protobuf Definition
syntax = "proto3";
package pocket.shared;
option go_package = "github.com/pokt-network/poktroll/x/shared/types";
option (gogoproto.stable_marshaler_all) = true;
// Include the original imports
import "cosmos_proto/cosmos.proto";
import "cosmos/base/v1beta1/coin.proto";
import "gogoproto/gogo.proto";
import "pocket/shared/service.proto";
// Previous proto definition (pre-update)
message SupplierDeprecated {
// Unchanged fields from the previous definition
string owner_address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
string operator_address = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];
cosmos.base.v1beta1.Coin stake = 3;
repeated SupplierServiceConfig services = 4;
uint64 unstake_session_end_height = 5;
// NEW CHANGES: The upgrade will change this map to a ServiceConfigUpdate repeated field
map<string, uint64> services_activation_heights_map = 6;
}2
Add Keeper Methods for the Previous Type
// GetAllSuppliersDeprecated returns all suppliers using the previous format
// TODO_NEXT_RELEASE: Remove this method prior to the next release
func (k Keeper) GetAllSuppliersDeprecated(ctx context.Context) (suppliers []sharedtypes.SupplierDeprecated) {
storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx))
store := prefix.NewStore(storeAdapter, types.KeyPrefix(types.SupplierKeyOperatorPrefix))
iterator := storetypes.KVStorePrefixIterator(store, []byte{})
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
var supplier sharedtypes.SupplierDeprecated
k.cdc.MustUnmarshal(iterator.Value(), &supplier)
suppliers = append(suppliers, supplier)
}
return
}3
Implement Migration Logic in the Upgrade Handler
CreateUpgradeHandler: func(
mm *module.Manager,
keepers *keepers.Keepers,
configurator module.Configurator,
) upgradetypes.UpgradeHandler {
return func(ctx context.Context, plan upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) {
logger := cosmosTypes.UnwrapSDKContext(ctx).Logger()
logger.Info("Starting upgrade handler", "upgrade_plan_name", Upgrade_0_0_14_PlanName)
supplierKeeper := keepers.SupplierKeeper
// Get all suppliers using the deprecated supplier keeper method
suppliers := supplierKeeper.GetAllSuppliersDeprecated(ctx)
for _, supplierDeprecated := range suppliers {
// Convert previous format to new format
supplier := sharedtypes.Supplier{
OperatorAddress: supplierDeprecated.OperatorAddress,
Services: supplierDeprecated.Services,
OwnerAddress: supplierDeprecated.OwnerAddress,
Stake: supplierDeprecated.Stake,
UnstakeSessionEndHeight: supplierDeprecated.UnstakeSessionEndHeight,
// Add new fields or transform data as needed
ServiceConfigHistory: []*sharedtypes.ServiceConfigUpdate{
{
Services: supplierDeprecated.Services,
EffectiveBlockHeight: 1,
},
},
}
// Update the supplier with the migrated data
supplierKeeper.SetAndIndexDehydratedSupplier(ctx, supplier)
logger.Info(
"Successfully migrated supplier data",
"supplier_address", supplier.OperatorAddress,
)
}
// Continue with other migrations
return mm.RunMigrations(ctx, configurator, vm)
}
},Best Practices
Example Use Cases
Last updated
Was this helpful?
