-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
## Description This PR implements the `fix` command that allows to fix BDJuno issues without having to re-index the whole database at once. Closes #227 Adds a way to fix #208 ## Checklist - [ ] Targeted PR against correct branch. - [ ] Linked to Github issue with discussion and accepted design OR link to spec that describes this work. - [ ] Wrote unit tests. - [ ] Re-reviewed `Files changed` in the Github PR explorer.
- Loading branch information
Showing
18 changed files
with
443 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
}, | ||
} | ||
} |
Oops, something went wrong.