Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Matt Kocubinski <mkocubinski@gmail.com>
174 lines
4.7 KiB
Go
174 lines
4.7 KiB
Go
package migrate
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
cmtjson "github.com/cometbft/cometbft/libs/json"
|
|
cmttypes "github.com/cometbft/cometbft/types"
|
|
|
|
"github.com/cosmos/cosmos-sdk/client"
|
|
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
"github.com/cosmos/cosmos-sdk/version"
|
|
"github.com/cosmos/cosmos-sdk/x/genutil/types"
|
|
)
|
|
|
|
type legacyAppGenesis struct {
|
|
AppName string `json:"app_name"`
|
|
AppVersion string `json:"app_version"`
|
|
GenesisTime time.Time `json:"genesis_time"`
|
|
ChainID string `json:"chain_id"`
|
|
InitialHeight int64 `json:"initial_height"`
|
|
AppHash []byte `json:"app_hash"`
|
|
AppState json.RawMessage `json:"app_state,omitempty"`
|
|
Consensus *legacyConsensusGenesis `json:"consensus,omitempty"`
|
|
}
|
|
|
|
type legacyConsensusGenesis struct {
|
|
Validators []cmttypes.GenesisValidator `json:"validators,omitempty"`
|
|
Params *cmttypes.ConsensusParams `json:"params,omitempty"`
|
|
}
|
|
|
|
func MigrateGenesisFile(oldGenFile string) (*types.AppGenesis, error) {
|
|
file, err := os.Open(filepath.Clean(oldGenFile))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer file.Close()
|
|
|
|
appGenesis, err := migrateGenesisValidator(file)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to read genesis from file %s: %w", oldGenFile, err)
|
|
}
|
|
|
|
return appGenesis, nil
|
|
}
|
|
|
|
// migrateGenesisValidator migrate current genesis file genesis validator to match of the
|
|
// new genesis validator type.
|
|
func migrateGenesisValidator(r io.Reader) (*types.AppGenesis, error) {
|
|
var newAg types.AppGenesis
|
|
var ag legacyAppGenesis
|
|
var err error
|
|
|
|
if rs, ok := r.(io.ReadSeeker); ok {
|
|
err = json.NewDecoder(rs).Decode(&ag)
|
|
if err == nil {
|
|
vals, err := convertValidators(ag.Consensus.Validators)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
newAg = types.AppGenesis{
|
|
AppName: ag.AppName,
|
|
AppVersion: ag.AppVersion,
|
|
GenesisTime: ag.GenesisTime,
|
|
ChainID: ag.ChainID,
|
|
InitialHeight: ag.InitialHeight,
|
|
AppHash: ag.AppHash,
|
|
AppState: ag.AppState,
|
|
Consensus: &types.ConsensusGenesis{
|
|
Validators: vals,
|
|
Params: ag.Consensus.Params,
|
|
},
|
|
}
|
|
|
|
return &newAg, nil
|
|
}
|
|
|
|
err = fmt.Errorf("error unmarshalling legacy AppGenesis: %w", err)
|
|
if _, serr := rs.Seek(0, io.SeekStart); serr != nil {
|
|
err = errors.Join(err, fmt.Errorf("error seeking back to the front: %w", serr))
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
jsonBlob, ioerr := io.ReadAll(r)
|
|
if ioerr != nil {
|
|
err = errors.Join(err, fmt.Errorf("failed to read file completely: %w", ioerr))
|
|
return nil, err
|
|
}
|
|
|
|
// fallback to comet genesis parsing
|
|
var ctmGenesis cmttypes.GenesisDoc
|
|
if uerr := cmtjson.Unmarshal(jsonBlob, &ctmGenesis); uerr != nil {
|
|
err = errors.Join(err, fmt.Errorf("failed fallback to CometBFT GenDoc: %w", uerr))
|
|
return nil, err
|
|
}
|
|
|
|
vals, err := convertValidators(ctmGenesis.Validators)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
newAg = types.AppGenesis{
|
|
AppName: version.AppName,
|
|
GenesisTime: ctmGenesis.GenesisTime,
|
|
ChainID: ctmGenesis.ChainID,
|
|
InitialHeight: ctmGenesis.InitialHeight,
|
|
AppHash: ctmGenesis.AppHash,
|
|
AppState: ctmGenesis.AppState,
|
|
Consensus: &types.ConsensusGenesis{
|
|
Validators: vals,
|
|
Params: ctmGenesis.ConsensusParams,
|
|
},
|
|
}
|
|
|
|
return &newAg, nil
|
|
}
|
|
|
|
func convertValidators(cmtVals []cmttypes.GenesisValidator) ([]sdk.GenesisValidator, error) {
|
|
vals := make([]sdk.GenesisValidator, len(cmtVals))
|
|
for i, cmtVal := range cmtVals {
|
|
pk, err := cryptocodec.FromCmtPubKeyInterface(cmtVal.PubKey)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
jsonPk, err := cryptocodec.PubKeyFromProto(pk)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
vals[i] = sdk.GenesisValidator{
|
|
Address: cmtVal.Address.Bytes(),
|
|
PubKey: jsonPk,
|
|
Power: cmtVal.Power,
|
|
Name: cmtVal.Name,
|
|
}
|
|
}
|
|
return vals, nil
|
|
}
|
|
|
|
// CometBFT Genesis Handling for JSON,
|
|
// this is necessary for json unmarshaling of legacyConsensusGenesis
|
|
func (cs *legacyConsensusGenesis) MarshalJSON() ([]byte, error) {
|
|
type Alias legacyConsensusGenesis
|
|
return cmtjson.Marshal(&Alias{
|
|
Validators: cs.Validators,
|
|
Params: cs.Params,
|
|
})
|
|
}
|
|
|
|
func (cs *legacyConsensusGenesis) UnmarshalJSON(b []byte) error {
|
|
type Alias legacyConsensusGenesis
|
|
|
|
result := Alias{}
|
|
if err := cmtjson.Unmarshal(b, &result); err != nil {
|
|
return err
|
|
}
|
|
|
|
cs.Params = result.Params
|
|
cs.Validators = result.Validators
|
|
|
|
return nil
|
|
}
|
|
|
|
// since we only need migrate the consensus validators content so there is no
|
|
// exported state migration.
|
|
func Migrate(appState types.AppMap, _ client.Context) (types.AppMap, error) {
|
|
return appState, nil
|
|
}
|