diff --git a/CHANGELOG.md b/CHANGELOG.md index e8adcadbe..2f1378732 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [v2.2.0](https://github.com/MinterTeam/minter-go-node/tree/v2.2.0) + +[Full Changelog](https://github.com/MinterTeam/minter-go-node/compare/v2.1.0...v2.2.0) + +### Fixed + +- Fix a critical bug in the exchange transaction through the pool +- Import and export for new entities +- Graceful stop of the node + ## [v2.1.0](https://github.com/MinterTeam/minter-go-node/tree/v2.1.0) [Full Changelog](https://github.com/MinterTeam/minter-go-node/compare/v2.0.3...v2.1.0) diff --git a/api/v2/service/block.go b/api/v2/service/block.go index 1f8e59e61..3dcfd01cc 100644 --- a/api/v2/service/block.go +++ b/api/v2/service/block.go @@ -49,8 +49,8 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes var totalValidators []*tmTypes.Validator { _, okValidators := fields[pb.BlockField_validators] - _, okEvidence := fields[pb.BlockField_evidence] - if okValidators || okEvidence { + _, okProposer := fields[pb.BlockField_proposer] + if okValidators || okProposer { valHeight := height - 1 if valHeight < 1 { valHeight = 1 diff --git a/api/v2/service/transaction.go b/api/v2/service/transaction.go index 2b043e4f2..5ac4801c7 100644 --- a/api/v2/service/transaction.go +++ b/api/v2/service/transaction.go @@ -8,7 +8,6 @@ import ( pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "strconv" "strings" ) @@ -31,14 +30,10 @@ func (s *Service) Transaction(ctx context.Context, req *pb.TransactionRequest) ( sender, _ := decodedTx.Sender() tags := make(map[string]string) - var gas int for _, tag := range tx.TxResult.Events[0].Attributes { key := string(tag.Key) value := string(tag.Value) tags[key] = value - if key == "tx.gas" { - gas, _ = strconv.Atoi(value) - } } cState := s.blockchain.CurrentState() @@ -64,7 +59,7 @@ func (s *Service) Transaction(ctx context.Context, req *pb.TransactionRequest) ( Id: uint64(decodedTx.GasCoin), Symbol: cState.Coins().GetCoin(decodedTx.GasCoin).GetFullSymbol(), }, - Gas: uint64(gas), + Gas: uint64(decodedTx.Gas()), TypeHex: decodedTx.Type.String(), Type: decodedTx.Type.UInt64(), Data: dataStruct, diff --git a/api/v2/service/transactions.go b/api/v2/service/transactions.go index 9da7c02bc..56403407a 100644 --- a/api/v2/service/transactions.go +++ b/api/v2/service/transactions.go @@ -8,7 +8,6 @@ import ( pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "strconv" "strings" ) @@ -37,14 +36,10 @@ func (s *Service) Transactions(ctx context.Context, req *pb.TransactionsRequest) sender, _ := decodedTx.Sender() tags := make(map[string]string) - var gas int for _, tag := range tx.TxResult.Events[0].Attributes { key := string(tag.Key) value := string(tag.Value) tags[key] = value - if key == "tx.gas" { - gas, _ = strconv.Atoi(value) - } } data, err := encode(decodedTx.GetDecodedData(), cState.Coins()) @@ -64,7 +59,7 @@ func (s *Service) Transactions(ctx context.Context, req *pb.TransactionsRequest) Id: uint64(decodedTx.GasCoin), Symbol: cState.Coins().GetCoin(decodedTx.GasCoin).GetFullSymbol(), }, - Gas: uint64(gas), + Gas: uint64(decodedTx.Gas()), TypeHex: decodedTx.Type.String(), Type: decodedTx.Type.UInt64(), Data: data, diff --git a/cmd/minter/cmd/export.go b/cmd/minter/cmd/export.go index 9426df86c..ac25ea4e2 100644 --- a/cmd/minter/cmd/export.go +++ b/cmd/minter/cmd/export.go @@ -1,148 +1,152 @@ package cmd -// -// import ( -// "crypto/sha256" -// "encoding/json" -// "fmt" -// "github.com/MinterTeam/minter-go-node/cmd/utils" -// "github.com/MinterTeam/minter-go-node/coreV2/state" -// "github.com/spf13/cobra" -// "github.com/tendermint/go-amino" -// tmproto "github.com/tendermint/tendermint/proto/tendermint/types" -// "github.com/tendermint/tendermint/types" -// "io" -// "log" -// "os" -// "time" -// ) -// -// var ( -// ExportCommand = &cobra.Command{ -// Use: "export", -// Short: "Minter export command", -// RunE: export, -// } -// ) -// -// const ( -// genesisPath = "genesis.json" -// -// blockMaxBytes int64 = 10000000 -// blockMaxGas int64 = 100000 -// blockTimeIotaMs int64 = 1000 -// -// evidenceMaxAgeNumBlocks = 1000 -// evidenceMaxAgeDuration = 24 * time.Hour -// ) -// -// func export(cmd *cobra.Command, args []string) error { -// height, err := cmd.Flags().GetUint64("height") -// if err != nil { -// log.Panicf("Cannot parse height: %s", err) -// } -// // -// // startHeight, err := cmd.Flags().GetUint64("start-height") -// // if err != nil { -// // log.Panicf("Cannot parse start-height: %s", err) -// // } -// -// chainID, err := cmd.Flags().GetString("chain-id") -// if err != nil { -// log.Panicf("Cannot parse chain id: %s", err) -// } -// -// genesisTime, err := cmd.Flags().GetDuration("genesis-time") -// if err != nil { -// log.Panicf("Cannot parse genesis time: %s", err) -// } -// -// indent, err := cmd.Flags().GetBool("indent") -// if err != nil { -// log.Panicf("Cannot parse indent: %s", err) -// } -// -// fmt.Println("Start exporting...") -// -// ldb, err := utils.NewStorage("", "").InitStateLevelDB("state", nil) -// if err != nil { -// log.Panicf("Cannot load db: %s", err) -// } -// -// currentState, err := state.NewCheckStateAtHeight(height, ldb) -// if err != nil { -// log.Panicf("Cannot new state at given height: %s", err) -// } -// -// exportTimeStart, newState := time.Now(), currentState.Export() -// fmt.Printf("State has been exported. Took %s", time.Since(exportTimeStart)) -// -// initialHeight := height -// -// var jsonBytes []byte -// if indent { -// jsonBytes, err = amino.NewCodec().MarshalJSONIndent(newState, "", " ") -// } else { -// jsonBytes, err = amino.NewCodec().MarshalJSON(newState) -// } -// if err != nil { -// log.Panicf("Cannot marshal state to json: %s", err) -// } -// -// appHash := [32]byte{} -// -// // compose genesis -// genesis := types.GenesisDoc{ -// GenesisTime: time.Unix(0, 0).Add(genesisTime), -// InitialHeight: int64(initialHeight), -// ChainID: chainID, -// ConsensusParams: &tmproto.ConsensusParams{ -// Block: tmproto.BlockParams{ -// MaxBytes: blockMaxBytes, -// MaxGas: blockMaxGas, -// TimeIotaMs: blockTimeIotaMs, -// }, -// Evidence: tmproto.EvidenceParams{ -// MaxAgeNumBlocks: evidenceMaxAgeNumBlocks, -// MaxAgeDuration: evidenceMaxAgeDuration, -// }, -// Validator: tmproto.ValidatorParams{ -// PubKeyTypes: []string{ -// types.ABCIPubKeyTypeEd25519, -// }, -// }, -// }, -// AppHash: appHash[:], -// AppState: json.RawMessage(jsonBytes), -// } -// -// err = genesis.ValidateAndComplete() -// if err != nil { -// log.Panicf("Failed to validate: %s", err) -// } -// -// if err := genesis.SaveAs(genesisPath); err != nil { -// log.Panicf("Failed to save genesis file: %s", err) -// } -// -// hash := getFileSha256Hash(genesisPath) -// fmt.Printf("\nOK\n%x\n", hash) -// -// return nil -// } -// -// func getFileSha256Hash(file string) []byte { -// f, err := os.Open(file) -// if err != nil { -// log.Fatal(err) -// } -// -// defer f.Close() -// -// h := sha256.New() -// if _, err := io.Copy(h, f); err != nil { -// log.Fatal(err) -// } -// -// return h.Sum(nil) -// } +import ( + "crypto/sha256" + "encoding/json" + "github.com/MinterTeam/minter-go-node/cmd/utils" + "github.com/MinterTeam/minter-go-node/coreV2/appdb" + "github.com/MinterTeam/minter-go-node/coreV2/state" + "github.com/spf13/cobra" + "github.com/tendermint/go-amino" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + "github.com/tendermint/tendermint/types" + "io" + "log" + "os" + "time" +) + +var ( + ExportCommand = &cobra.Command{ + Use: "export", + Short: "Minter export command", + RunE: export, + } +) + +const ( + genesisPath = "genesis.json" + + blockMaxBytes int64 = 10000000 + blockMaxGas int64 = 100000 + blockTimeIotaMs int64 = 1000 + + evidenceMaxAgeNumBlocks = 1000 + evidenceMaxAgeDuration = 24 * time.Hour +) + +func export(cmd *cobra.Command, args []string) error { + height, err := cmd.Flags().GetUint64("height") + if err != nil { + log.Panicf("Cannot parse height: %s", err) + } + + chainID, err := cmd.Flags().GetString("chain-id") + if err != nil { + log.Panicf("Cannot parse chain id: %s", err) + } + + genesisTime, err := cmd.Flags().GetDuration("genesis-time") + if err != nil { + log.Panicf("Cannot parse genesis time: %s", err) + } + + indent, err := cmd.Flags().GetBool("indent") + if err != nil { + log.Panicf("Cannot parse indent: %s", err) + } + + log.Println("Start exporting...") + + homeDir, err := cmd.Flags().GetString("home-dir") + if err != nil { + return err + } + storages := utils.NewStorage(homeDir, "") + + ldb, err := storages.InitStateLevelDB("data/state", nil) + if err != nil { + log.Panicf("Cannot load db: %s", err) + } + + currentState, err := state.NewCheckStateAtHeight(height, ldb) + if err != nil { + log.Panicf("Cannot new state at given height: %s, last available height %d", err, appdb.NewAppDB(storages.GetMinterHome(), cfg).GetLastHeight()) + } + + exportTimeStart := time.Now() + appState := currentState.Export() + log.Printf("State has been exported. Took %s\n", time.Since(exportTimeStart)) + + if err := appState.Verify(); err != nil { + log.Fatalf("Failed to validate: %s\n", err) + } + log.Printf("Verify state OK\n") + + var jsonBytes []byte + if indent { + jsonBytes, err = amino.NewCodec().MarshalJSONIndent(appState, "", " ") + } else { + jsonBytes, err = amino.NewCodec().MarshalJSON(appState) + } + if err != nil { + log.Panicf("Cannot marshal state to json: %s", err) + } + log.Printf("Marshal OK\n") + + // compose genesis + genesis := types.GenesisDoc{ + GenesisTime: time.Unix(0, 0).Add(genesisTime), + InitialHeight: int64(height), + ChainID: chainID, + ConsensusParams: &tmproto.ConsensusParams{ + Block: tmproto.BlockParams{ + MaxBytes: blockMaxBytes, + MaxGas: blockMaxGas, + TimeIotaMs: blockTimeIotaMs, + }, + Evidence: tmproto.EvidenceParams{ + MaxAgeNumBlocks: evidenceMaxAgeNumBlocks, + MaxAgeDuration: evidenceMaxAgeDuration, + }, + Validator: tmproto.ValidatorParams{ + PubKeyTypes: []string{ + types.ABCIPubKeyTypeEd25519, + }, + }, + }, + AppHash: nil, + AppState: json.RawMessage(jsonBytes), + } + + err = genesis.ValidateAndComplete() + if err != nil { + log.Panicf("Failed to validate: %s", err) + } + log.Printf("Validate genesis OK\n") + + if err := genesis.SaveAs(genesisPath); err != nil { + log.Panicf("Failed to save genesis file: %s", err) + } + + hash := getFileSha256Hash(genesisPath) + log.Printf("Finish with sha256 hash: \n%x\n", hash) + + return nil +} + +func getFileSha256Hash(file string) []byte { + f, err := os.Open(file) + if err != nil { + log.Fatal(err) + } + + defer f.Close() + + h := sha256.New() + if _, err := io.Copy(h, f); err != nil { + log.Fatal(err) + } + + return h.Sum(nil) +} diff --git a/cmd/minter/cmd/exportV1.go b/cmd/minter/cmd/exportV1.go deleted file mode 100644 index d86376f6f..000000000 --- a/cmd/minter/cmd/exportV1.go +++ /dev/null @@ -1,167 +0,0 @@ -package cmd - -import ( - "crypto/sha256" - "encoding/json" - "github.com/MinterTeam/minter-go-node/cmd/utils" - "github.com/MinterTeam/minter-go-node/coreV2/appdb" - "github.com/MinterTeam/minter-go-node/coreV2/state" - "github.com/spf13/cobra" - "github.com/tendermint/go-amino" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - "github.com/tendermint/tendermint/types" - "io" - "log" - "os" - "time" -) - -var ( - ExportCommand = &cobra.Command{ - Use: "export", - Short: "Minter export command", - RunE: export, - } -) - -const ( - genesisPath = "genesis.json" - - blockMaxBytes int64 = 10000000 - blockMaxGas int64 = 100000 - blockTimeIotaMs int64 = 1000 - - evidenceMaxAgeNumBlocks = 1000 - evidenceMaxAgeDuration = 24 * time.Hour -) - -func export(cmd *cobra.Command, args []string) error { - height, err := cmd.Flags().GetUint64("height") - if err != nil { - log.Panicf("Cannot parse height: %s", err) - } - - bipRate, err := cmd.Flags().GetFloat64("bip-price") - if err != nil { - log.Panicf("Cannot parse bip-price: %s", err) - } - - chainID, err := cmd.Flags().GetString("chain-id") - if err != nil { - log.Panicf("Cannot parse chain id: %s", err) - } - - genesisTime, err := cmd.Flags().GetDuration("genesis-time") - if err != nil { - log.Panicf("Cannot parse genesis time: %s", err) - } - - indent, err := cmd.Flags().GetBool("indent") - if err != nil { - log.Panicf("Cannot parse indent: %s", err) - } - - log.Println("Start exporting...") - - homeDir, err := cmd.Flags().GetString("home-dir") - if err != nil { - return err - } - storages := utils.NewStorage(homeDir, "") - - ldb, err := storages.InitStateLevelDB("data/state", nil) - if err != nil { - log.Panicf("Cannot load db: %s", err) - } - - currentState, err := state.NewCheckStateAtHeight(height, ldb) - if err != nil { - log.Panicf("Cannot new state at given height: %s, last available height %d", err, appdb.NewAppDB(storages.GetMinterHome(), cfg).GetLastHeight()) - } - - validators, err := cmd.Flags().GetStringSlice("validators") - if err != nil { - log.Panicf("Cannot parse validator: %s", err) - } - - addresses, err := cmd.Flags().GetStringSlice("rich-addresses") - if err != nil { - log.Panicf("Cannot parse validator: %s", err) - } - - exportTimeStart := time.Now() - appState := currentState.ExportV1(bipRate, validators, addresses) - log.Printf("State has been exported. Took %s\n", time.Since(exportTimeStart)) - - if err := appState.Verify(); err != nil { - log.Fatalf("Failed to validate: %s\n", err) - } - log.Printf("Verify state OK\n") - - var jsonBytes []byte - if indent { - jsonBytes, err = amino.NewCodec().MarshalJSONIndent(appState, "", " ") - } else { - jsonBytes, err = amino.NewCodec().MarshalJSON(appState) - } - if err != nil { - log.Panicf("Cannot marshal state to json: %s", err) - } - log.Printf("Marshal OK\n") - - // compose genesis - genesis := types.GenesisDoc{ - GenesisTime: time.Unix(0, 0).Add(genesisTime), - InitialHeight: int64(height), - ChainID: chainID, - ConsensusParams: &tmproto.ConsensusParams{ - Block: tmproto.BlockParams{ - MaxBytes: blockMaxBytes, - MaxGas: blockMaxGas, - TimeIotaMs: blockTimeIotaMs, - }, - Evidence: tmproto.EvidenceParams{ - MaxAgeNumBlocks: evidenceMaxAgeNumBlocks, - MaxAgeDuration: evidenceMaxAgeDuration, - }, - Validator: tmproto.ValidatorParams{ - PubKeyTypes: []string{ - types.ABCIPubKeyTypeEd25519, - }, - }, - }, - AppHash: nil, - AppState: json.RawMessage(jsonBytes), - } - - err = genesis.ValidateAndComplete() - if err != nil { - log.Panicf("Failed to validate: %s", err) - } - log.Printf("Validate genesis OK\n") - - if err := genesis.SaveAs(genesisPath); err != nil { - log.Panicf("Failed to save genesis file: %s", err) - } - - hash := getFileSha256Hash(genesisPath) - log.Printf("Finish with sha256 hash: \n%x\n", hash) - - return nil -} - -func getFileSha256Hash(file string) []byte { - f, err := os.Open(file) - if err != nil { - log.Fatal(err) - } - - defer f.Close() - - h := sha256.New() - if _, err := io.Copy(h, f); err != nil { - log.Fatal(err) - } - - return h.Sum(nil) -} diff --git a/cmd/minter/cmd/node.go b/cmd/minter/cmd/node.go index 93a2cf05a..7fbbd8ffe 100644 --- a/cmd/minter/cmd/node.go +++ b/cmd/minter/cmd/node.go @@ -14,7 +14,6 @@ import ( "github.com/MinterTeam/minter-go-node/log" "github.com/MinterTeam/minter-go-node/version" "github.com/spf13/cobra" - "github.com/tendermint/tendermint/abci/types" tmCfg "github.com/tendermint/tendermint/config" tmLog "github.com/tendermint/tendermint/libs/log" tmOS "github.com/tendermint/tendermint/libs/os" @@ -94,7 +93,6 @@ func runNode(cmd *cobra.Command) error { // start TM node node := startTendermintNode(app, tmConfig, logger, storages.GetMinterHome()) - app.SetTmNode(node) client := app.RpcClient() if !cfg.ValidatorMode { @@ -184,7 +182,7 @@ func checkRlimits() error { return nil } -func startTendermintNode(app types.Application, cfg *tmCfg.Config, logger tmLog.Logger, home string) *tmNode.Node { +func startTendermintNode(app *minter.Blockchain, cfg *tmCfg.Config, logger tmLog.Logger, home string) *tmNode.Node { nodeKey, err := p2p.LoadOrGenNodeKey(cfg.NodeKeyFile()) if err != nil { panic(err) @@ -206,6 +204,8 @@ func startTendermintNode(app types.Application, cfg *tmCfg.Config, logger tmLog. os.Exit(1) } + app.SetTmNode(node) + if err = node.Start(); err != nil { logger.Error("failed to start node", "err", err) os.Exit(1) diff --git a/cmd/minter/main.go b/cmd/minter/main.go index 923502a81..bc085a610 100644 --- a/cmd/minter/main.go +++ b/cmd/minter/main.go @@ -38,12 +38,9 @@ func main() { rootCmd.PersistentFlags().String("genesis", "https://github.com/MinterTeam/minter-go-node/releases/download/v2.0/genesis.json", "path with the genesis file to download") cmd.ExportCommand.Flags().Uint64("height", 0, "export height") - cmd.ExportCommand.Flags().Float64("bip-price", 0, "bip price in usd") cmd.ExportCommand.Flags().Bool("indent", false, "using indent") cmd.ExportCommand.Flags().String("chain-id", "", "export chain id") cmd.ExportCommand.Flags().Duration("genesis-time", 0, "export height") - cmd.ExportCommand.Flags().StringSlice("validators", []string{"Mpe1769d1239ff7b84cc582527d424a2f40ad2467170e76b45651789dfaf3564af"}, "testnet validator public key") - cmd.ExportCommand.Flags().StringSlice("rich-addresses", []string{"Mx6ab3a04c2f4d6022163f36a73840980cc8fc6a8b"}, "testnet rich addresses") if err := rootCmd.ExecuteContext(ctx); err != nil { panic(err) diff --git a/coreV2/minter/blockchain.go b/coreV2/minter/blockchain.go index 9f366cb3e..2e37baff1 100644 --- a/coreV2/minter/blockchain.go +++ b/coreV2/minter/blockchain.go @@ -20,6 +20,7 @@ import ( rpc "github.com/tendermint/tendermint/rpc/client/local" "log" "math/big" + "os" "sync" "sync/atomic" "time" @@ -73,6 +74,7 @@ type Blockchain struct { stopped bool grace *upgrades.Grace knownUpdates map[string]struct{} + stopOk chan struct{} } // NewMinterBlockchain creates Minter Blockchain instance, should be only called once @@ -102,6 +104,7 @@ func NewMinterBlockchain(storages *utils.Storage, cfg *config.Config, ctx contex stopChan: ctx, haltHeight: uint64(cfg.HaltHeight), updateStakesAndPayRewardsPeriod: period, + stopOk: make(chan struct{}), } if applicationDB.GetStartHeight() != 0 { app.initState() @@ -110,7 +113,7 @@ func NewMinterBlockchain(storages *utils.Storage, cfg *config.Config, ctx contex } func graceForUpdate(height uint64) *upgrades.GracePeriod { - return upgrades.NewGracePeriod(height, height+120) + return upgrades.NewGracePeriod(height, height+120, false) } const haltBlockV210 = 3431238 @@ -134,8 +137,9 @@ func (blockchain *Blockchain) initState() { blockchain.stateCheck = state.NewCheckState(stateDeliver) grace := upgrades.NewGrace() - grace.AddGracePeriods(upgrades.NewGracePeriod(initialHeight, initialHeight+120), - upgrades.NewGracePeriod(haltBlockV210, haltBlockV210+120)) + grace.AddGracePeriods(upgrades.NewGracePeriod(initialHeight, initialHeight+120, true), + upgrades.NewGracePeriod(haltBlockV210, haltBlockV210+120, true), + upgrades.NewGracePeriod(3612653, 3612653+120, true)) blockchain.knownUpdates = map[string]struct{}{ "": {}, // default version // add more for update @@ -465,6 +469,15 @@ func (blockchain *Blockchain) CheckTx(req abciTypes.RequestCheckTx) abciTypes.Re // Commit the state and return the application Merkle root hash func (blockchain *Blockchain) Commit() abciTypes.ResponseCommit { + if blockchain.stopped { + select { + case <-time.After(10 * time.Second): + blockchain.Close() + os.Exit(0) + case <-blockchain.stopOk: + os.Exit(0) + } + } if err := blockchain.stateDeliver.Check(); err != nil { panic(err) } diff --git a/coreV2/minter/minter.go b/coreV2/minter/minter.go index 60d3b4af4..daffc591e 100644 --- a/coreV2/minter/minter.go +++ b/coreV2/minter/minter.go @@ -17,6 +17,7 @@ import ( rpc "github.com/tendermint/tendermint/rpc/client/local" "log" "math/big" + "os" "sync/atomic" ) @@ -45,14 +46,20 @@ func (blockchain *Blockchain) checkStop() bool { func (blockchain *Blockchain) stop() { blockchain.stopped = true - go func() { - log.Println("Stopping Node") - log.Println("Node Stopped with error:", blockchain.tmNode.Stop()) - }() + if blockchain.tmNode == nil { + blockchain.Close() + os.Exit(0) + } else { + go func() { + log.Println("Stopping Node") + log.Println("Node Stopped with error:", blockchain.tmNode.Stop()) + }() + } } // WaitStop stops gracefully Minter Blockchain instance func (blockchain *Blockchain) WaitStop() error { + defer close(blockchain.stopOk) blockchain.tmNode.Wait() return blockchain.Close() } diff --git a/coreV2/state/candidates/candidate_test.go b/coreV2/state/candidates/candidate_test.go index cd56ef33c..f62b1616e 100644 --- a/coreV2/state/candidates/candidate_test.go +++ b/coreV2/state/candidates/candidate_test.go @@ -261,7 +261,7 @@ func TestCandidates_Commit_createOneCandidateWithID(t *testing.T) { b.SetChecker(checker.NewChecker(b)) candidates := NewCandidates(b, mutableTree.GetLastImmutable()) - candidates.CreateWithID([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10, 1) + candidates.CreateWithID([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10, 1, 0, 0) _, version, err := mutableTree.Commit(candidates) if err != nil { diff --git a/coreV2/state/candidates/candidates.go b/coreV2/state/candidates/candidates.go index 59688b73f..f33c73bfc 100644 --- a/coreV2/state/candidates/candidates.go +++ b/coreV2/state/candidates/candidates.go @@ -336,9 +336,9 @@ func (c *Candidates) Create(ownerAddress, rewardAddress, controlAddress types.Ad // CreateWithID creates a new candidate with given params and adds it to state // CreateWithID uses given ID to be associated with public key of a candidate -func (c *Candidates) CreateWithID(ownerAddress, rewardAddress, controlAddress types.Address, pubkey types.Pubkey, commission uint32, id uint32) { +func (c *Candidates) CreateWithID(ownerAddress, rewardAddress, controlAddress types.Address, pubkey types.Pubkey, commission, id uint32, commissionEditHeight, jail uint64) { c.setPubKeyID(pubkey, id) - c.Create(ownerAddress, rewardAddress, controlAddress, pubkey, commission, 0, 0) // todo: import jail? + c.Create(ownerAddress, rewardAddress, controlAddress, pubkey, commission, commissionEditHeight, jail) } // PunishByzantineCandidate finds candidate with given tmAddress and punishes it: @@ -932,16 +932,18 @@ func (c *Candidates) Export(state *types.AppState) { } state.Candidates = append(state.Candidates, types.Candidate{ - ID: uint64(candidate.ID), - RewardAddress: candidate.RewardAddress, - OwnerAddress: candidate.OwnerAddress, - ControlAddress: candidate.ControlAddress, - TotalBipStake: candidate.GetTotalBipStake().String(), - PubKey: candidate.PubKey, - Commission: uint64(candidate.Commission), - Status: uint64(candidate.Status), - Updates: updates, - Stakes: stakes, + ID: uint64(candidate.ID), + RewardAddress: candidate.RewardAddress, + OwnerAddress: candidate.OwnerAddress, + ControlAddress: candidate.ControlAddress, + TotalBipStake: candidate.GetTotalBipStake().String(), + PubKey: candidate.PubKey, + Commission: uint64(candidate.Commission), + Status: uint64(candidate.Status), + Updates: updates, + Stakes: stakes, + JailedUntil: candidate.JailedUntil, + LastEditCommissionHeight: candidate.LastEditCommissionHeight, }) } diff --git a/coreV2/state/state.go b/coreV2/state/state.go index fe3e605ed..2517d8726 100644 --- a/coreV2/state/state.go +++ b/coreV2/state/state.go @@ -23,7 +23,6 @@ import ( "github.com/cosmos/iavl" db "github.com/tendermint/tm-db" "log" - "math/big" "sync" ) @@ -59,185 +58,6 @@ func (cs *CheckState) Export() types.AppState { return *appState } -func (cs *CheckState) ExportV1(bipRate float64, validatorList []string, addresses []string) types.AppState { - appState := new(types.AppState) - - log.Printf("Handling validators...\n") - var activeCandidates []*types.Candidate - if types.CurrentChainID == types.ChainTestnet && len(validatorList) != 0 { - address := types.HexToAddress(addresses[0]) - for i, validator := range validatorList { - a := address - if len(addresses) >= len(validatorList) { - a = types.HexToAddress(addresses[i]) - } - - pubkey := types.HexToPubkey(validator) - activeCandidates = append(activeCandidates, &types.Candidate{ - ID: 0, - RewardAddress: a, - OwnerAddress: a, - ControlAddress: a, - TotalBipStake: "1000000000000000000000000000000", - PubKey: pubkey, - Commission: 15, - Stakes: []types.Stake{ - { - Owner: a, - Coin: 0, - Value: "1000000000000000000000000000000", - BipValue: "1000000000000000000000000000000", - }, - }, - Updates: nil, - Status: 2, - }) - appState.Validators = append(appState.Validators, types.Validator{ - TotalBipStake: "1000000000000000000000000000000", - PubKey: pubkey, - AccumReward: "0", - AbsentTimes: types.NewBitArray(validators.ValidatorMaxAbsentWindow), - }) - } - - } else { - cs.Validators().Export(appState) - } - - log.Printf("Handling candidates...\n") - droppedIDs := cs.Candidates().ExportV1(appState, uint64(cs.state.height), activeCandidates) - - log.Printf("Handling unbonds...\n") - cs.FrozenFunds().Export(appState, uint64(cs.state.height)) - log.Printf("Handling waitlist...\n") - cs.WaitList().ExportV1(appState, droppedIDs, uint64(cs.state.height)) - if types.CurrentChainID == types.ChainMainnet { - log.Printf("Handling checks...\n") - cs.Checks().Export(appState) - } - log.Printf("Handling halt votes...\n") - cs.Halts().Export(appState) - - if types.CurrentChainID == types.ChainTestnet && bipRate != 0 { - totalUSDCValue := helpers.BipToPip(big.NewInt(1000000000)) - poolUSDCValue := helpers.BipToPip(big.NewInt(10000)) - rate := big.NewFloat(bipRate) - poolBipValue, _ := big.NewFloat(0).Quo(big.NewFloat(0).SetInt(poolUSDCValue), rate).Int(nil) - - log.Printf("Handling accounts...\n") - subValues, coinOwners := cs.Accounts().ExportV1(appState, poolBipValue) - log.Printf("Handling coins...\n") - usdcCoinID, totalSubBipVolume := cs.Coins().ExportV1(appState, subValues, coinOwners) - - bridgeAddress := types.HexToAddress("Mxffffffffffffffffffffffffffffffffffffffff") - appState.Coins = append(appState.Coins, types.Coin{ - ID: uint64(usdcCoinID), - Name: "USDC", - Symbol: types.StrToCoinSymbol("MUSDC"), - Volume: helpers.BipToPip(big.NewInt(1000000000)).String(), - Crr: 0, - Reserve: "0", - MaxSupply: coins.MaxCoinSupply().String(), - Version: 0, - OwnerAddress: &bridgeAddress, - Mintable: true, - Burnable: true, - }) - - cs.App().ExportV1(appState, totalSubBipVolume) - log.Printf("Handling commissions...\n") - poolTokenVolume := cs.Swap().ExportV1(appState, usdcCoinID, poolUSDCValue, poolBipValue) - cs.Commission().ExportV1(appState, usdcCoinID) - - lpUSDC := uint64(usdcCoinID) + 1 - appState.Coins = append(appState.Coins, types.Coin{ - ID: lpUSDC, - Name: "Liquidity Pool 0:" + usdcCoinID.String(), - Symbol: types.StrToCoinSymbol("LP-1"), - Volume: poolTokenVolume.String(), - Crr: 0, - Reserve: "0", - MaxSupply: coins.MaxCoinSupply().String(), - Version: 0, - OwnerAddress: nil, - Mintable: true, - Burnable: true, - }) - - account := types.Account{ - Address: bridgeAddress, - Balance: []types.Balance{ - { - Coin: uint64(usdcCoinID), - Value: big.NewInt(0).Sub(totalUSDCValue, poolUSDCValue).String(), - }, - { - Coin: lpUSDC, - Value: big.NewInt(0).Sub(poolTokenVolume, big.NewInt(1000)).String(), - }, - }, - Nonce: 0, - MultisigData: &types.Multisig{ - Weights: []uint64{1000}, - Threshold: 667, - Addresses: []types.Address{ - types.HexToAddress("Mx90b704f155b3cd7f998802ff2ce5c39cb2a9caac"), - }, - }, - } - - if appState.Accounts[len(appState.Accounts)-1].Address == account.Address { - account.Balance = append(account.Balance, appState.Accounts[len(appState.Accounts)-1].Balance...) - appState.Accounts[len(appState.Accounts)-1] = account - } else { - appState.Accounts = append(appState.Accounts, account) - } - balance := types.Balance{ - Coin: lpUSDC, - Value: "1000", - } - - if appState.Accounts[0].Address == [20]byte{} { - appState.Accounts[0].Balance = append(appState.Accounts[0].Balance, balance) - } else { - appState.Accounts = append(appState.Accounts, types.Account{ - Address: types.Address{}, - Balance: []types.Balance{ - balance, - }, - Nonce: 0, - MultisigData: nil, - }) - } - } else { - log.Printf("Handling accounts...\n") - subValues, coinOwners := cs.Accounts().ExportV1(appState, big.NewInt(0)) - log.Printf("Handling coins...\n") - _, totalSubBipVolume := cs.Coins().ExportV1(appState, subValues, coinOwners) - cs.App().ExportV1(appState, totalSubBipVolume) - log.Printf("Handling commissions...\n") - cs.Commission().ExportV1(appState, types.GetBaseCoinID()) - } - - if types.CurrentChainID == types.ChainTestnet { - for _, address := range addresses { - appState.Accounts = append(appState.Accounts, types.Account{ - Address: types.HexToAddress(address), - Balance: []types.Balance{ - { - Coin: 0, - Value: "1000000000000000000000000000000000000", - }, - }, - Nonce: 0, - MultisigData: nil, - }) - } - } - - return *appState -} - func (cs *CheckState) Updates() update.RUpdate { return cs.state.Updates } @@ -453,7 +273,7 @@ func (s *State) Import(state types.AppState) error { } for _, c := range state.Candidates { - s.Candidates.CreateWithID(c.OwnerAddress, c.RewardAddress, c.ControlAddress, c.PubKey, uint32(c.Commission), uint32(c.ID)) + s.Candidates.CreateWithID(c.OwnerAddress, c.RewardAddress, c.ControlAddress, c.PubKey, uint32(c.Commission), uint32(c.ID), c.LastEditCommissionHeight, c.JailedUntil) if c.Status == candidates.CandidateStatusOnline { s.Candidates.SetOnline(c.PubKey) } diff --git a/coreV2/state/swap/swap.go b/coreV2/state/swap/swap.go index fc798c39c..13b870d88 100644 --- a/coreV2/state/swap/swap.go +++ b/coreV2/state/swap/swap.go @@ -123,6 +123,7 @@ func (s *Swap) Export(state *types.AppState) { Coin1: uint64(key.Coin1), Reserve0: reserve0.String(), Reserve1: reserve1.String(), + ID: uint64(pair.GetID()), } state.Pools = append(state.Pools, swap) diff --git a/coreV2/state/update/update.go b/coreV2/state/update/update.go index 152888032..f3a757809 100644 --- a/coreV2/state/update/update.go +++ b/coreV2/state/update/update.go @@ -15,7 +15,7 @@ const mainPrefix = byte('u') type RUpdate interface { // Deprecated - ExportV1(state *types.AppState, id types.CoinID) + ExportV1(state *types.AppState) Export(state *types.AppState) GetVotes(height uint64) []*Model @@ -83,7 +83,7 @@ func (c *Update) Export(state *types.AppState) { } // Deprecated -func (c *Update) ExportV1(state *types.AppState, id types.CoinID) { +func (c *Update) ExportV1(state *types.AppState) { return } diff --git a/coreV2/transaction/buy_swap_pool.go b/coreV2/transaction/buy_swap_pool.go index 5526582e1..48ae95d41 100644 --- a/coreV2/transaction/buy_swap_pool.go +++ b/coreV2/transaction/buy_swap_pool.go @@ -109,13 +109,13 @@ func (data BuySwapPoolData) Run(tx *Transaction, context state.Interface, reward reverseCoinIds(data.Coins) var calculatedAmountToSell *big.Int - resultCoin := data.Coins[len(data.Coins)-1] + lastIteration := len(data.Coins[1:]) - 1 { coinToBuy := data.Coins[0] coinToBuyModel := checkState.Coins().GetCoin(coinToBuy) valueToBuy := big.NewInt(0).Set(data.ValueToBuy) valueToSell := maxCoinSupply - for _, coinToSell := range data.Coins[1:] { + for i, coinToSell := range data.Coins[1:] { swapper := checkState.Swap().GetSwapper(coinToSell, coinToBuy) if isGasCommissionFromPoolSwap { if tx.GasCoin == coinToSell && coinToBuy.IsBaseCoin() { @@ -126,7 +126,7 @@ func (data BuySwapPoolData) Run(tx *Transaction, context state.Interface, reward } } - if coinToSell == resultCoin { + if i == lastIteration { valueToSell = data.MaximumValueToSell } @@ -152,7 +152,7 @@ func (data BuySwapPoolData) Run(tx *Transaction, context state.Interface, reward calculatedAmountToSell = valueToBuy } - coinToSell := resultCoin + coinToSell := data.Coins[len(data.Coins)-1] amount0 := new(big.Int).Set(calculatedAmountToSell) if tx.GasCoin == coinToSell { amount0.Add(amount0, commission) @@ -209,7 +209,7 @@ func (data BuySwapPoolData) Run(tx *Transaction, context state.Interface, reward valueToBuy = amountIn coinToBuy = coinToSell - if coinToSell == resultCoin { + if i == lastIteration { deliverState.Accounts.SubBalance(sender, coinToSell, amountIn) } } diff --git a/coreV2/transaction/sell_all_swap_pool.go b/coreV2/transaction/sell_all_swap_pool.go index 850312623..2192c9a46 100644 --- a/coreV2/transaction/sell_all_swap_pool.go +++ b/coreV2/transaction/sell_all_swap_pool.go @@ -128,20 +128,19 @@ func (data SellAllSwapPoolData) Run(tx *Transaction, context state.Interface, re Info: EncodeError(code.NewInsufficientFunds(sender.String(), balance.String(), sellCoin.GetFullSymbol(), coinToSell.String())), } } - + lastIteration := len(data.Coins[1:]) - 1 { coinToSell := data.Coins[0] coinToSellModel := sellCoin - resultCoin := data.Coins[len(data.Coins)-1] valueToSell := big.NewInt(0).Set(balance) valueToBuy := big.NewInt(0) - for _, coinToBuy := range data.Coins[1:] { + for i, coinToBuy := range data.Coins[1:] { swapper := checkState.Swap().GetSwapper(coinToSell, coinToBuy) if isGasCommissionFromPoolSwap == true && coinToBuy.IsBaseCoin() { swapper = commissionPoolSwapper.AddLastSwapStep(commission, commissionInBaseCoin) } - if coinToBuy == resultCoin { + if i == lastIteration { valueToBuy = data.MinimumValueToBuy } @@ -177,7 +176,6 @@ func (data SellAllSwapPoolData) Run(tx *Transaction, context state.Interface, re deliverState.Accounts.SubBalance(sender, sellCoin.ID(), commission) coinToSell := data.Coins[0] - resultCoin := data.Coins[len(data.Coins)-1] valueToSell := big.NewInt(0).Set(balance) var poolIDs tagPoolsChange @@ -200,7 +198,7 @@ func (data SellAllSwapPoolData) Run(tx *Transaction, context state.Interface, re valueToSell = amountOut coinToSell = coinToBuy - if resultCoin == coinToBuy { + if i == lastIteration { deliverState.Accounts.AddBalance(sender, coinToBuy, amountOut) } } @@ -214,7 +212,7 @@ func (data SellAllSwapPoolData) Run(tx *Transaction, context state.Interface, re {Key: []byte("tx.commission_in_base_coin"), Value: []byte(commissionInBaseCoin.String())}, {Key: []byte("tx.commission_conversion"), Value: []byte(isGasCommissionFromPoolSwap.String()), Index: true}, {Key: []byte("tx.commission_amount"), Value: []byte(commission.String())}, - {Key: []byte("tx.coin_to_buy"), Value: []byte(resultCoin.String()), Index: true}, + {Key: []byte("tx.coin_to_buy"), Value: []byte(data.Coins[len(data.Coins)-1].String()), Index: true}, {Key: []byte("tx.coin_to_sell"), Value: []byte(data.Coins[0].String()), Index: true}, {Key: []byte("tx.return"), Value: []byte(amountOut.String())}, {Key: []byte("tx.sell_amount"), Value: []byte(available.String())}, diff --git a/coreV2/transaction/sell_swap_pool.go b/coreV2/transaction/sell_swap_pool.go index 735bde15a..9eb0ecb68 100644 --- a/coreV2/transaction/sell_swap_pool.go +++ b/coreV2/transaction/sell_swap_pool.go @@ -93,13 +93,14 @@ func (data SellSwapPoolData) Run(tx *Transaction, context state.Interface, rewar return *errResp } + lastIteration := len(data.Coins[1:]) - 1 { coinToSell := data.Coins[0] coinToSellModel := checkState.Coins().GetCoin(coinToSell) - resultCoin := data.Coins[len(data.Coins)-1] + // resultCoin := data.Coins[lastIteration] valueToSell := data.ValueToSell valueToBuy := big.NewInt(0) - for _, coinToBuy := range data.Coins[1:] { + for i, coinToBuy := range data.Coins[1:] { swapper := checkState.Swap().GetSwapper(coinToSell, coinToBuy) if isGasCommissionFromPoolSwap { if tx.GasCoin == coinToSell && coinToBuy.IsBaseCoin() { @@ -110,7 +111,7 @@ func (data SellSwapPoolData) Run(tx *Transaction, context state.Interface, rewar } } - if coinToBuy == resultCoin { + if i == lastIteration { valueToBuy = data.MinimumValueToBuy } @@ -123,7 +124,7 @@ func (data SellSwapPoolData) Run(tx *Transaction, context state.Interface, rewar valueToSellCalc := swapper.CalculateBuyForSell(valueToSell) if valueToSellCalc == nil { reserve0, reserve1 := swapper.Reserves() - return Response{ // todo + return Response{ Code: code.SwapPoolUnknown, Log: fmt.Sprintf("swap pool has reserves %s %s and %d %s, you wanted sell %s %s", reserve0, coinToSellModel.GetFullSymbol(), reserve1, coinToBuyModel.GetFullSymbol(), valueToSell, coinToSellModel.GetFullSymbol()), Info: EncodeError(code.NewInsufficientLiquidity(coinToSellModel.ID().String(), valueToSell.String(), coinToBuyModel.ID().String(), valueToSellCalc.String(), reserve0.String(), reserve1.String())), @@ -169,7 +170,6 @@ func (data SellSwapPoolData) Run(tx *Transaction, context state.Interface, rewar rewardPool.Add(rewardPool, commissionInBaseCoin) coinToSell := data.Coins[0] - resultCoin := data.Coins[len(data.Coins)-1] valueToSell := data.ValueToSell var poolIDs tagPoolsChange @@ -192,7 +192,7 @@ func (data SellSwapPoolData) Run(tx *Transaction, context state.Interface, rewar valueToSell = amountOut coinToSell = coinToBuy - if resultCoin == coinToBuy { + if i == lastIteration { deliverState.Accounts.AddBalance(sender, coinToBuy, amountOut) } } @@ -204,7 +204,7 @@ func (data SellSwapPoolData) Run(tx *Transaction, context state.Interface, rewar {Key: []byte("tx.commission_in_base_coin"), Value: []byte(commissionInBaseCoin.String())}, {Key: []byte("tx.commission_conversion"), Value: []byte(isGasCommissionFromPoolSwap.String()), Index: true}, {Key: []byte("tx.commission_amount"), Value: []byte(commission.String())}, - {Key: []byte("tx.coin_to_buy"), Value: []byte(resultCoin.String()), Index: true}, + {Key: []byte("tx.coin_to_buy"), Value: []byte(data.Coins[lastIteration].String()), Index: true}, {Key: []byte("tx.coin_to_sell"), Value: []byte(data.Coins[0].String()), Index: true}, {Key: []byte("tx.return"), Value: []byte(amountOut.String())}, {Key: []byte("tx.pools"), Value: []byte(poolIDs.string())}, diff --git a/coreV2/transaction/sell_swap_pool_test.go b/coreV2/transaction/sell_swap_pool_test.go index d63b1b1b1..c11478558 100644 --- a/coreV2/transaction/sell_swap_pool_test.go +++ b/coreV2/transaction/sell_swap_pool_test.go @@ -925,3 +925,115 @@ func TestSellSwapPoolTx_Route(t *testing.T) { } } } + +func TestSellSwapPoolTx_Bug3612653(t *testing.T) { + t.Parallel() + cState := getState() + + coin := createTestCoin(cState) + coin1 := createNonReserveCoin(cState) + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + + cState.Accounts.AddBalance(addr, types.BasecoinID, helpers.BipToPip(big.NewInt(1000000))) + + cState.Accounts.SubBalance(types.Address{}, coin, helpers.BipToPip(big.NewInt(100000))) + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(100000))) + cState.Accounts.SubBalance(types.Address{}, coin1, helpers.BipToPip(big.NewInt(100000))) + cState.Accounts.AddBalance(addr, coin1, helpers.BipToPip(big.NewInt(100000))) + { + data := CreateSwapPoolData{ + Coin0: coin, + Volume0: helpers.BipToPip(big.NewInt(100)), + Coin1: coin1, + Volume1: helpers.BipToPip(big.NewInt(1000)), + } + + encodedData, err := rlp.EncodeToBytes(data) + + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: types.GetBaseCoinID(), + Type: TypeCreateSwapPool, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0, false) + + if response.Code != 0 { + t.Fatalf("Response code %d is not 0. Error: %s", response.Code, response.Log) + } + + if err := checkState(cState); err != nil { + t.Error(err) + } + } + { + data := SellSwapPoolData{ + Coins: []types.CoinID{coin, coin1, coin, coin1, coin}, + ValueToSell: big.NewInt(10), + MinimumValueToBuy: big.NewInt(8), + } + + encodedData, err := rlp.EncodeToBytes(data) + + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 2, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: types.GetBaseCoinID(), + Type: TypeSellSwapPool, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0, false) + + if response.Code != 0 { + t.Fatalf("Response code %d is not 0. Error: %s", response.Code, response.Log) + } + + if err := checkState(cState); err != nil { + t.Error(err) + } + } + + if cState.Accounts.GetBalance(addr, coin).String() != "99899999999999999999998" { + t.Error("bug balance coin") + } + if cState.Accounts.GetBalance(addr, coin1).String() != "99000000000000000000000" { + t.Error("bug balance coin1") + } +} diff --git a/coreV2/types/appstate.go b/coreV2/types/appstate.go index ddc0e6f13..d8a6a7900 100644 --- a/coreV2/types/appstate.go +++ b/coreV2/types/appstate.go @@ -272,16 +272,18 @@ type Validator struct { } type Candidate struct { - ID uint64 `json:"id"` - RewardAddress Address `json:"reward_address"` - OwnerAddress Address `json:"owner_address"` - ControlAddress Address `json:"control_address"` - TotalBipStake string `json:"total_bip_stake"` - PubKey Pubkey `json:"public_key"` - Commission uint64 `json:"commission"` - Stakes []Stake `json:"stakes,omitempty"` - Updates []Stake `json:"updates,omitempty"` - Status uint64 `json:"status"` + ID uint64 `json:"id"` + RewardAddress Address `json:"reward_address"` + OwnerAddress Address `json:"owner_address"` + ControlAddress Address `json:"control_address"` + TotalBipStake string `json:"total_bip_stake"` + PubKey Pubkey `json:"public_key"` + Commission uint64 `json:"commission"` + Stakes []Stake `json:"stakes,omitempty"` + Updates []Stake `json:"updates,omitempty"` + Status uint64 `json:"status"` + JailedUntil uint64 `json:"jailed_until,omitempty"` + LastEditCommissionHeight uint64 `json:"last_edit_commission_height,omitempty"` } type Stake struct { diff --git a/go.mod b/go.mod index 9bbccc002..08fe6ef04 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.2.2-0.20210405235123-df8990dd6dc2 + github.com/MinterTeam/node-grpc-gateway v1.3.1-0.20210422111554-4c532db60287 github.com/btcsuite/btcd v0.21.0-beta github.com/c-bata/go-prompt v0.2.3 github.com/cosmos/iavl v0.15.3 @@ -25,13 +25,13 @@ require ( github.com/stretchr/testify v1.7.0 github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca github.com/tendermint/go-amino v0.15.1 - github.com/tendermint/tendermint v0.34.9 + github.com/tendermint/tendermint v0.34.10 github.com/tendermint/tm-db v0.6.4 github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 github.com/urfave/cli/v2 v2.0.0 golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 golang.org/x/sys v0.0.0-20201020230747-6e5568b54d1a - google.golang.org/grpc v1.35.0 + google.golang.org/grpc v1.37.0 google.golang.org/protobuf v1.25.0 ) diff --git a/go.sum b/go.sum index 52f5d408f..e2744c74b 100644 --- a/go.sum +++ b/go.sum @@ -40,8 +40,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1: github.com/DataDog/zstd v1.4.1 h1:3oxKN3wbHibqx897utPC2LTQU4J+IHWWJO+glkAkpFM= github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.2.2-0.20210405235123-df8990dd6dc2 h1:ZK2v4TY7uDZm+wOC+Rz/dduMnqLYIDdfVLPA6kpMGKw= -github.com/MinterTeam/node-grpc-gateway v1.2.2-0.20210405235123-df8990dd6dc2/go.mod h1:d4Rw0MtsZTrFNLJJWr/jcurTYcqRVITzWuGDGo7aHxM= +github.com/MinterTeam/node-grpc-gateway v1.3.1-0.20210422111554-4c532db60287 h1:s8BGg9LDFbKtvUUIR950RNITRlPCUD0Jg0YaYkagpug= +github.com/MinterTeam/node-grpc-gateway v1.3.1-0.20210422111554-4c532db60287/go.mod h1:d4Rw0MtsZTrFNLJJWr/jcurTYcqRVITzWuGDGo7aHxM= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= @@ -159,6 +159,7 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ= github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= @@ -577,8 +578,8 @@ github.com/tendermint/go-amino v0.15.1/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoM github.com/tendermint/tendermint v0.34.0-rc4/go.mod h1:yotsojf2C1QBOw4dZrTcxbyxmPUrT4hNuOQWX9XUwB4= github.com/tendermint/tendermint v0.34.0-rc6/go.mod h1:ugzyZO5foutZImv0Iyx/gOFCX6mjJTgbLHTwi17VDVg= github.com/tendermint/tendermint v0.34.0/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ= -github.com/tendermint/tendermint v0.34.9 h1:9P2MXDEPOcPW0NBcHQ/HDSfvczZm+q5nUUw7AZ6f1Vc= -github.com/tendermint/tendermint v0.34.9/go.mod h1:kl4Z1JwGx1I+u1SXIzMDy7Z3T8LiMeCAOnzNn6AIMT4= +github.com/tendermint/tendermint v0.34.10 h1:wBOc/It8sh/pVH9np2V5fBvRmIyFN/bUrGPx+eAHexs= +github.com/tendermint/tendermint v0.34.10/go.mod h1:aeHL7alPh4uTBIJQ8mgFEE8VwJLXI1VD3rVOmH2Mcy0= github.com/tendermint/tm-db v0.6.2/go.mod h1:GYtQ67SUvATOcoY8/+x6ylk8Qo02BQyLrAs+yAcLvGI= github.com/tendermint/tm-db v0.6.3/go.mod h1:lfA1dL9/Y/Y8wwyPp2NMLyn5P5Ptr/gvDFNWtrCWSf8= github.com/tendermint/tm-db v0.6.4 h1:3N2jlnYQkXNQclQwd/eKV/NzlqPlfK21cpRRIx80XXQ= @@ -933,6 +934,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0 h1:TwIQcH3es+MojMVojxxfQ3l3OF2KzlRxML2xZq0kRo8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0 h1:uSZWeQJX5j11bIQ4AJoj+McDBo29cY1MCoC1wO3ts+c= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.0.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= diff --git a/upgrades/grace.go b/upgrades/grace.go index fe0e90ce3..75da18a3b 100644 --- a/upgrades/grace.go +++ b/upgrades/grace.go @@ -6,7 +6,7 @@ type Grace struct { func (g *Grace) IsUpgradeBlock(height uint64) bool { for _, period := range g.gracePeriods { - if height == period.from { + if height == period.from && period.upgrade { return true } } @@ -36,14 +36,15 @@ func (g *Grace) IsGraceBlock(block uint64) bool { } type GracePeriod struct { - from uint64 - to uint64 + from uint64 + to uint64 + upgrade bool } func (gp *GracePeriod) isApplicable(block uint64) bool { return block >= gp.from && block <= gp.to } -func NewGracePeriod(from uint64, to uint64) *GracePeriod { - return &GracePeriod{from: from, to: to} +func NewGracePeriod(from uint64, to uint64, upgrade bool) *GracePeriod { + return &GracePeriod{from: from, to: to, upgrade: upgrade} } diff --git a/version/version.go b/version/version.go index 07c1973d3..42ac71985 100755 --- a/version/version.go +++ b/version/version.go @@ -7,7 +7,7 @@ const ( var ( // Version must be a string because scripts like dist.sh read this file. - Version = "2.1.0" + Version = "2.2.0" // GitCommit is the current HEAD set using ldflags. GitCommit string