Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added fix command #228

Merged
merged 9 commits into from
Oct 18, 2021
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ all: lint build test-unit
### Build flags ###
###############################################################################

LD_FLAGS = -X github.com/desmos-labs/juno/version.Version=$(VERSION) \
-X github.com/desmos-labs/juno/version.Commit=$(COMMIT)
LD_FLAGS = -X github.com/forbole/juno/version.Version=$(VERSION) \
-X github.com/forbole/juno/version.Commit=$(COMMIT)

BUILD_FLAGS := -ldflags '$(LD_FLAGS)'

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[![Go Report Card](https://goreportcard.com/badge/github.com/forbole/bdjuno)](https://goreportcard.com/report/github.com/forbole/bdjuno)
![Codecov branch](https://img.shields.io/codecov/c/github/forbole/bdjuno/cosmos/v0.40.x)

BDJuno (shorthand for BigDipper Juno) is the [Juno](https://github.com/desmos-labs/juno) implementation
BDJuno (shorthand for BigDipper Juno) is the [Juno](https://github.com/forbole/juno) implementation
for [BigDipper](https://github.com/forbole/big-dipper).

It extends the custom Juno behavior by adding different handlers and custom operations to make it easier for BigDipper
Expand Down
4 changes: 3 additions & 1 deletion cmd/bdjuno/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
parsecmd "github.com/forbole/juno/v2/cmd/parse"
"github.com/forbole/juno/v2/modules/messages"

fixcmd "github.com/forbole/bdjuno/v2/cmd/fix"
migratecmd "github.com/forbole/bdjuno/v2/cmd/migrate"

"github.com/forbole/bdjuno/v2/types/config"
Expand All @@ -32,7 +33,8 @@ func main() {
cmd.VersionCmd(),
initcmd.InitCmd(cfg.GetInitConfig()),
parsecmd.ParseCmd(cfg.GetParseConfig()),
migratecmd.MigrateCmd(),
migratecmd.NewMigrateCmd(),
fixcmd.NewFixCmd(cfg.GetParseConfig()),
)

executor := cmd.PrepareRootCmd(cfg.GetName(), rootCmd)
Expand Down
40 changes: 40 additions & 0 deletions cmd/fix/fix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package fix

import (
"github.com/forbole/juno/v2/cmd/parse"
"github.com/spf13/cobra"

fixgov "github.com/forbole/bdjuno/v2/cmd/fix/gov"
fixstaking "github.com/forbole/bdjuno/v2/cmd/fix/staking"
)

// NewFixCmd returns the Cobra command allowing to fix some BDJuno bugs without having to re-sync the whole database
func NewFixCmd(parseCfg *parse.Config) *cobra.Command {
cmd := &cobra.Command{
Use: "fix",
Short: "Apply some fixes without the need to re-syncing the whole database from scratch",
PersistentPreRunE: runPersistentPreRuns(parse.ReadConfig(parseCfg)),
}

cmd.AddCommand(
fixgov.NewGovCmd(parseCfg),
fixstaking.NewStakingCmd(parseCfg),
)

return cmd
}

func runPersistentPreRuns(preRun func(_ *cobra.Command, _ []string) error) func(_ *cobra.Command, _ []string) error {
return func(cmd *cobra.Command, args []string) error {
if root := cmd.Root(); root != nil {
if root.PersistentPreRunE != nil {
err := root.PersistentPreRunE(root, args)
if err != nil {
return err
}
}
}

return preRun(cmd, args)
}
}
20 changes: 20 additions & 0 deletions cmd/fix/gov/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package gov

import (
"github.com/forbole/juno/v2/cmd/parse"
"github.com/spf13/cobra"
)

// NewGovCmd returns the Cobra command allowing to fix various things related to the x/gov module
func NewGovCmd(parseConfig *parse.Config) *cobra.Command {
cmd := &cobra.Command{
Use: "gov",
Short: "Fix things related to the x/gov module",
}

cmd.AddCommand(
proposalCmd(parseConfig),
)

return cmd
}
152 changes: 152 additions & 0 deletions cmd/fix/gov/proposal.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package gov

import (
"encoding/hex"
"fmt"

govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/forbole/juno/v2/cmd/parse"
"github.com/forbole/juno/v2/types/config"
"github.com/spf13/cobra"

"github.com/forbole/bdjuno/v2/database"
"github.com/forbole/bdjuno/v2/modules"
"github.com/forbole/bdjuno/v2/modules/gov"
"github.com/forbole/bdjuno/v2/utils"
)

// proposalCmd returns the Cobra command allowing to fix all things related to a proposal
func proposalCmd(parseConfig *parse.Config) *cobra.Command {
return &cobra.Command{
Use: "proposal [id]",
Short: "Get the description, votes and everything related to a proposal given its id",
RunE: func(cmd *cobra.Command, args []string) error {
proposalID := args[0]

parseCtx, err := parse.GetParsingContext(parseConfig)
if err != nil {
return err
}

sources, err := modules.BuildSources(config.Cfg.Node, parseCtx.EncodingConfig)
if err != nil {
return err
}

// Get the database
db := database.Cast(parseCtx.Database)

// Build the gov module
govModule := gov.NewModule(parseCtx.EncodingConfig.Marshaler, sources.GovSource, nil, nil, nil, db)

err = refreshProposalDetails(parseCtx, proposalID, govModule)
if err != nil {
return err
}

err = refreshProposalDeposits(parseCtx, proposalID, govModule)
if err != nil {
return err
}

err = refreshProposalVotes(parseCtx, proposalID, govModule)
if err != nil {
return err
}

return nil
},
}
}

func refreshProposalDetails(parseCtx *parse.Context, proposalID string, govModule *gov.Module) error {
// Get the tx that created the proposal
txs, err := utils.QueryTxs(parseCtx.Node, fmt.Sprintf("submit_proposal.proposal_id=%s", proposalID))
if err != nil {
return err
}

if len(txs) > 1 {
return fmt.Errorf("expecting only one create proposal transaction, found %d", len(txs))
}

// Get the tx details
tx, err := parseCtx.Node.Tx(hex.EncodeToString(txs[0].Tx.Hash()))
if err != nil {
return err
}

// Handle the MsgSubmitProposal messages
for index, msg := range tx.GetMsgs() {
if _, ok := msg.(*govtypes.MsgSubmitProposal); !ok {
continue
}

err = govModule.HandleMsg(index, msg, tx)
if err != nil {
return fmt.Errorf("error while handling MsgSubmitProposal: %s", err)
}
}

return nil
}

func refreshProposalDeposits(parseCtx *parse.Context, proposalID string, govModule *gov.Module) error {
// Get the tx that deposited to the proposal
txs, err := utils.QueryTxs(parseCtx.Node, fmt.Sprintf("proposal_deposit.proposal_id=%s", proposalID))
if err != nil {
return err
}

for _, tx := range txs {
// Get the tx details
junoTx, err := parseCtx.Node.Tx(hex.EncodeToString(tx.Tx.Hash()))
if err != nil {
return err
}

// Handle the MsgDeposit messages
for index, msg := range junoTx.GetMsgs() {
if _, ok := msg.(*govtypes.MsgDeposit); !ok {
continue
}

err = govModule.HandleMsg(index, msg, junoTx)
if err != nil {
return fmt.Errorf("error while handling MsgDeposit: %s", err)
}
}
}

return nil
}

func refreshProposalVotes(parseCtx *parse.Context, proposalID string, govModule *gov.Module) error {
// Get the tx that voted the proposal
txs, err := utils.QueryTxs(parseCtx.Node, fmt.Sprintf("proposal_vote.proposal_id=%s", proposalID))
if err != nil {
return err
}

for _, tx := range txs {
// Get the tx details
junoTx, err := parseCtx.Node.Tx(hex.EncodeToString(tx.Tx.Hash()))
if err != nil {
return err
}

// Handle the MsgVote messages
for index, msg := range junoTx.GetMsgs() {
if _, ok := msg.(*govtypes.MsgVote); !ok {
continue
}

err = govModule.HandleMsg(index, msg, junoTx)
if err != nil {
return fmt.Errorf("error while handling MsgVote: %s", err)
}
}
}

return nil
}
21 changes: 21 additions & 0 deletions cmd/fix/staking/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package staking

import (
"github.com/forbole/juno/v2/cmd/parse"
"github.com/spf13/cobra"
)

// NewStakingCmd returns the Cobra command that allows to fix all the things related to the x/staking module
func NewStakingCmd(parseConfig *parse.Config) *cobra.Command {
cmd := &cobra.Command{
Use: "staking",
Short: "Fix things related to the x/staking module",
}

cmd.AddCommand(
validatorsCmd(parseConfig),
slashesCmd(parseConfig),
)

return cmd
}
69 changes: 69 additions & 0 deletions cmd/fix/staking/slashes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package staking

import (
"fmt"

"github.com/forbole/juno/v2/cmd/parse"
"github.com/forbole/juno/v2/types/config"
"github.com/spf13/cobra"

"github.com/forbole/bdjuno/v2/database"
"github.com/forbole/bdjuno/v2/modules"
"github.com/forbole/bdjuno/v2/modules/staking"
)

// slashesCmd returns a Cobra command that allows to fix the delegations for all the slashed validators.
func slashesCmd(parseConfig *parse.Config) *cobra.Command {
return &cobra.Command{
Use: "slashes",
Short: "Fix the delegations for all the slashed validators, taking their delegations from the latest known height",
RunE: func(cmd *cobra.Command, args []string) error {
parseCtx, err := parse.GetParsingContext(parseConfig)
if err != nil {
return err
}

sources, err := modules.BuildSources(config.Cfg.Node, parseCtx.EncodingConfig)
if err != nil {
return err
}

// Get the database
db := database.Cast(parseCtx.Database)

// Get latest height
height, err := parseCtx.Node.LatestHeight()
if err != nil {
return fmt.Errorf("error while getting latest block height: %s", err)
}

// Get all validators
validators, err := sources.StakingSource.GetValidatorsWithStatus(height, "")
if err != nil {
return fmt.Errorf("error while getting validators: %s", err)
}

for _, validator := range validators {
// Get the validator delegations
delegations, err := sources.StakingSource.GetValidatorDelegations(height, validator.OperatorAddress)
if err != nil {
return fmt.Errorf("error while getting validator delegations: %s", err)
}

// Delete the old delegations
err = db.DeleteValidatorDelegations(validator.OperatorAddress)
if err != nil {
return fmt.Errorf("error while deleting validator delegations: %s", err)
}

// Save the delegations
err = db.SaveDelegations(staking.ConvertDelegationsResponses(height, delegations))
if err != nil {
return fmt.Errorf("error while saving delegations: %s", err)
}
}

return nil
},
}
}
Loading